summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/sql/compiler.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2021-02-05 13:38:28 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2021-02-05 13:54:37 -0500
commitbc9221bf781adfffdddf12860d4eed7650457a0a (patch)
tree83992d60fb056610cd29660a71a0284b74150785 /lib/sqlalchemy/sql/compiler.py
parentac1228a87290aca4aa64cec27e640817be932feb (diff)
downloadsqlalchemy-bc9221bf781adfffdddf12860d4eed7650457a0a.tar.gz
Track a second from_linter for lateral subqueries
Fixed bug where the "cartesian product" assertion was not correctly accommodating for joins between tables that relied upon the use of LATERAL to connect from a subquery to another subquery in the enclosing context. Additionally, enabled from_linting for the base assert_compile(), however it remains off by default; to enable by default we would have to make sure it isn't set for DDL compiles and there's also a lot of tests that would also need to turn it off, so leaving this off for expediency. Fixes: #5924 Change-Id: I22604baf572f8c4d96befcc610b3dcb79c13fc4a
Diffstat (limited to 'lib/sqlalchemy/sql/compiler.py')
-rw-r--r--lib/sqlalchemy/sql/compiler.py42
1 files changed, 37 insertions, 5 deletions
diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py
index 696b38e64..f22e8614b 100644
--- a/lib/sqlalchemy/sql/compiler.py
+++ b/lib/sqlalchemy/sql/compiler.py
@@ -1996,14 +1996,24 @@ class SQLCompiler(Compiled):
override_operator=None,
eager_grouping=False,
from_linter=None,
+ lateral_from_linter=None,
**kw
):
if from_linter and operators.is_comparison(binary.operator):
- from_linter.edges.update(
- itertools.product(
- binary.left._from_objects, binary.right._from_objects
+ if lateral_from_linter is not None:
+ enclosing_lateral = kw["enclosing_lateral"]
+ lateral_from_linter.edges.update(
+ itertools.product(
+ binary.left._from_objects + [enclosing_lateral],
+ binary.right._from_objects + [enclosing_lateral],
+ )
+ )
+ else:
+ from_linter.edges.update(
+ itertools.product(
+ binary.left._from_objects, binary.right._from_objects
+ )
)
- )
# don't allow "? = ?" to render
if (
@@ -2027,7 +2037,11 @@ class SQLCompiler(Compiled):
)
else:
return self._generate_generic_binary(
- binary, opstring, from_linter=from_linter, **kw
+ binary,
+ opstring,
+ from_linter=from_linter,
+ lateral_from_linter=lateral_from_linter,
+ **kw
)
def visit_function_as_comparison_op_binary(self, element, operator, **kw):
@@ -2570,6 +2584,24 @@ class SQLCompiler(Compiled):
from_linter=None,
**kwargs
):
+
+ if lateral:
+ if "enclosing_lateral" not in kwargs:
+ # if lateral is set and enclosing_lateral is not
+ # present, we assume we are being called directly
+ # from visit_lateral() and we need to set enclosing_lateral.
+ assert alias._is_lateral
+ kwargs["enclosing_lateral"] = alias
+
+ # for lateral objects, we track a second from_linter that is...
+ # lateral! to the level above us.
+ if (
+ from_linter
+ and "lateral_from_linter" not in kwargs
+ and "enclosing_lateral" in kwargs
+ ):
+ kwargs["lateral_from_linter"] = from_linter
+
if enclosing_alias is not None and enclosing_alias.element is alias:
inner = alias.element._compiler_dispatch(
self,