* outfuncs.c
* Output functions for Postgres tree nodes.
*
- * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* 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). For use in debugging, we also provide output
- * functions for nodes that appear in raw parsetrees, path, and plan trees.
- * These nodes however need not have input functions.
+ * 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 path. These nodes however need
+ * not have input functions.
*
*-------------------------------------------------------------------------
*/
#include <ctype.h>
#include "lib/stringinfo.h"
+#include "nodes/extensible.h"
#include "nodes/plannodes.h"
#include "nodes/relation.h"
#include "utils/datum.h"
+#include "utils/rel.h"
/*
/* Write a character-string (possibly NULL) field */
#define WRITE_STRING_FIELD(fldname) \
(appendStringInfo(str, " :" CppAsString(fldname) " "), \
- _outToken(str, node->fldname))
+ outToken(str, node->fldname))
/* Write a parse location field (actually same as INT case) */
#define WRITE_LOCATION_FIELD(fldname) \
/* Write a Node field */
#define WRITE_NODE_FIELD(fldname) \
(appendStringInfo(str, " :" CppAsString(fldname) " "), \
- _outNode(str, node->fldname))
+ outNode(str, node->fldname))
/* Write a bitmapset field */
#define WRITE_BITMAPSET_FIELD(fldname) \
(appendStringInfo(str, " :" CppAsString(fldname) " "), \
- _outBitmapset(str, node->fldname))
+ outBitmapset(str, node->fldname))
#define booltostr(x) ((x) ? "true" : "false")
-static void _outNode(StringInfo str, const void *obj);
-
/*
- * _outToken
+ * 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 "<>".
*/
-static void
-_outToken(StringInfo str, const char *s)
+void
+outToken(StringInfo str, const char *s)
{
if (s == NULL || *s == '\0')
{
*/
/* These characters only need to be quoted at the start of the string */
if (*s == '<' ||
- *s == '\"' ||
+ *s == '"' ||
isdigit((unsigned char) *s) ||
((*s == '+' || *s == '-') &&
(isdigit((unsigned char) s[1]) || s[1] == '.')))
*/
if (IsA(node, List))
{
- _outNode(str, lfirst(lc));
+ outNode(str, lfirst(lc));
if (lnext(lc))
appendStringInfoChar(str, ' ');
}
}
/*
- * _outBitmapset -
+ * outBitmapset -
* converts a bitmap set of integers
*
* Note: the output format is "(b int int ...)", similar to an integer List.
*/
-static void
-_outBitmapset(StringInfo str, const Bitmapset *bms)
+void
+outBitmapset(StringInfo str, const Bitmapset *bms)
{
int x;
/*
* Print the value of a Datum given its type.
*/
-static void
-_outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
+void
+outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
{
Size length,
i;
WRITE_BOOL_FIELD(hasModifyingCTE);
WRITE_BOOL_FIELD(canSetTag);
WRITE_BOOL_FIELD(transientPlan);
+ WRITE_BOOL_FIELD(dependsOnRole);
+ WRITE_BOOL_FIELD(parallelModeNeeded);
WRITE_NODE_FIELD(planTree);
WRITE_NODE_FIELD(rtable);
WRITE_NODE_FIELD(resultRelations);
- WRITE_NODE_FIELD(utilityStmt);
WRITE_NODE_FIELD(subplans);
WRITE_BITMAPSET_FIELD(rewindPlanIDs);
WRITE_NODE_FIELD(rowMarks);
WRITE_NODE_FIELD(relationOids);
WRITE_NODE_FIELD(invalItems);
WRITE_INT_FIELD(nParamExec);
- WRITE_BOOL_FIELD(hasRowSecurity);
+ WRITE_NODE_FIELD(utilityStmt);
+ WRITE_LOCATION_FIELD(stmt_location);
+ WRITE_LOCATION_FIELD(stmt_len);
}
/*
WRITE_FLOAT_FIELD(total_cost, "%.2f");
WRITE_FLOAT_FIELD(plan_rows, "%.0f");
WRITE_INT_FIELD(plan_width);
+ WRITE_BOOL_FIELD(parallel_aware);
+ WRITE_INT_FIELD(plan_node_id);
WRITE_NODE_FIELD(targetlist);
WRITE_NODE_FIELD(qual);
WRITE_NODE_FIELD(lefttree);
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(onConflictWhere);
+ WRITE_UINT_FIELD(exclRelRTI);
+ WRITE_NODE_FIELD(exclRelTlist);
}
static void
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_BOOL_FIELD(single_copy);
+ WRITE_BOOL_FIELD(invisible);
+}
+
static void
_outScan(StringInfo str, const Scan *node)
{
_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_FIELD(indexqualorig);
WRITE_NODE_FIELD(indexorderby);
WRITE_NODE_FIELD(indexorderbyorig);
+ WRITE_NODE_FIELD(indexorderbyops);
WRITE_ENUM_FIELD(indexorderdir, ScanDirection);
}
_outScanInfo(str, (const Scan *) node);
+ WRITE_ENUM_FIELD(operation, CmdType);
+ 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);
}
_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);
- if (node->methods->TextOutCustomScan)
- node->methods->TextOutCustomScan(str, node);
+ outToken(str, node->methods->CustomName);
}
static void
appendStringInfoString(str, " :mergeNullsFirst");
for (i = 0; i < numCols; i++)
- appendStringInfo(str, " %d", (int) node->mergeNullsFirst[i]);
+ appendStringInfo(str, " %s", booltostr(node->mergeNullsFirst[i]));
}
static void
_outPlanInfo(str, (const Plan *) node);
WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
+ WRITE_ENUM_FIELD(aggsplit, AggSplit);
WRITE_INT_FIELD(numCols);
appendStringInfoString(str, " :grpColIdx");
appendStringInfo(str, " %u", node->grpOperators[i]);
WRITE_LONG_FIELD(numGroups);
+ WRITE_BITMAPSET_FIELD(aggParams);
+ WRITE_NODE_FIELD(groupingSets);
+ WRITE_NODE_FIELD(chain);
}
static void
WRITE_UINT_FIELD(prti);
WRITE_UINT_FIELD(rowmarkId);
WRITE_ENUM_FIELD(markType, RowMarkType);
- WRITE_BOOL_FIELD(waitPolicy);
+ WRITE_INT_FIELD(allMarkTypes);
+ WRITE_ENUM_FIELD(strength, LockClauseStrength);
+ WRITE_ENUM_FIELD(waitPolicy, LockWaitPolicy);
WRITE_BOOL_FIELD(isParent);
}
*/
WRITE_STRING_FIELD(schemaname);
WRITE_STRING_FIELD(relname);
- WRITE_ENUM_FIELD(inhOpt, InhOption);
+ WRITE_BOOL_FIELD(inh);
WRITE_CHAR_FIELD(relpersistence);
WRITE_NODE_FIELD(alias);
WRITE_LOCATION_FIELD(location);
if (node->constisnull)
appendStringInfoString(str, "<>");
else
- _outDatum(str, node->constvalue, node->constlen, node->constbyval);
+ outDatum(str, node->constvalue, node->constlen, node->constbyval);
}
static void
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_BOOL_FIELD(aggvariadic);
WRITE_CHAR_FIELD(aggkind);
WRITE_UINT_FIELD(agglevelsup);
+ WRITE_ENUM_FIELD(aggsplit, AggSplit);
+ 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);
}
break;
}
appendStringInfoString(str, " :boolop ");
- _outToken(str, opstr);
+ outToken(str, opstr);
WRITE_NODE_FIELD(args);
WRITE_LOCATION_FIELD(location);
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_INT_FIELD(cursor_param);
}
+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_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 relation.h.
*
* 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.
{
WRITE_ENUM_FIELD(pathtype, NodeTag);
appendStringInfoString(str, " :parent_relids ");
- if (node->parent)
- _outBitmapset(str, node->parent->relids);
- else
- _outBitmapset(str, NULL);
+ 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);
+ outBitmapset(str, node->param_info->ppi_req_outer);
else
- _outBitmapset(str, NULL);
+ 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(tidquals);
}
+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)
{
_outPathInfo(str, (const Path *) node);
+ WRITE_NODE_FIELD(fdw_outerpath);
WRITE_NODE_FIELD(fdw_private);
}
_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);
- if (node->methods->TextOutCustomPath)
- node->methods->TextOutCustomPath(str, node);
+ outToken(str, node->methods->CustomName);
}
static void
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);
+}
+
+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
+_outSortPath(StringInfo str, const SortPath *node)
+{
+ WRITE_NODE_TYPE("SORTPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+}
+
+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_NODE_FIELD(groupClause);
+ WRITE_NODE_FIELD(qual);
+}
+
+static void
+_outGroupingSetsPath(StringInfo str, const GroupingSetsPath *node)
+{
+ WRITE_NODE_TYPE("GROUPINGSETSPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_NODE_FIELD(rollup_groupclauses);
+ WRITE_NODE_FIELD(rollup_lists);
+ WRITE_NODE_FIELD(qual);
+}
+
+static void
+_outMinMaxAggPath(StringInfo str, const MinMaxAggPath *node)
+{
+ WRITE_NODE_TYPE("MINMAXAGGPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(mmaggregates);
+ WRITE_NODE_FIELD(quals);
+}
+
+static void
+_outWindowAggPath(StringInfo str, const WindowAggPath *node)
+{
+ WRITE_NODE_TYPE("WINDOWAGGPATH");
+
+ _outPathInfo(str, (const Path *) node);
+
+ WRITE_NODE_FIELD(subpath);
+ WRITE_NODE_FIELD(winclause);
+ WRITE_NODE_FIELD(winpathkeys);
+}
+
+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_ENUM_FIELD(operation, CmdType);
+ WRITE_BOOL_FIELD(canSetTag);
+ WRITE_UINT_FIELD(nominalRelation);
+ WRITE_NODE_FIELD(resultRelations);
+ WRITE_NODE_FIELD(subpaths);
+ WRITE_NODE_FIELD(subroots);
+ 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);
+}
+
static void
_outNestPath(StringInfo str, const NestPath *node)
{
WRITE_INT_FIELD(nParamExec);
WRITE_UINT_FIELD(lastPHId);
WRITE_UINT_FIELD(lastRowMarkId);
+ WRITE_INT_FIELD(lastPlanNodeId);
WRITE_BOOL_FIELD(transientPlan);
- WRITE_BOOL_FIELD(hasRowSecurity);
+ WRITE_BOOL_FIELD(dependsOnRole);
+ WRITE_BOOL_FIELD(parallelModeOK);
+ WRITE_BOOL_FIELD(parallelModeNeeded);
+ WRITE_CHAR_FIELD(maxParallelHazard);
}
static void
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_NODE_FIELD(right_join_clauses);
WRITE_NODE_FIELD(full_join_clauses);
WRITE_NODE_FIELD(join_info_list);
- WRITE_NODE_FIELD(lateral_info_list);
WRITE_NODE_FIELD(append_rel_list);
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(minmax_aggs);
WRITE_FLOAT_FIELD(total_table_pages, "%.0f");
WRITE_FLOAT_FIELD(tuple_fraction, "%.4f");
WRITE_BOOL_FIELD(hasInheritedTarget);
WRITE_BOOL_FIELD(hasJoinRTEs);
WRITE_BOOL_FIELD(hasLateralRTEs);
+ WRITE_BOOL_FIELD(hasDeletedRTEs);
WRITE_BOOL_FIELD(hasHavingQual);
WRITE_BOOL_FIELD(hasPseudoConstantQuals);
WRITE_BOOL_FIELD(hasRecursion);
WRITE_ENUM_FIELD(reloptkind, RelOptKind);
WRITE_BITMAPSET_FIELD(relids);
WRITE_FLOAT_FIELD(rows, "%.0f");
- WRITE_INT_FIELD(width);
WRITE_BOOL_FIELD(consider_startup);
- WRITE_NODE_FIELD(reltargetlist);
+ 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_relids);
WRITE_BITMAPSET_FIELD(lateral_referencers);
WRITE_NODE_FIELD(indexlist);
WRITE_UINT_FIELD(pages);
WRITE_FLOAT_FIELD(tuples, "%.0f");
WRITE_FLOAT_FIELD(allvisfrac, "%.6f");
- WRITE_NODE_FIELD(subplan);
WRITE_NODE_FIELD(subroot);
WRITE_NODE_FIELD(subplan_params);
+ WRITE_INT_FIELD(rel_parallel_workers);
+ WRITE_OID_FIELD(serverid);
+ WRITE_OID_FIELD(userid);
+ WRITE_BOOL_FIELD(useridiscurrent);
/* we don't try to print fdwroutine or fdw_private */
WRITE_NODE_FIELD(baserestrictinfo);
WRITE_NODE_FIELD(joininfo);
/* 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 pg_am entry */
+ /* 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);
+ appendStringInfoString(str, " :conkey");
+ for (i = 0; i < node->nkeys; i++)
+ appendStringInfo(str, " %d", node->conkey[i]);
+ appendStringInfoString(str, " :confkey");
+ for (i = 0; i < node->nkeys; i++)
+ appendStringInfo(str, " %d", node->confkey[i]);
+ appendStringInfoString(str, " :conpfeqop");
+ for (i = 0; i < node->nkeys; i++)
+ appendStringInfo(str, " %u", node->conpfeqop[i]);
+ WRITE_INT_FIELD(nmatched_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
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);
+}
+
static void
_outParamPathInfo(StringInfo str, const ParamPathInfo *node)
{
WRITE_ENUM_FIELD(jointype, JoinType);
WRITE_BOOL_FIELD(lhs_strict);
WRITE_BOOL_FIELD(delay_upper_joins);
- WRITE_NODE_FIELD(join_quals);
-}
-
-static void
-_outLateralJoinInfo(StringInfo str, const LateralJoinInfo *node)
-{
- WRITE_NODE_TYPE("LATERALJOININFO");
-
- WRITE_BITMAPSET_FIELD(lateral_lhs);
- WRITE_BITMAPSET_FIELD(lateral_rhs);
+ 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
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.
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_STRING_FIELD(defname);
WRITE_NODE_FIELD(arg);
WRITE_ENUM_FIELD(defaction, DefElemAction);
+ WRITE_LOCATION_FIELD(location);
}
static void
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_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_NODE_FIELD(rtable);
WRITE_NODE_FIELD(jointree);
WRITE_NODE_FIELD(targetList);
- WRITE_NODE_FIELD(withCheckOptions);
+ WRITE_NODE_FIELD(onConflict);
WRITE_NODE_FIELD(returningList);
WRITE_NODE_FIELD(groupClause);
+ WRITE_NODE_FIELD(groupingSets);
WRITE_NODE_FIELD(havingQual);
WRITE_NODE_FIELD(windowClause);
WRITE_NODE_FIELD(distinctClause);
WRITE_NODE_FIELD(rowMarks);
WRITE_NODE_FIELD(setOperations);
WRITE_NODE_FIELD(constraintDeps);
+ /* withCheckOptions intentionally omitted, see comment in parsenodes.h */
+ WRITE_LOCATION_FIELD(stmt_location);
+ WRITE_LOCATION_FIELD(stmt_len);
}
static void
{
WRITE_NODE_TYPE("WITHCHECKOPTION");
- WRITE_STRING_FIELD(viewname);
+ WRITE_ENUM_FIELD(kind, WCOKind);
+ WRITE_STRING_FIELD(relname);
+ WRITE_STRING_FIELD(polname);
WRITE_NODE_FIELD(qual);
WRITE_BOOL_FIELD(cascaded);
}
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)
{
case RTE_RELATION:
WRITE_OID_FIELD(relid);
WRITE_CHAR_FIELD(relkind);
+ WRITE_NODE_FIELD(tablesample);
break;
case RTE_SUBQUERY:
WRITE_NODE_FIELD(subquery);
break;
case RTE_VALUES:
WRITE_NODE_FIELD(values_lists);
- WRITE_NODE_FIELD(values_collations);
+ 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(ctecoltypes);
- WRITE_NODE_FIELD(ctecoltypmods);
- WRITE_NODE_FIELD(ctecolcollations);
+ WRITE_NODE_FIELD(coltypes);
+ WRITE_NODE_FIELD(coltypmods);
+ WRITE_NODE_FIELD(colcollations);
break;
default:
elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind);
WRITE_UINT_FIELD(requiredPerms);
WRITE_OID_FIELD(checkAsUser);
WRITE_BITMAPSET_FIELD(selectedCols);
- WRITE_BITMAPSET_FIELD(modifiedCols);
+ WRITE_BITMAPSET_FIELD(insertedCols);
+ WRITE_BITMAPSET_FIELD(updatedCols);
WRITE_NODE_FIELD(securityQuals);
}
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)
{
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);
case T_String:
/*
- * We use _outToken to provide escaping of the string's content,
+ * 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);
+ outToken(str, value->val.str);
appendStringInfoChar(str, '"');
break;
case T_BitString:
{
WRITE_NODE_TYPE("A_INDICES");
+ WRITE_BOOL_FIELD(is_slice);
WRITE_NODE_FIELD(lidx);
WRITE_NODE_FIELD(uidx);
}
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
_outConstraint(StringInfo str, const Constraint *node)
{
}
}
+static void
+_outForeignKeyCacheInfo(StringInfo str, const ForeignKeyCacheInfo *node)
+{
+ int i;
+
+ WRITE_NODE_TYPE("FOREIGNKEYCACHEINFO");
+
+ WRITE_OID_FIELD(conrelid);
+ WRITE_OID_FIELD(confrelid);
+ WRITE_INT_FIELD(nkeys);
+ appendStringInfoString(str, " :conkey");
+ for (i = 0; i < node->nkeys; i++)
+ appendStringInfo(str, " %d", node->conkey[i]);
+ appendStringInfoString(str, " :confkey");
+ for (i = 0; i < node->nkeys; i++)
+ appendStringInfo(str, " %d", node->confkey[i]);
+ appendStringInfoString(str, " :conpfeqop");
+ for (i = 0; i < node->nkeys; i++)
+ appendStringInfo(str, " %u", node->conpfeqop[i]);
+}
+
+static void
+_outPartitionSpec(StringInfo str, const PartitionSpec *node)
+{
+ WRITE_NODE_TYPE("PARTITIONBY");
+
+ WRITE_STRING_FIELD(strategy);
+ WRITE_NODE_FIELD(partParams);
+ WRITE_LOCATION_FIELD(location);
+}
+
+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
+_outPartitionBoundSpec(StringInfo str, const PartitionBoundSpec *node)
+{
+ WRITE_NODE_TYPE("PARTITIONBOUND");
+
+ WRITE_CHAR_FIELD(strategy);
+ WRITE_NODE_FIELD(listdatums);
+ WRITE_NODE_FIELD(lowerdatums);
+ WRITE_NODE_FIELD(upperdatums);
+}
+
+static void
+_outPartitionRangeDatum(StringInfo str, const PartitionRangeDatum *node)
+{
+ WRITE_NODE_TYPE("PARTRANGEDATUM");
+
+ WRITE_BOOL_FIELD(infinite);
+ WRITE_NODE_FIELD(value);
+}
/*
- * _outNode -
+ * outNode -
* converts a Node into ascii string and append it to 'str'
*/
-static void
-_outNode(StringInfo str, const void *obj)
+void
+outNode(StringInfo str, const void *obj)
{
if (obj == NULL)
appendStringInfoString(str, "<>");
case T_BitmapOr:
_outBitmapOr(str, obj);
break;
+ case T_Gather:
+ _outGather(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_Aggref:
_outAggref(str, obj);
break;
+ case T_GroupingFunc:
+ _outGroupingFunc(str, obj);
+ break;
case T_WindowFunc:
_outWindowFunc(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_CurrentOfExpr:
_outCurrentOfExpr(str, obj);
break;
+ case T_InferenceElem:
+ _outInferenceElem(str, obj);
+ break;
case T_TargetEntry:
_outTargetEntry(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_TidPath:
_outTidPath(str, obj);
break;
+ case T_SubqueryScanPath:
+ _outSubqueryScanPath(str, obj);
+ break;
case T_ForeignPath:
_outForeignPath(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_SortPath:
+ _outSortPath(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_NestPath:
_outNestPath(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_PathKey:
_outPathKey(str, obj);
break;
+ case T_PathTarget:
+ _outPathTarget(str, obj);
+ break;
case T_ParamPathInfo:
_outParamPathInfo(str, obj);
break;
case T_SpecialJoinInfo:
_outSpecialJoinInfo(str, obj);
break;
- case T_LateralJoinInfo:
- _outLateralJoinInfo(str, obj);
- break;
case T_AppendRelInfo:
_outAppendRelInfo(str, obj);
break;
_outPlannerParamItem(str, obj);
break;
+ case T_ExtensibleNode:
+ _outExtensibleNode(str, obj);
+ break;
+
case T_CreateStmt:
_outCreateStmt(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_RangeTblFunction:
_outRangeTblFunction(str, obj);
break;
+ case T_TableSampleClause:
+ _outTableSampleClause(str, obj);
+ break;
case T_A_Expr:
_outAExpr(str, obj);
break;
case T_RangeFunction:
_outRangeFunction(str, obj);
break;
+ case T_RangeTableSample:
+ _outRangeTableSample(str, obj);
+ break;
case T_Constraint:
_outConstraint(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_PartitionSpec:
+ _outPartitionSpec(str, obj);
+ break;
+ case T_PartitionElem:
+ _outPartitionElem(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.
+ * dump structures that outNode only understands part of.
*/
elog(WARNING, "could not dump unrecognized node type: %d",
(int) nodeTag(obj));
/* see stringinfo.h for an explanation of this maneuver */
initStringInfo(&str);
- _outNode(&str, obj);
+ 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;
}