问题描述
我刚刚开始使用Postgres外部C函数进行测试.当我传递数字并返回时,该功能可以正常工作. (示例)
I am just beginning to test with Postgres External C Functions. When I pass in a Numeric and Return it the function works fine. (Example)
样本功能
PG_FUNCTION_INFO_V1(numericTesting);
Datum
numericTesting(PG_FUNCTION_ARGS)
{
Numeric p = PG_GETARG_NUMERIC(0);
PG_RETURN_NUMERIC(p);
}
但是,当我尝试对传入的变量执行任何数学函数时,它将无法编译.我得到
However, when I try to do any math functions on the variable passed in, it will not compile. I get
样本功能
PG_FUNCTION_INFO_V1(numericTesting);
Datum
numericTesting(PG_FUNCTION_ARGS)
{
Numeric p = PG_GETARG_NUMERIC(0);
PG_RETURN_NUMERIC(p * .5);
}
是什么原因造成的?我猜数值数据类型需要一些函数来允许数学运算.我尝试使用:PG_RETURN_NUMERIC(DatumGetNumeric(p * .5)),但结果相同.
What is causing this? I'm guessing the the Numeric datatype needs some function to allow math. I tried using: PG_RETURN_NUMERIC(DatumGetNumeric(p * .5)) but that had the same result.
推荐答案
Numeric
不是原始类型,因此您不能直接对其进行算术运算. C没有运算符重载,因此无法为Numeric添加乘法运算符.您必须使用适当的函数调用来将数字相乘.
Numeric
isn't a primitive type so you can't do arithmetic operations on it directly. C doesn't have operator overloading, so there's no way to add a multiply operator for Numeric. You'll have to use appropriate function calls to multiply numerics.
与编写Pg扩展功能时的大多数事情一样,阅读源代码并查看其在其他地方的工作方式可能会很有帮助.
As with most things when writing Pg extension functions it can be helpful to read the source and see how it's done elsewhere.
在这种情况下,请查看src/backend/utils/adt/numeric.c
.检查Datum numeric_mul(PG_FUNCTION_ARGS)
,您将在其中看到它使用mul_var(...)
进行工作.
In this case look at src/backend/utils/adt/numeric.c
. Examine Datum numeric_mul(PG_FUNCTION_ARGS)
where you'll see it use mul_var(...)
to do the work.
很遗憾,mul_var
是static
,因此不能在numeric.c
之外使用.令人讨厌和令人惊讶.必须有一种合理的方法来处理C
扩展功能中的NUMERIC
,而无需使用spi/fmgr通过SQL
运算符调用来完成工作,正如您在注释中所显示的那样,您可以使用DirectFunctionCall2
进行调用numeric_mul
运算符.
Unfortunately mul_var
is static
so it can't be used outside numeric.c
. Irritating and surprising. There must be a reasonable way to handle NUMERIC
from C
extension functions without using the spi/fmgr to do the work via SQL
operator calls, as you've shown in your comment where you use DirectFunctionCall2
to invoke the numeric_mul
operator.
看起来像可以直接从C调用的Numeric的公共内容在src/include/utils/numeric.h
中,所以让我们看一下.哎呀,不多,只有一些宏可以在Numeric
和Datum
之间进行转换,以及一些帮助程序GETARG
和RETURN
宏.看起来通过SQL调用进行使用可能是唯一的方法.
It looks like the public stuff for Numeric that's callable directly from C is in src/include/utils/numeric.h
so let's look there. Whoops, not much, just some macros for converting between Numeric
and Datum
and some helper GETARG
and RETURN
macros. Looks like usage via the SQL calls might be the only way.
如果确实发现通过SQL的Numeric接口使用DirectFunctionCall2
卡住了,则可以使用int4_numeric
从C整数的另一侧创建Numeric参数.
If you do find yourself stuck using DirectFunctionCall2
via the SQL interfaces for Numeric, you can create a Numeric argument for the other side from a C integer using int4_numeric
.
如果找不到解决方案,请在pgsql-general邮件列表中发布,您将获得更多使用C扩展及其源代码的经验.链接回这篇文章.
If you can't find a solution, post on the pgsql-general mailing list, you'll get more people experienced with C extensions and the source code there. Link back to this post if you do so.
这篇关于Postgres C函数-传递&返回数字的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!