Merge 'trunk' into 'prefetch_bug-unqualified_column_in_search_related_cond'
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI.pm
index 96a9478..aab6f31 100644 (file)
@@ -1549,20 +1549,43 @@ sub _dbh_execute_inserts_with_no_binds {
 }
 
 sub update {
-  my ($self, $source, @args) = @_; 
+  my ($self, $source, $data, $where, @args) = @_; 
 
   my $bind_attrs = $self->source_bind_attributes($source);
+  $where = $self->_strip_cond_qualifiers ($where);
 
-  return $self->_execute('update' => [], $source, $bind_attrs, @args);
+  return $self->_execute('update' => [], $source, $bind_attrs, $data, $where, @args);
 }
 
 
 sub delete {
-  my ($self, $source, @args) = @_; 
+  my ($self, $source, $where, @args) = @_;
 
   my $bind_attrs = $self->source_bind_attributes($source);
+  $where = $self->_strip_cond_qualifiers ($where);
 
-  return $self->_execute('delete' => [], $source, $bind_attrs, @args);
+  return $self->_execute('delete' => [], $source, $bind_attrs, $where, @args);
+}
+
+# Most databases do not allow aliasing of tables in UPDATE/DELETE. Thus
+# a condition containing 'me' or other table prefixes will not work
+# at all. Since we employ subqueries when multiple tables are involved
+# (joins), it is relatively safe to strip all column qualifiers. Worst
+# case scenario the error message will be a bit misleading, if the
+# user supplies a foreign qualifier without a join (the message would
+# be "can't find column X", when in fact the user shoud join T containing
+# T.X)
+sub _strip_cond_qualifiers {
+  my ($self, $where) = @_;
+
+  my $sqlmaker = $self->sql_maker;
+  my ($sql, @bind) = $sqlmaker->_recurse_where($where);
+  return undef unless $sql;
+
+  my ($qquot, $qsep) = map { quotemeta $_ } ( ($sqlmaker->quote_char||''), ($sqlmaker->name_sep||'.') );
+  $sql =~ s/ (?: $qquot [\w\-]+ $qquot | [\w\-]+ ) $qsep //gx;
+
+  return \[$sql, @bind];
 }
 
 # We were sent here because the $rs contains a complex search