Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit757f1ba

Browse files
committed
Fix RANGE partition pruning with multiple boolean partition keys
match_clause_to_partition_key incorrectly would returnPARTCLAUSE_UNSUPPORTED if a bool qual could not be matched to the currentpartition key. This was a problem, as it causes the calling function todiscard the qual and not try to match it to any other partition key. Ifthere was another partition key which did match this qual, then the qualwould not be checked again and we could fail to prune some partitions.The worst this could do was to cause partitions not to be pruned when theycould have been, so there was no danger of incorrect query results here.Fix this by changing match_boolean_partition_clause to have it return aPartClauseMatchStatus rather than a boolean value. This allows it tocommunicate if the qual is unsupported or if it just does not match thisparticular partition key, previously these two cases were treated thesame. Now, if match_clause_to_partition_key is unable to match the qualto any other qual type then we can simply return the value from thematch_boolean_partition_clause call so that the calling function properlytreats the qual as either unmatched or unsupported.Reported-by: Rares SalcudeanReviewed-by: Amit LangoteBackpatch-through: 11 where partition pruning was introducedDiscussion:https://postgr.es/m/CAHp_FN2xwEznH6oyS0hNTuUUZKp5PvegcVv=Co6nBXJ+mC7Y5w@mail.gmail.com
1 parent5918b82 commit757f1ba

File tree

3 files changed

+62
-15
lines changed

3 files changed

+62
-15
lines changed

‎src/backend/partitioning/partprune.c

Lines changed: 37 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -195,8 +195,10 @@ static PruneStepResult *perform_pruning_base_step(PartitionPruneContext *context
195195
staticPruneStepResult*perform_pruning_combine_step(PartitionPruneContext*context,
196196
PartitionPruneStepCombine*cstep,
197197
PruneStepResult**step_results);
198-
staticboolmatch_boolean_partition_clause(Oidpartopfamily,Expr*clause,
199-
Expr*partkey,Expr**outconst);
198+
staticPartClauseMatchStatusmatch_boolean_partition_clause(Oidpartopfamily,
199+
Expr*clause,
200+
Expr*partkey,
201+
Expr**outconst);
200202
staticvoidpartkey_datum_from_expr(PartitionPruneContext*context,
201203
Expr*expr,intstateidx,
202204
Datum*value,bool*isnull);
@@ -1603,6 +1605,7 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
16031605
bool*clause_is_not_null,PartClauseInfo**pc,
16041606
List**clause_steps)
16051607
{
1608+
PartClauseMatchStatusboolmatchstatus;
16061609
PartitionSchemepart_scheme=context->rel->part_scheme;
16071610
Oidpartopfamily=part_scheme->partopfamily[partkeyidx],
16081611
partcoll=part_scheme->partcollation[partkeyidx];
@@ -1611,7 +1614,10 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
16111614
/*
16121615
* Recognize specially shaped clauses that match a Boolean partition key.
16131616
*/
1614-
if (match_boolean_partition_clause(partopfamily,clause,partkey,&expr))
1617+
boolmatchstatus=match_boolean_partition_clause(partopfamily,clause,
1618+
partkey,&expr);
1619+
1620+
if (boolmatchstatus==PARTCLAUSE_MATCH_CLAUSE)
16151621
{
16161622
PartClauseInfo*partclause;
16171623

@@ -2127,7 +2133,21 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
21272133
returnPARTCLAUSE_MATCH_NULLNESS;
21282134
}
21292135

2130-
returnPARTCLAUSE_UNSUPPORTED;
2136+
/*
2137+
* If we get here then the return value depends on the result of the
2138+
* match_boolean_partition_clause call above. If the call returned
2139+
* PARTCLAUSE_UNSUPPORTED then we're either not dealing with a bool qual
2140+
* or the bool qual is not suitable for pruning. Since the qual didn't
2141+
* match up to any of the other qual types supported here, then trying to
2142+
* match it against any other partition key is a waste of time, so just
2143+
* return PARTCLAUSE_UNSUPPORTED. If the qual just couldn't be matched to
2144+
* this partition key, then it may match another, so return
2145+
* PARTCLAUSE_NOMATCH. The only other value that
2146+
* match_boolean_partition_clause can return is PARTCLAUSE_MATCH_CLAUSE,
2147+
* and since that value was already dealt with above, then we can just
2148+
* return boolmatchstatus.
2149+
*/
2150+
returnboolmatchstatus;
21312151
}
21322152

21332153
/*
@@ -3374,11 +3394,15 @@ perform_pruning_combine_step(PartitionPruneContext *context,
33743394
/*
33753395
* match_boolean_partition_clause
33763396
*
3377-
* Sets *outconst to a Const containing true or false value and returns true if
3378-
* we're able to match the clause to the partition key as specially-shaped
3379-
* Boolean clause. Returns false otherwise with *outconst set to NULL.
3397+
* If we're able to match the clause to the partition key as specially-shaped
3398+
* boolean clause, set *outconst to a Const containing a true or false value
3399+
* and return PARTCLAUSE_MATCH_CLAUSE. Returns PARTCLAUSE_UNSUPPORTED if the
3400+
* clause is not a boolean clause or if the boolean clause is unsuitable for
3401+
* partition pruning. Returns PARTCLAUSE_NOMATCH if it's a bool quals but
3402+
* just does not match this partition key. *outconst is set to NULL in the
3403+
* latter two cases.
33803404
*/
3381-
staticbool
3405+
staticPartClauseMatchStatus
33823406
match_boolean_partition_clause(Oidpartopfamily,Expr*clause,Expr*partkey,
33833407
Expr**outconst)
33843408
{
@@ -3387,7 +3411,7 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
33873411
*outconst=NULL;
33883412

33893413
if (!IsBooleanOpfamily(partopfamily))
3390-
returnfalse;
3414+
returnPARTCLAUSE_UNSUPPORTED;
33913415

33923416
if (IsA(clause,BooleanTest))
33933417
{
@@ -3396,7 +3420,7 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
33963420
/* Only IS [NOT] TRUE/FALSE are any good to us */
33973421
if (btest->booltesttype==IS_UNKNOWN||
33983422
btest->booltesttype==IS_NOT_UNKNOWN)
3399-
returnfalse;
3423+
returnPARTCLAUSE_UNSUPPORTED;
34003424

34013425
leftop=btest->arg;
34023426
if (IsA(leftop,RelabelType))
@@ -3409,7 +3433,7 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
34093433
: (Expr*)makeBoolConst(false, false);
34103434

34113435
if (*outconst)
3412-
returntrue;
3436+
returnPARTCLAUSE_MATCH_CLAUSE;
34133437
}
34143438
else
34153439
{
@@ -3429,10 +3453,10 @@ match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey,
34293453
*outconst= (Expr*)makeBoolConst(false, false);
34303454

34313455
if (*outconst)
3432-
returntrue;
3456+
returnPARTCLAUSE_MATCH_CLAUSE;
34333457
}
34343458

3435-
returnfalse;
3459+
returnPARTCLAUSE_NOMATCH;
34363460
}
34373461

34383462
/*

‎src/test/regress/expected/partition_prune.out

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1114,6 +1114,20 @@ explain (costs off) select * from boolpart where a is not unknown;
11141114
Filter: (a IS NOT UNKNOWN)
11151115
(7 rows)
11161116

1117+
create table boolrangep (a bool, b bool, c int) partition by range (a,b,c);
1118+
create table boolrangep_tf partition of boolrangep for values from ('true', 'false', 0) to ('true', 'false', 100);
1119+
create table boolrangep_ft partition of boolrangep for values from ('false', 'true', 0) to ('false', 'true', 100);
1120+
create table boolrangep_ff1 partition of boolrangep for values from ('false', 'false', 0) to ('false', 'false', 50);
1121+
create table boolrangep_ff2 partition of boolrangep for values from ('false', 'false', 50) to ('false', 'false', 100);
1122+
-- try a more complex case that's been known to trip up pruning in the past
1123+
explain (costs off) select * from boolrangep where not a and not b and c = 25;
1124+
QUERY PLAN
1125+
----------------------------------------------------
1126+
Append
1127+
-> Seq Scan on boolrangep_ff1
1128+
Filter: ((NOT a) AND (NOT b) AND (c = 25))
1129+
(3 rows)
1130+
11171131
-- test scalar-to-array operators
11181132
create table coercepart (a varchar) partition by list (a);
11191133
create table coercepart_ab partition of coercepart for values in ('ab');
@@ -1452,7 +1466,7 @@ explain (costs off) select * from rparted_by_int2 where a > 100000000000000;
14521466
Filter: (a > '100000000000000'::bigint)
14531467
(3 rows)
14541468

1455-
drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
1469+
drop table lp, coll_pruning, rlp, mc3p, mc2p, boolpart,boolrangep,rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
14561470
--
14571471
-- Test Partition pruning for HASH partitioning
14581472
--

‎src/test/regress/sql/partition_prune.sql

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@ explain (costs off) select * from boolpart where a is not true and a is not fals
159159
explain (costs off)select*from boolpartwhere a is unknown;
160160
explain (costs off)select*from boolpartwhere a is not unknown;
161161

162+
createtableboolrangep (a bool, b bool, cint) partition by range (a,b,c);
163+
createtableboolrangep_tf partition of boolrangep forvaluesfrom ('true','false',0) to ('true','false',100);
164+
createtableboolrangep_ft partition of boolrangep forvaluesfrom ('false','true',0) to ('false','true',100);
165+
createtableboolrangep_ff1 partition of boolrangep forvaluesfrom ('false','false',0) to ('false','false',50);
166+
createtableboolrangep_ff2 partition of boolrangep forvaluesfrom ('false','false',50) to ('false','false',100);
167+
168+
-- try a more complex case that's been known to trip up pruning in the past
169+
explain (costs off)select*from boolrangepwhere not aand not band c=25;
170+
162171
-- test scalar-to-array operators
163172
createtablecoercepart (avarchar) partition by list (a);
164173
createtablecoercepart_ab partition of coercepart forvaluesin ('ab');
@@ -264,7 +273,7 @@ create table rparted_by_int2_maxvalue partition of rparted_by_int2 for values fr
264273
-- all partitions but rparted_by_int2_maxvalue pruned
265274
explain (costs off)select*from rparted_by_int2where a>100000000000000;
266275

267-
droptable lp, coll_pruning, rlp, mc3p, mc2p, boolpart, rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
276+
droptable lp, coll_pruning, rlp, mc3p, mc2p, boolpart,boolrangep,rp, coll_pruning_multi, like_op_noprune, lparted_by_int2, rparted_by_int2;
268277

269278
--
270279
-- Test Partition pruning for HASH partitioning

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp