mirror of
https://github.com/postgres/postgres.git
synced 2025-05-21 15:54:08 +03:00
In find_mergeclauses_for_pathkeys, it's okay to return multiple merge
clauses per path key. Indeed, we *must* do so or we will be unable to form a valid plan for FULL JOIN with overlapping join conditions, eg select * from a full join b on a.v1 = b.v1 and a.v2 = b.v2 and a.v1 = b.v2.
This commit is contained in:
parent
c336b58f93
commit
c5c97318f9
@ -11,7 +11,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.35 2001/10/28 06:25:44 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.36 2001/11/11 20:33:53 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -752,25 +752,43 @@ find_mergeclauses_for_pathkeys(Query *root,
|
|||||||
List *mergeclauses = NIL;
|
List *mergeclauses = NIL;
|
||||||
List *i;
|
List *i;
|
||||||
|
|
||||||
|
/* make sure we have pathkeys cached in the clauses */
|
||||||
|
foreach(i, restrictinfos)
|
||||||
|
{
|
||||||
|
RestrictInfo *restrictinfo = lfirst(i);
|
||||||
|
|
||||||
|
cache_mergeclause_pathkeys(root, restrictinfo);
|
||||||
|
}
|
||||||
|
|
||||||
foreach(i, pathkeys)
|
foreach(i, pathkeys)
|
||||||
{
|
{
|
||||||
List *pathkey = lfirst(i);
|
List *pathkey = lfirst(i);
|
||||||
RestrictInfo *matched_restrictinfo = NULL;
|
List *matched_restrictinfos = NIL;
|
||||||
List *j;
|
List *j;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can match a pathkey against either left or right side of any
|
* We can match a pathkey against either left or right side of any
|
||||||
* mergejoin clause we haven't used yet. For the moment we use a
|
* mergejoin clause. (We examine both sides since we aren't told if
|
||||||
* dumb "greedy" algorithm with no backtracking. Is it worth
|
* the given pathkeys are for inner or outer input path; no confusion
|
||||||
* being any smarter to make a longer list of usable mergeclauses?
|
* is possible.) Furthermore, if there are multiple matching
|
||||||
* Probably not.
|
* clauses, take them all. In plain inner-join scenarios we expect
|
||||||
|
* only one match, because redundant-mergeclause elimination will
|
||||||
|
* have removed any redundant mergeclauses from the input list.
|
||||||
|
* However, in outer-join scenarios there might be multiple matches.
|
||||||
|
* An example is
|
||||||
|
*
|
||||||
|
* select * from a full join b on
|
||||||
|
* a.v1 = b.v1 and a.v2 = b.v2 and a.v1 = b.v2;
|
||||||
|
*
|
||||||
|
* Given the pathkeys ((a.v1), (a.v2)) it is okay to return all
|
||||||
|
* three clauses (in the order a.v1=b.v1, a.v1=b.v2, a.v2=b.v2)
|
||||||
|
* and indeed we *must* do so or we will be unable to form a
|
||||||
|
* valid plan.
|
||||||
*/
|
*/
|
||||||
foreach(j, restrictinfos)
|
foreach(j, restrictinfos)
|
||||||
{
|
{
|
||||||
RestrictInfo *restrictinfo = lfirst(j);
|
RestrictInfo *restrictinfo = lfirst(j);
|
||||||
|
|
||||||
cache_mergeclause_pathkeys(root, restrictinfo);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We can compare canonical pathkey sublists by simple pointer
|
* We can compare canonical pathkey sublists by simple pointer
|
||||||
* equality; see compare_pathkeys.
|
* equality; see compare_pathkeys.
|
||||||
@ -779,8 +797,8 @@ find_mergeclauses_for_pathkeys(Query *root,
|
|||||||
pathkey == restrictinfo->right_pathkey) &&
|
pathkey == restrictinfo->right_pathkey) &&
|
||||||
!ptrMember(restrictinfo, mergeclauses))
|
!ptrMember(restrictinfo, mergeclauses))
|
||||||
{
|
{
|
||||||
matched_restrictinfo = restrictinfo;
|
matched_restrictinfos = lappend(matched_restrictinfos,
|
||||||
break;
|
restrictinfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -789,14 +807,14 @@ find_mergeclauses_for_pathkeys(Query *root,
|
|||||||
* sort-key positions in the pathkeys are useless. (But we can
|
* sort-key positions in the pathkeys are useless. (But we can
|
||||||
* still mergejoin if we found at least one mergeclause.)
|
* still mergejoin if we found at least one mergeclause.)
|
||||||
*/
|
*/
|
||||||
if (!matched_restrictinfo)
|
if (matched_restrictinfos == NIL)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If we did find a usable mergeclause for this sort-key position,
|
* If we did find usable mergeclause(s) for this sort-key position,
|
||||||
* add it to result list.
|
* add them to result list.
|
||||||
*/
|
*/
|
||||||
mergeclauses = lappend(mergeclauses, matched_restrictinfo);
|
mergeclauses = nconc(mergeclauses, matched_restrictinfos);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mergeclauses;
|
return mergeclauses;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user