Re: Problem, partition pruning for prepared statement with IS NULL clause.
David Rowley <dgrowleyml@gmail.com>
From: David Rowley <dgrowleyml@gmail.com>
To: Sergei Glukhov <s.glukhov@postgrespro.ru>
Cc: pgsql-hackers@lists.postgresql.org
Date: 2023-10-12T12:27:57Z
Lists: pgsql-hackers
On Mon, 9 Oct 2023 at 12:26, David Rowley <dgrowleyml@gmail.com> wrote:
>
> On Sat, 7 Oct 2023 at 03:11, Sergei Glukhov <s.glukhov@postgrespro.ru> wrote:
> > I noticed that combination of prepared statement with generic plan and
> > 'IS NULL' clause could lead partition pruning to crash.
>
> > Test case:
> > ------
> > set plan_cache_mode to force_generic_plan;
> > prepare stmt AS select * from hp where a is null and b = $1;
> > explain execute stmt('xxx');
>
> Thanks for the detailed report and proposed patch.
>
> I think your proposed fix isn't quite correct. I think the problem
> lies in InitPartitionPruneContext() where we assume that the list
> positions of step->exprs are in sync with the keyno. If you look at
> perform_pruning_base_step() the code there makes a special effort to
> skip over any keyno when a bit is set in opstep->nullkeys.
I've now also pushed the fix for the incorrect logic for nullkeys in
ExecInitPruningContext().
I didn't quite find a test to make this work for v11. I tried calling
execute 5 times as we used to have to before the plan_cache_mode GUC
was added in v12, but the test case kept picking the custom plan. So I
ended up pushing v11 without any test. This goes out of support in ~1
month, so I'm not too concerned about the lack of test. I did do a
manual test to ensure it works with:
create table hp (a int, b text, c int) partition by hash (a, b);
create table hp0 partition of hp for values with (modulus 4, remainder 0);
create table hp3 partition of hp for values with (modulus 4, remainder 3);
create table hp1 partition of hp for values with (modulus 4, remainder 1);
create table hp2 partition of hp for values with (modulus 4, remainder 2);
prepare hp_q1 (text) as select * from hp where a is null and b = $1;
(set breakpoint in choose_custom_plan() and have it return false when
we hit it.)
explain (costs off) execute hp_q1('xxx');
David
Commits
-
Fix runtime partition pruning for HASH partitioned tables
- 2759924f33a6 11.22 landed
- 3cc0c25172b2 12.17 landed
- 890a73ba3ac0 13.13 landed
- d26f33c32436 14.10 landed
- 1e81d3e6e0a0 15.5 landed
- 595db9e9cc41 16.1 landed
- d9e46dfb78ab 17.0 landed
-
Fix incorrect step generation in HASH partition pruning
- 07f261b3172d 11.22 landed
- cd259de50ac5 12.17 landed
- 45c4b2a3aa72 13.13 landed
- cd15bff4814b 14.10 landed
- 916adc7c50bb 15.5 landed
- 6352f1627641 16.1 landed
- f0c409d9c7a6 17.0 landed