diff options
Diffstat (limited to 'src/backend/nodes/outfuncs.c')
-rw-r--r-- | src/backend/nodes/outfuncs.c | 4568 |
1 files changed, 4568 insertions, 0 deletions
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c new file mode 100644 index 0000000..0df9be1 --- /dev/null +++ b/src/backend/nodes/outfuncs.c @@ -0,0 +1,4568 @@ +/*------------------------------------------------------------------------- + * + * outfuncs.c + * Output functions for Postgres tree nodes. + * + * Portions Copyright (c) 1996-2021, 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) + +#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); +} + +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); +} + +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_OID_FIELD(startInRangeFunc); + WRITE_OID_FIELD(endInRangeFunc); + WRITE_OID_FIELD(inRangeColl); + WRITE_BOOL_FIELD(inRangeAsc); + WRITE_BOOL_FIELD(inRangeNullsFirst); +} + +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_UINT_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_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("COLLATE"); + + WRITE_NODE_FIELD(arg); + WRITE_OID_FIELD(collOid); + WRITE_LOCATION_FIELD(location); +} + +static void +_outCaseExpr(StringInfo str, const CaseExpr *node) +{ + WRITE_NODE_TYPE("CASE"); + + 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("WHEN"); + + 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("ARRAY"); + + 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("ROW"); + + 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("ROWCOMPARE"); + + 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("COALESCE"); + + 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("MINMAX"); + + 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); +} + +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); +} + +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(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); + if (node->sortgrouprefs) + { + int i; + + appendStringInfoString(str, " :sortgrouprefs"); + for (i = 0; i < list_length(node->exprs); i++) + appendStringInfo(str, " %u", node->sortgrouprefs[i]); + } + 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(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(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("NOTIFY"); + + WRITE_STRING_FIELD(conditionname); + WRITE_STRING_FIELD(payload); +} + +static void +_outDeclareCursorStmt(StringInfo str, const DeclareCursorStmt *node) +{ + WRITE_NODE_TYPE("DECLARECURSOR"); + + 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_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_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 +_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("RTE"); + + /* 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 +_outAExpr(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 +_outValue(StringInfo str, const Value *value) +{ + switch (value->type) + { + case T_Integer: + appendStringInfo(str, "%d", value->val.ival); + break; + case T_Float: + + /* + * We assume the value is a valid numeric literal and so does not + * need quoting. + */ + appendStringInfoString(str, value->val.str); + break; + case T_String: + + /* + * 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 (value->val.str[0] != '\0') + outToken(str, value->val.str); + appendStringInfoChar(str, '"'); + break; + case T_BitString: + /* internal representation already has leading 'b' */ + appendStringInfoString(str, value->val.str); + break; + case T_Null: + /* this is seen only within A_Const, not in transformed trees */ + appendStringInfoString(str, "NULL"); + break; + default: + elog(ERROR, "unrecognized node type: %d", (int) value->type); + break; + } +} + +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 +_outAConst(StringInfo str, const A_Const *node) +{ + WRITE_NODE_TYPE("A_CONST"); + + appendStringInfoString(str, " :val "); + _outValue(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(raw_expr); + WRITE_STRING_FIELD(cooked_expr); + 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); + 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_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(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); + else if (IsA(obj, Integer) || + IsA(obj, Float) || + IsA(obj, String) || + IsA(obj, BitString)) + { + /* nodeRead does not want to see { } around these! */ + _outValue(str, 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_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: + _outAExpr(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: + _outAConst(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; +} |