make list always parenthesised, make , op work for everything else
[scpubgit/Q-Branch.git] / lib / SQL / Abstract.pm
index 24b2396..6df60d8 100644 (file)
@@ -204,6 +204,10 @@ sub new {
     -bind => sub { shift; +{ @_ } },
     -in => '_expand_in',
     -not_in => '_expand_in',
+    -list => sub {
+      my ($self, $node, $args) = @_;
+      +{ $node => [ map $self->expand_expr($_), @$args ] };
+    },
   };
 
   $opt{expand_op} = {
@@ -244,6 +248,7 @@ sub new {
     ),
     (not => '_render_op_not'),
     (map +($_ => '_render_op_andor'), qw(and or)),
+    ',' => sub { shift->_render_op_multop(@_, 1) },
   };
 
   return bless \%opt, $class;
@@ -295,7 +300,7 @@ sub _returning {
   my $f = $options->{returning};
 
   my ($sql, @bind) = $self->render_aqt(
-    $self->_expand_maybe_list_expr($f, undef, -ident)
+    $self->_expand_maybe_list_expr($f, -ident)
   );
   return wantarray
     ? $self->_sqlcase(' returning ') . $sql
@@ -497,7 +502,7 @@ sub _select_fields {
   my ($self, $fields) = @_;
   return $fields unless ref($fields);
   return $self->render_aqt(
-    $self->_expand_maybe_list_expr($fields, undef, '-ident')
+    $self->_expand_maybe_list_expr($fields, '-ident')
   );
 }
 
@@ -1002,7 +1007,7 @@ sub _expand_in {
     my ($sql, @bind) = @$literal;
     my $opened_sql = $self->_open_outer_paren($sql);
     return +{ -op => [
-      $op, $self->_expand_ident(-ident => $k),
+      $op, $self->expand_expr($k, -ident),
       [ { -literal => [ $opened_sql, @bind ] } ]
     ] };
   }
@@ -1021,7 +1026,7 @@ sub _expand_in {
 
   return +{ -op => [
     $op,
-    $self->_expand_ident(-ident => $k),
+    $self->expand_expr($k, -ident),
     \@rhs
   ] };
 }
@@ -1073,8 +1078,8 @@ sub _render_ident {
 
 sub _render_list {
   my ($self, $list) = @_;
-  my @parts = grep length($_->[0]), map [ $self->render_aqt($_) ], @$list;
-  return join(', ', map $_->[0], @parts), map @{$_}[1..$#$_], @parts;
+  my ($sql, @bind) = $self->_render_op([ ',', @$list ]);
+  return "($sql)", @bind;  
 }
 
 sub _render_func {
@@ -1186,12 +1191,12 @@ sub _render_op_andor {
 }
 
 sub _render_op_multop {
-  my ($self, $op, $args) = @_;
+  my ($self, $op, $args, $strip_left) = @_;
   my @parts = grep length($_->[0]), map [ $self->render_aqt($_) ], @$args;
   return '' unless @parts;
   return @{$parts[0]} if @parts == 1;
   my ($final_sql) = join(
-    ' '.$self->_sqlcase(join ' ', split '_', $op).' ',
+    ($strip_left ? '' : ' ').$self->_sqlcase(join ' ', split '_', $op).' ',
     map $_->[0], @parts
   );
   return (
@@ -1277,7 +1282,9 @@ sub _expand_order_by {
               ),
                 map $self->expand_expr($_, -ident),
                 map ref($_) eq 'ARRAY' ? @$_ : $_, @to_expand;
-    return (@exp > 1 ? { -list => \@exp } : $exp[0]);
+    return undef unless @exp;
+    return undef if @exp == 1 and not defined($exp[0]);
+    return +{ -op => [ ',', @exp ] };
   };
 
   local @{$self->{expand}}{qw(-asc -desc)} = (($expander) x 2);
@@ -1316,8 +1323,9 @@ sub _chunkify_order_by {
     if $expanded->{-ident} or @{$expanded->{-literal}||[]} == 1;
 
   for ($expanded) {
-    if (ref() eq 'HASH' and my $l = $_->{-list}) {
-      return map $self->_chunkify_order_by($_), @$l;
+    if (ref() eq 'HASH' and $_->{-op} and $_->{-op}[0] eq ',') {
+      my ($comma, @list) = @{$_->{-op}};
+      return map $self->_chunkify_order_by($_), @list;
     }
     return [ $self->render_aqt($_) ];
   }
@@ -1331,7 +1339,7 @@ sub _table  {
   my $self = shift;
   my $from = shift;
   ($self->render_aqt(
-    $self->_expand_maybe_list_expr($from, undef, -ident)
+    $self->_expand_maybe_list_expr($from, -ident)
   ))[0];
 }
 
@@ -1341,18 +1349,11 @@ sub _table  {
 #======================================================================
 
 sub _expand_maybe_list_expr {
-  my ($self, $expr, $logic, $default) = @_;
-  my $e = do {
-    if (ref($expr) eq 'ARRAY') {
-      return { -list => [
-        map $self->expand_expr($_, $default), @$expr
-      ] } if @$expr > 1;
-      $expr->[0]
-    } else {
-      $expr
-    }
-  };
-  return $self->expand_expr($e, $default);
+  my ($self, $expr, $default) = @_;
+  return +{ -op => [ ',',
+    map $self->expand_expr($_, $default),
+      ref($expr) eq 'ARRAY' ? @$expr : $expr
+  ] };
 }
 
 # highly optimized, as it's called way too often