Fix for _order_by with bind values - will not work on DBIC - needs matching changes...
[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
54871ee9 18our $VERSION = '1.55';
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
f267b646 864 my (@sql, @bind);
865 for my $c ($self->_order_by_chunks ($val)) {
96449e8e 866
96449e8e 867
96449e8e 868
f267b646 869 $self->_SWITCH_refkind ($c, {
870 SCALAR => sub {
871 push @sql, $c
872 },
873 ARRAYREF => sub {
874 my ($s, @b) = @$c;
875 push @sql, $s;
876 push @bind, @b;
877 },
878 });
879 }
880
881 my $sql = join ', ', map { $_ . ' ' . $self->_sqlcase($direction) } @sql;
96449e8e 882
f267b646 883 return [$sql, @bind];
884 },
885 });
886}
96449e8e 887
888
889#======================================================================
890# DATASOURCE (FOR NOW, JUST PLAIN TABLE OR LIST OF TABLES)
891#======================================================================
892
893sub _table {
894 my $self = shift;
895 my $from = shift;
896 $self->_SWITCH_refkind($from, {
897 ARRAYREF => sub {join ', ', map { $self->_quote($_) } @$from;},
898 SCALAR => sub {$self->_quote($from)},
899 SCALARREF => sub {$$from},
900 ARRAYREFREF => sub {join ', ', @$from;},
901 });
902}
903
904
905#======================================================================
906# UTILITY FUNCTIONS
907#======================================================================
908
909sub _quote {
910 my $self = shift;
911 my $label = shift;
912
913 $label or puke "can't quote an empty label";
914
915 # left and right quote characters
916 my ($ql, $qr, @other) = $self->_SWITCH_refkind($self->{quote_char}, {
917 SCALAR => sub {($self->{quote_char}, $self->{quote_char})},
918 ARRAYREF => sub {@{$self->{quote_char}}},
919 UNDEF => sub {()},
920 });
921 not @other
922 or puke "quote_char must be an arrayref of 2 values";
923
924 # no quoting if no quoting chars
925 $ql or return $label;
926
927 # no quoting for literal SQL
928 return $$label if ref($label) eq 'SCALAR';
929
930 # separate table / column (if applicable)
931 my $sep = $self->{name_sep} || '';
932 my @to_quote = $sep ? split /\Q$sep\E/, $label : ($label);
933
934 # do the quoting, except for "*" or for `table`.*
935 my @quoted = map { $_ eq '*' ? $_: $ql.$_.$qr} @to_quote;
936
937 # reassemble and return.
938 return join $sep, @quoted;
939}
940
941
942# Conversion, if applicable
943sub _convert ($) {
944 my ($self, $arg) = @_;
945
946# LDNOTE : modified the previous implementation below because
947# it was not consistent : the first "return" is always an array,
948# the second "return" is context-dependent. Anyway, _convert
949# seems always used with just a single argument, so make it a
950# scalar function.
951# return @_ unless $self->{convert};
952# my $conv = $self->_sqlcase($self->{convert});
953# my @ret = map { $conv.'('.$_.')' } @_;
954# return wantarray ? @ret : $ret[0];
955 if ($self->{convert}) {
956 my $conv = $self->_sqlcase($self->{convert});
957 $arg = $conv.'('.$arg.')';
958 }
959 return $arg;
960}
961
962# And bindtype
963sub _bindtype (@) {
964 my $self = shift;
965 my($col, @vals) = @_;
966
967 #LDNOTE : changed original implementation below because it did not make
968 # sense when bindtype eq 'columns' and @vals > 1.
969# return $self->{bindtype} eq 'columns' ? [ $col, @vals ] : @vals;
970
971 return $self->{bindtype} eq 'columns' ? map {[$col, $_]} @vals : @vals;
972}
973
fe3ae272 974# Dies if any element of @bind is not in [colname => value] format
975# if bindtype is 'columns'.
976sub _assert_bindval_matches_bindtype {
977 my ($self, @bind) = @_;
978
979 if ($self->{bindtype} eq 'columns') {
980 foreach my $val (@bind) {
981 if (!defined $val || ref($val) ne 'ARRAY' || @$val != 2) {
982 die "bindtype 'columns' selected, you need to pass: [column_name => bind_value]"
983 }
984 }
985 }
986}
987
96449e8e 988sub _join_sql_clauses {
989 my ($self, $logic, $clauses_aref, $bind_aref) = @_;
990
991 if (@$clauses_aref > 1) {
992 my $join = " " . $self->_sqlcase($logic) . " ";
993 my $sql = '( ' . join($join, @$clauses_aref) . ' )';
994 return ($sql, @$bind_aref);
995 }
996 elsif (@$clauses_aref) {
997 return ($clauses_aref->[0], @$bind_aref); # no parentheses
998 }
999 else {
1000 return (); # if no SQL, ignore @$bind_aref
1001 }
1002}
1003
1004
1005# Fix SQL case, if so requested
1006sub _sqlcase {
1007 my $self = shift;
1008
1009 # LDNOTE: if $self->{case} is true, then it contains 'lower', so we
1010 # don't touch the argument ... crooked logic, but let's not change it!
1011 return $self->{case} ? $_[0] : uc($_[0]);
1012}
1013
1014
1015#======================================================================
1016# DISPATCHING FROM REFKIND
1017#======================================================================
1018
1019sub _refkind {
1020 my ($self, $data) = @_;
1021 my $suffix = '';
1022 my $ref;
90aab162 1023 my $n_steps = 0;
96449e8e 1024
96449e8e 1025 while (1) {
90aab162 1026 # blessed objects are treated like scalars
1027 $ref = (blessed $data) ? '' : ref $data;
1028 $n_steps += 1 if $ref;
1029 last if $ref ne 'REF';
96449e8e 1030 $data = $$data;
1031 }
1032
90aab162 1033 my $base = $ref || (defined $data ? 'SCALAR' : 'UNDEF');
1034
1035 return $base . ('REF' x $n_steps);
96449e8e 1036}
1037
90aab162 1038
1039
96449e8e 1040sub _try_refkind {
1041 my ($self, $data) = @_;
1042 my @try = ($self->_refkind($data));
1043 push @try, 'SCALAR_or_UNDEF' if $try[0] eq 'SCALAR' || $try[0] eq 'UNDEF';
1044 push @try, 'FALLBACK';
1045 return @try;
1046}
1047
1048sub _METHOD_FOR_refkind {
1049 my ($self, $meth_prefix, $data) = @_;
1050 my $method = first {$_} map {$self->can($meth_prefix."_".$_)}
1051 $self->_try_refkind($data)
1052 or puke "cannot dispatch on '$meth_prefix' for ".$self->_refkind($data);
1053 return $method;
1054}
1055
1056
1057sub _SWITCH_refkind {
1058 my ($self, $data, $dispatch_table) = @_;
1059
1060 my $coderef = first {$_} map {$dispatch_table->{$_}}
1061 $self->_try_refkind($data)
1062 or puke "no dispatch entry for ".$self->_refkind($data);
1063 $coderef->();
1064}
1065
1066
1067
1068
1069#======================================================================
1070# VALUES, GENERATE, AUTOLOAD
1071#======================================================================
1072
1073# LDNOTE: original code from nwiger, didn't touch code in that section
1074# I feel the AUTOLOAD stuff should not be the default, it should
1075# only be activated on explicit demand by user.
1076
1077sub values {
1078 my $self = shift;
1079 my $data = shift || return;
1080 puke "Argument to ", __PACKAGE__, "->values must be a \\%hash"
1081 unless ref $data eq 'HASH';
bab725ce 1082
1083 my @all_bind;
1084 foreach my $k ( sort keys %$data ) {
1085 my $v = $data->{$k};
1086 $self->_SWITCH_refkind($v, {
1087 ARRAYREF => sub {
1088 if ($self->{array_datatypes}) { # array datatype
1089 push @all_bind, $self->_bindtype($k, $v);
1090 }
1091 else { # literal SQL with bind
1092 my ($sql, @bind) = @$v;
1093 $self->_assert_bindval_matches_bindtype(@bind);
1094 push @all_bind, @bind;
1095 }
1096 },
1097 ARRAYREFREF => sub { # literal SQL with bind
1098 my ($sql, @bind) = @${$v};
1099 $self->_assert_bindval_matches_bindtype(@bind);
1100 push @all_bind, @bind;
1101 },
1102 SCALARREF => sub { # literal SQL without bind
1103 },
1104 SCALAR_or_UNDEF => sub {
1105 push @all_bind, $self->_bindtype($k, $v);
1106 },
1107 });
1108 }
1109
1110 return @all_bind;
96449e8e 1111}
1112
1113sub generate {
1114 my $self = shift;
1115
1116 my(@sql, @sqlq, @sqlv);
1117
1118 for (@_) {
1119 my $ref = ref $_;
1120 if ($ref eq 'HASH') {
1121 for my $k (sort keys %$_) {
1122 my $v = $_->{$k};
1123 my $r = ref $v;
1124 my $label = $self->_quote($k);
1125 if ($r eq 'ARRAY') {
fe3ae272 1126 # literal SQL with bind
1127 my ($sql, @bind) = @$v;
1128 $self->_assert_bindval_matches_bindtype(@bind);
96449e8e 1129 push @sqlq, "$label = $sql";
fe3ae272 1130 push @sqlv, @bind;
96449e8e 1131 } elsif ($r eq 'SCALAR') {
fe3ae272 1132 # literal SQL without bind
96449e8e 1133 push @sqlq, "$label = $$v";
1134 } else {
1135 push @sqlq, "$label = ?";
1136 push @sqlv, $self->_bindtype($k, $v);
1137 }
1138 }
1139 push @sql, $self->_sqlcase('set'), join ', ', @sqlq;
1140 } elsif ($ref eq 'ARRAY') {
1141 # unlike insert(), assume these are ONLY the column names, i.e. for SQL
1142 for my $v (@$_) {
1143 my $r = ref $v;
fe3ae272 1144 if ($r eq 'ARRAY') { # literal SQL with bind
1145 my ($sql, @bind) = @$v;
1146 $self->_assert_bindval_matches_bindtype(@bind);
1147 push @sqlq, $sql;
1148 push @sqlv, @bind;
1149 } elsif ($r eq 'SCALAR') { # literal SQL without bind
96449e8e 1150 # embedded literal SQL
1151 push @sqlq, $$v;
1152 } else {
1153 push @sqlq, '?';
1154 push @sqlv, $v;
1155 }
1156 }
1157 push @sql, '(' . join(', ', @sqlq) . ')';
1158 } elsif ($ref eq 'SCALAR') {
1159 # literal SQL
1160 push @sql, $$_;
1161 } else {
1162 # strings get case twiddled
1163 push @sql, $self->_sqlcase($_);
1164 }
1165 }
1166
1167 my $sql = join ' ', @sql;
1168
1169 # this is pretty tricky
1170 # if ask for an array, return ($stmt, @bind)
1171 # otherwise, s/?/shift @sqlv/ to put it inline
1172 if (wantarray) {
1173 return ($sql, @sqlv);
1174 } else {
1175 1 while $sql =~ s/\?/my $d = shift(@sqlv);
1176 ref $d ? $d->[1] : $d/e;
1177 return $sql;
1178 }
1179}
1180
1181
1182sub DESTROY { 1 }
1183
1184sub AUTOLOAD {
1185 # This allows us to check for a local, then _form, attr
1186 my $self = shift;
1187 my($name) = $AUTOLOAD =~ /.*::(.+)/;
1188 return $self->generate($name, @_);
1189}
1190
11911;
1192
1193
1194
1195__END__
32eab2da 1196
1197=head1 NAME
1198
1199SQL::Abstract - Generate SQL from Perl data structures
1200
1201=head1 SYNOPSIS
1202
1203 use SQL::Abstract;
1204
1205 my $sql = SQL::Abstract->new;
1206
1207 my($stmt, @bind) = $sql->select($table, \@fields, \%where, \@order);
1208
1209 my($stmt, @bind) = $sql->insert($table, \%fieldvals || \@values);
1210
1211 my($stmt, @bind) = $sql->update($table, \%fieldvals, \%where);
1212
1213 my($stmt, @bind) = $sql->delete($table, \%where);
1214
1215 # Then, use these in your DBI statements
1216 my $sth = $dbh->prepare($stmt);
1217 $sth->execute(@bind);
1218
1219 # Just generate the WHERE clause
abe72f94 1220 my($stmt, @bind) = $sql->where(\%where, \@order);
32eab2da 1221
1222 # Return values in the same order, for hashed queries
1223 # See PERFORMANCE section for more details
1224 my @bind = $sql->values(\%fieldvals);
1225
1226=head1 DESCRIPTION
1227
1228This module was inspired by the excellent L<DBIx::Abstract>.
1229However, in using that module I found that what I really wanted
1230to do was generate SQL, but still retain complete control over my
1231statement handles and use the DBI interface. So, I set out to
1232create an abstract SQL generation module.
1233
1234While based on the concepts used by L<DBIx::Abstract>, there are
1235several important differences, especially when it comes to WHERE
1236clauses. I have modified the concepts used to make the SQL easier
1237to generate from Perl data structures and, IMO, more intuitive.
1238The underlying idea is for this module to do what you mean, based
1239on the data structures you provide it. The big advantage is that
1240you don't have to modify your code every time your data changes,
1241as this module figures it out.
1242
1243To begin with, an SQL INSERT is as easy as just specifying a hash
1244of C<key=value> pairs:
1245
1246 my %data = (
1247 name => 'Jimbo Bobson',
1248 phone => '123-456-7890',
1249 address => '42 Sister Lane',
1250 city => 'St. Louis',
1251 state => 'Louisiana',
1252 );
1253
1254The SQL can then be generated with this:
1255
1256 my($stmt, @bind) = $sql->insert('people', \%data);
1257
1258Which would give you something like this:
1259
1260 $stmt = "INSERT INTO people
1261 (address, city, name, phone, state)
1262 VALUES (?, ?, ?, ?, ?)";
1263 @bind = ('42 Sister Lane', 'St. Louis', 'Jimbo Bobson',
1264 '123-456-7890', 'Louisiana');
1265
1266These are then used directly in your DBI code:
1267
1268 my $sth = $dbh->prepare($stmt);
1269 $sth->execute(@bind);
1270
96449e8e 1271=head2 Inserting and Updating Arrays
1272
1273If your database has array types (like for example Postgres),
1274activate the special option C<< array_datatypes => 1 >>
1275when creating the C<SQL::Abstract> object.
1276Then you may use an arrayref to insert and update database array types:
1277
1278 my $sql = SQL::Abstract->new(array_datatypes => 1);
1279 my %data = (
1280 planets => [qw/Mercury Venus Earth Mars/]
1281 );
1282
1283 my($stmt, @bind) = $sql->insert('solar_system', \%data);
1284
1285This results in:
1286
1287 $stmt = "INSERT INTO solar_system (planets) VALUES (?)"
1288
1289 @bind = (['Mercury', 'Venus', 'Earth', 'Mars']);
1290
1291
1292=head2 Inserting and Updating SQL
1293
1294In order to apply SQL functions to elements of your C<%data> you may
1295specify a reference to an arrayref for the given hash value. For example,
1296if you need to execute the Oracle C<to_date> function on a value, you can
1297say something like this:
32eab2da 1298
1299 my %data = (
1300 name => 'Bill',
96449e8e 1301 date_entered => \["to_date(?,'MM/DD/YYYY')", "03/02/2003"],
32eab2da 1302 );
1303
1304The first value in the array is the actual SQL. Any other values are
1305optional and would be included in the bind values array. This gives
1306you:
1307
1308 my($stmt, @bind) = $sql->insert('people', \%data);
1309
1310 $stmt = "INSERT INTO people (name, date_entered)
1311 VALUES (?, to_date(?,'MM/DD/YYYY'))";
1312 @bind = ('Bill', '03/02/2003');
1313
1314An UPDATE is just as easy, all you change is the name of the function:
1315
1316 my($stmt, @bind) = $sql->update('people', \%data);
1317
1318Notice that your C<%data> isn't touched; the module will generate
1319the appropriately quirky SQL for you automatically. Usually you'll
1320want to specify a WHERE clause for your UPDATE, though, which is
1321where handling C<%where> hashes comes in handy...
1322
96449e8e 1323=head2 Complex where statements
1324
32eab2da 1325This module can generate pretty complicated WHERE statements
1326easily. For example, simple C<key=value> pairs are taken to mean
1327equality, and if you want to see if a field is within a set
1328of values, you can use an arrayref. Let's say we wanted to
1329SELECT some data based on this criteria:
1330
1331 my %where = (
1332 requestor => 'inna',
1333 worker => ['nwiger', 'rcwe', 'sfz'],
1334 status => { '!=', 'completed' }
1335 );
1336
1337 my($stmt, @bind) = $sql->select('tickets', '*', \%where);
1338
1339The above would give you something like this:
1340
1341 $stmt = "SELECT * FROM tickets WHERE
1342 ( requestor = ? ) AND ( status != ? )
1343 AND ( worker = ? OR worker = ? OR worker = ? )";
1344 @bind = ('inna', 'completed', 'nwiger', 'rcwe', 'sfz');
1345
1346Which you could then use in DBI code like so:
1347
1348 my $sth = $dbh->prepare($stmt);
1349 $sth->execute(@bind);
1350
1351Easy, eh?
1352
1353=head1 FUNCTIONS
1354
1355The functions are simple. There's one for each major SQL operation,
1356and a constructor you use first. The arguments are specified in a
1357similar order to each function (table, then fields, then a where
1358clause) to try and simplify things.
1359
83cab70b 1360
83cab70b 1361
32eab2da 1362
1363=head2 new(option => 'value')
1364
1365The C<new()> function takes a list of options and values, and returns
1366a new B<SQL::Abstract> object which can then be used to generate SQL
1367through the methods below. The options accepted are:
1368
1369=over
1370
1371=item case
1372
1373If set to 'lower', then SQL will be generated in all lowercase. By
1374default SQL is generated in "textbook" case meaning something like:
1375
1376 SELECT a_field FROM a_table WHERE some_field LIKE '%someval%'
1377
96449e8e 1378Any setting other than 'lower' is ignored.
1379
32eab2da 1380=item cmp
1381
1382This determines what the default comparison operator is. By default
1383it is C<=>, meaning that a hash like this:
1384
1385 %where = (name => 'nwiger', email => 'nate@wiger.org');
1386
1387Will generate SQL like this:
1388
1389 WHERE name = 'nwiger' AND email = 'nate@wiger.org'
1390
1391However, you may want loose comparisons by default, so if you set
1392C<cmp> to C<like> you would get SQL such as:
1393
1394 WHERE name like 'nwiger' AND email like 'nate@wiger.org'
1395
1396You can also override the comparsion on an individual basis - see
1397the huge section on L</"WHERE CLAUSES"> at the bottom.
1398
96449e8e 1399=item sqltrue, sqlfalse
1400
1401Expressions for inserting boolean values within SQL statements.
6e0c6552 1402By default these are C<1=1> and C<1=0>. They are used
1403by the special operators C<-in> and C<-not_in> for generating
1404correct SQL even when the argument is an empty array (see below).
96449e8e 1405
32eab2da 1406=item logic
1407
1408This determines the default logical operator for multiple WHERE
7cac25e6 1409statements in arrays or hashes. If absent, the default logic is "or"
1410for arrays, and "and" for hashes. This means that a WHERE
32eab2da 1411array of the form:
1412
1413 @where = (
1414 event_date => {'>=', '2/13/99'},
1415 event_date => {'<=', '4/24/03'},
1416 );
1417
7cac25e6 1418will generate SQL like this:
32eab2da 1419
1420 WHERE event_date >= '2/13/99' OR event_date <= '4/24/03'
1421
1422This is probably not what you want given this query, though (look
1423at the dates). To change the "OR" to an "AND", simply specify:
1424
1425 my $sql = SQL::Abstract->new(logic => 'and');
1426
1427Which will change the above C<WHERE> to:
1428
1429 WHERE event_date >= '2/13/99' AND event_date <= '4/24/03'
1430
96449e8e 1431The logic can also be changed locally by inserting
7cac25e6 1432a modifier in front of an arrayref :
96449e8e 1433
7cac25e6 1434 @where = (-and => [event_date => {'>=', '2/13/99'},
1435 event_date => {'<=', '4/24/03'} ]);
96449e8e 1436
1437See the L</"WHERE CLAUSES"> section for explanations.
1438
32eab2da 1439=item convert
1440
1441This will automatically convert comparisons using the specified SQL
1442function for both column and value. This is mostly used with an argument
1443of C<upper> or C<lower>, so that the SQL will have the effect of
1444case-insensitive "searches". For example, this:
1445
1446 $sql = SQL::Abstract->new(convert => 'upper');
1447 %where = (keywords => 'MaKe iT CAse inSeNSItive');
1448
1449Will turn out the following SQL:
1450
1451 WHERE upper(keywords) like upper('MaKe iT CAse inSeNSItive')
1452
1453The conversion can be C<upper()>, C<lower()>, or any other SQL function
1454that can be applied symmetrically to fields (actually B<SQL::Abstract> does
1455not validate this option; it will just pass through what you specify verbatim).
1456
1457=item bindtype
1458
1459This is a kludge because many databases suck. For example, you can't
1460just bind values using DBI's C<execute()> for Oracle C<CLOB> or C<BLOB> fields.
1461Instead, you have to use C<bind_param()>:
1462
1463 $sth->bind_param(1, 'reg data');
1464 $sth->bind_param(2, $lots, {ora_type => ORA_CLOB});
1465
1466The problem is, B<SQL::Abstract> will normally just return a C<@bind> array,
1467which loses track of which field each slot refers to. Fear not.
1468
1469If you specify C<bindtype> in new, you can determine how C<@bind> is returned.
1470Currently, you can specify either C<normal> (default) or C<columns>. If you
1471specify C<columns>, you will get an array that looks like this:
1472
1473 my $sql = SQL::Abstract->new(bindtype => 'columns');
1474 my($stmt, @bind) = $sql->insert(...);
1475
1476 @bind = (
1477 [ 'column1', 'value1' ],
1478 [ 'column2', 'value2' ],
1479 [ 'column3', 'value3' ],
1480 );
1481
1482You can then iterate through this manually, using DBI's C<bind_param()>.
e3f9dff4 1483
32eab2da 1484 $sth->prepare($stmt);
1485 my $i = 1;
1486 for (@bind) {
1487 my($col, $data) = @$_;
1488 if ($col eq 'details' || $col eq 'comments') {
1489 $sth->bind_param($i, $data, {ora_type => ORA_CLOB});
1490 } elsif ($col eq 'image') {
1491 $sth->bind_param($i, $data, {ora_type => ORA_BLOB});
1492 } else {
1493 $sth->bind_param($i, $data);
1494 }
1495 $i++;
1496 }
1497 $sth->execute; # execute without @bind now
1498
1499Now, why would you still use B<SQL::Abstract> if you have to do this crap?
1500Basically, the advantage is still that you don't have to care which fields
1501are or are not included. You could wrap that above C<for> loop in a simple
1502sub called C<bind_fields()> or something and reuse it repeatedly. You still
1503get a layer of abstraction over manual SQL specification.
1504
deb148a2 1505Note that if you set L</bindtype> to C<columns>, the C<\[$sql, @bind]>
1506construct (see L</Literal SQL with placeholders and bind values (subqueries)>)
1507will expect the bind values in this format.
1508
32eab2da 1509=item quote_char
1510
1511This is the character that a table or column name will be quoted
1512with. By default this is an empty string, but you could set it to
1513the character C<`>, to generate SQL like this:
1514
1515 SELECT `a_field` FROM `a_table` WHERE `some_field` LIKE '%someval%'
1516
96449e8e 1517Alternatively, you can supply an array ref of two items, the first being the left
1518hand quote character, and the second the right hand quote character. For
1519example, you could supply C<['[',']']> for SQL Server 2000 compliant quotes
1520that generates SQL like this:
1521
1522 SELECT [a_field] FROM [a_table] WHERE [some_field] LIKE '%someval%'
1523
1524Quoting is useful if you have tables or columns names that are reserved
1525words in your database's SQL dialect.
32eab2da 1526
1527=item name_sep
1528
1529This is the character that separates a table and column name. It is
1530necessary to specify this when the C<quote_char> option is selected,
1531so that tables and column names can be individually quoted like this:
1532
1533 SELECT `table`.`one_field` FROM `table` WHERE `table`.`other_field` = 1
1534
96449e8e 1535=item array_datatypes
32eab2da 1536
96449e8e 1537When this option is true, arrayrefs in INSERT or UPDATE are
1538interpreted as array datatypes and are passed directly
1539to the DBI layer.
1540When this option is false, arrayrefs are interpreted
1541as literal SQL, just like refs to arrayrefs
1542(but this behavior is for backwards compatibility; when writing
1543new queries, use the "reference to arrayref" syntax
1544for literal SQL).
32eab2da 1545
32eab2da 1546
96449e8e 1547=item special_ops
32eab2da 1548
96449e8e 1549Takes a reference to a list of "special operators"
1550to extend the syntax understood by L<SQL::Abstract>.
1551See section L</"SPECIAL OPERATORS"> for details.
32eab2da 1552
32eab2da 1553
32eab2da 1554
96449e8e 1555=back
32eab2da 1556
1557=head2 insert($table, \@values || \%fieldvals)
1558
1559This is the simplest function. You simply give it a table name
1560and either an arrayref of values or hashref of field/value pairs.
1561It returns an SQL INSERT statement and a list of bind values.
96449e8e 1562See the sections on L</"Inserting and Updating Arrays"> and
1563L</"Inserting and Updating SQL"> for information on how to insert
1564with those data types.
32eab2da 1565
1566=head2 update($table, \%fieldvals, \%where)
1567
1568This takes a table, hashref of field/value pairs, and an optional
86298391 1569hashref L<WHERE clause|/WHERE CLAUSES>. It returns an SQL UPDATE function and a list
32eab2da 1570of bind values.
96449e8e 1571See the sections on L</"Inserting and Updating Arrays"> and
1572L</"Inserting and Updating SQL"> for information on how to insert
1573with those data types.
32eab2da 1574
96449e8e 1575=head2 select($source, $fields, $where, $order)
32eab2da 1576
96449e8e 1577This returns a SQL SELECT statement and associated list of bind values, as
1578specified by the arguments :
32eab2da 1579
96449e8e 1580=over
32eab2da 1581
96449e8e 1582=item $source
32eab2da 1583
96449e8e 1584Specification of the 'FROM' part of the statement.
1585The argument can be either a plain scalar (interpreted as a table
1586name, will be quoted), or an arrayref (interpreted as a list
1587of table names, joined by commas, quoted), or a scalarref
1588(literal table name, not quoted), or a ref to an arrayref
1589(list of literal table names, joined by commas, not quoted).
32eab2da 1590
96449e8e 1591=item $fields
32eab2da 1592
96449e8e 1593Specification of the list of fields to retrieve from
1594the source.
1595The argument can be either an arrayref (interpreted as a list
1596of field names, will be joined by commas and quoted), or a
1597plain scalar (literal SQL, not quoted).
1598Please observe that this API is not as flexible as for
e3f9dff4 1599the first argument C<$table>, for backwards compatibility reasons.
32eab2da 1600
96449e8e 1601=item $where
32eab2da 1602
96449e8e 1603Optional argument to specify the WHERE part of the query.
1604The argument is most often a hashref, but can also be
1605an arrayref or plain scalar --
1606see section L<WHERE clause|/"WHERE CLAUSES"> for details.
32eab2da 1607
96449e8e 1608=item $order
32eab2da 1609
96449e8e 1610Optional argument to specify the ORDER BY part of the query.
1611The argument can be a scalar, a hashref or an arrayref
1612-- see section L<ORDER BY clause|/"ORDER BY CLAUSES">
1613for details.
32eab2da 1614
96449e8e 1615=back
32eab2da 1616
32eab2da 1617
1618=head2 delete($table, \%where)
1619
86298391 1620This takes a table name and optional hashref L<WHERE clause|/WHERE CLAUSES>.
32eab2da 1621It returns an SQL DELETE statement and list of bind values.
1622
32eab2da 1623=head2 where(\%where, \@order)
1624
1625This is used to generate just the WHERE clause. For example,
1626if you have an arbitrary data structure and know what the
1627rest of your SQL is going to look like, but want an easy way
1628to produce a WHERE clause, use this. It returns an SQL WHERE
1629clause and list of bind values.
1630
32eab2da 1631
1632=head2 values(\%data)
1633
1634This just returns the values from the hash C<%data>, in the same
1635order that would be returned from any of the other above queries.
1636Using this allows you to markedly speed up your queries if you
1637are affecting lots of rows. See below under the L</"PERFORMANCE"> section.
1638
32eab2da 1639=head2 generate($any, 'number', $of, \@data, $struct, \%types)
1640
1641Warning: This is an experimental method and subject to change.
1642
1643This returns arbitrarily generated SQL. It's a really basic shortcut.
1644It will return two different things, depending on return context:
1645
1646 my($stmt, @bind) = $sql->generate('create table', \$table, \@fields);
1647 my $stmt_and_val = $sql->generate('create table', \$table, \@fields);
1648
1649These would return the following:
1650
1651 # First calling form
1652 $stmt = "CREATE TABLE test (?, ?)";
1653 @bind = (field1, field2);
1654
1655 # Second calling form
1656 $stmt_and_val = "CREATE TABLE test (field1, field2)";
1657
1658Depending on what you're trying to do, it's up to you to choose the correct
1659format. In this example, the second form is what you would want.
1660
1661By the same token:
1662
1663 $sql->generate('alter session', { nls_date_format => 'MM/YY' });
1664
1665Might give you:
1666
1667 ALTER SESSION SET nls_date_format = 'MM/YY'
1668
1669You get the idea. Strings get their case twiddled, but everything
1670else remains verbatim.
1671
32eab2da 1672
32eab2da 1673
32eab2da 1674
1675=head1 WHERE CLAUSES
1676
96449e8e 1677=head2 Introduction
1678
32eab2da 1679This module uses a variation on the idea from L<DBIx::Abstract>. It
1680is B<NOT>, repeat I<not> 100% compatible. B<The main logic of this
1681module is that things in arrays are OR'ed, and things in hashes
1682are AND'ed.>
1683
1684The easiest way to explain is to show lots of examples. After
1685each C<%where> hash shown, it is assumed you used:
1686
1687 my($stmt, @bind) = $sql->where(\%where);
1688
1689However, note that the C<%where> hash can be used directly in any
1690of the other functions as well, as described above.
1691
96449e8e 1692=head2 Key-value pairs
1693
32eab2da 1694So, let's get started. To begin, a simple hash:
1695
1696 my %where = (
1697 user => 'nwiger',
1698 status => 'completed'
1699 );
1700
1701Is converted to SQL C<key = val> statements:
1702
1703 $stmt = "WHERE user = ? AND status = ?";
1704 @bind = ('nwiger', 'completed');
1705
1706One common thing I end up doing is having a list of values that
1707a field can be in. To do this, simply specify a list inside of
1708an arrayref:
1709
1710 my %where = (
1711 user => 'nwiger',
1712 status => ['assigned', 'in-progress', 'pending'];
1713 );
1714
1715This simple code will create the following:
1716
1717 $stmt = "WHERE user = ? AND ( status = ? OR status = ? OR status = ? )";
1718 @bind = ('nwiger', 'assigned', 'in-progress', 'pending');
1719
7cac25e6 1720A field associated to an empty arrayref will be considered a
1721logical false and will generate 0=1.
8a68b5be 1722
6e0c6552 1723=head2 Specific comparison operators
96449e8e 1724
32eab2da 1725If you want to specify a different type of operator for your comparison,
1726you can use a hashref for a given column:
1727
1728 my %where = (
1729 user => 'nwiger',
1730 status => { '!=', 'completed' }
1731 );
1732
1733Which would generate:
1734
1735 $stmt = "WHERE user = ? AND status != ?";
1736 @bind = ('nwiger', 'completed');
1737
1738To test against multiple values, just enclose the values in an arrayref:
1739
96449e8e 1740 status => { '=', ['assigned', 'in-progress', 'pending'] };
1741
f2d5020d 1742Which would give you:
96449e8e 1743
1744 "WHERE status = ? OR status = ? OR status = ?"
1745
1746
1747The hashref can also contain multiple pairs, in which case it is expanded
32eab2da 1748into an C<AND> of its elements:
1749
1750 my %where = (
1751 user => 'nwiger',
1752 status => { '!=', 'completed', -not_like => 'pending%' }
1753 );
1754
1755 # Or more dynamically, like from a form
1756 $where{user} = 'nwiger';
1757 $where{status}{'!='} = 'completed';
1758 $where{status}{'-not_like'} = 'pending%';
1759
1760 # Both generate this
1761 $stmt = "WHERE user = ? AND status != ? AND status NOT LIKE ?";
1762 @bind = ('nwiger', 'completed', 'pending%');
1763
96449e8e 1764
32eab2da 1765To get an OR instead, you can combine it with the arrayref idea:
1766
1767 my %where => (
1768 user => 'nwiger',
1769 priority => [ {'=', 2}, {'!=', 1} ]
1770 );
1771
1772Which would generate:
1773
1774 $stmt = "WHERE user = ? AND priority = ? OR priority != ?";
1775 @bind = ('nwiger', '2', '1');
1776
44b9e502 1777If you want to include literal SQL (with or without bind values), just use a
1778scalar reference or array reference as the value:
1779
1780 my %where = (
1781 date_entered => { '>' => \["to_date(?, 'MM/DD/YYYY')", "11/26/2008"] },
1782 date_expires => { '<' => \"now()" }
1783 );
1784
1785Which would generate:
1786
1787 $stmt = "WHERE date_entered > "to_date(?, 'MM/DD/YYYY') AND date_expires < now()";
1788 @bind = ('11/26/2008');
1789
96449e8e 1790
1791=head2 Logic and nesting operators
1792
1793In the example above,
1794there is a subtle trap if you want to say something like
32eab2da 1795this (notice the C<AND>):
1796
1797 WHERE priority != ? AND priority != ?
1798
1799Because, in Perl you I<can't> do this:
1800
1801 priority => { '!=', 2, '!=', 1 }
1802
1803As the second C<!=> key will obliterate the first. The solution
1804is to use the special C<-modifier> form inside an arrayref:
1805
96449e8e 1806 priority => [ -and => {'!=', 2},
1807 {'!=', 1} ]
1808
32eab2da 1809
1810Normally, these would be joined by C<OR>, but the modifier tells it
1811to use C<AND> instead. (Hint: You can use this in conjunction with the
1812C<logic> option to C<new()> in order to change the way your queries
1813work by default.) B<Important:> Note that the C<-modifier> goes
1814B<INSIDE> the arrayref, as an extra first element. This will
1815B<NOT> do what you think it might:
1816
1817 priority => -and => [{'!=', 2}, {'!=', 1}] # WRONG!
1818
1819Here is a quick list of equivalencies, since there is some overlap:
1820
1821 # Same
1822 status => {'!=', 'completed', 'not like', 'pending%' }
1823 status => [ -and => {'!=', 'completed'}, {'not like', 'pending%'}]
1824
1825 # Same
1826 status => {'=', ['assigned', 'in-progress']}
1827 status => [ -or => {'=', 'assigned'}, {'=', 'in-progress'}]
1828 status => [ {'=', 'assigned'}, {'=', 'in-progress'} ]
1829
e3f9dff4 1830
1831
96449e8e 1832=head2 Special operators : IN, BETWEEN, etc.
1833
32eab2da 1834You can also use the hashref format to compare a list of fields using the
1835C<IN> comparison operator, by specifying the list as an arrayref:
1836
1837 my %where = (
1838 status => 'completed',
1839 reportid => { -in => [567, 2335, 2] }
1840 );
1841
1842Which would generate:
1843
1844 $stmt = "WHERE status = ? AND reportid IN (?,?,?)";
1845 @bind = ('completed', '567', '2335', '2');
1846
96449e8e 1847The reverse operator C<-not_in> generates SQL C<NOT IN> and is used in
1848the same way.
1849
6e0c6552 1850If the argument to C<-in> is an empty array, 'sqlfalse' is generated
1851(by default : C<1=0>). Similarly, C<< -not_in => [] >> generates
1852'sqltrue' (by default : C<1=1>).
1853
1854
1855
96449e8e 1856Another pair of operators is C<-between> and C<-not_between>,
1857used with an arrayref of two values:
32eab2da 1858
1859 my %where = (
1860 user => 'nwiger',
1861 completion_date => {
1862 -not_between => ['2002-10-01', '2003-02-06']
1863 }
1864 );
1865
1866Would give you:
1867
1868 WHERE user = ? AND completion_date NOT BETWEEN ( ? AND ? )
1869
96449e8e 1870These are the two builtin "special operators"; but the
1871list can be expanded : see section L</"SPECIAL OPERATORS"> below.
1872
107b72f1 1873=head2 Nested conditions, -and/-or prefixes
96449e8e 1874
32eab2da 1875So far, we've seen how multiple conditions are joined with a top-level
1876C<AND>. We can change this by putting the different conditions we want in
1877hashes and then putting those hashes in an array. For example:
1878
1879 my @where = (
1880 {
1881 user => 'nwiger',
1882 status => { -like => ['pending%', 'dispatched'] },
1883 },
1884 {
1885 user => 'robot',
1886 status => 'unassigned',
1887 }
1888 );
1889
1890This data structure would create the following:
1891
1892 $stmt = "WHERE ( user = ? AND ( status LIKE ? OR status LIKE ? ) )
1893 OR ( user = ? AND status = ? ) )";
1894 @bind = ('nwiger', 'pending', 'dispatched', 'robot', 'unassigned');
1895
107b72f1 1896
01a01e57 1897There is also a special C<-nest>
107b72f1 1898operator which adds an additional set of parens, to create a subquery.
1899For example, to get something like this:
1900
1901 $stmt = "WHERE user = ? AND ( workhrs > ? OR geo = ? )";
1902 @bind = ('nwiger', '20', 'ASIA');
1903
1904You would do:
1905
1906 my %where = (
1907 user => 'nwiger',
01a01e57 1908 -nest => [ workhrs => {'>', 20}, geo => 'ASIA' ],
107b72f1 1909 );
1910
1911
1912Finally, clauses in hashrefs or arrayrefs can be
7cac25e6 1913prefixed with an C<-and> or C<-or> to change the logic
1914inside :
32eab2da 1915
1916 my @where = (
1917 -and => [
1918 user => 'nwiger',
01a01e57 1919 -nest => [
7cac25e6 1920 -and => [workhrs => {'>', 20}, geo => 'ASIA' ],
1921 -and => [workhrs => {'<', 50}, geo => 'EURO' ]
32eab2da 1922 ],
1923 ],
1924 );
1925
1926That would yield:
1927
1928 WHERE ( user = ? AND
1929 ( ( workhrs > ? AND geo = ? )
1930 OR ( workhrs < ? AND geo = ? ) ) )
1931
107b72f1 1932
1933=head2 Algebraic inconsistency, for historical reasons
1934
7cac25e6 1935C<Important note>: when connecting several conditions, the C<-and->|C<-or>
1936operator goes C<outside> of the nested structure; whereas when connecting
1937several constraints on one column, the C<-and> operator goes
1938C<inside> the arrayref. Here is an example combining both features :
1939
1940 my @where = (
1941 -and => [a => 1, b => 2],
1942 -or => [c => 3, d => 4],
1943 e => [-and => {-like => 'foo%'}, {-like => '%bar'} ]
1944 )
1945
1946yielding
1947
1948 WHERE ( ( ( a = ? AND b = ? )
1949 OR ( c = ? OR d = ? )
1950 OR ( e LIKE ? AND e LIKE ? ) ) )
1951
107b72f1 1952This difference in syntax is unfortunate but must be preserved for
1953historical reasons. So be careful : the two examples below would
1954seem algebraically equivalent, but they are not
1955
1956 {col => [-and => {-like => 'foo%'}, {-like => '%bar'}]}
1957 # yields : WHERE ( ( col LIKE ? AND col LIKE ? ) )
1958
1959 [-and => {col => {-like => 'foo%'}, {col => {-like => '%bar'}}]]
1960 # yields : WHERE ( ( col LIKE ? OR col LIKE ? ) )
1961
7cac25e6 1962
96449e8e 1963=head2 Literal SQL
1964
32eab2da 1965Finally, sometimes only literal SQL will do. If you want to include
1966literal SQL verbatim, you can specify it as a scalar reference, namely:
1967
1968 my $inn = 'is Not Null';
1969 my %where = (
1970 priority => { '<', 2 },
1971 requestor => \$inn
1972 );
1973
1974This would create:
1975
1976 $stmt = "WHERE priority < ? AND requestor is Not Null";
1977 @bind = ('2');
1978
1979Note that in this example, you only get one bind parameter back, since
1980the verbatim SQL is passed as part of the statement.
1981
1982Of course, just to prove a point, the above can also be accomplished
1983with this:
1984
1985 my %where = (
1986 priority => { '<', 2 },
1987 requestor => { '!=', undef },
1988 );
1989
96449e8e 1990
32eab2da 1991TMTOWTDI.
1992
96449e8e 1993Conditions on boolean columns can be expressed in the
1994same way, passing a reference to an empty string :
1995
1996 my %where = (
1997 priority => { '<', 2 },
1998 is_ready => \"";
1999 );
2000
2001which yields
2002
2003 $stmt = "WHERE priority < ? AND is_ready";
2004 @bind = ('2');
2005
2006
2007=head2 Literal SQL with placeholders and bind values (subqueries)
2008
2009If the literal SQL to be inserted has placeholders and bind values,
2010use a reference to an arrayref (yes this is a double reference --
2011not so common, but perfectly legal Perl). For example, to find a date
2012in Postgres you can use something like this:
2013
2014 my %where = (
2015 date_column => \[q/= date '2008-09-30' - ?::integer/, 10/]
2016 )
2017
2018This would create:
2019
d2a8fe1a 2020 $stmt = "WHERE ( date_column = date '2008-09-30' - ?::integer )"
96449e8e 2021 @bind = ('10');
2022
deb148a2 2023Note that you must pass the bind values in the same format as they are returned
62552e7d 2024by L</where>. That means that if you set L</bindtype> to C<columns>, you must
26f2dca5 2025provide the bind values in the C<< [ column_meta => value ] >> format, where
2026C<column_meta> is an opaque scalar value; most commonly the column name, but
62552e7d 2027you can use any scalar value (including references and blessed references),
2028L<SQL::Abstract> will simply pass it through intact. So if C<bindtype> is set
2029to C<columns> the above example will look like:
deb148a2 2030
2031 my %where = (
2032 date_column => \[q/= date '2008-09-30' - ?::integer/, [ dummy => 10 ]/]
2033 )
96449e8e 2034
2035Literal SQL is especially useful for nesting parenthesized clauses in the
2036main SQL query. Here is a first example :
2037
2038 my ($sub_stmt, @sub_bind) = ("SELECT c1 FROM t1 WHERE c2 < ? AND c3 LIKE ?",
2039 100, "foo%");
2040 my %where = (
2041 foo => 1234,
2042 bar => \["IN ($sub_stmt)" => @sub_bind],
2043 );
2044
2045This yields :
2046
2047 $stmt = "WHERE (foo = ? AND bar IN (SELECT c1 FROM t1
2048 WHERE c2 < ? AND c3 LIKE ?))";
2049 @bind = (1234, 100, "foo%");
2050
2051Other subquery operators, like for example C<"E<gt> ALL"> or C<"NOT IN">,
2052are expressed in the same way. Of course the C<$sub_stmt> and
2053its associated bind values can be generated through a former call
2054to C<select()> :
2055
2056 my ($sub_stmt, @sub_bind)
2057 = $sql->select("t1", "c1", {c2 => {"<" => 100},
2058 c3 => {-like => "foo%"}});
2059 my %where = (
2060 foo => 1234,
2061 bar => \["> ALL ($sub_stmt)" => @sub_bind],
2062 );
2063
2064In the examples above, the subquery was used as an operator on a column;
2065but the same principle also applies for a clause within the main C<%where>
2066hash, like an EXISTS subquery :
2067
2068 my ($sub_stmt, @sub_bind)
2069 = $sql->select("t1", "*", {c1 => 1, c2 => \"> t0.c0"});
2070 my %where = (
2071 foo => 1234,
01a01e57 2072 -nest => \["EXISTS ($sub_stmt)" => @sub_bind],
96449e8e 2073 );
2074
2075which yields
2076
2077 $stmt = "WHERE (foo = ? AND EXISTS (SELECT * FROM t1
2078 WHERE c1 = ? AND c2 > t0.c0))";
2079 @bind = (1234, 1);
2080
2081
2082Observe that the condition on C<c2> in the subquery refers to
2083column C<t0.c0> of the main query : this is I<not> a bind
2084value, so we have to express it through a scalar ref.
2085Writing C<< c2 => {">" => "t0.c0"} >> would have generated
2086C<< c2 > ? >> with bind value C<"t0.c0"> ... not exactly
2087what we wanted here.
2088
2089Another use of the subquery technique is when some SQL clauses need
2090parentheses, as it often occurs with some proprietary SQL extensions
2091like for example fulltext expressions, geospatial expressions,
2092NATIVE clauses, etc. Here is an example of a fulltext query in MySQL :
2093
2094 my %where = (
01a01e57 2095 -nest => \["MATCH (col1, col2) AGAINST (?)" => qw/apples/]
96449e8e 2096 );
2097
2098Finally, here is an example where a subquery is used
2099for expressing unary negation:
2100
2101 my ($sub_stmt, @sub_bind)
2102 = $sql->where({age => [{"<" => 10}, {">" => 20}]});
2103 $sub_stmt =~ s/^ where //i; # don't want "WHERE" in the subclause
2104 my %where = (
2105 lname => {like => '%son%'},
01a01e57 2106 -nest => \["NOT ($sub_stmt)" => @sub_bind],
96449e8e 2107 );
2108
2109This yields
2110
2111 $stmt = "lname LIKE ? AND NOT ( age < ? OR age > ? )"
2112 @bind = ('%son%', 10, 20)
2113
2114
2115
2116=head2 Conclusion
2117
32eab2da 2118These pages could go on for a while, since the nesting of the data
2119structures this module can handle are pretty much unlimited (the
2120module implements the C<WHERE> expansion as a recursive function
2121internally). Your best bet is to "play around" with the module a
2122little to see how the data structures behave, and choose the best
2123format for your data based on that.
2124
2125And of course, all the values above will probably be replaced with
2126variables gotten from forms or the command line. After all, if you
2127knew everything ahead of time, you wouldn't have to worry about
2128dynamically-generating SQL and could just hardwire it into your
2129script.
2130
96449e8e 2131
2132
2133
86298391 2134=head1 ORDER BY CLAUSES
2135
2136Some functions take an order by clause. This can either be a scalar (just a
2137column name,) a hash of C<< { -desc => 'col' } >> or C<< { -asc => 'col' } >>,
1cfa1db3 2138or an array of either of the two previous forms. Examples:
2139
952f9e2d 2140 Given | Will Generate
1cfa1db3 2141 ----------------------------------------------------------
952f9e2d 2142 |
2143 \'colA DESC' | ORDER BY colA DESC
2144 |
2145 'colA' | ORDER BY colA
2146 |
2147 [qw/colA colB/] | ORDER BY colA, colB
2148 |
2149 {-asc => 'colA'} | ORDER BY colA ASC
2150 |
2151 {-desc => 'colB'} | ORDER BY colB DESC
2152 |
2153 ['colA', {-asc => 'colB'}] | ORDER BY colA, colB ASC
2154 |
2155 { -asc => [qw/colA colB] } | ORDER BY colA ASC, colB ASC
2156 |
2157 [ |
2158 { -asc => 'colA' }, | ORDER BY colA ASC, colB DESC,
2159 { -desc => [qw/colB/], | colC ASC, colD ASC
2160 { -asc => [qw/colC colD/],|
2161 ] |
2162 ===========================================================
86298391 2163
96449e8e 2164
2165
2166=head1 SPECIAL OPERATORS
2167
e3f9dff4 2168 my $sqlmaker = SQL::Abstract->new(special_ops => [
3a2e1a5e 2169 {
2170 regex => qr/.../,
e3f9dff4 2171 handler => sub {
2172 my ($self, $field, $op, $arg) = @_;
2173 ...
3a2e1a5e 2174 },
2175 },
2176 {
2177 regex => qr/.../,
2178 handler => 'method_name',
e3f9dff4 2179 },
2180 ]);
2181
2182A "special operator" is a SQL syntactic clause that can be
2183applied to a field, instead of a usual binary operator.
2184For example :
2185
2186 WHERE field IN (?, ?, ?)
2187 WHERE field BETWEEN ? AND ?
2188 WHERE MATCH(field) AGAINST (?, ?)
96449e8e 2189
e3f9dff4 2190Special operators IN and BETWEEN are fairly standard and therefore
3a2e1a5e 2191are builtin within C<SQL::Abstract> (as the overridable methods
2192C<_where_field_IN> and C<_where_field_BETWEEN>). For other operators,
2193like the MATCH .. AGAINST example above which is specific to MySQL,
2194you can write your own operator handlers - supply a C<special_ops>
2195argument to the C<new> method. That argument takes an arrayref of
2196operator definitions; each operator definition is a hashref with two
2197entries:
96449e8e 2198
e3f9dff4 2199=over
2200
2201=item regex
2202
2203the regular expression to match the operator
96449e8e 2204
e3f9dff4 2205=item handler
2206
3a2e1a5e 2207Either a coderef or a plain scalar method name. In both cases
2208the expected return is C<< ($sql, @bind) >>.
2209
2210When supplied with a method name, it is simply called on the
2211L<SQL::Abstract/> object as:
2212
2213 $self->$method_name ($field, $op, $arg)
2214
2215 Where:
2216
2217 $op is the part that matched the handler regex
2218 $field is the LHS of the operator
2219 $arg is the RHS
2220
2221When supplied with a coderef, it is called as:
2222
2223 $coderef->($self, $field, $op, $arg)
2224
e3f9dff4 2225
2226=back
2227
2228For example, here is an implementation
2229of the MATCH .. AGAINST syntax for MySQL
2230
2231 my $sqlmaker = SQL::Abstract->new(special_ops => [
2232
2233 # special op for MySql MATCH (field) AGAINST(word1, word2, ...)
2234 {regex => qr/^match$/i,
2235 handler => sub {
2236 my ($self, $field, $op, $arg) = @_;
2237 $arg = [$arg] if not ref $arg;
2238 my $label = $self->_quote($field);
2239 my ($placeholder) = $self->_convert('?');
2240 my $placeholders = join ", ", (($placeholder) x @$arg);
2241 my $sql = $self->_sqlcase('match') . " ($label) "
2242 . $self->_sqlcase('against') . " ($placeholders) ";
2243 my @bind = $self->_bindtype($field, @$arg);
2244 return ($sql, @bind);
2245 }
2246 },
2247
2248 ]);
96449e8e 2249
2250
32eab2da 2251=head1 PERFORMANCE
2252
2253Thanks to some benchmarking by Mark Stosberg, it turns out that
2254this module is many orders of magnitude faster than using C<DBIx::Abstract>.
2255I must admit this wasn't an intentional design issue, but it's a
2256byproduct of the fact that you get to control your C<DBI> handles
2257yourself.
2258
2259To maximize performance, use a code snippet like the following:
2260
2261 # prepare a statement handle using the first row
2262 # and then reuse it for the rest of the rows
2263 my($sth, $stmt);
2264 for my $href (@array_of_hashrefs) {
2265 $stmt ||= $sql->insert('table', $href);
2266 $sth ||= $dbh->prepare($stmt);
2267 $sth->execute($sql->values($href));
2268 }
2269
2270The reason this works is because the keys in your C<$href> are sorted
2271internally by B<SQL::Abstract>. Thus, as long as your data retains
2272the same structure, you only have to generate the SQL the first time
2273around. On subsequent queries, simply use the C<values> function provided
2274by this module to return your values in the correct order.
2275
96449e8e 2276
32eab2da 2277=head1 FORMBUILDER
2278
2279If you use my C<CGI::FormBuilder> module at all, you'll hopefully
2280really like this part (I do, at least). Building up a complex query
2281can be as simple as the following:
2282
2283 #!/usr/bin/perl
2284
2285 use CGI::FormBuilder;
2286 use SQL::Abstract;
2287
2288 my $form = CGI::FormBuilder->new(...);
2289 my $sql = SQL::Abstract->new;
2290
2291 if ($form->submitted) {
2292 my $field = $form->field;
2293 my $id = delete $field->{id};
2294 my($stmt, @bind) = $sql->update('table', $field, {id => $id});
2295 }
2296
2297Of course, you would still have to connect using C<DBI> to run the
2298query, but the point is that if you make your form look like your
2299table, the actual query script can be extremely simplistic.
2300
2301If you're B<REALLY> lazy (I am), check out C<HTML::QuickTable> for
2302a fast interface to returning and formatting data. I frequently
2303use these three modules together to write complex database query
2304apps in under 50 lines.
2305
32eab2da 2306
96449e8e 2307=head1 CHANGES
2308
2309Version 1.50 was a major internal refactoring of C<SQL::Abstract>.
2310Great care has been taken to preserve the I<published> behavior
2311documented in previous versions in the 1.* family; however,
2312some features that were previously undocumented, or behaved
2313differently from the documentation, had to be changed in order
2314to clarify the semantics. Hence, client code that was relying
2315on some dark areas of C<SQL::Abstract> v1.*
2316B<might behave differently> in v1.50.
32eab2da 2317
d2a8fe1a 2318The main changes are :
2319
96449e8e 2320=over
32eab2da 2321
96449e8e 2322=item *
32eab2da 2323
96449e8e 2324support for literal SQL through the C<< \ [$sql, bind] >> syntax.
2325
2326=item *
2327
145fbfc8 2328support for the { operator => \"..." } construct (to embed literal SQL)
2329
2330=item *
2331
9c37b9c0 2332support for the { operator => \["...", @bind] } construct (to embed literal SQL with bind values)
2333
2334=item *
2335
96449e8e 2336optional support for L<array datatypes|/"Inserting and Updating Arrays">
2337
2338=item *
2339
2340defensive programming : check arguments
2341
2342=item *
2343
2344fixed bug with global logic, which was previously implemented
7cac25e6 2345through global variables yielding side-effects. Prior versions would
96449e8e 2346interpret C<< [ {cond1, cond2}, [cond3, cond4] ] >>
2347as C<< "(cond1 AND cond2) OR (cond3 AND cond4)" >>.
2348Now this is interpreted
2349as C<< "(cond1 AND cond2) OR (cond3 OR cond4)" >>.
2350
96449e8e 2351
2352=item *
2353
2354fixed semantics of _bindtype on array args
2355
2356=item *
2357
2358dropped the C<_anoncopy> of the %where tree. No longer necessary,
2359we just avoid shifting arrays within that tree.
2360
2361=item *
2362
2363dropped the C<_modlogic> function
2364
2365=back
32eab2da 2366
32eab2da 2367
32eab2da 2368
2369=head1 ACKNOWLEDGEMENTS
2370
2371There are a number of individuals that have really helped out with
2372this module. Unfortunately, most of them submitted bugs via CPAN
2373so I have no idea who they are! But the people I do know are:
2374
86298391 2375 Ash Berlin (order_by hash term support)
b643abe1 2376 Matt Trout (DBIx::Class support)
32eab2da 2377 Mark Stosberg (benchmarking)
2378 Chas Owens (initial "IN" operator support)
2379 Philip Collins (per-field SQL functions)
2380 Eric Kolve (hashref "AND" support)
2381 Mike Fragassi (enhancements to "BETWEEN" and "LIKE")
2382 Dan Kubb (support for "quote_char" and "name_sep")
f5aab26e 2383 Guillermo Roditi (patch to cleanup "IN" and "BETWEEN", fix and tests for _order_by)
01a01e57 2384 Laurent Dami (internal refactoring, multiple -nest, extensible list of special operators, literal SQL)
dbdf7648 2385 Norbert Buchmuller (support for literal SQL in hashpair, misc. fixes & tests)
e96c510a 2386 Peter Rabbitson (rewrite of SQLA::Test, misc. fixes & tests)
32eab2da 2387
2388Thanks!
2389
32eab2da 2390=head1 SEE ALSO
2391
86298391 2392L<DBIx::Class>, L<DBIx::Abstract>, L<CGI::FormBuilder>, L<HTML::QuickTable>.
32eab2da 2393
32eab2da 2394=head1 AUTHOR
2395
b643abe1 2396Copyright (c) 2001-2007 Nathan Wiger <nwiger@cpan.org>. All Rights Reserved.
2397
2398This module is actively maintained by Matt Trout <mst@shadowcatsystems.co.uk>
32eab2da 2399
abe72f94 2400For support, your best bet is to try the C<DBIx::Class> users mailing list.
2401While not an official support venue, C<DBIx::Class> makes heavy use of
2402C<SQL::Abstract>, and as such list members there are very familiar with
2403how to create queries.
2404
0d067ded 2405=head1 LICENSE
2406
32eab2da 2407This module is free software; you may copy this under the terms of
2408the GNU General Public License, or the Artistic License, copies of
2409which should have accompanied your Perl kit.
2410
2411=cut
2412