Test sorting by 'short desc' column
[dbsrgits/DBIx-Class.git] / t / sqlmaker / limit_dialects / torture_quoted.t
CommitLineData
d1f4d28d 1use strict;
2use warnings;
3
4use Test::More;
5use Test::Exception;
6use Storable 'dclone';
7use lib qw(t/lib);
8use DBICTest ':DiffSQL';
9
10my $schema = DBICTest->init_schema(
11 no_deploy => 1,
12 quote_char => '`',
13 name_sep => '.',
14);
15
f32ef973 16my $bs = $schema->source('BooksInLibrary');
17$bs->remove_column('price');
18$bs->add_columns(
19 'price (#)' => {
20 data_type => 'integer',
21 is_nullable => 1,
22 },
70e0e783 23 'short desc' => {
24 data_type => 'text',
25 is_nullable => 1,
26 },
f32ef973 27);
28
d1f4d28d 29my $native_limit_dialect = $schema->storage->sql_maker->{limit_dialect};
30
31my $where_string = '`me`.`title` = ? AND `source` != ? AND `source` = ?';
32
33my @where_bind = (
34 [ {} => 'kama sutra' ],
35 [ {} => 'Study' ],
36 [ { sqlt_datatype => 'varchar', sqlt_size => 100, dbic_colname => 'source' } => 'Library' ],
37);
38my @select_bind = (
39 [ { sqlt_datatype => 'numeric' } => 11 ],
40 [ {} => 12 ],
41 [ { sqlt_datatype => 'integer', dbic_colname => 'me.id' } => 13 ],
42);
43my @group_bind = (
44 [ {} => 21 ],
45);
46my @having_bind = (
47 [ {} => 31 ],
48);
49my @order_bind = (
50 [ { sqlt_datatype => 'int' } => 1 ],
51 [ { sqlt_datatype => 'varchar', dbic_colname => 'name', sqlt_size => 100 } => 2 ],
52 [ {} => 3 ],
53);
54
55my $tests = {
56
57 LimitOffset => {
58 limit => [
59 "(
60 SELECT `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
61 FROM `books` `me`
62 JOIN `owners` `owner`
63 ON `owner`.`id` = `me`.`owner`
64 WHERE $where_string
65 GROUP BY (`me`.`id` / ?), `owner`.`id`
66 HAVING ?
67 LIMIT ?
68 )",
69 [
70 @select_bind,
71 @where_bind,
72 @group_bind,
73 @having_bind,
74 [ { sqlt_datatype => 'integer' } => 4 ],
75 ],
76 ],
77 limit_offset => [
78 "(
79 SELECT `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
80 FROM `books` `me`
81 JOIN `owners` `owner`
82 ON `owner`.`id` = `me`.`owner`
83 WHERE $where_string
84 GROUP BY (`me`.`id` / ?), `owner`.`id`
85 HAVING ?
86 LIMIT ?
87 OFFSET ?
88 )",
89 [
90 @select_bind,
91 @where_bind,
92 @group_bind,
93 @having_bind,
94 [ { sqlt_datatype => 'integer' } => 4 ],
95 [ { sqlt_datatype => 'integer' } => 3 ],
96 ],
97 ],
98 ordered_limit => [
99 "(
100 SELECT `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
101 FROM `books` `me`
102 JOIN `owners` `owner`
103 ON `owner`.`id` = `me`.`owner`
104 WHERE $where_string
105 GROUP BY (`me`.`id` / ?), `owner`.`id`
106 HAVING ?
70e0e783 107 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 108 LIMIT ?
109 )",
110 [
111 @select_bind,
112 @where_bind,
113 @group_bind,
114 @having_bind,
115 @order_bind,
116 [ { sqlt_datatype => 'integer' } => 4 ],
117 ]
118 ],
119 ordered_limit_offset => [
120 "(
121 SELECT `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
122 FROM `books` `me`
123 JOIN `owners` `owner`
124 ON `owner`.`id` = `me`.`owner`
125 WHERE $where_string
126 GROUP BY (`me`.`id` / ?), `owner`.`id`
127 HAVING ?
70e0e783 128 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 129 LIMIT ?
130 OFFSET ?
131 )",
132 [
133 @select_bind,
134 @where_bind,
135 @group_bind,
136 @having_bind,
137 @order_bind,
138 [ { sqlt_datatype => 'integer' } => 4 ],
139 [ { sqlt_datatype => 'integer' } => 3 ],
140 ],
141 ],
142 limit_offset_prefetch => [
143 "(
70e0e783 144 SELECT `me`.`name`, `books`.`id`, `books`.`source`, `books`.`owner`, `books`.`title`, `books`.`price (#)`, `books`.`short desc`
d1f4d28d 145 FROM (
146 SELECT `me`.`name`, `me`.`id`
147 FROM `owners` `me`
148 LIMIT ? OFFSET ?
149 ) `me`
150 LEFT JOIN `books` `books`
151 ON `books`.`owner` = `me`.`id`
152 )",
153 [
154 [ { sqlt_datatype => 'integer' } => 3 ],
155 [ { sqlt_datatype => 'integer' } => 1 ],
156 ]
157 ],
158 },
159
160 LimitXY => {
161 ordered_limit_offset => [
162 "(
163 SELECT `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
164 FROM `books` `me`
165 JOIN `owners` `owner`
166 ON `owner`.`id` = `me`.`owner`
167 WHERE $where_string
168 GROUP BY (`me`.`id` / ?), `owner`.`id`
169 HAVING ?
70e0e783 170 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 171 LIMIT ?, ?
172 )",
173 [
174 @select_bind,
175 @where_bind,
176 @group_bind,
177 @having_bind,
178 @order_bind,
179 [ { sqlt_datatype => 'integer' } => 3 ],
180 [ { sqlt_datatype => 'integer' } => 4 ],
181 ],
182 ],
183 limit_offset_prefetch => [
184 "(
70e0e783 185 SELECT `me`.`name`, `books`.`id`, `books`.`source`, `books`.`owner`, `books`.`title`, `books`.`price (#)`, `books`.`short desc`
d1f4d28d 186 FROM (
187 SELECT `me`.`name`, `me`.`id`
188 FROM `owners` `me`
189 LIMIT ?,?
190 ) `me`
191 LEFT JOIN `books` `books`
192 ON `books`.`owner` = `me`.`id`
193 )",
194 [
195 [ { sqlt_datatype => 'integer' } => 1 ],
196 [ { sqlt_datatype => 'integer' } => 3 ],
197 ]
198 ],
199 },
200
201 SkipFirst => {
202 ordered_limit_offset => [
203 "(
204 SELECT SKIP ? FIRST ? `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
205 FROM `books` `me`
206 JOIN `owners` `owner`
207 ON `owner`.`id` = `me`.`owner`
208 WHERE $where_string
209 GROUP BY (`me`.`id` / ?), `owner`.`id`
210 HAVING ?
70e0e783 211 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 212 )",
213 [
214 [ { sqlt_datatype => 'integer' } => 3 ],
215 [ { sqlt_datatype => 'integer' } => 4 ],
216 @select_bind,
217 @where_bind,
218 @group_bind,
219 @having_bind,
220 @order_bind,
221 ],
222 ],
223 limit_offset_prefetch => [
224 "(
70e0e783 225 SELECT `me`.`name`, `books`.`id`, `books`.`source`, `books`.`owner`, `books`.`title`, `books`.`price (#)`, `books`.`short desc`
d1f4d28d 226 FROM (
227 SELECT SKIP ? FIRST ? `me`.`name`, `me`.`id`
228 FROM `owners` `me`
229 ) `me`
230 LEFT JOIN `books` `books`
231 ON `books`.`owner` = `me`.`id`
232 )",
233 [
234 [ { sqlt_datatype => 'integer' } => 1 ],
235 [ { sqlt_datatype => 'integer' } => 3 ],
236 ]
237 ],
238 },
239
240 FirstSkip => {
241 ordered_limit_offset => [
242 "(
243 SELECT FIRST ? SKIP ? `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
244 FROM `books` `me`
245 JOIN `owners` `owner`
246 ON `owner`.`id` = `me`.`owner`
247 WHERE $where_string
248 GROUP BY (`me`.`id` / ?), `owner`.`id`
249 HAVING ?
70e0e783 250 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 251 )",
252 [
253 [ { sqlt_datatype => 'integer' } => 4 ],
254 [ { sqlt_datatype => 'integer' } => 3 ],
255 @select_bind,
256 @where_bind,
257 @group_bind,
258 @having_bind,
259 @order_bind,
260 ],
261 ],
262 limit_offset_prefetch => [
263 "(
70e0e783 264 SELECT `me`.`name`, `books`.`id`, `books`.`source`, `books`.`owner`, `books`.`title`, `books`.`price (#)`, `books`.`short desc`
d1f4d28d 265 FROM (
266 SELECT FIRST ? SKIP ? `me`.`name`, `me`.`id`
267 FROM `owners` `me`
268 ) `me`
269 LEFT JOIN `books` `books`
270 ON `books`.`owner` = `me`.`id`
271 )",
272 [
273 [ { sqlt_datatype => 'integer' } => 3 ],
274 [ { sqlt_datatype => 'integer' } => 1 ],
275 ]
276 ],
277 },
278
279 RowNumberOver => do {
280 my $unordered_sql = "(
281 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
282 FROM (
283 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`, ROW_NUMBER() OVER() AS `rno__row__index`
284 FROM (
285 SELECT `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`
286 FROM `books` `me`
287 JOIN `owners` `owner`
288 ON `owner`.`id` = `me`.`owner`
289 WHERE $where_string
290 GROUP BY (`me`.`id` / ?), `owner`.`id`
291 HAVING ?
292 ) `me`
293 ) `me`
294 WHERE `rno__row__index` >= ? AND `rno__row__index` <= ?
295 )";
296
297 my $ordered_sql = "(
298 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
299 FROM (
70e0e783 300 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`, ROW_NUMBER() OVER( ORDER BY `ORDER__BY__001`, `ORDER__BY__002`, `ORDER__BY__003` ) AS `rno__row__index`
d1f4d28d 301 FROM (
302 SELECT `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`,
70e0e783 303 ? / ? AS `ORDER__BY__001`, ? AS `ORDER__BY__002`, `me`.`short desc` AS `ORDER__BY__003`
d1f4d28d 304 FROM `books` `me`
305 JOIN `owners` `owner`
306 ON `owner`.`id` = `me`.`owner`
307 WHERE $where_string
308 GROUP BY (`me`.`id` / ?), `owner`.`id`
309 HAVING ?
310 ) `me`
311 ) `me`
312 WHERE `rno__row__index` >= ? AND `rno__row__index` <= ?
313 )";
314
315 {
316 limit => [$unordered_sql,
317 [
318 @select_bind,
319 @where_bind,
320 @group_bind,
321 @having_bind,
322 [ { sqlt_datatype => 'integer' } => 1 ],
323 [ { sqlt_datatype => 'integer' } => 4 ],
324 ],
325 ],
326 limit_offset => [$unordered_sql,
327 [
328 @select_bind,
329 @where_bind,
330 @group_bind,
331 @having_bind,
332 [ { sqlt_datatype => 'integer' } => 4 ],
333 [ { sqlt_datatype => 'integer' } => 7 ],
334 ],
335 ],
336 ordered_limit => [$ordered_sql,
337 [
338 @select_bind,
339 @order_bind,
340 @where_bind,
341 @group_bind,
342 @having_bind,
343 [ { sqlt_datatype => 'integer' } => 1 ],
344 [ { sqlt_datatype => 'integer' } => 4 ],
345 ],
346 ],
347 ordered_limit_offset => [$ordered_sql,
348 [
349 @select_bind,
350 @order_bind,
351 @where_bind,
352 @group_bind,
353 @having_bind,
354 [ { sqlt_datatype => 'integer' } => 4 ],
355 [ { sqlt_datatype => 'integer' } => 7 ],
356 ],
357 ],
358 limit_offset_prefetch => [
359 "(
70e0e783 360 SELECT `me`.`name`, `books`.`id`, `books`.`source`, `books`.`owner`, `books`.`title`, `books`.`price (#)`, `books`.`short desc`
d1f4d28d 361 FROM (
362 SELECT `me`.`name`, `me`.`id`
363 FROM (
364 SELECT `me`.`name`, `me`.`id`, ROW_NUMBER() OVER() AS `rno__row__index`
365 FROM (
366 SELECT `me`.`name`, `me`.`id` FROM `owners` `me`
367 ) `me`
368 ) `me`
369 WHERE `rno__row__index` >= ? AND `rno__row__index` <= ?
370 ) `me`
371 LEFT JOIN `books` `books`
372 ON `books`.`owner` = `me`.`id`
373 )",
374 [
375 [ { sqlt_datatype => 'integer' } => 2 ],
376 [ { sqlt_datatype => 'integer' } => 4 ],
377 ]
378 ],
379 };
380 },
381
382 RowNum => do {
383 my $limit_sql = sub {
384 sprintf "(
385 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
386 FROM (
387 SELECT `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`
388 FROM `books` `me`
389 JOIN `owners` `owner`
390 ON `owner`.`id` = `me`.`owner`
391 WHERE $where_string
392 GROUP BY (`me`.`id` / ?), `owner`.`id`
393 HAVING ?
394 %s
395 ) `me`
396 WHERE ROWNUM <= ?
397 )", $_[0] || '';
398 };
399
400 {
401 limit => [ $limit_sql->(),
402 [
403 @select_bind,
404 @where_bind,
405 @group_bind,
406 @having_bind,
407 [ { sqlt_datatype => 'integer' } => 4 ],
408 ],
409 ],
410 limit_offset => [
411 "(
412 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
413 FROM (
414 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`, ROWNUM AS `rownum__index`
415 FROM (
416 SELECT `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`
417 FROM `books` `me`
418 JOIN `owners` `owner`
419 ON `owner`.`id` = `me`.`owner`
420 WHERE $where_string
421 GROUP BY (`me`.`id` / ?), `owner`.`id`
422 HAVING ?
423 ) `me`
424 ) `me`
425 WHERE `rownum__index` BETWEEN ? AND ?
426 )",
427 [
428 @select_bind,
429 @where_bind,
430 @group_bind,
431 @having_bind,
432 [ { sqlt_datatype => 'integer' } => 4 ],
433 [ { sqlt_datatype => 'integer' } => 7 ],
434 ],
435 ],
70e0e783 436 ordered_limit => [ $limit_sql->('ORDER BY ? / ?, ?, `me`.`short desc`'),
d1f4d28d 437 [
438 @select_bind,
439 @where_bind,
440 @group_bind,
441 @having_bind,
442 @order_bind,
443 [ { sqlt_datatype => 'integer' } => 4 ],
444 ],
445 ],
446 ordered_limit_offset => [
447 "(
448 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
449 FROM (
450 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`, ROWNUM AS `rownum__index`
451 FROM (
452 SELECT `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`
453 FROM `books` `me`
454 JOIN `owners` `owner`
455 ON `owner`.`id` = `me`.`owner`
456 WHERE $where_string
457 GROUP BY (`me`.`id` / ?), `owner`.`id`
458 HAVING ?
70e0e783 459 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 460 ) `me`
461 WHERE ROWNUM <= ?
462 ) `me`
463 WHERE `rownum__index` >= ?
464 )",
465 [
466 @select_bind,
467 @where_bind,
468 @group_bind,
469 @having_bind,
470 @order_bind,
471 [ { sqlt_datatype => 'integer' } => 7 ],
472 [ { sqlt_datatype => 'integer' } => 4 ],
473 ],
474 ],
475 limit_offset_prefetch => [
476 "(
70e0e783 477 SELECT `me`.`name`, `books`.`id`, `books`.`source`, `books`.`owner`, `books`.`title`, `books`.`price (#)`, `books`.`short desc`
d1f4d28d 478 FROM (
479 SELECT `me`.`name`, `me`.`id`
480 FROM (
481 SELECT `me`.`name`, `me`.`id`, ROWNUM AS `rownum__index`
482 FROM (
483 SELECT `me`.`name`, `me`.`id`
484 FROM `owners` `me`
485 ) `me`
486 ) `me` WHERE `rownum__index` BETWEEN ? AND ?
487 ) `me`
488 LEFT JOIN `books` `books`
489 ON `books`.`owner` = `me`.`id`
490 )",
491 [
492 [ { sqlt_datatype => 'integer' } => 2 ],
493 [ { sqlt_datatype => 'integer' } => 4 ],
494 ]
495 ],
496 };
497 },
498
499 FetchFirst => {
500 limit => [
501 "(
502 SELECT `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
503 FROM `books` `me`
504 JOIN `owners` `owner`
505 ON `owner`.`id` = `me`.`owner`
506 WHERE $where_string
507 GROUP BY (`me`.`id` / ?), `owner`.`id`
508 HAVING ?
509 FETCH FIRST 4 ROWS ONLY
510 )",
511 [
512 @select_bind,
513 @where_bind,
514 @group_bind,
515 @having_bind,
516 ],
517 ],
518 limit_offset => [
519 "(
520 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
521 FROM (
522 SELECT `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`
523 FROM `books` `me`
524 JOIN `owners` `owner`
525 ON `owner`.`id` = `me`.`owner`
526 WHERE $where_string
527 GROUP BY (`me`.`id` / ?), `owner`.`id`
528 HAVING ?
529 ORDER BY `me`.`id`
530 FETCH FIRST 7 ROWS ONLY
531 ) `me`
532 ORDER BY `me`.`id` DESC
533 FETCH FIRST 4 ROWS ONLY
534 )",
535 [
536 @select_bind,
537 @where_bind,
538 @group_bind,
539 @having_bind,
540 ],
541 ],
542 ordered_limit => [
543 "(
544 SELECT `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
545 FROM `books` `me`
546 JOIN `owners` `owner`
547 ON `owner`.`id` = `me`.`owner`
548 WHERE $where_string
549 GROUP BY (`me`.`id` / ?), `owner`.`id`
550 HAVING ?
70e0e783 551 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 552 FETCH FIRST 4 ROWS ONLY
553 )",
554 [
555 @select_bind,
556 @where_bind,
557 @group_bind,
558 @having_bind,
559 @order_bind,
560 ],
561 ],
562 ordered_limit_offset => [
563 "(
564 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
565 FROM (
70e0e783 566 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`, `ORDER__BY__001`, `ORDER__BY__002`, `ORDER__BY__003`
d1f4d28d 567 FROM (
70e0e783 568 SELECT `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`, ? / ? AS `ORDER__BY__001`, ? AS `ORDER__BY__002`, `me`.`short desc` AS `ORDER__BY__003`
d1f4d28d 569 FROM `books` `me`
570 JOIN `owners` `owner`
571 ON `owner`.`id` = `me`.`owner`
572 WHERE $where_string
573 GROUP BY (`me`.`id` / ?), `owner`.`id`
574 HAVING ?
70e0e783 575 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 576 FETCH FIRST 7 ROWS ONLY
577 ) `me`
70e0e783 578 ORDER BY `ORDER__BY__001` DESC, `ORDER__BY__002` DESC, `ORDER__BY__003` DESC
d1f4d28d 579 FETCH FIRST 4 ROWS ONLY
580 ) `me`
70e0e783 581 ORDER BY `ORDER__BY__001`, `ORDER__BY__002`, `ORDER__BY__003`
d1f4d28d 582 )",
583 [
584 @select_bind,
585 @order_bind,
586 @where_bind,
587 @group_bind,
588 @having_bind,
589 @{ dclone \@order_bind }, # without this is_deeply throws a fit
590 ],
591 ],
592 limit_offset_prefetch => [
593 "(
70e0e783 594 SELECT `me`.`name`, `books`.`id`, `books`.`source`, `books`.`owner`, `books`.`title`, `books`.`price (#)`, `books`.`short desc`
d1f4d28d 595 FROM (
596 SELECT `me`.`name`, `me`.`id`
597 FROM (
598 SELECT `me`.`name`, `me`.`id`
599 FROM `owners` `me`
600 ORDER BY `me`.`id`
601 FETCH FIRST 4 ROWS ONLY
602 ) `me`
603 ORDER BY `me`.`id` DESC
604 FETCH FIRST 3 ROWS ONLY
605 ) `me`
606 LEFT JOIN `books` `books`
607 ON `books`.`owner` = `me`.`id`
608 )",
609 [],
610 ],
611 },
612
613 Top => {
614 limit => [
615 "(
616 SELECT TOP 4 `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
617 FROM `books` `me`
618 JOIN `owners` `owner`
619 ON `owner`.`id` = `me`.`owner`
620 WHERE $where_string
621 GROUP BY (`me`.`id` / ?), `owner`.`id`
622 HAVING ?
623 )",
624 [
625 @select_bind,
626 @where_bind,
627 @group_bind,
628 @having_bind,
629 ],
630 ],
631 limit_offset => [
632 "(
633 SELECT TOP 4 `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
634 FROM (
635 SELECT TOP 7 `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`
636 FROM `books` `me`
637 JOIN `owners` `owner`
638 ON `owner`.`id` = `me`.`owner`
639 WHERE $where_string
640 GROUP BY (`me`.`id` / ?), `owner`.`id`
641 HAVING ?
642 ORDER BY `me`.`id`
643 ) `me`
644 ORDER BY `me`.`id` DESC
645 )",
646 [
647 @select_bind,
648 @where_bind,
649 @group_bind,
650 @having_bind,
651 ],
652 ],
653 ordered_limit => [
654 "(
655 SELECT TOP 4 `me`.`id`, `owner`.`id`, `owner`.`name`, ? * ?, ?
656 FROM `books` `me`
657 JOIN `owners` `owner`
658 ON `owner`.`id` = `me`.`owner`
659 WHERE $where_string
660 GROUP BY (`me`.`id` / ?), `owner`.`id`
661 HAVING ?
70e0e783 662 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 663 )",
664 [
665 @select_bind,
666 @where_bind,
667 @group_bind,
668 @having_bind,
669 @order_bind,
670 ],
671 ],
672 ordered_limit_offset => [
673 "(
674 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
675 FROM (
70e0e783 676 SELECT TOP 4 `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`, `ORDER__BY__001`, `ORDER__BY__002`, `ORDER__BY__003`
d1f4d28d 677 FROM (
70e0e783 678 SELECT TOP 7 `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`, ? / ? AS `ORDER__BY__001`, ? AS `ORDER__BY__002`, `me`.`short desc` AS `ORDER__BY__003`
d1f4d28d 679 FROM `books` `me`
680 JOIN `owners` `owner`
681 ON `owner`.`id` = `me`.`owner`
682 WHERE $where_string
683 GROUP BY (`me`.`id` / ?), `owner`.`id`
684 HAVING ?
70e0e783 685 ORDER BY ? / ?, ?, `me`.`short desc`
d1f4d28d 686 ) `me`
70e0e783 687 ORDER BY `ORDER__BY__001` DESC, `ORDER__BY__002` DESC, `ORDER__BY__003` DESC
d1f4d28d 688 ) `me`
70e0e783 689 ORDER BY `ORDER__BY__001`, `ORDER__BY__002`, `ORDER__BY__003`
d1f4d28d 690 )",
691 [
692 @select_bind,
693 @order_bind,
694 @where_bind,
695 @group_bind,
696 @having_bind,
697 @{ dclone \@order_bind }, # without this is_deeply throws a fit
698 ],
699 ],
700 limit_offset_prefetch => [
701 "(
70e0e783 702 SELECT `me`.`name`, `books`.`id`, `books`.`source`, `books`.`owner`, `books`.`title`, `books`.`price (#)`, `books`.`short desc`
d1f4d28d 703 FROM (
704 SELECT TOP 3 `me`.`name`, `me`.`id`
705 FROM (
706 SELECT TOP 4 `me`.`name`, `me`.`id`
707 FROM `owners` `me`
708 ORDER BY `me`.`id`
709 ) `me`
710 ORDER BY `me`.`id` DESC
711 ) `me`
712 LEFT JOIN `books` `books`
713 ON `books`.`owner` = `me`.`id`
714 )",
715 [],
716 ],
717 },
718
719 GenericSubQ => {
720 ordered_limit => [
721 "(
722 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
723 FROM (
f32ef973 724 SELECT `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`, `me`.`price (#)`
d1f4d28d 725 FROM `books` `me`
726 JOIN `owners` `owner`
727 ON `owner`.`id` = `me`.`owner`
728 WHERE $where_string
729 GROUP BY (`me`.`id` / ?), `owner`.`id`
730 HAVING ?
731 ) `me`
732 WHERE (
733 SELECT COUNT( * )
734 FROM `books` `rownum__emulation`
735 WHERE
f32ef973 736 ( `me`.`price (#)` IS NULL AND `rownum__emulation`.`price (#)` IS NOT NULL )
d1f4d28d 737 OR
738 (
f32ef973 739 `rownum__emulation`.`price (#)` > `me`.`price (#)`
d1f4d28d 740 AND
f32ef973 741 `me`.`price (#)` IS NOT NULL
d1f4d28d 742 AND
f32ef973 743 `rownum__emulation`.`price (#)` IS NOT NULL
d1f4d28d 744 )
745 OR
746 (
747 (
f32ef973 748 `me`.`price (#)` = `rownum__emulation`.`price (#)`
d1f4d28d 749 OR
f32ef973 750 ( `me`.`price (#)` IS NULL AND `rownum__emulation`.`price (#)` IS NULL )
d1f4d28d 751 )
752 AND
753 `rownum__emulation`.`id` < `me`.`id`
754 )
755 ) < ?
f32ef973 756 ORDER BY `me`.`price (#)` DESC, `me`.`id` ASC
d1f4d28d 757 )",
758 [
759 @select_bind,
760 @where_bind,
761 @group_bind,
762 @having_bind,
763 [ { sqlt_datatype => 'integer' } => 4 ],
764 ],
765 ],
766 ordered_limit_offset => [
767 "(
768 SELECT `me`.`id`, `owner__id`, `owner__name`, `bar`, `baz`
769 FROM (
f32ef973 770 SELECT `me`.`id`, `owner`.`id` AS `owner__id`, `owner`.`name` AS `owner__name`, ? * ? AS `bar`, ? AS `baz`, `me`.`price (#)`
d1f4d28d 771 FROM `books` `me`
772 JOIN `owners` `owner`
773 ON `owner`.`id` = `me`.`owner`
774 WHERE $where_string
775 GROUP BY (`me`.`id` / ?), `owner`.`id`
776 HAVING ?
777 ) `me`
778 WHERE (
779 SELECT COUNT( * )
780 FROM `books` `rownum__emulation`
781 WHERE
f32ef973 782 ( `me`.`price (#)` IS NULL AND `rownum__emulation`.`price (#)` IS NOT NULL )
d1f4d28d 783 OR
784 (
f32ef973 785 `rownum__emulation`.`price (#)` > `me`.`price (#)`
d1f4d28d 786 AND
f32ef973 787 `me`.`price (#)` IS NOT NULL
d1f4d28d 788 AND
f32ef973 789 `rownum__emulation`.`price (#)` IS NOT NULL
d1f4d28d 790 )
791 OR
792 (
793 (
f32ef973 794 `me`.`price (#)` = `rownum__emulation`.`price (#)`
d1f4d28d 795 OR
f32ef973 796 ( `me`.`price (#)` IS NULL AND `rownum__emulation`.`price (#)` IS NULL )
d1f4d28d 797 )
798 AND
799 `rownum__emulation`.`id` < `me`.`id`
800 )
801 ) BETWEEN ? AND ?
f32ef973 802 ORDER BY `me`.`price (#)` DESC, `me`.`id` ASC
d1f4d28d 803 )",
804 [
805 @select_bind,
806 @where_bind,
807 @group_bind,
808 @having_bind,
809 [ { sqlt_datatype => 'integer' } => 3 ],
810 [ { sqlt_datatype => 'integer' } => 6 ],
811 ],
812 ],
813 limit_offset_prefetch => [
814 "(
70e0e783 815 SELECT `me`.`name`, `books`.`id`, `books`.`source`, `books`.`owner`, `books`.`title`, `books`.`price (#)`, `books`.`short desc`
d1f4d28d 816 FROM (
817 SELECT `me`.`name`, `me`.`id`
818 FROM (
819 SELECT `me`.`name`, `me`.`id`
820 FROM `owners` `me`
821 ) `me`
822 WHERE
823 (
824 SELECT COUNT(*)
825 FROM `owners` `rownum__emulation`
826 WHERE (
827 `rownum__emulation`.`name` < `me`.`name`
828 OR
829 (
830 `me`.`name` = `rownum__emulation`.`name`
831 AND
832 `rownum__emulation`.`id` > `me`.`id`
833 )
834 )
835 ) BETWEEN ? AND ?
836 ORDER BY `me`.`name` ASC, `me`.`id` DESC
837 ) `me`
838 LEFT JOIN `books` `books`
839 ON `books`.`owner` = `me`.`id`
840 ORDER BY `me`.`name` ASC, `me`.`id` DESC
841 )",
842 [
843 [ { sqlt_datatype => 'integer' } => 1 ],
844 [ { sqlt_datatype => 'integer' } => 3 ],
845 ],
846 ],
847 }
848};
849
850for my $limtype (sort keys %$tests) {
851
852 Test::Builder->new->is_passing or exit;
853
854 delete $schema->storage->_sql_maker->{_cached_syntax};
855 $schema->storage->_sql_maker->limit_dialect ($limtype);
856
857 # not deploying, so can't run
858 my $can_run = 0 && ($limtype eq $native_limit_dialect or $limtype eq 'GenericSubQ');
859
860 # chained search is necessary to exercise the recursive {where} parser
861 my $rs = $schema->resultset('BooksInLibrary')->search(
862 { 'me.title' => { '=' => \[ '?', 'kama sutra' ] } }
863 )->search(
864 { source => { '!=', \[ '?', [ {} => 'Study' ] ] } },
865 {
866 columns => [ { identifier => 'me.id' }, 'owner.id', 'owner.name' ], # people actually do that. BLEH!!! :)
867 join => 'owner', # single-rel manual prefetch
868 rows => 4,
869 '+columns' => { bar => \['? * ?', [ \ 'numeric' => 11 ], 12 ], baz => \[ '?', [ 'me.id' => 13 ] ] },
870 group_by => \[ '(`me`.`id` / ?), `owner`.`id`', 21 ],
871 having => \[ '?', 31 ],
872 }
873 );
874
875 #
876 # not all tests run on all dialects (somewhere impossible, somewhere makes no sense)
877 #
878
879 # only limit, no offset, no order
880 if ($tests->{$limtype}{limit}) {
881 lives_ok {
882 is_same_sql_bind(
883 $rs->as_query,
884 @{$tests->{$limtype}{limit}},
885 "$limtype: Unordered limit with select/group/having",
886 );
887
888 $rs->all if $can_run;
889 } "Grouped limit under $limtype";
890 }
891
892 # limit + offset, no order
893 if ($tests->{$limtype}{limit_offset}) {
894
895 lives_ok {
896 my $subrs = $rs->search({}, { offset => 3 });
897
898 is_same_sql_bind(
899 $subrs->as_query,
900 @{$tests->{$limtype}{limit_offset}},
901 "$limtype: Unordered limit+offset with select/group/having",
902 );
903
904 $subrs->all if $can_run;
905 } "Grouped limit+offset runs under $limtype";
906 }
907
908 # order + limit, no offset
909 $rs = $rs->search(undef, {
910 order_by => ( $limtype =~ /GenericSubQ/
70e0e783 911 ? [ { -desc => 'price (#)' }, 'me.id', \[ '`owner`.`name` + ?', 'bah' ], \'`me`.`short desc`' ] # needs a same-table stable order to be happy
912 : [ \['? / ?', [ \ 'int' => 1 ], [ name => 2 ]], \[ '?', 3 ], \'`me`.`short desc`' ]
d1f4d28d 913 ),
914 });
915
916 if ($tests->{$limtype}{ordered_limit}) {
917
918 lives_ok {
919 is_same_sql_bind(
920 $rs->as_query,
921 @{$tests->{$limtype}{ordered_limit}},
922 "$limtype: Ordered limit with select/group/having",
923 );
924
925 $rs->all if $can_run;
926 } "Grouped ordered limit runs under $limtype"
927 }
928
929 # order + limit + offset
930 if ($tests->{$limtype}{ordered_limit_offset}) {
931 lives_ok {
932 my $subrs = $rs->search({}, { offset => 3 });
933
934 is_same_sql_bind(
935 $subrs->as_query,
936 @{$tests->{$limtype}{ordered_limit_offset}},
937 "$limtype: Ordered limit+offset with select/group/having",
938 );
939
940 $subrs->all if $can_run;
941 } "Grouped ordered limit+offset runs under $limtype";
942 }
943
944 # complex prefetch on partial-fetch root with limit
945 my $pref_rs = $schema->resultset('Owners')->search({}, {
946 rows => 3,
947 offset => 1,
948 columns => 'name', # only the owner name, still prefetch all the books
949 prefetch => 'books',
950 ($limtype !~ /GenericSubQ/ ? () : (
951 # needs a same-table stable order to be happy
952 order_by => [ { -asc => 'me.name' }, \ '`me`.`id` DESC' ]
953 )),
954 });
955
956 lives_ok {
957 is_same_sql_bind (
958 $pref_rs->as_query,
959 @{$tests->{$limtype}{limit_offset_prefetch}},
960 "$limtype: Prefetch with limit+offset",
961 ) if $tests->{$limtype}{limit_offset_prefetch};
962
963 is ($pref_rs->all, 1, 'Expected count of objects on limited prefetch')
964 if $can_run;
965 } "Complex limited prefetch runs under $limtype";
966}
967
968done_testing;