diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/catalog/dependency.c | 14 | ||||
-rw-r--r-- | src/backend/executor/execExprInterp.c | 46 | ||||
-rw-r--r-- | src/backend/nodes/nodeFuncs.c | 16 | ||||
-rw-r--r-- | src/backend/nodes/outfuncs.c | 12 | ||||
-rw-r--r-- | src/backend/nodes/readfuncs.c | 16 | ||||
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 9 | ||||
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 23 | ||||
-rw-r--r-- | src/backend/utils/adt/ruleutils.c | 17 |
8 files changed, 122 insertions, 31 deletions
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index 1a7645d341f..6fffc290fad 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -1791,6 +1791,13 @@ find_expr_references_walker(Node *node, add_object_address(OCLASS_TYPE, cd->resulttype, 0, context->addrs); } + else if (IsA(node, NextValueExpr)) + { + NextValueExpr *nve = (NextValueExpr *) node; + + add_object_address(OCLASS_CLASS, nve->seqid, 0, + context->addrs); + } else if (IsA(node, OnConflictExpr)) { OnConflictExpr *onconflict = (OnConflictExpr *) node; @@ -1942,13 +1949,6 @@ find_expr_references_walker(Node *node, context->addrs); /* fall through to examine arguments */ } - else if (IsA(node, NextValueExpr)) - { - NextValueExpr *nve = (NextValueExpr *) node; - - add_object_address(OCLASS_CLASS, nve->seqid, 0, - context->addrs); - } return expression_tree_walker(node, find_expr_references_walker, (void *) context); diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c index c227d9bdd99..f2a52f62135 100644 --- a/src/backend/executor/execExprInterp.c +++ b/src/backend/executor/execExprInterp.c @@ -1232,21 +1232,11 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull) EEO_CASE(EEOP_NEXTVALUEEXPR) { - switch (op->d.nextvalueexpr.seqtypid) - { - case INT2OID: - *op->resvalue = Int16GetDatum((int16) nextval_internal(op->d.nextvalueexpr.seqid, false)); - break; - case INT4OID: - *op->resvalue = Int32GetDatum((int32) nextval_internal(op->d.nextvalueexpr.seqid, false)); - break; - case INT8OID: - *op->resvalue = Int64GetDatum((int64) nextval_internal(op->d.nextvalueexpr.seqid, false)); - break; - default: - elog(ERROR, "unsupported sequence type %u", op->d.nextvalueexpr.seqtypid); - } - *op->resnull = false; + /* + * Doesn't seem worthwhile to have an inline implementation + * efficiency-wise. + */ + ExecEvalNextValueExpr(state, op); EEO_NEXT(); } @@ -1990,6 +1980,32 @@ ExecEvalCurrentOfExpr(ExprState *state, ExprEvalStep *op) } /* + * Evaluate NextValueExpr. + */ +void +ExecEvalNextValueExpr(ExprState *state, ExprEvalStep *op) +{ + int64 newval = nextval_internal(op->d.nextvalueexpr.seqid, false); + + switch (op->d.nextvalueexpr.seqtypid) + { + case INT2OID: + *op->resvalue = Int16GetDatum((int16) newval); + break; + case INT4OID: + *op->resvalue = Int32GetDatum((int32) newval); + break; + case INT8OID: + *op->resvalue = Int64GetDatum((int64) newval); + break; + default: + elog(ERROR, "unsupported sequence type %u", + op->d.nextvalueexpr.seqtypid); + } + *op->resnull = false; +} + +/* * Evaluate NullTest / IS NULL for rows. */ void diff --git a/src/backend/nodes/nodeFuncs.c b/src/backend/nodes/nodeFuncs.c index 97ba25fc72c..e3eb0c57887 100644 --- a/src/backend/nodes/nodeFuncs.c +++ b/src/backend/nodes/nodeFuncs.c @@ -1642,10 +1642,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, 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. + * Note: we ignore MinMaxExpr, SQLValueFunction, XmlExpr, CoerceToDomain, + * and NextValueExpr 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, @@ -1865,12 +1865,12 @@ expression_tree_walker(Node *node, case T_Var: case T_Const: case T_Param: - case T_CoerceToDomainValue: case T_CaseTestExpr: + case T_SQLValueFunction: + case T_CoerceToDomainValue: 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 */ @@ -2461,12 +2461,12 @@ expression_tree_mutator(Node *node, } break; case T_Param: - case T_CoerceToDomainValue: case T_CaseTestExpr: + case T_SQLValueFunction: + case T_CoerceToDomainValue: case T_SetToDefault: case T_CurrentOfExpr: case T_NextValueExpr: - case T_SQLValueFunction: case T_RangeTblRef: case T_SortGroupClause: return (Node *) copyObject(node); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index b0abe9ec10f..21e39a0b810 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -1611,6 +1611,15 @@ _outCurrentOfExpr(StringInfo str, const CurrentOfExpr *node) } static void +_outNextValueExpr(StringInfo str, const NextValueExpr *node) +{ + WRITE_NODE_TYPE("NEXTVALUEEXPR"); + + WRITE_OID_FIELD(seqid); + WRITE_OID_FIELD(typeId); +} + +static void _outInferenceElem(StringInfo str, const InferenceElem *node) { WRITE_NODE_TYPE("INFERENCEELEM"); @@ -3872,6 +3881,9 @@ outNode(StringInfo str, const void *obj) case T_CurrentOfExpr: _outCurrentOfExpr(str, obj); break; + case T_NextValueExpr: + _outNextValueExpr(str, obj); + break; case T_InferenceElem: _outInferenceElem(str, obj); break; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 1380703cbc6..8ab09d74d60 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1203,6 +1203,20 @@ _readCurrentOfExpr(void) } /* + * _readNextValueExpr + */ +static NextValueExpr * +_readNextValueExpr(void) +{ + READ_LOCALS(NextValueExpr); + + READ_OID_FIELD(seqid); + READ_OID_FIELD(typeId); + + READ_DONE(); +} + +/* * _readInferenceElem */ static InferenceElem * @@ -2517,6 +2531,8 @@ parseNodeString(void) return_value = _readSetToDefault(); else if (MATCH("CURRENTOFEXPR", 13)) return_value = _readCurrentOfExpr(); + else if (MATCH("NEXTVALUEEXPR", 13)) + return_value = _readNextValueExpr(); else if (MATCH("INFERENCEELEM", 13)) return_value = _readInferenceElem(); else if (MATCH("TARGETENTRY", 11)) diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index eb653cf3bec..b35acb7bdcf 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -3627,6 +3627,15 @@ cost_qual_eval_walker(Node *node, cost_qual_eval_context *context) cpu_operator_cost; } } + else if (IsA(node, MinMaxExpr) || + IsA(node, SQLValueFunction) || + IsA(node, XmlExpr) || + IsA(node, CoerceToDomain) || + IsA(node, NextValueExpr)) + { + /* Treat all these as having cost 1 */ + context->total.per_tuple += cpu_operator_cost; + } else if (IsA(node, CurrentOfExpr)) { /* Report high cost to prevent selection of anything but TID scan */ diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 8961ed88a81..8b4425dcf90 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -902,6 +902,12 @@ contain_mutable_functions_walker(Node *node, void *context) return true; } + if (IsA(node, NextValueExpr)) + { + /* NextValueExpr is volatile */ + return true; + } + /* * It should be safe to treat MinMaxExpr as immutable, because it will * depend on a non-cross-type btree comparison function, and those should @@ -969,6 +975,12 @@ contain_volatile_functions_walker(Node *node, void *context) context)) return true; + if (IsA(node, NextValueExpr)) + { + /* NextValueExpr is volatile */ + return true; + } + /* * See notes in contain_mutable_functions_walker about why we treat * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while @@ -1019,6 +1031,8 @@ contain_volatile_functions_not_nextval_walker(Node *node, void *context) * See notes in contain_mutable_functions_walker about why we treat * MinMaxExpr, XmlExpr, and CoerceToDomain as immutable, while * SQLValueFunction is stable. Hence, none of them are of interest here. + * Also, since we're intentionally ignoring nextval(), presumably we + * should ignore NextValueExpr. */ /* Recurse to check arguments */ @@ -1146,7 +1160,7 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context) * contain a parallel-unsafe function; but useful constraints probably * never would have such, and assuming they do would cripple use of * parallel query in the presence of domain types.) SQLValueFunction - * should be safe in all cases. + * should be safe in all cases. NextValueExpr is parallel-unsafe. */ if (IsA(node, CoerceToDomain)) { @@ -1154,6 +1168,12 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context) return true; } + if (IsA(node, NextValueExpr)) + { + if (max_parallel_hazard_test(PROPARALLEL_UNSAFE, context)) + return true; + } + /* * As a notational convenience for callers, look through RestrictInfo. */ @@ -1495,6 +1515,7 @@ contain_leaked_vars_walker(Node *node, void *context) case T_SQLValueFunction: case T_NullTest: case T_BooleanTest: + case T_NextValueExpr: case T_List: /* diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c index 5cfb916684f..d2fb20d5649 100644 --- a/src/backend/utils/adt/ruleutils.c +++ b/src/backend/utils/adt/ruleutils.c @@ -7283,6 +7283,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags) case T_MinMaxExpr: case T_SQLValueFunction: case T_XmlExpr: + case T_NextValueExpr: case T_NullIfExpr: case T_Aggref: case T_WindowFunc: @@ -8612,6 +8613,22 @@ get_rule_expr(Node *node, deparse_context *context, } break; + case T_NextValueExpr: + { + NextValueExpr *nvexpr = (NextValueExpr *) node; + + /* + * This isn't exactly nextval(), but that seems close enough + * for EXPLAIN's purposes. + */ + appendStringInfoString(buf, "nextval("); + simple_quote_literal(buf, + generate_relation_name(nvexpr->seqid, + NIL)); + appendStringInfoChar(buf, ')'); + } + break; + case T_InferenceElem: { InferenceElem *iexpr = (InferenceElem *) node; |