Fix _select_for_update/delete - bring back old code, use subqueries only when results...
Peter Rabbitson [Wed, 13 May 2009 01:06:42 +0000 (01:06 +0000)]
lib/DBIx/Class/ResultSet.pm

index 903cb3e..4804dc7 100644 (file)
@@ -1312,10 +1312,58 @@ sub _cond_for_update_delete {
   # No-op. No condition, we're updating/deleting everything
   return $cond unless ref $full_cond;
 
-  foreach my $pk ($self->result_source->primary_columns) {
-      $cond->{$pk} = { -in => $self->get_column($pk)->as_query };
+  # Some attributes when present require a subquery
+  # This might not work on some database (mysql), but...
+  # it won't work without the subquery either so who cares
+  if (grep { defined $self->{attrs}{$_} } qw/join rows group_by/) {
+
+    foreach my $pk ($self->result_source->primary_columns) {
+      $cond->{$pk} = { IN => $self->get_column($pk)->as_query };
+    }
+
+    return $cond;
   }
 
+  if (ref $full_cond eq 'ARRAY') {
+    $cond = [
+      map {
+        my %hash;
+        foreach my $key (keys %{$_}) {
+          $key =~ /([^.]+)$/;
+          $hash{$1} = $_->{$key};
+        }
+        \%hash;
+      } @{$full_cond}
+    ];
+  }
+  elsif (ref $full_cond eq 'HASH') {
+    if ((keys %{$full_cond})[0] eq '-and') {
+      $cond->{-and} = [];
+      my @cond = @{$full_cond->{-and}};
+       for (my $i = 0; $i < @cond; $i++) {
+        my $entry = $cond[$i];
+        my $hash;
+        if (ref $entry eq 'HASH') {
+          $hash = $self->_cond_for_update_delete($entry);
+        }
+        else {
+          $entry =~ /([^.]+)$/;
+          $hash->{$1} = $cond[++$i];
+        }
+        push @{$cond->{-and}}, $hash;
+      }
+    }
+    else {
+      foreach my $key (keys %{$full_cond}) {
+        $key =~ /([^.]+)$/;
+        $cond->{$1} = $full_cond->{$key};
+      }
+    }
+  }
+  else {
+    $self->throw_exception("Can't update/delete on resultset with condition unless hash or array");
+  }
   return $cond;
 }