avdd wrote:
> Something a bit more normal now.
>
> Combining optimistic concurrency control with cascading PK updates is
> problematic, if you load the child relation, the session issues
> unecessary updates for the children, resulting in
> ConcurrentModificationError


this issue is fixed in trunk as of r6719.  mapper() now has a
passive_updates flag set to True by default.  The caveat for now is that
to run this test script on SQLite or MySQL/MyISAM requires setting the
flag to False, since the mapper has to make a definitive yes/no decision
on if it can assume a PK->FK change must occur via CASCADE or not, which
determines if it has to use the new or old PK value of the row in order to
locate it.   will look into automating this flag in a future release based
on dialect/table options.



>
> """
>
> import sqlalchemy as sql
> from sqlalchemy import orm
> from sqlalchemy.ext.declarative import declarative_base
>
> __metaclass__ = type
>
> engine = sql.create_engine("postgresql:///avdd")
> 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=True)
>     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.1'), C(i='C.2')])
>     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
>
> """
>
> --
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To post to this group, send email to sqlalch...@googlegroups.com.
> To unsubscribe from this group, send email to
> sqlalchemy+unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/sqlalchemy?hl=en.
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalch...@googlegroups.com.
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en.

Reply via email to