mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-27 19:15:05 -04:00
c703b9ce89
Ensure that the history table sets autoincrement=False, since these values are copied in all cases; the flag will emit an error as of 1.1 if the primary key is composite. Additionally, use the sqlite_autoincrement flag so that SQLite uses unique primary key identifiers for new rows even if some rows have been deleted. Fixes: #3872 Change-Id: I65912eb394b3b69d7f4e3c098f4f948b0a7a5374 Pull-request: https://bitbucket.org/zzzeek/sqlalchemy/pull-requests/93
726 lines
22 KiB
Python
726 lines
22 KiB
Python
"""Unit tests illustrating usage of the ``history_meta.py``
|
|
module functions."""
|
|
|
|
from unittest import TestCase
|
|
from sqlalchemy.ext.declarative import declarative_base
|
|
from .history_meta import Versioned, versioned_session
|
|
from sqlalchemy import create_engine, Column, Integer, String, \
|
|
ForeignKey, Boolean, select
|
|
from sqlalchemy.orm import clear_mappers, Session, deferred, relationship, \
|
|
column_property
|
|
from sqlalchemy.testing import AssertsCompiledSQL, eq_, assert_raises, ne_
|
|
from sqlalchemy.testing.entities import ComparableEntity
|
|
from sqlalchemy.orm import exc as orm_exc
|
|
import warnings
|
|
|
|
warnings.simplefilter("error")
|
|
|
|
engine = None
|
|
|
|
|
|
def setup_module():
|
|
global engine
|
|
engine = create_engine('sqlite://', echo=True)
|
|
|
|
|
|
class TestVersioning(TestCase, AssertsCompiledSQL):
|
|
__dialect__ = 'default'
|
|
|
|
def setUp(self):
|
|
self.session = Session(engine)
|
|
self.Base = declarative_base()
|
|
versioned_session(self.session)
|
|
|
|
def tearDown(self):
|
|
self.session.close()
|
|
clear_mappers()
|
|
self.Base.metadata.drop_all(engine)
|
|
|
|
def create_tables(self):
|
|
self.Base.metadata.create_all(engine)
|
|
|
|
def test_plain(self):
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
sc = SomeClass(name='sc1')
|
|
sess.add(sc)
|
|
sess.commit()
|
|
|
|
sc.name = 'sc1modified'
|
|
sess.commit()
|
|
|
|
assert sc.version == 2
|
|
|
|
SomeClassHistory = SomeClass.__history_mapper__.class_
|
|
|
|
eq_(
|
|
sess.query(SomeClassHistory).filter(
|
|
SomeClassHistory.version == 1).all(),
|
|
[SomeClassHistory(version=1, name='sc1')]
|
|
)
|
|
|
|
sc.name = 'sc1modified2'
|
|
|
|
eq_(
|
|
sess.query(SomeClassHistory).order_by(
|
|
SomeClassHistory.version).all(),
|
|
[
|
|
SomeClassHistory(version=1, name='sc1'),
|
|
SomeClassHistory(version=2, name='sc1modified')
|
|
]
|
|
)
|
|
|
|
assert sc.version == 3
|
|
|
|
sess.commit()
|
|
|
|
sc.name = 'temp'
|
|
sc.name = 'sc1modified2'
|
|
|
|
sess.commit()
|
|
|
|
eq_(
|
|
sess.query(SomeClassHistory).order_by(
|
|
SomeClassHistory.version).all(),
|
|
[
|
|
SomeClassHistory(version=1, name='sc1'),
|
|
SomeClassHistory(version=2, name='sc1modified')
|
|
]
|
|
)
|
|
|
|
sess.delete(sc)
|
|
sess.commit()
|
|
|
|
eq_(
|
|
sess.query(SomeClassHistory).order_by(
|
|
SomeClassHistory.version).all(),
|
|
[
|
|
SomeClassHistory(version=1, name='sc1'),
|
|
SomeClassHistory(version=2, name='sc1modified'),
|
|
SomeClassHistory(version=3, name='sc1modified2')
|
|
]
|
|
)
|
|
|
|
def test_w_mapper_versioning(self):
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
|
|
SomeClass.__mapper__.version_id_col = SomeClass.__table__.c.version
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
sc = SomeClass(name='sc1')
|
|
sess.add(sc)
|
|
sess.commit()
|
|
|
|
s2 = Session(sess.bind)
|
|
sc2 = s2.query(SomeClass).first()
|
|
sc2.name = 'sc1modified'
|
|
|
|
sc.name = 'sc1modified_again'
|
|
sess.commit()
|
|
|
|
eq_(sc.version, 2)
|
|
|
|
assert_raises(
|
|
orm_exc.StaleDataError,
|
|
s2.flush
|
|
)
|
|
|
|
def test_from_null(self):
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
sc = SomeClass()
|
|
sess.add(sc)
|
|
sess.commit()
|
|
|
|
sc.name = 'sc1'
|
|
sess.commit()
|
|
|
|
assert sc.version == 2
|
|
|
|
def test_insert_null(self):
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
boole = Column(Boolean, default=False)
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
sc = SomeClass(boole=True)
|
|
sess.add(sc)
|
|
sess.commit()
|
|
|
|
sc.boole = None
|
|
sess.commit()
|
|
|
|
sc.boole = False
|
|
sess.commit()
|
|
|
|
SomeClassHistory = SomeClass.__history_mapper__.class_
|
|
|
|
eq_(
|
|
sess.query(SomeClassHistory.boole).order_by(
|
|
SomeClassHistory.id).all(),
|
|
[(True, ), (None, )]
|
|
)
|
|
|
|
eq_(sc.version, 3)
|
|
|
|
def test_deferred(self):
|
|
"""test versioning of unloaded, deferred columns."""
|
|
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
data = deferred(Column(String(25)))
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
sc = SomeClass(name='sc1', data='somedata')
|
|
sess.add(sc)
|
|
sess.commit()
|
|
sess.close()
|
|
|
|
sc = sess.query(SomeClass).first()
|
|
assert 'data' not in sc.__dict__
|
|
|
|
sc.name = 'sc1modified'
|
|
sess.commit()
|
|
|
|
assert sc.version == 2
|
|
|
|
SomeClassHistory = SomeClass.__history_mapper__.class_
|
|
|
|
eq_(
|
|
sess.query(SomeClassHistory).filter(
|
|
SomeClassHistory.version == 1).all(),
|
|
[SomeClassHistory(version=1, name='sc1', data='somedata')]
|
|
)
|
|
|
|
def test_joined_inheritance(self):
|
|
class BaseClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'basetable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
type = Column(String(20))
|
|
|
|
__mapper_args__ = {
|
|
'polymorphic_on': type,
|
|
'polymorphic_identity': 'base'}
|
|
|
|
class SubClassSeparatePk(BaseClass):
|
|
__tablename__ = 'subtable1'
|
|
|
|
id = column_property(
|
|
Column(Integer, primary_key=True),
|
|
BaseClass.id
|
|
)
|
|
base_id = Column(Integer, ForeignKey('basetable.id'))
|
|
subdata1 = Column(String(50))
|
|
|
|
__mapper_args__ = {'polymorphic_identity': 'sep'}
|
|
|
|
class SubClassSamePk(BaseClass):
|
|
__tablename__ = 'subtable2'
|
|
|
|
id = Column(
|
|
Integer, ForeignKey('basetable.id'), primary_key=True)
|
|
subdata2 = Column(String(50))
|
|
|
|
__mapper_args__ = {'polymorphic_identity': 'same'}
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
|
|
sep1 = SubClassSeparatePk(name='sep1', subdata1='sep1subdata')
|
|
base1 = BaseClass(name='base1')
|
|
same1 = SubClassSamePk(name='same1', subdata2='same1subdata')
|
|
sess.add_all([sep1, base1, same1])
|
|
sess.commit()
|
|
|
|
base1.name = 'base1mod'
|
|
same1.subdata2 = 'same1subdatamod'
|
|
sep1.name = 'sep1mod'
|
|
sess.commit()
|
|
|
|
BaseClassHistory = BaseClass.__history_mapper__.class_
|
|
SubClassSeparatePkHistory = \
|
|
SubClassSeparatePk.__history_mapper__.class_
|
|
SubClassSamePkHistory = SubClassSamePk.__history_mapper__.class_
|
|
eq_(
|
|
sess.query(BaseClassHistory).order_by(BaseClassHistory.id).all(),
|
|
[
|
|
SubClassSeparatePkHistory(
|
|
id=1, name='sep1', type='sep', version=1),
|
|
BaseClassHistory(id=2, name='base1', type='base', version=1),
|
|
SubClassSamePkHistory(
|
|
id=3, name='same1', type='same', version=1)
|
|
]
|
|
)
|
|
|
|
same1.subdata2 = 'same1subdatamod2'
|
|
|
|
eq_(
|
|
sess.query(BaseClassHistory).order_by(
|
|
BaseClassHistory.id, BaseClassHistory.version).all(),
|
|
[
|
|
SubClassSeparatePkHistory(
|
|
id=1, name='sep1', type='sep', version=1),
|
|
BaseClassHistory(id=2, name='base1', type='base', version=1),
|
|
SubClassSamePkHistory(
|
|
id=3, name='same1', type='same', version=1),
|
|
SubClassSamePkHistory(
|
|
id=3, name='same1', type='same', version=2)
|
|
]
|
|
)
|
|
|
|
base1.name = 'base1mod2'
|
|
eq_(
|
|
sess.query(BaseClassHistory).order_by(
|
|
BaseClassHistory.id, BaseClassHistory.version).all(),
|
|
[
|
|
SubClassSeparatePkHistory(
|
|
id=1, name='sep1', type='sep', version=1),
|
|
BaseClassHistory(id=2, name='base1', type='base', version=1),
|
|
BaseClassHistory(
|
|
id=2, name='base1mod', type='base', version=2),
|
|
SubClassSamePkHistory(
|
|
id=3, name='same1', type='same', version=1),
|
|
SubClassSamePkHistory(
|
|
id=3, name='same1', type='same', version=2)
|
|
]
|
|
)
|
|
|
|
def test_joined_inheritance_multilevel(self):
|
|
class BaseClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'basetable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
type = Column(String(20))
|
|
|
|
__mapper_args__ = {
|
|
'polymorphic_on': type,
|
|
'polymorphic_identity': 'base'}
|
|
|
|
class SubClass(BaseClass):
|
|
__tablename__ = 'subtable'
|
|
|
|
id = column_property(
|
|
Column(Integer, primary_key=True),
|
|
BaseClass.id
|
|
)
|
|
base_id = Column(Integer, ForeignKey('basetable.id'))
|
|
subdata1 = Column(String(50))
|
|
|
|
__mapper_args__ = {'polymorphic_identity': 'sub'}
|
|
|
|
class SubSubClass(SubClass):
|
|
__tablename__ = 'subsubtable'
|
|
|
|
id = Column(Integer, ForeignKey('subtable.id'), primary_key=True)
|
|
subdata2 = Column(String(50))
|
|
|
|
__mapper_args__ = {'polymorphic_identity': 'subsub'}
|
|
|
|
self.create_tables()
|
|
|
|
SubSubHistory = SubSubClass.__history_mapper__.class_
|
|
sess = self.session
|
|
q = sess.query(SubSubHistory)
|
|
self.assert_compile(
|
|
q,
|
|
|
|
|
|
"SELECT "
|
|
|
|
"subsubtable_history.id AS subsubtable_history_id, "
|
|
"subtable_history.id AS subtable_history_id, "
|
|
"basetable_history.id AS basetable_history_id, "
|
|
|
|
"subsubtable_history.changed AS subsubtable_history_changed, "
|
|
"subtable_history.changed AS subtable_history_changed, "
|
|
"basetable_history.changed AS basetable_history_changed, "
|
|
|
|
"basetable_history.name AS basetable_history_name, "
|
|
|
|
"basetable_history.type AS basetable_history_type, "
|
|
|
|
"subsubtable_history.version AS subsubtable_history_version, "
|
|
"subtable_history.version AS subtable_history_version, "
|
|
"basetable_history.version AS basetable_history_version, "
|
|
|
|
|
|
"subtable_history.base_id AS subtable_history_base_id, "
|
|
"subtable_history.subdata1 AS subtable_history_subdata1, "
|
|
"subsubtable_history.subdata2 AS subsubtable_history_subdata2 "
|
|
"FROM basetable_history "
|
|
"JOIN subtable_history "
|
|
"ON basetable_history.id = subtable_history.base_id "
|
|
"AND basetable_history.version = subtable_history.version "
|
|
"JOIN subsubtable_history ON subtable_history.id = "
|
|
"subsubtable_history.id AND subtable_history.version = "
|
|
"subsubtable_history.version"
|
|
)
|
|
|
|
ssc = SubSubClass(name='ss1', subdata1='sd1', subdata2='sd2')
|
|
sess.add(ssc)
|
|
sess.commit()
|
|
eq_(
|
|
sess.query(SubSubHistory).all(),
|
|
[]
|
|
)
|
|
ssc.subdata1 = 'sd11'
|
|
ssc.subdata2 = 'sd22'
|
|
sess.commit()
|
|
eq_(
|
|
sess.query(SubSubHistory).all(),
|
|
[SubSubHistory(name='ss1', subdata1='sd1',
|
|
subdata2='sd2', type='subsub', version=1)]
|
|
)
|
|
eq_(ssc, SubSubClass(
|
|
name='ss1', subdata1='sd11',
|
|
subdata2='sd22', version=2))
|
|
|
|
def test_joined_inheritance_changed(self):
|
|
class BaseClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'basetable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
type = Column(String(20))
|
|
|
|
__mapper_args__ = {
|
|
'polymorphic_on': type,
|
|
'polymorphic_identity': 'base'
|
|
}
|
|
|
|
class SubClass(BaseClass):
|
|
__tablename__ = 'subtable'
|
|
|
|
id = Column(Integer, ForeignKey('basetable.id'), primary_key=True)
|
|
|
|
__mapper_args__ = {'polymorphic_identity': 'sep'}
|
|
|
|
self.create_tables()
|
|
|
|
BaseClassHistory = BaseClass.__history_mapper__.class_
|
|
SubClassHistory = SubClass.__history_mapper__.class_
|
|
sess = self.session
|
|
s1 = SubClass(name='s1')
|
|
sess.add(s1)
|
|
sess.commit()
|
|
|
|
s1.name = 's2'
|
|
sess.commit()
|
|
|
|
actual_changed_base = sess.scalar(
|
|
select([BaseClass.__history_mapper__.local_table.c.changed]))
|
|
actual_changed_sub = sess.scalar(
|
|
select([SubClass.__history_mapper__.local_table.c.changed]))
|
|
h1 = sess.query(BaseClassHistory).first()
|
|
eq_(h1.changed, actual_changed_base)
|
|
eq_(h1.changed, actual_changed_sub)
|
|
|
|
h1 = sess.query(SubClassHistory).first()
|
|
eq_(h1.changed, actual_changed_base)
|
|
eq_(h1.changed, actual_changed_sub)
|
|
|
|
def test_single_inheritance(self):
|
|
class BaseClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'basetable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
type = Column(String(50))
|
|
__mapper_args__ = {
|
|
'polymorphic_on': type,
|
|
'polymorphic_identity': 'base'}
|
|
|
|
class SubClass(BaseClass):
|
|
|
|
subname = Column(String(50), unique=True)
|
|
__mapper_args__ = {'polymorphic_identity': 'sub'}
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
|
|
b1 = BaseClass(name='b1')
|
|
sc = SubClass(name='s1', subname='sc1')
|
|
|
|
sess.add_all([b1, sc])
|
|
|
|
sess.commit()
|
|
|
|
b1.name = 'b1modified'
|
|
|
|
BaseClassHistory = BaseClass.__history_mapper__.class_
|
|
SubClassHistory = SubClass.__history_mapper__.class_
|
|
|
|
eq_(
|
|
sess.query(BaseClassHistory).order_by(
|
|
BaseClassHistory.id, BaseClassHistory.version).all(),
|
|
[BaseClassHistory(id=1, name='b1', type='base', version=1)]
|
|
)
|
|
|
|
sc.name = 's1modified'
|
|
b1.name = 'b1modified2'
|
|
|
|
eq_(
|
|
sess.query(BaseClassHistory).order_by(
|
|
BaseClassHistory.id, BaseClassHistory.version).all(),
|
|
[
|
|
BaseClassHistory(id=1, name='b1', type='base', version=1),
|
|
BaseClassHistory(
|
|
id=1, name='b1modified', type='base', version=2),
|
|
SubClassHistory(id=2, name='s1', type='sub', version=1)
|
|
]
|
|
)
|
|
|
|
# test the unique constraint on the subclass
|
|
# column
|
|
sc.name = "modifyagain"
|
|
sess.flush()
|
|
|
|
def test_unique(self):
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50), unique=True)
|
|
data = Column(String(50))
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
sc = SomeClass(name='sc1', data='sc1')
|
|
sess.add(sc)
|
|
sess.commit()
|
|
|
|
sc.data = 'sc1modified'
|
|
sess.commit()
|
|
|
|
assert sc.version == 2
|
|
|
|
sc.data = 'sc1modified2'
|
|
sess.commit()
|
|
|
|
assert sc.version == 3
|
|
|
|
def test_relationship(self):
|
|
|
|
class SomeRelated(self.Base, ComparableEntity):
|
|
__tablename__ = 'somerelated'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
related_id = Column(Integer, ForeignKey('somerelated.id'))
|
|
related = relationship("SomeRelated", backref='classes')
|
|
|
|
SomeClassHistory = SomeClass.__history_mapper__.class_
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
sc = SomeClass(name='sc1')
|
|
sess.add(sc)
|
|
sess.commit()
|
|
|
|
assert sc.version == 1
|
|
|
|
sr1 = SomeRelated()
|
|
sc.related = sr1
|
|
sess.commit()
|
|
|
|
assert sc.version == 2
|
|
|
|
eq_(
|
|
sess.query(SomeClassHistory).filter(
|
|
SomeClassHistory.version == 1).all(),
|
|
[SomeClassHistory(version=1, name='sc1', related_id=None)]
|
|
)
|
|
|
|
sc.related = None
|
|
|
|
eq_(
|
|
sess.query(SomeClassHistory).order_by(
|
|
SomeClassHistory.version).all(),
|
|
[
|
|
SomeClassHistory(version=1, name='sc1', related_id=None),
|
|
SomeClassHistory(version=2, name='sc1', related_id=sr1.id)
|
|
]
|
|
)
|
|
|
|
assert sc.version == 3
|
|
|
|
def test_backref_relationship(self):
|
|
|
|
class SomeRelated(self.Base, ComparableEntity):
|
|
__tablename__ = 'somerelated'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
related_id = Column(Integer, ForeignKey('sometable.id'))
|
|
related = relationship("SomeClass", backref='related')
|
|
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
sc = SomeClass()
|
|
sess.add(sc)
|
|
sess.commit()
|
|
|
|
assert sc.version == 1
|
|
|
|
sr = SomeRelated(name='sr', related=sc)
|
|
sess.add(sr)
|
|
sess.commit()
|
|
|
|
assert sc.version == 1
|
|
|
|
sr.name = 'sr2'
|
|
sess.commit()
|
|
|
|
assert sc.version == 1
|
|
|
|
sess.delete(sr)
|
|
sess.commit()
|
|
|
|
assert sc.version == 1
|
|
|
|
def test_create_double_flush(self):
|
|
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(30))
|
|
other = Column(String(30))
|
|
|
|
self.create_tables()
|
|
|
|
sc = SomeClass()
|
|
self.session.add(sc)
|
|
self.session.flush()
|
|
sc.name = 'Foo'
|
|
self.session.flush()
|
|
|
|
assert sc.version == 2
|
|
|
|
def test_mutate_plain_column(self):
|
|
class Document(self.Base, Versioned):
|
|
__tablename__ = 'document'
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
name = Column(String, nullable=True)
|
|
description_ = Column('description', String, nullable=True)
|
|
|
|
self.create_tables()
|
|
|
|
document = Document()
|
|
self.session.add(document)
|
|
document.name = 'Foo'
|
|
self.session.commit()
|
|
document.name = 'Bar'
|
|
self.session.commit()
|
|
|
|
DocumentHistory = Document.__history_mapper__.class_
|
|
v2 = self.session.query(Document).one()
|
|
v1 = self.session.query(DocumentHistory).one()
|
|
self.assertEqual(v1.id, v2.id)
|
|
self.assertEqual(v2.name, 'Bar')
|
|
self.assertEqual(v1.name, 'Foo')
|
|
|
|
def test_mutate_named_column(self):
|
|
class Document(self.Base, Versioned):
|
|
__tablename__ = 'document'
|
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
|
name = Column(String, nullable=True)
|
|
description_ = Column('description', String, nullable=True)
|
|
|
|
self.create_tables()
|
|
|
|
document = Document()
|
|
self.session.add(document)
|
|
document.description_ = 'Foo'
|
|
self.session.commit()
|
|
document.description_ = 'Bar'
|
|
self.session.commit()
|
|
|
|
DocumentHistory = Document.__history_mapper__.class_
|
|
v2 = self.session.query(Document).one()
|
|
v1 = self.session.query(DocumentHistory).one()
|
|
self.assertEqual(v1.id, v2.id)
|
|
self.assertEqual(v2.description_, 'Bar')
|
|
self.assertEqual(v1.description_, 'Foo')
|
|
|
|
def test_unique_identifiers_across_deletes(self):
|
|
"""Ensure unique integer values are used for the primary table.
|
|
|
|
Checks whether the database assigns the same identifier twice
|
|
within the span of a table. SQLite will do this if
|
|
sqlite_autoincrement is not set (e.g. SQLite's AUTOINCREMENT flag).
|
|
|
|
"""
|
|
|
|
class SomeClass(Versioned, self.Base, ComparableEntity):
|
|
__tablename__ = 'sometable'
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
name = Column(String(50))
|
|
|
|
self.create_tables()
|
|
sess = self.session
|
|
sc = SomeClass(name='sc1')
|
|
sess.add(sc)
|
|
sess.commit()
|
|
|
|
sess.delete(sc)
|
|
sess.commit()
|
|
|
|
sc2 = SomeClass(name='sc2')
|
|
sess.add(sc2)
|
|
sess.commit()
|
|
|
|
SomeClassHistory = SomeClass.__history_mapper__.class_
|
|
|
|
# only one entry should exist in the history table; one()
|
|
# ensures that
|
|
scdeleted = sess.query(SomeClassHistory).one()
|
|
|
|
# If sc2 has the same id that deleted sc1 had,
|
|
# it will fail when modified or deleted
|
|
# because of the violation of the uniqueness of the primary key on
|
|
# sometable_history
|
|
ne_(sc2.id, scdeleted.id)
|
|
|
|
# If previous assertion fails, this will also fail:
|
|
sc2.name = 'sc2 modified'
|
|
sess.commit()
|