]> granicus.if.org Git - postgresql/commitdiff
Minor refactoring to eliminate duplicate code and make startup a
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 14 May 2005 21:29:23 +0000 (21:29 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 14 May 2005 21:29:23 +0000 (21:29 +0000)
tad faster.

src/backend/executor/nodeMergejoin.c
src/include/nodes/execnodes.h

index be4a97574e5faaf1dc9b1c62e15b984fa22df7fe..6eb2bcc364db7db1e75524da5ef1f4a5a8773941 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.72 2005/05/13 21:20:16 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.73 2005/05/14 21:29:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -525,6 +525,86 @@ MJCompare(MergeJoinState *mergestate)
        return result;
 }
 
+
+/*
+ * Generate a fake join tuple with nulls for the inner tuple,
+ * and return it if it passes the non-join quals.
+ */
+static TupleTableSlot *
+MJFillOuter(MergeJoinState *node)
+{
+       ExprContext *econtext = node->js.ps.ps_ExprContext;
+       List       *otherqual = node->js.ps.qual;
+
+       ResetExprContext(econtext);
+
+       econtext->ecxt_outertuple = node->mj_OuterTupleSlot;
+       econtext->ecxt_innertuple = node->mj_NullInnerTupleSlot;
+
+       if (ExecQual(otherqual, econtext, false))
+       {
+               /*
+                * qualification succeeded.  now form the desired projection tuple
+                * and return the slot containing it.
+                */
+               TupleTableSlot *result;
+               ExprDoneCond isDone;
+
+               MJ_printf("ExecMergeJoin: returning outer fill tuple\n");
+
+               result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
+
+               if (isDone != ExprEndResult)
+               {
+                       node->js.ps.ps_TupFromTlist =
+                               (isDone == ExprMultipleResult);
+                       return result;
+               }
+       }
+
+       return NULL;
+}
+
+/*
+ * Generate a fake join tuple with nulls for the outer tuple,
+ * and return it if it passes the non-join quals.
+ */
+static TupleTableSlot *
+MJFillInner(MergeJoinState *node)
+{
+       ExprContext *econtext = node->js.ps.ps_ExprContext;
+       List       *otherqual = node->js.ps.qual;
+
+       ResetExprContext(econtext);
+
+       econtext->ecxt_outertuple = node->mj_NullOuterTupleSlot;
+       econtext->ecxt_innertuple = node->mj_InnerTupleSlot;
+
+       if (ExecQual(otherqual, econtext, false))
+       {
+               /*
+                * qualification succeeded.  now form the desired projection tuple
+                * and return the slot containing it.
+                */
+               TupleTableSlot *result;
+               ExprDoneCond isDone;
+
+               MJ_printf("ExecMergeJoin: returning inner fill tuple\n");
+
+               result = ExecProject(node->js.ps.ps_ProjInfo, &isDone);
+
+               if (isDone != ExprEndResult)
+               {
+                       node->js.ps.ps_TupFromTlist =
+                               (isDone == ExprMultipleResult);
+                       return result;
+               }
+       }
+
+       return NULL;
+}
+
+
 /* ----------------------------------------------------------------
  *             ExecMergeTupleDump
  *
@@ -612,33 +692,8 @@ ExecMergeJoin(MergeJoinState *node)
        econtext = node->js.ps.ps_ExprContext;
        joinqual = node->js.joinqual;
        otherqual = node->js.ps.qual;
-
-       switch (node->js.jointype)
-       {
-               case JOIN_INNER:
-               case JOIN_IN:
-                       doFillOuter = false;
-                       doFillInner = false;
-                       break;
-               case JOIN_LEFT:
-                       doFillOuter = true;
-                       doFillInner = false;
-                       break;
-               case JOIN_FULL:
-                       doFillOuter = true;
-                       doFillInner = true;
-                       break;
-               case JOIN_RIGHT:
-                       doFillOuter = false;
-                       doFillInner = true;
-                       break;
-               default:
-                       elog(ERROR, "unrecognized join type: %d",
-                                (int) node->js.jointype);
-                       doFillOuter = false;    /* keep compiler quiet */
-                       doFillInner = false;
-                       break;
-       }
+       doFillOuter = node->mj_FillOuter;
+       doFillInner = node->mj_FillInner;
 
        /*
         * Check to see if we're still projecting out tuples from a previous
@@ -707,15 +762,27 @@ ExecMergeJoin(MergeJoinState *node)
                                }
 
                                /* Compute join values and check for unmatchability */
-                               if (!MJEvalOuterValues(node) && !doFillOuter)
+                               if (MJEvalOuterValues(node))
                                {
-                                       /* Stay in same state to fetch next outer tuple */
-                                       node->mj_JoinState = EXEC_MJ_INITIALIZE_OUTER;
+                                       /* OK to go get the first inner tuple */
+                                       node->mj_JoinState = EXEC_MJ_INITIALIZE_INNER;
                                }
                                else
                                {
-                                       /* OK to go get the first inner tuple */
-                                       node->mj_JoinState = EXEC_MJ_INITIALIZE_INNER;
+                                       /* Stay in same state to fetch next outer tuple */
+                                       if (doFillOuter)
+                                       {
+                                               /*
+                                                * Generate a fake join tuple with nulls for the inner
+                                                * tuple, and return it if it passes the non-join
+                                                * quals.
+                                                */
+                                               TupleTableSlot *result;
+
+                                               result = MJFillOuter(node);
+                                               if (result)
+                                                       return result;
+                                       }
                                }
                                break;
 
@@ -745,12 +812,7 @@ ExecMergeJoin(MergeJoinState *node)
                                }
 
                                /* Compute join values and check for unmatchability */
-                               if (!MJEvalInnerValues(node, innerTupleSlot) && !doFillInner)
-                               {
-                                       /* Stay in same state to fetch next inner tuple */
-                                       node->mj_JoinState = EXEC_MJ_INITIALIZE_INNER;
-                               }
-                               else
+                               if (MJEvalInnerValues(node, innerTupleSlot))
                                {
                                        /*
                                         * OK, we have the initial tuples.      Begin by skipping
@@ -758,6 +820,23 @@ ExecMergeJoin(MergeJoinState *node)
                                         */
                                        node->mj_JoinState = EXEC_MJ_SKIP_TEST;
                                }
+                               else
+                               {
+                                       /* Stay in same state to fetch next inner tuple */
+                                       if (doFillInner)
+                                       {
+                                               /*
+                                                * Generate a fake join tuple with nulls for the outer
+                                                * tuple, and return it if it passes the non-join
+                                                * quals.
+                                                */
+                                               TupleTableSlot *result;
+
+                                               result = MJFillInner(node);
+                                               if (result)
+                                                       return result;
+                                       }
+                               }
                                break;
 
                                /*
@@ -856,37 +935,13 @@ ExecMergeJoin(MergeJoinState *node)
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       node->mj_MatchedInner = true;           /* do it only once */
-
-                                       ResetExprContext(econtext);
-
-                                       outerTupleSlot = node->mj_NullOuterTupleSlot;
-                                       econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = node->mj_InnerTupleSlot;
-                                       econtext->ecxt_innertuple = innerTupleSlot;
+                                       TupleTableSlot *result;
 
-                                       if (ExecQual(otherqual, econtext, false))
-                                       {
-                                               /*
-                                                * qualification succeeded.  now form the desired
-                                                * projection tuple and return the slot containing
-                                                * it.
-                                                */
-                                               TupleTableSlot *result;
-                                               ExprDoneCond isDone;
-
-                                               MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
-                                               result = ExecProject(node->js.ps.ps_ProjInfo,
-                                                                                        &isDone);
+                                       node->mj_MatchedInner = true;           /* do it only once */
 
-                                               if (isDone != ExprEndResult)
-                                               {
-                                                       node->js.ps.ps_TupFromTlist =
-                                                               (isDone == ExprMultipleResult);
-                                                       return result;
-                                               }
-                                       }
+                                       result = MJFillInner(node);
+                                       if (result)
+                                               return result;
                                }
 
                                /*
@@ -961,37 +1016,13 @@ ExecMergeJoin(MergeJoinState *node)
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       node->mj_MatchedOuter = true;           /* do it only once */
+                                       TupleTableSlot *result;
 
-                                       ResetExprContext(econtext);
-
-                                       outerTupleSlot = node->mj_OuterTupleSlot;
-                                       econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = node->mj_NullInnerTupleSlot;
-                                       econtext->ecxt_innertuple = innerTupleSlot;
-
-                                       if (ExecQual(otherqual, econtext, false))
-                                       {
-                                               /*
-                                                * qualification succeeded.  now form the desired
-                                                * projection tuple and return the slot containing
-                                                * it.
-                                                */
-                                               TupleTableSlot *result;
-                                               ExprDoneCond isDone;
-
-                                               MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
-                                               result = ExecProject(node->js.ps.ps_ProjInfo,
-                                                                                        &isDone);
+                                       node->mj_MatchedOuter = true;           /* do it only once */
 
-                                               if (isDone != ExprEndResult)
-                                               {
-                                                       node->js.ps.ps_TupFromTlist =
-                                                               (isDone == ExprMultipleResult);
-                                                       return result;
-                                               }
-                                       }
+                                       result = MJFillOuter(node);
+                                       if (result)
+                                               return result;
                                }
 
                                /*
@@ -1223,37 +1254,13 @@ ExecMergeJoin(MergeJoinState *node)
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       node->mj_MatchedOuter = true;           /* do it only once */
-
-                                       ResetExprContext(econtext);
-
-                                       outerTupleSlot = node->mj_OuterTupleSlot;
-                                       econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = node->mj_NullInnerTupleSlot;
-                                       econtext->ecxt_innertuple = innerTupleSlot;
-
-                                       if (ExecQual(otherqual, econtext, false))
-                                       {
-                                               /*
-                                                * qualification succeeded.  now form the desired
-                                                * projection tuple and return the slot containing
-                                                * it.
-                                                */
-                                               TupleTableSlot *result;
-                                               ExprDoneCond isDone;
+                                       TupleTableSlot *result;
 
-                                               MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
-                                               result = ExecProject(node->js.ps.ps_ProjInfo,
-                                                                                        &isDone);
+                                       node->mj_MatchedOuter = true;           /* do it only once */
 
-                                               if (isDone != ExprEndResult)
-                                               {
-                                                       node->js.ps.ps_TupFromTlist =
-                                                               (isDone == ExprMultipleResult);
-                                                       return result;
-                                               }
-                                       }
+                                       result = MJFillOuter(node);
+                                       if (result)
+                                               return result;
                                }
 
                                /*
@@ -1311,37 +1318,13 @@ ExecMergeJoin(MergeJoinState *node)
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       node->mj_MatchedInner = true;           /* do it only once */
-
-                                       ResetExprContext(econtext);
-
-                                       outerTupleSlot = node->mj_NullOuterTupleSlot;
-                                       econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = node->mj_InnerTupleSlot;
-                                       econtext->ecxt_innertuple = innerTupleSlot;
-
-                                       if (ExecQual(otherqual, econtext, false))
-                                       {
-                                               /*
-                                                * qualification succeeded.  now form the desired
-                                                * projection tuple and return the slot containing
-                                                * it.
-                                                */
-                                               TupleTableSlot *result;
-                                               ExprDoneCond isDone;
+                                       TupleTableSlot *result;
 
-                                               MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
-                                               result = ExecProject(node->js.ps.ps_ProjInfo,
-                                                                                        &isDone);
+                                       node->mj_MatchedInner = true;           /* do it only once */
 
-                                               if (isDone != ExprEndResult)
-                                               {
-                                                       node->js.ps.ps_TupFromTlist =
-                                                               (isDone == ExprMultipleResult);
-                                                       return result;
-                                               }
-                                       }
+                                       result = MJFillInner(node);
+                                       if (result)
+                                               return result;
                                }
 
                                /*
@@ -1402,37 +1385,13 @@ ExecMergeJoin(MergeJoinState *node)
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       node->mj_MatchedInner = true;           /* do it only once */
-
-                                       ResetExprContext(econtext);
-
-                                       outerTupleSlot = node->mj_NullOuterTupleSlot;
-                                       econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = node->mj_InnerTupleSlot;
-                                       econtext->ecxt_innertuple = innerTupleSlot;
+                                       TupleTableSlot *result;
 
-                                       if (ExecQual(otherqual, econtext, false))
-                                       {
-                                               /*
-                                                * qualification succeeded.  now form the desired
-                                                * projection tuple and return the slot containing
-                                                * it.
-                                                */
-                                               TupleTableSlot *result;
-                                               ExprDoneCond isDone;
-
-                                               MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
-                                               result = ExecProject(node->js.ps.ps_ProjInfo,
-                                                                                        &isDone);
+                                       node->mj_MatchedInner = true;           /* do it only once */
 
-                                               if (isDone != ExprEndResult)
-                                               {
-                                                       node->js.ps.ps_TupFromTlist =
-                                                               (isDone == ExprMultipleResult);
-                                                       return result;
-                                               }
-                                       }
+                                       result = MJFillInner(node);
+                                       if (result)
+                                               return result;
                                }
 
                                /*
@@ -1469,37 +1428,13 @@ ExecMergeJoin(MergeJoinState *node)
                                         * tuple, and return it if it passes the non-join
                                         * quals.
                                         */
-                                       node->mj_MatchedOuter = true;           /* do it only once */
+                                       TupleTableSlot *result;
 
-                                       ResetExprContext(econtext);
-
-                                       outerTupleSlot = node->mj_OuterTupleSlot;
-                                       econtext->ecxt_outertuple = outerTupleSlot;
-                                       innerTupleSlot = node->mj_NullInnerTupleSlot;
-                                       econtext->ecxt_innertuple = innerTupleSlot;
-
-                                       if (ExecQual(otherqual, econtext, false))
-                                       {
-                                               /*
-                                                * qualification succeeded.  now form the desired
-                                                * projection tuple and return the slot containing
-                                                * it.
-                                                */
-                                               TupleTableSlot *result;
-                                               ExprDoneCond isDone;
-
-                                               MJ_printf("ExecMergeJoin: returning fill tuple\n");
-
-                                               result = ExecProject(node->js.ps.ps_ProjInfo,
-                                                                                        &isDone);
+                                       node->mj_MatchedOuter = true;           /* do it only once */
 
-                                               if (isDone != ExprEndResult)
-                                               {
-                                                       node->js.ps.ps_TupFromTlist =
-                                                               (isDone == ExprMultipleResult);
-                                                       return result;
-                                               }
-                                       }
+                                       result = MJFillOuter(node);
+                                       if (result)
+                                               return result;
                                }
 
                                /*
@@ -1601,13 +1536,19 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate)
        {
                case JOIN_INNER:
                case JOIN_IN:
+                       mergestate->mj_FillOuter = false;
+                       mergestate->mj_FillInner = false;
                        break;
                case JOIN_LEFT:
+                       mergestate->mj_FillOuter = true;
+                       mergestate->mj_FillInner = false;
                        mergestate->mj_NullInnerTupleSlot =
                                ExecInitNullTupleSlot(estate,
                                                  ExecGetResultType(innerPlanState(mergestate)));
                        break;
                case JOIN_RIGHT:
+                       mergestate->mj_FillOuter = false;
+                       mergestate->mj_FillInner = true;
                        mergestate->mj_NullOuterTupleSlot =
                                ExecInitNullTupleSlot(estate,
                                                  ExecGetResultType(outerPlanState(mergestate)));
@@ -1622,6 +1563,8 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate)
                                                 errmsg("RIGHT JOIN is only supported with merge-joinable join conditions")));
                        break;
                case JOIN_FULL:
+                       mergestate->mj_FillOuter = true;
+                       mergestate->mj_FillInner = true;
                        mergestate->mj_NullOuterTupleSlot =
                                ExecInitNullTupleSlot(estate,
                                                  ExecGetResultType(outerPlanState(mergestate)));
index 9d47c17ad23f687eb267765e69be24b4ab6806e8..b92eb1722f1c25ab53290d31676eb93ea5cc58f2 100644 (file)
@@ -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.132 2005/05/13 21:20:16 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.133 2005/05/14 21:29:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1031,6 +1031,8 @@ typedef struct NestLoopState
  *             NumClauses                 number of mergejoinable join clauses
  *             Clauses                    info for each mergejoinable clause
  *             JoinState                  current "state" of join.  see execdefs.h
+ *             FillOuter                  true if should emit unjoined outer tuples anyway
+ *             FillInner                  true if should emit unjoined inner tuples anyway
  *             MatchedOuter       true if found a join match for current outer tuple
  *             MatchedInner       true if found a join match for current inner tuple
  *             OuterTupleSlot     slot in tuple table for cur outer tuple
@@ -1051,6 +1053,8 @@ typedef struct MergeJoinState
        int                     mj_NumClauses;
        MergeJoinClause mj_Clauses;     /* array of length mj_NumClauses */
        int                     mj_JoinState;
+       bool            mj_FillOuter;
+       bool            mj_FillInner;
        bool            mj_MatchedOuter;
        bool            mj_MatchedInner;
        TupleTableSlot *mj_OuterTupleSlot;