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