API reference¶
sqlalchemy_continuum.make_versioned(mapper=sa.orm.Mapper, session=sa.orm.session.Session, manager=versioning_manager, plugins=None, options=None, user_cls='User')
¶
This is the public API function of SQLAlchemy-Continuum for making certain mappers and sessions versioned. By default this applies to all mappers and all sessions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapper
|
SQLAlchemy mapper to apply the versioning to. |
Mapper
|
|
session
|
SQLAlchemy session to apply the versioning to. By default this is sa.orm.session.Session meaning it applies to all Session subclasses. |
Session
|
|
manager
|
SQLAlchemy-Continuum versioning manager. |
versioning_manager
|
|
plugins
|
Plugins to pass for versioning manager. |
None
|
|
options
|
A dictionary of VersioningManager options. |
None
|
|
user_cls
|
User class which the Transaction class should have relationship to. This can either be a class or string name of a class for lazy evaluation. |
'User'
|
Versioning Manager¶
sqlalchemy_continuum.manager.VersioningManager
¶
VersioningManager delegates versioning configuration operations to builder classes and the actual versioning to UnitOfWork class. Manager contains configuration options that act as defaults for all versioned classes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
unit_of_work_cls
|
The UnitOfWork class to use for initializing UnitOfWork objects for versioning |
UnitOfWork
|
|
transaction_cls
|
Transaction class to use for versioning. If None, the default Transaction class generated by TransactionFactory will be used. |
None
|
|
user_cls
|
User class which Transaction class should have relationship to. This can either be a class or string name of a class for lazy evaluation. |
None
|
|
options
|
Versioning options |
None
|
|
plugins
|
Versioning plugins that listen the events invoked by the manager. |
None
|
|
builder
|
Builder object which handles the building of versioning tables and models. |
None
|
after_flush(session, flush_context)
¶
After flush listener for SQLAlchemy sessions. If this manager has versioning enabled this listener gets the UnitOfWork associated with session's connections and invokes the process_after_flush method of that object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session |
required |
append_association_operation(conn, table_name, params, op)
¶
Append history association operation to pending_statements list.
apply_class_configuration_listeners(mapper)
¶
Applies class configuration listeners for given mapper.
The listener work in two phases:
- Class instrumentation phase The first listeners listens to class instrumentation event and handles the collecting of versioned models and adds them to the pending_classes list.
- After class configuration phase The second listener listens to after class configuration event and handles the actual history model generation based on list that was collected during class instrumenation phase.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapper
|
SQLAlchemy mapper to apply the class configuration listeners to |
required |
before_flush(session, flush_context, instances)
¶
Before flush listener for SQLAlchemy sessions. If this manager has versioning enabled this listener invokes the process before flush of associated UnitOfWork object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session |
required |
clear(session)
¶
Simple SQLAlchemy listener that is being invoked after successful transaction commit or when transaction rollback occurs. The purpose of this listener is to reset this UnitOfWork back to its initialization state.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session object |
required |
create_transaction_model()
¶
Create Transaction class but only if it doesn't already exist in declarative model registry.
is_excluded_property(model, key)
¶
Returns whether or not given property of given model is excluded from the associated history model.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
SQLAlchemy declarative model object. |
required | |
key
|
Model property key |
required |
option(model, name)
¶
Returns the option value for given model. If the option is not found from given model falls back to default values of this manager object. If the option is not found from this manager object either this method throws a KeyError.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
model
|
SQLAlchemy declarative object |
required | |
name
|
name of the versioning option |
required |
remove_class_configuration_listeners(mapper)
¶
Remove versioning class configuration listeners from specified mapper.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapper
|
mapper to remove class configuration listeners from |
required |
remove_operations_tracking(mapper)
¶
Remove listeners from specified mapper that track SQL inserts, updates and deletes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapper
|
mapper to remove the SQL operations tracking listeners from |
required |
remove_session_tracking(session)
¶
Remove listeners that track the operations (flushing, committing and
rolling back) of given session. This method should be used in
conjunction with remove_operations_tracking.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session to remove the operations tracking from |
required |
reset()
¶
Resets this manager's internal state.
This method should be used in test cases that create models on the fly. Otherwise history_class_map and some other variables would be polluted by no more used model classes.
track_cloned_connections(c, opt)
¶
Track cloned connections from association tables.
track_deletes(uow, target)
¶
Track object deletion operations. Whenever object is deleted it is added to this UnitOfWork's internal operations dictionary.
track_inserts(uow, target)
¶
Track object insert operations. Whenever object is inserted it is added to this UnitOfWork's internal operations dictionary.
track_operations(mapper)
¶
Attach listeners for specified mapper that track SQL inserts, updates and deletes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mapper
|
mapper to track the SQL operations from |
required |
track_session(session)
¶
Attach listeners that track the operations (flushing, committing and
rolling back) of given session. This method should be used in
conjunction with track_operations.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session to track the operations from |
required |
track_updates(uow, target)
¶
Track object update operations. Whenever object is updated it is added to this UnitOfWork's internal operations dictionary.
unit_of_work(session)
¶
Return the associated SQLAlchemy-Continuum UnitOfWork object for given SQLAlchemy session object.
If no UnitOfWork object exists for given object then this method tries to create one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session object |
required |
Builders¶
sqlalchemy_continuum.table_builder.TableBuilder
¶
sqlalchemy_continuum.model_builder.ModelBuilder
¶
VersionedModelBuilder handles the building of Version models based on parent table attributes and versioning configuration.
__call__(table, tx_class)
¶
Build history model and relationships to parent model, transaction log model.
__init__(versioning_manager, model)
¶
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
versioning_manager
|
VersioningManager object |
required | |
model
|
SQLAlchemy declarative model object that acts as a parent for the built version model |
required |
base_classes()
¶
Returns all base classes for history model.
build_model(table)
¶
Build history model class.
build_parent_relationship()
¶
Builds a relationship between currently built version class and parent class (the model whose history the currently build version class represents).
build_transaction_relationship(tx_class)
¶
Builds a relationship between currently built version class and Transaction class.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
tx_class
|
Transaction class |
required |
inheritance_args(cls, version_table, table)
¶
Return mapper inheritance args for currently built history model.
sqlalchemy_continuum.relationship_builder.RelationshipBuilder
¶
__call__()
¶
Builds reflected relationship between version classes based on given parent object's RelationshipProperty.
association_subquery(obj)
¶
Returns an EXISTS clause that checks if an association exists for given SQLAlchemy declarative object. This query is used by many_to_many_criteria method.
Example query:
EXISTS (
SELECT 1
FROM article_tag_version
WHERE article_id = 3
AND tag_id = tags_version.id
AND operation_type != 2
AND EXISTS (
SELECT 1
FROM article_tag_version as article_tag_version2
WHERE article_tag_version2.tag_id = article_tag_version.tag_id
AND article_tag_version2.tx_id <=5
AND article_tag_version2.article_id = 3
GROUP BY article_tag_version2.tag_id
HAVING
MAX(article_tag_version2.tx_id) =
article_tag_version.tx_id
)
)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
obj
|
SQLAlchemy declarative object |
required |
build_association_version_tables()
¶
Builds many-to-many association version table for given property. Association version tables are used for tracking change history of many-to-many associations.
many_to_many_criteria(obj)
¶
Returns the many-to-many query.
Looks up remote items through associations and for each item returns
returns the last version with a transaction less than or equal to the
transaction of obj. This must hold true for both the association and
the remote relation items.
Example¶
Select all tags of article with id 3 and transaction 5
SELECT tags_version.*
FROM tags_version
WHERE EXISTS (
SELECT 1
FROM article_tag_version
WHERE article_id = 3
AND tag_id = tags_version.id
AND operation_type != 2
AND EXISTS (
SELECT 1
FROM article_tag_version as article_tag_version2
WHERE article_tag_version2.tag_id = article_tag_version.tag_id
AND article_tag_version2.tx_id <= 5
GROUP BY article_tag_version2.tag_id
HAVING
MAX(article_tag_version2.tx_id) =
article_tag_version.tx_id
)
)
AND EXISTS (
SELECT 1
FROM tags_version as tags_version_2
WHERE tags_version_2.id = tags_version.id
AND tags_version_2.tx_id <= 5
GROUP BY tags_version_2.id
HAVING MAX(tags_version_2.tx_id) = tags_version.tx_id
)
AND operation_type != 2
many_to_one_criteria(obj)
¶
Returns the many-to-one query.
Returns the item on the 'one' side with the highest transaction id
as long as it is less or equal to the transaction id of the obj.
Example¶
Look up the Article of a Tag with article_id = 4 and transaction_id = 5
one_to_many_criteria(obj)
¶
Returns the one-to-many query.
For each item on the 'many' side, returns its latest version as long as
the transaction of that version is less than equal of the transaction
of obj.
Example¶
Using the Article-Tags relationship, where we look for tags of article_version with id = 3 and transaction = 5 the sql produced is
SELECT tags_version.*
FROM tags_version
WHERE tags_version.article_id = 3
AND tags_version.operation_type != 2
AND EXISTS (
SELECT 1
FROM tags_version as tags_version_last
WHERE tags_version_last.transaction_id <= 5
AND tags_version_last.id = tags_version.id
GROUP BY tags_version_last.id
HAVING
MAX(tags_version_last.transaction_id) =
tags_version.transaction_id
)
process_query(query)
¶
Process given SQLAlchemy Query object depending on the associated RelationshipProperty object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
query
|
SQLAlchemy Query object |
required |
reflected_relationship()
¶
Builds a reflected one-to-many, one-to-one and many-to-one relationship between two version classes.
UnitOfWork¶
sqlalchemy_continuum.unit_of_work.UnitOfWork
¶
has_changes
property
¶
Return whether or not this unit of work has changes.
assign_attributes(parent_obj, version_obj)
¶
Assign attributes values from parent object to version object.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent_obj
|
Parent object to get the attribute values from |
required | |
version_obj
|
Version object to assign the attribute values to |
required |
create_association_versions(session)
¶
Creates association table version records for given session.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session object |
required |
create_transaction(session)
¶
Create transaction object for given SQLAlchemy session.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session object |
required |
create_version_objects(session)
¶
Create version objects for given session based on operations collected by insert, update and deleted trackers.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session object |
required |
get_or_create_version_object(target)
¶
Return version object for given parent object. If no version object exists for given parent object, create one.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Parent object to create the version object for |
required |
is_modified(session)
¶
Return whether or not given session has been modified. Session has been modified if any versioned property of any version object in given session has been modified or if any of the plugins returns that session has been modified.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session object |
required |
make_versions(session)
¶
Create transaction, transaction changes records, version objects.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session object |
required |
process_after_flush(session)
¶
After flush processor for given session.
Creates version objects for all modified versioned parent objects that were affected during the flush phase.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session object |
required |
process_before_flush(session)
¶
Before flush processor for given session.
This method creates a version session which is later on used for the creation of version objects. It also creates Transaction object for the current transaction and invokes before_flush template method on all plugins.
If the given session had no relevant modifications regarding versioned objects this method does nothing.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session object |
required |
process_operation(operation)
¶
Process given operation object. The operation processing has x stages:
- Get or create a version object for given parent object
- Assign the operation type for this object
- Invoke listeners
- Update version validity in case validity strategy is used
- Mark operation as processed
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
operation
|
Operation object |
required |
reset(session=None)
¶
Reset the internal state of this UnitOfWork object. Normally this is called after transaction has been committed or rolled back.
update_version_validity(parent, version_obj)
¶
Updates previous version object end_transaction_id based on given parent object and newly created version object.
This method is only used when using 'validity' versioning strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent
|
SQLAlchemy declarative parent object |
required | |
version_obj
|
SQLAlchemy declarative version object See also: |
required |
version_validity_subquery(parent, version_obj, alias=None)
¶
Return the subquery needed by update_version_validity.
This method is only used when using 'validity' versioning strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
parent
|
SQLAlchemy declarative parent object |
required | |
version_obj
|
SQLAlchemy declarative version object See also: |
required |
History class¶
sqlalchemy_continuum.version.VersionClassBase
¶
changeset
property
¶
Return a dictionary of changed fields in this version with keys as field names and values as lists with first value as the old field value and second list value as the new value.
index
property
¶
Return the index of this version in the version history.
next
property
¶
Returns the next version relative to this version in the version history. If current version is the last version this method returns None.
If versions have been pre-fetched using all_versions() with
link_versions(), this will use the cached value instead of
making a database query.
previous
property
¶
Returns the previous version relative to this version in the version history. If current version is the first version this method returns None.
If versions have been pre-fetched using all_versions() with
link_versions(), this will use the cached value instead of
making a database query.
all_versions(session, primary_key_values, limit=None, offset=0, desc=True, link=True)
classmethod
¶
Efficiently fetch all versions for an entity in a single query.
This avoids N+1 queries when iterating through version history
by fetching all versions at once. When link=True, the returned
versions will have their .previous and .next properties
pre-populated from the cache.
Example:
# Get all versions of Article #5, newest first
versions = ArticleVersion.all_versions(
session,
{'id': 5},
limit=10 # Only get the 10 most recent versions
)
# Iterate without N+1 queries
for version in versions:
print(version.changeset)
print(version.previous) # Uses cached value, no query
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session |
required | |
primary_key_values
|
dict
|
Dict mapping primary key column names to values |
required |
limit
|
int | None
|
Maximum number of versions to return (None for all) |
None
|
offset
|
int
|
Number of versions to skip |
0
|
desc
|
bool
|
If True, return newest versions first (default) |
True
|
link
|
bool
|
If True, pre-populate previous/next caches (default) |
True
|
Returns:
| Type | Description |
|---|---|
list[VersionClassBase]
|
List of version objects |
version_at(session, primary_key_values, transaction_id)
classmethod
¶
Efficiently retrieve the version that was active at a specific transaction.
This is more efficient than iterating through versions manually, especially when using the validity strategy which can use range conditions.
Example:
# Get the version of Article #5 that was active at transaction #100
version = ArticleVersion.version_at(
session,
{'id': 5},
transaction_id=100
)
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
session
|
SQLAlchemy session |
required | |
primary_key_values
|
dict
|
Dict mapping primary key column names to values |
required |
transaction_id
|
int
|
The transaction ID to query at |
required |
Returns:
| Type | Description |
|---|---|
VersionClassBase | None
|
The version object active at that transaction, or None |
Changelog¶
See the changelog for a full list of changes in each release.