diff options
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 |