Merge lp:~percona-toolkit-dev/percona-toolkit/fix-sync-float-bug-1229861 into lp:~percona-toolkit-dev/percona-toolkit/release-2.2.5

Proposed by Daniel Nichter
Status: Merged
Approved by: Daniel Nichter
Approved revision: 632
Merged at revision: 631
Proposed branch: lp:~percona-toolkit-dev/percona-toolkit/fix-sync-float-bug-1229861
Merge into: lp:~percona-toolkit-dev/percona-toolkit/release-2.2.5
Diff against target: 242 lines (+97/-32)
5 files modified
bin/pt-table-sync (+24/-9)
lib/ChangeHandler.pm (+22/-9)
lib/Quoter.pm (+3/-0)
t/pt-table-sync/float_precision.t (+36/-14)
t/pt-table-sync/samples/sync-float.sql (+12/-0)
To merge this branch: bzr merge lp:~percona-toolkit-dev/percona-toolkit/fix-sync-float-bug-1229861
Reviewer Review Type Date Requested Status
Daniel Nichter Approve
Review via email: mp+190506@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Daniel Nichter (daniel-nichter) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'bin/pt-table-sync'
2--- bin/pt-table-sync 2013-08-08 19:28:36 +0000
3+++ bin/pt-table-sync 2013-10-10 22:59:17 +0000
4@@ -1873,6 +1873,8 @@
5 return $val if $val =~ m/^0x[0-9a-fA-F]+$/ # quote hex data
6 && !$args{is_char}; # unless is_char is true
7
8+ return $val if $args{is_float};
9+
10 $val =~ s/(['\\])/\\$1/g;
11 return "'$val'";
12 }
13@@ -3510,10 +3512,15 @@
14 my $types = $self->{tbl_struct}->{type_for};
15 return "UPDATE $self->{dst_db_tbl} SET "
16 . join(', ', map {
17- my $is_char = ($types->{$_} || '') =~ m/char|text/i;
18+ my $is_char = ($types->{$_} || '') =~ m/char|text/i;
19+ my $is_float = ($types->{$_} || '') =~ m/float|double/i;
20 $self->{Quoter}->quote($_)
21- . '=' . $self->{Quoter}->quote_val($row->{$_},
22- is_char => $is_char);
23+ . '='
24+ . $self->{Quoter}->quote_val(
25+ $row->{$_},
26+ is_char => $is_char,
27+ is_float => $is_float,
28+ );
29 } grep { !$in_where{$_} } @cols)
30 . " WHERE $where LIMIT 1";
31 }
32@@ -3552,10 +3559,16 @@
33 return "$verb INTO $self->{dst_db_tbl}("
34 . join(', ', map { $q->quote($_) } @cols)
35 . ') VALUES ('
36- . join(', ', map {
37- my $is_char = ($type_for->{$_} || '') =~ m/char|text/i;
38- $q->quote_val($row->{$_},
39- is_char => $is_char) } @cols )
40+ . join(', ',
41+ map {
42+ my $is_char = ($type_for->{$_} || '') =~ m/char|text/i;
43+ my $is_float = ($type_for->{$_} || '') =~ m/float|double/i;
44+ $q->quote_val(
45+ $row->{$_},
46+ is_char => $is_char,
47+ is_float => $is_float,
48+ )
49+ } @cols)
50 . ')';
51 }
52
53@@ -3564,9 +3577,11 @@
54 my @clauses = map {
55 my $val = $row->{$_};
56 my $sep = defined $val ? '=' : ' IS ';
57- my $is_char = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/char|text/i;
58+ my $is_char = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/char|text/i;
59+ my $is_float = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/float|double/i;
60 $self->{Quoter}->quote($_) . $sep . $self->{Quoter}->quote_val($val,
61- is_char => $is_char);
62+ is_char => $is_char,
63+ is_float => $is_float);
64 } @$cols;
65 return join(' AND ', @clauses);
66 }
67
68=== modified file 'lib/ChangeHandler.pm'
69--- lib/ChangeHandler.pm 2013-01-03 00:19:16 +0000
70+++ lib/ChangeHandler.pm 2013-10-10 22:59:17 +0000
71@@ -326,10 +326,15 @@
72 my $types = $self->{tbl_struct}->{type_for};
73 return "UPDATE $self->{dst_db_tbl} SET "
74 . join(', ', map {
75- my $is_char = ($types->{$_} || '') =~ m/char|text/i;
76+ my $is_char = ($types->{$_} || '') =~ m/char|text/i;
77+ my $is_float = ($types->{$_} || '') =~ m/float|double/i;
78 $self->{Quoter}->quote($_)
79- . '=' . $self->{Quoter}->quote_val($row->{$_},
80- is_char => $is_char);
81+ . '='
82+ . $self->{Quoter}->quote_val(
83+ $row->{$_},
84+ is_char => $is_char,
85+ is_float => $is_float,
86+ );
87 } grep { !$in_where{$_} } @cols)
88 . " WHERE $where LIMIT 1";
89 }
90@@ -399,10 +404,16 @@
91 return "$verb INTO $self->{dst_db_tbl}("
92 . join(', ', map { $q->quote($_) } @cols)
93 . ') VALUES ('
94- . join(', ', map {
95- my $is_char = ($type_for->{$_} || '') =~ m/char|text/i;
96- $q->quote_val($row->{$_},
97- is_char => $is_char) } @cols )
98+ . join(', ',
99+ map {
100+ my $is_char = ($type_for->{$_} || '') =~ m/char|text/i;
101+ my $is_float = ($type_for->{$_} || '') =~ m/float|double/i;
102+ $q->quote_val(
103+ $row->{$_},
104+ is_char => $is_char,
105+ is_float => $is_float,
106+ )
107+ } @cols)
108 . ')';
109 }
110
111@@ -420,9 +431,11 @@
112 my @clauses = map {
113 my $val = $row->{$_};
114 my $sep = defined $val ? '=' : ' IS ';
115- my $is_char = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/char|text/i;
116+ my $is_char = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/char|text/i;
117+ my $is_float = ($self->{tbl_struct}->{type_for}->{$_} || '') =~ m/float|double/i;
118 $self->{Quoter}->quote($_) . $sep . $self->{Quoter}->quote_val($val,
119- is_char => $is_char);
120+ is_char => $is_char,
121+ is_float => $is_float);
122 } @$cols;
123 return join(' AND ', @clauses);
124 }
125
126=== modified file 'lib/Quoter.pm'
127--- lib/Quoter.pm 2013-02-19 20:01:58 +0000
128+++ lib/Quoter.pm 2013-10-10 22:59:17 +0000
129@@ -77,6 +77,9 @@
130 return $val if $val =~ m/^0x[0-9a-fA-F]+$/ # quote hex data
131 && !$args{is_char}; # unless is_char is true
132
133+ # https://bugs.launchpad.net/percona-toolkit/+bug/1229861
134+ return $val if $args{is_float};
135+
136 # Quote and return non-numeric vals.
137 $val =~ s/(['\\])/\\$1/g;
138 return "'$val'";
139
140=== modified file 't/pt-table-sync/float_precision.t'
141--- t/pt-table-sync/float_precision.t 2012-07-11 18:21:47 +0000
142+++ t/pt-table-sync/float_precision.t 2013-10-10 22:59:17 +0000
143@@ -10,6 +10,7 @@
144 use warnings FATAL => 'all';
145 use English qw(-no_match_vars);
146 use Test::More;
147+use Data::Dumper;
148
149 use PerconaTest;
150 use Sandbox;
151@@ -27,21 +28,18 @@
152 elsif ( !$slave_dbh ) {
153 plan skip_all => 'Cannot connect to sandbox slave';
154 }
155-else {
156- plan tests => 3;
157-}
158-
159-$sb->wipe_clean($master_dbh);
160-$sb->wipe_clean($slave_dbh);
161+
162+my $master_dsn = $sb->dsn_for('master');
163+my $slave1_dsn = $sb->dsn_for('slave1');
164+
165+# #############################################################################
166+# Issue 410: mk-table-sync doesn't have --float-precision
167+# #############################################################################
168+
169 $sb->create_dbs($master_dbh, ['test']);
170-
171-# #############################################################################
172-# Issue 410: mk-table-sync doesn't have --float-precision
173-# #############################################################################
174-
175 $master_dbh->do('create table test.fl (id int not null primary key, f float(12,10), d double)');
176 $master_dbh->do('insert into test.fl values (1, 1.0000012, 2.0000012)');
177-sleep 1;
178+$sb->wait_for_slaves();
179 $slave_dbh->do('update test.fl set d = 2.0000013 where id = 1');
180
181 # The columns really are different at this point so we should
182@@ -50,7 +48,7 @@
183 $output = remove_traces($output);
184 is(
185 $output,
186- "REPLACE INTO `test`.`fl`(`id`, `f`, `d`) VALUES ('1', '1.0000011921', '2.0000012');
187+ "REPLACE INTO `test`.`fl`(`id`, `f`, `d`) VALUES ('1', 1.0000011921, 2.0000012);
188 ",
189 'No --float-precision so double col diff at high precision (issue 410)'
190 );
191@@ -66,9 +64,33 @@
192 );
193
194 # #############################################################################
195+# pt-table-sync quotes floats, prevents syncing
196+# https://bugs.launchpad.net/percona-toolkit/+bug/1229861
197+# #############################################################################
198+
199+$sb->load_file('master', "t/pt-table-sync/samples/sync-float.sql");
200+$slave_dbh->do("INSERT INTO sync_float_1229861.t (`c1`, `c2`, `c3`, `snrmin`, `snrmax`, `snravg`) VALUES (1,1,1,29.5,33.5,31.6)");
201+
202+$output = output(sub {
203+ pt_table_sync::main(
204+ "$master_dsn,D=sync_float_1229861,t=t",
205+ "$slave1_dsn",
206+ qw(--no-check-slave --print --execute))
207+ },
208+ stderr => 1,
209+);
210+
211+my $rows = $slave_dbh->selectall_arrayref("SELECT * FROM sync_float_1229861.t");
212+is_deeply(
213+ $rows,
214+ [],
215+ "Sync rows with float values (bug 1229861)"
216+) or diag(Dumper($rows), $output);
217+
218+# #############################################################################
219 # Done.
220 # #############################################################################
221 $sb->wipe_clean($master_dbh);
222 $sb->wipe_clean($slave_dbh);
223 ok($sb->ok(), "Sandbox servers") or BAIL_OUT(__FILE__ . " broke the sandbox");
224-exit;
225+done_testing;
226
227=== added file 't/pt-table-sync/samples/sync-float.sql'
228--- t/pt-table-sync/samples/sync-float.sql 1970-01-01 00:00:00 +0000
229+++ t/pt-table-sync/samples/sync-float.sql 2013-10-10 22:59:17 +0000
230@@ -0,0 +1,12 @@
231+DROP DATABASE IF EXISTS sync_float_1229861;
232+CREATE DATABASE sync_float_1229861;
233+USE sync_float_1229861;
234+CREATE TABLE `t` (
235+ `c1` int(10) DEFAULT NULL,
236+ `c2` int(10) DEFAULT NULL,
237+ `c3` int(10) DEFAULT NULL,
238+ `snrmin` float(3,1) DEFAULT NULL,
239+ `snrmax` float(3,1) DEFAULT NULL,
240+ `snravg` float(3,1) DEFAULT NULL,
241+ KEY `c2` (`c2`,`c3`)
242+) ENGINE=InnoDB;

Subscribers

People subscribed via source and target branches

to all changes: