on update cascade changes PK, mapper can't find the row
technically, this can't work in any case due to version_id_col, which will be inconsistent. but when removed, the mapper still attempts to update the rows whose PKs have changed - it any case, this needs to be supported so that other row values can be reached on update.
basically this is the one case where _save_obj() has to look at history.added instead of history.deleted when looking for a mutated primary key value. Somehow the dependency rules need to put a clue in there.
import sqlalchemy as sql
from sqlalchemy import orm
from sqlalchemy.ext.declarative import declarative_base
__metaclass__ = type
engine = sql.create_engine("postgresql://scott:tiger@localhost/test", echo=True)
metadata = sql.MetaData(bind=engine)
db = orm.create_session(bind=engine, autocommit=False)
T = declarative_base(metadata=metadata)
class P(T):
__tablename__ = 'p'
id = sql.Column(sql.String, primary_key=True)
version = sql.Column(sql.Integer, nullable=False, default=1)
cc = orm.relation('C', backref='parent', passive_updates=True)
__mapper_args__ = {'version_id_col': version}
class C(T):
__tablename__ = 'c'
i = sql.Column(sql.String, primary_key=True)
p = sql.Column(sql.String,
sql.ForeignKey('p.id',
onupdate='cascade',
ondelete='cascade'),
primary_key=False)
version = sql.Column(sql.Integer, nullable=False, default=1)
__mapper_args__ = {'version_id_col': version}
metadata.create_all()
P.__table__.delete().execute()
with db.transaction:
p = P(id='P1', cc=[C(i='C.2')](C(i='C.1'),))
db.add(p)
#db.expunge_all()
#p = db.query(P).first()
#with db.transaction:
# p.id = 'P2'
# ok, no ConcModError
#db.expunge_all()
#p = db.query(P).first()
with db.transaction:
p.id = 'P3'
p.cc
# issues spurious updates, throws ConcModError
Comments (6)
-
reporter -
reporter line 229 of
OneToManyDP
is where the pk sync happens:if self._pks_changed(uowcommit, state): for child in history.unchanged: self._synchronize(state, child, None, False, uowcommit)
-
reporter 53d7530ee8e976d8eab9cb4b31120f7c5aecd7b6 for reference
-
reporter the attached patch works around, but I'd like to see if the mechanism can be built into sync.populate, possibly place notes into the state itself not the UOW (might not be important), and the approach here can be generalized to fix
#1362as well since sync.populate is used by both inheritance sync as well as dependency sync -
reporter - changed status to resolved
-
reporter - removed milestone
Removing milestone: 0.6.xx (automated comment)
- Log in to comment
also see
#1362for a related issue.