--- /dev/null
+.. change::
+ :tags: bug, orm, performance, regression
+ :tickets: 11085
+
+ Adjusted the fix made in :ticket:`10570`, released in 2.0.23, where new
+ logic was added to reconcile possibly changing bound parameter values
+ across cache key generations used within the :func:`_orm.with_expression`
+ construct. The new logic changes the approach by which the new bound
+ parameter values are associated with the statement, avoiding the need to
+ deep-copy the statement which can result in a significant performance
+ penalty for very deep / complex SQL constructs. The new approach no longer
+ requires this deep-copy step.
def _adapt_cached_option_to_uncached_option(
self, context: QueryContext, uncached_opt: ORMOption
) -> ORMOption:
+ if uncached_opt is self:
+ return self
return self._adjust_for_extra_criteria(context)
def _prepend_path(self, path: PathRegistry) -> Load:
returning a new instance of this ``Load`` object.
"""
- orig_query = context.compile_state.select_statement
-
- orig_cache_key: Optional[CacheKey] = None
- replacement_cache_key: Optional[CacheKey] = None
- found_crit = False
- def process(opt: _LoadElement) -> _LoadElement:
- nonlocal orig_cache_key, replacement_cache_key, found_crit
-
- found_crit = True
+ # avoid generating cache keys for the queries if we don't
+ # actually have any extra_criteria options, which is the
+ # common case
+ for value in self.context:
+ if value._extra_criteria:
+ break
+ else:
+ return self
- if orig_cache_key is None or replacement_cache_key is None:
- orig_cache_key = orig_query._generate_cache_key()
- replacement_cache_key = context.query._generate_cache_key()
+ replacement_cache_key = context.query._generate_cache_key()
- if replacement_cache_key is not None:
- assert orig_cache_key is not None
+ if replacement_cache_key is None:
+ return self
- opt._extra_criteria = tuple(
- replacement_cache_key._apply_params_to_element(
- orig_cache_key, crit
- )
- for crit in opt._extra_criteria
+ orig_query = context.compile_state.select_statement
+ orig_cache_key = orig_query._generate_cache_key()
+ assert orig_cache_key is not None
+
+ def process(
+ opt: _LoadElement,
+ replacement_cache_key: CacheKey,
+ orig_cache_key: CacheKey,
+ ) -> _LoadElement:
+ cloned_opt = opt._clone()
+
+ cloned_opt._extra_criteria = tuple(
+ replacement_cache_key._apply_params_to_element(
+ orig_cache_key, crit
)
+ for crit in cloned_opt._extra_criteria
+ )
- return opt
+ return cloned_opt
- # avoid generating cache keys for the queries if we don't
- # actually have any extra_criteria options, which is the
- # common case
- new_context = tuple(
- process(value._clone()) if value._extra_criteria else value
+ cloned = self._clone()
+ cloned.context = tuple(
+ (
+ process(value, replacement_cache_key, orig_cache_key)
+ if value._extra_criteria
+ else value
+ )
for value in self.context
)
-
- if found_crit:
- cloned = self._clone()
- cloned.context = new_context
- return cloned
- else:
- return self
+ return cloned
def _reconcile_query_entities_with_us(self, mapper_entities, raiseerr):
"""called at process time to allow adjustment of the root
if typing.TYPE_CHECKING:
from .elements import BindParameter
from .elements import ClauseElement
+ from .elements import ColumnElement
from .visitors import _TraverseInternalsType
from ..engine.interfaces import _CoreSingleExecuteParams
_anon_map = prefix_anon_map()
return {b.key % _anon_map: b.effective_value for b in self.bindparams}
+ @util.preload_module("sqlalchemy.sql.elements")
def _apply_params_to_element(
- self, original_cache_key: CacheKey, target_element: ClauseElement
- ) -> ClauseElement:
- if target_element._is_immutable:
+ self, original_cache_key: CacheKey, target_element: ColumnElement[Any]
+ ) -> ColumnElement[Any]:
+ if target_element._is_immutable or original_cache_key is self:
return target_element
- translate = {
- k.key: v.value
- for k, v in zip(original_cache_key.bindparams, self.bindparams)
- }
-
- return target_element.params(translate)
+ elements = util.preloaded.sql_elements
+ return elements._OverrideBinds(
+ target_element, self.bindparams, original_cache_key.bindparams
+ )
def _ad_hoc_cache_key_from_args(
"""
return ""
+ def visit_override_binds(self, override_binds, **kw):
+ """SQL compile the nested element of an _OverrideBinds with
+ bindparams swapped out.
+
+ The _OverrideBinds is not normally expected to be compiled; it
+ is meant to be used when an already cached statement is to be used,
+ the compilation was already performed, and only the bound params should
+ be swapped in at execution time.
+
+ However, the test suite has some tests that exercise compilation
+ on individual elements without using the cache key version, so here we
+ modify the bound parameter collection for the given compiler based on
+ the translation.
+
+ """
+
+ # get SQL text first
+ sqltext = override_binds.element._compiler_dispatch(self, **kw)
+
+ # then change binds after the fact. note that we don't try to
+ # swap the bindparam as we compile, because our element may be
+ # elsewhere in the statement already (e.g. a subquery or perhaps a
+ # CTE) and was already visited / compiled. See
+ # test_relationship_criteria.py ->
+ # test_selectinload_local_criteria_subquery
+ for k in override_binds.translate:
+ if k not in self.binds:
+ continue
+ bp = self.binds[k]
+
+ new_bp = bp._with_value(
+ override_binds.translate[bp.key],
+ maintain_key=True,
+ required=False,
+ )
+ name = self.bind_names[bp]
+ self.binds[k] = self.binds[name] = new_bp
+ self.bind_names[new_bp] = name
+
+ return sqltext
+
def visit_grouping(self, grouping, asfrom=False, **kwargs):
return "(" + grouping.element._compiler_dispatch(self, **kwargs) + ")"
render_postcompile=False,
**kwargs,
):
+
if not skip_bind_expression:
impl = bindparam.type.dialect_impl(self.dialect)
if impl._has_bind_expression:
from .type_api import TypeEngine
from .visitors import _CloneCallableType
from .visitors import _TraverseInternalsType
+ from .visitors import anon_map
from ..engine import Connection
from ..engine import Dialect
from ..engine import Engine
self.type = state["type"]
+class _OverrideBinds(Grouping[_T]):
+ """used by cache_key->_apply_params_to_element to allow compilation /
+ execution of a SQL element that's been cached, using an alternate set of
+ bound parameter values.
+
+ This is used by the ORM to swap new parameter values into expressions
+ that are embedded into loader options like with_expression(),
+ selectinload(). Previously, this task was accomplished using the
+ .params() method which would perform a deep-copy instead. This deep
+ copy proved to be too expensive for more complex expressions.
+
+ See #11085
+
+ """
+
+ __visit_name__ = "override_binds"
+
+ def __init__(
+ self,
+ element: ColumnElement[_T],
+ bindparams: Sequence[BindParameter[Any]],
+ replaces_params: Sequence[BindParameter[Any]],
+ ):
+ self.element = element
+ self.translate = {
+ k.key: v.value for k, v in zip(replaces_params, bindparams)
+ }
+
+ def _gen_cache_key(
+ self, anon_map: anon_map, bindparams: List[BindParameter[Any]]
+ ) -> Optional[typing_Tuple[Any, ...]]:
+ """generate a cache key for the given element, substituting its bind
+ values for the translation values present."""
+
+ existing_bps: List[BindParameter[Any]] = []
+ ck = self.element._gen_cache_key(anon_map, existing_bps)
+
+ bindparams.extend(
+ (
+ bp._with_value(
+ self.translate[bp.key], maintain_key=True, required=False
+ )
+ if bp.key in self.translate
+ else bp
+ )
+ for bp in existing_bps
+ )
+
+ return ck
+
+
class _OverRange(IntEnum):
RANGE_UNBOUNDED = 0
RANGE_CURRENT = 1
from sqlalchemy import and_
from sqlalchemy import ForeignKey
+from sqlalchemy import Identity
from sqlalchemy import Integer
from sqlalchemy import join
+from sqlalchemy import literal_column
from sqlalchemy import select
from sqlalchemy import String
from sqlalchemy import testing
from sqlalchemy.orm import join as orm_join
from sqlalchemy.orm import joinedload
from sqlalchemy.orm import Load
+from sqlalchemy.orm import query_expression
from sqlalchemy.orm import relationship
from sqlalchemy.orm import selectinload
from sqlalchemy.orm import Session
from sqlalchemy.orm import sessionmaker
+from sqlalchemy.orm import with_expression
from sqlalchemy.testing import fixtures
from sqlalchemy.testing import profiling
from sqlalchemy.testing.fixtures import fixture_session
r = q.all() # noqa: F841
go()
+
+
+class WithExpresionLoaderOptTest(fixtures.DeclarativeMappedTest):
+ # keep caching on with this test.
+ __requires__ = ("python_profiling_backend",)
+
+ """test #11085"""
+
+ @classmethod
+ def setup_classes(cls):
+ Base = cls.DeclarativeBasic
+
+ class A(Base):
+ __tablename__ = "a"
+
+ id = Column(Integer, Identity(), primary_key=True)
+ data = Column(String(30))
+ bs = relationship("B")
+
+ class B(Base):
+ __tablename__ = "b"
+ id = Column(Integer, Identity(), primary_key=True)
+ a_id = Column(ForeignKey("a.id"))
+ boolean = query_expression()
+ d1 = Column(String(30))
+ d2 = Column(String(30))
+ d3 = Column(String(30))
+ d4 = Column(String(30))
+ d5 = Column(String(30))
+ d6 = Column(String(30))
+ d7 = Column(String(30))
+
+ @classmethod
+ def insert_data(cls, connection):
+ A, B = cls.classes("A", "B")
+
+ with Session(connection) as s:
+ s.add(
+ A(
+ bs=[
+ B(
+ d1="x",
+ d2="x",
+ d3="x",
+ d4="x",
+ d5="x",
+ d6="x",
+ d7="x",
+ )
+ ]
+ )
+ )
+ s.commit()
+
+ def test_from_opt_no_cache(self):
+ A, B = self.classes("A", "B")
+
+ @profiling.function_call_count(warmup=2)
+ def go():
+ with Session(
+ testing.db.execution_options(compiled_cache=None)
+ ) as sess:
+ _ = sess.execute(
+ select(A).options(
+ selectinload(A.bs).options(
+ with_expression(
+ B.boolean,
+ and_(
+ B.d1 == "x",
+ B.d2 == "x",
+ B.d3 == "x",
+ B.d4 == "x",
+ B.d5 == "x",
+ B.d6 == "x",
+ B.d7 == "x",
+ ),
+ )
+ )
+ )
+ ).scalars()
+
+ go()
+
+ def test_from_opt_after_cache(self):
+ A, B = self.classes("A", "B")
+
+ @profiling.function_call_count(warmup=2)
+ def go():
+ with Session(testing.db) as sess:
+ _ = sess.execute(
+ select(A).options(
+ selectinload(A.bs).options(
+ with_expression(
+ B.boolean,
+ and_(
+ B.d1 == literal_column("'x'"),
+ B.d2 == "x",
+ B.d3 == literal_column("'x'"),
+ B.d4 == "x",
+ B.d5 == literal_column("'x'"),
+ B.d6 == "x",
+ B.d7 == literal_column("'x'"),
+ ),
+ )
+ )
+ )
+ ).scalars()
+
+ go()
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 55930
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 65740
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 65640
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 51230
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 54230
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 64040
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 63940
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 49530
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 58530
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 66440
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 66240
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 54730
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 57530
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 65440
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 65240
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 53730
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 49130
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 51940
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 51840
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 46030
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 52830
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 60140
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 60040
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 49130
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 51830
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 59140
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 59040
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 48130
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 37705
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 40805
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 34505
# TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 36705
test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 39805
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 33505
# TEST: test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set
test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 3599
test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 3599
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 3598
# TEST: test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove
test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 5527
test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 5527
+test.aaa_profiling.test_orm.AttributeOverheadTest.test_collection_append_remove x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 5526
# TEST: test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching
test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 128
test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 128
+test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_key_bound_branching x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 124
# TEST: test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching
test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 128
test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 128
+test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 124
# TEST: test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline
-test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 15359
-test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 24383
+test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 15360
+test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 24378
+test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 15325
# TEST: test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols
-test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 21437
-test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 24461
+test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 21420
+test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 24444
+test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 21384
# TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 10654
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 11054
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 10804
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 11204
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 10754
# TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased_select_join
test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased_select_join x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 1154
test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased_select_join x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 1154
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased_select_join x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 1154
# TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain
test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 4304
test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 4604
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 4304
# TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 96282
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 109782
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 98632
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 112132
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 95532
# TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 93732
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 107432
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 96082
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 109782
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 92982
# TEST: test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results_integrated
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results_integrated x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 26339,1019,96653
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results_integrated x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 27438,1228,117553
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results_integrated x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 27016,1006,95353
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results_integrated x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 28168,1215,116253
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results_integrated x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 26604,974,92153
# TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 23981
test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 23981
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 22982
# TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 113158
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 123916
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 113225
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 123983
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 108201
# TEST: test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 21189
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 22709
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 21197
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 22705
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 20478
# TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_load
-test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 1480
-test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 1583
+test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 1481
+test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 1581
+test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 1412
# TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_no_load
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 108,20
test.aaa_profiling.test_orm.MergeTest.test_merge_no_load x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 108,20
+test.aaa_profiling.test_orm.MergeTest.test_merge_no_load x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 108,20
# TEST: test.aaa_profiling.test_orm.QueryTest.test_query_cols
-test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 6696
-test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 7456
+test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 6706
+test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 7436
+test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 6316
# TEST: test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results
-test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 277405
-test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 298505
+test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 277005
+test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 297305
+test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 263005
# TEST: test.aaa_profiling.test_orm.SessionTest.test_expire_lots
test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 1212
test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 1212
+test.aaa_profiling.test_orm.SessionTest.test_expire_lots x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 1098
+
+# TEST: test.aaa_profiling.test_orm.WithExpresionLoaderOptTest.test_from_opt_after_cache
+
+test.aaa_profiling.test_orm.WithExpresionLoaderOptTest.test_from_opt_after_cache x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 1418
+test.aaa_profiling.test_orm.WithExpresionLoaderOptTest.test_from_opt_after_cache x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 1504
+test.aaa_profiling.test_orm.WithExpresionLoaderOptTest.test_from_opt_after_cache x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 1399
+
+# TEST: test.aaa_profiling.test_orm.WithExpresionLoaderOptTest.test_from_opt_no_cache
+
+test.aaa_profiling.test_orm.WithExpresionLoaderOptTest.test_from_opt_no_cache x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_cextensions 1859
+test.aaa_profiling.test_orm.WithExpresionLoaderOptTest.test_from_opt_no_cache x86_64_linux_cpython_3.11_sqlite_pysqlite_dbapiunicode_nocextensions 1880
+test.aaa_profiling.test_orm.WithExpresionLoaderOptTest.test_from_opt_no_cache x86_64_linux_cpython_3.12_sqlite_pysqlite_dbapiunicode_cextensions 1830
# TEST: test.aaa_profiling.test_pool.QueuePoolTest.test_first_connect
from sqlalchemy.sql import bindparam
from sqlalchemy.sql import ColumnElement
from sqlalchemy.sql import dml
+from sqlalchemy.sql import elements
from sqlalchemy.sql import False_
from sqlalchemy.sql import func
from sqlalchemy.sql import operators
"__init__" in cls.__dict__
or issubclass(cls, AliasedReturnsRows)
)
- and not issubclass(cls, (Annotated))
+ and not issubclass(cls, (Annotated, elements._OverrideBinds))
and cls.__module__.startswith("sqlalchemy.")
and "orm" not in cls.__module__
and "compiler" not in cls.__module__