diff options
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 9 | ||||
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 324 | ||||
-rw-r--r-- | src/backend/optimizer/path/joinpath.c | 67 | ||||
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 60 | ||||
-rw-r--r-- | src/backend/optimizer/plan/initsplan.c | 24 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planagg.c | 18 | ||||
-rw-r--r-- | src/backend/optimizer/plan/subselect.c | 6 | ||||
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 10 | ||||
-rw-r--r-- | src/backend/optimizer/util/pathnode.c | 10 | ||||
-rw-r--r-- | src/backend/optimizer/util/plancat.c | 8 | ||||
-rw-r--r-- | src/backend/optimizer/util/predtest.c | 83 | ||||
-rw-r--r-- | src/backend/optimizer/util/restrictinfo.c | 3 |
12 files changed, 364 insertions, 258 deletions
diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 71685643efa..fbcf7d2b5f5 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -54,7 +54,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.170 2006/12/15 18:42:26 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/costsize.c,v 1.171 2006/12/23 00:43:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1258,6 +1258,8 @@ cost_mergejoin(MergePath *path, PlannerInfo *root) Path *outer_path = path->jpath.outerjoinpath; Path *inner_path = path->jpath.innerjoinpath; List *mergeclauses = path->path_mergeclauses; + List *mergefamilies = path->path_mergefamilies; + List *mergestrategies = path->path_mergestrategies; List *outersortkeys = path->outersortkeys; List *innersortkeys = path->innersortkeys; Cost startup_cost = 0; @@ -1347,13 +1349,16 @@ cost_mergejoin(MergePath *path, PlannerInfo *root) * * Since this calculation is somewhat expensive, and will be the same for * all mergejoin paths associated with the merge clause, we cache the - * results in the RestrictInfo node. + * results in the RestrictInfo node. XXX that won't work anymore once + * we support multiple possible orderings! */ if (mergeclauses && path->jpath.jointype != JOIN_FULL) { firstclause = (RestrictInfo *) linitial(mergeclauses); if (firstclause->left_mergescansel < 0) /* not computed yet? */ mergejoinscansel(root, (Node *) firstclause->clause, + linitial_oid(mergefamilies), + linitial_int(mergestrategies), &firstclause->left_mergescansel, &firstclause->right_mergescansel); diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index b15affa54d5..af081b82c8e 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.212 2006/10/04 00:29:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.213 2006/12/23 00:43:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,8 +19,8 @@ #include "access/skey.h" #include "catalog/pg_am.h" -#include "catalog/pg_opclass.h" #include "catalog/pg_operator.h" +#include "catalog/pg_opfamily.h" #include "catalog/pg_type.h" #include "nodes/makefuncs.h" #include "optimizer/clauses.h" @@ -40,10 +40,10 @@ /* * DoneMatchingIndexKeys() - MACRO */ -#define DoneMatchingIndexKeys(classes) (classes[0] == InvalidOid) +#define DoneMatchingIndexKeys(families) (families[0] == InvalidOid) -#define IsBooleanOpclass(opclass) \ - ((opclass) == BOOL_BTREE_OPS_OID || (opclass) == BOOL_HASH_OPS_OID) +#define IsBooleanOpfamily(opfamily) \ + ((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID) static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, @@ -61,15 +61,15 @@ static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, static List *pull_indexpath_quals(Path *bitmapqual); static bool lists_intersect_ptr(List *list1, List *list2); static bool match_clause_to_indexcol(IndexOptInfo *index, - int indexcol, Oid opclass, + int indexcol, Oid opfamily, RestrictInfo *rinfo, Relids outer_relids, SaOpControl saop_control); -static bool is_indexable_operator(Oid expr_op, Oid opclass, +static bool is_indexable_operator(Oid expr_op, Oid opfamily, bool indexkey_on_left); static bool match_rowcompare_to_indexcol(IndexOptInfo *index, int indexcol, - Oid opclass, + Oid opfamily, RowCompareExpr *clause, Relids outer_relids); static Relids indexable_outerrelids(RelOptInfo *rel); @@ -89,17 +89,17 @@ static bool match_index_to_query_keys(PlannerInfo *root, List *ignorables); static bool match_boolean_index_clause(Node *clause, int indexcol, IndexOptInfo *index); -static bool match_special_index_operator(Expr *clause, Oid opclass, +static bool match_special_index_operator(Expr *clause, Oid opfamily, bool indexkey_on_left); static Expr *expand_boolean_index_clause(Node *clause, int indexcol, IndexOptInfo *index); -static List *expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass); +static List *expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily); static RestrictInfo *expand_indexqual_rowcompare(RestrictInfo *rinfo, IndexOptInfo *index, int indexcol); -static List *prefix_quals(Node *leftop, Oid opclass, +static List *prefix_quals(Node *leftop, Oid opfamily, Const *prefix, Pattern_Prefix_Status pstatus); -static List *network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, +static List *network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop); static Datum string_to_datum(const char *str, Oid datatype); static Const *string_to_const(const char *str, Oid datatype); @@ -858,7 +858,7 @@ group_clauses_by_indexkey(IndexOptInfo *index, List *clausegroup_list = NIL; bool found_outer_clause = false; int indexcol = 0; - Oid *classes = index->classlist; + Oid *families = index->opfamily; *found_clause = false; /* default result */ @@ -867,7 +867,7 @@ group_clauses_by_indexkey(IndexOptInfo *index, do { - Oid curClass = classes[0]; + Oid curFamily = families[0]; List *clausegroup = NIL; ListCell *l; @@ -879,7 +879,7 @@ group_clauses_by_indexkey(IndexOptInfo *index, Assert(IsA(rinfo, RestrictInfo)); if (match_clause_to_indexcol(index, indexcol, - curClass, + curFamily, rinfo, outer_relids, saop_control)) @@ -899,7 +899,7 @@ group_clauses_by_indexkey(IndexOptInfo *index, Assert(IsA(rinfo, RestrictInfo)); if (match_clause_to_indexcol(index, indexcol, - curClass, + curFamily, rinfo, outer_relids, saop_control)) @@ -918,9 +918,9 @@ group_clauses_by_indexkey(IndexOptInfo *index, clausegroup_list = lappend(clausegroup_list, clausegroup); indexcol++; - classes++; + families++; - } while (!DoneMatchingIndexKeys(classes)); + } while (!DoneMatchingIndexKeys(families)); if (!*found_clause && !found_outer_clause) return NIL; /* no indexable clauses anywhere */ @@ -937,7 +937,7 @@ group_clauses_by_indexkey(IndexOptInfo *index, * * (1) must be in the form (indexkey op const) or (const op indexkey); * and - * (2) must contain an operator which is in the same class as the index + * (2) must contain an operator which is in the same family as the index * operator for this column, or is a "special" operator as recognized * by match_special_index_operator(). * @@ -978,7 +978,7 @@ group_clauses_by_indexkey(IndexOptInfo *index, * * 'index' is the index of interest. * 'indexcol' is a column number of 'index' (counting from 0). - * 'opclass' is the corresponding operator class. + * 'opfamily' is the corresponding operator family. * 'rinfo' is the clause to be tested (as a RestrictInfo node). * 'saop_control' indicates whether ScalarArrayOpExpr clauses can be used. * @@ -990,7 +990,7 @@ group_clauses_by_indexkey(IndexOptInfo *index, static bool match_clause_to_indexcol(IndexOptInfo *index, int indexcol, - Oid opclass, + Oid opfamily, RestrictInfo *rinfo, Relids outer_relids, SaOpControl saop_control) @@ -1013,7 +1013,7 @@ match_clause_to_indexcol(IndexOptInfo *index, return false; /* First check for boolean-index cases. */ - if (IsBooleanOpclass(opclass)) + if (IsBooleanOpfamily(opfamily)) { if (match_boolean_index_clause((Node *) clause, indexcol, index)) return true; @@ -1052,7 +1052,7 @@ match_clause_to_indexcol(IndexOptInfo *index, } else if (clause && IsA(clause, RowCompareExpr)) { - return match_rowcompare_to_indexcol(index, indexcol, opclass, + return match_rowcompare_to_indexcol(index, indexcol, opfamily, (RowCompareExpr *) clause, outer_relids); } @@ -1067,15 +1067,15 @@ match_clause_to_indexcol(IndexOptInfo *index, bms_is_subset(right_relids, outer_relids) && !contain_volatile_functions(rightop)) { - if (is_indexable_operator(expr_op, opclass, true)) + if (is_indexable_operator(expr_op, opfamily, true)) return true; /* - * If we didn't find a member of the index's opclass, see whether it + * If we didn't find a member of the index's opfamily, see whether it * is a "special" indexable operator. */ if (plain_op && - match_special_index_operator(clause, opclass, true)) + match_special_index_operator(clause, opfamily, true)) return true; return false; } @@ -1085,14 +1085,14 @@ match_clause_to_indexcol(IndexOptInfo *index, bms_is_subset(left_relids, outer_relids) && !contain_volatile_functions(leftop)) { - if (is_indexable_operator(expr_op, opclass, false)) + if (is_indexable_operator(expr_op, opfamily, false)) return true; /* - * If we didn't find a member of the index's opclass, see whether it + * If we didn't find a member of the index's opfamily, see whether it * is a "special" indexable operator. */ - if (match_special_index_operator(clause, opclass, false)) + if (match_special_index_operator(clause, opfamily, false)) return true; return false; } @@ -1102,14 +1102,14 @@ match_clause_to_indexcol(IndexOptInfo *index, /* * is_indexable_operator - * Does the operator match the specified index opclass? + * Does the operator match the specified index opfamily? * * If the indexkey is on the right, what we actually want to know * is whether the operator has a commutator operator that matches - * the opclass. + * the opfamily. */ static bool -is_indexable_operator(Oid expr_op, Oid opclass, bool indexkey_on_left) +is_indexable_operator(Oid expr_op, Oid opfamily, bool indexkey_on_left) { /* Get the commuted operator if necessary */ if (!indexkey_on_left) @@ -1119,8 +1119,8 @@ is_indexable_operator(Oid expr_op, Oid opclass, bool indexkey_on_left) return false; } - /* OK if the (commuted) operator is a member of the index's opclass */ - return op_in_opclass(expr_op, opclass); + /* OK if the (commuted) operator is a member of the index's opfamily */ + return op_in_opfamily(expr_op, opfamily); } /* @@ -1131,7 +1131,7 @@ is_indexable_operator(Oid expr_op, Oid opclass, bool indexkey_on_left) static bool match_rowcompare_to_indexcol(IndexOptInfo *index, int indexcol, - Oid opclass, + Oid opfamily, RowCompareExpr *clause, Relids outer_relids) { @@ -1144,13 +1144,14 @@ match_rowcompare_to_indexcol(IndexOptInfo *index, return false; /* - * We could do the matching on the basis of insisting that the opclass - * shown in the RowCompareExpr be the same as the index column's opclass, - * but that does not work well for cross-type comparisons (the opclass - * could be for the other datatype). Also it would fail to handle indexes - * using reverse-sort opclasses. Instead, match if the operator listed in - * the RowCompareExpr is the < <= > or >= member of the index opclass - * (after commutation, if the indexkey is on the right). + * We could do the matching on the basis of insisting that the opfamily + * shown in the RowCompareExpr be the same as the index column's opfamily, + * but that could fail in the presence of reverse-sort opfamilies: it'd + * be a matter of chance whether RowCompareExpr had picked the forward + * or reverse-sort family. So look only at the operator, and match + * if it is a member of the index's opfamily (after commutation, if the + * indexkey is on the right). We'll worry later about whether any + * additional operators are matchable to the index. */ leftop = (Node *) linitial(clause->largs); rightop = (Node *) linitial(clause->rargs); @@ -1177,8 +1178,8 @@ match_rowcompare_to_indexcol(IndexOptInfo *index, else return false; - /* We're good if the operator is the right type of opclass member */ - switch (get_op_opclass_strategy(expr_op, opclass)) + /* We're good if the operator is the right type of opfamily member */ + switch (get_op_opfamily_strategy(expr_op, opfamily)) { case BTLessStrategyNumber: case BTLessEqualStrategyNumber: @@ -1316,23 +1317,23 @@ matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids) { IndexOptInfo *index = (IndexOptInfo *) lfirst(l); int indexcol = 0; - Oid *classes = index->classlist; + Oid *families = index->opfamily; do { - Oid curClass = classes[0]; + Oid curFamily = families[0]; if (match_clause_to_indexcol(index, indexcol, - curClass, + curFamily, rinfo, outer_relids, SAOP_ALLOW)) return true; indexcol++; - classes++; - } while (!DoneMatchingIndexKeys(classes)); + families++; + } while (!DoneMatchingIndexKeys(families)); } return false; @@ -1601,11 +1602,11 @@ find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel, * Note: it would be possible to similarly ignore useless ORDER BY items; * that is, an index on just y could be considered to match the ordering of * ... WHERE x = 42 ORDER BY x, y; - * But proving that this is safe would require finding a btree opclass + * But proving that this is safe would require finding a btree opfamily * containing both the = operator and the < or > operator in the ORDER BY * item. That's significantly more expensive than what we do here, since * we'd have to look at restriction clauses unrelated to the current index - * and search for opclasses without any hint from the index. The practical + * and search for opfamilies without any hint from the index. The practical * use-cases seem to be mostly covered by ignoring index columns, so that's * all we do for now. * @@ -1627,7 +1628,7 @@ match_variant_ordering(PlannerInfo *root, /* * Forget the whole thing if not a btree index; our check for ignorable - * columns assumes we are dealing with btree opclasses. (It'd be possible + * columns assumes we are dealing with btree opfamilies. (It'd be possible * to factor out just the try for backwards indexscan, but considering * that we presently have no orderable indexes except btrees anyway, it's * hardly worth contorting this code for that case.) @@ -1685,7 +1686,7 @@ identify_ignorable_ordering_cols(PlannerInfo *root, foreach(l, restrictclauses) { List *sublist = (List *) lfirst(l); - Oid opclass = index->classlist[indexcol]; + Oid opfamily = index->opfamily[indexcol]; ListCell *l2; foreach(l2, sublist) @@ -1698,7 +1699,7 @@ identify_ignorable_ordering_cols(PlannerInfo *root, bool ispc; /* First check for boolean-index cases. */ - if (IsBooleanOpclass(opclass)) + if (IsBooleanOpfamily(opfamily)) { if (match_boolean_index_clause((Node *) clause, indexcol, index)) @@ -1729,18 +1730,18 @@ identify_ignorable_ordering_cols(PlannerInfo *root, { Assert(match_index_to_operand(lsecond(clause->args), indexcol, index)); - /* Must flip operator to get the opclass member */ + /* Must flip operator to get the opfamily member */ clause_op = get_commutator(clause_op); varonleft = false; } if (!OidIsValid(clause_op)) continue; /* ignore non match, per next comment */ - op_strategy = get_op_opclass_strategy(clause_op, opclass); + op_strategy = get_op_opfamily_strategy(clause_op, opfamily); /* * You might expect to see Assert(op_strategy != 0) here, but you * won't: the clause might contain a special indexable operator - * rather than an ordinary opclass member. Currently none of the + * rather than an ordinary opfamily member. Currently none of the * special operators are very likely to expand to an equality * operator; we do not bother to check, but just assume no match. */ @@ -1968,7 +1969,7 @@ match_index_to_operand(Node *operand, * * match_special_index_operator() is just an auxiliary function for * match_clause_to_indexcol(); after the latter fails to recognize a - * restriction opclause's operator as a member of an index's opclass, + * restriction opclause's operator as a member of an index's opfamily, * it asks match_special_index_operator() whether the clause should be * considered an indexqual anyway. * @@ -1978,7 +1979,7 @@ match_index_to_operand(Node *operand, * expand_indexqual_conditions() converts a list of lists of RestrictInfo * nodes (with implicit AND semantics across list elements) into * a list of clauses that the executor can actually handle. For operators - * that are members of the index's opclass this transformation is a no-op, + * that are members of the index's opfamily this transformation is a no-op, * but clauses recognized by match_special_index_operator() or * match_boolean_index_clause() must be converted into one or more "regular" * indexqual conditions. @@ -1989,8 +1990,8 @@ match_index_to_operand(Node *operand, * match_boolean_index_clause * Recognize restriction clauses that can be matched to a boolean index. * - * This should be called only when IsBooleanOpclass() recognizes the - * index's operator class. We check to see if the clause matches the + * This should be called only when IsBooleanOpfamily() recognizes the + * index's operator family. We check to see if the clause matches the * index's key. */ static bool @@ -2034,11 +2035,11 @@ match_boolean_index_clause(Node *clause, * * The given clause is already known to be a binary opclause having * the form (indexkey OP pseudoconst) or (pseudoconst OP indexkey), - * but the OP proved not to be one of the index's opclass operators. + * but the OP proved not to be one of the index's opfamily operators. * Return 'true' if we can do something with it anyway. */ static bool -match_special_index_operator(Expr *clause, Oid opclass, +match_special_index_operator(Expr *clause, Oid opfamily, bool indexkey_on_left) { bool isIndexable = false; @@ -2122,12 +2123,12 @@ match_special_index_operator(Expr *clause, Oid opclass, return false; /* - * Must also check that index's opclass supports the operators we will + * Must also check that index's opfamily supports the operators we will * want to apply. (A hash index, for example, will not support ">=".) * Currently, only btree supports the operators we need. * - * We insist on the opclass being the specific one we expect, else we'd do - * the wrong thing if someone were to make a reverse-sort opclass with the + * We insist on the opfamily being the specific one we expect, else we'd do + * the wrong thing if someone were to make a reverse-sort opfamily with the * same operators. */ switch (expr_op) @@ -2136,12 +2137,9 @@ match_special_index_operator(Expr *clause, Oid opclass, case OID_TEXT_ICLIKE_OP: case OID_TEXT_REGEXEQ_OP: case OID_TEXT_ICREGEXEQ_OP: - /* text operators will be used for varchar inputs, too */ isIndexable = - (opclass == TEXT_PATTERN_BTREE_OPS_OID) || - (opclass == TEXT_BTREE_OPS_OID && lc_collate_is_c()) || - (opclass == VARCHAR_PATTERN_BTREE_OPS_OID) || - (opclass == VARCHAR_BTREE_OPS_OID && lc_collate_is_c()); + (opfamily == TEXT_PATTERN_BTREE_FAM_OID) || + (opfamily == TEXT_BTREE_FAM_OID && lc_collate_is_c()); break; case OID_BPCHAR_LIKE_OP: @@ -2149,8 +2147,8 @@ match_special_index_operator(Expr *clause, Oid opclass, case OID_BPCHAR_REGEXEQ_OP: case OID_BPCHAR_ICREGEXEQ_OP: isIndexable = - (opclass == BPCHAR_PATTERN_BTREE_OPS_OID) || - (opclass == BPCHAR_BTREE_OPS_OID && lc_collate_is_c()); + (opfamily == BPCHAR_PATTERN_BTREE_FAM_OID) || + (opfamily == BPCHAR_BTREE_FAM_OID && lc_collate_is_c()); break; case OID_NAME_LIKE_OP: @@ -2158,18 +2156,17 @@ match_special_index_operator(Expr *clause, Oid opclass, case OID_NAME_REGEXEQ_OP: case OID_NAME_ICREGEXEQ_OP: isIndexable = - (opclass == NAME_PATTERN_BTREE_OPS_OID) || - (opclass == NAME_BTREE_OPS_OID && lc_collate_is_c()); + (opfamily == NAME_PATTERN_BTREE_FAM_OID) || + (opfamily == NAME_BTREE_FAM_OID && lc_collate_is_c()); break; case OID_BYTEA_LIKE_OP: - isIndexable = (opclass == BYTEA_BTREE_OPS_OID); + isIndexable = (opfamily == BYTEA_BTREE_FAM_OID); break; case OID_INET_SUB_OP: case OID_INET_SUBEQ_OP: - isIndexable = (opclass == INET_BTREE_OPS_OID || - opclass == CIDR_BTREE_OPS_OID); + isIndexable = (opfamily == NETWORK_BTREE_FAM_OID); break; } @@ -2180,7 +2177,7 @@ match_special_index_operator(Expr *clause, Oid opclass, * expand_indexqual_conditions * Given a list of sublists of RestrictInfo nodes, produce a flat list * of index qual clauses. Standard qual clauses (those in the index's - * opclass) are passed through unchanged. Boolean clauses and "special" + * opfamily) are passed through unchanged. Boolean clauses and "special" * index operators are expanded into clauses that the indexscan machinery * will know what to do with. RowCompare clauses are simplified if * necessary to create a clause that is fully checkable by the index. @@ -2196,7 +2193,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups) List *resultquals = NIL; ListCell *clausegroup_item; int indexcol = 0; - Oid *classes = index->classlist; + Oid *families = index->opfamily; if (clausegroups == NIL) return NIL; @@ -2204,7 +2201,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups) clausegroup_item = list_head(clausegroups); do { - Oid curClass = classes[0]; + Oid curFamily = families[0]; ListCell *l; foreach(l, (List *) lfirst(clausegroup_item)) @@ -2213,7 +2210,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups) Expr *clause = rinfo->clause; /* First check for boolean cases */ - if (IsBooleanOpclass(curClass)) + if (IsBooleanOpfamily(curFamily)) { Expr *boolqual; @@ -2240,7 +2237,7 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups) { resultquals = list_concat(resultquals, expand_indexqual_opclause(rinfo, - curClass)); + curFamily)); } else if (IsA(clause, ScalarArrayOpExpr)) { @@ -2262,8 +2259,8 @@ expand_indexqual_conditions(IndexOptInfo *index, List *clausegroups) clausegroup_item = lnext(clausegroup_item); indexcol++; - classes++; - } while (clausegroup_item != NULL && !DoneMatchingIndexKeys(classes)); + families++; + } while (clausegroup_item != NULL && !DoneMatchingIndexKeys(families)); Assert(clausegroup_item == NULL); /* else more groups than indexkeys */ @@ -2337,7 +2334,7 @@ expand_boolean_index_clause(Node *clause, * The input is a single RestrictInfo, the output a list of RestrictInfos */ static List * -expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass) +expand_indexqual_opclause(RestrictInfo *rinfo, Oid opfamily) { Expr *clause = rinfo->clause; @@ -2354,7 +2351,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass) switch (expr_op) { /* - * LIKE and regex operators are not members of any index opclass, + * LIKE and regex operators are not members of any index opfamily, * so if we find one in an indexqual list we can assume that it * was accepted by match_special_index_operator(). */ @@ -2364,7 +2361,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass) case OID_BYTEA_LIKE_OP: pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like, &prefix, &rest); - result = prefix_quals(leftop, opclass, prefix, pstatus); + result = prefix_quals(leftop, opfamily, prefix, pstatus); break; case OID_TEXT_ICLIKE_OP: @@ -2373,7 +2370,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass) /* the right-hand const is type text for all of these */ pstatus = pattern_fixed_prefix(patt, Pattern_Type_Like_IC, &prefix, &rest); - result = prefix_quals(leftop, opclass, prefix, pstatus); + result = prefix_quals(leftop, opfamily, prefix, pstatus); break; case OID_TEXT_REGEXEQ_OP: @@ -2382,7 +2379,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass) /* the right-hand const is type text for all of these */ pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex, &prefix, &rest); - result = prefix_quals(leftop, opclass, prefix, pstatus); + result = prefix_quals(leftop, opfamily, prefix, pstatus); break; case OID_TEXT_ICREGEXEQ_OP: @@ -2391,12 +2388,12 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass) /* the right-hand const is type text for all of these */ pstatus = pattern_fixed_prefix(patt, Pattern_Type_Regex_IC, &prefix, &rest); - result = prefix_quals(leftop, opclass, prefix, pstatus); + result = prefix_quals(leftop, opfamily, prefix, pstatus); break; case OID_INET_SUB_OP: case OID_INET_SUBEQ_OP: - result = network_prefix_quals(leftop, expr_op, opclass, + result = network_prefix_quals(leftop, expr_op, opfamily, patt->constvalue); break; @@ -2416,7 +2413,7 @@ expand_indexqual_opclause(RestrictInfo *rinfo, Oid opclass) * the specified column of the index. We can use additional columns of the * row comparison as index qualifications, so long as they match the index * in the "same direction", ie, the indexkeys are all on the same side of the - * clause and the operators are all the same-type members of the opclasses. + * clause and the operators are all the same-type members of the opfamilies. * If all the columns of the RowCompareExpr match in this way, we just use it * as-is. Otherwise, we build a shortened RowCompareExpr (if more than one * column matches) or a simple OpExpr (if the first-column match is all @@ -2433,12 +2430,14 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, RowCompareExpr *clause = (RowCompareExpr *) rinfo->clause; bool var_on_left; int op_strategy; - Oid op_subtype; + Oid op_lefttype; + Oid op_righttype; bool op_recheck; int matching_cols; Oid expr_op; - List *opclasses; - List *subtypes; + List *opfamilies; + List *lefttypes; + List *righttypes; List *new_ops; ListCell *largs_cell; ListCell *rargs_cell; @@ -2453,11 +2452,15 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, expr_op = linitial_oid(clause->opnos); if (!var_on_left) expr_op = get_commutator(expr_op); - get_op_opclass_properties(expr_op, index->classlist[indexcol], - &op_strategy, &op_subtype, &op_recheck); - /* Build lists of the opclasses and operator subtypes in case needed */ - opclasses = list_make1_oid(index->classlist[indexcol]); - subtypes = list_make1_oid(op_subtype); + get_op_opfamily_properties(expr_op, index->opfamily[indexcol], + &op_strategy, + &op_lefttype, + &op_righttype, + &op_recheck); + /* Build lists of the opfamilies and operator datatypes in case needed */ + opfamilies = list_make1_oid(index->opfamily[indexcol]); + lefttypes = list_make1_oid(op_lefttype); + righttypes = list_make1_oid(op_righttype); /* * See how many of the remaining columns match some index column in the @@ -2513,15 +2516,19 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, break; /* no match found */ /* Now, do we have the right operator for this column? */ - if (get_op_opclass_strategy(expr_op, index->classlist[i]) + if (get_op_opfamily_strategy(expr_op, index->opfamily[i]) != op_strategy) break; - /* Add opclass and subtype to lists */ - get_op_opclass_properties(expr_op, index->classlist[i], - &op_strategy, &op_subtype, &op_recheck); - opclasses = lappend_oid(opclasses, index->classlist[i]); - subtypes = lappend_oid(subtypes, op_subtype); + /* Add opfamily and datatypes to lists */ + get_op_opfamily_properties(expr_op, index->opfamily[i], + &op_strategy, + &op_lefttype, + &op_righttype, + &op_recheck); + opfamilies = lappend_oid(opfamilies, index->opfamily[i]); + lefttypes = lappend_oid(lefttypes, op_lefttype); + righttypes = lappend_oid(righttypes, op_righttype); /* This column matches, keep scanning */ matching_cols++; @@ -2547,8 +2554,9 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, } else { - ListCell *opclasses_cell; - ListCell *subtypes_cell; + ListCell *opfamilies_cell; + ListCell *lefttypes_cell; + ListCell *righttypes_cell; if (op_strategy == BTLessStrategyNumber) op_strategy = BTLessEqualStrategyNumber; @@ -2557,23 +2565,30 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, else elog(ERROR, "unexpected strategy number %d", op_strategy); new_ops = NIL; - forboth(opclasses_cell, opclasses, subtypes_cell, subtypes) + lefttypes_cell = list_head(lefttypes); + righttypes_cell = list_head(righttypes); + foreach(opfamilies_cell, opfamilies) { - expr_op = get_opclass_member(lfirst_oid(opclasses_cell), - lfirst_oid(subtypes_cell), - op_strategy); + Oid opfam = lfirst_oid(opfamilies_cell); + Oid lefttype = lfirst_oid(lefttypes_cell); + Oid righttype = lfirst_oid(righttypes_cell); + + expr_op = get_opfamily_member(opfam, lefttype, righttype, + op_strategy); if (!OidIsValid(expr_op)) /* should not happen */ - elog(ERROR, "could not find member %d of opclass %u", - op_strategy, lfirst_oid(opclasses_cell)); + elog(ERROR, "could not find member %d(%u,%u) of opfamily %u", + op_strategy, lefttype, righttype, opfam); if (!var_on_left) { expr_op = get_commutator(expr_op); if (!OidIsValid(expr_op)) /* should not happen */ - elog(ERROR, "could not find commutator of member %d of opclass %u", - op_strategy, lfirst_oid(opclasses_cell)); + elog(ERROR, "could not find commutator of member %d(%u,%u) of opfamily %u", + op_strategy, lefttype, righttype, opfam); } new_ops = lappend_oid(new_ops, expr_op); } + lefttypes_cell = lnext(lefttypes_cell); + righttypes_cell = lnext(righttypes_cell); } /* If we have more than one matching col, create a subset rowcompare */ @@ -2587,8 +2602,8 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, rc->rctype = (op_strategy == BTLessEqualStrategyNumber) ? ROWCOMPARE_GE : ROWCOMPARE_LE; rc->opnos = new_ops; - rc->opclasses = list_truncate(list_copy(clause->opclasses), - matching_cols); + rc->opfamilies = list_truncate(list_copy(clause->opfamilies), + matching_cols); rc->largs = list_truncate((List *) copyObject(clause->largs), matching_cols); rc->rargs = list_truncate((List *) copyObject(clause->rargs), @@ -2608,12 +2623,12 @@ expand_indexqual_rowcompare(RestrictInfo *rinfo, /* * Given a fixed prefix that all the "leftop" values must have, - * generate suitable indexqual condition(s). opclass is the index - * operator class; we use it to deduce the appropriate comparison + * generate suitable indexqual condition(s). opfamily is the index + * operator family; we use it to deduce the appropriate comparison * operators and operand datatypes. */ static List * -prefix_quals(Node *leftop, Oid opclass, +prefix_quals(Node *leftop, Oid opfamily, Const *prefix_const, Pattern_Prefix_Status pstatus) { List *result; @@ -2624,35 +2639,30 @@ prefix_quals(Node *leftop, Oid opclass, Assert(pstatus != Pattern_Prefix_None); - switch (opclass) + switch (opfamily) { - case TEXT_BTREE_OPS_OID: - case TEXT_PATTERN_BTREE_OPS_OID: + case TEXT_BTREE_FAM_OID: + case TEXT_PATTERN_BTREE_FAM_OID: datatype = TEXTOID; break; - case VARCHAR_BTREE_OPS_OID: - case VARCHAR_PATTERN_BTREE_OPS_OID: - datatype = VARCHAROID; - break; - - case BPCHAR_BTREE_OPS_OID: - case BPCHAR_PATTERN_BTREE_OPS_OID: + case BPCHAR_BTREE_FAM_OID: + case BPCHAR_PATTERN_BTREE_FAM_OID: datatype = BPCHAROID; break; - case NAME_BTREE_OPS_OID: - case NAME_PATTERN_BTREE_OPS_OID: + case NAME_BTREE_FAM_OID: + case NAME_PATTERN_BTREE_FAM_OID: datatype = NAMEOID; break; - case BYTEA_BTREE_OPS_OID: + case BYTEA_BTREE_FAM_OID: datatype = BYTEAOID; break; default: /* shouldn't get here */ - elog(ERROR, "unexpected opclass: %u", opclass); + elog(ERROR, "unexpected opfamily: %u", opfamily); return NIL; } @@ -2688,10 +2698,10 @@ prefix_quals(Node *leftop, Oid opclass, */ if (pstatus == Pattern_Prefix_Exact) { - oproid = get_opclass_member(opclass, InvalidOid, - BTEqualStrategyNumber); + oproid = get_opfamily_member(opfamily, datatype, datatype, + BTEqualStrategyNumber); if (oproid == InvalidOid) - elog(ERROR, "no = operator for opclass %u", opclass); + elog(ERROR, "no = operator for opfamily %u", opfamily); expr = make_opclause(oproid, BOOLOID, false, (Expr *) leftop, (Expr *) prefix_const); result = list_make1(make_restrictinfo(expr, true, false, false, NULL)); @@ -2703,10 +2713,10 @@ prefix_quals(Node *leftop, Oid opclass, * * We can always say "x >= prefix". */ - oproid = get_opclass_member(opclass, InvalidOid, - BTGreaterEqualStrategyNumber); + oproid = get_opfamily_member(opfamily, datatype, datatype, + BTGreaterEqualStrategyNumber); if (oproid == InvalidOid) - elog(ERROR, "no >= operator for opclass %u", opclass); + elog(ERROR, "no >= operator for opfamily %u", opfamily); expr = make_opclause(oproid, BOOLOID, false, (Expr *) leftop, (Expr *) prefix_const); result = list_make1(make_restrictinfo(expr, true, false, false, NULL)); @@ -2719,10 +2729,10 @@ prefix_quals(Node *leftop, Oid opclass, greaterstr = make_greater_string(prefix_const); if (greaterstr) { - oproid = get_opclass_member(opclass, InvalidOid, - BTLessStrategyNumber); + oproid = get_opfamily_member(opfamily, datatype, datatype, + BTLessStrategyNumber); if (oproid == InvalidOid) - elog(ERROR, "no < operator for opclass %u", opclass); + elog(ERROR, "no < operator for opfamily %u", opfamily); expr = make_opclause(oproid, BOOLOID, false, (Expr *) leftop, (Expr *) greaterstr); result = lappend(result, @@ -2733,12 +2743,12 @@ prefix_quals(Node *leftop, Oid opclass, } /* - * Given a leftop and a rightop, and a inet-class sup/sub operator, + * Given a leftop and a rightop, and a inet-family sup/sub operator, * generate suitable indexqual condition(s). expr_op is the original - * operator, and opclass is the index opclass. + * operator, and opfamily is the index opfamily. */ static List * -network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop) +network_prefix_quals(Node *leftop, Oid expr_op, Oid opfamily, Datum rightop) { bool is_eq; Oid datatype; @@ -2770,17 +2780,17 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop) */ if (is_eq) { - opr1oid = get_opclass_member(opclass, InvalidOid, - BTGreaterEqualStrategyNumber); + opr1oid = get_opfamily_member(opfamily, datatype, datatype, + BTGreaterEqualStrategyNumber); if (opr1oid == InvalidOid) - elog(ERROR, "no >= operator for opclass %u", opclass); + elog(ERROR, "no >= operator for opfamily %u", opfamily); } else { - opr1oid = get_opclass_member(opclass, InvalidOid, - BTGreaterStrategyNumber); + opr1oid = get_opfamily_member(opfamily, datatype, datatype, + BTGreaterStrategyNumber); if (opr1oid == InvalidOid) - elog(ERROR, "no > operator for opclass %u", opclass); + elog(ERROR, "no > operator for opfamily %u", opfamily); } opr1right = network_scan_first(rightop); @@ -2793,10 +2803,10 @@ network_prefix_quals(Node *leftop, Oid expr_op, Oid opclass, Datum rightop) /* create clause "key <= network_scan_last( rightop )" */ - opr2oid = get_opclass_member(opclass, InvalidOid, - BTLessEqualStrategyNumber); + opr2oid = get_opfamily_member(opfamily, datatype, datatype, + BTLessEqualStrategyNumber); if (opr2oid == InvalidOid) - elog(ERROR, "no <= operator for opclass %u", opclass); + elog(ERROR, "no <= operator for opfamily %u", opfamily); opr2right = network_scan_last(rightop); diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index 6882439ca3a..06022b373b5 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.107 2006/10/04 00:29:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.108 2006/12/23 00:43:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,6 +16,7 @@ #include <math.h> +#include "access/skey.h" #include "optimizer/cost.h" #include "optimizer/pathnode.h" #include "optimizer/paths.h" @@ -39,6 +40,8 @@ static List *select_mergejoin_clauses(RelOptInfo *joinrel, RelOptInfo *innerrel, List *restrictlist, JoinType jointype); +static void build_mergejoin_strat_lists(List *mergeclauses, + List **mergefamilies, List **mergestrategies); /* @@ -225,6 +228,8 @@ sort_inner_and_outer(PlannerInfo *root, List *front_pathkey = (List *) lfirst(l); List *cur_pathkeys; List *cur_mergeclauses; + List *mergefamilies; + List *mergestrategies; List *outerkeys; List *innerkeys; List *merge_pathkeys; @@ -269,6 +274,10 @@ sort_inner_and_outer(PlannerInfo *root, merge_pathkeys = build_join_pathkeys(root, joinrel, jointype, outerkeys); + /* Build opfamily info for execution */ + build_mergejoin_strat_lists(cur_mergeclauses, + &mergefamilies, &mergestrategies); + /* * And now we can make the path. */ @@ -281,6 +290,8 @@ sort_inner_and_outer(PlannerInfo *root, restrictlist, merge_pathkeys, cur_mergeclauses, + mergefamilies, + mergestrategies, outerkeys, innerkeys)); } @@ -410,6 +421,8 @@ match_unsorted_outer(PlannerInfo *root, Path *outerpath = (Path *) lfirst(l); List *merge_pathkeys; List *mergeclauses; + List *mergefamilies; + List *mergestrategies; List *innersortkeys; List *trialsortkeys; Path *cheapest_startup_inner; @@ -516,6 +529,10 @@ match_unsorted_outer(PlannerInfo *root, mergeclauses, innerrel); + /* Build opfamily info for execution */ + build_mergejoin_strat_lists(mergeclauses, + &mergefamilies, &mergestrategies); + /* * Generate a mergejoin on the basis of sorting the cheapest inner. * Since a sort will be needed, only cheapest total cost matters. (But @@ -531,6 +548,8 @@ match_unsorted_outer(PlannerInfo *root, restrictlist, merge_pathkeys, mergeclauses, + mergefamilies, + mergestrategies, NIL, innersortkeys)); @@ -589,6 +608,11 @@ match_unsorted_outer(PlannerInfo *root, } else newclauses = mergeclauses; + + /* Build opfamily info for execution */ + build_mergejoin_strat_lists(newclauses, + &mergefamilies, &mergestrategies); + add_path(joinrel, (Path *) create_mergejoin_path(root, joinrel, @@ -598,6 +622,8 @@ match_unsorted_outer(PlannerInfo *root, restrictlist, merge_pathkeys, newclauses, + mergefamilies, + mergestrategies, NIL, NIL)); cheapest_total_inner = innerpath; @@ -633,6 +659,11 @@ match_unsorted_outer(PlannerInfo *root, else newclauses = mergeclauses; } + + /* Build opfamily info for execution */ + build_mergejoin_strat_lists(newclauses, + &mergefamilies, &mergestrategies); + add_path(joinrel, (Path *) create_mergejoin_path(root, joinrel, @@ -642,6 +673,8 @@ match_unsorted_outer(PlannerInfo *root, restrictlist, merge_pathkeys, newclauses, + mergefamilies, + mergestrategies, NIL, NIL)); } @@ -946,3 +979,35 @@ select_mergejoin_clauses(RelOptInfo *joinrel, return result_list; } + +/* + * Temporary hack to build opfamily and strategy lists needed for mergejoin + * by the executor. We need to rethink the planner's handling of merge + * planning so that it can deal with multiple possible merge orders, but + * that's not done yet. + */ +static void +build_mergejoin_strat_lists(List *mergeclauses, + List **mergefamilies, List **mergestrategies) +{ + ListCell *l; + + *mergefamilies = NIL; + *mergestrategies = NIL; + + foreach(l, mergeclauses) + { + RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l); + + /* + * We do not need to worry about whether the mergeclause will be + * commuted at runtime --- it's the same opfamily either way. + */ + *mergefamilies = lappend_oid(*mergefamilies, restrictinfo->mergeopfamily); + /* + * For the moment, strategy must always be LessThan --- see + * hack version of get_op_mergejoin_info + */ + *mergestrategies = lappend_int(*mergestrategies, BTLessStrategyNumber); + } +} diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 14f1f1a10f4..f924994480b 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.217 2006/10/04 00:29:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/createplan.c,v 1.218 2006/12/23 00:43:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -73,7 +73,7 @@ static void fix_indexqual_references(List *indexquals, IndexPath *index_path, List **indexstrategy, List **indexsubtype); static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index, - Oid *opclass); + Oid *opfamily); static List *get_switched_clauses(List *clauses, Relids outerrelids); static List *order_qual_clauses(PlannerInfo *root, List *clauses); static void copy_path_costsize(Plan *dest, Path *src); @@ -113,7 +113,7 @@ static HashJoin *make_hashjoin(List *tlist, static Hash *make_hash(Plan *lefttree); static MergeJoin *make_mergejoin(List *tlist, List *joinclauses, List *otherclauses, - List *mergeclauses, + List *mergeclauses, List *mergefamilies, List *mergestrategies, Plan *lefttree, Plan *righttree, JoinType jointype); static Sort *make_sort(PlannerInfo *root, Plan *lefttree, int numCols, @@ -1540,6 +1540,8 @@ create_mergejoin_plan(PlannerInfo *root, joinclauses, otherclauses, mergeclauses, + best_path->path_mergefamilies, + best_path->path_mergestrategies, outer_plan, inner_plan, best_path->jpath.jointype); @@ -1676,9 +1678,10 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path, RestrictInfo *rinfo = (RestrictInfo *) lfirst(l); Expr *clause; Oid clause_op; - Oid opclass; + Oid opfamily; int stratno; - Oid stratsubtype; + Oid stratlefttype; + Oid stratrighttype; bool recheck; Assert(IsA(rinfo, RestrictInfo)); @@ -1709,11 +1712,11 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path, /* * Now, determine which index attribute this is, change the - * indexkey operand as needed, and get the index opclass. + * indexkey operand as needed, and get the index opfamily. */ linitial(op->args) = fix_indexqual_operand(linitial(op->args), index, - &opclass); + &opfamily); clause_op = op->opno; } else if (IsA(clause, RowCompareExpr)) @@ -1734,20 +1737,20 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path, * For each column in the row comparison, determine which index * attribute this is and change the indexkey operand as needed. * - * Save the index opclass for only the first column. We will - * return the operator and opclass info for just the first column + * Save the index opfamily for only the first column. We will + * return the operator and opfamily info for just the first column * of the row comparison; the executor will have to look up the * rest if it needs them. */ foreach(lc, rc->largs) { - Oid tmp_opclass; + Oid tmp_opfamily; lfirst(lc) = fix_indexqual_operand(lfirst(lc), index, - &tmp_opclass); + &tmp_opfamily); if (lc == list_head(rc->largs)) - opclass = tmp_opclass; + opfamily = tmp_opfamily; } clause_op = linitial_oid(rc->opnos); } @@ -1759,11 +1762,11 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path, /* * Now, determine which index attribute this is, change the - * indexkey operand as needed, and get the index opclass. + * indexkey operand as needed, and get the index opfamily. */ linitial(saop->args) = fix_indexqual_operand(linitial(saop->args), index, - &opclass); + &opfamily); clause_op = saop->opno; } else @@ -1776,15 +1779,18 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path, *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 + * Look up the (possibly commuted) operator in the operator family to + * get its strategy number and the recheck indicator. This also * double-checks that we found an operator matching the index. */ - get_op_opclass_properties(clause_op, opclass, - &stratno, &stratsubtype, &recheck); + get_op_opfamily_properties(clause_op, opfamily, + &stratno, + &stratlefttype, + &stratrighttype, + &recheck); *indexstrategy = lappend_int(*indexstrategy, stratno); - *indexsubtype = lappend_oid(*indexsubtype, stratsubtype); + *indexsubtype = lappend_oid(*indexsubtype, stratrighttype); /* If it's not lossy, add to nonlossy_indexquals */ if (!recheck) @@ -1793,7 +1799,7 @@ fix_indexqual_references(List *indexquals, IndexPath *index_path, } static Node * -fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opclass) +fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opfamily) { /* * We represent index keys by Var nodes having the varno of the base table @@ -1826,8 +1832,8 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opclass) { result = (Var *) copyObject(node); result->varattno = pos + 1; - /* return the correct opclass, too */ - *opclass = index->classlist[pos]; + /* return the correct opfamily, too */ + *opfamily = index->opfamily[pos]; return (Node *) result; } } @@ -1853,8 +1859,8 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opclass) result = makeVar(index->rel->relid, pos + 1, exprType(lfirst(indexpr_item)), -1, 0); - /* return the correct opclass, too */ - *opclass = index->classlist[pos]; + /* return the correct opfamily, too */ + *opfamily = index->opfamily[pos]; return (Node *) result; } indexpr_item = lnext(indexpr_item); @@ -1863,7 +1869,7 @@ fix_indexqual_operand(Node *node, IndexOptInfo *index, Oid *opclass) /* Ooops... */ elog(ERROR, "node is not an index attribute"); - *opclass = InvalidOid; /* keep compiler quiet */ + *opfamily = InvalidOid; /* keep compiler quiet */ return NULL; } @@ -2327,6 +2333,8 @@ make_mergejoin(List *tlist, List *joinclauses, List *otherclauses, List *mergeclauses, + List *mergefamilies, + List *mergestrategies, Plan *lefttree, Plan *righttree, JoinType jointype) @@ -2340,6 +2348,8 @@ make_mergejoin(List *tlist, plan->lefttree = lefttree; plan->righttree = righttree; node->mergeclauses = mergeclauses; + node->mergefamilies = mergefamilies; + node->mergestrategies = mergestrategies; node->join.jointype = jointype; node->join.joinqual = joinclauses; diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index da321a637b2..229b779af03 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.124 2006/12/07 19:33:40 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.125 2006/12/23 00:43:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1109,10 +1109,10 @@ process_implied_equality(PlannerInfo *root, /* * Let's just make sure this appears to be a compatible operator. + * + * XXX needs work */ - if (pgopform->oprlsortop != sortop1 || - pgopform->oprrsortop != sortop2 || - pgopform->oprresult != BOOLOID) + if (pgopform->oprresult != BOOLOID) ereport(ERROR, (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION), errmsg("equality operator for types %s and %s should be merge-joinable, but isn't", @@ -1276,6 +1276,7 @@ check_mergejoinable(RestrictInfo *restrictinfo) Oid opno, leftOp, rightOp; + Oid opfamily; if (restrictinfo->pseudoconstant) return; @@ -1286,14 +1287,17 @@ check_mergejoinable(RestrictInfo *restrictinfo) opno = ((OpExpr *) clause)->opno; - if (op_mergejoinable(opno, - &leftOp, - &rightOp) && + if (op_mergejoinable(opno) && !contain_volatile_functions((Node *) clause)) { - restrictinfo->mergejoinoperator = opno; - restrictinfo->left_sortop = leftOp; - restrictinfo->right_sortop = rightOp; + /* XXX for the moment, continue to force use of particular sortops */ + if (get_op_mergejoin_info(opno, &leftOp, &rightOp, &opfamily)) + { + restrictinfo->mergejoinoperator = opno; + restrictinfo->left_sortop = leftOp; + restrictinfo->right_sortop = rightOp; + restrictinfo->mergeopfamily = opfamily; + } } } diff --git a/src/backend/optimizer/plan/planagg.c b/src/backend/optimizer/plan/planagg.c index e64340ed21c..fcc8d510786 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.22 2006/10/04 00:29:54 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.23 2006/12/23 00:43:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -340,8 +340,8 @@ build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info) Assert(is_opclause(rinfo->clause)); strategy = - get_op_opclass_strategy(((OpExpr *) rinfo->clause)->opno, - index->classlist[prevcol]); + get_op_opfamily_strategy(((OpExpr *) rinfo->clause)->opno, + index->opfamily[prevcol]); if (strategy == BTEqualStrategyNumber) break; } @@ -390,10 +390,10 @@ build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info) * Does an aggregate match an index column? * * It matches if its argument is equal to the index column's data and its - * sortop is either the LessThan or GreaterThan member of the column's opclass. + * sortop is either a LessThan or GreaterThan member of the column's opfamily. * - * We return ForwardScanDirection if match the LessThan member, - * BackwardScanDirection if match the GreaterThan member, + * We return ForwardScanDirection if match a LessThan member, + * BackwardScanDirection if match a GreaterThan member, * and NoMovementScanDirection if there's no match. */ static ScanDirection @@ -405,9 +405,9 @@ match_agg_to_index_col(MinMaxAggInfo *info, IndexOptInfo *index, int indexcol) if (!match_index_to_operand((Node *) info->target, indexcol, index)) return NoMovementScanDirection; - /* Look up the operator in the opclass */ - strategy = get_op_opclass_strategy(info->aggsortop, - index->classlist[indexcol]); + /* Look up the operator in the opfamily */ + strategy = get_op_opfamily_strategy(info->aggsortop, + index->opfamily[indexcol]); if (strategy == BTLessStrategyNumber) return ForwardScanDirection; if (strategy == BTGreaterStrategyNumber) diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 7793d071cda..f42a28cddd5 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.114 2006/12/10 22:13:26 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/plan/subselect.c,v 1.115 2006/12/23 00:43:10 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -689,11 +689,11 @@ convert_IN_to_join(PlannerInfo *root, SubLink *sublink) return NULL; if (sublink->testexpr && IsA(sublink->testexpr, OpExpr)) { - List *opclasses; + List *opfamilies; List *opstrats; get_op_btree_interpretation(((OpExpr *) sublink->testexpr)->opno, - &opclasses, &opstrats); + &opfamilies, &opstrats); if (!list_member_int(opstrats, ROWCOMPARE_EQ)) return NULL; } diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index 73ad926418f..0f720c40e93 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.224 2006/12/21 16:05:13 petere Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.225 2006/12/23 00:43:10 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -1294,13 +1294,9 @@ CommuteRowCompareExpr(RowCompareExpr *clause) clause->opnos = newops; /* - * Note: we don't bother to update the opclasses list, but just set it to - * empty. This is OK since this routine is currently only used for index - * quals, and the index machinery won't use the opclass information. The - * original opclass list is NOT valid if we have commuted any cross-type - * comparisons, so don't leave it in place. + * Note: we need not change the opfamilies list; we assume any btree + * opfamily containing an operator will also contain its commutator. */ - clause->opclasses = NIL; /* XXX */ temp = clause->largs; clause->largs = clause->rargs; diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index 01f3151bee8..5042a3ff563 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.133 2006/10/04 00:29:55 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.134 2006/12/23 00:43:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1152,6 +1152,10 @@ create_nestloop_path(PlannerInfo *root, * 'pathkeys' are the path keys of the new join path * 'mergeclauses' are the RestrictInfo nodes to use as merge clauses * (this should be a subset of the restrict_clauses list) + * 'mergefamilies' are the btree opfamily OIDs identifying the merge + * ordering for each merge clause + * 'mergestrategies' are the btree operator strategies identifying the merge + * ordering for each merge clause * 'outersortkeys' are the sort varkeys for the outer relation * 'innersortkeys' are the sort varkeys for the inner relation */ @@ -1164,6 +1168,8 @@ create_mergejoin_path(PlannerInfo *root, List *restrict_clauses, List *pathkeys, List *mergeclauses, + List *mergefamilies, + List *mergestrategies, List *outersortkeys, List *innersortkeys) { @@ -1204,6 +1210,8 @@ create_mergejoin_path(PlannerInfo *root, pathnode->jpath.joinrestrictinfo = restrict_clauses; pathnode->jpath.path.pathkeys = pathkeys; pathnode->path_mergeclauses = mergeclauses; + pathnode->path_mergefamilies = mergefamilies; + pathnode->path_mergestrategies = mergestrategies; pathnode->outersortkeys = outersortkeys; pathnode->innersortkeys = innersortkeys; diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 70a77bd3bd8..5b80991aefe 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.128 2006/12/18 18:56:28 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/plancat.c,v 1.129 2006/12/23 00:43:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -169,16 +169,16 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, info->ncolumns = ncolumns = index->indnatts; /* - * Need to make classlist and ordering arrays large enough to put + * Need to make opfamily and ordering arrays large enough to put * a terminating 0 at the end of each one. */ info->indexkeys = (int *) palloc(sizeof(int) * ncolumns); - info->classlist = (Oid *) palloc0(sizeof(Oid) * (ncolumns + 1)); + info->opfamily = (Oid *) palloc0(sizeof(Oid) * (ncolumns + 1)); info->ordering = (Oid *) palloc0(sizeof(Oid) * (ncolumns + 1)); for (i = 0; i < ncolumns; i++) { - info->classlist[i] = indexRelation->rd_indclass->values[i]; + info->opfamily[i] = indexRelation->rd_opfamily[i]; info->indexkeys[i] = index->indkey.values[i]; } diff --git a/src/backend/optimizer/util/predtest.c b/src/backend/optimizer/util/predtest.c index 4a2609a4ab6..5f81cae4e85 100644 --- a/src/backend/optimizer/util/predtest.c +++ b/src/backend/optimizer/util/predtest.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.10 2006/10/04 00:29:55 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/predtest.c,v 1.11 2006/12/23 00:43:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -939,7 +939,7 @@ arrayexpr_cleanup_fn(PredIterInfo info) * already known immutable, so the clause will certainly always fail.) * * Finally, we may be able to deduce something using knowledge about btree - * operator classes; this is encapsulated in btree_predicate_proof(). + * operator families; this is encapsulated in btree_predicate_proof(). *---------- */ static bool @@ -989,7 +989,7 @@ predicate_implied_by_simple_clause(Expr *predicate, Node *clause) * that has "foo" as an input. See notes for implication case. * * Finally, we may be able to deduce something using knowledge about btree - * operator classes; this is encapsulated in btree_predicate_proof(). + * operator families; this is encapsulated in btree_predicate_proof(). *---------- */ static bool @@ -1062,8 +1062,8 @@ extract_not_arg(Node *clause) * The strategy numbers defined by btree indexes (see access/skey.h) are: * (1) < (2) <= (3) = (4) >= (5) > * and in addition we use (6) to represent <>. <> is not a btree-indexable - * operator, but we assume here that if the equality operator of a btree - * opclass has a negator operator, the negator behaves as <> for the opclass. + * operator, but we assume here that if an equality operator of a btree + * opfamily has a negator operator, the negator behaves as <> for the opfamily. * * The interpretation of: * @@ -1146,10 +1146,10 @@ static const StrategyNumber BT_refute_table[6][6] = { * What we look for here is binary boolean opclauses of the form * "foo op constant", where "foo" is the same in both clauses. The operators * and constants can be different but the operators must be in the same btree - * operator class. We use the above operator implication tables to + * operator family. We use the above operator implication tables to * derive implications between nonidentical clauses. (Note: "foo" is known * immutable, and constants are surely immutable, but we have to check that - * the operators are too. As of 8.0 it's possible for opclasses to contain + * the operators are too. As of 8.0 it's possible for opfamilies to contain * operators that are merely stable, and we dare not make deductions with * these.) *---------- @@ -1171,12 +1171,12 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it) pred_op_negator, clause_op_negator, test_op = InvalidOid; - Oid opclass_id; + Oid opfamily_id; bool found = false; StrategyNumber pred_strategy, clause_strategy, test_strategy; - Oid clause_subtype; + Oid clause_righttype; Expr *test_expr; ExprState *test_exprstate; Datum test_result; @@ -1272,28 +1272,30 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it) } /* - * Try to find a btree opclass containing the needed operators. + * Try to find a btree opfamily containing the needed operators. * - * We must find a btree opclass that contains both operators, else the + * XXX this needs work!!!!!!!!!!!!!!!!!!!!!!! + * + * We must find a btree opfamily that contains both operators, else the * implication can't be determined. Also, the pred_op has to be of * default subtype (implying left and right input datatypes are the same); * otherwise it's unsafe to put the pred_const on the left side of the - * test. Also, the opclass must contain a suitable test operator matching + * test. Also, the opfamily must contain a suitable test operator matching * the clause_const's type (which we take to mean that it has the same * subtype as the original clause_operator). * - * If there are multiple matching opclasses, assume we can use any one to + * If there are multiple matching opfamilies, assume we can use any one to * determine the logical relationship of the two operators and the correct * corresponding test operator. This should work for any logically - * consistent opclasses. + * consistent opfamilies. */ catlist = SearchSysCacheList(AMOPOPID, 1, ObjectIdGetDatum(pred_op), 0, 0, 0); /* - * If we couldn't find any opclass containing the pred_op, perhaps it is a - * <> operator. See if it has a negator that is in an opclass. + * If we couldn't find any opfamily containing the pred_op, perhaps it is a + * <> operator. See if it has a negator that is in an opfamily. */ pred_op_negated = false; if (catlist->n_members == 0) @@ -1312,23 +1314,22 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it) /* Also may need the clause_op's negator */ clause_op_negator = get_negator(clause_op); - /* Now search the opclasses */ + /* Now search the opfamilies */ for (i = 0; i < catlist->n_members; i++) { HeapTuple pred_tuple = &catlist->members[i]->tuple; Form_pg_amop pred_form = (Form_pg_amop) GETSTRUCT(pred_tuple); HeapTuple clause_tuple; - opclass_id = pred_form->amopclaid; - /* must be btree */ - if (!opclass_is_btree(opclass_id)) + if (pred_form->amopmethod != BTREE_AM_OID) continue; - /* predicate operator must be default within this opclass */ - if (pred_form->amopsubtype != InvalidOid) + /* predicate operator must be default within this opfamily */ + if (pred_form->amoplefttype != pred_form->amoprighttype) continue; /* Get the predicate operator's btree strategy number */ + opfamily_id = pred_form->amopfamily; pred_strategy = (StrategyNumber) pred_form->amopstrategy; Assert(pred_strategy >= 1 && pred_strategy <= 5); @@ -1341,37 +1342,39 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it) } /* - * From the same opclass, find a strategy number for the clause_op, if - * possible + * From the same opfamily, find a strategy number for the clause_op, + * if possible */ clause_tuple = SearchSysCache(AMOPOPID, ObjectIdGetDatum(clause_op), - ObjectIdGetDatum(opclass_id), + ObjectIdGetDatum(opfamily_id), 0, 0); if (HeapTupleIsValid(clause_tuple)) { Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple); - /* Get the restriction clause operator's strategy/subtype */ + /* Get the restriction clause operator's strategy/datatype */ clause_strategy = (StrategyNumber) clause_form->amopstrategy; Assert(clause_strategy >= 1 && clause_strategy <= 5); - clause_subtype = clause_form->amopsubtype; + Assert(clause_form->amoplefttype == pred_form->amoplefttype); + clause_righttype = clause_form->amoprighttype; ReleaseSysCache(clause_tuple); } else if (OidIsValid(clause_op_negator)) { clause_tuple = SearchSysCache(AMOPOPID, ObjectIdGetDatum(clause_op_negator), - ObjectIdGetDatum(opclass_id), + ObjectIdGetDatum(opfamily_id), 0, 0); if (HeapTupleIsValid(clause_tuple)) { Form_pg_amop clause_form = (Form_pg_amop) GETSTRUCT(clause_tuple); - /* Get the restriction clause operator's strategy/subtype */ + /* Get the restriction clause operator's strategy/datatype */ clause_strategy = (StrategyNumber) clause_form->amopstrategy; Assert(clause_strategy >= 1 && clause_strategy <= 5); - clause_subtype = clause_form->amopsubtype; + Assert(clause_form->amoplefttype == pred_form->amoplefttype); + clause_righttype = clause_form->amoprighttype; ReleaseSysCache(clause_tuple); /* Only consider negators that are = */ @@ -1400,20 +1403,24 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it) } /* - * See if opclass has an operator for the test strategy and the clause - * datatype. + * See if opfamily has an operator for the test strategy and the + * datatypes. */ if (test_strategy == BTNE) { - test_op = get_opclass_member(opclass_id, clause_subtype, - BTEqualStrategyNumber); + test_op = get_opfamily_member(opfamily_id, + pred_form->amoprighttype, + clause_righttype, + BTEqualStrategyNumber); if (OidIsValid(test_op)) test_op = get_negator(test_op); } else { - test_op = get_opclass_member(opclass_id, clause_subtype, - test_strategy); + test_op = get_opfamily_member(opfamily_id, + pred_form->amoprighttype, + clause_righttype, + test_strategy); } if (OidIsValid(test_op)) { @@ -1423,7 +1430,7 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it) * Note that we require only the test_op to be immutable, not the * original clause_op. (pred_op is assumed to have been checked * immutable by the caller.) Essentially we are assuming that the - * opclass is consistent even if it contains operators that are + * opfamily is consistent even if it contains operators that are * merely stable. */ if (op_volatile(test_op) == PROVOLATILE_IMMUTABLE) @@ -1438,7 +1445,7 @@ btree_predicate_proof(Expr *predicate, Node *clause, bool refute_it) if (!found) { - /* couldn't find a btree opclass to interpret the operators */ + /* couldn't find a btree opfamily to interpret the operators */ return false; } diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index 9176ae1680c..adfd9e47858 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.49 2006/10/04 00:29:55 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.50 2006/12/23 00:43:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -342,6 +342,7 @@ make_restrictinfo_internal(Expr *clause, restrictinfo->mergejoinoperator = InvalidOid; restrictinfo->left_sortop = InvalidOid; restrictinfo->right_sortop = InvalidOid; + restrictinfo->mergeopfamily = InvalidOid; restrictinfo->left_pathkey = NIL; restrictinfo->right_pathkey = NIL; |