Commit 184e7a73 authored by Tom Lane's avatar Tom Lane

Revise nodeMergejoin in light of example provided by Guillaume Smet.

When one side of the join has a NULL, we don't want to uselessly try
to match it against every remaining tuple of the other side.  While
at it, rewrite the comparison machinery to avoid multiple evaluations
of the left and right input expressions and to use a btree comparator
where available, instead of double operator calls.  Also revise the
state machine to eliminate redundant comparisons and hopefully make it
more readable too.
parent 2979334d
This diff is collapsed.
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/execdebug.h,v 1.26 2005/03/16 21:38:09 tgl Exp $
* $PostgreSQL: pgsql/src/include/executor/execdebug.h,v 1.27 2005/05/13 21:20:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -258,17 +258,14 @@ extern int NIndexTupleInserted;
#define MJ2_printf(s, p1, p2) printf(s, p1, p2)
#define MJ_debugtup(slot) debugtup(slot, NULL)
#define MJ_dump(state) ExecMergeTupleDump(state)
#define MJ_DEBUG_COMPARE(res) \
MJ1_printf(" MJCompare() returns %d\n", (res))
#define MJ_DEBUG_QUAL(clause, res) \
MJ2_printf(" ExecQual(%s, econtext) returns %s\n", \
CppAsString(clause), T_OR_F(res));
#define MJ_DEBUG_MERGE_COMPARE(qual, res) \
MJ2_printf(" MergeCompare(mergeclauses, %s, ...) returns %s\n", \
CppAsString(qual), T_OR_F(res));
CppAsString(clause), T_OR_F(res))
#define MJ_DEBUG_PROC_NODE(slot) \
MJ2_printf(" %s = ExecProcNode(...) returns %s\n", \
CppAsString(slot), NULL_OR_TUPLE(slot));
CppAsString(slot), NULL_OR_TUPLE(slot))
#else
......@@ -278,8 +275,8 @@ extern int NIndexTupleInserted;
#define MJ2_printf(s, p1, p2)
#define MJ_debugtup(slot)
#define MJ_dump(state)
#define MJ_DEBUG_COMPARE(res)
#define MJ_DEBUG_QUAL(clause, res)
#define MJ_DEBUG_MERGE_COMPARE(qual, res)
#define MJ_DEBUG_PROC_NODE(slot)
#endif /* EXEC_MERGEJOINDEBUG */
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/executor/execdefs.h,v 1.17 2004/12/31 22:03:29 pgsql Exp $
* $PostgreSQL: pgsql/src/include/executor/execdefs.h,v 1.18 2005/05/13 21:20:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -18,20 +18,16 @@
* Merge Join states
* ----------------
*/
#define EXEC_MJ_INITIALIZE 1
#define EXEC_MJ_JOINMARK 2
#define EXEC_MJ_JOINTEST 3
#define EXEC_MJ_JOINTUPLES 4
#define EXEC_MJ_NEXTOUTER 5
#define EXEC_MJ_TESTOUTER 6
#define EXEC_MJ_NEXTINNER 7
#define EXEC_MJ_SKIPOUTER_BEGIN 8
#define EXEC_MJ_SKIPOUTER_TEST 9
#define EXEC_MJ_SKIPOUTER_ADVANCE 10
#define EXEC_MJ_SKIPINNER_BEGIN 11
#define EXEC_MJ_SKIPINNER_TEST 12
#define EXEC_MJ_SKIPINNER_ADVANCE 13
#define EXEC_MJ_ENDOUTER 14
#define EXEC_MJ_ENDINNER 15
#define EXEC_MJ_INITIALIZE_OUTER 1
#define EXEC_MJ_INITIALIZE_INNER 2
#define EXEC_MJ_JOINTUPLES 3
#define EXEC_MJ_NEXTOUTER 4
#define EXEC_MJ_TESTOUTER 5
#define EXEC_MJ_NEXTINNER 6
#define EXEC_MJ_SKIP_TEST 7
#define EXEC_MJ_SKIPOUTER_ADVANCE 8
#define EXEC_MJ_SKIPINNER_ADVANCE 9
#define EXEC_MJ_ENDOUTER 10
#define EXEC_MJ_ENDINNER 11
#endif /* EXECDEFS_H */
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.131 2005/05/05 03:37:23 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.132 2005/05/13 21:20:16 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -1028,24 +1028,28 @@ typedef struct NestLoopState
/* ----------------
* MergeJoinState information
*
* OuterSkipQual outerKey1 < innerKey1 ...
* InnerSkipQual outerKey1 > innerKey1 ...
* JoinState current "state" of join. see executor.h
* NumClauses number of mergejoinable join clauses
* Clauses info for each mergejoinable clause
* JoinState current "state" of join. see execdefs.h
* MatchedOuter true if found a join match for current outer tuple
* MatchedInner true if found a join match for current inner tuple
* OuterTupleSlot pointer to slot in tuple table for cur outer tuple
* InnerTupleSlot pointer to slot in tuple table for cur inner tuple
* MarkedTupleSlot pointer to slot in tuple table for marked tuple
* OuterTupleSlot slot in tuple table for cur outer tuple
* InnerTupleSlot slot in tuple table for cur inner tuple
* MarkedTupleSlot slot in tuple table for marked tuple
* NullOuterTupleSlot prepared null tuple for right outer joins
* NullInnerTupleSlot prepared null tuple for left outer joins
* OuterEContext workspace for computing outer tuple's join values
* InnerEContext workspace for computing inner tuple's join values
* ----------------
*/
/* private in nodeMergejoin.c: */
typedef struct MergeJoinClauseData *MergeJoinClause;
typedef struct MergeJoinState
{
JoinState js; /* its first field is NodeTag */
List *mergeclauses; /* list of ExprState nodes */
List *mj_OuterSkipQual; /* list of ExprState nodes */
List *mj_InnerSkipQual; /* list of ExprState nodes */
int mj_NumClauses;
MergeJoinClause mj_Clauses; /* array of length mj_NumClauses */
int mj_JoinState;
bool mj_MatchedOuter;
bool mj_MatchedInner;
......@@ -1054,6 +1058,8 @@ typedef struct MergeJoinState
TupleTableSlot *mj_MarkedTupleSlot;
TupleTableSlot *mj_NullOuterTupleSlot;
TupleTableSlot *mj_NullInnerTupleSlot;
ExprContext *mj_OuterEContext;
ExprContext *mj_InnerEContext;
} MergeJoinState;
/* ----------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment