1996-07-09 08:22:35 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* joinutils.c
|
1997-09-07 07:04:48 +02:00
|
|
|
* Utilities for matching and building join and path keys
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
* Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* IDENTIFICATION
|
1999-07-16 00:40:16 +02:00
|
|
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.11 1999/07/15 22:39:25 momjian Exp $
|
1996-07-09 08:22:35 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#include "postgres.h"
|
|
|
|
|
|
|
|
|
|
|
|
#include "optimizer/paths.h"
|
|
|
|
#include "optimizer/keys.h"
|
|
|
|
#include "optimizer/tlist.h"
|
|
|
|
#include "optimizer/joininfo.h"
|
|
|
|
#include "optimizer/ordering.h"
|
|
|
|
|
1998-09-01 06:40:42 +02:00
|
|
|
static int match_pathkey_joinkeys(List *pathkey, List *joinkeys,
|
1999-05-25 18:15:34 +02:00
|
|
|
int outer_or_inner);
|
1999-02-22 06:26:58 +01:00
|
|
|
static List *new_join_pathkey(List *pathkeys, List *join_rel_tlist,
|
1999-05-25 18:15:34 +02:00
|
|
|
List *joinclauses);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-02-20 17:28:20 +01:00
|
|
|
|
1999-05-17 02:26:33 +02:00
|
|
|
/*--------------------
|
1999-02-20 17:28:20 +01:00
|
|
|
* Explanation of Path.pathkeys
|
|
|
|
*
|
1999-02-20 17:32:35 +01:00
|
|
|
* Path.pathkeys is a List of List of Var nodes that represent the sort
|
1999-02-20 17:28:20 +01:00
|
|
|
* order of the result generated by the Path.
|
|
|
|
*
|
|
|
|
* In single/base relation RelOptInfo's, the Path's represent various ways
|
1999-05-17 02:26:33 +02:00
|
|
|
* of generating the relation and the resulting ordering of the tuples.
|
|
|
|
* Sequential scan Paths have NIL pathkeys, indicating no known ordering.
|
|
|
|
* Index scans have Path.pathkeys that represent the chosen index.
|
1999-05-25 18:15:34 +02:00
|
|
|
* A single-key index pathkeys would be { {tab1_indexkey1} }. For a
|
1999-05-17 02:26:33 +02:00
|
|
|
* multi-key index pathkeys would be { {tab1_indexkey1}, {tab1_indexkey2} },
|
|
|
|
* indicating major sort by indexkey1 and minor sort by indexkey2.
|
1999-02-20 17:28:20 +01:00
|
|
|
*
|
|
|
|
* Multi-relation RelOptInfo Path's are more complicated. Mergejoins are
|
1999-05-17 02:26:33 +02:00
|
|
|
* only performed with equijoins ("="). Because of this, the multi-relation
|
1999-02-20 17:32:35 +01:00
|
|
|
* path actually has more than one primary Var key. For example, a
|
|
|
|
* mergejoin Path of "tab1.col1 = tab2.col1" would generate a pathkeys of
|
1999-05-17 02:26:33 +02:00
|
|
|
* { {tab1.col1, tab2.col1} }, indicating that the major sort order of the
|
|
|
|
* Path can be taken to be *either* tab1.col1 or tab2.col1.
|
|
|
|
* They are equal, so they are both primary sort keys. This allows future
|
|
|
|
* joins to use either Var as a pre-sorted key to prevent upper Mergejoins
|
|
|
|
* from having to re-sort the Path. This is why pathkeys is a List of Lists.
|
|
|
|
*
|
|
|
|
* Note that while the order of the top list is meaningful (primary vs.
|
|
|
|
* secondary sort key), the order of each sublist is arbitrary.
|
1999-02-20 20:02:43 +01:00
|
|
|
*
|
|
|
|
* For multi-key sorts, if the outer is sorted by a multi-key index, the
|
|
|
|
* multi-key index remains after the join. If the inner has a multi-key
|
|
|
|
* sort, only the primary key of the inner is added to the result.
|
|
|
|
* Mergejoins only join on the primary key. Currently, non-primary keys
|
|
|
|
* in the pathkeys List are of limited value.
|
|
|
|
*
|
1999-05-17 02:26:33 +02:00
|
|
|
* Although Hashjoins also work only with equijoin operators, it is *not*
|
|
|
|
* safe to consider the output of a Hashjoin to be sorted in any particular
|
|
|
|
* order --- not even the outer path's order. This is true because the
|
|
|
|
* executor might have to split the join into multiple batches.
|
|
|
|
*
|
|
|
|
* NestJoin does not perform sorting, and allows non-equijoins, so it does
|
1999-05-25 18:15:34 +02:00
|
|
|
* not allow useful pathkeys. (But couldn't we use the outer path's order?)
|
1999-02-20 20:02:43 +01:00
|
|
|
*
|
|
|
|
* -- bjm
|
1999-05-17 02:26:33 +02:00
|
|
|
*--------------------
|
1999-02-20 17:28:20 +01:00
|
|
|
*/
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1996-07-09 08:22:35 +02:00
|
|
|
/****************************************************************************
|
1997-09-07 07:04:48 +02:00
|
|
|
* KEY COMPARISONS
|
1996-07-09 08:22:35 +02:00
|
|
|
****************************************************************************/
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-19 06:18:06 +01:00
|
|
|
* order_joinkeys_by_pathkeys
|
1997-09-07 07:04:48 +02:00
|
|
|
* Attempts to match the keys of a path against the keys of join clauses.
|
|
|
|
* This is done by looking for a matching join key in 'joinkeys' for
|
1999-02-10 04:52:54 +01:00
|
|
|
* every path key in the list 'path.keys'. If there is a matching join key
|
1997-09-07 07:04:48 +02:00
|
|
|
* (not necessarily unique) for every path key, then the list of
|
|
|
|
* corresponding join keys and join clauses are returned in the order in
|
|
|
|
* which the keys matched the path keys.
|
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* 'pathkeys' is a list of path keys:
|
1997-09-07 07:04:48 +02:00
|
|
|
* ( ( (var) (var) ... ) ( (var) ... ) )
|
1996-07-09 08:22:35 +02:00
|
|
|
* 'joinkeys' is a list of join keys:
|
1997-09-07 07:04:48 +02:00
|
|
|
* ( (outer inner) (outer inner) ... )
|
1996-07-09 08:22:35 +02:00
|
|
|
* 'joinclauses' is a list of clauses corresponding to the join keys in
|
1997-09-07 07:04:48 +02:00
|
|
|
* 'joinkeys'
|
1999-02-22 06:26:58 +01:00
|
|
|
* 'outer_or_inner' is a flag that selects the desired pathkey of a join key
|
1997-09-07 07:04:48 +02:00
|
|
|
* in 'joinkeys'
|
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* Returns the join keys and corresponding join clauses in a list if all
|
|
|
|
* of the path keys were matched:
|
1997-09-07 07:04:48 +02:00
|
|
|
* (
|
1999-02-21 02:55:03 +01:00
|
|
|
* ( (outerkey0 innerkey0) ... (outerkeyN or innerkeyN) )
|
1997-09-07 07:04:48 +02:00
|
|
|
* ( clause0 ... clauseN )
|
|
|
|
* )
|
1996-07-09 08:22:35 +02:00
|
|
|
* and nil otherwise.
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* Returns a list of matched join keys and a list of matched join clauses
|
1999-02-21 02:55:03 +01:00
|
|
|
* in pointers if valid order can be found.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1999-02-21 02:55:03 +01:00
|
|
|
bool
|
1999-02-19 06:18:06 +01:00
|
|
|
order_joinkeys_by_pathkeys(List *pathkeys,
|
1999-05-25 18:15:34 +02:00
|
|
|
List *joinkeys,
|
|
|
|
List *joinclauses,
|
|
|
|
int outer_or_inner,
|
|
|
|
List **matchedJoinKeysPtr,
|
|
|
|
List **matchedJoinClausesPtr)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
List *matched_joinkeys = NIL;
|
|
|
|
List *matched_joinclauses = NIL;
|
|
|
|
List *pathkey = NIL;
|
|
|
|
List *i = NIL;
|
|
|
|
int matched_joinkey_index = -1;
|
1999-02-21 02:55:03 +01:00
|
|
|
int matched_keys = 0;
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1999-02-20 20:02:43 +01:00
|
|
|
/*
|
1999-05-25 18:15:34 +02:00
|
|
|
* Reorder the joinkeys by picking out one that matches each pathkey,
|
|
|
|
* and create a new joinkey/joinclause list in pathkey order
|
1999-02-20 20:02:43 +01:00
|
|
|
*/
|
1997-09-07 07:04:48 +02:00
|
|
|
foreach(i, pathkeys)
|
|
|
|
{
|
|
|
|
pathkey = lfirst(i);
|
1999-02-19 03:05:20 +01:00
|
|
|
matched_joinkey_index = match_pathkey_joinkeys(pathkey, joinkeys,
|
|
|
|
outer_or_inner);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
if (matched_joinkey_index != -1)
|
|
|
|
{
|
1999-02-21 02:55:03 +01:00
|
|
|
matched_keys++;
|
|
|
|
if (matchedJoinKeysPtr)
|
|
|
|
{
|
1999-05-25 18:15:34 +02:00
|
|
|
JoinKey *joinkey = nth(matched_joinkey_index, joinkeys);
|
|
|
|
|
1999-02-21 02:55:03 +01:00
|
|
|
matched_joinkeys = lappend(matched_joinkeys, joinkey);
|
|
|
|
}
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
if (matchedJoinClausesPtr)
|
1999-02-21 02:55:03 +01:00
|
|
|
{
|
|
|
|
Expr *joinclause = nth(matched_joinkey_index,
|
|
|
|
joinclauses);
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
Assert(joinclauses);
|
1999-02-21 02:55:03 +01:00
|
|
|
matched_joinclauses = lappend(matched_joinclauses, joinclause);
|
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
else
|
1999-05-25 18:15:34 +02:00
|
|
|
/* A pathkey could not be matched. */
|
1999-02-20 20:02:43 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
1999-05-25 18:15:34 +02:00
|
|
|
* Did we fail to match all the joinkeys? Extra pathkeys are no
|
|
|
|
* problem.
|
1999-02-20 20:02:43 +01:00
|
|
|
*/
|
1999-02-21 02:55:03 +01:00
|
|
|
if (matched_keys != length(joinkeys))
|
1999-02-20 20:02:43 +01:00
|
|
|
{
|
1999-05-25 18:15:34 +02:00
|
|
|
if (matchedJoinKeysPtr)
|
|
|
|
*matchedJoinKeysPtr = NIL;
|
|
|
|
if (matchedJoinClausesPtr)
|
|
|
|
*matchedJoinClausesPtr = NIL;
|
|
|
|
return false;
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
|
1999-02-21 02:55:03 +01:00
|
|
|
if (matchedJoinKeysPtr)
|
|
|
|
*matchedJoinKeysPtr = matched_joinkeys;
|
|
|
|
if (matchedJoinClausesPtr)
|
|
|
|
*matchedJoinClausesPtr = matched_joinclauses;
|
|
|
|
return true;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1999-02-19 03:05:20 +01:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-14 00:22:53 +01:00
|
|
|
* match_pathkey_joinkeys
|
1997-09-07 07:04:48 +02:00
|
|
|
* Returns the 0-based index into 'joinkeys' of the first joinkey whose
|
1999-02-22 06:26:58 +01:00
|
|
|
* outer or inner pathkey matches any subkey of 'pathkey'.
|
1999-02-20 20:02:43 +01:00
|
|
|
*
|
|
|
|
* All these keys are equivalent, so any of them can match. See above.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
|
|
|
static int
|
1997-09-08 23:56:23 +02:00
|
|
|
match_pathkey_joinkeys(List *pathkey,
|
|
|
|
List *joinkeys,
|
1999-02-19 03:05:20 +01:00
|
|
|
int outer_or_inner)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-02-22 06:26:58 +01:00
|
|
|
Var *key;
|
1997-09-08 04:41:22 +02:00
|
|
|
int pos;
|
1999-05-25 18:15:34 +02:00
|
|
|
List *i,
|
|
|
|
*x;
|
1997-09-08 04:41:22 +02:00
|
|
|
JoinKey *jk;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
foreach(i, pathkey)
|
|
|
|
{
|
1999-02-22 06:26:58 +01:00
|
|
|
key = (Var *) lfirst(i);
|
1997-09-07 07:04:48 +02:00
|
|
|
pos = 0;
|
|
|
|
foreach(x, joinkeys)
|
|
|
|
{
|
|
|
|
jk = (JoinKey *) lfirst(x);
|
1999-02-22 06:26:58 +01:00
|
|
|
if (equal(key, extract_join_key(jk, outer_or_inner)))
|
1998-09-01 05:29:17 +02:00
|
|
|
return pos;
|
1997-09-07 07:04:48 +02:00
|
|
|
pos++;
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1998-09-01 06:40:42 +02:00
|
|
|
return -1; /* no index found */
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1999-02-19 03:05:20 +01:00
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-19 06:18:06 +01:00
|
|
|
* get_cheapest_path_for_joinkeys
|
1997-09-07 07:04:48 +02:00
|
|
|
* Attempts to find a path in 'paths' whose keys match a set of join
|
|
|
|
* keys 'joinkeys'. To match,
|
|
|
|
* 1. the path node ordering must equal 'ordering'.
|
1999-02-22 06:26:58 +01:00
|
|
|
* 2. each pathkey of a given path must match(i.e., be(equal) to) the
|
|
|
|
* appropriate pathkey of the corresponding join key in 'joinkeys',
|
|
|
|
* i.e., the Nth path key must match its pathkeys against the pathkey of
|
1997-09-07 07:04:48 +02:00
|
|
|
* the Nth join key in 'joinkeys'.
|
|
|
|
*
|
|
|
|
* 'joinkeys' is the list of key pairs to which the path keys must be
|
|
|
|
* matched
|
1996-07-09 08:22:35 +02:00
|
|
|
* 'ordering' is the ordering of the(outer) path to which 'joinkeys'
|
1997-09-07 07:04:48 +02:00
|
|
|
* must correspond
|
1996-07-09 08:22:35 +02:00
|
|
|
* 'paths' is a list of(inner) paths which are to be matched against
|
1997-09-07 07:04:48 +02:00
|
|
|
* each join key in 'joinkeys'
|
1999-02-22 06:26:58 +01:00
|
|
|
* 'outer_or_inner' is a flag that selects the desired pathkey of a join key
|
1997-09-07 07:04:48 +02:00
|
|
|
* in 'joinkeys'
|
|
|
|
*
|
1999-02-19 03:05:20 +01:00
|
|
|
* Find the cheapest path that matches the join keys
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1998-02-26 05:46:47 +01:00
|
|
|
Path *
|
1999-02-19 06:18:06 +01:00
|
|
|
get_cheapest_path_for_joinkeys(List *joinkeys,
|
1999-05-25 18:15:34 +02:00
|
|
|
PathOrder *ordering,
|
|
|
|
List *paths,
|
|
|
|
int outer_or_inner)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Path *matched_path = NULL;
|
1999-05-17 02:26:33 +02:00
|
|
|
List *i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
foreach(i, paths)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
Path *path = (Path *) lfirst(i);
|
1999-02-22 06:26:58 +01:00
|
|
|
int better_sort;
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1999-02-21 02:55:03 +01:00
|
|
|
if (order_joinkeys_by_pathkeys(path->pathkeys, joinkeys, NIL,
|
|
|
|
outer_or_inner, NULL, NULL) &&
|
1999-02-19 06:18:06 +01:00
|
|
|
pathorder_match(ordering, path->pathorder, &better_sort) &&
|
|
|
|
better_sort == 0)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
1999-04-30 05:59:06 +02:00
|
|
|
if (matched_path == NULL ||
|
|
|
|
path->path_cost < matched_path->path_cost)
|
1997-09-07 07:04:48 +02:00
|
|
|
matched_path = path;
|
|
|
|
}
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1997-09-07 07:04:48 +02:00
|
|
|
return matched_path;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-22 06:26:58 +01:00
|
|
|
* make_pathkeys_from_joinkeys
|
|
|
|
* Builds a pathkey list for a path by pulling one of the pathkeys from
|
1997-09-07 07:04:48 +02:00
|
|
|
* a list of join keys 'joinkeys' and then finding the var node in the
|
1999-02-22 06:26:58 +01:00
|
|
|
* target list 'tlist' that corresponds to that pathkey.
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* 'joinkeys' is a list of join key pairs
|
|
|
|
* 'tlist' is a relation target list
|
1999-02-22 06:26:58 +01:00
|
|
|
* 'outer_or_inner' is a flag that selects the desired pathkey of a join key
|
1999-02-21 02:55:03 +01:00
|
|
|
* in 'joinkeys'
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
* Returns a list of pathkeys: ((tlvar1)(tlvar2)...(tlvarN)).
|
1999-02-10 04:52:54 +01:00
|
|
|
* It is a list of lists because of multi-key indexes.
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1998-02-26 05:46:47 +01:00
|
|
|
List *
|
1999-02-22 06:26:58 +01:00
|
|
|
make_pathkeys_from_joinkeys(List *joinkeys,
|
1999-05-25 18:15:34 +02:00
|
|
|
List *tlist,
|
|
|
|
int outer_or_inner)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
List *pathkeys = NIL;
|
|
|
|
List *jk;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
foreach(jk, joinkeys)
|
|
|
|
{
|
1997-09-08 04:41:22 +02:00
|
|
|
JoinKey *jkey = (JoinKey *) lfirst(jk);
|
1999-02-22 06:26:58 +01:00
|
|
|
Var *key;
|
1999-05-25 18:15:34 +02:00
|
|
|
List *p,
|
|
|
|
*p2;
|
1999-02-22 06:26:58 +01:00
|
|
|
bool found = false;
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
key = (Var *) extract_join_key(jkey, outer_or_inner);
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
/* check to see if it is in the target list */
|
|
|
|
if (matching_tlist_var(key, tlist))
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
/*
|
1999-05-25 18:15:34 +02:00
|
|
|
* Include it in the pathkeys list if we haven't already done
|
|
|
|
* so
|
1999-02-22 06:26:58 +01:00
|
|
|
*/
|
|
|
|
foreach(p, pathkeys)
|
|
|
|
{
|
|
|
|
List *pathkey = lfirst(p);
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
foreach(p2, pathkey)
|
|
|
|
{
|
|
|
|
Var *pkey = lfirst(p2);
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
if (equal(key, pkey))
|
|
|
|
{
|
|
|
|
found = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (found)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!found)
|
|
|
|
pathkeys = lappend(pathkeys, lcons(key, NIL));
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
}
|
1998-09-01 05:29:17 +02:00
|
|
|
return pathkeys;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************
|
1997-09-07 07:04:48 +02:00
|
|
|
* NEW PATHKEY FORMATION
|
1996-07-09 08:22:35 +02:00
|
|
|
****************************************************************************/
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-14 00:22:53 +01:00
|
|
|
* new_join_pathkeys
|
1997-09-07 07:04:48 +02:00
|
|
|
* Find the path keys for a join relation by finding all vars in the list
|
|
|
|
* of join clauses 'joinclauses' such that:
|
|
|
|
* (1) the var corresponding to the outer join relation is a
|
|
|
|
* key on the outer path
|
|
|
|
* (2) the var appears in the target list of the join relation
|
|
|
|
* In other words, add to each outer path key the inner path keys that
|
|
|
|
* are required for qualification.
|
|
|
|
*
|
1999-02-14 00:22:53 +01:00
|
|
|
* 'outer_pathkeys' is the list of the outer path's path keys
|
|
|
|
* 'join_rel_tlist' is the target list of the join relation
|
1996-07-09 08:22:35 +02:00
|
|
|
* 'joinclauses' is the list of restricting join clauses
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
|
|
|
* Returns the list of new path keys.
|
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1998-02-26 05:46:47 +01:00
|
|
|
List *
|
1997-09-08 23:56:23 +02:00
|
|
|
new_join_pathkeys(List *outer_pathkeys,
|
|
|
|
List *join_rel_tlist,
|
|
|
|
List *joinclauses)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
1999-02-22 06:26:58 +01:00
|
|
|
List *final_pathkeys = NIL;
|
1999-05-17 02:26:33 +02:00
|
|
|
List *i;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
|
|
|
foreach(i, outer_pathkeys)
|
|
|
|
{
|
1999-05-17 02:26:33 +02:00
|
|
|
List *outer_pathkey = lfirst(i);
|
|
|
|
List *new_pathkey;
|
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
new_pathkey = new_join_pathkey(outer_pathkey, join_rel_tlist,
|
1999-05-17 02:26:33 +02:00
|
|
|
joinclauses);
|
1999-02-22 06:26:58 +01:00
|
|
|
if (new_pathkey != NIL)
|
|
|
|
final_pathkeys = lappend(final_pathkeys, new_pathkey);
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
1999-02-22 06:26:58 +01:00
|
|
|
return final_pathkeys;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|
|
|
|
|
1997-09-07 07:04:48 +02:00
|
|
|
/*
|
1999-02-14 00:22:53 +01:00
|
|
|
* new_join_pathkey
|
1999-05-17 02:26:33 +02:00
|
|
|
* Generate an individual pathkey sublist, consisting of the outer vars
|
|
|
|
* already mentioned in 'pathkey' plus any inner vars that are joined to
|
|
|
|
* them (and thus can now also be considered path keys, per discussion
|
|
|
|
* at the top of this file).
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1999-02-22 06:26:58 +01:00
|
|
|
* Note that each returned pathkey is the var node found in
|
1999-02-14 00:22:53 +01:00
|
|
|
* 'join_rel_tlist' rather than the joinclause var node.
|
1999-05-25 18:15:34 +02:00
|
|
|
* (Is this important?) Also, we return a fully copied list
|
1999-05-17 02:26:33 +02:00
|
|
|
* that does not share any subnodes with existing data structures.
|
|
|
|
* (Is that important, either?)
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1999-05-17 02:26:33 +02:00
|
|
|
* Returns a new pathkey (list of pathkey variables).
|
1997-09-07 07:04:48 +02:00
|
|
|
*
|
1996-07-09 08:22:35 +02:00
|
|
|
*/
|
1997-09-08 04:41:22 +02:00
|
|
|
static List *
|
1999-02-22 06:26:58 +01:00
|
|
|
new_join_pathkey(List *pathkey,
|
1997-09-08 23:56:23 +02:00
|
|
|
List *join_rel_tlist,
|
|
|
|
List *joinclauses)
|
1996-07-09 08:22:35 +02:00
|
|
|
{
|
1999-05-17 02:26:33 +02:00
|
|
|
List *new_pathkey = NIL;
|
|
|
|
List *i,
|
|
|
|
*j;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
foreach(i, pathkey)
|
1997-09-07 07:04:48 +02:00
|
|
|
{
|
1999-02-22 06:26:58 +01:00
|
|
|
Var *key = (Var *) lfirst(i);
|
|
|
|
Expr *tlist_key;
|
|
|
|
|
|
|
|
Assert(key);
|
1999-05-25 18:15:34 +02:00
|
|
|
|
1999-02-22 06:26:58 +01:00
|
|
|
tlist_key = matching_tlist_var(key, join_rel_tlist);
|
1999-05-17 02:26:33 +02:00
|
|
|
if (tlist_key && !member(tlist_key, new_pathkey))
|
|
|
|
new_pathkey = lcons(copyObject(tlist_key), new_pathkey);
|
1996-07-09 08:22:35 +02:00
|
|
|
|
1999-05-17 02:26:33 +02:00
|
|
|
foreach(j, joinclauses)
|
|
|
|
{
|
|
|
|
Expr *joinclause = lfirst(j);
|
|
|
|
Expr *tlist_other_var;
|
1997-09-07 07:04:48 +02:00
|
|
|
|
1999-05-17 02:26:33 +02:00
|
|
|
tlist_other_var = matching_tlist_var(
|
1999-05-25 18:15:34 +02:00
|
|
|
other_join_clause_var(key, joinclause),
|
|
|
|
join_rel_tlist);
|
1999-05-17 02:26:33 +02:00
|
|
|
if (tlist_other_var && !member(tlist_other_var, new_pathkey))
|
|
|
|
new_pathkey = lcons(copyObject(tlist_other_var), new_pathkey);
|
1997-09-07 07:04:48 +02:00
|
|
|
}
|
|
|
|
}
|
1999-05-17 02:26:33 +02:00
|
|
|
|
|
|
|
return new_pathkey;
|
1996-07-09 08:22:35 +02:00
|
|
|
}
|