From 705cfa1818765f8971a49a0dc7a9d9b590c963f8 Mon Sep 17 00:00:00 2001
From: Matthias van de Meent <boekewurm+postgres@gmail.com>
Date: Mon, 12 Feb 2024 17:12:02 +0100
Subject: [PATCH v3 7/7] gen_node_support.pl: Optimize serialization of fields
 with copied values

The Var node's [syn] fields often contain the same data as their non-syn
counterparts. We invent a new pg_node_attr()ibute that represents this
relation, which allows us to omit these fields from serialization when they
are indeed copies of the original fields.
---
 src/backend/nodes/gen_node_support.pl | 94 ++++++++++++++++++---------
 src/backend/nodes/outfuncs.c          |  3 +
 src/backend/nodes/readfuncs.c         |  3 +
 src/include/nodes/primnodes.h         |  4 +-
 4 files changed, 70 insertions(+), 34 deletions(-)

diff --git a/src/backend/nodes/gen_node_support.pl b/src/backend/nodes/gen_node_support.pl
index fda8c3a494..66661a3881 100644
--- a/src/backend/nodes/gen_node_support.pl
+++ b/src/backend/nodes/gen_node_support.pl
@@ -363,6 +363,10 @@ foreach my $infile (@ARGV)
 						{
 							$manual_nodetag_number{$in_struct} = $1;
 						}
+						elsif ($attr =~ /^default_ref\(([\w\d."'-]+)\)$/)
+						{
+							# Unused at the node level
+						}
 						else
 						{
 							die
@@ -437,7 +441,7 @@ foreach my $infile (@ARGV)
 			}
 			# normal struct field
 			elsif ($line =~
-				/^\s*(.+)\s*\b(\w+)(\[[\w\s+]+\])?\s*(?:pg_node_attr\(([\w(), ]*)\))?;/
+				/^\s*(.+)\s*\b(\w+)(\[[\w\s+]+\])?\s*(?:pg_node_attr\(([\w\d(), ."'-]*)\))?;/
 			  )
 			{
 				if ($is_node_struct)
@@ -469,6 +473,7 @@ foreach my $infile (@ARGV)
 							if (   $attr !~ /^array_size\(\w+\)$/
 								&& $attr !~ /^copy_as\(\w+\)$/
 								&& $attr !~ /^read_as\(\w+\)$/
+								&& $attr !~ /^default_ref\([\w\d."'-]+\)$/
 								&& !elem $attr,
 								qw(copy_as_scalar
 								equal_as_scalar
@@ -495,7 +500,7 @@ foreach my $infile (@ARGV)
 			}
 			# function pointer field
 			elsif ($line =~
-				/^\s*([\w\s*]+)\s*\(\*(\w+)\)\s*\((.*)\)\s*(?:pg_node_attr\(([\w(), ]*)\))?;/
+				/^\s*([\w\s*]+)\s*\(\*(\w+)\)\s*\((.*)\)\s*(?:pg_node_attr\(([\w\d(), ."'-]*)\))?;/
 			  )
 			{
 				if ($is_node_struct)
@@ -970,6 +975,15 @@ _read${n}(void)
 		my $array_size_field;
 		my $read_as_field;
 		my $read_write_ignore = 0;
+		# Type read/write macro suffix, "" for normal use, or "_DEFAULT" when
+		# value argument.
+		my $s = "";
+		# Default parameter to read/write macro. Includes comma separator so
+		# that MACRO_NAME$s($fieldname$defaultparam) is the full complete
+		# read/write expression for essentially all types.
+		# Note that this (currently) only works for scalar values.
+		my $d = "";
+
 		foreach my $a (@a)
 		{
 			if ($a =~ /^array_size\(([\w.]+)\)$/)
@@ -988,6 +1002,19 @@ _read${n}(void)
 			{
 				$read_write_ignore = 1;
 			}
+			elsif ($a =~ /^default_ref\(([\w\d+."'-]+)\)$/)
+			{
+				$s = "_DEFAULT";
+				$d = ", NODE_FIELD($1)";
+			}
+		}
+
+		if ($s eq "_DEFAULT")
+		{
+			die "custom defaults for non-scalar fields are not supported\n\tat $n.$f"
+				unless (elem $t, @scalar_types or elem $t, @enum_types);
+			die "custom defaults for Location fields are not supported\n\tat $n.$f"
+				if ($t eq "Location");
 		}
 
 		if ($read_write_ignore)
@@ -1008,8 +1035,8 @@ _read${n}(void)
 		# select instructions by field type
 		if ($t eq 'bool')
 		{
-			print $off "\tWRITE_BOOL_FIELD($f);\n";
-			print $rff "\tREAD_BOOL_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_BOOL_FIELD$s($f$d);\n";
+			print $rff "\tREAD_BOOL_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'Location')
 		{
@@ -1018,8 +1045,11 @@ _read${n}(void)
 		}
 		elsif ($t eq 'TypMod')
 		{
-			print $off "\tWRITE_INT_FIELD_DEFAULT($f, -1);\n";
-			print $rff "\tREAD_INT_FIELD_DEFAULT($f, -1);\n" unless $no_read;
+			# The default value of a TypMod fields is -1, rather than 0
+			# for normal int fields.
+			$d = ", -1" if ($d eq "");
+			print $off "\tWRITE_INT_FIELD_DEFAULT($f$d);\n";
+			print $rff "\tREAD_INT_FIELD_DEFAULT($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'int'
 			|| $t eq 'int16'
@@ -1027,8 +1057,8 @@ _read${n}(void)
 			|| $t eq 'AttrNumber'
 			|| $t eq 'StrategyNumber')
 		{
-			print $off "\tWRITE_INT_FIELD($f);\n";
-			print $rff "\tREAD_INT_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_INT_FIELD$s($f$d);\n";
+			print $rff "\tREAD_INT_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'uint32'
 			|| $t eq 'bits32'
@@ -1036,56 +1066,56 @@ _read${n}(void)
 			|| $t eq 'Index'
 			|| $t eq 'SubTransactionId')
 		{
-			print $off "\tWRITE_UINT_FIELD($f);\n";
-			print $rff "\tREAD_UINT_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_UINT_FIELD$s($f$d);\n";
+			print $rff "\tREAD_UINT_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'uint64'
 			|| $t eq 'AclMode')
 		{
-			print $off "\tWRITE_UINT64_FIELD($f);\n";
-			print $rff "\tREAD_UINT64_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_UINT64_FIELD$s($f$d);\n";
+			print $rff "\tREAD_UINT64_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'Oid' || $t eq 'RelFileNumber')
 		{
-			print $off "\tWRITE_OID_FIELD($f);\n";
-			print $rff "\tREAD_OID_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_OID_FIELD$s($f$d);\n";
+			print $rff "\tREAD_OID_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'long')
 		{
-			print $off "\tWRITE_LONG_FIELD($f);\n";
-			print $rff "\tREAD_LONG_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_LONG_FIELD$s($f$d);\n";
+			print $rff "\tREAD_LONG_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'char')
 		{
-			print $off "\tWRITE_CHAR_FIELD($f);\n";
-			print $rff "\tREAD_CHAR_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_CHAR_FIELD$s($f$d);\n";
+			print $rff "\tREAD_CHAR_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'double')
 		{
-			print $off "\tWRITE_FLOAT_FIELD($f);\n";
-			print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_FLOAT_FIELD$s($f$d);\n";
+			print $rff "\tREAD_FLOAT_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'Cardinality')
 		{
-			print $off "\tWRITE_FLOAT_FIELD($f);\n";
-			print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_FLOAT_FIELD$s($f$d);\n";
+			print $rff "\tREAD_FLOAT_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'Cost')
 		{
-			print $off "\tWRITE_FLOAT_FIELD($f);\n";
-			print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_FLOAT_FIELD$s($f$d);\n";
+			print $rff "\tREAD_FLOAT_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'QualCost')
 		{
-			print $off "\tWRITE_FLOAT_FIELD($f.startup);\n";
-			print $off "\tWRITE_FLOAT_FIELD($f.per_tuple);\n";
-			print $rff "\tREAD_FLOAT_FIELD($f.startup);\n" unless $no_read;
-			print $rff "\tREAD_FLOAT_FIELD($f.per_tuple);\n" unless $no_read;
+			print $off "\tWRITE_FLOAT_FIELD$s($f.startup$d);\n";
+			print $off "\tWRITE_FLOAT_FIELD$s($f.per_tuple$d);\n";
+			print $rff "\tREAD_FLOAT_FIELD$s($f.startup$d);\n" unless $no_read;
+			print $rff "\tREAD_FLOAT_FIELD$s($f.per_tuple$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'Selectivity')
 		{
-			print $off "\tWRITE_FLOAT_FIELD($f);\n";
-			print $rff "\tREAD_FLOAT_FIELD($f);\n" unless $no_read;
+			print $off "\tWRITE_FLOAT_FIELD$s($f$d);\n";
+			print $rff "\tREAD_FLOAT_FIELD$s($f$d);\n" unless $no_read;
 		}
 		elsif ($t eq 'char*')
 		{
@@ -1099,8 +1129,8 @@ _read${n}(void)
 		}
 		elsif (elem $t, @enum_types)
 		{
-			print $off "\tWRITE_ENUM_FIELD($f, $t);\n";
-			print $rff "\tREAD_ENUM_FIELD($f, $t);\n" unless $no_read;
+			print $off "\tWRITE_ENUM_FIELD$s($f, $t$d);\n";
+			print $rff "\tREAD_ENUM_FIELD$s($f, $t$d);\n" unless $no_read;
 		}
 		# arrays of scalar types
 		elsif ($t =~ /^(\w+)(\*|\[\w+\])$/ and elem $1, @scalar_types)
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index f135753fb4..75a7703b62 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -240,6 +240,9 @@ static void outDouble(StringInfo str, double d);
 		} \
 	} while (0)
 
+/* Accessing a node's field goes like this */
+#define NODE_FIELD(fldname) (node->fldname)
+
 #define booltostr(x)  ((x) ? "true" : "false")
 
 
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 55e40f5603..4d11696e68 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -258,6 +258,9 @@
 #define READ_BOOL_ARRAY(fldname, len) \
 	READ_BOOL_ARRAY_DEFAULT(fldname, len, NULL)
 
+/* Accessing a node's field goes like this */
+#define NODE_FIELD(fldname) (local_node->fldname)
+
 /* Routine exit */
 #define READ_DONE() \
 	return local_node
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 94282497d7..9dd60ad5c5 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -274,9 +274,9 @@ typedef struct Var
 	 * their varno/varattno match.
 	 */
 	/* syntactic relation index (0 if unknown) */
-	Index		varnosyn pg_node_attr(equal_ignore, query_jumble_ignore);
+	Index		varnosyn pg_node_attr(equal_ignore, query_jumble_ignore, default_ref(varno));
 	/* syntactic attribute number */
-	AttrNumber	varattnosyn pg_node_attr(equal_ignore, query_jumble_ignore);
+	AttrNumber	varattnosyn pg_node_attr(equal_ignore, query_jumble_ignore, default_ref(varattno));
 
 	/* token location, or -1 if unknown */
 	Location	location;
-- 
2.40.1

