[sqlalchemy] post_update fails with backrefs set
In upgrading to 0.6.0 I've found a regression in behavior for relationships with backrefs that require post_update=True. from sqlalchemy import Table, Column, Integer, String, MetaData, create_engine, ForeignKey, ForeignKeyConstraint from sqlalchemy.orm import relation, sessionmaker, scoped_session, synonym, object_session, mapper, backref engine = create_engine('sqlite:///', echo=False) Session = scoped_session(sessionmaker(autoflush=True, autocommit=False, bind=engine)) metadata = MetaData() contacts = Table('contacts', metadata, Column('id', Integer, primary_key=True), Column('name', String(35)), Column('account_id', Integer), ForeignKeyConstraint(['account_id'], ['accounts.id'])) accounts = Table('accounts', metadata, Column('id', Integer, primary_key=True), Column('name', String(35)), Column('created_by_id', Integer), ForeignKeyConstraint(['created_by_id'], ['contacts.id'], name='fk1', use_alter=True)) class Contact(object): pass class Account(object): pass mapper(Contact, contacts, properties={ 'account': relation(Account, primaryjoin=contacts.c.account_id==accounts.c.id, post_update=True, #backref=backref('contacts', post_update=True) backref='contacts' ) }) mapper(Account, accounts, properties={ 'created_by': relation(Contact, primaryjoin=accounts.c.created_by_id==contacts.c.id), #'contacts': relation(Contact, primaryjoin=accounts.c.id==contacts.c.account_id) }) metadata.create_all(bind=engine) # create basic data frank = Contact() frank.name = Frank Session.add(frank) finc = Account() finc.name = Frank Inc. frank.account = finc Session.add(finc) Session.commit() Session.expunge_all() # reproduce the problem bob = Contact() bob.name = 'Bob' Session.add(bob) frank = Session.query(Contact).filter_by(name='Frank').first() finc = frank.account bob.account = finc assert bob.account == finc Session.commit() assert bob.account == finc If either backref on the 'account' relation of Contact is set then the UPDATE fails to issue. If the 'contacts' relation is defined directly on Account or the backref isn't defined at all then everything works as expected. This is tested on SQLAlchemy 0.6.0 with Python 2.6. I verified this as working under 0.5.8. -- 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.
[sqlalchemy] Re: reflecting (autoload=True) MySQL tinyint(1) fields
The docs for the MySQL dialect need to be updated to reflect this change. See http://www.sqlalchemy.org/docs/reference/dialects/mysql.html#sqlalchemy.dialects.mysql.TINYINT For what it's worth I'd really like to see this remain as an optional behavior. The BOOL/BOOLEN column types in MySQL are synonyms for TINYINT(1). Someone creating columns using BOOLs might reasonably expect to reflect that intention when autoloading. Really though, I just want a way to avoid manually overriding 200 column definitions. Is there a reasonable way to do that as is? On Mar 27, 5:29 pm, Michael Bayer mike...@zzzcomputing.com wrote: On Mar 27, 2010, at 5:17 PM, Michael Bayer wrote: On Mar 27, 2010, at 4:16 PM, Lloyd Kvam wrote: I've just discovered that some tinyint (8-bit) fields have had their values limited to 0 and 1 regardless of actual value supplied. Digging through the documentation, I've learned that when MySQL tables are reflected, tinyint(1) fields are processed as booleans. I did not find emails from others howling in pain, so I suppose most people are either happy with this behavior or unaffected. I understand why a bool column definition would be mapped to tinyint(1). However, doing the reverse, mapping tinyint(1) to bool, discards bits that MySQL would not discard. For me this was a misfeature. I would think that supplying bools to an integer field would work OK. In python 2 + True == 3. So people using booleans should not have too much difficulty, would they? Is there any chance you'd consider autoloading tinyint(1) as an integer field? sure i will remove this behavior today. it is out in r95ac46ca88ee. -- 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 athttp://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 athttp://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.
[sqlalchemy] Re: reflecting (autoload=True) MySQL tinyint(1) fields
0/1 generally works in Python but won't convert to formats with native boolean values correctly, in my case JSON. Just a note, your suggestion works for me but will fail for any unsigned columns. I have a working solution so I'm fine with moving on from the issue, Overall however, with MySQL's lack of a true boolean data type this change leaves MySQL users with no particularly clean way to represent true boolean types. Just my two cents. Thanks for the help. On May 4, 2:06 pm, Michael Bayer mike...@zzzcomputing.com wrote: On May 4, 2010, at 1:22 PM, Brad Wells wrote: The docs for the MySQL dialect need to be updated to reflect this change. Seehttp://www.sqlalchemy.org/docs/reference/dialects/mysql.html#sqlalche... For what it's worth I'd really like to see this remain as an optional behavior. The BOOL/BOOLEN column types in MySQL are synonyms for TINYINT(1). Someone creating columns using BOOLs might reasonably expect to reflect that intention when autoloading. Really though, I just want a way to avoid manually overriding 200 column definitions. Is there a reasonable way to do that as is? if you reflect as TINYINT you still get a 0/1 back in results and it still accepts True/False. You really need it to give you the True/ False tokens ? this is not entirely de facto in its methodology but this should work for now: # before create_engine is called from sqlalchemy.dialects.mysql import base base.ischema_names['tinyint'] = base.BOOLEAN On Mar 27, 5:29 pm, Michael Bayer mike...@zzzcomputing.com wrote: On Mar 27, 2010, at 5:17 PM, Michael Bayer wrote: On Mar 27, 2010, at 4:16 PM, Lloyd Kvam wrote: I've just discovered that some tinyint (8-bit) fields have had their values limited to 0 and 1 regardless of actual value supplied. Digging through the documentation, I've learned that when MySQL tables are reflected, tinyint(1) fields are processed as booleans. I did not find emails from others howling in pain, so I suppose most people are either happy with this behavior or unaffected. I understand why a bool column definition would be mapped to tinyint(1). However, doing the reverse, mapping tinyint(1) to bool, discards bits that MySQL would not discard. For me this was a misfeature. I would think that supplying bools to an integer field would work OK. In python 2 + True == 3. So people using booleans should not have too much difficulty, would they? Is there any chance you'd consider autoloading tinyint(1) as an integer field? sure i will remove this behavior today. it is out in r95ac46ca88ee. -- 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 athttp://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 athttp://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 athttp://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 athttp://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.
[sqlalchemy] Session-Aware Mapper deprecation page
Single table inheritance is broken in the given mapper creating function on the deprecation guide page. Returning the mapper corrects the issue. def session_mapper(scoped_session): def mapper(cls, *args, **kwargs): cls.query = scoped_session.query_property() return sqla_mapper(cls, *args, **kwargs) return mapper Thank you for the concise guide. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Column expressions and .count()
Is it possible to perform a query.count() on a query with a labeled column expression without count() adding the subselect? I need to filter on the value of the expression and get a count for a paged view. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] Re: 0.4 to 0.5 upgrade and 'One-to-many relation fails with unsaved, pending instance and is an orphan' error
Thank you for the detailed explanation of the problem and my possible solutions. On Jul 3, 10:14 am, Michael Bayer mike...@zzzcomputing.com wrote: oh man, i missed the biggest part of this one, after I noticed that you weren't doing anything to put the PhoneNumber in the session. Don't use Session.mapper. That is the main problem you're having in this specific case. Auto-adding free-standing objects to the session is a bad idea and I've downplayed the crap out of this legacy feature for years now. On Jul 2, 2009, at 7:21 PM, Brad Wells wrote: In the process of upgrading from 0.4 to 0.5 I've come across a troubling issue. With the following setup: from sqlalchemy import Table, Column, Integer, String, MetaData, create_engine, ForeignKey from sqlalchemy.orm import relation, sessionmaker, scoped_session engine = create_engine('sqlite:///mystuff.sqlite', echo=True) Session = scoped_session(sessionmaker(autoflush=True, transactional=True, bind=engine)) metadata = MetaData() mapper = Session.mapper time_zones = Table('time_zones', metadata, Column('id', Integer, primary_key=True), Column('name', String(35))) contacts = Table('contacts', metadata, Column('id', Integer, primary_key=True), Column('display_as', String(35)), Column('time_zone_id', Integer, ForeignKey ('time_zones.id'))) phone_numbers = Table('phone_numbers', metadata, Column('id', Integer, primary_key=True), Column('number', String(35)), Column('contact_id', Integer, ForeignKey ('contacts.id'))) class TimeZone(object): pass class Contact(object): pass class PhoneNumber(object): pass mapper(TimeZone, time_zones) mapper(Contact, contacts, properties={ 'time_zone': relation(TimeZone, backref='contacts'), 'phone_numbers': relation(PhoneNumber, backref='contact', cascade='all, delete-orphan') }) mapper(PhoneNumber, phone_numbers) metadata.create_all(bind=engine) ## Under 0.4 the following code executes fine: c = Contact(display_as='Fake, User') c.time_zone = TimeZone.query.filter_by(name='Africa/Algiers').first() ph = PhoneNumber(full='1234567890') c.phone_numbers.append(ph) Session.commit() But under 0.5 I receive an orphaned object error (see below for full output). I understand that the TimeZone query causes a flush in between the creation of the Contact and of the PhoneNumber. Without the flush in between (if the TimeZone query line is removed) SA 0.5 is correctly able execute the sample script. As per this thread (http://groups.google.com/group/sqlalchemy/ browse_thread/thread/6c71c61bc59223f?tvc=2) I see that a suggested remedy is to change the relation to cascade='all' rather than cascade='all, delete-orphan'. I would prefer not to do this as it really does make no sense in this case to have a PhoneNumber without a Contact. I could also set the relation via 'ph.contact = contact' but I would prefer to not have to comb all of our existing code for this new class of bug. What doesn't make sense to me is why 0.4 was able to correctly delay the insert of the new phone number record until after the query for the collection and now 0.5 can't. Thank you for the assistance -Brad Below is the full echo output of 0.4 and 0.5 0.4.8dev_r5095: 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 BEGIN 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 INSERT INTO contacts (display_as, time_zone_id) VALUES (?, ?) 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 ['Fake, User', None] 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 SELECT time_zones.id AS time_zones_id, time_zones.name AS time_zones_name FROM time_zones WHERE time_zones.name = ? ORDER BY time_zones.oid LIMIT 1 OFFSET 0 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 ['Africa/Algiers'] 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 SELECT phone_numbers.id AS phone_numbers_id, phone_numbers.number AS phone_numbers_number, phone_numbers.contact_id AS phone_numbers_contact_id FROM phone_numbers WHERE phone_numbers.contact_id = ? ORDER BY phone_numbers.oid 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 [4] 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 INSERT INTO phone_numbers (number, contact_id) VALUES (?, ?) 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 [None, 4] 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 COMMIT 0.5.4p2: sa_test.py:8: SADeprecationWarning: The 'transactional
[sqlalchemy] AttributeError: '_ProxyImpl' object has no attribute 'get_history'
I receive AttributeError: '_ProxyImpl' object has no attribute 'get_history' when attempting to use session.is_modified on a class with a synonym with a descriptor. Removing the descriptor from the synonym prevents the error. Code and full traceback below. # from sqlalchemy import Table, Column, Integer, String, MetaData, create_engine, ForeignKey from sqlalchemy.orm import relation, sessionmaker, scoped_session, mapper, synonym, object_session from sqlalchemy.orm.interfaces import MapperExtension class SynonymProp(object): def __init__(self, attribute): self._attribute = attribute def __set__(s, obj, value): setattr(obj, s._attribute, value) def __delete__(s, obj): delattr(obj, s._attribute) def __get__(s, obj, owner): if obj is None: return s return getattr(obj, s._attribute) class Extension(MapperExtension): def before_update(self, mapper, connection, instance): object_session(instance).is_modified(instance, include_collections=False) engine = create_engine('sqlite:///', echo=False) Session = scoped_session(sessionmaker(autoflush=True, autocommit=False, bind=engine)) metadata = MetaData() bananas = Table('bananas', metadata, Column('id', Integer, primary_key=True), Column('name', String(35))) class Banana(object): pass mapper(Banana, bananas, extension=Extension(), properties={ 'name': synonym('_name', map_column=True, descriptor=SynonymProp ('_name')) }) metadata.create_all(bind=engine) b1 = Banana() Session.add(b1) Session.commit() b1.name = 'Bob' Session.commit() # Traceback (most recent call last): File sa_test.py, line 50, in module Session.commit() File c:\program files\python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\scoping.py, line 121, in do return getattr(self.registry(), name)(*args, **kwargs) File C:\PROGRA~1\Python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\session.py, line 673, in commit self.transaction.commit() File C:\PROGRA~1\Python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\session.py, line 378, in commit self._prepare_impl() File C:\PROGRA~1\Python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\session.py, line 362, in _prepare_impl self.session.flush() File C:\PROGRA~1\Python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\session.py, line 1354, in flush self._flush(objects) File C:\PROGRA~1\Python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\session.py, line 1432, in _flush flush_context.execute() File c:\program files\python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\unitofwork.py, line 257, in execute UOWExecutor().execute(self, tasks) File c:\program files\python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\unitofwork.py, line 720, in execute self.execute_save_steps(trans, task) File c:\program files\python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\unitofwork.py, line 735, in execute_save_steps self.save_objects(trans, task) File c:\program files\python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\unitofwork.py, line 726, in save_objects task.mapper._save_obj(task.polymorphic_tosave_objects, trans) File c:\program files\python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\mapper.py, line 1251, in _save_obj mapper.extension.before_update(mapper, connection, state.obj()) File c:\program files\python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\util.py, line 234, in _do ret = getattr(ext, method)(*args, **kwargs) File sa_test.py, line 22, in before_update object_session(instance).is_modified(instance, include_collections=False) File C:\PROGRA~1\Python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\session.py, line 1483, in is_modified (added, unchanged, deleted) = attr.get_history(instance, passive=passive) File C:\PROGRA~1\Python\lib\site-packages\sqlalchemy-0.5.4p2- py2.5.egg\sqlalchemy\orm\attributes.py, line 108, in get_history return self.impl.get_history(instance_state(instance), instance_dict(instance), **kwargs) AttributeError: '_ProxyImpl' object has no attribute 'get_history' --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@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 -~--~~~~--~~--~--~---
[sqlalchemy] 0.4 to 0.5 upgrade and 'One-to-many relation fails with unsaved, pending instance and is an orphan' error
In the process of upgrading from 0.4 to 0.5 I've come across a troubling issue. With the following setup: from sqlalchemy import Table, Column, Integer, String, MetaData, create_engine, ForeignKey from sqlalchemy.orm import relation, sessionmaker, scoped_session engine = create_engine('sqlite:///mystuff.sqlite', echo=True) Session = scoped_session(sessionmaker(autoflush=True, transactional=True, bind=engine)) metadata = MetaData() mapper = Session.mapper time_zones = Table('time_zones', metadata, Column('id', Integer, primary_key=True), Column('name', String(35))) contacts = Table('contacts', metadata, Column('id', Integer, primary_key=True), Column('display_as', String(35)), Column('time_zone_id', Integer, ForeignKey ('time_zones.id'))) phone_numbers = Table('phone_numbers', metadata, Column('id', Integer, primary_key=True), Column('number', String(35)), Column('contact_id', Integer, ForeignKey ('contacts.id'))) class TimeZone(object): pass class Contact(object): pass class PhoneNumber(object): pass mapper(TimeZone, time_zones) mapper(Contact, contacts, properties={ 'time_zone': relation(TimeZone, backref='contacts'), 'phone_numbers': relation(PhoneNumber, backref='contact', cascade='all, delete-orphan') }) mapper(PhoneNumber, phone_numbers) metadata.create_all(bind=engine) ## Under 0.4 the following code executes fine: c = Contact(display_as='Fake, User') c.time_zone = TimeZone.query.filter_by(name='Africa/Algiers').first() ph = PhoneNumber(full='1234567890') c.phone_numbers.append(ph) Session.commit() But under 0.5 I receive an orphaned object error (see below for full output). I understand that the TimeZone query causes a flush in between the creation of the Contact and of the PhoneNumber. Without the flush in between (if the TimeZone query line is removed) SA 0.5 is correctly able execute the sample script. As per this thread (http://groups.google.com/group/sqlalchemy/ browse_thread/thread/6c71c61bc59223f?tvc=2) I see that a suggested remedy is to change the relation to cascade='all' rather than cascade='all, delete-orphan'. I would prefer not to do this as it really does make no sense in this case to have a PhoneNumber without a Contact. I could also set the relation via 'ph.contact = contact' but I would prefer to not have to comb all of our existing code for this new class of bug. What doesn't make sense to me is why 0.4 was able to correctly delay the insert of the new phone number record until after the query for the collection and now 0.5 can't. Thank you for the assistance -Brad Below is the full echo output of 0.4 and 0.5 0.4.8dev_r5095: 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 BEGIN 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 INSERT INTO contacts (display_as, time_zone_id) VALUES (?, ?) 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 ['Fake, User', None] 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 SELECT time_zones.id AS time_zones_id, time_zones.name AS time_zones_name FROM time_zones WHERE time_zones.name = ? ORDER BY time_zones.oid LIMIT 1 OFFSET 0 2009-07-02 18:51:17,391 INFO sqlalchemy.engine.base.Engine.0x..70 ['Africa/Algiers'] 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 SELECT phone_numbers.id AS phone_numbers_id, phone_numbers.number AS phone_numbers_number, phone_numbers.contact_id AS phone_numbers_contact_id FROM phone_numbers WHERE phone_numbers.contact_id = ? ORDER BY phone_numbers.oid 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 [4] 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 INSERT INTO phone_numbers (number, contact_id) VALUES (?, ?) 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 [None, 4] 2009-07-02 18:51:17,407 INFO sqlalchemy.engine.base.Engine.0x..70 COMMIT 0.5.4p2: sa_test.py:8: SADeprecationWarning: The 'transactional' argument to sessionmaker() is deprecated; use autocommit=True|False instead. Session = scoped_session(sessionmaker(autoflush=True, transactional=True, bind=engine)) 2009-07-02 18:54:41,658 INFO sqlalchemy.engine.base.Engine.0x...2f30 PRAGMA table_info(time_zones) 2009-07-02 18:54:41,658 INFO sqlalchemy.engine.base.Engine.0x...2f30 () 2009-07-02 18:54:41,658 INFO sqlalchemy.engine.base.Engine.0x...2f30 PRAGMA table_info(contacts) 2009-07-02 18:54:41,658 INFO sqlalchemy.engine.base.Engine.0x...2f30 () 2009-07-02 18:54:41,658 INFO sqlalchemy.engine.base.Engine.0x...2f30 PRAGMA table_info(phone_numbers) 2009-07-02 18:54:41,658 INFO sqlalchemy.engine.base.Engine.0x...2f30 () 2009-07-02 18:54:41,658 INFO
[sqlalchemy] AttributeError: 'property' object has no attribute 'impl'
I receive the following error with SA 0.4.7p1 and the latest 0.4 svn revision. AttributeError: 'property' object has no attribute 'impl' Mappers == mapper(TransactionType, transaction_types) transactions_mapper = mapper(Transaction, transactions, order_by=transactions.c.date, extension=[HistoryMapperExtension(), TransactionDateMapperExtension()], polymorphic_on=transactions.c.transaction_type_id, polymorphic_identity=0, exclude_properties=['number', 'address', 'shipping', 'handling', 'purchase_order', 'contact_note', 'notes', 'valid_until'], properties={ '_voided_at': transactions.c.voided_at, '_date': transactions.c.date, 'method': relation(PaymentMethodType, backref='transactions'), 'transaction_type': relation(TransactionType, backref='transactions'), 'created_by_id': transactions.c.created_by, 'updated_by_id': transactions.c.updated_by, 'created_by': relation(Contact, primaryjoin=transactions.c.created_by==contacts.c.id), 'updated_by': relation(Contact, primaryjoin=transactions.c.updated_by==contacts.c.id), }) mapper(Cost, inherits=transactions_mapper, polymorphic_identity=1, properties={ 'line_items': relation(LineItem, backref='cost', cascade='delete') }) mapper(Payment, inherits=transactions_mapper, polymorphic_identity=2) mapper(Receipt, inherits=transactions_mapper, polymorphic_identity=4) mapper(Adjustment, inherits=transactions_mapper, polymorphic_identity=5) abstract_sales_mapper = mapper(AbstractSale, inherits=transactions_mapper, polymorphic_on=transactions.c.transaction_type_id, properties={ 'number': transactions.c.number, 'address': transactions.c.address, 'shipping': transactions.c.shipping, 'handling': transactions.c.handling, 'purchase_order': transactions.c.purchase_order, 'contact_note': transactions.c.contact_note, 'notes': transactions.c.notes, 'payment_terms': relation(PaymentTerm, backref='abstract_sales'), 'line_items': relation(LineItem, backref='sale', cascade='delete', order_by=line_items.c.position) }) mapper(Sale, inherits=abstract_sales_mapper, polymorphic_identity=3) mapper(Quote, inherits=abstract_sales_mapper, polymorphic_identity=6, properties={ '_valid_until': transactions.c.valid_until }) The error occurs when performing a query on Transaction ex: Transaction.query.get(111) where row id 111 is a Quote type. If a query uses the specific class type ex: Quote.query.get(111) it completes successfully. I don't know if this is an SA bug or an error in my mappers. Any help is appreciated. -brad Full Traceback === In [53]: m.Transaction.query.get(112) ERROR: An unexpected error occurred while tokenizing input The following traceback may be corrupted or invalid The error message is: ('EOF in multi-line statement', (141, 0)) --- AttributeErrorTraceback (most recent call last) C:\Documents and Settings\bwells\workspace\ERP GIT TEST\erp\ipython console in module() C:\Program Files\Python\lib\site-packages\sqlalchemy-0.4.7p1-py2.5.egg \sqlalchemy\orm\query.pyc in get(self, ident, **kw args) 267 268 key = self.mapper.identity_key_from_primary_key(ident) -- 269 return self._get(key, ident, **kwargs) 270 271 def load(self, ident, raiseerr=True, **kwargs): C:\Program Files\Python\lib\site-packages\sqlalchemy-0.4.7p1-py2.5.egg \sqlalchemy\orm\query.pyc in _get(self, key, ident , refresh_instance, lockmode, only_load_props) 1066 try: 1067 # call using all() to avoid LIMIT compilation complexity - 1068 return q.all()[0] 1069 except IndexError: 1070 return None C:\Program Files\Python\lib\site-packages\sqlalchemy-0.4.7p1-py2.5.egg \sqlalchemy\orm\query.pyc in all(self) 876 877 -- 878 return list(self) 879 880 C:\Program Files\Python\lib\site-packages\sqlalchemy-0.4.7p1-py2.5.egg \sqlalchemy\orm\query.pyc in iterate_instances(sel f, cursor, *mappers_or_columns, **kwargs) 1001 rows = [] 1002 for row in fetch: - 1003 process[0](context, row, rows) 1004 elif single_entity: 1005 rows = [process[0](context, row) for row in fetch] C:\Program Files\Python\lib\site-packages\sqlalchemy-0.4.7p1-py2.5.egg \sqlalchemy\orm\query.pyc in main(context, row, re sult) 1579 row = context.row_adapter(row) 1580 self.mapper._instance(context, row, result, - 1581 extension=context.extension, only_load_props=context.only_load_props, refresh_instance=conte
[sqlalchemy] Orphan error
With the following simplified setup I receive the following error: FlushError: instance erp.model.financial.TransactionOffset object at 0x0203CC90 is an unsaved, pending instance and is an orphan (is not attached to any parent 'Transaction' instance via that classes' 'offsets' attribute) When attempting something along the lines of transactions = Transaction.query.all() offset = TransactionOffset() offset.transaction = transactions[4] offset.offset_transaction = transactions[5] meta.Session.commit() However, if I append offset to transactions[4].offsets it will save transaction_id, but not offset_transaction_id Classes: class Transaction(Entity): pass class TransactionOffset(Entity): pass Tables: transactions = Table('transactions', meta, Column('id', Integer, primary_key=True), Column('date', Date), Column('description', Text), Column('amount', Float), Column('transaction_code', String(50)), Column('approval_code', String(50)), Column('voided_at', DateTime), ) transaction_offsets = Table('transaction_offsets', meta, Column('id', Integer, primary_key=True), Column('amount', Float), Column('transaction_id', Integer), Column('offset_transaction_id', Integer), ForeignKeyConstraint(['transaction_id'], ['transactions.id']), ForeignKeyConstraint(['offset_transaction_id'], ['transactions.id']), ) Mappers: transactions_mapper = mapper(Transaction, transactions, properties={ 'offsets': relation(TransactionOffset, primaryjoin=transaction_offsets.c.transaction_id==transactions.c.id, cascade='all, delete- orphan'), }) mapper(TransactionOffset, transaction_offsets, properties={ 'transaction': relation(Transaction, primaryjoin=transaction_offsets.c.transaction_id==transactions.c.id, post_update=True), 'offset_transaction': relation(Transaction, primaryjoin=transaction_offsets.c.offset_transaction_id==transactions.c.id, post_update=True), }) -brad --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Re: Unknown inheritance type question
Thank you very much. again. -brad On Jun 5, 10:57 am, Michael Bayer [EMAIL PROTECTED] wrote: this mapping: transaction_sale_join = join(transactions, sales) mapper(Sale, transaction_sale_join, inherits=transactions_mapper, polymorphic_identity=3, properties={ 'line_items': relation(LineItem, backref='sale', cascade='all, delete-orphan') }) is incorrect. The inherits configuration will create the join from transactions-sales for you - Sale should be mapped directly to sales. On Jun 4, 2008, at 6:29 PM, Brad Wells wrote: The complexity of the following setup is that of the transaction type Sales also have their own table. I am unsure of how properly establish this relationship between Transactions, Sales and TransactionTypes. This setup so far allows me to create Sale objects and save them. However Sale.query.all() (for example) results in: OperationalError: (OperationalError) (1066, Not unique table/alias: 'transactions') any advice is appreciated. Tables: transactions = Table('transactions', meta, Column('id', Integer, primary_key=True), Column('transaction_type_id', Integer), ForeignKeyConstraint(['transaction_type_id'], ['transaction_types.id']), ) transaction_types = Table('transaction_types', meta, Column('id', Integer, primary_key=True), Column('name', String(15)), Column('has_line_items', Boolean), ) sales = Table('sales', meta, Column('id', Integer, primary_key=True), Column('address', Text), Column('shipping', Float), Column('handling', Float), Column('purchase_order', String(35)), Column('transaction_id', Integer), ForeignKeyConstraint(['transaction_id'], ['transactions.id']), ) line_items = Table('line_items', meta, Column('id', Integer, primary_key=True), Column('position', Integer), Column('description', Text), Column('quantity', Float), Column('units', String(15)), Column('unit_rate', Float), Column('tax', Float), Column('transaction_id', Integer), ForeignKeyConstraint(['transaction_id'], ['transactions.id']), ) Classes: class Transaction(Entity): pass class TransactionType(Entity): pass class Payment(Transaction): pass class Adjustment(Transaction): pass class Receipt(Transaction): pass # abstract class class LineItemTransaction(Transaction): pass class Cost(LineItemTransaction): pass class Sale(LineItemTransaction): pass class LineItem(Entity): pass Mappers: mapper(TransactionType, transaction_types) transactions_mapper = mapper(Transaction, transactions, polymorphic_on=transactions.c.transaction_type_id, polymorphic_identity=0, properties={ 'transaction_type': relation(TransactionType, backref='transactions'), }) mapper(Cost, inherits=transactions_mapper, polymorphic_identity=1, properties={ 'line_items': relation(LineItem, backref='cost', cascade='all, delete-orphan') }) mapper(Payment, inherits=transactions_mapper, polymorphic_identity=2) mapper(Receipt, inherits=transactions_mapper, polymorphic_identity=4) mapper(Adjustment, inherits=transactions_mapper, polymorphic_identity=5) transaction_sale_join = join(transactions, sales) mapper(Sale, transaction_sale_join, inherits=transactions_mapper, polymorphic_identity=3, properties={ 'line_items': relation(LineItem, backref='sale', cascade='all, delete-orphan') }) mapper(LineItem, line_items) -brad --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---
[sqlalchemy] Unknown inheritance type question
The complexity of the following setup is that of the transaction type Sales also have their own table. I am unsure of how properly establish this relationship between Transactions, Sales and TransactionTypes. This setup so far allows me to create Sale objects and save them. However Sale.query.all() (for example) results in: OperationalError: (OperationalError) (1066, Not unique table/alias: 'transactions') any advice is appreciated. Tables: transactions = Table('transactions', meta, Column('id', Integer, primary_key=True), Column('transaction_type_id', Integer), ForeignKeyConstraint(['transaction_type_id'], ['transaction_types.id']), ) transaction_types = Table('transaction_types', meta, Column('id', Integer, primary_key=True), Column('name', String(15)), Column('has_line_items', Boolean), ) sales = Table('sales', meta, Column('id', Integer, primary_key=True), Column('address', Text), Column('shipping', Float), Column('handling', Float), Column('purchase_order', String(35)), Column('transaction_id', Integer), ForeignKeyConstraint(['transaction_id'], ['transactions.id']), ) line_items = Table('line_items', meta, Column('id', Integer, primary_key=True), Column('position', Integer), Column('description', Text), Column('quantity', Float), Column('units', String(15)), Column('unit_rate', Float), Column('tax', Float), Column('transaction_id', Integer), ForeignKeyConstraint(['transaction_id'], ['transactions.id']), ) Classes: class Transaction(Entity): pass class TransactionType(Entity): pass class Payment(Transaction): pass class Adjustment(Transaction): pass class Receipt(Transaction): pass # abstract class class LineItemTransaction(Transaction): pass class Cost(LineItemTransaction): pass class Sale(LineItemTransaction): pass class LineItem(Entity): pass Mappers: mapper(TransactionType, transaction_types) transactions_mapper = mapper(Transaction, transactions, polymorphic_on=transactions.c.transaction_type_id, polymorphic_identity=0, properties={ 'transaction_type': relation(TransactionType, backref='transactions'), }) mapper(Cost, inherits=transactions_mapper, polymorphic_identity=1, properties={ 'line_items': relation(LineItem, backref='cost', cascade='all, delete-orphan') }) mapper(Payment, inherits=transactions_mapper, polymorphic_identity=2) mapper(Receipt, inherits=transactions_mapper, polymorphic_identity=4) mapper(Adjustment, inherits=transactions_mapper, polymorphic_identity=5) transaction_sale_join = join(transactions, sales) mapper(Sale, transaction_sale_join, inherits=transactions_mapper, polymorphic_identity=3, properties={ 'line_items': relation(LineItem, backref='sale', cascade='all, delete-orphan') }) mapper(LineItem, line_items) -brad --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups sqlalchemy group. To post to this group, send email to sqlalchemy@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/sqlalchemy?hl=en -~--~~~~--~~--~--~---