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