diff options
author | Pavan Deolasee | 2017-06-14 05:42:18 +0000 |
---|---|---|
committer | Pavan Deolasee | 2017-06-14 05:42:18 +0000 |
commit | 15dd5274c323fb93e4e3ea9ad2185aaaec10f79c (patch) | |
tree | 9dafb4c7f735d9429ea461dc792933af87493c33 /src/backend/nodes | |
parent | dfbb88e3bbb526dcb204b456b9e5cfd9d10d0d0a (diff) | |
parent | d5cb3bab564e0927ffac7c8729eacf181a12dd40 (diff) |
Merge from PG master upto d5cb3bab564e0927ffac7c8729eacf181a12dd40
This is the result of the "git merge remotes/PGSQL/master" upto the said commit
point. We have done some basic analysis, fixed compilation problems etc, but
bulk of the logical problems in conflict resolution etc will be handled by
subsequent commits.
Diffstat (limited to 'src/backend/nodes')
-rw-r--r-- | src/backend/nodes/bitmapset.c | 32 | ||||
-rw-r--r-- | src/backend/nodes/copyfuncs.c | 529 | ||||
-rw-r--r-- | src/backend/nodes/equalfuncs.c | 358 | ||||
-rw-r--r-- | src/backend/nodes/extensible.c | 2 | ||||
-rw-r--r-- | src/backend/nodes/list.c | 2 | ||||
-rw-r--r-- | src/backend/nodes/makefuncs.c | 19 | ||||
-rw-r--r-- | src/backend/nodes/nodeFuncs.c | 145 | ||||
-rw-r--r-- | src/backend/nodes/nodes.c | 2 | ||||
-rw-r--r-- | src/backend/nodes/outfuncs.c | 630 | ||||
-rw-r--r-- | src/backend/nodes/params.c | 2 | ||||
-rw-r--r-- | src/backend/nodes/print.c | 10 | ||||
-rw-r--r-- | src/backend/nodes/read.c | 2 | ||||
-rw-r--r-- | src/backend/nodes/readfuncs.c | 190 | ||||
-rw-r--r-- | src/backend/nodes/tidbitmap.c | 738 | ||||
-rw-r--r-- | src/backend/nodes/value.c | 2 |
15 files changed, 2311 insertions, 352 deletions
diff --git a/src/backend/nodes/bitmapset.c b/src/backend/nodes/bitmapset.c index 0626a49238..3348a22742 100644 --- a/src/backend/nodes/bitmapset.c +++ b/src/backend/nodes/bitmapset.c @@ -11,7 +11,7 @@ * bms_is_empty() in preference to testing for NULL.) * * - * Copyright (c) 2003-2016, PostgreSQL Global Development Group + * Copyright (c) 2003-2017, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/nodes/bitmapset.c @@ -21,6 +21,7 @@ #include "postgres.h" #include "access/hash.h" +#include "nodes/pg_list.h" #define WORDNUM(x) ((x) / BITS_PER_BITMAPWORD) @@ -458,6 +459,35 @@ bms_overlap(const Bitmapset *a, const Bitmapset *b) } /* + * bms_overlap_list - does a set overlap an integer list? + */ +bool +bms_overlap_list(const Bitmapset *a, const List *b) +{ + ListCell *lc; + int wordnum, + bitnum; + + if (a == NULL || b == NIL) + return false; + + foreach(lc, b) + { + int x = lfirst_int(lc); + + if (x < 0) + elog(ERROR, "negative bitmapset member not allowed"); + wordnum = WORDNUM(x); + bitnum = BITNUM(x); + if (wordnum < a->nwords) + if ((a->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0) + return true; + } + + return false; +} + +/* * bms_nonempty_difference - do sets have a nonempty difference? */ bool diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 0cdd6559d0..fc21909ea3 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -12,7 +12,7 @@ * * * Portions Copyright (c) 2012-2014, TransLattice, Inc. - * 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 * Portions Copyright (c) 2010-2012 Postgres-XC Development Group * @@ -52,7 +52,7 @@ /* Copy a field that is a pointer to some kind of Node or Node tree */ #define COPY_NODE_FIELD(fldname) \ - (newnode->fldname = copyObject(from->fldname)) + (newnode->fldname = copyObjectImpl(from->fldname)) /* Copy a field that is a pointer to a Bitmapset */ #define COPY_BITMAPSET_FIELD(fldname) \ @@ -99,7 +99,8 @@ _copyPlannedStmt(const PlannedStmt *from) COPY_NODE_FIELD(planTree); COPY_NODE_FIELD(rtable); COPY_NODE_FIELD(resultRelations); - COPY_NODE_FIELD(utilityStmt); + COPY_NODE_FIELD(nonleafResultRelations); + COPY_NODE_FIELD(rootResultRelations); COPY_NODE_FIELD(subplans); COPY_BITMAPSET_FIELD(rewindPlanIDs); COPY_NODE_FIELD(rowMarks); @@ -116,6 +117,9 @@ _copyPlannedStmt(const PlannedStmt *from) COPY_NODE_FIELD(distributionNodes); COPY_NODE_FIELD(distributionRestrict); #endif + COPY_NODE_FIELD(utilityStmt); + COPY_LOCATION_FIELD(stmt_location); + COPY_LOCATION_FIELD(stmt_len); return newnode; } @@ -134,6 +138,7 @@ CopyPlanFields(const Plan *from, Plan *newnode) COPY_SCALAR_FIELD(plan_rows); COPY_SCALAR_FIELD(plan_width); COPY_SCALAR_FIELD(parallel_aware); + COPY_SCALAR_FIELD(parallel_safe); COPY_SCALAR_FIELD(plan_node_id); COPY_NODE_FIELD(targetlist); COPY_NODE_FIELD(qual); @@ -183,6 +188,22 @@ _copyResult(const Result *from) } /* + * _copyProjectSet + */ +static ProjectSet * +_copyProjectSet(const ProjectSet *from) +{ + ProjectSet *newnode = makeNode(ProjectSet); + + /* + * copy node superclass fields + */ + CopyPlanFields((const Plan *) from, (Plan *) newnode); + + return newnode; +} + +/* * _copyModifyTable */ static ModifyTable * @@ -201,8 +222,10 @@ _copyModifyTable(const ModifyTable *from) COPY_SCALAR_FIELD(operation); COPY_SCALAR_FIELD(canSetTag); COPY_SCALAR_FIELD(nominalRelation); + COPY_NODE_FIELD(partitioned_rels); COPY_NODE_FIELD(resultRelations); COPY_SCALAR_FIELD(resultRelIndex); + COPY_SCALAR_FIELD(rootResultRelIndex); COPY_NODE_FIELD(plans); COPY_NODE_FIELD(withCheckOptionLists); COPY_NODE_FIELD(returningLists); @@ -236,6 +259,7 @@ _copyAppend(const Append *from) /* * copy remainder of node */ + COPY_NODE_FIELD(partitioned_rels); COPY_NODE_FIELD(appendplans); return newnode; @@ -257,6 +281,7 @@ _copyMergeAppend(const MergeAppend *from) /* * copy remainder of node */ + COPY_NODE_FIELD(partitioned_rels); COPY_NODE_FIELD(mergeplans); COPY_SCALAR_FIELD(numCols); COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber)); @@ -332,6 +357,7 @@ _copyBitmapOr(const BitmapOr *from) /* * copy remainder of node */ + COPY_SCALAR_FIELD(isshared); COPY_NODE_FIELD(bitmapplans); return newnode; @@ -360,6 +386,31 @@ _copyGather(const Gather *from) return newnode; } +/* + * _copyGatherMerge + */ +static GatherMerge * +_copyGatherMerge(const GatherMerge *from) +{ + GatherMerge *newnode = makeNode(GatherMerge); + + /* + * copy node superclass fields + */ + CopyPlanFields((const Plan *) from, (Plan *) newnode); + + /* + * copy remainder of node + */ + COPY_SCALAR_FIELD(num_workers); + COPY_SCALAR_FIELD(numCols); + COPY_POINTER_FIELD(sortColIdx, from->numCols * sizeof(AttrNumber)); + COPY_POINTER_FIELD(sortOperators, from->numCols * sizeof(Oid)); + COPY_POINTER_FIELD(collations, from->numCols * sizeof(Oid)); + COPY_POINTER_FIELD(nullsFirst, from->numCols * sizeof(bool)); + + return newnode; +} /* * CopyScanFields @@ -497,6 +548,7 @@ _copyBitmapIndexScan(const BitmapIndexScan *from) * copy remainder of node */ COPY_SCALAR_FIELD(indexid); + COPY_SCALAR_FIELD(isshared); COPY_NODE_FIELD(indexqual); COPY_NODE_FIELD(indexqualorig); @@ -589,6 +641,27 @@ _copyFunctionScan(const FunctionScan *from) } /* + * _copyTableFuncScan + */ +static TableFuncScan * +_copyTableFuncScan(const TableFuncScan *from) +{ + TableFuncScan *newnode = makeNode(TableFuncScan); + + /* + * copy node superclass fields + */ + CopyScanFields((const Scan *) from, (Scan *) newnode); + + /* + * copy remainder of node + */ + COPY_NODE_FIELD(tablefunc); + + return newnode; +} + +/* * _copyValuesScan */ static ValuesScan * @@ -632,6 +705,27 @@ _copyCteScan(const CteScan *from) } /* + * _copyNamedTuplestoreScan + */ +static NamedTuplestoreScan * +_copyNamedTuplestoreScan(const NamedTuplestoreScan *from) +{ + NamedTuplestoreScan *newnode = makeNode(NamedTuplestoreScan); + + /* + * copy node superclass fields + */ + CopyScanFields((const Scan *) from, (Scan *) newnode); + + /* + * copy remainder of node + */ + COPY_STRING_FIELD(enrname); + + return newnode; +} + +/* * _copyWorkTableScan */ static WorkTableScan * @@ -725,6 +819,7 @@ CopyJoinFields(const Join *from, Join *newnode) CopyPlanFields((const Plan *) from, (Plan *) newnode); COPY_SCALAR_FIELD(jointype); + COPY_SCALAR_FIELD(inner_unique); COPY_NODE_FIELD(joinqual); } @@ -785,6 +880,7 @@ _copyMergeJoin(const MergeJoin *from) /* * copy remainder of node */ + COPY_SCALAR_FIELD(skip_mark_restore); COPY_NODE_FIELD(mergeclauses); numCols = list_length(from->mergeclauses); if (numCols > 0) @@ -896,6 +992,7 @@ _copyAgg(const Agg *from) COPY_POINTER_FIELD(grpOperators, from->numCols * sizeof(Oid)); } COPY_SCALAR_FIELD(numGroups); + COPY_BITMAPSET_FIELD(aggParams); COPY_NODE_FIELD(groupingSets); COPY_NODE_FIELD(chain); @@ -974,8 +1071,6 @@ _copyHash(const Hash *from) COPY_SCALAR_FIELD(skewTable); COPY_SCALAR_FIELD(skewColumn); COPY_SCALAR_FIELD(skewInherit); - COPY_SCALAR_FIELD(skewColType); - COPY_SCALAR_FIELD(skewColTypmod); return newnode; } @@ -1283,7 +1378,7 @@ _copyRangeVar(const RangeVar *from) COPY_STRING_FIELD(catalogname); COPY_STRING_FIELD(schemaname); COPY_STRING_FIELD(relname); - COPY_SCALAR_FIELD(inhOpt); + COPY_SCALAR_FIELD(inh); COPY_SCALAR_FIELD(relpersistence); COPY_NODE_FIELD(alias); COPY_LOCATION_FIELD(location); @@ -1292,6 +1387,31 @@ _copyRangeVar(const RangeVar *from) } /* + * _copyTableFunc + */ +static TableFunc * +_copyTableFunc(const TableFunc *from) +{ + TableFunc *newnode = makeNode(TableFunc); + + COPY_NODE_FIELD(ns_names); + COPY_NODE_FIELD(ns_uris); + COPY_NODE_FIELD(docexpr); + COPY_NODE_FIELD(rowexpr); + COPY_NODE_FIELD(colnames); + COPY_NODE_FIELD(coltypes); + COPY_NODE_FIELD(coltypmods); + COPY_NODE_FIELD(colcollations); + COPY_NODE_FIELD(colexprs); + COPY_NODE_FIELD(coldefexprs); + COPY_BITMAPSET_FIELD(notnulls); + COPY_SCALAR_FIELD(ordinalitycol); + COPY_LOCATION_FIELD(location); + + return newnode; +} + +/* * _copyIntoClause */ static IntoClause * @@ -1652,6 +1772,7 @@ _copySubPlan(const SubPlan *from) COPY_SCALAR_FIELD(firstColCollation); COPY_SCALAR_FIELD(useHashTable); COPY_SCALAR_FIELD(unknownEqFalse); + COPY_SCALAR_FIELD(parallel_safe); COPY_NODE_FIELD(setParam); COPY_NODE_FIELD(parParam); COPY_NODE_FIELD(args); @@ -1929,6 +2050,22 @@ _copyMinMaxExpr(const MinMaxExpr *from) } /* + * _copySQLValueFunction + */ +static SQLValueFunction * +_copySQLValueFunction(const SQLValueFunction *from) +{ + SQLValueFunction *newnode = makeNode(SQLValueFunction); + + COPY_SCALAR_FIELD(op); + COPY_SCALAR_FIELD(type); + COPY_SCALAR_FIELD(typmod); + COPY_LOCATION_FIELD(location); + + return newnode; +} + +/* * _copyXmlExpr */ static XmlExpr * @@ -2045,6 +2182,20 @@ _copyCurrentOfExpr(const CurrentOfExpr *from) return newnode; } + /* + * _copyNextValueExpr + */ +static NextValueExpr * +_copyNextValueExpr(const NextValueExpr *from) +{ + NextValueExpr *newnode = makeNode(NextValueExpr); + + COPY_SCALAR_FIELD(seqid); + COPY_SCALAR_FIELD(typeId); + + return newnode; +} + /* * _copyInferenceElem */ @@ -2184,6 +2335,8 @@ _copyRestrictInfo(const RestrictInfo *from) COPY_SCALAR_FIELD(outerjoin_delayed); COPY_SCALAR_FIELD(can_join); COPY_SCALAR_FIELD(pseudoconstant); + COPY_SCALAR_FIELD(leakproof); + COPY_SCALAR_FIELD(security_level); COPY_BITMAPSET_FIELD(clause_relids); COPY_BITMAPSET_FIELD(required_relids); COPY_BITMAPSET_FIELD(outer_relids); @@ -2270,6 +2423,20 @@ _copyAppendRelInfo(const AppendRelInfo *from) } /* + * _copyPartitionedChildRelInfo + */ +static PartitionedChildRelInfo * +_copyPartitionedChildRelInfo(const PartitionedChildRelInfo *from) +{ + PartitionedChildRelInfo *newnode = makeNode(PartitionedChildRelInfo); + + COPY_SCALAR_FIELD(parent_relid); + COPY_NODE_FIELD(child_rels); + + return newnode; +} + +/* * _copyPlaceHolderInfo */ static PlaceHolderInfo * @@ -2308,14 +2475,15 @@ _copyRangeTblEntry(const RangeTblEntry *from) COPY_NODE_FIELD(joinaliasvars); COPY_NODE_FIELD(functions); COPY_SCALAR_FIELD(funcordinality); + COPY_NODE_FIELD(tablefunc); COPY_NODE_FIELD(values_lists); - COPY_NODE_FIELD(values_collations); COPY_STRING_FIELD(ctename); COPY_SCALAR_FIELD(ctelevelsup); COPY_SCALAR_FIELD(self_reference); - COPY_NODE_FIELD(ctecoltypes); - COPY_NODE_FIELD(ctecoltypmods); - COPY_NODE_FIELD(ctecolcollations); + COPY_STRING_FIELD(enrname); + COPY_NODE_FIELD(coltypes); + COPY_NODE_FIELD(coltypmods); + COPY_NODE_FIELD(colcollations); COPY_NODE_FIELD(alias); COPY_NODE_FIELD(eref); COPY_SCALAR_FIELD(lateral); @@ -2730,6 +2898,38 @@ _copyRangeTableSample(const RangeTableSample *from) return newnode; } +static RangeTableFunc * +_copyRangeTableFunc(const RangeTableFunc *from) +{ + RangeTableFunc *newnode = makeNode(RangeTableFunc); + + COPY_SCALAR_FIELD(lateral); + COPY_NODE_FIELD(docexpr); + COPY_NODE_FIELD(rowexpr); + COPY_NODE_FIELD(namespaces); + COPY_NODE_FIELD(columns); + COPY_NODE_FIELD(alias); + COPY_LOCATION_FIELD(location); + + return newnode; +} + +static RangeTableFuncCol * +_copyRangeTableFuncCol(const RangeTableFuncCol *from) +{ + RangeTableFuncCol *newnode = makeNode(RangeTableFuncCol); + + COPY_STRING_FIELD(colname); + COPY_NODE_FIELD(typeName); + COPY_SCALAR_FIELD(for_ordinality); + COPY_SCALAR_FIELD(is_not_null); + COPY_NODE_FIELD(colexpr); + COPY_NODE_FIELD(coldefexpr); + COPY_LOCATION_FIELD(location); + + return newnode; +} + static TypeCast * _copyTypeCast(const TypeCast *from) { @@ -2781,9 +2981,11 @@ _copyColumnDef(const ColumnDef *from) COPY_SCALAR_FIELD(is_local); COPY_SCALAR_FIELD(is_not_null); COPY_SCALAR_FIELD(is_from_type); + COPY_SCALAR_FIELD(is_from_parent); COPY_SCALAR_FIELD(storage); COPY_NODE_FIELD(raw_default); COPY_NODE_FIELD(cooked_default); + COPY_SCALAR_FIELD(identity); COPY_NODE_FIELD(collClause); COPY_SCALAR_FIELD(collOid); COPY_NODE_FIELD(constraints); @@ -2806,6 +3008,7 @@ _copyConstraint(const Constraint *from) COPY_SCALAR_FIELD(is_no_inherit); COPY_NODE_FIELD(raw_expr); COPY_STRING_FIELD(cooked_expr); + COPY_SCALAR_FIELD(generated_when); COPY_NODE_FIELD(keys); COPY_NODE_FIELD(exclusions); COPY_NODE_FIELD(options); @@ -2836,6 +3039,7 @@ _copyDefElem(const DefElem *from) COPY_STRING_FIELD(defname); COPY_NODE_FIELD(arg); COPY_SCALAR_FIELD(defaction); + COPY_LOCATION_FIELD(location); return newnode; } @@ -2877,6 +3081,18 @@ _copyRoleSpec(const RoleSpec *from) return newnode; } +static TriggerTransition * +_copyTriggerTransition(const TriggerTransition *from) +{ + TriggerTransition *newnode = makeNode(TriggerTransition); + + COPY_STRING_FIELD(name); + COPY_SCALAR_FIELD(isNew); + COPY_SCALAR_FIELD(isTable); + + return newnode; +} + static Query * _copyQuery(const Query *from) { @@ -2890,6 +3106,7 @@ _copyQuery(const Query *from) COPY_SCALAR_FIELD(resultRelation); COPY_SCALAR_FIELD(hasAggs); COPY_SCALAR_FIELD(hasWindowFuncs); + COPY_SCALAR_FIELD(hasTargetSRFs); COPY_SCALAR_FIELD(hasSubLinks); COPY_SCALAR_FIELD(hasDistinctOn); COPY_SCALAR_FIELD(hasRecursive); @@ -2900,6 +3117,7 @@ _copyQuery(const Query *from) COPY_NODE_FIELD(rtable); COPY_NODE_FIELD(jointree); COPY_NODE_FIELD(targetList); + COPY_SCALAR_FIELD(override); COPY_NODE_FIELD(onConflict); COPY_NODE_FIELD(returningList); COPY_NODE_FIELD(groupClause); @@ -2914,6 +3132,20 @@ _copyQuery(const Query *from) COPY_NODE_FIELD(setOperations); COPY_NODE_FIELD(constraintDeps); COPY_NODE_FIELD(withCheckOptions); + COPY_LOCATION_FIELD(stmt_location); + COPY_LOCATION_FIELD(stmt_len); + + return newnode; +} + +static RawStmt * +_copyRawStmt(const RawStmt *from) +{ + RawStmt *newnode = makeNode(RawStmt); + + COPY_NODE_FIELD(stmt); + COPY_LOCATION_FIELD(stmt_location); + COPY_LOCATION_FIELD(stmt_len); return newnode; } @@ -2929,6 +3161,7 @@ _copyInsertStmt(const InsertStmt *from) COPY_NODE_FIELD(onConflictClause); COPY_NODE_FIELD(returningList); COPY_NODE_FIELD(withClause); + COPY_SCALAR_FIELD(override); return newnode; } @@ -3034,6 +3267,16 @@ _copyAlterTableCmd(const AlterTableCmd *from) return newnode; } +static AlterCollationStmt * +_copyAlterCollationStmt(const AlterCollationStmt *from) +{ + AlterCollationStmt *newnode = makeNode(AlterCollationStmt); + + COPY_NODE_FIELD(collname); + + return newnode; +} + static AlterDomainStmt * _copyAlterDomainStmt(const AlterDomainStmt *from) { @@ -3066,13 +3309,14 @@ _copyGrantStmt(const GrantStmt *from) return newnode; } -static FuncWithArgs * -_copyFuncWithArgs(const FuncWithArgs *from) +static ObjectWithArgs * +_copyObjectWithArgs(const ObjectWithArgs *from) { - FuncWithArgs *newnode = makeNode(FuncWithArgs); + ObjectWithArgs *newnode = makeNode(ObjectWithArgs); - COPY_NODE_FIELD(funcname); - COPY_NODE_FIELD(funcargs); + COPY_NODE_FIELD(objname); + COPY_NODE_FIELD(objargs); + COPY_SCALAR_FIELD(args_unspecified); return newnode; } @@ -3200,6 +3444,8 @@ CopyCreateStmtFields(const CreateStmt *from, CreateStmt *newnode) COPY_NODE_FIELD(relation); COPY_NODE_FIELD(tableElts); COPY_NODE_FIELD(inhRelations); + COPY_NODE_FIELD(partspec); + COPY_NODE_FIELD(partbound); COPY_NODE_FIELD(ofTypename); COPY_NODE_FIELD(constraints); COPY_NODE_FIELD(options); @@ -3245,6 +3491,7 @@ _copyDefineStmt(const DefineStmt *from) COPY_NODE_FIELD(defnames); COPY_NODE_FIELD(args); COPY_NODE_FIELD(definition); + COPY_SCALAR_FIELD(if_not_exists); return newnode; } @@ -3255,7 +3502,6 @@ _copyDropStmt(const DropStmt *from) DropStmt *newnode = makeNode(DropStmt); COPY_NODE_FIELD(objects); - COPY_NODE_FIELD(arguments); COPY_SCALAR_FIELD(removeType); COPY_SCALAR_FIELD(behavior); COPY_SCALAR_FIELD(missing_ok); @@ -3282,8 +3528,7 @@ _copyCommentStmt(const CommentStmt *from) CommentStmt *newnode = makeNode(CommentStmt); COPY_SCALAR_FIELD(objtype); - COPY_NODE_FIELD(objname); - COPY_NODE_FIELD(objargs); + COPY_NODE_FIELD(object); COPY_STRING_FIELD(comment); return newnode; @@ -3295,8 +3540,7 @@ _copySecLabelStmt(const SecLabelStmt *from) SecLabelStmt *newnode = makeNode(SecLabelStmt); COPY_SCALAR_FIELD(objtype); - COPY_NODE_FIELD(objname); - COPY_NODE_FIELD(objargs); + COPY_NODE_FIELD(object); COPY_STRING_FIELD(provider); COPY_STRING_FIELD(label); @@ -3344,6 +3588,20 @@ _copyIndexStmt(const IndexStmt *from) return newnode; } +static CreateStatsStmt * +_copyCreateStatsStmt(const CreateStatsStmt *from) +{ + CreateStatsStmt *newnode = makeNode(CreateStatsStmt); + + COPY_NODE_FIELD(defnames); + COPY_NODE_FIELD(stat_types); + COPY_NODE_FIELD(exprs); + COPY_NODE_FIELD(relations); + COPY_SCALAR_FIELD(if_not_exists); + + return newnode; +} + static CreateFunctionStmt * _copyCreateFunctionStmt(const CreateFunctionStmt *from) { @@ -3402,7 +3660,6 @@ _copyRenameStmt(const RenameStmt *from) COPY_SCALAR_FIELD(relationType); COPY_NODE_FIELD(relation); COPY_NODE_FIELD(object); - COPY_NODE_FIELD(objarg); COPY_STRING_FIELD(subname); COPY_STRING_FIELD(newname); COPY_SCALAR_FIELD(behavior); @@ -3418,8 +3675,7 @@ _copyAlterObjectDependsStmt(const AlterObjectDependsStmt *from) COPY_SCALAR_FIELD(objectType); COPY_NODE_FIELD(relation); - COPY_NODE_FIELD(objname); - COPY_NODE_FIELD(objargs); + COPY_NODE_FIELD(object); COPY_NODE_FIELD(extname); return newnode; @@ -3433,7 +3689,6 @@ _copyAlterObjectSchemaStmt(const AlterObjectSchemaStmt *from) COPY_SCALAR_FIELD(objectType); COPY_NODE_FIELD(relation); COPY_NODE_FIELD(object); - COPY_NODE_FIELD(objarg); COPY_STRING_FIELD(newschema); COPY_SCALAR_FIELD(missing_ok); @@ -3448,7 +3703,6 @@ _copyAlterOwnerStmt(const AlterOwnerStmt *from) COPY_SCALAR_FIELD(objectType); COPY_NODE_FIELD(relation); COPY_NODE_FIELD(object); - COPY_NODE_FIELD(objarg); COPY_NODE_FIELD(newowner); return newnode; @@ -3460,7 +3714,6 @@ _copyAlterOperatorStmt(const AlterOperatorStmt *from) AlterOperatorStmt *newnode = makeNode(AlterOperatorStmt); COPY_NODE_FIELD(opername); - COPY_NODE_FIELD(operargs); COPY_NODE_FIELD(options); return newnode; @@ -3564,10 +3817,11 @@ _copyAlterEnumStmt(const AlterEnumStmt *from) AlterEnumStmt *newnode = makeNode(AlterEnumStmt); COPY_NODE_FIELD(typeName); + COPY_STRING_FIELD(oldVal); COPY_STRING_FIELD(newVal); COPY_STRING_FIELD(newValNeighbor); COPY_SCALAR_FIELD(newValIsAfter); - COPY_SCALAR_FIELD(skipIfExists); + COPY_SCALAR_FIELD(skipIfNewValExists); return newnode; } @@ -3632,7 +3886,6 @@ _copyCreateOpClassItem(const CreateOpClassItem *from) COPY_SCALAR_FIELD(itemtype); COPY_NODE_FIELD(name); - COPY_NODE_FIELD(args); COPY_SCALAR_FIELD(number); COPY_NODE_FIELD(order_family); COPY_NODE_FIELD(class_args); @@ -3790,6 +4043,7 @@ _copyCreateSeqStmt(const CreateSeqStmt *from) COPY_NODE_FIELD(sequence); COPY_NODE_FIELD(options); COPY_SCALAR_FIELD(ownerId); + COPY_SCALAR_FIELD(for_identity); COPY_SCALAR_FIELD(if_not_exists); return newnode; @@ -3802,6 +4056,7 @@ _copyAlterSeqStmt(const AlterSeqStmt *from) COPY_NODE_FIELD(sequence); COPY_NODE_FIELD(options); + COPY_SCALAR_FIELD(for_identity); COPY_SCALAR_FIELD(missing_ok); return newnode; @@ -3921,8 +4176,7 @@ _copyAlterExtensionContentsStmt(const AlterExtensionContentsStmt *from) COPY_STRING_FIELD(extname); COPY_SCALAR_FIELD(action); COPY_SCALAR_FIELD(objtype); - COPY_NODE_FIELD(objname); - COPY_NODE_FIELD(objargs); + COPY_NODE_FIELD(object); return newnode; } @@ -3961,6 +4215,7 @@ _copyCreateForeignServerStmt(const CreateForeignServerStmt *from) COPY_STRING_FIELD(version); COPY_STRING_FIELD(fdwname); COPY_NODE_FIELD(options); + COPY_SCALAR_FIELD(if_not_exists); return newnode; } @@ -3986,6 +4241,7 @@ _copyCreateUserMappingStmt(const CreateUserMappingStmt *from) COPY_NODE_FIELD(user); COPY_STRING_FIELD(servername); COPY_NODE_FIELD(options); + COPY_SCALAR_FIELD(if_not_exists); return newnode; } @@ -4083,6 +4339,7 @@ _copyCreateTrigStmt(const CreateTrigStmt *from) COPY_NODE_FIELD(columns); COPY_NODE_FIELD(whenClause); COPY_SCALAR_FIELD(isconstraint); + COPY_NODE_FIELD(transitionRels); COPY_SCALAR_FIELD(deferrable); COPY_SCALAR_FIELD(initdeferred); COPY_NODE_FIELD(constrrel); @@ -4343,6 +4600,7 @@ _copyCreatePolicyStmt(const CreatePolicyStmt *from) COPY_STRING_FIELD(policy_name); COPY_NODE_FIELD(table); COPY_STRING_FIELD(cmd_name); + COPY_SCALAR_FIELD(permissive); COPY_NODE_FIELD(roles); COPY_NODE_FIELD(qual); COPY_NODE_FIELD(with_check); @@ -4364,6 +4622,135 @@ _copyAlterPolicyStmt(const AlterPolicyStmt *from) return newnode; } +static PartitionElem * +_copyPartitionElem(const PartitionElem *from) +{ + PartitionElem *newnode = makeNode(PartitionElem); + + COPY_STRING_FIELD(name); + COPY_NODE_FIELD(expr); + COPY_NODE_FIELD(collation); + COPY_NODE_FIELD(opclass); + COPY_LOCATION_FIELD(location); + + return newnode; +} + +static PartitionSpec * +_copyPartitionSpec(const PartitionSpec *from) +{ + PartitionSpec *newnode = makeNode(PartitionSpec); + + COPY_STRING_FIELD(strategy); + COPY_NODE_FIELD(partParams); + COPY_LOCATION_FIELD(location); + + return newnode; +} + +static PartitionBoundSpec * +_copyPartitionBoundSpec(const PartitionBoundSpec *from) +{ + PartitionBoundSpec *newnode = makeNode(PartitionBoundSpec); + + COPY_SCALAR_FIELD(strategy); + COPY_NODE_FIELD(listdatums); + COPY_NODE_FIELD(lowerdatums); + COPY_NODE_FIELD(upperdatums); + COPY_LOCATION_FIELD(location); + + return newnode; +} + +static PartitionRangeDatum * +_copyPartitionRangeDatum(const PartitionRangeDatum *from) +{ + PartitionRangeDatum *newnode = makeNode(PartitionRangeDatum); + + COPY_SCALAR_FIELD(infinite); + COPY_NODE_FIELD(value); + COPY_LOCATION_FIELD(location); + + return newnode; +} + +static PartitionCmd * +_copyPartitionCmd(const PartitionCmd *from) +{ + PartitionCmd *newnode = makeNode(PartitionCmd); + + COPY_NODE_FIELD(name); + COPY_NODE_FIELD(bound); + + return newnode; +} + +static CreatePublicationStmt * +_copyCreatePublicationStmt(const CreatePublicationStmt *from) +{ + CreatePublicationStmt *newnode = makeNode(CreatePublicationStmt); + + COPY_STRING_FIELD(pubname); + COPY_NODE_FIELD(options); + COPY_NODE_FIELD(tables); + COPY_SCALAR_FIELD(for_all_tables); + + return newnode; +} + +static AlterPublicationStmt * +_copyAlterPublicationStmt(const AlterPublicationStmt *from) +{ + AlterPublicationStmt *newnode = makeNode(AlterPublicationStmt); + + COPY_STRING_FIELD(pubname); + COPY_NODE_FIELD(options); + COPY_NODE_FIELD(tables); + COPY_SCALAR_FIELD(for_all_tables); + COPY_SCALAR_FIELD(tableAction); + + return newnode; +} + +static CreateSubscriptionStmt * +_copyCreateSubscriptionStmt(const CreateSubscriptionStmt *from) +{ + CreateSubscriptionStmt *newnode = makeNode(CreateSubscriptionStmt); + + COPY_STRING_FIELD(subname); + COPY_STRING_FIELD(conninfo); + COPY_NODE_FIELD(publication); + COPY_NODE_FIELD(options); + + return newnode; +} + +static AlterSubscriptionStmt * +_copyAlterSubscriptionStmt(const AlterSubscriptionStmt *from) +{ + AlterSubscriptionStmt *newnode = makeNode(AlterSubscriptionStmt); + + COPY_SCALAR_FIELD(kind); + COPY_STRING_FIELD(subname); + COPY_STRING_FIELD(conninfo); + COPY_NODE_FIELD(publication); + COPY_NODE_FIELD(options); + + return newnode; +} + +static DropSubscriptionStmt * +_copyDropSubscriptionStmt(const DropSubscriptionStmt *from) +{ + DropSubscriptionStmt *newnode = makeNode(DropSubscriptionStmt); + + COPY_STRING_FIELD(subname); + COPY_SCALAR_FIELD(missing_ok); + COPY_SCALAR_FIELD(behavior); + + return newnode; +} + /* **************************************************************** * pg_list.h copy functions * **************************************************************** @@ -4376,7 +4763,7 @@ _copyAlterPolicyStmt(const AlterPolicyStmt *from) */ #define COPY_NODE_CELL(new, old) \ (new) = (ListCell *) palloc(sizeof(ListCell)); \ - lfirst(new) = copyObject(lfirst(old)); + lfirst(new) = copyObjectImpl(lfirst(old)); static List * _copyList(const List *from) @@ -4581,13 +4968,13 @@ _copyCleanConnStmt(const CleanConnStmt *from) #endif /* - * copyObject + * copyObjectImpl -- implementation of copyObject(); see nodes/nodes.h * * Create a copy of a Node tree or list. This is a "deep" copy: all * substructure is copied too, recursively. */ void * -copyObject(const void *from) +copyObjectImpl(const void *from) { void *retval; @@ -4611,6 +4998,9 @@ copyObject(const void *from) case T_Result: retval = _copyResult(from); break; + case T_ProjectSet: + retval = _copyProjectSet(from); + break; case T_ModifyTable: retval = _copyModifyTable(from); break; @@ -4635,6 +5025,9 @@ copyObject(const void *from) case T_Gather: retval = _copyGather(from); break; + case T_GatherMerge: + retval = _copyGatherMerge(from); + break; case T_SeqScan: retval = _copySeqScan(from); break; @@ -4662,12 +5055,18 @@ copyObject(const void *from) case T_FunctionScan: retval = _copyFunctionScan(from); break; + case T_TableFuncScan: + retval = _copyTableFuncScan(from); + break; case T_ValuesScan: retval = _copyValuesScan(from); break; case T_CteScan: retval = _copyCteScan(from); break; + case T_NamedTuplestoreScan: + retval = _copyNamedTuplestoreScan(from); + break; case T_WorkTableScan: retval = _copyWorkTableScan(from); break; @@ -4762,6 +5161,9 @@ copyObject(const void *from) case T_RangeVar: retval = _copyRangeVar(from); break; + case T_TableFunc: + retval = _copyTableFunc(from); + break; case T_IntoClause: retval = _copyIntoClause(from); break; @@ -4861,6 +5263,9 @@ copyObject(const void *from) case T_MinMaxExpr: retval = _copyMinMaxExpr(from); break; + case T_SQLValueFunction: + retval = _copySQLValueFunction(from); + break; case T_XmlExpr: retval = _copyXmlExpr(from); break; @@ -4882,6 +5287,9 @@ copyObject(const void *from) case T_CurrentOfExpr: retval = _copyCurrentOfExpr(from); break; + case T_NextValueExpr: + retval = _copyNextValueExpr(from); + break; case T_InferenceElem: retval = _copyInferenceElem(from); break; @@ -4919,6 +5327,9 @@ copyObject(const void *from) case T_AppendRelInfo: retval = _copyAppendRelInfo(from); break; + case T_PartitionedChildRelInfo: + retval = _copyPartitionedChildRelInfo(from); + break; case T_PlaceHolderInfo: retval = _copyPlaceHolderInfo(from); break; @@ -4963,6 +5374,9 @@ copyObject(const void *from) case T_Query: retval = _copyQuery(from); break; + case T_RawStmt: + retval = _copyRawStmt(from); + break; case T_InsertStmt: retval = _copyInsertStmt(from); break; @@ -4984,6 +5398,9 @@ copyObject(const void *from) case T_AlterTableCmd: retval = _copyAlterTableCmd(from); break; + case T_AlterCollationStmt: + retval = _copyAlterCollationStmt(from); + break; case T_AlterDomainStmt: retval = _copyAlterDomainStmt(from); break; @@ -5035,6 +5452,9 @@ copyObject(const void *from) case T_IndexStmt: retval = _copyIndexStmt(from); break; + case T_CreateStatsStmt: + retval = _copyCreateStatsStmt(from); + break; case T_CreateFunctionStmt: retval = _copyCreateFunctionStmt(from); break; @@ -5307,6 +5727,21 @@ copyObject(const void *from) case T_AlterPolicyStmt: retval = _copyAlterPolicyStmt(from); break; + case T_CreatePublicationStmt: + retval = _copyCreatePublicationStmt(from); + break; + case T_AlterPublicationStmt: + retval = _copyAlterPublicationStmt(from); + break; + case T_CreateSubscriptionStmt: + retval = _copyCreateSubscriptionStmt(from); + break; + case T_AlterSubscriptionStmt: + retval = _copyAlterSubscriptionStmt(from); + break; + case T_DropSubscriptionStmt: + retval = _copyDropSubscriptionStmt(from); + break; case T_A_Expr: retval = _copyAExpr(from); break; @@ -5361,6 +5796,12 @@ copyObject(const void *from) case T_RangeTableSample: retval = _copyRangeTableSample(from); break; + case T_RangeTableFunc: + retval = _copyRangeTableFunc(from); + break; + case T_RangeTableFuncCol: + retval = _copyRangeTableFuncCol(from); + break; case T_TypeName: retval = _copyTypeName(from); break; @@ -5415,8 +5856,8 @@ copyObject(const void *from) case T_CommonTableExpr: retval = _copyCommonTableExpr(from); break; - case T_FuncWithArgs: - retval = _copyFuncWithArgs(from); + case T_ObjectWithArgs: + retval = _copyObjectWithArgs(from); break; case T_AccessPriv: retval = _copyAccessPriv(from); @@ -5436,6 +5877,24 @@ copyObject(const void *from) case T_RoleSpec: retval = _copyRoleSpec(from); break; + case T_TriggerTransition: + retval = _copyTriggerTransition(from); + break; + case T_PartitionElem: + retval = _copyPartitionElem(from); + break; + case T_PartitionSpec: + retval = _copyPartitionSpec(from); + break; + case T_PartitionBoundSpec: + retval = _copyPartitionBoundSpec(from); + break; + case T_PartitionRangeDatum: + retval = _copyPartitionRangeDatum(from); + break; + case T_PartitionCmd: + retval = _copyPartitionCmd(from); + break; /* * MISCELLANEOUS NODES diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index e6f44f1cf8..c644aba4c1 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -19,7 +19,7 @@ * * * Portions Copyright (c) 2012-2014, TransLattice, Inc. - * 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 * Portions Copyright (c) 2010-2012 Postgres-XC Development Group * @@ -110,7 +110,7 @@ _equalRangeVar(const RangeVar *a, const RangeVar *b) COMPARE_STRING_FIELD(catalogname); COMPARE_STRING_FIELD(schemaname); COMPARE_STRING_FIELD(relname); - COMPARE_SCALAR_FIELD(inhOpt); + COMPARE_SCALAR_FIELD(inh); COMPARE_SCALAR_FIELD(relpersistence); COMPARE_NODE_FIELD(alias); COMPARE_LOCATION_FIELD(location); @@ -119,6 +119,26 @@ _equalRangeVar(const RangeVar *a, const RangeVar *b) } static bool +_equalTableFunc(const TableFunc *a, const TableFunc *b) +{ + COMPARE_NODE_FIELD(ns_names); + COMPARE_NODE_FIELD(ns_uris); + COMPARE_NODE_FIELD(docexpr); + COMPARE_NODE_FIELD(rowexpr); + COMPARE_NODE_FIELD(colnames); + COMPARE_NODE_FIELD(coltypes); + COMPARE_NODE_FIELD(coltypes); + COMPARE_NODE_FIELD(colcollations); + COMPARE_NODE_FIELD(colexprs); + COMPARE_NODE_FIELD(coldefexprs); + COMPARE_BITMAPSET_FIELD(notnulls); + COMPARE_SCALAR_FIELD(ordinalitycol); + COMPARE_LOCATION_FIELD(location); + + return true; +} + +static bool _equalIntoClause(const IntoClause *a, const IntoClause *b) { COMPARE_NODE_FIELD(rel); @@ -447,6 +467,7 @@ _equalSubPlan(const SubPlan *a, const SubPlan *b) COMPARE_SCALAR_FIELD(firstColCollation); COMPARE_SCALAR_FIELD(useHashTable); COMPARE_SCALAR_FIELD(unknownEqFalse); + COMPARE_SCALAR_FIELD(parallel_safe); COMPARE_NODE_FIELD(setParam); COMPARE_NODE_FIELD(parParam); COMPARE_NODE_FIELD(args); @@ -644,6 +665,17 @@ _equalMinMaxExpr(const MinMaxExpr *a, const MinMaxExpr *b) } static bool +_equalSQLValueFunction(const SQLValueFunction *a, const SQLValueFunction *b) +{ + COMPARE_SCALAR_FIELD(op); + COMPARE_SCALAR_FIELD(type); + COMPARE_SCALAR_FIELD(typmod); + COMPARE_LOCATION_FIELD(location); + + return true; +} + +static bool _equalXmlExpr(const XmlExpr *a, const XmlExpr *b) { COMPARE_SCALAR_FIELD(op); @@ -726,6 +758,15 @@ _equalCurrentOfExpr(const CurrentOfExpr *a, const CurrentOfExpr *b) } static bool +_equalNextValueExpr(const NextValueExpr *a, const NextValueExpr *b) +{ + COMPARE_SCALAR_FIELD(seqid); + COMPARE_SCALAR_FIELD(typeId); + + return true; +} + +static bool _equalInferenceElem(const InferenceElem *a, const InferenceElem *b) { COMPARE_NODE_FIELD(expr); @@ -818,6 +859,7 @@ _equalRestrictInfo(const RestrictInfo *a, const RestrictInfo *b) COMPARE_NODE_FIELD(clause); COMPARE_SCALAR_FIELD(is_pushed_down); COMPARE_SCALAR_FIELD(outerjoin_delayed); + COMPARE_SCALAR_FIELD(security_level); COMPARE_BITMAPSET_FIELD(required_relids); COMPARE_BITMAPSET_FIELD(outer_relids); COMPARE_BITMAPSET_FIELD(nullable_relids); @@ -887,6 +929,15 @@ _equalAppendRelInfo(const AppendRelInfo *a, const AppendRelInfo *b) } static bool +_equalPartitionedChildRelInfo(const PartitionedChildRelInfo *a, const PartitionedChildRelInfo *b) +{ + COMPARE_SCALAR_FIELD(parent_relid); + COMPARE_NODE_FIELD(child_rels); + + return true; +} + +static bool _equalPlaceHolderInfo(const PlaceHolderInfo *a, const PlaceHolderInfo *b) { COMPARE_SCALAR_FIELD(phid); @@ -934,6 +985,7 @@ _equalQuery(const Query *a, const Query *b) COMPARE_SCALAR_FIELD(resultRelation); COMPARE_SCALAR_FIELD(hasAggs); COMPARE_SCALAR_FIELD(hasWindowFuncs); + COMPARE_SCALAR_FIELD(hasTargetSRFs); COMPARE_SCALAR_FIELD(hasSubLinks); COMPARE_SCALAR_FIELD(hasDistinctOn); COMPARE_SCALAR_FIELD(hasRecursive); @@ -944,6 +996,7 @@ _equalQuery(const Query *a, const Query *b) COMPARE_NODE_FIELD(rtable); COMPARE_NODE_FIELD(jointree); COMPARE_NODE_FIELD(targetList); + COMPARE_SCALAR_FIELD(override); COMPARE_NODE_FIELD(onConflict); COMPARE_NODE_FIELD(returningList); COMPARE_NODE_FIELD(groupClause); @@ -958,6 +1011,18 @@ _equalQuery(const Query *a, const Query *b) COMPARE_NODE_FIELD(setOperations); COMPARE_NODE_FIELD(constraintDeps); COMPARE_NODE_FIELD(withCheckOptions); + COMPARE_LOCATION_FIELD(stmt_location); + COMPARE_LOCATION_FIELD(stmt_len); + + return true; +} + +static bool +_equalRawStmt(const RawStmt *a, const RawStmt *b) +{ + COMPARE_NODE_FIELD(stmt); + COMPARE_LOCATION_FIELD(stmt_location); + COMPARE_LOCATION_FIELD(stmt_len); return true; } @@ -971,6 +1036,7 @@ _equalInsertStmt(const InsertStmt *a, const InsertStmt *b) COMPARE_NODE_FIELD(onConflictClause); COMPARE_NODE_FIELD(returningList); COMPARE_NODE_FIELD(withClause); + COMPARE_SCALAR_FIELD(override); return true; } @@ -1065,6 +1131,14 @@ _equalAlterTableCmd(const AlterTableCmd *a, const AlterTableCmd *b) } static bool +_equalAlterCollationStmt(const AlterCollationStmt *a, const AlterCollationStmt *b) +{ + COMPARE_NODE_FIELD(collname); + + return true; +} + +static bool _equalAlterDomainStmt(const AlterDomainStmt *a, const AlterDomainStmt *b) { COMPARE_SCALAR_FIELD(subtype); @@ -1093,10 +1167,11 @@ _equalGrantStmt(const GrantStmt *a, const GrantStmt *b) } static bool -_equalFuncWithArgs(const FuncWithArgs *a, const FuncWithArgs *b) +_equalObjectWithArgs(const ObjectWithArgs *a, const ObjectWithArgs *b) { - COMPARE_NODE_FIELD(funcname); - COMPARE_NODE_FIELD(funcargs); + COMPARE_NODE_FIELD(objname); + COMPARE_NODE_FIELD(objargs); + COMPARE_SCALAR_FIELD(args_unspecified); return true; } @@ -1180,6 +1255,8 @@ _equalCreateStmt(const CreateStmt *a, const CreateStmt *b) COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(tableElts); COMPARE_NODE_FIELD(inhRelations); + COMPARE_NODE_FIELD(partspec); + COMPARE_NODE_FIELD(partbound); COMPARE_NODE_FIELD(ofTypename); COMPARE_NODE_FIELD(constraints); COMPARE_NODE_FIELD(options); @@ -1213,6 +1290,7 @@ _equalDefineStmt(const DefineStmt *a, const DefineStmt *b) COMPARE_NODE_FIELD(defnames); COMPARE_NODE_FIELD(args); COMPARE_NODE_FIELD(definition); + COMPARE_SCALAR_FIELD(if_not_exists); return true; } @@ -1221,7 +1299,6 @@ static bool _equalDropStmt(const DropStmt *a, const DropStmt *b) { COMPARE_NODE_FIELD(objects); - COMPARE_NODE_FIELD(arguments); COMPARE_SCALAR_FIELD(removeType); COMPARE_SCALAR_FIELD(behavior); COMPARE_SCALAR_FIELD(missing_ok); @@ -1244,8 +1321,7 @@ static bool _equalCommentStmt(const CommentStmt *a, const CommentStmt *b) { COMPARE_SCALAR_FIELD(objtype); - COMPARE_NODE_FIELD(objname); - COMPARE_NODE_FIELD(objargs); + COMPARE_NODE_FIELD(object); COMPARE_STRING_FIELD(comment); return true; @@ -1255,8 +1331,7 @@ static bool _equalSecLabelStmt(const SecLabelStmt *a, const SecLabelStmt *b) { COMPARE_SCALAR_FIELD(objtype); - COMPARE_NODE_FIELD(objname); - COMPARE_NODE_FIELD(objargs); + COMPARE_NODE_FIELD(object); COMPARE_STRING_FIELD(provider); COMPARE_STRING_FIELD(label); @@ -1301,6 +1376,18 @@ _equalIndexStmt(const IndexStmt *a, const IndexStmt *b) } static bool +_equalCreateStatsStmt(const CreateStatsStmt *a, const CreateStatsStmt *b) +{ + COMPARE_NODE_FIELD(defnames); + COMPARE_NODE_FIELD(stat_types); + COMPARE_NODE_FIELD(exprs); + COMPARE_NODE_FIELD(relations); + COMPARE_SCALAR_FIELD(if_not_exists); + + return true; +} + +static bool _equalCreateFunctionStmt(const CreateFunctionStmt *a, const CreateFunctionStmt *b) { COMPARE_SCALAR_FIELD(replace); @@ -1348,7 +1435,6 @@ _equalRenameStmt(const RenameStmt *a, const RenameStmt *b) COMPARE_SCALAR_FIELD(relationType); COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(object); - COMPARE_NODE_FIELD(objarg); COMPARE_STRING_FIELD(subname); COMPARE_STRING_FIELD(newname); COMPARE_SCALAR_FIELD(behavior); @@ -1362,8 +1448,7 @@ _equalAlterObjectDependsStmt(const AlterObjectDependsStmt *a, const AlterObjectD { COMPARE_SCALAR_FIELD(objectType); COMPARE_NODE_FIELD(relation); - COMPARE_NODE_FIELD(objname); - COMPARE_NODE_FIELD(objargs); + COMPARE_NODE_FIELD(object); COMPARE_NODE_FIELD(extname); return true; @@ -1375,7 +1460,6 @@ _equalAlterObjectSchemaStmt(const AlterObjectSchemaStmt *a, const AlterObjectSch COMPARE_SCALAR_FIELD(objectType); COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(object); - COMPARE_NODE_FIELD(objarg); COMPARE_STRING_FIELD(newschema); COMPARE_SCALAR_FIELD(missing_ok); @@ -1388,7 +1472,6 @@ _equalAlterOwnerStmt(const AlterOwnerStmt *a, const AlterOwnerStmt *b) COMPARE_SCALAR_FIELD(objectType); COMPARE_NODE_FIELD(relation); COMPARE_NODE_FIELD(object); - COMPARE_NODE_FIELD(objarg); COMPARE_NODE_FIELD(newowner); return true; @@ -1398,7 +1481,6 @@ static bool _equalAlterOperatorStmt(const AlterOperatorStmt *a, const AlterOperatorStmt *b) { COMPARE_NODE_FIELD(opername); - COMPARE_NODE_FIELD(operargs); COMPARE_NODE_FIELD(options); return true; @@ -1484,10 +1566,11 @@ static bool _equalAlterEnumStmt(const AlterEnumStmt *a, const AlterEnumStmt *b) { COMPARE_NODE_FIELD(typeName); + COMPARE_STRING_FIELD(oldVal); COMPARE_STRING_FIELD(newVal); COMPARE_STRING_FIELD(newValNeighbor); COMPARE_SCALAR_FIELD(newValIsAfter); - COMPARE_SCALAR_FIELD(skipIfExists); + COMPARE_SCALAR_FIELD(skipIfNewValExists); return true; } @@ -1542,7 +1625,6 @@ _equalCreateOpClassItem(const CreateOpClassItem *a, const CreateOpClassItem *b) { COMPARE_SCALAR_FIELD(itemtype); COMPARE_NODE_FIELD(name); - COMPARE_NODE_FIELD(args); COMPARE_SCALAR_FIELD(number); COMPARE_NODE_FIELD(order_family); COMPARE_NODE_FIELD(class_args); @@ -1675,6 +1757,7 @@ _equalCreateSeqStmt(const CreateSeqStmt *a, const CreateSeqStmt *b) COMPARE_NODE_FIELD(sequence); COMPARE_NODE_FIELD(options); COMPARE_SCALAR_FIELD(ownerId); + COMPARE_SCALAR_FIELD(for_identity); COMPARE_SCALAR_FIELD(if_not_exists); return true; @@ -1685,6 +1768,7 @@ _equalAlterSeqStmt(const AlterSeqStmt *a, const AlterSeqStmt *b) { COMPARE_NODE_FIELD(sequence); COMPARE_NODE_FIELD(options); + COMPARE_SCALAR_FIELD(for_identity); COMPARE_SCALAR_FIELD(missing_ok); return true; @@ -1786,8 +1870,7 @@ _equalAlterExtensionContentsStmt(const AlterExtensionContentsStmt *a, const Alte COMPARE_STRING_FIELD(extname); COMPARE_SCALAR_FIELD(action); COMPARE_SCALAR_FIELD(objtype); - COMPARE_NODE_FIELD(objname); - COMPARE_NODE_FIELD(objargs); + COMPARE_NODE_FIELD(object); return true; } @@ -1820,6 +1903,7 @@ _equalCreateForeignServerStmt(const CreateForeignServerStmt *a, const CreateFore COMPARE_STRING_FIELD(version); COMPARE_STRING_FIELD(fdwname); COMPARE_NODE_FIELD(options); + COMPARE_SCALAR_FIELD(if_not_exists); return true; } @@ -1841,6 +1925,7 @@ _equalCreateUserMappingStmt(const CreateUserMappingStmt *a, const CreateUserMapp COMPARE_NODE_FIELD(user); COMPARE_STRING_FIELD(servername); COMPARE_NODE_FIELD(options); + COMPARE_SCALAR_FIELD(if_not_exists); return true; } @@ -1925,6 +2010,7 @@ _equalCreateTrigStmt(const CreateTrigStmt *a, const CreateTrigStmt *b) COMPARE_NODE_FIELD(columns); COMPARE_NODE_FIELD(whenClause); COMPARE_SCALAR_FIELD(isconstraint); + COMPARE_NODE_FIELD(transitionRels); COMPARE_SCALAR_FIELD(deferrable); COMPARE_SCALAR_FIELD(initdeferred); COMPARE_NODE_FIELD(constrrel); @@ -2139,11 +2225,73 @@ _equalAlterTSConfigurationStmt(const AlterTSConfigurationStmt *a, } static bool +_equalCreatePublicationStmt(const CreatePublicationStmt *a, + const CreatePublicationStmt *b) +{ + COMPARE_STRING_FIELD(pubname); + COMPARE_NODE_FIELD(options); + COMPARE_NODE_FIELD(tables); + COMPARE_SCALAR_FIELD(for_all_tables); + + return true; +} + +static bool +_equalAlterPublicationStmt(const AlterPublicationStmt *a, + const AlterPublicationStmt *b) +{ + COMPARE_STRING_FIELD(pubname); + COMPARE_NODE_FIELD(options); + COMPARE_NODE_FIELD(tables); + COMPARE_SCALAR_FIELD(for_all_tables); + COMPARE_SCALAR_FIELD(tableAction); + + return true; +} + +static bool +_equalCreateSubscriptionStmt(const CreateSubscriptionStmt *a, + const CreateSubscriptionStmt *b) +{ + COMPARE_STRING_FIELD(subname); + COMPARE_STRING_FIELD(conninfo); + COMPARE_NODE_FIELD(publication); + COMPARE_NODE_FIELD(options); + + return true; +} + +static bool +_equalAlterSubscriptionStmt(const AlterSubscriptionStmt *a, + const AlterSubscriptionStmt *b) +{ + COMPARE_SCALAR_FIELD(kind); + COMPARE_STRING_FIELD(subname); + COMPARE_STRING_FIELD(conninfo); + COMPARE_NODE_FIELD(publication); + COMPARE_NODE_FIELD(options); + + return true; +} + +static bool +_equalDropSubscriptionStmt(const DropSubscriptionStmt *a, + const DropSubscriptionStmt *b) +{ + COMPARE_STRING_FIELD(subname); + COMPARE_SCALAR_FIELD(missing_ok); + COMPARE_SCALAR_FIELD(behavior); + + return true; +} + +static bool _equalCreatePolicyStmt(const CreatePolicyStmt *a, const CreatePolicyStmt *b) { COMPARE_STRING_FIELD(policy_name); COMPARE_NODE_FIELD(table); COMPARE_STRING_FIELD(cmd_name); + COMPARE_SCALAR_FIELD(permissive); COMPARE_NODE_FIELD(roles); COMPARE_NODE_FIELD(qual); COMPARE_NODE_FIELD(with_check); @@ -2373,6 +2521,36 @@ _equalRangeTableSample(const RangeTableSample *a, const RangeTableSample *b) } static bool +_equalRangeTableFunc(const RangeTableFunc *a, const RangeTableFunc *b) +{ + COMPARE_SCALAR_FIELD(lateral); + COMPARE_NODE_FIELD(docexpr); + COMPARE_NODE_FIELD(rowexpr); + COMPARE_NODE_FIELD(namespaces); + COMPARE_NODE_FIELD(columns); + COMPARE_NODE_FIELD(alias); + COMPARE_LOCATION_FIELD(location); + + return true; +} + +static bool +_equalRangeTableFuncCol(const RangeTableFuncCol *a, const RangeTableFuncCol *b) +{ + COMPARE_STRING_FIELD(colname); + COMPARE_NODE_FIELD(typeName); + COMPARE_SCALAR_FIELD(for_ordinality); + COMPARE_NODE_FIELD(typeName); + COMPARE_SCALAR_FIELD(is_not_null); + COMPARE_NODE_FIELD(colexpr); + COMPARE_NODE_FIELD(coldefexpr); + COMPARE_LOCATION_FIELD(location); + + return true; +} + + +static bool _equalIndexElem(const IndexElem *a, const IndexElem *b) { COMPARE_STRING_FIELD(name); @@ -2395,9 +2573,11 @@ _equalColumnDef(const ColumnDef *a, const ColumnDef *b) COMPARE_SCALAR_FIELD(is_local); COMPARE_SCALAR_FIELD(is_not_null); COMPARE_SCALAR_FIELD(is_from_type); + COMPARE_SCALAR_FIELD(is_from_parent); COMPARE_SCALAR_FIELD(storage); COMPARE_NODE_FIELD(raw_default); COMPARE_NODE_FIELD(cooked_default); + COMPARE_SCALAR_FIELD(identity); COMPARE_NODE_FIELD(collClause); COMPARE_SCALAR_FIELD(collOid); COMPARE_NODE_FIELD(constraints); @@ -2418,6 +2598,7 @@ _equalConstraint(const Constraint *a, const Constraint *b) COMPARE_SCALAR_FIELD(is_no_inherit); COMPARE_NODE_FIELD(raw_expr); COMPARE_STRING_FIELD(cooked_expr); + COMPARE_SCALAR_FIELD(generated_when); COMPARE_NODE_FIELD(keys); COMPARE_NODE_FIELD(exclusions); COMPARE_NODE_FIELD(options); @@ -2446,6 +2627,7 @@ _equalDefElem(const DefElem *a, const DefElem *b) COMPARE_STRING_FIELD(defname); COMPARE_NODE_FIELD(arg); COMPARE_SCALAR_FIELD(defaction); + COMPARE_LOCATION_FIELD(location); return true; } @@ -2456,6 +2638,7 @@ _equalLockingClause(const LockingClause *a, const LockingClause *b) COMPARE_NODE_FIELD(lockedRels); COMPARE_SCALAR_FIELD(strength); COMPARE_SCALAR_FIELD(waitPolicy); + COMPARE_LOCATION_FIELD(location); return true; } @@ -2472,15 +2655,15 @@ _equalRangeTblEntry(const RangeTblEntry *a, const RangeTblEntry *b) COMPARE_SCALAR_FIELD(jointype); COMPARE_NODE_FIELD(joinaliasvars); COMPARE_NODE_FIELD(functions); + COMPARE_NODE_FIELD(tablefunc); COMPARE_SCALAR_FIELD(funcordinality); COMPARE_NODE_FIELD(values_lists); - COMPARE_NODE_FIELD(values_collations); COMPARE_STRING_FIELD(ctename); COMPARE_SCALAR_FIELD(ctelevelsup); COMPARE_SCALAR_FIELD(self_reference); - COMPARE_NODE_FIELD(ctecoltypes); - COMPARE_NODE_FIELD(ctecoltypmods); - COMPARE_NODE_FIELD(ctecolcollations); + COMPARE_NODE_FIELD(coltypes); + COMPARE_NODE_FIELD(coltypmods); + COMPARE_NODE_FIELD(colcollations); COMPARE_NODE_FIELD(alias); COMPARE_NODE_FIELD(eref); COMPARE_SCALAR_FIELD(lateral); @@ -2682,6 +2865,69 @@ _equalRoleSpec(const RoleSpec *a, const RoleSpec *b) return true; } +static bool +_equalTriggerTransition(const TriggerTransition *a, const TriggerTransition *b) +{ + COMPARE_STRING_FIELD(name); + COMPARE_SCALAR_FIELD(isNew); + COMPARE_SCALAR_FIELD(isTable); + + return true; +} + +static bool +_equalPartitionElem(const PartitionElem *a, const PartitionElem *b) +{ + COMPARE_STRING_FIELD(name); + COMPARE_NODE_FIELD(expr); + COMPARE_NODE_FIELD(collation); + COMPARE_NODE_FIELD(opclass); + COMPARE_LOCATION_FIELD(location); + + return true; +} + +static bool +_equalPartitionSpec(const PartitionSpec *a, const PartitionSpec *b) +{ + COMPARE_STRING_FIELD(strategy); + COMPARE_NODE_FIELD(partParams); + COMPARE_LOCATION_FIELD(location); + + return true; +} + +static bool +_equalPartitionBoundSpec(const PartitionBoundSpec *a, const PartitionBoundSpec *b) +{ + COMPARE_SCALAR_FIELD(strategy); + COMPARE_NODE_FIELD(listdatums); + COMPARE_NODE_FIELD(lowerdatums); + COMPARE_NODE_FIELD(upperdatums); + COMPARE_LOCATION_FIELD(location); + + return true; +} + +static bool +_equalPartitionRangeDatum(const PartitionRangeDatum *a, const PartitionRangeDatum *b) +{ + COMPARE_SCALAR_FIELD(infinite); + COMPARE_NODE_FIELD(value); + COMPARE_LOCATION_FIELD(location); + + return true; +} + +static bool +_equalPartitionCmd(const PartitionCmd *a, const PartitionCmd *b) +{ + COMPARE_NODE_FIELD(name); + COMPARE_NODE_FIELD(bound); + + return true; +} + /* * Stuff from pg_list.h */ @@ -2891,6 +3137,9 @@ equal(const void *a, const void *b) case T_RangeVar: retval = _equalRangeVar(a, b); break; + case T_TableFunc: + retval = _equalTableFunc(a, b); + break; case T_IntoClause: retval = _equalIntoClause(a, b); break; @@ -2990,6 +3239,9 @@ equal(const void *a, const void *b) case T_MinMaxExpr: retval = _equalMinMaxExpr(a, b); break; + case T_SQLValueFunction: + retval = _equalSQLValueFunction(a, b); + break; case T_XmlExpr: retval = _equalXmlExpr(a, b); break; @@ -3011,6 +3263,9 @@ equal(const void *a, const void *b) case T_CurrentOfExpr: retval = _equalCurrentOfExpr(a, b); break; + case T_NextValueExpr: + retval = _equalNextValueExpr(a, b); + break; case T_InferenceElem: retval = _equalInferenceElem(a, b); break; @@ -3048,6 +3303,9 @@ equal(const void *a, const void *b) case T_AppendRelInfo: retval = _equalAppendRelInfo(a, b); break; + case T_PartitionedChildRelInfo: + retval = _equalPartitionedChildRelInfo(a, b); + break; case T_PlaceHolderInfo: retval = _equalPlaceHolderInfo(a, b); break; @@ -3079,6 +3337,9 @@ equal(const void *a, const void *b) case T_Query: retval = _equalQuery(a, b); break; + case T_RawStmt: + retval = _equalRawStmt(a, b); + break; case T_InsertStmt: retval = _equalInsertStmt(a, b); break; @@ -3100,6 +3361,9 @@ equal(const void *a, const void *b) case T_AlterTableCmd: retval = _equalAlterTableCmd(a, b); break; + case T_AlterCollationStmt: + retval = _equalAlterCollationStmt(a, b); + break; case T_AlterDomainStmt: retval = _equalAlterDomainStmt(a, b); break; @@ -3151,6 +3415,9 @@ equal(const void *a, const void *b) case T_IndexStmt: retval = _equalIndexStmt(a, b); break; + case T_CreateStatsStmt: + retval = _equalCreateStatsStmt(a, b); + break; case T_CreateFunctionStmt: retval = _equalCreateFunctionStmt(a, b); break; @@ -3423,6 +3690,21 @@ equal(const void *a, const void *b) case T_AlterPolicyStmt: retval = _equalAlterPolicyStmt(a, b); break; + case T_CreatePublicationStmt: + retval = _equalCreatePublicationStmt(a, b); + break; + case T_AlterPublicationStmt: + retval = _equalAlterPublicationStmt(a, b); + break; + case T_CreateSubscriptionStmt: + retval = _equalCreateSubscriptionStmt(a, b); + break; + case T_AlterSubscriptionStmt: + retval = _equalAlterSubscriptionStmt(a, b); + break; + case T_DropSubscriptionStmt: + retval = _equalDropSubscriptionStmt(a, b); + break; case T_A_Expr: retval = _equalAExpr(a, b); break; @@ -3477,6 +3759,12 @@ equal(const void *a, const void *b) case T_RangeTableSample: retval = _equalRangeTableSample(a, b); break; + case T_RangeTableFunc: + retval = _equalRangeTableFunc(a, b); + break; + case T_RangeTableFuncCol: + retval = _equalRangeTableFuncCol(a, b); + break; case T_TypeName: retval = _equalTypeName(a, b); break; @@ -3531,8 +3819,8 @@ equal(const void *a, const void *b) case T_CommonTableExpr: retval = _equalCommonTableExpr(a, b); break; - case T_FuncWithArgs: - retval = _equalFuncWithArgs(a, b); + case T_ObjectWithArgs: + retval = _equalObjectWithArgs(a, b); break; case T_AccessPriv: retval = _equalAccessPriv(a, b); @@ -3548,6 +3836,24 @@ equal(const void *a, const void *b) case T_RoleSpec: retval = _equalRoleSpec(a, b); break; + case T_TriggerTransition: + retval = _equalTriggerTransition(a, b); + break; + case T_PartitionElem: + retval = _equalPartitionElem(a, b); + break; + case T_PartitionSpec: + retval = _equalPartitionSpec(a, b); + break; + case T_PartitionBoundSpec: + retval = _equalPartitionBoundSpec(a, b); + break; + case T_PartitionRangeDatum: + retval = _equalPartitionRangeDatum(a, b); + break; + case T_PartitionCmd: + retval = _equalPartitionCmd(a, b); + break; default: elog(ERROR, "unrecognized node type: %d", diff --git a/src/backend/nodes/extensible.c b/src/backend/nodes/extensible.c index a4f1c99016..01cd3c84fb 100644 --- a/src/backend/nodes/extensible.c +++ b/src/backend/nodes/extensible.c @@ -10,7 +10,7 @@ * and GetExtensibleNodeMethods to get information about a previously * registered type of extensible node. * - * 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 * * IDENTIFICATION diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c index 085b68cd1f..f09aa248d8 100644 --- a/src/backend/nodes/list.c +++ b/src/backend/nodes/list.c @@ -4,7 +4,7 @@ * implementation for PostgreSQL generic linked list package * * - * 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 * * diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c index b564d403a5..f138afd706 100644 --- a/src/backend/nodes/makefuncs.c +++ b/src/backend/nodes/makefuncs.c @@ -4,7 +4,7 @@ * creator functions for primitive nodes. The functions here are for * the most frequently created 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 * * @@ -216,10 +216,10 @@ makeWholeRowVar(RangeTblEntry *rte, default: /* - * RTE is a join, subselect, or VALUES. We represent this as a - * whole-row Var of RECORD type. (Note that in most cases the Var - * will be expanded to a RowExpr during planning, but that is not - * our concern here.) + * RTE is a join, subselect, tablefunc, or VALUES. We represent + * this as a whole-row Var of RECORD type. (Note that in most + * cases the Var will be expanded to a RowExpr during planning, + * but that is not our concern here.) */ result = makeVar(varno, InvalidAttrNumber, @@ -429,7 +429,7 @@ makeRangeVar(char *schemaname, char *relname, int location) r->catalogname = NULL; r->schemaname = schemaname; r->relname = relname; - r->inhOpt = INH_DEFAULT; + r->inh = true; r->relpersistence = RELPERSISTENCE_PERMANENT; r->alias = NULL; r->location = location; @@ -500,6 +500,7 @@ makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid) n->is_local = true; n->is_not_null = false; n->is_from_type = false; + n->is_from_parent = false; n->storage = 0; n->raw_default = NULL; n->cooked_default = NULL; @@ -546,7 +547,7 @@ makeFuncExpr(Oid funcid, Oid rettype, List *args, * and no special action. */ DefElem * -makeDefElem(char *name, Node *arg) +makeDefElem(char *name, Node *arg, int location) { DefElem *res = makeNode(DefElem); @@ -554,6 +555,7 @@ makeDefElem(char *name, Node *arg) res->defname = name; res->arg = arg; res->defaction = DEFELEM_UNSPEC; + res->location = location; return res; } @@ -564,7 +566,7 @@ makeDefElem(char *name, Node *arg) */ DefElem * makeDefElemExtended(char *nameSpace, char *name, Node *arg, - DefElemAction defaction) + DefElemAction defaction, int location) { DefElem *res = makeNode(DefElem); @@ -572,6 +574,7 @@ makeDefElemExtended(char *nameSpace, char *name, Node *arg, res->defname = name; res->arg = arg; res->defaction = defaction; + res->location = location; return res; } diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index d05332c10a..eb3e1ce1c1 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -3,7 +3,7 @@ * nodeFuncs.c * Various general-purpose manipulations of Node trees * - * 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 * * @@ -111,8 +111,7 @@ exprType(const Node *expr) if (!qtree || !IsA(qtree, Query)) elog(ERROR, "cannot get type for untransformed sublink"); - tent = (TargetEntry *) linitial(qtree->targetList); - Assert(IsA(tent, TargetEntry)); + tent = linitial_node(TargetEntry, qtree->targetList); Assert(!tent->resjunk); type = exprType((Node *) tent->expr); if (sublink->subLinkType == ARRAY_SUBLINK) @@ -218,6 +217,9 @@ exprType(const Node *expr) case T_MinMaxExpr: type = ((const MinMaxExpr *) expr)->minmaxtype; break; + case T_SQLValueFunction: + type = ((const SQLValueFunction *) expr)->type; + break; case T_XmlExpr: if (((const XmlExpr *) expr)->op == IS_DOCUMENT) type = BOOLOID; @@ -244,6 +246,9 @@ exprType(const Node *expr) case T_CurrentOfExpr: type = BOOLOID; break; + case T_NextValueExpr: + type = ((const NextValueExpr *) expr)->typeId; + break; case T_InferenceElem: { const InferenceElem *n = (const InferenceElem *) expr; @@ -319,8 +324,7 @@ exprTypmod(const Node *expr) if (!qtree || !IsA(qtree, Query)) elog(ERROR, "cannot get type for untransformed sublink"); - tent = (TargetEntry *) linitial(qtree->targetList); - Assert(IsA(tent, TargetEntry)); + tent = linitial_node(TargetEntry, qtree->targetList); Assert(!tent->resjunk); return exprTypmod((Node *) tent->expr); /* note we don't need to care if it's an array */ @@ -378,9 +382,8 @@ exprTypmod(const Node *expr) return -1; /* no point in trying harder */ foreach(arg, cexpr->args) { - CaseWhen *w = (CaseWhen *) lfirst(arg); + CaseWhen *w = lfirst_node(CaseWhen, arg); - Assert(IsA(w, CaseWhen)); if (exprType((Node *) w->result) != casetype) return -1; if (exprTypmod((Node *) w->result) != typmod) @@ -479,6 +482,8 @@ exprTypmod(const Node *expr) return typmod; } break; + case T_SQLValueFunction: + return ((const SQLValueFunction *) expr)->typmod; case T_CoerceToDomain: return ((const CoerceToDomain *) expr)->resulttypmod; case T_CoerceToDomainValue: @@ -718,6 +723,8 @@ expression_returns_set_walker(Node *node, void *context) return false; if (IsA(node, MinMaxExpr)) return false; + if (IsA(node, SQLValueFunction)) + return false; if (IsA(node, XmlExpr)) return false; @@ -802,8 +809,7 @@ exprCollation(const Node *expr) if (!qtree || !IsA(qtree, Query)) elog(ERROR, "cannot get collation for untransformed sublink"); - tent = (TargetEntry *) linitial(qtree->targetList); - Assert(IsA(tent, TargetEntry)); + tent = linitial_node(TargetEntry, qtree->targetList); Assert(!tent->resjunk); coll = exprCollation((Node *) tent->expr); /* collation doesn't change if it's converted to array */ @@ -883,6 +889,9 @@ exprCollation(const Node *expr) case T_MinMaxExpr: coll = ((const MinMaxExpr *) expr)->minmaxcollid; break; + case T_SQLValueFunction: + coll = InvalidOid; /* all cases return non-collatable types */ + break; case T_XmlExpr: /* @@ -913,6 +922,9 @@ exprCollation(const Node *expr) case T_CurrentOfExpr: coll = InvalidOid; /* result is always boolean */ break; + case T_NextValueExpr: + coll = InvalidOid; /* result is always an integer type */ + break; case T_InferenceElem: coll = exprCollation((Node *) ((const InferenceElem *) expr)->expr); break; @@ -1042,8 +1054,7 @@ exprSetCollation(Node *expr, Oid collation) if (!qtree || !IsA(qtree, Query)) elog(ERROR, "cannot set collation for untransformed sublink"); - tent = (TargetEntry *) linitial(qtree->targetList); - Assert(IsA(tent, TargetEntry)); + tent = linitial_node(TargetEntry, qtree->targetList); Assert(!tent->resjunk); Assert(collation == exprCollation((Node *) tent->expr)); } @@ -1091,6 +1102,9 @@ exprSetCollation(Node *expr, Oid collation) case T_MinMaxExpr: ((MinMaxExpr *) expr)->minmaxcollid = collation; break; + case T_SQLValueFunction: + Assert(!OidIsValid(collation)); /* no collatable results */ + break; case T_XmlExpr: Assert((((XmlExpr *) expr)->op == IS_XMLSERIALIZE) ? (collation == DEFAULT_COLLATION_OID) : @@ -1114,6 +1128,10 @@ exprSetCollation(Node *expr, Oid collation) case T_CurrentOfExpr: Assert(!OidIsValid(collation)); /* result is always boolean */ break; + case T_NextValueExpr: + Assert(!OidIsValid(collation)); /* result is always an integer + * type */ + break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(expr)); break; @@ -1204,6 +1222,9 @@ exprLocation(const Node *expr) case T_RangeVar: loc = ((const RangeVar *) expr)->location; break; + case T_TableFunc: + loc = ((const TableFunc *) expr)->location; + break; case T_Var: loc = ((const Var *) expr)->location; break; @@ -1364,6 +1385,10 @@ exprLocation(const Node *expr) /* GREATEST/LEAST keyword should always be the first thing */ loc = ((const MinMaxExpr *) expr)->location; break; + case T_SQLValueFunction: + /* function keyword should always be the first thing */ + loc = ((const SQLValueFunction *) expr)->location; + break; case T_XmlExpr: { const XmlExpr *xexpr = (const XmlExpr *) expr; @@ -1535,6 +1560,18 @@ exprLocation(const Node *expr) /* just use nested expr's location */ loc = exprLocation((Node *) ((const InferenceElem *) expr)->expr); break; + case T_PartitionElem: + loc = ((const PartitionElem *) expr)->location; + break; + case T_PartitionSpec: + loc = ((const PartitionSpec *) expr)->location; + break; + case T_PartitionBoundSpec: + loc = ((const PartitionBoundSpec *) expr)->location; + break; + case T_PartitionRangeDatum: + loc = ((const PartitionRangeDatum *) expr)->location; + break; default: /* for any other node type it's just unknown... */ loc = -1; @@ -1633,9 +1670,10 @@ set_sa_opfuncid(ScalarArrayOpExpr *opexpr) * for themselves, in case additional checks should be made, or because they * have special rules about which parts of the tree need to be visited. * - * Note: we ignore MinMaxExpr, XmlExpr, and CoerceToDomain nodes, because they - * do not contain SQL function OIDs. However, they can invoke SQL-visible - * functions, so callers should take thought about how to treat them. + * Note: we ignore MinMaxExpr, SQLValueFunction, XmlExpr, and CoerceToDomain + * nodes, because they do not contain SQL function OIDs. However, they can + * invoke SQL-visible functions, so callers should take thought about how to + * treat them. */ bool check_functions_in_node(Node *node, check_function_callback checker, @@ -1859,6 +1897,8 @@ expression_tree_walker(Node *node, case T_CaseTestExpr: case T_SetToDefault: case T_CurrentOfExpr: + case T_NextValueExpr: + case T_SQLValueFunction: case T_RangeTblRef: case T_SortGroupClause: /* primitive node types with no expression subnodes */ @@ -2025,9 +2065,8 @@ expression_tree_walker(Node *node, /* we assume walker doesn't care about CaseWhens, either */ foreach(temp, caseexpr->args) { - CaseWhen *when = (CaseWhen *) lfirst(temp); + CaseWhen *when = lfirst_node(CaseWhen, temp); - Assert(IsA(when, CaseWhen)); if (walker(when->expr, context)) return true; if (walker(when->result, context)) @@ -2192,6 +2231,22 @@ expression_tree_walker(Node *node, return true; } break; + case T_TableFunc: + { + TableFunc *tf = (TableFunc *) node; + + if (walker(tf->ns_uris, context)) + return true; + if (walker(tf->docexpr, context)) + return true; + if (walker(tf->rowexpr, context)) + return true; + if (walker(tf->colexprs, context)) + return true; + if (walker(tf->coldefexprs, context)) + return true; + } + break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); @@ -2283,6 +2338,7 @@ range_table_walker(List *rtable, return true; break; case RTE_CTE: + case RTE_NAMEDTUPLESTORE: /* nothing to do */ break; case RTE_SUBQUERY: @@ -2299,6 +2355,10 @@ range_table_walker(List *rtable, if (walker(rte->functions, context)) return true; break; + case RTE_TABLEFUNC: + if (walker(rte->tablefunc, context)) + return true; + break; case RTE_VALUES: if (walker(rte->values_lists, context)) return true; @@ -2438,6 +2498,8 @@ expression_tree_mutator(Node *node, case T_CaseTestExpr: case T_SetToDefault: case T_CurrentOfExpr: + case T_NextValueExpr: + case T_SQLValueFunction: case T_RangeTblRef: case T_SortGroupClause: return (Node *) copyObject(node); @@ -2992,6 +3054,20 @@ expression_tree_mutator(Node *node, return (Node *) newnode; } break; + case T_TableFunc: + { + TableFunc *tf = (TableFunc *) node; + TableFunc *newnode; + + FLATCOPY(newnode, tf, TableFunc); + MUTATE(newnode->ns_uris, tf->ns_uris, List *); + MUTATE(newnode->docexpr, tf->docexpr, Node *); + MUTATE(newnode->rowexpr, tf->rowexpr, Node *); + MUTATE(newnode->colexprs, tf->colexprs, List *); + MUTATE(newnode->coldefexprs, tf->coldefexprs, List *); + return (Node *) newnode; + } + break; default: elog(ERROR, "unrecognized node type: %d", (int) nodeTag(node)); @@ -3086,6 +3162,7 @@ range_table_mutator(List *rtable, #ifdef PGXC case RTE_REMOTE_DUMMY: #endif /* PGXC */ + case RTE_NAMEDTUPLESTORE: /* nothing to do */ break; case RTE_SUBQUERY: @@ -3112,6 +3189,9 @@ range_table_mutator(List *rtable, case RTE_FUNCTION: MUTATE(newrte->functions, rte->functions, List *); break; + case RTE_TABLEFUNC: + MUTATE(newrte->tablefunc, rte->tablefunc, TableFunc *); + break; case RTE_VALUES: MUTATE(newrte->values_lists, rte->values_lists, List *); break; @@ -3205,6 +3285,7 @@ raw_expression_tree_walker(Node *node, { case T_SetToDefault: case T_CurrentOfExpr: + case T_SQLValueFunction: case T_Integer: case T_Float: case T_String: @@ -3242,9 +3323,8 @@ raw_expression_tree_walker(Node *node, /* we assume walker doesn't care about CaseWhens, either */ foreach(temp, caseexpr->args) { - CaseWhen *when = (CaseWhen *) lfirst(temp); + CaseWhen *when = lfirst_node(CaseWhen, temp); - Assert(IsA(when, CaseWhen)); if (walker(when->expr, context)) return true; if (walker(when->result, context)) @@ -3536,6 +3616,32 @@ raw_expression_tree_walker(Node *node, return true; } break; + case T_RangeTableFunc: + { + RangeTableFunc *rtf = (RangeTableFunc *) node; + + if (walker(rtf->docexpr, context)) + return true; + if (walker(rtf->rowexpr, context)) + return true; + if (walker(rtf->namespaces, context)) + return true; + if (walker(rtf->columns, context)) + return true; + if (walker(rtf->alias, context)) + return true; + } + break; + case T_RangeTableFuncCol: + { + RangeTableFuncCol *rtfc = (RangeTableFuncCol *) node; + + if (walker(rtfc->colexpr, context)) + return true; + if (walker(rtfc->coldefexpr, context)) + return true; + } + break; case T_TypeName: { TypeName *tn = (TypeName *) node; @@ -3716,9 +3822,8 @@ planstate_walk_subplans(List *plans, foreach(lc, plans) { - SubPlanState *sps = (SubPlanState *) lfirst(lc); + SubPlanState *sps = lfirst_node(SubPlanState, lc); - Assert(IsA(sps, SubPlanState)); if (walker(sps->planstate, context)) return true; } diff --git a/src/backend/nodes/nodes.c b/src/backend/nodes/nodes.c index aea3880858..d3345aae6d 100644 --- a/src/backend/nodes/nodes.c +++ b/src/backend/nodes/nodes.c @@ -4,7 +4,7 @@ * support code for nodes (now that we have removed the home-brew * inheritance system, our support code for nodes is much simpler) * - * 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 * * diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 522387a3f8..d5165ddd4e 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -4,7 +4,7 @@ * Output functions for Postgres tree nodes. * * Portions Copyright (c) 2012-2014, TransLattice, Inc. - * 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 * * @@ -118,7 +118,7 @@ set_portable_output(bool value) /* 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) \ @@ -134,7 +134,7 @@ set_portable_output(bool value) /* Write a bitmapset field */ #define WRITE_BITMAPSET_FIELD(fldname) \ (appendStringInfo(str, " :" CppAsString(fldname) " "), \ - _outBitmapset(str, node->fldname)) + outBitmapset(str, node->fldname)) #ifdef XCP #define NSP_NAME(oid) \ @@ -146,9 +146,9 @@ set_portable_output(bool value) */ #define WRITE_RELID_INTERNAL(relid) \ - (_outToken(str, OidIsValid((relid)) ? NSP_NAME(get_rel_namespace((relid))) : NULL), \ + (outToken(str, OidIsValid((relid)) ? NSP_NAME(get_rel_namespace((relid))) : NULL), \ appendStringInfoChar(str, ' '), \ - _outToken(str, OidIsValid((relid)) ? get_rel_name((relid)) : NULL)) + outToken(str, OidIsValid((relid)) ? get_rel_name((relid)) : NULL)) /* write an OID which is a relation OID */ #define WRITE_RELID_FIELD(fldname) \ @@ -179,9 +179,9 @@ set_portable_output(bool value) /* write an OID which is a data type OID */ #define WRITE_TYPID_FIELD(fldname) \ (appendStringInfo(str, " :" CppAsString(fldname) " "), \ - _outToken(str, OidIsValid(node->fldname) ? NSP_NAME(get_typ_namespace(node->fldname)) : NULL), \ + outToken(str, OidIsValid(node->fldname) ? NSP_NAME(get_typ_namespace(node->fldname)) : NULL), \ appendStringInfoChar(str, ' '), \ - _outToken(str, OidIsValid(node->fldname) ? get_typ_name(node->fldname) : NULL)) + outToken(str, OidIsValid(node->fldname) ? get_typ_name(node->fldname) : NULL)) /* write an OID which is a function OID */ #define WRITE_FUNCID_FIELD(fldname) \ @@ -191,18 +191,18 @@ set_portable_output(bool value) { \ Oid *argtypes; \ int i, nargs; \ - _outToken(str, NSP_NAME(get_func_namespace(node->fldname))); \ + outToken(str, NSP_NAME(get_func_namespace(node->fldname))); \ appendStringInfoChar(str, ' '); \ - _outToken(str, get_func_name(node->fldname)); \ + outToken(str, get_func_name(node->fldname)); \ appendStringInfoChar(str, ' '); \ get_func_signature(node->fldname, &argtypes, &nargs); \ appendStringInfo(str, "%d", nargs); \ for (i = 0; i < nargs; i++) \ { \ appendStringInfoChar(str, ' '); \ - _outToken(str, NSP_NAME(get_typ_namespace(argtypes[i]))); \ + outToken(str, NSP_NAME(get_typ_namespace(argtypes[i]))); \ appendStringInfoChar(str, ' '); \ - _outToken(str, get_typ_name(argtypes[i])); \ + outToken(str, get_typ_name(argtypes[i])); \ } \ } \ else \ @@ -216,20 +216,20 @@ set_portable_output(bool value) if (OidIsValid(node->fldname)) \ { \ Oid oprleft, oprright; \ - _outToken(str, NSP_NAME(get_opnamespace(node->fldname))); \ + outToken(str, NSP_NAME(get_opnamespace(node->fldname))); \ appendStringInfoChar(str, ' '); \ - _outToken(str, get_opname(node->fldname)); \ + outToken(str, get_opname(node->fldname)); \ appendStringInfoChar(str, ' '); \ op_input_types(node->fldname, &oprleft, &oprright); \ - _outToken(str, OidIsValid(oprleft) ? \ + outToken(str, OidIsValid(oprleft) ? \ NSP_NAME(get_typ_namespace(oprleft)) : NULL); \ appendStringInfoChar(str, ' '); \ - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); \ + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); \ appendStringInfoChar(str, ' '); \ - _outToken(str, OidIsValid(oprright) ? \ + outToken(str, OidIsValid(oprright) ? \ NSP_NAME(get_typ_namespace(oprright)) : NULL); \ appendStringInfoChar(str, ' '); \ - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); \ + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); \ appendStringInfoChar(str, ' '); \ } \ else \ @@ -242,9 +242,9 @@ set_portable_output(bool value) appendStringInfo(str, " :" CppAsString(fldname) " "); \ if (OidIsValid(node->fldname)) \ { \ - _outToken(str, NSP_NAME(get_collation_namespace(node->fldname))); \ + outToken(str, NSP_NAME(get_collation_namespace(node->fldname))); \ appendStringInfoChar(str, ' '); \ - _outToken(str, get_collation_name(node->fldname)); \ + outToken(str, get_collation_name(node->fldname)); \ appendStringInfo(str, " %d", get_collation_encoding(node->fldname)); \ } \ else \ @@ -258,14 +258,14 @@ set_portable_output(bool value) /* - * _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') { @@ -296,13 +296,6 @@ _outToken(StringInfo str, const char *s) } } -/* 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) { @@ -341,13 +334,13 @@ _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; @@ -359,13 +352,6 @@ _outBitmapset(StringInfo str, const Bitmapset *bms) 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. */ @@ -437,7 +423,7 @@ _printDatum(StringInfo str, Datum value, Oid typid) DateStyle = USE_ISO_DATES; textvalue = DatumGetCString(FunctionCall1(&finfo, tmpval)); - _outToken(str, textvalue); + outToken(str, textvalue); DateStyle = saveDateStyle; } @@ -464,13 +450,17 @@ _outPlannedStmt(StringInfo str, const PlannedStmt *node) WRITE_NODE_FIELD(planTree); WRITE_NODE_FIELD(rtable); WRITE_NODE_FIELD(resultRelations); - WRITE_NODE_FIELD(utilityStmt); + WRITE_NODE_FIELD(nonleafResultRelations); + WRITE_NODE_FIELD(rootResultRelations); 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_NODE_FIELD(utilityStmt); + WRITE_LOCATION_FIELD(stmt_location); + WRITE_LOCATION_FIELD(stmt_len); } /* @@ -484,6 +474,7 @@ _outPlanInfo(StringInfo str, const Plan *node) WRITE_FLOAT_FIELD(plan_rows, "%.0f"); WRITE_INT_FIELD(plan_width); WRITE_BOOL_FIELD(parallel_aware); + WRITE_BOOL_FIELD(parallel_safe); WRITE_INT_FIELD(plan_node_id); WRITE_NODE_FIELD(targetlist); WRITE_NODE_FIELD(qual); @@ -514,6 +505,7 @@ _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); } @@ -537,6 +529,14 @@ _outResult(StringInfo str, const Result *node) } 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"); @@ -546,8 +546,10 @@ _outModifyTable(StringInfo str, const ModifyTable *node) WRITE_ENUM_FIELD(operation, CmdType); WRITE_BOOL_FIELD(canSetTag); WRITE_UINT_FIELD(nominalRelation); + WRITE_NODE_FIELD(partitioned_rels); WRITE_NODE_FIELD(resultRelations); WRITE_INT_FIELD(resultRelIndex); + WRITE_INT_FIELD(rootResultRelIndex); WRITE_NODE_FIELD(plans); WRITE_NODE_FIELD(withCheckOptionLists); WRITE_NODE_FIELD(returningLists); @@ -579,6 +581,7 @@ _outAppend(StringInfo str, const Append *node) _outPlanInfo(str, (const Plan *) node); + WRITE_NODE_FIELD(partitioned_rels); WRITE_NODE_FIELD(appendplans); } @@ -591,6 +594,7 @@ _outMergeAppend(StringInfo str, const MergeAppend *node) _outPlanInfo(str, (const Plan *) node); + WRITE_NODE_FIELD(partitioned_rels); WRITE_NODE_FIELD(mergeplans); WRITE_INT_FIELD(numCols); @@ -609,20 +613,20 @@ _outMergeAppend(StringInfo str, const MergeAppend *node) /* Sort operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); } else #endif @@ -637,9 +641,9 @@ _outMergeAppend(StringInfo str, const MergeAppend *node) if (OidIsValid(coll)) { appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_collation_namespace(coll))); + outToken(str, NSP_NAME(get_collation_namespace(coll))); appendStringInfoChar(str, ' '); - _outToken(str, get_collation_name(coll)); + outToken(str, get_collation_name(coll)); appendStringInfo(str, " %d", get_collation_encoding(coll)); } else @@ -680,20 +684,20 @@ _outRecursiveUnion(StringInfo str, const RecursiveUnion *node) /* Unique operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); appendStringInfoChar(str, ' '); } else @@ -720,6 +724,7 @@ _outBitmapOr(StringInfo str, const BitmapOr *node) _outPlanInfo(str, (const Plan *) node); + WRITE_BOOL_FIELD(isshared); WRITE_NODE_FIELD(bitmapplans); } @@ -736,6 +741,35 @@ _outGather(StringInfo str, const Gather *node) } static void +_outGatherMerge(StringInfo str, const GatherMerge *node) +{ + int i; + + WRITE_NODE_TYPE("GATHERMERGE"); + + _outPlanInfo(str, (const Plan *) node); + + WRITE_INT_FIELD(num_workers); + WRITE_INT_FIELD(numCols); + + appendStringInfoString(str, " :sortColIdx"); + for (i = 0; i < node->numCols; i++) + appendStringInfo(str, " %d", node->sortColIdx[i]); + + appendStringInfoString(str, " :sortOperators"); + for (i = 0; i < node->numCols; i++) + appendStringInfo(str, " %u", node->sortOperators[i]); + + appendStringInfoString(str, " :collations"); + for (i = 0; i < node->numCols; i++) + appendStringInfo(str, " %u", node->collations[i]); + + appendStringInfoString(str, " :nullsFirst"); + for (i = 0; i < node->numCols; i++) + appendStringInfo(str, " %s", booltostr(node->nullsFirst[i])); +} + +static void _outScan(StringInfo str, const Scan *node) { WRITE_NODE_TYPE("SCAN"); @@ -857,6 +891,7 @@ _outBitmapIndexScan(StringInfo str, const BitmapIndexScan *node) else #endif WRITE_OID_FIELD(indexid); + WRITE_BOOL_FIELD(isshared); WRITE_NODE_FIELD(indexqual); WRITE_NODE_FIELD(indexqualorig); } @@ -903,6 +938,16 @@ _outFunctionScan(StringInfo str, const FunctionScan *node) } 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"); @@ -924,6 +969,16 @@ _outCteScan(StringInfo str, const CteScan *node) } 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"); @@ -965,7 +1020,7 @@ _outCustomScan(StringInfo str, const CustomScan *node) 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 @@ -996,6 +1051,7 @@ _outMergeJoin(StringInfo str, const MergeJoin *node) _outJoinPlanInfo(str, (const Join *) node); + WRITE_BOOL_FIELD(skip_mark_restore); WRITE_NODE_FIELD(mergeclauses); numCols = list_length(node->mergeclauses); @@ -1013,9 +1069,9 @@ _outMergeJoin(StringInfo str, const MergeJoin *node) if (OidIsValid(coll)) { appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_collation_namespace(coll))); + outToken(str, NSP_NAME(get_collation_namespace(coll))); appendStringInfoChar(str, ' '); - _outToken(str, get_collation_name(coll)); + outToken(str, get_collation_name(coll)); appendStringInfo(str, " %d", get_collation_encoding(coll)); } else @@ -1071,20 +1127,20 @@ _outAgg(StringInfo str, const Agg *node) /* Group operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); appendStringInfoChar(str, ' '); } else @@ -1092,6 +1148,7 @@ _outAgg(StringInfo str, const Agg *node) appendStringInfo(str, " %u", node->grpOperators[i]); WRITE_LONG_FIELD(numGroups); + WRITE_BITMAPSET_FIELD(aggParams); WRITE_NODE_FIELD(groupingSets); WRITE_NODE_FIELD(chain); } @@ -1122,20 +1179,20 @@ _outWindowAgg(StringInfo str, const WindowAgg *node) /* The operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); appendStringInfoChar(str, ' '); } else @@ -1158,20 +1215,20 @@ _outWindowAgg(StringInfo str, const WindowAgg *node) /* Group operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); appendStringInfoChar(str, ' '); } else @@ -1208,20 +1265,20 @@ _outGroup(StringInfo str, const Group *node) /* Group operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); appendStringInfoChar(str, ' '); } else @@ -1262,20 +1319,20 @@ _outSort(StringInfo str, const Sort *node) /* Sort operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); } else #endif @@ -1290,9 +1347,9 @@ _outSort(StringInfo str, const Sort *node) if (OidIsValid(coll)) { appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_collation_namespace(coll))); + outToken(str, NSP_NAME(get_collation_namespace(coll))); appendStringInfoChar(str, ' '); - _outToken(str, get_collation_name(coll)); + outToken(str, get_collation_name(coll)); appendStringInfo(str, " %d", get_collation_encoding(coll)); } else @@ -1332,20 +1389,20 @@ _outUnique(StringInfo str, const Unique *node) /* Unique operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); appendStringInfoChar(str, ' '); } else @@ -1368,13 +1425,6 @@ _outHash(StringInfo str, const Hash *node) WRITE_OID_FIELD(skewTable); WRITE_INT_FIELD(skewColumn); WRITE_BOOL_FIELD(skewInherit); -#ifdef XCP - if (portable_output) - WRITE_TYPID_FIELD(skewColType); - else -#endif - WRITE_OID_FIELD(skewColType); - WRITE_INT_FIELD(skewColTypmod); } static void @@ -1404,20 +1454,20 @@ _outSetOp(StringInfo str, const SetOp *node) /* Unique operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); } else #endif @@ -1503,9 +1553,9 @@ _outRemoteStmt(StringInfo str, const RemoteStmt *node) Oid ptype = rparam->paramtype; Assert(OidIsValid(ptype)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_typ_namespace(ptype))); + outToken(str, NSP_NAME(get_typ_namespace(ptype))); appendStringInfoChar(str, ' '); - _outToken(str, get_typ_name(ptype)); + outToken(str, get_typ_name(ptype)); } else appendStringInfo(str, " %u", rparam->paramtype); @@ -1539,20 +1589,20 @@ _outSimpleSort(StringInfo str, const SimpleSort *node) /* Sort operator is always valid */ Assert(OidIsValid(oper)); appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_opnamespace(oper))); + outToken(str, NSP_NAME(get_opnamespace(oper))); appendStringInfoChar(str, ' '); - _outToken(str, get_opname(oper)); + outToken(str, get_opname(oper)); appendStringInfoChar(str, ' '); op_input_types(oper, &oprleft, &oprright); - _outToken(str, OidIsValid(oprleft) ? + outToken(str, OidIsValid(oprleft) ? NSP_NAME(get_typ_namespace(oprleft)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); + outToken(str, OidIsValid(oprleft) ? get_typ_name(oprleft) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? + outToken(str, OidIsValid(oprright) ? NSP_NAME(get_typ_namespace(oprright)) : NULL); appendStringInfoChar(str, ' '); - _outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); + outToken(str, OidIsValid(oprright) ? get_typ_name(oprright) : NULL); } else appendStringInfo(str, " %u", node->sortOperators[i]); @@ -1565,9 +1615,9 @@ _outSimpleSort(StringInfo str, const SimpleSort *node) if (OidIsValid(coll)) { appendStringInfoChar(str, ' '); - _outToken(str, NSP_NAME(get_collation_namespace(coll))); + outToken(str, NSP_NAME(get_collation_namespace(coll))); appendStringInfoChar(str, ' '); - _outToken(str, get_collation_name(coll)); + outToken(str, get_collation_name(coll)); appendStringInfo(str, " %d", get_collation_encoding(coll)); } else @@ -1641,13 +1691,33 @@ _outRangeVar(StringInfo str, const RangeVar *node) */ 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); } static void +_outTableFunc(StringInfo str, const TableFunc *node) +{ + WRITE_NODE_TYPE("TABLEFUNC"); + + WRITE_NODE_FIELD(ns_names); + WRITE_NODE_FIELD(ns_uris); + 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"); @@ -2089,7 +2159,7 @@ _outBoolExpr(StringInfo str, const BoolExpr *node) break; } appendStringInfoString(str, " :boolop "); - _outToken(str, opstr); + outToken(str, opstr); WRITE_NODE_FIELD(args); WRITE_LOCATION_FIELD(location); @@ -2133,6 +2203,7 @@ _outSubPlan(StringInfo str, const SubPlan *node) 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); @@ -2448,6 +2519,17 @@ _outMinMaxExpr(StringInfo str, const MinMaxExpr *node) } 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"); @@ -2661,14 +2743,14 @@ _outPathInfo(StringInfo str, const Path *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); @@ -2687,6 +2769,7 @@ _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); @@ -2793,7 +2876,7 @@ _outCustomPath(StringInfo str, const CustomPath *node) 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 @@ -2803,6 +2886,7 @@ _outAppendPath(StringInfo str, const AppendPath *node) _outPathInfo(str, (const Path *) node); + WRITE_NODE_FIELD(partitioned_rels); WRITE_NODE_FIELD(subpaths); } @@ -2813,6 +2897,7 @@ _outMergeAppendPath(StringInfo str, const MergeAppendPath *node) _outPathInfo(str, (const Path *) node); + WRITE_NODE_FIELD(partitioned_rels); WRITE_NODE_FIELD(subpaths); WRITE_FLOAT_FIELD(limit_tuples, "%.0f"); } @@ -2859,6 +2944,7 @@ _outGatherPath(StringInfo str, const GatherPath *node) WRITE_NODE_FIELD(subpath); WRITE_BOOL_FIELD(single_copy); + WRITE_INT_FIELD(num_workers); } static void @@ -2873,6 +2959,16 @@ _outProjectionPath(StringInfo str, const ProjectionPath *node) } static void +_outProjectSetPath(StringInfo str, const ProjectSetPath *node) +{ + WRITE_NODE_TYPE("PROJECTSETPATH"); + + _outPathInfo(str, (const Path *) node); + + WRITE_NODE_FIELD(subpath); +} + +static void _outSortPath(StringInfo str, const SortPath *node) { WRITE_NODE_TYPE("SORTPATH"); @@ -2921,6 +3017,28 @@ _outAggPath(StringInfo str, const AggPath *node) } 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"); @@ -2928,8 +3046,8 @@ _outGroupingSetsPath(StringInfo str, const GroupingSetsPath *node) _outPathInfo(str, (const Path *) node); WRITE_NODE_FIELD(subpath); - WRITE_NODE_FIELD(rollup_groupclauses); - WRITE_NODE_FIELD(rollup_lists); + WRITE_ENUM_FIELD(aggstrategy, AggStrategy); + WRITE_NODE_FIELD(rollups); WRITE_NODE_FIELD(qual); } @@ -3008,6 +3126,7 @@ _outModifyTablePath(StringInfo str, const ModifyTablePath *node) WRITE_ENUM_FIELD(operation, CmdType); WRITE_BOOL_FIELD(canSetTag); WRITE_UINT_FIELD(nominalRelation); + WRITE_NODE_FIELD(partitioned_rels); WRITE_NODE_FIELD(resultRelations); WRITE_NODE_FIELD(subpaths); WRITE_NODE_FIELD(subroots); @@ -3031,6 +3150,17 @@ _outLimitPath(StringInfo str, const LimitPath *node) } 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"); @@ -3048,6 +3178,7 @@ _outMergePath(StringInfo str, const MergePath *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); } @@ -3073,6 +3204,8 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node) WRITE_NODE_FIELD(finalrtable); WRITE_NODE_FIELD(finalrowmarks); WRITE_NODE_FIELD(resultRelations); + WRITE_NODE_FIELD(nonleafResultRelations); + WRITE_NODE_FIELD(rootResultRelations); WRITE_NODE_FIELD(relationOids); WRITE_NODE_FIELD(invalItems); WRITE_INT_FIELD(nParamExec); @@ -3083,6 +3216,7 @@ _outPlannerGlobal(StringInfo str, const PlannerGlobal *node) WRITE_BOOL_FIELD(dependsOnRole); WRITE_BOOL_FIELD(parallelModeOK); WRITE_BOOL_FIELD(parallelModeNeeded); + WRITE_CHAR_FIELD(maxParallelHazard); } static void @@ -3110,6 +3244,7 @@ _outPlannerInfo(StringInfo str, const PlannerInfo *node) WRITE_NODE_FIELD(full_join_clauses); WRITE_NODE_FIELD(join_info_list); WRITE_NODE_FIELD(append_rel_list); + WRITE_NODE_FIELD(pcinfo_list); WRITE_NODE_FIELD(rowMarks); WRITE_NODE_FIELD(placeholder_list); WRITE_NODE_FIELD(fkey_list); @@ -3123,6 +3258,7 @@ _outPlannerInfo(StringInfo str, const PlannerInfo *node) 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(hasInheritedTarget); WRITE_BOOL_FIELD(hasJoinRTEs); WRITE_BOOL_FIELD(hasLateralRTEs); @@ -3165,6 +3301,7 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node) 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"); @@ -3175,9 +3312,12 @@ _outRelOptInfo(StringInfo str, const RelOptInfo *node) 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_BITMAPSET_FIELD(top_parent_relids); } static void @@ -3237,6 +3377,18 @@ _outForeignKeyOptInfo(StringInfo str, const ForeignKeyOptInfo *node) } 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) { /* @@ -3264,6 +3416,8 @@ _outEquivalenceClass(StringInfo str, const EquivalenceClass *node) 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 @@ -3330,6 +3484,8 @@ _outRestrictInfo(StringInfo str, const RestrictInfo *node) WRITE_BOOL_FIELD(outerjoin_delayed); WRITE_BOOL_FIELD(can_join); WRITE_BOOL_FIELD(pseudoconstant); + WRITE_BOOL_FIELD(leakproof); + WRITE_UINT_FIELD(security_level); WRITE_BITMAPSET_FIELD(clause_relids); WRITE_BITMAPSET_FIELD(required_relids); WRITE_BITMAPSET_FIELD(outer_relids); @@ -3397,6 +3553,15 @@ _outAppendRelInfo(StringInfo str, const AppendRelInfo *node) } static void +_outPartitionedChildRelInfo(StringInfo str, const PartitionedChildRelInfo *node) +{ + WRITE_NODE_TYPE("PARTITIONEDCHILDRELINFO"); + + WRITE_UINT_FIELD(parent_relid); + WRITE_NODE_FIELD(child_rels); +} + +static void _outPlaceHolderInfo(StringInfo str, const PlaceHolderInfo *node) { WRITE_NODE_TYPE("PLACEHOLDERINFO"); @@ -3468,6 +3633,8 @@ _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); @@ -3535,6 +3702,18 @@ _outIndexStmt(StringInfo str, const IndexStmt *node) } 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_BOOL_FIELD(if_not_exists); +} + +static void _outNotifyStmt(StringInfo str, const NotifyStmt *node) { WRITE_NODE_TYPE("NOTIFY"); @@ -3604,6 +3783,7 @@ _outDefElem(StringInfo str, const DefElem *node) WRITE_STRING_FIELD(defname); WRITE_NODE_FIELD(arg); WRITE_ENUM_FIELD(defaction, DefElemAction); + WRITE_LOCATION_FIELD(location); } static void @@ -3637,6 +3817,16 @@ _outXmlSerialize(StringInfo str, const XmlSerialize *node) } 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"); @@ -3647,9 +3837,11 @@ _outColumnDef(StringInfo str, const ColumnDef *node) WRITE_BOOL_FIELD(is_local); WRITE_BOOL_FIELD(is_not_null); WRITE_BOOL_FIELD(is_from_type); + WRITE_BOOL_FIELD(is_from_parent); WRITE_CHAR_FIELD(storage); WRITE_NODE_FIELD(raw_default); WRITE_NODE_FIELD(cooked_default); + WRITE_CHAR_FIELD(identity); WRITE_NODE_FIELD(collClause); WRITE_OID_FIELD(collOid); WRITE_NODE_FIELD(constraints); @@ -3744,6 +3936,7 @@ _outQuery(StringInfo str, const Query *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); @@ -3754,6 +3947,7 @@ _outQuery(StringInfo str, const Query *node) 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); @@ -3767,6 +3961,9 @@ _outQuery(StringInfo str, const Query *node) 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 @@ -3916,17 +4113,29 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node) 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(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; + case RTE_NAMEDTUPLESTORE: + WRITE_STRING_FIELD(enrname); + WRITE_OID_FIELD(relid); + WRITE_NODE_FIELD(coltypes); + WRITE_NODE_FIELD(coltypmods); + WRITE_NODE_FIELD(colcollations); break; #ifdef PGXC case RTE_REMOTE_DUMMY: @@ -4091,12 +4300,12 @@ _outValue(StringInfo str, const Value *value) 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: @@ -4259,6 +4468,34 @@ _outRangeTableSample(StringInfo str, const RangeTableSample *node) } 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"); @@ -4285,6 +4522,13 @@ _outConstraint(StringInfo str, const Constraint *node) 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_CHECK: appendStringInfoString(str, "CHECK"); WRITE_BOOL_FIELD(is_no_inherit); @@ -4378,6 +4622,49 @@ _outForeignKeyCacheInfo(StringInfo str, const ForeignKeyCacheInfo *node) appendStringInfo(str, " %u", node->conpfeqop[i]); } +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("PARTITIONBY"); + + WRITE_STRING_FIELD(strategy); + WRITE_NODE_FIELD(partParams); + 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); + /* XXX somebody forgot location field; too late to change for v10 */ +} + +static void +_outPartitionRangeDatum(StringInfo str, const PartitionRangeDatum *node) +{ + WRITE_NODE_TYPE("PARTRANGEDATUM"); + + WRITE_BOOL_FIELD(infinite); + WRITE_NODE_FIELD(value); + /* XXX somebody forgot location field; too late to change for v10 */ +} /* * outNode - @@ -4412,6 +4699,9 @@ outNode(StringInfo str, const void *obj) case T_Result: _outResult(str, obj); break; + case T_ProjectSet: + _outProjectSet(str, obj); + break; case T_ModifyTable: _outModifyTable(str, obj); break; @@ -4433,6 +4723,9 @@ outNode(StringInfo str, const void *obj) case T_Gather: _outGather(str, obj); break; + case T_GatherMerge: + _outGatherMerge(str, obj); + break; case T_Scan: _outScan(str, obj); break; @@ -4468,12 +4761,18 @@ outNode(StringInfo str, const void *obj) 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; @@ -4551,6 +4850,9 @@ outNode(StringInfo str, const void *obj) case T_RangeVar: _outRangeVar(str, obj); break; + case T_TableFunc: + _outTableFunc(str, obj); + break; case T_IntoClause: _outIntoClause(str, obj); break; @@ -4650,6 +4952,9 @@ outNode(StringInfo str, const void *obj) case T_MinMaxExpr: _outMinMaxExpr(str, obj); break; + case T_SQLValueFunction: + _outSQLValueFunction(str, obj); + break; case T_XmlExpr: _outXmlExpr(str, obj); break; @@ -4737,6 +5042,9 @@ outNode(StringInfo str, const void *obj) case T_ProjectionPath: _outProjectionPath(str, obj); break; + case T_ProjectSetPath: + _outProjectSetPath(str, obj); + break; case T_SortPath: _outSortPath(str, obj); break; @@ -4773,6 +5081,9 @@ outNode(StringInfo str, const void *obj) case T_LimitPath: _outLimitPath(str, obj); break; + case T_GatherMergePath: + _outGatherMergePath(str, obj); + break; case T_NestPath: _outNestPath(str, obj); break; @@ -4824,6 +5135,9 @@ outNode(StringInfo str, const void *obj) case T_AppendRelInfo: _outAppendRelInfo(str, obj); break; + case T_PartitionedChildRelInfo: + _outPartitionedChildRelInfo(str, obj); + break; case T_PlaceHolderInfo: _outPlaceHolderInfo(str, obj); break; @@ -4833,11 +5147,18 @@ outNode(StringInfo str, const void *obj) 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; @@ -4850,6 +5171,9 @@ outNode(StringInfo str, const void *obj) case T_IndexStmt: _outIndexStmt(str, obj); break; + case T_CreateStatsStmt: + _outCreateStatsStmt(str, obj); + break; case T_NotifyStmt: _outNotifyStmt(str, obj); break; @@ -4955,6 +5279,12 @@ outNode(StringInfo str, const void *obj) 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; @@ -4981,6 +5311,21 @@ outNode(StringInfo str, const void *obj) _outExecNodes(str, obj); break; #endif + 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: @@ -5010,3 +5355,18 @@ nodeToString(const void *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; +} diff --git a/src/backend/nodes/params.c b/src/backend/nodes/params.c index f2e26b80c4..0fb08b94db 100644 --- a/src/backend/nodes/params.c +++ b/src/backend/nodes/params.c @@ -4,7 +4,7 @@ * Support for finding the values associated with Param 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 * * IDENTIFICATION diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index a5b4d24262..0cf7f40c8c 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -3,7 +3,7 @@ * print.c * various print routines (used mostly for debugging) * - * 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 * * @@ -282,6 +282,10 @@ print_rt(const List *rtable) printf("%d\t%s\t[rangefunction]", i, rte->eref->aliasname); break; + case RTE_TABLEFUNC: + printf("%d\t%s\t[table function]", + i, rte->eref->aliasname); + break; case RTE_VALUES: printf("%d\t%s\t[values list]", i, rte->eref->aliasname); @@ -290,6 +294,10 @@ print_rt(const List *rtable) printf("%d\t%s\t[cte]", i, rte->eref->aliasname); break; + case RTE_NAMEDTUPLESTORE: + printf("%d\t%s\t[tuplestore]", + i, rte->eref->aliasname); + break; default: printf("%d\t%s\t[unknown rtekind]", i, rte->eref->aliasname); diff --git a/src/backend/nodes/read.c b/src/backend/nodes/read.c index c1ab494d77..b56f28e15f 100644 --- a/src/backend/nodes/read.c +++ b/src/backend/nodes/read.c @@ -4,7 +4,7 @@ * routines to convert a string (legal ascii representation of node) back * to 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 * * diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 933825cd74..23091c2bcc 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -4,7 +4,7 @@ * Reader functions for Postgres tree nodes. * * Portions Copyright (c) 2012-2014, TransLattice, Inc. - * 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 * Portions Copyright (c) 2010-2012 Postgres-XC Development Group * @@ -451,8 +451,6 @@ set_portable_input(bool value) */ #define atoui(x) ((unsigned int) strtoul((x), NULL, 10)) -#define atooid(x) ((Oid) strtoul((x), NULL, 10)) - #define strtobool(x) ((*(x) == 't') ? true : false) #define nullable_string(token,length) \ @@ -528,6 +526,7 @@ _readQuery(void) READ_INT_FIELD(resultRelation); READ_BOOL_FIELD(hasAggs); READ_BOOL_FIELD(hasWindowFuncs); + READ_BOOL_FIELD(hasTargetSRFs); READ_BOOL_FIELD(hasSubLinks); READ_BOOL_FIELD(hasDistinctOn); READ_BOOL_FIELD(hasRecursive); @@ -538,6 +537,7 @@ _readQuery(void) READ_NODE_FIELD(rtable); READ_NODE_FIELD(jointree); READ_NODE_FIELD(targetList); + READ_ENUM_FIELD(override, OverridingKind); READ_NODE_FIELD(onConflict); READ_NODE_FIELD(returningList); READ_NODE_FIELD(groupClause); @@ -551,6 +551,9 @@ _readQuery(void) READ_NODE_FIELD(rowMarks); READ_NODE_FIELD(setOperations); READ_NODE_FIELD(constraintDeps); + /* withCheckOptions intentionally omitted, see comment in parsenodes.h */ + READ_LOCATION_FIELD(stmt_location); + READ_LOCATION_FIELD(stmt_len); READ_DONE(); } @@ -748,7 +751,7 @@ _readRangeVar(void) READ_STRING_FIELD(schemaname); READ_STRING_FIELD(relname); - READ_ENUM_FIELD(inhOpt, InhOption); + READ_BOOL_FIELD(inh); READ_CHAR_FIELD(relpersistence); READ_NODE_FIELD(alias); READ_LOCATION_FIELD(location); @@ -756,6 +759,31 @@ _readRangeVar(void) READ_DONE(); } +/* + * _readTableFunc + */ +static TableFunc * +_readTableFunc(void) +{ + READ_LOCALS(TableFunc); + + READ_NODE_FIELD(ns_names); + READ_NODE_FIELD(ns_uris); + READ_NODE_FIELD(docexpr); + READ_NODE_FIELD(rowexpr); + READ_NODE_FIELD(colnames); + READ_NODE_FIELD(coltypes); + READ_NODE_FIELD(coltypmods); + READ_NODE_FIELD(colcollations); + READ_NODE_FIELD(colexprs); + READ_NODE_FIELD(coldefexprs); + READ_BITMAPSET_FIELD(notnulls); + READ_INT_FIELD(ordinalitycol); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + static IntoClause * _readIntoClause(void) { @@ -1679,6 +1707,22 @@ _readMinMaxExpr(void) } /* + * _readSQLValueFunction + */ +static SQLValueFunction * +_readSQLValueFunction(void) +{ + READ_LOCALS(SQLValueFunction); + + READ_ENUM_FIELD(op, SQLValueFunctionOp); + READ_OID_FIELD(type); + READ_INT_FIELD(typmod); + READ_LOCATION_FIELD(location); + + READ_DONE(); +} + +/* * _readXmlExpr */ static XmlExpr * @@ -1983,17 +2027,29 @@ _readRangeTblEntry(void) READ_NODE_FIELD(functions); READ_BOOL_FIELD(funcordinality); break; + case RTE_TABLEFUNC: + READ_NODE_FIELD(tablefunc); + break; case RTE_VALUES: READ_NODE_FIELD(values_lists); - READ_NODE_FIELD(values_collations); + READ_NODE_FIELD(coltypes); + READ_NODE_FIELD(coltypmods); + READ_NODE_FIELD(colcollations); break; case RTE_CTE: READ_STRING_FIELD(ctename); READ_UINT_FIELD(ctelevelsup); READ_BOOL_FIELD(self_reference); - READ_NODE_FIELD(ctecoltypes); - READ_NODE_FIELD(ctecoltypmods); - READ_NODE_FIELD(ctecolcollations); + READ_NODE_FIELD(coltypes); + READ_NODE_FIELD(coltypmods); + READ_NODE_FIELD(colcollations); + break; + case RTE_NAMEDTUPLESTORE: + READ_STRING_FIELD(enrname); + READ_OID_FIELD(relid); + READ_NODE_FIELD(coltypes); + READ_NODE_FIELD(coltypmods); + READ_NODE_FIELD(colcollations); break; #ifdef PGXC case RTE_REMOTE_DUMMY: @@ -2105,6 +2161,7 @@ _readDefElem(void) READ_STRING_FIELD(defname); READ_NODE_FIELD(arg); READ_ENUM_FIELD(defaction, DefElemAction); + READ_LOCATION_FIELD(location); READ_DONE(); } @@ -2141,13 +2198,17 @@ _readPlannedStmt(void) READ_NODE_FIELD(planTree); READ_NODE_FIELD(rtable); READ_NODE_FIELD(resultRelations); - READ_NODE_FIELD(utilityStmt); + READ_NODE_FIELD(nonleafResultRelations); + READ_NODE_FIELD(rootResultRelations); READ_NODE_FIELD(subplans); READ_BITMAPSET_FIELD(rewindPlanIDs); READ_NODE_FIELD(rowMarks); READ_NODE_FIELD(relationOids); READ_NODE_FIELD(invalItems); READ_INT_FIELD(nParamExec); + READ_NODE_FIELD(utilityStmt); + READ_LOCATION_FIELD(stmt_location); + READ_LOCATION_FIELD(stmt_len); READ_DONE(); } @@ -2168,6 +2229,19 @@ _readResult(void) } /* + * _readProjectSet + */ +static ProjectSet * +_readProjectSet(void) +{ + READ_LOCALS_NO_FIELDS(ProjectSet); + + ReadCommonPlan(&local_node->plan); + + READ_DONE(); +} + +/* * _readModifyTable */ static ModifyTable * @@ -2180,8 +2254,10 @@ _readModifyTable(void) READ_ENUM_FIELD(operation, CmdType); READ_BOOL_FIELD(canSetTag); READ_UINT_FIELD(nominalRelation); + READ_NODE_FIELD(partitioned_rels); READ_NODE_FIELD(resultRelations); READ_INT_FIELD(resultRelIndex); + READ_INT_FIELD(rootResultRelIndex); READ_NODE_FIELD(plans); READ_NODE_FIELD(withCheckOptionLists); READ_NODE_FIELD(returningLists); @@ -2212,6 +2288,7 @@ _readAppend(void) ReadCommonPlan(&local_node->plan); + READ_NODE_FIELD(partitioned_rels); READ_NODE_FIELD(appendplans); READ_DONE(); @@ -2228,6 +2305,7 @@ _readMergeAppend(void) ReadCommonPlan(&local_node->plan); + READ_NODE_FIELD(partitioned_rels); READ_NODE_FIELD(mergeplans); READ_INT_FIELD(numCols); READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols); @@ -2354,6 +2432,7 @@ _readBitmapOr(void) ReadCommonPlan(&local_node->plan); + READ_BOOL_FIELD(isshared); READ_NODE_FIELD(bitmapplans); READ_DONE(); @@ -2474,6 +2553,7 @@ _readBitmapIndexScan(void) READ_RELID_FIELD(indexid); else READ_OID_FIELD(indexid); + READ_BOOL_FIELD(isshared); READ_NODE_FIELD(indexqual); READ_NODE_FIELD(indexqualorig); @@ -2557,6 +2637,21 @@ _readValuesScan(void) } /* + * _readTableFuncScan + */ +static TableFuncScan * +_readTableFuncScan(void) +{ + READ_LOCALS(TableFuncScan); + + ReadCommonScan(&local_node->scan); + + READ_NODE_FIELD(tablefunc); + + READ_DONE(); +} + +/* * _readCteScan */ static CteScan * @@ -2650,6 +2745,7 @@ ReadCommonJoin(Join *local_node) ReadCommonPlan(&local_node->plan); READ_ENUM_FIELD(jointype, JoinType); + READ_BOOL_FIELD(inner_unique); READ_NODE_FIELD(joinqual); } @@ -2694,6 +2790,7 @@ _readMergeJoin(void) ReadCommonJoin(&local_node->join); + READ_BOOL_FIELD(skip_mark_restore); READ_NODE_FIELD(mergeclauses); numCols = list_length(local_node->mergeclauses); @@ -3001,6 +3098,7 @@ _readAgg(void) #endif READ_LONG_FIELD(numGroups); + READ_BITMAPSET_FIELD(aggParams); READ_NODE_FIELD(groupingSets); READ_NODE_FIELD(chain); @@ -3218,6 +3316,26 @@ _readGather(void) } /* + * _readGatherMerge + */ +static GatherMerge * +_readGatherMerge(void) +{ + READ_LOCALS(GatherMerge); + + ReadCommonPlan(&local_node->plan); + + READ_INT_FIELD(num_workers); + READ_INT_FIELD(numCols); + READ_ATTRNUMBER_ARRAY(sortColIdx, local_node->numCols); + READ_OID_ARRAY(sortOperators, local_node->numCols); + READ_OID_ARRAY(collations, local_node->numCols); + READ_BOOL_ARRAY(nullsFirst, local_node->numCols); + + READ_DONE(); +} + +/* * _readHash */ static Hash * @@ -3233,11 +3351,6 @@ _readHash(void) READ_OID_FIELD(skewTable); READ_INT_FIELD(skewColumn); READ_BOOL_FIELD(skewInherit); - if (portable_input) - READ_TYPID_FIELD(skewColType); - else - READ_OID_FIELD(skewColType); - READ_INT_FIELD(skewColTypmod); READ_DONE(); } @@ -3434,6 +3547,7 @@ _readSubPlan(void) READ_OID_FIELD(firstColCollation); READ_BOOL_FIELD(useHashTable); READ_BOOL_FIELD(unknownEqFalse); + READ_BOOL_FIELD(parallel_safe); READ_NODE_FIELD(setParam); READ_NODE_FIELD(parParam); READ_NODE_FIELD(args); @@ -3685,6 +3799,40 @@ _readSimpleSort(void) /* + * _readPartitionBoundSpec + */ +static PartitionBoundSpec * +_readPartitionBoundSpec(void) +{ + READ_LOCALS(PartitionBoundSpec); + + READ_CHAR_FIELD(strategy); + READ_NODE_FIELD(listdatums); + READ_NODE_FIELD(lowerdatums); + READ_NODE_FIELD(upperdatums); + /* XXX somebody forgot location field; too late to change for v10 */ + local_node->location = -1; + + READ_DONE(); +} + +/* + * _readPartitionRangeDatum + */ +static PartitionRangeDatum * +_readPartitionRangeDatum(void) +{ + READ_LOCALS(PartitionRangeDatum); + + READ_BOOL_FIELD(infinite); + READ_NODE_FIELD(value); + /* XXX somebody forgot location field; too late to change for v10 */ + local_node->location = -1; + + READ_DONE(); +} + +/* * parseNodeString * * Given a character string representing a node tree, parseNodeString creates @@ -3726,6 +3874,8 @@ parseNodeString(void) return_value = _readRangeVar(); else if (MATCH("INTOCLAUSE", 10)) return_value = _readIntoClause(); + else if (MATCH("TABLEFUNC", 9)) + return_value = _readTableFunc(); else if (MATCH("VAR", 3)) return_value = _readVar(); else if (MATCH("CONST", 5)) @@ -3786,6 +3936,8 @@ parseNodeString(void) return_value = _readCoalesceExpr(); else if (MATCH("MINMAX", 6)) return_value = _readMinMaxExpr(); + else if (MATCH("SQLVALUEFUNCTION", 16)) + return_value = _readSQLValueFunction(); else if (MATCH("XMLEXPR", 7)) return_value = _readXmlExpr(); else if (MATCH("NULLTEST", 8)) @@ -3830,6 +3982,8 @@ parseNodeString(void) return_value = _readPlan(); else if (MATCH("RESULT", 6)) return_value = _readResult(); + else if (MATCH("PROJECTSET", 10)) + return_value = _readProjectSet(); else if (MATCH("MODIFYTABLE", 11)) return_value = _readModifyTable(); else if (MATCH("APPEND", 6)) @@ -3864,6 +4018,8 @@ parseNodeString(void) return_value = _readFunctionScan(); else if (MATCH("VALUESSCAN", 10)) return_value = _readValuesScan(); + else if (MATCH("TABLEFUNCSCAN", 13)) + return_value = _readTableFuncScan(); else if (MATCH("CTESCAN", 7)) return_value = _readCteScan(); else if (MATCH("WORKTABLESCAN", 13)) @@ -3894,6 +4050,8 @@ parseNodeString(void) return_value = _readUnique(); else if (MATCH("GATHER", 6)) return_value = _readGather(); + else if (MATCH("GATHERMERGE", 11)) + return_value = _readGatherMerge(); else if (MATCH("HASH", 4)) return_value = _readHash(); else if (MATCH("SETOP", 5)) @@ -3920,6 +4078,10 @@ parseNodeString(void) return_value = _readRemoteStmt(); else if (MATCH("SIMPLESORT", 10)) return_value = _readSimpleSort(); + else if (MATCH("PARTITIONBOUND", 14)) + return_value = _readPartitionBoundSpec(); + else if (MATCH("PARTRANGEDATUM", 14)) + return_value = _readPartitionRangeDatum(); else { elog(ERROR, "badly formatted node string \"%.32s\"...", token); diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c index dfeb7d5c63..bbd39a2ed9 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -29,7 +29,7 @@ * and a non-lossy page. * * - * Copyright (c) 2003-2016, PostgreSQL Global Development Group + * Copyright (c) 2003-2017, PostgreSQL Global Development Group * * IDENTIFICATION * src/backend/nodes/tidbitmap.c @@ -43,7 +43,8 @@ #include "access/htup_details.h" #include "nodes/bitmapset.h" #include "nodes/tidbitmap.h" -#include "utils/hsearch.h" +#include "storage/lwlock.h" +#include "utils/dsa.h" /* * The maximum number of tuples per page is not large (typically 256 with @@ -61,12 +62,12 @@ * for that page in the page table. * * We actually store both exact pages and lossy chunks in the same hash - * table, using identical data structures. (This is because dynahash.c's - * memory management doesn't allow space to be transferred easily from one - * hashtable to another.) Therefore it's best if PAGES_PER_CHUNK is the - * same as MAX_TUPLES_PER_PAGE, or at least not too different. But we - * also want PAGES_PER_CHUNK to be a power of 2 to avoid expensive integer - * remainder operations. So, define it like this: + * table, using identical data structures. (This is because the memory + * management for hashtables doesn't easily/efficiently allow space to be + * transferred easily from one hashtable to another.) Therefore it's best + * if PAGES_PER_CHUNK is the same as MAX_TUPLES_PER_PAGE, or at least not + * too different. But we also want PAGES_PER_CHUNK to be a power of 2 to + * avoid expensive integer remainder operations. So, define it like this: */ #define PAGES_PER_CHUNK (BLCKSZ / 32) @@ -97,21 +98,31 @@ typedef struct PagetableEntry { BlockNumber blockno; /* page number (hashtable key) */ + char status; /* hash entry status */ bool ischunk; /* T = lossy storage, F = exact */ bool recheck; /* should the tuples be rechecked? */ bitmapword words[Max(WORDS_PER_PAGE, WORDS_PER_CHUNK)]; } PagetableEntry; /* - * dynahash.c is optimized for relatively large, long-lived hash tables. - * This is not ideal for TIDBitMap, particularly when we are using a bitmap - * scan on the inside of a nestloop join: a bitmap may well live only long - * enough to accumulate one entry in such cases. We therefore avoid creating - * an actual hashtable until we need two pagetable entries. When just one - * pagetable entry is needed, we store it in a fixed field of TIDBitMap. - * (NOTE: we don't get rid of the hashtable if the bitmap later shrinks down - * to zero or one page again. So, status can be TBM_HASH even when nentries - * is zero or one.) + * Holds array of pagetable entries. + */ +typedef struct PTEntryArray +{ + pg_atomic_uint32 refcount; /* no. of iterator attached */ + PagetableEntry ptentry[FLEXIBLE_ARRAY_MEMBER]; +} PTEntryArray; + +/* + * We want to avoid the overhead of creating the hashtable, which is + * comparatively large, when not necessary. Particularly when we are using a + * bitmap scan on the inside of a nestloop join: a bitmap may well live only + * long enough to accumulate one entry in such cases. We therefore avoid + * creating an actual hashtable until we need two pagetable entries. When + * just one pagetable entry is needed, we store it in a fixed field of + * TIDBitMap. (NOTE: we don't get rid of the hashtable if the bitmap later + * shrinks down to zero or one page again. So, status can be TBM_HASH even + * when nentries is zero or one.) */ typedef enum { @@ -121,6 +132,16 @@ typedef enum } TBMStatus; /* + * Current iterating state of the TBM. + */ +typedef enum +{ + TBM_NOT_ITERATING, /* not yet converted to page and chunk array */ + TBM_ITERATING_PRIVATE, /* converted to local page and chunk array */ + TBM_ITERATING_SHARED /* converted to shared page and chunk array */ +} TBMIteratingState; + +/* * Here is the representation for a whole TIDBitMap: */ struct TIDBitmap @@ -128,16 +149,22 @@ struct TIDBitmap NodeTag type; /* to make it a valid Node */ MemoryContext mcxt; /* memory context containing me */ TBMStatus status; /* see codes above */ - HTAB *pagetable; /* hash table of PagetableEntry's */ + struct pagetable_hash *pagetable; /* hash table of PagetableEntry's */ int nentries; /* number of entries in pagetable */ int maxentries; /* limit on same to meet maxbytes */ int npages; /* number of exact entries in pagetable */ int nchunks; /* number of lossy entries in pagetable */ - bool iterating; /* tbm_begin_iterate called? */ + TBMIteratingState iterating; /* tbm_begin_iterate called? */ + uint32 lossify_start; /* offset to start lossifying hashtable at */ PagetableEntry entry1; /* used when status == TBM_ONE_PAGE */ /* these are valid when iterating is true: */ PagetableEntry **spages; /* sorted exact-page list, or NULL */ PagetableEntry **schunks; /* sorted lossy-chunk list, or NULL */ + dsa_pointer dsapagetable; /* dsa_pointer to the element array */ + dsa_pointer dsapagetableold; /* dsa_pointer to the old element array */ + dsa_pointer ptpages; /* dsa_pointer to the page array */ + dsa_pointer ptchunks; /* dsa_pointer to the chunk array */ + dsa_area *dsa; /* reference to per-query dsa area */ }; /* @@ -155,6 +182,46 @@ struct TBMIterator TBMIterateResult output; /* MUST BE LAST (because variable-size) */ }; +/* + * Holds the shared members of the iterator so that multiple processes + * can jointly iterate. + */ +typedef struct TBMSharedIteratorState +{ + int nentries; /* number of entries in pagetable */ + int maxentries; /* limit on same to meet maxbytes */ + int npages; /* number of exact entries in pagetable */ + int nchunks; /* number of lossy entries in pagetable */ + dsa_pointer pagetable; /* dsa pointers to head of pagetable data */ + dsa_pointer spages; /* dsa pointer to page array */ + dsa_pointer schunks; /* dsa pointer to chunk array */ + LWLock lock; /* lock to protect below members */ + int spageptr; /* next spages index */ + int schunkptr; /* next schunks index */ + int schunkbit; /* next bit to check in current schunk */ +} TBMSharedIteratorState; + +/* + * pagetable iteration array. + */ +typedef struct PTIterationArray +{ + pg_atomic_uint32 refcount; /* no. of iterator attached */ + int index[FLEXIBLE_ARRAY_MEMBER]; /* index array */ +} PTIterationArray; + +/* + * same as TBMIterator, but it is used for joint iteration, therefore this + * also holds a reference to the shared state. + */ +struct TBMSharedIterator +{ + TBMSharedIteratorState *state; /* shared state */ + PTEntryArray *ptbase; /* pagetable element array */ + PTIterationArray *ptpages; /* sorted exact page index list */ + PTIterationArray *ptchunks; /* sorted lossy page index list */ + TBMIterateResult output; /* MUST BE LAST (because variable-size) */ +}; /* Local function prototypes */ static void tbm_union_page(TIDBitmap *a, const PagetableEntry *bpage); @@ -167,6 +234,38 @@ static bool tbm_page_is_lossy(const TIDBitmap *tbm, BlockNumber pageno); static void tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno); static void tbm_lossify(TIDBitmap *tbm); static int tbm_comparator(const void *left, const void *right); +static int tbm_shared_comparator(const void *left, const void *right, + void *arg); + +/* + * Simple inline murmur hash implementation for the exact width required, for + * performance. + */ +static inline uint32 +hash_blockno(BlockNumber b) +{ + uint32 h = b; + + h ^= h >> 16; + h *= 0x85ebca6b; + h ^= h >> 13; + h *= 0xc2b2ae35; + h ^= h >> 16; + return h; +} + +/* define hashtable mapping block numbers to PagetableEntry's */ +#define SH_USE_NONDEFAULT_ALLOCATOR +#define SH_PREFIX pagetable +#define SH_ELEMENT_TYPE PagetableEntry +#define SH_KEY_TYPE BlockNumber +#define SH_KEY blockno +#define SH_HASH_KEY(tb, key) hash_blockno(key) +#define SH_EQUAL(tb, a, b) a == b +#define SH_SCOPE static inline +#define SH_DEFINE +#define SH_DECLARE +#include "lib/simplehash.h" /* @@ -174,10 +273,12 @@ static int tbm_comparator(const void *left, const void *right); * * The bitmap will live in the memory context that is CurrentMemoryContext * at the time of this call. It will be limited to (approximately) maxbytes - * total memory consumption. + * total memory consumption. If the DSA passed to this function is not NULL + * then the memory for storing elements of the underlying page table will + * be allocated from the DSA. */ TIDBitmap * -tbm_create(long maxbytes) +tbm_create(long maxbytes, dsa_area *dsa) { TIDBitmap *tbm; long nbuckets; @@ -190,17 +291,21 @@ tbm_create(long maxbytes) /* * Estimate number of hashtable entries we can have within maxbytes. This - * estimates the hash overhead at MAXALIGN(sizeof(HASHELEMENT)) plus a - * pointer per hash entry, which is crude but good enough for our purpose. - * Also count an extra Pointer per entry for the arrays created during - * iteration readout. + * estimates the hash cost as sizeof(PagetableEntry), which is good enough + * for our purpose. Also count an extra Pointer per entry for the arrays + * created during iteration readout. */ nbuckets = maxbytes / - (MAXALIGN(sizeof(HASHELEMENT)) + MAXALIGN(sizeof(PagetableEntry)) - + sizeof(Pointer) + sizeof(Pointer)); + (sizeof(PagetableEntry) + sizeof(Pointer) + sizeof(Pointer)); nbuckets = Min(nbuckets, INT_MAX - 1); /* safety limit */ nbuckets = Max(nbuckets, 16); /* sanity limit */ tbm->maxentries = (int) nbuckets; + tbm->lossify_start = 0; + tbm->dsa = dsa; + tbm->dsapagetable = InvalidDsaPointer; + tbm->dsapagetableold = InvalidDsaPointer; + tbm->ptpages = InvalidDsaPointer; + tbm->ptchunks = InvalidDsaPointer; return tbm; } @@ -212,32 +317,25 @@ tbm_create(long maxbytes) static void tbm_create_pagetable(TIDBitmap *tbm) { - HASHCTL hash_ctl; - Assert(tbm->status != TBM_HASH); Assert(tbm->pagetable == NULL); - /* Create the hashtable proper */ - MemSet(&hash_ctl, 0, sizeof(hash_ctl)); - hash_ctl.keysize = sizeof(BlockNumber); - hash_ctl.entrysize = sizeof(PagetableEntry); - hash_ctl.hcxt = tbm->mcxt; - tbm->pagetable = hash_create("TIDBitmap", - 128, /* start small and extend */ - &hash_ctl, - HASH_ELEM | HASH_BLOBS | HASH_CONTEXT); + tbm->pagetable = pagetable_create(tbm->mcxt, 128, tbm); /* If entry1 is valid, push it into the hashtable */ if (tbm->status == TBM_ONE_PAGE) { PagetableEntry *page; bool found; + char oldstatus; - page = (PagetableEntry *) hash_search(tbm->pagetable, - (void *) &tbm->entry1.blockno, - HASH_ENTER, &found); + page = pagetable_insert(tbm->pagetable, + tbm->entry1.blockno, + &found); Assert(!found); + oldstatus = page->status; memcpy(page, &tbm->entry1, sizeof(PagetableEntry)); + page->status = oldstatus; } tbm->status = TBM_HASH; @@ -250,7 +348,7 @@ void tbm_free(TIDBitmap *tbm) { if (tbm->pagetable) - hash_destroy(tbm->pagetable); + pagetable_destroy(tbm->pagetable); if (tbm->spages) pfree(tbm->spages); if (tbm->schunks) @@ -259,6 +357,43 @@ tbm_free(TIDBitmap *tbm) } /* + * tbm_free_shared_area - free shared state + * + * Free shared iterator state, Also free shared pagetable and iterator arrays + * memory if they are not referred by any of the shared iterator i.e recount + * is becomes 0. + */ +void +tbm_free_shared_area(dsa_area *dsa, dsa_pointer dp) +{ + TBMSharedIteratorState *istate = dsa_get_address(dsa, dp); + PTEntryArray *ptbase; + PTIterationArray *ptpages; + PTIterationArray *ptchunks; + + if (DsaPointerIsValid(istate->pagetable)) + { + ptbase = dsa_get_address(dsa, istate->pagetable); + if (pg_atomic_sub_fetch_u32(&ptbase->refcount, 1) == 0) + dsa_free(dsa, istate->pagetable); + } + if (DsaPointerIsValid(istate->spages)) + { + ptpages = dsa_get_address(dsa, istate->spages); + if (pg_atomic_sub_fetch_u32(&ptpages->refcount, 1) == 0) + dsa_free(dsa, istate->spages); + } + if (DsaPointerIsValid(istate->schunks)) + { + ptchunks = dsa_get_address(dsa, istate->schunks); + if (pg_atomic_sub_fetch_u32(&ptchunks->refcount, 1) == 0) + dsa_free(dsa, istate->schunks); + } + + dsa_free(dsa, dp); +} + +/* * tbm_add_tuples - add some tuple IDs to a TIDBitmap * * If recheck is true, then the recheck flag will be set in the @@ -272,7 +407,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids, PagetableEntry *page = NULL; /* only valid when currblk is valid */ int i; - Assert(!tbm->iterating); + Assert(tbm->iterating == TBM_NOT_ITERATING); for (i = 0; i < ntids; i++) { BlockNumber blk = ItemPointerGetBlockNumber(tids + i); @@ -357,12 +492,12 @@ tbm_union(TIDBitmap *a, const TIDBitmap *b) tbm_union_page(a, &b->entry1); else { - HASH_SEQ_STATUS status; + pagetable_iterator i; PagetableEntry *bpage; Assert(b->status == TBM_HASH); - hash_seq_init(&status, b->pagetable); - while ((bpage = (PagetableEntry *) hash_seq_search(&status)) != NULL) + pagetable_start_iterate(b->pagetable, &i); + while ((bpage = pagetable_iterate(b->pagetable, &i)) != NULL) tbm_union_page(a, bpage); } } @@ -449,12 +584,12 @@ tbm_intersect(TIDBitmap *a, const TIDBitmap *b) } else { - HASH_SEQ_STATUS status; + pagetable_iterator i; PagetableEntry *apage; Assert(a->status == TBM_HASH); - hash_seq_init(&status, a->pagetable); - while ((apage = (PagetableEntry *) hash_seq_search(&status)) != NULL) + pagetable_start_iterate(a->pagetable, &i); + while ((apage = pagetable_iterate(a->pagetable, &i)) != NULL) { if (tbm_intersect_page(a, apage, b)) { @@ -464,9 +599,7 @@ tbm_intersect(TIDBitmap *a, const TIDBitmap *b) else a->npages--; a->nentries--; - if (hash_search(a->pagetable, - (void *) &apage->blockno, - HASH_REMOVE, NULL) == NULL) + if (!pagetable_delete(a->pagetable, apage->blockno)) elog(ERROR, "hash table corrupted"); } } @@ -583,6 +716,8 @@ tbm_begin_iterate(TIDBitmap *tbm) { TBMIterator *iterator; + Assert(tbm->iterating != TBM_ITERATING_SHARED); + /* * Create the TBMIterator struct, with enough trailing space to serve the * needs of the TBMIterateResult sub-struct. @@ -604,9 +739,9 @@ tbm_begin_iterate(TIDBitmap *tbm) * attached to the bitmap not the iterator, so they can be used by more * than one iterator. */ - if (tbm->status == TBM_HASH && !tbm->iterating) + if (tbm->status == TBM_HASH && tbm->iterating == TBM_NOT_ITERATING) { - HASH_SEQ_STATUS status; + pagetable_iterator i; PagetableEntry *page; int npages; int nchunks; @@ -620,9 +755,9 @@ tbm_begin_iterate(TIDBitmap *tbm) MemoryContextAlloc(tbm->mcxt, tbm->nchunks * sizeof(PagetableEntry *)); - hash_seq_init(&status, tbm->pagetable); npages = nchunks = 0; - while ((page = (PagetableEntry *) hash_seq_search(&status)) != NULL) + pagetable_start_iterate(tbm->pagetable, &i); + while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL) { if (page->ischunk) tbm->schunks[nchunks++] = page; @@ -639,12 +774,214 @@ tbm_begin_iterate(TIDBitmap *tbm) tbm_comparator); } - tbm->iterating = true; + tbm->iterating = TBM_ITERATING_PRIVATE; return iterator; } /* + * tbm_prepare_shared_iterate - prepare shared iteration state for a TIDBitmap. + * + * The necessary shared state will be allocated from the DSA passed to + * tbm_create, so that multiple processes can attach to it and iterate jointly. + * + * This will convert the pagetable hash into page and chunk array of the index + * into pagetable array. + */ +dsa_pointer +tbm_prepare_shared_iterate(TIDBitmap *tbm) +{ + dsa_pointer dp; + TBMSharedIteratorState *istate; + PTEntryArray *ptbase = NULL; + PTIterationArray *ptpages = NULL; + PTIterationArray *ptchunks = NULL; + + Assert(tbm->dsa != NULL); + Assert(tbm->iterating != TBM_ITERATING_PRIVATE); + + /* + * Allocate TBMSharedIteratorState from DSA to hold the shared members and + * lock, this will also be used by multiple worker for shared iterate. + */ + dp = dsa_allocate0(tbm->dsa, sizeof(TBMSharedIteratorState)); + istate = dsa_get_address(tbm->dsa, dp); + + /* + * If we're not already iterating, create and fill the sorted page lists. + * (If we are, the sorted page lists are already stored in the TIDBitmap, + * and we can just reuse them.) + */ + if (tbm->iterating == TBM_NOT_ITERATING) + { + pagetable_iterator i; + PagetableEntry *page; + int idx; + int npages; + int nchunks; + + /* + * Allocate the page and chunk array memory from the DSA to share + * across multiple processes. + */ + if (tbm->npages) + { + tbm->ptpages = dsa_allocate(tbm->dsa, sizeof(PTIterationArray) + + tbm->npages * sizeof(int)); + ptpages = dsa_get_address(tbm->dsa, tbm->ptpages); + pg_atomic_init_u32(&ptpages->refcount, 0); + } + if (tbm->nchunks) + { + tbm->ptchunks = dsa_allocate(tbm->dsa, sizeof(PTIterationArray) + + tbm->nchunks * sizeof(int)); + ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks); + pg_atomic_init_u32(&ptchunks->refcount, 0); + } + + /* + * If TBM status is TBM_HASH then iterate over the pagetable and + * convert it to page and chunk arrays. But if it's in the + * TBM_ONE_PAGE mode then directly allocate the space for one entry + * from the DSA. + */ + npages = nchunks = 0; + if (tbm->status == TBM_HASH) + { + ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable); + + pagetable_start_iterate(tbm->pagetable, &i); + while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL) + { + idx = page - ptbase->ptentry; + if (page->ischunk) + ptchunks->index[nchunks++] = idx; + else + ptpages->index[npages++] = idx; + } + + Assert(npages == tbm->npages); + Assert(nchunks == tbm->nchunks); + } + else if (tbm->status == TBM_ONE_PAGE) + { + /* + * In one page mode allocate the space for one pagetable entry, + * initialize it, and directly store its index (i.e. 0) in the + * page array. + */ + tbm->dsapagetable = dsa_allocate(tbm->dsa, sizeof(PTEntryArray) + + sizeof(PagetableEntry)); + ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable); + memcpy(ptbase->ptentry, &tbm->entry1, sizeof(PagetableEntry)); + ptpages->index[0] = 0; + } + + if (ptbase != NULL) + pg_atomic_init_u32(&ptbase->refcount, 0); + if (npages > 1) + qsort_arg((void *) (ptpages->index), npages, sizeof(int), + tbm_shared_comparator, (void *) ptbase->ptentry); + if (nchunks > 1) + qsort_arg((void *) (ptchunks->index), nchunks, sizeof(int), + tbm_shared_comparator, (void *) ptbase->ptentry); + } + + /* + * Store the TBM members in the shared state so that we can share them + * across multiple processes. + */ + istate->nentries = tbm->nentries; + istate->maxentries = tbm->maxentries; + istate->npages = tbm->npages; + istate->nchunks = tbm->nchunks; + istate->pagetable = tbm->dsapagetable; + istate->spages = tbm->ptpages; + istate->schunks = tbm->ptchunks; + + ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable); + ptpages = dsa_get_address(tbm->dsa, tbm->ptpages); + ptchunks = dsa_get_address(tbm->dsa, tbm->ptchunks); + + /* + * For every shared iterator, referring to pagetable and iterator array, + * increase the refcount by 1 so that while freeing the shared iterator we + * don't free pagetable and iterator array until its refcount becomes 0. + */ + if (ptbase != NULL) + pg_atomic_add_fetch_u32(&ptbase->refcount, 1); + if (ptpages != NULL) + pg_atomic_add_fetch_u32(&ptpages->refcount, 1); + if (ptchunks != NULL) + pg_atomic_add_fetch_u32(&ptchunks->refcount, 1); + + /* Initialize the iterator lock */ + LWLockInitialize(&istate->lock, LWTRANCHE_TBM); + + /* Initialize the shared iterator state */ + istate->schunkbit = 0; + istate->schunkptr = 0; + istate->spageptr = 0; + + tbm->iterating = TBM_ITERATING_SHARED; + + return dp; +} + +/* + * tbm_extract_page_tuple - extract the tuple offsets from a page + * + * The extracted offsets are stored into TBMIterateResult. + */ +static inline int +tbm_extract_page_tuple(PagetableEntry *page, TBMIterateResult *output) +{ + int wordnum; + int ntuples = 0; + + for (wordnum = 0; wordnum < WORDS_PER_PAGE; wordnum++) + { + bitmapword w = page->words[wordnum]; + + if (w != 0) + { + int off = wordnum * BITS_PER_BITMAPWORD + 1; + + while (w != 0) + { + if (w & 1) + output->offsets[ntuples++] = (OffsetNumber) off; + off++; + w >>= 1; + } + } + } + + return ntuples; +} + +/* + * tbm_advance_schunkbit - Advance the chunkbit + */ +static inline void +tbm_advance_schunkbit(PagetableEntry *chunk, int *schunkbitp) +{ + int schunkbit = *schunkbitp; + + while (schunkbit < PAGES_PER_CHUNK) + { + int wordnum = WORDNUM(schunkbit); + int bitnum = BITNUM(schunkbit); + + if ((chunk->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0) + break; + schunkbit++; + } + + *schunkbitp = schunkbit; +} + +/* * tbm_iterate - scan through next page of a TIDBitmap * * Returns a TBMIterateResult representing one page, or NULL if there are @@ -662,7 +999,7 @@ tbm_iterate(TBMIterator *iterator) TIDBitmap *tbm = iterator->tbm; TBMIterateResult *output = &(iterator->output); - Assert(tbm->iterating); + Assert(tbm->iterating == TBM_ITERATING_PRIVATE); /* * If lossy chunk pages remain, make sure we've advanced schunkptr/ @@ -673,15 +1010,7 @@ tbm_iterate(TBMIterator *iterator) PagetableEntry *chunk = tbm->schunks[iterator->schunkptr]; int schunkbit = iterator->schunkbit; - while (schunkbit < PAGES_PER_CHUNK) - { - int wordnum = WORDNUM(schunkbit); - int bitnum = BITNUM(schunkbit); - - if ((chunk->words[wordnum] & ((bitmapword) 1 << bitnum)) != 0) - break; - schunkbit++; - } + tbm_advance_schunkbit(chunk, &schunkbit); if (schunkbit < PAGES_PER_CHUNK) { iterator->schunkbit = schunkbit; @@ -718,7 +1047,6 @@ tbm_iterate(TBMIterator *iterator) { PagetableEntry *page; int ntuples; - int wordnum; /* In ONE_PAGE state, we don't allocate an spages[] array */ if (tbm->status == TBM_ONE_PAGE) @@ -727,31 +1055,108 @@ tbm_iterate(TBMIterator *iterator) page = tbm->spages[iterator->spageptr]; /* scan bitmap to extract individual offset numbers */ - ntuples = 0; - for (wordnum = 0; wordnum < WORDS_PER_PAGE; wordnum++) + ntuples = tbm_extract_page_tuple(page, output); + output->blockno = page->blockno; + output->ntuples = ntuples; + output->recheck = page->recheck; + iterator->spageptr++; + return output; + } + + /* Nothing more in the bitmap */ + return NULL; +} + +/* + * tbm_shared_iterate - scan through next page of a TIDBitmap + * + * As above, but this will iterate using an iterator which is shared + * across multiple processes. We need to acquire the iterator LWLock, + * before accessing the shared members. + */ +TBMIterateResult * +tbm_shared_iterate(TBMSharedIterator *iterator) +{ + TBMIterateResult *output = &iterator->output; + TBMSharedIteratorState *istate = iterator->state; + PagetableEntry *ptbase = NULL; + int *idxpages = NULL; + int *idxchunks = NULL; + + if (iterator->ptbase != NULL) + ptbase = iterator->ptbase->ptentry; + if (iterator->ptpages != NULL) + idxpages = iterator->ptpages->index; + if (iterator->ptchunks != NULL) + idxchunks = iterator->ptchunks->index; + + /* Acquire the LWLock before accessing the shared members */ + LWLockAcquire(&istate->lock, LW_EXCLUSIVE); + + /* + * If lossy chunk pages remain, make sure we've advanced schunkptr/ + * schunkbit to the next set bit. + */ + while (istate->schunkptr < istate->nchunks) + { + PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]]; + int schunkbit = istate->schunkbit; + + tbm_advance_schunkbit(chunk, &schunkbit); + if (schunkbit < PAGES_PER_CHUNK) { - bitmapword w = page->words[wordnum]; + istate->schunkbit = schunkbit; + break; + } + /* advance to next chunk */ + istate->schunkptr++; + istate->schunkbit = 0; + } - if (w != 0) - { - int off = wordnum * BITS_PER_BITMAPWORD + 1; + /* + * If both chunk and per-page data remain, must output the numerically + * earlier page. + */ + if (istate->schunkptr < istate->nchunks) + { + PagetableEntry *chunk = &ptbase[idxchunks[istate->schunkptr]]; + BlockNumber chunk_blockno; - while (w != 0) - { - if (w & 1) - output->offsets[ntuples++] = (OffsetNumber) off; - off++; - w >>= 1; - } - } + chunk_blockno = chunk->blockno + istate->schunkbit; + + if (istate->spageptr >= istate->npages || + chunk_blockno < ptbase[idxpages[istate->spageptr]].blockno) + { + /* Return a lossy page indicator from the chunk */ + output->blockno = chunk_blockno; + output->ntuples = -1; + output->recheck = true; + istate->schunkbit++; + + LWLockRelease(&istate->lock); + return output; } + } + + if (istate->spageptr < istate->npages) + { + PagetableEntry *page = &ptbase[idxpages[istate->spageptr]]; + int ntuples; + + /* scan bitmap to extract individual offset numbers */ + ntuples = tbm_extract_page_tuple(page, output); output->blockno = page->blockno; output->ntuples = ntuples; output->recheck = page->recheck; - iterator->spageptr++; + istate->spageptr++; + + LWLockRelease(&istate->lock); + return output; } + LWLockRelease(&istate->lock); + /* Nothing more in the bitmap */ return NULL; } @@ -770,6 +1175,18 @@ tbm_end_iterate(TBMIterator *iterator) } /* + * tbm_end_shared_iterate - finish a shared iteration over a TIDBitmap + * + * This doesn't free any of the shared state associated with the iterator, + * just our backend-private state. + */ +void +tbm_end_shared_iterate(TBMSharedIterator *iterator) +{ + pfree(iterator); +} + +/* * tbm_find_pageentry - find a PagetableEntry for the pageno * * Returns NULL if there is no non-lossy entry for the pageno. @@ -791,9 +1208,7 @@ tbm_find_pageentry(const TIDBitmap *tbm, BlockNumber pageno) return page; } - page = (PagetableEntry *) hash_search(tbm->pagetable, - (void *) &pageno, - HASH_FIND, NULL); + page = pagetable_lookup(tbm->pagetable, pageno); if (page == NULL) return NULL; if (page->ischunk) @@ -834,15 +1249,16 @@ tbm_get_pageentry(TIDBitmap *tbm, BlockNumber pageno) } /* Look up or create an entry */ - page = (PagetableEntry *) hash_search(tbm->pagetable, - (void *) &pageno, - HASH_ENTER, &found); + page = pagetable_insert(tbm->pagetable, pageno, &found); } /* Initialize it if not present before */ if (!found) { + char oldstatus = page->status; + MemSet(page, 0, sizeof(PagetableEntry)); + page->status = oldstatus; page->blockno = pageno; /* must count it too */ tbm->nentries++; @@ -869,9 +1285,9 @@ tbm_page_is_lossy(const TIDBitmap *tbm, BlockNumber pageno) bitno = pageno % PAGES_PER_CHUNK; chunk_pageno = pageno - bitno; - page = (PagetableEntry *) hash_search(tbm->pagetable, - (void *) &chunk_pageno, - HASH_FIND, NULL); + + page = pagetable_lookup(tbm->pagetable, chunk_pageno); + if (page != NULL && page->ischunk) { int wordnum = WORDNUM(bitno); @@ -912,9 +1328,7 @@ tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno) */ if (bitno != 0) { - if (hash_search(tbm->pagetable, - (void *) &pageno, - HASH_REMOVE, NULL) != NULL) + if (pagetable_delete(tbm->pagetable, pageno)) { /* It was present, so adjust counts */ tbm->nentries--; @@ -923,14 +1337,15 @@ tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno) } /* Look up or create entry for chunk-header page */ - page = (PagetableEntry *) hash_search(tbm->pagetable, - (void *) &chunk_pageno, - HASH_ENTER, &found); + page = pagetable_insert(tbm->pagetable, chunk_pageno, &found); /* Initialize it if not present before */ if (!found) { + char oldstatus = page->status; + MemSet(page, 0, sizeof(PagetableEntry)); + page->status = oldstatus; page->blockno = chunk_pageno; page->ischunk = true; /* must count it too */ @@ -939,8 +1354,11 @@ tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno) } else if (!page->ischunk) { + char oldstatus = page->status; + /* chunk header page was formerly non-lossy, make it lossy */ MemSet(page, 0, sizeof(PagetableEntry)); + page->status = oldstatus; page->blockno = chunk_pageno; page->ischunk = true; /* we assume it had some tuple bit(s) set, so mark it lossy */ @@ -962,7 +1380,7 @@ tbm_mark_page_lossy(TIDBitmap *tbm, BlockNumber pageno) static void tbm_lossify(TIDBitmap *tbm) { - HASH_SEQ_STATUS status; + pagetable_iterator i; PagetableEntry *page; /* @@ -974,11 +1392,11 @@ tbm_lossify(TIDBitmap *tbm) * push nentries down to significantly less than maxentries, or else we'll * just end up doing this again very soon. We shoot for maxentries/2. */ - Assert(!tbm->iterating); + Assert(tbm->iterating == TBM_NOT_ITERATING); Assert(tbm->status == TBM_HASH); - hash_seq_init(&status, tbm->pagetable); - while ((page = (PagetableEntry *) hash_seq_search(&status)) != NULL) + pagetable_start_iterate_at(tbm->pagetable, &i, tbm->lossify_start); + while ((page = pagetable_iterate(tbm->pagetable, &i)) != NULL) { if (page->ischunk) continue; /* already a chunk header */ @@ -995,15 +1413,19 @@ tbm_lossify(TIDBitmap *tbm) if (tbm->nentries <= tbm->maxentries / 2) { - /* we have done enough */ - hash_seq_term(&status); + /* + * We have made enough room. Remember where to start lossifying + * next round, so we evenly iterate over the hashtable. + */ + tbm->lossify_start = i.cur; break; } /* * Note: tbm_mark_page_lossy may have inserted a lossy chunk into the - * hashtable. We can continue the same seq_search scan since we do - * not care whether we visit lossy chunks or not. + * hashtable and may have deleted the non-lossy chunk. We can + * continue the same hash table scan, since failure to visit one + * element or visiting the newly inserted element, isn't fatal. */ } @@ -1036,3 +1458,107 @@ tbm_comparator(const void *left, const void *right) return 1; return 0; } + +/* + * As above, but this will get index into PagetableEntry array. Therefore, + * it needs to get actual PagetableEntry using the index before comparing the + * blockno. + */ +static int +tbm_shared_comparator(const void *left, const void *right, void *arg) +{ + PagetableEntry *base = (PagetableEntry *) arg; + PagetableEntry *lpage = &base[*(int *) left]; + PagetableEntry *rpage = &base[*(int *) right]; + + if (lpage->blockno < rpage->blockno) + return -1; + else if (lpage->blockno > rpage->blockno) + return 1; + return 0; +} + +/* + * tbm_attach_shared_iterate + * + * Allocate a backend-private iterator and attach the shared iterator state + * to it so that multiple processed can iterate jointly. + * + * We also converts the DSA pointers to local pointers and store them into + * our private iterator. + */ +TBMSharedIterator * +tbm_attach_shared_iterate(dsa_area *dsa, dsa_pointer dp) +{ + TBMSharedIterator *iterator; + TBMSharedIteratorState *istate; + + /* + * Create the TBMSharedIterator struct, with enough trailing space to + * serve the needs of the TBMIterateResult sub-struct. + */ + iterator = (TBMSharedIterator *) palloc0(sizeof(TBMSharedIterator) + + MAX_TUPLES_PER_PAGE * sizeof(OffsetNumber)); + + istate = (TBMSharedIteratorState *) dsa_get_address(dsa, dp); + + iterator->state = istate; + + iterator->ptbase = dsa_get_address(dsa, istate->pagetable); + + if (istate->npages) + iterator->ptpages = dsa_get_address(dsa, istate->spages); + if (istate->nchunks) + iterator->ptchunks = dsa_get_address(dsa, istate->schunks); + + return iterator; +} + +/* + * pagetable_allocate + * + * Callback function for allocating the memory for hashtable elements. + * Allocate memory for hashtable elements, using DSA if available. + */ +static inline void * +pagetable_allocate(pagetable_hash *pagetable, Size size) +{ + TIDBitmap *tbm = (TIDBitmap *) pagetable->private_data; + PTEntryArray *ptbase; + + if (tbm->dsa == NULL) + return MemoryContextAllocExtended(pagetable->ctx, size, + MCXT_ALLOC_HUGE | MCXT_ALLOC_ZERO); + + /* + * Save the dsapagetable reference in dsapagetableold before allocating + * new memory so that pagetable_free can free the old entry. + */ + tbm->dsapagetableold = tbm->dsapagetable; + tbm->dsapagetable = dsa_allocate_extended(tbm->dsa, + sizeof(PTEntryArray) + size, + DSA_ALLOC_HUGE | DSA_ALLOC_ZERO); + ptbase = dsa_get_address(tbm->dsa, tbm->dsapagetable); + + return ptbase->ptentry; +} + +/* + * pagetable_free + * + * Callback function for freeing hash table elements. + */ +static inline void +pagetable_free(pagetable_hash *pagetable, void *pointer) +{ + TIDBitmap *tbm = (TIDBitmap *) pagetable->private_data; + + /* pfree the input pointer if DSA is not available */ + if (tbm->dsa == NULL) + pfree(pointer); + else if (DsaPointerIsValid(tbm->dsapagetableold)) + { + dsa_free(tbm->dsa, tbm->dsapagetableold); + tbm->dsapagetableold = InvalidDsaPointer; + } +} diff --git a/src/backend/nodes/value.c b/src/backend/nodes/value.c index a5ed5bc7c2..5d2f96c103 100644 --- a/src/backend/nodes/value.c +++ b/src/backend/nodes/value.c @@ -4,7 +4,7 @@ * implementation of Value nodes * * - * Copyright (c) 2003-2016, PostgreSQL Global Development Group + * Copyright (c) 2003-2017, PostgreSQL Global Development Group * * * IDENTIFICATION |