77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.49 1999/02/21 03:48:45 scrappy Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.50 1999/03/01 00:10:33 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
4444#define NONAME_MATERIAL 2
4545
4646static List * switch_outer (List * clauses );
47+ static Oid * generate_merge_input_sortorder (List * pathkeys ,
48+ MergeOrder * mergeorder );
4749static Scan * create_scan_node (Path * best_path ,List * tlist );
4850static Join * create_join_node (JoinPath * best_path ,List * tlist );
4951static SeqScan * create_seqscan_node (Path * best_path ,List * tlist ,
@@ -70,8 +72,7 @@ static HashJoin *make_hashjoin(List *tlist, List *qpqual,
7072List * hashclauses ,Plan * lefttree ,Plan * righttree );
7173static Hash * make_hash (List * tlist ,Var * hashkey ,Plan * lefttree );
7274static MergeJoin * make_mergejoin (List * tlist ,List * qpqual ,
73- List * mergeclauses ,Oid opcode ,Oid * rightorder ,
74- Oid * leftorder ,Plan * righttree ,Plan * lefttree );
75+ List * mergeclauses ,Plan * righttree ,Plan * lefttree );
7576static Material * make_material (List * tlist ,Oid nonameid ,Plan * lefttree ,
7677int keycount );
7778
@@ -505,9 +506,6 @@ create_mergejoin_node(MergePath *best_path,
505506{
506507List * qpqual ,
507508* mergeclauses ;
508- RegProcedure opcode ;
509- Oid * outer_order ,
510- * inner_order ;
511509MergeJoin * join_node ;
512510
513511
@@ -528,50 +526,43 @@ create_mergejoin_node(MergePath *best_path,
528526outer_tlist ,
529527inner_tlist ));
530528
531- opcode = get_opcode ((best_path -> jpath .path .pathorder -> ord .merge )-> join_operator );
532-
533- outer_order = (Oid * )palloc (sizeof (Oid )* 2 );
534- outer_order [0 ]= (best_path -> jpath .path .pathorder -> ord .merge )-> left_operator ;
535- outer_order [1 ]= 0 ;
536-
537- inner_order = (Oid * )palloc (sizeof (Oid )* 2 );
538- inner_order [0 ]= (best_path -> jpath .path .pathorder -> ord .merge )-> right_operator ;
539- inner_order [1 ]= 0 ;
540-
541529/*
542530 * Create explicit sort paths for the outer and inner join paths if
543531 * necessary. The sort cost was already accounted for in the path.
544532 */
545533if (best_path -> outersortkeys )
546534{
535+ Oid * outer_order = generate_merge_input_sortorder (
536+ best_path -> outersortkeys ,
537+ best_path -> jpath .path .pathorder -> ord .merge );
547538Noname * sorted_outer_node = make_noname (outer_tlist ,
548- best_path -> outersortkeys ,
549- outer_order ,
550- outer_node ,
551- NONAME_SORT );
539+ best_path -> outersortkeys ,
540+ outer_order ,
541+ outer_node ,
542+ NONAME_SORT );
552543
553544sorted_outer_node -> plan .cost = outer_node -> cost ;
554545outer_node = (Plan * )sorted_outer_node ;
555546}
556547
557548if (best_path -> innersortkeys )
558549{
550+ Oid * inner_order = generate_merge_input_sortorder (
551+ best_path -> innersortkeys ,
552+ best_path -> jpath .path .pathorder -> ord .merge );
559553Noname * sorted_inner_node = make_noname (inner_tlist ,
560554best_path -> innersortkeys ,
561555inner_order ,
562556inner_node ,
563557NONAME_SORT );
564558
565- sorted_inner_node -> plan .cost = outer_node -> cost ;
559+ sorted_inner_node -> plan .cost = outer_node -> cost ;/* XXX not inner_node? */
566560inner_node = (Plan * )sorted_inner_node ;
567561}
568562
569563join_node = make_mergejoin (tlist ,
570564qpqual ,
571565mergeclauses ,
572- opcode ,
573- inner_order ,
574- outer_order ,
575566inner_node ,
576567outer_node );
577568
@@ -662,7 +653,7 @@ fix_indxqual_references(Node *clause, Path *index_path)
662653pos ++ ;
663654}
664655}
665- newclause = copyObject (( Node * ) clause );
656+ newclause = copyObject (clause );
666657((Var * )newclause )-> varattno = pos + 1 ;
667658return newclause ;
668659}
@@ -760,35 +751,39 @@ fix_indxqual_references(Node *clause, Path *index_path)
760751 * switch_outer
761752 * Given a list of merge clauses, rearranges the elements within the
762753 * clauses so the outer join variable is on the left and the inner is on
763- * the right.
764- *
765- * Returns the rearranged list ?
766- *
767- * XXX Shouldn't the operator be commuted?!
754+ * the right. The original list is not touched; a modified list
755+ * is returned.
768756 */
769757static List *
770758switch_outer (List * clauses )
771759{
772760List * t_list = NIL ;
773- Expr * temp = NULL ;
774- List * i = NIL ;
761+ Expr * temp ;
762+ List * i ;
775763Expr * clause ;
776764Node * op ;
777765
778766foreach (i ,clauses )
779767{
780768clause = lfirst (i );
769+ Assert (is_opclause ((Node * )clause ));
781770op = (Node * )get_rightop (clause );
782771Assert (op != (Node * )NULL );
783772if (IsA (op ,ArrayRef ))
784773op = ((ArrayRef * )op )-> refexpr ;
785774Assert (IsA (op ,Var ));
786775if (var_is_outer ((Var * )op ))
787776{
777+ /* Duplicate just enough of the structure to allow commuting
778+ * the clause without changing the original list. Could use
779+ * copyObject, but a complete deep copy is overkill.
780+ */
788781temp = make_clause (clause -> opType ,clause -> oper ,
789- lcons (get_rightop (clause ),
790- lcons (get_leftop (clause ),
782+ lcons (get_leftop (clause ),
783+ lcons (get_rightop (clause ),
791784NIL )));
785+ /* Commute it --- note this modifies the temp node in-place. */
786+ CommuteClause ((Node * )temp );
792787t_list = lappend (t_list ,temp );
793788}
794789else
@@ -797,6 +792,45 @@ switch_outer(List *clauses)
797792return t_list ;
798793}
799794
795+ /*
796+ * generate_merge_input_sortorder
797+ *
798+ * Generate the list of sort ops needed to sort one of the input paths for
799+ * a merge. We may have to use either left or right sortop for each item,
800+ * since the original mergejoin clause may or may not have been commuted
801+ * (compare switch_outer above).
802+ *
803+ * XXX This is largely a crock. It works only because group_clauses_by_order
804+ * only groups together mergejoin clauses that have identical MergeOrder info,
805+ * which means we can safely use a single MergeOrder input to deal with all
806+ * the data. There should be a more general data structure that allows coping
807+ * with groups of mergejoin clauses that have different join operators.
808+ */
809+ static Oid *
810+ generate_merge_input_sortorder (List * pathkeys ,MergeOrder * mergeorder )
811+ {
812+ int listlength = length (pathkeys );
813+ Oid * result = (Oid * )palloc (sizeof (Oid )* (listlength + 1 ));
814+ Oid * nextsortop = result ;
815+ List * p ;
816+
817+ foreach (p ,pathkeys )
818+ {
819+ Var * pkey = (Var * )lfirst ((List * )lfirst (p ));
820+ Assert (IsA (pkey ,Var ));
821+ if (pkey -> vartype == mergeorder -> left_type )
822+ * nextsortop ++ = mergeorder -> left_operator ;
823+ else if (pkey -> vartype == mergeorder -> right_type )
824+ * nextsortop ++ = mergeorder -> right_operator ;
825+ else
826+ elog (ERROR ,
827+ "generate_merge_input_sortorder: can't handle data type %d" ,
828+ pkey -> vartype );
829+ }
830+ * nextsortop ++ = InvalidOid ;
831+ return result ;
832+ }
833+
800834/*
801835 * set_noname_tlist_operators
802836 * Sets the key and keyop fields of resdom nodes in a target list.
@@ -806,18 +840,16 @@ switch_outer(List *clauses)
806840 *corresponding to vars in the target list that are to
807841 *be sorted or hashed
808842 * 'operators' is the corresponding list of N sort or hash operators
809- * 'keyno' is the first key number
810- * XXX - keyno ? doesn't exist - jeff
811843 *
812- * Returns the modified target list.
844+ * Returns the modified-in-place target list.
813845 */
814846static List *
815847set_noname_tlist_operators (List * tlist ,List * pathkeys ,Oid * operators )
816848{
817- Node * pathkey = NULL ;
818849int keyno = 1 ;
819- Resdom * resdom = (Resdom * )NULL ;
820- List * i = NIL ;
850+ Node * pathkey ;
851+ Resdom * resdom ;
852+ List * i ;
821853
822854foreach (i ,pathkeys )
823855{
@@ -828,12 +860,9 @@ set_noname_tlist_operators(List *tlist, List *pathkeys, Oid *operators)
828860/*
829861 * Order the resdom pathkey and replace the operator OID for each
830862 * key with the regproc OID.
831- *
832- * XXX Note that the optimizer only generates merge joins with 1
833- * operator (see create_mergejoin_node) - ay 2/95
834863 */
835864resdom -> reskey = keyno ;
836- resdom -> reskeyop = get_opcode (operators [0 ]);
865+ resdom -> reskeyop = get_opcode (operators [keyno - 1 ]);
837866}
838867keyno += 1 ;
839868}
@@ -1024,9 +1053,6 @@ static MergeJoin *
10241053make_mergejoin (List * tlist ,
10251054List * qpqual ,
10261055List * mergeclauses ,
1027- Oid opcode ,
1028- Oid * rightorder ,
1029- Oid * leftorder ,
10301056Plan * righttree ,
10311057Plan * lefttree )
10321058{
@@ -1041,9 +1067,6 @@ make_mergejoin(List *tlist,
10411067plan -> lefttree = lefttree ;
10421068plan -> righttree = righttree ;
10431069node -> mergeclauses = mergeclauses ;
1044- node -> mergejoinop = opcode ;
1045- node -> mergerightorder = rightorder ;
1046- node -> mergeleftorder = leftorder ;
10471070
10481071return node ;
10491072}