mirror of
https://github.com/postgres/postgres.git
synced 2025-05-05 09:19:17 +03:00
Update pathkeys comparison function.
This commit is contained in:
parent
148ec3b1d8
commit
0ff2733355
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.3 1999/02/20 16:32:35 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.4 1999/02/20 18:01:01 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -54,7 +54,7 @@ static List *new_matching_subkeys(Var *subkey, List *considered_subkeys,
|
|||||||
* { {tab1.col1, tab2.col1} }. This allows future joins to use either Var
|
* { {tab1.col1, tab2.col1} }. This allows future joins to use either Var
|
||||||
* as a pre-sorted key to prevent Mergejoins from having to re-sort the Path.
|
* as a pre-sorted key to prevent Mergejoins from having to re-sort the Path.
|
||||||
* They are equal, so they are both primary sort keys. This is why pathkeys
|
* They are equal, so they are both primary sort keys. This is why pathkeys
|
||||||
* is a List of Lists.
|
* is a List of Lists. -- bjm
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.18 1999/02/19 02:05:16 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/Attic/keys.c,v 1.19 1999/02/20 18:01:02 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -110,62 +110,70 @@ extract_join_key(JoinKey *jk, int outer_or_inner)
|
|||||||
* Returns t iff two sets of path keys are equivalent. They are
|
* Returns t iff two sets of path keys are equivalent. They are
|
||||||
* equivalent if the first Var nodes match the second Var nodes.
|
* equivalent if the first Var nodes match the second Var nodes.
|
||||||
*
|
*
|
||||||
* XXX It isn't necessary to check that each sublist exactly contain
|
* See the top of optimizer/path/pathkeys.c for a description of pathkeys.
|
||||||
* the same elements because if the routine that built these
|
* Each pathkey is ordered by its join order, so they not pre-ordered to
|
||||||
* sublists together is correct, having one element in common
|
* match. We must search them ourselves.
|
||||||
* implies having all elements in common.
|
|
||||||
* Huh? bjm
|
|
||||||
*
|
*
|
||||||
|
* This gets called a lot, so it is optimized.
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
pathkeys_match(List *keys1, List *keys2, int *better_key)
|
pathkeys_match(List *keys1, List *keys2, int *better_key)
|
||||||
{
|
{
|
||||||
List *key1,
|
List *key1,
|
||||||
*key2,
|
*key2;
|
||||||
*key1a,
|
bool key1_subsetof_key2 = true,
|
||||||
*key2a;
|
key2_subsetof_key1 = true;
|
||||||
|
|
||||||
for (key1 = keys1, key2 = keys2;
|
for (key1 = keys1, key2 = keys2;
|
||||||
key1 != NIL && key2 != NIL;
|
key1 != NIL && key2 != NIL;
|
||||||
key1 = lnext(key1), key2 = lnext(key2))
|
key1 = lnext(key1), key2 = lnext(key2))
|
||||||
{
|
{
|
||||||
for (key1a = lfirst(key1), key2a = lfirst(key2);
|
List *i;
|
||||||
key1a != NIL && key2a != NIL;
|
|
||||||
key1a = lnext(key1a), key2a = lnext(key2a))
|
if (key1_subsetof_key2)
|
||||||
if (!equal(lfirst(key1a), lfirst(key2a)))
|
foreach(i, lfirst(key1))
|
||||||
|
{
|
||||||
|
Var *subkey = lfirst(i);
|
||||||
|
if (!member(subkey, lfirst(key2)))
|
||||||
|
{
|
||||||
|
key1_subsetof_key2 = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key2_subsetof_key1)
|
||||||
|
foreach(i, lfirst(key2))
|
||||||
|
{
|
||||||
|
Var *subkey = lfirst(i);
|
||||||
|
if (!member(subkey, lfirst(key1)))
|
||||||
|
{
|
||||||
|
key2_subsetof_key1 = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!key1_subsetof_key2 && !key2_subsetof_key1)
|
||||||
|
break; /* no need to continue comparisons. */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!key1_subsetof_key2 && !key2_subsetof_key1)
|
||||||
{
|
{
|
||||||
*better_key = 0;
|
*better_key = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (key1a != NIL && key2a == NIL)
|
if (key1_subsetof_key2 && !key2_subsetof_key1)
|
||||||
{
|
|
||||||
*better_key = 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (key1a == NIL && key2a != NIL)
|
|
||||||
{
|
{
|
||||||
*better_key = 2;
|
*better_key = 2;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (!key1_subsetof_key2 && key2_subsetof_key1)
|
||||||
|
{
|
||||||
|
*better_key = 1;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now the result should be true if list keys2 has at least as many
|
|
||||||
* entries as keys1, ie, we did not fall off the end of keys2 first.
|
|
||||||
* 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 && key2 == NIL)
|
|
||||||
{
|
|
||||||
*better_key = 1;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (key1 == NIL && key2 != NIL)
|
|
||||||
{
|
|
||||||
*better_key = 2;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
*better_key = 0;
|
*better_key = 0;
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.37 1999/02/18 00:49:38 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.38 1999/02/20 18:01:02 momjian Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -172,15 +172,15 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
|||||||
{
|
{
|
||||||
path = (Path *) lfirst(temp);
|
path = (Path *) lfirst(temp);
|
||||||
|
|
||||||
#if 0
|
#ifdef OPTDUP_DEBUG
|
||||||
/*def OPTDUP_DEBUG*/
|
|
||||||
if (!pathkeys_match(new_path->pathkeys, path->pathkeys, &better_key) ||
|
if (!pathkeys_match(new_path->pathkeys, path->pathkeys, &better_key) ||
|
||||||
better_key != 0)
|
better_key != 0)
|
||||||
{
|
{
|
||||||
printf("oldpath\n");
|
printf("betterkey = %d\n", better_key);
|
||||||
pprint(path->pathkeys);
|
|
||||||
printf("newpath\n");
|
printf("newpath\n");
|
||||||
pprint(new_path->pathkeys);
|
pprint(new_path->pathkeys);
|
||||||
|
printf("oldpath\n");
|
||||||
|
pprint(path->pathkeys);
|
||||||
if (path->pathkeys && new_path->pathkeys &&
|
if (path->pathkeys && new_path->pathkeys &&
|
||||||
length(lfirst(path->pathkeys)) >= 2/* &&
|
length(lfirst(path->pathkeys)) >= 2/* &&
|
||||||
length(lfirst(path->pathkeys)) <
|
length(lfirst(path->pathkeys)) <
|
||||||
@ -191,10 +191,10 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
|||||||
&better_sort) ||
|
&better_sort) ||
|
||||||
better_sort != 0)
|
better_sort != 0)
|
||||||
{
|
{
|
||||||
printf("oldord\n");
|
|
||||||
pprint(path->pathorder);
|
|
||||||
printf("neword\n");
|
printf("neword\n");
|
||||||
pprint(new_path->pathorder);
|
pprint(new_path->pathorder);
|
||||||
|
printf("oldord\n");
|
||||||
|
pprint(path->pathorder);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -204,8 +204,8 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
|||||||
&better_sort))
|
&better_sort))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Replace pathkeys that match exactly, (1,2), (1,2).
|
* Replace pathkeys that match exactly, {{1,2}}, {{1,2}}
|
||||||
* Replace pathkeys (1,2) with (1,2,3) if the latter is not
|
* Replace pathkeys {{1,2}}with {{1,2,3}}} if the latter is not
|
||||||
* more expensive and replace unordered path with ordered
|
* more expensive and replace unordered path with ordered
|
||||||
* path if it is not more expensive. Favor sorted keys
|
* path if it is not more expensive. Favor sorted keys
|
||||||
* over unsorted keys in the same way.
|
* over unsorted keys in the same way.
|
||||||
@ -221,10 +221,10 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
|||||||
{
|
{
|
||||||
#ifdef OPTDUP_DEBUG
|
#ifdef OPTDUP_DEBUG
|
||||||
printf("replace with new %p old %p better key %d better sort %d\n", &new_path, &path, better_key, better_sort);
|
printf("replace with new %p old %p better key %d better sort %d\n", &new_path, &path, better_key, better_sort);
|
||||||
printf("old\n");
|
|
||||||
pprint(path);
|
|
||||||
printf("new\n");
|
printf("new\n");
|
||||||
pprint(new_path);
|
pprint(new_path);
|
||||||
|
printf("old\n");
|
||||||
|
pprint(path);
|
||||||
#endif
|
#endif
|
||||||
*is_new = false;
|
*is_new = false;
|
||||||
return path;
|
return path;
|
||||||
@ -241,10 +241,10 @@ better_path(Path *new_path, List *unique_paths, bool *is_new)
|
|||||||
{
|
{
|
||||||
#ifdef OPTDUP_DEBUG
|
#ifdef OPTDUP_DEBUG
|
||||||
printf("skip new %p old %p better key %d better sort %d\n", &new_path, &path, better_key, better_sort);
|
printf("skip new %p old %p better key %d better sort %d\n", &new_path, &path, better_key, better_sort);
|
||||||
printf("old\n");
|
|
||||||
pprint(path);
|
|
||||||
printf("new\n");
|
printf("new\n");
|
||||||
pprint(new_path);
|
pprint(new_path);
|
||||||
|
printf("old\n");
|
||||||
|
pprint(path);
|
||||||
#endif
|
#endif
|
||||||
*is_new = false;
|
*is_new = false;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user