diff --git a/src/backend/optimizer/util/keys.c b/src/backend/optimizer/util/keys.c index bf9e91abb6bea6bbfbcfc2884384164361f3efc1..1177f6bbb209477f4195ac5c7cb62eb5be40784b 100644 --- a/src/backend/optimizer/util/keys.c +++ b/src/backend/optimizer/util/keys.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.14 1999/02/10 21:02:41 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.15 1999/02/11 04:08:42 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -106,7 +106,7 @@ extract_join_subkey(JoinKey *jk, int which_subkey) } /* - * samekeys-- + * pathkeys_match-- * Returns t iff two sets of path keys are equivalent. They are * equivalent if the first Var nodes match the second Var nodes. * @@ -118,7 +118,7 @@ extract_join_subkey(JoinKey *jk, int which_subkey) * */ bool -samekeys(List *keys1, List *keys2) +pathkeys_match(List *keys1, List *keys2, int *longer_key) { List *key1, *key2, @@ -133,9 +133,20 @@ samekeys(List *keys1, List *keys2) key1a != NIL && key2a != NIL; key1a = lnext(key1a), key2a = lnext(key2a)) if (!equal(lfirst(key1a), lfirst(key2a))) + { + *longer_key = 0; return false; - if (key1a != NIL) - return false; + } + if (key1a != NIL && key2a == NIL) + { + *longer_key = 1; + return true; + } + if (key1a == NIL && key2a != NIL) + { + *longer_key = 2; + return true; + } } /* Now the result should be true if list keys2 has at least as many @@ -143,10 +154,18 @@ samekeys(List *keys1, List *keys2) * If key1 is now NIL then we hit the end of keys1 before or at the * same time as the end of keys2. */ - if (key1 == NIL) + if (key1 != NIL && key2 == NIL) + { + *longer_key = 1; return true; - else - return false; + } + if (key1 == NIL && key2 != NIL) + { + *longer_key = 2; + return true; + } + *longer_key = 0; + return true; } /* diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index a029b95909e1c0f4692b2237452fca5de1f2b8a1..02360d74f0880f17e2f5ca732190f648187a4107 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.23 1999/02/10 21:02:43 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.24 1999/02/11 04:08:43 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -29,7 +29,7 @@ #include "parser/parsetree.h" /* for getrelid() */ -static Path *better_path(Path *new_path, List *unique_paths, bool *noOther); +static Path *better_path(Path *new_path, List *unique_paths, bool *isNew); /***************************************************************************** @@ -107,16 +107,16 @@ add_pathlist(RelOptInfo *parent_rel, List *unique_paths, List *new_paths) { Path *new_path = (Path *) lfirst(p1); Path *old_path; - bool noOther; + bool is_new; /* Is this new path already in unique_paths? */ if (member(new_path, unique_paths)) continue; /* Find best matching path */ - old_path = better_path(new_path, unique_paths, &noOther); + old_path = better_path(new_path, unique_paths, &is_new); - if (noOther) + if (is_new) { /* This is a brand new path. */ new_path->parent = parent_rel; @@ -153,19 +153,19 @@ add_pathlist(RelOptInfo *parent_rel, List *unique_paths, List *new_paths) * */ static Path * -better_path(Path *new_path, List *unique_paths, bool *noOther) +better_path(Path *new_path, List *unique_paths, bool *is_new) { - Path *old_path = (Path *) NULL; Path *path = (Path *) NULL; List *temp = NIL; - Path *retval = NULL; + int longer_key; foreach(temp, unique_paths) { path = (Path *) lfirst(temp); #ifdef OPTDUP_DEBUG - if (!samekeys(path->pathkeys, new_path->pathkeys)) + if (!pathkeys_match(new_path->pathkeys, path->pathkeys, &longer_key) || + longer_key != 0) { printf("oldpath\n"); pprint(path->pathkeys); @@ -176,8 +176,7 @@ better_path(Path *new_path, List *unique_paths, bool *noOther) length(lfirst(path->pathkeys)) < length(lfirst(new_path->pathkeys))) sleep(0); /* set breakpoint here */ } - if (!equal_path_ordering(path->path_order, - new_path->path_order)) + if (!equal_path_ordering(new_path->path_order, path->path_order)) { printf("oldord\n"); pprint(path->path_order); @@ -185,26 +184,35 @@ better_path(Path *new_path, List *unique_paths, bool *noOther) pprint(new_path->path_order); } #endif - - if (samekeys(path->pathkeys, new_path->pathkeys) && - equal_path_ordering(path->path_order, - new_path->path_order)) + + if (pathkeys_match(new_path->pathkeys, path->pathkeys, &longer_key)) { - old_path = path; - break; + if (equal_path_ordering(new_path->path_order, path->path_order)) + { + /* + * Replace pathkeys that match exactly, (1,2), (1,2). + * Replace pathkeys (1,2) with (1,2,3) if the latter is not + * more expensive and replace unordered path with ordered + * path if it is not more expensive. + */ + if ((longer_key == 0 && new_path->path_cost < path->path_cost) || + (longer_key == 1 && new_path->path_cost <= path->path_cost) || + (longer_key == 2 && new_path->path_cost >= path->path_cost)) + { + *is_new = false; + return new_path; + } + else + { + *is_new = false; + return NULL; + } + } } } - if (old_path == NULL) - *noOther = true; - else - { - *noOther = false; - if (path_is_cheaper(new_path, old_path)) - retval = old_path; - } - - return retval; + *is_new = true; + return NULL; } diff --git a/src/include/optimizer/keys.h b/src/include/optimizer/keys.h index 8694819d193760e374523aec379e796fa1408fbd..a66fd2bc6bf7aec2c750cd8337435f741fde16a6 100644 --- a/src/include/optimizer/keys.h +++ b/src/include/optimizer/keys.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: keys.h,v 1.9 1999/02/10 21:02:48 momjian Exp $ + * $Id: keys.h,v 1.10 1999/02/11 04:08:44 momjian Exp $ * *------------------------------------------------------------------------- */ @@ -18,7 +18,7 @@ extern bool match_indexkey_operand(int indexkey, Var *operand, RelOptInfo *rel); extern Var *extract_join_subkey(JoinKey *jk, int which_subkey); -extern bool samekeys(List *keys1, List *keys2); +extern bool pathkeys_match(List *keys1, List *keys2, int *longer_key); extern List *collect_index_pathkeys(int *index_keys, List *tlist); #endif /* KEYS_H */