@@ -167,15 +167,13 @@ static List *get_steps_using_prefix(GeneratePruningStepsContext *context,
167
167
bool step_op_is_ne ,
168
168
Expr * step_lastexpr ,
169
169
Oid step_lastcmpfn ,
170
- int step_lastkeyno ,
171
170
Bitmapset * step_nullkeys ,
172
171
List * prefix );
173
172
static List * get_steps_using_prefix_recurse (GeneratePruningStepsContext * context ,
174
173
StrategyNumber step_opstrategy ,
175
174
bool step_op_is_ne ,
176
175
Expr * step_lastexpr ,
177
176
Oid step_lastcmpfn ,
178
- int step_lastkeyno ,
179
177
Bitmapset * step_nullkeys ,
180
178
List * prefix ,
181
179
ListCell * start ,
@@ -1531,7 +1529,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
1531
1529
pc -> op_is_ne ,
1532
1530
pc -> expr ,
1533
1531
pc -> cmpfn ,
1534
- 0 ,
1535
1532
NULL ,
1536
1533
NIL );
1537
1534
opsteps = list_concat (opsteps , pc_steps );
@@ -1657,7 +1654,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
1657
1654
pc -> op_is_ne ,
1658
1655
pc -> expr ,
1659
1656
pc -> cmpfn ,
1660
- pc -> keyno ,
1661
1657
NULL ,
1662
1658
prefix );
1663
1659
opsteps = list_concat (opsteps , pc_steps );
@@ -1731,7 +1727,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
1731
1727
false,
1732
1728
pc -> expr ,
1733
1729
pc -> cmpfn ,
1734
- pc -> keyno ,
1735
1730
nullkeys ,
1736
1731
prefix );
1737
1732
opsteps = list_concat (opsteps , pc_steps );
@@ -2350,40 +2345,49 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
2350
2345
2351
2346
/*
2352
2347
* get_steps_using_prefix
2353
- * Generate list of PartitionPruneStepOp steps each consisting of given
2354
- * opstrategy
2355
- *
2356
- * To generate steps, step_lastexpr and step_lastcmpfn are appended to
2357
- * expressions and cmpfns, respectively, extracted from the clauses in
2358
- * 'prefix'. Actually, since 'prefix' may contain multiple clauses for the
2359
- * same partition key column, we must generate steps for various combinations
2360
- * of the clauses of different keys.
2361
- *
2362
- * For list/range partitioning, callers must ensure that step_nullkeys is
2363
- * NULL, and that prefix contains at least one clause for each of the
2364
- * partition keys earlier than one specified in step_lastkeyno if it's
2365
- * greater than zero. For hash partitioning, step_nullkeys is allowed to be
2366
- * non-NULL, but they must ensure that prefix contains at least one clause
2367
- * for each of the partition keys other than those specified in step_nullkeys
2368
- * and step_lastkeyno.
2369
- *
2370
- * For both cases, callers must also ensure that clauses in prefix are sorted
2371
- * in ascending order of their partition key numbers.
2348
+ * Generate a list of PartitionPruneStepOps based on the given input.
2349
+ *
2350
+ * 'step_lastexpr' and 'step_lastcmpfn' are the Expr and comparison function
2351
+ * belonging to the final partition key that we have a clause for. 'prefix'
2352
+ * is a list of PartClauseInfos for partition key numbers prior to the given
2353
+ * 'step_lastexpr' and 'step_lastcmpfn'. 'prefix' may contain multiple
2354
+ * PartClauseInfos belonging to a single partition key. We will generate a
2355
+ * PartitionPruneStepOp for each combination of the given PartClauseInfos
2356
+ * using, at most, one PartClauseInfo per partition key.
2357
+ *
2358
+ * For LIST and RANGE partitioned tables, callers must ensure that
2359
+ * step_nullkeys is NULL, and that prefix contains at least one clause for
2360
+ * each of the partition keys prior to the key that 'step_lastexpr' and
2361
+ * 'step_lastcmpfn'belong to.
2362
+ *
2363
+ * For HASH partitioned tables, callers must ensure that 'prefix' contains at
2364
+ * least one clause for each of the partition keys apart from the final key
2365
+ * (the expr and comparison function for the final key are in 'step_lastexpr'
2366
+ * and 'step_lastcmpfn'). A bit set in step_nullkeys can substitute clauses
2367
+ * in the 'prefix' list for any given key. If a bit is set in 'step_nullkeys'
2368
+ * for a given key, then there must be no PartClauseInfo for that key in the
2369
+ * 'prefix' list.
2370
+ *
2371
+ * For each of the above cases, callers must ensure that PartClauseInfos in
2372
+ * 'prefix' are sorted in ascending order of keyno.
2372
2373
*/
2373
2374
static List *
2374
2375
get_steps_using_prefix (GeneratePruningStepsContext * context ,
2375
2376
StrategyNumber step_opstrategy ,
2376
2377
bool step_op_is_ne ,
2377
2378
Expr * step_lastexpr ,
2378
2379
Oid step_lastcmpfn ,
2379
- int step_lastkeyno ,
2380
2380
Bitmapset * step_nullkeys ,
2381
2381
List * prefix )
2382
2382
{
2383
+ /* step_nullkeys must be empty for RANGE and LIST partitioned tables */
2383
2384
Assert (step_nullkeys == NULL ||
2384
2385
context -> rel -> part_scheme -> strategy == PARTITION_STRATEGY_HASH );
2385
2386
2386
- /* Quick exit if there are no values to prefix with. */
2387
+ /*
2388
+ * No recursive processing is required when 'prefix' is an empty list.
2389
+ * This occurs when there is only 1 partition key column.
2390
+ */
2387
2391
if (prefix == NIL )
2388
2392
{
2389
2393
PartitionPruneStep * step ;
@@ -2397,13 +2401,12 @@ get_steps_using_prefix(GeneratePruningStepsContext *context,
2397
2401
return list_make1 (step );
2398
2402
}
2399
2403
2400
- /* Recurse to generate steps for various combinations . */
2404
+ /* Recurse to generate steps for every combination of clauses . */
2401
2405
return get_steps_using_prefix_recurse (context ,
2402
2406
step_opstrategy ,
2403
2407
step_op_is_ne ,
2404
2408
step_lastexpr ,
2405
2409
step_lastcmpfn ,
2406
- step_lastkeyno ,
2407
2410
step_nullkeys ,
2408
2411
prefix ,
2409
2412
list_head (prefix ),
@@ -2412,13 +2415,17 @@ get_steps_using_prefix(GeneratePruningStepsContext *context,
2412
2415
2413
2416
/*
2414
2417
* get_steps_using_prefix_recurse
2415
- * Recursively generate combinations of clauses for different partition
2416
- * keys and start generating steps upon reaching clauses for the greatest
2417
- * column that is less than the one for which we're currently generating
2418
- * steps (that is, step_lastkeyno)
2418
+ * Generate and return a list of PartitionPruneStepOps using the 'prefix'
2419
+ * list of PartClauseInfos starting at the 'start' cell.
2420
+ *
2421
+ * When 'prefix' contains multiple PartClauseInfos for a single partition key
2422
+ * we create a PartitionPruneStepOp for each combination of duplicated
2423
+ * PartClauseInfos. The returned list will contain a PartitionPruneStepOp
2424
+ * for each unique combination of input PartClauseInfos containing at most one
2425
+ * PartClauseInfo per partition key.
2419
2426
*
2420
- * 'prefix' is the list of PartClauseInfos.
2421
- * 'start' is where we should start iterating for the current invocation .
2427
+ * 'prefix' is the input list of PartClauseInfos sorted by keyno .
2428
+ * 'start' marks the cell that searching the 'prefix' list should start from .
2422
2429
* 'step_exprs' and 'step_cmpfns' each contains the expressions and cmpfns
2423
2430
* we've generated so far from the clauses for the previous part keys.
2424
2431
*/
@@ -2428,7 +2435,6 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2428
2435
bool step_op_is_ne ,
2429
2436
Expr * step_lastexpr ,
2430
2437
Oid step_lastcmpfn ,
2431
- int step_lastkeyno ,
2432
2438
Bitmapset * step_nullkeys ,
2433
2439
List * prefix ,
2434
2440
ListCell * start ,
@@ -2438,23 +2444,25 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2438
2444
List * result = NIL ;
2439
2445
ListCell * lc ;
2440
2446
int cur_keyno ;
2447
+ int final_keyno ;
2441
2448
2442
2449
/* Actually, recursion would be limited by PARTITION_MAX_KEYS. */
2443
2450
check_stack_depth ();
2444
2451
2445
- /* Check if we need to recurse. */
2446
2452
Assert (start != NULL );
2447
2453
cur_keyno = ((PartClauseInfo * ) lfirst (start ))-> keyno ;
2448
- if (cur_keyno < step_lastkeyno - 1 )
2454
+ final_keyno = ((PartClauseInfo * ) llast (prefix ))-> keyno ;
2455
+
2456
+ /* Check if we need to recurse. */
2457
+ if (cur_keyno < final_keyno )
2449
2458
{
2450
2459
PartClauseInfo * pc ;
2451
2460
ListCell * next_start ;
2452
2461
2453
2462
/*
2454
- * For each clause with cur_keyno, add its expr and cmpfn to
2455
- * step_exprs and step_cmpfns, respectively, and recurse after setting
2456
- * next_start to the ListCell of the first clause for the next
2457
- * partition key.
2463
+ * Find the first PartClauseInfo belonging to the next partition key,
2464
+ * the next recursive call must start iteration of the prefix list
2465
+ * from that point.
2458
2466
*/
2459
2467
for_each_cell (lc , prefix , start )
2460
2468
{
@@ -2463,8 +2471,15 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2463
2471
if (pc -> keyno > cur_keyno )
2464
2472
break ;
2465
2473
}
2474
+
2475
+ /* record where to start iterating in the next recursive call */
2466
2476
next_start = lc ;
2467
2477
2478
+ /*
2479
+ * For each PartClauseInfo with keyno set to cur_keyno, add its expr
2480
+ * and cmpfn to step_exprs and step_cmpfns, respectively, and recurse
2481
+ * using 'next_start' as the starting point in the 'prefix' list.
2482
+ */
2468
2483
for_each_cell (lc , prefix , start )
2469
2484
{
2470
2485
List * moresteps ;
@@ -2484,6 +2499,7 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2484
2499
}
2485
2500
else
2486
2501
{
2502
+ /* check the 'prefix' list is sorted correctly */
2487
2503
Assert (pc -> keyno > cur_keyno );
2488
2504
break ;
2489
2505
}
@@ -2493,7 +2509,6 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2493
2509
step_op_is_ne ,
2494
2510
step_lastexpr ,
2495
2511
step_lastcmpfn ,
2496
- step_lastkeyno ,
2497
2512
step_nullkeys ,
2498
2513
prefix ,
2499
2514
next_start ,
@@ -2512,8 +2527,8 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2512
2527
* each clause with cur_keyno, which is all clauses from here onward
2513
2528
* till the end of the list. Note that for hash partitioning,
2514
2529
* step_nullkeys is allowed to be non-empty, in which case step_exprs
2515
- * would only contain expressions for the earlier partition keys that
2516
- * are not specified in step_nullkeys.
2530
+ * would only contain expressions for the partition keys that are not
2531
+ * specified in step_nullkeys.
2517
2532
*/
2518
2533
Assert (list_length (step_exprs ) == cur_keyno ||
2519
2534
!bms_is_empty (step_nullkeys ));
0 commit comments