/usr/local/CPAN/Data-Model/Data/Model/Schema/SQL.pm
package Data::Model::Schema::SQL;
use strict;
use warnings;
use Carp ();
$Carp::Internal{(__PACKAGE__)}++;
sub new {
my($class, $schema) = @_;
bless { schema => $schema }, $class;
}
sub call_method {
my $self = shift;
my $method = shift;
$self->$method(@_) unless $self->{schema}->driver;
my @ret = $self->{schema}->driver->_as_sql_hook( $self, $method => @_ );
return @ret if defined $ret[0];
return $self->$method(@_);
}
sub as_column_type {
my($self, $column, $args) = @_;
my $type = uc($args->{type});
my $size = $args->{options}->{size} || 0;
$size = 0 unless $size =~ /^\d+$/;
if ($type =~ m/int/i) {
$type .= "($size)" if $size;
} elsif ($type =~ m/(?:real|float|double|numeric|decimal)/i) {
my $decimals = $args->{options}->{decimals} || 0;
$decimals = 0 unless $decimals =~ /^\d+$/;
if ($size && $decimals) {
$type .= "($size,$decimals)";
} elsif ($size) {
$type .= "($size)";
}
} elsif ($type =~ m/char/i) {
$size ||= 255;
$type .= "($size)";;
}
$type;
}
sub as_type_attributes {
my($self, $column, $args) = @_;
my $sql;
$sql .= $args->{options}->{unsigned} ? ' UNSIGNED' : '';
$sql .= $args->{options}->{zerofill} ? ' ZEROFILL' : '';
$sql .= $args->{options}->{binary} ? ' BINARY' : '';
$sql .= $args->{options}->{ascii} ? ' ASCII' : '';
$sql .= $args->{options}->{unicode} ? ' UNICODE' : '';
$sql;
}
sub as_default {
my($self, $column, $args) = @_;
my $default = $args->{options}->{default};
if (!defined($default)) {
return '';
}
if (CORE::ref($default) and CORE::ref($default) eq 'CODE') {
return '';
}
if ($args->{type} =~ m/(?:int|real|float|double|numeric|decimal|bit)/i) {
return ' DEFAULT ' . $default
}
return " DEFAULT '" . $default ."'";
}
sub as_column {
my($self, $column, $args) = @_;
my $opts = $args->{options};
return sprintf('%-15s %-15s', $column, $self->call_method( as_column_type => $column, $args ))
. $self->call_method( as_type_attributes => $column, $args )
. ($opts->{required} ? ' NOT NULL' : ($opts->{null} ? ' NULL' : ''))
. $self->call_method( as_default => $column, $args )
. ($opts->{auto_increment} ? ' AUTO_INCREMENT' : '')
. ($self->{unique} ? ' UNIQUE' : '')
. ($self->{primary_key} ? ' PRIMARY KEY' : '')
. ($self->{references} ? ' REFERENCES '
. $self->{references}->{table}->{name} .'('
. $self->{references}->{name} .')' : '')
;
}
sub as_primary_key {
my($self, $key) = @_;
return () unless @{ $key };
return 'PRIMARY KEY (' . join(', ', @{ $key }) .')';
}
sub as_unique {
my($self, $unique) = @_;
return () unless @{ $unique };
my @sql = ();
for my $data (@{ $unique }) {
my($name, $columns) = @{ $data };
push(@sql, 'UNIQUE ' . $name . ' (' . join(', ', @{ $columns }) . ')');
}
return @sql;
}
sub as_foreign {
my $self = shift;
return () unless @{ $self->{schema}->{foreign} };
my $sql = '';
for my $foreign (@{ $self->{schema}->{foreign} }) {
my @cols = @{ $foreign->{columns} };
my @refs = @{ $foreign->{references} };
$sql .= 'FOREIGN KEY ('
. join(', ', @cols)
. ') REFERENCES ' . $refs[0]->{table}->{name} .' ('
. join(', ', @refs)
. ')'
;
}
return $sql;
}
sub as_table_attributes {
my $self = shift;
my $hash = $self->{schema}->options->{create_sql_attributes};
$hash = +{} unless ref($hash) eq 'HASH';
my($ret) = $self->call_method( 'get_table_attributes', $hash );
$ret ? " $ret" : '';
}
sub get_table_attributes {}
sub as_create_table {
my $self = shift;
my $schema = $self->{schema};
my @values;
my %columns = %{ $schema->column };
for my $column ($schema->column_names) {
push @values, $self->call_method( as_column => $column, $schema->column->{$column} );
}
my @key = @{ $schema->key };
my $unique_hash = $schema->unique;
my @unique = sort { $a->[0] cmp $b->[0] }
map { [ $_ => $unique_hash->{$_} ] }
keys %{ $unique_hash };
if (my $name = $schema->options->{key_as_unique}) {
unshift @unique, [ $name, [ @key ] ];
@key = ();
}
my $index_hash = $schema->index;
my @index = sort { $a->[0] cmp $b->[0] }
map { [ $_ => $index_hash->{$_} ] }
keys %{ $index_hash };
push(@values, $self->call_method( 'as_primary_key', \@key ));
push(@values, $self->call_method( 'as_unique', \@unique ));
push(@values, $self->call_method( 'as_inner_index', \@index ));
push(@values, $self->call_method( 'as_foreign' ));
return 'CREATE TABLE '
. $self->{schema}->model
. " (\n " . join(",\n ", grep { $_ } @values) . "\n)"
. $self->as_table_attributes,
;
}
sub as_inner_index {
();
}
sub as_index {
my $self = shift;
my @sql = ();
while (my($name, $columns) = each %{ $self->{schema}->{index} }) {
push(@sql, 'CREATE'
. ' INDEX '
. $name
. ' ON ' . $self->{schema}->model
. ' (' . join(', ', @{ $columns } ) . ')'
);
}
return @sql;
}
sub as_create_indexes {
my $self = shift;
my @ret = $self->call_method( 'as_index' );
return () unless $ret[0];
return @ret;
}
sub as_sql {
my $self = shift;
return ($self->as_create_table, $self->as_create_indexes);
}
1;
__END__
copied by L<SQL::DB::Schema::Table>, L<SQL::DB::Schema::Column>