Resend this email to -hackers.  Sorry for the noise.

Thanks
Richard

---------- Forwarded message ---------
From: Richard Guo <guofengli...@gmail.com>
Date: Thu, Feb 2, 2023 at 9:51 AM
Subject: Re: pgsql: Remove over-optimistic Assert.
To: Tom Lane <t...@sss.pgh.pa.us>
Cc: <pgsql-committ...@lists.postgresql.org>, PostgreSQL-development <
pgsql-hack...@postgresql.org>



On Thu, Feb 2, 2023 at 8:40 AM Tom Lane <t...@sss.pgh.pa.us> wrote:

> Remove over-optimistic Assert.
>
> In commit 2489d76c4, I'd thought it'd be safe to assert that a
> PlaceHolderVar appearing in a scan-level expression has empty
> nullingrels.  However this is not so, as when we determine that a
> join relation is certainly empty we'll put its targetlist into a
> Result-with-constant-false-qual node, and nothing is done to adjust
> the nullingrels of the Vars or PHVs therein.  (Arguably, a Result
> used in this way isn't really a scan-level node, but it certainly
> isn't an upper node either ...)


It seems this is the only case we can have PlaceHolderVar with non-empty
nullingrels at scan level.  So I wonder if we can manually adjust the
nullingrels of PHVs in this special case, and keep the assertion about
phnullingrels being NULL in fix_scan_expr.  I think that assertion is
asserting the right thing in most cases.  It's a pity to lose it.

Currently for the tlist of a childless Result, we special-case ROWID_VAR
Vars in set_plan_refs and thus keep assertions about varno != ROWID_VAR
in fix_scan_expr.  Do you think we can special-case PHVs at the same
place by setting its phnullingrels to NULL?  I'm imagining something
like attached.

Thanks
Richard
From 41fc3b6855e5b6e525ec46a276a0892a321045e0 Mon Sep 17 00:00:00 2001
From: Richard Guo <guofenglinux@gmail.com>
Date: Thu, 2 Feb 2023 09:06:53 +0800
Subject: [PATCH v1] Adjust phnullingrels for childless Result

---
 src/backend/optimizer/plan/setrefs.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 186fc8014b..f6d8eaf1df 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -1045,16 +1045,32 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
 					 * expected to occur here, it seems safer to special-case
 					 * it here and keep the assertions that ROWID_VARs
 					 * shouldn't be seen by fix_scan_expr.
+					 *
+					 * The tlist of a childless Result could contain PHVs with
+					 * non-empty phnullingrels, in case it's a dummy plan
+					 * generated for empty join relation.  Special-case it here
+					 * by setting phnullingrels to NULL and keep the assertion
+					 * about phnullingrels being NULL in fix_scan_expr.
 					 */
 					foreach(l, splan->plan.targetlist)
 					{
 						TargetEntry *tle = (TargetEntry *) lfirst(l);
-						Var		   *var = (Var *) tle->expr;
 
-						if (var && IsA(var, Var) && var->varno == ROWID_VAR)
-							tle->expr = (Expr *) makeNullConst(var->vartype,
-															   var->vartypmod,
-															   var->varcollid);
+						if (tle->expr && IsA(tle->expr, Var))
+						{
+							Var		   *var = (Var *) tle->expr;
+
+							if (var->varno == ROWID_VAR)
+								tle->expr = (Expr *) makeNullConst(var->vartype,
+																   var->vartypmod,
+																   var->varcollid);
+						}
+						else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
+						{
+							PlaceHolderVar *phv = (PlaceHolderVar *) tle->expr;
+
+							phv->phnullingrels = NULL;
+						}
 					}
 
 					splan->plan.targetlist =
@@ -2205,7 +2221,7 @@ fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
 		/* At scan level, we should always just evaluate the contained expr */
 		PlaceHolderVar *phv = (PlaceHolderVar *) node;
 
-		/* XXX can we assert something about phnullingrels? */
+		Assert(phv->phnullingrels == NULL);
 		return fix_scan_expr_mutator((Node *) phv->phexpr, context);
 	}
 	if (IsA(node, AlternativeSubPlan))
-- 
2.31.0

Reply via email to