c - PostgreSQL 模块 - 如何将参数数组映射到函数中?

标签 c postgresql gcc

我正在尝试将一些 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;

最佳答案

如果您有可变数量的参数,您需要:

  • 声明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';

并处理 C 函数中的可变参数。有关操作方法,请参阅 concat 函数的 PostgreSQL 源代码。它的实现是src/backend/utils/adt/varlena.c中的text_concat,当前git head中第3842行;您的行号会有所不同。大部分工作在 concat_internal 中完成。

另一个例子是 format 函数,使用 C 实现 text_format(通过在 pg_proc.h 中查找),位于 varlena .c(根据git grep '^text_format'; Pg编码风格规则规定函数名必须在行的最左边开始),当前git中第3953行。虽然它是一个更复杂的函数,但它作为一个示例可能对您来说更好,因为它在一个地方完成所有工作,而不是分开进行辅助函数调用。它在 pg_proc.h 中声明,但如果它在 SQL 中声明,它看起来像这样:

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

您会看到 VARIADIC 参数可以像 C 中的任何其他参数一样访问,使用 PG_GETARG_...(argno) 宏. PG_NARGS() 宏报告传递的参数数量。 VARIADIC 参数可能为空,因此您必须使用 PG_ARGISNULL(argno) 并处理空参数的情况。

因此:我将使用 PG_NARGSPG_GETARG_TEXT_PPG_ARGISNULL 将其编写为 VARIADIC 函数。因为 Pg 的 VARIADIC 函数不能用零可变参数隐式调用,所以我会为 3 参数的情况编写一个包装器:

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、教程和源代码中函数中的文本处理。不要使用 strlenstrcatstrcpy 等,因为它们需要以 null 结尾的字符串。

关于c - PostgreSQL 模块 - 如何将参数数组映射到函数中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12679619/

相关文章:

c - 如何编写测试CPU和内存之间带宽的程序?(使用C或C++)

laravel - WhereRaw Laravel 变量

c - 仅对任意文件进行预处理器?

c++ - GCC 默认导出所有符号与 MSVC 默认不导出任何内容之间的设计原理是什么?

c - 缓冲区溢出C

c - 线程取消问题

c - 如何在c中获取 (3623752876 * 3623752876) % 4294434817

从 groovy 脚本运行时 Postgresql createdb 命令挂起

javascript - 如果 key 存在,如何更新 - sequelize

c - printf 和字符串存储优化