pg空值管理

📅 2026/6/30 5:32:57
pg空值管理
文章目录环境文档用途详细信息环境系统平台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 tupleint 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 indicatesnon-null.*/static inline bool att_isnull(int ATT, const bits8 *BITS){return !(BITS[ATT 3] (1 (ATT 0x07)));}att_isnull解释t_bits[…]的每一个元素是一个字节的数bits8uint8ATT 3: 元组属性编号从0开始编号8位一组正好对应一个t_bits[]当中的一个元素1(ATTOx7): 8位一组从0开始编号 1ATT(111)b计算的这这一组中的位置。3.TESTinfomask_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(buflen, | ); len strlen(buf); start buf len; } strcpy(start,macro_vector[i]); } i; } PG_RETURN_TEXT_P(cstring_to_text(buf)); }