Postgresql 中文操作指南

75.1. System Catalog Declaration Rules #

目录头文件的重要部分是 C 结构定义,它描述了目录的每一行的布局。这以 CATALOG 宏开始,它与 C 编译器相关,仅是 typedef struct FormData_catalogname. Each field in the struct gives rise to a catalog column. Fields can be annotated using the BKI property macros described in genbki.h 的简写形式,例如定义字段的默认值或将其标记为可为空或不可为空。 CATALOG 行还可以使用 genbki.h 中所述的其他一些 BKI 属性宏进行注释,以定义整个目录的其他属性,例如它是否为共享关系。

系统目录缓存代码(以及通常的大多数目录整理代码)假设所有系统目录元组的固定长度部分实际上都存在,因为它将此 C 结构声明映射到它们。因此,所有可变长度字段和可空字段都必须放在末尾,不能作为结构字段访问它们。例如,如果您尝试将 pg_type.typrelid 设置为 NULL,当某些代码尝试引用 typetup→typrelid(或更糟,typetup→typelem,因为该代码位于 typrelid 之后)时,它将会失败。这会导致随机错误甚至段错误。

为了部分防止这种类型的错误,不应使可变长度或可空字段直接对 C 编译器可见。这是通过将它们包装在 #ifdef CATALOG_VARLEN …​ #endif(其中 CATALOG_VARLEN 是一个从未被定义的符号)中完成的。这可以防止 C 代码不小心尝试访问可能不存在或可能处于其他偏移量的字段。作为防止创建不正确行的独立保护,我们要求将所有应该为不可空的列在 pg_attribute 中标记为不可空。如果引导代码为固定宽度并且前面没有可空或可变宽度列,引导代码将自动将目录列标记为 NOT NULL。如果此规则不充分,您可以根据需要使用 BKI_FORCE_NOT_NULLBKI_FORCE_NULL 注释强制正确标记。

前端代码不应包含任何 pg_xxx.h 目录头文件,因为这些文件可能包含在后端之外无法编译的 C 代码。(通常,这是因为这些文件还包含 src/backend/catalog/ 文件中的函数声明)。相反,前端代码可以包含相应的生成 pg_xxx_d.h 头,其中将包含 OID #define_s and any other data that might be of use on the client side. If you want macros or other code in a catalog header to be visible to frontend code, write _#ifdef EXPOSE_TO_CLIENT_CODE …​ #endif 围绕该部分以指示 genbki.pl 将该部分复制到 pg_xxx_d.h 头。

一些目录非常基础,甚至无法通过用于大多数目录的 BKI create 命令创建,因为该命令需要将信息写入这些目录中以描述新目录。这些称为 bootstrap 目录,定义一个需要很多额外的工作:您必须在 pg_classpg_type 的预加载内容中为它们手动准备适当的条目,这些条目需要更新以进行后续更改对目录结构的更改。(引导目录还需要在 pg_attribute 中预加载条目,但幸运的是,genbki.pl 现在可以处理这项任务。)如果可能,请避免使新目录成为引导目录。