提问人:thor 提问时间:11/1/2023 更新时间:11/1/2023 访问量:22
如何检索并使用 Postgres 类型的 outproc 将 Datum 转换为 cstring?
How to retreive and use the outproc of a Postgres type to convert a Datum to cstring?
问:
我正在尝试用 C 编写一个 PostgreSQL (16.x) 存储过程,以将任意类型化参数打印为 C 字符串。据我了解,每种类型都有其输入和输出功能。所以,我的计划是
获取参数类型的 Oid,(
extract_variadic_args
)通过 Oid(如下)检索该类型的
outproc
get_outproc_oid
调用 outproc 将参数的 Datum 转换为 c 字符串。(
OidOutputFunctionCall
)
到目前为止,我所拥有的代码(如下所列)可以编译,但给出了奇怪的结果。它不是将第一个参数打印为字符串,而是打印一些随机的大数字。我不熟悉服务器端 postgresql C 编程。因此,这里有一个问题。
有人可以帮忙解释出了什么问题以及如何使字符串转换工作吗?
到目前为止,我的代码:
Helper C 函数:
// for var2cstring
#include "utils/typcache.h"
#include "utils/fmgroids.h"
#include "utils/lsyscache.h"
void
get_outproc_oid(Oid typoid, Oid *outfuncoid) //adapted from json_categorize_type()
{
bool typisvarlena;
/* Look through any domain */
typoid = getBaseType(typoid);
*outfuncoid = InvalidOid;
switch (typoid)
{
case BOOLOID:
*outfuncoid = F_BOOLOUT;
break;
case INT2OID:
case INT4OID:
case INT8OID:
case FLOAT4OID:
case FLOAT8OID:
case NUMERICOID:
getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
break;
case DATEOID:
*outfuncoid = F_DATE_OUT;
break;
case TIMESTAMPOID:
*outfuncoid = F_TIMESTAMP_OUT;
break;
case TIMESTAMPTZOID:
*outfuncoid = F_TIMESTAMPTZ_OUT;
break;
case JSONOID:
getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
break;
case JSONBOID:
getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
break;
default:
/* Check for arrays and composites */
if (OidIsValid(get_element_type(typoid)) || typoid == ANYARRAYOID
|| typoid == ANYCOMPATIBLEARRAYOID || typoid == RECORDARRAYOID)
{
*outfuncoid = F_ARRAY_OUT;
}
else if (type_is_rowtype(typoid)) /* includes RECORDOID */
{
*outfuncoid = F_RECORD_OUT;
}
else
{
/* any other builtin type */
getTypeOutputInfo(typoid, outfuncoid, &typisvarlena);
}
break;
}
}
主要C功能:
PG_FUNCTION_INFO_V1(var2cstring);
//var2cstring
Datum var2cstring( PG_FUNCTION_ARGS )
{
int nargs;
int i;
Datum *args;
bool *nulls;
Oid *types;
Oid elemtype;
Oid outfuncoid;
/* fetch argument values to build the object */
nargs = extract_variadic_args(fcinfo, 0, false, &args, &types, &nulls);
//elemtype = get_fn_expr_argtype(fcinfo->flinfo, 0);
elemtype = types[0];
get_outproc_oid(elemtype, &outfuncoid);
Datum val = args[0];
char *sometext = OidOutputFunctionCall(outfuncoid, val);
PG_RETURN_CSTRING(sometext);
}
sql 文件:
CREATE OR REPLACE FUNCTION var2cstring(VARIADIC "any") RETURNS INT
AS '$libdir/vc_agg'
LANGUAGE C IMMUTABLE STRICT;
测试数据:
drop table if exists t2;
create table t2(v1 text, v2 text);
insert into t2 values
('Bob','Tom'),
('Tom', 'Bob'),
('Rich', 'Rich');
drop table if exists t3;
create table t3(v1 int, v2 int);
insert into t3 values
(1,2),
(2,1),
(3,3);
select var2cstring(v1, v2) from t2;
select var2cstring(v1, v2) from t3;
我希望得到第一列 v1,但得到了一些大数字:
var2cstring
-------------
1373702072
1373702072
1373702072
(3 rows)
var2cstring
-------------
1373702072
1373702072
1373702072
(3 rows)
答: 暂无答案
评论