|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * IDENTIFICATION |
11 | | - * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.47 2001/10/28 06:25:43 momjian Exp $ |
| 11 | + * $Header: /cvsroot/pgsql/src/backend/executor/nodeMergejoin.c,v 1.48 2002/03/01 04:09:22 tgl Exp $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
@@ -88,97 +88,62 @@ static bool MergeCompare(List *eqQual, List *compareQual, ExprContext *econtext) |
88 | 88 |
|
89 | 89 |
|
90 | 90 | /* ---------------------------------------------------------------- |
91 | | - *MJFormSkipQual |
| 91 | + *MJFormSkipQuals |
92 | 92 | * |
93 | 93 | *This takes the mergeclause which is a qualification of the |
94 | | - *form ((= expr expr) (= expr expr) ...) and forms a new |
95 | | - *qualification like ((> expr expr) (> expr expr) ...) which |
96 | | - *is used by ExecMergeJoin() in order to determine if we should |
97 | | - *skip tuples. The replacement operators are named either ">" |
98 | | - *or "<" according to the replaceopname parameter, and have the |
99 | | - *same operand data types as the "=" operators they replace. |
100 | | - *(We expect there to be such operators because the "=" operators |
| 94 | + *form ((= expr expr) (= expr expr) ...) and forms new lists |
| 95 | + *of the forms ((< expr expr) (< expr expr) ...) and |
| 96 | + *((> expr expr) (> expr expr) ...). These lists will be used |
| 97 | + *by ExecMergeJoin() to determine if we should skip tuples. |
| 98 | + *(We expect there to be suitable operators because the "=" operators |
101 | 99 | *were marked mergejoinable; however, there might be a different |
102 | 100 | *one needed in each qual clause.) |
103 | 101 | * ---------------------------------------------------------------- |
104 | 102 | */ |
105 | | -staticList* |
106 | | -MJFormSkipQual(List*qualList,char*replaceopname) |
| 103 | +staticvoid |
| 104 | +MJFormSkipQuals(List*qualList,List**ltQuals,List**gtQuals) |
107 | 105 | { |
108 | | -List*qualCopy; |
109 | | -List*qualcdr; |
110 | | -Expr*qual; |
111 | | -Oper*op; |
112 | | -HeapTupleoptup; |
113 | | -Form_pg_operatoropform; |
114 | | -Oidoprleft, |
115 | | -oprright; |
| 106 | +List*ltcdr, |
| 107 | +*gtcdr; |
116 | 108 |
|
117 | 109 | /* |
118 | | - * qualList is a list: ((op .. ..) ...) |
119 | | - * |
120 | | - * first we make a copy of it.copyObject() makes a deep copy so let's |
121 | | - * use it instead of the old fashoned lispCopy()... |
| 110 | + * Make modifiable copies of the qualList. |
122 | 111 | */ |
123 | | -qualCopy= (List*)copyObject((Node*)qualList); |
| 112 | +*ltQuals= (List*)copyObject((Node*)qualList); |
| 113 | +*gtQuals= (List*)copyObject((Node*)qualList); |
124 | 114 |
|
125 | | -foreach(qualcdr,qualCopy) |
| 115 | +/* |
| 116 | + * Scan both lists in parallel, so that we can update the operators |
| 117 | + * with the minimum number of syscache searches. |
| 118 | + */ |
| 119 | +ltcdr=*ltQuals; |
| 120 | +foreach(gtcdr,*gtQuals) |
126 | 121 | { |
127 | | -/* |
128 | | - * first get the current (op .. ..) list |
129 | | - */ |
130 | | -qual=lfirst(qualcdr); |
| 122 | +Expr*ltqual= (Expr*)lfirst(ltcdr); |
| 123 | +Expr*gtqual= (Expr*)lfirst(gtcdr); |
| 124 | +Oper*ltop= (Oper*)ltqual->oper; |
| 125 | +Oper*gtop= (Oper*)gtqual->oper; |
131 | 126 |
|
132 | 127 | /* |
133 | | - *now get at the op |
| 128 | + *The two ops should be identical, so use either one for lookup. |
134 | 129 | */ |
135 | | -op= (Oper*)qual->oper; |
136 | | -if (!IsA(op,Oper)) |
137 | | -elog(ERROR,"MJFormSkipQual: op not an Oper!"); |
| 130 | +if (!IsA(ltop,Oper)) |
| 131 | +elog(ERROR,"MJFormSkipQuals: op not an Oper!"); |
138 | 132 |
|
139 | 133 | /* |
140 | | - * Get the declared left and right operand types of the operator. |
141 | | - * Note we do *not* use the actual operand types, since those |
142 | | - * might be different in scenarios with binary-compatible data |
143 | | - * types. There should be "<" and ">" operators matching a |
144 | | - * mergejoinable "=" operator's declared operand types, but we |
145 | | - * might not find them if we search with the actual operand types. |
| 134 | + * Lookup the operators, and replace the data in the copied |
| 135 | + * operator nodes. |
146 | 136 | */ |
147 | | -optup=SearchSysCache(OPEROID, |
148 | | -ObjectIdGetDatum(op->opno), |
149 | | -0,0,0); |
150 | | -if (!HeapTupleIsValid(optup))/* shouldn't happen */ |
151 | | -elog(ERROR,"MJFormSkipQual: operator %u not found",op->opno); |
152 | | -opform= (Form_pg_operator)GETSTRUCT(optup); |
153 | | -oprleft=opform->oprleft; |
154 | | -oprright=opform->oprright; |
155 | | -ReleaseSysCache(optup); |
156 | | - |
157 | | -/* |
158 | | - * Now look up the matching "<" or ">" operator. If there isn't |
159 | | - * one, whoever marked the "=" operator mergejoinable was a loser. |
160 | | - */ |
161 | | -optup=SearchSysCache(OPERNAME, |
162 | | -PointerGetDatum(replaceopname), |
163 | | -ObjectIdGetDatum(oprleft), |
164 | | -ObjectIdGetDatum(oprright), |
165 | | -CharGetDatum('b')); |
166 | | -if (!HeapTupleIsValid(optup)) |
167 | | -elog(ERROR, |
168 | | -"MJFormSkipQual: mergejoin operator %u has no matching %s op", |
169 | | -op->opno,replaceopname); |
170 | | -opform= (Form_pg_operator)GETSTRUCT(optup); |
171 | | - |
172 | | -/* |
173 | | - * And replace the data in the copied operator node. |
174 | | - */ |
175 | | -op->opno=optup->t_data->t_oid; |
176 | | -op->opid=opform->oprcode; |
177 | | -op->op_fcache=NULL; |
178 | | -ReleaseSysCache(optup); |
| 137 | +op_mergejoin_crossops(ltop->opno, |
| 138 | +<op->opno, |
| 139 | +>op->opno, |
| 140 | +<op->opid, |
| 141 | +>op->opid); |
| 142 | +ltop->op_fcache=NULL; |
| 143 | +gtop->op_fcache=NULL; |
| 144 | + |
| 145 | +ltcdr=lnext(ltcdr); |
179 | 146 | } |
180 | | - |
181 | | -returnqualCopy; |
182 | 147 | } |
183 | 148 |
|
184 | 149 | /* ---------------------------------------------------------------- |
@@ -1430,7 +1395,6 @@ bool |
1430 | 1395 | ExecInitMergeJoin(MergeJoin*node,EState*estate,Plan*parent) |
1431 | 1396 | { |
1432 | 1397 | MergeJoinState*mergestate; |
1433 | | -List*joinclauses; |
1434 | 1398 |
|
1435 | 1399 | MJ1_printf("ExecInitMergeJoin: %s\n", |
1436 | 1400 | "initializing node"); |
@@ -1522,9 +1486,9 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, Plan *parent) |
1522 | 1486 | /* |
1523 | 1487 | * form merge skip qualifications |
1524 | 1488 | */ |
1525 | | -joinclauses=node->mergeclauses; |
1526 | | -mergestate->mj_OuterSkipQual=MJFormSkipQual(joinclauses,"<"); |
1527 | | -mergestate->mj_InnerSkipQual=MJFormSkipQual(joinclauses,">"); |
| 1489 | +MJFormSkipQuals(node->mergeclauses, |
| 1490 | +&mergestate->mj_OuterSkipQual, |
| 1491 | +&mergestate->mj_InnerSkipQual); |
1528 | 1492 |
|
1529 | 1493 | MJ_printf("\nExecInitMergeJoin: OuterSkipQual is "); |
1530 | 1494 | MJ_nodeDisplay(mergestate->mj_OuterSkipQual); |
|