aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execMain.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2008-07-26 19:15:35 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2008-07-26 19:15:35 +0000
commita77eaa6a95009a3441e0d475d1980259d45da072 (patch)
treee1f8f0f7e915ad440d9f7407a80d7b452034b133 /src/backend/executor/execMain.c
parent94be06af76ac85e362c42bff5824a5cd04860934 (diff)
downloadpostgresql-a77eaa6a95009a3441e0d475d1980259d45da072.tar.gz
postgresql-a77eaa6a95009a3441e0d475d1980259d45da072.zip
As noted by Andrew Gierth, there's really no need any more to force a junk
filter to be used when INSERT or SELECT INTO has a plan that returns raw disk tuples. The virtual-tuple-slot optimizations that were put in place awhile ago mean that ExecInsert has to do ExecMaterializeSlot, and that already copies the tuple if it's raw (and does so more efficiently than a junk filter, too). So get rid of that logic. This in turn means that we can throw away ExecMayReturnRawTuples, which wasn't used for any other purpose, and was always a kluge anyway. In passing, move a couple of SELECT-INTO-specific fields out of EState and into the private state of the SELECT INTO DestReceiver, as was foreseen in an old comment there. Also make intorel_receive use ExecMaterializeSlot not ExecCopySlotTuple, for consistency with ExecInsert and to possibly save a tuple copy step in some cases.
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r--src/backend/executor/execMain.c68
1 files changed, 29 insertions, 39 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 93f78046707..4a4c9188578 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.310 2008/07/18 18:23:46 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.311 2008/07/26 19:15:35 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -694,9 +694,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
/*
* Initialize the junk filter if needed. SELECT and INSERT queries need a
- * filter if there are any junk attrs in the tlist. INSERT and SELECT
- * INTO also need a filter if the plan may return raw disk tuples (else
- * heap_insert will be scribbling on the source relation!). UPDATE and
+ * filter if there are any junk attrs in the tlist. UPDATE and
* DELETE always need a filter, since there's always a junk 'ctid'
* attribute present --- no need to look first.
*/
@@ -718,10 +716,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
break;
}
}
- if (!junk_filter_needed &&
- (operation == CMD_INSERT || estate->es_select_into) &&
- ExecMayReturnRawTuples(planstate))
- junk_filter_needed = true;
break;
case CMD_UPDATE:
case CMD_DELETE:
@@ -2424,8 +2418,6 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
epqstate->es_result_relation_info = estate->es_result_relation_info;
epqstate->es_junkFilter = estate->es_junkFilter;
/* es_trig_target_relations must NOT be copied */
- epqstate->es_into_relation_descriptor = estate->es_into_relation_descriptor;
- epqstate->es_into_relation_use_wal = estate->es_into_relation_use_wal;
epqstate->es_param_list_info = estate->es_param_list_info;
if (estate->es_plannedstmt->nParamExec > 0)
epqstate->es_param_exec_vals = (ParamExecData *)
@@ -2559,15 +2551,14 @@ ExecGetActivePlanTree(QueryDesc *queryDesc)
*
* We implement SELECT INTO by diverting SELECT's normal output with
* a specialized DestReceiver type.
- *
- * TODO: remove some of the INTO-specific cruft from EState, and keep
- * it in the DestReceiver instead.
*/
typedef struct
{
DestReceiver pub; /* publicly-known function pointers */
EState *estate; /* EState we are working with */
+ Relation rel; /* Relation to write to */
+ bool use_wal; /* do we need to WAL-log our writes? */
} DR_intorel;
/*
@@ -2692,15 +2683,6 @@ OpenIntoRel(QueryDesc *queryDesc)
*/
intoRelationDesc = heap_open(intoRelationId, AccessExclusiveLock);
- /* use_wal off requires rd_targblock be initially invalid */
- Assert(intoRelationDesc->rd_targblock == InvalidBlockNumber);
-
- /*
- * We can skip WAL-logging the insertions, unless PITR is in use.
- */
- estate->es_into_relation_use_wal = XLogArchivingActive();
- estate->es_into_relation_descriptor = intoRelationDesc;
-
/*
* Now replace the query's DestReceiver with one for SELECT INTO
*/
@@ -2708,6 +2690,15 @@ OpenIntoRel(QueryDesc *queryDesc)
myState = (DR_intorel *) queryDesc->dest;
Assert(myState->pub.mydest == DestIntoRel);
myState->estate = estate;
+
+ /*
+ * We can skip WAL-logging the insertions, unless PITR is in use.
+ */
+ myState->use_wal = XLogArchivingActive();
+ myState->rel = intoRelationDesc;
+
+ /* use_wal off requires rd_targblock be initially invalid */
+ Assert(intoRelationDesc->rd_targblock == InvalidBlockNumber);
}
/*
@@ -2716,19 +2707,19 @@ OpenIntoRel(QueryDesc *queryDesc)
static void
CloseIntoRel(QueryDesc *queryDesc)
{
- EState *estate = queryDesc->estate;
+ DR_intorel *myState = (DR_intorel *) queryDesc->dest;
/* OpenIntoRel might never have gotten called */
- if (estate->es_into_relation_descriptor)
+ if (myState && myState->pub.mydest == DestIntoRel && myState->rel)
{
/* If we skipped using WAL, must heap_sync before commit */
- if (!estate->es_into_relation_use_wal)
- heap_sync(estate->es_into_relation_descriptor);
+ if (!myState->use_wal)
+ heap_sync(myState->rel);
/* close rel, but keep lock until commit */
- heap_close(estate->es_into_relation_descriptor, NoLock);
+ heap_close(myState->rel, NoLock);
- estate->es_into_relation_descriptor = NULL;
+ myState->rel = NULL;
}
}
@@ -2736,13 +2727,13 @@ CloseIntoRel(QueryDesc *queryDesc)
* CreateIntoRelDestReceiver -- create a suitable DestReceiver object
*
* Since CreateDestReceiver doesn't accept the parameters we'd need,
- * we just leave the private fields empty here. OpenIntoRel will
+ * we just leave the private fields zeroed here. OpenIntoRel will
* fill them in.
*/
DestReceiver *
CreateIntoRelDestReceiver(void)
{
- DR_intorel *self = (DR_intorel *) palloc(sizeof(DR_intorel));
+ DR_intorel *self = (DR_intorel *) palloc0(sizeof(DR_intorel));
self->pub.receiveSlot = intorel_receive;
self->pub.rStartup = intorel_startup;
@@ -2750,8 +2741,6 @@ CreateIntoRelDestReceiver(void)
self->pub.rDestroy = intorel_destroy;
self->pub.mydest = DestIntoRel;
- self->estate = NULL;
-
return (DestReceiver *) self;
}
@@ -2771,21 +2760,22 @@ static void
intorel_receive(TupleTableSlot *slot, DestReceiver *self)
{
DR_intorel *myState = (DR_intorel *) self;
- EState *estate = myState->estate;
HeapTuple tuple;
- tuple = ExecCopySlotTuple(slot);
+ /*
+ * get the heap tuple out of the tuple table slot, making sure we have a
+ * writable copy
+ */
+ tuple = ExecMaterializeSlot(slot);
- heap_insert(estate->es_into_relation_descriptor,
+ heap_insert(myState->rel,
tuple,
- estate->es_output_cid,
- estate->es_into_relation_use_wal,
+ myState->estate->es_output_cid,
+ myState->use_wal,
false); /* never any point in using FSM */
/* We know this is a newly created relation, so there are no indexes */
- heap_freetuple(tuple);
-
IncrAppended();
}