Minor documentation fixes; typos, POD formatting code syntax, return value explanatio...
[dbsrgits/SQL-Abstract.git] / lib / SQL / Abstract.pm
index 37d83cc..4279a9b 100644 (file)
@@ -16,6 +16,11 @@ BEGIN {
   else {
     require mro;
   }
+
+  *SQL::Abstract::_ENV_::DETECT_AUTOGENERATED_STRINGIFICATION = $ENV{SQLA_ISVALUE_IGNORE_AUTOGENERATED_STRINGIFICATION}
+    ? sub () { 0 }
+    : sub () { 1 }
+  ;
 }
 
 #======================================================================
@@ -84,47 +89,51 @@ sub is_literal_value ($) {
 # FIXME XSify - this can be done so much more efficiently
 sub is_plain_value ($) {
   no strict 'refs';
-    ! length ref $_[0]                                        ? [ $_[0] ]
+    ! length ref $_[0]                                        ? \($_[0])
   : (
     ref $_[0] eq 'HASH' and keys %{$_[0]} == 1
       and
     exists $_[0]->{-value}
-  )                                                           ? [ $_[0]->{-value} ]
+  )                                                           ? \($_[0]->{-value})
   : (
-      Scalar::Util::blessed $_[0]
+      # reuse @_ for even moar speedz
+      defined ( $_[1] = Scalar::Util::blessed $_[0] )
         and
       # deliberately not using Devel::OverloadInfo - the checks we are
       # intersted in are much more limited than the fullblown thing, and
       # this is a very hot piece of code
       (
-        # FIXME - DBI needs fixing to stringify regardless of DBD
-        #
         # simply using ->can('(""') can leave behind stub methods that
         # break actually using the overload later (see L<perldiag/Stub
         # found while resolving method "%s" overloading "%s" in package
         # "%s"> and the source of overload::mycan())
         #
         # either has stringification which DBI SHOULD prefer out of the box
-        grep { *{ (qq[${_}::(""]) }{CODE} } @{ mro::get_linear_isa( ref $_[0] ) }
+        grep { *{ (qq[${_}::(""]) }{CODE} } @{ $_[2] = mro::get_linear_isa( $_[1] ) }
           or
-        # has nummification and fallback is *not* disabled
-        # reuse @_ for even moar speedz
+        # has nummification or boolification, AND fallback is *not* disabled
         (
-          grep { *{"${_}::(0+"}{CODE} } @{ mro::get_linear_isa( ref $_[0] ) }
+          SQL::Abstract::_ENV_::DETECT_AUTOGENERATED_STRINGIFICATION
+            and
+          (
+            grep { *{"${_}::(0+"}{CODE} } @{$_[2]}
+              or
+            grep { *{"${_}::(bool"}{CODE} } @{$_[2]}
+          )
             and
           (
             # no fallback specified at all
-            ! ( ($_[1]) = grep { *{"${_}::()"}{CODE} } @{ mro::get_linear_isa( ref $_[0] ) } )
+            ! ( ($_[3]) = grep { *{"${_}::()"}{CODE} } @{$_[2]} )
               or
             # fallback explicitly undef
-            ! defined ${"$_[1]::()"}
+            ! defined ${"$_[3]::()"}
               or
             # explicitly true
-            ${"$_[1]::()"}
+            !! ${"$_[3]::()"}
           )
         )
       )
-    )                                                          ? [ "$_[0]" ]
+    )                                                          ? \($_[0])
   : undef;
 }
 
@@ -488,9 +497,15 @@ sub _recurse_where {
 
   my ($sql, @bind) =  $self->$method($where, $logic);
 
-  # DBIx::Class directly calls _recurse_where in scalar context, so
-  # we must implement it, even if not in the official API
-  return wantarray ? ($sql, @bind) : $sql;
+  # DBIx::Class used to call _recurse_where in scalar context
+  # something else might too...
+  if (wantarray) {
+    return ($sql, @bind);
+  }
+  else {
+    belch "Calling _recurse_where in scalar context is deprecated and will go away before 2.0";
+    return $sql;
+  }
 }
 
 
@@ -738,8 +753,8 @@ sub _where_op_BOOL {
 sub _where_op_IDENT {
   my $self = shift;
   my ($op, $rhs) = splice @_, -2;
-  if (ref $rhs) {
-    puke "-$op takes a single scalar argument (a quotable identifier)";
+  if (! defined $rhs or length ref $rhs) {
+    puke "-$op requires a single plain scalar argument (a quotable identifier)";
   }
 
   # in case we are called as a top level special op (no '=')
@@ -1709,7 +1724,7 @@ say something like this:
 
     my %data = (
         name => 'Bill',
-        date_entered => \["to_date(?,'MM/DD/YYYY')", "03/02/2003"],
+        date_entered => \[ "to_date(?,'MM/DD/YYYY')", "03/02/2003" ],
     );
 
 The first value in the array is the actual SQL. Any other values are
@@ -1763,9 +1778,9 @@ Easy, eh?
 
 =head1 METHODS
 
-The methods are simple. There's one for each major SQL operation,
+The methods are simple. There's one for every major SQL operation,
 and a constructor you use first. The arguments are specified in a
-similar order to each method (table, then fields, then a where
+similar order for each method (table, then fields, then a where
 clause) to try and simplify things.
 
 =head2 new(option => 'value')
@@ -1910,7 +1925,7 @@ 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]>
+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.
 
@@ -2148,9 +2163,50 @@ module:
 
 =back
 
-On failure returns C<undef>, on sucess returns a reference to a single
-element array containing the string-version of the supplied argument or
-C<[ undef ]> in case of an undefined initial argument.
+On failure returns C<undef>, on sucess returns a B<scalar> reference
+to the original supplied argument.
+
+=over
+
+=item * Note
+
+The stringification overloading detection is rather advanced: it takes
+into consideration not only the presence of a C<""> overload, but if that
+fails also checks for enabled
+L<autogenerated versions of C<"">|overload/Magic Autogeneration>, based
+on either C<0+> or C<bool>.
+
+Unfortunately testing in the field indicates that this
+detection B<< may tickle a latent bug in perl versions before 5.018 >>,
+but only when very large numbers of stringifying objects are involved.
+At the time of writing ( Sep 2014 ) there is no clear explanation of
+the direct cause, nor is there a manageably small test case that reliably
+reproduces the problem.
+
+If you encounter any of the following exceptions in B<random places within
+your application stack> - this module may be to blame:
+
+  Operation "ne": no method found,
+    left argument in overloaded package <something>,
+    right argument in overloaded package <something>
+
+or perhaps even
+
+  Stub found while resolving method "???" overloading """" in package <something>
+
+If you fall victim to the above - please attempt to reduce the problem
+to something that could be sent to the L<SQL::Abstract developers
+|DBIx::Class/GETTING HELP/SUPPORT>
+(either publicly or privately). As a workaround in the meantime you can
+set C<$ENV{SQLA_ISVALUE_IGNORE_AUTOGENERATED_STRINGIFICATION}> to a true
+value, which will most likely eliminate your problem (at the expense of
+not being able to properly detect exotic forms of stringification).
+
+This notice and environment variable will be removed in a future version,
+as soon as the underlying problem is found and a reliable workaround is
+devised.
+
+=back
 
 =head2 is_literal_value
 
@@ -2167,8 +2223,8 @@ module:
 
 =back
 
-On failure returns C<undef>, on sucess returns a reference to an array
-cotaining the unpacked version of the supplied literal SQL and bind values.
+On failure returns C<undef>, on sucess returns an B<array> reference
+containing the unpacked version of the supplied literal SQL and bind values.
 
 =head1 WHERE CLAUSES
 
@@ -2294,7 +2350,7 @@ Which would generate:
     @bind = ('2', '5', 'nwiger');
 
 If you want to include literal SQL (with or without bind values), just use a
-scalar reference or array reference as the value:
+scalar reference or reference to an arrayref as the value:
 
     my %where  = (
         date_entered => { '>' => \["to_date(?, 'MM/DD/YYYY')", "11/26/2008"] },
@@ -2303,7 +2359,7 @@ scalar reference or array reference as the value:
 
 Which would generate:
 
-    $stmt = "WHERE date_entered > "to_date(?, 'MM/DD/YYYY') AND date_expires < now()";
+    $stmt = "WHERE date_entered > to_date(?, 'MM/DD/YYYY') AND date_expires < now()";
     @bind = ('11/26/2008');
 
 
@@ -2317,7 +2373,7 @@ this (notice the C<AND>):
 
 Because, in Perl you I<can't> do this:
 
-    priority => { '!=', 2, '!=', 1 }
+    priority => { '!=' => 2, '!=' => 1 }
 
 As the second C<!=> key will obliterate the first. The solution
 is to use the special C<-modifier> form inside an arrayref:
@@ -2509,10 +2565,10 @@ to change the logic inside :
 
 That would yield:
 
-    WHERE ( user = ? AND (
-               ( workhrs > ? AND geo = ? )
-            OR ( workhrs < ? OR geo = ? )
-          ) )
+    $stmt = "WHERE ( user = ?
+               AND ( ( workhrs > ? AND geo = ? )
+                  OR ( workhrs < ? OR geo = ? ) ) )";
+    @bind = ('nwiger', '20', 'ASIA', '50', 'EURO');
 
 =head3 Algebraic inconsistency, for historical reasons
 
@@ -2633,7 +2689,7 @@ not so common, but perfectly legal Perl). For example, to find a date
 in Postgres you can use something like this:
 
     my %where = (
-       date_column => \[q/= date '2008-09-30' - ?::integer/, 10/]
+       date_column => \[ "= date '2008-09-30' - ?::integer", 10 ]
     )
 
 This would create:
@@ -2642,15 +2698,16 @@ This would create:
     @bind = ('10');
 
 Note that you must pass the bind values in the same format as they are returned
-by L</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 value (including references and blessed references),
-L<SQL::Abstract> will simply pass it through intact. So if C<bindtype> is set
-to C<columns> the above example will look like:
+by L<where|/where(\%where, \@order)>. This 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 value
+(including references and blessed references), L<SQL::Abstract> will simply
+pass it through intact. So if C<bindtype> is set to C<columns> the above
+example will look like:
 
     my %where = (
-       date_column => \[q/= date '2008-09-30' - ?::integer/, [ dummy => 10 ]/]
+       date_column => \[ "= date '2008-09-30' - ?::integer", [ {} => 10 ] ]
     )
 
 Literal SQL is especially useful for nesting parenthesized clauses in the
@@ -2857,14 +2914,14 @@ Either a coderef or a plain scalar method name. In both cases
 the expected return is C<< ($sql, @bind) >>.
 
 When supplied with a method name, it is simply called on the
-L<SQL::Abstract/> object as:
+L<SQL::Abstract> object as:
 
  $self->$method_name ($field, $op, $arg)
 
  Where:
 
-  $op is the part that matched the handler regex
   $field is the LHS of the operator
+  $op is the part that matched the handler regex
   $arg is the RHS
 
 When supplied with a coderef, it is called as:
@@ -2933,7 +2990,7 @@ Either a coderef or a plain scalar method name. In both cases
 the expected return is C<< $sql >>.
 
 When supplied with a method name, it is simply called on the
-L<SQL::Abstract/> object as:
+L<SQL::Abstract> object as:
 
  $self->$method_name ($op, $arg)
 
@@ -3041,7 +3098,7 @@ The main changes are :
 
 =item *
 
-support for literal SQL through the C<< \ [$sql, bind] >> syntax.
+support for literal SQL through the C<< \ [ $sql, @bind ] >> syntax.
 
 =item *