delete from, update using, join using
Matt S Trout [Sat, 13 Apr 2019 04:16:38 +0000 (04:16 +0000)]
lib/SQL/Abstract/Clauses.pm
lib/SQL/Abstract/ExtraClauses.pm
xt/clauses.t

index 2f6619a..b12dbca 100644 (file)
@@ -91,7 +91,7 @@ sub _expand_select_clause_order_by {
 
 sub _expand_update_clause_target {
   my ($self, $target) = @_;
-  +(target => $self->expand_expr($target, -ident));
+  +(target => $self->_expand_maybe_list_expr($target, -ident));
 }
 
 sub _expand_update_clause_set {
index 78680da..b874be5 100644 (file)
@@ -27,6 +27,12 @@ sub new {
   $new->{expand_op}{as} = '_expand_op_as';
   $new->{expand}{as} = '_expand_op_as';
   $new->{render}{as} = '_render_as';
+  splice(@{$new->{clauses_of}{update}}, 2, 0, 'from');
+  splice(@{$new->{clauses_of}{delete}}, 1, 0, 'using');
+  $new->{expand_clause}{'update.from'} = '_expand_select_clause_from';
+  $new->{expand_clause}{'delete.using'} = sub {
+    +(using => $_[0]->_expand_from_list(undef, $_[1]));
+  };
   return $new;
 }
 
@@ -71,6 +77,12 @@ sub _expand_join {
   if (my $as = delete $proto{as}) {
     $proto{to} = { -as => [ $proto{to}, ref($as) eq 'ARRAY' ? @$as : $as ] };
   }
+  if (defined($proto{using}) and ref(my $using = $proto{using}) ne 'HASH') {
+    $proto{using} = { -row => [
+      map [ $self->expand_expr($_, -ident) ],
+        ref($using) eq 'ARRAY' ? @$using: $using
+    ] };
+  }
   my %ret = map +($_ => $self->expand_expr($proto{$_}, -ident)),
               sort keys %proto;
   return +{ -join => \%ret };
@@ -95,7 +107,7 @@ sub _render_join {
       )
     ],
     [ $self->render_aqt(
-        map +($_->{-ident} or $_->{-as} ? $_ : { -row => [ $_ ] }), $args->{to}
+        map +($_->{-ident} || $_->{-as} ? $_ : { -row => [ $_ ] }), $args->{to}
     ) ],
     ($args->{on} ? (
       [ $self->_sqlcase('on') ],
index 5546d86..450b616 100644 (file)
@@ -38,4 +38,54 @@ is_same_sql_bind(
 
 is_same_sql($sql, q{SELECT a FROM (VALUES (1, 2), (3, 4)) AS t(a,b)});
 
+($sql) = $sqlac->update({
+  update => 'employees',
+  set => { sales_count => { sales_count => { '+', \1 } } },
+  from => 'accounts',
+  where => {
+    'accounts.name' => { '=' => \"'Acme Corporation'" },
+    'employees.id' => { -ident => 'accounts.sales_person' },
+  }
+});
+
+is_same_sql(
+  $sql,
+  q{UPDATE employees SET sales_count = sales_count + 1 FROM accounts
+    WHERE accounts.name = 'Acme Corporation'
+    AND employees.id = accounts.sales_person
+  }
+);
+
+($sql) = $sqlac->update({
+  update => [ qw(tab1 tab2) ],
+  set => {
+    'tab1.column1' => { -ident => 'value1' },
+    'tab1.column2' => { -ident => 'value2' },
+  },
+  where => { 'tab1.id' => { -ident => 'tab2.id' } },
+});
+
+is_same_sql(
+  $sql,
+  q{UPDATE tab1, tab2 SET tab1.column1 = value1, tab1.column2 = value2
+     WHERE tab1.id = tab2.id}
+);
+
+is_same_sql(
+  $sqlac->delete({
+    from => 'x',
+    using => 'y',
+    where => { 'x.id' => { -ident => 'y.x_id' } }
+  }),
+  q{DELETE FROM x USING y WHERE x.id = y.x_id}
+);
+
+is_same_sql(
+  $sqlac->select({
+    select => [ 'x.*', 'y.*' ],
+    from => [ 'x', -join => [ 'y', using => 'y_id' ] ],
+  }),
+  q{SELECT x.*, y.* FROM x JOIN y USING (y_id)},
+);
+
 done_testing;