7
7
*
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -426,55 +426,55 @@ create_nestloop_node(NestPath *best_path,
426
426
Plan * inner_node ,
427
427
List * inner_tlist )
428
428
{
429
- NestLoop * join_node = ( NestLoop * ) NULL ;
429
+ NestLoop * join_node ;
430
430
431
431
if (IsA (inner_node ,IndexScan ))
432
432
{
433
-
434
433
/*
435
434
* 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 .
439
438
*
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...
462
448
*
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.
467
453
*/
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 )
469
459
{
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 ));
471
466
472
- clauses = set_difference (clauses ,inner_indxqual );/* XXX */
473
467
/* 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 );
478
478
}
479
479
}
480
480
else if (IsA_Join (inner_node ))
@@ -512,10 +512,10 @@ create_mergejoin_node(MergePath *best_path,
512
512
* mergeclauses ;
513
513
MergeJoin * join_node ;
514
514
515
-
516
515
/*
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.
519
519
*/
520
520
qpqual = join_references (set_difference (clauses ,
521
521
best_path -> path_mergeclauses ),
@@ -571,14 +571,6 @@ create_mergejoin_node(MergePath *best_path,
571
571
return join_node ;
572
572
}
573
573
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
- */
582
574
static HashJoin *
583
575
create_hashjoin_node (HashPath * best_path ,
584
576
List * tlist ,
@@ -595,8 +587,16 @@ create_hashjoin_node(HashPath *best_path,
595
587
Var * innerhashkey ;
596
588
597
589
/*
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.
600
600
*/
601
601
qpqual = join_references (set_difference (clauses ,
602
602
best_path -> path_hashclauses ),
@@ -611,8 +611,12 @@ create_hashjoin_node(HashPath *best_path,
611
611
outer_tlist ,
612
612
inner_tlist ));
613
613
614
+ /* Now the righthand op of the sole hashclause is the inner hash key. */
614
615
innerhashkey = get_rightop (lfirst (hashclauses ));
615
616
617
+ /*
618
+ * Build the hash node and hash join node.
619
+ */
616
620
hash_node = make_hash (inner_tlist ,innerhashkey ,inner_node );
617
621
join_node = make_hashjoin (tlist ,
618
622
qpqual ,
@@ -791,7 +795,7 @@ switch_outer(List *clauses)
791
795
Assert (is_opclause ((Node * )clause ));
792
796
op = (Node * )get_rightop (clause );
793
797
Assert (op != (Node * )NULL );
794
- if (IsA (op ,ArrayRef ))
798
+ if (IsA (op ,ArrayRef ))/* I think this test is dead code ... tgl */
795
799
op = ((ArrayRef * )op )-> refexpr ;
796
800
Assert (IsA (op ,Var ));
797
801
if (var_is_outer ((Var * )op ))