Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit a77eaa6

Browse files
committed
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.
1 parent 94be06a commit a77eaa6

File tree

5 files changed

+33
-120
lines changed

5 files changed

+33
-120
lines changed

src/backend/executor/execAmi.c

+1-70
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.95 2008/07/10 01:17:29 tgl Exp $
9+
* $PostgreSQL: pgsql/src/backend/executor/execAmi.c,v 1.96 2008/07/26 19:15:35 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -424,72 +424,3 @@ ExecSupportsBackwardScan(Plan *node)
424424
return false;
425425
}
426426
}
427-
428-
/*
429-
* ExecMayReturnRawTuples
430-
* Check whether a plan tree may return "raw" disk tuples (that is,
431-
* pointers to original data in disk buffers, as opposed to temporary
432-
* tuples constructed by projection steps). In the case of Append,
433-
* some subplans may return raw tuples and others projected tuples;
434-
* we return "true" if any of the returned tuples could be raw.
435-
*
436-
* This must be passed an already-initialized planstate tree, because we
437-
* need to look at the results of ExecAssignScanProjectionInfo().
438-
*/
439-
bool
440-
ExecMayReturnRawTuples(PlanState *node)
441-
{
442-
/*
443-
* At a table scan node, we check whether ExecAssignScanProjectionInfo
444-
* decided to do projection or not. Most non-scan nodes always project
445-
* and so we can return "false" immediately. For nodes that don't project
446-
* but just pass up input tuples, we have to recursively examine the input
447-
* plan node.
448-
*
449-
* Note: Hash and Material are listed here because they sometimes return
450-
* an original input tuple, not a copy. But Sort and SetOp never return
451-
* an original tuple, so they can be treated like projecting nodes.
452-
*/
453-
switch (nodeTag(node))
454-
{
455-
/* Table scan nodes */
456-
case T_SeqScanState:
457-
case T_IndexScanState:
458-
case T_BitmapHeapScanState:
459-
case T_TidScanState:
460-
if (node->ps_ProjInfo == NULL)
461-
return true;
462-
break;
463-
464-
case T_SubqueryScanState:
465-
/* If not projecting, look at input plan */
466-
if (node->ps_ProjInfo == NULL)
467-
return ExecMayReturnRawTuples(((SubqueryScanState *) node)->subplan);
468-
break;
469-
470-
/* Non-projecting nodes */
471-
case T_HashState:
472-
case T_MaterialState:
473-
case T_UniqueState:
474-
case T_LimitState:
475-
return ExecMayReturnRawTuples(node->lefttree);
476-
477-
case T_AppendState:
478-
{
479-
AppendState *appendstate = (AppendState *) node;
480-
int j;
481-
482-
for (j = 0; j < appendstate->as_nplans; j++)
483-
{
484-
if (ExecMayReturnRawTuples(appendstate->appendplans[j]))
485-
return true;
486-
}
487-
break;
488-
}
489-
490-
/* All projecting node types come here */
491-
default:
492-
break;
493-
}
494-
return false;
495-
}

src/backend/executor/execMain.c

+29-39
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
*
2727
*
2828
* IDENTIFICATION
29-
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.310 2008/07/18 18:23:46 tgl Exp $
29+
* $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.311 2008/07/26 19:15:35 tgl Exp $
3030
*
3131
*-------------------------------------------------------------------------
3232
*/
@@ -694,9 +694,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
694694

695695
/*
696696
* Initialize the junk filter if needed. SELECT and INSERT queries need a
697-
* filter if there are any junk attrs in the tlist. INSERT and SELECT
698-
* INTO also need a filter if the plan may return raw disk tuples (else
699-
* heap_insert will be scribbling on the source relation!). UPDATE and
697+
* filter if there are any junk attrs in the tlist. UPDATE and
700698
* DELETE always need a filter, since there's always a junk 'ctid'
701699
* attribute present --- no need to look first.
702700
*/
@@ -718,10 +716,6 @@ InitPlan(QueryDesc *queryDesc, int eflags)
718716
break;
719717
}
720718
}
721-
if (!junk_filter_needed &&
722-
(operation == CMD_INSERT || estate->es_select_into) &&
723-
ExecMayReturnRawTuples(planstate))
724-
junk_filter_needed = true;
725719
break;
726720
case CMD_UPDATE:
727721
case CMD_DELETE:
@@ -2424,8 +2418,6 @@ EvalPlanQualStart(evalPlanQual *epq, EState *estate, evalPlanQual *priorepq)
24242418
epqstate->es_result_relation_info = estate->es_result_relation_info;
24252419
epqstate->es_junkFilter = estate->es_junkFilter;
24262420
/* es_trig_target_relations must NOT be copied */
2427-
epqstate->es_into_relation_descriptor = estate->es_into_relation_descriptor;
2428-
epqstate->es_into_relation_use_wal = estate->es_into_relation_use_wal;
24292421
epqstate->es_param_list_info = estate->es_param_list_info;
24302422
if (estate->es_plannedstmt->nParamExec > 0)
24312423
epqstate->es_param_exec_vals = (ParamExecData *)
@@ -2559,15 +2551,14 @@ ExecGetActivePlanTree(QueryDesc *queryDesc)
25592551
*
25602552
* We implement SELECT INTO by diverting SELECT's normal output with
25612553
* a specialized DestReceiver type.
2562-
*
2563-
* TODO: remove some of the INTO-specific cruft from EState, and keep
2564-
* it in the DestReceiver instead.
25652554
*/
25662555

25672556
typedef struct
25682557
{
25692558
DestReceiver pub; /* publicly-known function pointers */
25702559
EState *estate; /* EState we are working with */
2560+
Relation rel; /* Relation to write to */
2561+
bool use_wal; /* do we need to WAL-log our writes? */
25712562
} DR_intorel;
25722563

25732564
/*
@@ -2692,22 +2683,22 @@ OpenIntoRel(QueryDesc *queryDesc)
26922683
*/
26932684
intoRelationDesc = heap_open(intoRelationId, AccessExclusiveLock);
26942685

2695-
/* use_wal off requires rd_targblock be initially invalid */
2696-
Assert(intoRelationDesc->rd_targblock == InvalidBlockNumber);
2697-
2698-
/*
2699-
* We can skip WAL-logging the insertions, unless PITR is in use.
2700-
*/
2701-
estate->es_into_relation_use_wal = XLogArchivingActive();
2702-
estate->es_into_relation_descriptor = intoRelationDesc;
2703-
27042686
/*
27052687
* Now replace the query's DestReceiver with one for SELECT INTO
27062688
*/
27072689
queryDesc->dest = CreateDestReceiver(DestIntoRel, NULL);
27082690
myState = (DR_intorel *) queryDesc->dest;
27092691
Assert(myState->pub.mydest == DestIntoRel);
27102692
myState->estate = estate;
2693+
2694+
/*
2695+
* We can skip WAL-logging the insertions, unless PITR is in use.
2696+
*/
2697+
myState->use_wal = XLogArchivingActive();
2698+
myState->rel = intoRelationDesc;
2699+
2700+
/* use_wal off requires rd_targblock be initially invalid */
2701+
Assert(intoRelationDesc->rd_targblock == InvalidBlockNumber);
27112702
}
27122703

27132704
/*
@@ -2716,42 +2707,40 @@ OpenIntoRel(QueryDesc *queryDesc)
27162707
static void
27172708
CloseIntoRel(QueryDesc *queryDesc)
27182709
{
2719-
EState *estate = queryDesc->estate;
2710+
DR_intorel *myState = (DR_intorel *) queryDesc->dest;
27202711

27212712
/* OpenIntoRel might never have gotten called */
2722-
if (estate->es_into_relation_descriptor)
2713+
if (myState && myState->pub.mydest == DestIntoRel && myState->rel)
27232714
{
27242715
/* If we skipped using WAL, must heap_sync before commit */
2725-
if (!estate->es_into_relation_use_wal)
2726-
heap_sync(estate->es_into_relation_descriptor);
2716+
if (!myState->use_wal)
2717+
heap_sync(myState->rel);
27272718

27282719
/* close rel, but keep lock until commit */
2729-
heap_close(estate->es_into_relation_descriptor, NoLock);
2720+
heap_close(myState->rel, NoLock);
27302721

2731-
estate->es_into_relation_descriptor = NULL;
2722+
myState->rel = NULL;
27322723
}
27332724
}
27342725

27352726
/*
27362727
* CreateIntoRelDestReceiver -- create a suitable DestReceiver object
27372728
*
27382729
* Since CreateDestReceiver doesn't accept the parameters we'd need,
2739-
* we just leave the private fields empty here. OpenIntoRel will
2730+
* we just leave the private fields zeroed here. OpenIntoRel will
27402731
* fill them in.
27412732
*/
27422733
DestReceiver *
27432734
CreateIntoRelDestReceiver(void)
27442735
{
2745-
DR_intorel *self = (DR_intorel *) palloc(sizeof(DR_intorel));
2736+
DR_intorel *self = (DR_intorel *) palloc0(sizeof(DR_intorel));
27462737

27472738
self->pub.receiveSlot = intorel_receive;
27482739
self->pub.rStartup = intorel_startup;
27492740
self->pub.rShutdown = intorel_shutdown;
27502741
self->pub.rDestroy = intorel_destroy;
27512742
self->pub.mydest = DestIntoRel;
27522743

2753-
self->estate = NULL;
2754-
27552744
return (DestReceiver *) self;
27562745
}
27572746

@@ -2771,21 +2760,22 @@ static void
27712760
intorel_receive(TupleTableSlot *slot, DestReceiver *self)
27722761
{
27732762
DR_intorel *myState = (DR_intorel *) self;
2774-
EState *estate = myState->estate;
27752763
HeapTuple tuple;
27762764

2777-
tuple = ExecCopySlotTuple(slot);
2765+
/*
2766+
* get the heap tuple out of the tuple table slot, making sure we have a
2767+
* writable copy
2768+
*/
2769+
tuple = ExecMaterializeSlot(slot);
27782770

2779-
heap_insert(estate->es_into_relation_descriptor,
2771+
heap_insert(myState->rel,
27802772
tuple,
2781-
estate->es_output_cid,
2782-
estate->es_into_relation_use_wal,
2773+
myState->estate->es_output_cid,
2774+
myState->use_wal,
27832775
false); /* never any point in using FSM */
27842776

27852777
/* We know this is a newly created relation, so there are no indexes */
27862778

2787-
heap_freetuple(tuple);
2788-
27892779
IncrAppended();
27902780
}
27912781

src/backend/executor/execUtils.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.155 2008/03/26 21:10:38 alvherre Exp $
11+
* $PostgreSQL: pgsql/src/backend/executor/execUtils.c,v 1.156 2008/07/26 19:15:35 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -190,9 +190,6 @@ CreateExecutorState(void)
190190
estate->es_trig_target_relations = NIL;
191191
estate->es_trig_tuple_slot = NULL;
192192

193-
estate->es_into_relation_descriptor = NULL;
194-
estate->es_into_relation_use_wal = false;
195-
196193
estate->es_param_list_info = NULL;
197194
estate->es_param_exec_vals = NULL;
198195

src/include/executor/executor.h

+1-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.148 2008/07/18 18:23:47 tgl Exp $
10+
* $PostgreSQL: pgsql/src/include/executor/executor.h,v 1.149 2008/07/26 19:15:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -75,7 +75,6 @@ extern void ExecMarkPos(PlanState *node);
7575
extern void ExecRestrPos(PlanState *node);
7676
extern bool ExecSupportsMarkRestore(NodeTag plantype);
7777
extern bool ExecSupportsBackwardScan(Plan *node);
78-
extern bool ExecMayReturnRawTuples(PlanState *node);
7978

8079
/*
8180
* prototypes from functions in execCurrent.c

src/include/nodes/execnodes.h

+1-5
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.184 2008/06/19 00:46:06 alvherre Exp $
10+
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.185 2008/07/26 19:15:35 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -328,10 +328,6 @@ typedef struct EState
328328
List *es_trig_target_relations; /* trigger-only ResultRelInfos */
329329
TupleTableSlot *es_trig_tuple_slot; /* for trigger output tuples */
330330

331-
/* Stuff used for SELECT INTO: */
332-
Relation es_into_relation_descriptor;
333-
bool es_into_relation_use_wal;
334-
335331
/* Parameter info: */
336332
ParamListInfo es_param_list_info; /* values of external params */
337333
ParamExecData *es_param_exec_vals; /* values of internal params */

0 commit comments

Comments
 (0)