VARATT_EXTERNAL_GET_POINTER

版权声明:转载可以,请发红包 https://blog.csdn.net/akakakak250/article/details/65631759

前言:
在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 (0)
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强转为varattrib_1b_e *类型,此时attr的前两个字节分别对应结构体的va_headerva_tag
第二步,判断va_header是否为0x01,意思是判断attre是否是扩展类型
第三步,求attretag对应的结构体 大小是否与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 (0)**

综上所述:该宏其实就是一个拷贝过程。最终将attr 的数据,(从第三个字节开始为数据)拷贝到toast_pointer中。
中间过程简单解释:判断tag的类型,并根据tag类型求该类型对应的结构体大小,并将此结构体大小与toast_pointer(结构体)进行判断以确定是否可以拷贝。

猜你喜欢

转载自blog.csdn.net/akakakak250/article/details/65631759
今日推荐