Thanks very much for the quick reply! Perhaps I’m missing something, but in this example there is only one table (‘Bird’). The derived class doesn’t have a join table, it only differs in its polymorphic identity. Does your reasoning still apply in this case?
Thanks, Tom > On 12 Sep 2016, at 23:03, Mike Bayer <mike...@zzzcomputing.com> wrote: > > > > On 09/12/2016 05:30 PM, 'Thomas Gillam' via sqlalchemy wrote: >> Hello all, >> >> I ran into a problem today when running delete() on a query created on a >> derived polymorphic class. In a nutshell, the SQL produced from the >> batch delete didn't condition on the polymorphic type, resulting in much >> broader deletion than was intended. I'm running SQLAlchemy 1.0.9. >> >> Here's a minimal example which reproduces the problem in a temporary >> SQLite database, although I also observe the undesired behaviour on >> Postgres. > > unfortunately, the warning listed for query.update() at > http://docs.sqlalchemy.org/en/latest/orm/query.html?sqlalchemy.orm.query.Query.update > > <http://docs.sqlalchemy.org/en/latest/orm/query.html?sqlalchemy.orm.query.Query.update> > failed to be adapted for query.delete(), it is: > > The method supports multiple table updates, as detailed in Multiple Table > Updates, and this behavior does extend to support updates of > joined-inheritance and other multiple table mappings. However, the join > condition of an inheritance mapper is not automatically rendered. Care must > be taken in any multiple-table update to explicitly include the joining > condition between those tables, even in mappings where this is normally > automatic. E.g. if a class Engineer subclasses Employee, an UPDATE of the > Engineer local table using criteria against the Employee local table might > look like: > > this is not accurate for delete(), because multiple table deletes are not > supported. I will add this right now. > > > > > > >> >> | >> >> importlogging >> >> fromsqlalchemy importColumn,Float,Integer,String,create_engine >> >> fromsqlalchemy.ext.declarative importdeclarative_base >> >> fromsqlalchemy.orm importSession >> >> >> >> Base=declarative_base() >> >> >> >> classBird(Base): >> >> __tablename__ ="bird" >> >> id=Column(Integer,primary_key=True) >> >> wing_length =Column(Float) >> >> bird_type =Column(String) >> >> >> >> __mapper_args__ ={"polymorphic_on":bird_type, >> >> "polymorphic_identity":'Bird' >> >> } >> >> >> >> classPigeon(Bird): >> >> __mapper_args__ ={"polymorphic_on":Bird.bird_type, >> >> "polymorphic_identity":'Pigeon' >> >> } >> >> >> >> db_path ='C:\\Temp\\testsqllitedb3.db' <smb://Temp//testsqllitedb3.db'> >> <smb://Temp//testsqllitedb3.db' <smb://Temp//testsqllitedb3.db'>> >> >> engine =create_engine('sqlite:///'+db_path,echo=True) >> >> Base.metadata.create_all(engine) >> >> >> # Turn on logging >> >> logging.basicConfig() >> >> logging.getLogger('sqlalchemy.engine').setLevel(logging.INFO) >> >> >> session =Session(bind=engine) >> >> query =session.query(Pigeon).filter(Pigeon.wing_length >5) >> >> >> # First query for everything >> >> query.all() >> >> >> # Then query for deletion >> >> query.delete() >> >> | >> >> When running the all() query, the SQL that is logged to stdout is as >> expected -- it includes conditioning both on wing_length, and bird_type >> >> | >> 2016-09-12 18:26:22,578 INFO sqlalchemy.engine.base.Engine SELECT >> bird.id AS bird_id, bird.wing_length AS bird_wing_length, bird.bird_type >> AS bird_bird_type >> FROM bird >> WHERE bird.wing_length > ? AND bird.bird_type IN (?) >> 2016-09-12 18:26:22,579 INFO sqlalchemy.engine.base.Engine (5, 'Bird') >> | >> >> >> however, the conditioning on bird_type is not present when calling delete(): >> >> | >> 2016-09-12 18:26:22,584 INFO sqlalchemy.engine.base.Engine DELETE FROM >> bird WHERE bird.wing_length > ? >> 2016-09-12 18:26:22,584 INFO sqlalchemy.engine.base.Engine (5,) >> | >> >> >> The documentation includes some caveats about using the bulk delete with >> ORM, but from my reading these don't include the behaviour observed >> above. Would someone be able to confirm that this is indeed a bug >> please? If so, my guess as to the fix is that a few more thinks need to >> be added to the QueryContext which is constructed in >> orm.persistence.BulkUD._do_pre -- I'm not at all familiar with the code >> though, so it's just a hypothesis :) >> >> Thoughts and help would be much appreciated please! >> >> Thanks very much, >> Tom >> >> >> -- >> You received this message because you are subscribed to the Google >> Groups "sqlalchemy" group. >> To unsubscribe from this group and stop receiving emails from it, send >> an email to sqlalchemy+unsubscr...@googlegroups.com >> <mailto:sqlalchemy+unsubscr...@googlegroups.com> >> <mailto:sqlalchemy+unsubscr...@googlegroups.com >> <mailto:sqlalchemy+unsubscr...@googlegroups.com>>. >> To post to this group, send email to sqlalchemy@googlegroups.com >> <mailto:sqlalchemy@googlegroups.com> >> <mailto:sqlalchemy@googlegroups.com <mailto:sqlalchemy@googlegroups.com>>. >> Visit this group at https://groups.google.com/group/sqlalchemy >> <https://groups.google.com/group/sqlalchemy>. >> For more options, visit https://groups.google.com/d/optout >> <https://groups.google.com/d/optout>. > > -- > You received this message because you are subscribed to a topic in the Google > Groups "sqlalchemy" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/sqlalchemy/xusa7fjWnh0/unsubscribe. > To unsubscribe from this group and all its topics, send an email to > sqlalchemy+unsubscr...@googlegroups.com. > To post to this group, send email to sqlalchemy@googlegroups.com. > Visit this group at https://groups.google.com/group/sqlalchemy. > For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups "sqlalchemy" group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.