1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-13 14:22:43 +03:00

Reject opclass options in ON CONFLICT clause

It's as pointless as ASC/DESC and NULLS FIRST/LAST are, so reject all of
them in the same way.  While at it, normalize the others' error messages
to have less translatable strings.  Add tests for these errors.

Noticed while reviewing recent INSERT ON CONFLICT patches.

Author: Álvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Peter Geoghegan <pg@bowt.ie>
Discussion: https://postgr.es/m/202511271516.oiefpvn3z27m@alvherre.pgsql
This commit is contained in:
Álvaro Herrera
2025-12-12 14:26:42 +01:00
parent 493eb0da31
commit 630a93799d
3 changed files with 33 additions and 7 deletions

View File

@@ -3277,24 +3277,32 @@ resolve_unique_index_expr(ParseState *pstate, InferClause *infer,
* Raw grammar re-uses CREATE INDEX infrastructure for unique index * Raw grammar re-uses CREATE INDEX infrastructure for unique index
* inference clause, and so will accept opclasses by name and so on. * inference clause, and so will accept opclasses by name and so on.
* *
* Make no attempt to match ASC or DESC ordering or NULLS FIRST/NULLS * Make no attempt to match ASC or DESC ordering, NULLS FIRST/NULLS
* LAST ordering, since those are not significant for inference * LAST ordering or opclass options, since those are not significant
* purposes (any unique index matching the inference specification in * for inference purposes (any unique index matching the inference
* other regards is accepted indifferently). Actively reject this as * specification in other regards is accepted indifferently). Actively
* wrong-headed. * reject this as wrong-headed.
*/ */
if (ielem->ordering != SORTBY_DEFAULT) if (ielem->ordering != SORTBY_DEFAULT)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE), (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("ASC/DESC is not allowed in ON CONFLICT clause"), errmsg("%s is not allowed in ON CONFLICT clause",
"ASC/DESC"),
parser_errposition(pstate, parser_errposition(pstate,
exprLocation((Node *) infer)))); exprLocation((Node *) infer))));
if (ielem->nulls_ordering != SORTBY_NULLS_DEFAULT) if (ielem->nulls_ordering != SORTBY_NULLS_DEFAULT)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE), (errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("NULLS FIRST/LAST is not allowed in ON CONFLICT clause"), errmsg("%s is not allowed in ON CONFLICT clause",
"NULLS FIRST/LAST"),
parser_errposition(pstate, parser_errposition(pstate,
exprLocation((Node *) infer)))); exprLocation((Node *) infer))));
if (ielem->opclassopts)
ereport(ERROR,
errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
errmsg("operator class options are not allowed in ON CONFLICT clause"),
parser_errposition(pstate,
exprLocation((Node *) infer)));
if (!ielem->expr) if (!ielem->expr)
{ {

View File

@@ -2,6 +2,19 @@
-- insert...on conflict do unique index inference -- insert...on conflict do unique index inference
-- --
create table insertconflicttest(key int4, fruit text); create table insertconflicttest(key int4, fruit text);
-- invalid clauses
insert into insertconflicttest values (1) on conflict (key int4_ops (fillfactor=10)) do nothing;
ERROR: operator class options are not allowed in ON CONFLICT clause
LINE 1: ...rt into insertconflicttest values (1) on conflict (key int4_...
^
insert into insertconflicttest values (1) on conflict (key asc) do nothing;
ERROR: ASC/DESC is not allowed in ON CONFLICT clause
LINE 1: ...rt into insertconflicttest values (1) on conflict (key asc) ...
^
insert into insertconflicttest values (1) on conflict (key nulls last) do nothing;
ERROR: NULLS FIRST/LAST is not allowed in ON CONFLICT clause
LINE 1: ...rt into insertconflicttest values (1) on conflict (key nulls...
^
-- These things should work through a view, as well -- These things should work through a view, as well
create view insertconflictview as select * from insertconflicttest; create view insertconflictview as select * from insertconflicttest;
-- --

View File

@@ -3,6 +3,11 @@
-- --
create table insertconflicttest(key int4, fruit text); create table insertconflicttest(key int4, fruit text);
-- invalid clauses
insert into insertconflicttest values (1) on conflict (key int4_ops (fillfactor=10)) do nothing;
insert into insertconflicttest values (1) on conflict (key asc) do nothing;
insert into insertconflicttest values (1) on conflict (key nulls last) do nothing;
-- These things should work through a view, as well -- These things should work through a view, as well
create view insertconflictview as select * from insertconflicttest; create view insertconflictview as select * from insertconflicttest;