1SQL::Abstract::ReferencUes(e3r)Contributed Perl DocumentSaQtLi:o:nAbstract::Reference(3)
2
3
4
6 SQL::Abstract::Reference - Reference documentation for SQL::Abstract
7
9 Expression (expr)
10 The DWIM structure that's passed to most methods by default is referred
11 to as expression syntax. If you see a variable with "expr" in the name,
12 or a comment before a code block saying "# expr", this is what's being
13 described.
14
15 Abstract Query Tree (aqt)
16 The explicit structure that an expression is converted into before it's
17 rendered into SQL is referred to as an abstract query tree. If you see
18 a variable with "aqt" in the name, or a comment before a code block
19 saying "# aqt", this is what's being described.
20
21 SQL and Bind Values (query)
22 The final result of SQL::Abstract rendering is generally an SQL
23 statement plus bind values for passing to DBI, ala:
24
25 my ($sql, @bind) = $sqla->some_method(@args);
26 my @hashes = @{$dbh->do($sql, { Slice => {} }, @bind)};
27
28 If you see a comment before a code block saying "# query", the SQL +
29 bind array is what's being described.
30
31 Expander
32 An expander subroutine is written as:
33
34 sub {
35 my ($sqla, $name, $value, $k) = @_;
36 ...
37 return $aqt;
38 }
39
40 $name is the expr node type for node expanders, the op name for op
41 expanders, and the clause name for clause expanders.
42
43 $value is the body of the thing being expanded
44
45 If an op expander is being called as the binary operator in a
46 "hashtriple" expression, $k will be the hash key to be used as the left
47 hand side identifier.
48
49 This can trivially be converted to an "ident" type AQT node with:
50
51 my $ident = $sqla->expand_expr({ -ident => $k });
52
53 Renderer
54 A renderer subroutine looks like:
55
56 sub {
57 my ($sqla, $type, $value) = @_;
58 ...
59 $sqla->join_query_parts($join, @parts);
60 }
61
62 and can be registered on a per-type, per-op or per-clause basis.
63
65 An AQT node consists of a hashref with a single key, whose name is
66 "-type" where 'type' is the node type, and whose value is the data for
67 the node.
68
69 The following is an explanation of the built-in AQT type renderers;
70 additional renderers can be registered as part of the extension system.
71
72 literal
73 # expr
74 { -literal => [ 'SPANG(?, ?)', 1, 27 ] }
75
76 # query
77 SPANG(?, ?)
78 [ 1, 27 ]
79
80 ident
81 # expr
82 { -ident => 'foo' }
83
84 # query
85 foo
86 []
87
88 # expr
89 { -ident => [ 'foo', 'bar' ] }
90
91 # query
92 foo.bar
93 []
94
95 bind
96 # expr
97 { -bind => [ 'colname', 'value' ] }
98
99 # query
100 ?
101 [ 'value' ]
102
103 row
104 # expr
105 {
106 -row => [ { -bind => [ 'r', 1 ] }, { -ident => [ 'clown', 'car' ] } ]
107 }
108
109 # query
110 (?, clown.car)
111 [ 1 ]
112
113 func
114 # expr
115 {
116 -func => [ 'foo', { -ident => [ 'bar' ] }, { -bind => [ undef, 7 ] } ]
117 }
118
119 # query
120 FOO(bar, ?)
121 [ 7 ]
122
123 op
124 Standard binop:
125
126 # expr
127 { -op => [
128 '=', { -ident => [ 'bomb', 'status' ] },
129 { -value => 'unexploded' },
130 ] }
131
132 # query
133 bomb.status = ?
134 [ 'unexploded' ]
135
136 Prefix unop:
137
138 # expr
139 { -op => [ '-', { -ident => 'foo' } ] }
140
141 # query
142 - foo
143 []
144
145 Not as special case parenthesised unop:
146
147 # expr
148 { -op => [ 'not', { -ident => 'explosive' } ] }
149
150 # query
151 (NOT explosive)
152 []
153
154 Postfix unop: (is_null, is_not_null, asc, desc)
155
156 # expr
157 { -op => [ 'is_null', { -ident => [ 'bobby' ] } ] }
158
159 # query
160 bobby IS NULL
161 []
162
163 AND and OR:
164
165 # expr
166 { -op =>
167 [ 'and', { -ident => 'x' }, { -ident => 'y' }, { -ident => 'z' } ]
168 }
169
170 # query
171 ( x AND y AND z )
172 []
173
174 IN (and NOT IN):
175
176 # expr
177 { -op => [
178 'in', { -ident => 'card' }, { -bind => [ 'card', 3 ] },
179 { -bind => [ 'card', 'J' ] },
180 ] }
181
182 # query
183 card IN ( ?, ? )
184 [ 3, 'J' ]
185
186 BETWEEN (and NOT BETWEEN):
187
188 # expr
189 { -op => [
190 'between', { -ident => 'pints' }, { -bind => [ 'pints', 2 ] },
191 { -bind => [ 'pints', 4 ] },
192 ] }
193
194 # query
195 ( pints BETWEEN ? AND ? )
196 [ 2, 4 ]
197
198 Comma (use -row for parens):
199
200 # expr
201 { -op => [ ',', { -literal => [ 1 ] }, { -literal => [ 2 ] } ] }
202
203 # query
204 1, 2
205 []
206
207 values
208 # expr
209 { -values =>
210 { -row => [ { -bind => [ undef, 1 ] }, { -bind => [ undef, 2 ] } ] }
211 }
212
213 # query
214 VALUES (?, ?)
215 [ 1, 2 ]
216
217 # expr
218 { -values => [
219 { -row => [ { -literal => [ 1 ] }, { -literal => [ 2 ] } ] },
220 { -row => [ { -literal => [ 3 ] }, { -literal => [ 4 ] } ] },
221 ] }
222
223 # query
224 VALUES (1, 2), (3, 4)
225 []
226
227 keyword
228 # expr
229 { -keyword => 'insert_into' }
230
231 # query
232 INSERT INTO
233 []
234
235 statement types
236 AQT node types are also provided for "select", "insert", "update" and
237 "delete". These types are handled by the clauses system as discussed
238 later.
239
241 node expr
242 The simplest expression is just an AQT node:
243
244 # expr
245 { -ident => [ 'foo', 'bar' ] }
246
247 # aqt
248 { -ident => [ 'foo', 'bar' ] }
249
250 # query
251 foo.bar
252 []
253
254 However, even in the case of an AQT node, the node value will be
255 expanded if an expander has been registered for that node type:
256
257 # expr
258 { -ident => 'foo.bar' }
259
260 # aqt
261 { -ident => [ 'foo', 'bar' ] }
262
263 # query
264 foo.bar
265 []
266
267 identifier hashpair types
268 hashtriple
269
270 # expr
271 { id => { op => 'value' } }
272
273 # aqt
274 { -op =>
275 [ 'op', { -ident => [ 'id' ] }, { -bind => [ 'id', 'value' ] } ]
276 }
277
278 # query
279 id OP ?
280 [ 'value' ]
281
282 If the value is undef, attempts to convert equality and like ops to IS
283 NULL, and inequality and not like to IS NOT NULL:
284
285 # expr
286 { id => { '!=' => undef } }
287
288 # aqt
289 { -op => [ 'is_not_null', { -ident => [ 'id' ] } ] }
290
291 # query
292 id IS NOT NULL
293 []
294
295 identifier hashpair w/simple value
296
297 Equivalent to a hashtriple with an op of '='.
298
299 # expr
300 { id => 'value' }
301
302 # aqt
303 {
304 -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 'value' ] } ]
305 }
306
307 # query
308 id = ?
309 [ 'value' ]
310
311 (an object value will also follow this code path)
312
313 identifier hashpair w/undef RHS
314
315 Converted to IS NULL :
316
317 # expr
318 { id => undef }
319
320 # aqt
321 { -op => [ 'is_null', { -ident => [ 'id' ] } ] }
322
323 # query
324 id IS NULL
325 []
326
327 (equivalent to the -is operator) :
328
329 # expr
330 { id => { -is => undef } }
331
332 # aqt
333 { -op => [ 'is_null', { -ident => [ 'id' ] } ] }
334
335 # query
336 id IS NULL
337 []
338
339 identifier hashpair w/literal RHS
340
341 Directly appended to the key, remember you need to provide an operator:
342
343 # expr
344 { id => \"= dont_try_this_at_home" }
345
346 # aqt
347 { -literal => [ 'id = dont_try_this_at_home' ] }
348
349 # query
350 id = dont_try_this_at_home
351 []
352
353 # expr
354 { id => \[
355 "= seriously(?, ?, ?, ?)",
356 "use",
357 "-ident",
358 "and",
359 "-func",
360 ]
361 }
362
363 # aqt
364 { -literal =>
365 [ 'id = seriously(?, ?, ?, ?)', 'use', -ident => 'and', '-func' ]
366 }
367
368 # query
369 id = seriously(?, ?, ?, ?)
370 [ 'use', -ident => 'and', '-func' ]
371
372 (you may absolutely use this when there's no built-in expression type
373 for what you need and registering a custom one would be more hassle
374 than it's worth, but, y'know, do try and avoid it)
375
376 identifier hashpair w/arrayref value
377
378 Becomes equivalent to a -or over an arrayref of hashrefs with the
379 identifier as key and the member of the original arrayref as the value:
380
381 # expr
382 { id => [ 3, 4, { '>' => 12 } ] }
383
384 # aqt
385 { -op => [
386 'or',
387 { -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
388 { -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 4 ] } ] },
389 {
390 -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 12 ] } ]
391 },
392 ] }
393
394 # query
395 ( id = ? OR id = ? OR id > ? )
396 [ 3, 4, 12 ]
397
398 # expr
399 { -or => [ { id => 3 }, { id => 4 }, { id => { '>' => 12 } } ] }
400
401 # aqt
402 { -op => [
403 'or',
404 { -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
405 { -op => [ '=', { -ident => [ 'id' ] }, { -bind => [ 'id', 4 ] } ] },
406 {
407 -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 12 ] } ]
408 },
409 ] }
410
411 # query
412 ( id = ? OR id = ? OR id > ? )
413 [ 3, 4, 12 ]
414
415 Special Case: If the first element of the arrayref is -or or -and,
416 that's used as the top level logic op:
417
418 # expr
419 { id => [ -and => { '>' => 3 }, { '<' => 6 } ] }
420
421 # aqt
422 { -op => [
423 'and',
424 { -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
425 { -op => [ '<', { -ident => [ 'id' ] }, { -bind => [ 'id', 6 ] } ] },
426 ] }
427
428 # query
429 ( id > ? AND id < ? )
430 [ 3, 6 ]
431
432 identifier hashpair w/hashref value
433
434 Becomes equivalent to a -and over an arrayref of hashtriples
435 constructed with the identifier as the key and each key/value pair of
436 the original hashref as the value:
437
438 # expr
439 { id => { '<' => 4, '>' => 3 } }
440
441 # aqt
442 { -op => [
443 'and',
444 { -op => [ '<', { -ident => [ 'id' ] }, { -bind => [ 'id', 4 ] } ] },
445 { -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
446 ] }
447
448 # query
449 ( id < ? AND id > ? )
450 [ 4, 3 ]
451
452 is sugar for:
453
454 # expr
455 { -and => [ { id => { '<' => 4 } }, { id => { '>' => 3 } } ] }
456
457 # aqt
458 { -op => [
459 'and',
460 { -op => [ '<', { -ident => [ 'id' ] }, { -bind => [ 'id', 4 ] } ] },
461 { -op => [ '>', { -ident => [ 'id' ] }, { -bind => [ 'id', 3 ] } ] },
462 ] }
463
464 # query
465 ( id < ? AND id > ? )
466 [ 4, 3 ]
467
468 operator hashpair types
469 A hashpair whose key begins with a -, or whose key consists entirely of
470 nonword characters (thereby covering '=', '>', pg json ops, etc.) is
471 processed as an operator hashpair.
472
473 operator hashpair w/node type
474
475 If a node type expander is registered for the key, the hashpair is
476 treated as a "node expr".
477
478 operator hashpair w/registered op
479
480 If an expander is registered for the op name, that's run and the result
481 returned:
482
483 # expr
484 { -in => [ 'foo', 1, 2, 3 ] }
485
486 # aqt
487 { -op => [
488 'in', { -ident => [ 'foo' ] }, { -bind => [ undef, 1 ] },
489 { -bind => [ undef, 2 ] }, { -bind => [ undef, 3 ] },
490 ] }
491
492 # query
493 foo IN ( ?, ?, ? )
494 [ 1, 2, 3 ]
495
496 operator hashpair w/not prefix
497
498 If the op name starts -not_ this is stripped and turned into a -not
499 wrapper around the result:
500
501 # expr
502 { -not_ident => 'foo' }
503
504 # aqt
505 { -op => [ 'not', { -ident => [ 'foo' ] } ] }
506
507 # query
508 (NOT foo)
509 []
510
511 is equivalent to:
512
513 # expr
514 { -not => { -ident => 'foo' } }
515
516 # aqt
517 { -op => [ 'not', { -ident => [ 'foo' ] } ] }
518
519 # query
520 (NOT foo)
521 []
522
523 operator hashpair with unknown op
524
525 If the "unknown_unop_always_func" option is set (which is recommended
526 but defaults to off for backwards compatibility reasons), an unknown op
527 expands into a "-func" node:
528
529 # expr
530 { -count => { -ident => '*' } }
531
532 # aqt
533 { -func => [ 'count', { -ident => [ '*' ] } ] }
534
535 # query
536 COUNT(*)
537 []
538
539 If not, an unknown op will expand into a "-op" node.
540
541 hashref expr
542 A hashref with more than one pair becomes a "-and" over its hashpairs,
543 i.e.
544
545 # expr
546 { x => 1, y => 2 }
547
548 # aqt
549 { -op => [
550 'and',
551 { -op => [ '=', { -ident => [ 'x' ] }, { -bind => [ 'x', 1 ] } ] },
552 { -op => [ '=', { -ident => [ 'y' ] }, { -bind => [ 'y', 2 ] } ] },
553 ] }
554
555 # query
556 ( x = ? AND y = ? )
557 [ 1, 2 ]
558
559 is short hand for:
560
561 # expr
562 { -and => [ { x => 1 }, { y => 2 } ] }
563
564 # aqt
565 { -op => [
566 'and',
567 { -op => [ '=', { -ident => [ 'x' ] }, { -bind => [ 'x', 1 ] } ] },
568 { -op => [ '=', { -ident => [ 'y' ] }, { -bind => [ 'y', 2 ] } ] },
569 ] }
570
571 # query
572 ( x = ? AND y = ? )
573 [ 1, 2 ]
574
575 arrayref expr
576 An arrayref becomes a "-or" over its contents. Arrayrefs, hashrefs and
577 literals are all expanded and added to the clauses of the "-or". If the
578 arrayref contains a scalar it's treated as the key of a hashpair and
579 the next element as the value.
580
581 # expr
582 [ { x => 1 }, [ { y => 2 }, { z => 3 } ], 'key', 'value', \"lit()" ]
583
584 # aqt
585 { -op => [
586 'or',
587 { -op => [ '=', { -ident => [ 'x' ] }, { -bind => [ 'x', 1 ] } ] },
588 { -op => [
589 'or', {
590 -op => [ '=', { -ident => [ 'y' ] }, { -bind => [ 'y', 2 ] } ]
591 }, {
592 -op => [ '=', { -ident => [ 'z' ] }, { -bind => [ 'z', 3 ] } ]
593 },
594 ] }, { -op =>
595 [
596 '=', { -ident => [ 'key' ] },
597 { -bind => [ 'key', 'value' ] },
598 ]
599 },
600 { -literal => [ 'lit()' ] },
601 ] }
602
603 # query
604 ( x = ? OR ( y = ? OR z = ? ) OR key = ? OR lit() )
605 [ 1, 2, 3, 'value' ]
606
608 bool
609 Turns the old -bool syntax into the value expression, i.e.
610
611 # expr
612 { -bool => { -ident => 'foo' } }
613
614 # aqt
615 { -ident => [ 'foo' ] }
616
617 # query
618 foo
619 []
620
621 behaves the same way as the now-directly-supported
622
623 # expr
624 { -ident => 'foo' }
625
626 # aqt
627 { -ident => [ 'foo' ] }
628
629 # query
630 foo
631 []
632
633 row
634 Expands the elements of the value arrayref:
635
636 # expr
637 { -row => [ 1, { -ident => 'foo' }, 2, 3 ] }
638
639 # aqt
640 { -row => [
641 { -bind => [ undef, 1 ] }, { -ident => [ 'foo' ] },
642 { -bind => [ undef, 2 ] }, { -bind => [ undef, 3 ] },
643 ] }
644
645 # query
646 (?, foo, ?, ?)
647 [ 1, 2, 3 ]
648
649 op
650 If an expander is registered for the op name, delegates to the
651 expander; if not, expands the argument values:
652
653 # expr
654 { -op => [ 'ident', 'foo.bar' ] }
655
656 # aqt
657 { -ident => [ 'foo', 'bar' ] }
658
659 # query
660 foo.bar
661 []
662
663 # expr
664 { -op => [ '=', { -ident => 'foo' }, 3 ] }
665
666 # aqt
667 { -op => [ '=', { -ident => [ 'foo' ] }, { -bind => [ undef, 3 ] } ] }
668
669 # query
670 foo = ?
671 [ 3 ]
672
673 func
674 Expands the argument values:
675
676 # expr
677 { -func => [ 'coalesce', { -ident => 'thing' }, 'fallback' ] }
678
679 # aqt
680 { -func => [
681 'coalesce', { -ident => [ 'thing' ] },
682 { -bind => [ undef, 'fallback' ] },
683 ] }
684
685 # query
686 COALESCE(thing, ?)
687 [ 'fallback' ]
688
689 values
690 A hashref value is expanded as an expression:
691
692 # expr
693 { -values => { -row => [ 1, 2 ] } }
694
695 # aqt
696 { -values => [
697 { -row => [ { -bind => [ undef, 1 ] }, { -bind => [ undef, 2 ] } ] }
698 ] }
699
700 # query
701 VALUES (?, ?)
702 [ 1, 2 ]
703
704 An arrayref value's elements are either expressions or arrayrefs to be
705 treated as rows:
706
707 # expr
708 { -values => [ { -row => [ 1, 2 ] }, [ 3, 4 ] ] }
709
710 # aqt
711 { -values => [
712 { -row => [ { -bind => [ undef, 1 ] }, { -bind => [ undef, 2 ] } ] },
713 { -row => [ { -bind => [ undef, 3 ] }, { -bind => [ undef, 4 ] } ] },
714 ] }
715
716 # query
717 VALUES (?, ?), (?, ?)
718 [ 1, 2, 3, 4 ]
719
720 list
721 Expects a value or an arrayref of values, expands them, and returns
722 just the expanded aqt for a single entry or a comma operator for
723 multiple:
724
725 # expr
726 { -list => [ { -ident => 'foo' } ] }
727
728 # aqt
729 { -op => [ ',', { -ident => [ 'foo' ] } ] }
730
731 # query
732 foo
733 []
734
735 # expr
736 { -list => [ { -ident => 'foo' }, { -ident => 'bar' } ] }
737
738 # aqt
739 { -op => [ ',', { -ident => [ 'foo' ] }, { -ident => [ 'bar' ] } ] }
740
741 # query
742 foo, bar
743 []
744
745 between op
746 The RHS of between must either be a pair of exprs/plain values, or a
747 single literal expr:
748
749 # expr
750 { -between => [ 'size', 3, { -ident => 'max_size' } ] }
751
752 # aqt
753 { -op => [
754 'between', { -ident => [ 'size' ] }, { -bind => [ undef, 3 ] },
755 { -ident => [ 'max_size' ] },
756 ] }
757
758 # query
759 ( size BETWEEN ? AND max_size )
760 [ 3 ]
761
762 # expr
763 { size => { -between => [ 3, { -ident => 'max_size' } ] } }
764
765 # aqt
766 { -op => [
767 'between', { -ident => [ 'size' ] }, { -bind => [ 'size', 3 ] },
768 { -ident => [ 'max_size' ] },
769 ] }
770
771 # query
772 ( size BETWEEN ? AND max_size )
773 [ 3 ]
774
775 # expr
776 { size => { -between => \"3 AND 7" } }
777
778 # aqt
779 { -op =>
780 [
781 'between', { -ident => [ 'size' ] },
782 { -literal => [ '3 AND 7' ] },
783 ]
784 }
785
786 # query
787 ( size BETWEEN 3 AND 7 )
788 []
789
790 not_between is also expanded:
791
792 # expr
793 { size => { -not_between => [ 3, 7 ] } }
794
795 # aqt
796 { -op => [
797 'not_between', { -ident => [ 'size' ] },
798 { -bind => [ 'size', 3 ] }, { -bind => [ 'size', 7 ] },
799 ] }
800
801 # query
802 ( size NOT BETWEEN ? AND ? )
803 [ 3, 7 ]
804
805 in op
806 The RHS of in/not_in is either an expr/value or an arrayref of
807 exprs/values:
808
809 # expr
810 { foo => { -in => [ 1, 2 ] } }
811
812 # aqt
813 { -op => [
814 'in', { -ident => [ 'foo' ] }, { -bind => [ 'foo', 1 ] },
815 { -bind => [ 'foo', 2 ] },
816 ] }
817
818 # query
819 foo IN ( ?, ? )
820 [ 1, 2 ]
821
822 # expr
823 { bar => { -not_in => \"(1, 2)" } }
824
825 # aqt
826 { -op =>
827 [ 'not_in', { -ident => [ 'bar' ] }, { -literal => [ '1, 2' ] } ]
828 }
829
830 # query
831 bar NOT IN ( 1, 2 )
832 []
833
834 A non-trivial LHS is expanded with ident as the default rather than
835 value:
836
837 # expr
838 { -in => [
839 { -row => [ 'x', 'y' ] }, { -row => [ 1, 2 ] },
840 { -row => [ 3, 4 ] },
841 ] }
842
843 # aqt
844 { -op => [
845 'in', { -row => [ { -ident => [ 'x' ] }, { -ident => [ 'y' ] } ] },
846 { -row => [ { -bind => [ undef, 1 ] }, { -bind => [ undef, 2 ] } ] },
847 { -row => [ { -bind => [ undef, 3 ] }, { -bind => [ undef, 4 ] } ] },
848 ] }
849
850 # query
851 (x, y) IN ( (?, ?), (?, ?) )
852 [ 1, 2, 3, 4 ]
853
854 and/or ops
855 expands the same way as a plain arrayref/hashref expression but with
856 the logic type set to the op name.
857
858 is op
859 Expands is and is_not to null checks, RHS value must be undef:
860
861 # expr
862 { -is => [ 'foo', undef ] }
863
864 # aqt
865 { -op => [ 'is_null', { -ident => [ 'foo' ] } ] }
866
867 # query
868 foo IS NULL
869 []
870
871 # expr
872 { bar => { -is_not => undef } }
873
874 # aqt
875 { -op => [ 'is_not_null', { -ident => [ 'bar' ] } ] }
876
877 # query
878 bar IS NOT NULL
879 []
880
881 ident op
882 Expands a string ident to an arrayref by splitting on the configured
883 separator, almost always '.':
884
885 # expr
886 { -ident => 'foo.bar' }
887
888 # aqt
889 { -ident => [ 'foo', 'bar' ] }
890
891 # query
892 foo.bar
893 []
894
895 value op
896 Expands to a bind node with the currently applicable column name if
897 known:
898
899 # expr
900 { foo => { '=' => { -value => 3 } } }
901
902 # aqt
903 { -op => [ '=', { -ident => [ 'foo' ] }, { -bind => [ 'foo', 3 ] } ] }
904
905 # query
906 foo = ?
907 [ 3 ]
908
910 select
911 A select node accepts select, from, where and order_by clauses.
912
913 The select clause is expanded as a list expression with a -ident
914 default:
915
916 # expr
917 { -select => { _ => [ 'foo', 'bar', { -count => 'baz' } ] } }
918
919 # aqt
920 { -select => { select => { -op => [
921 ',', { -ident => [ 'foo' ] }, { -ident => [ 'bar' ] },
922 { -func => [ 'count', { -ident => [ 'baz' ] } ] },
923 ] } } }
924
925 # query
926 SELECT foo, bar, COUNT(baz)
927 []
928
929 The from clause is expanded as a list expression with a -ident default:
930
931 # expr
932 { -select => {
933 from => [ 'schema1.table1', { -ident => [ 'schema2', 'table2' ] } ]
934 } }
935
936 # aqt
937 { -select => { from => { -from_list => [
938 { -ident => [ 'schema1', 'table1' ] },
939 { -ident => [ 'schema2', 'table2' ] },
940 ] } } }
941
942 # query
943 FROM schema1.table1, schema2.table2
944 []
945
946 The where clause is expanded as a plain expression:
947
948 # expr
949 { -select => { where => { foo => 3 } } }
950
951 # aqt
952 { -select => { where => {
953 -op => [ '=', { -ident => [ 'foo' ] }, { -bind => [ 'foo', 3 ] } ]
954 } } }
955
956 # query
957 WHERE foo = ?
958 [ 3 ]
959
960 The order_by clause expands as a list expression at top level, but a
961 hashref element may be either an expr or a hashpair with key -asc or
962 -desc to indicate an order by direction:
963
964 # expr
965 { -select =>
966 { order_by => [ 'foo', { -desc => 'bar' }, { -max => 'baz' } ] }
967 }
968
969 # aqt
970 { -select => { order_by => { -op => [
971 ',', { -ident => [ 'foo' ] }, {
972 -op => [ ',', { -op => [ 'desc', { -ident => [ 'bar' ] } ] } ]
973 }, { -func => [ 'max', { -ident => [ 'baz' ] } ] },
974 ] } } }
975
976 # query
977 ORDER BY foo, bar DESC, MAX(baz)
978 []
979
980
981 An insert node accepts an into/target clause, a fields clause, a
982 values/from clause, and a returning clause.
983
984 The target clause is expanded with an ident default.
985
986 The fields clause is expanded as a list expression if an arrayref, and
987 otherwise passed through.
988
989 The from clause may either be an expr, a literal, an arrayref of column
990 values, or a hashref mapping colum names to values.
991
992 The returning clause is expanded as a list expr with an ident default.
993
994 # expr
995 { -insert => {
996 into => 'foo',
997 returning => 'id',
998 values => { bar => 'yay', baz => 'argh' },
999 } }
1000
1001 # aqt
1002 { -insert => {
1003 fields =>
1004 { -row => [ { -ident => [ 'bar' ] }, { -ident => [ 'baz' ] } ] },
1005 from => { -values => [ { -row => [
1006 { -bind => [ 'bar', 'yay' ] },
1007 { -bind => [ 'baz', 'argh' ] },
1008 ] } ] },
1009 returning => { -op => [ ',', { -ident => [ 'id' ] } ] },
1010 target => { -ident => [ 'foo' ] },
1011 } }
1012
1013 # query
1014 INSERT INTO foo (bar, baz) VALUES (?, ?) RETURNING id
1015 [ 'yay', 'argh' ]
1016
1017 # expr
1018 { -insert => {
1019 fields => [ 'bar', 'baz' ],
1020 from => { -select => { _ => [ 'bar', 'baz' ], from => 'other' } },
1021 into => 'foo',
1022 } }
1023
1024 # aqt
1025 { -insert => {
1026 fields => { -row => [ { -op =>
1027 [ ',', { -ident => [ 'bar' ] }, { -ident => [ 'baz' ] } ]
1028 } ] },
1029 from => { -select => {
1030 from => { -ident => [ 'other' ] },
1031 select => { -op =>
1032 [ ',', { -ident => [ 'bar' ] }, { -ident => [ 'baz' ] } ]
1033 },
1034 } },
1035 target => { -ident => [ 'foo' ] },
1036 } }
1037
1038 # query
1039 INSERT INTO foo (bar, baz) SELECT bar, baz FROM other
1040 []
1041
1042 update
1043 An update node accepts update/target (either may be used at expansion
1044 time), set, where, and returning clauses.
1045
1046 The target clause is expanded with an ident default.
1047
1048 The set clause (if not already a list expr) is expanded as a hashref
1049 where the keys are identifiers to be set and the values are
1050 exprs/values.
1051
1052 The where clauses is expanded as a normal expr.
1053
1054 The returning clause is expanded as a list expr with an ident default.
1055
1056 # expr
1057 { -update => {
1058 _ => 'foo',
1059 returning => [ 'id', 'baz' ],
1060 set => { bar => 3, baz => { baz => { '+' => 1 } } },
1061 where => { -not => { -ident => 'quux' } },
1062 } }
1063
1064 # aqt
1065 { -update => {
1066 returning =>
1067 {
1068 -op => [ ',', { -ident => [ 'id' ] }, { -ident => [ 'baz' ] } ]
1069 },
1070 set => { -op => [
1071 ',', { -op =>
1072 [ '=', { -ident => [ 'bar' ] }, { -bind => [ 'bar', 3 ] } ]
1073 }, { -op => [
1074 '=', { -ident => [ 'baz' ] }, { -op => [
1075 '+', { -ident => [ 'baz' ] },
1076 { -bind => [ 'baz', 1 ] },
1077 ] },
1078 ] },
1079 ] },
1080 target => { -ident => [ 'foo' ] },
1081 where => { -op => [ 'not', { -ident => [ 'quux' ] } ] },
1082 } }
1083
1084 # query
1085 UPDATE foo SET bar = ?, baz = baz + ? WHERE (NOT quux) RETURNING id, baz
1086 [ 3, 1 ]
1087
1088 delete
1089 delete accepts from/target, where, and returning clauses.
1090
1091 The target clause is expanded with an ident default.
1092
1093 The where clauses is expanded as a normal expr.
1094
1095 The returning clause is expanded as a list expr with an ident default.
1096
1097 # expr
1098 { -delete => {
1099 from => 'foo',
1100 returning => 'id',
1101 where => { bar => { '<' => 10 } },
1102 } }
1103
1104 # aqt
1105 { -delete => {
1106 returning => { -op => [ ',', { -ident => [ 'id' ] } ] },
1107 target => { -op => [ ',', { -ident => [ 'foo' ] } ] },
1108 where => { -op =>
1109 [ '<', { -ident => [ 'bar' ] }, { -bind => [ 'bar', 10 ] } ]
1110 },
1111 } }
1112
1113 # query
1114 DELETE FROM foo WHERE bar < ? RETURNING id
1115 [ 10 ]
1116
1117
1118
1119perl v5.38.0 2023-07-21 SQL::Abstract::Reference(3)