C言語関数ユーザ定義の関数はC(もしくはC++のようなCと互換性のある言語)で作成することができます。そのような関数は動的ロード可能オブジェクト(共有ライブラリとも呼ばれます)としてコンパイルされ、必要に応じてサーバにロードされます。動的ロード機能が、"C言語"関数を"内部"関数と区別するものです。コーディング方法は基本的に両方とも同じです。(したがって、標準内部関数ライブラリはユーザ定義のC関数のコーディング例の豊富な情報源となります。)現在、2つの異なる呼び出し規約がC関数で使用されています。1"呼び出し規約は、以下に示すように、その関数用に呼び出しマクロPG_FUNCTION_INFO_V1()を書くことで示されます。0")の関数であることを示します。FUNCTIONで指定する言語名はCです。旧形式の関数は移植性の問題と機能の不足のために勧められません。これは現在、互換性の理由のために存在しています。動的ロード特定のロード可能オブジェクト内のユーザ定義の関数がセッションで最初に呼び出されると、動的ローダは、その関数を呼び出すことができるように、オブジェクトファイルをメモリ内に読み込みます。FUNCTIONはその関数について、ロード可能オブジェクトファイルの名前とオブジェクトファイル中の呼び出される特定の関数のC名称(リンクシンボル)という2つの情報を指定しなければなりません。C名称が明示的に指定されなかった場合、SQLにおける関数名と同じものと仮定されます。FUNCTIONコマンドで与えられた名前に基づいて、共有オブジェクトファイルの場所を見つける際に以下のアルゴリズムが使用されます。名前が絶対パスの場合、指定されたファイルが読み込まれます。名前が$libdirという文字列から始まる場合、その部分はPostgreSQLパッケージのライブラリディレクトリで置き換えられます。このディレクトリはビルド時に決定されます。名前にディレクトリ部分がない場合、そのファイルはdynamic_library_path設定変数で指定されたパス内から検索されます。上記以外の場合(ファイルがパス内に存在しない場合や相対ディレクトリ部分を持つ場合)、動的ローダは指定された名前をそのまま使用し、ほとんどの場合は失敗します。(これは現在の作業ディレクトリに依存するため信頼できません。)ここまでの流れがうまくいかなかった場合、プラットフォーム独自の共有ライブラリファイル拡張子(多くの場合.so)が指定された名前に追加され、再度この流れを試みます。同様に失敗した場合は、読み込みは失敗します。共有ライブラリを$libdirから相対的に、もしくは動的ライブラリパスの通った所に配置することを推奨します。異なる場所に新しいインストレーションを配置する場合にバージョンアップを簡単にします。--pkglibdirコマンドを使用することでわかります。PostgreSQLサーバの実効ユーザIDはロード予定のファイルのパスまで到達できなければなりません。ある失敗として、postgresユーザに対して読み込み、実行、または両方の権限がそのファイルとその上位ディレクトリに与えられていないことがあります。FUNCTIONコマンドに与えたファイル名はそのままシステムカタログに保存されます。そのファイルを再度読み込む必要がある場合、同じ処理が適用されます。PostgreSQLはC関数を自動的にコンパイルしません。FUNCTIONコマンドで参照する前に、そのオブジェクトファイルはコンパイルされていなければなりません。さらなる情報については項35.9.6を参照してください。確実に、動的にロードされるモジュールが互換性がないサーバにロードされないように、PostgreSQLは、そのファイルに適切な内容を持つ"魔法のブロック"が含まれているかどうか検査します。これによりサーバは、メジャーバージョンが異なるPostgreSQL用にコンパイルされたモジュールなど、明確に互換性がないことを検知することができます。8.2から要求されています。魔法のブロックを含めるためには、以下をモジュールのソースファイルに一度(一度だけ)、fmgr.hヘッダファイルをincludeさせた後で、記述してください。PG_MODULE_MAGICPG_MODULE_MAGIC;#endifそのコードをリリース8.2より前のPostgreSQL用にコンパイルする必要がなければ、#ifdefテストを省略することができます。最初に使用された後も、動的にロードされたオブジェクトファイルはメモリ内に保持されます。同一セッションにおいてそのファイル内の関数をその後に呼び出した場合、シンボルテーブルの検索に要する小さなオーバーヘッドしかかかりません。再コンパイルした後など、そのオブジェクトファイルを強制的に再度読み込ませる必要がある場合は、新しいセッションを開始してください。省略することもできますが、動的にロードされるファイルに初期化処理関数と最終処理関数を含めることができます。_PG_initという関数がファイルに存在すると、この関数はファイルがロードされた直後に呼び出されます。この関数は引数を取らずvoid型を返さなければなりません。_PG_finiという関数がファイルに存在すると、この関数はファイルがアンロードされる直前に呼び出されます。この関数も同様に引数を取らずvoid型を返さなければなりません。_PG_finiがファイルのアンロード時にのみ呼び出されるものであり、処理の終了時に呼び出されるものではないことに注意してください。(現在、アンロードは無効となっていますので、決して発生しません。将来変更される可能性があります。C言語関数における基本型C言語関数の作成方法を理解するためには、PostgreSQLが基本データ型を内部でどのように表現し、どのようにそれらを関数とやり取りしているかを理解する必要があります。内部的にPostgreSQLは基本型を"メモリの小さな塊"とみなします。ある型を定義するユーザ定義関数は、言い換えると、PostgreSQLがそれを操作できる方法を定義します。PostgreSQLはデータの格納、ディスクからの取り出しのみを行い、データの入力や処理、出力にはユーザ定義関数を使用します。基本型は下記の3つのいずれかの内部書式を使用しています。固定長の値渡し固定長の参照渡し可変長の参照渡し値渡しは、1、2、4バイト長の型のみで使用することができます(使用するマシンのsizeof(Datum)が8の場合は8バイトも使用できます)。データ型を定義する際、その型がすべてのアーキテクチャにおいて同一の大きさ(バイト数)となるように定義するように注意してください。long型はマシンによっては4バイトであったり、8バイトであったりして危険ですが、int型はほとんどのUnixマシンでは4バイトです。Unixマシンにおけるint4の理論的な実装は以下のようになります。int4;(実際のPostgreSQLのCコードではこの型をint32と呼びます。ビットであることはCにおける規約だからです。したがってint8というCの型のサイズは1バイトであることに注意してください。int8というSQLの型はCではint64と呼ばれます。表35-1も参照してください。)一方、任意の大きさの固定長の型は参照として引き渡すことができます。例として以下にPostgreSQLの型の実装サンプルを示します。Point;それらの型のポインタのみがPostgreSQL関数の入出力時に使用できます。それらの型の値を返すためには、palloc()を使用して正しい大きさのメモリ領域を割り当て、そのメモリ領域に値を入力し、それのポインタを返します。(また、入力引数の1つと同じ型かつ同じ値を返したいのであれば、pallocを行う手間を省くことができます。この場合は入力値へのポインタを単に返してください。)最後に、すべての可変長型は参照として引き渡す必要があります。すべての可変長型は正確に4バイトの不透明なlengthフィールドから始まる必要があります。このフィールドはSET_VARSIZEで設定されます。このフィールドを設定してはいけません。その型に格納されるすべてのデータはlengthフィールドのすぐ後のメモリ領域に置かれる必要があります。lengthフィールドにはその構造体の総長が格納されます。lengthフィールドそのものもその大きさに含まれます。この他の重要な点は、データ型の値の中で初期化されていないビットを残さないことです。構造体内に存在する可能性がある整列用のパディングバイトを注意してすべてゼロクリアしてください。しないと、独自データ型の論理的に等価な定数がプランナにより一致しないものと判断され、(不正確ではありませんが)非効率的な計画をもたらすかもしれません。参照渡しの入力値の内容を決して変更しないでください。指定したポインタがディスクバッファを直接指し示している可能性がよくありますので、変更すると、ディスク上のデータを破壊してしまうかもしれません。この規則の唯一の例外について項35.10で説明します。text型を定義するには、下記のように行えます。text;ここで宣言されたdataフィールドは、明らかにすべての取り得る文字列を保持できる長さではありません。C言語では可変長の構造体を定義することは不可能ですので、Cコンパイラは配列の添字の範囲検査を行わないという事実に依存します。必要な領域量を割り当て、あたかも正しい長さで宣言されたかのように、配列としてアクセスするだけです。(この手法はよく使用されます。C言語に関する多くの書籍で説明されています。)可変長型を操作する時、正確な大きさのメモリを割り当て、lengthフィールドを正確に設定することに注意する必要があります。40バイトをtext構造体に保持させたい場合、下記のようなコードを使用します。40);...VARHDRSZはsizeof(int32)と同一ですが、可変長型のオーバーヘッド分の大きさを参照する時には、VARHDRSZマクロを使用する方が好ましい形式とみなされています。長さフィールドを単なる代入ではなくSET_VARSIZEマクロを使用して設定しなければなりません。表35-1は、PostgreSQLの組み込み型を使用するC言語関数を作成する時の、Cの型とSQL型との対応を規定したものです。"定義場所"列では、型定義を取り出すためにインクルードしなければならないヘッダファイルを示しています。(実際の定義は一覧中のファイルからインクルードされた、別のファイルであるかもしれません。ユーザは定義されたインタフェースを厳守することを推奨されています。postgres.hには必ず必要になる多くのものが宣言されていますので、ソースファイルの中で必ず初めにこのファイルをインクルードしなければならないことに注意してください。postgres.hここまでで基本型に関してあり得る構造体のすべてを記述しましたので、実際の関数の例をいくつか示すことができます。呼び出し規約まず最初に、現在は非推奨ですが理解しやすいので、"古いスタイル"の呼び出し規約を説明します。Version-0メソッドでは、C関数の引数と結果は、通常のCのプログラムの記述の方法と同じような形式で行いますが、上記の説明のように、各SQLのデータ型に対するC言語での表現を注意して使用してください。以下にいくつか例を示します。VARSIZEは構造体の総長をバイト数で表したものです。VARDATAは構造体のデータ領域へのポインタです。new_text;}上のコードがfuncs.cというファイルに用意され、共有オブジェクトとしてコンパイル済みであるとすると、以下のようなコマンドでPostgreSQLの関数を定義することができます。STRICT;ここで、DIRECTORYは共有ライブラリファイルのディレクトリ(例えば、本節で使用する例のコードが含まれるPostgreSQLチュートリアルディレクトリ)を表します。(AS句中では単に'funcs'を使用し、後でDIRECTORYを検索パスに追加する方がより良い方法です。どの場合でも、一般的に.soや.slが使用される、共有ライブラリ用のシステム独特の拡張子を省略することができます。)ここで、関数を"厳密(strict)"と指定していることに注目してください。これは、もし入力された値がNULLであった場合に、システムが自動的に返り値もNULLであるとみなすことを意味します。これを行うことによって、関数のコードで入力値がNULLであるかどうかの検査を行う必要がなくなります。これがなければ、参照渡し引数それぞれに対してヌルポインタについての検査を行うなど、NULL値の明示的な検査を行う必要性が出てきます。(値渡し引数に関しては、検査を行う方法は存在しません。)この呼び出し規約は単純ですが、この方法は移植性の面であまり優れていません。この方法でint型より小さいデータ型を渡す部分で問題を抱えているアーキテクチャも存在します。関数の結果としてNULLを返す簡単な方法はありません。その上、NULL引数をうまく処理する方法としては、関数を厳密なものにする以外方法はありません。次に説明するVersion-1規約ではこれらの問題が解決されています。呼び出し規約Version-1呼び出し規約では、引数と結果の引き渡しの複雑さをなくすためにマクロを使用しています。Version-1関数のC言語宣言は必ず下記のように行います。funcname(PG_FUNCTION_ARGS)さらに、マクロ呼び出しPG_FUNCTION_INFO_V1(funcname);が同じソースファイルに書かれている必要があります。(一般には、関数の直前に書かれます。PostgreSQLではすべての内部関数はVersion-1であると認識するので、このマクロの呼び出しはinternal言語関数では必要ありません。動的にロードされる関数では必要です。Version-1関数では、それぞれの実引数は、引数のデータ型に合ったPG_GETARG_xxx()マクロを使用して取り出され、結果は戻り値の型に合ったPG_RETURN_xxx()マクロを使用して返されます。PG_GETARG_xxx()は、その引数として、取り出す関数引数の番号(ゼロから始まります)を取ります。PG_RETURN_xxx()は、その引数として、実際に返す値を取ります。上記と同じ関数をVersion-1形式で記述したものを以下に示します。VARSIZEは構造体の総長をバイト数で表したものです。VARDATAは構造体のデータ領域へのポインタです。FUNCTIONコマンドはVersion-0と同じものです。Version-1のコーディング規約は無意味なものに見えるかもしれません。マクロが必要のない情報を隠蔽しているので、多数の改良が行われています。add_one_float8のコードでは、float8が参照渡しであることを意識する必要がなくなっています。別の例としては、可変長型のGETARGマクロは"TOASTされた"(圧縮または行外)値をより効率的に取り出すことができます。Version-1関数の1つの大きな改善点は、NULLの入力/結果の処理能力です。PG_ARGISNULL(n)マクロにより関数は各入力がNULLであるかどうかの検査を行うことができます。(もちろんこれは、"厳密"と宣言されていない関数でのみ必要です。PG_GETARG_xxx()マクロと同様、入力引数の番号はゼロから始まります。引数がNULLでないことを確認するまでは、PG_GETARG_xxx()の実行は控えなければなりません。結果としてNULLを返す場合は、PG_RETURN_NULL()を実行します。これは、厳密な関数と厳密でない関数の両方で使用可能です。新しい形式のインタフェースでは、その他のオプションとしてPG_GETARG_xxx()マクロの変形を2つ提供しています。1つ目のPG_GETARG_xxx_COPY()によって、安全に書き込むことができる指定引数のコピーが確実に返されます。(通常のマクロは、物理的にテーブルに格納されている値へのポインタを返すことがあるので、書き込んではなりません。PG_GETARG_xxx_COPY()マクロの結果は書き込み可能であることが保証されています。2つ目の変形は、引数を3つ取るPG_GETARG_xxx_SLICE()マクロからなります。1つ目は関数の引数の番号(上記の通り)です。2つ目と3つ目は、オフセットと返されるセグメントの長さです。オフセットはゼロから始まり、負の長さは残りの値を返すことを要求します。これらのマクロを使用すると、ストレージ種類が"external"(外部)である大きな値の一部へアクセスする際に非常に効果的です。storagetypeを使用して指定できます。storagetypeは、plain、external、extended、またはmainのいずれかです。)最後に、Version-1関数呼び出し規約では、結果集合(項35.9.9)を返すこと、およびトリガ関数(第36章)と手続型言語の呼び出しハンドラ(第51章)を実装することができます。Version-1コードは、標準Cの関数呼び出しプロトコルの制約を守りますので、Version-0よりも移植性があります。詳細についてはソース配布物内のsrc/backend/utils/fmgr/READMEを参照してください。C言語関数のコーディングについての規則をいくつか説明します。C言語以外の言語で記述した関数をPostgreSQLに組み込みむことは可能であるかもしれませんが、例えばC++、FORTRANやPascalといった言語はC言語と同じ呼び出し規約に従いませんので、多くの場合、(可能であったとしても)困難です。それはつまり、他の言語では同じ方法で関数に引数を渡したり、関数から結果を返すことを行わないということです。このため、C言語関数は実際にC言語で書かれているものと仮定します。C関数の作成と構築の基本規則を以下に示します。--includedir-serverを使用して、使用中のシステム(もしくはユーザが実行するシステム)にてPostgreSQLサーバのヘッダファイルがインストールされた場所を見つけます。PostgreSQLに動的にロードできるように独自コードをコンパイル/リンクする時には常に、特別なフラグが必要となります。特定のオペレーティングシステムにおけるコンパイル/リンク方法については項35.9.6を参照してください。忘れずに項35.9.1で説明した"魔法のブロック"を共有ライブラリで定義してください。メモリを割り当てる際、Cライブラリのmallocとfreeではなく、PostgreSQLのpallocとpfreeを使用してください。pallocで割り当てられたメモリは各トランザクションの終わりに自動的に解放され、メモリリークを防ぎます。memsetを使用して、構造体を必ずゼロクリアしてください(または最初の段階でpalloc0を用いて割り当ててください)。構造体の各フィールドを割り当てたとしても、ゴミの値を持つ整列用のパディング(構造体内の穴)があるかもしれません。しないと、ハッシュインデックスやハッシュ結合をサポートすることが困難です。ハッシュを計算するには、データ構造体内の有意なビットのみを取り出す必要があるためです。プランナはまた時折ビット単位の等価性を用いて定数の比較を行います。このため論理的にな値がビット単位で等価でない場合に望まない計画になってしまう可能性があります。ほとんどのPostgreSQLの内部型はpostgres.hに宣言されています。関数管理インタフェース(PG_FUNCTION_ARGSなど)はfmgr.hで宣言されています。したがって、少なくともこの2つのファイルをインクルードする必要があります。移植性に関する理由により、postgres.hをその他のシステムヘッダファイル、ユーザヘッダファイルよりも先にインクルードしておくことが最善です。postgres.hをインクルードすることはelog.h、palloc.hもインクルードすることになります。オブジェクトファイルで定義されているシンボル名は、互いに、またはPostgreSQLサーバの実行ファイルで定義されているものと異なっている必要があります。これに関するエラーが表示される場合は、関数名または変数名を変更する必要があります。動的にロードされる関数のコンパイルとリンクCで書かれたPostgreSQLの拡張関数を使うためには、サーバが動的にロードできるように特別な方法でコンパイルとリンクを行う必要があります。正確には共有ライブラリを作る必要があります。本節の説明以上の詳しい情報はオペレーティングシステムのドキュメント、特にCコンパイラccとリンクエディタldのマニュアルページを参照してください。PostgreSQLのソースコードのcontribディレクトリにいくつか実例があります。これらの例に頼るとPostgreSQLソースコードが利用できることに依存したモジュールが作られてしまいます。共有ライブラリの作成は一般的に実行プログラムのリンクに類似しています。ソースファイルがオブジェクトファイルにコンパイルされ、そのオブジェクトファイル同士がリンクされます。これらのオブジェクトファイルは位置独立なコード(PIC)として作られる必要があります。(実行プログラム用として作られたオブジェクトファイルはそのようにはコンパイルされません)。共有ライブラリをリンクするコマンドは実行プログラムのリンクと区別するための特別なフラグがあります(少なくとも理論上ではそのようになっています。他のシステムではもっと醜い実際が見受けられます)。次の例ではソースコードはfoo.cファイルにあると仮定し、foo.soという共有ライブラリを作るとします。中間のオブジェクトファイルは特別な記述がない限りfoo.oと呼ばれます。共有ライブラリは1つ以上のオブジェクトファイルを持つことができますが、ここでは1つしか使いません。FreeBSDPICを作るためのコンパイラフラグは-fpicです。共有ライブラリを作るコンパイラフラグは-sharedです。foo.oこれはFreeBSDのバージョン3.0に適用されます。HP-UXPICを作るためのシステムコンパイラのコンパイラフラグは+zです。GCCを使う場合は-fpicです。共有ライブラリのためのリンカフラグは-bです。したがって、以下のようになります。foo.oHP-UXは他のほとんどのシステムと異なり共有ライブラリに.slという拡張子を使います。IRIXPICがデフォルトで、特別なコンパイラオプションは何も必要ありません。共有ライブラリを作るためのリンカオプションは-sharedです。foo.oLinuxPICを作るためのコンパイラフラグは-fpicです。いくつかのプラットフォームでは状況によって-fpicが動作しない場合は-fPICを使わなければいけません。詳しい情報についてはGCCのマニュアルを参照してください。共有ライブラリを作るコンパイラフラグは-sharedです。完全な例は下記のようになります。X例を以下に示します。開発者用ツールがインストールされていることが前提です。foo.oNetBSDPICを作るためのコンパイラフラグは-fpicです。ELFシステムでは-sharedコンパイラフラグを使用して共有ライブラリをリンクします。-Bshareableが使われます。foo.oOpenBSDPICを作成するためのコンパイラフラグは-fpicです。-Bshareableを使用します。foo.oSolarisPICを作るためのコンパイラフラグはSunコンパイラでは-KPICで、GCCでは-fpicです。共有ライブラリをリンクするためには、どちらのコンパイラでもコンパイラオプションは-Gで、GCCの場合、代わりに-sharedオプションを使うこともできます。UNIXPICはデフォルトで、コンパイルコマンドは通常のものです。リンクのためには特別なオプション付きのldを使用します。foo.oシステムのコンパイラではなくGCCを使う場合も同じ手順です。特別のオプションは必要ありません。UnixWarePICを作るためのコンパイラフラグはSCOコンパイラでは-KPICで、GCCでは-fpicです。共有ライブラリのリンクは、SCOコンパイラではコンパイラオプションは-Gで、GCCでは-sharedです。Libtoolの使用を検討すべきです。これはプラットフォームの違いを、統一されたインタフェースで判らないようにします。これで完成した共有ライブラリファイルはPostgreSQLにロードすることができます。FUNCTIONコマンドにファイル名を指定する時には、中間オブジェクトファイルではなく共有ライブラリファイル名の名前を与えてください。FUNCTIONで省略することができ、そして移植性を最も高くするため通常は省略されます。サーバがライブラリファイルをどこに見つけるかに関しては項35.9.1を見直してください。複合型ではCの構造体のような固定のレイアウトがありません。複合型のインスタンスはNULLフィールドを持つことができます。複合型で継承階層の一部であるものは、同じ継承階層の他のメンバとは異なるフィールドを持つこともできます。そのため、PostgreSQLはC言語から複合型のフィールドにアクセスするための関数インタフェースを提供します。以下のような問い合わせに答える関数を書こうとしていると仮定します。0呼び出し規約を使用すると、c_overpaidは以下のように定義できます。1で作成すると、上の関数は以下のようになります。limit);}GetAttributeByNameは、指定された行から属性を返す、PostgreSQLシステム関数です。これには3つの引数があります。それらは、関数に渡されたHeapTupleHeader型の引数、求められた属性の名前、属性がNULLであるかどうかを通知する返りパラメータです。GetAttributeByNameは適切なDatumGetXXX()マクロを使用して適切なデータ型に変換可能なDatum型の値を返します。このNULLフラグが設定されている場合、戻り値の意味がないことに注意し、この結果で何かを行おうとする前に常に、NULLフラグを検査してください。対象列を名前ではなく列番号で選択するGetAttributeByNumもあります。下記のコマンドでc_overpaid関数をSQLで宣言します。STRICT;入力引数がNULLかどうかを検査する必要がないようにSTRICTを使用していることに注意してください。行(複合型)を返すC言語関数から行もしくは複合型の値を返すために、複合型の複雑な作成のほとんどを隠蔽するマクロや関数を提供する、特別なAPIを使用することができます。このAPIを使用するためには、ソースファイルで以下をインクルードする必要があります。"funcapi.h"複合型のデータ値(以降"タプル"と記す)を作成する2つの方法があります。Datum値の配列から作成する方法、もしくはタプルのある列の型の入力変換関数に渡すことができるC文字列の配列から作成することです。どちらの方法でも、まずタプル構造体用のTupleDesc記述子を入手、あるいは作成しなければなりません。Datumを使用する場合は、TupleDescをBlessTupleDescに渡し、各行に対してheap_form_tupleを呼び出します。BuildTupleFromCStringsを呼び出します。タプルの集合を返す関数の場合、この設定段階を最初の関数呼び出しで一度にまとめて行うことができます。必要なTupleDescの設定用の補助用関数がいくつかあります。ほとんどの複合型を返す関数での推奨方法は、以下の関数を呼び出し、呼び出し元の関数自身に渡されるfcinfo構造体と同じものを渡すことです。1呼び出し規約を使用していることが必要です。resultTypeIdをNULLとすることも、ローカル変数のアドレスを指定して関数の戻り値型のOIDを受け取ることができます。resultTupleDescはローカルなTupleDesc変数のアドレスでなければなりません。結果がTYPEFUNC_COMPOSITEかどうかを確認してください。TYPEFUNC_COMPOSITEであった場合、resultTupleDescには必要なTupleDescが格納されています。(TYPEFUNC_COMPOSITEではなかった場合、"レコード型を受け付けない文脈でレコードを返す関数が呼び出されました"というエラーを報告することができます。get_call_result_typeは、多様性関数の結果の実際の型を解決することができます。複合型を返す関数だけではなく、スカラの多様結果を返す関数でも有意です。resultTypeId出力は主にスカラの多様結果を返す関数で有意です。get_call_result_typeは、get_expr_result_typeと似たような関数で、関数呼び出しで想定される出力型を式のツリー構造として解決します。関数自身以外から結果型を決定したい場合に、これを使用することができます。get_func_result_typeという関数もあります。これは関数のOIDが利用できる場合にのみ使用することができます。これらの関数は、record型を返すものと宣言された関数では使用できません。get_func_result_typeは多様型を解決することができません。したがって、優先してget_call_result_typeを使用すべきです。古く、廃止予定のTupleDescを入手するための関数を以下に示します。*relname)これを指名したリレーションの行型用のTupleDescを取り出すために使用してください。*colaliases)これを型のOIDに基づいてTupleDescを取り出すために使用してください。これは、基本型もしくは複合型のTupleDescを取り出すために使用可能です。これはrecordを返す関数ではうまく動作しません。多様型を解決することもできません。TupleDescを獲得した後に、Datumを使用する場合は以下を呼び出してください。tupdesc)C文字列を使用する場合は以下を呼び出してください。tupdesc)集合を返す関数を作成する場合は、これらの関数の結果をFuncCallContext構造体に格納してください。それぞれtuple_descとattinmetaを使用します。Datumを使用する場合は、ユーザデータをDatum形式に格納したHeapTupleを構築するために以下を使用します。*isnull)C文字列を使用する場合は、ユーザデータをC文字列形式に格納したHeapTupleを構築するために以下を使用します。**values)valuesは行の各属性を1要素としたC文字列の配列です。各C文字列は、属性のデータ型用の入力関数が受け付け可能な形式でなければなりません。属性の値をNULL値として返すためには、values配列の対応するポインタにNULLを設定してください。この関数は返す行それぞれに対して繰り返し呼び出す必要があります。関数から返すタプルを構築し終わったら、それをDatumに変換しなければなりません。以下を使用して、HeapTupleを有効なDatumに変換してください。tuple)単一行のみを返すのであれば、このDatumを直接返すことができます。なくば、集合を返す関数における現在の戻り値として使用することができます。集合を返すC言語関数から集合(複数行)を返す機能のために特殊なAPIが用意されています。1呼び出し規約に従う必要があります。ソースファイルは上述の通りfuncapi.hをインクルードする必要があります。集合を返す関数(SRF)は返される項目ごとに呼び出されます。そのため、SRFは、過去の操作を記憶して呼び出しの度に次の項目を返すために十分な状態を保っている必要があります。この処理を制御を補助するためのFuncCallContext構造体が備わっています。関数内では、複数の呼び出しにまたがるFuncCallContextへのポインタを保持するには、fcinfo->flinfo->fn_extraを使用します。行われた呼び出しの回数。SRF_RETURN_NEXT()が呼び出される度に増分されます。max_callsは、便宜上用意されているだけで、設定は省略可能です。用意する必要があります。ユーザ定義のSRFのためにだけ存在します。取得するためのユーザ独自の構造へのポインタとして使用されます。基本データ型を返す場合には必要ありません。BuildTupleFromCStrings()を使用して返されるタプルを作成する場合にのみ必要です。SRF_RETURN_DONE()がクリーンアップの際に使用します。これはSRFの複数呼び出しで再利用される全てのメモリ用に最も適切なメモリコンテキストです。タプル説明を含む構造体へのポインタ。なくheap_form_tuple()を使用してタプルを作成する場合にのみ必要です。FuncCallContext;SRFはいくつかの関数およびマクロを使用してFuncCallContext構造体を自動的に操作します(またfn_extraで検索することを想定します)。SRF_IS_FIRSTCALL()を使用して、その関数呼び出しが初回のものであるか、2回目以降であるかを判断します。最初の呼び出し(のみ)で、SRF_FIRSTCALL_INIT()を使用して、FuncCallContextを初期化します。最初の呼び出しを含むすべての呼び出しで、SRF_PERCALL_SETUP()を使用して、FuncCallContextを使用するための適切な設定を行い、以前の受け渡しから残っている結果データを消去します。result)を使用して、そのデータを呼び出し側に返します。resultはDatum型、つまり1つの値またはタプルである必要があります。最後に、関数がデータを返し終わったら、SRF_RETURN_DONE(funcctx)を使用してSRFを片付け、終了します。SRFの呼び出し時に現行になっているメモリコンテキストは一時的なコンテキストで、各呼び出しの間に消去されます。pallocを使用して割り当てたもののすべてをpfreeする必要はありません。これらはいずれ消去されるものだからです。データ構造体を複数の呼び出しに渡って使用するように割り当てる場合は、どこか別の場所に置いておく必要があります。multi_call_memory_ctxによって参照されるメモリコンテキストは、SRFの実行が終わるまで使用可能にしなければならないデータの保管場所として適しています。ほとんどの場合、最初の呼び出しのセットアップ中にmulti_call_memory_ctxへ切り替える必要があるということです。完全な疑似コードの例を示します。これで項目を返し終わりました。後はクリーンアップするだけです。}}複合型を返す単純なSRFの完全な例は以下の通りです。返すタプルを構築するためのvalues配列を用意します。C文字列の配列でなければなりません。}}以下にこの関数をSQLで宣言する一例を示します。STRICT;他にも以下のようにOUTパラメータを使用する方法もあります。STRICT;この方法では、関数の出力型は形式上無名のrecord型になることに注意してください。ソース配布物内のcontrib/tablefuncモジュールのディレクトリには、集合を返す関数のより多くの例があります。引数と戻り値の多様性C言語関数は、anyelement、anyarray、anynonarray、anyenumおよびanyrange多様型を受け付ける、または返すように宣言することができます。多様関数の詳細な説明は項35.2.5を参照してください。関数の引数もしくは戻り値が多様型として定義される時、関数の作成者は前もって呼び出しにおけるデータ型や返すべきデータ型が何であるかを知ることはできません。C関数で引数の実データ型と、返すべきと想定された型を発見できるための2つのルーチンがfmgr.hに用意されています。argnum)という名前です。これらは結果もしくは引数型のOIDを返します。情報が利用できなければInvalidOidを返します。flinfo構造体は通常fcinfo->flinfoとしてアクセスされます。argnumパラメータは0から始まります。get_fn_expr_rettypeの代わりにget_call_result_typeを使用することもできます。"any"キーワードを付けて呼び出されたかどうかを判定するために使用できるget_fn_expr_variadicがあります。"any"の場合に有用です。任意の型の単一要素を受け付け、その型の1次元配列を返す関数を考えてみます。与えられた要素がNULLかどうか注意しつつ、要素を取り出します。この要素型に関する必要情報を取り出す。PG_RETURN_ARRAYTYPE_P(result);}以下のコマンドはSQLでmake_array関数を宣言します。IMMUTABLE;C言語関数でのみ使用できる多様性の変異体があります。"any"型のパラメータを取るように宣言できます。(この型名は、SQL予約語でもあるため二重引用符で括らなくてはならないことに注意してください。これは、他の"any"引数が同じ型になることを強要することも、関数の結果型の決定を支援することもない点を除いて、anyelementのように動作します。"any"であるように宣言可能です。これは任意の型の1つ以上の実引数と一致します(同じ型である必要はありません)。これらの引数は、通常のvariadic関数で起こったように、配列の中にまとめられません。それらは単に別々に関数に渡されるだけです。PG_NARGS()マクロと上に記載したメソッドは、この機能を使用するときに実際の引数とその型を決定するため使用されなければなりません。した関数のユーザは、その関数呼び出しにおいて、関数が配列要素を分離した引数として扱うだろうという予想のもとでVARIADICキーワードを良く使用するかもしれません。関数自身は必要ならば、get_fn_expr_variadicを実行した後で、実引数がVARIADIC付きであることを検出した場合に、その動作を実装しなければなりません。一部の関数呼び出しでは、関数固有の属性に基づいて計画作成を単純化できます。1)はnだけに単純化することができます。した関数固有の最適化を定義するためには、変形関数を作成し、そのOIDを主関数のpg_proc項目のprotransformフィールドに格納します。internalというSQLシグネチャを持たなければなりません。*は、主関数の呼び出しを表すダミーノードです。変形関数の式ツリー学習によって、式ツリーで表されるすべての可能性がある実際の呼び出しを単純化した式ツリーで置き換えることができることが証明された場合、単純化した式を構築し返します。なければ、(SQLのNULLではなく)NULLポインタを返します。PostgreSQLが変形関数によって単純化できる場合に主関数を呼び出さないことは保証されません。単純化した式と実際の主関数の呼び出しとで、厳密に等価であることを確実にしてください。現在、セキュリティ上の懸念から、この機能がSQLレベルでユーザに見えることはありません。このため、これは組み込み関数の最適化での使用のみで実用的です。共有メモリとLWLocksアドインはLWLocks(軽量ロック)とサーバ起動時に共有メモリの割り当てを保持することができます。shared_preload_librariesで指定して、こうしたアドインの共有ライブラリを事前にロードしなければなりません。共有メモリは、その_PG_init関数で以下を呼び出すことで保持されます。size)LWLocksはその_PG_init関数で以下を呼び出すことで保持されます。n)競合状態の可能性を防止するために、割り当てられた共有メモリへの接続やその初期化時に、以下のように各バックエンドでAddinShmemInitLock軽量ロックを使用しなければなりません。以下のガイドラインに従うことで、PostgreSQLの拡張を構築するためC++モードのコンパイラを利用できます。バックエンドからアクセスされる関数はすべてバックエンドに対してCインタフェースを提供しなければなりません。このC関数はC++関数を呼びだすことができます。これはバックエンドとC++コードの間でポインタとして渡される関数にも必要です。適切な解放メソッドを使ってメモリを解放してください。ほとんどのバックエンドメモリはpalloc()で確保されますので、pfree()を使って解放してください。この場合にC++のdelete()を使うと失敗するでしょう。C関数すべての最上位ですべての例外を捕捉するブロックを使ってください)。メモリ不足のようなイベントにより例外が発生する可能性がありますので、C++コードが何も例外を発生させない場合であっても、これは必要です。例外はすべて捕捉しなければなりません。適切なエラーをCインタフェースに渡してください。可能であれば、例外を完全に除去できるように-fno-exceptionsを付けてC++をコンパイルしてください。その場合、例えばnew()で返されるNULLの検査など、C++コード内で失敗の検査を行わなければなりません。C++コードからバックエンド関数を呼び出す場合には、C++呼び出しスタック内にC言語互換構造体(POD)のみが含まれていることを確認してください。バックエンドのエラーは、非PODオブジェクトを持つC++呼び出しスタックを適切に戻すことができない、長距離longjmp()を生成しますので、これは必要です。C関数の背後にC++コードを配置して、例外、メモリ、呼び出しスタックそれぞれの漏れを避けるのが最善です。