Merge lp:~percona-toolkit-dev/percona-toolkit/fix-password-comma-bug-886077 into lp:percona-toolkit/2.1
- fix-password-comma-bug-886077
- Merge into 2.1
Proposed by
Daniel Nichter
Status: | Merged |
---|---|
Merged at revision: | 263 |
Proposed branch: | lp:~percona-toolkit-dev/percona-toolkit/fix-password-comma-bug-886077 |
Merge into: | lp:percona-toolkit/2.1 |
Diff against target: |
996 lines (+297/-100) 26 files modified
bin/pt-archiver (+11/-6) bin/pt-config-diff (+4/-1) bin/pt-deadlock-logger (+11/-6) bin/pt-duplicate-key-checker (+11/-6) bin/pt-find (+11/-6) bin/pt-fk-error-logger (+11/-6) bin/pt-heartbeat (+11/-6) bin/pt-index-usage (+11/-6) bin/pt-kill (+4/-1) bin/pt-log-player (+11/-6) bin/pt-online-schema-change (+4/-1) bin/pt-query-advisor (+4/-1) bin/pt-query-digest (+11/-6) bin/pt-show-grants (+11/-6) bin/pt-slave-delay (+11/-6) bin/pt-slave-find (+11/-6) bin/pt-slave-restart (+11/-6) bin/pt-table-checksum (+4/-1) bin/pt-table-sync (+4/-1) bin/pt-table-usage (+4/-1) bin/pt-upgrade (+4/-1) bin/pt-variable-advisor (+11/-6) bin/pt-visual-explain (+11/-6) docs/percona-toolkit.pod (+14/-0) lib/DSNParser.pm (+6/-1) t/lib/DSNParser.t (+80/-1) |
To merge this branch: | bzr merge lp:~percona-toolkit-dev/percona-toolkit/fix-password-comma-bug-886077 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Daniel Nichter | Approve | ||
Review via email:
|
Commit message
Description of the change
To post a comment you must log in.
Revision history for this message
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
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-archiver' |
2 | --- bin/pt-archiver 2012-04-17 22:52:34 +0000 |
3 | +++ bin/pt-archiver 2012-05-24 17:33:24 +0000 |
4 | @@ -1454,6 +1454,8 @@ |
5 | $Data::Dumper::Indent = 0; |
6 | $Data::Dumper::Quotekeys = 0; |
7 | |
8 | +my $dsn_sep = qr/(?<!\\),/; |
9 | + |
10 | eval { |
11 | require DBI; |
12 | }; |
13 | @@ -1508,7 +1510,8 @@ |
14 | my %final_props; |
15 | my $opts = $self->{opts}; |
16 | |
17 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
18 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
19 | + $dsn_part =~ s/\\,/,/g; |
20 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
21 | $given_props{$prop_key} = $prop_val; |
22 | } |
23 | @@ -1567,12 +1570,14 @@ |
24 | sub as_string { |
25 | my ( $self, $dsn, $props ) = @_; |
26 | return $dsn unless ref $dsn; |
27 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
28 | + my @keys = $props ? @$props : sort keys %$dsn; |
29 | return join(',', |
30 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
31 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
32 | - grep { !$props || $allowed{$_} } |
33 | - sort keys %$dsn ); |
34 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
35 | + grep { |
36 | + exists $self->{opts}->{$_} |
37 | + && exists $dsn->{$_} |
38 | + && defined $dsn->{$_} |
39 | + } @keys); |
40 | } |
41 | |
42 | sub usage { |
43 | |
44 | === modified file 'bin/pt-config-diff' |
45 | --- bin/pt-config-diff 2012-04-03 19:42:45 +0000 |
46 | +++ bin/pt-config-diff 2012-05-24 17:33:24 +0000 |
47 | @@ -1053,6 +1053,8 @@ |
48 | $Data::Dumper::Indent = 0; |
49 | $Data::Dumper::Quotekeys = 0; |
50 | |
51 | +my $dsn_sep = qr/(?<!\\),/; |
52 | + |
53 | eval { |
54 | require DBI; |
55 | }; |
56 | @@ -1107,7 +1109,8 @@ |
57 | my %final_props; |
58 | my $opts = $self->{opts}; |
59 | |
60 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
61 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
62 | + $dsn_part =~ s/\\,/,/g; |
63 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
64 | $given_props{$prop_key} = $prop_val; |
65 | } |
66 | |
67 | === modified file 'bin/pt-deadlock-logger' |
68 | --- bin/pt-deadlock-logger 2012-04-03 19:42:45 +0000 |
69 | +++ bin/pt-deadlock-logger 2012-05-24 17:33:24 +0000 |
70 | @@ -1213,6 +1213,8 @@ |
71 | $Data::Dumper::Indent = 0; |
72 | $Data::Dumper::Quotekeys = 0; |
73 | |
74 | +my $dsn_sep = qr/(?<!\\),/; |
75 | + |
76 | eval { |
77 | require DBI; |
78 | }; |
79 | @@ -1267,7 +1269,8 @@ |
80 | my %final_props; |
81 | my $opts = $self->{opts}; |
82 | |
83 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
84 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
85 | + $dsn_part =~ s/\\,/,/g; |
86 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
87 | $given_props{$prop_key} = $prop_val; |
88 | } |
89 | @@ -1326,12 +1329,14 @@ |
90 | sub as_string { |
91 | my ( $self, $dsn, $props ) = @_; |
92 | return $dsn unless ref $dsn; |
93 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
94 | + my @keys = $props ? @$props : sort keys %$dsn; |
95 | return join(',', |
96 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
97 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
98 | - grep { !$props || $allowed{$_} } |
99 | - sort keys %$dsn ); |
100 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
101 | + grep { |
102 | + exists $self->{opts}->{$_} |
103 | + && exists $dsn->{$_} |
104 | + && defined $dsn->{$_} |
105 | + } @keys); |
106 | } |
107 | |
108 | sub usage { |
109 | |
110 | === modified file 'bin/pt-duplicate-key-checker' |
111 | --- bin/pt-duplicate-key-checker 2012-05-15 01:05:32 +0000 |
112 | +++ bin/pt-duplicate-key-checker 2012-05-24 17:33:24 +0000 |
113 | @@ -923,6 +923,8 @@ |
114 | $Data::Dumper::Indent = 0; |
115 | $Data::Dumper::Quotekeys = 0; |
116 | |
117 | +my $dsn_sep = qr/(?<!\\),/; |
118 | + |
119 | eval { |
120 | require DBI; |
121 | }; |
122 | @@ -977,7 +979,8 @@ |
123 | my %final_props; |
124 | my $opts = $self->{opts}; |
125 | |
126 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
127 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
128 | + $dsn_part =~ s/\\,/,/g; |
129 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
130 | $given_props{$prop_key} = $prop_val; |
131 | } |
132 | @@ -1036,12 +1039,14 @@ |
133 | sub as_string { |
134 | my ( $self, $dsn, $props ) = @_; |
135 | return $dsn unless ref $dsn; |
136 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
137 | + my @keys = $props ? @$props : sort keys %$dsn; |
138 | return join(',', |
139 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
140 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
141 | - grep { !$props || $allowed{$_} } |
142 | - sort keys %$dsn ); |
143 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
144 | + grep { |
145 | + exists $self->{opts}->{$_} |
146 | + && exists $dsn->{$_} |
147 | + && defined $dsn->{$_} |
148 | + } @keys); |
149 | } |
150 | |
151 | sub usage { |
152 | |
153 | === modified file 'bin/pt-find' |
154 | --- bin/pt-find 2012-04-03 19:42:45 +0000 |
155 | +++ bin/pt-find 2012-05-24 17:33:24 +0000 |
156 | @@ -28,6 +28,8 @@ |
157 | $Data::Dumper::Indent = 0; |
158 | $Data::Dumper::Quotekeys = 0; |
159 | |
160 | +my $dsn_sep = qr/(?<!\\),/; |
161 | + |
162 | eval { |
163 | require DBI; |
164 | }; |
165 | @@ -82,7 +84,8 @@ |
166 | my %final_props; |
167 | my $opts = $self->{opts}; |
168 | |
169 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
170 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
171 | + $dsn_part =~ s/\\,/,/g; |
172 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
173 | $given_props{$prop_key} = $prop_val; |
174 | } |
175 | @@ -141,12 +144,14 @@ |
176 | sub as_string { |
177 | my ( $self, $dsn, $props ) = @_; |
178 | return $dsn unless ref $dsn; |
179 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
180 | + my @keys = $props ? @$props : sort keys %$dsn; |
181 | return join(',', |
182 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
183 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
184 | - grep { !$props || $allowed{$_} } |
185 | - sort keys %$dsn ); |
186 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
187 | + grep { |
188 | + exists $self->{opts}->{$_} |
189 | + && exists $dsn->{$_} |
190 | + && defined $dsn->{$_} |
191 | + } @keys); |
192 | } |
193 | |
194 | sub usage { |
195 | |
196 | === modified file 'bin/pt-fk-error-logger' |
197 | --- bin/pt-fk-error-logger 2012-04-03 19:42:45 +0000 |
198 | +++ bin/pt-fk-error-logger 2012-05-24 17:33:24 +0000 |
199 | @@ -1130,6 +1130,8 @@ |
200 | $Data::Dumper::Indent = 0; |
201 | $Data::Dumper::Quotekeys = 0; |
202 | |
203 | +my $dsn_sep = qr/(?<!\\),/; |
204 | + |
205 | eval { |
206 | require DBI; |
207 | }; |
208 | @@ -1184,7 +1186,8 @@ |
209 | my %final_props; |
210 | my $opts = $self->{opts}; |
211 | |
212 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
213 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
214 | + $dsn_part =~ s/\\,/,/g; |
215 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
216 | $given_props{$prop_key} = $prop_val; |
217 | } |
218 | @@ -1243,12 +1246,14 @@ |
219 | sub as_string { |
220 | my ( $self, $dsn, $props ) = @_; |
221 | return $dsn unless ref $dsn; |
222 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
223 | + my @keys = $props ? @$props : sort keys %$dsn; |
224 | return join(',', |
225 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
226 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
227 | - grep { !$props || $allowed{$_} } |
228 | - sort keys %$dsn ); |
229 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
230 | + grep { |
231 | + exists $self->{opts}->{$_} |
232 | + && exists $dsn->{$_} |
233 | + && defined $dsn->{$_} |
234 | + } @keys); |
235 | } |
236 | |
237 | sub usage { |
238 | |
239 | === modified file 'bin/pt-heartbeat' |
240 | --- bin/pt-heartbeat 2012-05-17 14:54:36 +0000 |
241 | +++ bin/pt-heartbeat 2012-05-24 17:33:24 +0000 |
242 | @@ -1761,6 +1761,8 @@ |
243 | $Data::Dumper::Indent = 0; |
244 | $Data::Dumper::Quotekeys = 0; |
245 | |
246 | +my $dsn_sep = qr/(?<!\\),/; |
247 | + |
248 | eval { |
249 | require DBI; |
250 | }; |
251 | @@ -1815,7 +1817,8 @@ |
252 | my %final_props; |
253 | my $opts = $self->{opts}; |
254 | |
255 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
256 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
257 | + $dsn_part =~ s/\\,/,/g; |
258 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
259 | $given_props{$prop_key} = $prop_val; |
260 | } |
261 | @@ -1874,12 +1877,14 @@ |
262 | sub as_string { |
263 | my ( $self, $dsn, $props ) = @_; |
264 | return $dsn unless ref $dsn; |
265 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
266 | + my @keys = $props ? @$props : sort keys %$dsn; |
267 | return join(',', |
268 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
269 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
270 | - grep { !$props || $allowed{$_} } |
271 | - sort keys %$dsn ); |
272 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
273 | + grep { |
274 | + exists $self->{opts}->{$_} |
275 | + && exists $dsn->{$_} |
276 | + && defined $dsn->{$_} |
277 | + } @keys); |
278 | } |
279 | |
280 | sub usage { |
281 | |
282 | === modified file 'bin/pt-index-usage' |
283 | --- bin/pt-index-usage 2012-04-03 19:42:45 +0000 |
284 | +++ bin/pt-index-usage 2012-05-24 17:33:24 +0000 |
285 | @@ -28,6 +28,8 @@ |
286 | $Data::Dumper::Indent = 0; |
287 | $Data::Dumper::Quotekeys = 0; |
288 | |
289 | +my $dsn_sep = qr/(?<!\\),/; |
290 | + |
291 | eval { |
292 | require DBI; |
293 | }; |
294 | @@ -82,7 +84,8 @@ |
295 | my %final_props; |
296 | my $opts = $self->{opts}; |
297 | |
298 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
299 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
300 | + $dsn_part =~ s/\\,/,/g; |
301 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
302 | $given_props{$prop_key} = $prop_val; |
303 | } |
304 | @@ -141,12 +144,14 @@ |
305 | sub as_string { |
306 | my ( $self, $dsn, $props ) = @_; |
307 | return $dsn unless ref $dsn; |
308 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
309 | + my @keys = $props ? @$props : sort keys %$dsn; |
310 | return join(',', |
311 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
312 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
313 | - grep { !$props || $allowed{$_} } |
314 | - sort keys %$dsn ); |
315 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
316 | + grep { |
317 | + exists $self->{opts}->{$_} |
318 | + && exists $dsn->{$_} |
319 | + && defined $dsn->{$_} |
320 | + } @keys); |
321 | } |
322 | |
323 | sub usage { |
324 | |
325 | === modified file 'bin/pt-kill' |
326 | --- bin/pt-kill 2012-04-03 19:42:45 +0000 |
327 | +++ bin/pt-kill 2012-05-24 17:33:24 +0000 |
328 | @@ -1136,6 +1136,8 @@ |
329 | $Data::Dumper::Indent = 0; |
330 | $Data::Dumper::Quotekeys = 0; |
331 | |
332 | +my $dsn_sep = qr/(?<!\\),/; |
333 | + |
334 | eval { |
335 | require DBI; |
336 | }; |
337 | @@ -1190,7 +1192,8 @@ |
338 | my %final_props; |
339 | my $opts = $self->{opts}; |
340 | |
341 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
342 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
343 | + $dsn_part =~ s/\\,/,/g; |
344 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
345 | $given_props{$prop_key} = $prop_val; |
346 | } |
347 | |
348 | === modified file 'bin/pt-log-player' |
349 | --- bin/pt-log-player 2012-04-03 19:42:45 +0000 |
350 | +++ bin/pt-log-player 2012-05-24 17:33:24 +0000 |
351 | @@ -2008,6 +2008,8 @@ |
352 | $Data::Dumper::Indent = 0; |
353 | $Data::Dumper::Quotekeys = 0; |
354 | |
355 | +my $dsn_sep = qr/(?<!\\),/; |
356 | + |
357 | eval { |
358 | require DBI; |
359 | }; |
360 | @@ -2062,7 +2064,8 @@ |
361 | my %final_props; |
362 | my $opts = $self->{opts}; |
363 | |
364 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
365 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
366 | + $dsn_part =~ s/\\,/,/g; |
367 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
368 | $given_props{$prop_key} = $prop_val; |
369 | } |
370 | @@ -2121,12 +2124,14 @@ |
371 | sub as_string { |
372 | my ( $self, $dsn, $props ) = @_; |
373 | return $dsn unless ref $dsn; |
374 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
375 | + my @keys = $props ? @$props : sort keys %$dsn; |
376 | return join(',', |
377 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
378 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
379 | - grep { !$props || $allowed{$_} } |
380 | - sort keys %$dsn ); |
381 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
382 | + grep { |
383 | + exists $self->{opts}->{$_} |
384 | + && exists $dsn->{$_} |
385 | + && defined $dsn->{$_} |
386 | + } @keys); |
387 | } |
388 | |
389 | sub usage { |
390 | |
391 | === modified file 'bin/pt-online-schema-change' |
392 | --- bin/pt-online-schema-change 2012-05-17 14:54:36 +0000 |
393 | +++ bin/pt-online-schema-change 2012-05-24 17:33:24 +0000 |
394 | @@ -1136,6 +1136,8 @@ |
395 | $Data::Dumper::Indent = 0; |
396 | $Data::Dumper::Quotekeys = 0; |
397 | |
398 | +my $dsn_sep = qr/(?<!\\),/; |
399 | + |
400 | eval { |
401 | require DBI; |
402 | }; |
403 | @@ -1190,7 +1192,8 @@ |
404 | my %final_props; |
405 | my $opts = $self->{opts}; |
406 | |
407 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
408 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
409 | + $dsn_part =~ s/\\,/,/g; |
410 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
411 | $given_props{$prop_key} = $prop_val; |
412 | } |
413 | |
414 | === modified file 'bin/pt-query-advisor' |
415 | --- bin/pt-query-advisor 2012-04-03 19:42:45 +0000 |
416 | +++ bin/pt-query-advisor 2012-05-24 17:33:24 +0000 |
417 | @@ -28,6 +28,8 @@ |
418 | $Data::Dumper::Indent = 0; |
419 | $Data::Dumper::Quotekeys = 0; |
420 | |
421 | +my $dsn_sep = qr/(?<!\\),/; |
422 | + |
423 | eval { |
424 | require DBI; |
425 | }; |
426 | @@ -82,7 +84,8 @@ |
427 | my %final_props; |
428 | my $opts = $self->{opts}; |
429 | |
430 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
431 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
432 | + $dsn_part =~ s/\\,/,/g; |
433 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
434 | $given_props{$prop_key} = $prop_val; |
435 | } |
436 | |
437 | === modified file 'bin/pt-query-digest' |
438 | --- bin/pt-query-digest 2012-05-23 22:07:05 +0000 |
439 | +++ bin/pt-query-digest 2012-05-24 17:33:24 +0000 |
440 | @@ -28,6 +28,8 @@ |
441 | $Data::Dumper::Indent = 0; |
442 | $Data::Dumper::Quotekeys = 0; |
443 | |
444 | +my $dsn_sep = qr/(?<!\\),/; |
445 | + |
446 | eval { |
447 | require DBI; |
448 | }; |
449 | @@ -82,7 +84,8 @@ |
450 | my %final_props; |
451 | my $opts = $self->{opts}; |
452 | |
453 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
454 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
455 | + $dsn_part =~ s/\\,/,/g; |
456 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
457 | $given_props{$prop_key} = $prop_val; |
458 | } |
459 | @@ -141,12 +144,14 @@ |
460 | sub as_string { |
461 | my ( $self, $dsn, $props ) = @_; |
462 | return $dsn unless ref $dsn; |
463 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
464 | + my @keys = $props ? @$props : sort keys %$dsn; |
465 | return join(',', |
466 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
467 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
468 | - grep { !$props || $allowed{$_} } |
469 | - sort keys %$dsn ); |
470 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
471 | + grep { |
472 | + exists $self->{opts}->{$_} |
473 | + && exists $dsn->{$_} |
474 | + && defined $dsn->{$_} |
475 | + } @keys); |
476 | } |
477 | |
478 | sub usage { |
479 | |
480 | === modified file 'bin/pt-show-grants' |
481 | --- bin/pt-show-grants 2012-04-03 19:42:45 +0000 |
482 | +++ bin/pt-show-grants 2012-05-24 17:33:24 +0000 |
483 | @@ -1053,6 +1053,8 @@ |
484 | $Data::Dumper::Indent = 0; |
485 | $Data::Dumper::Quotekeys = 0; |
486 | |
487 | +my $dsn_sep = qr/(?<!\\),/; |
488 | + |
489 | eval { |
490 | require DBI; |
491 | }; |
492 | @@ -1107,7 +1109,8 @@ |
493 | my %final_props; |
494 | my $opts = $self->{opts}; |
495 | |
496 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
497 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
498 | + $dsn_part =~ s/\\,/,/g; |
499 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
500 | $given_props{$prop_key} = $prop_val; |
501 | } |
502 | @@ -1166,12 +1169,14 @@ |
503 | sub as_string { |
504 | my ( $self, $dsn, $props ) = @_; |
505 | return $dsn unless ref $dsn; |
506 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
507 | + my @keys = $props ? @$props : sort keys %$dsn; |
508 | return join(',', |
509 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
510 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
511 | - grep { !$props || $allowed{$_} } |
512 | - sort keys %$dsn ); |
513 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
514 | + grep { |
515 | + exists $self->{opts}->{$_} |
516 | + && exists $dsn->{$_} |
517 | + && defined $dsn->{$_} |
518 | + } @keys); |
519 | } |
520 | |
521 | sub usage { |
522 | |
523 | === modified file 'bin/pt-slave-delay' |
524 | --- bin/pt-slave-delay 2012-04-03 19:42:45 +0000 |
525 | +++ bin/pt-slave-delay 2012-05-24 17:33:24 +0000 |
526 | @@ -1136,6 +1136,8 @@ |
527 | $Data::Dumper::Indent = 0; |
528 | $Data::Dumper::Quotekeys = 0; |
529 | |
530 | +my $dsn_sep = qr/(?<!\\),/; |
531 | + |
532 | eval { |
533 | require DBI; |
534 | }; |
535 | @@ -1190,7 +1192,8 @@ |
536 | my %final_props; |
537 | my $opts = $self->{opts}; |
538 | |
539 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
540 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
541 | + $dsn_part =~ s/\\,/,/g; |
542 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
543 | $given_props{$prop_key} = $prop_val; |
544 | } |
545 | @@ -1249,12 +1252,14 @@ |
546 | sub as_string { |
547 | my ( $self, $dsn, $props ) = @_; |
548 | return $dsn unless ref $dsn; |
549 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
550 | + my @keys = $props ? @$props : sort keys %$dsn; |
551 | return join(',', |
552 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
553 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
554 | - grep { !$props || $allowed{$_} } |
555 | - sort keys %$dsn ); |
556 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
557 | + grep { |
558 | + exists $self->{opts}->{$_} |
559 | + && exists $dsn->{$_} |
560 | + && defined $dsn->{$_} |
561 | + } @keys); |
562 | } |
563 | |
564 | sub usage { |
565 | |
566 | === modified file 'bin/pt-slave-find' |
567 | --- bin/pt-slave-find 2012-05-17 14:54:36 +0000 |
568 | +++ bin/pt-slave-find 2012-05-24 17:33:24 +0000 |
569 | @@ -1053,6 +1053,8 @@ |
570 | $Data::Dumper::Indent = 0; |
571 | $Data::Dumper::Quotekeys = 0; |
572 | |
573 | +my $dsn_sep = qr/(?<!\\),/; |
574 | + |
575 | eval { |
576 | require DBI; |
577 | }; |
578 | @@ -1107,7 +1109,8 @@ |
579 | my %final_props; |
580 | my $opts = $self->{opts}; |
581 | |
582 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
583 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
584 | + $dsn_part =~ s/\\,/,/g; |
585 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
586 | $given_props{$prop_key} = $prop_val; |
587 | } |
588 | @@ -1166,12 +1169,14 @@ |
589 | sub as_string { |
590 | my ( $self, $dsn, $props ) = @_; |
591 | return $dsn unless ref $dsn; |
592 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
593 | + my @keys = $props ? @$props : sort keys %$dsn; |
594 | return join(',', |
595 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
596 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
597 | - grep { !$props || $allowed{$_} } |
598 | - sort keys %$dsn ); |
599 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
600 | + grep { |
601 | + exists $self->{opts}->{$_} |
602 | + && exists $dsn->{$_} |
603 | + && defined $dsn->{$_} |
604 | + } @keys); |
605 | } |
606 | |
607 | sub usage { |
608 | |
609 | === modified file 'bin/pt-slave-restart' |
610 | --- bin/pt-slave-restart 2012-05-17 14:54:36 +0000 |
611 | +++ bin/pt-slave-restart 2012-05-24 17:33:24 +0000 |
612 | @@ -1213,6 +1213,8 @@ |
613 | $Data::Dumper::Indent = 0; |
614 | $Data::Dumper::Quotekeys = 0; |
615 | |
616 | +my $dsn_sep = qr/(?<!\\),/; |
617 | + |
618 | eval { |
619 | require DBI; |
620 | }; |
621 | @@ -1267,7 +1269,8 @@ |
622 | my %final_props; |
623 | my $opts = $self->{opts}; |
624 | |
625 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
626 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
627 | + $dsn_part =~ s/\\,/,/g; |
628 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
629 | $given_props{$prop_key} = $prop_val; |
630 | } |
631 | @@ -1326,12 +1329,14 @@ |
632 | sub as_string { |
633 | my ( $self, $dsn, $props ) = @_; |
634 | return $dsn unless ref $dsn; |
635 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
636 | + my @keys = $props ? @$props : sort keys %$dsn; |
637 | return join(',', |
638 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
639 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
640 | - grep { !$props || $allowed{$_} } |
641 | - sort keys %$dsn ); |
642 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
643 | + grep { |
644 | + exists $self->{opts}->{$_} |
645 | + && exists $dsn->{$_} |
646 | + && defined $dsn->{$_} |
647 | + } @keys); |
648 | } |
649 | |
650 | sub usage { |
651 | |
652 | === modified file 'bin/pt-table-checksum' |
653 | --- bin/pt-table-checksum 2012-05-18 15:05:43 +0000 |
654 | +++ bin/pt-table-checksum 2012-05-24 17:33:24 +0000 |
655 | @@ -28,6 +28,8 @@ |
656 | $Data::Dumper::Indent = 0; |
657 | $Data::Dumper::Quotekeys = 0; |
658 | |
659 | +my $dsn_sep = qr/(?<!\\),/; |
660 | + |
661 | eval { |
662 | require DBI; |
663 | }; |
664 | @@ -82,7 +84,8 @@ |
665 | my %final_props; |
666 | my $opts = $self->{opts}; |
667 | |
668 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
669 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
670 | + $dsn_part =~ s/\\,/,/g; |
671 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
672 | $given_props{$prop_key} = $prop_val; |
673 | } |
674 | |
675 | === modified file 'bin/pt-table-sync' |
676 | --- bin/pt-table-sync 2012-05-22 17:47:24 +0000 |
677 | +++ bin/pt-table-sync 2012-05-24 17:33:24 +0000 |
678 | @@ -1172,6 +1172,8 @@ |
679 | $Data::Dumper::Indent = 0; |
680 | $Data::Dumper::Quotekeys = 0; |
681 | |
682 | +my $dsn_sep = qr/(?<!\\),/; |
683 | + |
684 | eval { |
685 | require DBI; |
686 | }; |
687 | @@ -1226,7 +1228,8 @@ |
688 | my %final_props; |
689 | my $opts = $self->{opts}; |
690 | |
691 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
692 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
693 | + $dsn_part =~ s/\\,/,/g; |
694 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
695 | $given_props{$prop_key} = $prop_val; |
696 | } |
697 | |
698 | === modified file 'bin/pt-table-usage' |
699 | --- bin/pt-table-usage 2012-04-03 19:42:45 +0000 |
700 | +++ bin/pt-table-usage 2012-05-24 17:33:24 +0000 |
701 | @@ -28,6 +28,8 @@ |
702 | $Data::Dumper::Indent = 0; |
703 | $Data::Dumper::Quotekeys = 0; |
704 | |
705 | +my $dsn_sep = qr/(?<!\\),/; |
706 | + |
707 | eval { |
708 | require DBI; |
709 | }; |
710 | @@ -82,7 +84,8 @@ |
711 | my %final_props; |
712 | my $opts = $self->{opts}; |
713 | |
714 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
715 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
716 | + $dsn_part =~ s/\\,/,/g; |
717 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
718 | $given_props{$prop_key} = $prop_val; |
719 | } |
720 | |
721 | === modified file 'bin/pt-upgrade' |
722 | --- bin/pt-upgrade 2012-04-03 19:42:45 +0000 |
723 | +++ bin/pt-upgrade 2012-05-24 17:33:24 +0000 |
724 | @@ -28,6 +28,8 @@ |
725 | $Data::Dumper::Indent = 0; |
726 | $Data::Dumper::Quotekeys = 0; |
727 | |
728 | +my $dsn_sep = qr/(?<!\\),/; |
729 | + |
730 | eval { |
731 | require DBI; |
732 | }; |
733 | @@ -82,7 +84,8 @@ |
734 | my %final_props; |
735 | my $opts = $self->{opts}; |
736 | |
737 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
738 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
739 | + $dsn_part =~ s/\\,/,/g; |
740 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
741 | $given_props{$prop_key} = $prop_val; |
742 | } |
743 | |
744 | === modified file 'bin/pt-variable-advisor' |
745 | --- bin/pt-variable-advisor 2012-04-03 19:42:45 +0000 |
746 | +++ bin/pt-variable-advisor 2012-05-24 17:33:24 +0000 |
747 | @@ -1053,6 +1053,8 @@ |
748 | $Data::Dumper::Indent = 0; |
749 | $Data::Dumper::Quotekeys = 0; |
750 | |
751 | +my $dsn_sep = qr/(?<!\\),/; |
752 | + |
753 | eval { |
754 | require DBI; |
755 | }; |
756 | @@ -1107,7 +1109,8 @@ |
757 | my %final_props; |
758 | my $opts = $self->{opts}; |
759 | |
760 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
761 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
762 | + $dsn_part =~ s/\\,/,/g; |
763 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
764 | $given_props{$prop_key} = $prop_val; |
765 | } |
766 | @@ -1166,12 +1169,14 @@ |
767 | sub as_string { |
768 | my ( $self, $dsn, $props ) = @_; |
769 | return $dsn unless ref $dsn; |
770 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
771 | + my @keys = $props ? @$props : sort keys %$dsn; |
772 | return join(',', |
773 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
774 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
775 | - grep { !$props || $allowed{$_} } |
776 | - sort keys %$dsn ); |
777 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
778 | + grep { |
779 | + exists $self->{opts}->{$_} |
780 | + && exists $dsn->{$_} |
781 | + && defined $dsn->{$_} |
782 | + } @keys); |
783 | } |
784 | |
785 | sub usage { |
786 | |
787 | === modified file 'bin/pt-visual-explain' |
788 | --- bin/pt-visual-explain 2012-04-03 19:42:45 +0000 |
789 | +++ bin/pt-visual-explain 2012-05-24 17:33:24 +0000 |
790 | @@ -1725,6 +1725,8 @@ |
791 | $Data::Dumper::Indent = 0; |
792 | $Data::Dumper::Quotekeys = 0; |
793 | |
794 | +my $dsn_sep = qr/(?<!\\),/; |
795 | + |
796 | eval { |
797 | require DBI; |
798 | }; |
799 | @@ -1779,7 +1781,8 @@ |
800 | my %final_props; |
801 | my $opts = $self->{opts}; |
802 | |
803 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
804 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
805 | + $dsn_part =~ s/\\,/,/g; |
806 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
807 | $given_props{$prop_key} = $prop_val; |
808 | } |
809 | @@ -1838,12 +1841,14 @@ |
810 | sub as_string { |
811 | my ( $self, $dsn, $props ) = @_; |
812 | return $dsn unless ref $dsn; |
813 | - my %allowed = $props ? map { $_=>1 } @$props : (); |
814 | + my @keys = $props ? @$props : sort keys %$dsn; |
815 | return join(',', |
816 | - map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
817 | - grep { defined $dsn->{$_} && $self->{opts}->{$_} } |
818 | - grep { !$props || $allowed{$_} } |
819 | - sort keys %$dsn ); |
820 | + map { "$_=" . ($_ eq 'p' ? '...' : $dsn->{$_}) } |
821 | + grep { |
822 | + exists $self->{opts}->{$_} |
823 | + && exists $dsn->{$_} |
824 | + && defined $dsn->{$_} |
825 | + } @keys); |
826 | } |
827 | |
828 | sub usage { |
829 | |
830 | === modified file 'docs/percona-toolkit.pod' |
831 | --- docs/percona-toolkit.pod 2012-04-03 19:42:45 +0000 |
832 | +++ docs/percona-toolkit.pod 2012-05-24 17:33:24 +0000 |
833 | @@ -313,6 +313,20 @@ |
834 | key part. For example, if DSN C<h=host1> and option C<--port=12345> are |
835 | specified, then the tool automatically adds C<P=12345> to DSN. |
836 | |
837 | +=head2 ESCAPING VALUES |
838 | + |
839 | +DSNs are usually specified on the command line, so shell quoting and escaping |
840 | +must be taken into account. Special characters, like asterisk (C<*>), need |
841 | +to be quoted and/or escaped properly to be passed as literal characters in |
842 | +DSN values. |
843 | + |
844 | +Since DSN parts are separated by commas, literal commas in DSN values must |
845 | +be escaped with a single backslash (C<\>). And since a backslash is |
846 | +the escape character for most shells, two backslashes are required to pass |
847 | +a literal backslash. For example, if the username is literally C<my,name>, |
848 | +it must be specified as C<my\\,name> on most shells. This applies to DSNs |
849 | +and DSN-related options like C<--user>. |
850 | + |
851 | =head2 KEY PARTS |
852 | |
853 | Many of the tools add more parts to DSNs for special purposes, and sometimes |
854 | |
855 | === modified file 'lib/DSNParser.pm' |
856 | --- lib/DSNParser.pm 2012-01-19 19:46:56 +0000 |
857 | +++ lib/DSNParser.pm 2012-05-24 17:33:24 +0000 |
858 | @@ -32,6 +32,10 @@ |
859 | $Data::Dumper::Indent = 0; |
860 | $Data::Dumper::Quotekeys = 0; |
861 | |
862 | +# Passwords may contain commas. |
863 | +# https://bugs.launchpad.net/percona-toolkit/+bug/886077 |
864 | +my $dsn_sep = qr/(?<!\\),/; |
865 | + |
866 | eval { |
867 | require DBI; |
868 | }; |
869 | @@ -126,7 +130,8 @@ |
870 | my $opts = $self->{opts}; |
871 | |
872 | # Parse given props |
873 | - foreach my $dsn_part ( split(/,/, $dsn) ) { |
874 | + foreach my $dsn_part ( split($dsn_sep, $dsn) ) { |
875 | + $dsn_part =~ s/\\,/,/g; |
876 | if ( my ($prop_key, $prop_val) = $dsn_part =~ m/^(.)=(.*)$/ ) { |
877 | # Handle the typical DSN parts like h=host, P=3306, etc. |
878 | $given_props{$prop_key} = $prop_val; |
879 | |
880 | === modified file 't/lib/DSNParser.t' |
881 | --- t/lib/DSNParser.t 2012-03-06 13:56:08 +0000 |
882 | +++ t/lib/DSNParser.t 2012-05-24 17:33:24 +0000 |
883 | @@ -9,12 +9,14 @@ |
884 | use strict; |
885 | use warnings FATAL => 'all'; |
886 | use English qw(-no_match_vars); |
887 | -use Test::More tests => 27; |
888 | +use Test::More tests => 35; |
889 | |
890 | use DSNParser; |
891 | use OptionParser; |
892 | use PerconaTest; |
893 | |
894 | +use Data::Dumper; |
895 | + |
896 | my $opts = [ |
897 | { |
898 | key => 'A', |
899 | @@ -83,6 +85,20 @@ |
900 | ); |
901 | |
902 | is_deeply( |
903 | + $dp->parse('S=/tmp/sock'), |
904 | + { u => undef, |
905 | + p => undef, |
906 | + S => '/tmp/sock', |
907 | + h => undef, |
908 | + P => undef, |
909 | + F => undef, |
910 | + D => undef, |
911 | + A => undef, |
912 | + }, |
913 | + 'Basic DSN with one part' |
914 | +); |
915 | + |
916 | +is_deeply( |
917 | $dp->parse('u=a,p=b,A=utf8'), |
918 | { u => 'a', |
919 | p => 'b', |
920 | @@ -392,6 +408,8 @@ |
921 | 'Copy DSN and overwrite destination' |
922 | ); |
923 | |
924 | +pop @$opts; # Remove t part. |
925 | + |
926 | # ############################################################################# |
927 | # Issue 93: DBI error messages can include full SQL |
928 | # ############################################################################# |
929 | @@ -462,6 +480,67 @@ |
930 | }; |
931 | |
932 | # ############################################################################# |
933 | +# Passwords with commas don't work, expose part of password |
934 | +# https://bugs.launchpad.net/percona-toolkit/+bug/886077 |
935 | +# ############################################################################# |
936 | + |
937 | +sub test_password_comma { |
938 | + my ($dsn_string, $pass, $port, $name) = @_; |
939 | + my $dsn = $dp->parse($dsn_string); |
940 | + is_deeply( |
941 | + $dsn, |
942 | + { u => 'a', |
943 | + p => $pass, |
944 | + S => undef, |
945 | + h => undef, |
946 | + P => $port, |
947 | + F => undef, |
948 | + D => undef, |
949 | + A => undef, |
950 | + }, |
951 | + "$name (bug 886077)" |
952 | + ) or diag(Dumper($dsn)); |
953 | +} |
954 | + |
955 | +my @password_commas = ( |
956 | + ['u=a,p=foo\,xxx,P=12345', 'foo,xxx', 12345, 'Pass with comma'], |
957 | + ['u=a,p=foo\,xxx', 'foo,xxx', undef, 'Pass with comma, last part'], |
958 | + ['u=a,p=foo\,,P=12345', 'foo,', 12345, 'Pass ends with comma'], |
959 | + ['u=a,p=foo\,', 'foo,', undef, 'Pass ends with comma, last part'], |
960 | + ['u=a,p=\,,P=12345', ',', 12345, 'Pass is a comma'], |
961 | +); |
962 | +foreach my $password_comma ( @password_commas ) { |
963 | + test_password_comma(@$password_comma); |
964 | +} |
965 | + |
966 | +sub test_password_comma_with_auto { |
967 | + my ($dsn_string, $pass, $port, $name) = @_; |
968 | + my $dsn = $dp->parse($dsn_string); |
969 | + is_deeply( |
970 | + $dsn, |
971 | + { u => undef, |
972 | + p => $pass, |
973 | + S => undef, |
974 | + h => 'host', |
975 | + P => $port, |
976 | + F => undef, |
977 | + D => undef, |
978 | + A => undef, |
979 | + }, |
980 | + "$name (bug 886077)" |
981 | + ) or diag(Dumper($dsn)); |
982 | +} |
983 | + |
984 | +@password_commas = ( |
985 | + ['host,p=a\,z,P=9', 'a,z', 9, 'Comma-pass with leading bareword host'], |
986 | + ['p=a\,z,P=9,host', 'a,z', 9, 'Comma-pass with trailing bareword host'], |
987 | + |
988 | +); |
989 | +foreach my $password_comma ( @password_commas ) { |
990 | + test_password_comma_with_auto(@$password_comma); |
991 | +} |
992 | + |
993 | +# ############################################################################# |
994 | # Done. |
995 | # ############################################################################# |
996 | $dbh->disconnect() if $dbh; |