~percona-toolkit-dev/percona-toolkit/release-2.2.2

« back to all changes in this revision

Viewing changes to t/lib/TableNibbler.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 tests => 24;
 
13
 
 
14
use TableParser;
 
15
use TableNibbler;
 
16
use Quoter;
 
17
use MaatkitTest;
 
18
 
 
19
my $q  = new Quoter();
 
20
my $tp = new TableParser(Quoter => $q);
 
21
my $n  = new TableNibbler(
 
22
   TableParser => $tp,
 
23
   Quoter      => $q,
 
24
);
 
25
 
 
26
my $t;
 
27
 
 
28
$t = $tp->parse( load_file('t/lib/samples/sakila.film.sql') );
 
29
 
 
30
is_deeply(
 
31
   $n->generate_asc_stmt (
 
32
      tbl_struct => $t,
 
33
      cols       => $t->{cols},
 
34
      index      => 'PRIMARY',
 
35
   ),
 
36
   {
 
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
 
40
                  last_update)],
 
41
      index => 'PRIMARY',
 
42
      where => '((`film_id` >= ?))',
 
43
      slice => [0],
 
44
      scols => [qw(film_id)],
 
45
      boundaries => {
 
46
         '>=' => '((`film_id` >= ?))',
 
47
         '>'  => '((`film_id` > ?))',
 
48
         '<=' => '((`film_id` <= ?))',
 
49
         '<'  => '((`film_id` < ?))',
 
50
      },
 
51
   },
 
52
   'asc stmt on sakila.film',
 
53
);
 
54
 
 
55
is_deeply(
 
56
   $n->generate_del_stmt (
 
57
      tbl_struct => $t,
 
58
   ),
 
59
   {
 
60
      cols  => [qw(film_id)],
 
61
      index => 'PRIMARY',
 
62
      where => '(`film_id` = ?)',
 
63
      slice => [0],
 
64
      scols => [qw(film_id)],
 
65
   },
 
66
   'del stmt on sakila.film',
 
67
);
 
68
 
 
69
is_deeply(
 
70
   $n->generate_asc_stmt (
 
71
      tbl_struct => $t,
 
72
      index      => 'PRIMARY',
 
73
   ),
 
74
   {
 
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
 
78
                  last_update)],
 
79
      index => 'PRIMARY',
 
80
      where => '((`film_id` >= ?))',
 
81
      slice => [0],
 
82
      scols => [qw(film_id)],
 
83
      boundaries => {
 
84
         '>=' => '((`film_id` >= ?))',
 
85
         '>'  => '((`film_id` > ?))',
 
86
         '<=' => '((`film_id` <= ?))',
 
87
         '<'  => '((`film_id` < ?))',
 
88
      },
 
89
   },
 
90
   'defaults to all columns',
 
91
);
 
92
 
 
93
throws_ok(
 
94
   sub {
 
95
      $n->generate_asc_stmt (
 
96
         tbl_struct => $t,
 
97
         cols   => $t->{cols},
 
98
         index  => 'title',
 
99
      )
 
100
   },
 
101
   qr/Index 'title' does not exist in table/,
 
102
   'Error on nonexistent index',
 
103
);
 
104
 
 
105
is_deeply(
 
106
   $n->generate_asc_stmt (
 
107
      tbl_struct => $t,
 
108
      cols   => $t->{cols},
 
109
      index  => 'idx_title',
 
110
   ),
 
111
   {
 
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
 
115
                  last_update)],
 
116
      index => 'idx_title',
 
117
      where => '((`title` >= ?))',
 
118
      slice => [1],
 
119
      scols => [qw(title)],
 
120
      boundaries => {
 
121
         '>=' => '((`title` >= ?))',
 
122
         '>'  => '((`title` > ?))',
 
123
         '<=' => '((`title` <= ?))',
 
124
         '<'  => '((`title` < ?))',
 
125
      },
 
126
   },
 
127
   'asc stmt on sakila.film with different index',
 
128
);
 
129
 
 
130
is_deeply(
 
131
   $n->generate_del_stmt (
 
132
      tbl_struct => $t,
 
133
      index  => 'idx_title',
 
134
      cols   => [qw(film_id)],
 
135
   ),
 
136
   {
 
137
      cols  => [qw(film_id title)],
 
138
      index => 'idx_title',
 
139
      where => '(`title` = ?)',
 
140
      slice => [1],
 
141
      scols => [qw(title)],
 
142
   },
 
143
   'del stmt on sakila.film with different index and extra column',
 
144
);
 
145
 
 
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.
 
149
is_deeply(
 
150
   $n->generate_asc_stmt (
 
151
      tbl_struct => $t,
 
152
      cols   => $t->{cols},
 
153
      index  => 'idx_title',
 
154
   ),
 
155
   {
 
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
 
159
                  last_update)],
 
160
      index => 'idx_title',
 
161
      where => '((`title` >= ?))',
 
162
      slice => [1],
 
163
      scols => [qw(title)],
 
164
      boundaries => {
 
165
         '>=' => '((`title` >= ?))',
 
166
         '>'  => '((`title` > ?))',
 
167
         '<=' => '((`title` <= ?))',
 
168
         '<'  => '((`title` < ?))',
 
169
      },
 
170
   },
 
171
   'Index returned in correct lettercase',
 
172
);
 
173
 
 
174
is_deeply(
 
175
   $n->generate_asc_stmt (
 
176
      tbl_struct => $t,
 
177
      cols   => [qw(title)],
 
178
      index  => 'PRIMARY',
 
179
   ),
 
180
   {
 
181
      cols  => [qw(title film_id)],
 
182
      index => 'PRIMARY',
 
183
      where => '((`film_id` >= ?))',
 
184
      slice => [1],
 
185
      scols => [qw(film_id)],
 
186
      boundaries => {
 
187
         '>=' => '((`film_id` >= ?))',
 
188
         '>'  => '((`film_id` > ?))',
 
189
         '<=' => '((`film_id` <= ?))',
 
190
         '<'  => '((`film_id` < ?))',
 
191
      },
 
192
   },
 
193
   'Required columns added to SELECT list',
 
194
);
 
195
 
 
196
# ##########################################################################
 
197
# Switch to the rental table
 
198
# ##########################################################################
 
199
$t = $tp->parse( load_file('t/lib/samples/sakila.rental.sql') );
 
200
 
 
201
is_deeply(
 
202
   $n->generate_asc_stmt(
 
203
      tbl_struct => $t,
 
204
      cols   => $t->{cols},
 
205
      index  => 'rental_date',
 
206
   ),
 
207
   {
 
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)],
 
215
      boundaries => {
 
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` < ?))',
 
228
      },
 
229
   },
 
230
   'Alternate index on sakila.rental',
 
231
);
 
232
 
 
233
is_deeply(
 
234
   $n->generate_del_stmt (
 
235
      tbl_struct => $t,
 
236
      index  => 'rental_date',
 
237
   ),
 
238
   {
 
239
      cols  => [qw(rental_date inventory_id customer_id)],
 
240
      index => 'rental_date',
 
241
      where => '(`rental_date` = ? AND `inventory_id` = ? AND `customer_id` = ?)',
 
242
      slice => [0, 1, 2],
 
243
      scols => [qw(rental_date inventory_id customer_id)],
 
244
   },
 
245
   'Alternate index on sakila.rental delete statement',
 
246
);
 
247
 
 
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') );
 
250
is_deeply(
 
251
   $n->generate_ins_stmt(
 
252
      ins_tbl  => $f,
 
253
      sel_cols => $t->{cols},
 
254
   ),
 
255
   {
 
256
      cols  => [qw(last_update)],
 
257
      slice => [6],
 
258
   },
 
259
   'Generated an INSERT statement from film into rental',
 
260
);
 
261
 
 
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') );  
 
264
is_deeply(
 
265
   $n->generate_ins_stmt(
 
266
      ins_tbl  => $ins_tbl,
 
267
      sel_cols => $sel_tbl->{cols},
 
268
   ),
 
269
   {
 
270
      cols  => [qw(id name)],
 
271
      slice => [0, 2],
 
272
   },
 
273
   'INSERT stmt with different col order and a missing ins col'
 
274
);
 
275
 
 
276
is_deeply(
 
277
   $n->generate_asc_stmt(
 
278
      tbl_struct => $t,
 
279
      cols   => $t->{cols},
 
280
      index  => 'rental_date',
 
281
      asc_first => 1,
 
282
   ),
 
283
   {
 
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` >= ?))',
 
288
      slice => [1],
 
289
      scols => [qw(rental_date)],
 
290
      boundaries => {
 
291
         '>=' => '((`rental_date` >= ?))',
 
292
         '>'  => '((`rental_date` > ?))',
 
293
         '<=' => '((`rental_date` <= ?))',
 
294
         '<'  => '((`rental_date` < ?))',
 
295
      },
 
296
   },
 
297
   'Alternate index with asc_first on sakila.rental',
 
298
);
 
299
 
 
300
is_deeply(
 
301
   $n->generate_asc_stmt(
 
302
      tbl_struct => $t,
 
303
      cols   => $t->{cols},
 
304
      index  => 'rental_date',
 
305
      asc_only => 1,
 
306
   ),
 
307
   {
 
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)],
 
315
      boundaries => {
 
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` < ?))',
 
328
      },
 
329
   },
 
330
   'Alternate index on sakila.rental with strict ascending',
 
331
);
 
332
 
 
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') );
 
337
 
 
338
is_deeply(
 
339
   $n->generate_asc_stmt(
 
340
      tbl_struct => $t,
 
341
      cols   => $t->{cols},
 
342
      index  => 'rental_date',
 
343
   ),
 
344
   {
 
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)],
 
353
      boundaries => {
 
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` < ?))))',
 
368
      },
 
369
   },
 
370
   'Alternate index on sakila.rental with nullable customer_id',
 
371
);
 
372
 
 
373
is_deeply(
 
374
   $n->generate_del_stmt (
 
375
      tbl_struct => $t,
 
376
      index  => 'rental_date',
 
377
   ),
 
378
   {
 
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)],
 
385
   },
 
386
   'Alternate index on sakila.rental delete statement with nullable customer_id',
 
387
);
 
388
 
 
389
is_deeply(
 
390
   $n->generate_asc_stmt(
 
391
      tbl_struct => $t,
 
392
      cols   => $t->{cols},
 
393
      index  => 'rental_date',
 
394
      asc_only => 1,
 
395
   ),
 
396
   {
 
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)],
 
405
      boundaries => {
 
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` < ?))))',
 
420
      },
 
421
   },
 
422
   'Alternate index on sakila.rental with nullable customer_id and strict ascending',
 
423
);
 
424
 
 
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') );
 
429
 
 
430
is_deeply(
 
431
   $n->generate_asc_stmt(
 
432
      tbl_struct => $t,
 
433
      cols   => $t->{cols},
 
434
      index  => 'rental_date',
 
435
   ),
 
436
   {
 
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)],
 
447
      boundaries => {
 
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` < ?))',
 
464
      },
 
465
   },
 
466
   'Alternate index on sakila.rental with nullable inventory_id',
 
467
);
 
468
 
 
469
is_deeply(
 
470
   $n->generate_asc_stmt(
 
471
      tbl_struct => $t,
 
472
      cols   => $t->{cols},
 
473
      index  => 'rental_date',
 
474
      asc_only => 1,
 
475
   ),
 
476
   {
 
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)],
 
487
      boundaries => {
 
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` < ?))',
 
504
      },
 
505
   },
 
506
   'Alternate index on sakila.rental with nullable inventory_id and strict ascending',
 
507
);
 
508
 
 
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') );
 
513
 
 
514
is_deeply(
 
515
   $n->generate_asc_stmt(
 
516
      tbl_struct => $t,
 
517
      index  => 'rental_date',
 
518
   ),
 
519
   {
 
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)],
 
527
      boundaries => {
 
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` < ?))',
 
540
      },
 
541
   },
 
542
   'Out-of-order index on sakila.rental',
 
543
);
 
544
 
 
545
# ##########################################################################
 
546
# Switch to table without any indexes
 
547
# ##########################################################################
 
548
$t = $tp->parse( load_file('t/lib/samples/t1.sql') );
 
549
 
 
550
# This test is no longer needed because TableSyncNibble shouldn't
 
551
# ask TableNibbler to asc an indexless table.
 
552
# throws_ok(
 
553
#    sub {
 
554
#       $n->generate_asc_stmt (
 
555
#          tbl_struct => $t,
 
556
#       )
 
557
#    },
 
558
#    qr/Cannot find an ascendable index in table/,
 
559
#    'Error when no good index',
 
560
# );
 
561
 
 
562
is_deeply(
 
563
   $n->generate_cmp_where(
 
564
      cols   => [qw(a b c d)],
 
565
      slice  => [0, 3],
 
566
      is_nullable => {},
 
567
      type   => '>=',
 
568
   ),
 
569
   {
 
570
      scols => [qw(a a d)],
 
571
      slice => [0, 0, 3],
 
572
      where => '((`a` > ?) OR (`a` = ? AND `d` >= ?))',
 
573
   },
 
574
   'WHERE for >=',
 
575
);
 
576
 
 
577
is_deeply(
 
578
   $n->generate_cmp_where(
 
579
      cols   => [qw(a b c d)],
 
580
      slice  => [0, 3],
 
581
      is_nullable => {},
 
582
      type   => '>',
 
583
   ),
 
584
   {
 
585
      scols => [qw(a a d)],
 
586
      slice => [0, 0, 3],
 
587
      where => '((`a` > ?) OR (`a` = ? AND `d` > ?))',
 
588
   },
 
589
   'WHERE for >',
 
590
);
 
591
 
 
592
is_deeply(
 
593
   $n->generate_cmp_where(
 
594
      cols   => [qw(a b c d)],
 
595
      slice  => [0, 3],
 
596
      is_nullable => {},
 
597
      type   => '<=',
 
598
   ),
 
599
   {
 
600
      scols => [qw(a a d)],
 
601
      slice => [0, 0, 3],
 
602
      where => '((`a` < ?) OR (`a` = ? AND `d` <= ?))',
 
603
   },
 
604
   'WHERE for <=',
 
605
);
 
606
 
 
607
is_deeply(
 
608
   $n->generate_cmp_where(
 
609
      cols   => [qw(a b c d)],
 
610
      slice  => [0, 3],
 
611
      is_nullable => {},
 
612
      type   => '<',
 
613
   ),
 
614
   {
 
615
      scols => [qw(a a d)],
 
616
      slice => [0, 0, 3],
 
617
      where => '((`a` < ?) OR (`a` = ? AND `d` < ?))',
 
618
   },
 
619
   'WHERE for <',
 
620
);
 
621
 
 
622
 
 
623
# #############################################################################
 
624
# Done.
 
625
# #############################################################################
 
626
exit;