@@ -164,16 +164,15 @@ static List *get_steps_using_prefix(GeneratePruningStepsContext *context,
164
164
bool step_op_is_ne ,
165
165
Expr * step_lastexpr ,
166
166
Oid step_lastcmpfn ,
167
- int step_lastkeyno ,
168
167
Bitmapset * step_nullkeys ,
169
168
List * prefix );
170
169
static List * get_steps_using_prefix_recurse (GeneratePruningStepsContext * context ,
171
170
StrategyNumber step_opstrategy ,
172
171
bool step_op_is_ne ,
173
172
Expr * step_lastexpr ,
174
173
Oid step_lastcmpfn ,
175
- int step_lastkeyno ,
176
174
Bitmapset * step_nullkeys ,
175
+ List * prefix ,
177
176
ListCell * start ,
178
177
List * step_exprs ,
179
178
List * step_cmpfns );
@@ -1424,7 +1423,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
1424
1423
pc -> op_is_ne ,
1425
1424
pc -> expr ,
1426
1425
pc -> cmpfn ,
1427
- 0 ,
1428
1426
NULL ,
1429
1427
NIL );
1430
1428
opsteps = list_concat (opsteps ,pc_steps );
@@ -1550,7 +1548,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
1550
1548
pc -> op_is_ne ,
1551
1549
pc -> expr ,
1552
1550
pc -> cmpfn ,
1553
- pc -> keyno ,
1554
1551
NULL ,
1555
1552
prefix );
1556
1553
opsteps = list_concat (opsteps ,pc_steps );
@@ -1624,7 +1621,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
1624
1621
false,
1625
1622
pc -> expr ,
1626
1623
pc -> cmpfn ,
1627
- pc -> keyno ,
1628
1624
nullkeys ,
1629
1625
prefix );
1630
1626
opsteps = list_concat (opsteps ,list_copy (pc_steps ));
@@ -2264,40 +2260,49 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
2264
2260
2265
2261
/*
2266
2262
* get_steps_using_prefix
2267
- *Generate list of PartitionPruneStepOp steps each consisting of given
2268
- *opstrategy
2269
- *
2270
- * To generate steps, step_lastexpr and step_lastcmpfn are appended to
2271
- * expressions and cmpfns, respectively, extracted from the clauses in
2272
- * 'prefix'. Actually, since 'prefix' may contain multiple clauses for the
2273
- * same partition key column, we must generate steps for various combinations
2274
- * of the clauses of different keys.
2275
- *
2276
- * For list/range partitioning, callers must ensure that step_nullkeys is
2277
- * NULL, and that prefix contains at least one clause for each of the
2278
- * partition keys earlier than one specified in step_lastkeyno if it's
2279
- * greater than zero. For hash partitioning, step_nullkeys is allowed to be
2280
- * non-NULL, but they must ensure that prefix contains at least one clause
2281
- * for each of the partition keys other than those specified in step_nullkeys
2282
- * and step_lastkeyno.
2283
- *
2284
- * For both cases, callers must also ensure that clauses in prefix are sorted
2285
- * in ascending order of their partition key numbers.
2263
+ *Generate a list of PartitionPruneStepOps based on the given input.
2264
+ *
2265
+ * 'step_lastexpr' and 'step_lastcmpfn' are the Expr and comparison function
2266
+ * belonging to the final partition key that we have a clause for. 'prefix'
2267
+ * is a list of PartClauseInfos for partition key numbers prior to the given
2268
+ * 'step_lastexpr' and 'step_lastcmpfn'. 'prefix' may contain multiple
2269
+ * PartClauseInfos belonging to a single partition key. We will generate a
2270
+ * PartitionPruneStepOp for each combination of the given PartClauseInfos
2271
+ * using, at most, one PartClauseInfo per partition key.
2272
+ *
2273
+ * For LIST and RANGE partitioned tables, callers must ensure that
2274
+ * step_nullkeys is NULL, and that prefix contains at least one clause for
2275
+ * each of the partition keys prior to the key that 'step_lastexpr' and
2276
+ * 'step_lastcmpfn'belong to.
2277
+ *
2278
+ * For HASH partitioned tables, callers must ensure that 'prefix' contains at
2279
+ * least one clause for each of the partition keys apart from the final key
2280
+ * (the expr and comparison function for the final key are in 'step_lastexpr'
2281
+ * and 'step_lastcmpfn'). A bit set in step_nullkeys can substitute clauses
2282
+ * in the 'prefix' list for any given key. If a bit is set in 'step_nullkeys'
2283
+ * for a given key, then there must be no PartClauseInfo for that key in the
2284
+ * 'prefix' list.
2285
+ *
2286
+ * For each of the above cases, callers must ensure that PartClauseInfos in
2287
+ * 'prefix' are sorted in ascending order of keyno.
2286
2288
*/
2287
2289
static List *
2288
2290
get_steps_using_prefix (GeneratePruningStepsContext * context ,
2289
2291
StrategyNumber step_opstrategy ,
2290
2292
bool step_op_is_ne ,
2291
2293
Expr * step_lastexpr ,
2292
2294
Oid step_lastcmpfn ,
2293
- int step_lastkeyno ,
2294
2295
Bitmapset * step_nullkeys ,
2295
2296
List * prefix )
2296
2297
{
2298
+ /* step_nullkeys must be empty for RANGE and LIST partitioned tables */
2297
2299
Assert (step_nullkeys == NULL ||
2298
2300
context -> rel -> part_scheme -> strategy == PARTITION_STRATEGY_HASH );
2299
2301
2300
- /* Quick exit if there are no values to prefix with. */
2302
+ /*
2303
+ * No recursive processing is required when 'prefix' is an empty list. This
2304
+ * occurs when there is only 1 partition key column.
2305
+ */
2301
2306
if (list_length (prefix )== 0 )
2302
2307
{
2303
2308
PartitionPruneStep * step ;
@@ -2311,26 +2316,31 @@ get_steps_using_prefix(GeneratePruningStepsContext *context,
2311
2316
return list_make1 (step );
2312
2317
}
2313
2318
2314
- /* Recurse to generate steps forvarious combinations . */
2319
+ /* Recurse to generate steps forevery combination of clauses . */
2315
2320
return get_steps_using_prefix_recurse (context ,
2316
2321
step_opstrategy ,
2317
2322
step_op_is_ne ,
2318
2323
step_lastexpr ,
2319
2324
step_lastcmpfn ,
2320
- step_lastkeyno ,
2321
2325
step_nullkeys ,
2326
+ prefix ,
2322
2327
list_head (prefix ),
2323
2328
NIL ,NIL );
2324
2329
}
2325
2330
2326
2331
/*
2327
2332
* get_steps_using_prefix_recurse
2328
- *Recursively generate combinations of clauses for different partition
2329
- *keys and start generating steps upon reaching clauses for the greatest
2330
- *column that is less than the one for which we're currently generating
2331
- *steps (that is, step_lastkeyno)
2333
+ *Generate and return a list of PartitionPruneStepOps using the 'prefix'
2334
+ *list of PartClauseInfos starting at the 'start' cell.
2335
+ *
2336
+ * When 'prefix' contains multiple PartClauseInfos for a single partition key
2337
+ * we create a PartitionPruneStepOp for each combination of duplicated
2338
+ * PartClauseInfos. The returned list will contain a PartitionPruneStepOp
2339
+ * for each unique combination of input PartClauseInfos containing at most one
2340
+ * PartClauseInfo per partition key.
2332
2341
*
2333
- * 'start' is where we should start iterating for the current invocation.
2342
+ * 'prefix' is the input list of PartClauseInfos sorted by keyno.
2343
+ * 'start' marks the cell that searching the 'prefix' list should start from.
2334
2344
* 'step_exprs' and 'step_cmpfns' each contains the expressions and cmpfns
2335
2345
* we've generated so far from the clauses for the previous part keys.
2336
2346
*/
@@ -2340,32 +2350,34 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2340
2350
bool step_op_is_ne ,
2341
2351
Expr * step_lastexpr ,
2342
2352
Oid step_lastcmpfn ,
2343
- int step_lastkeyno ,
2344
2353
Bitmapset * step_nullkeys ,
2354
+ List * prefix ,
2345
2355
ListCell * start ,
2346
2356
List * step_exprs ,
2347
2357
List * step_cmpfns )
2348
2358
{
2349
2359
List * result = NIL ;
2350
2360
ListCell * lc ;
2351
2361
int cur_keyno ;
2362
+ int final_keyno ;
2352
2363
2353
2364
/* Actually, recursion would be limited by PARTITION_MAX_KEYS. */
2354
2365
check_stack_depth ();
2355
2366
2356
- /* Check if we need to recurse. */
2357
2367
Assert (start != NULL );
2358
2368
cur_keyno = ((PartClauseInfo * )lfirst (start ))-> keyno ;
2359
- if (cur_keyno < step_lastkeyno - 1 )
2369
+ final_keyno = ((PartClauseInfo * )llast (prefix ))-> keyno ;
2370
+
2371
+ /* Check if we need to recurse. */
2372
+ if (cur_keyno < final_keyno )
2360
2373
{
2361
2374
PartClauseInfo * pc ;
2362
2375
ListCell * next_start ;
2363
2376
2364
2377
/*
2365
- * For each clause with cur_keyno, add its expr and cmpfn to
2366
- * step_exprs and step_cmpfns, respectively, and recurse after setting
2367
- * next_start to the ListCell of the first clause for the next
2368
- * partition key.
2378
+ * Find the first PartClauseInfo belonging to the next partition key, the
2379
+ * next recursive call must start iteration of the prefix list from that
2380
+ * point.
2369
2381
*/
2370
2382
for_each_cell (lc ,start )
2371
2383
{
@@ -2374,8 +2386,15 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2374
2386
if (pc -> keyno > cur_keyno )
2375
2387
break ;
2376
2388
}
2389
+
2390
+ /* record where to start iterating in the next recursive call */
2377
2391
next_start = lc ;
2378
2392
2393
+ /*
2394
+ * For each PartClauseInfo with keyno set to cur_keyno, add its expr and
2395
+ * cmpfn to step_exprs and step_cmpfns, respectively, and recurse using
2396
+ * 'next_start' as the starting point in the 'prefix' list.
2397
+ */
2379
2398
for_each_cell (lc ,start )
2380
2399
{
2381
2400
List * moresteps ;
@@ -2395,6 +2414,7 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2395
2414
}
2396
2415
else
2397
2416
{
2417
+ /* check the 'prefix' list is sorted correctly */
2398
2418
Assert (pc -> keyno > cur_keyno );
2399
2419
break ;
2400
2420
}
@@ -2404,8 +2424,8 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2404
2424
step_op_is_ne ,
2405
2425
step_lastexpr ,
2406
2426
step_lastcmpfn ,
2407
- step_lastkeyno ,
2408
2427
step_nullkeys ,
2428
+ prefix ,
2409
2429
next_start ,
2410
2430
step_exprs1 ,
2411
2431
step_cmpfns1 );
@@ -2422,8 +2442,8 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2422
2442
* each clause with cur_keyno, which is all clauses from here onward
2423
2443
* till the end of the list. Note that for hash partitioning,
2424
2444
* step_nullkeys is allowed to be non-empty, in which case step_exprs
2425
- * would only contain expressions for theearlier partition keys that
2426
- *are not specified in step_nullkeys.
2445
+ * would only contain expressions for the partition keys that are not
2446
+ * specified in step_nullkeys.
2427
2447
*/
2428
2448
Assert (list_length (step_exprs )== cur_keyno ||
2429
2449
!bms_is_empty (step_nullkeys ));