2012-10-01 69 views
1

在尝试的C测试代码一点点转换成一个PostgreSQL V1模块PostgreSQL模块 - 如何将参数数组映射到函数中?

代码最初设计为简单的命令行,它采用可变数目 - 的阵列 - 的文本参数;从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; 

回答

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'; 

,并在您C功能处理可变参数。有关如何使用concat函数,请参阅PostgreSQL源代码。它的实现是text_concat在当前git头的3842行中的src/backend/utils/adt/varlena.c;你的线路号码会有所不同。大部分工作都在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_NARGS,PG_GETARG_TEXT_P,PG_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个参数来调用它。

BTW,编码要知道,在PG text中的字符串不是空终止,不像那些传递给main()时。您必须使用PostgreSQL提供的长度。。请参阅src/include/fmgr.h,本教程以及源代码中的函数中的文本处理。请勿使用strlen,strcat,strcpy等,因为它们期望以空字符结尾的字符串。