@@ -165,15 +165,13 @@ static List *get_steps_using_prefix(GeneratePruningStepsContext *context,
165
165
bool step_op_is_ne ,
166
166
Expr * step_lastexpr ,
167
167
Oid step_lastcmpfn ,
168
- int step_lastkeyno ,
169
168
Bitmapset * step_nullkeys ,
170
169
List * prefix );
171
170
static List * get_steps_using_prefix_recurse (GeneratePruningStepsContext * context ,
172
171
StrategyNumber step_opstrategy ,
173
172
bool step_op_is_ne ,
174
173
Expr * step_lastexpr ,
175
174
Oid step_lastcmpfn ,
176
- int step_lastkeyno ,
177
175
Bitmapset * step_nullkeys ,
178
176
List * prefix ,
179
177
ListCell * start ,
@@ -1411,7 +1409,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
1411
1409
pc -> op_is_ne ,
1412
1410
pc -> expr ,
1413
1411
pc -> cmpfn ,
1414
- 0 ,
1415
1412
NULL ,
1416
1413
NIL );
1417
1414
opsteps = list_concat (opsteps ,pc_steps );
@@ -1537,7 +1534,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
1537
1534
pc -> op_is_ne ,
1538
1535
pc -> expr ,
1539
1536
pc -> cmpfn ,
1540
- pc -> keyno ,
1541
1537
NULL ,
1542
1538
prefix );
1543
1539
opsteps = list_concat (opsteps ,pc_steps );
@@ -1611,7 +1607,6 @@ gen_prune_steps_from_opexps(GeneratePruningStepsContext *context,
1611
1607
false,
1612
1608
pc -> expr ,
1613
1609
pc -> cmpfn ,
1614
- pc -> keyno ,
1615
1610
nullkeys ,
1616
1611
prefix );
1617
1612
opsteps = list_concat (opsteps ,pc_steps );
@@ -2251,40 +2246,49 @@ match_clause_to_partition_key(GeneratePruningStepsContext *context,
2251
2246
2252
2247
/*
2253
2248
* get_steps_using_prefix
2254
- *Generate list of PartitionPruneStepOp steps each consisting of given
2255
- *opstrategy
2256
- *
2257
- * To generate steps, step_lastexpr and step_lastcmpfn are appended to
2258
- * expressions and cmpfns, respectively, extracted from the clauses in
2259
- * 'prefix'. Actually, since 'prefix' may contain multiple clauses for the
2260
- * same partition key column, we must generate steps for various combinations
2261
- * of the clauses of different keys.
2262
- *
2263
- * For list/range partitioning, callers must ensure that step_nullkeys is
2264
- * NULL, and that prefix contains at least one clause for each of the
2265
- * partition keys earlier than one specified in step_lastkeyno if it's
2266
- * greater than zero. For hash partitioning, step_nullkeys is allowed to be
2267
- * non-NULL, but they must ensure that prefix contains at least one clause
2268
- * for each of the partition keys other than those specified in step_nullkeys
2269
- * and step_lastkeyno.
2270
- *
2271
- * For both cases, callers must also ensure that clauses in prefix are sorted
2272
- * in ascending order of their partition key numbers.
2249
+ *Generate a list of PartitionPruneStepOps based on the given input.
2250
+ *
2251
+ * 'step_lastexpr' and 'step_lastcmpfn' are the Expr and comparison function
2252
+ * belonging to the final partition key that we have a clause for. 'prefix'
2253
+ * is a list of PartClauseInfos for partition key numbers prior to the given
2254
+ * 'step_lastexpr' and 'step_lastcmpfn'. 'prefix' may contain multiple
2255
+ * PartClauseInfos belonging to a single partition key. We will generate a
2256
+ * PartitionPruneStepOp for each combination of the given PartClauseInfos
2257
+ * using, at most, one PartClauseInfo per partition key.
2258
+ *
2259
+ * For LIST and RANGE partitioned tables, callers must ensure that
2260
+ * step_nullkeys is NULL, and that prefix contains at least one clause for
2261
+ * each of the partition keys prior to the key that 'step_lastexpr' and
2262
+ * 'step_lastcmpfn'belong to.
2263
+ *
2264
+ * For HASH partitioned tables, callers must ensure that 'prefix' contains at
2265
+ * least one clause for each of the partition keys apart from the final key
2266
+ * (the expr and comparison function for the final key are in 'step_lastexpr'
2267
+ * and 'step_lastcmpfn'). A bit set in step_nullkeys can substitute clauses
2268
+ * in the 'prefix' list for any given key. If a bit is set in 'step_nullkeys'
2269
+ * for a given key, then there must be no PartClauseInfo for that key in the
2270
+ * 'prefix' list.
2271
+ *
2272
+ * For each of the above cases, callers must ensure that PartClauseInfos in
2273
+ * 'prefix' are sorted in ascending order of keyno.
2273
2274
*/
2274
2275
static List *
2275
2276
get_steps_using_prefix (GeneratePruningStepsContext * context ,
2276
2277
StrategyNumber step_opstrategy ,
2277
2278
bool step_op_is_ne ,
2278
2279
Expr * step_lastexpr ,
2279
2280
Oid step_lastcmpfn ,
2280
- int step_lastkeyno ,
2281
2281
Bitmapset * step_nullkeys ,
2282
2282
List * prefix )
2283
2283
{
2284
+ /* step_nullkeys must be empty for RANGE and LIST partitioned tables */
2284
2285
Assert (step_nullkeys == NULL ||
2285
2286
context -> rel -> part_scheme -> strategy == PARTITION_STRATEGY_HASH );
2286
2287
2287
- /* Quick exit if there are no values to prefix with. */
2288
+ /*
2289
+ * No recursive processing is required when 'prefix' is an empty list. This
2290
+ * occurs when there is only 1 partition key column.
2291
+ */
2288
2292
if (list_length (prefix )== 0 )
2289
2293
{
2290
2294
PartitionPruneStep * step ;
@@ -2298,13 +2302,12 @@ get_steps_using_prefix(GeneratePruningStepsContext *context,
2298
2302
return list_make1 (step );
2299
2303
}
2300
2304
2301
- /* Recurse to generate steps forvarious combinations . */
2305
+ /* Recurse to generate steps forevery combination of clauses . */
2302
2306
return get_steps_using_prefix_recurse (context ,
2303
2307
step_opstrategy ,
2304
2308
step_op_is_ne ,
2305
2309
step_lastexpr ,
2306
2310
step_lastcmpfn ,
2307
- step_lastkeyno ,
2308
2311
step_nullkeys ,
2309
2312
prefix ,
2310
2313
list_head (prefix ),
@@ -2313,13 +2316,17 @@ get_steps_using_prefix(GeneratePruningStepsContext *context,
2313
2316
2314
2317
/*
2315
2318
* get_steps_using_prefix_recurse
2316
- *Recursively generate combinations of clauses for different partition
2317
- *keys and start generating steps upon reaching clauses for the greatest
2318
- *column that is less than the one for which we're currently generating
2319
- *steps (that is, step_lastkeyno)
2319
+ *Generate and return a list of PartitionPruneStepOps using the 'prefix'
2320
+ *list of PartClauseInfos starting at the 'start' cell.
2321
+ *
2322
+ * When 'prefix' contains multiple PartClauseInfos for a single partition key
2323
+ * we create a PartitionPruneStepOp for each combination of duplicated
2324
+ * PartClauseInfos. The returned list will contain a PartitionPruneStepOp
2325
+ * for each unique combination of input PartClauseInfos containing at most one
2326
+ * PartClauseInfo per partition key.
2320
2327
*
2321
- * 'prefix' is the list of PartClauseInfos.
2322
- * 'start'is where we should start iterating for the current invocation .
2328
+ * 'prefix' is theinput list of PartClauseInfos sorted by keyno .
2329
+ * 'start'marks the cell that searching the 'prefix' list should start from .
2323
2330
* 'step_exprs' and 'step_cmpfns' each contains the expressions and cmpfns
2324
2331
* we've generated so far from the clauses for the previous part keys.
2325
2332
*/
@@ -2329,7 +2336,6 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2329
2336
bool step_op_is_ne ,
2330
2337
Expr * step_lastexpr ,
2331
2338
Oid step_lastcmpfn ,
2332
- int step_lastkeyno ,
2333
2339
Bitmapset * step_nullkeys ,
2334
2340
List * prefix ,
2335
2341
ListCell * start ,
@@ -2339,23 +2345,25 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2339
2345
List * result = NIL ;
2340
2346
ListCell * lc ;
2341
2347
int cur_keyno ;
2348
+ int final_keyno ;
2342
2349
2343
2350
/* Actually, recursion would be limited by PARTITION_MAX_KEYS. */
2344
2351
check_stack_depth ();
2345
2352
2346
- /* Check if we need to recurse. */
2347
2353
Assert (start != NULL );
2348
2354
cur_keyno = ((PartClauseInfo * )lfirst (start ))-> keyno ;
2349
- if (cur_keyno < step_lastkeyno - 1 )
2355
+ final_keyno = ((PartClauseInfo * )llast (prefix ))-> keyno ;
2356
+
2357
+ /* Check if we need to recurse. */
2358
+ if (cur_keyno < final_keyno )
2350
2359
{
2351
2360
PartClauseInfo * pc ;
2352
2361
ListCell * next_start ;
2353
2362
2354
2363
/*
2355
- * For each clause with cur_keyno, add its expr and cmpfn to
2356
- * step_exprs and step_cmpfns, respectively, and recurse after setting
2357
- * next_start to the ListCell of the first clause for the next
2358
- * partition key.
2364
+ * Find the first PartClauseInfo belonging to the next partition key, the
2365
+ * next recursive call must start iteration of the prefix list from that
2366
+ * point.
2359
2367
*/
2360
2368
for_each_cell (lc ,prefix ,start )
2361
2369
{
@@ -2364,8 +2372,15 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2364
2372
if (pc -> keyno > cur_keyno )
2365
2373
break ;
2366
2374
}
2375
+
2376
+ /* record where to start iterating in the next recursive call */
2367
2377
next_start = lc ;
2368
2378
2379
+ /*
2380
+ * For each PartClauseInfo with keyno set to cur_keyno, add its expr and
2381
+ * cmpfn to step_exprs and step_cmpfns, respectively, and recurse using
2382
+ * 'next_start' as the starting point in the 'prefix' list.
2383
+ */
2369
2384
for_each_cell (lc ,prefix ,start )
2370
2385
{
2371
2386
List * moresteps ;
@@ -2385,6 +2400,7 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2385
2400
}
2386
2401
else
2387
2402
{
2403
+ /* check the 'prefix' list is sorted correctly */
2388
2404
Assert (pc -> keyno > cur_keyno );
2389
2405
break ;
2390
2406
}
@@ -2394,7 +2410,6 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2394
2410
step_op_is_ne ,
2395
2411
step_lastexpr ,
2396
2412
step_lastcmpfn ,
2397
- step_lastkeyno ,
2398
2413
step_nullkeys ,
2399
2414
prefix ,
2400
2415
next_start ,
@@ -2413,8 +2428,8 @@ get_steps_using_prefix_recurse(GeneratePruningStepsContext *context,
2413
2428
* each clause with cur_keyno, which is all clauses from here onward
2414
2429
* till the end of the list. Note that for hash partitioning,
2415
2430
* step_nullkeys is allowed to be non-empty, in which case step_exprs
2416
- * would only contain expressions for theearlier partition keys that
2417
- *are not specified in step_nullkeys.
2431
+ * would only contain expressions for the partition keys that are not
2432
+ * specified in step_nullkeys.
2418
2433
*/
2419
2434
Assert (list_length (step_exprs )== cur_keyno ||
2420
2435
!bms_is_empty (step_nullkeys ));