the ZBlog demo can illustrate this. this relationship in mapper.py:
Topic.mapper = mapper(Topic, tables.topics)
TopicAssociation.mapper = mapper(TopicAssociation,tables.topic_xref,
primary_key=[tables.topic_xref.c.topic_id](tables.topic_xref.c.post_id,),
properties={
'topic':relation(Topic.mapper, lazy=False),
})
Post.mapper = mapper(Post, posts_with_ccount, properties={
'id':posts_with_ccount.c.post_id,
'topics':relation(TopicAssociation, lazy=False, private=True, association=Topic)
}, is_primary=True, order_by=[desc(posts_with_ccount.c.datetime)](desc(posts_with_ccount.c.datetime)))
this creates TopicAssociation as a many-to-many association object. If you go to the interface and enter a post, and put the same topic name twice, it saves. This is the bug. the list of TopicAssociations should somehow be unique based on the Topic object its attached to, just like any other collection. then if you go to update that post, the update on the topicassocaitions returns 2 rows instead of 1 and the concurrency detector goes off.
Does the following test-case correctly reproduce the issue? If so, then I don't think this is a bug in SA. Rather, it's a mis-configuration of the tables. There should be a UNIQUE constraint on the "enrol" table (note that I had to remove the primary_key=True directives on enrolTbl to reproduce the problem). This is a constraint issue, which we probably want to have the database enforce rather than SA.
The topic_xref table in zblog should be configured with primary_key=True on its *_id columns. That is unless it should allow multiple references to the same topic from a given post, in which case it will need a separate primary key column. If that's the case then Topics and Posts don't really have a true many-to-many relationship.
The other possible way to address this situation is to have ListAttribute or HistoryArraySet check the PK's of inserted/appended objects against other objects already in the list (i.e. enforce the set property more strictly). This leads to other questions though. For example: should ListAttribute verify that its objects can actually be inserted into the table to which it (ListAttribute) is mapped?
This brings up another issue though: could the *Set types in SA be eliminated in favor of the built-in set type in Python?