Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds the spatial index type #61

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion lib/MySQL/Diff.pm
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,7 @@ sub _diff_tables {
my @changes = (
$self->_diff_fields(@_),
$self->_diff_indices(@_),
$self->_diff_partitions(@_),
$self->_diff_primary_key(@_),
$self->_diff_foreign_key(@_),
$self->_diff_options(@_)
Expand Down Expand Up @@ -285,15 +286,18 @@ sub _diff_indices {
for my $index (keys %$indices1) {
debug(3,"table1 had index '$index'");
my $old_type = $table1->is_unique($index) ? 'UNIQUE' :
$table1->is_spatial($index) ? 'SPATIAL INDEX' :
$table1->is_fulltext($index) ? 'FULLTEXT INDEX' : 'INDEX';

if ($indices2 && $indices2->{$index}) {
if( ($indices1->{$index} ne $indices2->{$index}) or
($table1->is_unique($index) xor $table2->is_unique($index)) or
($table1->is_spatial($index) xor $table2->is_spatial($index)) or
($table1->is_fulltext($index) xor $table2->is_fulltext($index)) )
{
debug(3,"index '$index' changed");
my $new_type = $table2->is_unique($index) ? 'UNIQUE' :
$table2->is_spatial($index) ? 'SPATIAL INDEX' :
$table2->is_fulltext($index) ? 'FULLTEXT INDEX' : 'INDEX';

my $changes = "ALTER TABLE $name1 DROP INDEX $index;";
Expand Down Expand Up @@ -324,10 +328,59 @@ sub _diff_indices {
_key_covers_auto_col($table2, $index)
);
debug(3,"index '$index' added");
my $new_type = $table2->is_unique($index) ? 'UNIQUE' : 'INDEX';
my $new_type = $table2->is_unique($index) ? 'UNIQUE' :
$table2->is_spatial($index) ? 'SPATIAL INDEX' : 'INDEX';
push @changes, "ALTER TABLE $name1 ADD $new_type $index ($indices2->{$index});\n";
}
}
return @changes;
}

sub _diff_partitions {
my ($self, $table1, $table2) = @_;

my $name1 = $table1->name();

my $partitions1 = $table1->partitions();
my $partitions2 = $table2->partitions();

return () unless $partitions1 || $partitions2;

my @changes;

if($partitions1) {
for my $partition (keys %$partitions1) {
debug(3,"table1 had partition '$partition'");
if ($partitions2 && $partitions2->{$partition}){
if( ($partitions1->{$partition}{val} ne $partitions2->{$partition}{val}) or
($partitions1->{$partition}{op} ne $partitions2->{$partition}{op})){
debug(3,"partition '$partition' for values '$partitions1->{$partition}{op}' '$partitions1->{$partition}{val}' changed");
my $changes = "ALTER TABLE $name1 DROP PARTITION $partition;";
$changes .= " # was VALUES '$partitions1->{$partition}{op}' '$partitions1->{$partition}{val}'"
unless $self->{opts}{'no-old-defs'};
$changes .= "\nALTER TABLE $name1 ADD PARTITION (PARTITION $partition VALUES $partitions2->{$partition}{op} ($partitions2->{$partition}{val}));\n";
push @changes, $changes;
}
} else {
# ALTER TABLE t1 DROP PARTITION p0, p1;
debug(3,"partition '$partition' for values '$partitions1->{$partition}{op}' '$partitions1->{$partition}{val}' removed");
my $changes = "ALTER TABLE $name1 DROP PARTITION $partition;";
$changes .= " # was VALUES '$partitions1->{$partition}{op}' '$partitions1->{$partition}{val}'"
unless $self->{opts}{'no-old-defs'};
$changes .= "\n";
push @changes, $changes;
}
}
}

# ALTER TABLE t1 ADD PARTITION (PARTITION p3 VALUES LESS THAN (2002));
if($partitions2) {
for my $partition (keys %$partitions2) {
next if($partitions1 && $partitions1->{$partition});
debug(3,"partition '$partition' for values '$partitions2->{$partition}{op}' '$partitions2->{$partition}{val}' added");
push @changes, "ALTER TABLE $name1 ADD PARTITION (PARTITION $partition VALUES $partitions2->{$partition}{op} ($partitions2->{$partition}{val}));\n";
}
}

return @changes;
}
Expand Down
2 changes: 1 addition & 1 deletion lib/MySQL/Diff/Database.pm
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ sub _parse_defs {
return if $self->{_tables};

debug(2, "parsing table defs");
my $defs = join '', grep ! /^\s*(\#|--|SET|\/\*)/, @{$self->{_defs}};
my $defs = join '', grep ! /^\s*(\#|--|SET|\/\*\!\d{5}\sSET)/, @{$self->{_defs}};
$defs =~ s/`//sg;
my @tables = split /(?=^\s*(?:create|alter|drop)\s+table\s+)/im, $defs;
$self->{_tables} = [];
Expand Down
78 changes: 75 additions & 3 deletions lib/MySQL/Diff/Table.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@ MySQL::Diff::Table - Table Definition Class
my $fields = $db->fields(); # %$fields
my $primary_key = $db->primary_key();
my $indices = $db->indices(); # %$indices
my $partitions = $db->partitions(); # %$partitions
my $options = $db->options();

my $isfield = $db->isa_field($field);
my $isprimary = $db->isa_primary($field);
my $isindex = $db->isa_index($field);
my $isunique = $db->is_unique($field);
my $isspatial = $db->is_spatial($field);
my $isfulltext = $db->is_fulltext($field);
my $ipatitioned = $db->is_paritioned($field);

=head1 DESCRIPTION

Expand Down Expand Up @@ -101,6 +104,10 @@ Returns a hash reference to fields used as primary key fields.

Returns a hash reference to fields used as index fields.

=item * partitions

Returns a hash reference to fields used as partitions.

=item * options

Returns the additional options added to the table definition.
Expand All @@ -122,6 +129,10 @@ Returns 1 if given field is used as an index field, otherwise returns 0.

Returns 1 if given field is used as unique index field, otherwise returns 0.

=item * is_spatial

Returns 1 if given field is used as spatial index field, otherwise returns 0.

=item * is_fulltext

Returns 1 if given field is used as fulltext index field, otherwise returns 0.
Expand All @@ -130,6 +141,10 @@ Returns 1 if given field is used as fulltext index field, otherwise returns 0.

Returns 1 if given field is defined as an auto increment field, otherwise returns 0.

=item * is_paritioned

Returns if given fiel is a praritioned field

=back

=cut
Expand All @@ -140,16 +155,19 @@ sub field { my $self = shift; return $self->{fields}{$_[0]}; }
sub fields { my $self = shift; return $self->{fields}; }
sub primary_key { my $self = shift; return $self->{primary_key}; }
sub indices { my $self = shift; return $self->{indices}; }
sub partitions { my $self = shift; return $self->{partitions}; }
sub options { my $self = shift; return $self->{options}; }
sub foreign_key { my $self = shift; return $self->{foreign_key}; }

sub isa_field { my $self = shift; return $_[0] && $self->{fields}{$_[0]} ? 1 : 0; }
sub isa_primary { my $self = shift; return $_[0] && $self->{primary}{$_[0]} ? 1 : 0; }
sub isa_index { my $self = shift; return $_[0] && $self->{indices}{$_[0]} ? 1 : 0; }
sub is_unique { my $self = shift; return $_[0] && $self->{unique}{$_[0]} ? 1 : 0; }
sub is_spatial { my $self = shift; return $_[0] && $self->{spatial}{$_[0]} ? 1 : 0; }
sub is_fulltext { my $self = shift; return $_[0] && $self->{fulltext}{$_[0]} ? 1 : 0; }
sub is_auto_inc { my $self = shift; return $_[0] && $self->{auto_inc}{$_[0]} ? 1 : 0; }

sub is_partitioned { my $self = shift; return $_[0] && $self->{partitions}{$_[0]} ? 1 : 0; }
# ------------------------------------------------------------------------------
# Private Methods

Expand Down Expand Up @@ -206,6 +224,17 @@ sub _parse {
next;
}

if (/^(SPATIAL(?:\s+KEY|INDEX)?)\s+(\S+?)\s*\((.*)\)$/) {
my ($type, $key, $val) = ($1, $2, $3);
debug(4, "type: $type key: $key val: $val");
croak "SPATIAL index '$key' duplicated in table '$self->{name}'\n"
if $self->{fulltext}{$key};
$self->{indices}{$key} = $val;
$self->{spatial}{$key} = 1;
debug(4,"got SPATIAL index '$key': ($val)");
next;
}

if (/^(FULLTEXT(?:\s+KEY|INDEX)?)\s+(\S+?)\s*\((.*)\)$/) {
my ($type, $key, $val) = ($1, $2, $3);
croak "FULLTEXT index '$key' duplicated in table '$self->{name}'\n"
Expand All @@ -216,10 +245,53 @@ sub _parse {
next;
}

if (/^\)\s*(.*?);$/) { # end of table definition
if (/^\)\s*(.*?)(;?)$/) { # end of table definition
$self->{options} = $1;
debug(4,"got table options '$self->{options}'");
last;
if ($2){ # there is a ; at the end
debug(4,"got table options '$self->{options}'");
last;
}
debug(4,"got table options '$self->{options}' but no end ';'");
next;
}

if ($self->{options}) {
# option is set, but wait, there is more to this schema... e.g. a patition?
#
# got field def '/*!50100': PARTITION BY RANGE (HOUR(timestamp)) '
if(/^\/\*\!\d{5}\sPARTITION\sBY\s(\S+?)\s\((.+)\)/){
my ($func, $opt) = ($1, $2);
debug(4," got partition function:'$func' with op: '$opt'");
$self->{partition}{function} = $func;
$self->{partition}{option} = $opt;
next;
}
if($self->{partition}{function} eq "RANGE"){
if(/^\(?PARTITION (\S+?) VALUES (\S+?) THAN \(*(.*?)\)?\sENGINE = InnoDB(.*)/){
my ($name, $op, $val, $term) = ($1, "$2 THAN", $3, $4);
debug(4," got extended partition table options name:'$name' op: '$op' val: '$val' ");
$self->{partitions}{$name}{val} = $val;
$self->{partitions}{$name}{op} = $op;
if ($term =~ m/;/) {
debug(4," got last section - ending");
last;
}
next;
}
}
if($self->{partition}{function} eq "LIST"){
if(/^\(?PARTITION (\S+?) VALUES IN \(*(.*?)\)?\sENGINE = InnoDB(.*)/){
my ($name, $op, $val, $term) = ($1, "IN", $2, $3);
debug(4," got extended partition table options name:'$name' op: '$op' val: '$val' ");
$self->{partitions}{$name}{val} = $val;
$self->{partitions}{$name}{op} = $op;
if ($term =~ m/;/) {
debug(4," got last section - ending");
last;
}
next;
}
} # we can add other functions here such as hash... etc.
}

if (/^(\S+)\s*(.*)/) {
Expand Down
Loading