]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
pass more contextual information to PyWrapper param create
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 27 Dec 2022 17:29:38 +0000 (12:29 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 27 Dec 2022 19:04:19 +0000 (14:04 -0500)
Fixed issue in lambda SQL feature where the calculated type of a literal
value would not take into account the type coercion rules of the "compared
to type", leading to a lack of typing information for SQL expressions, such
as comparisons to :class:`.JSON` elements and similar.

Fixes: #9029
Change-Id: I381c8d7458d98ba762313dee9ec47a9c1881f74a

doc/build/changelog/unreleased_14/9029.rst [new file with mode: 0644]
lib/sqlalchemy/sql/coercions.py
lib/sqlalchemy/sql/lambdas.py
regen_callcounts.tox.ini
test/profiles.txt
test/sql/test_lambdas.py

diff --git a/doc/build/changelog/unreleased_14/9029.rst b/doc/build/changelog/unreleased_14/9029.rst
new file mode 100644 (file)
index 0000000..38114e9
--- /dev/null
@@ -0,0 +1,8 @@
+.. change::
+    :tags: bug, sql
+    :tickets: 9029
+
+    Fixed issue in lambda SQL feature where the calculated type of a literal
+    value would not take into account the type coercion rules of the "compared
+    to type", leading to a lack of typing information for SQL expressions, such
+    as comparisons to :class:`.JSON` elements and similar.
index 9c3e7480ae950f91ec4b57cb11af205b57355268..7a4e687736855e5a62cb902546afc127310fd6ab 100644 (file)
@@ -355,7 +355,12 @@ def expect(
 
     if not isinstance(
         element,
-        (elements.CompilerElement, schema.SchemaItem, schema.FetchedValue),
+        (
+            elements.CompilerElement,
+            schema.SchemaItem,
+            schema.FetchedValue,
+            lambdas.PyWrapper,
+        ),
     ):
         resolved = None
 
@@ -404,6 +409,8 @@ def expect(
                     )
             else:
                 resolved = element
+    elif isinstance(element, lambdas.PyWrapper):
+        resolved = element._sa__py_wrapper_literal(**kw)
     else:
         resolved = element
 
index 26e3a21bb4727d5994e4f3e5eb469e9b16675d99..d9b4988a6123b34b034ab67099e21db27d7933ce 100644 (file)
@@ -33,7 +33,6 @@ from . import coercions
 from . import elements
 from . import roles
 from . import schema
-from . import type_api
 from . import visitors
 from .base import _clone
 from .base import Executable
@@ -1308,11 +1307,11 @@ class PyWrapper(ColumnOperators):
             return value
 
     def operate(self, op, *other, **kwargs):
-        elem = object.__getattribute__(self, "__clause_element__")()
+        elem = object.__getattribute__(self, "_py_wrapper_literal")()
         return op(elem, *other, **kwargs)
 
     def reverse_operate(self, op, other, **kwargs):
-        elem = object.__getattribute__(self, "__clause_element__")()
+        elem = object.__getattribute__(self, "_py_wrapper_literal")()
         return op(other, elem, **kwargs)
 
     def _extract_bound_parameters(self, starting_point, result_list):
@@ -1325,16 +1324,19 @@ class PyWrapper(ColumnOperators):
             element = getter(starting_point)
             pywrapper._sa__extract_bound_parameters(element, result_list)
 
-    def __clause_element__(self):
+    def _py_wrapper_literal(self, expr=None, operator=None, **kw):
         param = object.__getattribute__(self, "_param")
         to_evaluate = object.__getattribute__(self, "_to_evaluate")
         if param is None:
             name = object.__getattribute__(self, "_name")
             self._param = param = elements.BindParameter(
-                name, required=False, unique=True
+                name,
+                required=False,
+                unique=True,
+                _compared_to_operator=operator,
+                _compared_to_type=expr.type if expr is not None else None,
             )
             self._has_param = True
-            param.type = type_api._resolve_value_to_type(to_evaluate)
         return param._with_value(to_evaluate, maintain_key=True)
 
     def __bool__(self):
@@ -1348,6 +1350,7 @@ class PyWrapper(ColumnOperators):
             "__clause_element__",
             "operate",
             "reverse_operate",
+            "_py_wrapper_literal",
             "__class__",
             "__dict__",
         ):
index 4f4fb6fe98fdc1ea1cddcf536c49c081e09bb5e9..5f9c2aa99bcc7ca9230ca389079073435c08b05e 100644 (file)
@@ -21,7 +21,15 @@ commands=
     db_{oracle}: {env:BASECOMMAND} {env:ORACLE:} {posargs}
     db_{mssql}: {env:BASECOMMAND} {env:MSSQL:} {posargs}
 
-passenv=ORACLE_HOME NLS_LANG TOX_POSTGRESQL TOX_MYSQL TOX_ORACLE TOX_MSSQL TOX_SQLITE TOX_WORKERS
+passenv=
+    ORACLE_HOME 
+    NLS_LANG 
+    TOX_POSTGRESQL 
+    TOX_MYSQL 
+    TOX_ORACLE 
+    TOX_MSSQL 
+    TOX_SQLITE 
+    TOX_WORKERS
 
 # -E     : ignore PYTHON* environment variables (such as PYTHONPATH)
 # -s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE
index a961df3f148bb7bc587a5301592bb15761efd216..6fb9c162e27768ba6da9d945d4ef01d3c1423442 100644 (file)
@@ -160,48 +160,48 @@ test.aaa_profiling.test_misc.EnumTest.test_create_enum_from_pep_435_w_expensive_
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 54230
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 64540
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 55030
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_w_annotation x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 65340
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 52530
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 62840
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 53330
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_bundle_wo_annotation x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 63640
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 57130
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 65540
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 57930
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_w_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 66340
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 56230
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 64640
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 57030
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_entity_wo_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 65440
 
 # TEST: test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle
 
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 47930
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 51240
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 48730
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 52040
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 51430
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 59240
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 52230
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_w_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 60040
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 50530
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 58340
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 51330
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_bundle_wo_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 59140
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 36205
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 39405
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 37005
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_w_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 40205
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 35305
-test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 38505
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 36105
+test.aaa_profiling.test_orm.AnnotatedOverheadTest.test_no_entity_wo_annotations x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 39305
 
 # TEST: test.aaa_profiling.test_orm.AttributeOverheadTest.test_attribute_set
 
@@ -225,18 +225,18 @@ test.aaa_profiling.test_orm.BranchedOptionTest.test_query_opts_unbound_branching
 
 # TEST: test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline
 
-test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 15331
-test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 26350
+test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 15341
+test.aaa_profiling.test_orm.DeferOptionsTest.test_baseline x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 26360
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 21409
-test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 26428
+test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 21419
+test.aaa_profiling.test_orm.DeferOptionsTest.test_defer_many_cols x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 26438
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 10154
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 10504
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 10704
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 11054
 
 # TEST: test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased_select_join
 
@@ -245,18 +245,18 @@ test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_aliased_select_join x8
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 4304
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 4554
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 4354
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_b_plain x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 4604
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 95582
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 106832
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 98682
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 109932
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 93232
-test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 104682
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 96132
+test.aaa_profiling.test_orm.JoinConditionTest.test_a_to_d_aliased x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 107582
 
 # TEST: test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results
 
@@ -265,8 +265,8 @@ test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results x86_64_linux_
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 26583,1030,97753
-test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results_integrated x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 27490,1216,116353
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results_integrated x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 26832,1031,97853
+test.aaa_profiling.test_orm.JoinedEagerLoadTest.test_fetch_results_integrated x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 27722,1217,116453
 
 # TEST: test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_identity
 
@@ -275,18 +275,18 @@ test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 112202
-test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 120459
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 112466
+test.aaa_profiling.test_orm.LoadManyToOneFromIdentityTest.test_many_to_one_load_no_identity x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 120723
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 20552
-test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 21986
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 20730
+test.aaa_profiling.test_orm.MergeBackrefsTest.test_merge_pending_with_all_pks x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 22152
 
 # TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_load
 
-test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 1428
-test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 1517
+test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 1453
+test.aaa_profiling.test_orm.MergeTest.test_merge_load x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 1542
 
 # TEST: test.aaa_profiling.test_orm.MergeTest.test_merge_no_load
 
@@ -295,13 +295,13 @@ test.aaa_profiling.test_orm.MergeTest.test_merge_no_load x86_64_linux_cpython_3.
 
 # TEST: test.aaa_profiling.test_orm.QueryTest.test_query_cols
 
-test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 6504
-test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 7324
+test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 6586
+test.aaa_profiling.test_orm.QueryTest.test_query_cols x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 7406
 
 # 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.10_sqlite_pysqlite_dbapiunicode_cextensions 271705
-test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 293705
+test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_cextensions 275705
+test.aaa_profiling.test_orm.SelectInEagerLoadTest.test_round_trip_results x86_64_linux_cpython_3.10_sqlite_pysqlite_dbapiunicode_nocextensions 297105
 
 # TEST: test.aaa_profiling.test_orm.SessionTest.test_expire_lots
 
index 96a6ecbf4830c7e69e9abca5bab3610c7a60a8bd..c3e271706f01fb3e9f182c3af3de98f2a922e67c 100644 (file)
@@ -31,6 +31,7 @@ from sqlalchemy.testing.assertsql import CompiledSQL
 from sqlalchemy.types import ARRAY
 from sqlalchemy.types import Boolean
 from sqlalchemy.types import Integer
+from sqlalchemy.types import JSON
 from sqlalchemy.types import String
 
 
@@ -1513,6 +1514,107 @@ class LambdaElementTest(
             expr, "users.name || :x_1", checkparams={"x_1": "bar"}
         )
 
+    def test_rhs_type_detection_from_left(self):
+        """test #9029"""
+        tt = table("tt", column("q", JSON))
+
+        x = {"foo": "bar"}
+
+        def mylambda():
+            return tt.c.q + x
+
+        expr = coercions.expect(roles.WhereHavingRole, mylambda)
+        is_(expr._resolved.right.type._type_affinity, JSON)
+
+    def test_rhs_type_detection_standalone(self):
+        """test related to #9029, as type coercion rule was changed"""
+
+        x = 5
+
+        def mylambda():
+            return x
+
+        expr = coercions.expect(roles.OrderByRole, mylambda)
+        is_(expr._resolved.type._type_affinity, Integer)
+
+        x = "now im a string"
+
+        # stays as int b.c. _resolved is cached
+        is_(expr._resolved.type._type_affinity, Integer)
+
+        # make a new one!  now it will be string
+        expr = coercions.expect(roles.OrderByRole, mylambda)
+        is_(expr._resolved.type._type_affinity, String)
+
+    @testing.only_on("sqlite")
+    @testing.variation("stmt_type", ["lambda_stmt", "lambda_crit"])
+    @testing.variation("callable_type", ["none", "closure", "parameter"])
+    def test_9029_integration(
+        self, metadata, connection, stmt_type, callable_type
+    ):
+        t = Table(
+            "t",
+            metadata,
+            Column("id", Integer, primary_key=True),
+            Column("data", JSON),
+        )
+
+        t.create(connection)
+
+        connection.execute(
+            t.insert(),
+            {
+                "id": 12,
+                "data": {"key": "value", "key2": {"subkey": [1, 2, 3]}},
+            },
+        )
+
+        d = {"key": "value", "key2": {"subkey": [1, 2, 3]}}
+
+        if callable_type.none:
+            if stmt_type.lambda_stmt:
+                stmt = lambda_stmt(lambda: select(t).filter(t.c.data == d))
+            elif stmt_type.lambda_crit:
+                stmt = select(t).filter(lambda: t.c.data == d)
+            else:
+                stmt_type.fail()
+
+            to_run = stmt
+
+        elif callable_type.closure:
+
+            def go():
+                if stmt_type.lambda_stmt:
+                    stmt = lambda_stmt(lambda: select(t).filter(t.c.data == d))
+                elif stmt_type.lambda_crit:
+                    stmt = select(t).filter(lambda: t.c.data == d)
+                else:
+                    stmt_type.fail()
+                return stmt
+
+            to_run = go()
+
+        elif callable_type.parameter:
+
+            def go(data):
+                if stmt_type.lambda_stmt:
+                    stmt = lambda_stmt(
+                        lambda: select(t).filter(t.c.data == data)
+                    )
+                elif stmt_type.lambda_crit:
+                    stmt = select(t).filter(lambda: t.c.data == data)
+                else:
+                    stmt_type.fail()
+
+                return stmt
+
+            to_run = go(d)
+
+        eq_(
+            connection.execute(to_run).first(),
+            (12, {"key": "value", "key2": {"subkey": [1, 2, 3]}}),
+        )
+
     def test_execute_constructed_uncached(self, user_address_fixture):
         users, addresses = user_address_fixture