From c97a547a4a0913e37e5dd1f026ac3c281326b215 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 31 Aug 2012 18:57:12 -0400
Subject: [PATCH] Partially restore qual scope checks in
 distribute_qual_to_rels().

The LATERAL implementation is now basically complete, and I still don't
see a cost-effective way to make an exact qual scope cross-check in the
presence of LATERAL.  However, I did add a PlannerInfo.hasLateralRTEs flag
along the way, so it's easy to make the check only when not hasLateralRTEs.
That seems to still be useful, and it beats having no check at all.
---
 src/backend/optimizer/plan/initsplan.c | 28 ++++++++++++--------------
 1 file changed, 13 insertions(+), 15 deletions(-)

diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c
index 824c6a7e473..f582d4067b9 100644
--- a/src/backend/optimizer/plan/initsplan.c
+++ b/src/backend/optimizer/plan/initsplan.c
@@ -1103,21 +1103,20 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
 	relids = pull_varnos(clause);
 
 	/*
-	 * Cross-check: clause should contain no relids not within its scope.
-	 * Otherwise the parser messed up.
+	 * Normally relids is a subset of qualscope, and we like to check that
+	 * here as a crosscheck on the parser and rewriter.  That need not be the
+	 * case when there are LATERAL RTEs, however: the clause could contain
+	 * references to rels outside its syntactic scope as a consequence of
+	 * pull-up of such references from a LATERAL subquery below it.  So, only
+	 * check if the query contains no LATERAL RTEs.
 	 *
-	 * XXX temporarily disable the qualscope cross-check, which tends to
-	 * reject quals pulled up from LATERAL subqueries.  This is only in the
-	 * nature of a debugging crosscheck anyway.  I'm loath to remove it
-	 * permanently, but need to think a bit harder about how to replace it.
-	 * See also disabled Assert below.  (The ojscope test is still okay
-	 * because we prevent pullup of LATERAL subqueries that might cause it to
-	 * be violated.)
+	 * However, if it's an outer-join clause, we always insist that relids be
+	 * a subset of ojscope.  This is safe because is_simple_subquery()
+	 * disallows pullup of LATERAL subqueries that could cause the restriction
+	 * to be violated.
 	 */
-#ifdef NOT_USED
-	if (!bms_is_subset(relids, qualscope))
+	if (!root->hasLateralRTEs && !bms_is_subset(relids, qualscope))
 		elog(ERROR, "JOIN qualification cannot refer to other relations");
-#endif
 	if (ojscope && !bms_is_subset(relids, ojscope))
 		elog(ERROR, "JOIN qualification cannot refer to other relations");
 
@@ -1272,9 +1271,8 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
 		if (outerjoin_delayed)
 		{
 			/* Should still be a subset of current scope ... */
-#ifdef NOT_USED					/* XXX temporarily disabled for LATERAL */
-			Assert(bms_is_subset(relids, qualscope));
-#endif
+			Assert(root->hasLateralRTEs || bms_is_subset(relids, qualscope));
+			Assert(ojscope == NULL || bms_is_subset(relids, ojscope));
 
 			/*
 			 * Because application of the qual will be delayed by outer join,
-- 
GitLab