summaryrefslogtreecommitdiff
path: root/test/sql
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-03-10 23:34:33 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2019-03-10 23:44:08 -0400
commit25fc9562f08fe26e4e2f6d4cf69c34b666f0180a (patch)
treeaa6647eb6eaa1a16694f0aa1cb3348de61c6594b /test/sql
parentd514c032cd0349afc93f89d5b99835198ae70112 (diff)
downloadsqlalchemy-25fc9562f08fe26e4e2f6d4cf69c34b666f0180a.tar.gz
Clone internals for Select._correlate_except collection as well as _correlate
Fixed bug where use of :func:`.with_polymorphic` or other aliased construct would not properly adapt when the aliased target were used as the :meth:`.Select.correlate_except` target of a subquery used inside of a :func:`.column_property`. This required a fix to the clause adaption mechanics to properly handle a selectable that shows up in the "correlate except" list, in a similar manner as which occurs for selectables that show up in the "correlate" list. This is ultimately a fairly fundamental bug that has lasted for a long time but it is hard to come across it. Fixes: #4537 Change-Id: Ibb97d4eea18b3c452aad519dd14919bfb84d422f
Diffstat (limited to 'test/sql')
-rw-r--r--test/sql/test_generative.py84
1 files changed, 84 insertions, 0 deletions
diff --git a/test/sql/test_generative.py b/test/sql/test_generative.py
index ccb5b15ea..9b902e8ff 100644
--- a/test/sql/test_generative.py
+++ b/test/sql/test_generative.py
@@ -1088,6 +1088,90 @@ class ClauseAdapterTest(fixtures.TestBase, AssertsCompiledSQL):
"AS anon_1 FROM table1 AS t1alias",
)
+ def test_correlate_except_on_clone(self):
+ # test [ticket:4537]'s issue
+
+ t1alias = t1.alias("t1alias")
+ j = t1.join(t1alias, t1.c.col1 == t1alias.c.col2)
+
+ vis = sql_util.ClauseAdapter(j)
+
+ # "control" subquery - uses correlate which has worked w/ adaption
+ # for a long time
+ control_s = (
+ select([t2.c.col1])
+ .where(t2.c.col1 == t1.c.col1)
+ .correlate(t2)
+ .as_scalar()
+ )
+
+ # test subquery - given only t1 and t2 in the enclosing selectable,
+ # will do the same thing as the "control" query since the correlation
+ # works out the same
+ s = (
+ select([t2.c.col1])
+ .where(t2.c.col1 == t1.c.col1)
+ .correlate_except(t1)
+ .as_scalar()
+ )
+
+ # use both subqueries in statements
+ control_stmt = select([control_s, t1.c.col1, t2.c.col1]).select_from(
+ t1.join(t2, t1.c.col1 == t2.c.col1)
+ )
+
+ stmt = select([s, t1.c.col1, t2.c.col1]).select_from(
+ t1.join(t2, t1.c.col1 == t2.c.col1)
+ )
+ # they are the same
+ self.assert_compile(
+ control_stmt,
+ "SELECT "
+ "(SELECT table2.col1 FROM table1 "
+ "WHERE table2.col1 = table1.col1) AS anon_1, "
+ "table1.col1, table2.col1 "
+ "FROM table1 "
+ "JOIN table2 ON table1.col1 = table2.col1",
+ )
+ self.assert_compile(
+ stmt,
+ "SELECT "
+ "(SELECT table2.col1 FROM table1 "
+ "WHERE table2.col1 = table1.col1) AS anon_1, "
+ "table1.col1, table2.col1 "
+ "FROM table1 "
+ "JOIN table2 ON table1.col1 = table2.col1",
+ )
+
+ # now test against the adaption of "t1" into "t1 JOIN t1alias".
+ # note in the control case, we aren't actually testing that
+ # Select is processing the "correlate" list during the adaption
+ # since we aren't adapting the "correlate"
+ self.assert_compile(
+ vis.traverse(control_stmt),
+ "SELECT "
+ "(SELECT table2.col1 FROM "
+ "table1 JOIN table1 AS t1alias ON table1.col1 = t1alias.col2 "
+ "WHERE table2.col1 = table1.col1) AS anon_1, "
+ "table1.col1, table2.col1 "
+ "FROM table1 JOIN table1 AS t1alias ON table1.col1 = t1alias.col2 "
+ "JOIN table2 ON table1.col1 = table2.col1",
+ )
+
+ # but here, correlate_except() does have the thing we're adapting
+ # so whatever is in there has to be expanded out to include
+ # the adaptation target, in this case "t1 JOIN t1alias".
+ self.assert_compile(
+ vis.traverse(stmt),
+ "SELECT "
+ "(SELECT table2.col1 FROM "
+ "table1 JOIN table1 AS t1alias ON table1.col1 = t1alias.col2 "
+ "WHERE table2.col1 = table1.col1) AS anon_1, "
+ "table1.col1, table2.col1 "
+ "FROM table1 JOIN table1 AS t1alias ON table1.col1 = t1alias.col2 "
+ "JOIN table2 ON table1.col1 = table2.col1",
+ )
+
@testing.fails_on_everything_except()
def test_joins_dont_adapt(self):
# adapting to a join, i.e. ClauseAdapter(t1.join(t2)), doesn't