Great, adding the primary_key=True to the linkTypes table solved my problem, thank you very much...
Cheers... E.Ozgur Yilmaz Lead Technical Director eoyilmaz.blogspot.com www.ozgurfx.com On Tue, Jan 11, 2011 at 5:24 PM, Michael Bayer <mike...@zzzcomputing.com>wrote: > > On Jan 11, 2011, at 8:51 AM, Erkan Özgür Yılmaz wrote: > > Hi all, > > This is my first question regarding to SQLAlchemy, you can count me as a > newbie. Here is my problem: > > I've this inheritance between my Python classes, everything were working > fine until last night when I've added another class to my inheritance > hierarchy. I've tried to find the cause of that pretty much read all the > documentation about session, but couldn't find any solution. > > I'm going to try to reduce the things I'm writing here by not including all > the attributes/methods below, so warn me if you spot something: > > This is the basic inheritance to let you figure out what is inheriting from > what: > > > > There's a subtle configuration problem here that is causing the mapper to > create the entity in the database in a way that throws it off when it goes > to get it back. Ticket #2019 is added for a warning to be emitted > corresponding to this condition. "linkTypes" has no primary key column, so > that when the mapper inserts the rows for LinkType, it doesn't insert into > the final "linkTypes" table. Later, when you access .name, > "sound_link_type" has been expired, which is the default behavior after a > commit, and the mapper goes to load its data from all of its tables. No > row is present in linkTypes, so the load returns nothing and the mapper > assumes the identity key has been deleted. > > I'd also note that you probably don't need all those "inherit_condition" > parameters, those are figured out automatically based on foreign keys - only > if there are multiple ways to join between parent and child tables, and the > mapper throws an error, do you need to use that param. > > > class SimpleEntity(object): > pass > > class Entity(SimpleEntity): > pass > > class TypeEntity(Entity): > pass > > class LinkType(TypeEntity): > pass > > > > Here are the Tables (just the ones used with these classes, there are a lot > other tables too, I can paste them here if you ask for): > > # SIMPLE ENTITY > simpleEntities = Table( > "simpleEntities", metadata, > Column("id", Integer, primary_key=True), > Column("name", String(256), nullable=False), > Column("description", String), > > Column( > "created_by_id", > Integer, > ForeignKey("users.id", use_alter=True, name="x") > ), > > Column( > "updated_by_id", > Integer, > ForeignKey("users.id", use_alter=True, name="x") > ), > > Column("date_created", DateTime), > Column("date_updated", DateTime), > Column("entity_type", String(128), nullable=False), > UniqueConstraint('name', 'entity_type') > > ) > > > # ENTITY > entities = Table( > "entities", metadata, > Column( > "id", > ForeignKey("simpleEntities.id"), > primary_key=True > ), > ) > > > > # TYPEENTITIES > typeEntities = Table( > "typeEntities", metadata, > Column( > "id", > Integer, > ForeignKey("entities.id"), > primary_key=True, > ), > ) > > > # LINKTYPES > linkTypes = Table( > "linkTypes", metadata, > Column( > "id", > Integer, > ForeignKey("typeEntities.id"), > ), > ) > > > > Mappers: > > # SimpleEntity > mapper( > entity.SimpleEntity, > tables.simpleEntities, > properties={ > "_name": tables.simpleEntities.c.name, > "name": synonym("_name"), > "_description": tables.simpleEntities.c.description, > "description": synonym("_description"), > "_created_by": relationship( > user.User, > backref="_entities_created", > primaryjoin=tables.simpleEntities.c.created_by_id== \ > tables.users.c.id, > post_update=True, > uselist=False > ), > "created_by": synonym("_created_by"), > "_updated_by": relationship( > user.User, > backref="_entities_updated", > primaryjoin=tables.simpleEntities.c.updated_by_id== \ > tables.users.c.id, > post_update=True, > uselist=False > ), > "updated_by": synonym("_updated_by"), > "_date_created": tables.simpleEntities.c.date_created, > "date_created": synonym("_date_created"), > "_date_updated": tables.simpleEntities.c.date_updated, > "date_updated": synonym("_date_updated") > }, > polymorphic_on=tables.simpleEntities.c.entity_type, > polymorphic_identity="SimpleEntity" > ) > > > # Entity > mapper( > entity.Entity, > tables.entities, > inherits=entity.SimpleEntity, > inherit_condition=tables.entities.c.id==tables.simpleEntities.c.id > , > polymorphic_identity="Entity", > properties={ > "_tags": relationship( > tag.Tag, > secondary=tables.entity_tags, > backref="_entities" > ), > "tags": synonym("_tags") > } > ) > > > # TypeEntity > mapper( > entity.TypeEntity, > tables.typeEntities, > inherits=entity.Entity, > inherit_condition=tables.typeEntities.c.id==tables.entities.c.id, > polymorphic_identity="TypeEntity", > ) > > > > # LinkType > mapper( > types.LinkType, > tables.linkTypes, > inherits=entity.TypeEntity, > inherit_condition=tables.linkTypes.c.id==tables.typeEntities.c.id, > polymorphic_identity="LinkType", > ) > > > > Alright here it comes slowly, my session object is set up in another module > (like the classes, tables and mappers are all in seperate modules), but I'm > going to try to merge them here: > > >>> engine = create_engine("sqlite:///:memory:", "echo":True) > > here are calls for the mappers shown above: > >>> mappers.setup() > >>> create_all(engine) > >>> Session = sessionmaker(bind=engine) > >>> session = Session() > > >>> sound_link_type = LinkType(name="Sound") > >>> sound_linkt_type.__dict__ > {'_created_by': None, '_sa_instance_state': > <sqlalchemy.orm.state.InstanceState object at 0x19866d0>, '_description': > '', '_date_updated': datetime.datetime(2011, 1, 11, 15, 44, 27, 954088), > '_date_created': datetime.datetime(2011, 1, 11, 15, 44, 27, 954074), > '_tags': [], '_name': 'Sound', '_nice_name': 'sound', '_updated_by': None} > > >>> session.add(sound_link_type) > >>> session.commit() > 2011-01-11 15:46:23,955 INFO sqlalchemy.engine.base.Engine.0x...8f50 BEGIN > (implicit) > 2011-01-11 15:46:23,956 INFO sqlalchemy.engine.base.Engine.0x...8f50 INSERT > INTO "simpleEntities" (name, description, created_by_id, updated_by_id, > date_created, date_updated, entity_type) VALUES (?, ?, ?, ?, ?, ?, ?) > 2011-01-11 15:46:23,957 INFO sqlalchemy.engine.base.Engine.0x...8f50 > ('Sound', '', None, None, '2011-01-11 15:44:27.954074', '2011-01-11 > 15:44:27.954088', 'LinkType') > 2011-01-11 15:46:23,960 INFO sqlalchemy.engine.base.Engine.0x...8f50 INSERT > INTO entities (id) VALUES (?) > 2011-01-11 15:46:23,961 INFO sqlalchemy.engine.base.Engine.0x...8f50 (3,) > 2011-01-11 15:46:23,962 INFO sqlalchemy.engine.base.Engine.0x...8f50 INSERT > INTO "typeEntities" (id) VALUES (?) > 2011-01-11 15:46:23,962 INFO sqlalchemy.engine.base.Engine.0x...8f50 (3,) > 2011-01-11 15:46:23,964 INFO sqlalchemy.engine.base.Engine.0x...8f50 COMMIT > > > >>> sound_link_type.__dict__ > {'_sa_instance_state': <sqlalchemy.orm.state.InstanceState object at > 0x19866d0>, '_nice_name': 'sound'} > > > >>> sound_link_type.name > 2011-01-11 15:47:00,570 INFO sqlalchemy.engine.base.Engine.0x...8f50 BEGIN > (implicit) > 2011-01-11 15:47:00,571 INFO sqlalchemy.engine.base.Engine.0x...8f50 SELECT > "simpleEntities".description AS "simpleEntities_description", > "simpleEntities".date_updated AS "simpleEntities_date_updated", > "simpleEntities".date_created AS "simpleEntities_date_created", > "simpleEntities".name AS "simpleEntities_name", "simpleEntities".id AS > "simpleEntities_id", entities.id AS entities_id, "typeEntities".id AS > "typeEntities_id", "linkTypes".id AS "linkTypes_id", > "simpleEntities".created_by_id AS "simpleEntities_created_by_id", > "simpleEntities".updated_by_id AS "simpleEntities_updated_by_id", > "simpleEntities".entity_type AS "simpleEntities_entity_type" > FROM "simpleEntities" JOIN entities ON entities.id = "simpleEntities".id > JOIN "typeEntities" ON "typeEntities".id = entities.id JOIN "linkTypes" ON > "linkTypes".id = "typeEntities".id > WHERE "simpleEntities".id = ? > 2011-01-11 15:47:00,571 INFO sqlalchemy.engine.base.Engine.0x...8f50 (3,) > 2011-01-11 15:47:00,832 INFO sqlalchemy.engine.base.Engine.0x...8f50 SELECT > "simpleEntities".description AS "simpleEntities_description", > "simpleEntities".date_updated AS "simpleEntities_date_updated", > "simpleEntities".date_created AS "simpleEntities_date_created", > "simpleEntities".name AS "simpleEntities_name", "simpleEntities".id AS > "simpleEntities_id", entities.id AS entities_id, "typeEntities".id AS > "typeEntities_id", "linkTypes".id AS "linkTypes_id", > "simpleEntities".created_by_id AS "simpleEntities_created_by_id", > "simpleEntities".updated_by_id AS "simpleEntities_updated_by_id", > "simpleEntities".entity_type AS "simpleEntities_entity_type" > FROM "simpleEntities" JOIN entities ON entities.id = "simpleEntities".id > JOIN "typeEntities" ON "typeEntities".id = entities.id JOIN "linkTypes" ON > "linkTypes".id = "typeEntities".id > WHERE "simpleEntities".id = ? > 2011-01-11 15:47:00,832 INFO sqlalchemy.engine.base.Engine.0x...8f50 (3,) > sqlalchemy.orm.exc.ObjectDeletedError: Instance '<LinkType at 0x19865d0>' > has been deleted. > > > any idea ??? (also for the sake of brevity I didn't include the echoed > lines when I call create_all, I can send it too if it will help) > > E.Ozgur Yilmaz > Lead Technical Director > eoyilmaz.blogspot.com > www.ozgurfx.com > > -- > 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<sqlalchemy%2bunsubscr...@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.