# 71.1. System Catalog Declaration Rules

The key part of a catalog header file is a C structure definition describing the layout of each row of the catalog. This begins with aCATALOGmacro, which so far as the C compiler is concerned is just shorthand fortypedef struct FormData_*catalogname*. Each field in the struct gives rise to a catalog column. Fields can be annotated using the BKI property macros described ingenbki.h, for example to define a default value for a field or mark it as nullable or not nullable. TheCATALOGline can also be annotated, with some other BKI property macros described ingenbki.h, to define other properties of the catalog as a whole, such as whether it is a shared relation.

The system catalog cache code (and most catalog-munging code in general) assumes that the fixed-length portions of all system catalog tuples are in fact present, because it maps this C struct declaration onto them. Thus, all variable-length fields and nullable fields must be placed at the end, and they cannot be accessed as struct fields. For example, if you tried to setpg_type.typrelidto be NULL, it would fail when some piece of code tried to referencetypetup->typrelid(or worse,typetup->typelem, because that followstyprelid)。这将导致随机错误甚至分段违规。

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

前端代码不应包含任何pg_xxx.h目录头文件,因为这些文件可能包含不会在后端之外编译的 C 代码。(通常,这是因为这些文件还包含函数的声明src/后端/目录/文件。)相反,前端代码可能包含相应的生成pg_xxx_d.h标头,将包含 OID#定义s 和任何其他可能在客户端使用的数据。如果您希望目录标题中的宏或其他代码对前端代码可见,请编写#ifdef EXPOSE_TO_CLIENT_CODE...#万一围绕该部分进行指导genbki.pl将该部分复制到pg_xxx_d.h标题。

一些目录是如此基础,以至于它们甚至无法由 BKI 创建创造用于大多数目录的命令,因为该命令需要将信息写入这些目录以描述新目录。这些被称为引导程序目录,并且定义一个需要很多额外的工作:您必须在预加载的内容中手动为它们准备适当的条目pg_classpg_type,并且这些条目将需要更新以用于目录结构的后续更改。(引导目录也需要在pg_attribute, 但幸运的是genbki.pl现在可以处理这些琐事。)尽可能避免使新目录成为引导目录。