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

Commit763f2ed

Browse files
committed
Rejigger materializing and fetching a HeapTuple from a slot.
Previously materializing a slot always returned a HeapTuple. Ascurrent work aims to reduce the reliance on HeapTuples (so otherstorage systems can work efficiently), that needs to change. Thussplit the tasks of materializing a slot (i.e. making it independentfrom the underlying storage / other memory contexts) from fetching aHeapTuple from the slot. For brevity, allow to fetch a HeapTuple froma slot and materializing the slot at the same time, controlled by aparameter.For now some callers of ExecFetchSlotHeapTuple, with materialize =true, expect that changes to the heap tuple will be reflected in theunderlying slot. Those places will be adapted in due course, so whilenot pretty, that's OK for now.Also rename ExecFetchSlotTuple to ExecFetchSlotHeapTupleDatum andExecFetchSlotTupleDatum to ExecFetchSlotHeapTupleDatum, as it's likelythat future storage methods will need similar methods. There alreadyis ExecFetchSlotMinimalTuple, so the new names make the naming schememore coherent.Author: Ashutosh Bapat and Andres Freund, with changes by Amit KhandekarDiscussion:https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
1 parent7ac0069 commit763f2ed

File tree

16 files changed

+154
-87
lines changed

16 files changed

+154
-87
lines changed

‎contrib/postgres_fdw/postgres_fdw.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3947,11 +3947,12 @@ apply_returning_filter(PgFdwDirectModifyState *dmstate,
39473947
ExecStoreVirtualTuple(resultSlot);
39483948

39493949
/*
3950-
* If we have any system columns to return, install them.
3950+
* If we have any system columns to return, materialize a heap tuple in the
3951+
* slot from column values set above and install system columns in that tuple.
39513952
*/
39523953
if (dmstate->hasSystemCols)
39533954
{
3954-
HeapTupleresultTup=ExecMaterializeSlot(resultSlot);
3955+
HeapTupleresultTup=ExecFetchSlotHeapTuple(resultSlot, true,NULL);
39553956

39563957
/* ctid */
39573958
if (dmstate->ctidAttno)

‎src/backend/commands/copy.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2899,7 +2899,7 @@ CopyFrom(CopyState cstate)
28992899
if (slot==NULL)/* "do nothing" */
29002900
skip_tuple= true;
29012901
else/* trigger might have changed tuple */
2902-
tuple=ExecMaterializeSlot(slot);
2902+
tuple=ExecFetchSlotHeapTuple(slot, true,NULL);
29032903
}
29042904

29052905
if (!skip_tuple)
@@ -2975,7 +2975,7 @@ CopyFrom(CopyState cstate)
29752975
continue;/* next tuple please */
29762976

29772977
/* FDW might have changed tuple */
2978-
tuple=ExecMaterializeSlot(slot);
2978+
tuple=ExecFetchSlotHeapTuple(slot, true,NULL);
29792979

29802980
/*
29812981
* AFTER ROW Triggers might reference the tableoid

‎src/backend/commands/createas.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -589,7 +589,7 @@ intorel_receive(TupleTableSlot *slot, DestReceiver *self)
589589
* get the heap tuple out of the tuple table slot, making sure we have a
590590
* writable copy
591591
*/
592-
tuple=ExecMaterializeSlot(slot);
592+
tuple=ExecCopySlotTuple(slot);
593593

594594
/*
595595
* force assignment of new OID (see comments in ExecInsert)

‎src/backend/commands/matview.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,7 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
484484
* get the heap tuple out of the tuple table slot, making sure we have a
485485
* writable copy
486486
*/
487-
tuple=ExecMaterializeSlot(slot);
487+
tuple=ExecCopySlotTuple(slot);
488488

489489
heap_insert(myState->transientrel,
490490
tuple,
@@ -494,6 +494,9 @@ transientrel_receive(TupleTableSlot *slot, DestReceiver *self)
494494

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

497+
/* Free the copied tuple. */
498+
heap_freetuple(tuple);
499+
497500
return true;
498501
}
499502

‎src/backend/commands/trigger.c

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2517,7 +2517,8 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
25172517
TupleTableSlot*slot)
25182518
{
25192519
TriggerDesc*trigdesc=relinfo->ri_TrigDesc;
2520-
HeapTupleslottuple=ExecMaterializeSlot(slot);
2520+
boolshould_free;
2521+
HeapTupleslottuple=ExecFetchSlotHeapTuple(slot, true,&should_free);
25212522
HeapTuplenewtuple=slottuple;
25222523
HeapTupleoldtuple;
25232524
TriggerDataLocTriggerData;
@@ -2556,7 +2557,11 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
25562557
if (oldtuple!=newtuple&&oldtuple!=slottuple)
25572558
heap_freetuple(oldtuple);
25582559
if (newtuple==NULL)
2560+
{
2561+
if (should_free)
2562+
heap_freetuple(slottuple);
25592563
returnNULL;/* "do nothing" */
2564+
}
25602565
}
25612566

25622567
if (newtuple!=slottuple)
@@ -2575,6 +2580,9 @@ ExecBRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
25752580
ExecStoreHeapTuple(newtuple,newslot, false);
25762581
slot=newslot;
25772582
}
2583+
2584+
if (should_free)
2585+
heap_freetuple(slottuple);
25782586
returnslot;
25792587
}
25802588

@@ -2598,7 +2606,8 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
25982606
TupleTableSlot*slot)
25992607
{
26002608
TriggerDesc*trigdesc=relinfo->ri_TrigDesc;
2601-
HeapTupleslottuple=ExecMaterializeSlot(slot);
2609+
boolshould_free;
2610+
HeapTupleslottuple=ExecFetchSlotHeapTuple(slot, true,&should_free);
26022611
HeapTuplenewtuple=slottuple;
26032612
HeapTupleoldtuple;
26042613
TriggerDataLocTriggerData;
@@ -2637,7 +2646,11 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
26372646
if (oldtuple!=newtuple&&oldtuple!=slottuple)
26382647
heap_freetuple(oldtuple);
26392648
if (newtuple==NULL)
2649+
{
2650+
if (should_free)
2651+
heap_freetuple(slottuple);
26402652
returnNULL;/* "do nothing" */
2653+
}
26412654
}
26422655

26432656
if (newtuple!=slottuple)
@@ -2656,6 +2669,9 @@ ExecIRInsertTriggers(EState *estate, ResultRelInfo *relinfo,
26562669
ExecStoreHeapTuple(newtuple,newslot, false);
26572670
slot=newslot;
26582671
}
2672+
2673+
if (should_free)
2674+
heap_freetuple(slottuple);
26592675
returnslot;
26602676
}
26612677

@@ -2976,7 +2992,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
29762992
TupleTableSlot*slot)
29772993
{
29782994
TriggerDesc*trigdesc=relinfo->ri_TrigDesc;
2979-
HeapTupleslottuple=ExecMaterializeSlot(slot);
2995+
HeapTupleslottuple=ExecFetchSlotHeapTuple(slot, true,NULL);
29802996
HeapTuplenewtuple=slottuple;
29812997
TriggerDataLocTriggerData;
29822998
HeapTupletrigtuple;
@@ -3018,7 +3034,7 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
30183034
if (newSlot!=NULL)
30193035
{
30203036
slot=ExecFilterJunk(relinfo->ri_junkFilter,newSlot);
3021-
slottuple=ExecMaterializeSlot(slot);
3037+
slottuple=ExecFetchSlotHeapTuple(slot, true,NULL);
30223038
newtuple=slottuple;
30233039
}
30243040

@@ -3132,7 +3148,7 @@ ExecIRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
31323148
HeapTupletrigtuple,TupleTableSlot*slot)
31333149
{
31343150
TriggerDesc*trigdesc=relinfo->ri_TrigDesc;
3135-
HeapTupleslottuple=ExecMaterializeSlot(slot);
3151+
HeapTupleslottuple=ExecFetchSlotHeapTuple(slot, true,NULL);
31363152
HeapTuplenewtuple=slottuple;
31373153
TriggerDataLocTriggerData;
31383154
HeapTupleoldtuple;
@@ -4262,22 +4278,22 @@ AfterTriggerExecute(AfterTriggerEvent event,
42624278
caseAFTER_TRIGGER_FDW_REUSE:
42634279

42644280
/*
4265-
*Using ExecMaterializeSlot() rather than ExecFetchSlotTuple()
4266-
*ensures that tg_trigtuple does not reference tuplestore memory.
4267-
*(It is formally possible for the trigger function toqueue
4268-
*trigger events that add to the same tuplestore, which can push
4269-
*other tuples out of memory.) The distinction is academic,
4270-
*because we start with aminimal tuple that ExecFetchSlotTuple()
4271-
*must materialize anyway.
4281+
*Materialize tuple in the slot so that tg_trigtuple does not
4282+
*reference tuplestore memory. (It is formally possible for the
4283+
*trigger function to queue trigger events that add tothe same
4284+
*tuplestore, which can push other tuples out of memory.) The
4285+
*distinction is academic, because we start with a minimal tuple
4286+
*that is stored as aheap tuple, constructed in different memory
4287+
*context, in the slot anyway.
42724288
*/
4273-
LocTriggerData.tg_trigtuple=
4274-
ExecMaterializeSlot(trig_tuple_slot1);
4289+
LocTriggerData.tg_trigtuple=ExecFetchSlotHeapTuple(trig_tuple_slot1,
4290+
true,NULL);
42754291
LocTriggerData.tg_trigtuplebuf=InvalidBuffer;
42764292

42774293
LocTriggerData.tg_newtuple=
42784294
((evtshared->ats_event&TRIGGER_EVENT_OPMASK)==
42794295
TRIGGER_EVENT_UPDATE) ?
4280-
ExecMaterializeSlot(trig_tuple_slot2) :NULL;
4296+
ExecFetchSlotHeapTuple(trig_tuple_slot2, true,NULL) :NULL;
42814297
LocTriggerData.tg_newtuplebuf=InvalidBuffer;
42824298

42834299
break;

‎src/backend/executor/execMain.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2549,7 +2549,7 @@ EvalPlanQual(EState *estate, EPQState *epqstate,
25492549
* is to guard against early re-use of the EPQ query.
25502550
*/
25512551
if (!TupIsNull(slot))
2552-
(void)ExecMaterializeSlot(slot);
2552+
ExecMaterializeSlot(slot);
25532553

25542554
/*
25552555
* Clear out the test tuple. This is needed in case the EPQ query is

‎src/backend/executor/execReplication.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ ExecSimpleRelationInsert(EState *estate, TupleTableSlot *slot)
418418
ExecPartitionCheck(resultRelInfo,slot,estate, true);
419419

420420
/* Materialize slot into a tuple that we can scribble upon. */
421-
tuple=ExecMaterializeSlot(slot);
421+
tuple=ExecFetchSlotHeapTuple(slot, true,NULL);
422422

423423
/* OK, store the tuple and create index entries for it */
424424
simple_heap_insert(rel,tuple);
@@ -485,7 +485,7 @@ ExecSimpleRelationUpdate(EState *estate, EPQState *epqstate,
485485
ExecPartitionCheck(resultRelInfo,slot,estate, true);
486486

487487
/* Materialize slot into a tuple that we can scribble upon. */
488-
tuple=ExecMaterializeSlot(slot);
488+
tuple=ExecFetchSlotHeapTuple(slot, true,NULL);
489489

490490
/* OK, update the tuple and index entries for it */
491491
simple_heap_update(rel,&searchslot->tts_tuple->t_self,

‎src/backend/executor/execSRF.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ ExecMakeFunctionResultSet(SetExprState *fcache,
521521
{
522522
/* We must return the whole tuple as a Datum. */
523523
*isNull= false;
524-
returnExecFetchSlotTupleDatum(fcache->funcResultSlot);
524+
returnExecFetchSlotHeapTupleDatum(fcache->funcResultSlot);
525525
}
526526
else
527527
{

‎src/backend/executor/execTuples.c

Lines changed: 50 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -676,30 +676,38 @@ ExecCopySlotMinimalTuple(TupleTableSlot *slot)
676676
slot->tts_isnull);
677677
}
678678

679-
/* --------------------------------
680-
*ExecFetchSlotTuple
681-
*Fetch the slot's regular physical tuple.
682-
*
683-
*If the slot contains a virtual tuple, we convert it to physical
684-
*form. The slot retains ownership of the physical tuple.
685-
*If it contains a minimal tuple we convert to regular form and store
686-
*that in addition to the minimal tuple (not instead of, because
687-
*callers may hold pointers to Datums within the minimal tuple).
688-
*
689-
* The main difference between this and ExecMaterializeSlot() is that this
690-
* does not guarantee that the contained tuple is local storage.
691-
* Hence, the result must be treated as read-only.
692-
* --------------------------------
679+
/*
680+
* ExecFetchSlotHeapTuple - fetch HeapTuple representing the slot's content
681+
*
682+
* The returned HeapTuple represents the slot's content as closely as
683+
* possible.
684+
*
685+
* If materialize is true, the contents of the slots will be made independent
686+
* from the underlying storage (i.e. all buffer pins are release, memory is
687+
* allocated in the slot's context).
688+
*
689+
* If shouldFree is not-NULL it'll be set to true if the returned tuple has
690+
* been allocated in the calling memory context, and must be freed by the
691+
* caller (via explicit pfree() or a memory context reset).
692+
*
693+
* NB: If materialize is true, modifications of the returned tuple are
694+
* allowed. But it depends on the type of the slot whether such modifications
695+
* will also affect the slot's contents. While that is not the nicest
696+
* behaviour, all such modifcations are in the process of being removed.
693697
*/
694698
HeapTuple
695-
ExecFetchSlotTuple(TupleTableSlot*slot)
699+
ExecFetchSlotHeapTuple(TupleTableSlot*slot,boolmaterialize,bool*shouldFree)
696700
{
697701
/*
698702
* sanity checks
699703
*/
700704
Assert(slot!=NULL);
701705
Assert(!TTS_EMPTY(slot));
702706

707+
/* will be used in the near future */
708+
if (shouldFree)
709+
*shouldFree= false;
710+
703711
/*
704712
* If we have a regular physical tuple then just return it.
705713
*/
@@ -722,7 +730,9 @@ ExecFetchSlotTuple(TupleTableSlot *slot)
722730
/*
723731
* Otherwise materialize the slot...
724732
*/
725-
returnExecMaterializeSlot(slot);
733+
ExecMaterializeSlot(slot);
734+
735+
returnslot->tts_tuple;
726736
}
727737

728738
/* --------------------------------
@@ -739,7 +749,7 @@ ExecFetchSlotTuple(TupleTableSlot *slot)
739749
* --------------------------------
740750
*/
741751
MinimalTuple
742-
ExecFetchSlotMinimalTuple(TupleTableSlot*slot)
752+
ExecFetchSlotMinimalTuple(TupleTableSlot*slot,bool*shouldFree)
743753
{
744754
MemoryContextoldContext;
745755

@@ -749,6 +759,9 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
749759
Assert(slot!=NULL);
750760
Assert(!TTS_EMPTY(slot));
751761

762+
/* will be used in the near future */
763+
if (shouldFree)
764+
*shouldFree= false;
752765

753766
/*
754767
* If we have a minimal physical tuple (local or not) then just return it.
@@ -779,40 +792,44 @@ ExecFetchSlotMinimalTuple(TupleTableSlot *slot)
779792
}
780793

781794
/* --------------------------------
782-
*ExecFetchSlotTupleDatum
795+
*ExecFetchSlotHeapTupleDatum
783796
*Fetch the slot's tuple as a composite-type Datum.
784797
*
785798
*The result is always freshly palloc'd in the caller's memory context.
786799
* --------------------------------
787800
*/
788801
Datum
789-
ExecFetchSlotTupleDatum(TupleTableSlot*slot)
802+
ExecFetchSlotHeapTupleDatum(TupleTableSlot*slot)
790803
{
791804
HeapTupletup;
792805
TupleDesctupdesc;
806+
boolshouldFree;
807+
Datumret;
793808

794809
/* Fetch slot's contents in regular-physical-tuple form */
795-
tup=ExecFetchSlotTuple(slot);
810+
tup=ExecFetchSlotHeapTuple(slot, false,&shouldFree);
796811
tupdesc=slot->tts_tupleDescriptor;
797812

798813
/* Convert to Datum form */
799-
returnheap_copy_tuple_as_datum(tup,tupdesc);
814+
ret=heap_copy_tuple_as_datum(tup,tupdesc);
815+
816+
if (shouldFree)
817+
pfree(tup);
818+
819+
returnret;
800820
}
801821

802-
/* --------------------------------
803-
*ExecMaterializeSlot
804-
*Force a slot into the "materialized" state.
822+
/* ExecMaterializeSlot - force a slot into the "materialized" state.
805823
*
806-
*This causes the slot's tuple to be a local copy not dependent on
807-
*any external storage. A pointer to the contained tuple is returned.
824+
* This causes the slot's tuple to be a local copy not dependent on any
825+
* external storage (i.e. pointing into a Buffer, or having allocations in
826+
* another memory context).
808827
*
809-
*A typical use for this operation is to prepare a computed tuple
810-
*for being stored on disk. The original data may or may not be
811-
*virtual, but in any case we need a private copy for heap_insert
812-
*to scribble on.
813-
* --------------------------------
828+
* A typical use for this operation is to prepare a computed tuple for being
829+
* stored on disk. The original data may or may not be virtual, but in any
830+
* case we need a private copy for heap_insert to scribble on.
814831
*/
815-
HeapTuple
832+
void
816833
ExecMaterializeSlot(TupleTableSlot*slot)
817834
{
818835
MemoryContextoldContext;
@@ -828,7 +845,7 @@ ExecMaterializeSlot(TupleTableSlot *slot)
828845
* nothing to do.
829846
*/
830847
if (slot->tts_tuple&&TTS_SHOULDFREE(slot))
831-
returnslot->tts_tuple;
848+
return;
832849

833850
/*
834851
* Otherwise, copy or build a physical tuple, and store it into the slot.
@@ -868,8 +885,6 @@ ExecMaterializeSlot(TupleTableSlot *slot)
868885
*/
869886
if (!TTS_SHOULDFREEMIN(slot))
870887
slot->tts_mintuple=NULL;
871-
872-
returnslot->tts_tuple;
873888
}
874889

875890
/* --------------------------------

‎src/backend/executor/functions.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,7 @@ postquel_get_single_result(TupleTableSlot *slot,
969969
{
970970
/* We must return the whole tuple as a Datum. */
971971
fcinfo->isnull= false;
972-
value=ExecFetchSlotTupleDatum(slot);
972+
value=ExecFetchSlotHeapTupleDatum(slot);
973973
}
974974
else
975975
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp