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