目錄標頭檔案中的關鍵部分是描述目錄每一行佈局的 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
標頭檔案中。
一些目錄非常基礎,以至於它們甚至無法透過用於大多數目錄的 create
命令建立,因為該命令需要向這些目錄寫入資訊來描述新目錄。這些被稱為 引導 目錄,定義它們需要大量額外工作:您必須手動準備預載入內容中包含的 pg_class
和 pg_type
的相應條目,並且這些條目需要針對目錄結構的後續更改進行更新。(引導目錄還需要 pg_attribute
的預載入條目,但幸運的是 genbki.pl
現在處理了這項工作。)如果可能,請儘量避免建立新的引導目錄。BKI create
命令,因為該命令需要向這些目錄寫入資訊來描述新的目錄。這些被稱為 引導 目錄,定義它們需要大量額外工作:您必須手動準備預載入內容中包含的 pg_class
和 pg_type
的相應條目,並且這些條目需要針對目錄結構的後續更改進行更新。(引導目錄還需要 pg_attribute
的預載入條目,但幸運的是 genbki.pl
現在處理了這項工作。)如果可能,請儘量避免建立新的引導目錄。
如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的內容,請使用 此表單 報告文件問題。