diff options
Diffstat (limited to 'src/backend/optimizer/path/indxpath.c')
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 276 |
1 files changed, 190 insertions, 86 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 5a86749a66f..db836e9ab17 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.6 1997/03/12 21:00:17 scrappy Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.7 1997/03/18 18:39:40 scrappy Exp $ * *------------------------------------------------------------------------- */ @@ -53,8 +53,9 @@ static bool match_index_to_operand(int indexkey, Expr *operand, static List *match_index_orclause(Rel *rel, Rel *index, int indexkey, int xclass, List *or_clauses, List *other_matching_indices); static List *group_clauses_by_indexkey(Rel *rel, Rel *index, - int *indexkeys, Oid *classes, List *clauseinfo_list, - bool join); + int *indexkeys, Oid *classes, List *clauseinfo_list); +static List *group_clauses_by_ikey_for_joins(Rel *rel, Rel *index, + int *indexkeys, Oid *classes, List *join_cinfo_list, List *restr_cinfo_list); static CInfo *match_clause_to_indexkey(Rel *rel, Rel *index, int indexkey, int xclass, CInfo *clauseInfo, bool join); static bool pred_test(List *predicate_list, List *clauseinfo_list, @@ -63,7 +64,8 @@ static bool one_pred_test(Expr *predicate, List *clauseinfo_list); static bool one_pred_clause_expr_test(Expr *predicate, Node *clause); static bool one_pred_clause_test(Expr *predicate, Node *clause); static bool clause_pred_clause_test(Expr *predicate, Node *clause); -static List *indexable_joinclauses(Rel *rel, Rel *index, List *joininfo_list); +static List *indexable_joinclauses (Rel *rel, Rel *index, + List *joininfo_list, List *clauseinfo_list); static List *index_innerjoin(Query *root, Rel *rel, List *clausegroup_list, Rel *index); static List *create_index_paths(Query *root, Rel *rel, Rel *index, @@ -114,7 +116,6 @@ find_index_paths (Query *root, List *joinclausegroups = NIL; List *joinpaths = NIL; List *retval = NIL; - extern List *add_index_paths(); if(indices == NIL) return(NULL); @@ -160,8 +161,7 @@ find_index_paths (Query *root, index, index->indexkeys, index->classlist, - clauseinfo_list, - false); + clauseinfo_list); scanpaths = NIL; if (scanclausegroups != NIL) @@ -178,7 +178,7 @@ find_index_paths (Query *root, * useful for a mergejoin, or if the index can possibly be * used for scanning the inner relation of a nestloop join. */ - joinclausegroups = indexable_joinclauses(rel,index,joininfo_list); + joinclausegroups = indexable_joinclauses(rel,index,joininfo_list, clauseinfo_list); joinpaths = NIL; if (joinclausegroups != NIL) @@ -375,10 +375,8 @@ match_index_orclause(Rel *rel, * (2) a list of join clauses between 'rel' and a fixed set of * relations, * depending on the value of 'join'. - * 'startlist' is a list of those clause nodes that have matched the keys - * that have already been checked. - * 'join' is a flag indicating that the clauses being checked are join - * clauses. + * + * NOTE: it works now for restriction clauses only. - vadim 03/18/97 * * Returns all possible groups of clauses that will match (given that * one or more clauses can match any of the remaining keys). @@ -391,45 +389,144 @@ group_clauses_by_indexkey(Rel *rel, Rel *index, int *indexkeys, Oid *classes, - List *clauseinfo_list, - bool join) + List *clauseinfo_list) { List *curCinfo = NIL; CInfo *matched_clause = (CInfo*)NULL; List *clausegroup = NIL; - + int curIndxKey; + Oid curClass; if (clauseinfo_list == NIL) return NIL; - foreach (curCinfo,clauseinfo_list) { - CInfo *temp = (CInfo*)lfirst(curCinfo); - int *curIndxKey = indexkeys; - Oid *curClass = classes; + while ( !DoneMatchingIndexKeys(indexkeys, index) ) + { + List *tempgroup = NIL; + + curIndxKey = indexkeys[0]; + curClass = classes[0]; + + foreach (curCinfo,clauseinfo_list) + { + CInfo *temp = (CInfo*)lfirst(curCinfo); + + matched_clause = match_clause_to_indexkey (rel, + index, + curIndxKey, + curClass, + temp, + false); + if (!matched_clause) + continue; + + tempgroup = lappend(tempgroup, matched_clause); + } + if ( tempgroup == NIL ) + break; + + clausegroup = nconc (clausegroup, tempgroup); + + indexkeys++; + classes++; + + } + + /* clausegroup holds all matched clauses ordered by indexkeys */ + + if (clausegroup != NIL) + return(lcons(clausegroup, NIL)); + return NIL; +} + +/* + * group-clauses-by-ikey-for-joins-- + * special edition of group-clauses-by-indexkey - will + * match join & restriction clauses. See comment in indexable_joinclauses. + * - vadim 03/18/97 + * + */ +static List * +group_clauses_by_ikey_for_joins(Rel *rel, + Rel *index, + int *indexkeys, + Oid *classes, + List *join_cinfo_list, + List *restr_cinfo_list) +{ + List *curCinfo = NIL; + CInfo *matched_clause = (CInfo*)NULL; + List *clausegroup = NIL; + int curIndxKey; + Oid curClass; + bool jfound = false; + + if (join_cinfo_list == NIL) + return NIL; + + while ( !DoneMatchingIndexKeys(indexkeys, index) ) + { + List *tempgroup = NIL; + + curIndxKey = indexkeys[0]; + curClass = classes[0]; + + foreach (curCinfo,join_cinfo_list) + { + CInfo *temp = (CInfo*)lfirst(curCinfo); + + matched_clause = match_clause_to_indexkey (rel, + index, + curIndxKey, + curClass, + temp, + true); + if (!matched_clause) + continue; + + tempgroup = lappend(tempgroup, matched_clause); + jfound = true; + } + foreach (curCinfo,restr_cinfo_list) + { + CInfo *temp = (CInfo*)lfirst(curCinfo); - do { - /* - * If we can't find any matching clauses for the first of - * the remaining keys, give up. - */ matched_clause = match_clause_to_indexkey (rel, index, - curIndxKey[0], - curClass[0], + curIndxKey, + curClass, temp, - join); + false); if (!matched_clause) - break; + continue; - clausegroup = lcons(matched_clause, clausegroup); - curIndxKey++; - curClass++; + tempgroup = lappend(tempgroup, matched_clause); + } + if ( tempgroup == NIL ) + break; - } while ( !DoneMatchingIndexKeys(curIndxKey, index) ); + clausegroup = nconc (clausegroup, tempgroup); + + indexkeys++; + classes++; + } + /* clausegroup holds all matched clauses ordered by indexkeys */ + if (clausegroup != NIL) + { + /* + * if no one join clause was matched then there ain't clauses + * for joins at all. + */ + if ( !jfound ) + { + freeList (clausegroup); + return NIL; + } return(lcons(clausegroup, NIL)); + } return NIL; } @@ -482,6 +579,7 @@ match_clause_to_indexkey(Rel *rel, Expr *clause = clauseInfo->clause; Var *leftop, *rightop; Oid join_op = InvalidOid; + Oid restrict_op = InvalidOid; bool isIndexable = false; if (or_clause((Node*)clause) || @@ -495,90 +593,87 @@ match_clause_to_indexkey(Rel *rel, * (operator var/func constant) and (operator constant var/func) */ if (!join) - { - Oid restrict_op = InvalidOid; - - /* - * Check for standard s-argable clause - */ + { + /* + * Check for standard s-argable clause + */ #ifdef INDEXSCAN_PATCH /* Handle also function parameters. DZ - 27-8-1996 */ - if ((rightop && IsA(rightop,Const)) || + if ((rightop && IsA(rightop,Const)) || (rightop && IsA(rightop,Param))) #else - if (rightop && IsA(rightop,Const)) + if (rightop && IsA(rightop,Const)) #endif - { - restrict_op = ((Oper*)((Expr*)clause)->oper)->opno; - isIndexable = - ( op_class(restrict_op, xclass, index->relam) && + { + restrict_op = ((Oper*)((Expr*)clause)->oper)->opno; + isIndexable = + ( op_class(restrict_op, xclass, index->relam) && IndexScanableOperand(leftop, indexkey, rel, index) ); - } + } - /* - * Must try to commute the clause to standard s-arg format. - */ + /* + * Must try to commute the clause to standard s-arg format. + */ #ifdef INDEXSCAN_PATCH /* ...And here... - vadim 01/22/97 */ - else if ((leftop && IsA(leftop,Const)) || + else if ((leftop && IsA(leftop,Const)) || (leftop && IsA(leftop,Param))) #else - else if (leftop && IsA(leftop,Const)) + else if (leftop && IsA(leftop,Const)) #endif - { - restrict_op = - get_commutator(((Oper*)((Expr*)clause)->oper)->opno); + { + restrict_op = + get_commutator(((Oper*)((Expr*)clause)->oper)->opno); - if ( (restrict_op != InvalidOid) && + if ( (restrict_op != InvalidOid) && op_class(restrict_op, xclass, index->relam) && IndexScanableOperand(rightop, indexkey,rel,index) ) - { - isIndexable = true; - /* - * In place list modification. - * (op const var/func) -> (op var/func const) - */ - /* BUG! Old version: - CommuteClause(clause, restrict_op); - */ - CommuteClause((Node*)clause); - } - } - } + { + isIndexable = true; + /* + * In place list modification. + * (op const var/func) -> (op var/func const) + */ + CommuteClause((Node*)clause); + } + } + } /* * Check for an indexable scan on one of the join relations. * clause is of the form (operator var/func var/func) */ else + { + if (rightop + && match_index_to_operand(indexkey,(Expr*)rightop,rel,index)) { - if (rightop - && match_index_to_operand(indexkey,(Expr*)rightop,rel,index)) { join_op = get_commutator(((Oper*)((Expr*)clause)->oper)->opno); - } else if (leftop + } else if (leftop && match_index_to_operand(indexkey, - (Expr*)leftop,rel,index)) { + (Expr*)leftop,rel,index)) + { join_op = ((Oper*)((Expr*)clause)->oper)->opno; - } + } - if ( join_op && op_class(join_op,xclass,index->relam) && + if ( join_op && op_class(join_op,xclass,index->relam) && join_clause_p((Node*)clause)) - { - isIndexable = true; - - /* - * If we're using the operand's commutator we must - * commute the clause. - */ - if (join_op != ((Oper*)((Expr*)clause)->oper)->opno) + { + isIndexable = true; + + /* + * If we're using the operand's commutator we must + * commute the clause. + */ + if (join_op != ((Oper*)((Expr*)clause)->oper)->opno) CommuteClause((Node*)clause); - } } + } if (isIndexable) return(clauseInfo); @@ -955,10 +1050,15 @@ clause_pred_clause_test(Expr *predicate, Node *clause) * in the join clause as its outer join relation. * * Returns a list of these clause groups. + * + * Added: clauseinfo_list - list of restriction CInfos. It's to + * support multi-column indices in joins and for cases + * when a key is in both join & restriction clauses. - vadim 03/18/97 * */ static List * -indexable_joinclauses(Rel *rel, Rel *index, List *joininfo_list) +indexable_joinclauses(Rel *rel, Rel *index, + List *joininfo_list, List *clauseinfo_list) { JInfo *joininfo = (JInfo*)NULL; List *cg_list = NIL; @@ -967,13 +1067,16 @@ indexable_joinclauses(Rel *rel, Rel *index, List *joininfo_list) foreach(i,joininfo_list) { joininfo = (JInfo*)lfirst(i); + + if ( joininfo->jinfoclauseinfo == NIL ) + continue; clausegroups = - group_clauses_by_indexkey (rel, + group_clauses_by_ikey_for_joins (rel, index, index->indexkeys, index->classlist, joininfo->jinfoclauseinfo, - true); + clauseinfo_list); if (clausegroups != NIL) { List *clauses = lfirst(clausegroups); @@ -1056,6 +1159,7 @@ index_innerjoin(Query *root, Rel *rel, List *clausegroup_list, Rel *index) pathnode->path.pathtype = T_IndexScan; pathnode->path.parent = rel; pathnode->indexid = index->relids; + pathnode->indexkeys = index->indexkeys; pathnode->indexqual = clausegroup; pathnode->path.joinid = ((CInfo*)lfirst(clausegroup))->cinfojoinid; @@ -1130,7 +1234,7 @@ create_index_paths(Query *root, temp = false; } } - + if (!join || temp) { /* restriction, ordering scan */ temp_path = create_index_path (root, rel,index,clausegroup,join); temp_node = |