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