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