From: | David Rowley <dgrowleyml(at)gmail(dot)com> |
---|---|
To: | David Kimura <david(dot)g(dot)kimura(at)gmail(dot)com> |
Cc: | PostgreSQL Development <pgsql-hackers(at)postgresql(dot)org> |
Subject: | Re: Unexpected (wrong?) result querying boolean partitioned table with NULL partition |
Date: | 2023-04-12 11:13:35 |
Message-ID: | CAApHDvpkzuwfDZvLiW2=52y9X7txUxcS2-c7zAyaHzaM0AxwKg@mail.gmail.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
On Wed, 12 Apr 2023 at 22:13, David Kimura <david(dot)g(dot)kimura(at)gmail(dot)com> wrote:
> Is it fair to assume that, given the same data, a partitioned table should
> return the same results as a non-partitioned table?
Yes, and also the same as when enable_partition_pruning is set to off.
> CREATE TABLE boolpart (a bool) PARTITION BY LIST (a);
> CREATE TABLE boolpart_default PARTITION OF boolpart default;
> CREATE TABLE boolpart_t PARTITION OF boolpart FOR VALUES IN ('true');
> CREATE TABLE boolpart_f PARTITION OF boolpart FOR VALUES IN ('false');
> INSERT INTO boolpart VALUES (true), (false), (null);
>
> EXPLAIN SELECT * FROM boolpart WHERE a IS NOT true;
> QUERY PLAN
> -----------------------------------------------------------------------
> Seq Scan on boolpart_f boolpart (cost=0.00..38.10 rows=1405 width=1)
> Filter: (a IS NOT TRUE)
> (2 rows)
>
> SELECT * FROM boolpart WHERE a IS NOT true;
> a
> ---
> f
> (1 row)
>
> Compare that to the result of a non-partitioned table:
>
> CREATE TABLE booltab (a bool);
> INSERT INTO booltab VALUES (true), (false), (null);
>
> EXPLAIN SELECT * FROM booltab WHERE a IS NOT true;
> QUERY PLAN
> -----------------------------------------------------------
> Seq Scan on booltab (cost=0.00..38.10 rows=1405 width=1)
> Filter: (a IS NOT TRUE)
> (2 rows)
>
> SELECT * FROM booltab WHERE a IS NOT true;
> a
> ---
> f
Ouch. That's certainly not correct.
> I think the issue has to do with assumptions made about boolean test IS NOT
> inequality logic which is different from inequality of other operators.
> Specifically, "true IS NOT NULL" is not the same as "true<>NULL".
Yeah, that's wrong.
> One idea is to use the negation operator for IS_NOT_(true|false) (i.e.
> BooleanNotEqualOperator instead of BooleanEqualOperator). But besides
> presumably being a more expensive operation, not equal is not part of the btree
> opfamily for bool_ops. So, seems like that won't really fit into the current
> partition pruning framework.
There's already code to effectively handle <> operators. Just the
PartClauseInfo.op_is_ne needs to be set to true.
get_matching_list_bounds() then handles that by taking the inverse of
the partitions matching the equality operator.
Effectively, I think that's the attached patch.
There seems to be a bunch of tests checking this already, all of them
assuming the incorrect plans.
David
Attachment | Content-Type | Size |
---|---|---|
fix_partprune_handling_of_NOT_TRUE_and_NOT_FALSE_boolean_quals.patch | application/octet-stream | 4.4 KB |
From | Date | Subject | |
---|---|---|---|
Next Message | Amit Kapila | 2023-04-12 11:23:35 | Re: Support logical replication of DDLs |
Previous Message | Hayato Kuroda (Fujitsu) | 2023-04-12 09:48:15 | RE: pg_upgrade and logical replication |