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