Release 1.56
[scpubgit/Q-Branch.git] / lib / SQL / Abstract.pm
CommitLineData
96449e8e 1package SQL::Abstract; # see doc at end of file
2
3# LDNOTE : this code is heavy refactoring from original SQLA.
4# Several design decisions will need discussion during
5# the test / diffusion / acceptance phase; those are marked with flag
6# 'LDNOTE' (note by laurent.dami AT free.fr)
7
8use Carp;
9use strict;
10use warnings;
fffe6900 11use List::Util qw/first/;
12use Scalar::Util qw/blessed/;
96449e8e 13
14#======================================================================
15# GLOBALS
16#======================================================================
17
a120d3e3 18our $VERSION = '1.56';
7479e27e 19
22f1a437 20# This would confuse some packagers
21#$VERSION = eval $VERSION; # numify for warning-free dev releases
96449e8e 22
23our $AUTOLOAD;
24
25# special operators (-in, -between). May be extended/overridden by user.
26# See section WHERE: BUILTIN SPECIAL OPERATORS below for implementation
27my @BUILTIN_SPECIAL_OPS = (
3a2e1a5e 28 {regex => qr/^(not )?between$/i, handler => '_where_field_BETWEEN'},
29 {regex => qr/^(not )?in$/i, handler => '_where_field_IN'},
96449e8e 30);
31
32#======================================================================
33# DEBUGGING AND ERROR REPORTING
34#======================================================================
35
36sub _debug {
37 return unless $_[0]->{debug}; shift; # a little faster
38 my $func = (caller(1))[3];
39 warn "[$func] ", @_, "\n";
40}
41
42sub belch (@) {
43 my($func) = (caller(1))[3];
44 carp "[$func] Warning: ", @_;
45}
46
47sub puke (@) {
48 my($func) = (caller(1))[3];
49 croak "[$func] Fatal: ", @_;
50}
51
52
53#======================================================================
54# NEW
55#======================================================================
56
57sub new {
58 my $self = shift;
59 my $class = ref($self) || $self;
60 my %opt = (ref $_[0] eq 'HASH') ? %{$_[0]} : @_;
61
62 # choose our case by keeping an option around
63 delete $opt{case} if $opt{case} && $opt{case} ne 'lower';
64
65 # default logic for interpreting arrayrefs
ef559da3 66 $opt{logic} = $opt{logic} ? uc $opt{logic} : 'OR';
96449e8e 67
68 # how to return bind vars
69 # LDNOTE: changed nwiger code : why this 'delete' ??
70 # $opt{bindtype} ||= delete($opt{bind_type}) || 'normal';
71 $opt{bindtype} ||= 'normal';
72
73 # default comparison is "=", but can be overridden
74 $opt{cmp} ||= '=';
75
76 # try to recognize which are the 'equality' and 'unequality' ops
77 # (temporary quickfix, should go through a more seasoned API)
78 $opt{equality_op} = qr/^(\Q$opt{cmp}\E|is|(is\s+)?like)$/i;
79 $opt{inequality_op} = qr/^(!=|<>|(is\s+)?not(\s+like)?)$/i;
80
81 # SQL booleans
82 $opt{sqltrue} ||= '1=1';
83 $opt{sqlfalse} ||= '0=1';
84
85 # special operators
86 $opt{special_ops} ||= [];
87 push @{$opt{special_ops}}, @BUILTIN_SPECIAL_OPS;
88
89 return bless \%opt, $class;
90}
91
92
93
94#======================================================================
95# INSERT methods
96#======================================================================
97
98sub insert {
99 my $self = shift;
100 my $table = $self->_table(shift);
101 my $data = shift || return;
102
103 my $method = $self->_METHOD_FOR_refkind("_insert", $data);
104 my ($sql, @bind) = $self->$method($data);
105 $sql = join " ", $self->_sqlcase('insert into'), $table, $sql;
106 return wantarray ? ($sql, @bind) : $sql;
107}
108
109sub _insert_HASHREF { # explicit list of fields and then values
110 my ($self, $data) = @_;
111
112 my @fields = sort keys %$data;
113
fe3ae272 114 my ($sql, @bind) = $self->_insert_values($data);
96449e8e 115
116 # assemble SQL
117 $_ = $self->_quote($_) foreach @fields;
118 $sql = "( ".join(", ", @fields).") ".$sql;
119
120 return ($sql, @bind);
121}
122
123sub _insert_ARRAYREF { # just generate values(?,?) part (no list of fields)
124 my ($self, $data) = @_;
125
126 # no names (arrayref) so can't generate bindtype
127 $self->{bindtype} ne 'columns'
128 or belch "can't do 'columns' bindtype when called with arrayref";
129
fe3ae272 130 # fold the list of values into a hash of column name - value pairs
131 # (where the column names are artificially generated, and their
132 # lexicographical ordering keep the ordering of the original list)
133 my $i = "a"; # incremented values will be in lexicographical order
134 my $data_in_hash = { map { ($i++ => $_) } @$data };
135
136 return $self->_insert_values($data_in_hash);
137}
138
139sub _insert_ARRAYREFREF { # literal SQL with bind
140 my ($self, $data) = @_;
141
142 my ($sql, @bind) = @${$data};
143 $self->_assert_bindval_matches_bindtype(@bind);
144
145 return ($sql, @bind);
146}
147
148
149sub _insert_SCALARREF { # literal SQL without bind
150 my ($self, $data) = @_;
151
152 return ($$data);
153}
154
155sub _insert_values {
156 my ($self, $data) = @_;
157
96449e8e 158 my (@values, @all_bind);
fe3ae272 159 foreach my $column (sort keys %$data) {
160 my $v = $data->{$column};
96449e8e 161
162 $self->_SWITCH_refkind($v, {
163
164 ARRAYREF => sub {
165 if ($self->{array_datatypes}) { # if array datatype are activated
166 push @values, '?';
fe3ae272 167 push @all_bind, $self->_bindtype($column, $v);
96449e8e 168 }
169 else { # else literal SQL with bind
170 my ($sql, @bind) = @$v;
fe3ae272 171 $self->_assert_bindval_matches_bindtype(@bind);
96449e8e 172 push @values, $sql;
173 push @all_bind, @bind;
174 }
175 },
176
177 ARRAYREFREF => sub { # literal SQL with bind
178 my ($sql, @bind) = @${$v};
fe3ae272 179 $self->_assert_bindval_matches_bindtype(@bind);
96449e8e 180 push @values, $sql;
181 push @all_bind, @bind;
182 },
183
184 # THINK : anything useful to do with a HASHREF ?
5db47f9f 185 HASHREF => sub { # (nothing, but old SQLA passed it through)
186 #TODO in SQLA >= 2.0 it will die instead
187 belch "HASH ref as bind value in insert is not supported";
188 push @values, '?';
fe3ae272 189 push @all_bind, $self->_bindtype($column, $v);
5db47f9f 190 },
96449e8e 191
192 SCALARREF => sub { # literal SQL without bind
193 push @values, $$v;
194 },
195
196 SCALAR_or_UNDEF => sub {
197 push @values, '?';
fe3ae272 198 push @all_bind, $self->_bindtype($column, $v);
96449e8e 199 },
200
201 });
202
203 }
204
205 my $sql = $self->_sqlcase('values')." ( ".join(", ", @values)." )";
206 return ($sql, @all_bind);
207}
208
209
96449e8e 210
211#======================================================================
212# UPDATE methods
213#======================================================================
214
215
216sub update {
217 my $self = shift;
218 my $table = $self->_table(shift);
219 my $data = shift || return;
220 my $where = shift;
221
222 # first build the 'SET' part of the sql statement
223 my (@set, @all_bind);
224 puke "Unsupported data type specified to \$sql->update"
225 unless ref $data eq 'HASH';
226
227 for my $k (sort keys %$data) {
228 my $v = $data->{$k};
229 my $r = ref $v;
230 my $label = $self->_quote($k);
231
232 $self->_SWITCH_refkind($v, {
233 ARRAYREF => sub {
234 if ($self->{array_datatypes}) { # array datatype
235 push @set, "$label = ?";
236 push @all_bind, $self->_bindtype($k, $v);
237 }
238 else { # literal SQL with bind
239 my ($sql, @bind) = @$v;
fe3ae272 240 $self->_assert_bindval_matches_bindtype(@bind);
96449e8e 241 push @set, "$label = $sql";
fe3ae272 242 push @all_bind, @bind;
96449e8e 243 }
244 },
245 ARRAYREFREF => sub { # literal SQL with bind
246 my ($sql, @bind) = @${$v};
fe3ae272 247 $self->_assert_bindval_matches_bindtype(@bind);
96449e8e 248 push @set, "$label = $sql";
fe3ae272 249 push @all_bind, @bind;
96449e8e 250 },
251 SCALARREF => sub { # literal SQL without bind
252 push @set, "$label = $$v";
253 },
254 SCALAR_or_UNDEF => sub {
255 push @set, "$label = ?";
256 push @all_bind, $self->_bindtype($k, $v);
257 },
258 });
259 }
260
261 # generate sql
262 my $sql = $self->_sqlcase('update') . " $table " . $self->_sqlcase('set ')
263 . join ', ', @set;
264
265 if ($where) {
266 my($where_sql, @where_bind) = $self->where($where);
267 $sql .= $where_sql;
268 push @all_bind, @where_bind;
269 }
270
271 return wantarray ? ($sql, @all_bind) : $sql;
272}
273
274
275
276
277#======================================================================
278# SELECT
279#======================================================================
280
281
282sub select {
283 my $self = shift;
284 my $table = $self->_table(shift);
285 my $fields = shift || '*';
286 my $where = shift;
287 my $order = shift;
288
289 my($where_sql, @bind) = $self->where($where, $order);
290
291 my $f = (ref $fields eq 'ARRAY') ? join ', ', map { $self->_quote($_) } @$fields
292 : $fields;
293 my $sql = join(' ', $self->_sqlcase('select'), $f,
294 $self->_sqlcase('from'), $table)
295 . $where_sql;
296
297 return wantarray ? ($sql, @bind) : $sql;
298}
299
300#======================================================================
301# DELETE
302#======================================================================
303
304
305sub delete {
306 my $self = shift;
307 my $table = $self->_table(shift);
308 my $where = shift;
309
310
311 my($where_sql, @bind) = $self->where($where);
312 my $sql = $self->_sqlcase('delete from') . " $table" . $where_sql;
313
314 return wantarray ? ($sql, @bind) : $sql;
315}
316
317
318#======================================================================
319# WHERE: entry point
320#======================================================================
321
322
323
324# Finally, a separate routine just to handle WHERE clauses
325sub where {
326 my ($self, $where, $order) = @_;
327
328 # where ?
329 my ($sql, @bind) = $self->_recurse_where($where);
330 $sql = $sql ? $self->_sqlcase(' where ') . "( $sql )" : '';
331
332 # order by?
333 if ($order) {
334 $sql .= $self->_order_by($order);
335 }
336
337 return wantarray ? ($sql, @bind) : $sql;
338}
339
340
341sub _recurse_where {
342 my ($self, $where, $logic) = @_;
343
344 # dispatch on appropriate method according to refkind of $where
345 my $method = $self->_METHOD_FOR_refkind("_where", $where);
311b2151 346
347
348 my ($sql, @bind) = $self->$method($where, $logic);
349
350 # DBIx::Class directly calls _recurse_where in scalar context, so
351 # we must implement it, even if not in the official API
352 return wantarray ? ($sql, @bind) : $sql;
96449e8e 353}
354
355
356
357#======================================================================
358# WHERE: top-level ARRAYREF
359#======================================================================
360
361
362sub _where_ARRAYREF {
5e1d09d5 363 my ($self, $where, $logic) = @_;
96449e8e 364
5e1d09d5 365 $logic = uc($logic || $self->{logic});
96449e8e 366 $logic eq 'AND' or $logic eq 'OR' or puke "unknown logic: $logic";
367
368 my @clauses = @$where;
369
96449e8e 370 my (@sql_clauses, @all_bind);
96449e8e 371 # need to use while() so can shift() for pairs
372 while (my $el = shift @clauses) {
373
374 # switch according to kind of $el and get corresponding ($sql, @bind)
375 my ($sql, @bind) = $self->_SWITCH_refkind($el, {
376
377 # skip empty elements, otherwise get invalid trailing AND stuff
378 ARRAYREF => sub {$self->_recurse_where($el) if @$el},
379
474e3335 380 ARRAYREFREF => sub { @{${$el}} if @{${$el}}},
381
96449e8e 382 HASHREF => sub {$self->_recurse_where($el, 'and') if %$el},
383 # LDNOTE : previous SQLA code for hashrefs was creating a dirty
384 # side-effect: the first hashref within an array would change
385 # the global logic to 'AND'. So [ {cond1, cond2}, [cond3, cond4] ]
386 # was interpreted as "(cond1 AND cond2) OR (cond3 AND cond4)",
387 # whereas it should be "(cond1 AND cond2) OR (cond3 OR cond4)".
388
389 SCALARREF => sub { ($$el); },
390
391 SCALAR => sub {# top-level arrayref with scalars, recurse in pairs
392 $self->_recurse_where({$el => shift(@clauses)})},
393
394 UNDEF => sub {puke "not supported : UNDEF in arrayref" },
395 });
396
4b7b6026 397 if ($sql) {
398 push @sql_clauses, $sql;
399 push @all_bind, @bind;
400 }
96449e8e 401 }
402
403 return $self->_join_sql_clauses($logic, \@sql_clauses, \@all_bind);
404}
405
474e3335 406#======================================================================
407# WHERE: top-level ARRAYREFREF
408#======================================================================
96449e8e 409
474e3335 410sub _where_ARRAYREFREF {
411 my ($self, $where) = @_;
412 my ($sql, @bind) = @{${$where}};
413
414 return ($sql, @bind);
415}
96449e8e 416
417#======================================================================
418# WHERE: top-level HASHREF
419#======================================================================
420
421sub _where_HASHREF {
422 my ($self, $where) = @_;
423 my (@sql_clauses, @all_bind);
424
96449e8e 425 for my $k (sort keys %$where) {
426 my $v = $where->{$k};
427
428 # ($k => $v) is either a special op or a regular hashpair
429 my ($sql, @bind) = ($k =~ /^-(.+)/) ? $self->_where_op_in_hash($1, $v)
430 : do {
431 my $method = $self->_METHOD_FOR_refkind("_where_hashpair", $v);
432 $self->$method($k, $v);
433 };
434
435 push @sql_clauses, $sql;
436 push @all_bind, @bind;
437 }
438
439 return $self->_join_sql_clauses('and', \@sql_clauses, \@all_bind);
440}
441
442
443sub _where_op_in_hash {
6dae476e 444 my ($self, $op_str, $v) = @_;
445
01a01e57 446 $op_str =~ /^ (AND|OR|NEST) ( \_? \d* ) $/xi
6dae476e 447 or puke "unknown operator: -$op_str";
448
449 my $op = uc($1); # uppercase, remove trailing digits
450 if ($2) {
01a01e57 451 belch 'Use of [and|or|nest]_N modifiers is deprecated and will be removed in SQLA v2.0. '
6dae476e 452 . "You probably wanted ...-and => [ $op_str => COND1, $op_str => COND2 ... ]";
453 }
96449e8e 454
96449e8e 455 $self->_debug("OP(-$op) within hashref, recursing...");
456
457 $self->_SWITCH_refkind($v, {
458
459 ARRAYREF => sub {
01a01e57 460 return $self->_where_ARRAYREF($v, $op eq 'NEST' ? '' : $op);
96449e8e 461 },
462
463 HASHREF => sub {
464 if ($op eq 'OR') {
106c861e 465 return $self->_where_ARRAYREF([ map { $_ => $v->{$_} } (sort keys %$v) ], 'OR');
96449e8e 466 }
01a01e57 467 else { # NEST | AND
96449e8e 468 return $self->_where_HASHREF($v);
469 }
470 },
471
472 SCALARREF => sub { # literal SQL
01a01e57 473 $op eq 'NEST'
474 or puke "-$op => \\\$scalar not supported, use -nest => ...";
96449e8e 475 return ($$v);
476 },
477
478 ARRAYREFREF => sub { # literal SQL
01a01e57 479 $op eq 'NEST'
480 or puke "-$op => \\[..] not supported, use -nest => ...";
96449e8e 481 return @{${$v}};
482 },
483
484 SCALAR => sub { # permissively interpreted as SQL
01a01e57 485 $op eq 'NEST'
486 or puke "-$op => 'scalar' not supported, use -nest => \\'scalar'";
487 belch "literal SQL should be -nest => \\'scalar' "
488 . "instead of -nest => 'scalar' ";
96449e8e 489 return ($v);
490 },
491
492 UNDEF => sub {
493 puke "-$op => undef not supported";
494 },
495 });
496}
497
498
499sub _where_hashpair_ARRAYREF {
500 my ($self, $k, $v) = @_;
501
502 if( @$v ) {
503 my @v = @$v; # need copy because of shift below
504 $self->_debug("ARRAY($k) means distribute over elements");
505
506 # put apart first element if it is an operator (-and, -or)
e3cecb45 507 my $op = (
508 (defined $v[0] && $v[0] =~ /^ - (?: AND|OR ) $/ix)
509 ? shift @v
510 : ''
04d940de 511 );
96449e8e 512 my @distributed = map { {$k => $_} } @v;
04d940de 513
514 if ($op) {
515 $self->_debug("OP($op) reinjected into the distributed array");
516 unshift @distributed, $op;
517 }
518
f67591bf 519 my $logic = $op ? substr($op, 1) : '';
96449e8e 520
f67591bf 521 return $self->_recurse_where(\@distributed, $logic);
96449e8e 522 }
523 else {
524 # LDNOTE : not sure of this one. What does "distribute over nothing" mean?
525 $self->_debug("empty ARRAY($k) means 0=1");
526 return ($self->{sqlfalse});
527 }
528}
529
530sub _where_hashpair_HASHREF {
eb49170d 531 my ($self, $k, $v, $logic) = @_;
532 $logic ||= 'and';
96449e8e 533
eb49170d 534 my ($all_sql, @all_bind);
96449e8e 535
536 for my $op (sort keys %$v) {
537 my $val = $v->{$op};
538
539 # put the operator in canonical form
540 $op =~ s/^-//; # remove initial dash
541 $op =~ tr/_/ /; # underscores become spaces
542 $op =~ s/^\s+//; # no initial space
543 $op =~ s/\s+$//; # no final space
544 $op =~ s/\s+/ /; # multiple spaces become one
545
546 my ($sql, @bind);
547
548 # CASE: special operators like -in or -between
549 my $special_op = first {$op =~ $_->{regex}} @{$self->{special_ops}};
550 if ($special_op) {
3a2e1a5e 551 my $handler = $special_op->{handler};
552 if (! $handler) {
553 puke "No handler supplied for special operator matching $special_op->{regex}";
554 }
555 elsif (not ref $handler) {
556 ($sql, @bind) = $self->$handler ($k, $op, $val);
557 }
558 elsif (ref $handler eq 'CODE') {
559 ($sql, @bind) = $handler->($self, $k, $op, $val);
560 }
561 else {
562 puke "Illegal handler for special operator matching $special_op->{regex} - expecting a method name or a coderef";
563 }
96449e8e 564 }
96449e8e 565 else {
cf838930 566 $self->_SWITCH_refkind($val, {
567
568 ARRAYREF => sub { # CASE: col => {op => \@vals}
569 ($sql, @bind) = $self->_where_field_op_ARRAYREF($k, $op, $val);
570 },
571
fe3ae272 572 SCALARREF => sub { # CASE: col => {op => \$scalar} (literal SQL without bind)
cf838930 573 $sql = join ' ', $self->_convert($self->_quote($k)),
574 $self->_sqlcase($op),
575 $$val;
576 },
577
fe3ae272 578 ARRAYREFREF => sub { # CASE: col => {op => \[$sql, @bind]} (literal SQL with bind)
b3be7bd0 579 my ($sub_sql, @sub_bind) = @$$val;
fe3ae272 580 $self->_assert_bindval_matches_bindtype(@sub_bind);
b3be7bd0 581 $sql = join ' ', $self->_convert($self->_quote($k)),
582 $self->_sqlcase($op),
583 $sub_sql;
fe3ae272 584 @bind = @sub_bind;
b3be7bd0 585 },
586
eb49170d 587 HASHREF => sub {
588 ($sql, @bind) = $self->_where_hashpair_HASHREF($k, $val, $op);
589 },
590
cf838930 591 UNDEF => sub { # CASE: col => {op => undef} : sql "IS (NOT)? NULL"
592 my $is = ($op =~ $self->{equality_op}) ? 'is' :
593 ($op =~ $self->{inequality_op}) ? 'is not' :
594 puke "unexpected operator '$op' with undef operand";
595 $sql = $self->_quote($k) . $self->_sqlcase(" $is null");
596 },
597
598 FALLBACK => sub { # CASE: col => {op => $scalar}
599 $sql = join ' ', $self->_convert($self->_quote($k)),
600 $self->_sqlcase($op),
601 $self->_convert('?');
602 @bind = $self->_bindtype($k, $val);
603 },
604 });
96449e8e 605 }
606
eb49170d 607 ($all_sql) = (defined $all_sql and $all_sql) ? $self->_join_sql_clauses($logic, [$all_sql, $sql], []) : $sql;
96449e8e 608 push @all_bind, @bind;
609 }
eb49170d 610 return ($all_sql, @all_bind);
96449e8e 611}
612
613
614
615sub _where_field_op_ARRAYREF {
616 my ($self, $k, $op, $vals) = @_;
617
ce261791 618 my @vals = @$vals; #always work on a copy
619
620 if(@vals) {
621 $self->_debug("ARRAY($vals) means multiple elements: [ @vals ]");
96449e8e 622
4030915f 623 # see if the first element is an -and/-or op
624 my $logic;
ce261791 625 if ($vals[0] =~ /^ - ( AND|OR ) $/ix) {
4030915f 626 $logic = uc $1;
ce261791 627 shift @vals;
4030915f 628 }
629
ce261791 630 # distribute $op over each remaining member of @vals, append logic if exists
631 return $self->_recurse_where([map { {$k => {$op, $_}} } @vals], $logic);
4030915f 632
f2d5020d 633 # LDNOTE : had planned to change the distribution logic when
96449e8e 634 # $op =~ $self->{inequality_op}, because of Morgan laws :
635 # with {field => {'!=' => [22, 33]}}, it would be ridiculous to generate
636 # WHERE field != 22 OR field != 33 : the user probably means
637 # WHERE field != 22 AND field != 33.
4030915f 638 # To do this, replace the above to roughly :
f2d5020d 639 # my $logic = ($op =~ $self->{inequality_op}) ? 'AND' : 'OR';
ce261791 640 # return $self->_recurse_where([map { {$k => {$op, $_}} } @vals], $logic);
96449e8e 641
96449e8e 642 }
643 else {
644 # try to DWIM on equality operators
645 # LDNOTE : not 100% sure this is the correct thing to do ...
646 return ($self->{sqlfalse}) if $op =~ $self->{equality_op};
647 return ($self->{sqltrue}) if $op =~ $self->{inequality_op};
648
649 # otherwise
650 puke "operator '$op' applied on an empty array (field '$k')";
651 }
652}
653
654
655sub _where_hashpair_SCALARREF {
656 my ($self, $k, $v) = @_;
657 $self->_debug("SCALAR($k) means literal SQL: $$v");
658 my $sql = $self->_quote($k) . " " . $$v;
659 return ($sql);
660}
661
fe3ae272 662# literal SQL with bind
96449e8e 663sub _where_hashpair_ARRAYREFREF {
664 my ($self, $k, $v) = @_;
665 $self->_debug("REF($k) means literal SQL: @${$v}");
666 my ($sql, @bind) = @${$v};
fe3ae272 667 $self->_assert_bindval_matches_bindtype(@bind);
96449e8e 668 $sql = $self->_quote($k) . " " . $sql;
96449e8e 669 return ($sql, @bind );
670}
671
fe3ae272 672# literal SQL without bind
96449e8e 673sub _where_hashpair_SCALAR {
674 my ($self, $k, $v) = @_;
675 $self->_debug("NOREF($k) means simple key=val: $k $self->{cmp} $v");
676 my $sql = join ' ', $self->_convert($self->_quote($k)),
677 $self->_sqlcase($self->{cmp}),
678 $self->_convert('?');
679 my @bind = $self->_bindtype($k, $v);
680 return ( $sql, @bind);
681}
682
683
684sub _where_hashpair_UNDEF {
685 my ($self, $k, $v) = @_;
686 $self->_debug("UNDEF($k) means IS NULL");
687 my $sql = $self->_quote($k) . $self->_sqlcase(' is null');
688 return ($sql);
689}
690
691#======================================================================
692# WHERE: TOP-LEVEL OTHERS (SCALARREF, SCALAR, UNDEF)
693#======================================================================
694
695
696sub _where_SCALARREF {
697 my ($self, $where) = @_;
698
699 # literal sql
700 $self->_debug("SCALAR(*top) means literal SQL: $$where");
701 return ($$where);
702}
703
704
705sub _where_SCALAR {
706 my ($self, $where) = @_;
707
708 # literal sql
709 $self->_debug("NOREF(*top) means literal SQL: $where");
710 return ($where);
711}
712
713
714sub _where_UNDEF {
715 my ($self) = @_;
716 return ();
717}
718
719
720#======================================================================
721# WHERE: BUILTIN SPECIAL OPERATORS (-in, -between)
722#======================================================================
723
724
725sub _where_field_BETWEEN {
726 my ($self, $k, $op, $vals) = @_;
727
cf02fc47 728 (ref $vals eq 'ARRAY' && @$vals == 2) or
729 (ref $vals eq 'REF' && (@$$vals == 1 || @$$vals == 2 || @$$vals == 3))
730 or puke "special op 'between' requires an arrayref of two values (or a scalarref or arrayrefref for literal SQL)";
96449e8e 731
cf02fc47 732 my ($clause, @bind, $label, $and, $placeholder);
733 $label = $self->_convert($self->_quote($k));
734 $and = ' ' . $self->_sqlcase('and') . ' ';
735 $placeholder = $self->_convert('?');
96449e8e 736 $op = $self->_sqlcase($op);
737
cf02fc47 738 if (ref $vals eq 'REF') {
739 ($clause, @bind) = @$$vals;
740 }
741 else {
742 my (@all_sql, @all_bind);
743
744 foreach my $val (@$vals) {
745 my ($sql, @bind) = $self->_SWITCH_refkind($val, {
746 SCALAR => sub {
747 return ($placeholder, ($val));
748 },
749 SCALARREF => sub {
750 return ($self->_convert($$val), ());
751 },
752 });
753 push @all_sql, $sql;
754 push @all_bind, @bind;
755 }
756
757 $clause = (join $and, @all_sql);
758 @bind = $self->_bindtype($k, @all_bind);
759 }
760 my $sql = "( $label $op $clause )";
96449e8e 761 return ($sql, @bind)
762}
763
764
765sub _where_field_IN {
766 my ($self, $k, $op, $vals) = @_;
767
768 # backwards compatibility : if scalar, force into an arrayref
769 $vals = [$vals] if defined $vals && ! ref $vals;
770
96449e8e 771 my ($label) = $self->_convert($self->_quote($k));
772 my ($placeholder) = $self->_convert('?');
96449e8e 773 $op = $self->_sqlcase($op);
774
8a0d798a 775 my ($sql, @bind) = $self->_SWITCH_refkind($vals, {
776 ARRAYREF => sub { # list of choices
777 if (@$vals) { # nonempty list
778 my $placeholders = join ", ", (($placeholder) x @$vals);
779 my $sql = "$label $op ( $placeholders )";
780 my @bind = $self->_bindtype($k, @$vals);
96449e8e 781
8a0d798a 782 return ($sql, @bind);
783 }
784 else { # empty list : some databases won't understand "IN ()", so DWIM
785 my $sql = ($op =~ /\bnot\b/i) ? $self->{sqltrue} : $self->{sqlfalse};
786 return ($sql);
787 }
788 },
789
790 ARRAYREFREF => sub { # literal SQL with bind
791 my ($sql, @bind) = @$$vals;
fe3ae272 792 $self->_assert_bindval_matches_bindtype(@bind);
8a0d798a 793 return ("$label $op ( $sql )", @bind);
794 },
795
796 FALLBACK => sub {
797 puke "special op 'in' requires an arrayref (or arrayref-ref)";
798 },
799 });
800
801 return ($sql, @bind);
96449e8e 802}
803
804
805
806
807
808
809#======================================================================
810# ORDER BY
811#======================================================================
812
813sub _order_by {
814 my ($self, $arg) = @_;
815
f267b646 816 my (@sql, @bind);
817 for my $c ($self->_order_by_chunks ($arg) ) {
818 $self->_SWITCH_refkind ($c, {
819 SCALAR => sub { push @sql, $c },
820 ARRAYREF => sub { push @sql, shift @$c; push @bind, @$c },
821 });
822 }
823
824 my $sql = @sql
825 ? sprintf ('%s %s',
826 $self->_sqlcase(' order by'),
827 join (', ', @sql)
828 )
829 : ''
830 ;
831
832 return wantarray ? ($sql, @bind) : $sql;
833}
834
835sub _order_by_chunks {
836 my ($self, $arg) = @_;
837
838 return $self->_SWITCH_refkind($arg, {
96449e8e 839
840 ARRAYREF => sub {
f267b646 841 map { $self->_order_by_chunks ($_ ) } @$arg;
96449e8e 842 },
843
f267b646 844 ARRAYREFREF => sub { [ @$$arg ] },
845
96449e8e 846 SCALAR => sub {$self->_quote($arg)},
f267b646 847
848 UNDEF => sub {return () },
849
96449e8e 850 SCALARREF => sub {$$arg}, # literal SQL, no quoting
96449e8e 851
f267b646 852 HASHREF => sub {
853 # get first pair in hash
854 my ($key, $val) = each %$arg;
96449e8e 855
f267b646 856 return () unless $key;
96449e8e 857
f267b646 858 if ( (keys %$arg) > 1 or not $key =~ /^-(desc|asc)/i ) {
859 puke "hash passed to _order_by must have exactly one key (-desc or -asc)";
860 }
96449e8e 861
f267b646 862 my $direction = $1;
96449e8e 863
e9bd3547 864 my @ret;
f267b646 865 for my $c ($self->_order_by_chunks ($val)) {
e9bd3547 866 my ($sql, @bind);
96449e8e 867
f267b646 868 $self->_SWITCH_refkind ($c, {
869 SCALAR => sub {
e9bd3547 870 $sql = $c;
f267b646 871 },
872 ARRAYREF => sub {
e9bd3547 873 ($sql, @bind) = @$c;
f267b646 874 },
875 });
f267b646 876
e9bd3547 877 $sql = $sql . ' ' . $self->_sqlcase($direction);
878
879 push @ret, [ $sql, @bind];
880 }
96449e8e 881
e9bd3547 882 return @ret;
f267b646 883 },
884 });
885}
96449e8e 886
887
888#======================================================================
889# DATASOURCE (FOR NOW, JUST PLAIN TABLE OR LIST OF TABLES)
890#======================================================================
891
892sub _table {
893 my $self = shift;
894 my $from = shift;
895 $self->_SWITCH_refkind($from, {
896 ARRAYREF => sub {join ', ', map { $self->_quote($_) } @$from;},
897 SCALAR => sub {$self->_quote($from)},
898 SCALARREF => sub {$$from},
899 ARRAYREFREF => sub {join ', ', @$from;},
900 });
901}
902
903
904#======================================================================
905# UTILITY FUNCTIONS
906#======================================================================
907
908sub _quote {
909 my $self = shift;
910 my $label = shift;
911
912 $label or puke "can't quote an empty label";
913
914 # left and right quote characters
915 my ($ql, $qr, @other) = $self->_SWITCH_refkind($self->{quote_char}, {
916 SCALAR => sub {($self->{quote_char}, $self->{quote_char})},
917 ARRAYREF => sub {@{$self->{quote_char}}},
918 UNDEF => sub {()},
919 });
920 not @other
921 or puke "quote_char must be an arrayref of 2 values";
922
923 # no quoting if no quoting chars
924 $ql or return $label;
925
926 # no quoting for literal SQL
927 return $$label if ref($label) eq 'SCALAR';
928
929 # separate table / column (if applicable)
930 my $sep = $self->{name_sep} || '';
931 my @to_quote = $sep ? split /\Q$sep\E/, $label : ($label);
932
933 # do the quoting, except for "*" or for `table`.*
934 my @quoted = map { $_ eq '*' ? $_: $ql.$_.$qr} @to_quote;
935
936 # reassemble and return.
937 return join $sep, @quoted;
938}
939
940
941# Conversion, if applicable
942sub _convert ($) {
943 my ($self, $arg) = @_;
944
945# LDNOTE : modified the previous implementation below because
946# it was not consistent : the first "return" is always an array,
947# the second "return" is context-dependent. Anyway, _convert
948# seems always used with just a single argument, so make it a
949# scalar function.
950# return @_ unless $self->{convert};
951# my $conv = $self->_sqlcase($self->{convert});
952# my @ret = map { $conv.'('.$_.')' } @_;
953# return wantarray ? @ret : $ret[0];
954 if ($self->{convert}) {
955 my $conv = $self->_sqlcase($self->{convert});
956 $arg = $conv.'('.$arg.')';
957 }
958 return $arg;
959}
960
961# And bindtype
962sub _bindtype (@) {
963 my $self = shift;
964 my($col, @vals) = @_;
965
966 #LDNOTE : changed original implementation below because it did not make
967 # sense when bindtype eq 'columns' and @vals > 1.
968# return $self->{bindtype} eq 'columns' ? [ $col, @vals ] : @vals;
969
970 return $self->{bindtype} eq 'columns' ? map {[$col, $_]} @vals : @vals;
971}
972
fe3ae272 973# Dies if any element of @bind is not in [colname => value] format
974# if bindtype is 'columns'.
975sub _assert_bindval_matches_bindtype {
976 my ($self, @bind) = @_;
977
978 if ($self->{bindtype} eq 'columns') {
979 foreach my $val (@bind) {
980 if (!defined $val || ref($val) ne 'ARRAY' || @$val != 2) {
981 die "bindtype 'columns' selected, you need to pass: [column_name => bind_value]"
982 }
983 }
984 }
985}
986
96449e8e 987sub _join_sql_clauses {
988 my ($self, $logic, $clauses_aref, $bind_aref) = @_;
989
990 if (@$clauses_aref > 1) {
991 my $join = " " . $self->_sqlcase($logic) . " ";
992 my $sql = '( ' . join($join, @$clauses_aref) . ' )';
993 return ($sql, @$bind_aref);
994 }
995 elsif (@$clauses_aref) {
996 return ($clauses_aref->[0], @$bind_aref); # no parentheses
997 }
998 else {
999 return (); # if no SQL, ignore @$bind_aref
1000 }
1001}
1002
1003
1004# Fix SQL case, if so requested
1005sub _sqlcase {
1006 my $self = shift;
1007
1008 # LDNOTE: if $self->{case} is true, then it contains 'lower', so we
1009 # don't touch the argument ... crooked logic, but let's not change it!
1010 return $self->{case} ? $_[0] : uc($_[0]);
1011}
1012
1013
1014#======================================================================
1015# DISPATCHING FROM REFKIND
1016#======================================================================
1017
1018sub _refkind {
1019 my ($self, $data) = @_;
1020 my $suffix = '';
1021 my $ref;
90aab162 1022 my $n_steps = 0;
96449e8e 1023
96449e8e 1024 while (1) {
90aab162 1025 # blessed objects are treated like scalars
1026 $ref = (blessed $data) ? '' : ref $data;
1027 $n_steps += 1 if $ref;
1028 last if $ref ne 'REF';
96449e8e 1029 $data = $$data;
1030 }
1031
90aab162 1032 my $base = $ref || (defined $data ? 'SCALAR' : 'UNDEF');
1033
1034 return $base . ('REF' x $n_steps);
96449e8e 1035}
1036
90aab162 1037
1038
96449e8e 1039sub _try_refkind {
1040 my ($self, $data) = @_;
1041 my @try = ($self->_refkind($data));
1042 push @try, 'SCALAR_or_UNDEF' if $try[0] eq 'SCALAR' || $try[0] eq 'UNDEF';
1043 push @try, 'FALLBACK';
1044 return @try;
1045}
1046
1047sub _METHOD_FOR_refkind {
1048 my ($self, $meth_prefix, $data) = @_;
1049 my $method = first {$_} map {$self->can($meth_prefix."_".$_)}
1050 $self->_try_refkind($data)
1051 or puke "cannot dispatch on '$meth_prefix' for ".$self->_refkind($data);
1052 return $method;
1053}
1054
1055
1056sub _SWITCH_refkind {
1057 my ($self, $data, $dispatch_table) = @_;
1058
1059 my $coderef = first {$_} map {$dispatch_table->{$_}}
1060 $self->_try_refkind($data)
1061 or puke "no dispatch entry for ".$self->_refkind($data);
1062 $coderef->();
1063}
1064
1065
1066
1067
1068#======================================================================
1069# VALUES, GENERATE, AUTOLOAD
1070#======================================================================
1071
1072# LDNOTE: original code from nwiger, didn't touch code in that section
1073# I feel the AUTOLOAD stuff should not be the default, it should
1074# only be activated on explicit demand by user.
1075
1076sub values {
1077 my $self = shift;
1078 my $data = shift || return;
1079 puke "Argument to ", __PACKAGE__, "->values must be a \\%hash"
1080 unless ref $data eq 'HASH';
bab725ce 1081
1082 my @all_bind;
1083 foreach my $k ( sort keys %$data ) {
1084 my $v = $data->{$k};
1085 $self->_SWITCH_refkind($v, {
1086 ARRAYREF => sub {
1087 if ($self->{array_datatypes}) { # array datatype
1088 push @all_bind, $self->_bindtype($k, $v);
1089 }
1090 else { # literal SQL with bind
1091 my ($sql, @bind) = @$v;
1092 $self->_assert_bindval_matches_bindtype(@bind);
1093 push @all_bind, @bind;
1094 }
1095 },
1096 ARRAYREFREF => sub { # literal SQL with bind
1097 my ($sql, @bind) = @${$v};
1098 $self->_assert_bindval_matches_bindtype(@bind);
1099 push @all_bind, @bind;
1100 },
1101 SCALARREF => sub { # literal SQL without bind
1102 },
1103 SCALAR_or_UNDEF => sub {
1104 push @all_bind, $self->_bindtype($k, $v);
1105 },
1106 });
1107 }
1108
1109 return @all_bind;
96449e8e 1110}
1111
1112sub generate {
1113 my $self = shift;
1114
1115 my(@sql, @sqlq, @sqlv);
1116
1117 for (@_) {
1118 my $ref = ref $_;
1119 if ($ref eq 'HASH') {
1120 for my $k (sort keys %$_) {
1121 my $v = $_->{$k};
1122 my $r = ref $v;
1123 my $label = $self->_quote($k);
1124 if ($r eq 'ARRAY') {
fe3ae272 1125 # literal SQL with bind
1126 my ($sql, @bind) = @$v;
1127 $self->_assert_bindval_matches_bindtype(@bind);
96449e8e 1128 push @sqlq, "$label = $sql";
fe3ae272 1129 push @sqlv, @bind;
96449e8e 1130 } elsif ($r eq 'SCALAR') {
fe3ae272 1131 # literal SQL without bind
96449e8e 1132 push @sqlq, "$label = $$v";
1133 } else {
1134 push @sqlq, "$label = ?";
1135 push @sqlv, $self->_bindtype($k, $v);
1136 }
1137 }
1138 push @sql, $self->_sqlcase('set'), join ', ', @sqlq;
1139 } elsif ($ref eq 'ARRAY') {
1140 # unlike insert(), assume these are ONLY the column names, i.e. for SQL
1141 for my $v (@$_) {
1142 my $r = ref $v;
fe3ae272 1143 if ($r eq 'ARRAY') { # literal SQL with bind
1144 my ($sql, @bind) = @$v;
1145 $self->_assert_bindval_matches_bindtype(@bind);
1146 push @sqlq, $sql;
1147 push @sqlv, @bind;
1148 } elsif ($r eq 'SCALAR') { # literal SQL without bind
96449e8e 1149 # embedded literal SQL
1150 push @sqlq, $$v;
1151 } else {
1152 push @sqlq, '?';
1153 push @sqlv, $v;
1154 }
1155 }
1156 push @sql, '(' . join(', ', @sqlq) . ')';
1157 } elsif ($ref eq 'SCALAR') {
1158 # literal SQL
1159 push @sql, $$_;
1160 } else {
1161 # strings get case twiddled
1162 push @sql, $self->_sqlcase($_);
1163 }
1164 }
1165
1166 my $sql = join ' ', @sql;
1167
1168 # this is pretty tricky
1169 # if ask for an array, return ($stmt, @bind)
1170 # otherwise, s/?/shift @sqlv/ to put it inline
1171 if (wantarray) {
1172 return ($sql, @sqlv);
1173 } else {
1174 1 while $sql =~ s/\?/my $d = shift(@sqlv);
1175 ref $d ? $d->[1] : $d/e;
1176 return $sql;
1177 }
1178}
1179
1180
1181sub DESTROY { 1 }
1182
1183sub AUTOLOAD {
1184 # This allows us to check for a local, then _form, attr
1185 my $self = shift;
1186 my($name) = $AUTOLOAD =~ /.*::(.+)/;
1187 return $self->generate($name, @_);
1188}
1189
11901;
1191
1192
1193
1194__END__
32eab2da 1195
1196=head1 NAME
1197
1198SQL::Abstract - Generate SQL from Perl data structures
1199
1200=head1 SYNOPSIS
1201
1202 use SQL::Abstract;
1203
1204 my $sql = SQL::Abstract->new;
1205
1206 my($stmt, @bind) = $sql->select($table, \@fields, \%where, \@order);
1207
1208 my($stmt, @bind) = $sql->insert($table, \%fieldvals || \@values);
1209
1210 my($stmt, @bind) = $sql->update($table, \%fieldvals, \%where);
1211
1212 my($stmt, @bind) = $sql->delete($table, \%where);
1213
1214 # Then, use these in your DBI statements
1215 my $sth = $dbh->prepare($stmt);
1216 $sth->execute(@bind);
1217
1218 # Just generate the WHERE clause
abe72f94 1219 my($stmt, @bind) = $sql->where(\%where, \@order);
32eab2da 1220
1221 # Return values in the same order, for hashed queries
1222 # See PERFORMANCE section for more details
1223 my @bind = $sql->values(\%fieldvals);
1224
1225=head1 DESCRIPTION
1226
1227This module was inspired by the excellent L<DBIx::Abstract>.
1228However, in using that module I found that what I really wanted
1229to do was generate SQL, but still retain complete control over my
1230statement handles and use the DBI interface. So, I set out to
1231create an abstract SQL generation module.
1232
1233While based on the concepts used by L<DBIx::Abstract>, there are
1234several important differences, especially when it comes to WHERE
1235clauses. I have modified the concepts used to make the SQL easier
1236to generate from Perl data structures and, IMO, more intuitive.
1237The underlying idea is for this module to do what you mean, based
1238on the data structures you provide it. The big advantage is that
1239you don't have to modify your code every time your data changes,
1240as this module figures it out.
1241
1242To begin with, an SQL INSERT is as easy as just specifying a hash
1243of C<key=value> pairs:
1244
1245 my %data = (
1246 name => 'Jimbo Bobson',
1247 phone => '123-456-7890',
1248 address => '42 Sister Lane',
1249 city => 'St. Louis',
1250 state => 'Louisiana',
1251 );
1252
1253The SQL can then be generated with this:
1254
1255 my($stmt, @bind) = $sql->insert('people', \%data);
1256
1257Which would give you something like this:
1258
1259 $stmt = "INSERT INTO people
1260 (address, city, name, phone, state)
1261 VALUES (?, ?, ?, ?, ?)";
1262 @bind = ('42 Sister Lane', 'St. Louis', 'Jimbo Bobson',
1263 '123-456-7890', 'Louisiana');
1264
1265These are then used directly in your DBI code:
1266
1267 my $sth = $dbh->prepare($stmt);
1268 $sth->execute(@bind);
1269
96449e8e 1270=head2 Inserting and Updating Arrays
1271
1272If your database has array types (like for example Postgres),
1273activate the special option C<< array_datatypes => 1 >>
1274when creating the C<SQL::Abstract> object.
1275Then you may use an arrayref to insert and update database array types:
1276
1277 my $sql = SQL::Abstract->new(array_datatypes => 1);
1278 my %data = (
1279 planets => [qw/Mercury Venus Earth Mars/]
1280 );
1281
1282 my($stmt, @bind) = $sql->insert('solar_system', \%data);
1283
1284This results in:
1285
1286 $stmt = "INSERT INTO solar_system (planets) VALUES (?)"
1287
1288 @bind = (['Mercury', 'Venus', 'Earth', 'Mars']);
1289
1290
1291=head2 Inserting and Updating SQL
1292
1293In order to apply SQL functions to elements of your C<%data> you may
1294specify a reference to an arrayref for the given hash value. For example,
1295if you need to execute the Oracle C<to_date> function on a value, you can
1296say something like this:
32eab2da 1297
1298 my %data = (
1299 name => 'Bill',
96449e8e 1300 date_entered => \["to_date(?,'MM/DD/YYYY')", "03/02/2003"],
32eab2da 1301 );
1302
1303The first value in the array is the actual SQL. Any other values are
1304optional and would be included in the bind values array. This gives
1305you:
1306
1307 my($stmt, @bind) = $sql->insert('people', \%data);
1308
1309 $stmt = "INSERT INTO people (name, date_entered)
1310 VALUES (?, to_date(?,'MM/DD/YYYY'))";
1311 @bind = ('Bill', '03/02/2003');
1312
1313An UPDATE is just as easy, all you change is the name of the function:
1314
1315 my($stmt, @bind) = $sql->update('people', \%data);
1316
1317Notice that your C<%data> isn't touched; the module will generate
1318the appropriately quirky SQL for you automatically. Usually you'll
1319want to specify a WHERE clause for your UPDATE, though, which is
1320where handling C<%where> hashes comes in handy...
1321
96449e8e 1322=head2 Complex where statements
1323
32eab2da 1324This module can generate pretty complicated WHERE statements
1325easily. For example, simple C<key=value> pairs are taken to mean
1326equality, and if you want to see if a field is within a set
1327of values, you can use an arrayref. Let's say we wanted to
1328SELECT some data based on this criteria:
1329
1330 my %where = (
1331 requestor => 'inna',
1332 worker => ['nwiger', 'rcwe', 'sfz'],
1333 status => { '!=', 'completed' }
1334 );
1335
1336 my($stmt, @bind) = $sql->select('tickets', '*', \%where);
1337
1338The above would give you something like this:
1339
1340 $stmt = "SELECT * FROM tickets WHERE
1341 ( requestor = ? ) AND ( status != ? )
1342 AND ( worker = ? OR worker = ? OR worker = ? )";
1343 @bind = ('inna', 'completed', 'nwiger', 'rcwe', 'sfz');
1344
1345Which you could then use in DBI code like so:
1346
1347 my $sth = $dbh->prepare($stmt);
1348 $sth->execute(@bind);
1349
1350Easy, eh?
1351
1352=head1 FUNCTIONS
1353
1354The functions are simple. There's one for each major SQL operation,
1355and a constructor you use first. The arguments are specified in a
1356similar order to each function (table, then fields, then a where
1357clause) to try and simplify things.
1358
83cab70b 1359
83cab70b 1360
32eab2da 1361
1362=head2 new(option => 'value')
1363
1364The C<new()> function takes a list of options and values, and returns
1365a new B<SQL::Abstract> object which can then be used to generate SQL
1366through the methods below. The options accepted are:
1367
1368=over
1369
1370=item case
1371
1372If set to 'lower', then SQL will be generated in all lowercase. By
1373default SQL is generated in "textbook" case meaning something like:
1374
1375 SELECT a_field FROM a_table WHERE some_field LIKE '%someval%'
1376
96449e8e 1377Any setting other than 'lower' is ignored.
1378
32eab2da 1379=item cmp
1380
1381This determines what the default comparison operator is. By default
1382it is C<=>, meaning that a hash like this:
1383
1384 %where = (name => 'nwiger', email => 'nate@wiger.org');
1385
1386Will generate SQL like this:
1387
1388 WHERE name = 'nwiger' AND email = 'nate@wiger.org'
1389
1390However, you may want loose comparisons by default, so if you set
1391C<cmp> to C<like> you would get SQL such as:
1392
1393 WHERE name like 'nwiger' AND email like 'nate@wiger.org'
1394
1395You can also override the comparsion on an individual basis - see
1396the huge section on L</"WHERE CLAUSES"> at the bottom.
1397
96449e8e 1398=item sqltrue, sqlfalse
1399
1400Expressions for inserting boolean values within SQL statements.
6e0c6552 1401By default these are C<1=1> and C<1=0>. They are used
1402by the special operators C<-in> and C<-not_in> for generating
1403correct SQL even when the argument is an empty array (see below).
96449e8e 1404
32eab2da 1405=item logic
1406
1407This determines the default logical operator for multiple WHERE
7cac25e6 1408statements in arrays or hashes. If absent, the default logic is "or"
1409for arrays, and "and" for hashes. This means that a WHERE
32eab2da 1410array of the form:
1411
1412 @where = (
1413 event_date => {'>=', '2/13/99'},
1414 event_date => {'<=', '4/24/03'},
1415 );
1416
7cac25e6 1417will generate SQL like this:
32eab2da 1418
1419 WHERE event_date >= '2/13/99' OR event_date <= '4/24/03'
1420
1421This is probably not what you want given this query, though (look
1422at the dates). To change the "OR" to an "AND", simply specify:
1423
1424 my $sql = SQL::Abstract->new(logic => 'and');
1425
1426Which will change the above C<WHERE> to:
1427
1428 WHERE event_date >= '2/13/99' AND event_date <= '4/24/03'
1429
96449e8e 1430The logic can also be changed locally by inserting
7cac25e6 1431a modifier in front of an arrayref :
96449e8e 1432
7cac25e6 1433 @where = (-and => [event_date => {'>=', '2/13/99'},
1434 event_date => {'<=', '4/24/03'} ]);
96449e8e 1435
1436See the L</"WHERE CLAUSES"> section for explanations.
1437
32eab2da 1438=item convert
1439
1440This will automatically convert comparisons using the specified SQL
1441function for both column and value. This is mostly used with an argument
1442of C<upper> or C<lower>, so that the SQL will have the effect of
1443case-insensitive "searches". For example, this:
1444
1445 $sql = SQL::Abstract->new(convert => 'upper');
1446 %where = (keywords => 'MaKe iT CAse inSeNSItive');
1447
1448Will turn out the following SQL:
1449
1450 WHERE upper(keywords) like upper('MaKe iT CAse inSeNSItive')
1451
1452The conversion can be C<upper()>, C<lower()>, or any other SQL function
1453that can be applied symmetrically to fields (actually B<SQL::Abstract> does
1454not validate this option; it will just pass through what you specify verbatim).
1455
1456=item bindtype
1457
1458This is a kludge because many databases suck. For example, you can't
1459just bind values using DBI's C<execute()> for Oracle C<CLOB> or C<BLOB> fields.
1460Instead, you have to use C<bind_param()>:
1461
1462 $sth->bind_param(1, 'reg data');
1463 $sth->bind_param(2, $lots, {ora_type => ORA_CLOB});
1464
1465The problem is, B<SQL::Abstract> will normally just return a C<@bind> array,
1466which loses track of which field each slot refers to. Fear not.
1467
1468If you specify C<bindtype> in new, you can determine how C<@bind> is returned.
1469Currently, you can specify either C<normal> (default) or C<columns>. If you
1470specify C<columns>, you will get an array that looks like this:
1471
1472 my $sql = SQL::Abstract->new(bindtype => 'columns');
1473 my($stmt, @bind) = $sql->insert(...);
1474
1475 @bind = (
1476 [ 'column1', 'value1' ],
1477 [ 'column2', 'value2' ],
1478 [ 'column3', 'value3' ],
1479 );
1480
1481You can then iterate through this manually, using DBI's C<bind_param()>.
e3f9dff4 1482
32eab2da 1483 $sth->prepare($stmt);
1484 my $i = 1;
1485 for (@bind) {
1486 my($col, $data) = @$_;
1487 if ($col eq 'details' || $col eq 'comments') {
1488 $sth->bind_param($i, $data, {ora_type => ORA_CLOB});
1489 } elsif ($col eq 'image') {
1490 $sth->bind_param($i, $data, {ora_type => ORA_BLOB});
1491 } else {
1492 $sth->bind_param($i, $data);
1493 }
1494 $i++;
1495 }
1496 $sth->execute; # execute without @bind now
1497
1498Now, why would you still use B<SQL::Abstract> if you have to do this crap?
1499Basically, the advantage is still that you don't have to care which fields
1500are or are not included. You could wrap that above C<for> loop in a simple
1501sub called C<bind_fields()> or something and reuse it repeatedly. You still
1502get a layer of abstraction over manual SQL specification.
1503
deb148a2 1504Note that if you set L</bindtype> to C<columns>, the C<\[$sql, @bind]>
1505construct (see L</Literal SQL with placeholders and bind values (subqueries)>)
1506will expect the bind values in this format.
1507
32eab2da 1508=item quote_char
1509
1510This is the character that a table or column name will be quoted
1511with. By default this is an empty string, but you could set it to
1512the character C<`>, to generate SQL like this:
1513
1514 SELECT `a_field` FROM `a_table` WHERE `some_field` LIKE '%someval%'
1515
96449e8e 1516Alternatively, you can supply an array ref of two items, the first being the left
1517hand quote character, and the second the right hand quote character. For
1518example, you could supply C<['[',']']> for SQL Server 2000 compliant quotes
1519that generates SQL like this:
1520
1521 SELECT [a_field] FROM [a_table] WHERE [some_field] LIKE '%someval%'
1522
1523Quoting is useful if you have tables or columns names that are reserved
1524words in your database's SQL dialect.
32eab2da 1525
1526=item name_sep
1527
1528This is the character that separates a table and column name. It is
1529necessary to specify this when the C<quote_char> option is selected,
1530so that tables and column names can be individually quoted like this:
1531
1532 SELECT `table`.`one_field` FROM `table` WHERE `table`.`other_field` = 1
1533
96449e8e 1534=item array_datatypes
32eab2da 1535
96449e8e 1536When this option is true, arrayrefs in INSERT or UPDATE are
1537interpreted as array datatypes and are passed directly
1538to the DBI layer.
1539When this option is false, arrayrefs are interpreted
1540as literal SQL, just like refs to arrayrefs
1541(but this behavior is for backwards compatibility; when writing
1542new queries, use the "reference to arrayref" syntax
1543for literal SQL).
32eab2da 1544
32eab2da 1545
96449e8e 1546=item special_ops
32eab2da 1547
96449e8e 1548Takes a reference to a list of "special operators"
1549to extend the syntax understood by L<SQL::Abstract>.
1550See section L</"SPECIAL OPERATORS"> for details.
32eab2da 1551
32eab2da 1552
32eab2da 1553
96449e8e 1554=back
32eab2da 1555
1556=head2 insert($table, \@values || \%fieldvals)
1557
1558This is the simplest function. You simply give it a table name
1559and either an arrayref of values or hashref of field/value pairs.
1560It returns an SQL INSERT statement and a list of bind values.
96449e8e 1561See the sections on L</"Inserting and Updating Arrays"> and
1562L</"Inserting and Updating SQL"> for information on how to insert
1563with those data types.
32eab2da 1564
1565=head2 update($table, \%fieldvals, \%where)
1566
1567This takes a table, hashref of field/value pairs, and an optional
86298391 1568hashref L<WHERE clause|/WHERE CLAUSES>. It returns an SQL UPDATE function and a list
32eab2da 1569of bind values.
96449e8e 1570See the sections on L</"Inserting and Updating Arrays"> and
1571L</"Inserting and Updating SQL"> for information on how to insert
1572with those data types.
32eab2da 1573
96449e8e 1574=head2 select($source, $fields, $where, $order)
32eab2da 1575
96449e8e 1576This returns a SQL SELECT statement and associated list of bind values, as
1577specified by the arguments :
32eab2da 1578
96449e8e 1579=over
32eab2da 1580
96449e8e 1581=item $source
32eab2da 1582
96449e8e 1583Specification of the 'FROM' part of the statement.
1584The argument can be either a plain scalar (interpreted as a table
1585name, will be quoted), or an arrayref (interpreted as a list
1586of table names, joined by commas, quoted), or a scalarref
1587(literal table name, not quoted), or a ref to an arrayref
1588(list of literal table names, joined by commas, not quoted).
32eab2da 1589
96449e8e 1590=item $fields
32eab2da 1591
96449e8e 1592Specification of the list of fields to retrieve from
1593the source.
1594The argument can be either an arrayref (interpreted as a list
1595of field names, will be joined by commas and quoted), or a
1596plain scalar (literal SQL, not quoted).
1597Please observe that this API is not as flexible as for
e3f9dff4 1598the first argument C<$table>, for backwards compatibility reasons.
32eab2da 1599
96449e8e 1600=item $where
32eab2da 1601
96449e8e 1602Optional argument to specify the WHERE part of the query.
1603The argument is most often a hashref, but can also be
1604an arrayref or plain scalar --
1605see section L<WHERE clause|/"WHERE CLAUSES"> for details.
32eab2da 1606
96449e8e 1607=item $order
32eab2da 1608
96449e8e 1609Optional argument to specify the ORDER BY part of the query.
1610The argument can be a scalar, a hashref or an arrayref
1611-- see section L<ORDER BY clause|/"ORDER BY CLAUSES">
1612for details.
32eab2da 1613
96449e8e 1614=back
32eab2da 1615
32eab2da 1616
1617=head2 delete($table, \%where)
1618
86298391 1619This takes a table name and optional hashref L<WHERE clause|/WHERE CLAUSES>.
32eab2da 1620It returns an SQL DELETE statement and list of bind values.
1621
32eab2da 1622=head2 where(\%where, \@order)
1623
1624This is used to generate just the WHERE clause. For example,
1625if you have an arbitrary data structure and know what the
1626rest of your SQL is going to look like, but want an easy way
1627to produce a WHERE clause, use this. It returns an SQL WHERE
1628clause and list of bind values.
1629
32eab2da 1630
1631=head2 values(\%data)
1632
1633This just returns the values from the hash C<%data>, in the same
1634order that would be returned from any of the other above queries.
1635Using this allows you to markedly speed up your queries if you
1636are affecting lots of rows. See below under the L</"PERFORMANCE"> section.
1637
32eab2da 1638=head2 generate($any, 'number', $of, \@data, $struct, \%types)
1639
1640Warning: This is an experimental method and subject to change.
1641
1642This returns arbitrarily generated SQL. It's a really basic shortcut.
1643It will return two different things, depending on return context:
1644
1645 my($stmt, @bind) = $sql->generate('create table', \$table, \@fields);
1646 my $stmt_and_val = $sql->generate('create table', \$table, \@fields);
1647
1648These would return the following:
1649
1650 # First calling form
1651 $stmt = "CREATE TABLE test (?, ?)";
1652 @bind = (field1, field2);
1653
1654 # Second calling form
1655 $stmt_and_val = "CREATE TABLE test (field1, field2)";
1656
1657Depending on what you're trying to do, it's up to you to choose the correct
1658format. In this example, the second form is what you would want.
1659
1660By the same token:
1661
1662 $sql->generate('alter session', { nls_date_format => 'MM/YY' });
1663
1664Might give you:
1665
1666 ALTER SESSION SET nls_date_format = 'MM/YY'
1667
1668You get the idea. Strings get their case twiddled, but everything
1669else remains verbatim.
1670
32eab2da 1671
32eab2da 1672
32eab2da 1673
1674=head1 WHERE CLAUSES
1675
96449e8e 1676=head2 Introduction
1677
32eab2da 1678This module uses a variation on the idea from L<DBIx::Abstract>. It
1679is B<NOT>, repeat I<not> 100% compatible. B<The main logic of this
1680module is that things in arrays are OR'ed, and things in hashes
1681are AND'ed.>
1682
1683The easiest way to explain is to show lots of examples. After
1684each C<%where> hash shown, it is assumed you used:
1685
1686 my($stmt, @bind) = $sql->where(\%where);
1687
1688However, note that the C<%where> hash can be used directly in any
1689of the other functions as well, as described above.
1690
96449e8e 1691=head2 Key-value pairs
1692
32eab2da 1693So, let's get started. To begin, a simple hash:
1694
1695 my %where = (
1696 user => 'nwiger',
1697 status => 'completed'
1698 );
1699
1700Is converted to SQL C<key = val> statements:
1701
1702 $stmt = "WHERE user = ? AND status = ?";
1703 @bind = ('nwiger', 'completed');
1704
1705One common thing I end up doing is having a list of values that
1706a field can be in. To do this, simply specify a list inside of
1707an arrayref:
1708
1709 my %where = (
1710 user => 'nwiger',
1711 status => ['assigned', 'in-progress', 'pending'];
1712 );
1713
1714This simple code will create the following:
1715
1716 $stmt = "WHERE user = ? AND ( status = ? OR status = ? OR status = ? )";
1717 @bind = ('nwiger', 'assigned', 'in-progress', 'pending');
1718
7cac25e6 1719A field associated to an empty arrayref will be considered a
1720logical false and will generate 0=1.
8a68b5be 1721
6e0c6552 1722=head2 Specific comparison operators
96449e8e 1723
32eab2da 1724If you want to specify a different type of operator for your comparison,
1725you can use a hashref for a given column:
1726
1727 my %where = (
1728 user => 'nwiger',
1729 status => { '!=', 'completed' }
1730 );
1731
1732Which would generate:
1733
1734 $stmt = "WHERE user = ? AND status != ?";
1735 @bind = ('nwiger', 'completed');
1736
1737To test against multiple values, just enclose the values in an arrayref:
1738
96449e8e 1739 status => { '=', ['assigned', 'in-progress', 'pending'] };
1740
f2d5020d 1741Which would give you:
96449e8e 1742
1743 "WHERE status = ? OR status = ? OR status = ?"
1744
1745
1746The hashref can also contain multiple pairs, in which case it is expanded
32eab2da 1747into an C<AND> of its elements:
1748
1749 my %where = (
1750 user => 'nwiger',
1751 status => { '!=', 'completed', -not_like => 'pending%' }
1752 );
1753
1754 # Or more dynamically, like from a form
1755 $where{user} = 'nwiger';
1756 $where{status}{'!='} = 'completed';
1757 $where{status}{'-not_like'} = 'pending%';
1758
1759 # Both generate this
1760 $stmt = "WHERE user = ? AND status != ? AND status NOT LIKE ?";
1761 @bind = ('nwiger', 'completed', 'pending%');
1762
96449e8e 1763
32eab2da 1764To get an OR instead, you can combine it with the arrayref idea:
1765
1766 my %where => (
1767 user => 'nwiger',
1768 priority => [ {'=', 2}, {'!=', 1} ]
1769 );
1770
1771Which would generate:
1772
1773 $stmt = "WHERE user = ? AND priority = ? OR priority != ?";
1774 @bind = ('nwiger', '2', '1');
1775
44b9e502 1776If you want to include literal SQL (with or without bind values), just use a
1777scalar reference or array reference as the value:
1778
1779 my %where = (
1780 date_entered => { '>' => \["to_date(?, 'MM/DD/YYYY')", "11/26/2008"] },
1781 date_expires => { '<' => \"now()" }
1782 );
1783
1784Which would generate:
1785
1786 $stmt = "WHERE date_entered > "to_date(?, 'MM/DD/YYYY') AND date_expires < now()";
1787 @bind = ('11/26/2008');
1788
96449e8e 1789
1790=head2 Logic and nesting operators
1791
1792In the example above,
1793there is a subtle trap if you want to say something like
32eab2da 1794this (notice the C<AND>):
1795
1796 WHERE priority != ? AND priority != ?
1797
1798Because, in Perl you I<can't> do this:
1799
1800 priority => { '!=', 2, '!=', 1 }
1801
1802As the second C<!=> key will obliterate the first. The solution
1803is to use the special C<-modifier> form inside an arrayref:
1804
96449e8e 1805 priority => [ -and => {'!=', 2},
1806 {'!=', 1} ]
1807
32eab2da 1808
1809Normally, these would be joined by C<OR>, but the modifier tells it
1810to use C<AND> instead. (Hint: You can use this in conjunction with the
1811C<logic> option to C<new()> in order to change the way your queries
1812work by default.) B<Important:> Note that the C<-modifier> goes
1813B<INSIDE> the arrayref, as an extra first element. This will
1814B<NOT> do what you think it might:
1815
1816 priority => -and => [{'!=', 2}, {'!=', 1}] # WRONG!
1817
1818Here is a quick list of equivalencies, since there is some overlap:
1819
1820 # Same
1821 status => {'!=', 'completed', 'not like', 'pending%' }
1822 status => [ -and => {'!=', 'completed'}, {'not like', 'pending%'}]
1823
1824 # Same
1825 status => {'=', ['assigned', 'in-progress']}
1826 status => [ -or => {'=', 'assigned'}, {'=', 'in-progress'}]
1827 status => [ {'=', 'assigned'}, {'=', 'in-progress'} ]
1828
e3f9dff4 1829
1830
96449e8e 1831=head2 Special operators : IN, BETWEEN, etc.
1832
32eab2da 1833You can also use the hashref format to compare a list of fields using the
1834C<IN> comparison operator, by specifying the list as an arrayref:
1835
1836 my %where = (
1837 status => 'completed',
1838 reportid => { -in => [567, 2335, 2] }
1839 );
1840
1841Which would generate:
1842
1843 $stmt = "WHERE status = ? AND reportid IN (?,?,?)";
1844 @bind = ('completed', '567', '2335', '2');
1845
96449e8e 1846The reverse operator C<-not_in> generates SQL C<NOT IN> and is used in
1847the same way.
1848
6e0c6552 1849If the argument to C<-in> is an empty array, 'sqlfalse' is generated
1850(by default : C<1=0>). Similarly, C<< -not_in => [] >> generates
1851'sqltrue' (by default : C<1=1>).
1852
1853
1854
96449e8e 1855Another pair of operators is C<-between> and C<-not_between>,
1856used with an arrayref of two values:
32eab2da 1857
1858 my %where = (
1859 user => 'nwiger',
1860 completion_date => {
1861 -not_between => ['2002-10-01', '2003-02-06']
1862 }
1863 );
1864
1865Would give you:
1866
1867 WHERE user = ? AND completion_date NOT BETWEEN ( ? AND ? )
1868
96449e8e 1869These are the two builtin "special operators"; but the
1870list can be expanded : see section L</"SPECIAL OPERATORS"> below.
1871
107b72f1 1872=head2 Nested conditions, -and/-or prefixes
96449e8e 1873
32eab2da 1874So far, we've seen how multiple conditions are joined with a top-level
1875C<AND>. We can change this by putting the different conditions we want in
1876hashes and then putting those hashes in an array. For example:
1877
1878 my @where = (
1879 {
1880 user => 'nwiger',
1881 status => { -like => ['pending%', 'dispatched'] },
1882 },
1883 {
1884 user => 'robot',
1885 status => 'unassigned',
1886 }
1887 );
1888
1889This data structure would create the following:
1890
1891 $stmt = "WHERE ( user = ? AND ( status LIKE ? OR status LIKE ? ) )
1892 OR ( user = ? AND status = ? ) )";
1893 @bind = ('nwiger', 'pending', 'dispatched', 'robot', 'unassigned');
1894
107b72f1 1895
01a01e57 1896There is also a special C<-nest>
107b72f1 1897operator which adds an additional set of parens, to create a subquery.
1898For example, to get something like this:
1899
1900 $stmt = "WHERE user = ? AND ( workhrs > ? OR geo = ? )";
1901 @bind = ('nwiger', '20', 'ASIA');
1902
1903You would do:
1904
1905 my %where = (
1906 user => 'nwiger',
01a01e57 1907 -nest => [ workhrs => {'>', 20}, geo => 'ASIA' ],
107b72f1 1908 );
1909
1910
1911Finally, clauses in hashrefs or arrayrefs can be
7cac25e6 1912prefixed with an C<-and> or C<-or> to change the logic
1913inside :
32eab2da 1914
1915 my @where = (
1916 -and => [
1917 user => 'nwiger',
01a01e57 1918 -nest => [
7cac25e6 1919 -and => [workhrs => {'>', 20}, geo => 'ASIA' ],
1920 -and => [workhrs => {'<', 50}, geo => 'EURO' ]
32eab2da 1921 ],
1922 ],
1923 );
1924
1925That would yield:
1926
1927 WHERE ( user = ? AND
1928 ( ( workhrs > ? AND geo = ? )
1929 OR ( workhrs < ? AND geo = ? ) ) )
1930
107b72f1 1931
1932=head2 Algebraic inconsistency, for historical reasons
1933
7cac25e6 1934C<Important note>: when connecting several conditions, the C<-and->|C<-or>
1935operator goes C<outside> of the nested structure; whereas when connecting
1936several constraints on one column, the C<-and> operator goes
1937C<inside> the arrayref. Here is an example combining both features :
1938
1939 my @where = (
1940 -and => [a => 1, b => 2],
1941 -or => [c => 3, d => 4],
1942 e => [-and => {-like => 'foo%'}, {-like => '%bar'} ]
1943 )
1944
1945yielding
1946
1947 WHERE ( ( ( a = ? AND b = ? )
1948 OR ( c = ? OR d = ? )
1949 OR ( e LIKE ? AND e LIKE ? ) ) )
1950
107b72f1 1951This difference in syntax is unfortunate but must be preserved for
1952historical reasons. So be careful : the two examples below would
1953seem algebraically equivalent, but they are not
1954
1955 {col => [-and => {-like => 'foo%'}, {-like => '%bar'}]}
1956 # yields : WHERE ( ( col LIKE ? AND col LIKE ? ) )
1957
1958 [-and => {col => {-like => 'foo%'}, {col => {-like => '%bar'}}]]
1959 # yields : WHERE ( ( col LIKE ? OR col LIKE ? ) )
1960
7cac25e6 1961
96449e8e 1962=head2 Literal SQL
1963
32eab2da 1964Finally, sometimes only literal SQL will do. If you want to include
1965literal SQL verbatim, you can specify it as a scalar reference, namely:
1966
1967 my $inn = 'is Not Null';
1968 my %where = (
1969 priority => { '<', 2 },
1970 requestor => \$inn
1971 );
1972
1973This would create:
1974
1975 $stmt = "WHERE priority < ? AND requestor is Not Null";
1976 @bind = ('2');
1977
1978Note that in this example, you only get one bind parameter back, since
1979the verbatim SQL is passed as part of the statement.
1980
1981Of course, just to prove a point, the above can also be accomplished
1982with this:
1983
1984 my %where = (
1985 priority => { '<', 2 },
1986 requestor => { '!=', undef },
1987 );
1988
96449e8e 1989
32eab2da 1990TMTOWTDI.
1991
96449e8e 1992Conditions on boolean columns can be expressed in the
1993same way, passing a reference to an empty string :
1994
1995 my %where = (
1996 priority => { '<', 2 },
1997 is_ready => \"";
1998 );
1999
2000which yields
2001
2002 $stmt = "WHERE priority < ? AND is_ready";
2003 @bind = ('2');
2004
2005
2006=head2 Literal SQL with placeholders and bind values (subqueries)
2007
2008If the literal SQL to be inserted has placeholders and bind values,
2009use a reference to an arrayref (yes this is a double reference --
2010not so common, but perfectly legal Perl). For example, to find a date
2011in Postgres you can use something like this:
2012
2013 my %where = (
2014 date_column => \[q/= date '2008-09-30' - ?::integer/, 10/]
2015 )
2016
2017This would create:
2018
d2a8fe1a 2019 $stmt = "WHERE ( date_column = date '2008-09-30' - ?::integer )"
96449e8e 2020 @bind = ('10');
2021
deb148a2 2022Note that you must pass the bind values in the same format as they are returned
62552e7d 2023by L</where>. That means that if you set L</bindtype> to C<columns>, you must
26f2dca5 2024provide the bind values in the C<< [ column_meta => value ] >> format, where
2025C<column_meta> is an opaque scalar value; most commonly the column name, but
62552e7d 2026you can use any scalar value (including references and blessed references),
2027L<SQL::Abstract> will simply pass it through intact. So if C<bindtype> is set
2028to C<columns> the above example will look like:
deb148a2 2029
2030 my %where = (
2031 date_column => \[q/= date '2008-09-30' - ?::integer/, [ dummy => 10 ]/]
2032 )
96449e8e 2033
2034Literal SQL is especially useful for nesting parenthesized clauses in the
2035main SQL query. Here is a first example :
2036
2037 my ($sub_stmt, @sub_bind) = ("SELECT c1 FROM t1 WHERE c2 < ? AND c3 LIKE ?",
2038 100, "foo%");
2039 my %where = (
2040 foo => 1234,
2041 bar => \["IN ($sub_stmt)" => @sub_bind],
2042 );
2043
2044This yields :
2045
2046 $stmt = "WHERE (foo = ? AND bar IN (SELECT c1 FROM t1
2047 WHERE c2 < ? AND c3 LIKE ?))";
2048 @bind = (1234, 100, "foo%");
2049
2050Other subquery operators, like for example C<"E<gt> ALL"> or C<"NOT IN">,
2051are expressed in the same way. Of course the C<$sub_stmt> and
2052its associated bind values can be generated through a former call
2053to C<select()> :
2054
2055 my ($sub_stmt, @sub_bind)
2056 = $sql->select("t1", "c1", {c2 => {"<" => 100},
2057 c3 => {-like => "foo%"}});
2058 my %where = (
2059 foo => 1234,
2060 bar => \["> ALL ($sub_stmt)" => @sub_bind],
2061 );
2062
2063In the examples above, the subquery was used as an operator on a column;
2064but the same principle also applies for a clause within the main C<%where>
2065hash, like an EXISTS subquery :
2066
2067 my ($sub_stmt, @sub_bind)
2068 = $sql->select("t1", "*", {c1 => 1, c2 => \"> t0.c0"});
2069 my %where = (
2070 foo => 1234,
01a01e57 2071 -nest => \["EXISTS ($sub_stmt)" => @sub_bind],
96449e8e 2072 );
2073
2074which yields
2075
2076 $stmt = "WHERE (foo = ? AND EXISTS (SELECT * FROM t1
2077 WHERE c1 = ? AND c2 > t0.c0))";
2078 @bind = (1234, 1);
2079
2080
2081Observe that the condition on C<c2> in the subquery refers to
2082column C<t0.c0> of the main query : this is I<not> a bind
2083value, so we have to express it through a scalar ref.
2084Writing C<< c2 => {">" => "t0.c0"} >> would have generated
2085C<< c2 > ? >> with bind value C<"t0.c0"> ... not exactly
2086what we wanted here.
2087
2088Another use of the subquery technique is when some SQL clauses need
2089parentheses, as it often occurs with some proprietary SQL extensions
2090like for example fulltext expressions, geospatial expressions,
2091NATIVE clauses, etc. Here is an example of a fulltext query in MySQL :
2092
2093 my %where = (
01a01e57 2094 -nest => \["MATCH (col1, col2) AGAINST (?)" => qw/apples/]
96449e8e 2095 );
2096
2097Finally, here is an example where a subquery is used
2098for expressing unary negation:
2099
2100 my ($sub_stmt, @sub_bind)
2101 = $sql->where({age => [{"<" => 10}, {">" => 20}]});
2102 $sub_stmt =~ s/^ where //i; # don't want "WHERE" in the subclause
2103 my %where = (
2104 lname => {like => '%son%'},
01a01e57 2105 -nest => \["NOT ($sub_stmt)" => @sub_bind],
96449e8e 2106 );
2107
2108This yields
2109
2110 $stmt = "lname LIKE ? AND NOT ( age < ? OR age > ? )"
2111 @bind = ('%son%', 10, 20)
2112
2113
2114
2115=head2 Conclusion
2116
32eab2da 2117These pages could go on for a while, since the nesting of the data
2118structures this module can handle are pretty much unlimited (the
2119module implements the C<WHERE> expansion as a recursive function
2120internally). Your best bet is to "play around" with the module a
2121little to see how the data structures behave, and choose the best
2122format for your data based on that.
2123
2124And of course, all the values above will probably be replaced with
2125variables gotten from forms or the command line. After all, if you
2126knew everything ahead of time, you wouldn't have to worry about
2127dynamically-generating SQL and could just hardwire it into your
2128script.
2129
96449e8e 2130
2131
2132
86298391 2133=head1 ORDER BY CLAUSES
2134
2135Some functions take an order by clause. This can either be a scalar (just a
2136column name,) a hash of C<< { -desc => 'col' } >> or C<< { -asc => 'col' } >>,
1cfa1db3 2137or an array of either of the two previous forms. Examples:
2138
952f9e2d 2139 Given | Will Generate
1cfa1db3 2140 ----------------------------------------------------------
952f9e2d 2141 |
2142 \'colA DESC' | ORDER BY colA DESC
2143 |
2144 'colA' | ORDER BY colA
2145 |
2146 [qw/colA colB/] | ORDER BY colA, colB
2147 |
2148 {-asc => 'colA'} | ORDER BY colA ASC
2149 |
2150 {-desc => 'colB'} | ORDER BY colB DESC
2151 |
2152 ['colA', {-asc => 'colB'}] | ORDER BY colA, colB ASC
2153 |
2154 { -asc => [qw/colA colB] } | ORDER BY colA ASC, colB ASC
2155 |
2156 [ |
2157 { -asc => 'colA' }, | ORDER BY colA ASC, colB DESC,
2158 { -desc => [qw/colB/], | colC ASC, colD ASC
2159 { -asc => [qw/colC colD/],|
2160 ] |
2161 ===========================================================
86298391 2162
96449e8e 2163
2164
2165=head1 SPECIAL OPERATORS
2166
e3f9dff4 2167 my $sqlmaker = SQL::Abstract->new(special_ops => [
3a2e1a5e 2168 {
2169 regex => qr/.../,
e3f9dff4 2170 handler => sub {
2171 my ($self, $field, $op, $arg) = @_;
2172 ...
3a2e1a5e 2173 },
2174 },
2175 {
2176 regex => qr/.../,
2177 handler => 'method_name',
e3f9dff4 2178 },
2179 ]);
2180
2181A "special operator" is a SQL syntactic clause that can be
2182applied to a field, instead of a usual binary operator.
2183For example :
2184
2185 WHERE field IN (?, ?, ?)
2186 WHERE field BETWEEN ? AND ?
2187 WHERE MATCH(field) AGAINST (?, ?)
96449e8e 2188
e3f9dff4 2189Special operators IN and BETWEEN are fairly standard and therefore
3a2e1a5e 2190are builtin within C<SQL::Abstract> (as the overridable methods
2191C<_where_field_IN> and C<_where_field_BETWEEN>). For other operators,
2192like the MATCH .. AGAINST example above which is specific to MySQL,
2193you can write your own operator handlers - supply a C<special_ops>
2194argument to the C<new> method. That argument takes an arrayref of
2195operator definitions; each operator definition is a hashref with two
2196entries:
96449e8e 2197
e3f9dff4 2198=over
2199
2200=item regex
2201
2202the regular expression to match the operator
96449e8e 2203
e3f9dff4 2204=item handler
2205
3a2e1a5e 2206Either a coderef or a plain scalar method name. In both cases
2207the expected return is C<< ($sql, @bind) >>.
2208
2209When supplied with a method name, it is simply called on the
2210L<SQL::Abstract/> object as:
2211
2212 $self->$method_name ($field, $op, $arg)
2213
2214 Where:
2215
2216 $op is the part that matched the handler regex
2217 $field is the LHS of the operator
2218 $arg is the RHS
2219
2220When supplied with a coderef, it is called as:
2221
2222 $coderef->($self, $field, $op, $arg)
2223
e3f9dff4 2224
2225=back
2226
2227For example, here is an implementation
2228of the MATCH .. AGAINST syntax for MySQL
2229
2230 my $sqlmaker = SQL::Abstract->new(special_ops => [
2231
2232 # special op for MySql MATCH (field) AGAINST(word1, word2, ...)
2233 {regex => qr/^match$/i,
2234 handler => sub {
2235 my ($self, $field, $op, $arg) = @_;
2236 $arg = [$arg] if not ref $arg;
2237 my $label = $self->_quote($field);
2238 my ($placeholder) = $self->_convert('?');
2239 my $placeholders = join ", ", (($placeholder) x @$arg);
2240 my $sql = $self->_sqlcase('match') . " ($label) "
2241 . $self->_sqlcase('against') . " ($placeholders) ";
2242 my @bind = $self->_bindtype($field, @$arg);
2243 return ($sql, @bind);
2244 }
2245 },
2246
2247 ]);
96449e8e 2248
2249
32eab2da 2250=head1 PERFORMANCE
2251
2252Thanks to some benchmarking by Mark Stosberg, it turns out that
2253this module is many orders of magnitude faster than using C<DBIx::Abstract>.
2254I must admit this wasn't an intentional design issue, but it's a
2255byproduct of the fact that you get to control your C<DBI> handles
2256yourself.
2257
2258To maximize performance, use a code snippet like the following:
2259
2260 # prepare a statement handle using the first row
2261 # and then reuse it for the rest of the rows
2262 my($sth, $stmt);
2263 for my $href (@array_of_hashrefs) {
2264 $stmt ||= $sql->insert('table', $href);
2265 $sth ||= $dbh->prepare($stmt);
2266 $sth->execute($sql->values($href));
2267 }
2268
2269The reason this works is because the keys in your C<$href> are sorted
2270internally by B<SQL::Abstract>. Thus, as long as your data retains
2271the same structure, you only have to generate the SQL the first time
2272around. On subsequent queries, simply use the C<values> function provided
2273by this module to return your values in the correct order.
2274
96449e8e 2275
32eab2da 2276=head1 FORMBUILDER
2277
2278If you use my C<CGI::FormBuilder> module at all, you'll hopefully
2279really like this part (I do, at least). Building up a complex query
2280can be as simple as the following:
2281
2282 #!/usr/bin/perl
2283
2284 use CGI::FormBuilder;
2285 use SQL::Abstract;
2286
2287 my $form = CGI::FormBuilder->new(...);
2288 my $sql = SQL::Abstract->new;
2289
2290 if ($form->submitted) {
2291 my $field = $form->field;
2292 my $id = delete $field->{id};
2293 my($stmt, @bind) = $sql->update('table', $field, {id => $id});
2294 }
2295
2296Of course, you would still have to connect using C<DBI> to run the
2297query, but the point is that if you make your form look like your
2298table, the actual query script can be extremely simplistic.
2299
2300If you're B<REALLY> lazy (I am), check out C<HTML::QuickTable> for
2301a fast interface to returning and formatting data. I frequently
2302use these three modules together to write complex database query
2303apps in under 50 lines.
2304
32eab2da 2305
96449e8e 2306=head1 CHANGES
2307
2308Version 1.50 was a major internal refactoring of C<SQL::Abstract>.
2309Great care has been taken to preserve the I<published> behavior
2310documented in previous versions in the 1.* family; however,
2311some features that were previously undocumented, or behaved
2312differently from the documentation, had to be changed in order
2313to clarify the semantics. Hence, client code that was relying
2314on some dark areas of C<SQL::Abstract> v1.*
2315B<might behave differently> in v1.50.
32eab2da 2316
d2a8fe1a 2317The main changes are :
2318
96449e8e 2319=over
32eab2da 2320
96449e8e 2321=item *
32eab2da 2322
96449e8e 2323support for literal SQL through the C<< \ [$sql, bind] >> syntax.
2324
2325=item *
2326
145fbfc8 2327support for the { operator => \"..." } construct (to embed literal SQL)
2328
2329=item *
2330
9c37b9c0 2331support for the { operator => \["...", @bind] } construct (to embed literal SQL with bind values)
2332
2333=item *
2334
96449e8e 2335optional support for L<array datatypes|/"Inserting and Updating Arrays">
2336
2337=item *
2338
2339defensive programming : check arguments
2340
2341=item *
2342
2343fixed bug with global logic, which was previously implemented
7cac25e6 2344through global variables yielding side-effects. Prior versions would
96449e8e 2345interpret C<< [ {cond1, cond2}, [cond3, cond4] ] >>
2346as C<< "(cond1 AND cond2) OR (cond3 AND cond4)" >>.
2347Now this is interpreted
2348as C<< "(cond1 AND cond2) OR (cond3 OR cond4)" >>.
2349
96449e8e 2350
2351=item *
2352
2353fixed semantics of _bindtype on array args
2354
2355=item *
2356
2357dropped the C<_anoncopy> of the %where tree. No longer necessary,
2358we just avoid shifting arrays within that tree.
2359
2360=item *
2361
2362dropped the C<_modlogic> function
2363
2364=back
32eab2da 2365
32eab2da 2366
32eab2da 2367
2368=head1 ACKNOWLEDGEMENTS
2369
2370There are a number of individuals that have really helped out with
2371this module. Unfortunately, most of them submitted bugs via CPAN
2372so I have no idea who they are! But the people I do know are:
2373
86298391 2374 Ash Berlin (order_by hash term support)
b643abe1 2375 Matt Trout (DBIx::Class support)
32eab2da 2376 Mark Stosberg (benchmarking)
2377 Chas Owens (initial "IN" operator support)
2378 Philip Collins (per-field SQL functions)
2379 Eric Kolve (hashref "AND" support)
2380 Mike Fragassi (enhancements to "BETWEEN" and "LIKE")
2381 Dan Kubb (support for "quote_char" and "name_sep")
f5aab26e 2382 Guillermo Roditi (patch to cleanup "IN" and "BETWEEN", fix and tests for _order_by)
01a01e57 2383 Laurent Dami (internal refactoring, multiple -nest, extensible list of special operators, literal SQL)
dbdf7648 2384 Norbert Buchmuller (support for literal SQL in hashpair, misc. fixes & tests)
e96c510a 2385 Peter Rabbitson (rewrite of SQLA::Test, misc. fixes & tests)
32eab2da 2386
2387Thanks!
2388
32eab2da 2389=head1 SEE ALSO
2390
86298391 2391L<DBIx::Class>, L<DBIx::Abstract>, L<CGI::FormBuilder>, L<HTML::QuickTable>.
32eab2da 2392
32eab2da 2393=head1 AUTHOR
2394
b643abe1 2395Copyright (c) 2001-2007 Nathan Wiger <nwiger@cpan.org>. All Rights Reserved.
2396
2397This module is actively maintained by Matt Trout <mst@shadowcatsystems.co.uk>
32eab2da 2398
abe72f94 2399For support, your best bet is to try the C<DBIx::Class> users mailing list.
2400While not an official support venue, C<DBIx::Class> makes heavy use of
2401C<SQL::Abstract>, and as such list members there are very familiar with
2402how to create queries.
2403
0d067ded 2404=head1 LICENSE
2405
32eab2da 2406This module is free software; you may copy this under the terms of
2407the GNU General Public License, or the Artistic License, copies of
2408which should have accompanied your Perl kit.
2409
2410=cut
2411