[sqlalchemy] preserve polymorphic_identity for subclasses
hello, here's a test case: https://gist.github.com/plq/5ed0c135222ea76d77fc (also see below) is it possible to preserve the polymorphic_identity values of subclasses that contain changes to non-sqla parts of a class? I understand that the reason for this is D2.__mapper__.class_ != D2. Is there a way to clone the class mapper and change just the mapped class? best, burak ps: the test case: from sqlalchemy import Column, Integer from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class C(Base): __tablename__ = 'C' id = Column(Integer, primary_key=True) t = Column(Integer) __mapper_args__ = { 'polymorphic_on': t, 'polymorphic_identity': 1, } assert C().t == 1 class D(C): __mapper_args__ = { 'polymorphic_identity': 2, } assert D().t == 2 class D2(D): foo = 'bar' assert D2().t == 2 -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
[sqlalchemy] Using a backref-generated attribute in an event listener
I tried this code: @listens_for(AttachmentFolder.all_attachments, 'append') def _attachment_added(target, value, *unused): target.modified_dt = now_utc() However AttachmentFolder.all_attachments is a backref so it doesn't exist at import time (I usually register listeners right after the definition of the model class). So I tried using the mapper_configured event, but backrefs still don't exist at that point. Besides flipping the relationship/backref around (which would work only because I don't have any listeners on the relationship itself yet), is there any clean way to bind an event listener to a backref? -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] Using a backref-generated attribute in an event listener
On 6/29/15 5:37 AM, Adrian wrote: I tried this code: @listens_for(AttachmentFolder.all_attachments, 'append') def _attachment_added(target, value, *unused): target.modified_dt = now_utc() However AttachmentFolder.all_attachments is a backref so it doesn't exist at import time (I usually register listeners right after the definition of the model class). So I tried using the mapper_configured event, but backrefs still don't exist at that point. Besides flipping the relationship/backref around (which would work only because I don't have any listeners on the relationship itself yet), is there any clean way to bind an event listener to a backref? During mapper_configured(), backrefs which *originate* from that mapper should have been built up, however the receiving mapper may have already been invoked on mapper_configured() before this other mapper adds the backref relationship. For this reason the SQLAlchemy documentation (outside of the tutorial) recommends to forego the use of backref() and use two relationship() objects instead with back_populates; this is clearer and simpler. Another event you can use is the after_configured() event which fires once *all* mappers are set up, that would work also. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com mailto:sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com mailto:sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] preserve polymorphic_identity for subclasses
On 6/29/15 8:47 AM, Burak Arslan wrote: hello, here's a test case: https://gist.github.com/plq/5ed0c135222ea76d77fc (also see below) is it possible to preserve the polymorphic_identity values of subclasses that contain changes to non-sqla parts of a class? I understand that the reason for this is D2.__mapper__.class_ != D2. Is there a way to clone the class mapper and change just the mapped class? you can do this: class D2(D): foo = 'bar' __mapper_args__ = { 'polymorphic_identity': 2, } though you'll get a warning. SQLAlchemy expects that you will build up the functionality of your class *underneath* the mapping, that is, you can use mixins and __abstract__ to apply behaviors to your class, but the descendant-most class is the thing you're persisting. if you say session.add(D()) and session.add(D2()), the ORM will give you indeterminate results; if an identity is already present and it's a D2, you'll get a D2 back from a result set, otherwise you'll get a D. The design of mappings discourages designs that would produce this issue. best, burak ps: the test case: from sqlalchemy import Column, Integer from sqlalchemy.ext.declarative import declarative_base Base = declarative_base() class C(Base): __tablename__ = 'C' id = Column(Integer, primary_key=True) t = Column(Integer) __mapper_args__ = { 'polymorphic_on': t, 'polymorphic_identity': 1, } assert C().t == 1 class D(C): __mapper_args__ = { 'polymorphic_identity': 2, } assert D().t == 2 class D2(D): foo = 'bar' assert D2().t == 2 -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com mailto:sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com mailto:sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
[sqlalchemy] how to recycle connections grown stale after checkout
Hi, What is the best way to forcefully/manually “recycle” a checked out connection that I know to have become stale since it was checked out? And by stale, I mean this is a MySQL connection that has idled beyond MySQL’s wait_timeout (triggering a MySQL has gone away error when it's eventually accessed). While I’ve set pool_recycle to a value less than MySQL’s wait_timeout, this doesn’t help, as pool_recycle recycles connections only at checkout, and my connection is live at checkout but expiring after being checked out (due to some unavoidable long-running code). Here’s an illustration of the problem: engine = create_engine('mysql://…', pool_recycle=10) Session = sessionmaker(bind=engine) Base = declarative_base() session = Session() row = engine.execute(text(show session variables like 'wait_timeout' )).first() wait_timeout = int(row[1]) print session.query(MyModel).count() sleepfor = wait_timeout + 5 print Sleep for wait_timeout + 5 (sleeping for {} seconds)format( sleepfor) sleep(sleepfor) # this next query will fail with OperationalError: (_mysql_exceptions.OperationalError) (2006, 'MySQL server has gone away') print session.query(MyModel).count() I’ve come up with a few workarounds that seem to work, including: a) creating a new session for the second query, e.g. sleep(sleepfor) new_session = Session() print new_session.query(MyModel).count() ...and b) closing the session before the second query in order to trigger a recycle, e.g. sleep(sleepfor) session.close() print session.query(MyModel).count() But these seem heavy handed and wrong. What I’d like to do is just discard this stale connection (in my session and in the pool) and get a fresh one, but I can’t determine how to. Thanks for any help. Andy -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] how to recycle connections grown stale after checkout
Michael, Thanks very much. This helps. I'm using InnoDB without autocommit. The reason for the odd, long-idling connection is that I'm actually using Flask-SQLAlchemy, and the long-idling connection is held by Flask-SQLAlchemy's primary, request-scoped session. I do some long-running, non-transactional work in my request, then come back to the session and try to commit, and the connection, checked out at the start of the request, has become stale and been dropped by MySQL. Although this is specific to Flask-SQLAlchemy, the actual events are reproducible in SQLAlchemy (as above) so I figured it must be common and asked here. I recognize that session.connection().invalidate(), or close(), would result in loss of session state, but I need a way to pick up at this point and continue with additional queries even after the disconnect, so getting a fresh connection at that point seemed like the best approach. Thanks, Andy On Monday, June 29, 2015 at 4:14:11 PM UTC-4, Michael Bayer wrote: On 6/29/15 2:33 PM, Andy Crain wrote: But these seem heavy handed and wrong. What I’d like to do is just discard this stale connection (in my session and in the pool) and get a fresh one, but I can’t determine how to. at the bottom of that section, the important part is about invalidation: http://docs.sqlalchemy.org/en/rel_1_0/core/pooling.html#more-on-invalidation specifically invalidate(): http://docs.sqlalchemy.org/en/rel_1_0/core/connections.html?highlight=invalidate#sqlalchemy.engine.Connection.invalidate from session: session.connection().invalidate() however, you've now killed off your transaction, and you will lose whatever isn't committed on it.If you don't need the transaction to last this long, then you shouldn't have a connection checked out - the Session only has a connection checked out when you are in a transaction. So I think the original assertion due to some unavoidable long-running code doesn't really make any sense, especially if you are using an ORM Session.If this isn't impacting you because you are on MyISAM and are essentially using autocommit, then just set your Session to use autocommit: http://docs.sqlalchemy.org/en/rel_1_0/orm/session_transaction.html#autocommit-mode; no more stale connections. Thanks for any help. Andy -- 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+...@googlegroups.com javascript:. To post to this group, send email to sqlal...@googlegroups.com javascript:. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
[sqlalchemy] Re: how to recycle connections grown stale after checkout
Jonathan, Thanks, but I'm attempting to deal with connections that have expired *after* checkout. The strategies discussed at that URL address freshness of connections upon checkout. From that page: Note that the invalidation *only* occurs during checkout - not on any connections that are held in a checked out state. Thanks, Andy On Monday, June 29, 2015 at 3:46:29 PM UTC-4, Jonathan Vanasco wrote: http://docs.sqlalchemy.org/en/latest/core/pooling.html#dealing-with-disconnects -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
Re: [sqlalchemy] how to recycle connections grown stale after checkout
On 6/29/15 2:33 PM, Andy Crain wrote: But these seem heavy handed and wrong. What I’d like to do is just discard this stale connection (in my session and in the pool) and get a fresh one, but I can’t determine how to. at the bottom of that section, the important part is about invalidation: http://docs.sqlalchemy.org/en/rel_1_0/core/pooling.html#more-on-invalidation specifically invalidate(): http://docs.sqlalchemy.org/en/rel_1_0/core/connections.html?highlight=invalidate#sqlalchemy.engine.Connection.invalidate from session: session.connection().invalidate() however, you've now killed off your transaction, and you will lose whatever isn't committed on it.If you don't need the transaction to last this long, then you shouldn't have a connection checked out - the Session only has a connection checked out when you are in a transaction. So I think the original assertion due to some unavoidable long-running code doesn't really make any sense, especially if you are using an ORM Session.If this isn't impacting you because you are on MyISAM and are essentially using autocommit, then just set your Session to use autocommit: http://docs.sqlalchemy.org/en/rel_1_0/orm/session_transaction.html#autocommit-mode; no more stale connections. Thanks for any help. Andy -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com mailto:sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com mailto:sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout. -- You received this message because you are subscribed to the Google Groups sqlalchemy group. To unsubscribe from this group and stop receiving emails from it, send an email to sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.
[sqlalchemy] Re: how to recycle connections grown stale after checkout
http://docs.sqlalchemy.org/en/latest/core/pooling.html#dealing-with-disconnects -- 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 http://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.