mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
Fix assorted partition pruning bugs
match_clause_to_partition_key failed to consider COERCION_PATH_ARRAYCOERCE cases in scalar-op-array expressions, so it was possible to crash the server easily. To handle this case properly (ie. prune partitions) we would need to run a bit of executor code during planning. Maybe it can be improved, but for now let's just not crash. Add a test case that used to trigger the crash. Author: Michaël Paquier match_clause_to_partition_key failed to indicate that operators that don't have a commutator in a btree opclass are unsupported. It is possible for this to cause a crash later if such an operator is used in a scalar-op-array expression. Add a test case that used to the crash. Author: Amit Langote One caller of gen_partprune_steps_internal in match_clause_to_partition_key was too optimistic about the former never returning an empty step list. Rid it of its innocence. (Having fixed the bug above, I no longer know how to exploit this, so no test case for it, but it remained a bug.) Revise code flow a little bit, for succintness. Author: Álvaro Herrera Reported-by: Marina Polyakova Reviewed-by: Michaël Paquier Reviewed-by: Amit Langote Reviewed-by: Álvaro Herrera Discussion: https://postgr.es/m/ff8f9bfa485ff961d6bb43e54120485b@postgrespro.ru
This commit is contained in:
@ -1073,6 +1073,72 @@ explain (costs off) select * from boolpart where a is not unknown;
|
||||
Filter: (a IS NOT UNKNOWN)
|
||||
(7 rows)
|
||||
|
||||
-- test scalar-to-array operators
|
||||
create table coercepart (a varchar) partition by list (a);
|
||||
create table coercepart_ab partition of coercepart for values in ('ab');
|
||||
create table coercepart_bc partition of coercepart for values in ('bc');
|
||||
create table coercepart_cd partition of coercepart for values in ('cd');
|
||||
explain (costs off) select * from coercepart where a in ('ab', to_char(125, '999'));
|
||||
QUERY PLAN
|
||||
------------------------------------------------------------------------------------------------------------------------------
|
||||
Append
|
||||
-> Seq Scan on coercepart_ab
|
||||
Filter: ((a)::text = ANY ((ARRAY['ab'::character varying, (to_char(125, '999'::text))::character varying])::text[]))
|
||||
-> Seq Scan on coercepart_bc
|
||||
Filter: ((a)::text = ANY ((ARRAY['ab'::character varying, (to_char(125, '999'::text))::character varying])::text[]))
|
||||
-> Seq Scan on coercepart_cd
|
||||
Filter: ((a)::text = ANY ((ARRAY['ab'::character varying, (to_char(125, '999'::text))::character varying])::text[]))
|
||||
(7 rows)
|
||||
|
||||
explain (costs off) select * from coercepart where a ~ any ('{ab}');
|
||||
QUERY PLAN
|
||||
----------------------------------------------------
|
||||
Append
|
||||
-> Seq Scan on coercepart_ab
|
||||
Filter: ((a)::text ~ ANY ('{ab}'::text[]))
|
||||
-> Seq Scan on coercepart_bc
|
||||
Filter: ((a)::text ~ ANY ('{ab}'::text[]))
|
||||
-> Seq Scan on coercepart_cd
|
||||
Filter: ((a)::text ~ ANY ('{ab}'::text[]))
|
||||
(7 rows)
|
||||
|
||||
explain (costs off) select * from coercepart where a !~ all ('{ab}');
|
||||
QUERY PLAN
|
||||
-----------------------------------------------------
|
||||
Append
|
||||
-> Seq Scan on coercepart_ab
|
||||
Filter: ((a)::text !~ ALL ('{ab}'::text[]))
|
||||
-> Seq Scan on coercepart_bc
|
||||
Filter: ((a)::text !~ ALL ('{ab}'::text[]))
|
||||
-> Seq Scan on coercepart_cd
|
||||
Filter: ((a)::text !~ ALL ('{ab}'::text[]))
|
||||
(7 rows)
|
||||
|
||||
explain (costs off) select * from coercepart where a ~ any ('{ab,bc}');
|
||||
QUERY PLAN
|
||||
-------------------------------------------------------
|
||||
Append
|
||||
-> Seq Scan on coercepart_ab
|
||||
Filter: ((a)::text ~ ANY ('{ab,bc}'::text[]))
|
||||
-> Seq Scan on coercepart_bc
|
||||
Filter: ((a)::text ~ ANY ('{ab,bc}'::text[]))
|
||||
-> Seq Scan on coercepart_cd
|
||||
Filter: ((a)::text ~ ANY ('{ab,bc}'::text[]))
|
||||
(7 rows)
|
||||
|
||||
explain (costs off) select * from coercepart where a !~ all ('{ab,bc}');
|
||||
QUERY PLAN
|
||||
--------------------------------------------------------
|
||||
Append
|
||||
-> Seq Scan on coercepart_ab
|
||||
Filter: ((a)::text !~ ALL ('{ab,bc}'::text[]))
|
||||
-> Seq Scan on coercepart_bc
|
||||
Filter: ((a)::text !~ ALL ('{ab,bc}'::text[]))
|
||||
-> Seq Scan on coercepart_cd
|
||||
Filter: ((a)::text !~ ALL ('{ab,bc}'::text[]))
|
||||
(7 rows)
|
||||
|
||||
drop table coercepart;
|
||||
--
|
||||
-- some more cases
|
||||
--
|
||||
|
@ -152,6 +152,20 @@ explain (costs off) select * from boolpart where a is not true and a is not fals
|
||||
explain (costs off) select * from boolpart where a is unknown;
|
||||
explain (costs off) select * from boolpart where a is not unknown;
|
||||
|
||||
-- test scalar-to-array operators
|
||||
create table coercepart (a varchar) partition by list (a);
|
||||
create table coercepart_ab partition of coercepart for values in ('ab');
|
||||
create table coercepart_bc partition of coercepart for values in ('bc');
|
||||
create table coercepart_cd partition of coercepart for values in ('cd');
|
||||
|
||||
explain (costs off) select * from coercepart where a in ('ab', to_char(125, '999'));
|
||||
explain (costs off) select * from coercepart where a ~ any ('{ab}');
|
||||
explain (costs off) select * from coercepart where a !~ all ('{ab}');
|
||||
explain (costs off) select * from coercepart where a ~ any ('{ab,bc}');
|
||||
explain (costs off) select * from coercepart where a !~ all ('{ab,bc}');
|
||||
|
||||
drop table coercepart;
|
||||
|
||||
--
|
||||
-- some more cases
|
||||
--
|
||||
|
Reference in New Issue
Block a user