diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/path/clausesel.c | 39 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 241 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 100 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planagg.c | 3 | ||||
-rw-r--r-- | src/backend/optimizer/util/restrictinfo.c | 4 |
5 files changed, 283 insertions, 104 deletions
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index 9a4990898e9..eba6bf1d148 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.75 2005/10/15 02:49:19 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.76 2005/11/25 19:47:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -624,12 +624,45 @@ clause_selectivity(PlannerInfo *root, */ s1 = (Selectivity) 0.5; } - else if (IsA(clause, DistinctExpr) || - IsA(clause, ScalarArrayOpExpr)) + else if (IsA(clause, DistinctExpr)) { /* can we do better? */ s1 = (Selectivity) 0.5; } + else if (IsA(clause, ScalarArrayOpExpr)) + { + /* First, decide if it's a join clause, same as for OpExpr */ + bool is_join_clause; + + if (varRelid != 0) + { + /* + * If we are considering a nestloop join then all clauses are + * restriction clauses, since we are only interested in the one + * relation. + */ + is_join_clause = false; + } + else + { + /* + * Otherwise, it's a join if there's more than one relation used. + * We can optimize this calculation if an rinfo was passed. + */ + if (rinfo) + is_join_clause = (bms_membership(rinfo->clause_relids) == + BMS_MULTIPLE); + else + is_join_clause = (NumRelids(clause) > 1); + } + + /* Use node specific selectivity calculation function */ + s1 = scalararraysel(root, + (ScalarArrayOpExpr *) clause, + is_join_clause, + varRelid, + jointype); + } else if (IsA(clause, NullTest)) { /* Use node specific selectivity calculation function */ diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 6f3157a23f6..fde89455685 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.193 2005/11/22 18:17:12 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.194 2005/11/25 19:47:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ #include "optimizer/paths.h" #include "optimizer/predtest.h" #include "optimizer/restrictinfo.h" +#include "optimizer/var.h" #include "utils/builtins.h" #include "utils/lsyscache.h" #include "utils/memutils.h" @@ -40,9 +41,6 @@ */ #define DoneMatchingIndexKeys(classes) (classes[0] == InvalidOid) -#define is_indexable_operator(clause,opclass,indexkey_on_left) \ - (indexable_operator(clause,opclass,indexkey_on_left) != InvalidOid) - #define IsBooleanOpclass(opclass) \ ((opclass) == BOOL_BTREE_OPS_OID || (opclass) == BOOL_HASH_OPS_OID) @@ -50,16 +48,18 @@ static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, bool istoplevel, bool isjoininner, - Relids outer_relids); + Relids outer_relids, + SaOpControl saop_control); static Path *choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths); static int bitmap_path_comparator(const void *a, const void *b); static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths); static bool match_clause_to_indexcol(IndexOptInfo *index, int indexcol, Oid opclass, RestrictInfo *rinfo, - Relids outer_relids); -static Oid indexable_operator(Expr *clause, Oid opclass, - bool indexkey_on_left); + Relids outer_relids, + SaOpControl saop_control); +static bool is_indexable_operator(Oid expr_op, Oid opclass, + bool indexkey_on_left); static Relids indexable_outerrelids(RelOptInfo *rel); static bool matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids); @@ -150,7 +150,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) */ indexpaths = find_usable_indexes(root, rel, rel->baserestrictinfo, NIL, - true, false, NULL); + true, false, NULL, SAOP_FORBID); /* * We can submit them all to add_path. (This generates access paths for @@ -228,6 +228,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) * given clauses are join clauses) * 'outer_relids' identifies the outer side of the join (pass NULL * if not isjoininner) + * 'saop_control' indicates whether ScalarArrayOpExpr clauses can be used * * Note: check_partial_indexes() must have been run previously. *---------- @@ -236,7 +237,8 @@ static List * find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, bool istoplevel, bool isjoininner, - Relids outer_relids) + Relids outer_relids, + SaOpControl saop_control) { List *result = NIL; List *all_clauses = NIL; /* not computed till needed */ @@ -267,6 +269,10 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, * predOK index to an arm of an OR, which would be a legal but * pointlessly inefficient plan. (A better plan will be generated by * just scanning the predOK index alone, no OR.) + * + * If saop_control is SAOP_REQUIRE and istoplevel is false, the caller + * is only interested in indexquals involving ScalarArrayOps, so don't + * set useful_predicate to true. */ useful_predicate = false; if (index->indpred != NIL) @@ -292,7 +298,8 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, if (!predicate_implied_by(index->indpred, all_clauses)) continue; /* can't use it at all */ - if (!predicate_implied_by(index->indpred, outer_clauses)) + if (saop_control != SAOP_REQUIRE && + !predicate_implied_by(index->indpred, outer_clauses)) useful_predicate = true; } } @@ -300,12 +307,14 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, /* * 1. Match the index against the available restriction clauses. * found_clause is set true only if at least one of the current - * clauses was used. + * clauses was used (and, if saop_control is SAOP_REQUIRE, it + * has to have been a ScalarArrayOpExpr clause). */ restrictclauses = group_clauses_by_indexkey(index, clauses, outer_clauses, outer_relids, + saop_control, &found_clause); /* @@ -380,9 +389,9 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, /* * generate_bitmap_or_paths - * Look through the list of clauses to find OR clauses, and generate - * a BitmapOrPath for each one we can handle that way. Return a list - * of the generated BitmapOrPaths. + * Look through the list of clauses to find OR clauses and + * ScalarArrayOpExpr clauses, and generate a BitmapOrPath for each one + * we can handle that way. Return a list of the generated BitmapOrPaths. * * outer_clauses is a list of additional clauses that can be assumed true * for the purpose of generating indexquals, but are not to be searched for @@ -396,6 +405,7 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, { List *result = NIL; List *all_clauses; + bool have_saop = false; ListCell *l; /* @@ -412,9 +422,16 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, ListCell *j; Assert(IsA(rinfo, RestrictInfo)); - /* Ignore RestrictInfos that aren't ORs */ + /* + * In this loop we ignore RestrictInfos that aren't ORs; but take + * note of ScalarArrayOpExpr for later. + */ if (!restriction_is_or_clause(rinfo)) + { + if (IsA(rinfo->clause, ScalarArrayOpExpr)) + have_saop = true; continue; + } /* * We must be able to match at least one index to each of the arms of @@ -436,7 +453,8 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, all_clauses, false, isjoininner, - outer_relids); + outer_relids, + SAOP_ALLOW); /* Recurse in case there are sub-ORs */ indlist = list_concat(indlist, generate_bitmap_or_paths(root, rel, @@ -454,7 +472,8 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, all_clauses, false, isjoininner, - outer_relids); + outer_relids, + SAOP_ALLOW); } /* @@ -486,6 +505,29 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, } } + /* + * If we saw any top-level ScalarArrayOpExpr clauses, see if we can + * generate a bitmap index path that uses those but not any OR clauses. + */ + if (have_saop) + { + List *pathlist; + Path *bitmapqual; + + pathlist = find_usable_indexes(root, rel, + clauses, + outer_clauses, + false, + isjoininner, + outer_relids, + SAOP_REQUIRE); + if (pathlist != NIL) + { + bitmapqual = (Path *) create_bitmap_or_path(root, rel, pathlist); + result = lappend(result, bitmapqual); + } + } + return result; } @@ -526,7 +568,8 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths) * * We also make some effort to detect directly redundant input paths, as * can happen if there are multiple possibly usable indexes. For this we - * look only at plain IndexPath inputs, not at sub-OR clauses. And we + * look only at plain IndexPath and single-element BitmapOrPath inputs + * (the latter can arise in the presence of ScalarArrayOpExpr quals). We * consider an index redundant if all its index conditions were already * used by earlier indexes. (We could use predicate_implied_by to have a * more intelligent, but much more expensive, check --- but in most cases @@ -555,10 +598,17 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths) paths = list_make1(patharray[0]); costsofar = bitmap_and_cost_est(root, rel, paths); + qualsofar = NIL; if (IsA(patharray[0], IndexPath)) qualsofar = list_copy(((IndexPath *) patharray[0])->indexclauses); - else - qualsofar = NIL; + else if (IsA(patharray[0], BitmapOrPath)) + { + List *orquals = ((BitmapOrPath *) patharray[0])->bitmapquals; + + if (list_length(orquals) == 1 && + IsA(linitial(orquals), IndexPath)) + qualsofar = list_copy(((IndexPath *) linitial(orquals))->indexclauses); + } lastcell = list_head(paths); /* for quick deletions */ for (i = 1; i < npaths; i++) @@ -573,6 +623,16 @@ choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths) if (list_difference_ptr(newqual, qualsofar) == NIL) continue; /* redundant */ } + else if (IsA(newpath, BitmapOrPath)) + { + List *orquals = ((BitmapOrPath *) newpath)->bitmapquals; + + if (list_length(orquals) == 1 && + IsA(linitial(orquals), IndexPath)) + newqual = ((IndexPath *) linitial(orquals))->indexclauses; + if (list_difference_ptr(newqual, qualsofar) == NIL) + continue; /* redundant */ + } paths = lappend(paths, newpath); newcost = bitmap_and_cost_est(root, rel, paths); @@ -665,6 +725,10 @@ bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths) * outer_relids determines what Vars will be allowed on the other side * of a possible index qual; see match_clause_to_indexcol(). * + * 'saop_control' indicates whether ScalarArrayOpExpr clauses can be used. + * When it's SAOP_REQUIRE, *found_clause is set TRUE only if we used at least + * one ScalarArrayOpExpr from the current clauses list. + * * If the index has amoptionalkey = false, we give up and return NIL when * there are no restriction clauses matching the first index key. Otherwise, * we return NIL if there are no restriction clauses matching any index key. @@ -682,6 +746,7 @@ List * group_clauses_by_indexkey(IndexOptInfo *index, List *clauses, List *outer_clauses, Relids outer_relids, + SaOpControl saop_control, bool *found_clause) { List *clausegroup_list = NIL; @@ -710,10 +775,13 @@ group_clauses_by_indexkey(IndexOptInfo *index, indexcol, curClass, rinfo, - outer_relids)) + outer_relids, + saop_control)) { clausegroup = list_append_unique_ptr(clausegroup, rinfo); - *found_clause = true; + if (saop_control != SAOP_REQUIRE || + IsA(rinfo->clause, ScalarArrayOpExpr)) + *found_clause = true; } } @@ -727,7 +795,8 @@ group_clauses_by_indexkey(IndexOptInfo *index, indexcol, curClass, rinfo, - outer_relids)) + outer_relids, + saop_control)) { clausegroup = list_append_unique_ptr(clausegroup, rinfo); found_outer_clause = true; @@ -785,6 +854,11 @@ group_clauses_by_indexkey(IndexOptInfo *index, * We do not actually do the commuting here, but we check whether a * suitable commutator operator is available. * + * It is also possible to match ScalarArrayOpExpr clauses to indexes, when + * the clause is of the form "indexkey op ANY (arrayconst)". Since the + * executor can only handle these in the context of bitmap index scans, + * our caller specifies whether to allow these or not. + * * For boolean indexes, it is also possible to match the clause directly * to the indexkey; or perhaps the clause is (NOT indexkey). * @@ -792,6 +866,7 @@ group_clauses_by_indexkey(IndexOptInfo *index, * 'indexcol' is a column number of 'index' (counting from 0). * 'opclass' is the corresponding operator class. * 'rinfo' is the clause to be tested (as a RestrictInfo node). + * 'saop_control' indicates whether ScalarArrayOpExpr clauses can be used. * * Returns true if the clause can be used with this index key. * @@ -803,11 +878,16 @@ match_clause_to_indexcol(IndexOptInfo *index, int indexcol, Oid opclass, RestrictInfo *rinfo, - Relids outer_relids) + Relids outer_relids, + SaOpControl saop_control) { Expr *clause = rinfo->clause; Node *leftop, *rightop; + Relids left_relids; + Relids right_relids; + Oid expr_op; + bool plain_op; /* First check for boolean-index cases. */ if (IsBooleanOpclass(opclass)) @@ -816,12 +896,37 @@ match_clause_to_indexcol(IndexOptInfo *index, return true; } - /* Else clause must be a binary opclause. */ - if (!is_opclause(clause)) - return false; - leftop = get_leftop(clause); - rightop = get_rightop(clause); - if (!leftop || !rightop) + /* + * Clause must be a binary opclause, or possibly a ScalarArrayOpExpr + * (which is always binary, by definition). + */ + if (is_opclause(clause)) + { + leftop = get_leftop(clause); + rightop = get_rightop(clause); + if (!leftop || !rightop) + return false; + left_relids = rinfo->left_relids; + right_relids = rinfo->right_relids; + expr_op = ((OpExpr *) clause)->opno; + plain_op = true; + } + else if (saop_control != SAOP_FORBID && + clause && IsA(clause, ScalarArrayOpExpr)) + { + ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause; + + /* We only accept ANY clauses, not ALL */ + if (!saop->useOr) + return false; + leftop = (Node *) linitial(saop->args); + rightop = (Node *) lsecond(saop->args); + left_relids = NULL; /* not actually needed */ + right_relids = pull_varnos(rightop); + expr_op = saop->opno; + plain_op = false; + } + else return false; /* @@ -829,26 +934,28 @@ match_clause_to_indexcol(IndexOptInfo *index, * (constant operator indexkey). See above notes about const-ness. */ if (match_index_to_operand(leftop, indexcol, index) && - bms_is_subset(rinfo->right_relids, outer_relids) && + bms_is_subset(right_relids, outer_relids) && !contain_volatile_functions(rightop)) { - if (is_indexable_operator(clause, opclass, true)) + if (is_indexable_operator(expr_op, opclass, true)) return true; /* * If we didn't find a member of the index's opclass, see whether it * is a "special" indexable operator. */ - if (match_special_index_operator(clause, opclass, true)) + if (plain_op && + match_special_index_operator(clause, opclass, true)) return true; return false; } - if (match_index_to_operand(rightop, indexcol, index) && - bms_is_subset(rinfo->left_relids, outer_relids) && + if (plain_op && + match_index_to_operand(rightop, indexcol, index) && + bms_is_subset(left_relids, outer_relids) && !contain_volatile_functions(leftop)) { - if (is_indexable_operator(clause, opclass, false)) + if (is_indexable_operator(expr_op, opclass, false)) return true; /* @@ -864,36 +971,26 @@ match_clause_to_indexcol(IndexOptInfo *index, } /* - * indexable_operator - * Does a binary opclause contain an operator matching the index opclass? + * is_indexable_operator + * Does the operator match the specified index opclass? * * If the indexkey is on the right, what we actually want to know * is whether the operator has a commutator operator that matches - * the index's opclass. - * - * Returns the OID of the matching operator, or InvalidOid if no match. - * (Formerly, this routine might return a binary-compatible operator - * rather than the original one, but that kluge is history.) + * the opclass. */ -static Oid -indexable_operator(Expr *clause, Oid opclass, bool indexkey_on_left) +static bool +is_indexable_operator(Oid expr_op, Oid opclass, bool indexkey_on_left) { - Oid expr_op = ((OpExpr *) clause)->opno; - Oid commuted_op; - /* Get the commuted operator if necessary */ - if (indexkey_on_left) - commuted_op = expr_op; - else - commuted_op = get_commutator(expr_op); - if (commuted_op == InvalidOid) - return InvalidOid; + if (!indexkey_on_left) + { + expr_op = get_commutator(expr_op); + if (expr_op == InvalidOid) + return false; + } /* OK if the (commuted) operator is a member of the index's opclass */ - if (op_in_opclass(commuted_op, opclass)) - return expr_op; - - return InvalidOid; + return op_in_opclass(expr_op, opclass); } /**************************************************************************** @@ -1031,7 +1128,8 @@ matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids) indexcol, curClass, rinfo, - outer_relids)) + outer_relids, + SAOP_ALLOW)) return true; indexcol++; @@ -1137,16 +1235,17 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, /* * Find all the index paths that are usable for this join, except for - * stuff involving OR clauses. + * stuff involving OR and ScalarArrayOpExpr clauses. */ indexpaths = find_usable_indexes(root, rel, clause_list, NIL, false, true, - outer_relids); + outer_relids, + SAOP_FORBID); /* - * Generate BitmapOrPaths for any suitable OR-clauses present in the - * clause list. + * Generate BitmapOrPaths for any suitable OR-clauses or ScalarArrayOpExpr + * clauses present in the clause list. */ bitindexpaths = generate_bitmap_or_paths(root, rel, clause_list, NIL, @@ -1384,7 +1483,10 @@ identify_ignorable_ordering_cols(PlannerInfo *root, bool varonleft; bool ispc; - /* We know this clause passed match_clause_to_indexcol */ + /* + * We know this clause passed match_clause_to_indexcol as a + * toplevel clause; so it's not a ScalarArrayOp. + */ /* First check for boolean-index cases. */ if (IsBooleanOpclass(opclass)) @@ -1923,6 +2025,13 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups) } } + /* Next check for ScalarArrayOp cases */ + if (IsA(rinfo->clause, ScalarArrayOpExpr)) + { + resultquals = lappend(resultquals, rinfo); + continue; + } + resultquals = list_concat(resultquals, expand_indexqual_condition(rinfo, curClass)); @@ -2001,7 +2110,7 @@ expand_boolean_index_clause(Node *clause, /* * expand_indexqual_condition --- expand a single indexqual condition - * (other than a boolean-qual case) + * (other than a boolean-qual or ScalarArrayOp case) * * The input is a single RestrictInfo, the output a list of RestrictInfos */ diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 978419842e3..3bd760fda3a 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.203 2005/11/22 18:17:12 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.204 2005/11/25 19:47:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1069,17 +1069,28 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, subindexquals = lappend(subindexquals, make_ands_explicit(subindexqual)); } - plan = (Plan *) make_bitmap_or(subplans); - plan->startup_cost = opath->path.startup_cost; - plan->total_cost = opath->path.total_cost; - plan->plan_rows = - clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples); - plan->plan_width = 0; /* meaningless */ + /* + * In the presence of ScalarArrayOpExpr quals, we might have built + * BitmapOrPaths with just one subpath; don't add an OR step. + */ + if (list_length(subplans) == 1) + { + plan = (Plan *) linitial(subplans); + } + else + { + plan = (Plan *) make_bitmap_or(subplans); + plan->startup_cost = opath->path.startup_cost; + plan->total_cost = opath->path.total_cost; + plan->plan_rows = + clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples); + plan->plan_width = 0; /* meaningless */ + } /* * If there were constant-TRUE subquals, the OR reduces to constant * TRUE. Also, avoid generating one-element ORs, which could happen - * due to redundancy elimination. + * due to redundancy elimination or ScalarArrayOpExpr quals. */ if (const_true_subqual) *qual = NIL; @@ -1531,18 +1542,14 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path, foreach(l, indexquals) { RestrictInfo *rinfo = (RestrictInfo *) lfirst(l); - OpExpr *clause; - OpExpr *newclause; + Expr *clause; + Oid clause_op; Oid opclass; int stratno; Oid stratsubtype; bool recheck; Assert(IsA(rinfo, RestrictInfo)); - clause = (OpExpr *) rinfo->clause; - if (!IsA(clause, OpExpr) || - list_length(clause->args) != 2) - elog(ERROR, "indexqual clause is not binary opclause"); /* * Make a copy that will become the fixed clause. @@ -1551,33 +1558,62 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path, * is a subplan in the arguments of the opclause. So just do a full * copy. */ - newclause = (OpExpr *) copyObject((Node *) clause); + clause = (Expr *) copyObject((Node *) rinfo->clause); - /* - * Check to see if the indexkey is on the right; if so, commute the - * clause. The indexkey should be the side that refers to (only) the - * base relation. - */ - if (!bms_equal(rinfo->left_relids, index->rel->relids)) - CommuteClause(newclause); + if (IsA(clause, OpExpr)) + { + OpExpr *op = (OpExpr *) clause; - /* - * Now, determine which index attribute this is, change the indexkey - * operand as needed, and get the index opclass. - */ - linitial(newclause->args) = - fix_indexqual_operand(linitial(newclause->args), - index, - &opclass); + if (list_length(op->args) != 2) + elog(ERROR, "indexqual clause is not binary opclause"); + + /* + * Check to see if the indexkey is on the right; if so, commute + * the clause. The indexkey should be the side that refers to + * (only) the base relation. + */ + if (!bms_equal(rinfo->left_relids, index->rel->relids)) + CommuteClause(op); + + /* + * Now, determine which index attribute this is, change the + * indexkey operand as needed, and get the index opclass. + */ + linitial(op->args) = fix_indexqual_operand(linitial(op->args), + index, + &opclass); + clause_op = op->opno; + } + else if (IsA(clause, ScalarArrayOpExpr)) + { + ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause; + + /* Never need to commute... */ + + /* + * Now, determine which index attribute this is, change the + * indexkey operand as needed, and get the index opclass. + */ + linitial(saop->args) = fix_indexqual_operand(linitial(saop->args), + index, + &opclass); + clause_op = saop->opno; + } + else + { + elog(ERROR, "unsupported indexqual type: %d", + (int) nodeTag(clause)); + continue; /* keep compiler quiet */ + } - *fixed_indexquals = lappend(*fixed_indexquals, newclause); + *fixed_indexquals = lappend(*fixed_indexquals, clause); /* * Look up the (possibly commuted) operator in the operator class to * get its strategy numbers and the recheck indicator. This also * double-checks that we found an operator matching the index. */ - get_op_opclass_properties(newclause->opno, opclass, + get_op_opclass_properties(clause_op, opclass, &stratno, &stratsubtype, &recheck); *indexstrategy = lappend_int(*indexstrategy, stratno); diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index f3a49b30063..f4a3c605c35 100644 --- a/src/backend/optimizer/plan/planagg.c +++ b/src/backend/optimizer/plan/planagg.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.11 2005/11/22 18:17:13 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.12 2005/11/25 19:47:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -347,6 +347,7 @@ build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info) index->rel->baserestrictinfo, NIL, NULL, + SAOP_FORBID, &found_clause); if (list_length(restrictclauses) < indexcol) diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index dc135ae9b34..a14117032b9 100644 --- a/src/backend/optimizer/util/restrictinfo.c +++ b/src/backend/optimizer/util/restrictinfo.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.44 2005/11/22 18:17:15 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.45 2005/11/25 19:47:49 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -171,7 +171,7 @@ make_restrictinfo_from_bitmapqual(Path *bitmapqual, /* * Avoid generating one-element ORs, which could happen due to - * redundancy elimination. + * redundancy elimination or ScalarArrayOpExpr quals. */ if (list_length(withris) <= 1) result = withris; |