バージョンごとのドキュメント一覧

67.1. システムカタログの宣言ルール #

<title>System Catalog Declaration Rules</title>

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 a <literal>CATALOG</literal> macro, which so far as the C compiler is concerned is just shorthand for <literal>typedef struct FormData_<replaceable>catalogname</replaceable></literal>. Each field in the struct gives rise to a catalog column. Fields can be annotated using the BKI property macros described in <filename>genbki.h</filename>, for example to define a default value for a field or mark it as nullable or not nullable. The <literal>CATALOG</literal> line can also be annotated, with some other BKI property macros described in <filename>genbki.h</filename>, to define other properties of the catalog as a whole, such as whether it is a shared relation. カタログヘッダファイルの肝心な部分は、カタログにおける行の配置を記述するC構造体定義です。 これはCATALOGマクロで始まりますが、Cコンパイラの観点からすると、単にtypedef struct FormData_catalognameの短縮形です。 構造体の各々のフィールドは、カタログの列を生成します。 フィールドにはgenbki.hに記述されたBKIプロパティマクロを使って注釈を付けることができます。 たとえば、フィールドのデフォルト値を定義したり、NULLが許されるかどうかのフラグを付けることができます。 CATALOG行にも注釈が付けられます。 genbki.hに記述されたBKIプロパティマクロを使って、共有リレーションであるかどうかといった、そのカタログ全体のプロパティを定義することができます。

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 set <structname>pg_type</structname>.<structfield>typrelid</structfield> to be NULL, it would fail when some piece of code tried to reference <literal>typetup-&gt;typrelid</literal> (or worse, <literal>typetup-&gt;typelem</literal>, because that follows <structfield>typrelid</structfield>). This would result in random errors or even segmentation violations. システムカタログキャッシュのコード(そして一般的にたいていのカタログを触るコード)は、すべてのシステムカタログタプルに固定長部分が実際に存在するとみなします。 システムカタログキャッシュのコードは、C構造体定義をその固定部分にマップするからです。 したがって、すべての可変長フィールドと、NULLを許容するフィールドは、最後尾に置かれなければならず、また、構造体のフィールドとしてはアクセスできません。 たとえば、pg_type.typrelidをNULLにしようとすると、他のコード部分がtypetup->typrelidを参照しようとして失敗します。(あるいはもっと悪いことにtypetup->typelemを参照中に失敗します。なぜなら、そのフィールドはtyprelidの後に来るからです。) これはランダムなエラーとなるか、あるいはセグメンテーション違反にすらなってしまいます。

As a partial guard against this type of error, variable-length or nullable fields should not be made directly visible to the C compiler. This is accomplished by wrapping them in <literal>#ifdef CATALOG_VARLEN</literal> ... <literal>#endif</literal> (where <literal>CATALOG_VARLEN</literal> is a symbol that is never defined). This prevents C code from carelessly trying to access fields that might not be there or might be at some other offset. As an independent guard against creating incorrect rows, we require all columns that should be non-nullable to be marked so in <structname>pg_attribute</structname>. The bootstrap code will automatically mark catalog columns as <literal>NOT NULL</literal> if they are fixed-width and are not preceded by any nullable or variable-width column. Where this rule is inadequate, you can force correct marking by using <literal>BKI_FORCE_NOT_NULL</literal> and <literal>BKI_FORCE_NULL</literal> annotations as needed. この種のエラーから部分的に身を守るためには、可変長あるいはNULLを許容するフィールドはCコンパイラから直接見えないようにすべきです。 これは#ifdef CATALOG_VARLEN ... #endifの中に入れることで達成できます。(ここで、CATALOG_VARLENは、決して定義されないシンボルです。) これにより、Cコードが不注意で存在しないフィールドにアクセスしようとしたり、オフセットが違うフィールドにアクセスしようとするのを防ぐことができます。 不正な行を作るのを防ぐ独立したガードとして、NULLを許容しないすべての列をpg_attributeでそのように宣言することを要求します。 ブートストラップコードは、固定長で、かつ、NULLを許容したり可変幅である列の次ではないカタログ列に対して自動的にNOT NULLのマークを付けます。 このルールが不適切なら、BKI_FORCE_NOT_NULLBKI_FORCE_NULLを必要に応じて使ってマーキングを修正できます。

Frontend code should not include any <filename>pg_xxx.h</filename> 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 <filename>src/backend/catalog/</filename> files.) Instead, frontend code may include the corresponding generated <filename>pg_xxx_d.h</filename> header, which will contain OID <literal>#define</literal>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 <literal>#ifdef EXPOSE_TO_CLIENT_CODE</literal> ... <literal>#endif</literal> around that section to instruct <filename>genbki.pl</filename> to copy that section to the <filename>pg_xxx_d.h</filename> header. フロントエンドのコードはすべてのpg_xxx.hカタログヘッダファイルをincludeすべきではありません。 バックエンド以外ではコンパイルできないCコードを含んでいるかもしれないからです。 (典型的には、src/backend/catalog/ファイル中に関数宣言を含んでいることによって起こります。) その代わりに、フロントエンドは生成されたpg_xxx_d.hヘッダをincludeできます。 このファイルは、OIDの#defineと、クライアント側で必要になるデータを含んでいます。 カタログヘッダ中のマクロやその他のコードをフロントエンドから見えるようにしたい場合は、#ifdef EXPOSE_TO_CLIENT_CODE ... #endifで該当セクションを囲むことにより、genbki.plがそのセクションをpg_xxx_d.hにコピーするように指示してください。

A few of the catalogs are so fundamental that they can't even be created by the <acronym>BKI</acronym> <literal>create</literal> command that's used for most catalogs, because that command needs to write information into these catalogs to describe the new catalog. These are called <firstterm>bootstrap</firstterm> catalogs, and defining one takes a lot of extra work: you have to manually prepare appropriate entries for them in the pre-loaded contents of <structname>pg_class</structname> and <structname>pg_type</structname>, and those entries will need to be updated for subsequent changes to the catalog's structure. (Bootstrap catalogs also need pre-loaded entries in <structname>pg_attribute</structname>, but fortunately <filename>genbki.pl</filename> handles that chore nowadays.) Avoid making new catalogs be bootstrap catalogs if at all possible. 少数のカタログは非常に基本的なものなので、ほとんどのカタログで使用されるBKI createコマンドですら作成できません。そのコマンドが、新しいカタログの記述をこれらのカタログに書き込む必要があるからです。 これらはブートストラップカタログと呼ばれ、定義するためには大量の追加の作業が必要です。 pg_classpg_typeのあらかじめロード済みの内容上に手動で適切なエントリを用意し、後のカタログ構造への変更に合わせてそれらのエントリを更新する必要があります。 (また、ブートストラップカタログはpg_attribute中のロード済みのエントリを必要としますが、幸いにも最近はgenbki.plが適切に処理してくれます。) 可能ならば、新しいカタログをブートストラップカタログとして作るのは避けてください。