Re: Multi-Column List Partitioning - Mailing list pgsql-hackers

From Amit Langote
Subject Re: Multi-Column List Partitioning
Date
Msg-id CA+HiwqFWxRpite4KU3JXnWhOqp7_uYjYai2jYUn6H+1McSEYBQ@mail.gmail.com
Whole thread Raw
In response to Re: Multi-Column List Partitioning  (Amit Langote <amitlangote09@gmail.com>)
Responses Re: Multi-Column List Partitioning
List pgsql-hackers
On Fri, May 21, 2021 at 1:02 PM Amit Langote <amitlangote09@gmail.com> wrote:
> I will now take a look at the patch itself.

Some quick observations:

* I get a lot of instances of the following 2 warnings when compiling
the patched code:

Warning #1:

partprune.c: In function ‘get_matching_list_bounds’:
partprune.c:2731:11: warning: passing argument 5 of
‘partition_list_bsearch’ makes pointer from integer without a cast
[enabled by default]
           nvalues, value, &is_equal);
           ^
In file included from partprune.c:53:0:
../../../src/include/partitioning/partbounds.h:117:12: note: expected
‘Datum *’ but argument is of type ‘Datum’
 extern int partition_list_bsearch(FmgrInfo *partsupfunc,

Warning #2:

partprune.c:2781:12: warning: incompatible integer to pointer
conversion passing 'Datum'
      (aka 'unsigned long') to parameter of type 'Datum *' (aka
'unsigned long *'); take the
      address with & [-Wint-conversion]

          value, &is_equal);

          ^~~~~

          &
../../../src/include/partitioning/partbounds.h:120:32: note: passing
argument to parameter 'value'
      here
  ...int nvalues, Datum *value, bool *is_equal);

* I think this code:

===
        /* Get the only column's name in case we need to output an error */
        if (key->partattrs[0] != 0)
            colname = get_attname(RelationGetRelid(parent),
                                  key->partattrs[0], false);
        else
            colname = deparse_expression((Node *) linitial(partexprs),

deparse_context_for(RelationGetRelationName(parent),

RelationGetRelid(parent)),
                                         false, false);
        /* Need its type data too */
        coltype = get_partition_col_typid(key, 0);
        coltypmod = get_partition_col_typmod(key, 0);
        partcollation = get_partition_col_collation(key, 0);
===

belongs in the new function transformPartitionListBounds that you
added, because without doing so, any errors having to do with
partitioning columns other than the first one will report the first
column's name in the error message:

postgres=# create table foo (a bool, b bool) partition by list (a, b);
CREATE TABLE

-- this is fine!
postgres=# create table foo_true_true partition of foo for values in (1, true);
ERROR:  specified value cannot be cast to type boolean for column "a"
LINE 1: ...able foo_true_true partition of foo for values in (1, true);

-- not this!
postgres=# create table foo_true_true partition of foo for values in (true, 1);
ERROR:  specified value cannot be cast to type boolean for column "a"
LINE 1: ...able foo_true_true partition of foo for values in (true, 1);

* The following prototype of transformPartitionListBounds() means that
all values in a given bound list are analyzed with the first
partitioning column's colname, type, typmod, etc., which is wrong:

+static List *
+transformPartitionListBounds(ParseState *pstate, PartitionBoundSpec *spec,
+                            char *colname, Oid coltype, int32 coltypmod,
+                            Oid partcollation, int partnatts)
+{

An example of wrong behavior because of that:

postgres=# create table foo (a bool, b text) partition by list (a, b);
CREATE TABLE
Time: 3.967 ms
postgres=# create table foo_true_true partition of foo for values in
(true, 'whatever');
ERROR:  invalid input syntax for type boolean: "whatever"
LINE 1: ...o_true_true partition of foo for values in (true, 'whatever'...

"whatever" should've been accepted but because it's checked with a's
type, it is wrongly flagged.

Please take a look at how transformPartitionRangeBound() handles this,
especially how it uses the correct partitioning column's info to
analyze the corresponding bound value expression.

I will continue looking next week.

--
Amit Langote
EDB: http://www.enterprisedb.com



pgsql-hackers by date:

Previous
From: Peter Smith
Date:
Subject: Re: Refactor "mutually exclusive options" error reporting code in parse_subscription_options
Next
From: Andrew Dunstan
Date:
Subject: Re: multi-install PostgresNode fails with older postgres versions