77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.68 1999/08/09 06:20:26 momjian Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.69 1999/08/10 02:58:56 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -426,55 +426,55 @@ create_nestloop_node(NestPath *best_path,
426426Plan * inner_node ,
427427List * inner_tlist )
428428{
429- NestLoop * join_node = ( NestLoop * ) NULL ;
429+ NestLoop * join_node ;
430430
431431if (IsA (inner_node ,IndexScan ))
432432{
433-
434433/*
435434 * An index is being used to reduce the number of tuples scanned
436- * in the inner relation.There will never be more than one index
437- *used in theinner scan path, so weneed only consider the first
438- *set of qualifications in indxqual .
435+ * in the inner relation. If there are join clauses being used
436+ *with theindex, wemust update their outer-rel var nodes to
437+ *refer to the outer relation .
439438 *
440- * But there may be more than one clause in this "first set" in the
441- * case of multi-column indices. - vadim 03/18/97
442- */
443-
444- List * inner_indxqual = lfirst (((IndexScan * )inner_node )-> indxqual );
445- List * inner_qual ;
446- bool found = false;
447-
448- foreach (inner_qual ,inner_indxqual )
449- {
450- if (!qual_clause_p ((Node * )lfirst (inner_qual )))
451- {
452- found = true;
453- break ;
454- }
455- }
456-
457- /*
458- * If we have in fact found a join index qualification, remove
459- * these index clauses from the nestloop's join clauses and reset
460- * the inner(index) scan's qualification so that the var nodes
461- * refer to the proper outer join relation attributes.
439+ * We can also remove those join clauses from the list of clauses
440+ * that have to be checked as qpquals at the join node, but only
441+ * if there's just one indexscan in the inner path (otherwise,
442+ * several different sets of clauses are being ORed together).
443+ *
444+ * Note: if the index is lossy, the same clauses may also be getting
445+ * checked as qpquals in the indexscan. We can still remove them
446+ * from the nestloop's qpquals, but we gotta update the outer-rel
447+ * vars in the indexscan's qpquals too...
462448 *
463- * XXXRemoving index clauses doesn't work properly: 1.
464- *fix_indxqual_references may change varattno-s in
465- *inner_indxqual; 2. clauses may be commuted Ihavn't time tofix
466- *it at the moment. - vadim 04/24/97
449+ * XXXas of 8/99, removal of redundant joinclauses doesn't work
450+ *all the time, since it will fail to recognize clauses that have
451+ *been commuted in the indexqual. Ihope tomake this problem go
452+ *away soon by not commuting indexqual clauses --- tgl.
467453 */
468- if (found )
454+ IndexScan * innerscan = (IndexScan * )inner_node ;
455+ List * indxqualorig = innerscan -> indxqualorig ;
456+
457+ /* No work needed if indxqual refers only to its own relation... */
458+ if (NumRelids ((Node * )indxqualorig )> 1 )
469459{
470- List * new_inner_qual ;
460+ /* Remove redundant tests from my clauses, if possible.
461+ * Note we must compare against indxqualorig not the "fixed"
462+ * indxqual (which has index attnos instead of relation attnos).
463+ */
464+ if (length (indxqualorig )== 1 )/* single indexscan? */
465+ clauses = set_difference (clauses ,lfirst (indxqualorig ));
471466
472- clauses = set_difference (clauses ,inner_indxqual );/* XXX */
473467/* only refs to outer vars get changed in the inner indexqual */
474- new_inner_qual = join_references (inner_indxqual ,
475- outer_tlist ,
476- NIL );
477- ((IndexScan * )inner_node )-> indxqual = lcons (new_inner_qual ,NIL );
468+ innerscan -> indxqualorig = join_references (indxqualorig ,
469+ outer_tlist ,
470+ NIL );
471+ innerscan -> indxqual = join_references (innerscan -> indxqual ,
472+ outer_tlist ,
473+ NIL );
474+ if (NumRelids ((Node * )inner_node -> qual )> 1 )
475+ inner_node -> qual = join_references (inner_node -> qual ,
476+ outer_tlist ,
477+ NIL );
478478}
479479}
480480else if (IsA_Join (inner_node ))
@@ -512,10 +512,10 @@ create_mergejoin_node(MergePath *best_path,
512512* mergeclauses ;
513513MergeJoin * join_node ;
514514
515-
516515/*
517- * Separate the mergeclauses from the other join qualification clauses
518- * and set those clauses to contain references to lower attributes.
516+ * Remove the mergeclauses from the list of join qual clauses,
517+ * leaving the list of quals that must be checked as qpquals.
518+ * Set those clauses to contain INNER/OUTER var references.
519519 */
520520qpqual = join_references (set_difference (clauses ,
521521best_path -> path_mergeclauses ),
@@ -571,14 +571,6 @@ create_mergejoin_node(MergePath *best_path,
571571return join_node ;
572572}
573573
574- /*
575- * create_hashjoin_node--XXX HASH
576- *
577- * Returns a new hashjoin node.
578- *
579- * XXX hash join ops are totally bogus -- how the hell do we choose
580- *these?? at runtime? what about a hash index?
581- */
582574static HashJoin *
583575create_hashjoin_node (HashPath * best_path ,
584576List * tlist ,
@@ -595,8 +587,16 @@ create_hashjoin_node(HashPath *best_path,
595587Var * innerhashkey ;
596588
597589/*
598- * Separate the hashclauses from the other join qualification clauses
599- * and set those clauses to contain references to lower attributes.
590+ * NOTE: there will always be exactly one hashclause in the list
591+ * best_path->path_hashclauses (cf. hash_inner_and_outer()).
592+ * We represent it as a list anyway for convenience with routines
593+ * that want to work on lists of clauses.
594+ */
595+
596+ /*
597+ * Remove the hashclauses from the list of join qual clauses,
598+ * leaving the list of quals that must be checked as qpquals.
599+ * Set those clauses to contain INNER/OUTER var references.
600600 */
601601qpqual = join_references (set_difference (clauses ,
602602best_path -> path_hashclauses ),
@@ -611,8 +611,12 @@ create_hashjoin_node(HashPath *best_path,
611611outer_tlist ,
612612inner_tlist ));
613613
614+ /* Now the righthand op of the sole hashclause is the inner hash key. */
614615innerhashkey = get_rightop (lfirst (hashclauses ));
615616
617+ /*
618+ * Build the hash node and hash join node.
619+ */
616620hash_node = make_hash (inner_tlist ,innerhashkey ,inner_node );
617621join_node = make_hashjoin (tlist ,
618622qpqual ,
@@ -791,7 +795,7 @@ switch_outer(List *clauses)
791795Assert (is_opclause ((Node * )clause ));
792796op = (Node * )get_rightop (clause );
793797Assert (op != (Node * )NULL );
794- if (IsA (op ,ArrayRef ))
798+ if (IsA (op ,ArrayRef ))/* I think this test is dead code ... tgl */
795799op = ((ArrayRef * )op )-> refexpr ;
796800Assert (IsA (op ,Var ));
797801if (var_is_outer ((Var * )op ))