diff --git a/bin/pt-table-sync b/bin/pt-table-sync index 814a4890..097fad74 100755 --- a/bin/pt-table-sync +++ b/bin/pt-table-sync @@ -1873,6 +1873,8 @@ sub quote_val { return $val if $val =~ m/^0x[0-9a-fA-F]+$/ # quote hex data && !$args{is_char}; # unless is_char is true + return $val if $args{is_float}; + $val =~ s/(['\\])/\\$1/g; return "'$val'"; } @@ -3510,10 +3512,15 @@ sub make_UPDATE { my $types = $self->{tbl_struct}->{type_for}; return "UPDATE $self->{dst_db_tbl} SET " . join(', ', map { - my $is_char = ($types->{$_} || '') =~ m/char|text/i; + my $is_char = ($types->{$_} || '') =~ m/char|text/i; + my $is_float = ($types->{$_} || '') =~ m/float|double/i; $self->{Quoter}->quote($_) - . '=' . $self->{Quoter}->quote_val($row->{$_}, - is_char => $is_char); + . '=' + . $self->{Quoter}->quote_val( + $row->{$_}, + is_char => $is_char, + is_float => $is_float, + ); } grep { !$in_where{$_} } @cols) . " WHERE $where LIMIT 1"; } @@ -3552,10 +3559,16 @@ sub make_row { return "$verb INTO $self->{dst_db_tbl}(" . join(', ', map { $q->quote($_) } @cols) . ') VALUES (' - . join(', ', map { - my $is_char = ($type_for->{$_} || '') =~ m/char|text/i; - $q->quote_val($row->{$_}, - is_char => $is_char) } @cols ) + . join(', ', + map { + my $is_char = ($type_for->{$_} || '') =~ m/char|text/i; + my $is_float = ($type_for->{$_} || '') =~ m/float|double/i; + $q->quote_val( + $row->{$_}, + is_char => $is_char, + is_float => $is_float, + ) + } @cols) . ')'; } @@ -3564,9 +3577,11 @@ sub make_where_clause { my @clauses = map { my $val = $row->{$_}; my $sep = defined $val ? '=' : ' IS '; - my $is_char = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/char|text/i; + my $is_char = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/char|text/i; + my $is_float = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/float|double/i; $self->{Quoter}->quote($_) . $sep . $self->{Quoter}->quote_val($val, - is_char => $is_char); + is_char => $is_char, + is_float => $is_float); } @$cols; return join(' AND ', @clauses); } diff --git a/lib/ChangeHandler.pm b/lib/ChangeHandler.pm index c8ac3977..26a24fa0 100644 --- a/lib/ChangeHandler.pm +++ b/lib/ChangeHandler.pm @@ -326,10 +326,15 @@ sub make_UPDATE { my $types = $self->{tbl_struct}->{type_for}; return "UPDATE $self->{dst_db_tbl} SET " . join(', ', map { - my $is_char = ($types->{$_} || '') =~ m/char|text/i; + my $is_char = ($types->{$_} || '') =~ m/char|text/i; + my $is_float = ($types->{$_} || '') =~ m/float|double/i; $self->{Quoter}->quote($_) - . '=' . $self->{Quoter}->quote_val($row->{$_}, - is_char => $is_char); + . '=' + . $self->{Quoter}->quote_val( + $row->{$_}, + is_char => $is_char, + is_float => $is_float, + ); } grep { !$in_where{$_} } @cols) . " WHERE $where LIMIT 1"; } @@ -399,10 +404,16 @@ sub make_row { return "$verb INTO $self->{dst_db_tbl}(" . join(', ', map { $q->quote($_) } @cols) . ') VALUES (' - . join(', ', map { - my $is_char = ($type_for->{$_} || '') =~ m/char|text/i; - $q->quote_val($row->{$_}, - is_char => $is_char) } @cols ) + . join(', ', + map { + my $is_char = ($type_for->{$_} || '') =~ m/char|text/i; + my $is_float = ($type_for->{$_} || '') =~ m/float|double/i; + $q->quote_val( + $row->{$_}, + is_char => $is_char, + is_float => $is_float, + ) + } @cols) . ')'; } @@ -420,9 +431,11 @@ sub make_where_clause { my @clauses = map { my $val = $row->{$_}; my $sep = defined $val ? '=' : ' IS '; - my $is_char = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/char|text/i; + my $is_char = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/char|text/i; + my $is_float = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/float|double/i; $self->{Quoter}->quote($_) . $sep . $self->{Quoter}->quote_val($val, - is_char => $is_char); + is_char => $is_char, + is_float => $is_float); } @$cols; return join(' AND ', @clauses); } diff --git a/lib/Quoter.pm b/lib/Quoter.pm index 091c4d4b..35edf120 100644 --- a/lib/Quoter.pm +++ b/lib/Quoter.pm @@ -77,6 +77,9 @@ sub quote_val { return $val if $val =~ m/^0x[0-9a-fA-F]+$/ # quote hex data && !$args{is_char}; # unless is_char is true + # https://bugs.launchpad.net/percona-toolkit/+bug/1229861 + return $val if $args{is_float}; + # Quote and return non-numeric vals. $val =~ s/(['\\])/\\$1/g; return "'$val'"; diff --git a/t/pt-table-sync/float_precision.t b/t/pt-table-sync/float_precision.t index c3e827d8..e49a3e01 100644 --- a/t/pt-table-sync/float_precision.t +++ b/t/pt-table-sync/float_precision.t @@ -48,7 +48,7 @@ $output = `$trunk/bin/pt-table-sync --sync-to-master h=127.1,P=12346,u=msandbox, $output = remove_traces($output); is( $output, - "REPLACE INTO `test`.`fl`(`id`, `f`, `d`) VALUES ('1', '1.0000011921', '2.0000012'); + "REPLACE INTO `test`.`fl`(`id`, `f`, `d`) VALUES ('1', 1.0000011921, 2.0000012); ", 'No --float-precision so double col diff at high precision (issue 410)' );