1Rose::DB::Object::QueryUBsueirldCeorn(t3r)ibuted Perl DoRcousmee:n:tDaBt:i:oOnbject::QueryBuilder(3)
2
3
4
6 Rose::DB::Object::QueryBuilder - Build SQL queries on behalf of
7 Rose::DB::Object::Manager.
8
10 use Rose::DB::Object::QueryBuilder qw(build_select);
11
12 # Build simple query
13 $sql = build_select
14 (
15 dbh => $dbh,
16 select => 'COUNT(*)',
17 tables => [ 'articles' ],
18 columns => { articles => [ qw(id category type title date) ] },
19 query =>
20 [
21 category => [ 'sports', 'science' ],
22 type => 'news',
23 title => { like => [ '%million%',
24 '%resident%' ] },
25 ],
26 query_is_sql => 1);
27
28 $sth = $dbh->prepare($sql);
29 $sth->execute;
30 $count = $sth->fetchrow_array;
31
32 ...
33
34 # Return query with placeholders, plus bind values
35 ($sql, $bind) = build_select
36 (
37 dbh => $dbh,
38 tables => [ 'articles' ],
39 columns => { articles => [ qw(id category type title date) ] },
40 query =>
41 [
42 category => [ 'sports', 'science' ],
43 type => 'news',
44 title => { like => [ '%million%',
45 '%resident%' ] },
46 ],
47 query_is_sql => 1,
48 sort_by => 'title DESC, category',
49 limit => 5);
50
51 $sth = $dbh->prepare($sql);
52 $sth->execute(@$bind);
53
54 while($row = $sth->fetchrow_hashref) { ... }
55
56 ...
57
58 # Coerce query values into the right format
59 ($sql, $bind) = build_select
60 (
61 db => $db,
62 tables => [ 'articles' ],
63 columns => { articles => [ qw(id category type title date) ] },
64 classes => { articles => 'Article' },
65 query =>
66 [
67 type => 'news',
68 date => { lt => 'now' },
69 date => { gt => DateTime->new(...) },
70 ],
71 sort_by => 'title DESC, category',
72 limit => 5);
73
74 $sth = $dbh->prepare($sql);
75 $sth->execute(@$bind);
76
78 Rose::DB::Object::QueryBuilder is used to build SQL queries, primarily
79 in service of the Rose::DB::Object::Manager class. It (optionally)
80 exports two functions: build_select() and build_where_clause().
81
83 build_select PARAMS
84 Returns an SQL "select" query string (in scalar context) or an SQL
85 "select" query string with placeholders and a reference to an array
86 of bind values (in list context) constructed based on PARAMS.
87 Valid PARAMS are described below.
88
89 clauses CLAUSES
90 A reference to an array of extra SQL clauses to add to the
91 "WHERE" portion of the query string. This is the obligatory
92 "escape hatch" for clauses that are not supported by arguments
93 to the query parameter.
94
95 columns HASHREF
96 A reference to a hash keyed by table name, each of which points
97 to a reference to an array of the names of the columns in that
98 table. Example:
99
100 $sql = build_select(columns =>
101 {
102 table1 => [ 'col1', 'col2', ... ],
103 table2 => [ 'col1', 'col2', ... ],
104 ...
105 });
106
107 This argument is required.
108
109 db DB
110 A Rose::DB-derived object. This argument is required if
111 query_is_sql is false or omitted.
112
113 dbh DBH
114 A DBI database handle already connected to the correct
115 database. If this argument is omitted, an attempt will be made
116 to extract a database handle from the db argument. If this
117 fails, or if there is no db argument, a fatal error will occur.
118
119 group_by CLAUSE
120 A fully formed SQL "GROUP BY ..." clause, sans the words "GROUP
121 BY", or a reference to an array of strings to be joined with a
122 comma and appended to the "GROUP BY" clause.
123
124 limit NUMBER
125 A number to use in the "LIMIT ..." clause.
126
127 logic LOGIC
128 A string indicating the logic that will be used to join the
129 statements in the WHERE clause. Valid values for LOGIC are
130 "AND" and "OR". If omitted, it defaults to "AND".
131
132 pretty BOOL
133 If true, the SQL returned will have slightly nicer formatting.
134
135 query PARAMS
136 The query parameters, passed as a reference to an array of
137 name/value pairs, scalar references, or array references.
138 PARAMS may include an arbitrary list of selection parameters
139 used to modify the "WHERE" clause of the SQL select statement.
140 Any query parameter that is not in one of the forms described
141 below will cause a fatal error.
142
143 Valid selection parameters are described below, along with the
144 SQL clause they add to the select statement.
145
146 Simple equality:
147
148 'NAME' => "foo" # COLUMN = 'foo'
149 '!NAME' => "foo" # NOT(COLUMN = 'foo')
150
151 'NAME' => [ "a", "b" ] # COLUMN IN ('a', 'b')
152 '!NAME' => [ "a", "b" ] # COLUMN NOT(IN ('a', 'b'))
153
154 Is/is not null:
155
156 'NAME' => undef # COLUMN IS NULL
157 '!NAME' => undef # COLUMN IS NOT NULL
158
159 'NAME' => { eq => undef } # COLUMN IS NULL
160 'NAME' => { ne => undef } # COLUMN IS NOT NULL
161
162 Comparisons:
163
164 NAME => { OP => "foo" } # COLUMN OP 'foo'
165
166 # (COLUMN OP 'foo' OR COLUMN OP 'goo')
167 NAME => { OP => [ "foo", "goo" ] }
168
169 "OP" can be any of the following:
170
171 OP SQL operator
172 ------------- ------------
173 similar SIMILAR TO
174 match ~
175 imatch ~*
176 regex, regexp REGEXP
177 like LIKE
178 ilike ILIKE
179 rlike RLIKE
180 is IS
181 is_not IS NOT
182 ne <>
183 eq =
184 lt <
185 gt >
186 le <=
187 ge >=
188
189 Ranges:
190
191 NAME => { between => [ 1, 99 ] } # COLUMN BETWEEN 1 AND 99
192
193 NAME => { gt_lt => [ 1, 99 ] } # (COLUMN > 1 AND < 99)
194 NAME => { gt_le => [ 1, 99 ] } # (COLUMN > 1 AND <= 99)
195 NAME => { ge_lt => [ 1, 99 ] } # (COLUMN >= 1 AND < 99)
196 NAME => { ge_le => [ 1, 99 ] } # (COLUMN >= 1 AND <= 99)
197
198 If a value is a reference to a scalar, that scalar is "inlined"
199 without any quoting.
200
201 'NAME' => \"foo" # COLUMN = foo
202 'NAME' => [ "a", \"b" ] # COLUMN IN ('a', b)
203
204 Undefined values are translated to the keyword NULL when
205 included in a multi-value comparison.
206
207 'NAME' => [ "a", undef ] # COLUMN IN ('a', NULL)
208
209 Set operations:
210
211 ### Informix (default) ###
212
213 # A IN COLUMN
214 'NAME' => { in_set => 'A' }
215
216 # NOT(A IN COLUMN)
217 '!NAME' => { in_set => 'A' }
218
219 # (A IN COLUMN OR B IN COLUMN)
220 'NAME' => { in_set => [ 'A', 'B'] }
221 'NAME' => { any_in_set => [ 'A', 'B'] }
222
223 # NOT(A IN COLUMN) AND NOT(B IN COLUMN)
224 '!NAME' => { in_set => [ 'A', 'B'] }
225 '!NAME' => { any_in_set => [ 'A', 'B'] }
226
227 # (A IN COLUMN AND B IN COLUMN)
228 'NAME' => { all_in_set => [ 'A', 'B'] }
229
230 # NOT(A IN COLUMN AND B IN COLUMN)
231 '!NAME' => { all_in_set => [ 'A', 'B'] }
232
233 ### MySQL (requires db parameter) ###
234
235 # FIND_IN_SET(A, COLUMN) > 0
236 'NAME' => { in_set => 'A' }
237
238 # NOT(FIND_IN_SET(A, COLUMN) > 0)
239 '!NAME' => { in_set => 'A' }
240
241 # (FIND_IN_SET(A, COLUMN) > 0 OR FIND_IN_SET(B, COLUMN) > 0)
242 'NAME' => { in_set => [ 'A', 'B'] }
243 'NAME' => { any_in_set => [ 'A', 'B'] }
244
245 # NOT(FIND_IN_SET(A, COLUMN) > 0) AND NOT(FIND_IN_SET(B, COLUMN) > 0)
246 '!NAME' => { in_set => [ 'A', 'B'] }
247 '!NAME' => { any_in_set => [ 'A', 'B'] }
248
249 # (FIND_IN_SET(A, COLUMN) > 0 AND FIND_IN_SET(B, COLUMN) > 0)
250 'NAME' => { all_in_set => [ 'A', 'B'] }
251
252 # NOT(FIND_IN_SET(A, COLUMN) > 0 AND FIND_IN_SET(B, COLUMN) > 0)
253 '!NAME' => { all_in_set => [ 'A', 'B'] }
254
255 Array operations:
256
257 # A = ANY(COLUMN)
258 'NAME' => { in_array => 'A' }
259
260 # NOT(A = ANY(COLUMN))
261 '!NAME' => { in_array => 'A' }
262
263 # (A = ANY(COLUMN) OR B = ANY(COLUMN))
264 'NAME' => { in_array => [ 'A', 'B'] }
265 'NAME' => { any_in_array => [ 'A', 'B'] }
266
267 # NOT(A = ANY(COLUMN) OR B = ANY(COLUMN))
268 '!NAME' => { in_array => [ 'A', 'B'] }
269 '!NAME' => { any_in_array => [ 'A', 'B'] }
270
271 # (A = ANY(COLUMN) AND B = ANY(COLUMN))
272 'NAME' => { all_in_array => [ 'A', 'B'] }
273
274 # NOT(A = ANY(COLUMN) AND B = ANY(COLUMN))
275 '!NAME' => { all_in_array => [ 'A', 'B'] }
276
277 PostgreSQL ltree operations:
278
279 OP SQL operator
280 ------------- ------------
281 ltree_ancestor @>
282 ltree_descendant <@
283 ltree_query ~
284 ltree_ltxtquery @
285 ltree_concat ||
286
287 Any of the operations described above can have "_sql" appended
288 to indicate that the corresponding values are to be "inlined"
289 (i.e., included in the SQL query as-is, with no quoting of any
290 kind). This is useful for comparing two columns. For example,
291 this query:
292
293 query => [ legs => { gt_sql => 'eyes' } ]
294
295 would produce this SQL:
296
297 SELECT ... FROM animals WHERE legs > eyes
298
299 where "legs" and "eyes" are both left unquoted.
300
301 The same NAME string may be repeated multiple times. (This is
302 the primary reason that the query is a reference to an array of
303 name/value pairs, rather than a reference to a hash, which
304 would only allow each NAME once.) Example:
305
306 query =>
307 [
308 age => { gt => 10 },
309 age => { lt => 20 },
310 ]
311
312 The string "NAME" can take many forms, each of which eventually
313 resolves to a database column (COLUMN in the examples above).
314
315 Literal SQL can be included by providing a reference to a
316 scalar:
317
318 \'mycol > 123'
319
320 To use placeholders and bind values, pass a reference to an
321 array containing a scalar reference to the literal SQL with
322 placeholders as the first item, followed by a list of values to
323 bind:
324
325 [ \'mycol > ?' => 123 ]
326
327 "column"
328 A bare column name. If the query includes more than one
329 table, the column name may be ambiguous if it appears in
330 two or more tables. In that case, a fatal error will
331 occur. To solve this, use one of the less ambiguous forms
332 below.
333
334 "table.column"
335 A column name and a table name joined by a dot. This is
336 the "fully qualified" column name.
337
338 "tN.column"
339 A column name and a table alias joined by a dot. The table
340 alias is in the form "tN", where "N" is a number starting
341 from 1. See the documentation for tables parameter below
342 to learn how table aliases are assigned to tables.
343
344 Any of the above prefixed with "!"
345 This indicates the negation of the specified condition.
346
347 If query_is_sql is false or omitted, then NAME can also take on
348 these additional forms:
349
350 "method"
351 A get_set column method name from a
352 Rose::DB::Object-derived class fronting one of the tables
353 being queried. There may be ambiguity here if the same
354 method name is defined on more than one of the classes
355 involved in the query. In such a case, the method will be
356 mapped to the first Rose::DB::Object-derived class that
357 contains a method by that name, considered in the order
358 that the tables are provided in the tables parameter.
359
360 "!method"
361 This indicates the negation of the specified condition.
362
363 Un-prefixed column or method names that are ambiguous (i.e.,
364 exist in more than one of the tables being queried) are
365 considered to be part of the primary table ("t1").
366
367 Finally, in the case of apparently intractable ambiguity, like
368 when a table name is the same as another table's alias,
369 remember that you can always use the "tn_"-prefixed column name
370 aliases, which are unique within a given query.
371
372 All of these clauses are joined by logic (default: "AND") in
373 the final query. Example:
374
375 $sql = build_select
376 (
377 dbh => $dbh,
378 select => 'id, title',
379 tables => [ 'articles' ],
380 columns => { articles => [ qw(id category type title) ] },
381 query =>
382 [
383 category => [ 'sports', 'science' ],
384 type => 'news',
385 title => { like => [ '%million%',
386 '%resident%' ] },
387 ],
388 query_is_sql => 1);
389
390 The above returns an SQL statement something like this:
391
392 SELECT id, title FROM articles WHERE
393 category IN ('sports', 'science')
394 AND
395 type = 'news'
396 AND
397 (title LIKE '%million%' OR title LIKE '%resident%')
398 LIMIT 5
399
400 Nested boolean logic is possible using the special keywords
401 "and" and "or" (case insensitive). Example:
402
403 $sql = build_select
404 (
405 dbh => $dbh,
406 select => 'id, title',
407 tables => [ 'articles' ],
408 columns => { articles => [ qw(id category type title) ] },
409 query =>
410 [
411 or =>
412 [
413 and => [ category => undef, type => 'aux' ],
414 category => [ 'sports', 'science' ],
415 ],
416 type => 'news',
417 title => { like => [ '%million%',
418 '%resident%' ] },
419 ],
420 query_is_sql => 1);
421
422 which returns an SQL statement something like this:
423
424 SELECT id, title FROM articles WHERE
425 (
426 (
427 category IS NULL AND
428 type = 'aux'
429 )
430 OR category IN ('sports', 'science')
431 )
432 AND
433 type = 'news'
434 AND
435 (title LIKE '%million%' OR title LIKE '%resident%')
436
437 The "and" and "or" keywords can be used multiple times within a
438 query (just like all other NAME specifiers described earlier)
439 and can be arbitrarily nested.
440
441 If you have a column named "and" or "or", you'll have to use
442 the fully-qualified (table.column) or alias-qualified
443 (tN.column) forms in order to address that column.
444
445 If query_is_sql is false or omitted, all of the parameter
446 values are passed through the "parse_value()" and
447 "format_value()" methods of their corresponding
448 Rose::DB::Object::Metadata::Column-derived column objects.
449
450 If a column object returns true from its manager_uses_method()
451 method, then its parameter value is passed through the
452 corresponding Rose::DB::Object-derived object method instead.
453
454 Example:
455
456 $dt = DateTime->new(year => 2001, month => 1, day => 31);
457
458 $sql = build_select
459 (
460 db => $db,
461 select => 'id, category',
462 tables => [ 'articles' ],
463 columns => { articles => [ qw(id category type date) ] },
464 classes => { articles => 'Article' },
465 query =>
466 [
467 type => 'news',
468 date => { lt => '12/25/2003 8pm' },
469 date => { gt => $dt },
470 ],
471 sort_by => 'id DESC, category',
472 limit => 5);
473
474 The above returns an SQL statement something like this:
475
476 SELECT id, category FROM articles WHERE
477 type = 'news'
478 AND
479 date < '2003-12-25 20:00:00'
480 AND
481 date > '2001-01-31 00:00:00'
482 ORDER BY id DESC, category
483 LIMIT 5
484
485 Finally, here's an example using more than one table:
486
487 $dt = DateTime->new(year => 2001, month => 1, day => 31);
488
489 $sql = build_select
490 (
491 db => $db,
492 tables => [ 'articles', 'categories' ],
493 columns =>
494 {
495 articles => [ qw(id name category_id date) ],
496 categories => [ qw(id name description) ],
497 },
498 classes =>
499 {
500 articles => 'Article',
501 categories => 'Category',
502 },
503 query =>
504 [
505 '!t1.name' => { like => '%foo%' },
506 t2.name => 'news',
507 date => { lt => '12/25/2003 8pm' },
508 date => { gt => $dt },
509 ],
510 clauses =>
511 [
512 't1.category_id = t2.id',
513 ],
514 sort_by => 'articles.name DESC, t2.name',
515 limit => 5);
516
517 The above returns an SQL statement something like this:
518
519 SELECT
520 t1.id,
521 t1.name,
522 t1.category_id,
523 t1.date,
524 t2.id,
525 t2.name,
526 t2.description
527 FROM
528 articles t1,
529 categories t2
530 WHERE
531 t1.category_id = t2.id
532 AND
533 NOT(t1.name LIKE '%foo%')
534 AND
535 t2.name = 'news'
536 AND
537 t1.date < '2003-12-25 20:00:00'
538 AND
539 t1.date > '2001-01-31 00:00:00'
540 ORDER BY articles.name DESC, t2.name
541 LIMIT 5
542
543 query_is_sql BOOL
544 If omitted, this boolean flag is false. If true, then the
545 values of the query parameters are taken as literal strings
546 that are suitable for direct use in SQL queries. Example:
547
548 $sql = build_select
549 (
550 query_is_sql => 1,
551 query =>
552 [
553 date => { lt => '2003-12-25 20:00:00' },
554 ],
555 ...
556 );
557
558 Here the date value "2003-12-25 20:00:00" must be in the format
559 that the current database expects for columns of that data
560 type.
561
562 But if query_is_sql is false or omitted, then any query value
563 that can be handled by the Rose::DB::Object-derived object
564 method that services the corresponding database column is
565 valid. (Note that this is only possible when this method is
566 called from one of the built-in Rose::DB::Object::Manager
567 methods, e.g., get_objects().)
568
569 Example:
570
571 $dt = DateTime->new(year => 2001, month => 1, day => 31);
572
573 $sql = build_select
574 (
575 query =>
576 [
577 date => { gt => $dt },
578 date => { lt => '12/25/2003 8pm' },
579 ],
580 ...
581 );
582
583 Here a DateTime object and a loosely formatted date are passed
584 as values. Provided the Rose::DB::Object-derived object method
585 that services the "date" column can handle such values, they
586 will be parsed and formatted as appropriate for the current
587 database.
588
589 The advantage of this approach is that the query values do not
590 have to be so rigorously specified, nor do they have to be in a
591 database-specific format.
592
593 The disadvantage is that all of this parsing and formatting is
594 done for every query value, and that adds additional overhead
595 to each call.
596
597 Usually, this overhead is dwarfed by the time required for the
598 database to service the query, and, perhaps more importantly,
599 the reduced maintenance headache and busywork required to
600 properly format all query values.
601
602 select COLUMNS
603 The names of the columns to select from the table. COLUMNS may
604 be a string of comma-separated column names, or a reference to
605 an array of column names. If this parameter is omitted, it
606 defaults to all of the columns in all of the tables
607 participating in the query (according to the value of the
608 columns argument).
609
610 sort_by [ CLAUSE | ARRAYREF ]
611 A fully formed SQL "ORDER BY ..." clause, sans the words "ORDER
612 BY", or a reference to an array of strings to be joined with a
613 comma and appended to the "ORDER BY" clause.
614
615 If an item in the referenced array is itself a reference to a
616 scalar, then that item will be dereferenced and passed through
617 unmodified.
618
619 tables TABLES
620 A reference to an array of table names. This argument is
621 required. A fatal error will occur if it is omitted.
622
623 If more than one table is in the list, then each table is
624 aliased to "tN", where N is an ascending number starting with
625 1. The tables are numbered according to their order in TABLES.
626 Example:
627
628 $sql = build_select(tables => [ 'foo', 'bar', 'baz' ], ...);
629
630 print $sql;
631
632 # SELECT ... FROM
633 # foo AS t1,
634 # bar AS t2,
635 # baz AS t3
636 # ...
637
638 Furthermore, if there is no explicit value for the select
639 parameter and if the unique_aliases parameter is set to true,
640 then each selected column is aliased with a "tN_" prefix in a
641 multi-table query. Example:
642
643 SELECT
644 t1.id AS t1_id,
645 t1.name AS t1_name,
646 t2.id AS t2_id,
647 t2.name AS t2_name
648 FROM
649 foo AS t1,
650 bar AS t2
651 WHERE
652 ...
653
654 These unique aliases provide a technique of last resort for
655 unambiguously addressing a column in a query clause.
656
657 unique_aliases BOOL
658 If true, then each selected column will be given a unique alias
659 by prefixing it with its table alias and an underscore. The
660 default value is false. See the documentation for the tables
661 parameter above for an example.
662
663 build_where_clause PARAMS
664 This works the same as the build_select() function, except that it
665 only returns the "WHERE" clause of the SQL query, sans the word
666 "WHERE" and prefixed with a single space.
667
669 John C. Siracusa (siracusa@gmail.com)
670
672 Copyright (c) 2010 by John C. Siracusa. All rights reserved. This
673 program is free software; you can redistribute it and/or modify it
674 under the same terms as Perl itself.
675
676
677
678perl v5.32.0 2020-07-28 Rose::DB::Object::QueryBuilder(3)