|
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);
|
|