SQL-Translator
view release on metacpan or search on metacpan
lib/SQL/Translator/Parser/MySQL.pm view on Meta::CPAN
# do nothing; is there a better way to write this? -- ky
}
my $result = $parser->startrule($data);
return $translator->error("Parse failed.") unless defined $result;
warn "Parse result:" . Dumper($result) if $DEBUG;
my $schema = $translator->schema;
$schema->name($result->{'database_name'}) if $result->{'database_name'};
my @tables
= sort { $result->{'tables'}{$a}{'order'} <=> $result->{'tables'}{$b}{'order'} } keys %{ $result->{'tables'} };
for my $table_name (@tables) {
my $tdata = $result->{tables}{$table_name};
my $table = $schema->add_table(name => $tdata->{'table_name'},)
or die $schema->error;
$table->comments($tdata->{'comments'});
my @fields = sort { $tdata->{'fields'}->{$a}->{'order'} <=> $tdata->{'fields'}->{$b}->{'order'} }
keys %{ $tdata->{'fields'} };
for my $fname (@fields) {
my $fdata = $tdata->{'fields'}{$fname};
my $field = $table->add_field(
name => $fdata->{'name'},
data_type => $fdata->{'data_type'},
size => $fdata->{'size'},
default_value => $fdata->{'default'},
is_auto_increment => $fdata->{'is_auto_inc'},
is_nullable => $fdata->{'null'},
comments => $fdata->{'comments'},
) or die $table->error;
$table->primary_key($field->name) if $fdata->{'is_primary_key'};
for my $qual (qw[ binary unsigned zerofill list collate ], 'character set', 'on update') {
if (my $val = $fdata->{$qual} || $fdata->{ uc $qual }) {
next if ref $val eq 'ARRAY' && !@$val;
$field->extra($qual, $val);
}
}
if ($fdata->{'has_index'}) {
$table->add_index(
name => '',
type => 'NORMAL',
fields => $fdata->{'name'},
) or die $table->error;
}
if ($fdata->{'is_unique'}) {
$table->add_constraint(
name => '',
type => 'UNIQUE',
fields => $fdata->{'name'},
) or die $table->error;
}
for my $cdata (@{ $fdata->{'constraints'} }) {
next unless $cdata->{'type'} eq 'foreign_key';
$cdata->{'fields'} ||= [ $field->name ];
push @{ $tdata->{'constraints'} }, $cdata;
}
}
for my $idata (@{ $tdata->{'indices'} || [] }) {
my $index = $table->add_index(
name => $idata->{'name'},
type => uc $idata->{'type'},
fields => $idata->{'fields'},
) or die $table->error;
}
if (my @options = @{ $tdata->{'table_options'} || [] }) {
my @cleaned_options;
my @ignore_opts
= $translator->parser_args->{'ignore_opts'}
? split(/,/, $translator->parser_args->{'ignore_opts'})
: ();
if (@ignore_opts) {
my $ignores = { map { $_ => 1 } @ignore_opts };
foreach my $option (@options) {
# make sure the option isn't in ignore list
my ($option_key) = keys %$option;
if (!exists $ignores->{$option_key}) {
push @cleaned_options, $option;
}
}
} else {
@cleaned_options = @options;
}
$table->options(\@cleaned_options) or die $table->error;
}
for my $cdata (@{ $tdata->{'constraints'} || [] }) {
my $constraint = $table->add_constraint(
name => $cdata->{'name'},
type => $cdata->{'type'},
fields => $cdata->{'fields'},
expression => $cdata->{'expression'},
reference_table => $cdata->{'reference_table'},
reference_fields => $cdata->{'reference_fields'},
match_type => $cdata->{'match_type'} || '',
on_delete => $cdata->{'on_delete'} || $cdata->{'on_delete_do'},
on_update => $cdata->{'on_update'} || $cdata->{'on_update_do'},
) or die $table->error;
}
# After the constrains and PK/idxs have been created,
# we normalize fields
normalize_field($_) for $table->get_fields;
}
my @procedures = sort { $result->{procedures}->{$a}->{'order'} <=> $result->{procedures}->{$b}->{'order'} }
keys %{ $result->{procedures} };
for my $proc_name (@procedures) {
$schema->add_procedure(
name => $proc_name,
owner => $result->{procedures}->{$proc_name}->{owner},
sql => $result->{procedures}->{$proc_name}->{sql},
);
}
my @views
= sort { $result->{views}->{$a}->{'order'} <=> $result->{views}->{$b}->{'order'} } keys %{ $result->{views} };
for my $view_name (@views) {
my $view = $result->{'views'}{$view_name};
my @flds = map { $_->{'alias'} || $_->{'name'} } @{ $view->{'select'}{'columns'} || [] };
my @from = map { $_->{'alias'} || $_->{'name'} } @{ $view->{'from'}{'tables'} || [] };
$schema->add_view(
name => $view_name,
sql => $view->{'sql'},
order => $view->{'order'},
fields => \@flds,
tables => \@from,
options => $view->{'options'}
);
}
return 1;
}
# Takes a field, and returns
sub normalize_field {
my ($field) = @_;
my ($size, $type, $list, $unsigned, $changed);
$size = $field->size;
$type = $field->data_type;
$list = $field->extra->{list} || [];
$unsigned = defined($field->extra->{unsigned});
if (!ref $size && $size eq 0) {
if (lc $type eq 'tinyint') {
$changed = $size != 4 - $unsigned;
$size = 4 - $unsigned;
} elsif (lc $type eq 'smallint') {
$changed = $size != 6 - $unsigned;
$size = 6 - $unsigned;
} elsif (lc $type eq 'mediumint') {
$changed = $size != 9 - $unsigned;
$size = 9 - $unsigned;
( run in 1.087 second using v1.01-cache-2.11-cpan-99c4e6809bf )