diff options
Diffstat (limited to 'lib/sqlalchemy/orm/query.py')
| -rw-r--r-- | lib/sqlalchemy/orm/query.py | 594 |
1 files changed, 302 insertions, 292 deletions
diff --git a/lib/sqlalchemy/orm/query.py b/lib/sqlalchemy/orm/query.py index c340e9856..12e11b26c 100644 --- a/lib/sqlalchemy/orm/query.py +++ b/lib/sqlalchemy/orm/query.py @@ -24,19 +24,19 @@ from itertools import chain from . import ( attributes, interfaces, object_mapper, persistence, exc as orm_exc, loading - ) +) from .base import _entity_descriptor, _is_aliased_class, \ - _is_mapped_class, _orm_columns, _generative + _is_mapped_class, _orm_columns, _generative from .path_registry import PathRegistry from .util import ( AliasedClass, ORMAdapter, join as orm_join, with_parent, aliased - ) +) from .. import sql, util, log, exc as sa_exc, inspect, inspection from ..sql.expression import _interpret_as_from from ..sql import ( - util as sql_util, - expression, visitors - ) + util as sql_util, + expression, visitors +) from ..sql.base import ColumnCollection from . import properties @@ -45,6 +45,7 @@ __all__ = ['Query', 'QueryContext', 'aliased'] _path_registry = PathRegistry.root + @inspection._self_inspects @log.class_logger class Query(object): @@ -124,22 +125,22 @@ class Query(object): if entity not in d: ext_info = inspect(entity) if not ext_info.is_aliased_class and \ - ext_info.mapper.with_polymorphic: + ext_info.mapper.with_polymorphic: if ext_info.mapper.mapped_table not in \ - self._polymorphic_adapters: + self._polymorphic_adapters: self._mapper_loads_polymorphically_with( ext_info.mapper, sql_util.ColumnAdapter( - ext_info.selectable, - ext_info.mapper._equivalent_columns + ext_info.selectable, + ext_info.mapper._equivalent_columns ) ) aliased_adapter = None elif ext_info.is_aliased_class: aliased_adapter = sql_util.ColumnAdapter( - ext_info.selectable, - ext_info.mapper._equivalent_columns - ) + ext_info.selectable, + ext_info.mapper._equivalent_columns + ) else: aliased_adapter = None @@ -163,17 +164,17 @@ class Query(object): info = inspect(from_obj) if hasattr(info, 'mapper') and \ - (info.is_mapper or info.is_aliased_class): + (info.is_mapper or info.is_aliased_class): self._select_from_entity = from_obj if set_base_alias: raise sa_exc.ArgumentError( - "A selectable (FromClause) instance is " - "expected when the base alias is being set.") + "A selectable (FromClause) instance is " + "expected when the base alias is being set.") fa.append(info.selectable) elif not info.is_selectable: raise sa_exc.ArgumentError( - "argument is not a mapped class, mapper, " - "aliased(), or FromClause instance.") + "argument is not a mapped class, mapper, " + "aliased(), or FromClause instance.") else: if isinstance(from_obj, expression.SelectBase): from_obj = from_obj.alias() @@ -184,11 +185,11 @@ class Query(object): self._from_obj = tuple(fa) if set_base_alias and \ - len(self._from_obj) == 1 and \ - isinstance(select_from_alias, expression.Alias): + len(self._from_obj) == 1 and \ + isinstance(select_from_alias, expression.Alias): equivs = self.__all_equivs() self._from_obj_alias = sql_util.ColumnAdapter( - self._from_obj[0], equivs) + self._from_obj[0], equivs) def _reset_polymorphic_adapter(self, mapper): for m2 in mapper._with_polymorphic_mappers: @@ -216,11 +217,11 @@ class Query(object): def _adapt_col_list(self, cols): return [ - self._adapt_clause( - expression._literal_as_text(o), - True, True) - for o in cols - ] + self._adapt_clause( + expression._literal_as_text(o), + True, True) + for o in cols + ] @_generative() def _adapt_all_clauses(self): @@ -270,18 +271,18 @@ class Query(object): # if 'orm only', look for ORM annotations # in the element before adapting. if not _orm_only or \ - '_orm_adapt' in elem._annotations or \ - "parententity" in elem._annotations: + '_orm_adapt' in elem._annotations or \ + "parententity" in elem._annotations: e = adapter(elem) if e is not None: return e return visitors.replacement_traverse( - clause, - {}, - replace - ) + clause, + {}, + replace + ) def _entity_zero(self): return self._entities[0] @@ -311,26 +312,26 @@ class Query(object): def _only_mapper_zero(self, rationale=None): if len(self._entities) > 1: raise sa_exc.InvalidRequestError( - rationale or - "This operation requires a Query " - "against a single mapper." - ) + rationale or + "This operation requires a Query " + "against a single mapper." + ) return self._mapper_zero() def _only_full_mapper_zero(self, methname): if self._entities != [self._primary_entity]: raise sa_exc.InvalidRequestError( - "%s() can only be used against " - "a single mapped class." % methname) + "%s() can only be used against " + "a single mapped class." % methname) return self._primary_entity.entity_zero def _only_entity_zero(self, rationale=None): if len(self._entities) > 1: raise sa_exc.InvalidRequestError( - rationale or - "This operation requires a Query " - "against a single mapper." - ) + rationale or + "This operation requires a Query " + "against a single mapper." + ) return self._entity_zero() def __all_equivs(self): @@ -340,7 +341,8 @@ class Query(object): return equivs def _get_condition(self): - return self._no_criterion_condition("get", order_by=False, distinct=False) + return self._no_criterion_condition( + "get", order_by=False, distinct=False) def _get_existing_condition(self): self._no_criterion_assertion("get", order_by=False, distinct=False) @@ -354,8 +356,8 @@ class Query(object): self._group_by or (order_by and self._order_by) or \ (distinct and self._distinct): raise sa_exc.InvalidRequestError( - "Query.%s() being called on a " - "Query with existing criterion. " % meth) + "Query.%s() being called on a " + "Query with existing criterion. " % meth) def _no_criterion_condition(self, meth, order_by=True, distinct=True): self._no_criterion_assertion(meth, order_by, distinct) @@ -369,8 +371,8 @@ class Query(object): return if self._order_by: raise sa_exc.InvalidRequestError( - "Query.%s() being called on a " - "Query with existing criterion. " % meth) + "Query.%s() being called on a " + "Query with existing criterion. " % meth) self._no_criterion_condition(meth) def _no_statement_condition(self, meth): @@ -411,9 +413,9 @@ class Query(object): ) def _get_options(self, populate_existing=None, - version_check=None, - only_load_props=None, - refresh_state=None): + version_check=None, + only_load_props=None, + refresh_state=None): if populate_existing: self._populate_existing = populate_existing if version_check: @@ -441,11 +443,10 @@ class Query(object): """ stmt = self._compile_context(labels=self._with_labels).\ - statement + statement if self._params: stmt = stmt.params(self._params) - # TODO: there's no tests covering effects of # the annotation not being there return stmt._annotate({'no_replacement_traverse': True}) @@ -662,9 +663,9 @@ class Query(object): @_generative(_no_clauseelement_condition) def with_polymorphic(self, - cls_or_mappers, - selectable=None, - polymorphic_on=None): + cls_or_mappers, + selectable=None, + polymorphic_on=None): """Load columns for inheriting classes. :meth:`.Query.with_polymorphic` applies transformations @@ -692,13 +693,13 @@ class Query(object): if not self._primary_entity: raise sa_exc.InvalidRequestError( - "No primary mapper set up for this Query.") + "No primary mapper set up for this Query.") entity = self._entities[0]._clone() self._entities = [entity] + self._entities[1:] entity.set_with_polymorphic(self, - cls_or_mappers, - selectable=selectable, - polymorphic_on=polymorphic_on) + cls_or_mappers, + selectable=selectable, + polymorphic_on=polymorphic_on) @_generative() def yield_per(self, count): @@ -717,15 +718,16 @@ class Query(object): Also note that while :meth:`~sqlalchemy.orm.query.Query.yield_per` will set the ``stream_results`` execution option to True, currently - this is only understood by :mod:`~sqlalchemy.dialects.postgresql.psycopg2` dialect - which will stream results using server side cursors instead of pre-buffer - all rows for this query. Other DBAPIs pre-buffer all rows before - making them available. + this is only understood by + :mod:`~sqlalchemy.dialects.postgresql.psycopg2` dialect which will + stream results using server side cursors instead of pre-buffer all + rows for this query. Other DBAPIs pre-buffer all rows before making + them available. """ self._yield_per = count self._execution_options = self._execution_options.union( - {"stream_results": True}) + {"stream_results": True}) def get(self, ident): """Return an instance based on the given primary key identifier, @@ -795,9 +797,9 @@ class Query(object): if len(ident) != len(mapper.primary_key): raise sa_exc.InvalidRequestError( - "Incorrect number of values in identifier to formulate " - "primary key for query.get(); primary key columns are %s" % - ','.join("'%s'" % c for c in mapper.primary_key)) + "Incorrect number of values in identifier to formulate " + "primary key for query.get(); primary key columns are %s" % + ','.join("'%s'" % c for c in mapper.primary_key)) key = mapper.identity_key_from_primary_key(ident) @@ -839,9 +841,9 @@ class Query(object): """ self._correlate = self._correlate.union( - _interpret_as_from(s) - if s is not None else None - for s in args) + _interpret_as_from(s) + if s is not None else None + for s in args) @_generative() def autoflush(self, setting): @@ -900,17 +902,17 @@ class Query(object): for prop in mapper.iterate_properties: if isinstance(prop, properties.RelationshipProperty) and \ - prop.mapper is self._mapper_zero(): + prop.mapper is self._mapper_zero(): property = prop break else: raise sa_exc.InvalidRequestError( - "Could not locate a property which relates instances " - "of class '%s' to instances of class '%s'" % - ( - self._mapper_zero().class_.__name__, - instance.__class__.__name__) - ) + "Could not locate a property which relates instances " + "of class '%s' to instances of class '%s'" % + ( + self._mapper_zero().class_.__name__, + instance.__class__.__name__) + ) return self.filter(with_parent(instance, property)) @@ -943,8 +945,8 @@ class Query(object): """ fromclause = self.with_labels().enable_eagerloads(False).\ - _set_enable_single_crit(False).\ - statement.correlate(None) + _set_enable_single_crit(False).\ + statement.correlate(None) q = self._from_selectable(fromclause) if entities: q._set_entities(entities) @@ -1039,8 +1041,9 @@ class Query(object): self._set_entity_selectables(self._entities[l:]) @util.pending_deprecation("0.7", - ":meth:`.add_column` is superseded by :meth:`.add_columns`", - False) + ":meth:`.add_column` is superseded " + "by :meth:`.add_columns`", + False) def add_column(self, column): """Add a column expression to the list of result columns to be returned. @@ -1205,8 +1208,8 @@ class Query(object): kwargs.update(args[0]) elif len(args) > 0: raise sa_exc.ArgumentError( - "params() takes zero or one positional argument, " - "which is a dictionary.") + "params() takes zero or one positional argument, " + "which is a dictionary.") self._params = self._params.copy() self._params.update(kwargs) @@ -1246,7 +1249,6 @@ class Query(object): else: self._criterion = criterion - def filter_by(self, **kwargs): """apply the given filtering criterion to a copy of this :class:`.Query`, using keyword expressions. @@ -1271,7 +1273,7 @@ class Query(object): """ clauses = [_entity_descriptor(self._joinpoint_zero(), key) == value - for key, value in kwargs.items()] + for key, value in kwargs.items()] return self.filter(sql.and_(*clauses)) @_generative(_no_statement_condition, _no_limit_offset) @@ -1324,7 +1326,8 @@ class Query(object): """apply a HAVING criterion to the query and return the newly resulting :class:`.Query`. - :meth:`~.Query.having` is used in conjunction with :meth:`~.Query.group_by`. + :meth:`~.Query.having` is used in conjunction with + :meth:`~.Query.group_by`. HAVING criterion makes it possible to use filters on aggregate functions like COUNT, SUM, AVG, MAX, and MIN, eg.:: @@ -1342,8 +1345,8 @@ class Query(object): if criterion is not None and \ not isinstance(criterion, sql.ClauseElement): raise sa_exc.ArgumentError( - "having() argument must be of type " - "sqlalchemy.sql.ClauseElement or string") + "having() argument must be of type " + "sqlalchemy.sql.ClauseElement or string") criterion = self._adapt_clause(criterion, True, True) @@ -1391,7 +1394,7 @@ class Query(object): """ return self._from_selectable( - expression.union(*([self] + list(q)))) + expression.union(*([self] + list(q)))) def union_all(self, *q): """Produce a UNION ALL of this Query against one or more queries. @@ -1401,8 +1404,8 @@ class Query(object): """ return self._from_selectable( - expression.union_all(*([self] + list(q))) - ) + expression.union_all(*([self] + list(q))) + ) def intersect(self, *q): """Produce an INTERSECT of this Query against one or more queries. @@ -1412,8 +1415,8 @@ class Query(object): """ return self._from_selectable( - expression.intersect(*([self] + list(q))) - ) + expression.intersect(*([self] + list(q))) + ) def intersect_all(self, *q): """Produce an INTERSECT ALL of this Query against one or more queries. @@ -1423,8 +1426,8 @@ class Query(object): """ return self._from_selectable( - expression.intersect_all(*([self] + list(q))) - ) + expression.intersect_all(*([self] + list(q))) + ) def except_(self, *q): """Produce an EXCEPT of this Query against one or more queries. @@ -1434,8 +1437,8 @@ class Query(object): """ return self._from_selectable( - expression.except_(*([self] + list(q))) - ) + expression.except_(*([self] + list(q))) + ) def except_all(self, *q): """Produce an EXCEPT ALL of this Query against one or more queries. @@ -1445,8 +1448,8 @@ class Query(object): """ return self._from_selectable( - expression.except_all(*([self] + list(q))) - ) + expression.except_all(*([self] + list(q))) + ) def join(self, *props, **kwargs): """Create a SQL JOIN against this :class:`.Query` object's criterion @@ -1456,8 +1459,8 @@ class Query(object): Consider a mapping between two classes ``User`` and ``Address``, with a relationship ``User.addresses`` representing a collection - of ``Address`` objects associated with each ``User``. The most common - usage of :meth:`~.Query.join` is to create a JOIN along this + of ``Address`` objects associated with each ``User``. The most + common usage of :meth:`~.Query.join` is to create a JOIN along this relationship, using the ``User.addresses`` attribute as an indicator for how this should occur:: @@ -1683,8 +1686,8 @@ class Query(object): :ref:`ormtutorial_joins` in the ORM tutorial. - :ref:`inheritance_toplevel` for details on how :meth:`~.Query.join` - is used for inheritance relationships. + :ref:`inheritance_toplevel` for details on how + :meth:`~.Query.join` is used for inheritance relationships. :func:`.orm.join` - a standalone ORM-level join function, used internally by :meth:`.Query.join`, which in previous @@ -1692,13 +1695,13 @@ class Query(object): """ aliased, from_joinpoint = kwargs.pop('aliased', False),\ - kwargs.pop('from_joinpoint', False) + kwargs.pop('from_joinpoint', False) if kwargs: raise TypeError("unknown arguments: %s" % - ','.join(kwargs.keys)) + ','.join(kwargs.keys)) return self._join(props, - outerjoin=False, create_aliases=aliased, - from_joinpoint=from_joinpoint) + outerjoin=False, create_aliases=aliased, + from_joinpoint=from_joinpoint) def outerjoin(self, *props, **kwargs): """Create a left outer join against this ``Query`` object's criterion @@ -1708,13 +1711,13 @@ class Query(object): """ aliased, from_joinpoint = kwargs.pop('aliased', False), \ - kwargs.pop('from_joinpoint', False) + kwargs.pop('from_joinpoint', False) if kwargs: raise TypeError("unknown arguments: %s" % - ','.join(kwargs)) + ','.join(kwargs)) return self._join(props, - outerjoin=True, create_aliases=aliased, - from_joinpoint=from_joinpoint) + outerjoin=True, create_aliases=aliased, + from_joinpoint=from_joinpoint) def _update_joinpoint(self, jp): self._joinpoint = jp @@ -1740,9 +1743,9 @@ class Query(object): if len(keys) == 2 and \ isinstance(keys[0], (expression.FromClause, - type, AliasedClass)) and \ + type, AliasedClass)) and \ isinstance(keys[1], (str, expression.ClauseElement, - interfaces.PropComparator)): + interfaces.PropComparator)): # detect 2-arg form of join and # convert to a tuple. keys = (keys,) @@ -1761,7 +1764,8 @@ class Query(object): # is a little bit of legacy behavior still at work here # which means they might be in either order. may possibly # lock this down to (right_entity, onclause) in 0.6. - if isinstance(arg1, (interfaces.PropComparator, util.string_types)): + if isinstance( + arg1, (interfaces.PropComparator, util.string_types)): right_entity, onclause = arg2, arg1 else: right_entity, onclause = arg1, arg2 @@ -1777,7 +1781,7 @@ class Query(object): # check for q.join(Class.propname, from_joinpoint=True) # and Class is that of the current joinpoint elif from_joinpoint and \ - isinstance(onclause, interfaces.PropComparator): + isinstance(onclause, interfaces.PropComparator): left_entity = onclause._parententity info = inspect(self._joinpoint_zero()) @@ -1789,7 +1793,7 @@ class Query(object): if left_mapper is left_entity: left_entity = self._joinpoint_zero() descriptor = _entity_descriptor(left_entity, - onclause.key) + onclause.key) onclause = descriptor if isinstance(onclause, interfaces.PropComparator): @@ -1804,7 +1808,7 @@ class Query(object): left_entity = onclause._parententity prop = onclause.property - if not isinstance(onclause, attributes.QueryableAttribute): + if not isinstance(onclause, attributes.QueryableAttribute): onclause = prop if not create_aliases: @@ -1829,10 +1833,9 @@ class Query(object): raise NotImplementedError("query.join(a==b) not supported.") self._join_left_to_right( - left_entity, - right_entity, onclause, - outerjoin, create_aliases, prop) - + left_entity, + right_entity, onclause, + outerjoin, create_aliases, prop) def _join_left_to_right(self, left, right, onclause, outerjoin, create_aliases, prop): @@ -1848,48 +1851,49 @@ class Query(object): if left is None: raise sa_exc.InvalidRequestError( - "Don't know how to join from %s; please use " - "select_from() to establish the left " - "entity/selectable of this join" % self._entities[0]) + "Don't know how to join from %s; please use " + "select_from() to establish the left " + "entity/selectable of this join" % self._entities[0]) if left is right and \ not create_aliases: raise sa_exc.InvalidRequestError( - "Can't construct a join from %s to %s, they " - "are the same entity" % - (left, right)) + "Can't construct a join from %s to %s, they " + "are the same entity" % + (left, right)) l_info = inspect(left) r_info = inspect(right) - overlap = False if not create_aliases: right_mapper = getattr(r_info, "mapper", None) # if the target is a joined inheritance mapping, # be more liberal about auto-aliasing. if right_mapper and ( - right_mapper.with_polymorphic or - isinstance(right_mapper.mapped_table, expression.Join) - ): + right_mapper.with_polymorphic or + isinstance(right_mapper.mapped_table, expression.Join) + ): for from_obj in self._from_obj or [l_info.selectable]: - if sql_util.selectables_overlap(l_info.selectable, from_obj) and \ - sql_util.selectables_overlap(from_obj, r_info.selectable): + if sql_util.selectables_overlap( + l_info.selectable, from_obj) and \ + sql_util.selectables_overlap( + from_obj, r_info.selectable): overlap = True break - elif sql_util.selectables_overlap(l_info.selectable, r_info.selectable): + elif sql_util.selectables_overlap(l_info.selectable, + r_info.selectable): overlap = True - if overlap and l_info.selectable is r_info.selectable: raise sa_exc.InvalidRequestError( - "Can't join table/selectable '%s' to itself" % - l_info.selectable) + "Can't join table/selectable '%s' to itself" % + l_info.selectable) right, onclause = self._prepare_right_side( - r_info, right, onclause, - create_aliases, - prop, overlap) + r_info, right, onclause, + create_aliases, + prop, overlap) # if joining on a MapperProperty path, # track the path to prevent redundant joins @@ -1904,7 +1908,7 @@ class Query(object): self._join_to_left(l_info, left, right, onclause, outerjoin) def _prepare_right_side(self, r_info, right, onclause, create_aliases, - prop, overlap): + prop, overlap): info = r_info right_mapper, right_selectable, right_is_aliased = \ @@ -1918,8 +1922,8 @@ class Query(object): if right_mapper and prop and \ not right_mapper.common_parent(prop.mapper): raise sa_exc.InvalidRequestError( - "Join target %s does not correspond to " - "the right side of join condition %s" % (right, onclause) + "Join target %s does not correspond to " + "the right side of join condition %s" % (right, onclause) ) if not right_mapper and prop: @@ -1929,11 +1933,11 @@ class Query(object): if right_mapper and right is right_selectable: if not right_selectable.is_derived_from( - right_mapper.mapped_table): + right_mapper.mapped_table): raise sa_exc.InvalidRequestError( "Selectable '%s' is not derived from '%s'" % (right_selectable.description, - right_mapper.mapped_table.description)) + right_mapper.mapped_table.description)) if isinstance(right_selectable, expression.SelectBase): # TODO: this isn't even covered now! @@ -1943,16 +1947,16 @@ class Query(object): right = aliased(right_mapper, right_selectable) aliased_entity = right_mapper and \ - not right_is_aliased and \ - ( - right_mapper.with_polymorphic and isinstance( - right_mapper._with_polymorphic_selectable, - expression.Alias) - or - overlap # test for overlap: - # orm/inheritance/relationships.py - # SelfReferentialM2MTest - ) + not right_is_aliased and \ + ( + right_mapper.with_polymorphic and isinstance( + right_mapper._with_polymorphic_selectable, + expression.Alias) + or + overlap # test for overlap: + # orm/inheritance/relationships.py + # SelfReferentialM2MTest + ) if not need_adapter and (create_aliases or aliased_entity): right = aliased(right, flat=True) @@ -1962,10 +1966,11 @@ class Query(object): # apply an adapter to all subsequent filter() calls # until reset_joinpoint() is called. if need_adapter: - self._filter_aliases = ORMAdapter(right, - equivalents=right_mapper and - right_mapper._equivalent_columns or {}, - chain_to=self._filter_aliases) + self._filter_aliases = ORMAdapter( + right, + equivalents=right_mapper and + right_mapper._equivalent_columns or {}, + chain_to=self._filter_aliases) # if the onclause is a ClauseElement, adapt it with any # adapters that are in place right now @@ -1978,12 +1983,12 @@ class Query(object): # set are also adapted. if aliased_entity and not create_aliases: self._mapper_loads_polymorphically_with( - right_mapper, - ORMAdapter( - right, - equivalents=right_mapper._equivalent_columns - ) - ) + right_mapper, + ORMAdapter( + right, + equivalents=right_mapper._equivalent_columns + ) + ) return right, onclause @@ -1994,22 +1999,22 @@ class Query(object): if self._from_obj: replace_clause_index, clause = sql_util.find_join_source( - self._from_obj, - left_selectable) + self._from_obj, + left_selectable) if clause is not None: try: clause = orm_join(clause, - right, - onclause, isouter=outerjoin) + right, + onclause, isouter=outerjoin) except sa_exc.ArgumentError as ae: raise sa_exc.InvalidRequestError( - "Could not find a FROM clause to join from. " - "Tried joining to %s, but got: %s" % (right, ae)) + "Could not find a FROM clause to join from. " + "Tried joining to %s, but got: %s" % (right, ae)) self._from_obj = \ - self._from_obj[:replace_clause_index] + \ - (clause, ) + \ - self._from_obj[replace_clause_index + 1:] + self._from_obj[:replace_clause_index] + \ + (clause, ) + \ + self._from_obj[replace_clause_index + 1:] return if left_mapper: @@ -2027,8 +2032,8 @@ class Query(object): clause = orm_join(clause, right, onclause, isouter=outerjoin) except sa_exc.ArgumentError as ae: raise sa_exc.InvalidRequestError( - "Could not find a FROM clause to join from. " - "Tried joining to %s, but got: %s" % (right, ae)) + "Could not find a FROM clause to join from. " + "Tried joining to %s, but got: %s" % (right, ae)) self._from_obj = self._from_obj + (clause,) def _reset_joinpoint(self): @@ -2186,14 +2191,14 @@ class Query(object): start, stop, step = util.decode_slice(item) if isinstance(stop, int) and \ - isinstance(start, int) and \ - stop - start <= 0: + isinstance(start, int) and \ + stop - start <= 0: return [] # perhaps we should execute a count() here so that we # can still use LIMIT/OFFSET ? elif (isinstance(start, int) and start < 0) \ - or (isinstance(stop, int) and stop < 0): + or (isinstance(stop, int) and stop < 0): return list(self)[item] res = self.slice(start, stop) @@ -2310,11 +2315,11 @@ class Query(object): statement = sql.text(statement) if not isinstance(statement, - (expression.TextClause, - expression.SelectBase)): + (expression.TextClause, + expression.SelectBase)): raise sa_exc.ArgumentError( - "from_statement accepts text(), select(), " - "and union() objects only.") + "from_statement accepts text(), select(), " + "and union() objects only.") self._statement = statement @@ -2408,16 +2413,16 @@ class Query(object): def _connection_from_session(self, **kw): conn = self.session.connection( - **kw) + **kw) if self._execution_options: conn = conn.execution_options(**self._execution_options) return conn def _execute_and_instances(self, querycontext): conn = self._connection_from_session( - mapper=self._mapper_zero_or_none(), - clause=querycontext.statement, - close_with_result=True) + mapper=self._mapper_zero_or_none(), + clause=querycontext.statement, + close_with_result=True) result = conn.execute(querycontext.statement, self._params) return loading.instances(self, result, querycontext) @@ -2553,7 +2558,7 @@ class Query(object): # .with_only_columns() after we have a core select() so that # we get just "SELECT 1" without any entities. return sql.exists(self.add_columns('1').with_labels(). - statement.with_only_columns(['1'])) + statement.with_only_columns(['1'])) def count(self): """Return a count of rows this Query would return. @@ -2629,10 +2634,11 @@ class Query(object): This method has several key caveats: - * The method does **not** offer in-Python cascading of relationships - it - is assumed that ON DELETE CASCADE/SET NULL/etc. is configured for any foreign key - references which require it, otherwise the database may emit an - integrity violation if foreign key references are being enforced. + * The method does **not** offer in-Python cascading of relationships + - it is assumed that ON DELETE CASCADE/SET NULL/etc. is configured + for any foreign key references which require it, otherwise the + database may emit an integrity violation if foreign key references + are being enforced. After the DELETE, dependent objects in the :class:`.Session` which were impacted by an ON DELETE may not contain the current @@ -2641,8 +2647,8 @@ class Query(object): which normally occurs upon :meth:`.Session.commit` or can be forced by using :meth:`.Session.expire_all`. Accessing an expired object whose row has been deleted will invoke a SELECT to locate the - row; when the row is not found, an :class:`~sqlalchemy.orm.exc.ObjectDeletedError` - is raised. + row; when the row is not found, an + :class:`~sqlalchemy.orm.exc.ObjectDeletedError` is raised. * The :meth:`.MapperEvents.before_delete` and :meth:`.MapperEvents.after_delete` @@ -2657,10 +2663,10 @@ class Query(object): :ref:`inserts_and_updates` - Core SQL tutorial """ - #TODO: cascades need handling. + # TODO: cascades need handling. delete_op = persistence.BulkDelete.factory( - self, synchronize_session) + self, synchronize_session) delete_op.exec_() return delete_op.rowcount @@ -2698,9 +2704,9 @@ class Query(object): This method has several key caveats: - * The method does **not** offer in-Python cascading of relationships - it - is assumed that ON UPDATE CASCADE is configured for any foreign key - references which require it, otherwise the database may emit an + * The method does **not** offer in-Python cascading of relationships + - it is assumed that ON UPDATE CASCADE is configured for any foreign + key references which require it, otherwise the database may emit an integrity violation if foreign key references are being enforced. After the UPDATE, dependent objects in the :class:`.Session` which @@ -2709,16 +2715,16 @@ class Query(object): which normally occurs upon :meth:`.Session.commit` or can be forced by using :meth:`.Session.expire_all`. - * As of 0.8, this method will support multiple table updates, as detailed - in :ref:`multi_table_updates`, and this behavior does extend to support - updates of joined-inheritance and other multiple table mappings. However, - the **join condition of an inheritance mapper is currently not - automatically rendered**. - Care must be taken in any multiple-table update to explicitly include - the joining condition between those tables, even in mappings where - this is normally automatic. - E.g. if a class ``Engineer`` subclasses ``Employee``, an UPDATE of the - ``Engineer`` local table using criteria against the ``Employee`` + * As of 0.8, this method will support multiple table updates, as + detailed in :ref:`multi_table_updates`, and this behavior does + extend to support updates of joined-inheritance and other multiple + table mappings. However, the **join condition of an inheritance + mapper is currently not automatically rendered**. + Care must be taken in any multiple-table update to explicitly + include the joining condition between those tables, even in mappings + where this is normally automatic. + E.g. if a class ``Engineer`` subclasses ``Employee``, an UPDATE of + the ``Engineer`` local table using criteria against the ``Employee`` local table might look like:: session.query(Engineer).\\ @@ -2740,18 +2746,17 @@ class Query(object): """ - #TODO: value keys need to be mapped to corresponding sql cols and + # TODO: value keys need to be mapped to corresponding sql cols and # instr.attr.s to string keys - #TODO: updates of manytoone relationships need to be converted to + # TODO: updates of manytoone relationships need to be converted to # fk assignments - #TODO: cascades need handling. + # TODO: cascades need handling. update_op = persistence.BulkUpdate.factory( - self, synchronize_session, values) + self, synchronize_session, values) update_op.exec_() return update_op.rowcount - def _compile_context(self, labels=True): context = QueryContext(self) @@ -2784,13 +2789,13 @@ class Query(object): if not context.primary_columns: if self._only_load_props: raise sa_exc.InvalidRequestError( - "No column-based properties specified for " - "refresh operation. Use session.expire() " - "to reload collections and related items.") + "No column-based properties specified for " + "refresh operation. Use session.expire() " + "to reload collections and related items.") else: raise sa_exc.InvalidRequestError( - "Query contains no columns with which to " - "SELECT from.") + "Query contains no columns with which to " + "SELECT from.") if context.multi_row_eager_loaders and self._should_nest_selectable: context.statement = self._compound_eager_statement(context) @@ -2805,26 +2810,26 @@ class Query(object): if context.order_by: order_by_col_expr = list( - chain(*[ - sql_util.unwrap_order_by(o) - for o in context.order_by - ]) - ) + chain(*[ + sql_util.unwrap_order_by(o) + for o in context.order_by + ]) + ) else: context.order_by = None order_by_col_expr = [] inner = sql.select( - context.primary_columns + order_by_col_expr, - context.whereclause, - from_obj=context.froms, - use_labels=context.labels, - # TODO: this order_by is only needed if - # LIMIT/OFFSET is present in self._select_args, - # else the application on the outside is enough - order_by=context.order_by, - **self._select_args - ) + context.primary_columns + order_by_col_expr, + context.whereclause, + from_obj=context.froms, + use_labels=context.labels, + # TODO: this order_by is only needed if + # LIMIT/OFFSET is present in self._select_args, + # else the application on the outside is enough + order_by=context.order_by, + **self._select_args + ) for hint in self._with_hints: inner = inner.with_hint(*hint) @@ -2839,8 +2844,8 @@ class Query(object): context.adapter = sql_util.ColumnAdapter(inner, equivs) statement = sql.select( - [inner] + context.secondary_columns, - use_labels=context.labels) + [inner] + context.secondary_columns, + use_labels=context.labels) statement._for_update_arg = context._for_update_arg @@ -2850,8 +2855,8 @@ class Query(object): # giving us a marker as to where the "splice point" of # the join should be from_clause = sql_util.splice_joins( - from_clause, - eager_join, eager_join.stop_on) + from_clause, + eager_join, eager_join.stop_on) statement.append_from(from_clause) @@ -2871,24 +2876,24 @@ class Query(object): if self._distinct and context.order_by: order_by_col_expr = list( - chain(*[ - sql_util.unwrap_order_by(o) - for o in context.order_by - ]) - ) + chain(*[ + sql_util.unwrap_order_by(o) + for o in context.order_by + ]) + ) context.primary_columns += order_by_col_expr context.froms += tuple(context.eager_joins.values()) statement = sql.select( - context.primary_columns + - context.secondary_columns, - context.whereclause, - from_obj=context.froms, - use_labels=context.labels, - order_by=context.order_by, - **self._select_args - ) + context.primary_columns + + context.secondary_columns, + context.whereclause, + from_obj=context.froms, + use_labels=context.labels, + order_by=context.order_by, + **self._select_args + ) statement._for_update_arg = context._for_update_arg for hint in self._with_hints: @@ -2920,14 +2925,15 @@ class Query(object): single_crit = adapter.traverse(single_crit) single_crit = self._adapt_clause(single_crit, False, False) context.whereclause = sql.and_( - sql.True_._ifnone(context.whereclause), - single_crit) + sql.True_._ifnone(context.whereclause), + single_crit) def __str__(self): return str(self._compile_context().statement) from ..sql.selectable import ForUpdateArg + class LockmodeArg(ForUpdateArg): @classmethod def parse_legacy_query(self, mode): @@ -2944,10 +2950,11 @@ class LockmodeArg(ForUpdateArg): read = False else: raise sa_exc.ArgumentError( - "Unknown with_lockmode argument: %r" % mode) + "Unknown with_lockmode argument: %r" % mode) return LockmodeArg(read=read, nowait=nowait) + class _QueryEntity(object): """represent an entity column returned within a Query result.""" @@ -2955,7 +2962,7 @@ class _QueryEntity(object): if cls is _QueryEntity: entity = args[1] if not isinstance(entity, util.string_types) and \ - _is_mapped_class(entity): + _is_mapped_class(entity): cls = _MapperEntity elif isinstance(entity, Bundle): cls = _BundleEntity @@ -2989,7 +2996,7 @@ class _MapperEntity(_QueryEntity): self.is_aliased_class = ext_info.is_aliased_class self._with_polymorphic = ext_info.with_polymorphic_mappers self._polymorphic_discriminator = \ - ext_info.polymorphic_on + ext_info.polymorphic_on self.entity_zero = ext_info if ext_info.is_aliased_class: self._label_name = self.entity_zero.name @@ -2999,7 +3006,7 @@ class _MapperEntity(_QueryEntity): self.custom_rows = bool(self.mapper.dispatch.append_result) def set_with_polymorphic(self, query, cls_or_mappers, - selectable, polymorphic_on): + selectable, polymorphic_on): """Receive an update from a call to query.with_polymorphic(). Note the newer style of using a free standing with_polymporphic() @@ -3010,23 +3017,23 @@ class _MapperEntity(_QueryEntity): if self.is_aliased_class: # TODO: invalidrequest ? raise NotImplementedError( - "Can't use with_polymorphic() against " - "an Aliased object" - ) + "Can't use with_polymorphic() against " + "an Aliased object" + ) if cls_or_mappers is None: query._reset_polymorphic_adapter(self.mapper) return mappers, from_obj = self.mapper._with_polymorphic_args( - cls_or_mappers, selectable) + cls_or_mappers, selectable) self._with_polymorphic = mappers self._polymorphic_discriminator = polymorphic_on self.selectable = from_obj - query._mapper_loads_polymorphically_with(self.mapper, - sql_util.ColumnAdapter(from_obj, - self.mapper._equivalent_columns)) + query._mapper_loads_polymorphically_with( + self.mapper, sql_util.ColumnAdapter( + from_obj, self.mapper._equivalent_columns)) filter_fn = id @@ -3115,7 +3122,7 @@ class _MapperEntity(_QueryEntity): def setup_context(self, query, context): adapter = self._get_entity_clauses(query, context) - #if self._adapted_selectable is None: + # if self._adapted_selectable is None: context.froms += (self.selectable,) if context.order_by is False and self.mapper.order_by: @@ -3124,10 +3131,10 @@ class _MapperEntity(_QueryEntity): # apply adaptation to the mapper's order_by if needed. if adapter: context.order_by = adapter.adapt_list( - util.to_list( - context.order_by - ) - ) + util.to_list( + context.order_by + ) + ) if self._with_polymorphic: poly_properties = self.mapper._iterate_polymorphic_properties( @@ -3161,6 +3168,7 @@ class _MapperEntity(_QueryEntity): def __str__(self): return str(self.mapper) + @inspection._self_inspects class Bundle(object): """A grouping of SQL expressions that are returned by a :class:`.Query` @@ -3192,7 +3200,8 @@ class Bundle(object): bn = Bundle("mybundle", MyClass.x, MyClass.y) - for row in session.query(bn).filter(bn.c.x == 5).filter(bn.c.y == 4): + for row in session.query(bn).filter( + bn.c.x == 5).filter(bn.c.y == 4): print(row.mybundle.x, row.mybundle.y) :param name: name of the bundle. @@ -3206,7 +3215,7 @@ class Bundle(object): self.exprs = exprs self.c = self.columns = ColumnCollection() self.columns.update((getattr(col, "key", col._label), col) - for col in exprs) + for col in exprs) self.single_entity = kw.pop('single_entity', self.single_entity) columns = None @@ -3225,7 +3234,8 @@ class Bundle(object): Bundle('b3', MyClass.x, MyClass.y) ) - q = sess.query(b1).filter(b1.c.b2.c.a == 5).filter(b1.c.b3.c.y == 9) + q = sess.query(b1).filter( + b1.c.b2.c.a == 5).filter(b1.c.b3.c.y == 9) .. seealso:: @@ -3266,7 +3276,8 @@ class Bundle(object): """ def proc(row, result): - return util.KeyedTuple([proc(row, None) for proc in procs], labels) + return util.KeyedTuple( + [proc(row, None) for proc in procs], labels) return proc @@ -3318,9 +3329,9 @@ class _BundleEntity(_QueryEntity): def adapt_to_selectable(self, query, sel): c = _BundleEntity(query, self.bundle, setup_entities=False) - #c._label_name = self._label_name - #c.entity_zero = self.entity_zero - #c.entities = self.entities + # c._label_name = self._label_name + # c.entity_zero = self.entity_zero + # c.entities = self.entities for ent in self._entities: ent.adapt_to_selectable(c, sel) @@ -3335,14 +3346,15 @@ class _BundleEntity(_QueryEntity): def row_processor(self, query, context, custom_rows): procs, labels = zip( - *[ent.row_processor(query, context, custom_rows) - for ent in self._entities] - ) + *[ent.row_processor(query, context, custom_rows) + for ent in self._entities] + ) proc = self.bundle.create_row_processor(query, procs, labels) return proc, self._label_name + class _ColumnEntity(_QueryEntity): """Column/expression based entity.""" @@ -3354,16 +3366,16 @@ class _ColumnEntity(_QueryEntity): column = sql.literal_column(column) self._label_name = column.name elif isinstance(column, ( - attributes.QueryableAttribute, - interfaces.PropComparator - )): + attributes.QueryableAttribute, + interfaces.PropComparator + )): self._label_name = column.key column = column._query_clause_element() else: self._label_name = getattr(column, 'key', None) if not isinstance(column, expression.ColumnElement) and \ - hasattr(column, '_select_iterable'): + hasattr(column, '_select_iterable'): for c in column._select_iterable: if c is column: break @@ -3414,7 +3426,7 @@ class _ColumnEntity(_QueryEntity): for elem in visitors.iterate(column, {}) if 'parententity' in elem._annotations and actual_froms.intersection(elem._from_objects) - ) + ) if self.entities: self.entity_zero = list(self.entities)[0] @@ -3456,14 +3468,14 @@ class _ColumnEntity(_QueryEntity): return entity is self.entity_zero else: return not _is_aliased_class(self.entity_zero) and \ - entity.common_parent(self.entity_zero) + entity.common_parent(self.entity_zero) def _resolve_expr_against_query_aliases(self, query, expr, context): return query._adapt_clause(expr, False, True) def row_processor(self, query, context, custom_rows): column = self._resolve_expr_against_query_aliases( - query, self.column, context) + query, self.column, context) if context.adapter: column = context.adapter.columns[column] @@ -3475,7 +3487,7 @@ class _ColumnEntity(_QueryEntity): def setup_context(self, query, context): column = self._resolve_expr_against_query_aliases( - query, self.column, context) + query, self.column, context) context.froms += tuple(self.froms) context.primary_columns.append(column) @@ -3493,8 +3505,8 @@ class QueryContext(object): if query._statement is not None: if isinstance(query._statement, expression.SelectBase) and \ - not query._statement._textual and \ - not query._statement.use_labels: + not query._statement._textual and \ + not query._statement.use_labels: self.statement = query._statement.apply_labels() else: self.statement = query._statement @@ -3516,7 +3528,7 @@ class QueryContext(object): self.eager_joins = {} self.create_eager_joins = [] self.propagate_options = set(o for o in query._with_options if - o.propagate_to_loaders) + o.propagate_to_loaders) self.attributes = query._attributes.copy() @@ -3563,5 +3575,3 @@ class AliasOption(interfaces.MapperOption): else: alias = self.alias query._from_obj_alias = sql_util.ColumnAdapter(alias) - - |
