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