aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_utilcmd.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2020-09-23 18:04:53 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2020-09-23 18:04:53 -0400
commit6b2c4e59d016ea40c42fdc66367d6463e792c125 (patch)
tree9cadeea7569aed429782e3ec7b4d1dcdf0d31b20 /src/backend/parser/parse_utilcmd.c
parent3ea7e9550e58c4016625c7e3e4a1340edfc9adf4 (diff)
downloadpostgresql-6b2c4e59d016ea40c42fdc66367d6463e792c125.tar.gz
postgresql-6b2c4e59d016ea40c42fdc66367d6463e792c125.zip
Improve error cursor positions for problems with partition bounds.
We failed to pass down the query string to check_new_partition_bound, so that its attempts to provide error cursor positions were for naught; one must have the query string to get parser_errposition to do anything. Adjust its API to require a ParseState to be passed down. Also, improve the logic inside check_new_partition_bound so that the cursor points at the partition bound for the specific column causing the issue, when one can be identified. That part is also for naught if we can't determine the query position of the column with the problem. Improve transformPartitionBoundValue so that it makes sure that const-simplified partition expressions will be properly labeled with positions. In passing, skip calling evaluate_expr if the value is already a Const, which is surely the most common case. Alexandra Wang, Ashwin Agrawal, Amit Langote; reviewed by Ashutosh Bapat Discussion: https://postgr.es/m/CACiyaSopZoqssfMzgHk6fAkp01cL6vnqBdmTw2C5_KJaFR_aMg@mail.gmail.com Discussion: https://postgr.es/m/CAJV4CdrZ5mKuaEsRSbLf2URQ3h6iMtKD=hik8MaF5WwdmC9uZw@mail.gmail.com
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r--src/backend/parser/parse_utilcmd.c53
1 files changed, 37 insertions, 16 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index ec944371dd3..164312d60e2 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -4164,7 +4164,7 @@ validateInfiniteBounds(ParseState *pstate, List *blist)
}
/*
- * Transform one constant in a partition bound spec
+ * Transform one entry in a partition bound spec, producing a constant.
*/
static Const *
transformPartitionBoundValue(ParseState *pstate, Node *val,
@@ -4177,6 +4177,13 @@ transformPartitionBoundValue(ParseState *pstate, Node *val,
value = transformExpr(pstate, val, EXPR_KIND_PARTITION_BOUND);
/*
+ * transformExpr() should have already rejected column references,
+ * subqueries, aggregates, window functions, and SRFs, based on the
+ * EXPR_KIND_ of a partition bound expression.
+ */
+ Assert(!contain_var_clause(value));
+
+ /*
* Check that the input expression's collation is compatible with one
* specified for the parent's partition key (partcollation). Don't throw
* an error if it's the default collation which we'll replace with the
@@ -4220,7 +4227,11 @@ transformPartitionBoundValue(ParseState *pstate, Node *val,
parser_errposition(pstate, exprLocation(value))));
}
- /* Coerce to correct type */
+ /*
+ * Coerce to the correct type. This might cause an explicit coercion step
+ * to be added on top of the expression, which must be evaluated before
+ * returning the result to the caller.
+ */
value = coerce_to_target_type(pstate,
value, exprType(value),
colType,
@@ -4236,25 +4247,35 @@ transformPartitionBoundValue(ParseState *pstate, Node *val,
format_type_be(colType), colName),
parser_errposition(pstate, exprLocation(val))));
- /* Simplify the expression, in case we had a coercion */
- if (!IsA(value, Const))
- value = (Node *) expression_planner((Expr *) value);
-
/*
- * transformExpr() should have already rejected column references,
- * subqueries, aggregates, window functions, and SRFs, based on the
- * EXPR_KIND_ for a default expression.
+ * Evaluate the expression, if needed, assigning the partition key's data
+ * type and collation to the resulting Const node.
*/
- Assert(!contain_var_clause(value));
+ if (!IsA(value, Const))
+ {
+ value = (Node *) expression_planner((Expr *) value);
+ value = (Node *) evaluate_expr((Expr *) value, colType, colTypmod,
+ partCollation);
+ if (!IsA(value, Const))
+ elog(ERROR, "could not evaluate partition bound expression");
+ }
+ else
+ {
+ /*
+ * If the expression is already a Const, as is often the case, we can
+ * skip the rather expensive steps above. But we still have to insert
+ * the right collation, since coerce_to_target_type doesn't handle
+ * that.
+ */
+ ((Const *) value)->constcollid = partCollation;
+ }
/*
- * Evaluate the expression, assigning the partition key's collation to the
- * resulting Const expression.
+ * Attach original expression's parse location to the Const, so that
+ * that's what will be reported for any later errors related to this
+ * partition bound.
*/
- value = (Node *) evaluate_expr((Expr *) value, colType, colTypmod,
- partCollation);
- if (!IsA(value, Const))
- elog(ERROR, "could not evaluate partition bound expression");
+ ((Const *) value)->location = exprLocation(val);
return (Const *) value;
}