Bump to 1.50
[scpubgit/Q-Branch.git] / lib / SQL / Abstract.pm
index dc28d48..58902e7 100644 (file)
@@ -15,9 +15,10 @@ use Scalar::Util qw/blessed/;
 # GLOBALS
 #======================================================================
 
-our $VERSION  = '1.49_02';
-$VERSION      = eval $VERSION; # numify for warning-free dev releases
+our $VERSION  = '1.50';
 
+# This would confuse some packagers
+#$VERSION      = eval $VERSION; # numify for warning-free dev releases
 
 our $AUTOLOAD;
 
@@ -386,6 +387,8 @@ sub _where_ARRAYREF {
       # skip empty elements, otherwise get invalid trailing AND stuff
       ARRAYREF  => sub {$self->_recurse_where($el)        if @$el},
 
+      ARRAYREFREF => sub { @{${$el}}                 if @{${$el}}},
+
       HASHREF   => sub {$self->_recurse_where($el, 'and') if %$el},
            # LDNOTE : previous SQLA code for hashrefs was creating a dirty
            # side-effect: the first hashref within an array would change
@@ -410,7 +413,16 @@ sub _where_ARRAYREF {
   return $self->_join_sql_clauses($logic, \@sql_clauses, \@all_bind);
 }
 
+#======================================================================
+# WHERE: top-level ARRAYREFREF
+#======================================================================
 
+sub _where_ARRAYREFREF {
+    my ($self, $where) = @_;
+    my ($sql, @bind) = @{${$where}};
+
+    return ($sql, @bind);
+}
 
 #======================================================================
 # WHERE: top-level HASHREF
@@ -990,7 +1002,35 @@ sub values {
     my $data = shift || return;
     puke "Argument to ", __PACKAGE__, "->values must be a \\%hash"
         unless ref $data eq 'HASH';
-    return map { $self->_bindtype($_, $data->{$_}) } sort keys %$data;
+
+    my @all_bind;
+    foreach my $k ( sort keys %$data ) {
+        my $v = $data->{$k};
+        $self->_SWITCH_refkind($v, {
+          ARRAYREF => sub { 
+            if ($self->{array_datatypes}) { # array datatype
+              push @all_bind, $self->_bindtype($k, $v);
+            }
+            else {                          # literal SQL with bind
+              my ($sql, @bind) = @$v;
+              $self->_assert_bindval_matches_bindtype(@bind);
+              push @all_bind, @bind;
+            }
+          },
+          ARRAYREFREF => sub { # literal SQL with bind
+            my ($sql, @bind) = @${$v};
+            $self->_assert_bindval_matches_bindtype(@bind);
+            push @all_bind, @bind;
+          },
+          SCALARREF => sub {  # literal SQL without bind
+          },
+          SCALAR_or_UNDEF => sub {
+            push @all_bind, $self->_bindtype($k, $v);
+          },
+        });
+    }
+
+    return @all_bind;
 }
 
 sub generate {
@@ -1382,6 +1422,10 @@ are or are not included. You could wrap that above C<for> loop in a simple
 sub called C<bind_fields()> or something and reuse it repeatedly. You still
 get a layer of abstraction over manual SQL specification.
 
+Note that if you set L</bindtype> to C<columns>, the C<\[$sql, @bind]>
+construct (see L</Literal SQL with placeholders and bind values (subqueries)>)
+will expect the bind values in this format.
+
 =item quote_char
 
 This is the character that a table or column name will be quoted
@@ -1875,6 +1919,17 @@ This would create:
     $stmt = "WHERE ( date_column = date '2008-09-30' - ?::integer )"
     @bind = ('10');
 
+Note that you must pass the bind values in the same format as they are returned
+by C</where>. That means that if you set L</bindtype> to C<columns>, you must
+provide the bind values in the C<< [ column_meta => value ] >> format, where
+C<column_meta> is an opaque scalar value; most commonly the column name, but
+you can use any scalar scalar value (including references and blessed
+references), L<SQL::Abstract> will simply pass it through intact. So eg. the
+above example will look like:
+
+    my %where = (
+       date_column => \[q/= date '2008-09-30' - ?::integer/, [ dummy => 10 ]/]
+    )
 
 Literal SQL is especially useful for nesting parenthesized clauses in the
 main SQL query. Here is a first example :