Optimizer fix for samekeys() and cost fixes for longer optimizer keys.
authorBruce Momjian
Thu, 11 Feb 1999 04:08:44 +0000 (04:08 +0000)
committerBruce Momjian
Thu, 11 Feb 1999 04:08:44 +0000 (04:08 +0000)
src/backend/optimizer/util/keys.c
src/backend/optimizer/util/pathnode.c
src/include/optimizer/keys.h

index bf9e91abb6bea6bbfbcfc2884384164361f3efc1..1177f6bbb209477f4195ac5c7cb62eb5be40784b 100644 (file)
@@ -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;
 }
 
 /*
index a029b95909e1c0f4692b2237452fca5de1f2b8a1..02360d74f0880f17e2f5ca732190f648187a4107 100644 (file)
@@ -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;
 }
 
 
index 8694819d193760e374523aec379e796fa1408fbd..a66fd2bc6bf7aec2c750cd8337435f741fde16a6 100644 (file)
@@ -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 */