v3-0006-WIP-AssertRangeTblEntryIsValid.patch

text/plain

Filename: v3-0006-WIP-AssertRangeTblEntryIsValid.patch
Type: text/plain
Part: 5
Message: Re: automating RangeTblEntry node support

Patch

Format: format-patch
Series: patch v3-0006
Subject: WIP: AssertRangeTblEntryIsValid()
File+
src/backend/nodes/nodeFuncs.c 59 0
src/backend/nodes/outfuncs.c 2 0
src/backend/nodes/readfuncs.c 2 0
src/include/nodes/nodeFuncs.h 6 0
From 357cfbc2622480abf6a041dc3715f439b74c789f Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter@eisentraut.org>
Date: Mon, 11 Mar 2024 09:15:33 +0100
Subject: [PATCH v3 6/8] WIP: AssertRangeTblEntryIsValid()

This provides a function AssertRangeTblEntryIsValid() that checks that
a RangeTblEntry node is filled with a valid combination of fields.
This is hooked into the write/read functions so that it is executed by
WRITE_READ_PARSE_PLAN_TREES.

Discussion: https://www.postgresql.org/message-id/flat/4b27fc50-8cd6-46f5-ab20-88dbaadca645@eisentraut.org
---
 src/backend/nodes/nodeFuncs.c | 59 +++++++++++++++++++++++++++++++++++
 src/backend/nodes/outfuncs.c  |  2 ++
 src/backend/nodes/readfuncs.c |  2 ++
 src/include/nodes/nodeFuncs.h |  6 ++++
 4 files changed, 69 insertions(+)

diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c
index 6ba8e73256..db1b9bec13 100644
--- a/src/backend/nodes/nodeFuncs.c
+++ b/src/backend/nodes/nodeFuncs.c
@@ -4571,3 +4571,62 @@ planstate_walk_members(PlanState **planstates, int nplans,
 
 	return false;
 }
+
+#ifdef USE_ASSERT_CHECKING
+
+/*
+ * Assertion check that a RangeTblEntry node is filled with a valid
+ * combination of fields.
+ *
+ * Best used together with WRITE_READ_PARSE_PLAN_TREES.
+ */
+void
+AssertRangeTblEntryIsValid(const RangeTblEntry *rte)
+{
+	Assert(rte->rtekind == RTE_RELATION ||
+		   rte->rtekind == RTE_SUBQUERY ||
+		   rte->rtekind == RTE_JOIN ||
+		   rte->rtekind == RTE_FUNCTION ||
+		   rte->rtekind == RTE_TABLEFUNC ||
+		   rte->rtekind == RTE_VALUES ||
+		   rte->rtekind == RTE_CTE ||
+		   rte->rtekind == RTE_NAMEDTUPLESTORE ||
+		   rte->rtekind == RTE_RESULT);
+
+	Assert(rte->eref);
+
+	if (rte->relid)
+		Assert(rte->rtekind == RTE_RELATION || rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_NAMEDTUPLESTORE);
+	if (rte->inh)
+		Assert(rte->rtekind == RTE_RELATION || rte->rtekind == RTE_SUBQUERY);
+	if (rte->relkind)
+		Assert(rte->rtekind == RTE_RELATION || rte->rtekind == RTE_SUBQUERY);
+	if (rte->rellockmode)
+		Assert(rte->rtekind == RTE_RELATION || rte->rtekind == RTE_SUBQUERY);
+	if (rte->tablesample)
+		Assert(rte->rtekind == RTE_RELATION);
+	if (rte->perminfoindex)
+		Assert(rte->rtekind == RTE_RELATION || rte->rtekind == RTE_SUBQUERY);
+	if (rte->subquery)
+		Assert(rte->rtekind == RTE_SUBQUERY);
+	if (rte->security_barrier)
+		Assert(rte->rtekind == RTE_SUBQUERY);
+	if (rte->joinmergedcols || rte->joinaliasvars || rte->joinleftcols || rte->joinrightcols || rte->join_using_alias)
+		Assert(rte->rtekind == RTE_JOIN);
+	if (rte->functions || rte->funcordinality)
+		Assert(rte->rtekind == RTE_FUNCTION);
+	if (rte->tablefunc)
+		Assert(rte->rtekind == RTE_TABLEFUNC);
+	if (rte->values_lists)
+		Assert(rte->rtekind == RTE_VALUES);
+	if (rte->ctename || rte->ctelevelsup || rte->self_reference)
+		Assert(rte->rtekind == RTE_CTE);
+	if (rte->coltypes || rte->coltypmods || rte->colcollations)
+		Assert(rte->rtekind == RTE_TABLEFUNC || rte->rtekind == RTE_VALUES || rte->rtekind == RTE_CTE || rte->rtekind == RTE_NAMEDTUPLESTORE);
+	if (rte->enrname || rte->enrtuples)
+		Assert(rte->rtekind == RTE_NAMEDTUPLESTORE);
+	if (rte->lateral)
+		Assert(rte->rtekind == RTE_RELATION || rte->rtekind == RTE_SUBQUERY || rte->rtekind == RTE_FUNCTION || rte->rtekind == RTE_TABLEFUNC || rte->rtekind == RTE_VALUES);
+}
+
+#endif
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index c55375e7f9..5e34584c55 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -21,6 +21,7 @@
 #include "lib/stringinfo.h"
 #include "miscadmin.h"
 #include "nodes/bitmapset.h"
+#include "nodes/nodeFuncs.h"
 #include "nodes/nodes.h"
 #include "nodes/pg_list.h"
 #include "utils/datum.h"
@@ -492,6 +493,7 @@ _outExtensibleNode(StringInfo str, const ExtensibleNode *node)
 static void
 _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
 {
+	AssertRangeTblEntryIsValid(node);
 	WRITE_NODE_TYPE("RANGETBLENTRY");
 
 	WRITE_NODE_FIELD(alias);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index c4d01a441a..217d81041a 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -30,6 +30,7 @@
 
 #include "miscadmin.h"
 #include "nodes/bitmapset.h"
+#include "nodes/nodeFuncs.h"
 #include "nodes/readfuncs.h"
 
 
@@ -432,6 +433,7 @@ _readRangeTblEntry(void)
 	READ_BOOL_FIELD(inFromCl);
 	READ_NODE_FIELD(securityQuals);
 
+	AssertRangeTblEntryIsValid(local_node);
 	READ_DONE();
 }
 
diff --git a/src/include/nodes/nodeFuncs.h b/src/include/nodes/nodeFuncs.h
index eaba59bed8..873ed9e9b7 100644
--- a/src/include/nodes/nodeFuncs.h
+++ b/src/include/nodes/nodeFuncs.h
@@ -219,4 +219,10 @@ extern bool planstate_tree_walker_impl(struct PlanState *planstate,
 									   planstate_tree_walker_callback walker,
 									   void *context);
 
+#ifdef USE_ASSERT_CHECKING
+extern void AssertRangeTblEntryIsValid(const RangeTblEntry *rte);
+#else
+#define AssertRangeTblEntryIsValid(rte) ((void)true)
+#endif
+
 #endif							/* NODEFUNCS_H */
-- 
2.44.0