aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/dependency.c14
-rw-r--r--src/backend/executor/execExprInterp.c46
-rw-r--r--src/backend/nodes/nodeFuncs.c16
-rw-r--r--src/backend/nodes/outfuncs.c12
-rw-r--r--src/backend/nodes/readfuncs.c16
-rw-r--r--src/backend/optimizer/path/costsize.c9
-rw-r--r--src/backend/optimizer/util/clauses.c23
-rw-r--r--src/backend/utils/adt/ruleutils.c17
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;