@@ -1255,6 +1255,7 @@ group_similar_or_args(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *rinfo)
1255
1255
ListCell * lc2 ;
1256
1256
List * orargs ;
1257
1257
List * result = NIL ;
1258
+ Index relid = rel -> relid ;
1258
1259
1259
1260
Assert (IsA (rinfo -> orclause , BoolExpr ));
1260
1261
orargs = ((BoolExpr * ) rinfo -> orclause )-> args ;
@@ -1319,10 +1320,13 @@ group_similar_or_args(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *rinfo)
1319
1320
/*
1320
1321
* Check for clauses of the form: (indexkey operator constant) or
1321
1322
* (constant operator indexkey). But we don't know a particular index
1322
- * yet. First check for a constant, which must be Const or Param.
1323
- * That's cheaper than search for an index key among all indexes.
1323
+ * yet. Therefore, we try to distinguish the potential index key and
1324
+ * constant first, then search for a matching index key among all
1325
+ * indexes.
1324
1326
*/
1325
- if (IsA (leftop , Const ) || IsA (leftop , Param ))
1327
+ if (bms_is_member (relid , argrinfo -> right_relids ) &&
1328
+ !bms_is_member (relid , argrinfo -> left_relids ) &&
1329
+ !contain_volatile_functions (leftop ))
1326
1330
{
1327
1331
opno = get_commutator (opno );
1328
1332
@@ -1333,7 +1337,9 @@ group_similar_or_args(PlannerInfo *root, RelOptInfo *rel, RestrictInfo *rinfo)
1333
1337
}
1334
1338
nonConstExpr = rightop ;
1335
1339
}
1336
- else if (IsA (rightop , Const ) || IsA (rightop , Param ))
1340
+ else if (bms_is_member (relid , argrinfo -> left_relids ) &&
1341
+ !bms_is_member (relid , argrinfo -> right_relids ) &&
1342
+ !contain_volatile_functions (rightop ))
1337
1343
{
1338
1344
nonConstExpr = leftop ;
1339
1345
}
@@ -2414,6 +2420,7 @@ match_restriction_clauses_to_index(PlannerInfo *root,
2414
2420
* Identify join clauses for the rel that match the index.
2415
2421
* Matching clauses are added to *clauseset.
2416
2422
* Also, add any potentially usable join OR clauses to *joinorclauses.
2423
+ * They also might be processed by match_clause_to_index() as a whole.
2417
2424
*/
2418
2425
static void
2419
2426
match_join_clauses_to_index (PlannerInfo * root ,
@@ -2432,11 +2439,15 @@ match_join_clauses_to_index(PlannerInfo *root,
2432
2439
if (!join_clause_is_movable_to (rinfo , rel ))
2433
2440
continue ;
2434
2441
2435
- /* Potentially usable, so see if it matches the index or is an OR */
2442
+ /*
2443
+ * Potentially usable, so see if it matches the index or is an OR. Use
2444
+ * list_append_unique_ptr() here to avoid possible duplicates when
2445
+ * processing the same clauses with different indexes.
2446
+ */
2436
2447
if (restriction_is_or_clause (rinfo ))
2437
- * joinorclauses = lappend (* joinorclauses , rinfo );
2438
- else
2439
- match_clause_to_index (root , rinfo , index , clauseset );
2448
+ * joinorclauses = list_append_unique_ptr (* joinorclauses , rinfo );
2449
+
2450
+ match_clause_to_index (root , rinfo , index , clauseset );
2440
2451
}
2441
2452
}
2442
2453
@@ -2585,10 +2596,7 @@ match_clause_to_index(PlannerInfo *root,
2585
2596
* (3) must match the collation of the index, if collation is relevant.
2586
2597
*
2587
2598
* Our definition of "const" is exceedingly liberal: we allow anything that
2588
- * doesn't involve a volatile function or a Var of the index's relation
2589
- * except for a boolean OR expression input: due to a trade-off between the
2590
- * expected execution speedup and planning complexity, we limit or->saop
2591
- * transformation by obvious cases when an index scan can get a profit.
2599
+ * doesn't involve a volatile function or a Var of the index's relation.
2592
2600
* In particular, Vars belonging to other relations of the query are
2593
2601
* accepted here, since a clause of that form can be used in a
2594
2602
* parameterized indexscan. It's the responsibility of higher code levels
@@ -3247,7 +3255,8 @@ match_orclause_to_indexcol(PlannerInfo *root,
3247
3255
Oid arraytype = InvalidOid ;
3248
3256
Oid inputcollid = InvalidOid ;
3249
3257
bool firstTime = true;
3250
- bool haveParam = false;
3258
+ bool haveNonConst = false;
3259
+ Index indexRelid = index -> rel -> relid ;
3251
3260
3252
3261
Assert (IsA (orclause , BoolExpr ));
3253
3262
Assert (orclause -> boolop == OR_EXPR );
@@ -3259,10 +3268,9 @@ match_orclause_to_indexcol(PlannerInfo *root,
3259
3268
/*
3260
3269
* Try to convert a list of OR-clauses to a single SAOP expression. Each
3261
3270
* OR entry must be in the form: (indexkey operator constant) or (constant
3262
- * operator indexkey). Operators of all the entries must match. Constant
3263
- * might be either Const or Param. To be effective, give up on the first
3264
- * non-matching entry. Exit is implemented as a break from the loop,
3265
- * which is catched afterwards.
3271
+ * operator indexkey). Operators of all the entries must match. To be
3272
+ * effective, give up on the first non-matching entry. Exit is
3273
+ * implemented as a break from the loop, which is catched afterwards.
3266
3274
*/
3267
3275
foreach (lc , orclause -> args )
3268
3276
{
@@ -3313,17 +3321,21 @@ match_orclause_to_indexcol(PlannerInfo *root,
3313
3321
3314
3322
/*
3315
3323
* Check for clauses of the form: (indexkey operator constant) or
3316
- * (constant operator indexkey). Determine indexkey side first, check
3317
- * the constant later .
3324
+ * (constant operator indexkey). See match_clause_to_indexcol's notes
3325
+ * about const-ness .
3318
3326
*/
3319
3327
leftop = (Node * ) linitial (subClause -> args );
3320
3328
rightop = (Node * ) lsecond (subClause -> args );
3321
- if (match_index_to_operand (leftop , indexcol , index ))
3329
+ if (match_index_to_operand (leftop , indexcol , index ) &&
3330
+ !bms_is_member (indexRelid , subRinfo -> right_relids ) &&
3331
+ !contain_volatile_functions (rightop ))
3322
3332
{
3323
3333
indexExpr = leftop ;
3324
3334
constExpr = rightop ;
3325
3335
}
3326
- else if (match_index_to_operand (rightop , indexcol , index ))
3336
+ else if (match_index_to_operand (rightop , indexcol , index ) &&
3337
+ !bms_is_member (indexRelid , subRinfo -> left_relids ) &&
3338
+ !contain_volatile_functions (leftop ))
3327
3339
{
3328
3340
opno = get_commutator (opno );
3329
3341
if (!OidIsValid (opno ))
@@ -3350,10 +3362,6 @@ match_orclause_to_indexcol(PlannerInfo *root,
3350
3362
if (IsA (indexExpr , RelabelType ))
3351
3363
indexExpr = (Node * ) ((RelabelType * ) indexExpr )-> arg ;
3352
3364
3353
- /* We allow constant to be Const or Param */
3354
- if (!IsA (constExpr , Const ) && !IsA (constExpr , Param ))
3355
- break ;
3356
-
3357
3365
/* Forbid transformation for composite types, records. */
3358
3366
if (type_is_rowtype (exprType (constExpr )) ||
3359
3367
type_is_rowtype (exprType (indexExpr )))
@@ -3390,8 +3398,12 @@ match_orclause_to_indexcol(PlannerInfo *root,
3390
3398
break ;
3391
3399
}
3392
3400
3393
- if (IsA (constExpr , Param ))
3394
- haveParam = true;
3401
+ /*
3402
+ * Check if our list of constants in match_clause_to_indexcol's
3403
+ * understanding of const-ness have something other than Const.
3404
+ */
3405
+ if (!IsA (constExpr , Const ))
3406
+ haveNonConst = true;
3395
3407
consts = lappend (consts , constExpr );
3396
3408
}
3397
3409
@@ -3408,10 +3420,10 @@ match_orclause_to_indexcol(PlannerInfo *root,
3408
3420
3409
3421
/*
3410
3422
* Assemble an array from the list of constants. It seems more profitable
3411
- * to build a const array. But in the presence of parameters , we don't
3423
+ * to build a const array. But in the presence of other nodes , we don't
3412
3424
* have a specific value here and must employ an ArrayExpr instead.
3413
3425
*/
3414
- if (haveParam )
3426
+ if (haveNonConst )
3415
3427
{
3416
3428
ArrayExpr * arrayExpr = makeNode (ArrayExpr );
3417
3429
0 commit comments