Changeset 312

Show
Ignore:
Timestamp:
03/24/08 21:10:57 (5 years ago)
Author:
cleverdevil
Message:

Two changes to the versioning extension:

  • Applied a patch resolving ticket 35, so that the extension respects the current transaction.
  • Added an optional check_concurrency keyword argument to the extension, supporting the usage of SQLAlchemy's built-in optimistic concurrency check.
Location:
elixir/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • elixir/trunk/elixir/ext/versioned.py

    r286 r312  
    3737The acts_as_versioned statement also accepts an optional `ignore` argument  
    3838that consists of a list of strings, specifying names of fields.  Changes in  
    39 those fields will not result in a version increment. 
     39those fields will not result in a version increment.  In addition, you can 
     40pass in an optional `check_concurrent` argument, which will use SQLAlchemy's 
     41built-in optimistic concurrency mechanisms.  
    4042 
    4143Note that relationships that are stored in mapping tables will not be included 
     
    104106                # the instance was really updated, so we create a new version 
    105107                colvalues = dict(values.items())  
    106                 instance.__class__.__history_table__.insert().execute(colvalues)  
     108                connection.execute(instance.__class__.__history_table__.insert(), colvalues) 
    107109                instance.version = instance.version + 1 
    108110                instance.timestamp = datetime.now() 
     
    112114         
    113115    def before_delete(self, mapper, connection, instance): 
    114         instance.__history_table__.delete( 
     116        connection.execute(instance.__history_table__.delete( 
    115117            get_history_where(instance) 
    116         ).execute() 
     118        )) 
    117119        return EXT_PASS 
    118120 
     
    127129class VersionedEntityBuilder(object): 
    128130         
    129     def __init__(self, entity, ignore=[]): 
     131    def __init__(self, entity, ignore=[], check_concurrent=False): 
    130132        entity._descriptor.add_mapper_extension(versioned_mapper_extension) 
    131133        self.entity = entity 
     134        self.check_concurrent = check_concurrent 
     135         
    132136        # Changes in these fields will be ignored 
    133137        entity.__ignored_fields__ = ignore 
     
    140144        self.entity._descriptor.add_column(version_col) 
    141145        self.entity._descriptor.add_column(timestamp_col) 
     146         
     147        # add a concurrent_version column to the entity, if required 
     148        if self.check_concurrent: 
     149            self.entity._descriptor.version_id_col = 'concurrent_version' 
    142150    
    143151    # we copy columns from the main entity table, so we need it to exist first 
    144152    def after_table(self): 
    145153        entity = self.entity 
    146  
     154         
    147155        # look for events 
    148156        after_revert_events = [] 
     
    153161        # create a history table for the entity 
    154162        #TODO: fail more noticeably in case there is a version col 
    155         columns = [column.copy() for column in entity.table.c  
    156                                  if column.name != 'version'] 
     163        columns = [ 
     164            column.copy() for column in entity.table.c  
     165            if column.name not in ('version', 'concurrent_version') 
     166        ] 
    157167        columns.append(Column('version', Integer, primary_key=True)) 
    158168        table = Table(entity.table.name + '_history', entity.table.metadata,  
     
    222232            differences = {} 
    223233            for column in self.c: 
    224                 if column.name == 'version': 
     234                if column.name in ('version', 'concurrent_version'): 
    225235                    continue 
    226236                this = getattr(self, column.name) 
  • elixir/trunk/tests/test_versioning.py

    r286 r312  
    145145        assert movie.version == 4 
    146146        assert movie.versions[-2].description == "description 3" 
     147 
     148        # Updates to the history table must be inside the transaction 
     149        session.begin() 
     150        movie = Movie(id=3, title='Foo', description='1') 
     151        session.commit(); 
     152         
     153        session.begin() 
     154        movie.description = '2' 
     155        session.flush() 
     156        session.rollback() 
     157        session.clear() 
     158         
     159        session.begin() 
     160        movie = Movie.get_by(title='Foo') 
     161        movie.description = '3' 
     162        session.commit() 
     163