diff options
author | Robert Haas | 2017-03-27 14:37:29 +0000 |
---|---|---|
committer | Robert Haas | 2017-03-27 14:37:41 +0000 |
commit | 8355a011a0124bdf7ccbada206a967d427039553 (patch) | |
tree | 2aa543f244724152d7a692eb694e54ef1455dd1d | |
parent | 3371e4d9b12455fe1f8d1516d0bd915aab86be17 (diff) |
Allow ON CONFLICT .. DO NOTHING on a partitioned table.
ON CONFLICT .. DO UPDATE still doesn't work, for lack of a way of
enforcing uniqueness across partitions, but we can still allow this
case.
Amit Langote, per discussion with Peter Geoghegan. Additional
wordsmithing by me.
Discussion: http://postgr.es/m/CAA-aLv7Z4uygtq-Q5CvDi9Y=VZxUyEnuWjL=EwCfOof=L04hgg@mail.gmail.com
-rw-r--r-- | doc/src/sgml/ddl.sgml | 8 | ||||
-rw-r--r-- | src/backend/parser/analyze.c | 8 | ||||
-rw-r--r-- | src/test/regress/expected/insert_conflict.out | 10 | ||||
-rw-r--r-- | src/test/regress/sql/insert_conflict.sql | 10 |
4 files changed, 26 insertions, 10 deletions
diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 09b5b3ff70..d1e915c11a 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -3854,8 +3854,12 @@ ANALYZE measurement; <listitem> <para> - <command>INSERT</command> statements with <literal>ON CONFLICT</> - clause are currently not allowed on partitioned tables. + Using the <literal>ON CONFLICT</literal> clause with partitioned tables + will cause an error if <literal>DO UPDATE</literal> 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. </para> </listitem> diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 3571e50aea..25699fbc4a 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -842,16 +842,8 @@ 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 8d005fddd4..c90d381b34 100644 --- a/src/test/regress/expected/insert_conflict.out +++ b/src/test/regress/expected/insert_conflict.out @@ -786,3 +786,13 @@ 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 df3a9b59b5..78bffc783d 100644 --- a/src/test/regress/sql/insert_conflict.sql +++ b/src/test/regress/sql/insert_conflict.sql @@ -471,3 +471,13 @@ 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; |