|
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 |
| -static List * |
106 |
| -MJFormSkipQual(List *qualList, char *replaceopname) |
| 103 | +static void |
| 104 | +MJFormSkipQuals(List *qualList, List **ltQuals, List **gtQuals) |
107 | 105 | {
|
108 |
| - List *qualCopy; |
109 |
| - List *qualcdr; |
110 |
| - Expr *qual; |
111 |
| - Oper *op; |
112 |
| - HeapTuple optup; |
113 |
| - Form_pg_operator opform; |
114 |
| - Oid oprleft, |
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 |
| - return qualCopy; |
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);
|
|
0 commit comments