return str(self._as_query())
def __iter__(self):
- return iter(self._iter())
+ return self._iter().__iter__()
def _iter(self):
bq = self.bq
Equivalent to :meth:`_query.Query.first`.
"""
+
bq = self.bq.with_criteria(lambda q: q.slice(0, 1))
- ret = list(
+ return (
bq.for_session(self.session)
.params(self._params)
._using_post_criteria(self._post_criteria)
+ ._iter()
+ .first()
)
- if len(ret) > 0:
- return ret[0]
- else:
- return None
def one(self):
"""Return exactly one result or raise an exception.
Equivalent to :meth:`_query.Query.one`.
"""
- try:
- ret = self.one_or_none()
- except orm_exc.MultipleResultsFound as err:
- util.raise_(
- orm_exc.MultipleResultsFound(
- "Multiple rows were found for one()"
- ),
- replace_context=err,
- )
- else:
- if ret is None:
- raise orm_exc.NoResultFound("No row was found for one()")
- return ret
+ return self._iter().one()
def one_or_none(self):
"""Return one or zero results, or raise an exception for multiple
.. versionadded:: 1.0.9
"""
- ret = list(self)
-
- l = len(ret)
- if l == 1:
- return ret[0]
- elif l == 0:
- return None
- else:
- raise orm_exc.MultipleResultsFound(
- "Multiple rows were found for one_or_none()"
- )
+ return self._iter().one_or_none()
def all(self):
"""Return all rows.
"""
from __future__ import absolute_import
-import collections
-
from . import attributes
from . import exc as orm_exc
from . import path_registry
identity_class = mapper._identity_class
- populators = collections.defaultdict(list)
+ compile_state = context.compile_state
+
+ populators = {}
props = mapper._prop_set
if only_load_props is not None:
props = props.intersection(mapper._props[k] for k in only_load_props)
- quick_populators = path.get(
- context.attributes, "memoized_setups", _none_set
- )
+ getters = path.get(compile_state.attributes, "getters", None)
+ if getters is None:
+ # directives given to us by the ColumnLoader.setup_query()
+ # methods. Turn these directives into getters against the
+ # actual result set.
+ quick_populators = path.get(
+ context.attributes, "memoized_setups", _none_set
+ )
+ cached_populators = {
+ "new": [],
+ "expire": [],
+ "quick": [],
+ "todo": [],
+ "delayed": [],
+ "existing": [],
+ "eager": [],
+ }
- for prop in props:
- if prop in quick_populators:
- # this is an inlined path just for column-based attributes.
- col = quick_populators[prop]
- if col is _DEFER_FOR_STATE:
- populators["new"].append(
- (prop.key, prop._deferred_column_loader)
- )
- elif col is _SET_DEFERRED_EXPIRED:
- # note that in this path, we are no longer
- # searching in the result to see if the column might
- # be present in some unexpected way.
- populators["expire"].append((prop.key, False))
- elif col is _RAISE_FOR_STATE:
- populators["new"].append((prop.key, prop._raise_column_loader))
- else:
- getter = None
- if not getter:
- getter = result._getter(col, False)
- if getter:
- populators["quick"].append((prop.key, getter))
- else:
- # fall back to the ColumnProperty itself, which
- # will iterate through all of its columns
- # to see if one fits
- prop.create_row_processor(
- context, path, mapper, result, adapter, populators
+ pk_cols = mapper.primary_key
+
+ if adapter:
+ pk_cols = [adapter.columns[c] for c in pk_cols]
+ getters = {
+ "populators": cached_populators,
+ "primary_key_getter": result._tuple_getter(pk_cols),
+ }
+
+ for prop in props:
+ if prop in quick_populators:
+ # this is an inlined path just for column-based attributes.
+ col = quick_populators[prop]
+ if col is _DEFER_FOR_STATE:
+ cached_populators["new"].append(
+ (prop.key, prop._deferred_column_loader)
)
- else:
- prop.create_row_processor(
- context, path, mapper, result, adapter, populators
- )
+ elif col is _SET_DEFERRED_EXPIRED:
+ # note that in this path, we are no longer
+ # searching in the result to see if the column might
+ # be present in some unexpected way.
+ cached_populators["expire"].append((prop.key, False))
+ elif col is _RAISE_FOR_STATE:
+ cached_populators["new"].append(
+ (prop.key, prop._raise_column_loader)
+ )
+ else:
+ getter = None
+ if not getter:
+ getter = result._getter(col, False)
+ if getter:
+ cached_populators["quick"].append((prop.key, getter))
+ else:
+ # fall back to the ColumnProperty itself, which
+ # will iterate through all of its columns
+ # to see if one fits
+ prop.create_row_processor(
+ context,
+ path,
+ mapper,
+ result,
+ adapter,
+ cached_populators,
+ )
+ else:
+ cached_populators["todo"].append(prop)
+ path.set(compile_state.attributes, "getters", getters)
+
+ cached_populators = getters["populators"]
+ populators = {k: list(v) for k, v in cached_populators.items()}
+ for prop in cached_populators["todo"]:
+ prop.create_row_processor(
+ context, path, mapper, result, adapter, populators
+ )
propagated_loader_options = context.propagated_loader_options
load_path = (
else:
refresh_identity_key = None
- pk_cols = mapper.primary_key
-
- if adapter:
- pk_cols = [adapter.columns[c] for c in pk_cols]
- tuple_getter = result._tuple_getter(pk_cols)
+ primary_key_getter = getters["primary_key_getter"]
if mapper.allow_partial_pks:
is_not_primary_key = _none_set.issuperset
else:
# look at the row, see if that identity is in the
# session, or we have to create a new one
- identitykey = (identity_class, tuple_getter(row), identity_token)
+ identitykey = (
+ identity_class,
+ primary_key_getter(row),
+ identity_token,
+ )
instance = session_identity_map.get(identitykey)
def ensure_no_pk(row):
identitykey = (
identity_class,
- tuple_getter(row),
+ primary_key_getter(row),
identity_token,
)
if not is_not_primary_key(identitykey[1]):