Postgresql数据库新增一张系统表

网友投稿 459 2022-12-02

Postgresql数据库新增一张系统表

在catalog 的makefile 中添加相应的系统表头文件

./src/backend/catalog/Makefile:42: pg_foreign_table.h pg_partition_key.h \

建表

– 以pg_partition_key为例,给该表添加代码pg_partition_key.h

在include的 catalog目录下添加这张表的定义

CATALOG宏定义为​​#define CATALOG(name,oid,oidmacro) typedef struct CppConcat(FormData_,name)​​​,定义在src/include/catalog/genbki.h中。所以这里的结构体为​​typedef struct FormData_pg_partition_key​​

#ifndef PG_PARTITION_KEY_H#define PG_PARTITION_KEY_H#include "catalog/genbki.h"#define PartitionKeyRelationId 3180CATALOG(pg_partition_key,3180) BKI_WITHOUT_OIDS{ Oid pkrelid; int16 pkattnum; } FormData_pg_partition_key;typedef FormData_pg_partition_key *Form_pg_partition_key;#define Natts_pg_partition_key    2#define Anum_pg_partition_key_pkrelid    1#define Anum_pg_partition_key_pkattnum 2#endif

在catalog 的indexing.h 头文件中添加系统表的唯一性索引

DECLARE_UNIQUE_INDEX(pg_partition_key_relid_index, 3181, on pg_partition_key using btree(pkrelid oid_ops));#define PartitionKeyRelidIndexId 3181

Syscache

– 以 pg_partion_key为例

首先要在syscache.h中添加 SysCacheIdentifier

要在syscache.c 的 cacheinfo[] 中添加这张表

cache的定义:

struct cachedesc{ Oid reloid; Oid indoid; int nkeys; int key[4]; int nbuckets; };

仿造它添加条目

{PartitionKeyRelationId, PartitionKeyRelidIndexId, 1, { Anum_pg_partition_key_pkrelid, 0, 0, 0 }, 128}

注意:

字段顺序要和index中顺序相对应,和表字段顺序没关系好像最多就支持4个字段。因为SearchSysCache等函数 最多就支搜4个字段如果有多个索引,取其中一个索引就可以, 不要求必须是unique索引

执行syscache 进行查找

void GetPartitionKeyInfo(Oid pkrelid, int16 *attnum){ Form_pg_partition_key form_pk; HeapTuple tuple; Assert(attnum); if (!OidIsValid(pkrelid)) return ; tuple = SearchSysCache1((int)PARTITIONKEYREL, ObjectIdGetDatum(pkrelid)); if (!HeapTupleIsValid(tuple)) ereport(ERROR,(errmsg("Can not find partition key of relation(%u).",pkrelid))); Assert(tuple != NULL); form_pk = (Form_pg_partition_key)GETSTRUCT(tuple); *attnum = form_pk->pkattnum; ReleaseSysCache(tuple);}

执行syscache进行多行查找

bool result = false; CatCList *catlist; int i; catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno)); for (i = 0; i < catlist->n_members; i++) { HeapTuple tuple = &catlist->members[i]->tuple; Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple); if (aform->amopmethod != BTREE_AM_OID) continue; if (aform->amopstrategy == BTLessStrategyNumber || aform->amopstrategy == BTGreaterStrategyNumber) { if (aform->amoplefttype == aform->amoprighttype) { *opfamily = aform->amopfamily; *opcintype = aform->amoplefttype; *strategy = aform->amopstrategy; result = true; break; } } }

注意: SearchSysCacheList1 函数查找的字段数要少于index的字段数。

打开系统表的方式

用heap_open的方式打开系统表,用这种方式可以比较方便的动态插入和删除

用heapopen方式打开系统表/用户表,还可以用heap_open的方式打开系统表,例如seclable.c中的部分:

= heap_open(SecLabelRelationId, RowExclusiveLock); scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true, SnapshotNow, 4, keys); oldtup = systable_getnext(scan); if (HeapTupleIsValid(oldtup)) { if (label == NULL) simple_heap_delete(pg_seclabel, &oldtup->t_self); else{ replaces[Anum_pg_seclabel_label - 1] = true; newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_seclabel), values, nulls, replaces); simple_heap_update(pg_seclabel, &oldtup->t_self, newtup); } } systable_endscan(scan); if (newtup == NULL && label != NULL){ newtup = heap_form_tuple(RelationGetDescr(pg_seclabel),values, nulls); simple_heap_insert(pg_seclabel, newtup); } if (newtup != NULL){ CatalogUpdateIndexes(pg_seclabel, newtup); heap_freetuple(newtup); } heap_close(pg_seclabel, RowExclusiveLock);

从heaptuple中获取datum 的方法(这两个方法不仅适用于syscache,而且适用于一般的heap表)

方法1

= heap_open(SecLabelRelationId, AccessShareLock); scan = systable_beginscan(pg_seclabel, SecLabelObjectIndexId, true, SnapshotNow, 4, keys); tuple = systable_getnext(scan); if (HeapTupleIsValid(tuple)) { datum = heap_getattr(tuple, Anum_pg_seclabel_label, RelationGetDescr(pg_seclabel), &isnull); if (!isnull) seclabel = TextDatumGetCString(datum); } systable_endscan(scan); heap_close(pg_seclabel, AccessShareLock);

方法2 对于text 和 bytea,从系统缓存中获取不宜采用Form_xxx->yyy这种方法,而适合采用SysCacheGetAttr 方法 例如获取fdw options的:

= SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tp, Anum_pg_foreign_data_wrapper_fdwoptions, &isnull);

方法3 还有一个方法也是类似

= fastgetattr(tuple, Anum_pg_class_reloptions, tupdesc, &isnull);

其中tupdesc 可以通过 RelationGetDescr(pg_seclabel) 获得 SysCacheGetAttr 调用了 heap_getattr heap_getattr 本质上也是调用了 fastgetattr 和 heap_getsysattr, heap_getattr 更通用,不光可以针对系统表, 也可以针对用户表

其他要注意的地方:

initdb的问题

问题描述: initdb -E UTF-8 -D ~/database6 --locale=en_US.UTF8 -U postgres -W 在initdb的时候,出现错误: (gdb) FATAL: type 17 not supported as catcache key catcache.c: 162 (发现是在执行这个命令的时候:/home/hl/uda_new/cplusplus/ci/postgres/bin/postgres" --single -F -O -c search_path=pg_catalog -c exit_on_error=true template1但这个命令又不能单独执行,不管他)

这个是因为BYTEAOID 没有指定hash函数和等值函数,解决的办法就是在这个函数中把BYTEAOID添加上(bytea和text本质上存储格式是相通的,所以这样改没有太大问题)

static void GetCCHashEqFuncs(Oid keytype, PGFunction *hashfunc, RegProcedure *eqfunc){... case TEXTOID: case BYTEAOID: *hashfunc = hashtext; *eqfunc = F_TEXTEQ;...}

SysCache 使用的问题

SysCacheGetAttr(DATASRCCFGREL, tuple, Anum_pg_data_src_cfg_datasrckind, &isNull); 使用syscache的地方。第一个参数是在 syscache.h中的enum SysCacheIdentifier 中的id,而不是OID

查找系统缓存的问题

ERROR: could not determine which collation to use for string comparison HINT: Use the COLLATE clause to set the collation explicitly. 这个是index和 syscache.c 中定义的字段对不上

建议新增系统表的时候,在查找字段上定义为NameData 而不要定义为Text, 否则查找很成问题

以Postgresql9.3.5为例

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Scala中Array和List的区别说明
下一篇:PostgreSQL数据库事务系统——ResourceOwner
相关文章

 发表评论

暂时没有评论,来抢沙发吧~