瀚高数据库
目录
环境
文档用途
详细信息
环境
系统平台:Linux x86-64 Red Hat Enterprise Linux 7
版本:14,13,12
文档用途
从元组底层的角度看属性为空的判定
详细信息
1.元组头部结构及其主要字段解释说明
2.伪代码
HeapTupleHeader tup = tuple->t_data; // 某个表当中某个元组的元组头部指针
bits8 *bp = tup->t_bits; // ptr to null bitmap in one tuple
int tdesc_natts = ((Relation)rel)->rd_att->natts; // 从RelationData中的TupleDescData获取元组的属性数量
int natts = ((tup)->t_infomask2 & HEAP_NATTS_MASK) // 在该元组的元组头部中,根据infomask2计算该元组的属性数目 HEAP_NATTS_MASK = 0x7ff, 11位
natts = Min(natts, tdesc_natts); // 新元组数目可能比预期的要多,为了避免越界访问,选小
bool hasnulls = tup->infomask & HEAP_HASNULL;
for (attnum = 0; attnum < natts; attnum++)
{
Form_pg_attribute thisatt = &((Relation)rel)->rd_att->attrs[i]; //对每个属性获取pg_attribute的描述
if (hasnulls && att_isnull(attnum, bp))// 在该元组的t_bits当中判断该属性对应的属性值是否为空
{
......
}
}
att_isnull实现:
/*
* Check a tuple's null bitmap to determine whether the attribute is null.
* Note that a 0 in the null bitmap indicates a null, while 1 indicates
* non-null.
*/
static inline bool att_isnull(int ATT, const bits8 *BITS)
{
return !(BITS[ATT >> 3] & (1 << (ATT & 0x07)));
}
att_isnull解释:
t_bits[…]的每一个元素是一个字节的数,bits8==uint8
ATT >> 3: 元组属性编号从0开始编号,8位一组,正好对应一个t_bits[]当中的一个元素
1<<(ATT&Ox7): 8位一组,从0开始编号, 1<<ATT&(111)b计算的这这一组中的位置。
3.TEST
infomask_show函数实现:
#include "postgres.h"
#include "fmgr.h"
#include "utils/varlena.h"
#include "utils/builtins.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(infomask_show);
//#define HEAP_HASNULL 0x0001 /* has null attribute(s) */
//#define HEAP_HASVARWIDTH 0x0002 /* has variable-width attribute(s) */
//#define HEAP_HASEXTERNAL 0x0004 /* has external stored attribute(s) */
//#define HEAP_HASOID_OLD 0x0008 /* has an object-id field */
//#define HEAP_XMAX_KEYSHR_LOCK 0x0010 /* xmax is a key-shared locker */
//#define HEAP_COMBOCID 0x0020 /* t_cid is a combo CID */
//#define HEAP_XMAX_EXCL_LOCK 0x0040 /* xmax is exclusive locker */
//#define HEAP_XMAX_LOCK_ONLY 0x0080 /* xmax, if valid, is only a locker */
/* xmax is a shared locker */
//#define HEAP_XMAX_SHR_LOCK (HEAP_XMAX_EXCL_LOCK | HEAP_XMAX_KEYSHR_LOCK)
//#define HEAP_LOCK_MASK (HEAP_XMAX_SHR_LOCK | HEAP_XMAX_EXCL_LOCK | \
HEAP_XMAX_KEYSHR_LOCK)
//#define HEAP_XMIN_COMMITTED 0x0100 /* t_xmin committed */
//#define HEAP_XMIN_INVALID 0x0200 /* t_xmin invalid/aborted */
//#define HEAP_XMIN_FROZEN (HEAP_XMIN_COMMITTED|HEAP_XMIN_INVALID)
//#define HEAP_XMAX_COMMITTED 0x0400 /* t_xmax committed */
//#define HEAP_XMAX_INVALID 0x0800 /* t_xmax invalid/aborted */
//#define HEAP_XMAX_IS_MULTI 0x1000 /* t_xmax is a MultiXactId */
//#define HEAP_UPDATED 0x2000 /* this is UPDATEd version of row */
//#define HEAP_MOVED_OFF 0x4000 /* moved to another place by pre-9.0 * VACUUM FULL; kept for binary * * upgrade support */
//#define HEAP_MOVED_IN 0x8000 /* moved from another place by pre-9.0* VACUUM FULL; kept for binary* * upgrade support */
char buf[1024];
char *macro_vector[] = {"HEAP_HASNULL","HEAP_HASVARWIDTH","HEAP_HASEXTERNAL","HEAP_HASOID_OLD","HEAP_XMAX_KEYSHR_LOCK","HEAP_COMBOCID",
"HEAP_XMAX_EXCL_LOCK","HEAP_XMAX_LOCK_ONLY","HEAP_XMIN_COMMITTED","HEAP_XMIN_INVALID","HEAP_XMIN_FROZEN","HEAP_XMAX_COMMITTED","HEAP_XMAX_INVALID","HEAP_XMAX_IS_MULTI",
"HEAP_UPDATED","HEAP_MOVED_OFF","HEAP_MOVED_IN"};
Datum infomask_show(PG_FUNCTION_ARGS)
{
unsigned short infomask_bits = PG_GETARG_UINT16(0);
//PG_RETURN_UINT16(infomask_bits);
int i = 0;
char *start = buf;
while (i < 16)
{
if (infomask_bits & (1 << i))
{
if( i > 0 )
{
int len = strlen(buf);
strcpy(buf+len, " | ");
len = strlen(buf);
start = buf + len;
}
strcpy(start,macro_vector[i]);
}
i++;
}
PG_RETURN_TEXT_P(cstring_to_text(buf));
}