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