Commit | Line | Data |
d70ca130 |
1 | use strict; |
2 | use warnings; |
3 | |
03f6671a |
4 | use FindBin; |
5 | use lib "$FindBin::Bin/../../lib"; |
96bbece0 |
6 | use Test::SQL::Abstract::Util qw/ |
7 | mk_name |
8 | mk_value |
d4656fcf |
9 | mk_expr |
96bbece0 |
10 | field_op_value |
11 | :dumper_sort |
12 | /; |
03f6671a |
13 | |
1c51edc4 |
14 | use SQL::Abstract::Compat; |
d70ca130 |
15 | |
0073ca43 |
16 | use Test::More tests => 17; |
d70ca130 |
17 | use Test::Differences; |
18 | |
1c51edc4 |
19 | ok(my $visitor = SQL::Abstract::Compat->new); |
d70ca130 |
20 | |
00f4d23e |
21 | |
627dcb62 |
22 | my $foo_id = { -type => 'identifier', elements => [qw/foo/] }; |
23 | my $bar_id = { -type => 'identifier', elements => [qw/bar/] }; |
c6039348 |
24 | |
00f4d23e |
25 | my $foo_eq_1 = field_op_value($foo_id, '==', 1); |
26 | my $bar_eq_str = field_op_value($bar_id, '==', 'some str'); |
d70ca130 |
27 | |
28 | eq_or_diff |
37716782 |
29 | $visitor->recurse_where({ foo => 1 }), |
d70ca130 |
30 | $foo_eq_1, |
31 | "Single value hash"; |
32 | |
33 | |
d70ca130 |
34 | |
35 | eq_or_diff |
37716782 |
36 | $visitor->recurse_where({ foo => 1, bar => 'some str' }), |
d70ca130 |
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 |
37716782 |
47 | $visitor->recurse_where({ -or => { foo => 1, bar => 'some str' } }), |
d70ca130 |
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 |
37716782 |
59 | $visitor->recurse_where([ -and => { foo => 1, bar => 'some str' } ]), |
d70ca130 |
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 |
37716782 |
71 | $visitor->recurse_where([ -and => { foo => 1, bar => 'some str' }, { foo => 1} ]), |
d70ca130 |
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 | }, |
c6039348 |
85 | "-and as first element of array + hash"; |
86 | |
87 | eq_or_diff |
37716782 |
88 | $visitor->recurse_where({ foo => { '!=' => 'bar' } }), |
00f4d23e |
89 | field_op_value($foo_id, '!=', 'bar'), |
c6039348 |
90 | "foo => { '!=' => 'bar' }"; |
91 | |
92 | eq_or_diff |
37716782 |
93 | $visitor->recurse_where({ foo => [ 1, 'bar' ] }), |
c6039348 |
94 | { -type => 'expr', |
95 | op => 'or', |
96 | args => [ |
97 | $foo_eq_1, |
00f4d23e |
98 | field_op_value($foo_id, '==', 'bar'), |
c6039348 |
99 | ], |
100 | }, |
101 | "foo => [ 1, 'bar' ]"; |
102 | |
2e828b0b |
103 | eq_or_diff |
37716782 |
104 | $visitor->recurse_where({ foo => { -in => [ 1, 'bar' ] } }), |
2e828b0b |
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 |
37716782 |
116 | $visitor->recurse_where({ foo => { -not_in => [ 1, 'bar' ] } }), |
2e828b0b |
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 |
37716782 |
128 | $visitor->recurse_where({ foo => { -in => [ ] } }), |
2e828b0b |
129 | { -type => 'expr', |
130 | op => 'in', |
131 | args => [ |
132 | $foo_id, |
133 | ] |
134 | }, |
135 | "foo => { -in => [ ] }"; |
136 | |
00f4d23e |
137 | my $worker_eq = sub { |
138 | return { |
139 | -type => 'expr', |
140 | op => '==', |
141 | args => [ |
627dcb62 |
142 | { -type => 'identifier', elements => ['worker'] }, |
00f4d23e |
143 | { -type => 'value', value => $_[0] }, |
144 | ], |
145 | } |
146 | }; |
03f6671a |
147 | |
00f4d23e |
148 | eq_or_diff |
37716782 |
149 | $visitor->recurse_where( { |
00f4d23e |
150 | requestor => 'inna', |
151 | worker => ['nwiger', 'rcwe', 'sfz'], |
152 | status => { '!=', 'completed' } |
153 | } ), |
154 | { -type => 'expr', |
155 | op => 'and', |
156 | args => [ |
03f6671a |
157 | field_op_value(qw/requestor == inna/), |
00f4d23e |
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 | }, |
00f4d23e |
167 | ] |
168 | }, |
03f6671a |
169 | "complex expr 1"; |
00f4d23e |
170 | |
171 | |
03f6671a |
172 | $visitor->convert('UPPER'); |
173 | |
0073ca43 |
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 | |
03f6671a |
184 | eq_or_diff |
185 | $visitor->select_ast( |
186 | 'test', '*', [ { ticket => [11, 12, 13] } ] |
187 | ), |
188 | { -type => 'select', |
627dcb62 |
189 | columns => [ { -type => 'identifier', elements => ['*'] } ], |
190 | tablespec => { -type => 'identifier', elements => ['test'] }, |
0073ca43 |
191 | where => $ticket_or_eq |
03f6671a |
192 | }, |
193 | "Complex AST with convert('UPPER')"; |
194 | |
0073ca43 |
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', |
627dcb62 |
216 | columns => [ { -type => 'identifier', elements => ['*'] } ], |
217 | tablespec => { -type => 'identifier', elements => ['test'] }, |
0073ca43 |
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', |
627dcb62 |
241 | columns => [ { -type => 'identifier', elements => ['*'] } ], |
242 | tablespec => { -type => 'identifier', elements => ['test'] }, |
0073ca43 |
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', |
627dcb62 |
282 | columns => [ { -type => 'identifier', elements => ['*'] } ], |
283 | tablespec => { -type => 'identifier', elements => ['test'] }, |
0073ca43 |
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 | |
03f6671a |
297 | eq_or_diff |
298 | $visitor->select_ast( |
299 | 'test', '*', [ { ticket => [11, 12, 13], |
300 | hostname => { in => ['ntf', 'avd', 'bvd', '123'] } }, |
0073ca43 |
301 | { tack => { between => [qw/tick tock/] } }, |
302 | { a => [qw/b c d/], |
303 | e => { '!=', [qw(f g)] }, |
304 | q => { 'not in', [14..20] } |
305 | } |
03f6671a |
306 | ] |
307 | ), |
308 | { -type => 'select', |
627dcb62 |
309 | columns => [ { -type => 'identifier', elements => ['*'] } ], |
310 | tablespec => { -type => 'identifier', elements => ['test'] }, |
0073ca43 |
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 | } |
03f6671a |
327 | ] } |
0073ca43 |
328 | ] |
329 | } |
03f6671a |
330 | }, |
0073ca43 |
331 | "Complex AST [ {a => [1,2],b => 3}, { c => 4 }, { d => [5,6,7], e => { '!=' => [8,9] }, q => {'not in' => [10,11] } } ]"; |
00f4d23e |
332 | |
03f6671a |
333 | |
d4656fcf |
334 | sub upper { mk_expr(UPPER => @_) } |
03f6671a |
335 | |
03f6671a |
336 | |