From 202203bed6bb5c1965c72710e8df59193b4b5932 Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Wed, 3 Jan 2024 15:24:15 +0100
Subject: [PATCH v1 6/7] NodeSupport: Apply some more defaults/serialization
 optimizations

This reduces raw serialized size of the initdb pg_rewrite.ev_action
dataset by 7.5%, it's pglz-compressed dataset by 4%/12kB, and the size
of the template0 database by 2 blocks.
---
 src/backend/nodes/outfuncs.c   | 32 +++++++++++++--------------
 src/backend/nodes/readfuncs.c  | 37 +++++++++++++++++--------------
 src/include/nodes/parsenodes.h | 17 +++++++++------
 src/include/nodes/pathnodes.h  |  2 +-
 src/include/nodes/primnodes.h  | 40 +++++++++++++++++++---------------
 5 files changed, 70 insertions(+), 58 deletions(-)

diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index f6cfcc8a4c..83f7e43242 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -457,18 +457,18 @@ _outConst(StringInfo str, const Const *node)
 	WRITE_NODE_TYPE("CONST");
 
 	WRITE_OID_FIELD(consttype);
-	WRITE_INT_FIELD(consttypmod);
+	WRITE_INT_FIELD_DEFAULT(consttypmod, -1);
 	WRITE_OID_FIELD(constcollid);
-	WRITE_INT_FIELD(constlen);
+	WRITE_INT_FIELD_DEFAULT(constlen, -1);
 	WRITE_BOOL_FIELD(constbyval);
 	WRITE_BOOL_FIELD(constisnull);
 	WRITE_LOCATION_FIELD(location);
 
-	appendStringInfoString(str, " :constvalue ");
-	if (node->constisnull)
-		appendStringInfoString(str, "<>");
-	else
+	if (!node->constisnull)
+	{
+		appendStringInfoString(str, " :constvalue ");
 		outDatum(str, node->constvalue, node->constlen, node->constbyval);
+	}
 }
 
 static void
@@ -579,10 +579,10 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
 	{
 		case RTE_RELATION:
 			WRITE_OID_FIELD(relid);
-			WRITE_CHAR_FIELD(relkind);
-			WRITE_INT_FIELD(rellockmode);
+			WRITE_CHAR_FIELD_DEFAULT(relkind, 'r'); /* default: 'r'elation */
+			WRITE_INT_FIELD_DEFAULT(rellockmode, 1); /* AccessShareLock */
 			WRITE_NODE_FIELD(tablesample);
-			WRITE_UINT_FIELD(perminfoindex);
+			WRITE_UINT_FIELD_DEFAULT(perminfoindex, 1); /* Index starts at 1 */
 			break;
 		case RTE_SUBQUERY:
 			WRITE_NODE_FIELD(subquery);
@@ -591,7 +591,7 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
 			WRITE_OID_FIELD(relid);
 			WRITE_CHAR_FIELD(relkind);
 			WRITE_INT_FIELD(rellockmode);
-			WRITE_UINT_FIELD(perminfoindex);
+			WRITE_UINT_FIELD_DEFAULT(perminfoindex, 1); /* Index starts at 1 */
 			break;
 		case RTE_JOIN:
 			WRITE_ENUM_FIELD(jointype, JoinType);
@@ -640,8 +640,8 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
 	}
 
 	WRITE_BOOL_FIELD(lateral);
-	WRITE_BOOL_FIELD(inh);
-	WRITE_BOOL_FIELD(inFromCl);
+	WRITE_BOOL_FIELD_DEFAULT(inh, true); /* safe assumption */
+	WRITE_BOOL_FIELD_DEFAULT(inFromCl, true); /* safe assumption */
 	WRITE_NODE_FIELD(securityQuals);
 }
 
@@ -798,7 +798,7 @@ _outConstraint(StringInfo str, const Constraint *node)
 			WRITE_INT_FIELD(inhcount);
 			WRITE_BOOL_FIELD(is_no_inherit);
 			WRITE_BOOL_FIELD(skip_validation);
-			WRITE_BOOL_FIELD(initially_valid);
+			WRITE_BOOL_FIELD_DEFAULT(initially_valid, true);
 			break;
 
 		case CONSTR_DEFAULT:
@@ -826,7 +826,7 @@ _outConstraint(StringInfo str, const Constraint *node)
 			WRITE_NODE_FIELD(raw_expr);
 			WRITE_STRING_FIELD(cooked_expr);
 			WRITE_BOOL_FIELD(skip_validation);
-			WRITE_BOOL_FIELD(initially_valid);
+			WRITE_BOOL_FIELD_DEFAULT(initially_valid, true);
 			break;
 
 		case CONSTR_PRIMARY:
@@ -842,7 +842,7 @@ _outConstraint(StringInfo str, const Constraint *node)
 
 		case CONSTR_UNIQUE:
 			appendStringInfoString(str, "UNIQUE");
-			WRITE_BOOL_FIELD(nulls_not_distinct);
+			WRITE_BOOL_FIELD_DEFAULT(nulls_not_distinct, true);
 			WRITE_NODE_FIELD(keys);
 			WRITE_NODE_FIELD(including);
 			WRITE_NODE_FIELD(options);
@@ -876,7 +876,7 @@ _outConstraint(StringInfo str, const Constraint *node)
 			WRITE_NODE_FIELD(old_conpfeqop);
 			WRITE_OID_FIELD(old_pktable_oid);
 			WRITE_BOOL_FIELD(skip_validation);
-			WRITE_BOOL_FIELD(initially_valid);
+			WRITE_BOOL_FIELD_DEFAULT(initially_valid, true);
 			break;
 
 		case CONSTR_ATTR_DEFERRABLE:
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 4287a7ec6e..19c023fb32 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -356,18 +356,23 @@ _readConst(void)
 	READ_LOCALS(Const);
 
 	READ_OID_FIELD(consttype);
-	READ_INT_FIELD(consttypmod);
+	READ_INT_FIELD_DEFAULT(consttypmod, -1);
 	READ_OID_FIELD(constcollid);
-	READ_INT_FIELD(constlen);
+	READ_INT_FIELD_DEFAULT(constlen, -1);
 	READ_BOOL_FIELD(constbyval);
 	READ_BOOL_FIELD(constisnull);
 	READ_LOCATION_FIELD(location);
 
-	token = pg_strtok(&length); /* skip :constvalue */
-	if (local_node->constisnull)
-		token = pg_strtok(&length); /* skip "<>" */
-	else
+	if (pg_strtoken_next(":constvalue"))
+	{
+		token = pg_strtok(&length); /* skip :constvalue */
+		Assert(strncmp(token, ":constvalue", sizeof(":constvalue") - 1) == 0);
 		local_node->constvalue = readDatum(local_node->constbyval);
+	}
+	else
+	{
+		/* value was omitted */
+	}
 
 	READ_DONE();
 }
@@ -493,7 +498,7 @@ _readConstraint(void)
 			READ_INT_FIELD(inhcount);
 			READ_BOOL_FIELD(is_no_inherit);
 			READ_BOOL_FIELD(skip_validation);
-			READ_BOOL_FIELD(initially_valid);
+			READ_BOOL_FIELD_DEFAULT(initially_valid, true);
 			break;
 
 		case CONSTR_DEFAULT:
@@ -517,7 +522,7 @@ _readConstraint(void)
 			READ_NODE_FIELD(raw_expr);
 			READ_STRING_FIELD(cooked_expr);
 			READ_BOOL_FIELD(skip_validation);
-			READ_BOOL_FIELD(initially_valid);
+			READ_BOOL_FIELD_DEFAULT(initially_valid, true);
 			break;
 
 		case CONSTR_PRIMARY:
@@ -531,7 +536,7 @@ _readConstraint(void)
 			break;
 
 		case CONSTR_UNIQUE:
-			READ_BOOL_FIELD(nulls_not_distinct);
+			READ_BOOL_FIELD_DEFAULT(nulls_not_distinct, true);
 			READ_NODE_FIELD(keys);
 			READ_NODE_FIELD(including);
 			READ_NODE_FIELD(options);
@@ -563,7 +568,7 @@ _readConstraint(void)
 			READ_NODE_FIELD(old_conpfeqop);
 			READ_OID_FIELD(old_pktable_oid);
 			READ_BOOL_FIELD(skip_validation);
-			READ_BOOL_FIELD(initially_valid);
+			READ_BOOL_FIELD_DEFAULT(initially_valid, true);
 			break;
 
 		case CONSTR_ATTR_DEFERRABLE:
@@ -595,10 +600,10 @@ _readRangeTblEntry(void)
 	{
 		case RTE_RELATION:
 			READ_OID_FIELD(relid);
-			READ_CHAR_FIELD(relkind);
-			READ_INT_FIELD(rellockmode);
+			READ_CHAR_FIELD_DEFAULT(relkind, 'r');
+			READ_INT_FIELD_DEFAULT(rellockmode, 1);
 			READ_NODE_FIELD(tablesample);
-			READ_UINT_FIELD(perminfoindex);
+			READ_UINT_FIELD_DEFAULT(perminfoindex, 1);
 			break;
 		case RTE_SUBQUERY:
 			READ_NODE_FIELD(subquery);
@@ -607,7 +612,7 @@ _readRangeTblEntry(void)
 			READ_OID_FIELD(relid);
 			READ_CHAR_FIELD(relkind);
 			READ_INT_FIELD(rellockmode);
-			READ_UINT_FIELD(perminfoindex);
+			READ_UINT_FIELD_DEFAULT(perminfoindex, 1);
 			break;
 		case RTE_JOIN:
 			READ_ENUM_FIELD(jointype, JoinType);
@@ -666,8 +671,8 @@ _readRangeTblEntry(void)
 	}
 
 	READ_BOOL_FIELD(lateral);
-	READ_BOOL_FIELD(inh);
-	READ_BOOL_FIELD(inFromCl);
+	READ_BOOL_FIELD_DEFAULT(inh, true); /* safe assumption */
+	READ_BOOL_FIELD_DEFAULT(inFromCl, true); /* safe assumption */
 	READ_NODE_FIELD(securityQuals);
 
 	READ_DONE();
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index e11b044b89..dd6508ae84 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -261,7 +261,7 @@ typedef struct TypeName
 	bool		setof;			/* is a set? */
 	bool		pct_type;		/* %TYPE specified? */
 	List	   *typmods;		/* type modifier expression(s) */
-	int32		typemod;		/* prespecified type modifier */
+	int32		typemod pg_node_attr(default(-1)); /* prespecified type modifier */
 	List	   *arrayBounds;	/* array bounds */
 	int			location;		/* token location, or -1 if unknown */
 } TypeName;
@@ -556,7 +556,8 @@ typedef struct WindowDef
 	char	   *refname;		/* referenced window name, if any */
 	List	   *partitionClause;	/* PARTITION BY expression list */
 	List	   *orderClause;	/* ORDER BY (list of SortBy) */
-	int			frameOptions;	/* frame_clause options, see below */
+	/* frame_clause options, see below */
+	int			frameOptions pg_node_attr(default(FRAMEOPTION_DEFAULTS));
 	Node	   *startOffset;	/* expression for starting bound, if any */
 	Node	   *endOffset;		/* expression for ending bound, if any */
 	int			location;		/* parse location, or -1 if none/unknown */
@@ -1235,7 +1236,8 @@ typedef struct RTEPermissionInfo
 	NodeTag		type;
 
 	Oid			relid;			/* relation OID */
-	bool		inh;			/* separately check inheritance children? */
+	/* separately check inheritance children? */
+	bool		inh pg_node_attr(default(true));
 	/* bitmask of required access permissions, in views usually ACL_SELECT */
 	AclMode		requiredPerms pg_node_attr(default(ACL_SELECT));
 	Oid			checkAsUser;	/* if valid, check access as this role */
@@ -1388,8 +1390,8 @@ typedef struct SortGroupClause
 	Oid			eqop;			/* the equality operator ('=' op) */
 	Oid			sortop;			/* the ordering operator ('<' op), or 0 */
 	bool		nulls_first;	/* do NULLs come before normal values? */
-	/* can eqop be implemented by hashing? */
-	bool		hashable pg_node_attr(query_jumble_ignore);
+	/* can eqop be implemented by hashing? (often true for builtin operators) */
+	bool		hashable pg_node_attr(query_jumble_ignore, default(true));
 } SortGroupClause;
 
 /*
@@ -1491,7 +1493,8 @@ typedef struct WindowClause
 	List	   *partitionClause;	/* PARTITION BY list */
 	/* ORDER BY list */
 	List	   *orderClause;
-	int			frameOptions;	/* frame_clause options, see WindowDef */
+	/* frame_clause options, see WindowDef */
+	int			frameOptions pg_node_attr(default(FRAMEOPTION_DEFAULTS));
 	Node	   *startOffset;	/* expression for starting bound, if any */
 	Node	   *endOffset;		/* expression for ending bound, if any */
 	/* qual to help short-circuit execution */
@@ -2025,7 +2028,7 @@ typedef struct SelectStmt
 typedef struct SetOperationStmt
 {
 	NodeTag		type;
-	SetOperation op;			/* type of set op */
+	SetOperation op pg_node_attr(default(1)); /* type of set op */
 	bool		all;			/* ALL specified? */
 	Node	   *larg;			/* left child */
 	Node	   *rarg;			/* right child */
diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h
index e688fc2b79..78ee667704 100644
--- a/src/include/nodes/pathnodes.h
+++ b/src/include/nodes/pathnodes.h
@@ -3380,7 +3380,7 @@ typedef struct AggTransInfo
 
 	/* Additional data about transtype */
 	int32		aggtranstypmod pg_node_attr(default(-1));
-	int			transtypeLen;
+	int			transtypeLen pg_node_attr(default(-1));
 	bool		transtypeByVal;
 
 	/* Space-consumption estimate */
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index acb275900f..bb11231554 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -245,7 +245,7 @@ typedef struct Var
 	/*
 	 * attribute number of this var, or zero for all attrs ("whole-row Var")
 	 */
-	AttrNumber	varattno;
+	AttrNumber	varattno pg_node_attr(default(1));
 
 	/* pg_type OID for the type of this var */
 	Oid			vartype pg_node_attr(query_jumble_ignore);
@@ -305,7 +305,7 @@ typedef struct Const
 	/* OID of collation, or InvalidOid if none */
 	Oid			constcollid pg_node_attr(query_jumble_ignore);
 	/* typlen of the constant's datatype */
-	int			constlen pg_node_attr(query_jumble_ignore);
+	int			constlen pg_node_attr(query_jumble_ignore, default(-1));
 	/* the constant's value */
 	Datum		constvalue pg_node_attr(query_jumble_ignore);
 	/* whether the constant is null (if true, constvalue is undefined) */
@@ -364,7 +364,8 @@ typedef struct Param
 {
 	Expr		xpr;
 	ParamKind	paramkind;		/* kind of parameter. See above */
-	int			paramid;		/* numeric ID for parameter */
+	/* numeric ID for parameter */
+	int			paramid pg_node_attr(default(1));
 	Oid			paramtype;		/* pg_type OID of parameter's datatype */
 	/* typmod value, if known */
 	int32		paramtypmod pg_node_attr(query_jumble_ignore, default(-1));
@@ -476,7 +477,7 @@ typedef struct Aggref
 	bool		aggvariadic pg_node_attr(query_jumble_ignore);
 
 	/* aggregate kind (see pg_aggregate.h) */
-	char		aggkind pg_node_attr(query_jumble_ignore);
+	char		aggkind pg_node_attr(query_jumble_ignore, default('n'));
 
 	/* aggregate input already sorted */
 	bool		aggpresorted pg_node_attr(equal_ignore, query_jumble_ignore);
@@ -760,7 +761,7 @@ typedef struct OpExpr
 	Oid			opfuncid pg_node_attr(equal_ignore_if_zero, query_jumble_ignore);
 
 	/* PG_TYPE OID of result value */
-	Oid			opresulttype pg_node_attr(query_jumble_ignore);
+	Oid			opresulttype pg_node_attr(query_jumble_ignore, default(BOOLOID));
 
 	/* true if operator returns set */
 	bool		opretset pg_node_attr(query_jumble_ignore);
@@ -845,8 +846,8 @@ typedef struct ScalarArrayOpExpr
 	/* PG_PROC OID of negator of opfuncid function or InvalidOid.  See above */
 	Oid			negfuncid pg_node_attr(equal_ignore_if_zero, query_jumble_ignore);
 
-	/* true for ANY, false for ALL */
-	bool		useOr;
+	/* true for ANY, false for ALL - usually users use ANY */
+	bool		useOr pg_node_attr(default(true));
 
 	/* OID of collation that operator should use */
 	Oid			inputcollid pg_node_attr(query_jumble_ignore);
@@ -1127,7 +1128,7 @@ typedef struct RelabelType
 	/* OID of collation, or InvalidOid if none */
 	Oid			resultcollid pg_node_attr(query_jumble_ignore);
 	/* how to display this node */
-	CoercionForm relabelformat pg_node_attr(query_jumble_ignore);
+	CoercionForm relabelformat pg_node_attr(query_jumble_ignore, default(COERCE_EXPLICIT_CAST));
 	int			location;		/* token location, or -1 if unknown */
 } RelabelType;
 
@@ -1148,8 +1149,8 @@ typedef struct CoerceViaIO
 	/* output typmod is not stored, but is presumed -1 */
 	/* OID of collation, or InvalidOid if none */
 	Oid			resultcollid pg_node_attr(query_jumble_ignore);
-	/* how to display this node */
-	CoercionForm coerceformat pg_node_attr(query_jumble_ignore);
+	/* how to display this node, in pg_rewrite this is generally an implicit cast */
+	CoercionForm coerceformat pg_node_attr(query_jumble_ignore, default(COERCE_IMPLICIT_CAST));
 	int			location;		/* token location, or -1 if unknown */
 } CoerceViaIO;
 
@@ -1176,8 +1177,9 @@ typedef struct ArrayCoerceExpr
 	int32		resulttypmod pg_node_attr(query_jumble_ignore, default(-1));
 	/* OID of collation, or InvalidOid if none */
 	Oid			resultcollid pg_node_attr(query_jumble_ignore);
-	/* how to display this node */
-	CoercionForm coerceformat pg_node_attr(query_jumble_ignore);
+	/* How to display this node. Arrays don't often have implicit casts, so
+	 * we default to explicit casts */
+	CoercionForm coerceformat pg_node_attr(query_jumble_ignore, default(COERCE_EXPLICIT_CAST));
 	int			location;		/* token location, or -1 if unknown */
 } ArrayCoerceExpr;
 
@@ -1293,7 +1295,7 @@ typedef struct CaseTestExpr
 	Expr		xpr;
 	Oid			typeId;			/* type for substituted value */
 	/* typemod for substituted value */
-	int32		typeMod pg_node_attr(query_jumble_ignore);
+	int32		typeMod pg_node_attr(query_jumble_ignore, default(-1));
 	/* collation for the substituted value */
 	Oid			collation pg_node_attr(query_jumble_ignore);
 } CaseTestExpr;
@@ -1702,7 +1704,8 @@ typedef struct NullTest
 {
 	Expr		xpr;
 	Expr	   *arg;			/* input expression */
-	NullTestType nulltesttype;	/* IS NULL, IS NOT NULL */
+	/* IS NULL, IS NOT NULL */
+	NullTestType nulltesttype pg_node_attr(default(IS_NOT_NULL));
 	/* T to perform field-by-field null checks */
 	bool		argisrow pg_node_attr(query_jumble_ignore);
 	int			location;		/* token location, or -1 if unknown */
@@ -1789,7 +1792,7 @@ typedef struct CoerceToDomainValue
 	/* type for substituted value */
 	Oid			typeId;
 	/* typemod for substituted value */
-	int32		typeMod pg_node_attr(query_jumble_ignore);
+	int32		typeMod pg_node_attr(query_jumble_ignore, default(-1));
 	/* collation for the substituted value */
 	Oid			collation pg_node_attr(query_jumble_ignore);
 	/* token location, or -1 if unknown */
@@ -1809,7 +1812,7 @@ typedef struct SetToDefault
 	/* type for substituted value */
 	Oid			typeId;
 	/* typemod for substituted value */
-	int32		typeMod pg_node_attr(query_jumble_ignore);
+	int32		typeMod pg_node_attr(query_jumble_ignore, default(-1));
 	/* collation for the substituted value */
 	Oid			collation pg_node_attr(query_jumble_ignore);
 	/* token location, or -1 if unknown */
@@ -1926,8 +1929,9 @@ typedef struct TargetEntry
 	Expr		xpr;
 	/* expression to evaluate */
 	Expr	   *expr;
-	/* attribute number (see notes above) */
-	AttrNumber	resno;
+	/* attribute number (see notes above).
+	 * Counting starts at 1, so that's the default for serialization, too. */
+	AttrNumber	resno pg_node_attr(default(1));
 	/* name of the column (could be NULL) */
 	char	   *resname pg_node_attr(query_jumble_ignore);
 	/* nonzero if referenced by a sort/group clause */
-- 
2.40.1

