Skip to content

Commit

Permalink
Adding some more debug values for this (#2)
Browse files Browse the repository at this point in the history
* Adding some more debug values for this

* Maybe?

* make it a bit more concretet

* correct variable casting

* Adds partition methods to table

* Adds diffing in one direction

* Works both ways, needs to dedup though

* Compares partitions in both directions correctly

* Spelling mistakes and regexp greedy

* Commands masked as comments for version compatability are included

* Keep comments if they are actually commands

* More generic end finder for regular and partition ends, added partition function/option finder

* first test

* Correct tests

* Correct tests

* doh

* Adds test in other direction

* Comment unused tests

* Comment unused tests - but really
  • Loading branch information
tnosaj authored Jan 30, 2020
1 parent 0b6d656 commit 7624158
Show file tree
Hide file tree
Showing 4 changed files with 205 additions and 5 deletions.
49 changes: 49 additions & 0 deletions 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 @@ -334,6 +335,54 @@ sub _diff_indices {
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}' THAN '$partitions1->{$partition}{val}' changed");
my $changes = "ALTER TABLE $name1 DROP PARTITION $partition;";
$changes .= " # was VALUES '$partitions1->{$partition}{op}' THAN '$partitions1->{$partition}{val}'"
unless $self->{opts}{'no-old-defs'};
$changes .= "\nALTER TABLE $name1 ADD PARTITION (PARTITION $partition VALUES $partitions2->{$partition}{op} THAN ($partitions2->{$partition}{val}));\n";
push @changes, $changes;
}
} else {
# ALTER TABLE t1 DROP PARTITION p0, p1;
debug(3,"partition '$partition' for values '$partitions1->{$partition}{op}' THAN '$partitions1->{$partition}{val}' removed");
my $changes = "ALTER TABLE $name1 DROP PARTITION $partition;";
$changes .= " # was VALUES '$partitions1->{$partition}{op}' THAN '$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}' THAN '$partitions2->{$partition}{val}' added");
push @changes, "ALTER TABLE $name1 ADD PARTITION (PARTITION $partition VALUES $partitions2->{$partition}{op} THAN ($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
50 changes: 46 additions & 4 deletions lib/MySQL/Diff/Table.pm
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ 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);
Expand All @@ -23,6 +24,7 @@ MySQL::Diff::Table - Table Definition Class
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 @@ -102,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 Down Expand Up @@ -135,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 @@ -145,6 +155,7 @@ 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}; }

Expand All @@ -156,6 +167,7 @@ sub is_spatial { my $self = shift; return $_[0] && $self->{spatial}{$_[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 @@ -218,7 +230,7 @@ sub _parse {
croak "SPATIAL index '$key' duplicated in table '$self->{name}'\n"
if $self->{fulltext}{$key};
$self->{indices}{$key} = $val;
$self->{spatial}{$key} = 1;
$self->{spatial}{$key} = 1;
debug(4,"got SPATIAL index '$key': ($val)");
next;
}
Expand All @@ -233,10 +245,40 @@ 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, $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;
}
} # we can add other functions here such as hash... etc.
}

if (/^(\S+)\s*(.*)/) {
Expand Down
109 changes: 109 additions & 0 deletions t/all.t
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,80 @@ CREATE TABLE zap (
polygons multipolygon NOT NULL,
SPATIAL INDEX idx_polygons (polygons)
) DEFAULT CHARACTER SET utf8;
',

pip1 => '
CREATE TABLE pip (
id VARCHAR(255) NOT NULL,
timestamp DATETIME(3) NOT NULL,
PRIMARY KEY(id,timestamp)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
PARTITION BY RANGE (HOUR(timestamp)) (
PARTITION p0 VALUES LESS THAN (1),
PARTITION p1 VALUES LESS THAN (2),
PARTITION p2 VALUES LESS THAN (3),
PARTITION p3 VALUES LESS THAN (4),
PARTITION p4 VALUES LESS THAN (5),
PARTITION p5 VALUES LESS THAN (6),
PARTITION p6 VALUES LESS THAN (7),
PARTITION p7 VALUES LESS THAN (8),
PARTITION p8 VALUES LESS THAN (9),
PARTITION p9 VALUES LESS THAN (10),
PARTITION p10 VALUES LESS THAN (11),
PARTITION p11 VALUES LESS THAN (12),
PARTITION p12 VALUES LESS THAN (13),
PARTITION p13 VALUES LESS THAN (14),
PARTITION p14 VALUES LESS THAN (15),
PARTITION p15 VALUES LESS THAN (16),
PARTITION p16 VALUES LESS THAN (17),
PARTITION p17 VALUES LESS THAN (18),
PARTITION p18 VALUES LESS THAN (19),
PARTITION p19 VALUES LESS THAN (20),
PARTITION p20 VALUES LESS THAN (21),
PARTITION p21 VALUES LESS THAN (22),
PARTITION p22 VALUES LESS THAN MAXVALUE
);
',

pip2 => '
CREATE TABLE pip (
id VARCHAR(255) NOT NULL,
timestamp DATETIME(3) NOT NULL,
PRIMARY KEY(id,timestamp)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
PARTITION BY RANGE (HOUR(timestamp)) (
PARTITION p0 VALUES LESS THAN (1),
PARTITION p1 VALUES LESS THAN (2),
PARTITION p2 VALUES LESS THAN (3),
PARTITION p3 VALUES LESS THAN (4),
PARTITION p4 VALUES LESS THAN (5),
PARTITION p5 VALUES LESS THAN (6),
PARTITION p6 VALUES LESS THAN (7),
PARTITION p7 VALUES LESS THAN (8),
PARTITION p8 VALUES LESS THAN (9),
PARTITION p9 VALUES LESS THAN (10),
PARTITION p10 VALUES LESS THAN (11),
PARTITION p11 VALUES LESS THAN (12),
PARTITION p12 VALUES LESS THAN (13),
PARTITION p13 VALUES LESS THAN (14),
PARTITION p14 VALUES LESS THAN (15),
PARTITION p15 VALUES LESS THAN (16),
PARTITION p16 VALUES LESS THAN (17),
PARTITION p17 VALUES LESS THAN (18),
PARTITION p18 VALUES LESS THAN (19),
PARTITION p19 VALUES LESS THAN (20),
PARTITION p20 VALUES LESS THAN (21),
PARTITION p21 VALUES LESS THAN (22),
PARTITION p22 VALUES LESS THAN (23),
PARTITION p23 VALUES LESS THAN MAXVALUE
);
',
pip3 => '
CREATE TABLE pip (
id VARCHAR(255) NOT NULL,
timestamp DATETIME(3) NOT NULL,
PRIMARY KEY(id,timestamp)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
',

);
Expand Down Expand Up @@ -560,6 +634,41 @@ ALTER TABLE zap ADD SPATIAL INDEX idx_polygons (polygons);
## +++ file: tmp.db2
ALTER TABLE zap DROP INDEX idx_polygons; # was SPATIAL INDEX (polygons)
',
],

'Add partition' =>
[
{},
$tables{pip1},
$tables{pip2},
'## mysqldiff <VERSION>
##
## Run on <DATE>
##
## --- file: tmp.db1
## +++ file: tmp.db2
ALTER TABLE pip DROP PARTITION p22; # was VALUES \'LESS\' THAN \'MAXVALUE\'
ALTER TABLE pip ADD PARTITION (PARTITION p22 VALUES LESS THAN (23));
ALTER TABLE pip ADD PARTITION (PARTITION p23 VALUES LESS THAN (MAXVALUE));
',
],
'remove partition' =>
[
{},
$tables{pip2},
$tables{pip1},
'## mysqldiff <VERSION>
##
## Run on <DATE>
##
## --- file: tmp.db1
## +++ file: tmp.db2
ALTER TABLE pip DROP PARTITION p23; # was VALUES \'LESS\' THAN \'MAXVALUE\'
ALTER TABLE pip DROP PARTITION p22; # was VALUES \'LESS\' THAN \'23\'
ALTER TABLE pip ADD PARTITION (PARTITION p22 VALUES LESS THAN (MAXVALUE));
',
],
);
Expand Down

0 comments on commit 7624158

Please sign in to comment.