diff options
Diffstat (limited to 'src/backend/optimizer/plan/createplan.c')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 303 |
1 files changed, 126 insertions, 177 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 04024cc493..cec76e3844 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -83,10 +83,8 @@ static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path, Plan *outer_plan, Plan *inner_plan); static Node *replace_nestloop_params(PlannerInfo *root, Node *expr); static Node *replace_nestloop_params_mutator(Node *node, PlannerInfo *root); -static List *fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, - List *indexquals); -static List *fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path, - List *indexorderbys); +static List *fix_indexqual_references(PlannerInfo *root, IndexPath *index_path); +static List *fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path); static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol); static List *get_switched_clauses(List *clauses, Relids outerrelids); static List *order_qual_clauses(PlannerInfo *root, List *clauses); @@ -1082,11 +1080,11 @@ create_indexscan_plan(PlannerInfo *root, bool indexonly) { Scan *scan_plan; + List *indexquals = best_path->indexquals; List *indexorderbys = best_path->indexorderbys; Index baserelid = best_path->path.parent->relid; Oid indexoid = best_path->indexinfo->indexoid; List *qpqual; - List *indexquals; List *stripped_indexquals; List *fixed_indexquals; List *fixed_indexorderbys; @@ -1097,13 +1095,6 @@ create_indexscan_plan(PlannerInfo *root, Assert(best_path->path.parent->rtekind == RTE_RELATION); /* - * We need to flatten the indexquals list-of-sublists, since most of the - * processing below doesn't care which index column each qual is - * associated with. - */ - indexquals = flatten_clausegroups_list(best_path->indexquals); - - /* * Build "stripped" indexquals structure (no RestrictInfos) to pass to * executor as indexqualorig */ @@ -1111,23 +1102,14 @@ create_indexscan_plan(PlannerInfo *root, /* * The executor needs a copy with the indexkey on the left of each clause - * and with index Vars substituted for table ones. Here we use the - * unflattened list so we can conveniently tell which index column each - * clause is for. + * and with index Vars substituted for table ones. */ - fixed_indexquals = fix_indexqual_references(root, best_path, - best_path->indexquals); + fixed_indexquals = fix_indexqual_references(root, best_path); /* * Likewise fix up index attr references in the ORDER BY expressions. */ - fixed_indexorderbys = fix_indexorderby_references(root, best_path, - indexorderbys); - - /* - * Also produce a flat list to become the indexorderbyorig. - */ - indexorderbys = flatten_indexorderbys_list(indexorderbys); + fixed_indexorderbys = fix_indexorderby_references(root, best_path); /* * If this is an innerjoin scan, the indexclauses will contain join @@ -1506,7 +1488,7 @@ create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples); plan->plan_width = 0; /* meaningless */ *qual = get_actual_clauses(ipath->indexclauses); - *indexqual = get_actual_clauses(flatten_clausegroups_list(ipath->indexquals)); + *indexqual = get_actual_clauses(ipath->indexquals); foreach(l, ipath->indexinfo->indpred) { Expr *pred = (Expr *) lfirst(l); @@ -2484,8 +2466,7 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root) * Adjust indexqual clauses to the form the executor's indexqual * machinery needs. * - * We have five tasks here: - * * Flatten the list-of-sublists structure of indexquals into a simple list. + * We have four tasks here: * * Remove RestrictInfo nodes from the input clauses. * * Replace any outer-relation Var or PHV nodes with nestloop Params. * (XXX eventually, that responsibility should go elsewhere?) @@ -2494,140 +2475,128 @@ replace_nestloop_params_mutator(Node *node, PlannerInfo *root) * * If the index key is on the right, commute the clause to put it on the * left. * - * The result is a modified copy of the indexquals list --- the + * The result is a modified copy of the path's indexquals list --- the * original is not changed. Note also that the copy shares no substructure * with the original; this is needed in case there is a subplan in it (we need * two separate copies of the subplan tree, or things will go awry). */ static List * -fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, - List *indexquals) +fix_indexqual_references(PlannerInfo *root, IndexPath *index_path) { IndexOptInfo *index = index_path->indexinfo; List *fixed_indexquals; - ListCell *lc1; - int indexcol; + ListCell *lcc, + *lci; fixed_indexquals = NIL; - /* clausegroups must correspond to index columns */ - Assert(list_length(indexquals) <= index->ncolumns); - - indexcol = 0; - foreach(lc1, indexquals) + forboth(lcc, index_path->indexquals, lci, index_path->indexqualcols) { - List *clausegroup = (List *) lfirst(lc1); - ListCell *lc2; + RestrictInfo *rinfo = (RestrictInfo *) lfirst(lcc); + int indexcol = lfirst_int(lci); + Node *clause; + + Assert(IsA(rinfo, RestrictInfo)); + + /* + * Replace any outer-relation variables with nestloop params. + * + * This also makes a copy of the clause, so it's safe to modify it + * in-place below. + */ + clause = replace_nestloop_params(root, (Node *) rinfo->clause); - foreach(lc2, clausegroup) + if (IsA(clause, OpExpr)) { - RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc2); - Node *clause; + OpExpr *op = (OpExpr *) clause; - Assert(IsA(rinfo, RestrictInfo)); + if (list_length(op->args) != 2) + elog(ERROR, "indexqual clause is not binary opclause"); /* - * Replace any outer-relation variables with nestloop params. - * - * This also makes a copy of the clause, so it's safe to modify it - * in-place below. + * 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. */ - clause = replace_nestloop_params(root, (Node *) rinfo->clause); + if (!bms_equal(rinfo->left_relids, index->rel->relids)) + CommuteOpExpr(op); - if (IsA(clause, OpExpr)) - { - OpExpr *op = (OpExpr *) clause; + /* + * Now replace the indexkey expression with an index Var. + */ + linitial(op->args) = fix_indexqual_operand(linitial(op->args), + index, + indexcol); + } + else if (IsA(clause, RowCompareExpr)) + { + RowCompareExpr *rc = (RowCompareExpr *) clause; + Expr *newrc; + List *indexcolnos; + bool var_on_left; + ListCell *lca, + *lcai; - if (list_length(op->args) != 2) - elog(ERROR, "indexqual clause is not binary opclause"); + /* + * Re-discover which index columns are used in the rowcompare. + */ + newrc = adjust_rowcompare_for_index(rc, + index, + indexcol, + &indexcolnos, + &var_on_left); - /* - * 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)) - CommuteOpExpr(op); + /* + * Trouble if adjust_rowcompare_for_index thought the + * RowCompareExpr didn't match the index as-is; the clause should + * have gone through that routine already. + */ + if (newrc != (Expr *) rc) + elog(ERROR, "inconsistent results from adjust_rowcompare_for_index"); - /* - * Now replace the indexkey expression with an index Var. - */ - linitial(op->args) = fix_indexqual_operand(linitial(op->args), - index, - indexcol); - } - else if (IsA(clause, RowCompareExpr)) - { - RowCompareExpr *rc = (RowCompareExpr *) clause; - Expr *newrc; - List *indexcolnos; - bool var_on_left; - ListCell *lca, - *lci; + /* + * Check to see if the indexkey is on the right; if so, commute + * the clause. + */ + if (!var_on_left) + CommuteRowCompareExpr(rc); - /* - * Re-discover which index columns are used in the rowcompare. - */ - newrc = adjust_rowcompare_for_index(rc, + /* + * Now replace the indexkey expressions with index Vars. + */ + Assert(list_length(rc->largs) == list_length(indexcolnos)); + forboth(lca, rc->largs, lcai, indexcolnos) + { + lfirst(lca) = fix_indexqual_operand(lfirst(lca), index, - indexcol, - &indexcolnos, - &var_on_left); - - /* - * Trouble if adjust_rowcompare_for_index thought the - * RowCompareExpr didn't match the index as-is; the clause - * should have gone through that routine already. - */ - if (newrc != (Expr *) rc) - elog(ERROR, "inconsistent results from adjust_rowcompare_for_index"); - - /* - * Check to see if the indexkey is on the right; if so, - * commute the clause. - */ - if (!var_on_left) - CommuteRowCompareExpr(rc); - - /* - * Now replace the indexkey expressions with index Vars. - */ - Assert(list_length(rc->largs) == list_length(indexcolnos)); - forboth(lca, rc->largs, lci, indexcolnos) - { - lfirst(lca) = fix_indexqual_operand(lfirst(lca), - index, - lfirst_int(lci)); - } + lfirst_int(lcai)); } - else if (IsA(clause, ScalarArrayOpExpr)) - { - ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause; - - /* Never need to commute... */ + } + else if (IsA(clause, ScalarArrayOpExpr)) + { + ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause; - /* Replace the indexkey expression with an index Var. */ - linitial(saop->args) = fix_indexqual_operand(linitial(saop->args), - index, - indexcol); - } - else if (IsA(clause, NullTest)) - { - NullTest *nt = (NullTest *) clause; + /* Never need to commute... */ - /* Replace the indexkey expression with an index Var. */ - nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg, + /* Replace the indexkey expression with an index Var. */ + linitial(saop->args) = fix_indexqual_operand(linitial(saop->args), index, indexcol); - } - else - elog(ERROR, "unsupported indexqual type: %d", - (int) nodeTag(clause)); + } + else if (IsA(clause, NullTest)) + { + NullTest *nt = (NullTest *) clause; - fixed_indexquals = lappend(fixed_indexquals, clause); + /* Replace the indexkey expression with an index Var. */ + nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg, + index, + indexcol); } + else + elog(ERROR, "unsupported indexqual type: %d", + (int) nodeTag(clause)); - indexcol++; + fixed_indexquals = lappend(fixed_indexquals, clause); } return fixed_indexquals; @@ -2645,67 +2614,47 @@ fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, * is allowed for ordering operators. */ static List * -fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path, - List *indexorderbys) +fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path) { IndexOptInfo *index = index_path->indexinfo; List *fixed_indexorderbys; - ListCell *lc1; + ListCell *lcc, + *lci; fixed_indexorderbys = NIL; - foreach(lc1, indexorderbys) + forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols) { - List *percollists = (List *) lfirst(lc1); - ListCell *lc2; - int indexcol; + Node *clause = (Node *) lfirst(lcc); + int indexcol = lfirst_int(lci); - /* percollists must correspond to index columns */ - Assert(list_length(percollists) <= index->ncolumns); + /* + * Replace any outer-relation variables with nestloop params. + * + * This also makes a copy of the clause, so it's safe to modify it + * in-place below. + */ + clause = replace_nestloop_params(root, clause); - indexcol = 0; - foreach(lc2, percollists) + if (IsA(clause, OpExpr)) { - List *percollist = (List *) lfirst(lc2); - - if (percollist != NIL) - { - Node *clause = (Node *) linitial(percollist); - - /* Should have only one clause per index column */ - Assert(list_length(percollist) == 1); - - /* - * Replace any outer-relation variables with nestloop params. - * - * This also makes a copy of the clause, so it's safe to - * modify it in-place below. - */ - clause = replace_nestloop_params(root, clause); - - if (IsA(clause, OpExpr)) - { - OpExpr *op = (OpExpr *) clause; - - if (list_length(op->args) != 2) - elog(ERROR, "indexorderby clause is not binary opclause"); - - /* - * Now replace the indexkey expression with an index Var. - */ - linitial(op->args) = fix_indexqual_operand(linitial(op->args), - index, - indexcol); - } - else - elog(ERROR, "unsupported indexorderby type: %d", - (int) nodeTag(clause)); + OpExpr *op = (OpExpr *) clause; - fixed_indexorderbys = lappend(fixed_indexorderbys, clause); - } + if (list_length(op->args) != 2) + elog(ERROR, "indexorderby clause is not binary opclause"); - indexcol++; + /* + * Now replace the indexkey expression with an index Var. + */ + linitial(op->args) = fix_indexqual_operand(linitial(op->args), + index, + indexcol); } + else + elog(ERROR, "unsupported indexorderby type: %d", + (int) nodeTag(clause)); + + fixed_indexorderbys = lappend(fixed_indexorderbys, clause); } return fixed_indexorderbys; |