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