Alzabo
view release on metacpan or search on metacpan
lib/Alzabo/RDBMSRules/MySQL.pm view on Meta::CPAN
$sql .= join ', ', map {$_->name} $new->primary_key;
$sql .= ')';
push @sql, $sql;
}
foreach ( $new->primary_key )
{
if ( $_->sequenced &&
! ( $old->has_column( $_->name ) &&
$old->column( $_->name )->is_primary_key ) )
{
my $sql = $self->column_sql($_);
push @sql,
'ALTER TABLE ' . $new->name . ' CHANGE COLUMN ' . $_->name . ' ' . $sql;
}
}
return @sql;
}
sub alter_table_name_sql
{
my $self = shift;
my $table = shift;
return 'RENAME TABLE ' . $table->former_name . ' TO ' . $table->name;
}
sub alter_table_attributes_sql
{
my $self = shift;
my %p = @_;
# This doesn't work right if new table has no attributes
return;
return 'ALTER TABLE ' . $p{new}->name . ' ' . join ' ', $p{new}->attributes;
}
sub alter_column_name_sql
{
my $self = shift;
my $column = shift;
return
( 'ALTER TABLE ' . $column->table->name . ' CHANGE COLUMN ' .
$column->former_name . ' ' . $self->column_sql($column)
);
}
sub reverse_engineer
{
my $self = shift;
my $schema = shift;
my $driver = $schema->driver;
my $has_table_types =
$driver->one_row( sql => 'SHOW VARIABLES LIKE ?',
bind => 'table_type' );
foreach my $table ( $driver->tables )
{
my $table_name = $self->_clean_table_name($table);
my $t = $schema->make_table( name => $table_name );
foreach my $row ( $driver->rows( sql => "DESCRIBE $table" ) )
{
my ($type, @a);
if ( $row->[1] =~ /\A(?:ENUM|SET)/i )
{
$type = $row->[1];
}
else
{
($type, @a) = split /\s+/, $row->[1];
}
my $default = $row->[4] if defined $row->[4] && uc $row->[4] ne 'NULL';
my $seq = 0;
foreach my $a ( split /\s+/, $row->[5] )
{
if ( uc $a eq 'AUTO_INCREMENT' )
{
$seq = 1;
}
else
{
push @a, $a;
}
}
my %p;
if ( $type !~ /ENUM|SET/i
&& $type =~ /(\w+)\((\d+)(?:\s*,\s*(\d+))?\)$/ )
{
$type = uc $1;
$type = 'INTEGER' if $type eq 'INT';
# skip defaults
unless ( $type eq 'TINYINT' && ( $2 == 4 || $2 == 3 ) ||
$type eq 'SMALLINT' && ( $2 == 6 || $2 == 5 ) ||
$type eq 'MEDIUMINT' && ( $2 == 9 || $2 == 8 ) ||
$type eq 'INTEGER' && ( $2 == 11 || $2 == 10 ) ||
$type eq 'BIGINT' && ( $2 == 21 || $2 == 20 ) ||
$type eq 'YEAR' && $2 == 4 ||
$type eq 'TIMESTAMP' && $2 == 14
)
{
$p{length} = $2;
$p{precision} = $3;
}
}
$type = $self->_capitalize_type($type);
$default = undef
if $self->_can_ignore_default( $type, $default );
my $c = $t->make_column( name => $row->[0],
type => $type,
nullable => $row->[2] eq 'YES',
sequenced => $seq,
default => $default,
attributes => \@a,
primary_key => $row->[3] eq 'PRI',
%p,
);
}
my %i;
foreach my $row ( $driver->rows( sql => "SHOW INDEX FROM $table" ) )
{
next if $row->[2] eq 'PRIMARY';
my $type_i = $driver->major_version >= 4 ? 10 : 9;
$i{ $row->[2] }{fulltext} =
$row->[$type_i] && $row->[$type_i] =~ /fulltext/i ? 1 : 0;
$i{ $row->[2] }{cols}[ $row->[3] - 1 ]{column} = $t->column( $row->[4] );
if ( defined $row->[7] )
{
# MySQL (at least 4.0.17) reports a sub_part of 1 for
# the second column of a fulltext index.
if ( ! $i{ $row->[2] }{fulltext} || $row->[7] > 1 )
{
$i{ $row->[2] }{cols}[ $row->[3] - 1 ]{prefix} = $row->[7]
}
}
$i{ $row->[2] }{unique} = $row->[1] ? 0 : 1;
}
foreach my $index (keys %i)
{
$t->make_index( columns => $i{$index}{cols},
unique => $i{$index}{unique},
fulltext => $i{$index}{fulltext} );
}
if ( $has_table_types )
{
my $table_type =
( $driver->one_row( sql => 'SHOW TABLE STATUS LIKE ?',
bind => $table_name ) )[1];
$t->add_attribute( 'TYPE=' . uc $table_type );
}
}
}
my %ignored_defaults = ( DATETIME => '0000-00-00 00:00:00',
DATE => '0000-00-00',
YEAR => '0000',
CHAR => '',
VARCHAR => '',
TINTYTEXT => '',
SMALLTEXT => '',
MEDIUMTEXT => '',
TEXT => '',
LONGTEXT => '',
);
sub _can_ignore_default
{
my $self = shift;
my $type = shift;
my $default = shift;
return 1 unless defined $default;
return 1
if exists $ignored_defaults{$type} && $default eq $ignored_defaults{$type};
if ( $type eq 'DECIMAL' )
{
return 1 if $default =~ /0\.0+/;
}
if ( $type =~ /INT/ )
{
return 1 unless $default;
}
return 0;
}
sub rules_id
{
return 'MySQL';
}
1;
__END__
=head1 NAME
Alzabo::RDBMSRules::MySQL - MySQL specific database rules.
=head1 SYNOPSIS
use Alzabo::RDBMSRules::MySQL;
=head1 DESCRIPTION
( run in 1.590 second using v1.01-cache-2.11-cpan-2398b32b56e )