diff options
Diffstat (limited to 'src/backend/executor/execMain.c')
-rw-r--r-- | src/backend/executor/execMain.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index 54df18d3c79..569d0ba7ade 100644 --- a/src/backend/executor/execMain.c +++ b/src/backend/executor/execMain.c @@ -2445,6 +2445,7 @@ typedef struct { DestReceiver pub; /* publicly-known function pointers */ EState *estate; /* EState we are working with */ + DestReceiver *origdest; /* QueryDesc's original receiver */ Relation rel; /* Relation to write to */ int hi_options; /* heap_insert performance options */ BulkInsertState bistate; /* bulk insert state */ @@ -2651,12 +2652,14 @@ OpenIntoRel(QueryDesc *queryDesc) /* * Now replace the query's DestReceiver with one for SELECT INTO */ - queryDesc->dest = CreateDestReceiver(DestIntoRel); - myState = (DR_intorel *) queryDesc->dest; + myState = (DR_intorel *) CreateDestReceiver(DestIntoRel); Assert(myState->pub.mydest == DestIntoRel); myState->estate = estate; + myState->origdest = queryDesc->dest; myState->rel = intoRelationDesc; + queryDesc->dest = (DestReceiver *) myState; + /* * We can skip WAL-logging the insertions, unless PITR or streaming * replication is in use. We can skip the FSM in any case. @@ -2677,8 +2680,11 @@ CloseIntoRel(QueryDesc *queryDesc) { DR_intorel *myState = (DR_intorel *) queryDesc->dest; - /* OpenIntoRel might never have gotten called */ - if (myState && myState->pub.mydest == DestIntoRel && myState->rel) + /* + * OpenIntoRel might never have gotten called, and we also want to guard + * against double destruction. + */ + if (myState && myState->pub.mydest == DestIntoRel) { FreeBulkInsertState(myState->bistate); @@ -2689,7 +2695,11 @@ CloseIntoRel(QueryDesc *queryDesc) /* close rel, but keep lock until commit */ heap_close(myState->rel, NoLock); - myState->rel = NULL; + /* restore the receiver belonging to executor's caller */ + queryDesc->dest = myState->origdest; + + /* might as well invoke my destructor */ + intorel_destroy((DestReceiver *) myState); } } |