]> granicus.if.org Git - postgresql/commitdiff
Revert "Allow ON CONFLICT .. DO NOTHING on a partitioned table."
authorRobert Haas <rhaas@postgresql.org>
Fri, 31 Mar 2017 20:47:38 +0000 (16:47 -0400)
committerRobert Haas <rhaas@postgresql.org>
Fri, 31 Mar 2017 20:48:21 +0000 (16:48 -0400)
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
src/backend/parser/analyze.c
src/test/regress/expected/insert_conflict.out
src/test/regress/sql/insert_conflict.sql

index d1e915c11aa9ea92daeca57f232734d4e285622c..09b5b3ff70d9ca800e33519d27c284296826b759 100644 (file)
@@ -3854,12 +3854,8 @@ ANALYZE measurement;
 
     <listitem>
      <para>
-      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.
+      <command>INSERT</command> statements with <literal>ON CONFLICT</>
+      clause are currently not allowed on partitioned tables.
      </para>
     </listitem>
 
index f6025225be40b2d2fa6918f16f1219f08cf5f63c..8f11c46621e188c585c89ae826ea4413139c367e 100644 (file)
@@ -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
index c90d381b34f92a452448d33aa291931b6fc9675d..8d005fddd46c4c56840a59ade08d3f71c00c8983 100644 (file)
@@ -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;
index 78bffc783dcc71aa6e37037f6812d3662f1f64f5..df3a9b59b5b0882549c1d9aa70b6330fee2f7064 100644 (file)
@@ -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;