Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitad429fe

Browse files
committed
Teach nodeMergejoin how to handle DESC and/or NULLS FIRST sort orders.
So far only tested by hacking the planner ...
1 parent5b88b85 commitad429fe

File tree

1 file changed

+55
-77
lines changed

1 file changed

+55
-77
lines changed

‎src/backend/executor/nodeMergejoin.c

Lines changed: 55 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.85 2007/01/10 18:06:02 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.86 2007/01/11 17:19:13 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -39,12 +39,13 @@
3939
*therefore it should scan the outer relation first to find a
4040
*matching tuple and so on.
4141
*
42-
*Therefore, when initializing the merge-join node, we look up the
43-
*associated sort operators.We assume the planner has seen to it
44-
*that the inputs are correctly sorted by these operators. Rather
45-
*than directly executing the merge join clauses, we evaluate the
46-
*left and right key expressions separately and then compare the
47-
*columns one at a time (see MJCompare).
42+
*Therefore, rather than directly executing the merge join clauses,
43+
*we evaluate the left and right key expressions separately and then
44+
*compare the columns one at a time (see MJCompare). The planner
45+
*passes us enough information about the sort ordering of the inputs
46+
*to allow us to determine how to make the comparison. We may use the
47+
*appropriate btree comparison function, since Postgres' only notion
48+
*of ordering is specified by btree opfamilies.
4849
*
4950
*
5051
*Consider the above relations and suppose that the executor has
@@ -104,19 +105,8 @@
104105

105106

106107
/*
107-
* Comparison strategies supported by MJCompare
108-
*
109-
* XXX eventually should extend MJCompare to support descending-order sorts.
110-
* There are some tricky issues however about being sure we are on the same
111-
* page as the underlying sort or index as to which end NULLs sort to.
108+
* Runtime data for each mergejoin clause
112109
*/
113-
typedefenum
114-
{
115-
MERGEFUNC_CMP,/* -1 / 0 / 1 three-way comparator */
116-
MERGEFUNC_REV_CMP/* same, reversing the sense of the result */
117-
}MergeFunctionKind;
118-
119-
/* Runtime data for each mergejoin clause */
120110
typedefstructMergeJoinClauseData
121111
{
122112
/* Executable expression trees */
@@ -136,7 +126,8 @@ typedef struct MergeJoinClauseData
136126
* The comparison strategy in use, and the lookup info to let us call the
137127
* btree comparison support function.
138128
*/
139-
MergeFunctionKindcmpstrategy;
129+
boolreverse;/* if true, negate the cmpfn's output */
130+
boolnulls_first;/* if true, nulls sort low */
140131
FmgrInfocmpfinfo;
141132
}MergeJoinClauseData;
142133

@@ -158,11 +149,11 @@ typedef struct MergeJoinClauseData
158149
* In addition to the expressions themselves, the planner passes the btree
159150
* opfamily OID, btree strategy number (BTLessStrategyNumber or
160151
* BTGreaterStrategyNumber), and nulls-first flag that identify the intended
161-
*merge semantics for each merge key. The mergejoinable operator is an
152+
*sort ordering for each merge key. The mergejoinable operator is an
162153
* equality operator in this opfamily, and the two inputs are guaranteed to be
163154
* ordered in either increasing or decreasing (respectively) order according
164-
* to this opfamily. This allows us to obtaintheneeded comparison functions
165-
* from the opfamily.
155+
* to this opfamily, with nulls at the indicated end oftherange. This
156+
*allows us to obtain the needed comparison functionfrom the opfamily.
166157
*/
167158
staticMergeJoinClause
168159
MJExamineQuals(List*mergeclauses,
@@ -193,11 +184,6 @@ MJExamineQuals(List *mergeclauses,
193184
RegProcedurecmpproc;
194185
AclResultaclresult;
195186

196-
/* Later we'll support both ascending and descending sort... */
197-
Assert(opstrategy==BTLessStrategyNumber);
198-
clause->cmpstrategy=MERGEFUNC_CMP;
199-
Assert(!nulls_first);
200-
201187
if (!IsA(qual,OpExpr))
202188
elog(ERROR,"mergejoin clause is not an OpExpr");
203189

@@ -213,15 +199,19 @@ MJExamineQuals(List *mergeclauses,
213199
&op_lefttype,
214200
&op_righttype,
215201
&op_recheck);
216-
Assert(op_strategy==BTEqualStrategyNumber);
217-
Assert(!op_recheck);
202+
if (op_strategy!=BTEqualStrategyNumber)/* should not happen */
203+
elog(ERROR,"cannot merge using non-equality operator %u",
204+
qual->opno);
205+
Assert(!op_recheck);/* never true for btree */
218206

219207
/* And get the matching support procedure (comparison function) */
220208
cmpproc=get_opfamily_proc(opfamily,
221209
op_lefttype,
222210
op_righttype,
223211
BTORDER_PROC);
224-
Assert(RegProcedureIsValid(cmpproc));
212+
if (!RegProcedureIsValid(cmpproc))/* should not happen */
213+
elog(ERROR,"missing support function %d(%u,%u) in opfamily %u",
214+
BTORDER_PROC,op_lefttype,op_righttype,opfamily);
225215

226216
/* Check permission to call cmp function */
227217
aclresult=pg_proc_aclcheck(cmpproc,GetUserId(),ACL_EXECUTE);
@@ -232,6 +222,16 @@ MJExamineQuals(List *mergeclauses,
232222
/* Set up the fmgr lookup information */
233223
fmgr_info(cmpproc,&(clause->cmpfinfo));
234224

225+
/* Fill the additional comparison-strategy flags */
226+
if (opstrategy==BTLessStrategyNumber)
227+
clause->reverse= false;
228+
elseif (opstrategy==BTGreaterStrategyNumber)
229+
clause->reverse= true;
230+
else/* planner screwed up */
231+
elog(ERROR,"unsupported mergejoin strategy %d",opstrategy);
232+
233+
clause->nulls_first=nulls_first;
234+
235235
iClause++;
236236
}
237237

@@ -324,10 +324,10 @@ MJEvalInnerValues(MergeJoinState *mergestate, TupleTableSlot *innerslot)
324324
* MJEvalOuterValues and MJEvalInnerValues must already have been called
325325
* for the current outer and inner tuples, respectively.
326326
*/
327-
staticint
327+
staticint32
328328
MJCompare(MergeJoinState*mergestate)
329329
{
330-
intresult=0;
330+
int32result=0;
331331
boolnulleqnull= false;
332332
ExprContext*econtext=mergestate->js.ps.ps_ExprContext;
333333
inti;
@@ -348,26 +348,33 @@ MJCompare(MergeJoinState *mergestate)
348348
Datumfresult;
349349

350350
/*
351-
* Deal with null inputs. We treat NULL as sorting after non-NULL.
351+
* Deal with null inputs.
352352
*/
353353
if (clause->lisnull)
354354
{
355355
if (clause->risnull)
356356
{
357-
nulleqnull= true;
357+
nulleqnull= true;/* NULL "=" NULL */
358358
continue;
359359
}
360-
/* NULL > non-NULL */
361-
result=1;
360+
if (clause->nulls_first)
361+
result=-1;/* NULL "<" NOT_NULL */
362+
else
363+
result=1;/* NULL ">" NOT_NULL */
362364
break;
363365
}
364366
if (clause->risnull)
365367
{
366-
/* non-NULL < NULL */
367-
result=-1;
368+
if (clause->nulls_first)
369+
result=1;/* NOT_NULL ">" NULL */
370+
else
371+
result=-1;/* NOT_NULL "<" NULL */
368372
break;
369373
}
370374

375+
/*
376+
* OK to call the comparison function.
377+
*/
371378
InitFunctionCallInfoData(fcinfo,&(clause->cmpfinfo),2,
372379
NULL,NULL);
373380
fcinfo.arg[0]=clause->ldatum;
@@ -377,45 +384,16 @@ MJCompare(MergeJoinState *mergestate)
377384
fresult=FunctionCallInvoke(&fcinfo);
378385
if (fcinfo.isnull)
379386
{
380-
nulleqnull= true;
381-
continue;
382-
}
383-
if (DatumGetInt32(fresult)==0)
384-
{
385-
/* equal */
387+
nulleqnull= true;/* treat like NULL = NULL */
386388
continue;
387389
}
388-
if (clause->cmpstrategy==MERGEFUNC_CMP)
389-
{
390-
if (DatumGetInt32(fresult)<0)
391-
{
392-
/* less than */
393-
result=-1;
394-
break;
395-
}
396-
else
397-
{
398-
/* greater than */
399-
result=1;
400-
break;
401-
}
402-
}
403-
else
404-
{
405-
/* reverse the sort order */
406-
if (DatumGetInt32(fresult)>0)
407-
{
408-
/* less than */
409-
result=-1;
410-
break;
411-
}
412-
else
413-
{
414-
/* greater than */
415-
result=1;
416-
break;
417-
}
418-
}
390+
result=DatumGetInt32(fresult);
391+
392+
if (clause->reverse)
393+
result=-result;
394+
395+
if (result!=0)
396+
break;
419397
}
420398

421399
/*
@@ -581,7 +559,7 @@ ExecMergeJoin(MergeJoinState *node)
581559
List*joinqual;
582560
List*otherqual;
583561
boolqualResult;
584-
intcompareResult;
562+
int32compareResult;
585563
PlanState*innerPlan;
586564
TupleTableSlot*innerTupleSlot;
587565
PlanState*outerPlan;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp