This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
# orm/loading.py
|
||||
# Copyright (C) 2005-2023 the SQLAlchemy authors and contributors
|
||||
# Copyright (C) 2005-2025 the SQLAlchemy authors and contributors
|
||||
# <see AUTHORS file>
|
||||
#
|
||||
# This module is part of SQLAlchemy and is released under
|
||||
@@ -39,6 +39,7 @@ from .base import PassiveFlag
|
||||
from .context import FromStatement
|
||||
from .context import ORMCompileState
|
||||
from .context import QueryContext
|
||||
from .strategies import SelectInLoader
|
||||
from .util import _none_set
|
||||
from .util import state_str
|
||||
from .. import exc as sa_exc
|
||||
@@ -149,9 +150,11 @@ def instances(cursor: CursorResult[Any], context: QueryContext) -> Result[Any]:
|
||||
|
||||
raise sa_exc.InvalidRequestError(
|
||||
"Can't apply uniqueness to row tuple containing value of "
|
||||
f"""type {datatype!r}; {'the values returned appear to be'
|
||||
if uncertain else 'this datatype produces'} """
|
||||
"non-hashable values"
|
||||
f"""type {datatype!r}; {
|
||||
'the values returned appear to be'
|
||||
if uncertain
|
||||
else 'this datatype produces'
|
||||
} non-hashable values"""
|
||||
)
|
||||
|
||||
return go
|
||||
@@ -179,20 +182,22 @@ def instances(cursor: CursorResult[Any], context: QueryContext) -> Result[Any]:
|
||||
return go
|
||||
|
||||
unique_filters = [
|
||||
_no_unique
|
||||
if context.yield_per
|
||||
else _not_hashable(
|
||||
ent.column.type, # type: ignore
|
||||
legacy=context.load_options._legacy_uniquing,
|
||||
uncertain=ent._null_column_type,
|
||||
(
|
||||
_no_unique
|
||||
if context.yield_per
|
||||
else (
|
||||
_not_hashable(
|
||||
ent.column.type, # type: ignore
|
||||
legacy=context.load_options._legacy_uniquing,
|
||||
uncertain=ent._null_column_type,
|
||||
)
|
||||
if (
|
||||
not ent.use_id_for_hash
|
||||
and (ent._non_hashable_value or ent._null_column_type)
|
||||
)
|
||||
else id if ent.use_id_for_hash else None
|
||||
)
|
||||
)
|
||||
if (
|
||||
not ent.use_id_for_hash
|
||||
and (ent._non_hashable_value or ent._null_column_type)
|
||||
)
|
||||
else id
|
||||
if ent.use_id_for_hash
|
||||
else None
|
||||
for ent in context.compile_state._entities
|
||||
]
|
||||
|
||||
@@ -1006,21 +1011,38 @@ def _instance_processor(
|
||||
# loading does not apply
|
||||
assert only_load_props is None
|
||||
|
||||
callable_ = _load_subclass_via_in(
|
||||
context,
|
||||
path,
|
||||
selectin_load_via,
|
||||
_polymorphic_from,
|
||||
option_entities,
|
||||
)
|
||||
PostLoad.callable_for_path(
|
||||
context,
|
||||
load_path,
|
||||
selectin_load_via.mapper,
|
||||
selectin_load_via,
|
||||
callable_,
|
||||
selectin_load_via,
|
||||
)
|
||||
if selectin_load_via.is_mapper:
|
||||
_load_supers = []
|
||||
_endmost_mapper = selectin_load_via
|
||||
while (
|
||||
_endmost_mapper
|
||||
and _endmost_mapper is not _polymorphic_from
|
||||
):
|
||||
_load_supers.append(_endmost_mapper)
|
||||
_endmost_mapper = _endmost_mapper.inherits
|
||||
else:
|
||||
_load_supers = [selectin_load_via]
|
||||
|
||||
for _selectinload_entity in _load_supers:
|
||||
if PostLoad.path_exists(
|
||||
context, load_path, _selectinload_entity
|
||||
):
|
||||
continue
|
||||
callable_ = _load_subclass_via_in(
|
||||
context,
|
||||
path,
|
||||
_selectinload_entity,
|
||||
_polymorphic_from,
|
||||
option_entities,
|
||||
)
|
||||
PostLoad.callable_for_path(
|
||||
context,
|
||||
load_path,
|
||||
_selectinload_entity.mapper,
|
||||
_selectinload_entity,
|
||||
callable_,
|
||||
_selectinload_entity,
|
||||
)
|
||||
|
||||
post_load = PostLoad.for_context(context, load_path, only_load_props)
|
||||
|
||||
@@ -1288,15 +1310,18 @@ def _load_subclass_via_in(
|
||||
if context.populate_existing:
|
||||
q2 = q2.execution_options(populate_existing=True)
|
||||
|
||||
context.session.execute(
|
||||
q2,
|
||||
dict(
|
||||
primary_keys=[
|
||||
state.key[1][0] if zero_idx else state.key[1]
|
||||
for state, load_attrs in states
|
||||
]
|
||||
),
|
||||
).unique().scalars().all()
|
||||
while states:
|
||||
chunk = states[0 : SelectInLoader._chunksize]
|
||||
states = states[SelectInLoader._chunksize :]
|
||||
context.session.execute(
|
||||
q2,
|
||||
dict(
|
||||
primary_keys=[
|
||||
state.key[1][0] if zero_idx else state.key[1]
|
||||
for state, load_attrs in chunk
|
||||
]
|
||||
),
|
||||
).unique().scalars().all()
|
||||
|
||||
return do_load
|
||||
|
||||
|
||||
Reference in New Issue
Block a user