2
0

tuptable.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. /*-------------------------------------------------------------------------
  2. *
  3. * tuptable.h
  4. * tuple table support stuff
  5. *
  6. *
  7. * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
  8. * Portions Copyright (c) 1994, Regents of the University of California
  9. *
  10. * src/include/executor/tuptable.h
  11. *
  12. *-------------------------------------------------------------------------
  13. */
  14. #ifndef TUPTABLE_H
  15. #define TUPTABLE_H
  16. #include "access/htup.h"
  17. #include "access/htup_details.h"
  18. #include "access/sysattr.h"
  19. #include "access/tupdesc.h"
  20. #include "storage/buf.h"
  21. /*----------
  22. * The executor stores tuples in a "tuple table" which is a List of
  23. * independent TupleTableSlots.
  24. *
  25. * There's various different types of tuple table slots, each being able to
  26. * store different types of tuples. Additional types of slots can be added
  27. * without modifying core code. The type of a slot is determined by the
  28. * TupleTableSlotOps* passed to the slot creation routine. The builtin types
  29. * of slots are
  30. *
  31. * 1. physical tuple in a disk buffer page (TTSOpsBufferHeapTuple)
  32. * 2. physical tuple constructed in palloc'ed memory (TTSOpsHeapTuple)
  33. * 3. "minimal" physical tuple constructed in palloc'ed memory
  34. * (TTSOpsMinimalTuple)
  35. * 4. "virtual" tuple consisting of Datum/isnull arrays (TTSOpsVirtual)
  36. *
  37. *
  38. * The first two cases are similar in that they both deal with "materialized"
  39. * tuples, but resource management is different. For a tuple in a disk page
  40. * we need to hold a pin on the buffer until the TupleTableSlot's reference
  41. * to the tuple is dropped; while for a palloc'd tuple we usually want the
  42. * tuple pfree'd when the TupleTableSlot's reference is dropped.
  43. *
  44. * A "minimal" tuple is handled similarly to a palloc'd regular tuple.
  45. * At present, minimal tuples never are stored in buffers, so there is no
  46. * parallel to case 1. Note that a minimal tuple has no "system columns".
  47. * (Actually, it could have an OID, but we have no need to access the OID.)
  48. *
  49. * A "virtual" tuple is an optimization used to minimize physical data copying
  50. * in a nest of plan nodes. Until materialized pass-by-reference Datums in
  51. * the slot point to storage that is not directly associated with the
  52. * TupleTableSlot; generally they will point to part of a tuple stored in a
  53. * lower plan node's output TupleTableSlot, or to a function result
  54. * constructed in a plan node's per-tuple econtext. It is the responsibility
  55. * of the generating plan node to be sure these resources are not released for
  56. * as long as the virtual tuple needs to be valid or is materialized. Note
  57. * also that a virtual tuple does not have any "system columns".
  58. *
  59. * The Datum/isnull arrays of a TupleTableSlot serve double duty. For virtual
  60. * slots they are the authoritative data. For the other builtin slots,
  61. * the arrays contain data extracted from the tuple. (In this state, any
  62. * pass-by-reference Datums point into the physical tuple.) The extracted
  63. * information is built "lazily", ie, only as needed. This serves to avoid
  64. * repeated extraction of data from the physical tuple.
  65. *
  66. * A TupleTableSlot can also be "empty", indicated by flag TTS_FLAG_EMPTY set
  67. * in tts_flags, holding no valid data. This is the only valid state for a
  68. * freshly-created slot that has not yet had a tuple descriptor assigned to
  69. * it. In this state, TTS_SHOULDFREE should not be set in tts_flags, tts_tuple
  70. * must be NULL and tts_nvalid zero.
  71. *
  72. * The tupleDescriptor is simply referenced, not copied, by the TupleTableSlot
  73. * code. The caller of ExecSetSlotDescriptor() is responsible for providing
  74. * a descriptor that will live as long as the slot does. (Typically, both
  75. * slots and descriptors are in per-query memory and are freed by memory
  76. * context deallocation at query end; so it's not worth providing any extra
  77. * mechanism to do more. However, the slot will increment the tupdesc
  78. * reference count if a reference-counted tupdesc is supplied.)
  79. *
  80. * When TTS_SHOULDFREE is set in tts_flags, the physical tuple is "owned" by
  81. * the slot and should be freed when the slot's reference to the tuple is
  82. * dropped.
  83. *
  84. * tts_values/tts_isnull are allocated either when the slot is created (when
  85. * the descriptor is provided), or when a descriptor is assigned to the slot;
  86. * they are of length equal to the descriptor's natts.
  87. *
  88. * The TTS_FLAG_SLOW flag is saved state for
  89. * slot_deform_heap_tuple, and should not be touched by any other code.
  90. *----------
  91. */
  92. /* true = slot is empty */
  93. #define TTS_FLAG_EMPTY (1 << 1)
  94. #define TTS_EMPTY(slot) (((slot)->tts_flags & TTS_FLAG_EMPTY) != 0)
  95. /* should pfree tuple "owned" by the slot? */
  96. #define TTS_FLAG_SHOULDFREE (1 << 2)
  97. #define TTS_SHOULDFREE(slot) (((slot)->tts_flags & TTS_FLAG_SHOULDFREE) != 0)
  98. /* saved state for slot_deform_heap_tuple */
  99. #define TTS_FLAG_SLOW (1 << 3)
  100. #define TTS_SLOW(slot) (((slot)->tts_flags & TTS_FLAG_SLOW) != 0)
  101. /* fixed tuple descriptor */
  102. #define TTS_FLAG_FIXED (1 << 4)
  103. #define TTS_FIXED(slot) (((slot)->tts_flags & TTS_FLAG_FIXED) != 0)
  104. struct TupleTableSlotOps;
  105. typedef struct TupleTableSlotOps TupleTableSlotOps;
  106. /* base tuple table slot type */
  107. typedef struct TupleTableSlot
  108. {
  109. NodeTag type;
  110. #define FIELDNO_TUPLETABLESLOT_FLAGS 1
  111. uint16 tts_flags; /* Boolean states */
  112. #define FIELDNO_TUPLETABLESLOT_NVALID 2
  113. AttrNumber tts_nvalid; /* # of valid values in tts_values */
  114. const TupleTableSlotOps *const tts_ops; /* implementation of slot */
  115. #define FIELDNO_TUPLETABLESLOT_TUPLEDESCRIPTOR 4
  116. TupleDesc tts_tupleDescriptor; /* slot's tuple descriptor */
  117. #define FIELDNO_TUPLETABLESLOT_VALUES 5
  118. Datum *tts_values; /* current per-attribute values */
  119. #define FIELDNO_TUPLETABLESLOT_ISNULL 6
  120. bool *tts_isnull; /* current per-attribute isnull flags */
  121. MemoryContext tts_mcxt; /* slot itself is in this context */
  122. ItemPointerData tts_tid; /* stored tuple's tid */
  123. Oid tts_tableOid; /* table oid of tuple */
  124. } TupleTableSlot;
  125. /* routines for a TupleTableSlot implementation */
  126. struct TupleTableSlotOps
  127. {
  128. /* Minimum size of the slot */
  129. size_t base_slot_size;
  130. /* Initialization. */
  131. void (*init) (TupleTableSlot *slot);
  132. /* Destruction. */
  133. void (*release) (TupleTableSlot *slot);
  134. /*
  135. * Clear the contents of the slot. Only the contents are expected to be
  136. * cleared and not the tuple descriptor. Typically an implementation of
  137. * this callback should free the memory allocated for the tuple contained
  138. * in the slot.
  139. */
  140. void (*clear) (TupleTableSlot *slot);
  141. /*
  142. * Fill up first natts entries of tts_values and tts_isnull arrays with
  143. * values from the tuple contained in the slot. The function may be called
  144. * with natts more than the number of attributes available in the tuple,
  145. * in which case it should set tts_nvalid to the number of returned
  146. * columns.
  147. */
  148. void (*getsomeattrs) (TupleTableSlot *slot, int natts);
  149. /*
  150. * Returns value of the given system attribute as a datum and sets isnull
  151. * to false, if it's not NULL. Throws an error if the slot type does not
  152. * support system attributes.
  153. */
  154. Datum (*getsysattr) (TupleTableSlot *slot, int attnum, bool *isnull);
  155. /*
  156. * Make the contents of the slot solely depend on the slot, and not on
  157. * underlying resources (like another memory context, buffers, etc).
  158. */
  159. void (*materialize) (TupleTableSlot *slot);
  160. /*
  161. * Copy the contents of the source slot into the destination slot's own
  162. * context. Invoked using callback of the destination slot.
  163. */
  164. void (*copyslot) (TupleTableSlot *dstslot, TupleTableSlot *srcslot);
  165. /*
  166. * Return a heap tuple "owned" by the slot. It is slot's responsibility to
  167. * free the memory consumed by the heap tuple. If the slot can not "own" a
  168. * heap tuple, it should not implement this callback and should set it as
  169. * NULL.
  170. */
  171. HeapTuple (*get_heap_tuple) (TupleTableSlot *slot);
  172. /*
  173. * Return a minimal tuple "owned" by the slot. It is slot's responsibility
  174. * to free the memory consumed by the minimal tuple. If the slot can not
  175. * "own" a minimal tuple, it should not implement this callback and should
  176. * set it as NULL.
  177. */
  178. MinimalTuple (*get_minimal_tuple) (TupleTableSlot *slot);
  179. /*
  180. * Return a copy of heap tuple representing the contents of the slot. The
  181. * copy needs to be palloc'd in the current memory context. The slot
  182. * itself is expected to remain unaffected. It is *not* expected to have
  183. * meaningful "system columns" in the copy. The copy is not be "owned" by
  184. * the slot i.e. the caller has to take responsibility to free memory
  185. * consumed by the slot.
  186. */
  187. HeapTuple (*copy_heap_tuple) (TupleTableSlot *slot);
  188. /*
  189. * Return a copy of minimal tuple representing the contents of the slot.
  190. * The copy needs to be palloc'd in the current memory context. The slot
  191. * itself is expected to remain unaffected. It is *not* expected to have
  192. * meaningful "system columns" in the copy. The copy is not be "owned" by
  193. * the slot i.e. the caller has to take responsibility to free memory
  194. * consumed by the slot.
  195. */
  196. MinimalTuple (*copy_minimal_tuple) (TupleTableSlot *slot);
  197. };
  198. /*
  199. * Predefined TupleTableSlotOps for various types of TupleTableSlotOps. The
  200. * same are used to identify the type of a given slot.
  201. */
  202. extern PGDLLIMPORT const TupleTableSlotOps TTSOpsVirtual;
  203. extern PGDLLIMPORT const TupleTableSlotOps TTSOpsHeapTuple;
  204. extern PGDLLIMPORT const TupleTableSlotOps TTSOpsMinimalTuple;
  205. extern PGDLLIMPORT const TupleTableSlotOps TTSOpsBufferHeapTuple;
  206. #define TTS_IS_VIRTUAL(slot) ((slot)->tts_ops == &TTSOpsVirtual)
  207. #define TTS_IS_HEAPTUPLE(slot) ((slot)->tts_ops == &TTSOpsHeapTuple)
  208. #define TTS_IS_MINIMALTUPLE(slot) ((slot)->tts_ops == &TTSOpsMinimalTuple)
  209. #define TTS_IS_BUFFERTUPLE(slot) ((slot)->tts_ops == &TTSOpsBufferHeapTuple)
  210. /*
  211. * Tuple table slot implementations.
  212. */
  213. typedef struct VirtualTupleTableSlot
  214. {
  215. TupleTableSlot base;
  216. char *data; /* data for materialized slots */
  217. } VirtualTupleTableSlot;
  218. typedef struct HeapTupleTableSlot
  219. {
  220. TupleTableSlot base;
  221. #define FIELDNO_HEAPTUPLETABLESLOT_TUPLE 1
  222. HeapTuple tuple; /* physical tuple */
  223. #define FIELDNO_HEAPTUPLETABLESLOT_OFF 2
  224. uint32 off; /* saved state for slot_deform_heap_tuple */
  225. HeapTupleData tupdata; /* optional workspace for storing tuple */
  226. } HeapTupleTableSlot;
  227. /* heap tuple residing in a buffer */
  228. typedef struct BufferHeapTupleTableSlot
  229. {
  230. HeapTupleTableSlot base;
  231. /*
  232. * If buffer is not InvalidBuffer, then the slot is holding a pin on the
  233. * indicated buffer page; drop the pin when we release the slot's
  234. * reference to that buffer. (TTS_FLAG_SHOULDFREE should not be set in
  235. * such a case, since presumably tts_tuple is pointing into the buffer.)
  236. */
  237. Buffer buffer; /* tuple's buffer, or InvalidBuffer */
  238. } BufferHeapTupleTableSlot;
  239. typedef struct MinimalTupleTableSlot
  240. {
  241. TupleTableSlot base;
  242. /*
  243. * In a minimal slot tuple points at minhdr and the fields of that struct
  244. * are set correctly for access to the minimal tuple; in particular,
  245. * minhdr.t_data points MINIMAL_TUPLE_OFFSET bytes before mintuple. This
  246. * allows column extraction to treat the case identically to regular
  247. * physical tuples.
  248. */
  249. #define FIELDNO_MINIMALTUPLETABLESLOT_TUPLE 1
  250. HeapTuple tuple; /* tuple wrapper */
  251. MinimalTuple mintuple; /* minimal tuple, or NULL if none */
  252. HeapTupleData minhdr; /* workspace for minimal-tuple-only case */
  253. #define FIELDNO_MINIMALTUPLETABLESLOT_OFF 4
  254. uint32 off; /* saved state for slot_deform_heap_tuple */
  255. } MinimalTupleTableSlot;
  256. /*
  257. * TupIsNull -- is a TupleTableSlot empty?
  258. */
  259. #define TupIsNull(slot) \
  260. ((slot) == NULL || TTS_EMPTY(slot))
  261. /* in executor/execTuples.c */
  262. extern TupleTableSlot *MakeTupleTableSlot(TupleDesc tupleDesc,
  263. const TupleTableSlotOps *tts_ops);
  264. extern TupleTableSlot *ExecAllocTableSlot(List **tupleTable, TupleDesc desc,
  265. const TupleTableSlotOps *tts_ops);
  266. extern void ExecResetTupleTable(List *tupleTable, bool shouldFree);
  267. extern TupleTableSlot *MakeSingleTupleTableSlot(TupleDesc tupdesc,
  268. const TupleTableSlotOps *tts_ops);
  269. extern void ExecDropSingleTupleTableSlot(TupleTableSlot *slot);
  270. extern void ExecSetSlotDescriptor(TupleTableSlot *slot, TupleDesc tupdesc);
  271. extern TupleTableSlot *ExecStoreHeapTuple(HeapTuple tuple,
  272. TupleTableSlot *slot,
  273. bool shouldFree);
  274. extern void ExecForceStoreHeapTuple(HeapTuple tuple,
  275. TupleTableSlot *slot,
  276. bool shouldFree);
  277. extern TupleTableSlot *ExecStoreBufferHeapTuple(HeapTuple tuple,
  278. TupleTableSlot *slot,
  279. Buffer buffer);
  280. extern TupleTableSlot *ExecStorePinnedBufferHeapTuple(HeapTuple tuple,
  281. TupleTableSlot *slot,
  282. Buffer buffer);
  283. extern TupleTableSlot *ExecStoreMinimalTuple(MinimalTuple mtup,
  284. TupleTableSlot *slot,
  285. bool shouldFree);
  286. extern void ExecForceStoreMinimalTuple(MinimalTuple mtup, TupleTableSlot *slot,
  287. bool shouldFree);
  288. extern TupleTableSlot *ExecStoreVirtualTuple(TupleTableSlot *slot);
  289. extern TupleTableSlot *ExecStoreAllNullTuple(TupleTableSlot *slot);
  290. extern void ExecStoreHeapTupleDatum(Datum data, TupleTableSlot *slot);
  291. extern HeapTuple ExecFetchSlotHeapTuple(TupleTableSlot *slot, bool materialize, bool *shouldFree);
  292. extern MinimalTuple ExecFetchSlotMinimalTuple(TupleTableSlot *slot,
  293. bool *shouldFree);
  294. extern Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot);
  295. extern void slot_getmissingattrs(TupleTableSlot *slot, int startAttNum,
  296. int lastAttNum);
  297. extern void slot_getsomeattrs_int(TupleTableSlot *slot, int attnum);
  298. #ifndef FRONTEND
  299. /*
  300. * This function forces the entries of the slot's Datum/isnull arrays to be
  301. * valid at least up through the attnum'th entry.
  302. */
  303. static inline void
  304. slot_getsomeattrs(TupleTableSlot *slot, int attnum)
  305. {
  306. if (slot->tts_nvalid < attnum)
  307. slot_getsomeattrs_int(slot, attnum);
  308. }
  309. /*
  310. * slot_getallattrs
  311. * This function forces all the entries of the slot's Datum/isnull
  312. * arrays to be valid. The caller may then extract data directly
  313. * from those arrays instead of using slot_getattr.
  314. */
  315. static inline void
  316. slot_getallattrs(TupleTableSlot *slot)
  317. {
  318. slot_getsomeattrs(slot, slot->tts_tupleDescriptor->natts);
  319. }
  320. /*
  321. * slot_attisnull
  322. *
  323. * Detect whether an attribute of the slot is null, without actually fetching
  324. * it.
  325. */
  326. static inline bool
  327. slot_attisnull(TupleTableSlot *slot, int attnum)
  328. {
  329. AssertArg(attnum > 0);
  330. if (attnum > slot->tts_nvalid)
  331. slot_getsomeattrs(slot, attnum);
  332. return slot->tts_isnull[attnum - 1];
  333. }
  334. /*
  335. * slot_getattr - fetch one attribute of the slot's contents.
  336. */
  337. static inline Datum
  338. slot_getattr(TupleTableSlot *slot, int attnum,
  339. bool *isnull)
  340. {
  341. AssertArg(attnum > 0);
  342. if (attnum > slot->tts_nvalid)
  343. slot_getsomeattrs(slot, attnum);
  344. *isnull = slot->tts_isnull[attnum - 1];
  345. return slot->tts_values[attnum - 1];
  346. }
  347. /*
  348. * slot_getsysattr - fetch a system attribute of the slot's current tuple.
  349. *
  350. * If the slot type does not contain system attributes, this will throw an
  351. * error. Hence before calling this function, callers should make sure that
  352. * the slot type is the one that supports system attributes.
  353. */
  354. static inline Datum
  355. slot_getsysattr(TupleTableSlot *slot, int attnum, bool *isnull)
  356. {
  357. AssertArg(attnum < 0); /* caller error */
  358. if (attnum == TableOidAttributeNumber)
  359. {
  360. *isnull = false;
  361. return ObjectIdGetDatum(slot->tts_tableOid);
  362. }
  363. else if (attnum == SelfItemPointerAttributeNumber)
  364. {
  365. *isnull = false;
  366. return PointerGetDatum(&slot->tts_tid);
  367. }
  368. /* Fetch the system attribute from the underlying tuple. */
  369. return slot->tts_ops->getsysattr(slot, attnum, isnull);
  370. }
  371. /*
  372. * ExecClearTuple - clear the slot's contents
  373. */
  374. static inline TupleTableSlot *
  375. ExecClearTuple(TupleTableSlot *slot)
  376. {
  377. slot->tts_ops->clear(slot);
  378. return slot;
  379. }
  380. /* ExecMaterializeSlot - force a slot into the "materialized" state.
  381. *
  382. * This causes the slot's tuple to be a local copy not dependent on any
  383. * external storage (i.e. pointing into a Buffer, or having allocations in
  384. * another memory context).
  385. *
  386. * A typical use for this operation is to prepare a computed tuple for being
  387. * stored on disk. The original data may or may not be virtual, but in any
  388. * case we need a private copy for heap_insert to scribble on.
  389. */
  390. static inline void
  391. ExecMaterializeSlot(TupleTableSlot *slot)
  392. {
  393. slot->tts_ops->materialize(slot);
  394. }
  395. /*
  396. * ExecCopySlotHeapTuple - return HeapTuple allocated in caller's context
  397. */
  398. static inline HeapTuple
  399. ExecCopySlotHeapTuple(TupleTableSlot *slot)
  400. {
  401. Assert(!TTS_EMPTY(slot));
  402. return slot->tts_ops->copy_heap_tuple(slot);
  403. }
  404. /*
  405. * ExecCopySlotMinimalTuple - return MinimalTuple allocated in caller's context
  406. */
  407. static inline MinimalTuple
  408. ExecCopySlotMinimalTuple(TupleTableSlot *slot)
  409. {
  410. return slot->tts_ops->copy_minimal_tuple(slot);
  411. }
  412. /*
  413. * ExecCopySlot - copy one slot's contents into another.
  414. *
  415. * If a source's system attributes are supposed to be accessed in the target
  416. * slot, the target slot and source slot types need to match.
  417. */
  418. static inline TupleTableSlot *
  419. ExecCopySlot(TupleTableSlot *dstslot, TupleTableSlot *srcslot)
  420. {
  421. Assert(!TTS_EMPTY(srcslot));
  422. AssertArg(srcslot != dstslot);
  423. dstslot->tts_ops->copyslot(dstslot, srcslot);
  424. return dstslot;
  425. }
  426. #endif /* FRONTEND */
  427. #endif /* TUPTABLE_H */