72.1. Правила объявления системного каталога#
72.1. Правила объявления системного каталога
Ключевая часть заголовочного файла каталога - это определение структуры на языке C, описывающей структуру каждой строки каталога. Она начинается с макроса CATALOG
, который, по мнению компилятора C, является сокращением для typedef struct FormData_
. Каждое поле в структуре соответствует колонке каталога. Поля могут быть аннотированы с использованием макросов свойств BKI, описанных в файле catalogname
genbki.h
, например, для определения значения по умолчанию для поля или отметки его как допускающего значение NULL или не допускающего его. Строка CATALOG
также может быть аннотирована с использованием других макросов свойств BKI, описанных в файле genbki.h
, для определения других свойств каталога в целом, таких как является ли он общим отношением.
Код кеша системного каталога (и большая часть кода манипулирования каталогами в общем)
предполагает, что фиксированная часть всех кортежей системного каталога
фактически присутствует, потому что он отображает это объявление структуры C на них.
Таким образом, все переменные поля и поля с возможным значением NULL должны быть размещены в конце,
и к ним нельзя обращаться как к полям структуры.
Например, если вы попытаетесь установить pg_type
.typrelid
в значение NULL, это приведет к ошибке, когда какой-то код попытается обратиться к
typetup->typrelid
(или, что еще хуже,
typetup->typelem
, потому что это следует за
typrelid
). Это может привести к
случайным ошибкам или даже нарушениям сегментации.
Для частичной защиты от этого типа ошибок переменные переменной длины или с возможным значением NULL не должны быть напрямую видимыми для компилятора C. Это достигается обертыванием их в #ifdef CATALOG_VARLEN
... #endif
(где CATALOG_VARLEN
- это символ, который никогда не определен). Это предотвращает небрежный доступ к полям C-кода, которые могут отсутствовать или находиться на другом смещении.
В качестве независимой защиты от создания некорректных строк мы требуем, чтобы все столбцы, которые должны быть ненулевыми, были отмечены такими в pg_attribute
. Код загрузки автоматически помечает каталожные столбцы как NOT NULL
, если они имеют фиксированную ширину и не предшествуют ни одному столбцу с возможным значением NULL или переменной шириной.
Если эта правило недостаточно, вы можете принудительно указать правильную маркировку, используя аннотации BKI_FORCE_NOT_NULL
и BKI_FORCE_NULL
по мере необходимости.
Frontend code should not include any pg_xxx.h
catalog header file, as these files may contain C code that won't compile outside the backend. (Typically, that happens because these files also contain declarations for functions in src/backend/catalog/
files).
Instead, frontend code may include the corresponding generated pg_xxx_d.h
header, which will contain 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
around that section to instruct genbki.pl
to copy that section to the pg_xxx_d.h
header.
Некоторые из каталогов настолько фундаментальны, что их нельзя создать даже с помощью команды BKI create
, которая используется для большинства каталогов, потому что эта команда должна записывать информацию в эти каталоги, чтобы описать новый каталог. Эти каталоги называются bootstrap каталогами, и их определение требует дополнительной работы: вам нужно вручную подготовить соответствующие записи для них в предварительно загруженных содержимых pg_class
и pg_type
, и эти записи будут нуждаться в обновлении при последующих изменениях структуры каталога.
(Bootstrap каталоги также требуют предварительно загруженных записей в pg_attribute
, но, к счастью, сейчас этим занимается genbki.pl
).
Постарайтесь избегать создания новых каталогов в качестве bootstrap каталогов, если это возможно.