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 args 只是一个任意的上限,并且您实际上可以采用任意数量的参数,那么您应该只写:

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.

另一个例子是format具有 C 实现(text_format通过pg_proc.h在 虽然是一个更复杂的函数,但作为一个示例对您来说可能更好,因为它在一个地方完成所有工作,而不是拆分为辅助函数调用。它是在其中声明的,但如果它是在 SQL 中声明的,它看起来像:varlena.cgit grep '^text_format'pg_proc.h

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

在那里,您会看到使用宏VARIADIC可以像访问任何其他 from 一样访问参数。宏报告传递的参数数量。arguments 可能为 null,因此您必须使用和处理 null 参数的情况。CPG_GETARG_...(argno)PG_NARGS()VARIADICPG_ARGISNULL(argno)

所以:我会用, ,将它写成一个VARIADIC函数。因为 Pg 的函数不能用零可变参数隐式调用,所以我会为 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 个参数调用它。

顺便说一句,在编码时要注意 Pg 中的字符串text不是以空结尾的,这与传递给main(). 您必须使用 PostgreSQL 提供的长度。. 请参阅src/include/fmgr.h、教程和源代码中函数中的文本处理。不要使用strlen, strcat,strcpy等,因为它们需要以空字符结尾的字符串。

于 2012-10-02T00:12:47.027 回答