diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-02-11 14:41:29 -0500 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2011-02-11 14:41:29 -0500 |
commit | d7fda4ae03f0e1c1ab73ced15e7b0472f36d1024 (patch) | |
tree | 280225601b0b1768423babdef6fb52766f4b21d2 /lib/sqlalchemy | |
parent | 33eae4a1405b1968ad486bfe3aefee7f7d631128 (diff) | |
download | sqlalchemy-d7fda4ae03f0e1c1ab73ced15e7b0472f36d1024.tar.gz |
- Additional tuning to "many-to-one" relationship
loads during a flush(). A change in version 0.6.6
([ticket:2002]) required that more "unnecessary" m2o
loads during a flush could occur. Extra loading modes have
been added so that the SQL emitted in this
specific use case is trimmed back, while still
retrieving the information the flush needs in order
to not miss anything. [ticket:2049]
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r-- | lib/sqlalchemy/orm/attributes.py | 12 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/dependency.py | 7 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/query.py | 4 | ||||
-rw-r--r-- | lib/sqlalchemy/orm/strategies.py | 13 |
4 files changed, 31 insertions, 5 deletions
diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index ca1137c3f..c0ec474cb 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -37,9 +37,19 @@ PASSIVE_NO_INITIALIZE = True #util.symbol('PASSIVE_NO_INITIALIZE') # this is used by backrefs. PASSIVE_NO_FETCH = util.symbol('PASSIVE_NO_FETCH') -"""Symbol indicating that loader callables should not be fired off. +"""Symbol indicating that loader callables should not emit SQL. Non-initialized attributes should be initialized to an empty value.""" +PASSIVE_NO_FETCH_RELATED = util.symbol('PASSIVE_NO_FETCH_RELATED') +"""Symbol indicating that loader callables should not emit SQL for + the related object, but can refresh the attributes of the local + instance. + Non-initialized attributes should be initialized to an empty value. + + The unit of work uses this mode to check if history is present + with minimal SQL emitted. + """ + PASSIVE_ONLY_PERSISTENT = util.symbol('PASSIVE_ONLY_PERSISTENT') """Symbol indicating that loader callables should only fire off for persistent objects. diff --git a/lib/sqlalchemy/orm/dependency.py b/lib/sqlalchemy/orm/dependency.py index e3e2f5d56..dde0d94c8 100644 --- a/lib/sqlalchemy/orm/dependency.py +++ b/lib/sqlalchemy/orm/dependency.py @@ -219,7 +219,12 @@ class DependencyProcessor(object): pass def prop_has_changes(self, uowcommit, states, isdelete): - passive = not isdelete or self.passive_deletes + if not isdelete or self.passive_deletes: + passive = attributes.PASSIVE_NO_INITIALIZE + elif self.direction is MANYTOONE: + passive = attributes.PASSIVE_NO_FETCH_RELATED + else: + passive = attributes.PASSIVE_OFF for s in states: # TODO: add a high speed method diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index 71a6edd31..43699b4d9 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -1947,6 +1947,10 @@ class Query(object): if passive is attributes.PASSIVE_NO_FETCH: # TODO: no coverage here return attributes.PASSIVE_NO_RESULT + elif passive is attributes.PASSIVE_NO_FETCH_RELATED: + # this mode is used within a flush and the instance's + # expired state will be checked soon enough, if necessary + return instance try: state(passive) except orm_exc.ObjectDeletedError: diff --git a/lib/sqlalchemy/orm/strategies.py b/lib/sqlalchemy/orm/strategies.py index bf7f04995..8d5649a39 100644 --- a/lib/sqlalchemy/orm/strategies.py +++ b/lib/sqlalchemy/orm/strategies.py @@ -451,7 +451,8 @@ class LazyLoader(AbstractRelationshipLoader): pending = not state.key if ( - passive is attributes.PASSIVE_NO_FETCH and + (passive is attributes.PASSIVE_NO_FETCH or \ + passive is attributes.PASSIVE_NO_FETCH_RELATED) and not self.use_get ) or ( passive is attributes.PASSIVE_ONLY_PERSISTENT and @@ -476,12 +477,17 @@ class LazyLoader(AbstractRelationshipLoader): get_attr = instance_mapper._get_state_attr_by_column dict_ = state.dict + if passive is attributes.PASSIVE_NO_FETCH_RELATED: + attr_passive = attributes.PASSIVE_OFF + else: + attr_passive = passive + ident = [ get_attr( state, state.dict, self._equated_columns[pk], - passive=passive) + passive=attr_passive) for pk in prop_mapper.primary_key ] if attributes.PASSIVE_NO_RESULT in ident: @@ -494,7 +500,8 @@ class LazyLoader(AbstractRelationshipLoader): instance = Query._get_from_identity(session, ident_key, passive) if instance is not None: return instance - elif passive is attributes.PASSIVE_NO_FETCH: + elif passive is attributes.PASSIVE_NO_FETCH or \ + passive is attributes.PASSIVE_NO_FETCH_RELATED: return attributes.PASSIVE_NO_RESULT q = session.query(prop_mapper)._adapt_all_clauses() |