Changeset 3272

Show
Ignore:
Timestamp:
05/30/07 15:57:52 (1 year ago)
Author:
mscott
Message:

Correct the cascade delete implementation.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/Schevo/schevo/transaction.py

    r3266 r3272  
    376376 
    377377 
    378 def find_chains(entity): 
    379     db = entity.sys.db 
    380     traversed = set() 
    381     chains = [] 
    382     _find_chains(db, entity, traversed, chains) 
    383     return chains 
    384  
    385  
    386 def _find_chains(db, entity, traversed, chains, chain=None): 
    387     if chain is None: 
    388         chain = [] 
    389     chain.append(entity) 
    390     if entity in traversed: 
    391         chains.append(chain) 
    392         return 
    393     traversed.add(entity) 
    394     entity_extent_name = entity._extent.name 
    395     for (e_name, f_name), others in entity.sys.links().iteritems(): 
    396         extent = db.extent(e_name) 
    397         for referrer in others: 
    398             _find_chains(db, referrer, traversed, chains, chain) 
    399  
    400  
    401378class Delete(Transaction): 
    402379    """Delete an existing entity instance.""" 
     
    451428        # also requesting cascade deletion. 
    452429        restricter_keys = set(restricters) - set(cascaders) 
    453         # Starting at the entity whose deletion is requested, find 
    454         # chains of circular references that contain that entity, and 
    455         # make sure they are not in the restricters. 
    456         chains = find_chains(entity) 
    457         for chain in chains: 
    458             if chain[0] == entity and chain[0] == chain[-1]: 
    459                 chain = frozenset(chain) 
    460                 for referrer, restricter_set in restricters.iteritems(): 
    461                     for f_name, referred in frozenset(restricter_set): 
    462                         if referred in chain: 
    463                             restricter_set.remove((f_name, referred)) 
    464                     if len(restricter_set) == 0: 
    465                         restricter_keys.discard(referrer) 
     430        # The entity whose deletion was requested should never be 
     431        # considered a restricter. 
     432        restricter_keys.discard(entity) 
    466433        if len(restricter_keys) != 0: 
    467434            # Raise DeleteRestricted if there are any restricters left 
     
    522489                    extent_name, oid, field_dump_map, field_related_entity_map) 
    523490            referrers.add((extent_name, oid, referrer)) 
     491        # Everything checks out okay for this entity, so add it to the 
     492        # set of deleted entities. 
     493        deletes.add((entity.__class__, entity._oid)) 
    524494        # Delete entities in a deterministic (sorted) fashion. 
    525         deletes.add((entity.__class__, entity._oid)) 
    526495        for extent_name, oid, referrer in sorted(referrers): 
    527496            referrer_e_o = referrer.__class__, referrer._oid 
  • trunk/Schevo/tests/test_on_delete.py

    r3268 r3272  
    416416        assert raises(error.DeleteRestricted, db.execute, tx) 
    417417 
    418     def test_cascade_bamm(self): 
     418    def test_restrict_bamm(self): 
    419419        bamm = db.execute(db.Bamm.t.create()) 
    420420        tx = bamm.t.delete() 
    421         db.execute(tx) 
    422         assert bamm not in db.Bamm 
     421        assert raises(error.DeleteRestricted, db.execute, tx) 
    423422 
    424423    def test_cascade_complex(self):