前言:
在pg存储中有一种格式就是扩展格式,或者成为线外存储,本章解释的宏就是其中的一个。
翻译
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \
do { \
varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \
Assert(VARATT_IS_EXTERNAL(attre)); \
Assert(VARSIZE_EXTERNAL(attre) == sizeof(toast_pointer) + VARHDRSZ_EXTERNAL); \
memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \
} while ()
typedef unsigned char uint8; /* == 8 bits */
typedef struct
{
uint8 va_header; /* Always 0x80 or 0x01 */
uint8 va_tag; /* Type of datum */
char va_data[FLEXIBLE_ARRAY_MEMBER]; /* Type-specific data */
} varattrib_1b_e;
//2,3部分宏
//判断PTR的第一个字节是否为'0x01'
#define VARATT_IS_EXTERNAL(PTR) VARATT_IS_1B_E(PTR)
#define VARATT_IS_1B_E(PTR) ((((varattrib_1b *) (PTR))->va_header) == 0x01)
/*求结构体varattrib_1b_e*的va_data偏移,其实就是前两个元素,header和tag字节大小,此处为2*/
#define VARHDRSZ_EXTERNAL offsetof(varattrib_1b_e, va_data)
/*求头部大小加根据tag类型获取大小*/
#define VARSIZE_EXTERNAL(PTR) (VARHDRSZ_EXTERNAL + VARTAG_SIZE(VARTAG_EXTERNAL(PTR)))
/*获取PTR的tag的值/类型*/
#define VARTAG_EXTERNAL(PTR) VARTAG_1B_E(PTR)
#define VARTAG_1B_E(PTR) (((varattrib_1b_e *) (PTR))->va_tag)
/*根据tag的类型进行求不同结构体大小*/
#define VARTAG_SIZE(tag) \
((tag) == VARTAG_INDIRECT ? sizeof(varatt_indirect) : \
VARTAG_IS_EXPANDED(tag) ? sizeof(varatt_expanded) : \
(tag) == VARTAG_ONDISK ? sizeof(varatt_external) : \
TrapMacro(true, "unrecognized TOAST vartag"))
第一步,将传入参数强转为
attr
类型,此时attr的前两个字节分别对应结构体的
varattrib_1b_e *
和
va_header
va_tag
。
第二步,判断
是否为
va_header
,意思是判断
0x01
attre
是否是扩展类型
第三步,求
中
attre
对应的结构体 大小是否与
tag
toast_pointer
相同
二,三步其实是assert,判断,阅读代码时,可以忽略.
第四步,将
拷贝到
attre
中。
toast_pointer
原版
/*
* Macro to fetch the possibly-unaligned contents of an EXTERNAL datum
* into a local "struct varatt_external" toast pointer. This should be
* just a memcpy, but some versions of gcc seem to produce broken code
* that assumes the datum contents are aligned. Introducing an explicit
* intermediate "varattrib_1b_e *" variable seems to fix it.
*/
#define VARATT_EXTERNAL_GET_POINTER(toast_pointer, attr) \
do { \
varattrib_1b_e *attre = (varattrib_1b_e *) (attr); \
Assert(VARATT_IS_EXTERNAL(attre)); \
Assert(VARSIZE_EXTERNAL(attre) == sizeof(toast_pointer) + VARHDRSZ_EXTERNAL); \
memcpy(&(toast_pointer), VARDATA_EXTERNAL(attre), sizeof(toast_pointer)); \
} while ()**
综上所述:该宏其实就是一个拷贝过程。最终将
attr
的数据,(从第三个字节开始为数据)拷贝到
toast_pointer
中。
中间过程简单解释:判断tag的类型,并根据tag类型求该类型对应的结构体大小,并将此结构体大小与
toast_pointer
(结构体)进行判断以确定是否可以拷贝。