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);
12
use Test::More tests => 24;
20
my $tp = new TableParser(Quoter => $q);
21
my $n = new TableNibbler(
28
$t = $tp->parse( load_file('t/lib/samples/sakila.film.sql') );
31
$n->generate_asc_stmt (
37
cols => [qw(film_id title description release_year language_id
38
original_language_id rental_duration rental_rate
39
length replacement_cost rating special_features
42
where => '((`film_id` >= ?))',
44
scols => [qw(film_id)],
46
'>=' => '((`film_id` >= ?))',
47
'>' => '((`film_id` > ?))',
48
'<=' => '((`film_id` <= ?))',
49
'<' => '((`film_id` < ?))',
52
'asc stmt on sakila.film',
56
$n->generate_del_stmt (
60
cols => [qw(film_id)],
62
where => '(`film_id` = ?)',
64
scols => [qw(film_id)],
66
'del stmt on sakila.film',
70
$n->generate_asc_stmt (
75
cols => [qw(film_id title description release_year language_id
76
original_language_id rental_duration rental_rate
77
length replacement_cost rating special_features
80
where => '((`film_id` >= ?))',
82
scols => [qw(film_id)],
84
'>=' => '((`film_id` >= ?))',
85
'>' => '((`film_id` > ?))',
86
'<=' => '((`film_id` <= ?))',
87
'<' => '((`film_id` < ?))',
90
'defaults to all columns',
95
$n->generate_asc_stmt (
101
qr/Index 'title' does not exist in table/,
102
'Error on nonexistent index',
106
$n->generate_asc_stmt (
109
index => 'idx_title',
112
cols => [qw(film_id title description release_year language_id
113
original_language_id rental_duration rental_rate
114
length replacement_cost rating special_features
116
index => 'idx_title',
117
where => '((`title` >= ?))',
119
scols => [qw(title)],
121
'>=' => '((`title` >= ?))',
122
'>' => '((`title` > ?))',
123
'<=' => '((`title` <= ?))',
124
'<' => '((`title` < ?))',
127
'asc stmt on sakila.film with different index',
131
$n->generate_del_stmt (
133
index => 'idx_title',
134
cols => [qw(film_id)],
137
cols => [qw(film_id title)],
138
index => 'idx_title',
139
where => '(`title` = ?)',
141
scols => [qw(title)],
143
'del stmt on sakila.film with different index and extra column',
146
# TableParser::find_best_index() is case-insensitive, returning the
147
# correct case even if the wrong case is given. But generate_asc_stmt()
148
# no longer calls find_best_index() so this test is a moot point.
150
$n->generate_asc_stmt (
153
index => 'idx_title',
156
cols => [qw(film_id title description release_year language_id
157
original_language_id rental_duration rental_rate
158
length replacement_cost rating special_features
160
index => 'idx_title',
161
where => '((`title` >= ?))',
163
scols => [qw(title)],
165
'>=' => '((`title` >= ?))',
166
'>' => '((`title` > ?))',
167
'<=' => '((`title` <= ?))',
168
'<' => '((`title` < ?))',
171
'Index returned in correct lettercase',
175
$n->generate_asc_stmt (
181
cols => [qw(title film_id)],
183
where => '((`film_id` >= ?))',
185
scols => [qw(film_id)],
187
'>=' => '((`film_id` >= ?))',
188
'>' => '((`film_id` > ?))',
189
'<=' => '((`film_id` <= ?))',
190
'<' => '((`film_id` < ?))',
193
'Required columns added to SELECT list',
196
# ##########################################################################
197
# Switch to the rental table
198
# ##########################################################################
199
$t = $tp->parse( load_file('t/lib/samples/sakila.rental.sql') );
202
$n->generate_asc_stmt(
205
index => 'rental_date',
208
cols => [qw(rental_id rental_date inventory_id customer_id
209
return_date staff_id last_update)],
210
index => 'rental_date',
211
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
212
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND `customer_id` >= ?))',
213
slice => [1, 1, 2, 1, 2, 3],
214
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id)],
216
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
217
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
218
. '= ? AND `customer_id` >= ?))',
219
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
220
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
221
. '= ? AND `customer_id` > ?))',
222
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
223
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
224
. '= ? AND `customer_id` <= ?))',
225
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
226
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
227
. '= ? AND `customer_id` < ?))',
230
'Alternate index on sakila.rental',
234
$n->generate_del_stmt (
236
index => 'rental_date',
239
cols => [qw(rental_date inventory_id customer_id)],
240
index => 'rental_date',
241
where => '(`rental_date` = ? AND `inventory_id` = ? AND `customer_id` = ?)',
243
scols => [qw(rental_date inventory_id customer_id)],
245
'Alternate index on sakila.rental delete statement',
248
# Check that I can select from one table and insert into another OK
249
my $f = $tp->parse( load_file('t/lib/samples/sakila.film.sql') );
251
$n->generate_ins_stmt(
253
sel_cols => $t->{cols},
256
cols => [qw(last_update)],
259
'Generated an INSERT statement from film into rental',
262
my $sel_tbl = $tp->parse( load_file('t/lib/samples/issue_131_sel.sql') );
263
my $ins_tbl = $tp->parse( load_file('t/lib/samples/issue_131_ins.sql') );
265
$n->generate_ins_stmt(
267
sel_cols => $sel_tbl->{cols},
270
cols => [qw(id name)],
273
'INSERT stmt with different col order and a missing ins col'
277
$n->generate_asc_stmt(
280
index => 'rental_date',
284
cols => [qw(rental_id rental_date inventory_id customer_id
285
return_date staff_id last_update)],
286
index => 'rental_date',
287
where => '((`rental_date` >= ?))',
289
scols => [qw(rental_date)],
291
'>=' => '((`rental_date` >= ?))',
292
'>' => '((`rental_date` > ?))',
293
'<=' => '((`rental_date` <= ?))',
294
'<' => '((`rental_date` < ?))',
297
'Alternate index with asc_first on sakila.rental',
301
$n->generate_asc_stmt(
304
index => 'rental_date',
308
cols => [qw(rental_id rental_date inventory_id customer_id
309
return_date staff_id last_update)],
310
index => 'rental_date',
311
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
312
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND `customer_id` > ?))',
313
slice => [1, 1, 2, 1, 2, 3],
314
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id)],
316
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
317
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
318
. '= ? AND `customer_id` >= ?))',
319
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
320
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
321
. '= ? AND `customer_id` > ?))',
322
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
323
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
324
. '= ? AND `customer_id` <= ?))',
325
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
326
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
327
. '= ? AND `customer_id` < ?))',
330
'Alternate index on sakila.rental with strict ascending',
333
# ##########################################################################
334
# Switch to the rental table with customer_id nullable
335
# ##########################################################################
336
$t = $tp->parse( load_file('t/lib/samples/sakila.rental.null.sql') );
339
$n->generate_asc_stmt(
342
index => 'rental_date',
345
cols => [qw(rental_id rental_date inventory_id customer_id
346
return_date staff_id last_update)],
347
index => 'rental_date',
348
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
349
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND '
350
. '(? IS NULL OR `customer_id` >= ?)))',
351
slice => [1, 1, 2, 1, 2, 3, 3],
352
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id customer_id)],
354
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
355
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
356
. '= ? AND (? IS NULL OR `customer_id` >= ?)))',
357
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
358
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
359
. '= ? AND ((? IS NULL AND `customer_id` IS NOT NULL) '
360
. 'OR (`customer_id` > ?))))',
361
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
362
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
363
. '= ? AND (? IS NULL OR `customer_id` <= ?)))',
364
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
365
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
366
. '= ? AND ((? IS NOT NULL AND `customer_id` IS NULL) '
367
. 'OR (`customer_id` < ?))))',
370
'Alternate index on sakila.rental with nullable customer_id',
374
$n->generate_del_stmt (
376
index => 'rental_date',
379
cols => [qw(rental_date inventory_id customer_id)],
380
index => 'rental_date',
381
where => '(`rental_date` = ? AND `inventory_id` = ? AND '
382
. '((? IS NULL AND `customer_id` IS NULL) OR (`customer_id` = ?)))',
383
slice => [0, 1, 2, 2],
384
scols => [qw(rental_date inventory_id customer_id customer_id)],
386
'Alternate index on sakila.rental delete statement with nullable customer_id',
390
$n->generate_asc_stmt(
393
index => 'rental_date',
397
cols => [qw(rental_id rental_date inventory_id customer_id
398
return_date staff_id last_update)],
399
index => 'rental_date',
400
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
401
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND '
402
. '((? IS NULL AND `customer_id` IS NOT NULL) OR (`customer_id` > ?))))',
403
slice => [1, 1, 2, 1, 2, 3, 3],
404
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id customer_id)],
406
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
407
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
408
. '= ? AND (? IS NULL OR `customer_id` >= ?)))',
409
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
410
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
411
. '= ? AND ((? IS NULL AND `customer_id` IS NOT NULL) '
412
. 'OR (`customer_id` > ?))))',
413
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
414
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
415
. '= ? AND (? IS NULL OR `customer_id` <= ?)))',
416
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
417
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
418
. '= ? AND ((? IS NOT NULL AND `customer_id` IS NULL) '
419
. 'OR (`customer_id` < ?))))',
422
'Alternate index on sakila.rental with nullable customer_id and strict ascending',
425
# ##########################################################################
426
# Switch to the rental table with inventory_id nullable
427
# ##########################################################################
428
$t = $tp->parse( load_file('t/lib/samples/sakila.rental.null2.sql') );
431
$n->generate_asc_stmt(
434
index => 'rental_date',
437
cols => [qw(rental_id rental_date inventory_id customer_id
438
return_date staff_id last_update)],
439
index => 'rental_date',
440
where => '((`rental_date` > ?) OR '
441
. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL) OR (`inventory_id` > ?)))'
442
. ' OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
443
. 'OR (`inventory_id` = ?)) AND `customer_id` >= ?))',
444
slice => [1, 1, 2, 2, 1, 2, 2, 3],
445
scols => [qw(rental_date rental_date inventory_id inventory_id
446
rental_date inventory_id inventory_id customer_id)],
448
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
449
. '((? IS NULL AND `inventory_id` IS NOT NULL) OR (`inventory_id` '
450
. '> ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` '
451
. 'IS NULL) OR (`inventory_id` = ?)) AND `customer_id` >= ?))',
452
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL '
453
. 'AND `inventory_id` IS NOT NULL) OR (`inventory_id` > ?))) OR '
454
. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
455
. 'OR (`inventory_id` = ?)) AND `customer_id` > ?))',
456
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND ((? IS NOT '
457
. 'NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?))) OR '
458
. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
459
. 'OR (`inventory_id` = ?)) AND `customer_id` <= ?))',
460
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND ((? IS NOT '
461
. 'NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?))) '
462
. 'OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS '
463
. 'NULL) OR (`inventory_id` = ?)) AND `customer_id` < ?))',
466
'Alternate index on sakila.rental with nullable inventory_id',
470
$n->generate_asc_stmt(
473
index => 'rental_date',
477
cols => [qw(rental_id rental_date inventory_id customer_id
478
return_date staff_id last_update)],
479
index => 'rental_date',
480
where => '((`rental_date` > ?) OR '
481
. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NOT NULL) OR (`inventory_id` > ?)))'
482
. ' OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
483
. 'OR (`inventory_id` = ?)) AND `customer_id` > ?))',
484
slice => [1, 1, 2, 2, 1, 2, 2, 3],
485
scols => [qw(rental_date rental_date inventory_id inventory_id
486
rental_date inventory_id inventory_id customer_id)],
488
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
489
. '((? IS NULL AND `inventory_id` IS NOT NULL) OR (`inventory_id` '
490
. '> ?))) OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` '
491
. 'IS NULL) OR (`inventory_id` = ?)) AND `customer_id` >= ?))',
492
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND ((? IS NULL '
493
. 'AND `inventory_id` IS NOT NULL) OR (`inventory_id` > ?))) OR '
494
. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
495
. 'OR (`inventory_id` = ?)) AND `customer_id` > ?))',
496
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND ((? IS NOT '
497
. 'NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?))) OR '
498
. '(`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS NULL) '
499
. 'OR (`inventory_id` = ?)) AND `customer_id` <= ?))',
500
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND ((? IS NOT '
501
. 'NULL AND `inventory_id` IS NULL) OR (`inventory_id` < ?))) '
502
. 'OR (`rental_date` = ? AND ((? IS NULL AND `inventory_id` IS '
503
. 'NULL) OR (`inventory_id` = ?)) AND `customer_id` < ?))',
506
'Alternate index on sakila.rental with nullable inventory_id and strict ascending',
509
# ##########################################################################
510
# Switch to the rental table with cols in a different order.
511
# ##########################################################################
512
$t = $tp->parse( load_file('t/lib/samples/sakila.rental.remix.sql') );
515
$n->generate_asc_stmt(
517
index => 'rental_date',
520
cols => [qw(rental_id rental_date customer_id inventory_id
521
return_date staff_id last_update)],
522
index => 'rental_date',
523
where => '((`rental_date` > ?) OR (`rental_date` = ? AND `inventory_id` > ?)'
524
. ' OR (`rental_date` = ? AND `inventory_id` = ? AND `customer_id` >= ?))',
525
slice => [1, 1, 3, 1, 3, 2],
526
scols => [qw(rental_date rental_date inventory_id rental_date inventory_id customer_id)],
528
'>=' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
529
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
530
. '= ? AND `customer_id` >= ?))',
531
'>' => '((`rental_date` > ?) OR (`rental_date` = ? AND '
532
. '`inventory_id` > ?) OR (`rental_date` = ? AND `inventory_id` '
533
. '= ? AND `customer_id` > ?))',
534
'<=' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
535
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
536
. '= ? AND `customer_id` <= ?))',
537
'<' => '((`rental_date` < ?) OR (`rental_date` = ? AND '
538
. '`inventory_id` < ?) OR (`rental_date` = ? AND `inventory_id` '
539
. '= ? AND `customer_id` < ?))',
542
'Out-of-order index on sakila.rental',
545
# ##########################################################################
546
# Switch to table without any indexes
547
# ##########################################################################
548
$t = $tp->parse( load_file('t/lib/samples/t1.sql') );
550
# This test is no longer needed because TableSyncNibble shouldn't
551
# ask TableNibbler to asc an indexless table.
554
# $n->generate_asc_stmt (
558
# qr/Cannot find an ascendable index in table/,
559
# 'Error when no good index',
563
$n->generate_cmp_where(
564
cols => [qw(a b c d)],
570
scols => [qw(a a d)],
572
where => '((`a` > ?) OR (`a` = ? AND `d` >= ?))',
578
$n->generate_cmp_where(
579
cols => [qw(a b c d)],
585
scols => [qw(a a d)],
587
where => '((`a` > ?) OR (`a` = ? AND `d` > ?))',
593
$n->generate_cmp_where(
594
cols => [qw(a b c d)],
600
scols => [qw(a a d)],
602
where => '((`a` < ?) OR (`a` = ? AND `d` <= ?))',
608
$n->generate_cmp_where(
609
cols => [qw(a b c d)],
615
scols => [qw(a a d)],
617
where => '((`a` < ?) OR (`a` = ? AND `d` < ?))',
623
# #############################################################################
625
# #############################################################################