From 7ecb7143589f38d679bb566311dfa9be1a650fd5 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Mon, 27 Mar 2017 10:51:46 -0400 Subject: [PATCH] Fix improper NULL handling in list partitioning code. 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 | 10 +++++++--- src/test/regress/expected/insert.out | 7 +++++++ src/test/regress/sql/insert.sql | 6 ++++++ 3 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/backend/catalog/partition.c b/src/backend/catalog/partition.c index b434c384c9..f9fd1366e2 100644 --- a/src/backend/catalog/partition.c +++ b/src/backend/catalog/partition.c @@ -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; diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out index 116854e142..7fafa98212 100644 --- a/src/test/regress/expected/insert.out +++ b/src/test/regress/expected/insert.out @@ -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); diff --git a/src/test/regress/sql/insert.sql b/src/test/regress/sql/insert.sql index c56c3c22f8..f9c00705a2 100644 --- a/src/test/regress/sql/insert.sql +++ b/src/test/regress/sql/insert.sql @@ -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);