Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitad7dbee

Browse files
committed
Allow tupleslots to have a fixed tupledesc, use in executor nodes.
The reason for doing so is that it will allow expression evaluation tooptimize based on the underlying tupledesc. In particular it willallow to JIT tuple deforming together with the expression itself.For that expression initialization needs to be moved after therelevant slots are initialized - mostly unproblematic, except in thecase of nodeWorktablescan.c.After doing so there's no need for ExecAssignResultType() andExecAssignResultTypeFromTL() anymore, as all former callers have beenconverted to create a slot with a fixed descriptor.When creating a slot with a fixed descriptor, tts_values/isnull can beallocated together with the main slot, reducing allocation overheadand increasing cache density a bit.Author: Andres FreundDiscussion:https://postgr.es/m/20171206093717.vqdxe5icqttpxs3p@alap3.anarazel.de
1 parentbf6c614 commitad7dbee

File tree

52 files changed

+566
-778
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+566
-778
lines changed

‎src/backend/commands/copy.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2444,10 +2444,9 @@ CopyFrom(CopyState cstate)
24442444
estate->es_range_table=cstate->range_table;
24452445

24462446
/* Set up a tuple slot too */
2447-
myslot=ExecInitExtraTupleSlot(estate);
2448-
ExecSetSlotDescriptor(myslot,tupDesc);
2447+
myslot=ExecInitExtraTupleSlot(estate,tupDesc);
24492448
/* Triggers might need a slot as well */
2450-
estate->es_trig_tuple_slot=ExecInitExtraTupleSlot(estate);
2449+
estate->es_trig_tuple_slot=ExecInitExtraTupleSlot(estate,NULL);
24512450

24522451
/* Prepare to catch AFTER triggers. */
24532452
AfterTriggerBeginQuery();

‎src/backend/commands/trigger.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3251,7 +3251,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
32513251
if (estate->es_trig_oldtup_slot==NULL)
32523252
{
32533253
oldContext=MemoryContextSwitchTo(estate->es_query_cxt);
3254-
estate->es_trig_oldtup_slot=ExecInitExtraTupleSlot(estate);
3254+
estate->es_trig_oldtup_slot=
3255+
ExecInitExtraTupleSlot(estate,NULL);
32553256
MemoryContextSwitchTo(oldContext);
32563257
}
32573258
oldslot=estate->es_trig_oldtup_slot;
@@ -3264,7 +3265,8 @@ TriggerEnabled(EState *estate, ResultRelInfo *relinfo,
32643265
if (estate->es_trig_newtup_slot==NULL)
32653266
{
32663267
oldContext=MemoryContextSwitchTo(estate->es_query_cxt);
3267-
estate->es_trig_newtup_slot=ExecInitExtraTupleSlot(estate);
3268+
estate->es_trig_newtup_slot=
3269+
ExecInitExtraTupleSlot(estate,NULL);
32683270
MemoryContextSwitchTo(oldContext);
32693271
}
32703272
newslot=estate->es_trig_newtup_slot;

‎src/backend/executor/README

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,8 @@ This is a sketch of control flow for full query processing:
243243
switch to per-query context to run ExecInitNode
244244
AfterTriggerBeginQuery
245245
ExecInitNode --- recursively scans plan tree
246+
ExecInitNode
247+
recurse into subsidiary nodes
246248
CreateExprContext
247249
creates per-tuple context
248250
ExecInitExpr

‎src/backend/executor/execExpr.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2415,7 +2415,7 @@ ExecInitWholeRowVar(ExprEvalStep *scratch, Var *variable, ExprState *state)
24152415
scratch->d.wholerow.junkFilter=
24162416
ExecInitJunkFilter(subplan->plan->targetlist,
24172417
ExecGetResultType(subplan)->tdhasoid,
2418-
ExecInitExtraTupleSlot(parent->state));
2418+
ExecInitExtraTupleSlot(parent->state,NULL));
24192419
}
24202420
}
24212421
}

‎src/backend/executor/execMain.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1073,7 +1073,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
10731073

10741074
j=ExecInitJunkFilter(planstate->plan->targetlist,
10751075
tupType->tdhasoid,
1076-
ExecInitExtraTupleSlot(estate));
1076+
ExecInitExtraTupleSlot(estate,NULL));
10771077
estate->es_junkFilter=j;
10781078

10791079
/* Want to return the cleaned tuple type */

‎src/backend/executor/execPartition.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
9393
* We need an additional tuple slot for storing transient tuples that
9494
* are converted to the root table descriptor.
9595
*/
96-
proute->root_tuple_slot=MakeTupleTableSlot();
96+
proute->root_tuple_slot=MakeTupleTableSlot(NULL);
9797
}
9898
else
9999
{
@@ -112,7 +112,7 @@ ExecSetupPartitionTupleRouting(ModifyTableState *mtstate,
112112
* (such as ModifyTableState) and released when the node finishes
113113
* processing.
114114
*/
115-
proute->partition_tuple_slot=MakeTupleTableSlot();
115+
proute->partition_tuple_slot=MakeTupleTableSlot(NULL);
116116

117117
i=0;
118118
foreach(cell,leaf_parts)

‎src/backend/executor/execScan.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ ExecScan(ScanState *node,
229229
* the scan node, because the planner will preferentially generate a matching
230230
* tlist.
231231
*
232-
*ExecAssignScanTypemust have beencalled already.
232+
*The scan slot's descriptormust have beenset already.
233233
*/
234234
void
235235
ExecAssignScanProjectionInfo(ScanState*node)

‎src/backend/executor/execTuples.c

Lines changed: 85 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
*At ExecutorStart()
5959
*----------------
6060
*- ExecInitSeqScan() calls ExecInitScanTupleSlot() and
61-
*ExecInitResultTupleSlot() to construct TupleTableSlots
61+
*ExecInitResultTupleSlotTL() to construct TupleTableSlots
6262
* for the tuples returned by the access methods and the
6363
* tuples resulting from performing target list projections.
6464
*
@@ -104,26 +104,56 @@ static TupleDesc ExecTypeFromTLInternal(List *targetList,
104104
/* --------------------------------
105105
*MakeTupleTableSlot
106106
*
107-
*Basic routine to make an empty TupleTableSlot.
107+
*Basic routine to make an empty TupleTableSlot. If tupleDesc is
108+
*specified the slot's descriptor is fixed for it's lifetime, gaining
109+
*some efficiency. If that's undesirable, pass NULL.
108110
* --------------------------------
109111
*/
110112
TupleTableSlot*
111-
MakeTupleTableSlot(void)
113+
MakeTupleTableSlot(TupleDesctupleDesc)
112114
{
113-
TupleTableSlot*slot=makeNode(TupleTableSlot);
115+
Sizesz;
116+
TupleTableSlot*slot;
114117

118+
/*
119+
* When a fixed descriptor is specified, we can reduce overhead by
120+
* allocating the entire slot in one go.
121+
*/
122+
if (tupleDesc)
123+
sz=MAXALIGN(sizeof(TupleTableSlot))+
124+
MAXALIGN(tupleDesc->natts*sizeof(Datum))+
125+
MAXALIGN(tupleDesc->natts*sizeof(bool));
126+
else
127+
sz=sizeof(TupleTableSlot);
128+
129+
slot=palloc0(sz);
130+
slot->type=T_TupleTableSlot;
115131
slot->tts_isempty= true;
116132
slot->tts_shouldFree= false;
117133
slot->tts_shouldFreeMin= false;
118134
slot->tts_tuple=NULL;
119-
slot->tts_tupleDescriptor=NULL;
135+
slot->tts_fixedTupleDescriptor=tupleDesc!=NULL;
136+
slot->tts_tupleDescriptor=tupleDesc;
120137
slot->tts_mcxt=CurrentMemoryContext;
121138
slot->tts_buffer=InvalidBuffer;
122139
slot->tts_nvalid=0;
123140
slot->tts_values=NULL;
124141
slot->tts_isnull=NULL;
125142
slot->tts_mintuple=NULL;
126143

144+
if (tupleDesc!=NULL)
145+
{
146+
slot->tts_values= (Datum*)
147+
(((char*)slot)
148+
+MAXALIGN(sizeof(TupleTableSlot)));
149+
slot->tts_isnull= (bool*)
150+
(((char*)slot)
151+
+MAXALIGN(sizeof(TupleTableSlot))
152+
+MAXALIGN(tupleDesc->natts*sizeof(Datum)));
153+
154+
PinTupleDesc(tupleDesc);
155+
}
156+
127157
returnslot;
128158
}
129159

@@ -134,9 +164,9 @@ MakeTupleTableSlot(void)
134164
* --------------------------------
135165
*/
136166
TupleTableSlot*
137-
ExecAllocTableSlot(List**tupleTable)
167+
ExecAllocTableSlot(List**tupleTable,TupleDescdesc)
138168
{
139-
TupleTableSlot*slot=MakeTupleTableSlot();
169+
TupleTableSlot*slot=MakeTupleTableSlot(desc);
140170

141171
*tupleTable=lappend(*tupleTable,slot);
142172

@@ -173,10 +203,13 @@ ExecResetTupleTable(List *tupleTable,/* tuple table */
173203
/* If shouldFree, release memory occupied by the slot itself */
174204
if (shouldFree)
175205
{
176-
if (slot->tts_values)
177-
pfree(slot->tts_values);
178-
if (slot->tts_isnull)
179-
pfree(slot->tts_isnull);
206+
if (!slot->tts_fixedTupleDescriptor)
207+
{
208+
if (slot->tts_values)
209+
pfree(slot->tts_values);
210+
if (slot->tts_isnull)
211+
pfree(slot->tts_isnull);
212+
}
180213
pfree(slot);
181214
}
182215
}
@@ -198,9 +231,7 @@ ExecResetTupleTable(List *tupleTable,/* tuple table */
198231
TupleTableSlot*
199232
MakeSingleTupleTableSlot(TupleDesctupdesc)
200233
{
201-
TupleTableSlot*slot=MakeTupleTableSlot();
202-
203-
ExecSetSlotDescriptor(slot,tupdesc);
234+
TupleTableSlot*slot=MakeTupleTableSlot(tupdesc);
204235

205236
returnslot;
206237
}
@@ -220,10 +251,13 @@ ExecDropSingleTupleTableSlot(TupleTableSlot *slot)
220251
ExecClearTuple(slot);
221252
if (slot->tts_tupleDescriptor)
222253
ReleaseTupleDesc(slot->tts_tupleDescriptor);
223-
if (slot->tts_values)
224-
pfree(slot->tts_values);
225-
if (slot->tts_isnull)
226-
pfree(slot->tts_isnull);
254+
if (!slot->tts_fixedTupleDescriptor)
255+
{
256+
if (slot->tts_values)
257+
pfree(slot->tts_values);
258+
if (slot->tts_isnull)
259+
pfree(slot->tts_isnull);
260+
}
227261
pfree(slot);
228262
}
229263

@@ -247,6 +281,8 @@ void
247281
ExecSetSlotDescriptor(TupleTableSlot*slot,/* slot to change */
248282
TupleDesctupdesc)/* new tuple descriptor */
249283
{
284+
Assert(!slot->tts_fixedTupleDescriptor);
285+
250286
/* For safety, make sure slot is empty before changing it */
251287
ExecClearTuple(slot);
252288

@@ -816,7 +852,7 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
816852
*/
817853

818854
/* --------------------------------
819-
*ExecInit{Result,Scan,Extra}TupleSlot
855+
*ExecInit{Result,Scan,Extra}TupleSlot[TL]
820856
*
821857
*These are convenience routines to initialize the specified slot
822858
*in nodes inheriting the appropriate state. ExecInitExtraTupleSlot
@@ -825,33 +861,55 @@ ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
825861
*/
826862

827863
/* ----------------
828-
*ExecInitResultTupleSlot
864+
*ExecInitResultTupleSlotTL
865+
*
866+
*Initialize result tuple slot, using the plan node's targetlist.
829867
* ----------------
830868
*/
831869
void
832-
ExecInitResultTupleSlot(EState*estate,PlanState*planstate)
870+
ExecInitResultTupleSlotTL(EState*estate,PlanState*planstate)
833871
{
834-
planstate->ps_ResultTupleSlot=ExecAllocTableSlot(&estate->es_tupleTable);
872+
boolhasoid;
873+
TupleDesctupDesc;
874+
875+
if (ExecContextForcesOids(planstate,&hasoid))
876+
{
877+
/* context forces OID choice; hasoid is now set correctly */
878+
}
879+
else
880+
{
881+
/* given free choice, don't leave space for OIDs in result tuples */
882+
hasoid= false;
883+
}
884+
885+
tupDesc=ExecTypeFromTL(planstate->plan->targetlist,hasoid);
886+
887+
planstate->ps_ResultTupleSlot=ExecAllocTableSlot(&estate->es_tupleTable,tupDesc);
835888
}
836889

837890
/* ----------------
838891
*ExecInitScanTupleSlot
839892
* ----------------
840893
*/
841894
void
842-
ExecInitScanTupleSlot(EState*estate,ScanState*scanstate)
895+
ExecInitScanTupleSlot(EState*estate,ScanState*scanstate,TupleDesctupledesc)
843896
{
844-
scanstate->ss_ScanTupleSlot=ExecAllocTableSlot(&estate->es_tupleTable);
897+
scanstate->ss_ScanTupleSlot=ExecAllocTableSlot(&estate->es_tupleTable,
898+
tupledesc);
845899
}
846900

847901
/* ----------------
848902
*ExecInitExtraTupleSlot
903+
*
904+
* Return a newly created slot. If tupledesc is non-NULL the slot will have
905+
* that as its fixed tupledesc. Otherwise the caller needs to use
906+
* ExecSetSlotDescriptor() to set the descriptor before use.
849907
* ----------------
850908
*/
851909
TupleTableSlot*
852-
ExecInitExtraTupleSlot(EState*estate)
910+
ExecInitExtraTupleSlot(EState*estate,TupleDesctupledesc)
853911
{
854-
returnExecAllocTableSlot(&estate->es_tupleTable);
912+
returnExecAllocTableSlot(&estate->es_tupleTable,tupledesc);
855913
}
856914

857915
/* ----------------
@@ -865,9 +923,7 @@ ExecInitExtraTupleSlot(EState *estate)
865923
TupleTableSlot*
866924
ExecInitNullTupleSlot(EState*estate,TupleDesctupType)
867925
{
868-
TupleTableSlot*slot=ExecInitExtraTupleSlot(estate);
869-
870-
ExecSetSlotDescriptor(slot,tupType);
926+
TupleTableSlot*slot=ExecInitExtraTupleSlot(estate,tupType);
871927

872928
returnExecStoreAllNullTuple(slot);
873929
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp