* outfuncs.c
* Output functions for Postgres tree nodes.
*
- * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
#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 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")
/*
- * _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')
{
}
}
-/* for use by extensions which define extensible nodes */
-void
-outToken(StringInfo str, const char *s)
-{
- _outToken(str, s);
-}
-
static void
_outList(StringInfo str, const List *node)
{
}
/*
- * _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;
appendStringInfoChar(str, ')');
}
-/* for use by extensions which define extensible nodes */
-void
-outBitmapset(StringInfo str, const Bitmapset *bms)
-{
- _outBitmapset(str, bms);
-}
-
/*
* Print the value of a Datum given its type.
*/
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_BOOL_FIELD(parallelModeNeeded);
- WRITE_BOOL_FIELD(hasForeignJoin);
+ WRITE_NODE_FIELD(utilityStmt);
+ WRITE_LOCATION_FIELD(stmt_location);
+ WRITE_LOCATION_FIELD(stmt_len);
}
/*
WRITE_BITMAPSET_FIELD(custom_relids);
/* CustomName is a key to lookup CustomScanMethods */
appendStringInfoString(str, " :methods ");
- _outToken(str, node->methods->CustomName);
+ outToken(str, node->methods->CustomName);
}
static void
_outPlanInfo(str, (const Plan *) node);
WRITE_ENUM_FIELD(aggstrategy, AggStrategy);
- WRITE_BOOL_FIELD(combineStates);
- WRITE_BOOL_FIELD(finalizeAggs);
- WRITE_BOOL_FIELD(serialStates);
+ 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);
}
*/
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);
WRITE_OID_FIELD(aggfnoid);
WRITE_OID_FIELD(aggtype);
- WRITE_OID_FIELD(aggoutputtype);
WRITE_OID_FIELD(aggcollid);
WRITE_OID_FIELD(inputcollid);
WRITE_OID_FIELD(aggtranstype);
WRITE_NODE_FIELD(aggfilter);
WRITE_BOOL_FIELD(aggstar);
WRITE_BOOL_FIELD(aggvariadic);
- WRITE_BOOL_FIELD(aggcombine);
- WRITE_BOOL_FIELD(aggpartial);
WRITE_CHAR_FIELD(aggkind);
WRITE_UINT_FIELD(agglevelsup);
+ WRITE_ENUM_FIELD(aggsplit, AggSplit);
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_ENUM_FIELD(pathtype, NodeTag);
appendStringInfoString(str, " :parent_relids ");
- _outBitmapset(str, node->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);
+ 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_NODE_FIELD(custom_paths);
WRITE_NODE_FIELD(custom_private);
appendStringInfoString(str, " :methods ");
- _outToken(str, node->methods->CustomName);
+ outToken(str, node->methods->CustomName);
}
static void
_outPathInfo(str, (const Path *) node);
WRITE_NODE_FIELD(subpath);
+ WRITE_BOOL_FIELD(dummypp);
}
static void
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);
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_BOOL_FIELD(wholePlanParallelSafe);
- WRITE_BOOL_FIELD(hasForeignJoin);
+ WRITE_CHAR_FIELD(maxParallelHazard);
}
static void
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_FLOAT_FIELD(allvisfrac, "%.6f");
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);
/* 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
_outEquivalenceClass(StringInfo str, const EquivalenceClass *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_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(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
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);
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:
}
}
+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 -
case T_MinMaxExpr:
_outMinMaxExpr(str, obj);
break;
+ case T_SQLValueFunction:
+ _outSQLValueFunction(str, obj);
+ break;
case T_XmlExpr:
_outXmlExpr(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_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:
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;
+}