Skip to content

Commit 7fb585f

Browse files
committed
LITE-30014 Transactional verbose_id is using wrong base id body reference
1 parent fb55489 commit 7fb585f

File tree

4 files changed

+70
-48
lines changed

4 files changed

+70
-48
lines changed

connect_extension_utils/db/models.py

+23-25
Original file line numberDiff line numberDiff line change
@@ -95,18 +95,12 @@ def add_next_with_verbose(self, instance, related_id_field):
9595
instance_class = instance.__class__
9696
new_suffix = 0
9797
related_id_value = getattr(instance, related_id_field)
98-
if self.query(
99-
self.query(instance_class)
100-
.filter(instance_class.__dict__[related_id_field] == related_id_value)
101-
.exists(),
102-
).scalar():
103-
last_obj = (
104-
self.query(instance_class)
105-
.order_by(
106-
instance_class.id.desc(),
107-
)
108-
.first()
109-
)
98+
last_obj = self._get_last_obj_for_next_verbose(
99+
instance_class,
100+
related_id_field,
101+
related_id_value,
102+
)
103+
if last_obj:
110104
_instance_id, suffix = last_obj.id.rsplit("-", 1)
111105
new_suffix = int(suffix) + 1
112106
else:
@@ -121,19 +115,12 @@ def add_all_with_next_verbose(self, instances, related_id_field):
121115
instance_class = first_item.__class__
122116
new_suffix = 0
123117
related_id_value = getattr(first_item, related_id_field)
124-
125-
if self.query(
126-
self.query(instance_class)
127-
.filter(instance_class.__dict__[related_id_field] == related_id_value)
128-
.exists(),
129-
).scalar():
130-
last_obj = (
131-
self.query(instance_class)
132-
.order_by(
133-
instance_class.id.desc(),
134-
)
135-
.first()
136-
)
118+
last_obj = self._get_last_obj_for_next_verbose(
119+
instance_class,
120+
related_id_field,
121+
related_id_value,
122+
)
123+
if last_obj:
137124
_instance_id, suffix = last_obj.id.rsplit("-", 1)
138125
new_suffix = int(suffix) + 1
139126
else:
@@ -146,6 +133,17 @@ def add_all_with_next_verbose(self, instances, related_id_field):
146133

147134
return self.add_all(instances)
148135

136+
def _get_last_obj_for_next_verbose(self, model_class, related_id_field, related_id_value):
137+
base_qs = self.query(model_class).filter(
138+
model_class.__dict__[related_id_field] == related_id_value,
139+
)
140+
last_obj = None
141+
if self.query(base_qs.exists()).scalar():
142+
last_obj = base_qs.order_by(
143+
model_class.id.desc(),
144+
).first()
145+
return last_obj
146+
149147

150148
SessionLocal = sessionmaker(autocommit=False, autoflush=False, class_=VerboseBaseSession)
151149
Model = declarative_base()

connect_extension_utils/testing/factories.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -38,32 +38,32 @@ class Meta:
3838

3939
@classmethod
4040
def _save(cls, model_class, session, args, kwargs):
41-
obj = model_class(*args, **kwargs)
41+
save_method = None
4242
if cls._meta._is_transactional:
43+
obj = model_class(*args, **kwargs)
4344
kwargs['id'] = cls.add_next_with_verbose(
4445
model_class,
4546
session,
4647
obj,
4748
cls._meta._related_id_field,
4849
)
49-
return super()._save(model_class, session, args, kwargs)
50+
save_method = factory.alchemy.SQLAlchemyModelFactory.__dict__['_save']
51+
cls.save_method = save_method or super()._save
52+
return cls.save_method(model_class, session, args, kwargs)
5053

5154
@classmethod
5255
def add_next_with_verbose(cls, model_class, session, obj, related_id_field):
5356
new_suffix = 0
5457
related_id_value = getattr(obj, related_id_field)
58+
base_qs = session.query(model_class).filter(
59+
model_class.__dict__[related_id_field] == related_id_value,
60+
)
5561
if session.query(
56-
session.query(model_class)
57-
.filter(model_class.__dict__[related_id_field] == related_id_value)
58-
.exists(),
62+
base_qs.exists(),
5963
).scalar():
60-
last_obj = (
61-
session.query(model_class)
62-
.order_by(
63-
model_class.id.desc(),
64-
)
65-
.first()
66-
)
64+
last_obj = base_qs.order_by(
65+
model_class.id.desc(),
66+
).first()
6767
_instance_id, suffix = last_obj.id.rsplit("-", 1)
6868
new_suffix = int(suffix) + 1
6969
else:

tests/db/test_models.py

+30-10
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,10 @@ def test_add_verbose_bulk(dbsession):
3939

4040

4141
def test_add_with_next_verbose(dbsession):
42-
obj = MyModel(
43-
name='Foo',
44-
created_by='Jony',
45-
)
42+
obj = MyModel(name='Foo', created_by='Jony')
43+
obj_2 = MyModel(name='Bar', created_by='Neri')
4644
dbsession.add_with_verbose(obj)
45+
dbsession.add_with_verbose(obj_2)
4746
dbsession.commit()
4847
trx_obj = TransactionalModel(
4948
my_model_id=obj.id,
@@ -55,37 +54,58 @@ def test_add_with_next_verbose(dbsession):
5554
)
5655
dbsession.add_next_with_verbose(trx_obj_2, related_id_field='my_model_id')
5756
dbsession.commit()
57+
trx_obj_3 = TransactionalModel(
58+
my_model_id=obj_2.id,
59+
)
60+
dbsession.add_next_with_verbose(trx_obj_3, related_id_field='my_model_id')
61+
dbsession.commit()
5862
assert trx_obj.id.startswith(TransactionalModel.PREFIX)
5963
assert trx_obj.id.endswith('000')
64+
assert obj.id.split('-', 1)[-1] in trx_obj.id
6065
assert trx_obj_2.id.startswith(TransactionalModel.PREFIX)
6166
assert trx_obj_2.id.endswith('001')
67+
assert obj.id.split('-', 1)[-1] in trx_obj_2.id
68+
assert trx_obj_3.id.startswith(TransactionalModel.PREFIX)
69+
assert trx_obj_3.id.endswith('000')
70+
assert obj_2.id.split('-', 1)[-1] in trx_obj_3.id
6271

6372

6473
def test_add_with_next_verbose_bulk(dbsession):
6574
m_obj = MyModel(
6675
name='Foo',
6776
created_by='Jony',
6877
)
69-
dbsession.add_with_verbose(m_obj)
78+
m_obj2 = MyModel(name='Bar', created_by='Neri')
79+
dbsession.add_all_with_verbose([m_obj, m_obj2])
7080
dbsession.commit()
81+
82+
trx_1 = TransactionalModel(my_model_id=m_obj.id)
83+
dbsession.add_next_with_verbose(
84+
trx_1,
85+
related_id_field='my_model_id',
86+
)
87+
dbsession.commit()
88+
7189
instances = []
7290
for _ in range(3):
7391
instances.append(
7492
TransactionalModel(
75-
my_model_id=m_obj.id,
93+
my_model_id=m_obj2.id,
7694
),
7795
)
7896
dbsession.add_all_with_next_verbose(instances, related_id_field='my_model_id')
7997
dbsession.commit()
8098
for idx, obj in enumerate(instances):
8199
assert obj.id.startswith(TransactionalModel.PREFIX)
82100
assert obj.id.endswith(f'00{idx}')
101+
assert m_obj2.id.split('-', 1)[-1] in obj.id
83102

84-
new_obj = TransactionalModel(my_model_id=m_obj.id)
85-
dbsession.add_all_with_next_verbose([new_obj], related_id_field='my_model_id')
103+
new_trx_obj = TransactionalModel(my_model_id=m_obj.id)
104+
dbsession.add_all_with_next_verbose([new_trx_obj], related_id_field='my_model_id')
86105
dbsession.commit()
87-
assert new_obj.id.startswith(TransactionalModel.PREFIX)
88-
assert new_obj.id.endswith('003')
106+
assert new_trx_obj.id.startswith(TransactionalModel.PREFIX)
107+
assert new_trx_obj.id.endswith('001')
108+
assert m_obj.id.split('-', 1)[-1] in new_trx_obj.id
89109

90110

91111
def test_add_with_verbose_bulk_fail_instances_not_same_class(dbsession):

tests/testing/test_factories.py

+5-1
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ def test_model_factory(my_model_factory):
44
assert obj.name.startswith("My Model")
55

66

7-
def test_related_model_factory(my_model_factory, related_model_factory):
7+
def test_related_model_factory(my_model_factory, related_model_factory, dbsession):
88
rel_obj = related_model_factory()
99
assert rel_obj.id.startswith(related_model_factory._meta.model.PREFIX)
1010
assert rel_obj.my_model_id.startswith(my_model_factory._meta.model.PREFIX)
11+
assert dbsession.query(related_model_factory._meta.model).count() == 1
12+
assert dbsession.query(my_model_factory._meta.model).count() == 1
1113

1214

1315
def test_transactional_model_factory(
@@ -24,3 +26,5 @@ def test_transactional_model_factory(
2426
_, body = base.split("-", 1)
2527
assert trx_obj.my_model_id == f"{my_model_factory._meta.model.PREFIX}-{body}"
2628
assert id_suffix == f"00{suffix}"
29+
assert dbsession.query(my_model_factory._meta.model).count() == 1
30+
assert dbsession.query(transactional_model_factory._meta.model).count() == 3

0 commit comments

Comments
 (0)