Refactor test code a bit
[dbsrgits/SQL-Abstract-2.0-ish.git] / t / compat / ast / 01.t
1 use strict;
2 use warnings;
3
4 use FindBin;
5 use lib "$FindBin::Bin/../../lib";
6 use Test::SQL::Abstract::Util qw/
7   mk_name
8   mk_value
9   field_op_value
10   :dumper_sort
11 /;
12
13 use SQL::Abstract::Compat;
14
15 use Test::More tests => 17;
16 use Test::Differences;
17
18 ok(my $visitor = SQL::Abstract::Compat->new);
19
20
21 my $foo_id = { -type => 'identifier', elements => [qw/foo/] };
22 my $bar_id = { -type => 'identifier', elements => [qw/bar/] };
23
24 my $foo_eq_1 = field_op_value($foo_id, '==', 1);
25 my $bar_eq_str = field_op_value($bar_id, '==', 'some str');
26
27 eq_or_diff
28   $visitor->recurse_where({ foo => 1 }),
29   $foo_eq_1,
30   "Single value hash";
31
32
33
34 eq_or_diff
35   $visitor->recurse_where({ foo => 1, bar => 'some str' }),
36   { -type => 'expr',
37     op => 'and',
38     args => [
39       $bar_eq_str,
40       $foo_eq_1,
41     ]
42   },
43   "two keys in hash";
44
45 eq_or_diff
46   $visitor->recurse_where({ -or => { foo => 1, bar => 'some str' } }),
47   { -type => 'expr',
48     op => 'or',
49     args => [
50       $bar_eq_str,
51       $foo_eq_1,
52     ]
53   },
54   "-or key in hash";
55
56
57 eq_or_diff
58   $visitor->recurse_where([ -and => { foo => 1, bar => 'some str' } ]),
59   { -type => 'expr',
60     op => 'and',
61     args => [
62       $bar_eq_str,
63       $foo_eq_1,
64     ]
65   },
66   "-and as first element of array";
67
68
69 eq_or_diff
70   $visitor->recurse_where([ -and => { foo => 1, bar => 'some str' }, { foo => 1} ]),
71   { -type => 'expr',
72     op => 'or',
73     args => [
74       { -type => 'expr',
75         op => 'and',
76         args => [
77           $bar_eq_str,
78           $foo_eq_1,
79         ]
80       },
81       $foo_eq_1,
82     ]
83   },
84   "-and as first element of array + hash";
85
86 eq_or_diff
87   $visitor->recurse_where({ foo => { '!=' => 'bar' } }),
88   field_op_value($foo_id, '!=', 'bar'),
89   "foo => { '!=' => 'bar' }";
90
91 eq_or_diff
92   $visitor->recurse_where({ foo => [ 1, 'bar' ] }),
93   { -type => 'expr',
94     op => 'or',
95     args => [
96       $foo_eq_1,
97       field_op_value($foo_id, '==', 'bar'),
98     ],
99   },
100   "foo => [ 1, 'bar' ]";
101
102 eq_or_diff
103   $visitor->recurse_where({ foo => { -in => [ 1, 'bar' ] } }),
104   { -type => 'expr',
105     op => 'in',
106     args => [
107       $foo_id,
108       { -type => 'value', value => 1 },
109       { -type => 'value', value => 'bar' },
110     ]
111   },
112   "foo => { -in => [ 1, 'bar' ] }";
113
114 eq_or_diff
115   $visitor->recurse_where({ foo => { -not_in => [ 1, 'bar' ] } }),
116   { -type => 'expr',
117     op => 'not_in',
118     args => [
119       $foo_id,
120       { -type => 'value', value => 1 },
121       { -type => 'value', value => 'bar' },
122     ]
123   },
124   "foo => { -not_in => [ 1, 'bar' ] }";
125
126 eq_or_diff
127   $visitor->recurse_where({ foo => { -in => [ ] } }),
128   { -type => 'expr',
129     op => 'in',
130     args => [
131       $foo_id,
132     ]
133   },
134   "foo => { -in => [ ] }";
135
136 my $worker_eq = sub {
137   return { 
138     -type => 'expr',
139     op => '==',
140     args => [
141       { -type => 'identifier', elements => ['worker'] },
142       { -type => 'value', value => $_[0] },
143     ],
144   }
145 };
146
147 eq_or_diff
148   $visitor->recurse_where( {
149     requestor => 'inna',
150     worker => ['nwiger', 'rcwe', 'sfz'],
151     status => { '!=', 'completed' }
152   } ),
153   { -type => 'expr',
154     op => 'and',
155     args => [
156       field_op_value(qw/requestor == inna/),
157       field_op_value(qw/status != completed/), 
158       { -type => 'expr',
159         op => 'or',
160         args => [
161           field_op_value(qw/worker == nwiger/), 
162           field_op_value(qw/worker == rcwe/), 
163           field_op_value(qw/worker == sfz/), 
164         ]
165       },
166     ]
167   },
168   "complex expr 1";
169
170
171 $visitor->convert('UPPER');
172
173 my $ticket_or_eq = { 
174   -type => 'expr', 
175   op => 'or',
176   args => [
177     field_op_value( upper(mk_name('ticket')), '==', upper(mk_value(11))),
178     field_op_value( upper(mk_name('ticket')), '==', upper(mk_value(12))),
179     field_op_value( upper(mk_name('ticket')), '==', upper(mk_value(13))),
180   ] 
181 };
182
183 eq_or_diff
184   $visitor->select_ast(
185     'test', '*', [ { ticket => [11, 12, 13] } ]
186   ),
187   { -type => 'select',
188     columns => [ { -type => 'identifier', elements => ['*'] } ],
189     tablespec => { -type => 'identifier', elements => ['test'] },
190     where => $ticket_or_eq
191   },
192   "Complex AST with convert('UPPER')";
193
194 my $hostname_and_ticket = {
195   -type => 'expr',
196   op => 'and',
197   args => [
198     field_op_value( upper(mk_name('hostname')),
199                     in => [ map {
200                       upper(mk_value($_))
201                     } qw/ntf avd bvd 123/ ]
202                   ),
203     $ticket_or_eq,
204   ]
205 };
206
207 eq_or_diff
208   $visitor->select_ast(
209     'test', '*', [ { ticket => [11, 12, 13],
210                      hostname => { in => ['ntf', 'avd', 'bvd', '123'] }
211                    }
212                  ]
213   ),
214   { -type => 'select',
215     columns => [ { -type => 'identifier', elements => ['*'] } ],
216     tablespec => { -type => 'identifier', elements => ['test'] },
217     where => $hostname_and_ticket
218   },
219   "Complex AST mixing arrays+hashes with convert('UPPER')";
220
221 my $tack_between = {
222   -type => 'expr',
223   op => 'between',
224   args => [
225     upper(mk_name('tack')),
226     upper(mk_value('tick')),
227     upper(mk_value('tock')),
228   ]
229 };
230
231 eq_or_diff
232   $visitor->select_ast(
233     'test', '*', [ { ticket => [11, 12, 13],
234                      hostname => { in => ['ntf', 'avd', 'bvd', '123'] }
235                    },
236                    { tack => { between => [qw/tick tock/] } }
237                  ]
238   ),
239   { -type => 'select',
240     columns => [ { -type => 'identifier', elements => ['*'] } ],
241     tablespec => { -type => 'identifier', elements => ['test'] },
242     where => {
243       -type => 'expr',
244       op => 'or',
245       args => [
246         $hostname_and_ticket,
247         $tack_between,
248       ]
249     }
250   },
251   "Complex AST mixing [ {a => [1,2],b => 3}, { c => 4 }]";
252
253 my $a_or_eq = {
254  -type => 'expr',
255  op => 'or',
256  args => [ map {
257   { -type => 'expr', op => '==', args => [ upper(mk_name('a')), upper(mk_value($_)) ] }
258  } qw/b c d/ ]
259 };
260
261 my $e_ne = {
262  -type => 'expr',
263  op => 'or',
264  args => [ map {
265   { -type => 'expr', op => '!=', args => [ upper(mk_name('e')), upper(mk_value($_)) ] }
266  } qw/f g/ ]
267 };
268
269 eq_or_diff
270   $visitor->select_ast(
271     'test', '*', [ { ticket => [11, 12, 13],
272                      hostname => { in => ['ntf', 'avd', 'bvd', '123'] }
273                    },
274                    { tack => { between => [qw/tick tock/] } },
275                    { a => [qw/b c d/], 
276                      e => { '!=', [qw(f g)] }, 
277                    }
278                  ]
279   ),
280   { -type => 'select',
281     columns => [ { -type => 'identifier', elements => ['*'] } ],
282     tablespec => { -type => 'identifier', elements => ['test'] },
283     where => {
284       -type => 'expr',
285       op => 'or',
286       args => [
287         $hostname_and_ticket,
288         $tack_between,
289         { -type => 'expr', op => 'and', args => [ $a_or_eq, $e_ne ] }
290       ]
291     }
292   },
293   "Complex AST mixing [ {a => [1,2],b => 3}, { c => 4 }, { d => [5,6,7], e => { '!=' => [8,9] } } ]";
294
295
296 eq_or_diff
297   $visitor->select_ast(
298     'test', '*', [ { ticket => [11, 12, 13], 
299                      hostname => { in => ['ntf', 'avd', 'bvd', '123'] } },
300                   { tack => { between => [qw/tick tock/] } },
301                   { a => [qw/b c d/], 
302                     e => { '!=', [qw(f g)] }, 
303                     q => { 'not in', [14..20] } 
304                   }
305                  ]
306   ),
307   { -type => 'select',
308     columns => [ { -type => 'identifier', elements => ['*'] } ],
309     tablespec => { -type => 'identifier', elements => ['test'] },
310     where => {
311       -type => 'expr',
312       op => 'or',
313       args => [
314         $hostname_and_ticket,
315         $tack_between,
316         { -type => 'expr', op => 'and', args => [ 
317           $a_or_eq, 
318           $e_ne,
319           { -type => 'expr',
320             op => 'not_in',
321             args => [
322               upper(mk_name('q')),
323               map { upper(mk_value($_)) } 14..20
324             ]
325           }
326         ] }
327       ]
328     }
329   },
330   "Complex AST [ {a => [1,2],b => 3}, { c => 4 }, { d => [5,6,7], e => { '!=' => [8,9] }, q => {'not in' => [10,11] } } ]";
331
332
333 sub upper { expr(UPPER => @_) }
334
335 sub expr {
336   my ($op, @args) = @_;
337
338   return {
339     -type => 'expr',
340     op => $op,
341     args => [@args]
342   };
343 }
344