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