diff options
Diffstat (limited to 'src/backend/executor')
-rw-r--r-- | src/backend/executor/nodeMaterial.c | 36 | ||||
-rw-r--r-- | src/backend/executor/nodeMergejoin.c | 38 |
2 files changed, 58 insertions, 16 deletions
diff --git a/src/backend/executor/nodeMaterial.c b/src/backend/executor/nodeMaterial.c index 1cb4e63b975..e216c1f9e95 100644 --- a/src/backend/executor/nodeMaterial.c +++ b/src/backend/executor/nodeMaterial.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.58 2007/01/05 22:19:28 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeMaterial.c,v 1.59 2007/05/21 17:57:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -56,10 +56,10 @@ ExecMaterial(MaterialState *node) /* * If first time through, and we need a tuplestore, initialize it. */ - if (tuplestorestate == NULL && node->randomAccess) + if (tuplestorestate == NULL && node->eflags != 0) { tuplestorestate = tuplestore_begin_heap(true, false, work_mem); - + tuplestore_set_eflags(tuplestorestate, node->eflags); node->tuplestorestate = (void *) tuplestorestate; } @@ -162,14 +162,14 @@ ExecInitMaterial(Material *node, EState *estate, int eflags) matstate->ss.ps.state = estate; /* - * We must have random access to the subplan output to do backward scan or - * mark/restore. We also prefer to materialize the subplan output if we - * might be called on to rewind and replay it many times. However, if none - * of these cases apply, we can skip storing the data. + * We must have a tuplestore buffering the subplan output to do backward + * scan or mark/restore. We also prefer to materialize the subplan output + * if we might be called on to rewind and replay it many times. However, + * if none of these cases apply, we can skip storing the data. */ - matstate->randomAccess = (eflags & (EXEC_FLAG_REWIND | - EXEC_FLAG_BACKWARD | - EXEC_FLAG_MARK)) != 0; + matstate->eflags = (eflags & (EXEC_FLAG_REWIND | + EXEC_FLAG_BACKWARD | + EXEC_FLAG_MARK)); matstate->eof_underlying = false; matstate->tuplestorestate = NULL; @@ -255,7 +255,7 @@ ExecEndMaterial(MaterialState *node) void ExecMaterialMarkPos(MaterialState *node) { - Assert(node->randomAccess); + Assert(node->eflags & EXEC_FLAG_MARK); /* * if we haven't materialized yet, just return. @@ -275,7 +275,7 @@ ExecMaterialMarkPos(MaterialState *node) void ExecMaterialRestrPos(MaterialState *node) { - Assert(node->randomAccess); + Assert(node->eflags & EXEC_FLAG_MARK); /* * if we haven't materialized yet, just return. @@ -300,7 +300,7 @@ ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt) { ExecClearTuple(node->ss.ps.ps_ResultTupleSlot); - if (node->randomAccess) + if (node->eflags != 0) { /* * If we haven't materialized yet, just return. If outerplan' chgParam @@ -312,15 +312,21 @@ ExecMaterialReScan(MaterialState *node, ExprContext *exprCtxt) /* * If subnode is to be rescanned then we forget previous stored - * results; we have to re-read the subplan and re-store. + * results; we have to re-read the subplan and re-store. Also, + * if we told tuplestore it needn't support rescan, we lose and + * must re-read. (This last should not happen in common cases; + * else our caller lied by not passing EXEC_FLAG_REWIND to us.) * * Otherwise we can just rewind and rescan the stored output. The * state of the subnode does not change. */ - if (((PlanState *) node)->lefttree->chgParam != NULL) + if (((PlanState *) node)->lefttree->chgParam != NULL || + (node->eflags & EXEC_FLAG_REWIND) == 0) { tuplestore_end((Tuplestorestate *) node->tuplestorestate); node->tuplestorestate = NULL; + if (((PlanState *) node)->lefttree->chgParam == NULL) + ExecReScan(((PlanState *) node)->lefttree, exprCtxt); node->eof_underlying = false; } else diff --git a/src/backend/executor/nodeMergejoin.c b/src/backend/executor/nodeMergejoin.c index ad4aace6536..794871e5ba4 100644 --- a/src/backend/executor/nodeMergejoin.c +++ b/src/backend/executor/nodeMergejoin.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.87 2007/02/02 00:07:03 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeMergejoin.c,v 1.88 2007/05/21 17:57:33 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -706,6 +706,9 @@ ExecMergeJoin(MergeJoinState *node) } else { + /* Mark before advancing, if wanted */ + if (node->mj_ExtraMarks) + ExecMarkPos(innerPlan); /* Stay in same state to fetch next inner tuple */ if (doFillInner) { @@ -830,6 +833,9 @@ ExecMergeJoin(MergeJoinState *node) * now we get the next inner tuple, if any. If there's none, * advance to next outer tuple (which may be able to join to * previously marked tuples). + * + * NB: must NOT do "extraMarks" here, since we may need to + * return to previously marked tuples. */ innerTupleSlot = ExecProcNode(innerPlan); node->mj_InnerTupleSlot = innerTupleSlot; @@ -1140,6 +1146,9 @@ ExecMergeJoin(MergeJoinState *node) break; /* + * SKIPOUTER_ADVANCE: advance over an outer tuple that is + * known not to join to any inner tuple. + * * Before advancing, we check to see if we must emit an * outer-join fill tuple for this outer tuple. */ @@ -1204,6 +1213,9 @@ ExecMergeJoin(MergeJoinState *node) break; /* + * SKIPINNER_ADVANCE: advance over an inner tuple that is + * known not to join to any outer tuple. + * * Before advancing, we check to see if we must emit an * outer-join fill tuple for this inner tuple. */ @@ -1225,6 +1237,10 @@ ExecMergeJoin(MergeJoinState *node) return result; } + /* Mark before advancing, if wanted */ + if (node->mj_ExtraMarks) + ExecMarkPos(innerPlan); + /* * now we get the next inner tuple, if any */ @@ -1295,6 +1311,10 @@ ExecMergeJoin(MergeJoinState *node) return result; } + /* Mark before advancing, if wanted */ + if (node->mj_ExtraMarks) + ExecMarkPos(innerPlan); + /* * now we get the next inner tuple, if any */ @@ -1425,6 +1445,22 @@ ExecInitMergeJoin(MergeJoin *node, EState *estate, int eflags) innerPlanState(mergestate) = ExecInitNode(innerPlan(node), estate, eflags | EXEC_FLAG_MARK); + /* + * For certain types of inner child nodes, it is advantageous to issue + * MARK every time we advance past an inner tuple we will never return + * to. For other types, MARK on a tuple we cannot return to is a waste + * of cycles. Detect which case applies and set mj_ExtraMarks if we + * want to issue "unnecessary" MARK calls. + * + * Currently, only Material wants the extra MARKs, and it will be helpful + * only if eflags doesn't specify REWIND. + */ + if (IsA(innerPlan(node), Material) && + (eflags & EXEC_FLAG_REWIND) == 0) + mergestate->mj_ExtraMarks = true; + else + mergestate->mj_ExtraMarks = false; + #define MERGEJOIN_NSLOTS 4 /* |