add prefix unop example, and example for new keyword node type
[scpubgit/Q-Branch.git] / lib / SQL / Abstract / Reference.pm
CommitLineData
79d30ac3 1package SQL::Abstract::Reference;
2
31;
4
5__END__
6=head1 NAME
7
8SQL::Abstract::Reference - Reference documentation for L<SQL::Abstract>
9
10=head1 TERMS
11
12=head2 Expression (expr)
13
14The DWIM structure that's passed to most methods by default is referred to
15as expression syntax. If you see a variable with C<expr> in the name, or a
16comment before a code block saying C<# expr>, this is what's being described.
17
18=head2 Abstract Query Tree (aqt)
19
20The explicit structure that an expression is converted into before it's
21rendered into SQL is referred to as an abstract query tree. If you see a
22variable with C<aqt> in the name, or a comment before a code block saying
edf5ac22 23C<# aqt>, this is what's being described.
79d30ac3 24
25=head2 SQL and Bind Values (query)
26
27The final result of L<SQL::Abstract> rendering is generally an SQL statement
28plus bind values for passing to DBI, ala:
29
30 my ($sql, @bind) = $sqla->some_method(@args);
31 my @hashes = @{$dbh->do($sql, { Slice => {} }, @bind)};
32
33If you see a comment before a code block saying C<# query>, the SQL + bind
34array is what's being described.
35
29f96af0 36=head2 Expander
37
38An expander subroutine is written as:
39
40 sub {
41 my ($sqla, $name, $value, $k) = @_;
42 ...
43 return $aqt;
44 }
45
46$name is the expr node type for node expanders, the op name for op
47expanders, and the clause name for clause expanders.
48
49$value is the body of the thing being expanded
50
51If an op expander is being called as the binary operator in a L</hashtriple>
52expression, $k will be the hash key to be used as the left hand side
53identifier.
54
55This can trivially be converted to an C<ident> type AQT node with:
56
57 my $ident = $sqla->expand_expr({ -ident => $k });
58
59=head2 Renderer
60
61A renderer subroutine looks like:
62
63 sub {
64 my ($sqla, $type, $value) = @_;
65 ...
66 $sqla->join_query_parts($join, @parts);
67 }
68
69and can be registered on a per-type, per-op or per-clause basis.
70
79d30ac3 71=head1 AQT node types
72
73An AQT node consists of a hashref with a single key, whose name is C<-type>
74where 'type' is the node type, and whose value is the data for the node.
75
29f96af0 76The following is an explanation of the built-in AQT type renderers;
77additional renderers can be registered as part of the extension system.
78
79d30ac3 79=head2 literal
80
81 # expr
82 { -literal => [ 'SPANG(?, ?)', 1, 27 ] }
83
84 # query
85 SPANG(?, ?)
86 [ 1, 27 ]
87
88=head2 ident
89
90 # expr
91 { -ident => 'foo' }
92
93 # query
94 foo
95 []
96
97 # expr
98 { -ident => [ 'foo', 'bar' ] }
99
100 # query
101 foo.bar
102 []
103
104=head2 bind
105
106 # expr
107 { -bind => [ 'colname', 'value' ] }
108
109 # query
110 ?
111 [ 'value' ]
112
113=head2 row
114
115 # expr
116 {
117 -row => [ { -bind => [ 'r', 1 ] }, { -ident => [ 'clown', 'car' ] } ]
118 }
119
120 # query
121 (?, clown.car)
122 [ 1 ]
123
124=head2 func
125
126 # expr
127 {
128 -func => [ 'foo', { -ident => [ 'bar' ] }, { -bind => [ undef, 7 ] } ]
129 }
130
131 # query
132 FOO(bar, ?)
133 [ 7 ]
134
135=head2 op
136
137Standard binop:
138
139 # expr
140 { -op => [
141 '=', { -ident => [ 'bomb', 'status' ] },
142 { -value => 'unexploded' },
143 ] }
144
145 # query
146 bomb.status = ?
147 [ 'unexploded' ]
148
d4c5cd24 149
150Prefix unop:
151
152 # expr
153 { -op => [ '-', { -ident => 'foo' } ] }
154
155 # query
156 - foo
157 []
158
159Not as special case parenthesised unop:
79d30ac3 160
161 # expr
162 { -op => [ 'not', { -ident => 'explosive' } ] }
163
164 # query
165 (NOT explosive)
166 []
167
168Postfix unop: (is_null, is_not_null, asc, desc)
169
170 # expr
171 { -op => [ 'is_null', { -ident => [ 'bobby' ] } ] }
172
173 # query
174 bobby IS NULL
175 []
176
177AND and OR:
178
179 # expr
180 { -op =>
181 [ 'and', { -ident => 'x' }, { -ident => 'y' }, { -ident => 'z' } ]
182 }
183
184 # query
185 ( x AND y AND z )
186 []
187
188IN (and NOT IN):
189
190 # expr
191 { -op => [
192 'in', { -ident => 'card' }, { -bind => [ 'card', 3 ] },
193 { -bind => [ 'card', 'J' ] },
194 ] }
195
196 # query
197 card IN ( ?, ? )
198 [ 3, 'J' ]
199
200BETWEEN (and NOT BETWEEN):
201
202 # expr
203 { -op => [
204 'between', { -ident => 'pints' }, { -bind => [ 'pints', 2 ] },
205 { -bind => [ 'pints', 4 ] },
206 ] }
207
208 # query
209 ( pints BETWEEN ? AND ? )
210 [ 2, 4 ]
211
212Comma (use -row for parens):
213
214 # expr
215 { -op => [ ',', { -literal => [ 1 ] }, { -literal => [ 2 ] } ] }
216
217 # query
218 1, 2
219 []
220
221=head2 values
222
223 # expr
224 { -values =>
225 { -row => [ { -bind => [ undef, 1 ] }, { -bind => [ undef, 2 ] } ] }
226 }
227
228 # query
229 VALUES (?, ?)
230 [ 1, 2 ]
231
232 # expr
233 { -values => [
234 { -row => [ { -literal => [ 1 ] }, { -literal => [ 2 ] } ] },
235 { -row => [ { -literal => [ 3 ] }, { -literal => [ 4 ] } ] },
236 ] }
237
238 # query
239 VALUES (1, 2), (3, 4)
240 []
241
d4c5cd24 242=head2 keyword
243
244 # expr
245 { -keyword => 'insert_into' }
246
247 # query
248 INSERT INTO
249 []
250
79d30ac3 251=head2 statement types
252
253AQT node types are also provided for C<select>, C<insert>, C<update> and
254C<delete>. These types are handled by the clauses system as discussed later.
255
256=head1 Expressions
257
29f96af0 258=head2 node expr
259
79d30ac3 260The simplest expression is just an AQT node:
261
262 # expr
263 { -ident => [ 'foo', 'bar' ] }
264
265 # aqt
266 { -ident => [ 'foo', 'bar' ] }
267
268 # query
269 foo.bar
270 []
271
272However, even in the case of an AQT node, the node value will be expanded if
273an expander has been registered for that node type:
274
275 # expr
276 { -ident => 'foo.bar' }
277
278 # aqt
279 { -ident => [ 'foo', 'bar' ] }
280
281 # query
282 foo.bar
283 []
284
29f96af0 285=head2 identifier hashpair types
286
287=head3 hashtriple
288
289 # expr
290 { id => { op => 'value' } }
291
292 # aqt
293 { -op =>
294 [ 'op', { -ident => [ 'id' ] }, { -bind => [ 'id', 'value' ] } ]
295 }
296
297 # query
298 id OP ?
299 [ 'value' ]
300
0f4493cb 301If the value is undef, attempts to convert equality and like ops to IS NULL,
302and inequality and not like to IS NOT NULL:
303
304 # expr
305 { id => { '!=' => undef } }
306
307 # aqt
308 { -op => [ 'is_not_null', { -ident => [ 'id' ] } ] }
309
310 # query
311 id IS NOT NULL
312 []
313
29f96af0 314=head3 identifier hashpair w/simple value
315
316Equivalent to a hashtriple with an op of '='.
317
318 # expr
319 { id => 'value' }
320
321 # aqt
322 {
323 -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 'value' ] } ]
324 }
325
326 # query
327 id = ?
328 [ 'value' ]
329
330(an object value will also follow this code path)
331
332=head3 identifier hashpair w/undef RHS
333
334Converted to IS NULL :
335
336 # expr
337 { id => undef }
338
339 # aqt
340 { -op => [ 'is_null', { -ident => [ 'id' ] } ] }
341
342 # query
343 id IS NULL
344 []
345
972c9823 346(equivalent to the -is operator) :
347
348 # expr
349 { id => { -is => undef } }
350
351 # aqt
352 { -op => [ 'is_null', { -ident => [ 'id' ] } ] }
353
354 # query
355 id IS NULL
356 []
357
29f96af0 358=head3 identifier hashpair w/literal RHS
359
360Directly appended to the key, remember you need to provide an operator:
361
362 # expr
363 { id => \"= dont_try_this_at_home" }
364
365 # aqt
366 { -literal => [ 'id = dont_try_this_at_home' ] }
367
368 # query
369 id = dont_try_this_at_home
370 []
371
372 # expr
373 { id => \[
374 "= seriously(?, ?, ?, ?, ?)",
375 "use",
376 "-ident",
377 "and",
378 "-func",
379 ]
380 }
381
382 # aqt
383 { -literal =>
384 [ 'id = seriously(?, ?, ?, ?, ?)', 'use', -ident => 'and', '-func' ]
385 }
386
387 # query
388 id = seriously(?, ?, ?, ?, ?)
389 [ 'use', -ident => 'and', '-func' ]
390
391(you may absolutely use this when there's no built-in expression type for
392what you need and registering a custom one would be more hassle than it's
393worth, but, y'know, do try and avoid it)
394
395=head3 identifier hashpair w/arrayref value
396
397Becomes equivalent to a -or over an arrayref of hashrefs with the identifier
398as key and the member of the original arrayref as the value:
399
400 # expr
401 { id => [ 3, 4, { '>' => 12 } ] }
402
403 # aqt
404 { -op => [
405 'or',
406 { -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
407 { -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 4 ] } ] },
408 {
409 -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 12 ] } ]
410 },
411 ] }
412
413 # query
414 ( id = ? OR id = ? OR id > ? )
415 [ 3, 4, 12 ]
416
417 # expr
418 { -or => [ { id => 3 }, { id => 4 }, { id => { '>' => 12 } } ] }
419
420 # aqt
421 { -op => [
422 'or',
423 { -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
424 { -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 4 ] } ] },
425 {
426 -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 12 ] } ]
427 },
428 ] }
429
430 # query
431 ( id = ? OR id = ? OR id > ? )
432 [ 3, 4, 12 ]
433
434Special Case: If the first element of the arrayref is -or or -and, that's
435used as the top level logic op:
436
437 # expr
438 { id => [ -and => { '>' => 3 }, { '<' => 6 } ] }
439
440 # aqt
441 { -op => [
442 'and',
443 { -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
444 { -op => [ '<', { -ident => [ 'id' ] }, { -bind => [ 'id', 6 ] } ] },
445 ] }
446
447 # query
448 ( id > ? AND id < ? )
449 [ 3, 6 ]
450
451=head3 identifier hashpair w/hashref value
452
453Becomes equivalent to a -and over an arrayref of hashtriples constructed
454with the identifier as the key and each key/value pair of the original
edf5ac22 455hashref as the value:
29f96af0 456
457 # expr
458 { id => { '<' => 4, '>' => 3 } }
459
460 # aqt
461 { -op => [
462 'and',
463 { -op => [ '<', { -ident => [ 'id' ] }, { -bind => [ 'id', 4 ] } ] },
464 { -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
465 ] }
466
467 # query
468 ( id < ? AND id > ? )
469 [ 4, 3 ]
470
972c9823 471is sugar for:
472
29f96af0 473 # expr
474 { -and => [ { id => { '<' => 4 } }, { id => { '>' => 3 } } ] }
475
476 # aqt
477 { -op => [
478 'and',
479 { -op => [ '<', { -ident => [ 'id' ] }, { -bind => [ 'id', 4 ] } ] },
480 { -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
481 ] }
482
483 # query
484 ( id < ? AND id > ? )
485 [ 4, 3 ]
486
972c9823 487=head2 operator hashpair types
488
489A hashpair whose key begins with a -, or whose key consists entirely of
490nonword characters (thereby covering '=', '>', pg json ops, etc.) is
491processed as an operator hashpair.
492
493=head3 operator hashpair w/node type
494
495If a node type expander is registered for the key, the hashpair is
496treated as a L</node expr>.
497
498=head3 operator hashpair w/registered op
499
500If an expander is registered for the op name, that's run and the
501result returned:
502
503 # expr
504 { -in => [ 'foo', 1, 2, 3 ] }
505
506 # aqt
507 { -op => [
508 'in', { -ident => [ 'foo' ] }, { -bind => [ undef, 1 ] },
509 { -bind => [ undef, 2 ] }, { -bind => [ undef, 3 ] },
510 ] }
511
512 # query
513 foo IN ( ?, ?, ? )
514 [ 1, 2, 3 ]
515
516=head3 operator hashpair w/not prefix
517
518If the op name starts -not_ this is stripped and turned into a -not
519wrapper around the result:
520
521 # expr
522 { -not_ident => 'foo' }
523
524 # aqt
525 { -op => [ 'not', { -ident => [ 'foo' ] } ] }
526
527 # query
528 (NOT foo)
529 []
530
531is equivalent to:
532
533 # expr
534 { -not => { -ident => 'foo' } }
535
536 # aqt
537 { -op => [ 'not', { -ident => [ 'foo' ] } ] }
538
539 # query
540 (NOT foo)
541 []
542
543=head3 operator hashpair with unknown op
544
545If the C<unknown_unop_always_func> option is set (which is recommended but
546defaults to off for backwards compatibility reasons), an unknown op
547expands into a C<-func> node:
548
549 # expr
550 { -count => { -ident => '*' } }
551
552 # aqt
553 { -func => [ 'count', { -ident => [ '*' ] } ] }
554
555 # query
556 COUNT(*)
557 []
558
559If not, an unknown op will expand into a C<-op> node.
560
561=head2 hashref expr
562
563A hashref with more than one pair becomes a C<-and> over its hashpairs, i.e.
564
565 # expr
566 { x => 1, y => 2 }
567
568 # aqt
569 { -op => [
570 'and',
571 { -op => [ '=', { -ident => [ 'x' ] }, { -bind => [ 'x', 1 ] } ] },
572 { -op => [ '=', { -ident => [ 'y' ] }, { -bind => [ 'y', 2 ] } ] },
573 ] }
574
575 # query
576 ( x = ? AND y = ? )
577 [ 1, 2 ]
578
579is short hand for:
580
581 # expr
582 { -and => [ { x => 1 }, { y => 2 } ] }
583
584 # aqt
585 { -op => [
586 'and',
587 { -op => [ '=', { -ident => [ 'x' ] }, { -bind => [ 'x', 1 ] } ] },
588 { -op => [ '=', { -ident => [ 'y' ] }, { -bind => [ 'y', 2 ] } ] },
589 ] }
590
591 # query
592 ( x = ? AND y = ? )
593 [ 1, 2 ]
594
595=head2 arrayref expr
596
24479414 597An arrayref becomes a C<-or> over its contents. Arrayrefs, hashrefs and
598literals are all expanded and added to the clauses of the C<-or>. If the
599arrayref contains a scalar it's treated as the key of a hashpair and the
600next element as the value.
601
602 # expr
603 [ { x => 1 }, [ { y => 2 }, { z => 3 } ], 'key', 'value', \"lit()" ]
604
605 # aqt
606 { -op => [
607 'or',
608 { -op => [ '=', { -ident => [ 'x' ] }, { -bind => [ 'x', 1 ] } ] },
609 { -op => [
610 'or', {
611 -op => [ '=', { -ident => [ 'y' ] }, { -bind => [ 'y', 2 ] } ]
612 }, {
613 -op => [ '=', { -ident => [ 'z' ] }, { -bind => [ 'z', 3 ] } ]
614 },
615 ] }, { -op =>
616 [
617 '=', { -ident => [ 'key' ] },
618 { -bind => [ 'key', 'value' ] },
619 ]
620 },
621 { -literal => [ 'lit()' ] },
622 ] }
623
624 # query
625 ( x = ? OR ( y = ? OR z = ? ) OR key = ? OR lit() )
626 [ 1, 2, 3, 'value' ]
627
29f96af0 628=cut