1. paulgb
  2. sqlalchemy


Mike Bayer  committed 65b05cb

- MySQL's update does work. add some logic to compiler to convert from ORM column to Table column

  • Participants
  • Parent commits 49ea0b2
  • Branches default

Comments (0)

Files changed (3)


View file
     and if the parent table is referenced in the
     WHERE clause, the compiler will call upon
     UPDATE..FROM syntax as allowed by the dialect
-    to satisfy the WHERE clause.  Target columns
-    must still be in the target table i.e.
-    does not support MySQL's multi-table update
-    feature (even though this is in Core).
+    to satisfy the WHERE clause.  MySQL's multi-table
+    update feature is also supported if columns
+    are specified by object in the "values" dicitionary.
     PG's DELETE..USING is also not available
     in Core yet.

File lib/sqlalchemy/sql/compiler.py

View file
         # special logic that only occurs for multi-table UPDATE
         # statements
         if extra_tables and stmt.parameters:
+            normalized_params = dict(
+                (sql._clause_element_as_expr(c), param)
+                for c, param in stmt.parameters.items()
+            )
             assert self.isupdate
             affected_tables = set()
             for t in extra_tables:
                 for c in t.c:
-                    if c in stmt.parameters:
+                    if c in normalized_params:
                         check_columns[c.key] = c
-                        value = stmt.parameters[c]
+                        value = normalized_params[c]
                         if sql._is_literal(value):
                             value = self._create_crud_bind_param(
                                             c, value, required=value is required)
             # server_onupdate for these
             for t in affected_tables:
                 for c in t.c:
-                    if c in stmt.parameters:
+                    if c in normalized_params:
                     elif c.onupdate is not None and not c.onupdate.is_sequence:
                         if c.onupdate.is_clause_element:

File test/orm/test_update_delete.py

View file
             set([('e1', 'e1', ), ('e2', 'e5')])
+    @testing.only_on('mysql', 'Multi table update')
+    def test_update_from_multitable(self):
+        Engineer = self.classes.Engineer
+        Person = self.classes.Person
+        s = Session(testing.db)
+        s.query(Engineer).filter(Engineer.id == Person.id).\
+            filter(Person.name == 'e2').update({Person.name: 'e22',
+                                Engineer.engineer_name: 'e55'})
+        eq_(
+            set(s.query(Person.name, Engineer.engineer_name)),
+            set([('e1', 'e1', ), ('e22', 'e55')])
+        )