#ifndef TUPTABLE_H
#define TUPTABLE_H
#include "access/htup.h"
#include "access/htup_details.h"
#include "access/sysattr.h"
#include "access/tupdesc.h"
#include "storage/buf.h"
#define TTS_FLAG_EMPTY (1 << 1)
#define TTS_EMPTY(slot) (((slot)->tts_flags & TTS_FLAG_EMPTY) != 0)
#define TTS_FLAG_SHOULDFREE (1 << 2)
#define TTS_SHOULDFREE(slot) (((slot)->tts_flags & TTS_FLAG_SHOULDFREE) != 0)
#define TTS_FLAG_SLOW (1 << 3)
#define TTS_SLOW(slot) (((slot)->tts_flags & TTS_FLAG_SLOW) != 0)
#define TTS_FLAG_FIXED (1 << 4)
#define TTS_FIXED(slot) (((slot)->tts_flags & TTS_FLAG_FIXED) != 0)
struct TupleTableSlotOps;
typedef struct TupleTableSlotOps TupleTableSlotOps;
typedef struct TupleTableSlot
{
NodeTag type;
#define FIELDNO_TUPLETABLESLOT_FLAGS 1
uint16 tts_flags;
#define FIELDNO_TUPLETABLESLOT_NVALID 2
AttrNumber tts_nvalid;
const TupleTableSlotOps *const tts_ops;
#define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
TupleDesc tts_tupleDescriptor;
#define FIELDNO_TUPLETABLESLOT_VALUES 5
Datum *tts_values;
#define FIELDNO_TUPLETABLESLOT_ISNULL 6
bool *tts_isnull;
MemoryContext tts_mcxt;
ItemPointerData tts_tid;
Oid tts_tableOid;
} TupleTableSlot;
struct TupleTableSlotOps
{
size_t base_slot_size;
void (*init) (TupleTableSlot *slot);
void (*release) (TupleTableSlot *slot);
void (*clear) (TupleTableSlot *slot);
void (*getsomeattrs) (TupleTableSlot *slot, int natts);
Datum (*getsysattr) (TupleTableSlot *slot, int attnum, bool *isnull);
bool (*is_current_xact_tuple) (TupleTableSlot *slot);
void (*materialize) (TupleTableSlot *slot);
void (*copyslot) (TupleTableSlot *dstslot, TupleTableSlot *srcslot);
HeapTuple (*get_heap_tuple) (TupleTableSlot *slot);
MinimalTuple (*get_minimal_tuple) (TupleTableSlot *slot);
HeapTuple (*copy_heap_tuple) (TupleTableSlot *slot);
MinimalTuple (*copy_minimal_tuple) (TupleTableSlot *slot);
};
extern PGDLLIMPORT const TupleTableSlotOps TTSOpsVirtual;
extern PGDLLIMPORT const TupleTableSlotOps TTSOpsHeapTuple;
extern PGDLLIMPORT const TupleTableSlotOps TTSOpsMinimalTuple;
extern PGDLLIMPORT const TupleTableSlotOps TTSOpsBufferHeapTuple;
#define TTS_IS_VIRTUAL(slot) ((slot)->tts_ops == &TTSOpsVirtual)
#define TTS_IS_HEAPTUPLE(slot) ((slot)->tts_ops == &TTSOpsHeapTuple)
#define TTS_IS_MINIMALTUPLE(slot) ((slot)->tts_ops == &TTSOpsMinimalTuple)
#define TTS_IS_BUFFERTUPLE(slot) ((slot)->tts_ops == &TTSOpsBufferHeapTuple)
typedef struct VirtualTupleTableSlot
{
pg_node_attr(abstract)
TupleTableSlot base;
char *data;
} VirtualTupleTableSlot;
typedef struct HeapTupleTableSlot
{
pg_node_attr(abstract)
TupleTableSlot base;
#define FIELDNO_HEAPTUPLETABLESLOT_TUPLE 1
HeapTuple tuple;
#define FIELDNO_HEAPTUPLETABLESLOT_OFF 2
uint32 off;
HeapTupleData tupdata;
} HeapTupleTableSlot;
typedef struct BufferHeapTupleTableSlot
{
pg_node_attr(abstract)
HeapTupleTableSlot base;
Buffer buffer;
} BufferHeapTupleTableSlot;
typedef struct MinimalTupleTableSlot
{
pg_node_attr(abstract)
TupleTableSlot base;
#define FIELDNO_MINIMALTUPLETABLESLOT_TUPLE 1
HeapTuple tuple;
MinimalTuple mintuple;
HeapTupleData minhdr;
#define FIELDNO_MINIMALTUPLETABLESLOT_OFF 4
uint32 off;
} MinimalTupleTableSlot;
#define TupIsNull(slot) \
((slot) == NULL || TTS_EMPTY(slot))
extern TupleTableSlot *MakeTupleTableSlot(TupleDesc tupleDesc,
const TupleTableSlotOps *tts_ops);
extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc,
const TupleTableSlotOps *tts_ops);
extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc,
const TupleTableSlotOps *tts_ops);
extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
extern TupleTableSlot *ExecStoreHeapTuple(HeapTuple tuple,
TupleTableSlot *slot,
bool shouldFree);
extern void ExecForceStoreHeapTuple(HeapTuple tuple,
TupleTableSlot *slot,
bool shouldFree);
extern TupleTableSlot *ExecStoreBufferHeapTuple(HeapTuple tuple,
TupleTableSlot *slot,
Buffer buffer);
extern TupleTableSlot *ExecStorePinnedBufferHeapTuple(HeapTuple tuple,
TupleTableSlot *slot,
Buffer buffer);
extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup,
TupleTableSlot *slot,
bool shouldFree);
extern void ExecForceStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot,
bool shouldFree);
extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot);
extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot);
extern void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot);
extern HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree);
extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
bool *shouldFree);
extern Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot);
extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum,
int lastAttNum);
extern void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum);
#ifndef FRONTEND
static inline void
slot_getsomeattrs(TupleTableSlot *slot, int attnum)
{
if (slot->tts_nvalid < attnum)
slot_getsomeattrs_int(slot, attnum);
}
static inline void
slot_getallattrs(TupleTableSlot *slot)
{
slot_getsomeattrs(slot, slot->tts_tupleDescriptor->natts);
}
static inline bool
slot_attisnull(TupleTableSlot *slot, int attnum)
{
Assert(attnum > 0);
if (attnum > slot->tts_nvalid)
slot_getsomeattrs(slot, attnum);
return slot->tts_isnull[attnum - 1];
}
static inline Datum
slot_getattr(TupleTableSlot *slot, int attnum,
bool *isnull)
{
Assert(attnum > 0);
if (attnum > slot->tts_nvalid)
slot_getsomeattrs(slot, attnum);
*isnull = slot->tts_isnull[attnum - 1];
return slot->tts_values[attnum - 1];
}
static inline Datum
slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
{
Assert(attnum < 0);
if (attnum == TableOidAttributeNumber)
{
*isnull = false;
return ObjectIdGetDatum(slot->tts_tableOid);
}
else if (attnum == SelfItemPointerAttributeNumber)
{
*isnull = false;
return PointerGetDatum(&slot->tts_tid);
}
return slot->tts_ops->getsysattr(slot, attnum, isnull);
}
static inline bool
slot_is_current_xact_tuple(TupleTableSlot *slot)
{
return slot->tts_ops->is_current_xact_tuple(slot);
}
static inline TupleTableSlot *
ExecClearTuple(TupleTableSlot *slot)
{
slot->tts_ops->clear(slot);
return slot;
}
static inline void
ExecMaterializeSlot(TupleTableSlot *slot)
{
slot->tts_ops->materialize(slot);
}
static inline HeapTuple
ExecCopySlotHeapTuple(TupleTableSlot *slot)
{
Assert(!TTS_EMPTY(slot));
return slot->tts_ops->copy_heap_tuple(slot);
}
static inline MinimalTuple
ExecCopySlotMinimalTuple(TupleTableSlot *slot)
{
return slot->tts_ops->copy_minimal_tuple(slot);
}
static inline TupleTableSlot *
ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
{
Assert(!TTS_EMPTY(srcslot));
Assert(srcslot != dstslot);
Assert(dstslot->tts_tupleDescriptor->natts ==
srcslot->tts_tupleDescriptor->natts);
dstslot->tts_ops->copyslot(dstslot, srcslot);
return dstslot;
}
#endif
#endif