summaryrefslogtreecommitdiffstats
path: root/src/backend/nodes/outfuncs.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/nodes/outfuncs.c')
-rw-r--r--src/backend/nodes/outfuncs.c4634
1 files changed, 4634 insertions, 0 deletions
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
new file mode 100644
index 0000000..3f8e586
--- /dev/null
+++ b/src/backend/nodes/outfuncs.c
@@ -0,0 +1,4634 @@
+/*-------------------------------------------------------------------------
+ *
+ * outfuncs.c
+ * Output functions for Postgres tree nodes.
+ *
+ * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/nodes/outfuncs.c
+ *
+ * NOTES
+ * Every node type that can appear in stored rules' parsetrees *must*
+ * have an output function defined here (as well as an input function
+ * in readfuncs.c). In addition, plan nodes should have input and
+ * output functions so that they can be sent to parallel workers.
+ *
+ * For use in debugging, we also provide output functions for nodes
+ * that appear in raw parsetrees and planner Paths. These node types
+ * need not have input functions. Output support for raw parsetrees
+ * is somewhat incomplete, too; in particular, utility statements are
+ * almost entirely unsupported. We try to support everything that can
+ * appear in a raw SELECT, though.
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <ctype.h>
+
+#include "lib/stringinfo.h"
+#include "miscadmin.h"
+#include "nodes/extensible.h"
+#include "nodes/pathnodes.h"
+#include "nodes/plannodes.h"
+#include "utils/datum.h"
+#include "utils/rel.h"
+
+static void outChar(StringInfo str, char c);
+
+
+/*
+ * Macros to simplify output of different kinds of fields. Use these
+ * wherever possible to reduce the chance for silly typos. Note that these
+ * hard-wire conventions about the names of the local variables in an Out
+ * routine.
+ */
+
+/* Write the label for the node type */
+#define WRITE_NODE_TYPE(nodelabel) \
+ appendStringInfoString(str, nodelabel)
+
+/* Write an integer field (anything written as ":fldname %d") */
+#define WRITE_INT_FIELD(fldname) \
+ appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
+
+/* Write an unsigned integer field (anything written as ":fldname %u") */
+#define WRITE_UINT_FIELD(fldname) \
+ appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
+
+/* Write an unsigned integer field (anything written with UINT64_FORMAT) */
+#define WRITE_UINT64_FIELD(fldname) \
+ appendStringInfo(str, " :" CppAsString(fldname) " " UINT64_FORMAT, \
+ node->fldname)
+
+/* Write an OID field (don't hard-wire assumption that OID is same as uint) */
+#define WRITE_OID_FIELD(fldname) \
+ appendStringInfo(str, " :" CppAsString(fldname) " %u", node->fldname)
+
+/* Write a long-integer field */
+#define WRITE_LONG_FIELD(fldname) \
+ appendStringInfo(str, " :" CppAsString(fldname) " %ld", node->fldname)
+
+/* Write a char field (ie, one ascii character) */
+#define WRITE_CHAR_FIELD(fldname) \
+ (appendStringInfo(str, " :" CppAsString(fldname) " "), \
+ outChar(str, node->fldname))
+
+/* Write an enumerated-type field as an integer code */
+#define WRITE_ENUM_FIELD(fldname, enumtype) \
+ appendStringInfo(str, " :" CppAsString(fldname) " %d", \
+ (int) node->fldname)
+
+/* Write a float field --- caller must give format to define precision */
+#define WRITE_FLOAT_FIELD(fldname,format) \
+ appendStringInfo(str, " :" CppAsString(fldname) " " format, node->fldname)
+
+/* Write a boolean field */
+#define WRITE_BOOL_FIELD(fldname) \
+ appendStringInfo(str, " :" CppAsString(fldname) " %s", \
+ booltostr(node->fldname))
+
+/* Write a character-string (possibly NULL) field */
+#define WRITE_STRING_FIELD(fldname) \
+ (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
+ outToken(str, node->fldname))
+
+/* Write a parse location field (actually same as INT case) */
+#define WRITE_LOCATION_FIELD(fldname) \
+ appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
+
+/* Write a Node field */
+#define WRITE_NODE_FIELD(fldname) \
+ (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
+ outNode(str, node->fldname))
+
+/* Write a bitmapset field */
+#define WRITE_BITMAPSET_FIELD(fldname) \
+ (appendStringInfoString(str, " :" CppAsString(fldname) " "), \
+ outBitmapset(str, node->fldname))
+
+#define WRITE_ATTRNUMBER_ARRAY(fldname, len) \
+ do { \
+ appendStringInfoString(str, " :" CppAsString(fldname) " "); \
+ for (int i = 0; i < len; i++) \
+ appendStringInfo(str, " %d", node->fldname[i]); \
+ } while(0)
+
+#define WRITE_OID_ARRAY(fldname, len) \
+ do { \
+ appendStringInfoString(str, " :" CppAsString(fldname) " "); \
+ for (int i = 0; i < len; i++) \
+ appendStringInfo(str, " %u", node->fldname[i]); \
+ } while(0)
+
+/*
+ * This macro supports the case that the field is NULL. For the other array
+ * macros, that is currently not needed.
+ */
+#define WRITE_INDEX_ARRAY(fldname, len) \
+ do { \
+ appendStringInfoString(str, " :" CppAsString(fldname) " "); \
+ if (node->fldname) \
+ for (int i = 0; i < len; i++) \
+ appendStringInfo(str, " %u", node->fldname[i]); \
+ else \
+ appendStringInfoString(str, "<>"); \
+ } while(0)
+
+#define WRITE_INT_ARRAY(fldname, len) \
+ do { \
+ appendStringInfoString(str, " :" CppAsString(fldname) " "); \
+ for (int i = 0; i < len; i++) \
+ appendStringInfo(str, " %d", node->fldname[i]); \
+ } while(0)
+
+#define WRITE_BOOL_ARRAY(fldname, len) \
+ do { \
+ appendStringInfoString(str, " :" CppAsString(fldname) " "); \
+ for (int i = 0; i < len; i++) \
+ appendStringInfo(str, " %s", booltostr(node->fldname[i])); \
+ } while(0)
+
+
+#define booltostr(x) ((x) ? "true" : "false")
+
+
+/*
+ * outToken
+ * Convert an ordinary string (eg, an identifier) into a form that
+ * will be decoded back to a plain token by read.c's functions.
+ *
+ * If a null or empty string is given, it is encoded as "<>".
+ */
+void
+outToken(StringInfo str, const char *s)
+{
+ if (s == NULL || *s == '\0')
+ {
+ appendStringInfoString(str, "<>");
+ return;
+ }
+
+ /*
+ * Look for characters or patterns that are treated specially by read.c
+ * (either in pg_strtok() or in nodeRead()), and therefore need a
+ * protective backslash.
+ */
+ /* These characters only need to be quoted at the start of the string */
+ if (*s == '<' ||
+ *s == '"' ||
+ isdigit((unsigned char) *s) ||
+ ((*s == '+' || *s == '-') &&
+ (isdigit((unsigned char) s[1]) || s[1] == '.')))
+ appendStringInfoChar(str, '\\');
+ while (*s)
+ {
+ /* These chars must be backslashed anywhere in the string */
+ if (*s == ' ' || *s == '\n' || *s == '\t' ||
+ *s == '(' || *s == ')' || *s == '{' || *s == '}' ||
+ *s == '\\')
+ appendStringInfoChar(str, '\\');
+ appendStringInfoChar(str, *s++);
+ }
+}
+
+/*
+ * Convert one char. Goes through outToken() so that special characters are
+ * escaped.
+ */
+static void
+outChar(StringInfo str, char c)
+{
+ char in[2];
+
+ in[0] = c;
+ in[1] = '\0';
+
+ outToken(str, in);
+}
+
+static void
+_outList(StringInfo str, const List *node)
+{
+ const ListCell *lc;
+
+ appendStringInfoChar(str, '(');
+
+ if (IsA(node, IntList))
+ appendStringInfoChar(str, 'i');
+ else if (IsA(node, OidList))
+ appendStringInfoChar(str, 'o');
+
+ foreach(lc, node)
+ {
+ /*
+ * For the sake of backward compatibility, we emit a slightly
+ * different whitespace format for lists of nodes vs. other types of
+ * lists. XXX: is this necessary?
+ */
+ if (IsA(node, List))
+ {
+ outNode(str, lfirst(lc));
+ if (lnext(node, lc))
+ appendStringInfoChar(str, ' ');
+ }
+ else if (IsA(node, IntList))
+ appendStringInfo(str, " %d", lfirst_int(lc));
+ else if (IsA(node, OidList))
+ appendStringInfo(str, " %u", lfirst_oid(lc));
+ else
+ elog(ERROR, "unrecognized list node type: %d",
+ (int) node->type);
+ }
+
+ appendStringInfoChar(str, ')');
+}
+
+/*
+ * outBitmapset -
+ * converts a bitmap set of integers
+ *
+ * Note: the output format is "(b int int ...)", similar to an integer List.
+ */
+void
+outBitmapset(StringInfo str, const Bitmapset *bms)
+{
+ int x;
+
+ appendStringInfoChar(str, '(');
+ appendStringInfoChar(str, 'b');
+ x = -1;
+ while ((x = bms_next_member(bms, x)) >= 0)
+ appendStringInfo(str, " %d", x);
+ appendStringInfoChar(str, ')');
+}
+
+/*
+ * Print the value of a Datum given its type.
+ */
+void
+outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
+{
+ Size length,
+ i;
+ char *s;
+
+ length = datumGetSize(value, typbyval, typlen);
+
+ if (typbyval)
+ {
+ s = (char *) (&value);
+ appendStringInfo(str, "%u [ ", (unsigned int) length);
+ for (i = 0; i < (Size) sizeof(Datum); i++)
+ appendStringInfo(str, "%d ", (int) (s[i]));
+ appendStringInfoChar(str, ']');
+ }
+ else
+ {
+ s = (char *) DatumGetPointer(value);
+ if (!PointerIsValid(s))
+ appendStringInfoString(str, "0 [ ]");
+ else
+ {
+ appendStringInfo(str, "%u [ ", (unsigned int) length);
+ for (i = 0; i < length; i++)
+ appendStringInfo(str, "%d ", (int) (s[i]));
+ appendStringInfoChar(str, ']');
+ }
+ }
+}
+
+
+/*
+ * Stuff from plannodes.h
+ */
+
+static void
+_outPlannedStmt(StringInfo str, const PlannedStmt *node)
+{
+ WRITE_NODE_TYPE("PLANNEDSTMT");
+
+ WRITE_ENUM_FIELD(commandType, CmdType);
+ WRITE_UINT64_FIELD(queryId);
+ WRITE_BOOL_FIELD(hasReturning);
+ WRITE_BOOL_FIELD(hasModifyingCTE);
+ WRITE_BOOL_FIELD(canSetTag);
+ WRITE_BOOL_FIELD(transientPlan);
+ WRITE_BOOL_FIELD(dependsOnRole);
+ WRITE_BOOL_FIELD(parallelModeNeeded);
+ WRITE_INT_FIELD(jitFlags);
+ WRITE_NODE_FIELD(planTree);
+ WRITE_NODE_FIELD(rtable);
+ WRITE_NODE_FIELD(resultRelations);
+ WRITE_NODE_FIELD(appendRelations);
+ WRITE_NODE_FIELD(subplans);
+ WRITE_BITMAPSET_FIELD(rewindPlanIDs);
+ WRITE_NODE_FIELD(rowMarks);
+ WRITE_NODE_FIELD(relationOids);
+ WRITE_NODE_FIELD(invalItems);
+ WRITE_NODE_FIELD(paramExecTypes);
+ WRITE_NODE_FIELD(utilityStmt);
+ WRITE_LOCATION_FIELD(stmt_location);
+ WRITE_INT_FIELD(stmt_len);
+}
+
+/*
+ * print the basic stuff of all nodes that inherit from Plan
+ */
+static void
+_outPlanInfo(StringInfo str, const Plan *node)
+{
+ WRITE_FLOAT_FIELD(startup_cost, "%.2f");
+ WRITE_FLOAT_FIELD(total_cost, "%.2f");
+ WRITE_FLOAT_FIELD(plan_rows, "%.0f");
+ WRITE_INT_FIELD(plan_width);
+ WRITE_BOOL_FIELD(parallel_aware);
+ WRITE_BOOL_FIELD(parallel_safe);
+ WRITE_BOOL_FIELD(async_capable);
+ WRITE_INT_FIELD(plan_node_id);
+ WRITE_NODE_FIELD(targetlist);
+ WRITE_NODE_FIELD(qual);
+ WRITE_NODE_FIELD(lefttree);
+ WRITE_NODE_FIELD(righttree);
+ WRITE_NODE_FIELD(initPlan);
+ WRITE_BITMAPSET_FIELD(extParam);
+ WRITE_BITMAPSET_FIELD(allParam);
+}
+
+/*
+ * print the basic stuff of all nodes that inherit from Scan
+ */
+static void
+_outScanInfo(StringInfo str, const Scan *node)
+{
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_UINT_FIELD(scanrelid);
+}
+
+/*
+ * print the basic stuff of all nodes that inherit from Join
+ */
+static void
+_outJoinPlanInfo(StringInfo str, const Join *node)
+{
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_ENUM_FIELD(jointype, JoinType);
+ WRITE_BOOL_FIELD(inner_unique);
+ WRITE_NODE_FIELD(joinqual);
+}
+
+
+static void
+_outPlan(StringInfo str, const Plan *node)
+{
+ WRITE_NODE_TYPE("PLAN");
+
+ _outPlanInfo(str, (const Plan *) node);
+}
+
+static void
+_outResult(StringInfo str, const Result *node)
+{
+ WRITE_NODE_TYPE("RESULT");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_NODE_FIELD(resconstantqual);
+}
+
+static void
+_outProjectSet(StringInfo str, const ProjectSet *node)
+{
+ WRITE_NODE_TYPE("PROJECTSET");
+
+ _outPlanInfo(str, (const Plan *) node);
+}
+
+static void
+_outModifyTable(StringInfo str, const ModifyTable *node)
+{
+ WRITE_NODE_TYPE("MODIFYTABLE");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_ENUM_FIELD(operation, CmdType);
+ WRITE_BOOL_FIELD(canSetTag);
+ WRITE_UINT_FIELD(nominalRelation);
+ WRITE_UINT_FIELD(rootRelation);
+ WRITE_BOOL_FIELD(partColsUpdated);
+ WRITE_NODE_FIELD(resultRelations);
+ WRITE_NODE_FIELD(updateColnosLists);
+ WRITE_NODE_FIELD(withCheckOptionLists);
+ WRITE_NODE_FIELD(returningLists);
+ WRITE_NODE_FIELD(fdwPrivLists);
+ WRITE_BITMAPSET_FIELD(fdwDirectModifyPlans);
+ WRITE_NODE_FIELD(rowMarks);
+ WRITE_INT_FIELD(epqParam);
+ WRITE_ENUM_FIELD(onConflictAction, OnConflictAction);
+ WRITE_NODE_FIELD(arbiterIndexes);
+ WRITE_NODE_FIELD(onConflictSet);
+ WRITE_NODE_FIELD(onConflictCols);
+ WRITE_NODE_FIELD(onConflictWhere);
+ WRITE_UINT_FIELD(exclRelRTI);
+ WRITE_NODE_FIELD(exclRelTlist);
+ WRITE_NODE_FIELD(mergeActionLists);
+}
+
+static void
+_outAppend(StringInfo str, const Append *node)
+{
+ WRITE_NODE_TYPE("APPEND");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_BITMAPSET_FIELD(apprelids);
+ WRITE_NODE_FIELD(appendplans);
+ WRITE_INT_FIELD(nasyncplans);
+ WRITE_INT_FIELD(first_partial_plan);
+ WRITE_NODE_FIELD(part_prune_info);
+}
+
+static void
+_outMergeAppend(StringInfo str, const MergeAppend *node)
+{
+ WRITE_NODE_TYPE("MERGEAPPEND");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_BITMAPSET_FIELD(apprelids);
+ WRITE_NODE_FIELD(mergeplans);
+ WRITE_INT_FIELD(numCols);
+ WRITE_ATTRNUMBER_ARRAY(sortColIdx, node->numCols);
+ WRITE_OID_ARRAY(sortOperators, node->numCols);
+ WRITE_OID_ARRAY(collations, node->numCols);
+ WRITE_BOOL_ARRAY(nullsFirst, node->numCols);
+ WRITE_NODE_FIELD(part_prune_info);
+}
+
+static void
+_outRecursiveUnion(StringInfo str, const RecursiveUnion *node)
+{
+ WRITE_NODE_TYPE("RECURSIVEUNION");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_INT_FIELD(wtParam);
+ WRITE_INT_FIELD(numCols);
+ WRITE_ATTRNUMBER_ARRAY(dupColIdx, node->numCols);
+ WRITE_OID_ARRAY(dupOperators, node->numCols);
+ WRITE_OID_ARRAY(dupCollations, node->numCols);
+ WRITE_LONG_FIELD(numGroups);
+}
+
+static void
+_outBitmapAnd(StringInfo str, const BitmapAnd *node)
+{
+ WRITE_NODE_TYPE("BITMAPAND");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_NODE_FIELD(bitmapplans);
+}
+
+static void
+_outBitmapOr(StringInfo str, const BitmapOr *node)
+{
+ WRITE_NODE_TYPE("BITMAPOR");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_BOOL_FIELD(isshared);
+ WRITE_NODE_FIELD(bitmapplans);
+}
+
+static void
+_outGather(StringInfo str, const Gather *node)
+{
+ WRITE_NODE_TYPE("GATHER");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_INT_FIELD(num_workers);
+ WRITE_INT_FIELD(rescan_param);
+ WRITE_BOOL_FIELD(single_copy);
+ WRITE_BOOL_FIELD(invisible);
+ WRITE_BITMAPSET_FIELD(initParam);
+}
+
+static void
+_outGatherMerge(StringInfo str, const GatherMerge *node)
+{
+ WRITE_NODE_TYPE("GATHERMERGE");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_INT_FIELD(num_workers);
+ WRITE_INT_FIELD(rescan_param);
+ WRITE_INT_FIELD(numCols);
+ WRITE_ATTRNUMBER_ARRAY(sortColIdx, node->numCols);
+ WRITE_OID_ARRAY(sortOperators, node->numCols);
+ WRITE_OID_ARRAY(collations, node->numCols);
+ WRITE_BOOL_ARRAY(nullsFirst, node->numCols);
+ WRITE_BITMAPSET_FIELD(initParam);
+}
+
+static void
+_outScan(StringInfo str, const Scan *node)
+{
+ WRITE_NODE_TYPE("SCAN");
+
+ _outScanInfo(str, node);
+}
+
+static void
+_outSeqScan(StringInfo str, const SeqScan *node)
+{
+ WRITE_NODE_TYPE("SEQSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+}
+
+static void
+_outSampleScan(StringInfo str, const SampleScan *node)
+{
+ WRITE_NODE_TYPE("SAMPLESCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_NODE_FIELD(tablesample);
+}
+
+static void
+_outIndexScan(StringInfo str, const IndexScan *node)
+{
+ WRITE_NODE_TYPE("INDEXSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_OID_FIELD(indexid);
+ WRITE_NODE_FIELD(indexqual);
+ WRITE_NODE_FIELD(indexqualorig);
+ WRITE_NODE_FIELD(indexorderby);
+ WRITE_NODE_FIELD(indexorderbyorig);
+ WRITE_NODE_FIELD(indexorderbyops);
+ WRITE_ENUM_FIELD(indexorderdir, ScanDirection);
+}
+
+static void
+_outIndexOnlyScan(StringInfo str, const IndexOnlyScan *node)
+{
+ WRITE_NODE_TYPE("INDEXONLYSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_OID_FIELD(indexid);
+ WRITE_NODE_FIELD(indexqual);
+ WRITE_NODE_FIELD(recheckqual);
+ WRITE_NODE_FIELD(indexorderby);
+ WRITE_NODE_FIELD(indextlist);
+ WRITE_ENUM_FIELD(indexorderdir, ScanDirection);
+}
+
+static void
+_outBitmapIndexScan(StringInfo str, const BitmapIndexScan *node)
+{
+ WRITE_NODE_TYPE("BITMAPINDEXSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_OID_FIELD(indexid);
+ WRITE_BOOL_FIELD(isshared);
+ WRITE_NODE_FIELD(indexqual);
+ WRITE_NODE_FIELD(indexqualorig);
+}
+
+static void
+_outBitmapHeapScan(StringInfo str, const BitmapHeapScan *node)
+{
+ WRITE_NODE_TYPE("BITMAPHEAPSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_NODE_FIELD(bitmapqualorig);
+}
+
+static void
+_outTidScan(StringInfo str, const TidScan *node)
+{
+ WRITE_NODE_TYPE("TIDSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_NODE_FIELD(tidquals);
+}
+
+static void
+_outTidRangeScan(StringInfo str, const TidRangeScan *node)
+{
+ WRITE_NODE_TYPE("TIDRANGESCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_NODE_FIELD(tidrangequals);
+}
+
+static void
+_outSubqueryScan(StringInfo str, const SubqueryScan *node)
+{
+ WRITE_NODE_TYPE("SUBQUERYSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_NODE_FIELD(subplan);
+ WRITE_ENUM_FIELD(scanstatus, SubqueryScanStatus);
+}
+
+static void
+_outFunctionScan(StringInfo str, const FunctionScan *node)
+{
+ WRITE_NODE_TYPE("FUNCTIONSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_NODE_FIELD(functions);
+ WRITE_BOOL_FIELD(funcordinality);
+}
+
+static void
+_outTableFuncScan(StringInfo str, const TableFuncScan *node)
+{
+ WRITE_NODE_TYPE("TABLEFUNCSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_NODE_FIELD(tablefunc);
+}
+
+static void
+_outValuesScan(StringInfo str, const ValuesScan *node)
+{
+ WRITE_NODE_TYPE("VALUESSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_NODE_FIELD(values_lists);
+}
+
+static void
+_outCteScan(StringInfo str, const CteScan *node)
+{
+ WRITE_NODE_TYPE("CTESCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_INT_FIELD(ctePlanId);
+ WRITE_INT_FIELD(cteParam);
+}
+
+static void
+_outNamedTuplestoreScan(StringInfo str, const NamedTuplestoreScan *node)
+{
+ WRITE_NODE_TYPE("NAMEDTUPLESTORESCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_STRING_FIELD(enrname);
+}
+
+static void
+_outWorkTableScan(StringInfo str, const WorkTableScan *node)
+{
+ WRITE_NODE_TYPE("WORKTABLESCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_INT_FIELD(wtParam);
+}
+
+static void
+_outForeignScan(StringInfo str, const ForeignScan *node)
+{
+ WRITE_NODE_TYPE("FOREIGNSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_ENUM_FIELD(operation, CmdType);
+ WRITE_UINT_FIELD(resultRelation);
+ WRITE_OID_FIELD(fs_server);
+ WRITE_NODE_FIELD(fdw_exprs);
+ WRITE_NODE_FIELD(fdw_private);
+ WRITE_NODE_FIELD(fdw_scan_tlist);
+ WRITE_NODE_FIELD(fdw_recheck_quals);
+ WRITE_BITMAPSET_FIELD(fs_relids);
+ WRITE_BOOL_FIELD(fsSystemCol);
+}
+
+static void
+_outCustomScan(StringInfo str, const CustomScan *node)
+{
+ WRITE_NODE_TYPE("CUSTOMSCAN");
+
+ _outScanInfo(str, (const Scan *) node);
+
+ WRITE_UINT_FIELD(flags);
+ WRITE_NODE_FIELD(custom_plans);
+ WRITE_NODE_FIELD(custom_exprs);
+ WRITE_NODE_FIELD(custom_private);
+ WRITE_NODE_FIELD(custom_scan_tlist);
+ WRITE_BITMAPSET_FIELD(custom_relids);
+ /* CustomName is a key to lookup CustomScanMethods */
+ appendStringInfoString(str, " :methods ");
+ outToken(str, node->methods->CustomName);
+}
+
+static void
+_outJoin(StringInfo str, const Join *node)
+{
+ WRITE_NODE_TYPE("JOIN");
+
+ _outJoinPlanInfo(str, (const Join *) node);
+}
+
+static void
+_outNestLoop(StringInfo str, const NestLoop *node)
+{
+ WRITE_NODE_TYPE("NESTLOOP");
+
+ _outJoinPlanInfo(str, (const Join *) node);
+
+ WRITE_NODE_FIELD(nestParams);
+}
+
+static void
+_outMergeJoin(StringInfo str, const MergeJoin *node)
+{
+ int numCols;
+
+ WRITE_NODE_TYPE("MERGEJOIN");
+
+ _outJoinPlanInfo(str, (const Join *) node);
+
+ WRITE_BOOL_FIELD(skip_mark_restore);
+ WRITE_NODE_FIELD(mergeclauses);
+
+ numCols = list_length(node->mergeclauses);
+
+ WRITE_OID_ARRAY(mergeFamilies, numCols);
+ WRITE_OID_ARRAY(mergeCollations, numCols);
+ WRITE_INT_ARRAY(mergeStrategies, numCols);
+ WRITE_BOOL_ARRAY(mergeNullsFirst, numCols);
+}
+
+static void
+_outHashJoin(StringInfo str, const HashJoin *node)
+{
+ WRITE_NODE_TYPE("HASHJOIN");
+
+ _outJoinPlanInfo(str, (const Join *) node);
+
+ WRITE_NODE_FIELD(hashclauses);
+ WRITE_NODE_FIELD(hashoperators);
+ WRITE_NODE_FIELD(hashcollations);
+ WRITE_NODE_FIELD(hashkeys);
+}
+
+static void
+_outAgg(StringInfo str, const Agg *node)
+{
+ WRITE_NODE_TYPE("AGG");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
+ WRITE_ENUM_FIELD(aggsplit, AggSplit);
+ WRITE_INT_FIELD(numCols);
+ WRITE_ATTRNUMBER_ARRAY(grpColIdx, node->numCols);
+ WRITE_OID_ARRAY(grpOperators, node->numCols);
+ WRITE_OID_ARRAY(grpCollations, node->numCols);
+ WRITE_LONG_FIELD(numGroups);
+ WRITE_UINT64_FIELD(transitionSpace);
+ WRITE_BITMAPSET_FIELD(aggParams);
+ WRITE_NODE_FIELD(groupingSets);
+ WRITE_NODE_FIELD(chain);
+}
+
+static void
+_outWindowAgg(StringInfo str, const WindowAgg *node)
+{
+ WRITE_NODE_TYPE("WINDOWAGG");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_UINT_FIELD(winref);
+ WRITE_INT_FIELD(partNumCols);
+ WRITE_ATTRNUMBER_ARRAY(partColIdx, node->partNumCols);
+ WRITE_OID_ARRAY(partOperators, node->partNumCols);
+ WRITE_OID_ARRAY(partCollations, node->partNumCols);
+ WRITE_INT_FIELD(ordNumCols);
+ WRITE_ATTRNUMBER_ARRAY(ordColIdx, node->ordNumCols);
+ WRITE_OID_ARRAY(ordOperators, node->ordNumCols);
+ WRITE_OID_ARRAY(ordCollations, node->ordNumCols);
+ WRITE_INT_FIELD(frameOptions);
+ WRITE_NODE_FIELD(startOffset);
+ WRITE_NODE_FIELD(endOffset);
+ WRITE_NODE_FIELD(runCondition);
+ WRITE_NODE_FIELD(runConditionOrig);
+ WRITE_OID_FIELD(startInRangeFunc);
+ WRITE_OID_FIELD(endInRangeFunc);
+ WRITE_OID_FIELD(inRangeColl);
+ WRITE_BOOL_FIELD(inRangeAsc);
+ WRITE_BOOL_FIELD(inRangeNullsFirst);
+ WRITE_BOOL_FIELD(topWindow);
+}
+
+static void
+_outGroup(StringInfo str, const Group *node)
+{
+ WRITE_NODE_TYPE("GROUP");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_INT_FIELD(numCols);
+ WRITE_ATTRNUMBER_ARRAY(grpColIdx, node->numCols);
+ WRITE_OID_ARRAY(grpOperators, node->numCols);
+ WRITE_OID_ARRAY(grpCollations, node->numCols);
+}
+
+static void
+_outMaterial(StringInfo str, const Material *node)
+{
+ WRITE_NODE_TYPE("MATERIAL");
+
+ _outPlanInfo(str, (const Plan *) node);
+}
+
+static void
+_outMemoize(StringInfo str, const Memoize *node)
+{
+ WRITE_NODE_TYPE("MEMOIZE");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_INT_FIELD(numKeys);
+ WRITE_OID_ARRAY(hashOperators, node->numKeys);
+ WRITE_OID_ARRAY(collations, node->numKeys);
+ WRITE_NODE_FIELD(param_exprs);
+ WRITE_BOOL_FIELD(singlerow);
+ WRITE_BOOL_FIELD(binary_mode);
+ WRITE_UINT_FIELD(est_entries);
+ WRITE_BITMAPSET_FIELD(keyparamids);
+}
+
+static void
+_outSortInfo(StringInfo str, const Sort *node)
+{
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_INT_FIELD(numCols);
+ WRITE_ATTRNUMBER_ARRAY(sortColIdx, node->numCols);
+ WRITE_OID_ARRAY(sortOperators, node->numCols);
+ WRITE_OID_ARRAY(collations, node->numCols);
+ WRITE_BOOL_ARRAY(nullsFirst, node->numCols);
+}
+
+static void
+_outSort(StringInfo str, const Sort *node)
+{
+ WRITE_NODE_TYPE("SORT");
+
+ _outSortInfo(str, node);
+}
+
+static void
+_outIncrementalSort(StringInfo str, const IncrementalSort *node)
+{
+ WRITE_NODE_TYPE("INCREMENTALSORT");
+
+ _outSortInfo(str, (const Sort *) node);
+
+ WRITE_INT_FIELD(nPresortedCols);
+}
+
+static void
+_outUnique(StringInfo str, const Unique *node)
+{
+ WRITE_NODE_TYPE("UNIQUE");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_INT_FIELD(numCols);
+ WRITE_ATTRNUMBER_ARRAY(uniqColIdx, node->numCols);
+ WRITE_OID_ARRAY(uniqOperators, node->numCols);
+ WRITE_OID_ARRAY(uniqCollations, node->numCols);
+}
+
+static void
+_outHash(StringInfo str, const Hash *node)
+{
+ WRITE_NODE_TYPE("HASH");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_NODE_FIELD(hashkeys);
+ WRITE_OID_FIELD(skewTable);
+ WRITE_INT_FIELD(skewColumn);
+ WRITE_BOOL_FIELD(skewInherit);
+ WRITE_FLOAT_FIELD(rows_total, "%.0f");
+}
+
+static void
+_outSetOp(StringInfo str, const SetOp *node)
+{
+ WRITE_NODE_TYPE("SETOP");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_ENUM_FIELD(cmd, SetOpCmd);
+ WRITE_ENUM_FIELD(strategy, SetOpStrategy);
+ WRITE_INT_FIELD(numCols);
+ WRITE_ATTRNUMBER_ARRAY(dupColIdx, node->numCols);
+ WRITE_OID_ARRAY(dupOperators, node->numCols);
+ WRITE_OID_ARRAY(dupCollations, node->numCols);
+ WRITE_INT_FIELD(flagColIdx);
+ WRITE_INT_FIELD(firstFlag);
+ WRITE_LONG_FIELD(numGroups);
+}
+
+static void
+_outLockRows(StringInfo str, const LockRows *node)
+{
+ WRITE_NODE_TYPE("LOCKROWS");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_NODE_FIELD(rowMarks);
+ WRITE_INT_FIELD(epqParam);
+}
+
+static void
+_outLimit(StringInfo str, const Limit *node)
+{
+ WRITE_NODE_TYPE("LIMIT");
+
+ _outPlanInfo(str, (const Plan *) node);
+
+ WRITE_NODE_FIELD(limitOffset);
+ WRITE_NODE_FIELD(limitCount);
+ WRITE_ENUM_FIELD(limitOption, LimitOption);
+ WRITE_INT_FIELD(uniqNumCols);
+ WRITE_ATTRNUMBER_ARRAY(uniqColIdx, node->uniqNumCols);
+ WRITE_OID_ARRAY(uniqOperators, node->uniqNumCols);
+ WRITE_OID_ARRAY(uniqCollations, node->uniqNumCols);
+}
+
+static void
+_outNestLoopParam(StringInfo str, const NestLoopParam *node)
+{
+ WRITE_NODE_TYPE("NESTLOOPPARAM");
+
+ WRITE_INT_FIELD(paramno);
+ WRITE_NODE_FIELD(paramval);
+}
+
+static void
+_outPlanRowMark(StringInfo str, const PlanRowMark *node)
+{
+ WRITE_NODE_TYPE("PLANROWMARK");
+
+ WRITE_UINT_FIELD(rti);
+ WRITE_UINT_FIELD(prti);
+ WRITE_UINT_FIELD(rowmarkId);
+ WRITE_ENUM_FIELD(markType, RowMarkType);
+ WRITE_INT_FIELD(allMarkTypes);
+ WRITE_ENUM_FIELD(strength, LockClauseStrength);
+ WRITE_ENUM_FIELD(waitPolicy, LockWaitPolicy);
+ WRITE_BOOL_FIELD(isParent);
+}
+
+static void
+_outPartitionPruneInfo(StringInfo str, const PartitionPruneInfo *node)
+{
+ WRITE_NODE_TYPE("PARTITIONPRUNEINFO");
+
+ WRITE_NODE_FIELD(prune_infos);
+ WRITE_BITMAPSET_FIELD(other_subplans);
+}
+
+static void
+_outPartitionedRelPruneInfo(StringInfo str, const PartitionedRelPruneInfo *node)
+{
+ WRITE_NODE_TYPE("PARTITIONEDRELPRUNEINFO");
+
+ WRITE_UINT_FIELD(rtindex);
+ WRITE_BITMAPSET_FIELD(present_parts);
+ WRITE_INT_FIELD(nparts);
+ WRITE_INT_ARRAY(subplan_map, node->nparts);
+ WRITE_INT_ARRAY(subpart_map, node->nparts);
+ WRITE_OID_ARRAY(relid_map, node->nparts);
+ WRITE_NODE_FIELD(initial_pruning_steps);
+ WRITE_NODE_FIELD(exec_pruning_steps);
+ WRITE_BITMAPSET_FIELD(execparamids);
+}
+
+static void
+_outPartitionPruneStepOp(StringInfo str, const PartitionPruneStepOp *node)
+{
+ WRITE_NODE_TYPE("PARTITIONPRUNESTEPOP");
+
+ WRITE_INT_FIELD(step.step_id);
+ WRITE_INT_FIELD(opstrategy);
+ WRITE_NODE_FIELD(exprs);
+ WRITE_NODE_FIELD(cmpfns);
+ WRITE_BITMAPSET_FIELD(nullkeys);
+}
+
+static void
+_outPartitionPruneStepCombine(StringInfo str, const PartitionPruneStepCombine *node)
+{
+ WRITE_NODE_TYPE("PARTITIONPRUNESTEPCOMBINE");
+
+ WRITE_INT_FIELD(step.step_id);
+ WRITE_ENUM_FIELD(combineOp, PartitionPruneCombineOp);
+ WRITE_NODE_FIELD(source_stepids);
+}
+
+static void
+_outPlanInvalItem(StringInfo str, const PlanInvalItem *node)
+{
+ WRITE_NODE_TYPE("PLANINVALITEM");
+
+ WRITE_INT_FIELD(cacheId);
+ WRITE_UINT_FIELD(hashValue);
+}
+
+/*****************************************************************************
+ *
+ * Stuff from primnodes.h.
+ *
+ *****************************************************************************/
+
+static void
+_outAlias(StringInfo str, const Alias *node)
+{
+ WRITE_NODE_TYPE("ALIAS");
+
+ WRITE_STRING_FIELD(aliasname);
+ WRITE_NODE_FIELD(colnames);
+}
+
+static void
+_outRangeVar(StringInfo str, const RangeVar *node)
+{
+ WRITE_NODE_TYPE("RANGEVAR");
+
+ /*
+ * we deliberately ignore catalogname here, since it is presently not
+ * semantically meaningful
+ */
+ WRITE_STRING_FIELD(schemaname);
+ WRITE_STRING_FIELD(relname);
+ WRITE_BOOL_FIELD(inh);
+ WRITE_CHAR_FIELD(relpersistence);
+ WRITE_NODE_FIELD(alias);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outTableFunc(StringInfo str, const TableFunc *node)
+{
+ WRITE_NODE_TYPE("TABLEFUNC");
+
+ WRITE_NODE_FIELD(ns_uris);
+ WRITE_NODE_FIELD(ns_names);
+ WRITE_NODE_FIELD(docexpr);
+ WRITE_NODE_FIELD(rowexpr);
+ WRITE_NODE_FIELD(colnames);
+ WRITE_NODE_FIELD(coltypes);
+ WRITE_NODE_FIELD(coltypmods);
+ WRITE_NODE_FIELD(colcollations);
+ WRITE_NODE_FIELD(colexprs);
+ WRITE_NODE_FIELD(coldefexprs);
+ WRITE_BITMAPSET_FIELD(notnulls);
+ WRITE_INT_FIELD(ordinalitycol);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outIntoClause(StringInfo str, const IntoClause *node)
+{
+ WRITE_NODE_TYPE("INTOCLAUSE");
+
+ WRITE_NODE_FIELD(rel);
+ WRITE_NODE_FIELD(colNames);
+ WRITE_STRING_FIELD(accessMethod);
+ WRITE_NODE_FIELD(options);
+ WRITE_ENUM_FIELD(onCommit, OnCommitAction);
+ WRITE_STRING_FIELD(tableSpaceName);
+ WRITE_NODE_FIELD(viewQuery);
+ WRITE_BOOL_FIELD(skipData);
+}
+
+static void
+_outVar(StringInfo str, const Var *node)
+{
+ WRITE_NODE_TYPE("VAR");
+
+ WRITE_INT_FIELD(varno);
+ WRITE_INT_FIELD(varattno);
+ WRITE_OID_FIELD(vartype);
+ WRITE_INT_FIELD(vartypmod);
+ WRITE_OID_FIELD(varcollid);
+ WRITE_UINT_FIELD(varlevelsup);
+ WRITE_UINT_FIELD(varnosyn);
+ WRITE_INT_FIELD(varattnosyn);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outConst(StringInfo str, const Const *node)
+{
+ WRITE_NODE_TYPE("CONST");
+
+ WRITE_OID_FIELD(consttype);
+ WRITE_INT_FIELD(consttypmod);
+ WRITE_OID_FIELD(constcollid);
+ WRITE_INT_FIELD(constlen);
+ WRITE_BOOL_FIELD(constbyval);
+ WRITE_BOOL_FIELD(constisnull);
+ WRITE_LOCATION_FIELD(location);
+
+ appendStringInfoString(str, " :constvalue ");
+ if (node->constisnull)
+ appendStringInfoString(str, "<>");
+ else
+ outDatum(str, node->constvalue, node->constlen, node->constbyval);
+}
+
+static void
+_outParam(StringInfo str, const Param *node)
+{
+ WRITE_NODE_TYPE("PARAM");
+
+ WRITE_ENUM_FIELD(paramkind, ParamKind);
+ WRITE_INT_FIELD(paramid);
+ WRITE_OID_FIELD(paramtype);
+ WRITE_INT_FIELD(paramtypmod);
+ WRITE_OID_FIELD(paramcollid);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outAggref(StringInfo str, const Aggref *node)
+{
+ WRITE_NODE_TYPE("AGGREF");
+
+ WRITE_OID_FIELD(aggfnoid);
+ WRITE_OID_FIELD(aggtype);
+ WRITE_OID_FIELD(aggcollid);
+ WRITE_OID_FIELD(inputcollid);
+ WRITE_OID_FIELD(aggtranstype);
+ WRITE_NODE_FIELD(aggargtypes);
+ WRITE_NODE_FIELD(aggdirectargs);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(aggorder);
+ WRITE_NODE_FIELD(aggdistinct);
+ WRITE_NODE_FIELD(aggfilter);
+ WRITE_BOOL_FIELD(aggstar);
+ WRITE_BOOL_FIELD(aggvariadic);
+ WRITE_CHAR_FIELD(aggkind);
+ WRITE_UINT_FIELD(agglevelsup);
+ WRITE_ENUM_FIELD(aggsplit, AggSplit);
+ WRITE_INT_FIELD(aggno);
+ WRITE_INT_FIELD(aggtransno);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outGroupingFunc(StringInfo str, const GroupingFunc *node)
+{
+ WRITE_NODE_TYPE("GROUPINGFUNC");
+
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(refs);
+ WRITE_NODE_FIELD(cols);
+ WRITE_UINT_FIELD(agglevelsup);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outWindowFunc(StringInfo str, const WindowFunc *node)
+{
+ WRITE_NODE_TYPE("WINDOWFUNC");
+
+ WRITE_OID_FIELD(winfnoid);
+ WRITE_OID_FIELD(wintype);
+ WRITE_OID_FIELD(wincollid);
+ WRITE_OID_FIELD(inputcollid);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(aggfilter);
+ WRITE_UINT_FIELD(winref);
+ WRITE_BOOL_FIELD(winstar);
+ WRITE_BOOL_FIELD(winagg);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outSubscriptingRef(StringInfo str, const SubscriptingRef *node)
+{
+ WRITE_NODE_TYPE("SUBSCRIPTINGREF");
+
+ WRITE_OID_FIELD(refcontainertype);
+ WRITE_OID_FIELD(refelemtype);
+ WRITE_OID_FIELD(refrestype);
+ WRITE_INT_FIELD(reftypmod);
+ WRITE_OID_FIELD(refcollid);
+ WRITE_NODE_FIELD(refupperindexpr);
+ WRITE_NODE_FIELD(reflowerindexpr);
+ WRITE_NODE_FIELD(refexpr);
+ WRITE_NODE_FIELD(refassgnexpr);
+}
+
+static void
+_outFuncExpr(StringInfo str, const FuncExpr *node)
+{
+ WRITE_NODE_TYPE("FUNCEXPR");
+
+ WRITE_OID_FIELD(funcid);
+ WRITE_OID_FIELD(funcresulttype);
+ WRITE_BOOL_FIELD(funcretset);
+ WRITE_BOOL_FIELD(funcvariadic);
+ WRITE_ENUM_FIELD(funcformat, CoercionForm);
+ WRITE_OID_FIELD(funccollid);
+ WRITE_OID_FIELD(inputcollid);
+ WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outNamedArgExpr(StringInfo str, const NamedArgExpr *node)
+{
+ WRITE_NODE_TYPE("NAMEDARGEXPR");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_STRING_FIELD(name);
+ WRITE_INT_FIELD(argnumber);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outOpExpr(StringInfo str, const OpExpr *node)
+{
+ WRITE_NODE_TYPE("OPEXPR");
+
+ WRITE_OID_FIELD(opno);
+ WRITE_OID_FIELD(opfuncid);
+ WRITE_OID_FIELD(opresulttype);
+ WRITE_BOOL_FIELD(opretset);
+ WRITE_OID_FIELD(opcollid);
+ WRITE_OID_FIELD(inputcollid);
+ WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outDistinctExpr(StringInfo str, const DistinctExpr *node)
+{
+ WRITE_NODE_TYPE("DISTINCTEXPR");
+
+ WRITE_OID_FIELD(opno);
+ WRITE_OID_FIELD(opfuncid);
+ WRITE_OID_FIELD(opresulttype);
+ WRITE_BOOL_FIELD(opretset);
+ WRITE_OID_FIELD(opcollid);
+ WRITE_OID_FIELD(inputcollid);
+ WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outNullIfExpr(StringInfo str, const NullIfExpr *node)
+{
+ WRITE_NODE_TYPE("NULLIFEXPR");
+
+ WRITE_OID_FIELD(opno);
+ WRITE_OID_FIELD(opfuncid);
+ WRITE_OID_FIELD(opresulttype);
+ WRITE_BOOL_FIELD(opretset);
+ WRITE_OID_FIELD(opcollid);
+ WRITE_OID_FIELD(inputcollid);
+ WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outScalarArrayOpExpr(StringInfo str, const ScalarArrayOpExpr *node)
+{
+ WRITE_NODE_TYPE("SCALARARRAYOPEXPR");
+
+ WRITE_OID_FIELD(opno);
+ WRITE_OID_FIELD(opfuncid);
+ WRITE_OID_FIELD(hashfuncid);
+ WRITE_OID_FIELD(negfuncid);
+ WRITE_BOOL_FIELD(useOr);
+ WRITE_OID_FIELD(inputcollid);
+ WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outBoolExpr(StringInfo str, const BoolExpr *node)
+{
+ char *opstr = NULL;
+
+ WRITE_NODE_TYPE("BOOLEXPR");
+
+ /* do-it-yourself enum representation */
+ switch (node->boolop)
+ {
+ case AND_EXPR:
+ opstr = "and";
+ break;
+ case OR_EXPR:
+ opstr = "or";
+ break;
+ case NOT_EXPR:
+ opstr = "not";
+ break;
+ }
+ appendStringInfoString(str, " :boolop ");
+ outToken(str, opstr);
+
+ WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outSubLink(StringInfo str, const SubLink *node)
+{
+ WRITE_NODE_TYPE("SUBLINK");
+
+ WRITE_ENUM_FIELD(subLinkType, SubLinkType);
+ WRITE_INT_FIELD(subLinkId);
+ WRITE_NODE_FIELD(testexpr);
+ WRITE_NODE_FIELD(operName);
+ WRITE_NODE_FIELD(subselect);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outSubPlan(StringInfo str, const SubPlan *node)
+{
+ WRITE_NODE_TYPE("SUBPLAN");
+
+ WRITE_ENUM_FIELD(subLinkType, SubLinkType);
+ WRITE_NODE_FIELD(testexpr);
+ WRITE_NODE_FIELD(paramIds);
+ WRITE_INT_FIELD(plan_id);
+ WRITE_STRING_FIELD(plan_name);
+ WRITE_OID_FIELD(firstColType);
+ WRITE_INT_FIELD(firstColTypmod);
+ WRITE_OID_FIELD(firstColCollation);
+ WRITE_BOOL_FIELD(useHashTable);
+ WRITE_BOOL_FIELD(unknownEqFalse);
+ WRITE_BOOL_FIELD(parallel_safe);
+ WRITE_NODE_FIELD(setParam);
+ WRITE_NODE_FIELD(parParam);
+ WRITE_NODE_FIELD(args);
+ WRITE_FLOAT_FIELD(startup_cost, "%.2f");
+ WRITE_FLOAT_FIELD(per_call_cost, "%.2f");
+}
+
+static void
+_outAlternativeSubPlan(StringInfo str, const AlternativeSubPlan *node)
+{
+ WRITE_NODE_TYPE("ALTERNATIVESUBPLAN");
+
+ WRITE_NODE_FIELD(subplans);
+}
+
+static void
+_outFieldSelect(StringInfo str, const FieldSelect *node)
+{
+ WRITE_NODE_TYPE("FIELDSELECT");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_INT_FIELD(fieldnum);
+ WRITE_OID_FIELD(resulttype);
+ WRITE_INT_FIELD(resulttypmod);
+ WRITE_OID_FIELD(resultcollid);
+}
+
+static void
+_outFieldStore(StringInfo str, const FieldStore *node)
+{
+ WRITE_NODE_TYPE("FIELDSTORE");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_NODE_FIELD(newvals);
+ WRITE_NODE_FIELD(fieldnums);
+ WRITE_OID_FIELD(resulttype);
+}
+
+static void
+_outRelabelType(StringInfo str, const RelabelType *node)
+{
+ WRITE_NODE_TYPE("RELABELTYPE");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_OID_FIELD(resulttype);
+ WRITE_INT_FIELD(resulttypmod);
+ WRITE_OID_FIELD(resultcollid);
+ WRITE_ENUM_FIELD(relabelformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCoerceViaIO(StringInfo str, const CoerceViaIO *node)
+{
+ WRITE_NODE_TYPE("COERCEVIAIO");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_OID_FIELD(resulttype);
+ WRITE_OID_FIELD(resultcollid);
+ WRITE_ENUM_FIELD(coerceformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outArrayCoerceExpr(StringInfo str, const ArrayCoerceExpr *node)
+{
+ WRITE_NODE_TYPE("ARRAYCOERCEEXPR");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_NODE_FIELD(elemexpr);
+ WRITE_OID_FIELD(resulttype);
+ WRITE_INT_FIELD(resulttypmod);
+ WRITE_OID_FIELD(resultcollid);
+ WRITE_ENUM_FIELD(coerceformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outConvertRowtypeExpr(StringInfo str, const ConvertRowtypeExpr *node)
+{
+ WRITE_NODE_TYPE("CONVERTROWTYPEEXPR");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_OID_FIELD(resulttype);
+ WRITE_ENUM_FIELD(convertformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCollateExpr(StringInfo str, const CollateExpr *node)
+{
+ WRITE_NODE_TYPE("COLLATEEXPR");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_OID_FIELD(collOid);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCaseExpr(StringInfo str, const CaseExpr *node)
+{
+ WRITE_NODE_TYPE("CASEEXPR");
+
+ WRITE_OID_FIELD(casetype);
+ WRITE_OID_FIELD(casecollid);
+ WRITE_NODE_FIELD(arg);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(defresult);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCaseWhen(StringInfo str, const CaseWhen *node)
+{
+ WRITE_NODE_TYPE("CASEWHEN");
+
+ WRITE_NODE_FIELD(expr);
+ WRITE_NODE_FIELD(result);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCaseTestExpr(StringInfo str, const CaseTestExpr *node)
+{
+ WRITE_NODE_TYPE("CASETESTEXPR");
+
+ WRITE_OID_FIELD(typeId);
+ WRITE_INT_FIELD(typeMod);
+ WRITE_OID_FIELD(collation);
+}
+
+static void
+_outArrayExpr(StringInfo str, const ArrayExpr *node)
+{
+ WRITE_NODE_TYPE("ARRAYEXPR");
+
+ WRITE_OID_FIELD(array_typeid);
+ WRITE_OID_FIELD(array_collid);
+ WRITE_OID_FIELD(element_typeid);
+ WRITE_NODE_FIELD(elements);
+ WRITE_BOOL_FIELD(multidims);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outRowExpr(StringInfo str, const RowExpr *node)
+{
+ WRITE_NODE_TYPE("ROWEXPR");
+
+ WRITE_NODE_FIELD(args);
+ WRITE_OID_FIELD(row_typeid);
+ WRITE_ENUM_FIELD(row_format, CoercionForm);
+ WRITE_NODE_FIELD(colnames);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outRowCompareExpr(StringInfo str, const RowCompareExpr *node)
+{
+ WRITE_NODE_TYPE("ROWCOMPAREEXPR");
+
+ WRITE_ENUM_FIELD(rctype, RowCompareType);
+ WRITE_NODE_FIELD(opnos);
+ WRITE_NODE_FIELD(opfamilies);
+ WRITE_NODE_FIELD(inputcollids);
+ WRITE_NODE_FIELD(largs);
+ WRITE_NODE_FIELD(rargs);
+}
+
+static void
+_outCoalesceExpr(StringInfo str, const CoalesceExpr *node)
+{
+ WRITE_NODE_TYPE("COALESCEEXPR");
+
+ WRITE_OID_FIELD(coalescetype);
+ WRITE_OID_FIELD(coalescecollid);
+ WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outMinMaxExpr(StringInfo str, const MinMaxExpr *node)
+{
+ WRITE_NODE_TYPE("MINMAXEXPR");
+
+ WRITE_OID_FIELD(minmaxtype);
+ WRITE_OID_FIELD(minmaxcollid);
+ WRITE_OID_FIELD(inputcollid);
+ WRITE_ENUM_FIELD(op, MinMaxOp);
+ WRITE_NODE_FIELD(args);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outSQLValueFunction(StringInfo str, const SQLValueFunction *node)
+{
+ WRITE_NODE_TYPE("SQLVALUEFUNCTION");
+
+ WRITE_ENUM_FIELD(op, SQLValueFunctionOp);
+ WRITE_OID_FIELD(type);
+ WRITE_INT_FIELD(typmod);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outXmlExpr(StringInfo str, const XmlExpr *node)
+{
+ WRITE_NODE_TYPE("XMLEXPR");
+
+ WRITE_ENUM_FIELD(op, XmlExprOp);
+ WRITE_STRING_FIELD(name);
+ WRITE_NODE_FIELD(named_args);
+ WRITE_NODE_FIELD(arg_names);
+ WRITE_NODE_FIELD(args);
+ WRITE_ENUM_FIELD(xmloption, XmlOptionType);
+ WRITE_OID_FIELD(type);
+ WRITE_INT_FIELD(typmod);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outNullTest(StringInfo str, const NullTest *node)
+{
+ WRITE_NODE_TYPE("NULLTEST");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_ENUM_FIELD(nulltesttype, NullTestType);
+ WRITE_BOOL_FIELD(argisrow);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outBooleanTest(StringInfo str, const BooleanTest *node)
+{
+ WRITE_NODE_TYPE("BOOLEANTEST");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_ENUM_FIELD(booltesttype, BoolTestType);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCoerceToDomain(StringInfo str, const CoerceToDomain *node)
+{
+ WRITE_NODE_TYPE("COERCETODOMAIN");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_OID_FIELD(resulttype);
+ WRITE_INT_FIELD(resulttypmod);
+ WRITE_OID_FIELD(resultcollid);
+ WRITE_ENUM_FIELD(coercionformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCoerceToDomainValue(StringInfo str, const CoerceToDomainValue *node)
+{
+ WRITE_NODE_TYPE("COERCETODOMAINVALUE");
+
+ WRITE_OID_FIELD(typeId);
+ WRITE_INT_FIELD(typeMod);
+ WRITE_OID_FIELD(collation);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outSetToDefault(StringInfo str, const SetToDefault *node)
+{
+ WRITE_NODE_TYPE("SETTODEFAULT");
+
+ WRITE_OID_FIELD(typeId);
+ WRITE_INT_FIELD(typeMod);
+ WRITE_OID_FIELD(collation);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCurrentOfExpr(StringInfo str, const CurrentOfExpr *node)
+{
+ WRITE_NODE_TYPE("CURRENTOFEXPR");
+
+ WRITE_UINT_FIELD(cvarno);
+ WRITE_STRING_FIELD(cursor_name);
+ WRITE_INT_FIELD(cursor_param);
+}
+
+static void
+_outNextValueExpr(StringInfo str, const NextValueExpr *node)
+{
+ WRITE_NODE_TYPE("NEXTVALUEEXPR");
+
+ WRITE_OID_FIELD(seqid);
+ WRITE_OID_FIELD(typeId);
+}
+
+static void
+_outInferenceElem(StringInfo str, const InferenceElem *node)
+{
+ WRITE_NODE_TYPE("INFERENCEELEM");
+
+ WRITE_NODE_FIELD(expr);
+ WRITE_OID_FIELD(infercollid);
+ WRITE_OID_FIELD(inferopclass);
+}
+
+static void
+_outTargetEntry(StringInfo str, const TargetEntry *node)
+{
+ WRITE_NODE_TYPE("TARGETENTRY");
+
+ WRITE_NODE_FIELD(expr);
+ WRITE_INT_FIELD(resno);
+ WRITE_STRING_FIELD(resname);
+ WRITE_UINT_FIELD(ressortgroupref);
+ WRITE_OID_FIELD(resorigtbl);
+ WRITE_INT_FIELD(resorigcol);
+ WRITE_BOOL_FIELD(resjunk);
+}
+
+static void
+_outRangeTblRef(StringInfo str, const RangeTblRef *node)
+{
+ WRITE_NODE_TYPE("RANGETBLREF");
+
+ WRITE_INT_FIELD(rtindex);
+}
+
+static void
+_outJoinExpr(StringInfo str, const JoinExpr *node)
+{
+ WRITE_NODE_TYPE("JOINEXPR");
+
+ WRITE_ENUM_FIELD(jointype, JoinType);
+ WRITE_BOOL_FIELD(isNatural);
+ WRITE_NODE_FIELD(larg);
+ WRITE_NODE_FIELD(rarg);
+ WRITE_NODE_FIELD(usingClause);
+ WRITE_NODE_FIELD(join_using_alias);
+ WRITE_NODE_FIELD(quals);
+ WRITE_NODE_FIELD(alias);
+ WRITE_INT_FIELD(rtindex);
+}
+
+static void
+_outFromExpr(StringInfo str, const FromExpr *node)
+{
+ WRITE_NODE_TYPE("FROMEXPR");
+
+ WRITE_NODE_FIELD(fromlist);
+ WRITE_NODE_FIELD(quals);
+}
+
+static void
+_outOnConflictExpr(StringInfo str, const OnConflictExpr *node)
+{
+ WRITE_NODE_TYPE("ONCONFLICTEXPR");
+
+ WRITE_ENUM_FIELD(action, OnConflictAction);
+ WRITE_NODE_FIELD(arbiterElems);
+ WRITE_NODE_FIELD(arbiterWhere);
+ WRITE_OID_FIELD(constraint);
+ WRITE_NODE_FIELD(onConflictSet);
+ WRITE_NODE_FIELD(onConflictWhere);
+ WRITE_INT_FIELD(exclRelIndex);
+ WRITE_NODE_FIELD(exclRelTlist);
+}
+
+/*****************************************************************************
+ *
+ * Stuff from pathnodes.h.
+ *
+ *****************************************************************************/
+
+/*
+ * print the basic stuff of all nodes that inherit from Path
+ *
+ * Note we do NOT print the parent, else we'd be in infinite recursion.
+ * We can print the parent's relids for identification purposes, though.
+ * We print the pathtarget only if it's not the default one for the rel.
+ * We also do not print the whole of param_info, since it's printed by
+ * _outRelOptInfo; it's sufficient and less cluttering to print just the
+ * required outer relids.
+ */
+static void
+_outPathInfo(StringInfo str, const Path *node)
+{
+ WRITE_ENUM_FIELD(pathtype, NodeTag);
+ appendStringInfoString(str, " :parent_relids ");
+ outBitmapset(str, node->parent->relids);
+ if (node->pathtarget != node->parent->reltarget)
+ WRITE_NODE_FIELD(pathtarget);
+ appendStringInfoString(str, " :required_outer ");
+ if (node->param_info)
+ outBitmapset(str, node->param_info->ppi_req_outer);
+ else
+ outBitmapset(str, NULL);
+ WRITE_BOOL_FIELD(parallel_aware);
+ WRITE_BOOL_FIELD(parallel_safe);
+ WRITE_INT_FIELD(parallel_workers);
+ WRITE_FLOAT_FIELD(rows, "%.0f");
+ WRITE_FLOAT_FIELD(startup_cost, "%.2f");
+ WRITE_FLOAT_FIELD(total_cost, "%.2f");
+ WRITE_NODE_FIELD(pathkeys);
+}
+
+/*
+ * print the basic stuff of all nodes that inherit from JoinPath
+ */
+static void
+_outJoinPathInfo(StringInfo str, const JoinPath *node)
+{
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_ENUM_FIELD(jointype, JoinType);
+ WRITE_BOOL_FIELD(inner_unique);
+ WRITE_NODE_FIELD(outerjoinpath);
+ WRITE_NODE_FIELD(innerjoinpath);
+ WRITE_NODE_FIELD(joinrestrictinfo);
+}
+
+static void
+_outPath(StringInfo str, const Path *node)
+{
+ WRITE_NODE_TYPE("PATH");
+
+ _outPathInfo(str, (const Path *) node);
+}
+
+static void
+_outIndexPath(StringInfo str, const IndexPath *node)
+{
+ WRITE_NODE_TYPE("INDEXPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(indexinfo);
+ WRITE_NODE_FIELD(indexclauses);
+ WRITE_NODE_FIELD(indexorderbys);
+ WRITE_NODE_FIELD(indexorderbycols);
+ WRITE_ENUM_FIELD(indexscandir, ScanDirection);
+ WRITE_FLOAT_FIELD(indextotalcost, "%.2f");
+ WRITE_FLOAT_FIELD(indexselectivity, "%.4f");
+}
+
+static void
+_outBitmapHeapPath(StringInfo str, const BitmapHeapPath *node)
+{
+ WRITE_NODE_TYPE("BITMAPHEAPPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(bitmapqual);
+}
+
+static void
+_outBitmapAndPath(StringInfo str, const BitmapAndPath *node)
+{
+ WRITE_NODE_TYPE("BITMAPANDPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(bitmapquals);
+ WRITE_FLOAT_FIELD(bitmapselectivity, "%.4f");
+}
+
+static void
+_outBitmapOrPath(StringInfo str, const BitmapOrPath *node)
+{
+ WRITE_NODE_TYPE("BITMAPORPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(bitmapquals);
+ WRITE_FLOAT_FIELD(bitmapselectivity, "%.4f");
+}
+
+static void
+_outTidPath(StringInfo str, const TidPath *node)
+{
+ WRITE_NODE_TYPE("TIDPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(tidquals);
+}
+
+static void
+_outTidRangePath(StringInfo str, const TidRangePath *node)
+{
+ WRITE_NODE_TYPE("TIDRANGEPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(tidrangequals);
+}
+
+static void
+_outSubqueryScanPath(StringInfo str, const SubqueryScanPath *node)
+{
+ WRITE_NODE_TYPE("SUBQUERYSCANPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+}
+
+static void
+_outForeignPath(StringInfo str, const ForeignPath *node)
+{
+ WRITE_NODE_TYPE("FOREIGNPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(fdw_outerpath);
+ WRITE_NODE_FIELD(fdw_private);
+}
+
+static void
+_outCustomPath(StringInfo str, const CustomPath *node)
+{
+ WRITE_NODE_TYPE("CUSTOMPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_UINT_FIELD(flags);
+ WRITE_NODE_FIELD(custom_paths);
+ WRITE_NODE_FIELD(custom_private);
+ appendStringInfoString(str, " :methods ");
+ outToken(str, node->methods->CustomName);
+}
+
+static void
+_outAppendPath(StringInfo str, const AppendPath *node)
+{
+ WRITE_NODE_TYPE("APPENDPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpaths);
+ WRITE_INT_FIELD(first_partial_path);
+ WRITE_FLOAT_FIELD(limit_tuples, "%.0f");
+}
+
+static void
+_outMergeAppendPath(StringInfo str, const MergeAppendPath *node)
+{
+ WRITE_NODE_TYPE("MERGEAPPENDPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpaths);
+ WRITE_FLOAT_FIELD(limit_tuples, "%.0f");
+}
+
+static void
+_outGroupResultPath(StringInfo str, const GroupResultPath *node)
+{
+ WRITE_NODE_TYPE("GROUPRESULTPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(quals);
+}
+
+static void
+_outMaterialPath(StringInfo str, const MaterialPath *node)
+{
+ WRITE_NODE_TYPE("MATERIALPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+}
+
+static void
+_outMemoizePath(StringInfo str, const MemoizePath *node)
+{
+ WRITE_NODE_TYPE("MEMOIZEPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_NODE_FIELD(hash_operators);
+ WRITE_NODE_FIELD(param_exprs);
+ WRITE_BOOL_FIELD(singlerow);
+ WRITE_BOOL_FIELD(binary_mode);
+ WRITE_FLOAT_FIELD(calls, "%.0f");
+ WRITE_UINT_FIELD(est_entries);
+}
+
+static void
+_outUniquePath(StringInfo str, const UniquePath *node)
+{
+ WRITE_NODE_TYPE("UNIQUEPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_ENUM_FIELD(umethod, UniquePathMethod);
+ WRITE_NODE_FIELD(in_operators);
+ WRITE_NODE_FIELD(uniq_exprs);
+}
+
+static void
+_outGatherPath(StringInfo str, const GatherPath *node)
+{
+ WRITE_NODE_TYPE("GATHERPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_BOOL_FIELD(single_copy);
+ WRITE_INT_FIELD(num_workers);
+}
+
+static void
+_outProjectionPath(StringInfo str, const ProjectionPath *node)
+{
+ WRITE_NODE_TYPE("PROJECTIONPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_BOOL_FIELD(dummypp);
+}
+
+static void
+_outProjectSetPath(StringInfo str, const ProjectSetPath *node)
+{
+ WRITE_NODE_TYPE("PROJECTSETPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+}
+
+static void
+_outSortPathInfo(StringInfo str, const SortPath *node)
+{
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+}
+
+static void
+_outSortPath(StringInfo str, const SortPath *node)
+{
+ WRITE_NODE_TYPE("SORTPATH");
+
+ _outSortPathInfo(str, node);
+}
+
+static void
+_outIncrementalSortPath(StringInfo str, const IncrementalSortPath *node)
+{
+ WRITE_NODE_TYPE("INCREMENTALSORTPATH");
+
+ _outSortPathInfo(str, (const SortPath *) node);
+
+ WRITE_INT_FIELD(nPresortedCols);
+}
+
+static void
+_outGroupPath(StringInfo str, const GroupPath *node)
+{
+ WRITE_NODE_TYPE("GROUPPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_NODE_FIELD(groupClause);
+ WRITE_NODE_FIELD(qual);
+}
+
+static void
+_outUpperUniquePath(StringInfo str, const UpperUniquePath *node)
+{
+ WRITE_NODE_TYPE("UPPERUNIQUEPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_INT_FIELD(numkeys);
+}
+
+static void
+_outAggPath(StringInfo str, const AggPath *node)
+{
+ WRITE_NODE_TYPE("AGGPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
+ WRITE_ENUM_FIELD(aggsplit, AggSplit);
+ WRITE_FLOAT_FIELD(numGroups, "%.0f");
+ WRITE_UINT64_FIELD(transitionSpace);
+ WRITE_NODE_FIELD(groupClause);
+ WRITE_NODE_FIELD(qual);
+}
+
+static void
+_outRollupData(StringInfo str, const RollupData *node)
+{
+ WRITE_NODE_TYPE("ROLLUP");
+
+ WRITE_NODE_FIELD(groupClause);
+ WRITE_NODE_FIELD(gsets);
+ WRITE_NODE_FIELD(gsets_data);
+ WRITE_FLOAT_FIELD(numGroups, "%.0f");
+ WRITE_BOOL_FIELD(hashable);
+ WRITE_BOOL_FIELD(is_hashed);
+}
+
+static void
+_outGroupingSetData(StringInfo str, const GroupingSetData *node)
+{
+ WRITE_NODE_TYPE("GSDATA");
+
+ WRITE_NODE_FIELD(set);
+ WRITE_FLOAT_FIELD(numGroups, "%.0f");
+}
+
+static void
+_outGroupingSetsPath(StringInfo str, const GroupingSetsPath *node)
+{
+ WRITE_NODE_TYPE("GROUPINGSETSPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
+ WRITE_NODE_FIELD(rollups);
+ WRITE_NODE_FIELD(qual);
+ WRITE_UINT64_FIELD(transitionSpace);
+}
+
+static void
+_outMinMaxAggPath(StringInfo str, const MinMaxAggPath *node)
+{
+ WRITE_NODE_TYPE("MINMAXAGGPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(mmaggregates);
+ WRITE_NODE_FIELD(quals);
+}
+
+static void
+_outWindowAggPath(StringInfo str, const WindowAggPath *node)
+{
+ WRITE_NODE_TYPE("WINDOWAGGPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_NODE_FIELD(winclause);
+ WRITE_NODE_FIELD(qual);
+ WRITE_BOOL_FIELD(topwindow);
+}
+
+static void
+_outSetOpPath(StringInfo str, const SetOpPath *node)
+{
+ WRITE_NODE_TYPE("SETOPPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_ENUM_FIELD(cmd, SetOpCmd);
+ WRITE_ENUM_FIELD(strategy, SetOpStrategy);
+ WRITE_NODE_FIELD(distinctList);
+ WRITE_INT_FIELD(flagColIdx);
+ WRITE_INT_FIELD(firstFlag);
+ WRITE_FLOAT_FIELD(numGroups, "%.0f");
+}
+
+static void
+_outRecursiveUnionPath(StringInfo str, const RecursiveUnionPath *node)
+{
+ WRITE_NODE_TYPE("RECURSIVEUNIONPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(leftpath);
+ WRITE_NODE_FIELD(rightpath);
+ WRITE_NODE_FIELD(distinctList);
+ WRITE_INT_FIELD(wtParam);
+ WRITE_FLOAT_FIELD(numGroups, "%.0f");
+}
+
+static void
+_outLockRowsPath(StringInfo str, const LockRowsPath *node)
+{
+ WRITE_NODE_TYPE("LOCKROWSPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_NODE_FIELD(rowMarks);
+ WRITE_INT_FIELD(epqParam);
+}
+
+static void
+_outModifyTablePath(StringInfo str, const ModifyTablePath *node)
+{
+ WRITE_NODE_TYPE("MODIFYTABLEPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_ENUM_FIELD(operation, CmdType);
+ WRITE_BOOL_FIELD(canSetTag);
+ WRITE_UINT_FIELD(nominalRelation);
+ WRITE_UINT_FIELD(rootRelation);
+ WRITE_BOOL_FIELD(partColsUpdated);
+ WRITE_NODE_FIELD(resultRelations);
+ WRITE_NODE_FIELD(updateColnosLists);
+ WRITE_NODE_FIELD(withCheckOptionLists);
+ WRITE_NODE_FIELD(returningLists);
+ WRITE_NODE_FIELD(rowMarks);
+ WRITE_NODE_FIELD(onconflict);
+ WRITE_INT_FIELD(epqParam);
+ WRITE_NODE_FIELD(mergeActionLists);
+}
+
+static void
+_outLimitPath(StringInfo str, const LimitPath *node)
+{
+ WRITE_NODE_TYPE("LIMITPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_NODE_FIELD(limitOffset);
+ WRITE_NODE_FIELD(limitCount);
+ WRITE_ENUM_FIELD(limitOption, LimitOption);
+}
+
+static void
+_outGatherMergePath(StringInfo str, const GatherMergePath *node)
+{
+ WRITE_NODE_TYPE("GATHERMERGEPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_INT_FIELD(num_workers);
+}
+
+static void
+_outNestPath(StringInfo str, const NestPath *node)
+{
+ WRITE_NODE_TYPE("NESTPATH");
+
+ _outJoinPathInfo(str, (const JoinPath *) node);
+}
+
+static void
+_outMergePath(StringInfo str, const MergePath *node)
+{
+ WRITE_NODE_TYPE("MERGEPATH");
+
+ _outJoinPathInfo(str, (const JoinPath *) node);
+
+ WRITE_NODE_FIELD(path_mergeclauses);
+ WRITE_NODE_FIELD(outersortkeys);
+ WRITE_NODE_FIELD(innersortkeys);
+ WRITE_BOOL_FIELD(skip_mark_restore);
+ WRITE_BOOL_FIELD(materialize_inner);
+}
+
+static void
+_outHashPath(StringInfo str, const HashPath *node)
+{
+ WRITE_NODE_TYPE("HASHPATH");
+
+ _outJoinPathInfo(str, (const JoinPath *) node);
+
+ WRITE_NODE_FIELD(path_hashclauses);
+ WRITE_INT_FIELD(num_batches);
+ WRITE_FLOAT_FIELD(inner_rows_total, "%.0f");
+}
+
+static void
+_outPlannerGlobal(StringInfo str, const PlannerGlobal *node)
+{
+ WRITE_NODE_TYPE("PLANNERGLOBAL");
+
+ /* NB: this isn't a complete set of fields */
+ WRITE_NODE_FIELD(subplans);
+ WRITE_BITMAPSET_FIELD(rewindPlanIDs);
+ WRITE_NODE_FIELD(finalrtable);
+ WRITE_NODE_FIELD(finalrowmarks);
+ WRITE_NODE_FIELD(resultRelations);
+ WRITE_NODE_FIELD(appendRelations);
+ WRITE_NODE_FIELD(relationOids);
+ WRITE_NODE_FIELD(invalItems);
+ WRITE_NODE_FIELD(paramExecTypes);
+ WRITE_UINT_FIELD(lastPHId);
+ WRITE_UINT_FIELD(lastRowMarkId);
+ WRITE_INT_FIELD(lastPlanNodeId);
+ WRITE_BOOL_FIELD(transientPlan);
+ WRITE_BOOL_FIELD(dependsOnRole);
+ WRITE_BOOL_FIELD(parallelModeOK);
+ WRITE_BOOL_FIELD(parallelModeNeeded);
+ WRITE_CHAR_FIELD(maxParallelHazard);
+}
+
+static void
+_outPlannerInfo(StringInfo str, const PlannerInfo *node)
+{
+ WRITE_NODE_TYPE("PLANNERINFO");
+
+ /* NB: this isn't a complete set of fields */
+ WRITE_NODE_FIELD(parse);
+ WRITE_NODE_FIELD(glob);
+ WRITE_UINT_FIELD(query_level);
+ WRITE_NODE_FIELD(plan_params);
+ WRITE_BITMAPSET_FIELD(outer_params);
+ WRITE_BITMAPSET_FIELD(all_baserels);
+ WRITE_BITMAPSET_FIELD(nullable_baserels);
+ WRITE_NODE_FIELD(join_rel_list);
+ WRITE_INT_FIELD(join_cur_level);
+ WRITE_NODE_FIELD(init_plans);
+ WRITE_NODE_FIELD(cte_plan_ids);
+ WRITE_NODE_FIELD(multiexpr_params);
+ WRITE_NODE_FIELD(eq_classes);
+ WRITE_BOOL_FIELD(ec_merging_done);
+ WRITE_NODE_FIELD(canon_pathkeys);
+ WRITE_NODE_FIELD(left_join_clauses);
+ WRITE_NODE_FIELD(right_join_clauses);
+ WRITE_NODE_FIELD(full_join_clauses);
+ WRITE_NODE_FIELD(join_info_list);
+ WRITE_BITMAPSET_FIELD(all_result_relids);
+ WRITE_BITMAPSET_FIELD(leaf_result_relids);
+ WRITE_NODE_FIELD(append_rel_list);
+ WRITE_NODE_FIELD(row_identity_vars);
+ WRITE_NODE_FIELD(rowMarks);
+ WRITE_NODE_FIELD(placeholder_list);
+ WRITE_NODE_FIELD(fkey_list);
+ WRITE_NODE_FIELD(query_pathkeys);
+ WRITE_NODE_FIELD(group_pathkeys);
+ WRITE_NODE_FIELD(window_pathkeys);
+ WRITE_NODE_FIELD(distinct_pathkeys);
+ WRITE_NODE_FIELD(sort_pathkeys);
+ WRITE_NODE_FIELD(processed_tlist);
+ WRITE_NODE_FIELD(update_colnos);
+ WRITE_NODE_FIELD(minmax_aggs);
+ WRITE_FLOAT_FIELD(total_table_pages, "%.0f");
+ WRITE_FLOAT_FIELD(tuple_fraction, "%.4f");
+ WRITE_FLOAT_FIELD(limit_tuples, "%.0f");
+ WRITE_UINT_FIELD(qual_security_level);
+ WRITE_BOOL_FIELD(hasJoinRTEs);
+ WRITE_BOOL_FIELD(hasLateralRTEs);
+ WRITE_BOOL_FIELD(hasHavingQual);
+ WRITE_BOOL_FIELD(hasPseudoConstantQuals);
+ WRITE_BOOL_FIELD(hasAlternativeSubPlans);
+ WRITE_BOOL_FIELD(hasRecursion);
+ WRITE_INT_FIELD(wt_param_id);
+ WRITE_BITMAPSET_FIELD(curOuterRels);
+ WRITE_NODE_FIELD(curOuterParams);
+ WRITE_BOOL_FIELD(partColsUpdated);
+}
+
+static void
+_outRelOptInfo(StringInfo str, const RelOptInfo *node)
+{
+ WRITE_NODE_TYPE("RELOPTINFO");
+
+ /* NB: this isn't a complete set of fields */
+ WRITE_ENUM_FIELD(reloptkind, RelOptKind);
+ WRITE_BITMAPSET_FIELD(relids);
+ WRITE_FLOAT_FIELD(rows, "%.0f");
+ WRITE_BOOL_FIELD(consider_startup);
+ WRITE_BOOL_FIELD(consider_param_startup);
+ WRITE_BOOL_FIELD(consider_parallel);
+ WRITE_NODE_FIELD(reltarget);
+ WRITE_NODE_FIELD(pathlist);
+ WRITE_NODE_FIELD(ppilist);
+ WRITE_NODE_FIELD(partial_pathlist);
+ WRITE_NODE_FIELD(cheapest_startup_path);
+ WRITE_NODE_FIELD(cheapest_total_path);
+ WRITE_NODE_FIELD(cheapest_unique_path);
+ WRITE_NODE_FIELD(cheapest_parameterized_paths);
+ WRITE_BITMAPSET_FIELD(direct_lateral_relids);
+ WRITE_BITMAPSET_FIELD(lateral_relids);
+ WRITE_UINT_FIELD(relid);
+ WRITE_OID_FIELD(reltablespace);
+ WRITE_ENUM_FIELD(rtekind, RTEKind);
+ WRITE_INT_FIELD(min_attr);
+ WRITE_INT_FIELD(max_attr);
+ WRITE_NODE_FIELD(lateral_vars);
+ WRITE_BITMAPSET_FIELD(lateral_referencers);
+ WRITE_NODE_FIELD(indexlist);
+ WRITE_NODE_FIELD(statlist);
+ WRITE_UINT_FIELD(pages);
+ WRITE_FLOAT_FIELD(tuples, "%.0f");
+ WRITE_FLOAT_FIELD(allvisfrac, "%.6f");
+ WRITE_BITMAPSET_FIELD(eclass_indexes);
+ WRITE_NODE_FIELD(subroot);
+ WRITE_NODE_FIELD(subplan_params);
+ WRITE_INT_FIELD(rel_parallel_workers);
+ WRITE_UINT_FIELD(amflags);
+ WRITE_OID_FIELD(serverid);
+ WRITE_OID_FIELD(userid);
+ WRITE_BOOL_FIELD(useridiscurrent);
+ /* we don't try to print fdwroutine or fdw_private */
+ /* can't print unique_for_rels/non_unique_for_rels; BMSes aren't Nodes */
+ WRITE_NODE_FIELD(baserestrictinfo);
+ WRITE_UINT_FIELD(baserestrict_min_security);
+ WRITE_NODE_FIELD(joininfo);
+ WRITE_BOOL_FIELD(has_eclass_joins);
+ WRITE_BOOL_FIELD(consider_partitionwise_join);
+ WRITE_BITMAPSET_FIELD(top_parent_relids);
+ WRITE_BOOL_FIELD(partbounds_merged);
+ WRITE_BITMAPSET_FIELD(live_parts);
+ WRITE_BITMAPSET_FIELD(all_partrels);
+}
+
+static void
+_outIndexOptInfo(StringInfo str, const IndexOptInfo *node)
+{
+ WRITE_NODE_TYPE("INDEXOPTINFO");
+
+ /* NB: this isn't a complete set of fields */
+ WRITE_OID_FIELD(indexoid);
+ /* Do NOT print rel field, else infinite recursion */
+ WRITE_UINT_FIELD(pages);
+ WRITE_FLOAT_FIELD(tuples, "%.0f");
+ WRITE_INT_FIELD(tree_height);
+ WRITE_INT_FIELD(ncolumns);
+ /* array fields aren't really worth the trouble to print */
+ WRITE_OID_FIELD(relam);
+ /* indexprs is redundant since we print indextlist */
+ WRITE_NODE_FIELD(indpred);
+ WRITE_NODE_FIELD(indextlist);
+ WRITE_NODE_FIELD(indrestrictinfo);
+ WRITE_BOOL_FIELD(predOK);
+ WRITE_BOOL_FIELD(unique);
+ WRITE_BOOL_FIELD(immediate);
+ WRITE_BOOL_FIELD(hypothetical);
+ /* we don't bother with fields copied from the index AM's API struct */
+}
+
+static void
+_outForeignKeyOptInfo(StringInfo str, const ForeignKeyOptInfo *node)
+{
+ int i;
+
+ WRITE_NODE_TYPE("FOREIGNKEYOPTINFO");
+
+ WRITE_UINT_FIELD(con_relid);
+ WRITE_UINT_FIELD(ref_relid);
+ WRITE_INT_FIELD(nkeys);
+ WRITE_ATTRNUMBER_ARRAY(conkey, node->nkeys);
+ WRITE_ATTRNUMBER_ARRAY(confkey, node->nkeys);
+ WRITE_OID_ARRAY(conpfeqop, node->nkeys);
+ WRITE_INT_FIELD(nmatched_ec);
+ WRITE_INT_FIELD(nconst_ec);
+ WRITE_INT_FIELD(nmatched_rcols);
+ WRITE_INT_FIELD(nmatched_ri);
+ /* for compactness, just print the number of matches per column: */
+ appendStringInfoString(str, " :eclass");
+ for (i = 0; i < node->nkeys; i++)
+ appendStringInfo(str, " %d", (node->eclass[i] != NULL));
+ appendStringInfoString(str, " :rinfos");
+ for (i = 0; i < node->nkeys; i++)
+ appendStringInfo(str, " %d", list_length(node->rinfos[i]));
+}
+
+static void
+_outStatisticExtInfo(StringInfo str, const StatisticExtInfo *node)
+{
+ WRITE_NODE_TYPE("STATISTICEXTINFO");
+
+ /* NB: this isn't a complete set of fields */
+ WRITE_OID_FIELD(statOid);
+ /* don't write rel, leads to infinite recursion in plan tree dump */
+ WRITE_CHAR_FIELD(kind);
+ WRITE_BITMAPSET_FIELD(keys);
+}
+
+static void
+_outEquivalenceClass(StringInfo str, const EquivalenceClass *node)
+{
+ /*
+ * To simplify reading, we just chase up to the topmost merged EC and
+ * print that, without bothering to show the merge-ees separately.
+ */
+ while (node->ec_merged)
+ node = node->ec_merged;
+
+ WRITE_NODE_TYPE("EQUIVALENCECLASS");
+
+ WRITE_NODE_FIELD(ec_opfamilies);
+ WRITE_OID_FIELD(ec_collation);
+ WRITE_NODE_FIELD(ec_members);
+ WRITE_NODE_FIELD(ec_sources);
+ WRITE_NODE_FIELD(ec_derives);
+ WRITE_BITMAPSET_FIELD(ec_relids);
+ WRITE_BOOL_FIELD(ec_has_const);
+ WRITE_BOOL_FIELD(ec_has_volatile);
+ WRITE_BOOL_FIELD(ec_below_outer_join);
+ WRITE_BOOL_FIELD(ec_broken);
+ WRITE_UINT_FIELD(ec_sortref);
+ WRITE_UINT_FIELD(ec_min_security);
+ WRITE_UINT_FIELD(ec_max_security);
+}
+
+static void
+_outEquivalenceMember(StringInfo str, const EquivalenceMember *node)
+{
+ WRITE_NODE_TYPE("EQUIVALENCEMEMBER");
+
+ WRITE_NODE_FIELD(em_expr);
+ WRITE_BITMAPSET_FIELD(em_relids);
+ WRITE_BITMAPSET_FIELD(em_nullable_relids);
+ WRITE_BOOL_FIELD(em_is_const);
+ WRITE_BOOL_FIELD(em_is_child);
+ WRITE_OID_FIELD(em_datatype);
+}
+
+static void
+_outPathKey(StringInfo str, const PathKey *node)
+{
+ WRITE_NODE_TYPE("PATHKEY");
+
+ WRITE_NODE_FIELD(pk_eclass);
+ WRITE_OID_FIELD(pk_opfamily);
+ WRITE_INT_FIELD(pk_strategy);
+ WRITE_BOOL_FIELD(pk_nulls_first);
+}
+
+static void
+_outPathTarget(StringInfo str, const PathTarget *node)
+{
+ WRITE_NODE_TYPE("PATHTARGET");
+
+ WRITE_NODE_FIELD(exprs);
+ WRITE_INDEX_ARRAY(sortgrouprefs, list_length(node->exprs));
+ WRITE_FLOAT_FIELD(cost.startup, "%.2f");
+ WRITE_FLOAT_FIELD(cost.per_tuple, "%.2f");
+ WRITE_INT_FIELD(width);
+ WRITE_ENUM_FIELD(has_volatile_expr, VolatileFunctionStatus);
+}
+
+static void
+_outParamPathInfo(StringInfo str, const ParamPathInfo *node)
+{
+ WRITE_NODE_TYPE("PARAMPATHINFO");
+
+ WRITE_BITMAPSET_FIELD(ppi_req_outer);
+ WRITE_FLOAT_FIELD(ppi_rows, "%.0f");
+ WRITE_NODE_FIELD(ppi_clauses);
+}
+
+static void
+_outRestrictInfo(StringInfo str, const RestrictInfo *node)
+{
+ WRITE_NODE_TYPE("RESTRICTINFO");
+
+ /* NB: this isn't a complete set of fields */
+ WRITE_NODE_FIELD(clause);
+ WRITE_BOOL_FIELD(is_pushed_down);
+ WRITE_BOOL_FIELD(outerjoin_delayed);
+ WRITE_BOOL_FIELD(can_join);
+ WRITE_BOOL_FIELD(pseudoconstant);
+ WRITE_BOOL_FIELD(leakproof);
+ WRITE_ENUM_FIELD(has_volatile, VolatileFunctionStatus);
+ WRITE_UINT_FIELD(security_level);
+ WRITE_BITMAPSET_FIELD(clause_relids);
+ WRITE_BITMAPSET_FIELD(required_relids);
+ WRITE_BITMAPSET_FIELD(outer_relids);
+ WRITE_BITMAPSET_FIELD(nullable_relids);
+ WRITE_BITMAPSET_FIELD(left_relids);
+ WRITE_BITMAPSET_FIELD(right_relids);
+ WRITE_NODE_FIELD(orclause);
+ /* don't write parent_ec, leads to infinite recursion in plan tree dump */
+ WRITE_FLOAT_FIELD(norm_selec, "%.4f");
+ WRITE_FLOAT_FIELD(outer_selec, "%.4f");
+ WRITE_NODE_FIELD(mergeopfamilies);
+ /* don't write left_ec, leads to infinite recursion in plan tree dump */
+ /* don't write right_ec, leads to infinite recursion in plan tree dump */
+ WRITE_NODE_FIELD(left_em);
+ WRITE_NODE_FIELD(right_em);
+ WRITE_BOOL_FIELD(outer_is_left);
+ WRITE_OID_FIELD(hashjoinoperator);
+ WRITE_OID_FIELD(left_hasheqoperator);
+ WRITE_OID_FIELD(right_hasheqoperator);
+}
+
+static void
+_outIndexClause(StringInfo str, const IndexClause *node)
+{
+ WRITE_NODE_TYPE("INDEXCLAUSE");
+
+ WRITE_NODE_FIELD(rinfo);
+ WRITE_NODE_FIELD(indexquals);
+ WRITE_BOOL_FIELD(lossy);
+ WRITE_INT_FIELD(indexcol);
+ WRITE_NODE_FIELD(indexcols);
+}
+
+static void
+_outPlaceHolderVar(StringInfo str, const PlaceHolderVar *node)
+{
+ WRITE_NODE_TYPE("PLACEHOLDERVAR");
+
+ WRITE_NODE_FIELD(phexpr);
+ WRITE_BITMAPSET_FIELD(phrels);
+ WRITE_UINT_FIELD(phid);
+ WRITE_UINT_FIELD(phlevelsup);
+}
+
+static void
+_outSpecialJoinInfo(StringInfo str, const SpecialJoinInfo *node)
+{
+ WRITE_NODE_TYPE("SPECIALJOININFO");
+
+ WRITE_BITMAPSET_FIELD(min_lefthand);
+ WRITE_BITMAPSET_FIELD(min_righthand);
+ WRITE_BITMAPSET_FIELD(syn_lefthand);
+ WRITE_BITMAPSET_FIELD(syn_righthand);
+ WRITE_ENUM_FIELD(jointype, JoinType);
+ WRITE_BOOL_FIELD(lhs_strict);
+ WRITE_BOOL_FIELD(delay_upper_joins);
+ WRITE_BOOL_FIELD(semi_can_btree);
+ WRITE_BOOL_FIELD(semi_can_hash);
+ WRITE_NODE_FIELD(semi_operators);
+ WRITE_NODE_FIELD(semi_rhs_exprs);
+}
+
+static void
+_outAppendRelInfo(StringInfo str, const AppendRelInfo *node)
+{
+ WRITE_NODE_TYPE("APPENDRELINFO");
+
+ WRITE_UINT_FIELD(parent_relid);
+ WRITE_UINT_FIELD(child_relid);
+ WRITE_OID_FIELD(parent_reltype);
+ WRITE_OID_FIELD(child_reltype);
+ WRITE_NODE_FIELD(translated_vars);
+ WRITE_INT_FIELD(num_child_cols);
+ WRITE_ATTRNUMBER_ARRAY(parent_colnos, node->num_child_cols);
+ WRITE_OID_FIELD(parent_reloid);
+}
+
+static void
+_outRowIdentityVarInfo(StringInfo str, const RowIdentityVarInfo *node)
+{
+ WRITE_NODE_TYPE("ROWIDENTITYVARINFO");
+
+ WRITE_NODE_FIELD(rowidvar);
+ WRITE_INT_FIELD(rowidwidth);
+ WRITE_STRING_FIELD(rowidname);
+ WRITE_BITMAPSET_FIELD(rowidrels);
+}
+
+static void
+_outPlaceHolderInfo(StringInfo str, const PlaceHolderInfo *node)
+{
+ WRITE_NODE_TYPE("PLACEHOLDERINFO");
+
+ WRITE_UINT_FIELD(phid);
+ WRITE_NODE_FIELD(ph_var);
+ WRITE_BITMAPSET_FIELD(ph_eval_at);
+ WRITE_BITMAPSET_FIELD(ph_lateral);
+ WRITE_BITMAPSET_FIELD(ph_needed);
+ WRITE_INT_FIELD(ph_width);
+}
+
+static void
+_outMinMaxAggInfo(StringInfo str, const MinMaxAggInfo *node)
+{
+ WRITE_NODE_TYPE("MINMAXAGGINFO");
+
+ WRITE_OID_FIELD(aggfnoid);
+ WRITE_OID_FIELD(aggsortop);
+ WRITE_NODE_FIELD(target);
+ /* We intentionally omit subroot --- too large, not interesting enough */
+ WRITE_NODE_FIELD(path);
+ WRITE_FLOAT_FIELD(pathcost, "%.2f");
+ WRITE_NODE_FIELD(param);
+}
+
+static void
+_outPlannerParamItem(StringInfo str, const PlannerParamItem *node)
+{
+ WRITE_NODE_TYPE("PLANNERPARAMITEM");
+
+ WRITE_NODE_FIELD(item);
+ WRITE_INT_FIELD(paramId);
+}
+
+/*****************************************************************************
+ *
+ * Stuff from extensible.h
+ *
+ *****************************************************************************/
+
+static void
+_outExtensibleNode(StringInfo str, const ExtensibleNode *node)
+{
+ const ExtensibleNodeMethods *methods;
+
+ methods = GetExtensibleNodeMethods(node->extnodename, false);
+
+ WRITE_NODE_TYPE("EXTENSIBLENODE");
+
+ WRITE_STRING_FIELD(extnodename);
+
+ /* serialize the private fields */
+ methods->nodeOut(str, node);
+}
+
+/*****************************************************************************
+ *
+ * Stuff from parsenodes.h.
+ *
+ *****************************************************************************/
+
+/*
+ * print the basic stuff of all nodes that inherit from CreateStmt
+ */
+static void
+_outCreateStmtInfo(StringInfo str, const CreateStmt *node)
+{
+ WRITE_NODE_FIELD(relation);
+ WRITE_NODE_FIELD(tableElts);
+ WRITE_NODE_FIELD(inhRelations);
+ WRITE_NODE_FIELD(partspec);
+ WRITE_NODE_FIELD(partbound);
+ WRITE_NODE_FIELD(ofTypename);
+ WRITE_NODE_FIELD(constraints);
+ WRITE_NODE_FIELD(options);
+ WRITE_ENUM_FIELD(oncommit, OnCommitAction);
+ WRITE_STRING_FIELD(tablespacename);
+ WRITE_STRING_FIELD(accessMethod);
+ WRITE_BOOL_FIELD(if_not_exists);
+}
+
+static void
+_outCreateStmt(StringInfo str, const CreateStmt *node)
+{
+ WRITE_NODE_TYPE("CREATESTMT");
+
+ _outCreateStmtInfo(str, (const CreateStmt *) node);
+}
+
+static void
+_outCreateForeignTableStmt(StringInfo str, const CreateForeignTableStmt *node)
+{
+ WRITE_NODE_TYPE("CREATEFOREIGNTABLESTMT");
+
+ _outCreateStmtInfo(str, (const CreateStmt *) node);
+
+ WRITE_STRING_FIELD(servername);
+ WRITE_NODE_FIELD(options);
+}
+
+static void
+_outImportForeignSchemaStmt(StringInfo str, const ImportForeignSchemaStmt *node)
+{
+ WRITE_NODE_TYPE("IMPORTFOREIGNSCHEMASTMT");
+
+ WRITE_STRING_FIELD(server_name);
+ WRITE_STRING_FIELD(remote_schema);
+ WRITE_STRING_FIELD(local_schema);
+ WRITE_ENUM_FIELD(list_type, ImportForeignSchemaType);
+ WRITE_NODE_FIELD(table_list);
+ WRITE_NODE_FIELD(options);
+}
+
+static void
+_outIndexStmt(StringInfo str, const IndexStmt *node)
+{
+ WRITE_NODE_TYPE("INDEXSTMT");
+
+ WRITE_STRING_FIELD(idxname);
+ WRITE_NODE_FIELD(relation);
+ WRITE_STRING_FIELD(accessMethod);
+ WRITE_STRING_FIELD(tableSpace);
+ WRITE_NODE_FIELD(indexParams);
+ WRITE_NODE_FIELD(indexIncludingParams);
+ WRITE_NODE_FIELD(options);
+ WRITE_NODE_FIELD(whereClause);
+ WRITE_NODE_FIELD(excludeOpNames);
+ WRITE_STRING_FIELD(idxcomment);
+ WRITE_OID_FIELD(indexOid);
+ WRITE_OID_FIELD(oldNode);
+ WRITE_UINT_FIELD(oldCreateSubid);
+ WRITE_UINT_FIELD(oldFirstRelfilenodeSubid);
+ WRITE_BOOL_FIELD(unique);
+ WRITE_BOOL_FIELD(nulls_not_distinct);
+ WRITE_BOOL_FIELD(primary);
+ WRITE_BOOL_FIELD(isconstraint);
+ WRITE_BOOL_FIELD(deferrable);
+ WRITE_BOOL_FIELD(initdeferred);
+ WRITE_BOOL_FIELD(transformed);
+ WRITE_BOOL_FIELD(concurrent);
+ WRITE_BOOL_FIELD(if_not_exists);
+ WRITE_BOOL_FIELD(reset_default_tblspc);
+}
+
+static void
+_outCreateStatsStmt(StringInfo str, const CreateStatsStmt *node)
+{
+ WRITE_NODE_TYPE("CREATESTATSSTMT");
+
+ WRITE_NODE_FIELD(defnames);
+ WRITE_NODE_FIELD(stat_types);
+ WRITE_NODE_FIELD(exprs);
+ WRITE_NODE_FIELD(relations);
+ WRITE_STRING_FIELD(stxcomment);
+ WRITE_BOOL_FIELD(transformed);
+ WRITE_BOOL_FIELD(if_not_exists);
+}
+
+static void
+_outAlterStatsStmt(StringInfo str, const AlterStatsStmt *node)
+{
+ WRITE_NODE_TYPE("ALTERSTATSSTMT");
+
+ WRITE_NODE_FIELD(defnames);
+ WRITE_INT_FIELD(stxstattarget);
+ WRITE_BOOL_FIELD(missing_ok);
+}
+
+static void
+_outNotifyStmt(StringInfo str, const NotifyStmt *node)
+{
+ WRITE_NODE_TYPE("NOTIFYSTMT");
+
+ WRITE_STRING_FIELD(conditionname);
+ WRITE_STRING_FIELD(payload);
+}
+
+static void
+_outDeclareCursorStmt(StringInfo str, const DeclareCursorStmt *node)
+{
+ WRITE_NODE_TYPE("DECLARECURSORSTMT");
+
+ WRITE_STRING_FIELD(portalname);
+ WRITE_INT_FIELD(options);
+ WRITE_NODE_FIELD(query);
+}
+
+static void
+_outSelectStmt(StringInfo str, const SelectStmt *node)
+{
+ WRITE_NODE_TYPE("SELECT");
+
+ WRITE_NODE_FIELD(distinctClause);
+ WRITE_NODE_FIELD(intoClause);
+ WRITE_NODE_FIELD(targetList);
+ WRITE_NODE_FIELD(fromClause);
+ WRITE_NODE_FIELD(whereClause);
+ WRITE_NODE_FIELD(groupClause);
+ WRITE_BOOL_FIELD(groupDistinct);
+ WRITE_NODE_FIELD(havingClause);
+ WRITE_NODE_FIELD(windowClause);
+ WRITE_NODE_FIELD(valuesLists);
+ WRITE_NODE_FIELD(sortClause);
+ WRITE_NODE_FIELD(limitOffset);
+ WRITE_NODE_FIELD(limitCount);
+ WRITE_ENUM_FIELD(limitOption, LimitOption);
+ WRITE_NODE_FIELD(lockingClause);
+ WRITE_NODE_FIELD(withClause);
+ WRITE_ENUM_FIELD(op, SetOperation);
+ WRITE_BOOL_FIELD(all);
+ WRITE_NODE_FIELD(larg);
+ WRITE_NODE_FIELD(rarg);
+}
+
+static void
+_outReturnStmt(StringInfo str, const ReturnStmt *node)
+{
+ WRITE_NODE_TYPE("RETURN");
+
+ WRITE_NODE_FIELD(returnval);
+}
+
+static void
+_outPLAssignStmt(StringInfo str, const PLAssignStmt *node)
+{
+ WRITE_NODE_TYPE("PLASSIGN");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_NODE_FIELD(indirection);
+ WRITE_INT_FIELD(nnames);
+ WRITE_NODE_FIELD(val);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outFuncCall(StringInfo str, const FuncCall *node)
+{
+ WRITE_NODE_TYPE("FUNCCALL");
+
+ WRITE_NODE_FIELD(funcname);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(agg_order);
+ WRITE_NODE_FIELD(agg_filter);
+ WRITE_NODE_FIELD(over);
+ WRITE_BOOL_FIELD(agg_within_group);
+ WRITE_BOOL_FIELD(agg_star);
+ WRITE_BOOL_FIELD(agg_distinct);
+ WRITE_BOOL_FIELD(func_variadic);
+ WRITE_ENUM_FIELD(funcformat, CoercionForm);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outDefElem(StringInfo str, const DefElem *node)
+{
+ WRITE_NODE_TYPE("DEFELEM");
+
+ WRITE_STRING_FIELD(defnamespace);
+ WRITE_STRING_FIELD(defname);
+ WRITE_NODE_FIELD(arg);
+ WRITE_ENUM_FIELD(defaction, DefElemAction);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outTableLikeClause(StringInfo str, const TableLikeClause *node)
+{
+ WRITE_NODE_TYPE("TABLELIKECLAUSE");
+
+ WRITE_NODE_FIELD(relation);
+ WRITE_UINT_FIELD(options);
+ WRITE_OID_FIELD(relationOid);
+}
+
+static void
+_outLockingClause(StringInfo str, const LockingClause *node)
+{
+ WRITE_NODE_TYPE("LOCKINGCLAUSE");
+
+ WRITE_NODE_FIELD(lockedRels);
+ WRITE_ENUM_FIELD(strength, LockClauseStrength);
+ WRITE_ENUM_FIELD(waitPolicy, LockWaitPolicy);
+}
+
+static void
+_outXmlSerialize(StringInfo str, const XmlSerialize *node)
+{
+ WRITE_NODE_TYPE("XMLSERIALIZE");
+
+ WRITE_ENUM_FIELD(xmloption, XmlOptionType);
+ WRITE_NODE_FIELD(expr);
+ WRITE_NODE_FIELD(typeName);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outTriggerTransition(StringInfo str, const TriggerTransition *node)
+{
+ WRITE_NODE_TYPE("TRIGGERTRANSITION");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_BOOL_FIELD(isNew);
+ WRITE_BOOL_FIELD(isTable);
+}
+
+static void
+_outColumnDef(StringInfo str, const ColumnDef *node)
+{
+ WRITE_NODE_TYPE("COLUMNDEF");
+
+ WRITE_STRING_FIELD(colname);
+ WRITE_NODE_FIELD(typeName);
+ WRITE_STRING_FIELD(compression);
+ WRITE_INT_FIELD(inhcount);
+ WRITE_BOOL_FIELD(is_local);
+ WRITE_BOOL_FIELD(is_not_null);
+ WRITE_BOOL_FIELD(is_from_type);
+ WRITE_CHAR_FIELD(storage);
+ WRITE_NODE_FIELD(raw_default);
+ WRITE_NODE_FIELD(cooked_default);
+ WRITE_CHAR_FIELD(identity);
+ WRITE_NODE_FIELD(identitySequence);
+ WRITE_CHAR_FIELD(generated);
+ WRITE_NODE_FIELD(collClause);
+ WRITE_OID_FIELD(collOid);
+ WRITE_NODE_FIELD(constraints);
+ WRITE_NODE_FIELD(fdwoptions);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outTypeName(StringInfo str, const TypeName *node)
+{
+ WRITE_NODE_TYPE("TYPENAME");
+
+ WRITE_NODE_FIELD(names);
+ WRITE_OID_FIELD(typeOid);
+ WRITE_BOOL_FIELD(setof);
+ WRITE_BOOL_FIELD(pct_type);
+ WRITE_NODE_FIELD(typmods);
+ WRITE_INT_FIELD(typemod);
+ WRITE_NODE_FIELD(arrayBounds);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outTypeCast(StringInfo str, const TypeCast *node)
+{
+ WRITE_NODE_TYPE("TYPECAST");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_NODE_FIELD(typeName);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCollateClause(StringInfo str, const CollateClause *node)
+{
+ WRITE_NODE_TYPE("COLLATECLAUSE");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_NODE_FIELD(collname);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outIndexElem(StringInfo str, const IndexElem *node)
+{
+ WRITE_NODE_TYPE("INDEXELEM");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_NODE_FIELD(expr);
+ WRITE_STRING_FIELD(indexcolname);
+ WRITE_NODE_FIELD(collation);
+ WRITE_NODE_FIELD(opclass);
+ WRITE_NODE_FIELD(opclassopts);
+ WRITE_ENUM_FIELD(ordering, SortByDir);
+ WRITE_ENUM_FIELD(nulls_ordering, SortByNulls);
+}
+
+static void
+_outStatsElem(StringInfo str, const StatsElem *node)
+{
+ WRITE_NODE_TYPE("STATSELEM");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_NODE_FIELD(expr);
+}
+
+static void
+_outQuery(StringInfo str, const Query *node)
+{
+ WRITE_NODE_TYPE("QUERY");
+
+ WRITE_ENUM_FIELD(commandType, CmdType);
+ WRITE_ENUM_FIELD(querySource, QuerySource);
+ /* we intentionally do not print the queryId field */
+ WRITE_BOOL_FIELD(canSetTag);
+
+ /*
+ * Hack to work around missing outfuncs routines for a lot of the
+ * utility-statement node types. (The only one we actually *need* for
+ * rules support is NotifyStmt.) Someday we ought to support 'em all, but
+ * for the meantime do this to avoid getting lots of warnings when running
+ * with debug_print_parse on.
+ */
+ if (node->utilityStmt)
+ {
+ switch (nodeTag(node->utilityStmt))
+ {
+ case T_CreateStmt:
+ case T_IndexStmt:
+ case T_NotifyStmt:
+ case T_DeclareCursorStmt:
+ WRITE_NODE_FIELD(utilityStmt);
+ break;
+ default:
+ appendStringInfoString(str, " :utilityStmt ?");
+ break;
+ }
+ }
+ else
+ appendStringInfoString(str, " :utilityStmt <>");
+
+ WRITE_INT_FIELD(resultRelation);
+ WRITE_BOOL_FIELD(hasAggs);
+ WRITE_BOOL_FIELD(hasWindowFuncs);
+ WRITE_BOOL_FIELD(hasTargetSRFs);
+ WRITE_BOOL_FIELD(hasSubLinks);
+ WRITE_BOOL_FIELD(hasDistinctOn);
+ WRITE_BOOL_FIELD(hasRecursive);
+ WRITE_BOOL_FIELD(hasModifyingCTE);
+ WRITE_BOOL_FIELD(hasForUpdate);
+ WRITE_BOOL_FIELD(hasRowSecurity);
+ WRITE_BOOL_FIELD(isReturn);
+ WRITE_NODE_FIELD(cteList);
+ WRITE_NODE_FIELD(rtable);
+ WRITE_NODE_FIELD(jointree);
+ WRITE_NODE_FIELD(targetList);
+ WRITE_ENUM_FIELD(override, OverridingKind);
+ WRITE_NODE_FIELD(onConflict);
+ WRITE_NODE_FIELD(returningList);
+ WRITE_NODE_FIELD(groupClause);
+ WRITE_BOOL_FIELD(groupDistinct);
+ WRITE_NODE_FIELD(groupingSets);
+ WRITE_NODE_FIELD(havingQual);
+ WRITE_NODE_FIELD(windowClause);
+ WRITE_NODE_FIELD(distinctClause);
+ WRITE_NODE_FIELD(sortClause);
+ WRITE_NODE_FIELD(limitOffset);
+ WRITE_NODE_FIELD(limitCount);
+ WRITE_ENUM_FIELD(limitOption, LimitOption);
+ WRITE_NODE_FIELD(rowMarks);
+ WRITE_NODE_FIELD(setOperations);
+ WRITE_NODE_FIELD(constraintDeps);
+ WRITE_NODE_FIELD(withCheckOptions);
+ WRITE_NODE_FIELD(mergeActionList);
+ WRITE_BOOL_FIELD(mergeUseOuterJoin);
+ WRITE_LOCATION_FIELD(stmt_location);
+ WRITE_INT_FIELD(stmt_len);
+}
+
+static void
+_outWithCheckOption(StringInfo str, const WithCheckOption *node)
+{
+ WRITE_NODE_TYPE("WITHCHECKOPTION");
+
+ WRITE_ENUM_FIELD(kind, WCOKind);
+ WRITE_STRING_FIELD(relname);
+ WRITE_STRING_FIELD(polname);
+ WRITE_NODE_FIELD(qual);
+ WRITE_BOOL_FIELD(cascaded);
+}
+
+static void
+_outSortGroupClause(StringInfo str, const SortGroupClause *node)
+{
+ WRITE_NODE_TYPE("SORTGROUPCLAUSE");
+
+ WRITE_UINT_FIELD(tleSortGroupRef);
+ WRITE_OID_FIELD(eqop);
+ WRITE_OID_FIELD(sortop);
+ WRITE_BOOL_FIELD(nulls_first);
+ WRITE_BOOL_FIELD(hashable);
+}
+
+static void
+_outGroupingSet(StringInfo str, const GroupingSet *node)
+{
+ WRITE_NODE_TYPE("GROUPINGSET");
+
+ WRITE_ENUM_FIELD(kind, GroupingSetKind);
+ WRITE_NODE_FIELD(content);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outWindowClause(StringInfo str, const WindowClause *node)
+{
+ WRITE_NODE_TYPE("WINDOWCLAUSE");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_STRING_FIELD(refname);
+ WRITE_NODE_FIELD(partitionClause);
+ WRITE_NODE_FIELD(orderClause);
+ WRITE_INT_FIELD(frameOptions);
+ WRITE_NODE_FIELD(startOffset);
+ WRITE_NODE_FIELD(endOffset);
+ WRITE_NODE_FIELD(runCondition);
+ WRITE_OID_FIELD(startInRangeFunc);
+ WRITE_OID_FIELD(endInRangeFunc);
+ WRITE_OID_FIELD(inRangeColl);
+ WRITE_BOOL_FIELD(inRangeAsc);
+ WRITE_BOOL_FIELD(inRangeNullsFirst);
+ WRITE_UINT_FIELD(winref);
+ WRITE_BOOL_FIELD(copiedOrder);
+}
+
+static void
+_outRowMarkClause(StringInfo str, const RowMarkClause *node)
+{
+ WRITE_NODE_TYPE("ROWMARKCLAUSE");
+
+ WRITE_UINT_FIELD(rti);
+ WRITE_ENUM_FIELD(strength, LockClauseStrength);
+ WRITE_ENUM_FIELD(waitPolicy, LockWaitPolicy);
+ WRITE_BOOL_FIELD(pushedDown);
+}
+
+static void
+_outWithClause(StringInfo str, const WithClause *node)
+{
+ WRITE_NODE_TYPE("WITHCLAUSE");
+
+ WRITE_NODE_FIELD(ctes);
+ WRITE_BOOL_FIELD(recursive);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCTESearchClause(StringInfo str, const CTESearchClause *node)
+{
+ WRITE_NODE_TYPE("CTESEARCHCLAUSE");
+
+ WRITE_NODE_FIELD(search_col_list);
+ WRITE_BOOL_FIELD(search_breadth_first);
+ WRITE_STRING_FIELD(search_seq_column);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outCTECycleClause(StringInfo str, const CTECycleClause *node)
+{
+ WRITE_NODE_TYPE("CTECYCLECLAUSE");
+
+ WRITE_NODE_FIELD(cycle_col_list);
+ WRITE_STRING_FIELD(cycle_mark_column);
+ WRITE_NODE_FIELD(cycle_mark_value);
+ WRITE_NODE_FIELD(cycle_mark_default);
+ WRITE_STRING_FIELD(cycle_path_column);
+ WRITE_LOCATION_FIELD(location);
+ WRITE_OID_FIELD(cycle_mark_type);
+ WRITE_INT_FIELD(cycle_mark_typmod);
+ WRITE_OID_FIELD(cycle_mark_collation);
+ WRITE_OID_FIELD(cycle_mark_neop);
+}
+
+static void
+_outCommonTableExpr(StringInfo str, const CommonTableExpr *node)
+{
+ WRITE_NODE_TYPE("COMMONTABLEEXPR");
+
+ WRITE_STRING_FIELD(ctename);
+ WRITE_NODE_FIELD(aliascolnames);
+ WRITE_ENUM_FIELD(ctematerialized, CTEMaterialize);
+ WRITE_NODE_FIELD(ctequery);
+ WRITE_NODE_FIELD(search_clause);
+ WRITE_NODE_FIELD(cycle_clause);
+ WRITE_LOCATION_FIELD(location);
+ WRITE_BOOL_FIELD(cterecursive);
+ WRITE_INT_FIELD(cterefcount);
+ WRITE_NODE_FIELD(ctecolnames);
+ WRITE_NODE_FIELD(ctecoltypes);
+ WRITE_NODE_FIELD(ctecoltypmods);
+ WRITE_NODE_FIELD(ctecolcollations);
+}
+
+static void
+_outMergeWhenClause(StringInfo str, const MergeWhenClause *node)
+{
+ WRITE_NODE_TYPE("MERGEWHENCLAUSE");
+
+ WRITE_BOOL_FIELD(matched);
+ WRITE_ENUM_FIELD(commandType, CmdType);
+ WRITE_ENUM_FIELD(override, OverridingKind);
+ WRITE_NODE_FIELD(condition);
+ WRITE_NODE_FIELD(targetList);
+ WRITE_NODE_FIELD(values);
+}
+
+static void
+_outMergeAction(StringInfo str, const MergeAction *node)
+{
+ WRITE_NODE_TYPE("MERGEACTION");
+
+ WRITE_BOOL_FIELD(matched);
+ WRITE_ENUM_FIELD(commandType, CmdType);
+ WRITE_ENUM_FIELD(override, OverridingKind);
+ WRITE_NODE_FIELD(qual);
+ WRITE_NODE_FIELD(targetList);
+ WRITE_NODE_FIELD(updateColnos);
+}
+
+static void
+_outSetOperationStmt(StringInfo str, const SetOperationStmt *node)
+{
+ WRITE_NODE_TYPE("SETOPERATIONSTMT");
+
+ WRITE_ENUM_FIELD(op, SetOperation);
+ WRITE_BOOL_FIELD(all);
+ WRITE_NODE_FIELD(larg);
+ WRITE_NODE_FIELD(rarg);
+ WRITE_NODE_FIELD(colTypes);
+ WRITE_NODE_FIELD(colTypmods);
+ WRITE_NODE_FIELD(colCollations);
+ WRITE_NODE_FIELD(groupClauses);
+}
+
+static void
+_outRangeTblEntry(StringInfo str, const RangeTblEntry *node)
+{
+ WRITE_NODE_TYPE("RANGETBLENTRY");
+
+ /* put alias + eref first to make dump more legible */
+ WRITE_NODE_FIELD(alias);
+ WRITE_NODE_FIELD(eref);
+ WRITE_ENUM_FIELD(rtekind, RTEKind);
+
+ switch (node->rtekind)
+ {
+ case RTE_RELATION:
+ WRITE_OID_FIELD(relid);
+ WRITE_CHAR_FIELD(relkind);
+ WRITE_INT_FIELD(rellockmode);
+ WRITE_NODE_FIELD(tablesample);
+ break;
+ case RTE_SUBQUERY:
+ WRITE_NODE_FIELD(subquery);
+ WRITE_BOOL_FIELD(security_barrier);
+ break;
+ case RTE_JOIN:
+ WRITE_ENUM_FIELD(jointype, JoinType);
+ WRITE_INT_FIELD(joinmergedcols);
+ WRITE_NODE_FIELD(joinaliasvars);
+ WRITE_NODE_FIELD(joinleftcols);
+ WRITE_NODE_FIELD(joinrightcols);
+ WRITE_NODE_FIELD(join_using_alias);
+ break;
+ case RTE_FUNCTION:
+ WRITE_NODE_FIELD(functions);
+ WRITE_BOOL_FIELD(funcordinality);
+ break;
+ case RTE_TABLEFUNC:
+ WRITE_NODE_FIELD(tablefunc);
+ break;
+ case RTE_VALUES:
+ WRITE_NODE_FIELD(values_lists);
+ WRITE_NODE_FIELD(coltypes);
+ WRITE_NODE_FIELD(coltypmods);
+ WRITE_NODE_FIELD(colcollations);
+ break;
+ case RTE_CTE:
+ WRITE_STRING_FIELD(ctename);
+ WRITE_UINT_FIELD(ctelevelsup);
+ WRITE_BOOL_FIELD(self_reference);
+ WRITE_NODE_FIELD(coltypes);
+ WRITE_NODE_FIELD(coltypmods);
+ WRITE_NODE_FIELD(colcollations);
+ break;
+ case RTE_NAMEDTUPLESTORE:
+ WRITE_STRING_FIELD(enrname);
+ WRITE_FLOAT_FIELD(enrtuples, "%.0f");
+ WRITE_OID_FIELD(relid);
+ WRITE_NODE_FIELD(coltypes);
+ WRITE_NODE_FIELD(coltypmods);
+ WRITE_NODE_FIELD(colcollations);
+ break;
+ case RTE_RESULT:
+ /* no extra fields */
+ break;
+ default:
+ elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind);
+ break;
+ }
+
+ WRITE_BOOL_FIELD(lateral);
+ WRITE_BOOL_FIELD(inh);
+ WRITE_BOOL_FIELD(inFromCl);
+ WRITE_UINT_FIELD(requiredPerms);
+ WRITE_OID_FIELD(checkAsUser);
+ WRITE_BITMAPSET_FIELD(selectedCols);
+ WRITE_BITMAPSET_FIELD(insertedCols);
+ WRITE_BITMAPSET_FIELD(updatedCols);
+ WRITE_BITMAPSET_FIELD(extraUpdatedCols);
+ WRITE_NODE_FIELD(securityQuals);
+}
+
+static void
+_outRangeTblFunction(StringInfo str, const RangeTblFunction *node)
+{
+ WRITE_NODE_TYPE("RANGETBLFUNCTION");
+
+ WRITE_NODE_FIELD(funcexpr);
+ WRITE_INT_FIELD(funccolcount);
+ WRITE_NODE_FIELD(funccolnames);
+ WRITE_NODE_FIELD(funccoltypes);
+ WRITE_NODE_FIELD(funccoltypmods);
+ WRITE_NODE_FIELD(funccolcollations);
+ WRITE_BITMAPSET_FIELD(funcparams);
+}
+
+static void
+_outTableSampleClause(StringInfo str, const TableSampleClause *node)
+{
+ WRITE_NODE_TYPE("TABLESAMPLECLAUSE");
+
+ WRITE_OID_FIELD(tsmhandler);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(repeatable);
+}
+
+static void
+_outA_Expr(StringInfo str, const A_Expr *node)
+{
+ WRITE_NODE_TYPE("AEXPR");
+
+ switch (node->kind)
+ {
+ case AEXPR_OP:
+ appendStringInfoChar(str, ' ');
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_OP_ANY:
+ appendStringInfoChar(str, ' ');
+ WRITE_NODE_FIELD(name);
+ appendStringInfoString(str, " ANY ");
+ break;
+ case AEXPR_OP_ALL:
+ appendStringInfoChar(str, ' ');
+ WRITE_NODE_FIELD(name);
+ appendStringInfoString(str, " ALL ");
+ break;
+ case AEXPR_DISTINCT:
+ appendStringInfoString(str, " DISTINCT ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_NOT_DISTINCT:
+ appendStringInfoString(str, " NOT_DISTINCT ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_NULLIF:
+ appendStringInfoString(str, " NULLIF ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_IN:
+ appendStringInfoString(str, " IN ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_LIKE:
+ appendStringInfoString(str, " LIKE ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_ILIKE:
+ appendStringInfoString(str, " ILIKE ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_SIMILAR:
+ appendStringInfoString(str, " SIMILAR ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_BETWEEN:
+ appendStringInfoString(str, " BETWEEN ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_NOT_BETWEEN:
+ appendStringInfoString(str, " NOT_BETWEEN ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_BETWEEN_SYM:
+ appendStringInfoString(str, " BETWEEN_SYM ");
+ WRITE_NODE_FIELD(name);
+ break;
+ case AEXPR_NOT_BETWEEN_SYM:
+ appendStringInfoString(str, " NOT_BETWEEN_SYM ");
+ WRITE_NODE_FIELD(name);
+ break;
+ default:
+ appendStringInfoString(str, " ??");
+ break;
+ }
+
+ WRITE_NODE_FIELD(lexpr);
+ WRITE_NODE_FIELD(rexpr);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outInteger(StringInfo str, const Integer *node)
+{
+ appendStringInfo(str, "%d", node->ival);
+}
+
+static void
+_outFloat(StringInfo str, const Float *node)
+{
+ /*
+ * We assume the value is a valid numeric literal and so does not need
+ * quoting.
+ */
+ appendStringInfoString(str, node->fval);
+}
+
+static void
+_outBoolean(StringInfo str, const Boolean *node)
+{
+ appendStringInfoString(str, node->boolval ? "true" : "false");
+}
+
+static void
+_outString(StringInfo str, const String *node)
+{
+ /*
+ * We use outToken to provide escaping of the string's content, but we
+ * don't want it to do anything with an empty string.
+ */
+ appendStringInfoChar(str, '"');
+ if (node->sval[0] != '\0')
+ outToken(str, node->sval);
+ appendStringInfoChar(str, '"');
+}
+
+static void
+_outBitString(StringInfo str, const BitString *node)
+{
+ /* internal representation already has leading 'b' */
+ appendStringInfoString(str, node->bsval);
+}
+
+static void
+_outColumnRef(StringInfo str, const ColumnRef *node)
+{
+ WRITE_NODE_TYPE("COLUMNREF");
+
+ WRITE_NODE_FIELD(fields);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outParamRef(StringInfo str, const ParamRef *node)
+{
+ WRITE_NODE_TYPE("PARAMREF");
+
+ WRITE_INT_FIELD(number);
+ WRITE_LOCATION_FIELD(location);
+}
+
+/*
+ * Node types found in raw parse trees (supported for debug purposes)
+ */
+
+static void
+_outRawStmt(StringInfo str, const RawStmt *node)
+{
+ WRITE_NODE_TYPE("RAWSTMT");
+
+ WRITE_NODE_FIELD(stmt);
+ WRITE_LOCATION_FIELD(stmt_location);
+ WRITE_INT_FIELD(stmt_len);
+}
+
+static void
+_outA_Const(StringInfo str, const A_Const *node)
+{
+ WRITE_NODE_TYPE("A_CONST");
+
+ if (node->isnull)
+ appendStringInfoString(str, " NULL");
+ else
+ {
+ appendStringInfoString(str, " :val ");
+ outNode(str, &node->val);
+ }
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outA_Star(StringInfo str, const A_Star *node)
+{
+ WRITE_NODE_TYPE("A_STAR");
+}
+
+static void
+_outA_Indices(StringInfo str, const A_Indices *node)
+{
+ WRITE_NODE_TYPE("A_INDICES");
+
+ WRITE_BOOL_FIELD(is_slice);
+ WRITE_NODE_FIELD(lidx);
+ WRITE_NODE_FIELD(uidx);
+}
+
+static void
+_outA_Indirection(StringInfo str, const A_Indirection *node)
+{
+ WRITE_NODE_TYPE("A_INDIRECTION");
+
+ WRITE_NODE_FIELD(arg);
+ WRITE_NODE_FIELD(indirection);
+}
+
+static void
+_outA_ArrayExpr(StringInfo str, const A_ArrayExpr *node)
+{
+ WRITE_NODE_TYPE("A_ARRAYEXPR");
+
+ WRITE_NODE_FIELD(elements);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outResTarget(StringInfo str, const ResTarget *node)
+{
+ WRITE_NODE_TYPE("RESTARGET");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_NODE_FIELD(indirection);
+ WRITE_NODE_FIELD(val);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outMultiAssignRef(StringInfo str, const MultiAssignRef *node)
+{
+ WRITE_NODE_TYPE("MULTIASSIGNREF");
+
+ WRITE_NODE_FIELD(source);
+ WRITE_INT_FIELD(colno);
+ WRITE_INT_FIELD(ncolumns);
+}
+
+static void
+_outSortBy(StringInfo str, const SortBy *node)
+{
+ WRITE_NODE_TYPE("SORTBY");
+
+ WRITE_NODE_FIELD(node);
+ WRITE_ENUM_FIELD(sortby_dir, SortByDir);
+ WRITE_ENUM_FIELD(sortby_nulls, SortByNulls);
+ WRITE_NODE_FIELD(useOp);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outWindowDef(StringInfo str, const WindowDef *node)
+{
+ WRITE_NODE_TYPE("WINDOWDEF");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_STRING_FIELD(refname);
+ WRITE_NODE_FIELD(partitionClause);
+ WRITE_NODE_FIELD(orderClause);
+ WRITE_INT_FIELD(frameOptions);
+ WRITE_NODE_FIELD(startOffset);
+ WRITE_NODE_FIELD(endOffset);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outRangeSubselect(StringInfo str, const RangeSubselect *node)
+{
+ WRITE_NODE_TYPE("RANGESUBSELECT");
+
+ WRITE_BOOL_FIELD(lateral);
+ WRITE_NODE_FIELD(subquery);
+ WRITE_NODE_FIELD(alias);
+}
+
+static void
+_outRangeFunction(StringInfo str, const RangeFunction *node)
+{
+ WRITE_NODE_TYPE("RANGEFUNCTION");
+
+ WRITE_BOOL_FIELD(lateral);
+ WRITE_BOOL_FIELD(ordinality);
+ WRITE_BOOL_FIELD(is_rowsfrom);
+ WRITE_NODE_FIELD(functions);
+ WRITE_NODE_FIELD(alias);
+ WRITE_NODE_FIELD(coldeflist);
+}
+
+static void
+_outRangeTableSample(StringInfo str, const RangeTableSample *node)
+{
+ WRITE_NODE_TYPE("RANGETABLESAMPLE");
+
+ WRITE_NODE_FIELD(relation);
+ WRITE_NODE_FIELD(method);
+ WRITE_NODE_FIELD(args);
+ WRITE_NODE_FIELD(repeatable);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outRangeTableFunc(StringInfo str, const RangeTableFunc *node)
+{
+ WRITE_NODE_TYPE("RANGETABLEFUNC");
+
+ WRITE_BOOL_FIELD(lateral);
+ WRITE_NODE_FIELD(docexpr);
+ WRITE_NODE_FIELD(rowexpr);
+ WRITE_NODE_FIELD(namespaces);
+ WRITE_NODE_FIELD(columns);
+ WRITE_NODE_FIELD(alias);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outRangeTableFuncCol(StringInfo str, const RangeTableFuncCol *node)
+{
+ WRITE_NODE_TYPE("RANGETABLEFUNCCOL");
+
+ WRITE_STRING_FIELD(colname);
+ WRITE_NODE_FIELD(typeName);
+ WRITE_BOOL_FIELD(for_ordinality);
+ WRITE_BOOL_FIELD(is_not_null);
+ WRITE_NODE_FIELD(colexpr);
+ WRITE_NODE_FIELD(coldefexpr);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outConstraint(StringInfo str, const Constraint *node)
+{
+ WRITE_NODE_TYPE("CONSTRAINT");
+
+ WRITE_STRING_FIELD(conname);
+ WRITE_BOOL_FIELD(deferrable);
+ WRITE_BOOL_FIELD(initdeferred);
+ WRITE_LOCATION_FIELD(location);
+
+ appendStringInfoString(str, " :contype ");
+ switch (node->contype)
+ {
+ case CONSTR_NULL:
+ appendStringInfoString(str, "NULL");
+ break;
+
+ case CONSTR_NOTNULL:
+ appendStringInfoString(str, "NOT_NULL");
+ break;
+
+ case CONSTR_DEFAULT:
+ appendStringInfoString(str, "DEFAULT");
+ WRITE_NODE_FIELD(raw_expr);
+ WRITE_STRING_FIELD(cooked_expr);
+ break;
+
+ case CONSTR_IDENTITY:
+ appendStringInfoString(str, "IDENTITY");
+ WRITE_NODE_FIELD(options);
+ WRITE_CHAR_FIELD(generated_when);
+ break;
+
+ case CONSTR_GENERATED:
+ appendStringInfoString(str, "GENERATED");
+ WRITE_NODE_FIELD(raw_expr);
+ WRITE_STRING_FIELD(cooked_expr);
+ WRITE_CHAR_FIELD(generated_when);
+ break;
+
+ case CONSTR_CHECK:
+ appendStringInfoString(str, "CHECK");
+ WRITE_BOOL_FIELD(is_no_inherit);
+ WRITE_NODE_FIELD(raw_expr);
+ WRITE_STRING_FIELD(cooked_expr);
+ WRITE_BOOL_FIELD(skip_validation);
+ WRITE_BOOL_FIELD(initially_valid);
+ break;
+
+ case CONSTR_PRIMARY:
+ appendStringInfoString(str, "PRIMARY_KEY");
+ WRITE_NODE_FIELD(keys);
+ WRITE_NODE_FIELD(including);
+ WRITE_NODE_FIELD(options);
+ WRITE_STRING_FIELD(indexname);
+ WRITE_STRING_FIELD(indexspace);
+ WRITE_BOOL_FIELD(reset_default_tblspc);
+ /* access_method and where_clause not currently used */
+ break;
+
+ case CONSTR_UNIQUE:
+ appendStringInfoString(str, "UNIQUE");
+ WRITE_BOOL_FIELD(nulls_not_distinct);
+ WRITE_NODE_FIELD(keys);
+ WRITE_NODE_FIELD(including);
+ WRITE_NODE_FIELD(options);
+ WRITE_STRING_FIELD(indexname);
+ WRITE_STRING_FIELD(indexspace);
+ WRITE_BOOL_FIELD(reset_default_tblspc);
+ /* access_method and where_clause not currently used */
+ break;
+
+ case CONSTR_EXCLUSION:
+ appendStringInfoString(str, "EXCLUSION");
+ WRITE_NODE_FIELD(exclusions);
+ WRITE_NODE_FIELD(including);
+ WRITE_NODE_FIELD(options);
+ WRITE_STRING_FIELD(indexname);
+ WRITE_STRING_FIELD(indexspace);
+ WRITE_BOOL_FIELD(reset_default_tblspc);
+ WRITE_STRING_FIELD(access_method);
+ WRITE_NODE_FIELD(where_clause);
+ break;
+
+ case CONSTR_FOREIGN:
+ appendStringInfoString(str, "FOREIGN_KEY");
+ WRITE_NODE_FIELD(pktable);
+ WRITE_NODE_FIELD(fk_attrs);
+ WRITE_NODE_FIELD(pk_attrs);
+ WRITE_CHAR_FIELD(fk_matchtype);
+ WRITE_CHAR_FIELD(fk_upd_action);
+ WRITE_CHAR_FIELD(fk_del_action);
+ WRITE_NODE_FIELD(fk_del_set_cols);
+ WRITE_NODE_FIELD(old_conpfeqop);
+ WRITE_OID_FIELD(old_pktable_oid);
+ WRITE_BOOL_FIELD(skip_validation);
+ WRITE_BOOL_FIELD(initially_valid);
+ break;
+
+ case CONSTR_ATTR_DEFERRABLE:
+ appendStringInfoString(str, "ATTR_DEFERRABLE");
+ break;
+
+ case CONSTR_ATTR_NOT_DEFERRABLE:
+ appendStringInfoString(str, "ATTR_NOT_DEFERRABLE");
+ break;
+
+ case CONSTR_ATTR_DEFERRED:
+ appendStringInfoString(str, "ATTR_DEFERRED");
+ break;
+
+ case CONSTR_ATTR_IMMEDIATE:
+ appendStringInfoString(str, "ATTR_IMMEDIATE");
+ break;
+
+ default:
+ appendStringInfo(str, "<unrecognized_constraint %d>",
+ (int) node->contype);
+ break;
+ }
+}
+
+static void
+_outForeignKeyCacheInfo(StringInfo str, const ForeignKeyCacheInfo *node)
+{
+ WRITE_NODE_TYPE("FOREIGNKEYCACHEINFO");
+
+ WRITE_OID_FIELD(conoid);
+ WRITE_OID_FIELD(conrelid);
+ WRITE_OID_FIELD(confrelid);
+ WRITE_INT_FIELD(nkeys);
+ WRITE_ATTRNUMBER_ARRAY(conkey, node->nkeys);
+ WRITE_ATTRNUMBER_ARRAY(confkey, node->nkeys);
+ WRITE_OID_ARRAY(conpfeqop, node->nkeys);
+}
+
+static void
+_outPartitionElem(StringInfo str, const PartitionElem *node)
+{
+ WRITE_NODE_TYPE("PARTITIONELEM");
+
+ WRITE_STRING_FIELD(name);
+ WRITE_NODE_FIELD(expr);
+ WRITE_NODE_FIELD(collation);
+ WRITE_NODE_FIELD(opclass);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outPartitionSpec(StringInfo str, const PartitionSpec *node)
+{
+ WRITE_NODE_TYPE("PARTITIONSPEC");
+
+ WRITE_STRING_FIELD(strategy);
+ WRITE_NODE_FIELD(partParams);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outPartitionBoundSpec(StringInfo str, const PartitionBoundSpec *node)
+{
+ WRITE_NODE_TYPE("PARTITIONBOUNDSPEC");
+
+ WRITE_CHAR_FIELD(strategy);
+ WRITE_BOOL_FIELD(is_default);
+ WRITE_INT_FIELD(modulus);
+ WRITE_INT_FIELD(remainder);
+ WRITE_NODE_FIELD(listdatums);
+ WRITE_NODE_FIELD(lowerdatums);
+ WRITE_NODE_FIELD(upperdatums);
+ WRITE_LOCATION_FIELD(location);
+}
+
+static void
+_outPartitionRangeDatum(StringInfo str, const PartitionRangeDatum *node)
+{
+ WRITE_NODE_TYPE("PARTITIONRANGEDATUM");
+
+ WRITE_ENUM_FIELD(kind, PartitionRangeDatumKind);
+ WRITE_NODE_FIELD(value);
+ WRITE_LOCATION_FIELD(location);
+}
+
+/*
+ * outNode -
+ * converts a Node into ascii string and append it to 'str'
+ */
+void
+outNode(StringInfo str, const void *obj)
+{
+ /* Guard against stack overflow due to overly complex expressions */
+ check_stack_depth();
+
+ if (obj == NULL)
+ appendStringInfoString(str, "<>");
+ else if (IsA(obj, List) || IsA(obj, IntList) || IsA(obj, OidList))
+ _outList(str, obj);
+ /* nodeRead does not want to see { } around these! */
+ else if (IsA(obj, Integer))
+ _outInteger(str, (Integer *) obj);
+ else if (IsA(obj, Float))
+ _outFloat(str, (Float *) obj);
+ else if (IsA(obj, Boolean))
+ _outBoolean(str, (Boolean *) obj);
+ else if (IsA(obj, String))
+ _outString(str, (String *) obj);
+ else if (IsA(obj, BitString))
+ _outBitString(str, (BitString *) obj);
+ else
+ {
+ appendStringInfoChar(str, '{');
+ switch (nodeTag(obj))
+ {
+ case T_PlannedStmt:
+ _outPlannedStmt(str, obj);
+ break;
+ case T_Plan:
+ _outPlan(str, obj);
+ break;
+ case T_Result:
+ _outResult(str, obj);
+ break;
+ case T_ProjectSet:
+ _outProjectSet(str, obj);
+ break;
+ case T_ModifyTable:
+ _outModifyTable(str, obj);
+ break;
+ case T_Append:
+ _outAppend(str, obj);
+ break;
+ case T_MergeAppend:
+ _outMergeAppend(str, obj);
+ break;
+ case T_RecursiveUnion:
+ _outRecursiveUnion(str, obj);
+ break;
+ case T_BitmapAnd:
+ _outBitmapAnd(str, obj);
+ break;
+ case T_BitmapOr:
+ _outBitmapOr(str, obj);
+ break;
+ case T_Gather:
+ _outGather(str, obj);
+ break;
+ case T_GatherMerge:
+ _outGatherMerge(str, obj);
+ break;
+ case T_Scan:
+ _outScan(str, obj);
+ break;
+ case T_SeqScan:
+ _outSeqScan(str, obj);
+ break;
+ case T_SampleScan:
+ _outSampleScan(str, obj);
+ break;
+ case T_IndexScan:
+ _outIndexScan(str, obj);
+ break;
+ case T_IndexOnlyScan:
+ _outIndexOnlyScan(str, obj);
+ break;
+ case T_BitmapIndexScan:
+ _outBitmapIndexScan(str, obj);
+ break;
+ case T_BitmapHeapScan:
+ _outBitmapHeapScan(str, obj);
+ break;
+ case T_TidScan:
+ _outTidScan(str, obj);
+ break;
+ case T_TidRangeScan:
+ _outTidRangeScan(str, obj);
+ break;
+ case T_SubqueryScan:
+ _outSubqueryScan(str, obj);
+ break;
+ case T_FunctionScan:
+ _outFunctionScan(str, obj);
+ break;
+ case T_TableFuncScan:
+ _outTableFuncScan(str, obj);
+ break;
+ case T_ValuesScan:
+ _outValuesScan(str, obj);
+ break;
+ case T_CteScan:
+ _outCteScan(str, obj);
+ break;
+ case T_NamedTuplestoreScan:
+ _outNamedTuplestoreScan(str, obj);
+ break;
+ case T_WorkTableScan:
+ _outWorkTableScan(str, obj);
+ break;
+ case T_ForeignScan:
+ _outForeignScan(str, obj);
+ break;
+ case T_CustomScan:
+ _outCustomScan(str, obj);
+ break;
+ case T_Join:
+ _outJoin(str, obj);
+ break;
+ case T_NestLoop:
+ _outNestLoop(str, obj);
+ break;
+ case T_MergeJoin:
+ _outMergeJoin(str, obj);
+ break;
+ case T_HashJoin:
+ _outHashJoin(str, obj);
+ break;
+ case T_Agg:
+ _outAgg(str, obj);
+ break;
+ case T_WindowAgg:
+ _outWindowAgg(str, obj);
+ break;
+ case T_Group:
+ _outGroup(str, obj);
+ break;
+ case T_Material:
+ _outMaterial(str, obj);
+ break;
+ case T_Memoize:
+ _outMemoize(str, obj);
+ break;
+ case T_Sort:
+ _outSort(str, obj);
+ break;
+ case T_IncrementalSort:
+ _outIncrementalSort(str, obj);
+ break;
+ case T_Unique:
+ _outUnique(str, obj);
+ break;
+ case T_Hash:
+ _outHash(str, obj);
+ break;
+ case T_SetOp:
+ _outSetOp(str, obj);
+ break;
+ case T_LockRows:
+ _outLockRows(str, obj);
+ break;
+ case T_Limit:
+ _outLimit(str, obj);
+ break;
+ case T_NestLoopParam:
+ _outNestLoopParam(str, obj);
+ break;
+ case T_PlanRowMark:
+ _outPlanRowMark(str, obj);
+ break;
+ case T_PartitionPruneInfo:
+ _outPartitionPruneInfo(str, obj);
+ break;
+ case T_PartitionedRelPruneInfo:
+ _outPartitionedRelPruneInfo(str, obj);
+ break;
+ case T_PartitionPruneStepOp:
+ _outPartitionPruneStepOp(str, obj);
+ break;
+ case T_PartitionPruneStepCombine:
+ _outPartitionPruneStepCombine(str, obj);
+ break;
+ case T_PlanInvalItem:
+ _outPlanInvalItem(str, obj);
+ break;
+ case T_Alias:
+ _outAlias(str, obj);
+ break;
+ case T_RangeVar:
+ _outRangeVar(str, obj);
+ break;
+ case T_TableFunc:
+ _outTableFunc(str, obj);
+ break;
+ case T_IntoClause:
+ _outIntoClause(str, obj);
+ break;
+ case T_Var:
+ _outVar(str, obj);
+ break;
+ case T_Const:
+ _outConst(str, obj);
+ break;
+ case T_Param:
+ _outParam(str, obj);
+ break;
+ case T_Aggref:
+ _outAggref(str, obj);
+ break;
+ case T_GroupingFunc:
+ _outGroupingFunc(str, obj);
+ break;
+ case T_WindowFunc:
+ _outWindowFunc(str, obj);
+ break;
+ case T_SubscriptingRef:
+ _outSubscriptingRef(str, obj);
+ break;
+ case T_FuncExpr:
+ _outFuncExpr(str, obj);
+ break;
+ case T_NamedArgExpr:
+ _outNamedArgExpr(str, obj);
+ break;
+ case T_OpExpr:
+ _outOpExpr(str, obj);
+ break;
+ case T_DistinctExpr:
+ _outDistinctExpr(str, obj);
+ break;
+ case T_NullIfExpr:
+ _outNullIfExpr(str, obj);
+ break;
+ case T_ScalarArrayOpExpr:
+ _outScalarArrayOpExpr(str, obj);
+ break;
+ case T_BoolExpr:
+ _outBoolExpr(str, obj);
+ break;
+ case T_SubLink:
+ _outSubLink(str, obj);
+ break;
+ case T_SubPlan:
+ _outSubPlan(str, obj);
+ break;
+ case T_AlternativeSubPlan:
+ _outAlternativeSubPlan(str, obj);
+ break;
+ case T_FieldSelect:
+ _outFieldSelect(str, obj);
+ break;
+ case T_FieldStore:
+ _outFieldStore(str, obj);
+ break;
+ case T_RelabelType:
+ _outRelabelType(str, obj);
+ break;
+ case T_CoerceViaIO:
+ _outCoerceViaIO(str, obj);
+ break;
+ case T_ArrayCoerceExpr:
+ _outArrayCoerceExpr(str, obj);
+ break;
+ case T_ConvertRowtypeExpr:
+ _outConvertRowtypeExpr(str, obj);
+ break;
+ case T_CollateExpr:
+ _outCollateExpr(str, obj);
+ break;
+ case T_CaseExpr:
+ _outCaseExpr(str, obj);
+ break;
+ case T_CaseWhen:
+ _outCaseWhen(str, obj);
+ break;
+ case T_CaseTestExpr:
+ _outCaseTestExpr(str, obj);
+ break;
+ case T_ArrayExpr:
+ _outArrayExpr(str, obj);
+ break;
+ case T_RowExpr:
+ _outRowExpr(str, obj);
+ break;
+ case T_RowCompareExpr:
+ _outRowCompareExpr(str, obj);
+ break;
+ case T_CoalesceExpr:
+ _outCoalesceExpr(str, obj);
+ break;
+ case T_MinMaxExpr:
+ _outMinMaxExpr(str, obj);
+ break;
+ case T_SQLValueFunction:
+ _outSQLValueFunction(str, obj);
+ break;
+ case T_XmlExpr:
+ _outXmlExpr(str, obj);
+ break;
+ case T_NullTest:
+ _outNullTest(str, obj);
+ break;
+ case T_BooleanTest:
+ _outBooleanTest(str, obj);
+ break;
+ case T_CoerceToDomain:
+ _outCoerceToDomain(str, obj);
+ break;
+ case T_CoerceToDomainValue:
+ _outCoerceToDomainValue(str, obj);
+ break;
+ case T_SetToDefault:
+ _outSetToDefault(str, obj);
+ break;
+ case T_CurrentOfExpr:
+ _outCurrentOfExpr(str, obj);
+ break;
+ case T_NextValueExpr:
+ _outNextValueExpr(str, obj);
+ break;
+ case T_InferenceElem:
+ _outInferenceElem(str, obj);
+ break;
+ case T_TargetEntry:
+ _outTargetEntry(str, obj);
+ break;
+ case T_RangeTblRef:
+ _outRangeTblRef(str, obj);
+ break;
+ case T_JoinExpr:
+ _outJoinExpr(str, obj);
+ break;
+ case T_FromExpr:
+ _outFromExpr(str, obj);
+ break;
+ case T_OnConflictExpr:
+ _outOnConflictExpr(str, obj);
+ break;
+ case T_Path:
+ _outPath(str, obj);
+ break;
+ case T_IndexPath:
+ _outIndexPath(str, obj);
+ break;
+ case T_BitmapHeapPath:
+ _outBitmapHeapPath(str, obj);
+ break;
+ case T_BitmapAndPath:
+ _outBitmapAndPath(str, obj);
+ break;
+ case T_BitmapOrPath:
+ _outBitmapOrPath(str, obj);
+ break;
+ case T_TidPath:
+ _outTidPath(str, obj);
+ break;
+ case T_TidRangePath:
+ _outTidRangePath(str, obj);
+ break;
+ case T_SubqueryScanPath:
+ _outSubqueryScanPath(str, obj);
+ break;
+ case T_ForeignPath:
+ _outForeignPath(str, obj);
+ break;
+ case T_CustomPath:
+ _outCustomPath(str, obj);
+ break;
+ case T_AppendPath:
+ _outAppendPath(str, obj);
+ break;
+ case T_MergeAppendPath:
+ _outMergeAppendPath(str, obj);
+ break;
+ case T_GroupResultPath:
+ _outGroupResultPath(str, obj);
+ break;
+ case T_MaterialPath:
+ _outMaterialPath(str, obj);
+ break;
+ case T_MemoizePath:
+ _outMemoizePath(str, obj);
+ break;
+ case T_UniquePath:
+ _outUniquePath(str, obj);
+ break;
+ case T_GatherPath:
+ _outGatherPath(str, obj);
+ break;
+ case T_ProjectionPath:
+ _outProjectionPath(str, obj);
+ break;
+ case T_ProjectSetPath:
+ _outProjectSetPath(str, obj);
+ break;
+ case T_SortPath:
+ _outSortPath(str, obj);
+ break;
+ case T_IncrementalSortPath:
+ _outIncrementalSortPath(str, obj);
+ break;
+ case T_GroupPath:
+ _outGroupPath(str, obj);
+ break;
+ case T_UpperUniquePath:
+ _outUpperUniquePath(str, obj);
+ break;
+ case T_AggPath:
+ _outAggPath(str, obj);
+ break;
+ case T_GroupingSetsPath:
+ _outGroupingSetsPath(str, obj);
+ break;
+ case T_MinMaxAggPath:
+ _outMinMaxAggPath(str, obj);
+ break;
+ case T_WindowAggPath:
+ _outWindowAggPath(str, obj);
+ break;
+ case T_SetOpPath:
+ _outSetOpPath(str, obj);
+ break;
+ case T_RecursiveUnionPath:
+ _outRecursiveUnionPath(str, obj);
+ break;
+ case T_LockRowsPath:
+ _outLockRowsPath(str, obj);
+ break;
+ case T_ModifyTablePath:
+ _outModifyTablePath(str, obj);
+ break;
+ case T_LimitPath:
+ _outLimitPath(str, obj);
+ break;
+ case T_GatherMergePath:
+ _outGatherMergePath(str, obj);
+ break;
+ case T_NestPath:
+ _outNestPath(str, obj);
+ break;
+ case T_MergePath:
+ _outMergePath(str, obj);
+ break;
+ case T_HashPath:
+ _outHashPath(str, obj);
+ break;
+ case T_PlannerGlobal:
+ _outPlannerGlobal(str, obj);
+ break;
+ case T_PlannerInfo:
+ _outPlannerInfo(str, obj);
+ break;
+ case T_RelOptInfo:
+ _outRelOptInfo(str, obj);
+ break;
+ case T_IndexOptInfo:
+ _outIndexOptInfo(str, obj);
+ break;
+ case T_ForeignKeyOptInfo:
+ _outForeignKeyOptInfo(str, obj);
+ break;
+ case T_EquivalenceClass:
+ _outEquivalenceClass(str, obj);
+ break;
+ case T_EquivalenceMember:
+ _outEquivalenceMember(str, obj);
+ break;
+ case T_PathKey:
+ _outPathKey(str, obj);
+ break;
+ case T_PathTarget:
+ _outPathTarget(str, obj);
+ break;
+ case T_ParamPathInfo:
+ _outParamPathInfo(str, obj);
+ break;
+ case T_RestrictInfo:
+ _outRestrictInfo(str, obj);
+ break;
+ case T_IndexClause:
+ _outIndexClause(str, obj);
+ break;
+ case T_PlaceHolderVar:
+ _outPlaceHolderVar(str, obj);
+ break;
+ case T_SpecialJoinInfo:
+ _outSpecialJoinInfo(str, obj);
+ break;
+ case T_AppendRelInfo:
+ _outAppendRelInfo(str, obj);
+ break;
+ case T_RowIdentityVarInfo:
+ _outRowIdentityVarInfo(str, obj);
+ break;
+ case T_PlaceHolderInfo:
+ _outPlaceHolderInfo(str, obj);
+ break;
+ case T_MinMaxAggInfo:
+ _outMinMaxAggInfo(str, obj);
+ break;
+ case T_PlannerParamItem:
+ _outPlannerParamItem(str, obj);
+ break;
+ case T_RollupData:
+ _outRollupData(str, obj);
+ break;
+ case T_GroupingSetData:
+ _outGroupingSetData(str, obj);
+ break;
+ case T_StatisticExtInfo:
+ _outStatisticExtInfo(str, obj);
+ break;
+ case T_ExtensibleNode:
+ _outExtensibleNode(str, obj);
+ break;
+ case T_CreateStmt:
+ _outCreateStmt(str, obj);
+ break;
+ case T_CreateForeignTableStmt:
+ _outCreateForeignTableStmt(str, obj);
+ break;
+ case T_ImportForeignSchemaStmt:
+ _outImportForeignSchemaStmt(str, obj);
+ break;
+ case T_IndexStmt:
+ _outIndexStmt(str, obj);
+ break;
+ case T_CreateStatsStmt:
+ _outCreateStatsStmt(str, obj);
+ break;
+ case T_AlterStatsStmt:
+ _outAlterStatsStmt(str, obj);
+ break;
+ case T_NotifyStmt:
+ _outNotifyStmt(str, obj);
+ break;
+ case T_DeclareCursorStmt:
+ _outDeclareCursorStmt(str, obj);
+ break;
+ case T_SelectStmt:
+ _outSelectStmt(str, obj);
+ break;
+ case T_ReturnStmt:
+ _outReturnStmt(str, obj);
+ break;
+ case T_PLAssignStmt:
+ _outPLAssignStmt(str, obj);
+ break;
+ case T_ColumnDef:
+ _outColumnDef(str, obj);
+ break;
+ case T_TypeName:
+ _outTypeName(str, obj);
+ break;
+ case T_TypeCast:
+ _outTypeCast(str, obj);
+ break;
+ case T_CollateClause:
+ _outCollateClause(str, obj);
+ break;
+ case T_IndexElem:
+ _outIndexElem(str, obj);
+ break;
+ case T_StatsElem:
+ _outStatsElem(str, obj);
+ break;
+ case T_Query:
+ _outQuery(str, obj);
+ break;
+ case T_WithCheckOption:
+ _outWithCheckOption(str, obj);
+ break;
+ case T_SortGroupClause:
+ _outSortGroupClause(str, obj);
+ break;
+ case T_GroupingSet:
+ _outGroupingSet(str, obj);
+ break;
+ case T_WindowClause:
+ _outWindowClause(str, obj);
+ break;
+ case T_RowMarkClause:
+ _outRowMarkClause(str, obj);
+ break;
+ case T_WithClause:
+ _outWithClause(str, obj);
+ break;
+ case T_CTESearchClause:
+ _outCTESearchClause(str, obj);
+ break;
+ case T_CTECycleClause:
+ _outCTECycleClause(str, obj);
+ break;
+ case T_CommonTableExpr:
+ _outCommonTableExpr(str, obj);
+ break;
+ case T_MergeWhenClause:
+ _outMergeWhenClause(str, obj);
+ break;
+ case T_MergeAction:
+ _outMergeAction(str, obj);
+ break;
+ case T_SetOperationStmt:
+ _outSetOperationStmt(str, obj);
+ break;
+ case T_RangeTblEntry:
+ _outRangeTblEntry(str, obj);
+ break;
+ case T_RangeTblFunction:
+ _outRangeTblFunction(str, obj);
+ break;
+ case T_TableSampleClause:
+ _outTableSampleClause(str, obj);
+ break;
+ case T_A_Expr:
+ _outA_Expr(str, obj);
+ break;
+ case T_ColumnRef:
+ _outColumnRef(str, obj);
+ break;
+ case T_ParamRef:
+ _outParamRef(str, obj);
+ break;
+ case T_RawStmt:
+ _outRawStmt(str, obj);
+ break;
+ case T_A_Const:
+ _outA_Const(str, obj);
+ break;
+ case T_A_Star:
+ _outA_Star(str, obj);
+ break;
+ case T_A_Indices:
+ _outA_Indices(str, obj);
+ break;
+ case T_A_Indirection:
+ _outA_Indirection(str, obj);
+ break;
+ case T_A_ArrayExpr:
+ _outA_ArrayExpr(str, obj);
+ break;
+ case T_ResTarget:
+ _outResTarget(str, obj);
+ break;
+ case T_MultiAssignRef:
+ _outMultiAssignRef(str, obj);
+ break;
+ case T_SortBy:
+ _outSortBy(str, obj);
+ break;
+ case T_WindowDef:
+ _outWindowDef(str, obj);
+ break;
+ case T_RangeSubselect:
+ _outRangeSubselect(str, obj);
+ break;
+ case T_RangeFunction:
+ _outRangeFunction(str, obj);
+ break;
+ case T_RangeTableSample:
+ _outRangeTableSample(str, obj);
+ break;
+ case T_RangeTableFunc:
+ _outRangeTableFunc(str, obj);
+ break;
+ case T_RangeTableFuncCol:
+ _outRangeTableFuncCol(str, obj);
+ break;
+ case T_Constraint:
+ _outConstraint(str, obj);
+ break;
+ case T_FuncCall:
+ _outFuncCall(str, obj);
+ break;
+ case T_DefElem:
+ _outDefElem(str, obj);
+ break;
+ case T_TableLikeClause:
+ _outTableLikeClause(str, obj);
+ break;
+ case T_LockingClause:
+ _outLockingClause(str, obj);
+ break;
+ case T_XmlSerialize:
+ _outXmlSerialize(str, obj);
+ break;
+ case T_ForeignKeyCacheInfo:
+ _outForeignKeyCacheInfo(str, obj);
+ break;
+ case T_TriggerTransition:
+ _outTriggerTransition(str, obj);
+ break;
+ case T_PartitionElem:
+ _outPartitionElem(str, obj);
+ break;
+ case T_PartitionSpec:
+ _outPartitionSpec(str, obj);
+ break;
+ case T_PartitionBoundSpec:
+ _outPartitionBoundSpec(str, obj);
+ break;
+ case T_PartitionRangeDatum:
+ _outPartitionRangeDatum(str, obj);
+ break;
+
+ default:
+
+ /*
+ * This should be an ERROR, but it's too useful to be able to
+ * dump structures that outNode only understands part of.
+ */
+ elog(WARNING, "could not dump unrecognized node type: %d",
+ (int) nodeTag(obj));
+ break;
+ }
+ appendStringInfoChar(str, '}');
+ }
+}
+
+/*
+ * nodeToString -
+ * returns the ascii representation of the Node as a palloc'd string
+ */
+char *
+nodeToString(const void *obj)
+{
+ StringInfoData str;
+
+ /* see stringinfo.h for an explanation of this maneuver */
+ initStringInfo(&str);
+ outNode(&str, obj);
+ return str.data;
+}
+
+/*
+ * bmsToString -
+ * returns the ascii representation of the Bitmapset as a palloc'd string
+ */
+char *
+bmsToString(const Bitmapset *bms)
+{
+ StringInfoData str;
+
+ /* see stringinfo.h for an explanation of this maneuver */
+ initStringInfo(&str);
+ outBitmapset(&str, bms);
+ return str.data;
+}