From f05230752d53c4aa74cffa9b699983bbb6bcb118 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Fri, 31 Mar 2017 16:47:38 -0400 Subject: [PATCH] Revert "Allow ON CONFLICT .. DO NOTHING on a partitioned table." This reverts commit 8355a011a0124bdf7ccbada206a967d427039553, which turns out to have been a misguided effort. We can't really support this in a partitioning hierarchy after all for exactly the reasons stated in the documentation removed by that commit. It's still possible to use ON CONFLICT .. DO NOTHING (or for that matter ON CONFLICT .. DO UPDATE) on individual partitions if desired, but but to allow this on a partitioned table implies that we have some way of evaluating uniqueness across the whole partitioning hierarchy, which is false. Shinoda Noriyoshi noticed that the old code was crashing (which we could fix, though not in a nice way) and Amit Langote realized that this was indicative of a fundamental problem with the commit being reverted here. Discussion: http://postgr.es/m/ff3dc21d-7204-c09c-50ac-cf11a8c45c81@lab.ntt.co.jp --- doc/src/sgml/ddl.sgml | 8 ++------ src/backend/parser/analyze.c | 8 ++++++++ src/test/regress/expected/insert_conflict.out | 10 ---------- src/test/regress/sql/insert_conflict.sql | 10 ---------- 4 files changed, 10 insertions(+), 26 deletions(-) diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index d1e915c11a..09b5b3ff70 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -3854,12 +3854,8 @@ ANALYZE measurement; - Using the ON CONFLICT clause with partitioned tables - will cause an error if DO UPDATE is specified as the - alternative action, because unique or exclusion constraints can only be - created on individual partitions. There is no support for enforcing - uniqueness (or an exclusion constraint) across an entire partitioning - hierarchy. + INSERT statements with ON CONFLICT + clause are currently not allowed on partitioned tables. diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index f6025225be..8f11c46621 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -842,8 +842,16 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) /* Process ON CONFLICT, if any. */ if (stmt->onConflictClause) + { + /* Bail out if target relation is partitioned table */ + if (pstate->p_target_rangetblentry->relkind == RELKIND_PARTITIONED_TABLE) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("ON CONFLICT clause is not supported with partitioned tables"))); + qry->onConflict = transformOnConflictClause(pstate, stmt->onConflictClause); + } /* * If we have a RETURNING clause, we need to add the target relation to diff --git a/src/test/regress/expected/insert_conflict.out b/src/test/regress/expected/insert_conflict.out index c90d381b34..8d005fddd4 100644 --- a/src/test/regress/expected/insert_conflict.out +++ b/src/test/regress/expected/insert_conflict.out @@ -786,13 +786,3 @@ select * from selfconflict; (3 rows) drop table selfconflict; --- check that the following works: --- insert into partitioned_table on conflict do nothing -create table parted_conflict_test (a int, b char) partition by list (a); -create table parted_conflict_test_1 partition of parted_conflict_test for values in (1); -insert into parted_conflict_test values (1, 'a') on conflict do nothing; -insert into parted_conflict_test values (1, 'a') on conflict do nothing; --- however, on conflict do update not supported yet -insert into parted_conflict_test values (1) on conflict (a) do update set b = excluded.b where excluded.a = 1; -ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification -drop table parted_conflict_test, parted_conflict_test_1; diff --git a/src/test/regress/sql/insert_conflict.sql b/src/test/regress/sql/insert_conflict.sql index 78bffc783d..df3a9b59b5 100644 --- a/src/test/regress/sql/insert_conflict.sql +++ b/src/test/regress/sql/insert_conflict.sql @@ -471,13 +471,3 @@ commit; select * from selfconflict; drop table selfconflict; - --- check that the following works: --- insert into partitioned_table on conflict do nothing -create table parted_conflict_test (a int, b char) partition by list (a); -create table parted_conflict_test_1 partition of parted_conflict_test for values in (1); -insert into parted_conflict_test values (1, 'a') on conflict do nothing; -insert into parted_conflict_test values (1, 'a') on conflict do nothing; --- however, on conflict do update not supported yet -insert into parted_conflict_test values (1) on conflict (a) do update set b = excluded.b where excluded.a = 1; -drop table parted_conflict_test, parted_conflict_test_1; -- 2.40.0