~percona-toolkit-dev/percona-toolkit/fix-log-parser-writer-bug-963225

« back to all changes in this revision

Viewing changes to t/lib/TableChecksum.t

  • Committer: Daniel Nichter
  • Date: 2011-06-24 17:22:06 UTC
  • Revision ID: daniel@percona.com-20110624172206-c7q4s4ad6r260zz6
Add lib/, t/lib/, and sandbox/.  All modules are updated and passing on MySQL 5.1.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
 
 
3
BEGIN {
 
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";
 
7
};
 
8
 
 
9
use strict;
 
10
use warnings FATAL => 'all';
 
11
use English qw(-no_match_vars);
 
12
use Test::More;
 
13
 
 
14
use TableChecksum;
 
15
use VersionParser;
 
16
use TableParser;
 
17
use Quoter;
 
18
use MySQLDump;
 
19
use DSNParser;
 
20
use Sandbox;
 
21
use MaatkitTest;
 
22
 
 
23
my $dp = new DSNParser(opts=>$dsn_opts);
 
24
my $sb = new Sandbox(basedir => '/tmp', DSNParser => $dp);
 
25
my $dbh = $sb->get_dbh_for('master');
 
26
 
 
27
if ( !$dbh ) {
 
28
   plan skip_all => "Cannot connect to sandbox master";
 
29
}
 
30
else {
 
31
   plan tests => 51;
 
32
}
 
33
 
 
34
$sb->create_dbs($dbh, ['test']);
 
35
 
 
36
my $q  = new Quoter();
 
37
my $tp = new TableParser(Quoter => $q);
 
38
my $vp = new VersionParser();
 
39
my $du = new MySQLDump();
 
40
my $c  = new TableChecksum(Quoter=>$q, VersionParser=>$vp);
 
41
 
 
42
my $t;
 
43
 
 
44
my %args = map { $_ => undef }
 
45
   qw(db tbl tbl_struct algorithm function crc_wid crc_type opt_slice);
 
46
 
 
47
throws_ok (
 
48
   sub { $c->best_algorithm( %args, algorithm => 'foo', ) },
 
49
   qr/Invalid checksum algorithm/,
 
50
   'Algorithm=foo',
 
51
);
 
52
 
 
53
# Inject the VersionParser with some bogus versions.  Later I'll just pass the
 
54
# string version number instead of a real DBH, so the version parsing will
 
55
# return the value I want.
 
56
foreach my $ver( qw(4.0.0 4.1.1) ) {
 
57
   $vp->{$ver} = $vp->parse($ver);
 
58
}
 
59
 
 
60
is (
 
61
   $c->best_algorithm(
 
62
      algorithm => 'CHECKSUM',
 
63
      dbh       => '4.1.1',
 
64
   ),
 
65
   'CHECKSUM',
 
66
   'Prefers CHECKSUM',
 
67
);
 
68
 
 
69
is (
 
70
   $c->best_algorithm(
 
71
      dbh       => '4.1.1',
 
72
   ),
 
73
   'CHECKSUM',
 
74
   'Default is CHECKSUM',
 
75
);
 
76
 
 
77
is (
 
78
   $c->best_algorithm(
 
79
      algorithm => 'CHECKSUM',
 
80
      dbh       => '4.1.1',
 
81
      where     => 1,
 
82
   ),
 
83
   'BIT_XOR',
 
84
   'CHECKSUM eliminated by where',
 
85
);
 
86
 
 
87
is (
 
88
   $c->best_algorithm(
 
89
      algorithm => 'CHECKSUM',
 
90
      dbh       => '4.1.1',
 
91
      chunk     => 1,
 
92
   ),
 
93
   'BIT_XOR',
 
94
   'CHECKSUM eliminated by chunk',
 
95
);
 
96
 
 
97
is (
 
98
   $c->best_algorithm(
 
99
      algorithm => 'CHECKSUM',
 
100
      dbh       => '4.1.1',
 
101
      replicate => 1,
 
102
   ),
 
103
   'BIT_XOR',
 
104
   'CHECKSUM eliminated by replicate',
 
105
);
 
106
 
 
107
is (
 
108
   $c->best_algorithm(
 
109
      dbh       => '4.1.1',
 
110
      count     => 1,
 
111
   ),
 
112
   'BIT_XOR',
 
113
   'Default CHECKSUM eliminated by count',
 
114
);
 
115
 
 
116
is (
 
117
   $c->best_algorithm(
 
118
      algorithm => 'CHECKSUM',
 
119
      dbh       => '4.1.1',
 
120
      count     => 1,
 
121
   ),
 
122
   'CHECKSUM',
 
123
   'Explicit CHECKSUM not eliminated by count',
 
124
);
 
125
 
 
126
is (
 
127
   $c->best_algorithm(
 
128
      algorithm => 'CHECKSUM',
 
129
      dbh       => '4.0.0',
 
130
   ),
 
131
   'ACCUM',
 
132
   'CHECKSUM and BIT_XOR eliminated by version',
 
133
);
 
134
 
 
135
is (
 
136
   $c->best_algorithm(
 
137
      algorithm => 'BIT_XOR',
 
138
      dbh       => '4.1.1',
 
139
   ),
 
140
   'BIT_XOR',
 
141
   'BIT_XOR as requested',
 
142
);
 
143
 
 
144
is (
 
145
   $c->best_algorithm(
 
146
      algorithm => 'BIT_XOR',
 
147
      dbh       => '4.0.0',
 
148
   ),
 
149
   'ACCUM',
 
150
   'BIT_XOR eliminated by version',
 
151
);
 
152
 
 
153
is (
 
154
   $c->best_algorithm(
 
155
      algorithm => 'ACCUM',
 
156
      dbh       => '4.1.1',
 
157
   ),
 
158
   'ACCUM',
 
159
   'ACCUM as requested',
 
160
);
 
161
 
 
162
ok($c->is_hash_algorithm('ACCUM'), 'ACCUM is hash');
 
163
ok($c->is_hash_algorithm('BIT_XOR'), 'BIT_XOR is hash');
 
164
ok(!$c->is_hash_algorithm('CHECKSUM'), 'CHECKSUM is not hash');
 
165
 
 
166
is (
 
167
   $c->make_xor_slices(
 
168
      query   => 'FOO',
 
169
      crc_wid => 1,
 
170
   ),
 
171
   "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(FOO, 1, 1), 16, 10) "
 
172
      . "AS UNSIGNED)), 10, 16), 1, '0')",
 
173
   'FOO XOR slices 1 wide',
 
174
);
 
175
 
 
176
is (
 
177
   $c->make_xor_slices(
 
178
      query   => 'FOO',
 
179
      crc_wid => 16,
 
180
   ),
 
181
   "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(FOO, 1, 16), 16, 10) "
 
182
      . "AS UNSIGNED)), 10, 16), 16, '0')",
 
183
   'FOO XOR slices 16 wide',
 
184
);
 
185
 
 
186
is (
 
187
   $c->make_xor_slices(
 
188
      query   => 'FOO',
 
189
      crc_wid => 17,
 
190
   ),
 
191
   "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(FOO, 1, 16), 16, 10) "
 
192
      . "AS UNSIGNED)), 10, 16), 16, '0'), "
 
193
      . "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(FOO, 17, 1), 16, 10) "
 
194
      . "AS UNSIGNED)), 10, 16), 1, '0')",
 
195
   'FOO XOR slices 17 wide',
 
196
);
 
197
 
 
198
is (
 
199
   $c->make_xor_slices(
 
200
      query   => 'FOO',
 
201
      crc_wid => 32,
 
202
   ),
 
203
   "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(FOO, 1, 16), 16, 10) "
 
204
      . "AS UNSIGNED)), 10, 16), 16, '0'), "
 
205
      . "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(FOO, 17, 16), 16, 10) "
 
206
      . "AS UNSIGNED)), 10, 16), 16, '0')",
 
207
   'FOO XOR slices 32 wide',
 
208
);
 
209
 
 
210
is (
 
211
   $c->make_xor_slices(
 
212
      query     => 'FOO',
 
213
      crc_wid   => 32,
 
214
      opt_slice => 0,
 
215
   ),
 
216
   "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(\@crc := FOO, 1, 16), 16, 10) "
 
217
      . "AS UNSIGNED)), 10, 16), 16, '0'), "
 
218
      . "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(\@crc, 17, 16), 16, 10) "
 
219
      . "AS UNSIGNED)), 10, 16), 16, '0')",
 
220
   'XOR slice optimized in slice 0',
 
221
);
 
222
 
 
223
is (
 
224
   $c->make_xor_slices(
 
225
      query     => 'FOO',
 
226
      crc_wid   => 32,
 
227
      opt_slice => 1,
 
228
   ),
 
229
   "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(\@crc, 1, 16), 16, 10) "
 
230
      . "AS UNSIGNED)), 10, 16), 16, '0'), "
 
231
      . "LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(\@crc := FOO, 17, 16), 16, 10) "
 
232
      . "AS UNSIGNED)), 10, 16), 16, '0')",
 
233
   'XOR slice optimized in slice 1',
 
234
);
 
235
 
 
236
$t = $tp->parse(load_file('t/lib/samples/sakila.film.sql'));
 
237
 
 
238
is (
 
239
   $c->make_row_checksum(
 
240
      function  => 'SHA1',
 
241
      tbl_struct => $t,
 
242
   ),
 
243
     q{`film_id`, `title`, `description`, `release_year`, `language_id`, `original_language_id`, `rental_duration`, `rental_rate`, `length`, `replacement_cost`, `rating`, `special_features`, `last_update` + 0 AS `last_update`, }
 
244
   . q{SHA1(CONCAT_WS('#', }
 
245
   . q{`film_id`, `title`, `description`, `release_year`, `language_id`, }
 
246
   . q{`original_language_id`, `rental_duration`, `rental_rate`, `length`, }
 
247
   . q{`replacement_cost`, `rating`, `special_features`, `last_update` + 0, }
 
248
   . q{CONCAT(ISNULL(`description`), ISNULL(`release_year`), }
 
249
   . q{ISNULL(`original_language_id`), ISNULL(`length`), }
 
250
   . q{ISNULL(`rating`), ISNULL(`special_features`))))},
 
251
   'SHA1 query for sakila.film',
 
252
);
 
253
 
 
254
is (
 
255
   $c->make_row_checksum(
 
256
      function      => 'FNV_64',
 
257
      tbl_struct => $t,
 
258
   ),
 
259
     q{`film_id`, `title`, `description`, `release_year`, `language_id`, `original_language_id`, `rental_duration`, `rental_rate`, `length`, `replacement_cost`, `rating`, `special_features`, `last_update` + 0 AS `last_update`, }
 
260
   . q{FNV_64(}
 
261
   . q{`film_id`, `title`, `description`, `release_year`, `language_id`, }
 
262
   . q{`original_language_id`, `rental_duration`, `rental_rate`, `length`, }
 
263
   . q{`replacement_cost`, `rating`, `special_features`, `last_update` + 0)},
 
264
   'FNV_64 query for sakila.film',
 
265
);
 
266
 
 
267
is (
 
268
   $c->make_row_checksum(
 
269
      function      => 'SHA1',
 
270
      tbl_struct => $t,
 
271
      cols      => [qw(film_id)],
 
272
   ),
 
273
   q{`film_id`, SHA1(`film_id`)},
 
274
   'SHA1 query for sakila.film with only one column',
 
275
);
 
276
 
 
277
is (
 
278
   $c->make_row_checksum(
 
279
      function      => 'SHA1',
 
280
      tbl_struct => $t,
 
281
      cols      => [qw(FILM_ID)],
 
282
   ),
 
283
   q{`film_id`, SHA1(`film_id`)},
 
284
   'Column names are case-insensitive',
 
285
);
 
286
 
 
287
is (
 
288
   $c->make_row_checksum(
 
289
      function      => 'SHA1',
 
290
      tbl_struct => $t,
 
291
      cols      => [qw(film_id title)],
 
292
      sep       => '%',
 
293
   ),
 
294
   q{`film_id`, `title`, SHA1(CONCAT_WS('%', `film_id`, `title`))},
 
295
   'Separator',
 
296
);
 
297
 
 
298
is (
 
299
   $c->make_row_checksum(
 
300
      function      => 'SHA1',
 
301
      tbl_struct => $t,
 
302
      cols      => [qw(film_id title)],
 
303
      sep       => "'%'",
 
304
   ),
 
305
   q{`film_id`, `title`, SHA1(CONCAT_WS('%', `film_id`, `title`))},
 
306
   'Bad separator',
 
307
);
 
308
 
 
309
is (
 
310
   $c->make_row_checksum(
 
311
      function      => 'SHA1',
 
312
      tbl_struct => $t,
 
313
      cols      => [qw(film_id title)],
 
314
      sep       => "'''",
 
315
   ),
 
316
   q{`film_id`, `title`, SHA1(CONCAT_WS('#', `film_id`, `title`))},
 
317
   'Really bad separator',
 
318
);
 
319
 
 
320
$t = $tp->parse(load_file('t/lib/samples/sakila.rental.float.sql'));
 
321
is (
 
322
   $c->make_row_checksum(
 
323
      function      => 'SHA1',
 
324
      tbl_struct => $t,
 
325
   ),
 
326
   q{`rental_id`, `foo`, SHA1(CONCAT_WS('#', `rental_id`, `foo`))},
 
327
   'FLOAT column is like any other',
 
328
);
 
329
 
 
330
is (
 
331
   $c->make_row_checksum(
 
332
      function      => 'SHA1',
 
333
      tbl_struct => $t,
 
334
      float_precision => 5,
 
335
   ),
 
336
   q{`rental_id`, ROUND(`foo`, 5), SHA1(CONCAT_WS('#', `rental_id`, ROUND(`foo`, 5)))},
 
337
   'FLOAT column is rounded to 5 places',
 
338
);
 
339
 
 
340
$t = $tp->parse(load_file('t/lib/samples/sakila.film.sql'));
 
341
 
 
342
like(
 
343
   $c->make_row_checksum(
 
344
      function   => 'SHA1',
 
345
      tbl_struct => $t,
 
346
      trim       => 1,
 
347
   ),
 
348
   qr{TRIM\(`title`\)},
 
349
   'VARCHAR column is trimmed',
 
350
);
 
351
 
 
352
is (
 
353
   $c->make_checksum_query(
 
354
      %args,
 
355
      db        => 'sakila',
 
356
      tbl       => 'film',
 
357
      tbl_struct => $t,
 
358
      algorithm => 'CHECKSUM',
 
359
      function      => 'SHA1',
 
360
      crc_wid   => 40,
 
361
      crc_type  => 'varchar',
 
362
   ),
 
363
   'CHECKSUM TABLE `sakila`.`film`',
 
364
   'Sakila.film CHECKSUM',
 
365
);
 
366
 
 
367
throws_ok (
 
368
   sub { $c->make_checksum_query(
 
369
            %args,
 
370
            db        => 'sakila',
 
371
            tbl       => 'film',
 
372
            tbl_struct => $t,
 
373
            algorithm => 'BIT_XOR',
 
374
            crc_wid   => 40,
 
375
            cols      => [qw(film_id)],
 
376
            crc_type  => 'varchar',
 
377
            function  => 'SHA1',
 
378
            algorithm => 'CHECKSUM TABLE',
 
379
         )
 
380
   },
 
381
   qr/missing checksum algorithm/,
 
382
   'Complains about bad algorithm',
 
383
);
 
384
 
 
385
is (
 
386
   $c->make_checksum_query(
 
387
      %args,
 
388
      db         => 'sakila',
 
389
      tbl        => 'film',
 
390
      tbl_struct => $t,
 
391
      algorithm  => 'BIT_XOR',
 
392
      function   => 'SHA1',
 
393
      crc_wid    => 40,
 
394
      cols       => [qw(film_id)],
 
395
      crc_type   => 'varchar',
 
396
   ),
 
397
   q{SELECT /*PROGRESS_COMMENT*//*CHUNK_NUM*/ COUNT(*) AS cnt, }
 
398
   . q{COALESCE(LOWER(CONCAT(LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(SHA1(`film_id`), 1, }
 
399
   . q{16), 16, 10) AS UNSIGNED)), 10, 16), 16, '0'), }
 
400
   . q{LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(SHA1(`film_id`), 17, 16), 16, }
 
401
   . q{10) AS UNSIGNED)), 10, 16), 16, '0'), }
 
402
   . q{LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(SHA1(`film_id`), 33, 8), 16, }
 
403
   . q{10) AS UNSIGNED)), 10, 16), 8, '0'))), 0) AS crc }
 
404
   . q{FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/},
 
405
   'Sakila.film SHA1 BIT_XOR',
 
406
);
 
407
 
 
408
is (
 
409
   $c->make_checksum_query(
 
410
      %args,
 
411
      db         => 'sakila',
 
412
      tbl        => 'film',
 
413
      tbl_struct => $t,
 
414
      algorithm  => 'BIT_XOR',
 
415
      function   => 'FNV_64',
 
416
      crc_wid    => 99,
 
417
      cols       => [qw(film_id)],
 
418
      crc_type   => 'bigint',
 
419
   ),
 
420
   q{SELECT /*PROGRESS_COMMENT*//*CHUNK_NUM*/ COUNT(*) AS cnt, }
 
421
   . q{COALESCE(LOWER(CONV(BIT_XOR(CAST(FNV_64(`film_id`) AS UNSIGNED)), 10, 16)), 0) AS crc }
 
422
   . q{FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/},
 
423
   'Sakila.film FNV_64 BIT_XOR',
 
424
);
 
425
 
 
426
is (
 
427
   $c->make_checksum_query(
 
428
      %args,
 
429
      db         => 'sakila',
 
430
      tbl        => 'film',
 
431
      tbl_struct => $t,
 
432
      algorithm  => 'BIT_XOR',
 
433
      function   => 'FNV_64',
 
434
      crc_wid    => 99,
 
435
      cols       => [qw(film_id)],
 
436
      buffer     => 1,
 
437
      crc_type   => 'bigint',
 
438
   ),
 
439
   q{SELECT SQL_BUFFER_RESULT /*PROGRESS_COMMENT*//*CHUNK_NUM*/ COUNT(*) AS cnt, }
 
440
   . q{COALESCE(LOWER(CONV(BIT_XOR(CAST(FNV_64(`film_id`) AS UNSIGNED)), 10, 16)), 0) AS crc }
 
441
   . q{FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/},
 
442
   'Sakila.film FNV_64 BIT_XOR',
 
443
);
 
444
 
 
445
is (
 
446
   $c->make_checksum_query(
 
447
      %args,
 
448
      db         => 'sakila',
 
449
      tbl        => 'film',
 
450
      tbl_struct => $t,
 
451
      algorithm  => 'BIT_XOR',
 
452
      function   => 'CRC32',
 
453
      crc_wid    => 99,
 
454
      cols       => [qw(film_id)],
 
455
      buffer     => 1,
 
456
      crc_type   => 'int',
 
457
   ),
 
458
   q{SELECT SQL_BUFFER_RESULT /*PROGRESS_COMMENT*//*CHUNK_NUM*/ COUNT(*) AS cnt, }
 
459
   . q{COALESCE(LOWER(CONV(BIT_XOR(CAST(CRC32(`film_id`) AS UNSIGNED)), 10, 16)), 0) AS crc }
 
460
   . q{FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/},
 
461
   'Sakila.film CRC32 BIT_XOR',
 
462
);
 
463
 
 
464
is (
 
465
   $c->make_checksum_query(
 
466
      %args,
 
467
      db         => 'sakila',
 
468
      tbl        => 'film',
 
469
      tbl_struct => $t,
 
470
      algorithm  => 'BIT_XOR',
 
471
      function   => 'SHA1',
 
472
      crc_wid    => 40,
 
473
      cols       => [qw(film_id)],
 
474
      replicate  => 'test.checksum',
 
475
      crc_type   => 'varchar',
 
476
   ),
 
477
   q{REPLACE /*PROGRESS_COMMENT*/ INTO test.checksum }
 
478
   . q{(db, tbl, chunk, boundaries, this_cnt, this_crc) }
 
479
   . q{SELECT ?, ?, /*CHUNK_NUM*/ ?, COUNT(*) AS cnt, }
 
480
   . q{COALESCE(LOWER(CONCAT(LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(SHA1(`film_id`), 1, }
 
481
   . q{16), 16, 10) AS UNSIGNED)), 10, 16), 16, '0'), }
 
482
   . q{LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(SHA1(`film_id`), 17, 16), 16, }
 
483
   . q{10) AS UNSIGNED)), 10, 16), 16, '0'), }
 
484
   . q{LPAD(CONV(BIT_XOR(CAST(CONV(SUBSTRING(SHA1(`film_id`), 33, 8), 16, }
 
485
   . q{10) AS UNSIGNED)), 10, 16), 8, '0'))), 0) AS crc }
 
486
   . q{FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/},
 
487
   'Sakila.film SHA1 BIT_XOR with replication',
 
488
);
 
489
 
 
490
is (
 
491
   $c->make_checksum_query(
 
492
      %args,
 
493
      db         => 'sakila',
 
494
      tbl        => 'film',
 
495
      tbl_struct => $t,
 
496
      algorithm  => 'ACCUM',
 
497
      function   => 'SHA1',
 
498
      crc_wid    => 40,
 
499
      crc_type   => 'varchar',
 
500
   ),
 
501
   q{SELECT /*PROGRESS_COMMENT*//*CHUNK_NUM*/ COUNT(*) AS cnt, }
 
502
   . q{COALESCE(RIGHT(MAX(@crc := CONCAT(LPAD(@cnt := @cnt + 1, 16, '0'), }
 
503
   . q{SHA1(CONCAT(@crc, SHA1(CONCAT_WS('#', }
 
504
   . q{`film_id`, `title`, `description`, `release_year`, `language_id`, }
 
505
   . q{`original_language_id`, `rental_duration`, `rental_rate`, `length`, }
 
506
   . q{`replacement_cost`, `rating`, `special_features`, `last_update` + 0, }
 
507
   . q{CONCAT(ISNULL(`description`), ISNULL(`release_year`), }
 
508
   . q{ISNULL(`original_language_id`), ISNULL(`length`), }
 
509
   . q{ISNULL(`rating`), ISNULL(`special_features`)))))))), 40), 0) AS crc }
 
510
   . q{FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/},
 
511
   'Sakila.film SHA1 ACCUM',
 
512
);
 
513
 
 
514
is (
 
515
   $c->make_checksum_query(
 
516
      %args,
 
517
      db         => 'sakila',
 
518
      tbl        => 'film',
 
519
      tbl_struct => $t,
 
520
      algorithm  => 'ACCUM',
 
521
      function   => 'FNV_64',
 
522
      crc_wid    => 16,
 
523
      crc_type   => 'bigint',
 
524
   ),
 
525
   q{SELECT /*PROGRESS_COMMENT*//*CHUNK_NUM*/ COUNT(*) AS cnt, }
 
526
   . q{COALESCE(RIGHT(MAX(@crc := CONCAT(LPAD(@cnt := @cnt + 1, 16, '0'), }
 
527
   . q{CONV(CAST(FNV_64(CONCAT(@crc, FNV_64(}
 
528
   . q{`film_id`, `title`, `description`, `release_year`, `language_id`, }
 
529
   . q{`original_language_id`, `rental_duration`, `rental_rate`, `length`, }
 
530
   . q{`replacement_cost`, `rating`, `special_features`, `last_update` + 0}
 
531
   . q{))) AS UNSIGNED), 10, 16))), 16), 0) AS crc }
 
532
   . q{FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/},
 
533
   'Sakila.film FNV_64 ACCUM',
 
534
);
 
535
 
 
536
is (
 
537
   $c->make_checksum_query(
 
538
      %args,
 
539
      db         => 'sakila',
 
540
      tbl        => 'film',
 
541
      tbl_struct => $t,
 
542
      algorithm  => 'ACCUM',
 
543
      function   => 'CRC32',
 
544
      crc_wid    => 16,
 
545
      crc_type   => 'int',
 
546
      cols       => [qw(film_id)],
 
547
   ),
 
548
   q{SELECT /*PROGRESS_COMMENT*//*CHUNK_NUM*/ COUNT(*) AS cnt, }
 
549
   . q{COALESCE(RIGHT(MAX(@crc := CONCAT(LPAD(@cnt := @cnt + 1, 16, '0'), }
 
550
   . q{CONV(CAST(CRC32(CONCAT(@crc, CRC32(`film_id`}
 
551
   . q{))) AS UNSIGNED), 10, 16))), 16), 0) AS crc }
 
552
   . q{FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/},
 
553
   'Sakila.film CRC32 ACCUM',
 
554
);
 
555
 
 
556
is (
 
557
   $c->make_checksum_query(
 
558
      %args,
 
559
      db         => 'sakila',
 
560
      tbl        => 'film',
 
561
      tbl_struct => $t,
 
562
      algorithm  => 'ACCUM',
 
563
      function   => 'SHA1',
 
564
      crc_wid    => 40,
 
565
      replicate  => 'test.checksum',
 
566
      crc_type   => 'varchar',
 
567
   ),
 
568
   q{REPLACE /*PROGRESS_COMMENT*/ INTO test.checksum }
 
569
   . q{(db, tbl, chunk, boundaries, this_cnt, this_crc) }
 
570
   . q{SELECT ?, ?, /*CHUNK_NUM*/ ?, COUNT(*) AS cnt, }
 
571
   . q{COALESCE(RIGHT(MAX(@crc := CONCAT(LPAD(@cnt := @cnt + 1, 16, '0'), }
 
572
   . q{SHA1(CONCAT(@crc, SHA1(CONCAT_WS('#', }
 
573
   . q{`film_id`, `title`, `description`, `release_year`, `language_id`, }
 
574
   . q{`original_language_id`, `rental_duration`, `rental_rate`, `length`, }
 
575
   . q{`replacement_cost`, `rating`, `special_features`, `last_update` + 0, }
 
576
   . q{CONCAT(ISNULL(`description`), ISNULL(`release_year`), }
 
577
   . q{ISNULL(`original_language_id`), ISNULL(`length`), }
 
578
   . q{ISNULL(`rating`), ISNULL(`special_features`)))))))), 40), 0) AS crc }
 
579
   . q{FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/},
 
580
   'Sakila.film SHA1 ACCUM with replication',
 
581
);
 
582
 
 
583
is ( $c->crc32('hello world'), 222957957, 'CRC32 of hello world');
 
584
 
 
585
# #############################################################################
 
586
# Sandbox tests.
 
587
# #############################################################################
 
588
like(
 
589
   $c->choose_hash_func(
 
590
      dbh => $dbh,
 
591
   ),
 
592
   qr/CRC32|FNV_64|MD5/,
 
593
   'CRC32, FNV_64 or MD5 is default',
 
594
);
 
595
 
 
596
like(
 
597
   $c->choose_hash_func(
 
598
      dbh      => $dbh,
 
599
      function => 'SHA99',
 
600
   ),
 
601
   qr/CRC32|FNV_64|MD5/,
 
602
   'SHA99 does not exist so I get CRC32 or friends',
 
603
);
 
604
 
 
605
is(
 
606
   $c->choose_hash_func(
 
607
      dbh      => $dbh,
 
608
      function => 'MD5',
 
609
   ),
 
610
   'MD5',
 
611
   'MD5 requested and MD5 granted',
 
612
);
 
613
 
 
614
is(
 
615
   $c->optimize_xor(
 
616
      dbh      => $dbh,
 
617
      function => 'SHA1',
 
618
   ),
 
619
   '2',
 
620
   'SHA1 slice is 2',
 
621
);
 
622
 
 
623
is(
 
624
   $c->optimize_xor(
 
625
      dbh      => $dbh,
 
626
      function => 'MD5',
 
627
   ),
 
628
   '1',
 
629
   'MD5 slice is 1',
 
630
);
 
631
 
 
632
is_deeply(
 
633
   [$c->get_crc_type($dbh, 'CRC32')],
 
634
   [qw(int 10)],
 
635
   'Type and length of CRC32'
 
636
);
 
637
 
 
638
is_deeply(
 
639
   [$c->get_crc_type($dbh, 'MD5')],
 
640
   [qw(varchar 32)],
 
641
   'Type and length of MD5'
 
642
);
 
643
 
 
644
# #############################################################################
 
645
# Issue 94: Enhance mk-table-checksum, add a --ignorecols option
 
646
# #############################################################################
 
647
$sb->load_file('master', 't/lib/samples/issue_94.sql');
 
648
$t= $tp->parse( $du->get_create_table($dbh, $q, 'test', 'issue_94') );
 
649
my $query = $c->make_checksum_query(
 
650
   db         => 'test',
 
651
   tbl        => 'issue_47',
 
652
   tbl_struct => $t,
 
653
   algorithm  => 'ACCUM',
 
654
   function   => 'CRC32',
 
655
   crc_wid    => 16,
 
656
   crc_type   => 'int',
 
657
   opt_slice  => undef,
 
658
   cols       => undef,
 
659
   sep        => '#',
 
660
   replicate  => undef,
 
661
   precision  => undef,
 
662
   trim       => undef,
 
663
   ignorecols => {'c'=>1},
 
664
);
 
665
is($query,
 
666
   'SELECT /*PROGRESS_COMMENT*//*CHUNK_NUM*/ COUNT(*) AS cnt, COALESCE(RIGHT(MAX(@crc := CONCAT(LPAD(@cnt := @cnt + 1, 16, \'0\'), CONV(CAST(CRC32(CONCAT(@crc, CRC32(CONCAT_WS(\'#\', `a`, `b`)))) AS UNSIGNED), 10, 16))), 16), 0) AS crc FROM /*DB_TBL*//*INDEX_HINT*//*WHERE*/',
 
667
   'Ignores specified columns');
 
668
 
 
669
$sb->wipe_clean($dbh);
 
670
exit;