Fix Tester to deal properly with NOT and single parenthesized expressions
[dbsrgits/SQL-Abstract.git] / t / 10test.t
1 #!/usr/bin/perl
2
3 use strict;
4 use warnings;
5 use List::Util qw(sum);
6
7 use Test::More;
8
9 # equivalent to $Module::Install::AUTHOR
10 my $author = (
11   ( not -d './inc' )
12     or
13   ( -e ($^O eq 'VMS' ? './inc/_author' : './inc/.author') )
14 );
15
16 if (not $author and not $ENV{SQLATEST_TESTER} and not $ENV{AUTOMATED_TESTING}) {
17   plan skip_all => 'Skipping resource intensive self-tests, use SQLATEST_TESTER=1 to run';
18 }
19
20
21 my @sql_tests = (
22       # WHERE condition - equal
23       {
24         equal => 1,
25         statements => [
26           q/SELECT foo FROM bar WHERE a = 1/,
27           q/SELECT foo FROM bar WHERE a=1/,
28           q/SELECT foo FROM bar WHERE (a = 1)/,
29           q/SELECT foo FROM bar WHERE (a=1)/,
30           q/SELECT foo FROM bar WHERE ( a = 1 )/,
31           q/
32             SELECT
33               foo
34             FROM
35               bar
36             WHERE
37               a = 1
38           /,
39           q/
40             SELECT
41               foo
42             FROM
43               bar
44             WHERE
45               (a = 1)
46           /,
47           q/
48             SELECT
49               foo
50             FROM
51               bar
52             WHERE
53               ( a = 1 )
54           /,
55           q/SELECT foo FROM bar WHERE ((a = 1))/,
56           q/SELECT foo FROM bar WHERE ( (a = 1) )/,
57           q/SELECT foo FROM bar WHERE ( ( a = 1 ) )/,
58         ]
59       },
60       {
61         equal => 1,
62         statements => [
63           q/SELECT foo FROM bar WHERE a = 1 AND b = 1/,
64           q/SELECT foo FROM bar WHERE (a = 1) AND (b = 1)/,
65           q/SELECT foo FROM bar WHERE ((a = 1) AND (b = 1))/,
66           q/SELECT foo FROM bar WHERE (a = 1 AND b = 1)/,
67           q/SELECT foo FROM bar WHERE ((a = 1 AND b = 1))/,
68           q/SELECT foo FROM bar WHERE (((a = 1) AND (b = 1)))/,
69           q/
70             SELECT
71               foo
72             FROM
73               bar
74             WHERE
75               a = 1
76               AND
77               b = 1
78           /,
79           q/
80             SELECT
81               foo
82             FROM
83               bar
84             WHERE
85               (a = 1
86               AND
87               b = 1)
88           /,
89           q/
90             SELECT
91               foo
92             FROM
93               bar
94             WHERE
95               (a = 1)
96               AND
97               (b = 1)
98           /,
99           q/
100             SELECT
101               foo
102             FROM
103               bar
104             WHERE
105               ((a = 1)
106               AND
107               (b = 1))
108           /,
109         ]
110       },
111       {
112         equal => 1,
113         statements => [
114           q/SELECT foo FROM bar WHERE a = 1 AND b = 1 AND c = 1/,
115           q/SELECT foo FROM bar WHERE (a = 1 AND b = 1 AND c = 1)/,
116           q/SELECT foo FROM bar WHERE (a = 1 AND b = 1) AND c = 1/,
117           q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 AND c = 1)/,
118           q/SELECT foo FROM bar WHERE ((((a = 1))) AND (b = 1 AND c = 1))/,
119         ]
120       },
121       {
122         equal => 1,
123         statements => [
124           q/SELECT foo FROM bar WHERE a = 1 OR b = 1 OR c = 1/,
125           q/SELECT foo FROM bar WHERE (a = 1 OR b = 1) OR c = 1/,
126           q/SELECT foo FROM bar WHERE a = 1 OR (b = 1 OR c = 1)/,
127           q/SELECT foo FROM bar WHERE a = 1 OR ((b = 1 OR (c = 1)))/,
128         ]
129       },
130       {
131         equal => 1,
132         statements => [
133           q/SELECT foo FROM bar WHERE (a = 1) AND (b = 1 OR c = 1 OR d = 1) AND (e = 1 AND f = 1)/,
134           q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 OR c = 1 OR d = 1) AND e = 1 AND (f = 1)/,
135           q/SELECT foo FROM bar WHERE ( ((a = 1) AND ( b = 1 OR (c = 1 OR d = 1) )) AND ((e = 1)) AND f = 1) /,
136         ]
137       },
138       {
139         equal => 1,
140         statements => [
141           q/SELECT foo FROM bar WHERE (a) AND (b = 2)/,
142           q/SELECT foo FROM bar WHERE (a AND b = 2)/,
143           q/SELECT foo FROM bar WHERE (a AND (b = 2))/,
144           q/SELECT foo FROM bar WHERE a AND (b = 2)/,
145         ]
146       },
147       {
148         equal => 0,
149         statements => [
150           q/SELECT foo FROM bar WHERE NOT a AND (b = 2)/,
151           q/SELECT foo FROM bar WHERE (NOT a) AND (b = 2)/,
152         ]
153       },
154       {
155         equal => 0,
156         parenthesis_significant => 1,
157         statements => [
158           q/SELECT foo FROM bar WHERE a = 1 AND b = 1 AND c = 1/,
159           q/SELECT foo FROM bar WHERE (a = 1 AND b = 1 AND c = 1)/,
160           q/SELECT foo FROM bar WHERE (a = 1 AND b = 1) AND c = 1/,
161           q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 AND c = 1)/,
162           q/SELECT foo FROM bar WHERE ((((a = 1))) AND (b = 1 AND c = 1))/,
163         ]
164       },
165       {
166         equal => 0,
167         parenthesis_significant => 1,
168         statements => [
169           q/SELECT foo FROM bar WHERE a = 1 OR b = 1 OR c = 1/,
170           q/SELECT foo FROM bar WHERE (a = 1 OR b = 1) OR c = 1/,
171           q/SELECT foo FROM bar WHERE a = 1 OR (b = 1 OR c = 1)/,
172           q/SELECT foo FROM bar WHERE a = 1 OR ((b = 1 OR (c = 1)))/,
173         ]
174       },
175       {
176         equal => 0,
177         parenthesis_significant => 1,
178         statements => [
179           q/SELECT foo FROM bar WHERE (a = 1) AND (b = 1 OR c = 1 OR d = 1) AND (e = 1 AND f = 1)/,
180           q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 OR c = 1 OR d = 1) AND e = 1 AND (f = 1)/,
181           q/SELECT foo FROM bar WHERE ( ((a = 1) AND ( b = 1 OR (c = 1 OR d = 1) )) AND ((e = 1)) AND f = 1) /,
182         ]
183       },
184
185       # WHERE condition - different
186       {
187         equal => 0,
188         statements => [
189           q/SELECT foo FROM bar WHERE a = 1/,
190           q/SELECT quux FROM bar WHERE a = 1/,
191           q/SELECT foo FROM quux WHERE a = 1/,
192           q/FOOBAR foo FROM bar WHERE a = 1/,
193
194           q/SELECT foo FROM bar WHERE a = 2/,
195           q/SELECT foo FROM bar WHERE a < 1/,
196           q/SELECT foo FROM bar WHERE b = 1/,
197           q/SELECT foo FROM bar WHERE (c = 1)/,
198           q/SELECT foo FROM bar WHERE (d = 1)/,
199
200           q/SELECT foo FROM bar WHERE a = 1 AND quux/,
201           q/SELECT foo FROM bar WHERE a = 1 GROUP BY foo/,
202           q/SELECT foo FROM bar WHERE a = 1 ORDER BY foo/,
203           q/SELECT foo FROM bar WHERE a = 1 LIMIT 1/,
204           q/SELECT foo FROM bar WHERE a = 1 OFFSET 1/,
205           q/SELECT foo FROM bar JOIN quux WHERE a = 1/,
206           q/SELECT foo FROM bar JOIN quux ON a = 1 WHERE a = 1/,
207         ]
208       },
209       {
210         equal => 0,
211         statements => [
212           q/SELECT foo FROM bar WHERE a = 1 AND b = 1/,
213           q/SELECT quux FROM bar WHERE a = 1 AND b = 1/,
214           q/SELECT foo FROM quux WHERE a = 1 AND b = 1/,
215           q/FOOBAR foo FROM bar WHERE a = 1 AND b = 1/,
216
217           q/SELECT foo FROM bar WHERE a = 2 AND b = 1/,
218           q/SELECT foo FROM bar WHERE a = 3 AND (b = 1)/,
219           q/SELECT foo FROM bar WHERE (a = 4) AND b = 1/,
220           q/SELECT foo FROM bar WHERE (a = 5) AND (b = 1)/,
221           q/SELECT foo FROM bar WHERE ((a = 6) AND (b = 1))/,
222           q/SELECT foo FROM bar WHERE ((a = 7) AND (b = 1))/,
223
224           q/SELECT foo FROM bar WHERE a = 1 AND b = 2/,
225           q/SELECT foo FROM bar WHERE a = 1 AND (b = 3)/,
226           q/SELECT foo FROM bar WHERE (a = 1) AND b = 4/,
227           q/SELECT foo FROM bar WHERE (a = 1) AND (b = 5)/,
228           q/SELECT foo FROM bar WHERE ((a = 1) AND (b = 6))/,
229           q/SELECT foo FROM bar WHERE ((a = 1) AND (b = 7))/,
230
231           q/SELECT foo FROM bar WHERE a < 1 AND b = 1/,
232           q/SELECT foo FROM bar WHERE b = 1 AND b = 1/,
233           q/SELECT foo FROM bar WHERE (c = 1) AND b = 1/,
234           q/SELECT foo FROM bar WHERE (d = 1) AND b = 1/,
235
236           q/SELECT foo FROM bar WHERE a = 1 AND b = 1 AND quux/,
237           q/SELECT foo FROM bar WHERE a = 1 AND b = 1 GROUP BY foo/,
238           q/SELECT foo FROM bar WHERE a = 1 AND b = 1 ORDER BY foo/,
239           q/SELECT foo FROM bar WHERE a = 1 AND b = 1 LIMIT 1/,
240           q/SELECT foo FROM bar WHERE a = 1 AND b = 1 OFFSET 1/,
241           q/SELECT foo FROM bar JOIN quux WHERE a = 1 AND b = 1/,
242           q/SELECT foo FROM bar JOIN quux ON a = 1 WHERE a = 1 AND b = 1/,
243         ]
244       },
245       {
246         equal => 0,
247         statements => [
248           q/SELECT foo FROM bar WHERE a = 1 AND b = 1 OR c = 1/,
249           q/SELECT foo FROM bar WHERE (a = 1 AND b = 1) OR c = 1/,
250           q/SELECT foo FROM bar WHERE a = 1 AND (b = 1 OR c = 1)/,
251         ]
252       },
253       {
254         equal => 0,
255         statements => [
256           q/SELECT foo FROM bar WHERE a = 1 OR b = 1 AND c = 1/,
257           q/SELECT foo FROM bar WHERE (a = 1 OR b = 1) AND c = 1/,
258           q/SELECT foo FROM bar WHERE a = 1 OR (b = 1 AND c = 1)/,
259         ]
260       },
261       {
262         equal => 0,
263         statements => [
264           # BETWEEN with/without parenthesis around itself/RHS is a sticky business
265           # if I made a mistake here, simply rewrite the special BETWEEN handling in
266           # _recurse_parse()
267           #
268           # by RIBASUSHI
269           q/SELECT foo FROM bar WHERE ( completion_date BETWEEN ? AND ? AND status = ? )/,
270           q/SELECT foo FROM bar WHERE completion_date BETWEEN (? AND ?) AND status = ?/,
271           q/SELECT foo FROM bar WHERE ( (completion_date BETWEEN (? AND ?) ) AND status = ? )/,
272           q/SELECT foo FROM bar WHERE ( (completion_date BETWEEN (? AND ? AND status = ?) ) )/,
273         ]
274       },
275
276       # JOIN condition - equal
277       {
278         equal => 1,
279         statements => [
280           q/SELECT foo FROM bar JOIN baz ON a = 1 WHERE x = 1/,
281           q/SELECT foo FROM bar JOIN baz ON a=1 WHERE x = 1/,
282           q/SELECT foo FROM bar JOIN baz ON (a = 1) WHERE x = 1/,
283           q/SELECT foo FROM bar JOIN baz ON (a=1) WHERE x = 1/,
284           q/SELECT foo FROM bar JOIN baz ON ( a = 1 ) WHERE x = 1/,
285           q/
286             SELECT
287               foo
288             FROM
289               bar
290             JOIN
291               baz
292             ON
293               a = 1
294             WHERE
295               x = 1
296           /,
297           q/
298             SELECT
299               foo
300             FROM
301               bar
302             JOIN
303               baz
304             ON
305               (a = 1)
306             WHERE
307               x = 1
308           /,
309           q/
310             SELECT
311               foo
312             FROM
313               bar
314             JOIN
315               baz
316             ON
317               ( a = 1 )
318             WHERE
319               x = 1
320           /,
321           q/SELECT foo FROM bar JOIN baz ON ((a = 1)) WHERE x = 1/,
322           q/SELECT foo FROM bar JOIN baz ON ( (a = 1) ) WHERE x = 1/,
323           q/SELECT foo FROM bar JOIN baz ON ( ( a = 1 ) ) WHERE x = 1/,
324         ]
325       },
326       {
327         equal => 1,
328         statements => [
329           q/SELECT foo FROM bar JOIN baz ON a = 1 AND b = 1 WHERE x = 1/,
330           q/SELECT foo FROM bar JOIN baz ON (a = 1) AND (b = 1) WHERE x = 1/,
331           q/SELECT foo FROM bar JOIN baz ON ((a = 1) AND (b = 1)) WHERE x = 1/,
332           q/SELECT foo FROM bar JOIN baz ON (a = 1 AND b = 1) WHERE x = 1/,
333           q/SELECT foo FROM bar JOIN baz ON ((a = 1 AND b = 1)) WHERE x = 1/,
334           q/SELECT foo FROM bar JOIN baz ON (((a = 1) AND (b = 1))) WHERE x = 1/,
335           q/
336             SELECT
337               foo
338             FROM
339               bar
340             JOIN
341               baz
342             ON
343               a = 1
344               AND
345               b = 1
346             WHERE
347               x = 1
348           /,
349           q/
350             SELECT
351               foo
352             FROM
353               bar
354             JOIN
355               baz
356             ON
357               (a = 1
358               AND
359               b = 1)
360             WHERE
361               x = 1
362           /,
363           q/
364             SELECT
365               foo
366             FROM
367               bar
368             JOIN
369               baz
370             ON
371               (a = 1)
372               AND
373               (b = 1)
374             WHERE
375               x = 1
376           /,
377           q/
378             SELECT
379               foo
380             FROM
381               bar
382             JOIN
383               baz
384             ON
385               ((a = 1)
386               AND
387               (b = 1))
388             WHERE
389               x = 1
390           /,
391         ]
392       },
393
394       # JOIN condition - different
395       {
396         equal => 0,
397         statements => [
398           q/SELECT foo FROM bar JOIN quux ON a = 1 WHERE quuux/,
399           q/SELECT quux FROM bar JOIN quux ON a = 1 WHERE quuux/,
400           q/SELECT foo FROM quux JOIN quux ON a = 1 WHERE quuux/,
401           q/FOOBAR foo FROM bar JOIN quux ON a = 1 WHERE quuux/,
402
403           q/SELECT foo FROM bar JOIN quux ON a = 2 WHERE quuux/,
404           q/SELECT foo FROM bar JOIN quux ON a < 1 WHERE quuux/,
405           q/SELECT foo FROM bar JOIN quux ON b = 1 WHERE quuux/,
406           q/SELECT foo FROM bar JOIN quux ON (c = 1) WHERE quuux/,
407           q/SELECT foo FROM bar JOIN quux ON (d = 1) WHERE quuux/,
408
409           q/SELECT foo FROM bar JOIN quux ON a = 1 AND quuux/,
410           q/SELECT foo FROM bar JOIN quux ON a = 1 GROUP BY foo/,
411           q/SELECT foo FROM bar JOIN quux ON a = 1 ORDER BY foo/,
412           q/SELECT foo FROM bar JOIN quux ON a = 1 LIMIT 1/,
413           q/SELECT foo FROM bar JOIN quux ON a = 1 OFFSET 1/,
414           q/SELECT foo FROM bar JOIN quux ON a = 1 JOIN quuux/,
415           q/SELECT foo FROM bar JOIN quux ON a = 1 JOIN quuux ON a = 1/,
416         ]
417       },
418       {
419         equal => 0,
420         statements => [
421           q/SELECT foo FROM bar JOIN quux ON a = 1 AND b = 1 WHERE quuux/,
422           q/SELECT quux FROM bar JOIN quux ON a = 1 AND b = 1 WHERE quuux/,
423           q/SELECT foo FROM quux JOIN quux ON a = 1 AND b = 1 WHERE quuux/,
424           q/FOOBAR foo FROM bar JOIN quux ON a = 1 AND b = 1 WHERE quuux/,
425
426           q/SELECT foo FROM bar JOIN quux ON a = 2 AND b = 1 WHERE quuux/,
427           q/SELECT foo FROM bar JOIN quux ON a = 3 AND (b = 1) WHERE quuux/,
428           q/SELECT foo FROM bar JOIN quux ON (a = 4) AND b = 1 WHERE quuux/,
429           q/SELECT foo FROM bar JOIN quux ON (a = 5) AND (b = 1) WHERE quuux/,
430           q/SELECT foo FROM bar JOIN quux ON ((a = 6) AND (b = 1)) WHERE quuux/,
431           q/SELECT foo FROM bar JOIN quux ON ((a = 7) AND (b = 1)) WHERE quuux/,
432
433           q/SELECT foo FROM bar JOIN quux ON a = 1 AND b = 2 WHERE quuux/,
434           q/SELECT foo FROM bar JOIN quux ON a = 1 AND (b = 3) WHERE quuux/,
435           q/SELECT foo FROM bar JOIN quux ON (a = 1) AND b = 4 WHERE quuux/,
436           q/SELECT foo FROM bar JOIN quux ON (a = 1) AND (b = 5) WHERE quuux/,
437           q/SELECT foo FROM bar JOIN quux ON ((a = 1) AND (b = 6)) WHERE quuux/,
438           q/SELECT foo FROM bar JOIN quux ON ((a = 1) AND (b = 7)) WHERE quuux/,
439
440           q/SELECT foo FROM bar JOIN quux ON a < 1 AND b = 1 WHERE quuux/,
441           q/SELECT foo FROM bar JOIN quux ON b = 1 AND b = 1 WHERE quuux/,
442           q/SELECT foo FROM bar JOIN quux ON (c = 1) AND b = 1 WHERE quuux/,
443           q/SELECT foo FROM bar JOIN quux ON (d = 1) AND b = 1 WHERE quuux/,
444
445           q/SELECT foo FROM bar JOIN quux ON a = 1 AND b = 1 AND quuux/,
446           q/SELECT foo FROM bar JOIN quux ON a = 1 AND b = 1 GROUP BY foo/,
447           q/SELECT foo FROM bar JOIN quux ON a = 1 AND b = 1 ORDER BY foo/,
448           q/SELECT foo FROM bar JOIN quux ON a = 1 AND b = 1 LIMIT 1/,
449           q/SELECT foo FROM bar JOIN quux ON a = 1 AND b = 1 OFFSET 1/,
450           q/SELECT foo FROM bar JOIN quux JOIN quuux ON a = 1 AND b = 1/,
451           q/SELECT foo FROM bar JOIN quux ON a = 1 JOIN quuux ON a = 1 AND b = 1/,
452         ]
453       },
454
455       # DISTINCT ON (...) not confused with JOIN ON (...)
456       {
457         equal => 1,
458         statements => [
459           q/SELECT DISTINCT ON (foo, quux) foo, quux FROM bar WHERE a = 1/,
460           q/SELECT DISTINCT ON (foo, quux) foo, quux FROM bar WHERE a=1/,
461           q/SELECT DISTINCT ON (foo, quux) foo, quux FROM bar WHERE (a = 1)/,
462           q/SELECT DISTINCT ON (foo, quux) foo, quux FROM bar WHERE (a=1)/,
463           q/SELECT DISTINCT ON (foo, quux) foo, quux FROM bar WHERE ( a = 1 )/,
464           q/
465             SELECT DISTINCT ON (foo, quux)
466               foo,
467               quux
468             FROM
469               bar
470             WHERE
471               a = 1
472           /,
473           q/
474             SELECT DISTINCT ON (foo, quux)
475               foo,
476               quux
477             FROM
478               bar
479             WHERE
480               (a = 1)
481           /,
482           q/
483             SELECT DISTINCT ON (foo, quux)
484               foo,
485               quux
486             FROM
487               bar
488             WHERE
489               ( a = 1 )
490           /,
491           q/SELECT DISTINCT ON (foo, quux) foo, quux FROM bar WHERE ((a = 1))/,
492           q/SELECT DISTINCT ON (foo, quux) foo, quux FROM bar WHERE ( (a = 1) )/,
493           q/SELECT DISTINCT ON (foo, quux) foo, quux FROM bar WHERE ( ( a = 1 ) )/,
494         ]
495       },
496
497       # subselects - equal
498       {
499         equal => 1,
500         statements => [
501           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1) AS foo WHERE a = 1/,
502           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1) AS foo WHERE (a = 1)/,
503           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1)) AS foo WHERE a = 1/,
504           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1)) AS foo WHERE (a = 1)/,
505         ]
506       },
507       {
508         equal => 1,
509         statements => [
510           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND c = 1) AS foo WHERE a = 1/,
511           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND (c = 1)) AS foo WHERE a = 1/,
512           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND c = 1) AS foo WHERE a = 1/,
513           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND (c = 1)) AS foo WHERE a = 1/,
514           q/SELECT * FROM (SELECT * FROM bar WHERE ((b = 1) AND (c = 1))) AS foo WHERE a = 1/,
515
516           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND c = 1) AS foo WHERE (a = 1)/,
517           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND (c = 1)) AS foo WHERE (a = 1)/,
518           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND c = 1) AS foo WHERE (a = 1)/,
519           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND (c = 1)) AS foo WHERE (a = 1)/,
520           q/SELECT * FROM (SELECT * FROM bar WHERE ((b = 1) AND (c = 1))) AS foo WHERE (a = 1)/,
521         ]
522       },
523
524       # subselects - different
525       {
526         equal => 0,
527         statements => [
528           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1) AS foo WHERE a = 1/,
529           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1) AS foo WHERE a = 2/,
530           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1) AS foo WHERE (a = 3)/,
531           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1)) AS foo WHERE a = 4/,
532           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1)) AS foo WHERE (a = 5)/,
533           q/SELECT * FROM (SELECT * FROM bar WHERE b = 2) AS foo WHERE a = 1/,
534           q/SELECT * FROM (SELECT * FROM bar WHERE b = 3) AS foo WHERE (a = 1)/,
535           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 4)) AS foo WHERE a = 1/,
536           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 5)) AS foo WHERE (a = 1)/,
537         ]
538       },
539       {
540         equal => 0,
541         statements => [
542           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND c = 1) AS foo WHERE a = 1/,
543           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND c = 2) AS foo WHERE a = 1/,
544           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND (c = 3)) AS foo WHERE a = 1/,
545           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND (c = 4)) AS foo WHERE a = 1/,
546           q/SELECT * FROM (SELECT * FROM bar WHERE ((b = 1) AND (c = 5))) AS foo WHERE a = 1/,
547
548           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND c = 6) AS foo WHERE (a = 1)/,
549           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND c = 7) AS foo WHERE (a = 1)/,
550           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND (c = 8)) AS foo WHERE (a = 1)/,
551           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND (c = 9)) AS foo WHERE (a = 1)/,
552           q/SELECT * FROM (SELECT * FROM bar WHERE ((b = 1) AND (c = 10))) AS foo WHERE (a = 1)/,
553
554           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND c = 1) AS foo WHERE a = 2/,
555           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND c = 2) AS foo WHERE a = 2/,
556           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND (c = 3)) AS foo WHERE a = 2/,
557           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND (c = 4)) AS foo WHERE a = 2/,
558           q/SELECT * FROM (SELECT * FROM bar WHERE ((b = 1) AND (c = 5))) AS foo WHERE a = 2/,
559
560           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND c = 6) AS foo WHERE (a = 2)/,
561           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND c = 7) AS foo WHERE (a = 2)/,
562           q/SELECT * FROM (SELECT * FROM bar WHERE b = 1 AND (c = 8)) AS foo WHERE (a = 2)/,
563           q/SELECT * FROM (SELECT * FROM bar WHERE (b = 1) AND (c = 9)) AS foo WHERE (a = 2)/,
564           q/SELECT * FROM (SELECT * FROM bar WHERE ((b = 1) AND (c = 10))) AS foo WHERE (a = 2)/,
565         ]
566       },
567 );
568
569 my @bind_tests = (
570   # scalar - equal
571   {
572     equal => 1,
573     bindvals => [
574       undef,
575       undef,
576     ]
577   },
578   {
579     equal => 1,
580     bindvals => [
581       'foo',
582       'foo',
583     ]
584   },
585   {
586     equal => 1,
587     bindvals => [
588       42,
589       42,
590       '42',
591     ]
592   },
593
594   # scalarref - equal
595   {
596     equal => 1,
597     bindvals => [
598       \'foo',
599       \'foo',
600     ]
601   },
602   {
603     equal => 1,
604     bindvals => [
605       \42,
606       \42,
607       \'42',
608     ]
609   },
610
611   # arrayref - equal
612   {
613     equal => 1,
614     bindvals => [
615       [],
616       []
617     ]
618   },
619   {
620     equal => 1,
621     bindvals => [
622       [42],
623       [42],
624       ['42'],
625     ]
626   },
627   {
628     equal => 1,
629     bindvals => [
630       [1, 42],
631       [1, 42],
632       ['1', 42],
633       [1, '42'],
634       ['1', '42'],
635     ]
636   },
637
638   # hashref - equal
639   {
640     equal => 1,
641     bindvals => [
642       { foo => 42 },
643       { foo => 42 },
644       { foo => '42' },
645     ]
646   },
647   {
648     equal => 1,
649     bindvals => [
650       { foo => 42, bar => 1 },
651       { foo => 42, bar => 1 },
652       { foo => '42', bar => 1 },
653     ]
654   },
655
656   # blessed object - equal
657   {
658     equal => 1,
659     bindvals => [
660       bless(\(local $_ = 42), 'Life::Universe::Everything'),
661       bless(\(local $_ = 42), 'Life::Universe::Everything'),
662     ]
663   },
664   {
665     equal => 1,
666     bindvals => [
667       bless([42], 'Life::Universe::Everything'),
668       bless([42], 'Life::Universe::Everything'),
669     ]
670   },
671   {
672     equal => 1,
673     bindvals => [
674       bless({ answer => 42 }, 'Life::Universe::Everything'),
675       bless({ answer => 42 }, 'Life::Universe::Everything'),
676     ]
677   },
678
679   # complex data structure - equal
680   {
681     equal => 1,
682     bindvals => [
683       [42, { foo => 'bar', quux => [1, 2, \3, { quux => [4, 5] } ] }, 8 ],
684       [42, { foo => 'bar', quux => [1, 2, \3, { quux => [4, 5] } ] }, 8 ],
685     ]
686   },
687
688
689   # scalar - different
690   {
691     equal => 0,
692     bindvals => [
693       undef,
694       'foo',
695       42,
696     ]
697   },
698
699   # scalarref - different
700   {
701     equal => 0,
702     bindvals => [
703       \undef,
704       \'foo',
705       \42,
706     ]
707   },
708
709   # arrayref - different
710   {
711     equal => 0,
712     bindvals => [
713       [undef],
714       ['foo'],
715       [42],
716     ]
717   },
718
719   # hashref - different
720   {
721     equal => 0,
722     bindvals => [
723       { foo => undef },
724       { foo => 'bar' },
725       { foo => 42 },
726     ]
727   },
728
729   # different types
730   {
731     equal => 0,
732     bindvals => [
733       'foo',
734       \'foo',
735       ['foo'],
736       { foo => 'bar' },
737     ]
738   },
739
740   # complex data structure - different
741   {
742     equal => 0,
743     bindvals => [
744       [42, { foo => 'bar', quux => [1, 2, \3, { quux => [4, 5] } ] }, 8 ],
745       [43, { foo => 'bar', quux => [1, 2, \3, { quux => [4, 5] } ] }, 8 ],
746       [42, { foo => 'baz', quux => [1, 2, \3, { quux => [4, 5] } ] }, 8 ],
747       [42, { bar => 'bar', quux => [1, 2, \3, { quux => [4, 5] } ] }, 8 ],
748       [42, { foo => 'bar', quuux => [1, 2, \3, { quux => [4, 5] } ] }, 8 ],
749       [42, { foo => 'bar', quux => [0, 1, 2, \3, { quux => [4, 5] } ] }, 8 ],
750       [42, { foo => 'bar', quux => [1, 2, 3, { quux => [4, 5] } ] }, 8 ],
751       [42, { foo => 'bar', quux => [1, 2, \4, { quux => [4, 5] } ] }, 8 ],
752       [42, { foo => 'bar', quux => [1, 2, \3, { quuux => [4, 5] } ] }, 8 ],
753       [42, { foo => 'bar', quux => [1, 2, \3, { quux => [4, 5, 6] } ] }, 8 ],
754       [42, { foo => 'bar', quux => [1, 2, \3, { quux => 4 } ] }, 8 ],
755       [42, { foo => 'bar', quux => [1, 2, \3, { quux => [4, 5], quuux => 1 } ] }, 8 ],
756       [42, { foo => 'bar', quux => [1, 2, \3, { quux => [4, 5] } ] }, 8, 9 ],
757     ]
758   },
759 );
760
761 plan tests => 1 +
762   sum(
763     map { $_ * ($_ - 1) / 2 }
764       map { scalar @{$_->{statements}} }
765         @sql_tests
766   ) +
767   sum(
768     map { $_ * ($_ - 1) / 2 }
769       map { scalar @{$_->{bindvals}} }
770         @bind_tests
771   ) +
772   3;
773
774 use_ok('SQL::Abstract::Test', import => [qw(
775   eq_sql_bind eq_sql eq_bind is_same_sql_bind
776 )]);
777
778 for my $test (@sql_tests) {
779   my $statements = $test->{statements};
780   while (@$statements) {
781     my $sql1 = shift @$statements;
782     foreach my $sql2 (@$statements) {
783
784       no warnings qw/once/; # perl 5.10 is dumb
785       local $SQL::Abstract::Test::parenthesis_significant = $test->{parenthesis_significant}
786         if $test->{parenthesis_significant};
787       my $equal = eq_sql($sql1, $sql2);
788
789       TODO: {
790         local $TODO = $test->{todo} if $test->{todo};
791
792         if ($test->{equal}) {
793           ok($equal, "equal SQL expressions should have been considered equal");
794         } else {
795           ok(!$equal, "different SQL expressions should have been considered not equal");
796         }
797
798         if ($equal ^ $test->{equal}) {
799           diag("sql1: $sql1");
800           diag("sql2: $sql2");
801         }
802       }
803     }
804   }
805 }
806
807 for my $test (@bind_tests) {
808   my $bindvals = $test->{bindvals};
809   while (@$bindvals) {
810     my $bind1 = shift @$bindvals;
811     foreach my $bind2 (@$bindvals) {
812       my $equal = eq_bind($bind1, $bind2);
813       if ($test->{equal}) {
814         ok($equal, "equal bind values considered equal");
815       } else {
816         ok(!$equal, "different bind values considered not equal");
817       }
818
819       if ($equal ^ $test->{equal}) {
820         diag("bind1: " . Dumper($bind1));
821         diag("bind2: " . Dumper($bind2));
822       }
823     }
824   }
825 }
826
827 ok(eq_sql_bind(
828     "SELECT * FROM foo WHERE id = ?", [42],
829     "SELECT * FROM foo WHERE (id = ?)", [42],
830   ),
831   "eq_sql_bind considers equal SQL expressions and bind values equal"
832 );
833
834
835 ok(!eq_sql_bind(
836     "SELECT * FROM foo WHERE id = ?", [42],
837     "SELECT * FROM foo WHERE (id = ?)", [0],
838   ),
839   "eq_sql_bind considers equal SQL expressions and different bind values different"
840 );
841
842 ok(!eq_sql_bind(
843     "SELECT * FROM foo WHERE id = ?", [42],
844     "SELECT * FROM bar WHERE (id = ?)", [42],
845   ),
846   "eq_sql_bind considers different SQL expressions and equal bind values different"
847 );