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