]> granicus.if.org Git - postgresql/blob - src/backend/optimizer/path/mergeutils.c
Optimizer cleanup.
[postgresql] / src / backend / optimizer / path / mergeutils.c
1 /*-------------------------------------------------------------------------
2  *
3  * mergeutils.c--
4  *        Utilities for finding applicable merge clauses and pathkeys
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/optimizer/path/Attic/mergeutils.c,v 1.14 1999/02/08 04:29:12 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include "nodes/pg_list.h"
17 #include "nodes/relation.h"
18
19 #include "optimizer/internal.h"
20 #include "optimizer/paths.h"
21 #include "optimizer/clauses.h"
22 #include "optimizer/ordering.h"
23
24 /*
25  * group-clauses-by-order--
26  *        If a join clause node in 'restrictinfo-list' is mergejoinable, store
27  *        it within a mergeinfo node containing other clause nodes with the same
28  *        mergejoin ordering.
29  *
30  * 'restrictinfo-list' is the list of restrictinfo nodes
31  * 'inner-relid' is the relid of the inner join relation
32  *
33  * Returns the new list of mergeinfo nodes.
34  *
35  */
36 List *
37 group_clauses_by_order(List *restrictinfo_list,
38                                            int inner_relid)
39 {
40         List       *mergeinfo_list = NIL;
41         List       *xrestrictinfo = NIL;
42
43         foreach(xrestrictinfo, restrictinfo_list)
44         {
45                 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(xrestrictinfo);
46                 MergeOrder *merge_ordering = restrictinfo->mergejoinorder;
47
48                 if (merge_ordering)
49                 {
50
51                         /*
52                          * Create a new mergeinfo node and add it to 'mergeinfo-list'
53                          * if one does not yet exist for this merge ordering.
54                          */
55                         PathOrder       path_order;
56                         MergeInfo          *xmergeinfo;
57                         Expr       *clause = restrictinfo->clause;
58                         Var                *leftop = get_leftop(clause);
59                         Var                *rightop = get_rightop(clause);
60                         JoinKey    *keys;
61
62                         path_order.ordtype = MERGE_ORDER;
63                         path_order.ord.merge = merge_ordering;
64                         xmergeinfo = match_order_mergeinfo(&path_order, mergeinfo_list);
65                         if (inner_relid == leftop->varno)
66                         {
67                                 keys = makeNode(JoinKey);
68                                 keys->outer = rightop;
69                                 keys->inner = leftop;
70                         }
71                         else
72                         {
73                                 keys = makeNode(JoinKey);
74                                 keys->outer = leftop;
75                                 keys->inner = rightop;
76                         }
77
78                         if (xmergeinfo == NULL)
79                         {
80                                 xmergeinfo = makeNode(MergeInfo);
81
82                                 xmergeinfo->m_ordering = merge_ordering;
83                                 mergeinfo_list = lcons(xmergeinfo,
84                                                                            mergeinfo_list);
85                         }
86
87                         ((JoinMethod *) xmergeinfo)->clauses = lcons(clause,
88                                           ((JoinMethod *) xmergeinfo)->clauses);
89                         ((JoinMethod *) xmergeinfo)->jmkeys = lcons(keys,
90                                           ((JoinMethod *) xmergeinfo)->jmkeys);
91                 }
92         }
93         return mergeinfo_list;
94 }
95
96
97 /*
98  * match-order-mergeinfo--
99  *        Searches the list 'mergeinfo-list' for a mergeinfo node whose order
100  *        field equals 'ordering'.
101  *
102  * Returns the node if it exists.
103  *
104  */
105 MergeInfo *
106 match_order_mergeinfo(PathOrder *ordering, List *mergeinfo_list)
107 {
108         MergeOrder *xmergeorder;
109         List       *xmergeinfo = NIL;
110
111         foreach(xmergeinfo, mergeinfo_list)
112         {
113                 MergeInfo          *mergeinfo = (MergeInfo *) lfirst(xmergeinfo);
114
115                 xmergeorder = mergeinfo->m_ordering;
116
117                 if ((ordering->ordtype == MERGE_ORDER &&
118                  equal_merge_ordering(ordering->ord.merge, xmergeorder)) ||
119                         (ordering->ordtype == SORTOP_ORDER &&
120                    equal_path_merge_ordering(ordering->ord.sortop, xmergeorder)))
121                 {
122
123                         return mergeinfo;
124                 }
125         }
126         return (MergeInfo *) NIL;
127 }