gooderp18绿色标准版
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

246 lignes
7.3KB

  1. /*-------------------------------------------------------------------------
  2. *
  3. * tupmacs.h
  4. * Tuple macros used by both index tuples and heap tuples.
  5. *
  6. *
  7. * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
  8. * Portions Copyright (c) 1994, Regents of the University of California
  9. *
  10. * src/include/access/tupmacs.h
  11. *
  12. *-------------------------------------------------------------------------
  13. */
  14. #ifndef TUPMACS_H
  15. #define TUPMACS_H
  16. /*
  17. * Check a tuple's null bitmap to determine whether the attribute is null.
  18. * Note that a 0 in the null bitmap indicates a null, while 1 indicates
  19. * non-null.
  20. */
  21. #define att_isnull(ATT, BITS) (!((BITS)[(ATT) >> 3] & (1 << ((ATT) & 0x07))))
  22. /*
  23. * Given a Form_pg_attribute and a pointer into a tuple's data area,
  24. * return the correct value or pointer.
  25. *
  26. * We return a Datum value in all cases. If the attribute has "byval" false,
  27. * we return the same pointer into the tuple data area that we're passed.
  28. * Otherwise, we return the correct number of bytes fetched from the data
  29. * area and extended to Datum form.
  30. *
  31. * On machines where Datum is 8 bytes, we support fetching 8-byte byval
  32. * attributes; otherwise, only 1, 2, and 4-byte values are supported.
  33. *
  34. * Note that T must already be properly aligned for this to work correctly.
  35. */
  36. #define fetchatt(A,T) fetch_att(T, (A)->attbyval, (A)->attlen)
  37. /*
  38. * Same, but work from byval/len parameters rather than Form_pg_attribute.
  39. */
  40. #if SIZEOF_DATUM == 8
  41. #define fetch_att(T,attbyval,attlen) \
  42. ( \
  43. (attbyval) ? \
  44. ( \
  45. (attlen) == (int) sizeof(Datum) ? \
  46. *((Datum *)(T)) \
  47. : \
  48. ( \
  49. (attlen) == (int) sizeof(int32) ? \
  50. Int32GetDatum(*((int32 *)(T))) \
  51. : \
  52. ( \
  53. (attlen) == (int) sizeof(int16) ? \
  54. Int16GetDatum(*((int16 *)(T))) \
  55. : \
  56. ( \
  57. AssertMacro((attlen) == 1), \
  58. CharGetDatum(*((char *)(T))) \
  59. ) \
  60. ) \
  61. ) \
  62. ) \
  63. : \
  64. PointerGetDatum((char *) (T)) \
  65. )
  66. #else /* SIZEOF_DATUM != 8 */
  67. #define fetch_att(T,attbyval,attlen) \
  68. ( \
  69. (attbyval) ? \
  70. ( \
  71. (attlen) == (int) sizeof(int32) ? \
  72. Int32GetDatum(*((int32 *)(T))) \
  73. : \
  74. ( \
  75. (attlen) == (int) sizeof(int16) ? \
  76. Int16GetDatum(*((int16 *)(T))) \
  77. : \
  78. ( \
  79. AssertMacro((attlen) == 1), \
  80. CharGetDatum(*((char *)(T))) \
  81. ) \
  82. ) \
  83. ) \
  84. : \
  85. PointerGetDatum((char *) (T)) \
  86. )
  87. #endif /* SIZEOF_DATUM == 8 */
  88. /*
  89. * att_align_datum aligns the given offset as needed for a datum of alignment
  90. * requirement attalign and typlen attlen. attdatum is the Datum variable
  91. * we intend to pack into a tuple (it's only accessed if we are dealing with
  92. * a varlena type). Note that this assumes the Datum will be stored as-is;
  93. * callers that are intending to convert non-short varlena datums to short
  94. * format have to account for that themselves.
  95. */
  96. #define att_align_datum(cur_offset, attalign, attlen, attdatum) \
  97. ( \
  98. ((attlen) == -1 && VARATT_IS_SHORT(DatumGetPointer(attdatum))) ? \
  99. (uintptr_t) (cur_offset) : \
  100. att_align_nominal(cur_offset, attalign) \
  101. )
  102. /*
  103. * att_align_pointer performs the same calculation as att_align_datum,
  104. * but is used when walking a tuple. attptr is the current actual data
  105. * pointer; when accessing a varlena field we have to "peek" to see if we
  106. * are looking at a pad byte or the first byte of a 1-byte-header datum.
  107. * (A zero byte must be either a pad byte, or the first byte of a correctly
  108. * aligned 4-byte length word; in either case we can align safely. A non-zero
  109. * byte must be either a 1-byte length word, or the first byte of a correctly
  110. * aligned 4-byte length word; in either case we need not align.)
  111. *
  112. * Note: some callers pass a "char *" pointer for cur_offset. This is
  113. * a bit of a hack but should work all right as long as uintptr_t is the
  114. * correct width.
  115. */
  116. #define att_align_pointer(cur_offset, attalign, attlen, attptr) \
  117. ( \
  118. ((attlen) == -1 && VARATT_NOT_PAD_BYTE(attptr)) ? \
  119. (uintptr_t) (cur_offset) : \
  120. att_align_nominal(cur_offset, attalign) \
  121. )
  122. /*
  123. * att_align_nominal aligns the given offset as needed for a datum of alignment
  124. * requirement attalign, ignoring any consideration of packed varlena datums.
  125. * There are three main use cases for using this macro directly:
  126. * * we know that the att in question is not varlena (attlen != -1);
  127. * in this case it is cheaper than the above macros and just as good.
  128. * * we need to estimate alignment padding cost abstractly, ie without
  129. * reference to a real tuple. We must assume the worst case that
  130. * all varlenas are aligned.
  131. * * within arrays, we unconditionally align varlenas (XXX this should be
  132. * revisited, probably).
  133. *
  134. * The attalign cases are tested in what is hopefully something like their
  135. * frequency of occurrence.
  136. */
  137. #define att_align_nominal(cur_offset, attalign) \
  138. ( \
  139. ((attalign) == 'i') ? INTALIGN(cur_offset) : \
  140. (((attalign) == 'c') ? (uintptr_t) (cur_offset) : \
  141. (((attalign) == 'd') ? DOUBLEALIGN(cur_offset) : \
  142. ( \
  143. AssertMacro((attalign) == 's'), \
  144. SHORTALIGN(cur_offset) \
  145. ))) \
  146. )
  147. /*
  148. * att_addlength_datum increments the given offset by the space needed for
  149. * the given Datum variable. attdatum is only accessed if we are dealing
  150. * with a variable-length attribute.
  151. */
  152. #define att_addlength_datum(cur_offset, attlen, attdatum) \
  153. att_addlength_pointer(cur_offset, attlen, DatumGetPointer(attdatum))
  154. /*
  155. * att_addlength_pointer performs the same calculation as att_addlength_datum,
  156. * but is used when walking a tuple --- attptr is the pointer to the field
  157. * within the tuple.
  158. *
  159. * Note: some callers pass a "char *" pointer for cur_offset. This is
  160. * actually perfectly OK, but probably should be cleaned up along with
  161. * the same practice for att_align_pointer.
  162. */
  163. #define att_addlength_pointer(cur_offset, attlen, attptr) \
  164. ( \
  165. ((attlen) > 0) ? \
  166. ( \
  167. (cur_offset) + (attlen) \
  168. ) \
  169. : (((attlen) == -1) ? \
  170. ( \
  171. (cur_offset) + VARSIZE_ANY(attptr) \
  172. ) \
  173. : \
  174. ( \
  175. AssertMacro((attlen) == -2), \
  176. (cur_offset) + (strlen((char *) (attptr)) + 1) \
  177. )) \
  178. )
  179. /*
  180. * store_att_byval is a partial inverse of fetch_att: store a given Datum
  181. * value into a tuple data area at the specified address. However, it only
  182. * handles the byval case, because in typical usage the caller needs to
  183. * distinguish by-val and by-ref cases anyway, and so a do-it-all macro
  184. * wouldn't be convenient.
  185. */
  186. #if SIZEOF_DATUM == 8
  187. #define store_att_byval(T,newdatum,attlen) \
  188. do { \
  189. switch (attlen) \
  190. { \
  191. case sizeof(char): \
  192. *(char *) (T) = DatumGetChar(newdatum); \
  193. break; \
  194. case sizeof(int16): \
  195. *(int16 *) (T) = DatumGetInt16(newdatum); \
  196. break; \
  197. case sizeof(int32): \
  198. *(int32 *) (T) = DatumGetInt32(newdatum); \
  199. break; \
  200. case sizeof(Datum): \
  201. *(Datum *) (T) = (newdatum); \
  202. break; \
  203. default: \
  204. elog(ERROR, "unsupported byval length: %d", \
  205. (int) (attlen)); \
  206. break; \
  207. } \
  208. } while (0)
  209. #else /* SIZEOF_DATUM != 8 */
  210. #define store_att_byval(T,newdatum,attlen) \
  211. do { \
  212. switch (attlen) \
  213. { \
  214. case sizeof(char): \
  215. *(char *) (T) = DatumGetChar(newdatum); \
  216. break; \
  217. case sizeof(int16): \
  218. *(int16 *) (T) = DatumGetInt16(newdatum); \
  219. break; \
  220. case sizeof(int32): \
  221. *(int32 *) (T) = DatumGetInt32(newdatum); \
  222. break; \
  223. default: \
  224. elog(ERROR, "unsupported byval length: %d", \
  225. (int) (attlen)); \
  226. break; \
  227. } \
  228. } while (0)
  229. #endif /* SIZEOF_DATUM == 8 */
  230. #endif
上海开阖软件有限公司 沪ICP备12045867号-1