77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.4 1999/02/2018:01:01 momjian Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.5 1999/02/2019:02:41 momjian Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -54,7 +54,19 @@ static List *new_matching_subkeys(Var *subkey, List *considered_subkeys,
5454 *{ {tab1.col1, tab2.col1} }. This allows future joins to use either Var
5555 *as a pre-sorted key to prevent Mergejoins from having to re-sort the Path.
5656 *They are equal, so they are both primary sort keys. This is why pathkeys
57- *is a List of Lists. -- bjm
57+ *is a List of Lists.
58+ *
59+ *For multi-key sorts, if the outer is sorted by a multi-key index, the
60+ *multi-key index remains after the join. If the inner has a multi-key
61+ *sort, only the primary key of the inner is added to the result.
62+ *Mergejoins only join on the primary key. Currently, non-primary keys
63+ *in the pathkeys List are of limited value.
64+ *
65+ *HashJoin has similar functionality. NestJoin does not perform sorting,
66+ *and allows non-equajoins, so it does not allow useful pathkeys.
67+ *
68+ *-- bjm
69+ *
5870 */
5971
6072/****************************************************************************
@@ -92,17 +104,21 @@ static List *new_matching_subkeys(Var *subkey, List *considered_subkeys,
92104 */
93105List *
94106order_joinkeys_by_pathkeys (List * pathkeys ,
95- List * joinkeys ,
96- List * joinclauses ,
97- int outer_or_inner ,
98- List * * matchedJoinClausesPtr )
107+ List * joinkeys ,
108+ List * joinclauses ,
109+ int outer_or_inner ,
110+ List * * matchedJoinClausesPtr )
99111{
100112List * matched_joinkeys = NIL ;
101113List * matched_joinclauses = NIL ;
102114List * pathkey = NIL ;
103115List * i = NIL ;
104116int matched_joinkey_index = -1 ;
105117
118+ /*
119+ *Reorder the joinkeys by picking out one that matches each pathkey,
120+ *and create a new joinkey/joinclause list in pathkey order
121+ */
106122foreach (i ,pathkeys )
107123{
108124pathkey = lfirst (i );
@@ -118,10 +134,18 @@ order_joinkeys_by_pathkeys(List *pathkeys,
118134matched_joinclauses = lappend (matched_joinclauses ,joinclause );
119135}
120136else
121- {
137+ /*A pathkey could not be matched. */
138+ break ;
139+ }
140+
141+ /*
142+ *Did we fail to match all the joinkeys?
143+ *Extra pathkeys are no problem.
144+ */
145+ if (length (joinkeys )!= length (matched_joinkeys ))
146+ {
122147* matchedJoinClausesPtr = NIL ;
123148return NIL ;
124- }
125149}
126150
127151* matchedJoinClausesPtr = matched_joinclauses ;
@@ -133,6 +157,8 @@ order_joinkeys_by_pathkeys(List *pathkeys,
133157 * match_pathkey_joinkeys
134158 * Returns the 0-based index into 'joinkeys' of the first joinkey whose
135159 * outer or inner subkey matches any subkey of 'pathkey'.
160+ *
161+ *All these keys are equivalent, so any of them can match. See above.
136162 */
137163static int
138164match_pathkey_joinkeys (List * pathkey ,
@@ -141,8 +167,7 @@ match_pathkey_joinkeys(List *pathkey,
141167{
142168Var * path_subkey ;
143169int pos ;
144- List * i = NIL ;
145- List * x = NIL ;
170+ List * i ,* x ;
146171JoinKey * jk ;
147172
148173foreach (i ,pathkey )
@@ -152,8 +177,7 @@ match_pathkey_joinkeys(List *pathkey,
152177foreach (x ,joinkeys )
153178{
154179jk = (JoinKey * )lfirst (x );
155- if (var_equal (path_subkey ,
156- extract_join_key (jk ,outer_or_inner )))
180+ if (var_equal (path_subkey ,extract_join_key (jk ,outer_or_inner )))
157181return pos ;
158182pos ++ ;
159183}