Hi Mike,
Thanks for the quick response. If that's the intended behaviour I'll go
back to non-bulk inserts for my inherited types. Doubtless I could work
around it by inserting N new Entities, fetching their autoincrement ID's
then using them to make Child1 and Child2's but I don't trust myself with
the added complexity.
Cheers,
Alex.
On Monday, February 29, 2016 at 10:38:22 PM UTC, Alex Hewson wrote:
>
> Hello All,
>
> I'm trying to use the new bulk_save_objects() to improve performance on
> bulk inserts, and have run into a problem. If bulk_save_objects() is used
> to save objects of a polymorphic class..
>
>1. They are created correctly in the DB, with polymorphic type column
>populated correctly
>2. BUT queries for the new objects will return one of incorrect type.
>In my case I'm getting instances of Child1 back when I would expect to get
>a Child2.
>
> The following code demonstrates the problem:
>
> #!/usr/bin/env python3
> # -*- coding: utf-8 -*-
>
> from sqlalchemy import create_engine
> from sqlalchemy import Column, Integer, SmallInteger, String, ForeignKey
> from sqlalchemy.orm import sessionmaker
> from sqlalchemy.ext.declarative import declarative_base
>
> Base = declarative_base()
>
> class Entity(Base):
> __tablename__ = 'Entity'
> Id = Column(Integer, primary_key=True, nullable=False)
> Content = Column(String)
> _polytype = Column(SmallInteger, nullable=False)
>
> __mapper_args__ = {
> 'polymorphic_identity':1,
> 'polymorphic_on':_polytype
> }
>
> class Child1(Entity):
> __tablename__ = 'Child1'
> MyId= Column(ForeignKey("Entity.Id"), primary_key=True)
> __mapper_args__ = {'polymorphic_identity':11}
>
> class Child2(Entity):
> __tablename__ = 'Child2'
> MyId= Column(ForeignKey("Entity.Id"), primary_key=True)
> __mapper_args__ = {'polymorphic_identity':12}
>
>
> if __name__ == '__main__':
> # engine = create_engine('sqlite:///:memory:', echo=False)
> engine = create_engine('sqlite:///test.db', echo=False)
> Session = sessionmaker(bind=engine)
> sess = Session()
> Base.metadata.create_all(engine)
> c1_many = [Child1(Content="c1inst_%d"%i) for i in range(0,1000)]
> c2_many = [Child2(Content="c2inst_%d"%i) for i in range(0,1000)]
> sess.bulk_save_objects(c1_many)
> sess.bulk_save_objects(c2_many)
> # sess.add_all(c1_many)
> # sess.add_all(c2_many)
> sess.flush()
> sess.commit()
> for c in sess.query(Child1):
> assert isinstance(c, Child1)
> for c in sess.query(Child2):
> assert isinstance(c, Child2)
>
>
> All the calls to assert isinstance(c, Child1) complete successfully. But
> once we start checking for Child2 - boom, we are still getting back Child1
> instances.
>
> At first I wondered if I was misunderstanding SA's implementation of
> polymorphism, so tried inserting rows the traditional way with
> sess.add_all(). But that works fine so I think I've exposed a bug in the
> new bulk_save_objects() code.
>
> My environment is Python 3.5.1, SQLAlchemy==1.0.12, SQLite 3.8.10.2 on OSX.
>
--
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.