Fix improper NULL handling in list partitioning code.
authorRobert Haas <rhaas@postgresql.org>
Mon, 27 Mar 2017 14:51:46 +0000 (10:51 -0400)
committerRobert Haas <rhaas@postgresql.org>
Mon, 27 Mar 2017 14:51:46 +0000 (10:51 -0400)
The previous logic was wrong when the value was NULL but there was
no partition for NULL.

Amit Langote, reviewed by Jeevan Ladhe

Discussion: http://postgr.es/m/d64f8498-70eb-3c88-b56d-c54fd3b0500f@lab.ntt.co.jp

src/backend/catalog/partition.c
src/test/regress/expected/insert.out
src/test/regress/sql/insert.sql

index b434c384c97aa33fd32ac97b44db3b9a49f2975c..f9fd1366e26adefe8d8bcb6b169b4c74619da838 100644 (file)
@@ -1729,10 +1729,14 @@ get_partition_for_tuple(PartitionDispatch *pd,
                        errmsg("range partition key of row contains null")));
        }
 
-       if (partdesc->boundinfo->has_null && isnull[0])
-           /* Tuple maps to the null-accepting list partition */
+       /*
+        * A null partition key is only acceptable if null-accepting list
+        * partition exists.
+        */
+       cur_index = -1;
+       if (isnull[0] && partdesc->boundinfo->has_null)
            cur_index = partdesc->boundinfo->null_index;
-       else
+       else if (!isnull[0])
        {
            /* Else bsearch in partdesc->boundinfo */
            bool        equal = false;
index 116854e1420838b30c2e2489a1560a4aed951a7d..7fafa982126dda29a1c51aa7144200c0462182fa 100644 (file)
@@ -365,6 +365,13 @@ DETAIL:  Failing row contains (1, 2).
 insert into mlparted1 (a, b) values (2, 3);
 ERROR:  new row for relation "mlparted11" violates partition constraint
 DETAIL:  Failing row contains (3, 2).
+-- check routing error through a list partitioned table when the key is null
+create table lparted_nonullpart (a int, b char) partition by list (b);
+create table lparted_nonullpart_a partition of lparted_nonullpart for values in ('a');
+insert into lparted_nonullpart values (1);
+ERROR:  no partition of relation "lparted_nonullpart" found for row
+DETAIL:  Partition key of the failing row contains (b) = (null).
+drop table lparted_nonullpart;
 -- check that RETURNING works correctly with tuple-routing
 alter table mlparted drop constraint check_b;
 create table mlparted12 partition of mlparted1 for values from (5) to (10);
index c56c3c22f8e5a34fa5c99bac2b262d43820fe4b8..f9c00705a2204086cd4f83e5b09e1f50b9d46f48 100644 (file)
@@ -226,6 +226,12 @@ insert into mlparted values (1, 2);
 -- selected by tuple-routing
 insert into mlparted1 (a, b) values (2, 3);
 
+-- check routing error through a list partitioned table when the key is null
+create table lparted_nonullpart (a int, b char) partition by list (b);
+create table lparted_nonullpart_a partition of lparted_nonullpart for values in ('a');
+insert into lparted_nonullpart values (1);
+drop table lparted_nonullpart;
+
 -- check that RETURNING works correctly with tuple-routing
 alter table mlparted drop constraint check_b;
 create table mlparted12 partition of mlparted1 for values from (5) to (10);