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

Commit4f26932

Browse files
author
Etsuro Fujita
committed
Fix yet another issue with step generation in partition pruning.
Commit1383874 fixed some issues with step generation in partitionpruning, but there was yet another one: get_steps_using_prefix() assumesthat clauses in the passed-in prefix list are sorted in ascending orderof their partition key numbers, but the caller failed to ensure this forrange partitioning, which led to an assertion failure in debug builds.Adjust the caller function to arrange the clauses in the prefix list inthe required order for range partitioning.Back-patch to v11, like the previous commit.Patch by me, reviewed by Amit Langote.Discussion:https://postgr.es/m/CAPmGK16jkXiFG0YqMbU66wte-oJTfW6D1HaNvQf%3D%2B5o9%3Dm55wQ%40mail.gmail.com
1 parenta2e0cf4 commit4f26932

File tree

3 files changed

+96
-57
lines changed

3 files changed

+96
-57
lines changed

‎src/backend/partitioning/partprune.c‎

Lines changed: 81 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
13751375
List*eq_clauses=btree_clauses[BTEqualStrategyNumber];
13761376
List*le_clauses=btree_clauses[BTLessEqualStrategyNumber];
13771377
List*ge_clauses=btree_clauses[BTGreaterEqualStrategyNumber];
1378-
boolpk_has_clauses[PARTITION_MAX_KEYS];
13791378
intstrat;
13801379

13811380
/*
@@ -1395,10 +1394,15 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
13951394
foreach(lc,btree_clauses[strat])
13961395
{
13971396
PartClauseInfo*pc=lfirst(lc);
1397+
ListCell*eq_start;
1398+
ListCell*le_start;
1399+
ListCell*ge_start;
13981400
ListCell*lc1;
13991401
List*prefix=NIL;
14001402
List*pc_steps;
14011403
boolprefix_valid= true;
1404+
boolpk_has_clauses;
1405+
intkeyno;
14021406

14031407
/*
14041408
* If this is a clause for the first partition key,
@@ -1423,79 +1427,96 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
14231427
continue;
14241428
}
14251429

1426-
/* (Re-)initialize the pk_has_clauses array */
1427-
Assert(pc->keyno>0);
1428-
for (i=0;i<pc->keyno;i++)
1429-
pk_has_clauses[i]= false;
1430+
eq_start=list_head(eq_clauses);
1431+
le_start=list_head(le_clauses);
1432+
ge_start=list_head(ge_clauses);
14301433

14311434
/*
1432-
*Expressions from =clausescan always beinthe
1433-
*prefix, provided they're from an earlierkey.
1435+
*We arrangeclausesinto prefixinascending order
1436+
*of their partitionkey numbers.
14341437
*/
1435-
foreach(lc1,eq_clauses)
1438+
for (keyno=0;keyno<pc->keyno;keyno++)
14361439
{
1437-
PartClauseInfo*eqpc=lfirst(lc1);
1440+
pk_has_clauses= false;
14381441

1439-
if (eqpc->keyno==pc->keyno)
1440-
break;
1441-
if (eqpc->keyno<pc->keyno)
1442+
/*
1443+
* Expressions from = clauses can always be in the
1444+
* prefix, provided they're from an earlier key.
1445+
*/
1446+
for_each_cell(lc1,eq_start)
14421447
{
1443-
prefix=lappend(prefix,eqpc);
1444-
pk_has_clauses[eqpc->keyno]= true;
1445-
}
1446-
}
1448+
PartClauseInfo*eqpc=lfirst(lc1);
14471449

1448-
/*
1449-
* If we're generating steps for </<= strategy, we can
1450-
* add other <= clauses to the prefix, provided
1451-
* they're from an earlier key.
1452-
*/
1453-
if (strat==BTLessStrategyNumber||
1454-
strat==BTLessEqualStrategyNumber)
1455-
{
1456-
foreach(lc1,le_clauses)
1457-
{
1458-
PartClauseInfo*lepc=lfirst(lc1);
1459-
1460-
if (lepc->keyno==pc->keyno)
1450+
if (eqpc->keyno==keyno)
1451+
{
1452+
prefix=lappend(prefix,eqpc);
1453+
pk_has_clauses= true;
1454+
}
1455+
else
1456+
{
1457+
Assert(eqpc->keyno>keyno);
14611458
break;
1462-
if (lepc->keyno<pc->keyno)
1459+
}
1460+
}
1461+
eq_start=lc1;
1462+
1463+
/*
1464+
* If we're generating steps for </<= strategy, we
1465+
* can add other <= clauses to the prefix,
1466+
* provided they're from an earlier key.
1467+
*/
1468+
if (strat==BTLessStrategyNumber||
1469+
strat==BTLessEqualStrategyNumber)
1470+
{
1471+
for_each_cell(lc1,le_start)
14631472
{
1464-
prefix=lappend(prefix,lepc);
1465-
pk_has_clauses[lepc->keyno]= true;
1473+
PartClauseInfo*lepc=lfirst(lc1);
1474+
1475+
if (lepc->keyno==keyno)
1476+
{
1477+
prefix=lappend(prefix,lepc);
1478+
pk_has_clauses= true;
1479+
}
1480+
else
1481+
{
1482+
Assert(lepc->keyno>keyno);
1483+
break;
1484+
}
14661485
}
1486+
le_start=lc1;
14671487
}
1468-
}
14691488

1470-
/*
1471-
* If we're generating steps for >/>= strategy, we can
1472-
* add other >= clauses to the prefix, provided
1473-
* they're from an earlier key.
1474-
*/
1475-
if (strat==BTGreaterStrategyNumber||
1476-
strat==BTGreaterEqualStrategyNumber)
1477-
{
1478-
foreach(lc1,ge_clauses)
1489+
/*
1490+
* If we're generating steps for >/>= strategy, we
1491+
* can add other >= clauses to the prefix,
1492+
* provided they're from an earlier key.
1493+
*/
1494+
if (strat==BTGreaterStrategyNumber||
1495+
strat==BTGreaterEqualStrategyNumber)
14791496
{
1480-
PartClauseInfo*gepc=lfirst(lc1);
1481-
1482-
if (gepc->keyno==pc->keyno)
1483-
break;
1484-
if (gepc->keyno<pc->keyno)
1497+
for_each_cell(lc1,ge_start)
14851498
{
1486-
prefix=lappend(prefix,gepc);
1487-
pk_has_clauses[gepc->keyno]= true;
1499+
PartClauseInfo*gepc=lfirst(lc1);
1500+
1501+
if (gepc->keyno==keyno)
1502+
{
1503+
prefix=lappend(prefix,gepc);
1504+
pk_has_clauses= true;
1505+
}
1506+
else
1507+
{
1508+
Assert(gepc->keyno>keyno);
1509+
break;
1510+
}
14881511
}
1512+
ge_start=lc1;
14891513
}
1490-
}
14911514

1492-
/*
1493-
* Check whether every earlier partition key has at
1494-
* least one clause.
1495-
*/
1496-
for (i=0;i<pc->keyno;i++)
1497-
{
1498-
if (!pk_has_clauses[i])
1515+
/*
1516+
* If this key has no clauses, prefix is not valid
1517+
* anymore.
1518+
*/
1519+
if (!pk_has_clauses)
14991520
{
15001521
prefix_valid= false;
15011522
break;
@@ -2254,6 +2275,9 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
22542275
* non-NULL, but they must ensure that prefix contains at least one clause
22552276
* for each of the partition keys other than those specified in step_nullkeys
22562277
* and step_lastkeyno.
2278+
*
2279+
* For both cases, callers must also ensure that clauses in prefix are sorted
2280+
* in ascending order of their partition key numbers.
22572281
*/
22582282
staticList*
22592283
get_steps_using_prefix(GeneratePruningStepsContext*context,

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3963,6 +3963,16 @@ explain (costs off) select * from rp_prefix_test3 where a >= 1 and b >= 1 and b
39633963
Filter: ((a >= 1) AND (b >= 1) AND (b >= 2) AND (c >= 2) AND (d >= 0))
39643964
(2 rows)
39653965

3966+
-- Test that get_steps_using_prefix() handles a prefix that contains multiple
3967+
-- clauses for the partition key b (ie, b >= 1 and b = 2) (This also tests
3968+
-- that the caller arranges clauses in that prefix in the required order)
3969+
explain (costs off) select * from rp_prefix_test3 where a >= 1 and b >= 1 and b = 2 and c = 2 and d >= 0;
3970+
QUERY PLAN
3971+
------------------------------------------------------------------------
3972+
Seq Scan on rp_prefix_test3_p2
3973+
Filter: ((a >= 1) AND (b >= 1) AND (d >= 0) AND (b = 2) AND (c = 2))
3974+
(2 rows)
3975+
39663976
create table hp_prefix_test (a int, b int, c int, d int) partition by hash (a part_test_int4_ops, b part_test_int4_ops, c part_test_int4_ops, d part_test_int4_ops);
39673977
create table hp_prefix_test_p1 partition of hp_prefix_test for values with (modulus 2, remainder 0);
39683978
create table hp_prefix_test_p2 partition of hp_prefix_test for values with (modulus 2, remainder 1);

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1141,6 +1141,11 @@ create table rp_prefix_test3_p2 partition of rp_prefix_test3 for values from (2,
11411141
-- clauses for the partition key b (ie, b >= 1 and b >= 2)
11421142
explain (costs off)select*from rp_prefix_test3where a>=1and b>=1and b>=2and c>=2and d>=0;
11431143

1144+
-- Test that get_steps_using_prefix() handles a prefix that contains multiple
1145+
-- clauses for the partition key b (ie, b >= 1 and b = 2) (This also tests
1146+
-- that the caller arranges clauses in that prefix in the required order)
1147+
explain (costs off)select*from rp_prefix_test3where a>=1and b>=1and b=2and c=2and d>=0;
1148+
11441149
createtablehp_prefix_test (aint, bint, cint, dint) partition by hash (a part_test_int4_ops, b part_test_int4_ops, c part_test_int4_ops, d part_test_int4_ops);
11451150
createtablehp_prefix_test_p1 partition of hp_prefix_test forvalues with (modulus2, remainder0);
11461151
createtablehp_prefix_test_p2 partition of hp_prefix_test forvalues with (modulus2, remainder1);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp