4
die "The PERCONA_TOOLKIT_BRANCH environment variable is not set.\n"
5
unless $ENV{PERCONA_TOOLKIT_BRANCH} && -d $ENV{PERCONA_TOOLKIT_BRANCH};
6
unshift @INC, "$ENV{PERCONA_TOOLKIT_BRANCH}/lib";
10
use warnings FATAL => 'all';
11
use English qw(-no_match_vars);
35
my $dp = new DSNParser(opts=>$dsn_opts);
36
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
37
my $dbh1 = $sb->get_dbh_for('master');
38
my $dbh2 = $sb->get_dbh_for('slave1');
41
plan skip_all => "Cannot connect to sandbox master";
44
plan skip_all => "Cannot connect to sandbox slave";
50
$sb->create_dbs($dbh1, ['test']);
52
Transformers->import(qw(make_checksum));
54
my $vp = new VersionParser();
56
my $qp = new QueryParser();
57
my $du = new MySQLDump(cache => 0);
58
my $tp = new TableParser(Quoter => $q);
59
my $tc = new TableChecksum(Quoter => $q, VersionParser => $vp);
60
my $of = new Outfile();
62
my $ts = new TableSyncer(
79
my $plugin = new TableSyncGroupBy(Quoter => $q);
86
{ dbh => $dbh1, name => 'master' },
87
{ dbh => $dbh2, name => 'slave' },
91
my ( $when, %args ) = @_;
92
die "I don't know when $when is"
93
unless $when eq 'before_execute'
95
|| $when eq 'after_execute';
96
for my $i ( 0..$#events ) {
97
$events[$i] = $cr->$when(
99
dbh => $hosts->[$i]->{dbh},
106
return make_checksum(@_);
109
# #############################################################################
110
# Test the checksum method.
111
# #############################################################################
113
diag(`/tmp/12345/use < $trunk/t/lib/samples/compare-results.sql`);
115
$cr = new CompareResults(
116
method => 'checksum',
117
'base-dir' => '/dev/null', # not used with checksum method
118
plugins => [$plugin],
123
isa_ok($cr, 'CompareResults');
127
arg => 'select * from test.t where i>0',
128
fingerprint => 'select * from test.t where i>?',
132
arg => 'select * from test.t where i>0',
133
fingerprint => 'select * from test.t where i>?',
139
MaatkitTest::wait_until(
143
$r = $dbh1->selectrow_arrayref('SHOW TABLES FROM test LIKE "dropme"');
145
return 1 if ($r->[0] || '') eq 'dropme';
146
diag('Waiting for CREATE TABLE...') unless $i++;
154
$dbh1->selectrow_arrayref('SHOW TABLES FROM test LIKE "dropme"'),
156
'checksum: temp table exists'
159
proc('before_execute', db=>'test', 'temp-table'=>'dropme');
162
$events[0]->{wrapped_query},
163
'CREATE TEMPORARY TABLE `test`.`dropme` AS select * from test.t where i>0',
164
'checksum: before_execute() wraps query in CREATE TEMPORARY TABLE'
168
$dbh1->selectall_arrayref('SHOW TABLES FROM test LIKE "dropme"'),
170
'checksum: before_execute() drops temp table'
174
!exists $events[0]->{Query_time},
175
"checksum: Query_time doesn't exist before execute()"
181
exists $events[0]->{Query_time},
182
"checksum: Query_time exists after exectue()"
186
$events[0]->{Query_time},
188
"checksum: Query_time is a number ($events[0]->{Query_time})"
192
$events[0]->{wrapped_query},
193
'CREATE TEMPORARY TABLE `test`.`dropme` AS select * from test.t where i>0',
194
"checksum: execute() doesn't unwrap query"
198
$dbh1->selectall_arrayref('select * from test.dropme'),
200
'checksum: Result set selected into the temp table'
204
!exists $events[0]->{row_count},
205
"checksum: row_count doesn't exist before after_execute()"
209
!exists $events[0]->{checksum},
210
"checksum: checksum doesn't exist before after_execute()"
213
proc('after_execute');
216
$events[0]->{wrapped_query},
217
'CREATE TEMPORARY TABLE `test`.`dropme` AS select * from test.t where i>0',
218
'checksum: after_execute() left wrapped query'
222
$dbh1->selectall_arrayref('SHOW TABLES FROM test LIKE "dropme"'),
224
'checksum: after_execute() drops temp table'
233
different_row_counts => 0,
234
different_checksums => 0,
235
different_column_counts => 0,
236
different_column_types => 0,
238
'checksum: compare, no differences'
242
$events[0]->{row_count},
244
"checksum: correct row_count after after_execute()"
248
$events[0]->{checksum},
250
"checksum: correct checksum after after_execute()"
254
!exists $events[0]->{wrapped_query},
255
'checksum: wrapped query removed after compare'
258
# Make checksums differ.
259
$dbh2->do('update test.t set i = 99 where i=1');
261
proc('before_execute', db=>'test', 'temp-table'=>'dropme');
263
proc('after_execute');
271
different_row_counts => 0,
272
different_checksums => 1,
273
different_column_counts => 0,
274
different_column_types => 0,
276
'checksum: compare, different checksums'
279
# Make row counts differ, too.
280
$dbh2->do('insert into test.t values (4)');
282
proc('before_execute', db=>'test', 'temp-table'=>'dropme');
284
proc('after_execute');
292
different_row_counts => 1,
293
different_checksums => 1,
294
different_column_counts => 0,
295
different_column_types => 0,
297
'checksum: compare, different checksums and row counts'
301
# Checksum differences
302
# Query ID master slave
303
# ================== ========= ==========
304
# D2D386B840D3BEEA-1 $events[0]->{checksum} $events[1]->{checksum}
306
# Row count differences
307
# Query ID master slave
308
# ================== ====== =====
309
# D2D386B840D3BEEA-1 3 4
313
$cr->report(hosts => $hosts),
318
my %samples = $cr->samples($events[0]->{fingerprint});
322
1 => 'select * from test.t where i>0',
327
# #############################################################################
328
# Test the rows method.
329
# #############################################################################
331
my $tmpdir = '/tmp/mk-upgrade-res';
333
diag(`/tmp/12345/use < $trunk/t/lib/samples/compare-results.sql`);
334
diag(`rm -rf $tmpdir; mkdir $tmpdir`);
336
$cr = new CompareResults(
338
'base-dir' => $tmpdir,
339
plugins => [$plugin],
344
isa_ok($cr, 'CompareResults');
348
arg => 'select * from test.t',
352
arg => 'select * from test.t',
358
MaatkitTest::wait_until(
362
$r = $dbh1->selectrow_arrayref('SHOW TABLES FROM test LIKE "dropme"');
364
return 1 if ($r->[0] || '') eq 'dropme';
365
diag('Waiting for CREATE TABLE...') unless $i++;
373
$dbh1->selectrow_arrayref('SHOW TABLES FROM test LIKE "dropme"'),
375
'rows: temp table exists'
378
proc('before_execute');
382
'select * from test.t',
383
"rows: before_execute() doesn't wrap query and doesn't require tmp table"
387
$dbh1->selectrow_arrayref('SHOW TABLES FROM test LIKE "dropme"'),
389
"rows: before_execute() doesn't drop temp table"
393
!exists $events[0]->{Query_time},
394
"rows: Query_time doesn't exist before execute()"
398
!exists $events[0]->{results_sth},
399
"rows: results_sth doesn't exist before execute()"
405
exists $events[0]->{Query_time},
406
"rows: query_time exists after exectue()"
410
exists $events[0]->{results_sth},
411
"rows: results_sth exists after exectue()"
415
$events[0]->{Query_time},
417
"rows: Query_time is a number ($events[0]->{Query_time})"
421
!exists $events[0]->{row_count},
422
"rows: row_count doesn't exist before after_execute()"
426
$cr->after_execute(event=>$events[0]),
428
"rows: after_execute() doesn't modify the event"
437
different_row_counts => 0,
438
different_column_values => 0,
439
different_column_counts => 0,
440
different_column_types => 0,
442
'rows: compare, no differences'
446
$events[0]->{row_count},
448
"rows: compare() sets row_count"
452
$events[1]->{row_count},
454
"rows: compare() sets row_count"
457
# Make the result set differ.
458
$dbh2->do('insert into test.t values (5)');
460
proc('before_execute');
469
different_row_counts => 1,
470
different_column_values => 0,
471
different_column_counts => 0,
472
different_column_types => 0,
474
'rows: compare, different row counts'
477
# Use test.t2 and make a column value differ.
480
arg => 'select * from test.t2',
482
fingerprint => 'select * from test.t2',
486
arg => 'select * from test.t2',
488
fingerprint => 'select * from test.t2',
493
$dbh2->do('update test.t2 set c="should be c" where i=3');
496
$dbh2->selectrow_arrayref('select c from test.t2 where i=3'),
498
'rows: column value is different'
501
proc('before_execute');
510
different_row_counts => 0,
511
different_column_values => 1,
512
different_column_counts => 0,
513
different_column_types => 0,
515
'rows: compare, different column values'
519
$dbh1->selectall_arrayref('show indexes from test.mk_upgrade_left'),
521
'Did not add indexes'
525
# Column value differences
526
# Query ID Column master slave
527
# ================== ====== ====== ===========
528
# CFC309761E9131C5-3 c c should be c
530
# Row count differences
531
# Query ID master slave
532
# ================== ====== =====
533
# B8B721D77EA1FD78-0 3 4
537
$cr->report(hosts => $hosts),
542
%samples = $cr->samples($events[0]->{fingerprint});
546
3 => 'select * from test.t2'
551
# #############################################################################
552
# Test max-different-rows.
553
# #############################################################################
555
$dbh2->do('update test.t2 set c="should be a" where i=1');
556
$dbh2->do('update test.t2 set c="should be b" where i=2');
557
proc('before_execute');
564
'max-different-rows' => 1,
568
different_row_counts => 0,
569
different_column_values => 1,
570
different_column_counts => 0,
571
different_column_types => 0,
573
'rows: compare, stop at max-different-rows'
577
$dbh1->selectall_arrayref('show indexes from test.mk_upgrade_left'),
578
[['mk_upgrade_left','0','i','1','i','A',undef,undef, undef,'YES','BTREE','']],
583
# Column value differences
584
# Query ID Column master slave
585
# ================== ====== ====== ===========
586
# CFC309761E9131C5-3 c a should be a
590
$cr->report(hosts => $hosts),
592
'rows: report max-different-rows'
595
# #############################################################################
596
# Double check that outfiles have correct contents.
597
# #############################################################################
599
# This test uses the results from the max-different-rows test above.
601
my @outfile = split(/[\t\n]+/, `cat /tmp/mk-upgrade-res/left-outfile.txt`);
608
@outfile = split(/[\t\n]+/, `cat /tmp/mk-upgrade-res/right-outfile.txt`);
611
['1', 'should be a', '2', 'should be b', '3', 'should be c'],
615
# #############################################################################
616
# Test float-precision.
617
# #############################################################################
620
arg => 'select * from test.t3',
622
fingerprint => 'select * from test.t3',
626
arg => 'select * from test.t3',
628
fingerprint => 'select * from test.t3',
634
$dbh2->do('update test.t3 set f=1.12346 where 1');
635
proc('before_execute');
644
different_row_counts => 0,
645
different_column_values => 1,
646
different_column_counts => 0,
647
different_column_types => 0,
649
'rows: compare, different without float-precision'
652
proc('before_execute');
659
'float-precision' => 3
662
different_row_counts => 0,
663
different_column_values => 0,
664
different_column_counts => 0,
665
different_column_types => 0,
667
'rows: compare, not different with float-precision'
670
# #############################################################################
671
# Test when left has more rows than right.
672
# #############################################################################
674
$dbh1->do('update test.t3 set f=0 where 1');
675
$dbh1->do('SET SQL_LOG_BIN=0');
676
$dbh1->do('insert into test.t3 values (2.0),(3.0)');
677
$dbh1->do('SET SQL_LOG_BIN=1');
679
my $left_n_rows = $dbh1->selectcol_arrayref('select count(*) from test.t3')->[0];
680
my $right_n_rows = $dbh2->selectcol_arrayref('select count(*) from test.t3')->[0];
682
$left_n_rows == 3 && $right_n_rows == 1,
683
'Left has extra rows'
686
proc('before_execute');
693
'float-precision' => 3
696
different_row_counts => 1,
697
different_column_values => 0,
698
different_column_counts => 0,
699
different_column_types => 0,
701
'rows: compare, left with more rows'
705
# Row count differences
706
# Query ID master slave
707
# ================== ====== =====
708
# D56E6FABA26D1F1C-3 3 1
712
$cr->report(hosts => $hosts),
714
'rows: report, left with more rows'
717
# #############################################################################
718
# Try to compare without having done the actions.
719
# #############################################################################
722
arg => 'select * from test.t',
726
arg => 'select * from test.t',
731
$cr = new CompareResults(
732
method => 'checksum',
733
'base-dir' => '/dev/null', # not used with checksum method
734
plugins => [$plugin],
741
@diffs = $cr->compare(events => \@events, hosts => $hosts);
747
"compare() checksums without actions doesn't die"
753
different_row_counts => 0,
754
different_checksums => 0,
755
different_column_counts => 0,
756
different_column_types => 0,
758
'No differences after bad compare()'
761
$cr = new CompareResults(
763
'base-dir' => $tmpdir,
764
plugins => [$plugin],
770
@diffs = $cr->compare(events => \@events, hosts => $hosts);
776
"compare() rows without actions doesn't die"
782
different_row_counts => 0,
783
different_column_values => 0,
784
different_column_counts => 0,
785
different_column_types => 0,
787
'No differences after bad compare()'
790
# #############################################################################
792
# #############################################################################
796
open STDERR, '>', \$output;
797
$cr->_d('Complete test coverage');
801
qr/Complete test coverage/,
804
diag(`rm -rf $tmpdir`);
805
diag(`rm -rf /tmp/*outfile.txt`);
806
$sb->wipe_clean($dbh1);