With commit 4e5fe9ad19, range partition missing handling for the NULLpartition key - Mailing list pgsql-hackers

From Rushabh Lathia
Subject With commit 4e5fe9ad19, range partition missing handling for the NULLpartition key
Date
Msg-id CAGPqQf0Y1iJyk4QJBdMf=pS9i6Q0JUMM_h5-qkR3OMJ-e04PyA@mail.gmail.com
Whole thread Raw
Responses Re: With commit 4e5fe9ad19, range partition missing handling for theNULL partition key  (Amit Langote <Langote_Amit_f8@lab.ntt.co.jp>)
List pgsql-hackers
Consider the below test:

CREATE TABLE range_tab(a int, b int) PARTITION BY RANGE(a);
CREATE TABLE range_tab_p1 PARTITION OF range_tab FOR VALUES FROM (minvalue) TO (10);
CREATE TABLE range_tab_p2 PARTITION OF range_tab FOR VALUES FROM (10) TO (20);
CREATE TABLE range_tab_p3 PARTITION OF range_tab FOR VALUES FROM (20) TO (maxvalue);

INSERT INTO range_tab VALUES(NULL, 10);

Above insert should fail with an error "no partition of relation found for row".

Looking further I found that, this behaviour is changed after below commit:

commit 4e5fe9ad19e14af360de7970caa8b150436c9dec
Author: Robert Haas <rhaas@postgresql.org>
Date:   Wed Nov 15 10:23:28 2017 -0500

    Centralize executor-related partitioning code.
   
    Some code is moved from partition.c, which has grown very quickly lately;
    splitting the executor parts out might help to keep it from getting
    totally out of control.  Other code is moved from execMain.c.  All is
    moved to a new file execPartition.c.  get_partition_for_tuple now has
    a new interface that more clearly separates executor concerns from
    generic concerns.
   
    Amit Langote.  A slight comment tweak by me.

Before above commit insert with NULL partition key in the range partition
was throwing a proper error.

postgres@112171=#INSERT INTO range_tab VALUES(NULL, 10);
ERROR:  no partition of relation "range_tab" found for row
DETAIL:  Partition key of the failing row contains (a) = (null).

Looking at the code partition_bound_cmp(), before 4e5fe9ad19 commit there
was a condition for the null values:

                     /*
                     * No range includes NULL, so this will be accepted by the
                     * default partition if there is one, and otherwise
                     * rejected.
                     */
                    for (i = 0; i < key->partnatts; i++)
                    {
                        if (isnull[i] &&
                            partition_bound_has_default(partdesc->boundinfo))
                        {
                            range_partkey_has_null = true;
                            break;
                        }
                        else if (isnull[i])
                        {
                            *failed_at = parent;
                            *failed_slot = slot;
                            result = -1;
                            goto error_exit;
                        }
                    }

But after commit, condition for isnull is missing.  It doesn't look intentional,
is it?

Attaching patch to fix as well as regression test.

Thanks,
Rushabh Lathia
Attachment

pgsql-hackers by date:

Previous
From: Jing Wang
Date:
Subject: Re: [HACKERS] Support to COMMENT ON DATABASE CURRENT_DATABASE
Next
From: Simon Riggs
Date:
Subject: Re: [HACKERS] Issues with logical replication