]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
added unit test for the old commit that was in [changeset:1186]. modified its behavi...
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 31 Mar 2006 23:43:20 +0000 (23:43 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 31 Mar 2006 23:43:20 +0000 (23:43 +0000)
lib/sqlalchemy/mapping/properties.py
lib/sqlalchemy/mapping/unitofwork.py
test/objectstore.py

index fa14dc4deb2f84f64462a1da6866c761196ae1de..6d30c5ffe8d0d0dc05c55d97b3885cc96daf697a 100644 (file)
@@ -451,7 +451,10 @@ class PropertyLoader(MapperProperty):
                     for child in childlist.deleted_items() + childlist.unchanged_items():
                         if child is None:
                             continue
-                        uowcommit.register_object(child, isdelete=True)
+                        # if private child object, and is in the uow's "deleted" list,
+                        # insure its in the list of items to be deleted
+                        if child in uowcommit.uow.deleted:
+                            uowcommit.register_object(child, isdelete=True)
             elif self.post_update:
                 # post_update means we have to update our row to not reference the child object
                 # before we can DELETE the row
@@ -462,16 +465,15 @@ class PropertyLoader(MapperProperty):
             # head object is being deleted, and we manage its list of child objects
             # the child objects have to have their foreign key to the parent set to NULL
             if self.private and not self.post_update:
-                # if we are privately managed, then all our objects should
-                # have been marked as "todelete" already and no attribute adjustment is needed.
-                # however, if they say objectstore.commit(x), i.e. on an individual object,
-                # then this extra step is more important.
                 for obj in deplist:
                     childlist = getlist(obj, False)
                     for child in childlist.deleted_items() + childlist.unchanged_items():
                         if child is None:
                             continue
-                        uowcommit.register_object(child, isdelete=True)
+                        # if private child object, and is in the uow's "deleted" list,
+                        # insure its in the list of items to be deleted
+                        if child in uowcommit.uow.deleted:
+                            uowcommit.register_object(child, isdelete=True)
             else:
                 for obj in deplist:
                     childlist = getlist(obj, False)
@@ -529,8 +531,6 @@ class PropertyLoader(MapperProperty):
                     for child in childlist.deleted_items():
                         if not self.private:
                             self._synchronize(obj, child, None, True)
-                        if self.direction == PropertyLoader.ONETOMANY:
-                            # for a cyclical task, this registration is handled by the objectstore
                             uowcommit.register_object(child, isdelete=self.private)
 
     def execute(self, instance, row, identitykey, imap, isnew):
index 1eea546df7d11cb790b0137f865b45595d856fe7..7c3ca8fd70eb91e2a4978faf4ba740746b5a84ff 100644 (file)
@@ -44,7 +44,8 @@ class UOWListElement(attributes.ListElement):
     def list_value_changed(self, obj, key, item, listval, isdelete):
         sess = get_session(obj)
         if not isdelete and sess.deleted.contains(item):
-            raise InvalidRequestError("re-inserting a deleted value into a list")
+            #raise InvalidRequestError("re-inserting a deleted value into a list")
+            del sess.deleted[item]
         sess.modified_lists.append(self)
         if self.deleteremoved and isdelete:
             sess.register_deleted(item)
index 73bbc1da432f3cbdb399e6890b65038421a9d1a1..44945dcbd5cc5a9c36b739e6e8e5eac19137dd86 100644 (file)
@@ -263,6 +263,79 @@ class PKTest(AssertMixin):
         e.assigned = datetime.date.today()
         e.data = 'some more data'
         objectstore.commit()
+
+class PrivateAttrTest(AssertMixin):
+    """tests various things to do with private=True mappers"""
+    def setUpAll(self):
+        global a_table, b_table
+        a_table = Table('a',testbase.db,
+            Column('a_id', Integer, Sequence('next_a_id'), primary_key=True),
+            Column('data', String(10)),
+            ).create()
+    
+        b_table = Table('b',testbase.db,
+            Column('b_id',Integer,Sequence('next_b_id'),primary_key=True),
+            Column('a_id',Integer,ForeignKey('a.a_id')),
+            Column('data',String(10))).create()
+    def tearDownAll(self):
+        b_table.drop()
+        a_table.drop()
+    def setUp(self):
+        objectstore.clear()
+        clear_mappers()
+    
+    def testsinglecommit(self):
+        """tests that a commit of a single object deletes private relationships"""
+        class A(object):pass
+        class B(object):pass
+    
+        assign_mapper(B,b_table)
+        assign_mapper(A,a_table,properties= {'bs' : relation 
+        (B.mapper,private=True)})
+    
+        # create some objects
+        a = A(data='a1')
+        a.bs = []
+    
+        # add a 'B' instance
+        b1 = B(data='1111')
+        a.bs.append(b1)
+    
+        # add another one
+        b2 = B(data='2222')
+        a.bs.append(b2)
+    
+        # inserts both A and Bs
+        objectstore.commit(a)
+    
+        objectstore.delete(a)
+        objectstore.commit(a)
+        
+        assert b_table.count().scalar() == 0
+
+    def testswitchparent(self):
+        """tests that you can switch the parent of an object in a backref scenario"""
+        class A(object):pass
+        class B(object):pass
+    
+        assign_mapper(B,b_table)
+        assign_mapper(A,a_table,properties= {
+            'bs' : relation (B.mapper,private=True, backref='a')}
+        )
+        a1 = A(data='testa1')
+        a2 = A(data='testa2')
+        b = B(data='testb')
+        b.a = a1
+        objectstore.commit()
+        objectstore.clear()
+        sess = objectstore.get_session()
+        a1 = A.mapper.get(a1.a_id)
+        a2 = A.mapper.get(a2.a_id)
+        assert a1.bs[0].a is a1
+        b = a1.bs[0]
+        b.a = a2
+        assert b not in sess.deleted
+        objectstore.commit()
         
 class DefaultTest(AssertMixin):
     """tests that when saving objects whose table contains DefaultGenerators, either python-side, preexec or database-side,