目錄標頭檔的關鍵部分是一個 C 結構定義,描述了目錄中每一列的佈局。 這始於一個 CATALOG
巨集,就 C 編譯器而言,它只是 typedef struct FormData_
的簡寫。結構中的每個欄位都會產生一個目錄欄位。欄位可以使用 catalogname
genbki.h
中描述的 BKI 屬性巨集進行註解,例如為欄位定義預設值,或將其標記為可為空或不可為空。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_NULL
和 BKI_FORCE_NULL
註解來強制執行正確的標記。
前端程式碼不應包含任何 pg_xxx.h
目錄標頭檔,因為這些檔案可能包含在後端之外無法編譯的 C 程式碼。(通常,發生這種情況是因為這些檔案還包含 src/backend/catalog/
檔案中函式的宣告。)相反,前端程式碼可以包含相應產生的 pg_xxx_d.h
標頭,它將包含 OID #define
s 和任何其他可能在客戶端有用的資料。如果您希望目錄標頭中的巨集或其他程式碼對前端程式碼可見,請在該區段周圍編寫 #ifdef EXPOSE_TO_CLIENT_CODE
... #endif
以指示 genbki.pl
將該區段複製到 pg_xxx_d.h
標頭。
少數目錄非常基本,甚至無法透過BKI 用於大多數目錄的 create
命令建立,因為該命令需要將資訊寫入這些目錄,以描述新目錄。 這些被稱為引導目錄,定義一個需要做很多額外的工作:您必須手動準備 pg_class
和 pg_type
的預載內容中適合它們的條目,並且這些條目需要更新以應對目錄結構的後續變更。(引導目錄也需要在 pg_attribute
中預載條目,但幸運的是,現在 genbki.pl
可以處理這項繁瑣的工作。)如果可以的話,避免將新的目錄設為引導目錄。
如果您在文件中發現任何不正確、與您使用特定功能時的體驗不符或需要進一步澄清的地方,請使用此表單回報文件問題。