[sqlalchemy] Problems with merge relations
I'm using merge to push objects into a db. (Long story short: I have a set of objects that have to behave identically if they are persisted or not, and may be retrieved or sent to a set of databases. Hence the use of merge.) However, merged objects appear object joined by a relation and backrefs twice. Is this a bug or an I making some subtle mistake? A condensed demonstration - the names of the mapped objects and tables are unimportant, but a Biosequence has a one-to-many with a set of Annotations, established by a backref:: from sqlalchemy import * from sqlalchemy.orm import * metadata = MetaData() class Biosequence (object): pass class Annotation (object): pass table_biosequences = Table ('biosequences', metadata, Column ('identifier', Integer(), primary_key=True), Column ('dummy', String(16)), ) table_seqannotations = Table ('seqannotations', metadata, Column ('identifier', Integer(), primary_key=True), Column ('biosequence_id', Integer(), ForeignKey ('biosequences.identifier')), ) mapper (Annotation, table_seqannotations) mapper (Biosequence, table_biosequences, properties={ 'annotations':relation ( Annotation, backref='biosequence_ref', lazy=False, cascade=all, delete, delete-orphan, ), }, ) engine = create_engine ('sqlite:///', convert_unicode=True, # echo=True, ) sessionfactory = sessionmaker (bind=engine, autoflush=False, transactional=False) session = sessionfactory() metadata.create_all (bind=engine, checkfirst=True) # make an object with 3 'children' bseq = Biosequence() anns = [Annotation() for x in range (3)] bseq.annotations = anns print Original num of anns:, len (bseq.annotations) # the merged copy has 6 children merge_bseq = session.merge (bseq) session.flush() print Now num of anns still:, len (bseq.annotations) print Ids:, [x.identifier for x in bseq.annotations] print Merged copy num of anns:, len (merge_bseq.annotations) print Ids:, [x.identifier for x in merge_bseq.annotations] # as does the return! results = session.query (Biosequence) print Number of results, results.count() returned_bseq = results.one() print Returned num of anns:, len (returned_bseq.annotations) print Ids:, [x.identifier for x in returned_bseq.annotations] # make an new object with 3 children bseq2 = Biosequence() bseq2.annotations = [Annotation() for x in range (3)] print New obj num of anns:, len (bseq.annotations) session.save_or_update (bseq2) session.flush() # and it works as expected results = session.query (Biosequence) print Number of retreived objects, results.count() returned_bseqs = results.all() for item in returned_bseqs: print Returned num of anns:, len (item.annotations) print Ids:, [x.identifier for x in item.annotations] Which returns:: Original num of anns: 3 Now num of anns still: 3 Ids: [None, None, None] Merged copy num of anns: 6 Ids: [1, 1, 2, 2, 3, 3] Number of results 1 Returned num of anns: 6 Ids: [1, 1, 2, 2, 3, 3] New obj num of anns: 3 Number of retreived objects 2 Returned num of anns: 6 Ids: [1, 1, 2, 2, 3, 3] Returned num of anns: 3 Ids: [4, 5, 6] In summary: if an object is stored using 'save_or_update', when later retrieved, it has the correct number of related children. If merged, the returned merge copy has each child twice. If this object is retrieved later, it still has every child twice. Looking at the db, the correct number of child rows is being stored and the relations are correct. It therefore looks like there's a problem in the session for merged objects. Any pointers? -- Dr Paul-Michael Agapow: VieDigitale / Inst. for Animal Health [EMAIL PROTECTED] / [EMAIL PROTECTED] --~--~-~--~~~---~--~~ 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: odd question
On Jan 23, 2008 10:24 PM, Monty Taylor [EMAIL PROTECTED] wrote: This may or may not be elixir specific... If I have an auto-generated mapping table for a many-to-many relationship, is there a sensible way to add another column to it that's also has a foreign key relationship to a third table? Like, if I had this: Products id int name varchar ProductTypes id int name varchar Groups id int name varchar and then I defined a many to many between products and groups to get products_groups product_id group_id and I wanted to add producttype_id to that ... You'll probably want to use the Association Object pattern, as described at: http://www.sqlalchemy.org/docs/04/mappers.html#advdatamapping_relation_patterns_association And possibly, the AssociationProxy plugin, at: http://www.sqlalchemy.org/docs/04/plugins.html#plugins_associationproxy This one can be used with Elixir just fine. You just need to import it from SQLAlchemy: from sqlalchemy.ext.associationproxy import AssociationProxy -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ 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: a way to share Session.mapper(SomeObject) across two scoped sessions?
On Jan 25, 2008 9:18 PM, Michael Bayer [EMAIL PROTECTED] wrote: On Jan 25, 2008, at 2:02 PM, Kumar McMillan wrote: On Jan 25, 2008 11:58 AM, Michael Bayer [EMAIL PROTECTED] wrote: The Session.mapper function is not worth it, in my opinion, it exists due to the sheer popularity of its previous incarnation, assign_mapper. I much prefer keeping things explicit. I can understand that. I am trying to get this working for an application that has its entire model declared in Elixir already. I like how easy Elixir is and so I'd rather not abandon that layer. But, there is probably a way to configure Elixir for save_on_init=False, I will give it a go. You can provide your own session (configured as you wish) to Elixir. Only the default provided session (it's there for your convenience only but you can perfectly not use it) use Session.mapper (and hence the save_on_init thing). elixir shouldn't be dependent on Session.mapper, if it is, I would advise the elixir folks change that requirement ASAP. in my view, at this point elixir should be for mapper configuration only; after that it should hand off to straight SQLAlchemy for normal runtime operation with any kind of Session configuration; else its just getting in the way. As I said above, it is not anymore (it used to be dependent on assign_mapper), but I changed it to support any kind of session (in version 0.3 I think). The only thing, is that we still provide a default session, which is based on Session.mapper, for convenience and backward compatibility. Maybe we should state more prominently in the Elixir doc that this is only a default session and that you can use any session you like. -- Gaëtan de Menten http://openhex.org --~--~-~--~~~---~--~~ 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: a way to share Session.mapper(SomeObject) across two scoped sessions?
Gaetan de Menten wrote: The only thing, is that we still provide a default session, which is based on Session.mapper, for convenience and backward compatibility. Maybe we should state more prominently in the Elixir doc that this is only a default session and that you can use any session you like. FYI, I think this should go in the advanced tutorial I referred to this morning on the Elixir list... -- Jonathan LaCour http://cleverdevil.org --~--~-~--~~~---~--~~ 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: Problems with merge relations
its the backref. as a temporary workaround you can remove it for merge() to function properly. fix wil be out today and very possible release 0.4.3 will be today for this. On Jan 30, 2008, at 6:14 AM, Paul-Michael Agapow wrote: from sqlalchemy import * from sqlalchemy.orm import * metadata = MetaData() class Biosequence (object): pass class Annotation (object): pass table_biosequences = Table ('biosequences', metadata, Column ('identifier', Integer(), primary_key=True), Column ('dummy', String(16)), ) table_seqannotations = Table ('seqannotations', metadata, Column ('identifier', Integer(), primary_key=True), Column ('biosequence_id', Integer(), ForeignKey ('biosequences.identifier')), ) mapper (Annotation, table_seqannotations) mapper (Biosequence, table_biosequences, properties={ 'annotations':relation ( Annotation, backref='biosequence_ref', lazy=False, cascade=all, delete, delete-orphan, ), }, ) engine = create_engine ('sqlite:///', convert_unicode=True, # echo=True, ) sessionfactory = sessionmaker (bind=engine, autoflush=False, transactional=False) session = sessionfactory() metadata.create_all (bind=engine, checkfirst=True) # make an object with 3 'children' bseq = Biosequence() anns = [Annotation() for x in range (3)] bseq.annotations = anns print Original num of anns:, len (bseq.annotations) # the merged copy has 6 children merge_bseq = session.merge (bseq) session.flush() print Now num of anns still:, len (bseq.annotations) print Ids:, [x.identifier for x in bseq.annotations] print Merged copy num of anns:, len (merge_bseq.annotations) print Ids:, [x.identifier for x in merge_bseq.annotations] # as does the return! results = session.query (Biosequence) print Number of results, results.count() returned_bseq = results.one() print Returned num of anns:, len (returned_bseq.annotations) print Ids:, [x.identifier for x in returned_bseq.annotations] # make an new object with 3 children bseq2 = Biosequence() bseq2.annotations = [Annotation() for x in range (3)] print New obj num of anns:, len (bseq.annotations) session.save_or_update (bseq2) session.flush() # and it works as expected results = session.query (Biosequence) print Number of retreived objects, results.count() returned_bseqs = results.all() for item in returned_bseqs: print Returned num of anns:, len (item.annotations) print Ids:, [x.identifier for x in item.annotations] --~--~-~--~~~---~--~~ 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: Problems with merge relations
OK this issue is actually limited to transient objects only; that is, if you had flushed your session before doing the merge() it would have worked. The fix is in r4104. Im considering putting out 0.4.3 today as a mostly bugfix release but have not decided yet. On Jan 30, 2008, at 6:14 AM, Paul-Michael Agapow wrote: I'm using merge to push objects into a db. (Long story short: I have a set of objects that have to behave identically if they are persisted or not, and may be retrieved or sent to a set of databases. Hence the use of merge.) However, merged objects appear object joined by a relation and backrefs twice. Is this a bug or an I making some subtle mistake? A condensed demonstration - the names of the mapped objects and tables are unimportant, but a Biosequence has a one-to-many with a set of Annotations, established by a backref:: from sqlalchemy import * from sqlalchemy.orm import * metadata = MetaData() class Biosequence (object): pass class Annotation (object): pass table_biosequences = Table ('biosequences', metadata, Column ('identifier', Integer(), primary_key=True), Column ('dummy', String(16)), ) table_seqannotations = Table ('seqannotations', metadata, Column ('identifier', Integer(), primary_key=True), Column ('biosequence_id', Integer(), ForeignKey ('biosequences.identifier')), ) mapper (Annotation, table_seqannotations) mapper (Biosequence, table_biosequences, properties={ 'annotations':relation ( Annotation, backref='biosequence_ref', lazy=False, cascade=all, delete, delete-orphan, ), }, ) engine = create_engine ('sqlite:///', convert_unicode=True, # echo=True, ) sessionfactory = sessionmaker (bind=engine, autoflush=False, transactional=False) session = sessionfactory() metadata.create_all (bind=engine, checkfirst=True) # make an object with 3 'children' bseq = Biosequence() anns = [Annotation() for x in range (3)] bseq.annotations = anns print Original num of anns:, len (bseq.annotations) # the merged copy has 6 children merge_bseq = session.merge (bseq) session.flush() print Now num of anns still:, len (bseq.annotations) print Ids:, [x.identifier for x in bseq.annotations] print Merged copy num of anns:, len (merge_bseq.annotations) print Ids:, [x.identifier for x in merge_bseq.annotations] # as does the return! results = session.query (Biosequence) print Number of results, results.count() returned_bseq = results.one() print Returned num of anns:, len (returned_bseq.annotations) print Ids:, [x.identifier for x in returned_bseq.annotations] # make an new object with 3 children bseq2 = Biosequence() bseq2.annotations = [Annotation() for x in range (3)] print New obj num of anns:, len (bseq.annotations) session.save_or_update (bseq2) session.flush() # and it works as expected results = session.query (Biosequence) print Number of retreived objects, results.count() returned_bseqs = results.all() for item in returned_bseqs: print Returned num of anns:, len (item.annotations) print Ids:, [x.identifier for x in item.annotations] Which returns:: Original num of anns: 3 Now num of anns still: 3 Ids: [None, None, None] Merged copy num of anns: 6 Ids: [1, 1, 2, 2, 3, 3] Number of results 1 Returned num of anns: 6 Ids: [1, 1, 2, 2, 3, 3] New obj num of anns: 3 Number of retreived objects 2 Returned num of anns: 6 Ids: [1, 1, 2, 2, 3, 3] Returned num of anns: 3 Ids: [4, 5, 6] In summary: if an object is stored using 'save_or_update', when later retrieved, it has the correct number of related children. If merged, the returned merge copy has each child twice. If this object is retrieved later, it still has every child twice. Looking at the db, the correct number of child rows is being stored and the relations are correct. It therefore looks like there's a problem in the session for merged objects. Any pointers? -- Dr Paul-Michael Agapow: VieDigitale / Inst. for Animal Health [EMAIL PROTECTED] / [EMAIL PROTECTED] --~--~-~--~~~---~--~~ 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
[sqlalchemy] Re: Problems with merge relations
On Jan 30, 2008, at 12:39 PM, Michael Bayer wrote: OK this issue is actually limited to transient objects only; that is, if you had flushed your session before doing the merge() it would have worked. The fix is in r4104. Im considering putting out 0.4.3 today as a mostly bugfix release but have not decided yet. to clarify, i meant, if in your test case you were merge()ing Biosequence/Annotation objects which were already persistent from a previous flush(), that alleviates the bug. --~--~-~--~~~---~--~~ 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] Questions on MapperExtension
Hello, I have recently converted a Pylons app from SQLObject to SQLAlchemy 0.3.10. Conversion went quite well. I need to serialize access to some of my objects, so I've looked into extending MapperExtension as described at [1] to add a mutex on load. First, I define an extension and instantiate it: from sqlalchemy.orm import MapperExtension import mutex class MutexExtension(MapperExtension): def create_instance(self, mapper, selectcontext, row, class_): self.mutex = mutex.mutex() return None mutexext = MutexExtension() --- My mapper setup looks like this: switch_mapper = mapper (Switch, switch_table, extension=[mutexext.mutexext, sac.ext], properties={'ports':sqla.relation(SwitchPort)}) When I try to fetch objects from the database, I get a exception setting self.entity_name: Module sqlalchemy.orm.mapper:1485 in _instance instance = self._create_instance(context.session) else: instance._entity_name = self.entity_name if self.__should_log_debug: self.__log_debug(_instance(): created new instance %s identity %s % (mapperutil.instance_str(instance), %str(identitykey))) instance._entity_name = self.entity_name exceptions.AttributeError: 'NoneType' object has no attribute '_entity_name' What did I do wrong? Thanks, Ross [1] http://www.sqlalchemy.org/docs/03/adv_datamapping.html#advdatamapping_extending --~--~-~--~~~---~--~~ 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: Questions on MapperExtension
sorry, the docstring is wrong. create_instance() should return EXT_CONTINUE if it would like to bypass creating the instance itself. However, self here is the MapperExtension instance, not the mapped instance. the method is called before anything is created. if you want to populate an attribute on a newly loaded instance but not create it, you're better off using populate_instance(). return EXT_CONTINUE from that method as well. class MyExt(MapperExtension): def populate_instance(self, mapper, selectcontext, row, instance, **flags): if not hasattr(instance, 'mutex'): instance.mutex = mutex() return EXT CONTINUE the hasattr() is assuming you dont want to replace the mutex in the case of a session.refresh() or similar. On Jan 30, 2008, at 1:36 PM, Ross wrote: Hello, I have recently converted a Pylons app from SQLObject to SQLAlchemy 0.3.10. Conversion went quite well. I need to serialize access to some of my objects, so I've looked into extending MapperExtension as described at [1] to add a mutex on load. First, I define an extension and instantiate it: from sqlalchemy.orm import MapperExtension import mutex class MutexExtension(MapperExtension): def create_instance(self, mapper, selectcontext, row, class_): self.mutex = mutex.mutex() return None mutexext = MutexExtension() --- My mapper setup looks like this: switch_mapper = mapper (Switch, switch_table, extension=[mutexext.mutexext, sac.ext], properties={'ports':sqla.relation(SwitchPort)}) When I try to fetch objects from the database, I get a exception setting self.entity_name: Module sqlalchemy.orm.mapper:1485 in _instance instance = self._create_instance(context.session) else: instance._entity_name = self.entity_name if self.__should_log_debug: self.__log_debug(_instance(): created new instance %s identity %s % (mapperutil.instance_str(instance), %str(identitykey))) instance._entity_name = self.entity_name exceptions.AttributeError: 'NoneType' object has no attribute '_entity_name' What did I do wrong? Thanks, Ross [1] http://www.sqlalchemy.org/docs/03/adv_datamapping.html#advdatamapping_extending --~--~-~--~~~---~--~~ 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: DPAPI Error
On Jan 30, 2008, at 2:10 PM, jon wrote: Thanks for getting back to me and apologies for the stacktrace barf ;-) One thing...I have the following line in my environment.py: config['pylons.g'].sa_engine = engine_from_config(config, 'sqlalchemy.', convert_unicode=True, pool_size=1, max_overflow=3) I can turn on/off the convert_unicode option and I still get the same error. I spoke with one of our DBAs and he said the results of roleseq.nextval is a number. SA is looking for a String here or None, according to the exception error: exceptions.TypeError: expecting None or a string Sooo...is this still an SA thing and if so what do you suggest as a workaround? jon - none of that has anything to do with the error message here. You need to grep thorugh your code for the specific string : Sequence(u'roleseq'), or something equivalent. I know its there because the Oracle dialect does not invent or reflect any sequence names. You need to make that sequence name into a regular string object; as above you'd take out the u inside the parenthesis. let me know when you find it as I'd like to confirm this is the source of the issuethanks ! - mike --~--~-~--~~~---~--~~ 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: Questions on MapperExtension
On 0.3.x, use EXT_PASS rather than EXT_CONTINUE. Michael Bayer wrote: sorry, the docstring is wrong. create_instance() should return EXT_CONTINUE if it would like to bypass creating the instance itself. However, self here is the MapperExtension instance, not the mapped instance. the method is called before anything is created. if you want to populate an attribute on a newly loaded instance but not create it, you're better off using populate_instance(). return EXT_CONTINUE from that method as well. class MyExt(MapperExtension): def populate_instance(self, mapper, selectcontext, row, instance, **flags): if not hasattr(instance, 'mutex'): instance.mutex = mutex() return EXT CONTINUE the hasattr() is assuming you dont want to replace the mutex in the case of a session.refresh() or similar. On Jan 30, 2008, at 1:36 PM, Ross wrote: Hello, I have recently converted a Pylons app from SQLObject to SQLAlchemy 0.3.10. Conversion went quite well. I need to serialize access to some of my objects, so I've looked into extending MapperExtension as described at [1] to add a mutex on load. First, I define an extension and instantiate it: from sqlalchemy.orm import MapperExtension import mutex class MutexExtension(MapperExtension): def create_instance(self, mapper, selectcontext, row, class_): self.mutex = mutex.mutex() return None mutexext = MutexExtension() --- My mapper setup looks like this: switch_mapper = mapper (Switch, switch_table, extension=[mutexext.mutexext, sac.ext], properties={'ports':sqla.relation(SwitchPort)}) When I try to fetch objects from the database, I get a exception setting self.entity_name: Module sqlalchemy.orm.mapper:1485 in _instance instance = self._create_instance(context.session) else: instance._entity_name = self.entity_name if self.__should_log_debug: self.__log_debug(_instance(): created new instance %s identity %s % (mapperutil.instance_str(instance), %str(identitykey))) instance._entity_name = self.entity_name exceptions.AttributeError: 'NoneType' object has no attribute '_entity_name' What did I do wrong? Thanks, Ross [1] http://www.sqlalchemy.org/docs/03/adv_datamapping.html#advdatamapping_extending --~--~-~--~~~---~--~~ 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: Questions on MapperExtension
oh, 0.3. well theres another question. If you just converted from SQLObject, why to SA 0.3 ? 0.4 is the currently supported version and is also vastly superior to 0.3. On Jan 30, 2008, at 2:40 PM, jason kirtland wrote: On 0.3.x, use EXT_PASS rather than EXT_CONTINUE. Michael Bayer wrote: sorry, the docstring is wrong. create_instance() should return EXT_CONTINUE if it would like to bypass creating the instance itself. However, self here is the MapperExtension instance, not the mapped instance. the method is called before anything is created. if you want to populate an attribute on a newly loaded instance but not create it, you're better off using populate_instance(). return EXT_CONTINUE from that method as well. class MyExt(MapperExtension): def populate_instance(self, mapper, selectcontext, row, instance, **flags): if not hasattr(instance, 'mutex'): instance.mutex = mutex() return EXT CONTINUE the hasattr() is assuming you dont want to replace the mutex in the case of a session.refresh() or similar. On Jan 30, 2008, at 1:36 PM, Ross wrote: Hello, I have recently converted a Pylons app from SQLObject to SQLAlchemy 0.3.10. Conversion went quite well. I need to serialize access to some of my objects, so I've looked into extending MapperExtension as described at [1] to add a mutex on load. First, I define an extension and instantiate it: from sqlalchemy.orm import MapperExtension import mutex class MutexExtension(MapperExtension): def create_instance(self, mapper, selectcontext, row, class_): self.mutex = mutex.mutex() return None mutexext = MutexExtension() --- My mapper setup looks like this: switch_mapper = mapper (Switch, switch_table, extension=[mutexext.mutexext, sac.ext], properties={'ports':sqla.relation(SwitchPort)}) When I try to fetch objects from the database, I get a exception setting self.entity_name: Module sqlalchemy.orm.mapper:1485 in _instance instance = self._create_instance(context.session) else: instance._entity_name = self.entity_name if self.__should_log_debug: self.__log_debug(_instance(): created new instance %s identity %s % (mapperutil.instance_str(instance), %str(identitykey))) instance._entity_name = self.entity_name exceptions.AttributeError: 'NoneType' object has no attribute '_entity_name' What did I do wrong? Thanks, Ross [1] http://www.sqlalchemy.org/docs/03/adv_datamapping.html#advdatamapping_extending --~--~-~--~~~---~--~~ 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: DPAPI Error
Hi Mike, Thanks for your patience...here is the entry I have for that table in model/__init__.py role_table = Table('role', metadata, Column('roleseq', Integer, Sequence('roleseq'), primary_key=True), I know that I specifically didn't set things up for Unicode in this app either...this file is the only one that contains the Sequence declaration. Thanks, Jon On Jan 30, 11:34 am, Michael Bayer [EMAIL PROTECTED] wrote: On Jan 30, 2008, at 2:10 PM, jon wrote: Thanks for getting back to me and apologies for the stacktrace barf ;-) One thing...I have the following line in my environment.py: config['pylons.g'].sa_engine = engine_from_config(config, 'sqlalchemy.', convert_unicode=True, pool_size=1, max_overflow=3) I can turn on/off the convert_unicode option and I still get the same error. I spoke with one of our DBAs and he said the results of roleseq.nextval is a number. SA is looking for a String here or None, according to the exception error: exceptions.TypeError: expecting None or a string Sooo...is this still an SA thing and if so what do you suggest as a workaround? jon - none of that has anything to do with the error message here. You need to grep thorugh your code for the specific string : Sequence(u'roleseq'), or something equivalent. I know its there because the Oracle dialect does not invent or reflect any sequence names. You need to make that sequence name into a regular string object; as above you'd take out the u inside the parenthesis. let me know when you find it as I'd like to confirm this is the source of the issuethanks ! - mike --~--~-~--~~~---~--~~ 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: Questions on MapperExtension
Thanks - populate_instance does exactly what I was looking for! I went to SA 0.3 with SAContext because I was familiar with it. Porting from SQLObject was straightforward, but a fairly large task. From reading at pylonshq, converting 0.3 to 0.4 seemed to be much easier than converting SQLObject to SQLAlchemy. So I decided I'd tackle them as two phases so I could keep my code working for as long as possible. I know I'm going to want to upgrade at some point because I'll make good use of the self-referential updates. Thanks for the tips! On Jan 30, 2:48 pm, Michael Bayer [EMAIL PROTECTED] wrote: oh, 0.3. well theres another question. If you just converted from SQLObject, why to SA 0.3 ? 0.4 is the currently supported version and is also vastly superior to 0.3. On Jan 30, 2008, at 2:40 PM, jason kirtland wrote: On 0.3.x, use EXT_PASS rather than EXT_CONTINUE. Michael Bayer wrote: sorry, the docstring is wrong. create_instance() should return EXT_CONTINUE if it would like to bypass creating the instance itself. However, self here is the MapperExtension instance, not the mapped instance. the method is called before anything is created. if you want to populate an attribute on a newly loaded instance but not create it, you're better off using populate_instance(). return EXT_CONTINUE from that method as well. class MyExt(MapperExtension): def populate_instance(self, mapper, selectcontext, row, instance, **flags): if not hasattr(instance, 'mutex'): instance.mutex = mutex() return EXT CONTINUE the hasattr() is assuming you dont want to replace the mutex in the case of a session.refresh() or similar. On Jan 30, 2008, at 1:36 PM, Ross wrote: Hello, I have recently converted a Pylons app from SQLObject to SQLAlchemy 0.3.10. Conversion went quite well. I need to serialize access to some of my objects, so I've looked into extending MapperExtension as described at [1] to add a mutex on load. First, I define an extension and instantiate it: from sqlalchemy.orm import MapperExtension import mutex class MutexExtension(MapperExtension): def create_instance(self, mapper, selectcontext, row, class_): self.mutex = mutex.mutex() return None mutexext = MutexExtension() --- My mapper setup looks like this: switch_mapper = mapper (Switch, switch_table, extension=[mutexext.mutexext, sac.ext], properties={'ports':sqla.relation(SwitchPort)}) When I try to fetch objects from the database, I get a exception setting self.entity_name: Module sqlalchemy.orm.mapper:1485 in _instance instance = self._create_instance(context.session) else: instance._entity_name = self.entity_name if self.__should_log_debug: self.__log_debug(_instance(): created new instance %s identity %s % (mapperutil.instance_str(instance), %str(identitykey))) instance._entity_name = self.entity_name exceptions.AttributeError: 'NoneType' object has no attribute '_entity_name' What did I do wrong? Thanks, Ross [1]http://www.sqlalchemy.org/docs/03/adv_datamapping.html#advdatamapping... --~--~-~--~~~---~--~~ 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: DPAPI Error
hey jon - OK, I found an issue that is very likely to be what you are experiencing; easy to fix as always but unless you can run on SVN trunk r4106, you'll have to workaround it. There may be a schema identifier somewhere in your app that contains the identifier 'roleseq' as a unicode string, which is getting cached as a u''. So if you can't hunt that down (which you shouldn't have to), you can force it to cache the non-unicode string for now if you do this to your engine as early as possible (i.e. before the incorrect value gets cached): engine.dialect.identifier_preparer.format_sequence(Sequence('roleseq')) hope thats the issue. - mike On Jan 30, 2008, at 3:14 PM, jon wrote: Hi Mike, Thanks for your patience...here is the entry I have for that table in model/__init__.py role_table = Table('role', metadata, Column('roleseq', Integer, Sequence('roleseq'), primary_key=True), I know that I specifically didn't set things up for Unicode in this app either...this file is the only one that contains the Sequence declaration. Thanks, Jon On Jan 30, 11:34 am, Michael Bayer [EMAIL PROTECTED] wrote: On Jan 30, 2008, at 2:10 PM, jon wrote: Thanks for getting back to me and apologies for the stacktrace barf ;-) One thing...I have the following line in my environment.py: config['pylons.g'].sa_engine = engine_from_config(config, 'sqlalchemy.', convert_unicode=True, pool_size=1, max_overflow=3) I can turn on/off the convert_unicode option and I still get the same error. I spoke with one of our DBAs and he said the results of roleseq.nextval is a number. SA is looking for a String here or None, according to the exception error: exceptions.TypeError: expecting None or a string Sooo...is this still an SA thing and if so what do you suggest as a workaround? jon - none of that has anything to do with the error message here. You need to grep thorugh your code for the specific string : Sequence(u'roleseq'), or something equivalent. I know its there because the Oracle dialect does not invent or reflect any sequence names. You need to make that sequence name into a regular string object; as above you'd take out the u inside the parenthesis. let me know when you find it as I'd like to confirm this is the source of the issuethanks ! - mike --~--~-~--~~~---~--~~ 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: select.count() vs MSSQL
...or is select.alias().count().scalar()the standard way to do this? On Jan 30, 2008 7:29 PM, Rick Morrison [EMAIL PROTECTED] wrote: Just noticed that select.count() doesn't work on MSSQL. The implementation wraps the select() in an outer query; MSSQL requires an alias for the inner table when you do this. What's the visit_xxx function that we need to catch in the db module to ensure the inner query is aliasized ? --~--~-~--~~~---~--~~ 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: select.count() vs MSSQL
youd have to override visit_select() and pick up on compiler.is_subquery(). you could then do some tricks similar to what oracle.py does in visit_select() to create a wrapping layer. also i noticed the usage of a kwarg 'mssql_aliased' which seems to be referenced nowhere. On Jan 30, 2008, at 7:29 PM, Rick Morrison wrote: Just noticed that select.count() doesn't work on MSSQL. The implementation wraps the select() in an outer query; MSSQL requires an alias for the inner table when you do this. What's the visit_xxx function that we need to catch in the db module to ensure the inner query is aliasized ? --~--~-~--~~~---~--~~ 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: SQLAlchemy advanced tutorial at PyCon
On Jan 28, 4:23 pm, Jonathan Ellis [EMAIL PROTECTED] wrote: What would you like to see covered in an advanced SQLAlchemy session? Something on association objects would be good. --~--~-~--~~~---~--~~ 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: select.count() vs MSSQL
Thanks Mike, I've got my local visit_select() a bit munged-up right now with an implementation of OFFSET, so I'm going to wait a bit on this. In the meantime, a follow-up: Not every MSSQL subquery needs to be aliased, only when the subquery is used as a derived table, as the SA implementation of select.count() does. Is it safe to alias all subqueries (for example, those used by EXISTS etc.), or, is there some flag that select.count() sets that the aliasing code could check, or would it make more sense to have select.count() check a Dialect-specific flag like 'derived_tables_require_alias' and do the aliasing there? also i noticed the usage of a kwarg 'mssql_aliased' which seems to be referenced nowhere. Looks to me as if the kwarg is being used as a flag to avoid recursion into the visit_table() method. It may not be needed anymore, I'm not up on all the whens and hows of how the visitor pattern threads though all its calls for the Dialects. --~--~-~--~~~---~--~~ 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: select.count() vs MSSQL
On Jan 30, 2008, at 10:52 PM, Rick Morrison wrote: Thanks Mike, I've got my local visit_select() a bit munged-up right now with an implementation of OFFSET, so I'm going to wait a bit on this. In the meantime, a follow-up: Not every MSSQL subquery needs to be aliased, only when the subquery is used as a derived table, as the SA implementation of select.count() does. Is it safe to alias all subqueries (for example, those used by EXISTS etc.), or, is there some flag that select.count() sets that the aliasing code could check, or would it make more sense to have select.count() check a Dialect- specific flag like 'derived_tables_require_alias' and do the aliasing there? you can in fact alias whatever select you want, i think. select.count() doesn't produce any kind of special construct that could be detected in the compiler. there is the notion that subqueries which are used as scalar subqueries, i.e. for EXISTS, are wrapped in a _ScalarSelect wrapper (i.e. select.as_scalar()), but some more tracking would have to be added to the compiler to figure out that a particular SELECT is wrapped in a scalar (you could also do that tracking in the mssql compiler too by overriding visit_grouping()). also i noticed the usage of a kwarg 'mssql_aliased' which seems to be referenced nowhere. Looks to me as if the kwarg is being used as a flag to avoid recursion into the visit_table() method. It may not be needed anymore, I'm not up on all the whens and hows of how the visitor pattern threads though all its calls for the Dialects. yes its referenced there, somehow my text editor missed it earlier. --~--~-~--~~~---~--~~ 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: select.count() vs MSSQL
On Jan 30, 2008, at 11:08 PM, Michael Bayer wrote: you can in fact alias whatever select you want, i think. select.count() doesn't produce any kind of special construct that could be detected in the compiler. there is the notion that subqueries which are used as scalar subqueries, i.e. for EXISTS, are wrapped in a _ScalarSelect wrapper (i.e. select.as_scalar()), but some more tracking would have to be added to the compiler to figure out that a particular SELECT is wrapped in a scalar (you could also do that tracking in the mssql compiler too by overriding visit_grouping()). like this: Index: lib/sqlalchemy/databases/mssql.py === --- lib/sqlalchemy/databases/mssql.py (revision 4108) +++ lib/sqlalchemy/databases/mssql.py (working copy) @@ -896,6 +896,9 @@ else: return None +def visit_select(self, select, within_grouping=False, **kwargs): +return super(MSSQLCompiler, self).visit_select(select, **kwargs) + def visit_table(self, table, mssql_aliased=False, **kwargs): if mssql_aliased: return super(MSSQLCompiler, self).visit_table(table, **kwargs) Index: lib/sqlalchemy/sql/compiler.py === --- lib/sqlalchemy/sql/compiler.py (revision 4108) +++ lib/sqlalchemy/sql/compiler.py (working copy) @@ -230,7 +230,7 @@ return def visit_grouping(self, grouping, **kwargs): -return ( + self.process(grouping.elem) + ) +return ( + self.process(grouping.elem, within_grouping=True) + ) def visit_label(self, label, result_map=None): labelname = self._truncated_identifier(colident, label.name) --~--~-~--~~~---~--~~ 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 -~--~~~~--~~--~--~---