Warn about deprecation of and/or/nestX
[dbsrgits/SQL-Abstract.git] / lib / SQL / Abstract.pm
index ea890ce..65b5011 100644 (file)
@@ -442,11 +442,17 @@ sub _where_HASHREF {
 
 
 sub _where_op_in_hash {
-  my ($self, $op, $v) = @_; 
+  my ($self, $op_str, $v) = @_; 
+
+  $op_str =~ /^ (AND|OR|NEST) ( \_? \d* ) $/xi
+    or puke "unknown operator: -$op_str";
+
+  my $op = uc($1); # uppercase, remove trailing digits
+  if ($2) {
+    belch 'Use of [and|or|nest]_N modifiers is deprecated and will be removed in SQLA v2.0. '
+          . "You probably wanted ...-and => [ $op_str => COND1, $op_str => COND2 ... ]";
+  }
 
-  $op =~ /^(AND|OR|NEST)[_\d]*/i
-    or puke "unknown operator: -$op";
-  $op = uc($1); # uppercase, remove trailing digits
   $self->_debug("OP(-$op) within hashref, recursing...");
 
   $self->_SWITCH_refkind($v, {
@@ -499,11 +505,17 @@ sub _where_hashpair_ARRAYREF {
     $self->_debug("ARRAY($k) means distribute over elements");
 
     # put apart first element if it is an operator (-and, -or)
-    my $op = $v[0] =~ /^-/ ? shift @v : undef;
-    $self->_debug("OP($op) reinjected into the distributed array") if $op;
-
+    my $op = ($v[0] =~ /^ - (?: AND|OR ) $/ix
+      ? shift @v
+      : ''
+    );
     my @distributed = map { {$k =>  $_} } @v;
-    unshift @distributed, $op if $op;
+
+    if ($op) {
+      $self->_debug("OP($op) reinjected into the distributed array");
+      unshift @distributed, $op;
+    }
+
     my $logic = $op ? substr($op, 1) : '';
 
     return $self->_recurse_where(\@distributed, $logic);
@@ -1734,29 +1746,6 @@ Here is a quick list of equivalencies, since there is some overlap:
     status => [ -or => {'=', 'assigned'}, {'=', 'in-progress'}]
     status => [ {'=', 'assigned'}, {'=', 'in-progress'} ]
 
-In addition to C<-and> and C<-or>, there is also a special C<-nest>
-operator which adds an additional set of parens, to create a subquery.
-For example, to get something like this:
-
-    $stmt = "WHERE user = ? AND ( workhrs > ? OR geo = ? )";
-    @bind = ('nwiger', '20', 'ASIA');
-
-You would do:
-
-    my %where = (
-         user => 'nwiger',
-        -nest => [ workhrs => {'>', 20}, geo => 'ASIA' ],
-    );
-
-If you need several nested subexpressions, you can number
-the C<-nest> branches :
-
-    my %where = (
-         user => 'nwiger',
-        -nest1 => ...,
-        -nest2 => ...,
-        ...
-    );
 
 
 =head2 Special operators : IN, BETWEEN, etc.
@@ -1794,7 +1783,7 @@ Would give you:
 These are the two builtin "special operators"; but the 
 list can be expanded : see section L</"SPECIAL OPERATORS"> below.
 
-=head2 Nested conditions
+=head2 Nested conditions, -and/-or prefixes
 
 So far, we've seen how multiple conditions are joined with a top-level
 C<AND>.  We can change this by putting the different conditions we want in
@@ -1817,8 +1806,23 @@ This data structure would create the following:
                 OR ( user = ? AND status = ? ) )";
     @bind = ('nwiger', 'pending', 'dispatched', 'robot', 'unassigned');
 
-This can be combined with the C<-nest> operator to properly group
-SQL statements. Furthermore, hashrefs or arrayrefs can be
+
+There is also a special C<-nest>
+operator which adds an additional set of parens, to create a subquery.
+For example, to get something like this:
+
+    $stmt = "WHERE user = ? AND ( workhrs > ? OR geo = ? )";
+    @bind = ('nwiger', '20', 'ASIA');
+
+You would do:
+
+    my %where = (
+         user => 'nwiger',
+        -nest => [ workhrs => {'>', 20}, geo => 'ASIA' ],
+    );
+
+
+Finally, clauses in hashrefs or arrayrefs can be
 prefixed with an C<-and> or C<-or> to change the logic
 inside :
 
@@ -1838,6 +1842,9 @@ That would yield:
           ( ( workhrs > ? AND geo = ? )
          OR ( workhrs < ? AND geo = ? ) ) )
 
+
+=head2 Algebraic inconsistency, for historical reasons
+
 C<Important note>: when connecting several conditions, the C<-and->|C<-or>
 operator goes C<outside> of the nested structure; whereas when connecting
 several constraints on one column, the C<-and> operator goes
@@ -1855,6 +1862,16 @@ yielding
             OR ( c = ? OR d = ? ) 
             OR ( e LIKE ? AND e LIKE ? ) ) )
 
+This difference in syntax is unfortunate but must be preserved for
+historical reasons. So be careful : the two examples below would
+seem algebraically equivalent, but they are not
+
+  {col => [-and => {-like => 'foo%'}, {-like => '%bar'}]} 
+  # yields : WHERE ( ( col LIKE ? AND col LIKE ? ) )
+
+  [-and => {col => {-like => 'foo%'}, {col => {-like => '%bar'}}]] 
+  # yields : WHERE ( ( col LIKE ? OR col LIKE ? ) )
+
 
 =head2 Literal SQL