]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed a bug with the unitofwork's "row switch" mechanism,
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 13 Jan 2009 06:11:17 +0000 (06:11 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 13 Jan 2009 06:11:17 +0000 (06:11 +0000)
i.e. the conversion of INSERT/DELETE into an UPDATE, when
combined with joined-table inheritance and an object
which contained no defined values for the child table where
an UPDATE with no SET clause would be rendered.

CHANGES
lib/sqlalchemy/orm/mapper.py
test/orm/unitofwork.py

diff --git a/CHANGES b/CHANGES
index 35c0032f27e3b0aa13006b80ad71b988ec744ce7..409e25340f8b5928b5337ee8d47f4a8220efe3c6 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -40,6 +40,12 @@ CHANGES
     - ColumnProperty (and front-end helpers such as ``deferred``) no
       longer ignores unknown **keyword arguments.
 
+    - Fixed a bug with the unitofwork's "row switch" mechanism,
+      i.e. the conversion of INSERT/DELETE into an UPDATE, when
+      combined with joined-table inheritance and an object
+      which contained no defined values for the child table where
+      an UPDATE with no SET clause would be rendered.
+      
 - schema
     - Index now accepts column-oriented InstrumentedAttributes
       (i.e. column-based mapped class attributes) as column
index 04fc9d0ef1381691e3005c69bbc2a21e472e33ee..6bcc89b3c23cf96d1319beed23d6d877b7017f6f 100644 (file)
@@ -1305,13 +1305,15 @@ class Mapper(object):
                                 if col in pks:
                                     if history.deleted:
                                         params[col._label] = prop.get_col_value(col, history.deleted[0])
+                                        hasdata = True
                                     else:
                                         # row switch logic can reach us here
                                         # remove the pk from the update params so the update doesn't
                                         # attempt to include the pk in the update statement
                                         del params[col.key]
                                         params[col._label] = prop.get_col_value(col, history.added[0])
-                                hasdata = True
+                                else:
+                                    hasdata = True
                             elif col in pks:
                                 params[col._label] = mapper._get_state_attr_by_column(state, col)
                     if hasdata:
index a4363b5e5ff2a06a686a7676033e7da59c1db4bc..553713da539fe233bcbe1d1f2d9d793463d9e331 100644 (file)
@@ -2216,6 +2216,49 @@ class RowSwitchTest(_base.MappedTest):
         assert list(sess.execute(t5.select(), mapper=T5)) == [(2, 'some other t5')]
         assert list(sess.execute(t6.select(), mapper=T5)) == [(1, 'some other t6', 2)]
 
+class InheritingRowSwitchTest(_base.MappedTest):
+    def define_tables(self, metadata):
+        Table('parent', metadata,
+            Column('id', Integer, primary_key=True),
+            Column('pdata', String(30))
+        )
+        Table('child', metadata,
+            Column('id', Integer, primary_key=True),
+            Column('pid', Integer, ForeignKey('parent.id')),
+            Column('cdata', String(30))
+        )
+
+    def setup_classes(self):
+        class P(_base.ComparableEntity):
+            pass
+
+        class C(P):
+            pass
+    
+    @testing.resolve_artifact_names
+    def test_row_switch_no_child_table(self):
+        mapper(P, parent)
+        mapper(C, child, inherits=P)
+        
+        sess = create_session()
+        c1 = C(id=1, pdata='c1', cdata='c1')
+        sess.add(c1)
+        sess.flush()
+        
+        # establish a row switch between c1 and c2.
+        # c2 has no value for the "child" table
+        c2 = C(id=1, pdata='c2')
+        sess.add(c2)
+        sess.delete(c1)
+
+        self.assert_sql_execution(testing.db, sess.flush,
+            CompiledSQL("UPDATE parent SET pdata=:pdata WHERE parent.id = :parent_id",
+                {'pdata':'c2', 'parent_id':1}
+            )
+        )
+        
+        
+
 class TransactionTest(_base.MappedTest):
     __requires__ = ('deferrable_constraints',)