1

少しの C テスト コードを PostgreSQL v1 モジュールに変換しようとしています。

元々単純なコマンド ラインとして設計されたコードで、テキスト引数の可変数 (配列) を取ります。3から7まで

元のコードの宣言はコメント化されています。私は今、それを PG 共有オブジェクト関数に変換しようとしています。関数へのすべての引数はテキスト文字列になります (基本コマンド、オプションなど)。

配列を関数に宣言/渡すにはどうすればよいですか?

    PG_FUNCTION_INFO_V1(embed_0);

Datum
embed_0(PG_FUNCTION_ARGS)

// THIS was the declaration when it was a C executable:
// int main(int argc, char *argv[])
{
// don't think mapping argc to a PG type is needed here, right?
// (argc is not a parameter?)
int     *argc; // = PG_GETARG_INT32(0);
char    argv[] = PG_GETARG_TEXT_P(0);

int i;
Object *pName, *pCall, *pPart1, *pPart2, *pArgs, *pValue;
4

1 に答える 1

1

可変数の引数がある場合は、次のいずれかを行う必要があります。

  • それを宣言しVARIADICます。
  • 引数の数が異なる関数に対してn 個の異なるシグネチャを作成します。また
  • C最も一般的な形式である 7 引数の種類のみを作成してから、最も一般的な形式を呼び出す引数が少ない場合の SQL 関数ラッパーを作成します。

本当に 3、4、5、6、および 7 引数のバージョンだけが必要な場合は、次のようにします。

CREATE FUNCTION embed0(text,text,text,text,text,text,text) RETURNS text
LANGUAGE 'C' AS 'embed0','embed0';

CREATE OR REPLACE FUNCTION embed0(text,text,text) RETURNS text AS $$
SELECT embed0($1,$2,$2,NULL,NULL,NULL,NULL);
$$ LANGUAGE 'SQL';

// ... etc

7 つの引数が任意の上限であり、実際には任意の数の引数を取ることができる場合は、代わりに次のように記述します。

CREATE FUNCTION embed0(text,text,text,VARIADIC text) RETURNS text
LANGUAGE 'C' AS 'embed0','embed0';

関数で可変引数を処理しますCconcat方法については、関数の PostgreSQL ソース コードを参照してください。その実装はtext_concatsrc/backend/utils/adt/varlena.c現在の git head の 3842 行目にあります。回線番号が異なります。ほとんどの作業は で行われconcat_internalます。

もう 1 つの例は、現在のformatgit . より複雑な関数ですが、ヘルパー関数呼び出しのために分割するのではなく、すべての作業を 1 か所で行うため、例としてはより適切かもしれません。で宣言されていますが、SQL で宣言されている場合は次のようになります。text_formatpg_proc.hvarlena.cgit grep '^text_format'pg_proc.h

CREATE FUNCTION format(text, VARIADIC text) RETURNS text AS 'internal','text_format';

マクロを使用して、VARIADICから他の引数と同じように引数にアクセスできることがわかります。マクロは、渡された引数の数を報告します。引数は nullの場合があるため、null 引数のケースを使用して処理する必要があります。CPG_GETARG_...(argno)PG_NARGS()VARIADICPG_ARGISNULL(argno)

だから:私は、、、を使用して関数としてそれを書きVARIADICます。Pg の関数は、可変引数が 0 の場合に暗黙的に呼び出すことはできないため、次のような 3 つの引数の場合のラッパーを作成します。PG_NARGSPG_GETARG_TEXT_PPG_ARGISNULLVARIADIC

CREATE OR REPLACE FUNCTION embed_0(text,text,text) RETURNS text AS $$
SELECT embed_0($1,$2,$2, VARIADIC ARRAY[]::text[]);
$$ LANGUAGE 'SQL';

、空の配列を可変個引数として渡します。そうすれば、3つの引数でも呼び出すことができます。

textところで、コーディングするときは、に渡されるものとは異なり、Pg の文字列が null で終了しないことに注意してmain()ください。PostgreSQL が提供する長さを使用する必要があります。. src/include/fmgr.h、チュートリアル、およびソース コード内の関数でのテキスト処理を参照してください。strlenstrcat、などは使用しないでくださいstrcpy。NULL で終わる文字列が必要になるからです。

于 2012-10-02T00:12:47.027 に答える