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

Commit4da597e

Browse files
committed
Make TupleTableSlots extensible, finish split of existing slot type.
This commit completes the work prepared in1a0586d, splitting theold TupleTableSlot implementation (which could store buffer, heap,minimal and virtual slots) into four different slot types. Asdescribed in the aforementioned commit, this is done with the goal ofmaking tuple table slots extensible, to allow for pluggable tableaccess methods.To achieve runtime extensibility for TupleTableSlots, operations onslots that can differ between types of slots are performed using theTupleTableSlotOps struct provided at slot creation time. Thatincludes information from the size of TupleTableSlot struct to beallocated, initialization, deforming etc. See the struct's definitionfor more detailed information about callbacks TupleTableSlotOps.I decided to rename TTSOpsBufferTuple to TTSOpsBufferHeapTuple andExecCopySlotTuple to ExecCopySlotHeapTuple, as that seems moreconsistent with other naming introduced in recent patches.There's plenty optimization potential in the slot implementation, butaccording to benchmarking the state after this commit has similarperformance characteristics to before this set of changes, which seemssufficient.There's a few changes in execReplication.c that currently need to pokethrough the slot abstraction, that'll be repaired once the pluggablestorage patchset provides the necessary infrastructure.Author: Andres Freund and Ashutosh Bapat, with changes by Amit KhandekarDiscussion:https://postgr.es/m/20181105210039.hh4vvi4vwoq5ba2q@alap3.anarazel.de
1 parent0201d79 commit4da597e

27 files changed

+1505
-867
lines changed

‎src/backend/access/common/heaptuple.c

Lines changed: 3 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@
7171
#defineVARLENA_ATT_IS_PACKABLE(att) \
7272
((att)->attstorage != 'p')
7373

74+
staticDatumgetmissingattr(TupleDesctupleDesc,intattnum,bool*isnull);
75+
7476

7577
/* ----------------------------------------------------------------
7678
*misc support routines
@@ -80,7 +82,7 @@
8082
/*
8183
* Return the missing value of an attribute, or NULL if there isn't one.
8284
*/
83-
Datum
85+
staticDatum
8486
getmissingattr(TupleDesctupleDesc,
8587
intattnum,bool*isnull)
8688
{
@@ -1350,186 +1352,6 @@ heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc,
13501352
values[attnum]=getmissingattr(tupleDesc,attnum+1,&isnull[attnum]);
13511353
}
13521354

1353-
/*
1354-
* slot_deform_tuple
1355-
*Given a TupleTableSlot, extract data from the slot's physical tuple
1356-
*into its Datum/isnull arrays. Data is extracted up through the
1357-
*natts'th column (caller must ensure this is a legal column number).
1358-
*
1359-
*This is essentially an incremental version of heap_deform_tuple:
1360-
*on each call we extract attributes up to the one needed, without
1361-
*re-computing information about previously extracted attributes.
1362-
*slot->tts_nvalid is the number of attributes already extracted.
1363-
*/
1364-
void
1365-
slot_deform_tuple(TupleTableSlot*slot,intnatts)
1366-
{
1367-
HeapTupletuple=slot->tts_tuple;
1368-
TupleDesctupleDesc=slot->tts_tupleDescriptor;
1369-
Datum*values=slot->tts_values;
1370-
bool*isnull=slot->tts_isnull;
1371-
HeapTupleHeadertup=tuple->t_data;
1372-
boolhasnulls=HeapTupleHasNulls(tuple);
1373-
intattnum;
1374-
char*tp;/* ptr to tuple data */
1375-
uint32off;/* offset in tuple data */
1376-
bits8*bp=tup->t_bits;/* ptr to null bitmap in tuple */
1377-
boolslow;/* can we use/set attcacheoff? */
1378-
1379-
/*
1380-
* Check whether the first call for this tuple, and initialize or restore
1381-
* loop state.
1382-
*/
1383-
attnum=slot->tts_nvalid;
1384-
if (attnum==0)
1385-
{
1386-
/* Start from the first attribute */
1387-
off=0;
1388-
slow= false;
1389-
}
1390-
else
1391-
{
1392-
/* Restore state from previous execution */
1393-
off=slot->tts_off;
1394-
slow=TTS_SLOW(slot);
1395-
}
1396-
1397-
tp= (char*)tup+tup->t_hoff;
1398-
1399-
for (;attnum<natts;attnum++)
1400-
{
1401-
Form_pg_attributethisatt=TupleDescAttr(tupleDesc,attnum);
1402-
1403-
if (hasnulls&&att_isnull(attnum,bp))
1404-
{
1405-
values[attnum]= (Datum)0;
1406-
isnull[attnum]= true;
1407-
slow= true;/* can't use attcacheoff anymore */
1408-
continue;
1409-
}
1410-
1411-
isnull[attnum]= false;
1412-
1413-
if (!slow&&thisatt->attcacheoff >=0)
1414-
off=thisatt->attcacheoff;
1415-
elseif (thisatt->attlen==-1)
1416-
{
1417-
/*
1418-
* We can only cache the offset for a varlena attribute if the
1419-
* offset is already suitably aligned, so that there would be no
1420-
* pad bytes in any case: then the offset will be valid for either
1421-
* an aligned or unaligned value.
1422-
*/
1423-
if (!slow&&
1424-
off==att_align_nominal(off,thisatt->attalign))
1425-
thisatt->attcacheoff=off;
1426-
else
1427-
{
1428-
off=att_align_pointer(off,thisatt->attalign,-1,
1429-
tp+off);
1430-
slow= true;
1431-
}
1432-
}
1433-
else
1434-
{
1435-
/* not varlena, so safe to use att_align_nominal */
1436-
off=att_align_nominal(off,thisatt->attalign);
1437-
1438-
if (!slow)
1439-
thisatt->attcacheoff=off;
1440-
}
1441-
1442-
values[attnum]=fetchatt(thisatt,tp+off);
1443-
1444-
off=att_addlength_pointer(off,thisatt->attlen,tp+off);
1445-
1446-
if (thisatt->attlen <=0)
1447-
slow= true;/* can't use attcacheoff anymore */
1448-
}
1449-
1450-
/*
1451-
* Save state for next execution
1452-
*/
1453-
slot->tts_nvalid=attnum;
1454-
slot->tts_off=off;
1455-
if (slow)
1456-
slot->tts_flags |=TTS_FLAG_SLOW;
1457-
else
1458-
slot->tts_flags &= ~TTS_FLAG_SLOW;
1459-
}
1460-
1461-
/*
1462-
* slot_attisnull
1463-
*Detect whether an attribute of the slot is null, without
1464-
*actually fetching it.
1465-
*/
1466-
bool
1467-
slot_attisnull(TupleTableSlot*slot,intattnum)
1468-
{
1469-
HeapTupletuple=slot->tts_tuple;
1470-
TupleDesctupleDesc=slot->tts_tupleDescriptor;
1471-
1472-
/*
1473-
* system attributes are handled by heap_attisnull
1474-
*/
1475-
if (attnum <=0)
1476-
{
1477-
if (tuple==NULL)/* internal error */
1478-
elog(ERROR,"cannot extract system attribute from virtual tuple");
1479-
if (tuple==&(slot->tts_minhdr))/* internal error */
1480-
elog(ERROR,"cannot extract system attribute from minimal tuple");
1481-
returnheap_attisnull(tuple,attnum,tupleDesc);
1482-
}
1483-
1484-
/*
1485-
* fast path if desired attribute already cached
1486-
*/
1487-
if (attnum <=slot->tts_nvalid)
1488-
returnslot->tts_isnull[attnum-1];
1489-
1490-
/*
1491-
* return NULL if attnum is out of range according to the tupdesc
1492-
*/
1493-
if (attnum>tupleDesc->natts)
1494-
return true;
1495-
1496-
/*
1497-
* otherwise we had better have a physical tuple (tts_nvalid should equal
1498-
* natts in all virtual-tuple cases)
1499-
*/
1500-
if (tuple==NULL)/* internal error */
1501-
elog(ERROR,"cannot extract attribute from empty tuple slot");
1502-
1503-
/* and let the tuple tell it */
1504-
returnheap_attisnull(tuple,attnum,tupleDesc);
1505-
}
1506-
1507-
/*
1508-
* slot_getsysattr
1509-
*This function fetches a system attribute of the slot's current tuple.
1510-
*Unlike slot_getattr, if the slot does not contain system attributes,
1511-
*this will return false (with a NULL attribute value) instead of
1512-
*throwing an error.
1513-
*/
1514-
bool
1515-
slot_getsysattr(TupleTableSlot*slot,intattnum,
1516-
Datum*value,bool*isnull)
1517-
{
1518-
HeapTupletuple=slot->tts_tuple;
1519-
1520-
Assert(attnum<0);/* else caller error */
1521-
if (tuple==NULL||
1522-
tuple==&(slot->tts_minhdr))
1523-
{
1524-
/* No physical tuple, or minimal tuple, so fail */
1525-
*value= (Datum)0;
1526-
*isnull= true;
1527-
return false;
1528-
}
1529-
*value=heap_getsysattr(tuple,attnum,slot->tts_tupleDescriptor,isnull);
1530-
return true;
1531-
}
1532-
15331355
/*
15341356
* heap_freetuple
15351357
*/

‎src/backend/catalog/index.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2041,7 +2041,9 @@ FormIndexDatum(IndexInfo *indexInfo,
20412041
DatumiDatum;
20422042
boolisNull;
20432043

2044-
if (keycol!=0)
2044+
if (keycol<0)
2045+
iDatum=slot_getsysattr(slot,keycol,&isNull);
2046+
elseif (keycol!=0)
20452047
{
20462048
/*
20472049
* Plain index column; get the value we need directly from the

‎src/backend/commands/copy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2850,7 +2850,7 @@ CopyFrom(CopyState cstate)
28502850
* freed after each batch insert.
28512851
*/
28522852
oldcontext=MemoryContextSwitchTo(GetPerTupleMemoryContext(estate));
2853-
tuple=ExecCopySlotTuple(slot);
2853+
tuple=ExecCopySlotHeapTuple(slot);
28542854
MemoryContextSwitchTo(oldcontext);
28552855
}
28562856

‎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=ExecCopySlotTuple(slot);
592+
tuple=ExecCopySlotHeapTuple(slot);
593593

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

‎src/backend/commands/matview.c

Lines changed: 1 addition & 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=ExecCopySlotTuple(slot);
487+
tuple=ExecCopySlotHeapTuple(slot);
488488

489489
heap_insert(myState->transientrel,
490490
tuple,

‎src/backend/executor/execCurrent.c

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -218,27 +218,25 @@ execCurrentOf(CurrentOfExpr *cexpr,
218218
ItemPointertuple_tid;
219219

220220
#ifdefUSE_ASSERT_CHECKING
221-
if (!slot_getsysattr(scanstate->ss_ScanTupleSlot,
222-
TableOidAttributeNumber,
223-
&ldatum,
224-
&lisnull))
221+
ldatum=slot_getsysattr(scanstate->ss_ScanTupleSlot,
222+
TableOidAttributeNumber,
223+
&lisnull);
224+
if (lisnull)
225225
ereport(ERROR,
226226
(errcode(ERRCODE_INVALID_CURSOR_STATE),
227227
errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
228228
cursor_name,table_name)));
229-
Assert(!lisnull);
230229
Assert(DatumGetObjectId(ldatum)==table_oid);
231230
#endif
232231

233-
if (!slot_getsysattr(scanstate->ss_ScanTupleSlot,
234-
SelfItemPointerAttributeNumber,
235-
&ldatum,
236-
&lisnull))
232+
ldatum=slot_getsysattr(scanstate->ss_ScanTupleSlot,
233+
SelfItemPointerAttributeNumber,
234+
&lisnull);
235+
if (lisnull)
237236
ereport(ERROR,
238237
(errcode(ERRCODE_INVALID_CURSOR_STATE),
239238
errmsg("cursor \"%s\" is not a simply updatable scan of table \"%s\"",
240239
cursor_name,table_name)));
241-
Assert(!lisnull);
242240
tuple_tid= (ItemPointer)DatumGetPointer(ldatum);
243241

244242
*current_tid=*tuple_tid;

‎src/backend/executor/execExprInterp.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1875,11 +1875,11 @@ CheckOpSlotCompatibility(ExprEvalStep *op, TupleTableSlot *slot)
18751875
* Should probably fixed at some point, but for now it's easier to allow
18761876
* buffer and heap tuples to be used interchangably.
18771877
*/
1878-
if (slot->tts_ops==&TTSOpsBufferTuple&&
1878+
if (slot->tts_ops==&TTSOpsBufferHeapTuple&&
18791879
op->d.fetch.kind==&TTSOpsHeapTuple)
18801880
return;
18811881
if (slot->tts_ops==&TTSOpsHeapTuple&&
1882-
op->d.fetch.kind==&TTSOpsBufferTuple)
1882+
op->d.fetch.kind==&TTSOpsBufferHeapTuple)
18831883
return;
18841884

18851885
/*
@@ -4025,15 +4025,15 @@ void
40254025
ExecEvalSysVar(ExprState*state,ExprEvalStep*op,ExprContext*econtext,
40264026
TupleTableSlot*slot)
40274027
{
4028-
boolsuccess;
4028+
Datumd;
40294029

40304030
/* slot_getsysattr has sufficient defenses against bad attnums */
4031-
success=slot_getsysattr(slot,
4032-
op->d.var.attnum,
4033-
op->resvalue,
4034-
op->resnull);
4031+
d=slot_getsysattr(slot,
4032+
op->d.var.attnum,
4033+
op->resnull);
4034+
*op->resvalue=d;
40354035
/* this ought to be unreachable, but it's cheap enough to check */
4036-
if (unlikely(!success))
4036+
if (unlikely(*op->resnull))
40374037
elog(ERROR,"failed to fetch attribute from slot");
40384038
}
40394039

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp