Postgresql c函数返回一行有2个字段

Posted

技术标签:

【中文标题】Postgresql c函数返回一行有2个字段【英文标题】:Postgresql c function returning one row with 2 fileds 【发布时间】:2013-11-09 10:41:54 【问题描述】:

我是 postgresql c 函数的新手,我开始学习示例。

我想编写一个简单的函数,它在 SQL 内部并接收参数 evaluete 并分别返回 2 个字段作为 2 列的总和(现在更简单)。

下面的函数通过检查有问题

(get_call_result_type(fcinfo, &resultTypeId, &resultTupleDesc) != TYPEFUNC_COMPOSITE)

如果我删除这一行,我会从这个查询中得到 1 个整数

select * from pdc_imuanno(2012);

和来自

的错误
select (a).* from pdc_imuanno(2012) a;

因为不是复合类型。

如果不正确,我该如何为元组准备模板

resultTupleDesc = CreateTemplateTupleDesc(2, false);
TupleDescInitEntry(resultTupleDesc, (AttrNumber) 1, "abp1", FLOAT4OID, -1, 0);
TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "abp2", FLOAT4OID, -1, 0);

还有更多

get_call_result_type(fcinfo, &resultTypeId, &resultTupleDesc)

fcinfo 是什么,从何而来?

源表:

CREATE TABLE imu.calcolo (
  codfis character varying(16) NOT NULL,
  anno integer NOT NULL,
  abp1 numeric,
  abp2 numeric,
  CONSTRAINT imucalcolo_pkey PRIMARY KEY (codfis, anno)
)
WITH ( OIDS=FALSE );
-------------------------------------------------------
#include "postgres.h"
#include "fmgr.h"

#include "catalog/pg_type.h"
#include "funcapi.h"
#include "executor/spi.h"
#include "lib/stringinfo.h"
#include "miscadmin.h"

#include <math.h>

#include "utils/builtins.h"
#include "utils/guc.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/numeric.h"

#include "access/htup_details.h"

#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif

PG_FUNCTION_INFO_V1(test_query);
Datum test_query(PG_FUNCTION_ARGS);

Datum
test_query(PG_FUNCTION_ARGS)

  TupleDesc resultTupleDesc, tupledesc;
  bool bisnull, cisnull;
  Oid resultTypeId;
  Datum retvals[2];
  bool retnulls[2];
  HeapTuple rettuple;

  sprintf(query,"SELECT anno, abp1::real, abp2::real "
                "FROM imu.calcolo WHERE anno = %d;",PG_GETARG_INT32(0));

  int ret;
  int proc;
  float abp1 = 0;
  float abp2 = 0;
  SPI_connect();
  ret = SPI_exec(query,0);
  proc = SPI_processed;

  if (ret > 0 && SPI_tuptable != NULL)
  
    HeapTuple tuple;
    tupledesc = SPI_tuptable->tupdesc;
    SPITupleTable *tuptable = SPI_tuptable;
    for (j = 0; j < proc; j++)
    
      tuple = tuptable->vals[j];
      abp1 += DatumGetFloat4(SPI_getbinval(tuple, tupledesc, 2, &bisnull));
      abp2 += DatumGetFloat4(SPI_getbinval(tuple, tupledesc, 3, &cisnull));
    
  
  resultTupleDesc = CreateTemplateTupleDesc(2, false);
  TupleDescInitEntry(resultTupleDesc, (AttrNumber) 1, "abp1", FLOAT4OID, -1, 0);
  TupleDescInitEntry(resultTupleDesc, (AttrNumber) 2, "abp2", FLOAT4OID, -1, 0);

  if (get_call_result_type(fcinfo, &resultTypeId, &resultTupleDesc) != TYPEFUNC_COMPOSITE) 
    ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                    errmsg("function returning record called in context that cannot accept type record")));
  
  resultTupleDesc = BlessTupleDesc(resultTupleDesc);
  SPI_finish();
  retvals[0] = Float4GetDatum(abp1);
  retvals[1] = Float4GetDatum(abp2);
  retnulls[1] = bisnull;
  retnulls[2] = cisnull;
  rettuple = heap_form_tuple( resultTupleDesc, retvals, retnulls);
  PG_RETURN_DATUM( HeapTupleGetDatum( rettuple ) );



创作功能:

CREATE FUNCTION pdc_imuanno(integer)
RETURNS float
AS 'pdc','test_query'
LANGUAGE C STABLE STRICT;
ALTER FUNCTION pdc_imuanno(integer) OWNER TO www;

查询:

select * from pdc_imuanno(2012);

好的,我发现了一个简单而愚蠢的错误 我自己创建了返回 1 个字段的函数,并希望看到返回 2 个字段。

使用这个创建 sql 它可以工作

CREATE FUNCTION pdc_imuanno(integer)
RETURNS TABLE(abp1 real, abp2 real)
AS 'pdc','test_query'
LANGUAGE C STABLE STRICT;

无论如何,它适用于有限数量的求和,如果我扩展行数,它会崩溃 在这一点上

rettuple = heap_form_tuple( resultTupleDesc, retvals, retnulls);

我猜值的类型有一些错误

所以我将表格字段查询为 numeric::real,我将它们作为 float4 并将它们作为数据输出。

我的错误在哪里?

非常感谢您的帮助。

这是我在 *** 上的第一篇文章。

卢卡

【问题讨论】:

PostgreSQL 版本?请显示完整的可编译 C 文件。 我在 linux box 上使用的 PostgreSQL 是 9.3。 看起来您将问题确定为函数签名与声明不匹配。我很高兴。如果您有后续问题,请发布新问题。链接回这个以获取上下文。包括对您正在尝试做的事情的解释,而不仅仅是您的问题。 【参考方案1】:

在:

get_call_result_type(fcinfo, &amp;resultTypeId, &amp;resultTupleDesc)

fcinfo - 是什么以及来自哪里?

fcinfo 是 v1 调用约定中 PG_FUNCTION_ARGS 的一部分。它是函数调用的上下文,包含各种细节,如参数等。其中大部分由 GETARG 宏等在幕后处理,但您需要将其传递给辅助函数。

由于拼写错误等原因,问题的其余部分很难理解。我猜测您想用 C 编写一个函数来将两个值相加并返回结果?如果是这样,那么作为复合类型中的两个字段返回没有多大意义。请显示相关的CREATE TYPE 语句、您用于定义函数的CREATE OR REPLACE FUNCTION 声明,并说明您要做什么以及为什么。

(如果您编辑您的问题,请发表评论以回复此答案,否则我不会知道您已编辑。)

【讨论】:

非常感谢克雷格,我已经改进了问题。

以上是关于Postgresql c函数返回一行有2个字段的主要内容,如果未能解决你的问题,请参考以下文章

PostgreSQL:使用窗口函数返回单行

从 PostgreSQL 中的字段中提取数字

PostgreSQL如何导入数据

PostgreSQL 在使用自定义类型时只返回一行

急求一个c语言定义函数的程序,有一个参数但无返回值,实现输出一行n

PostgreSQL 高级SQL(五) 内建窗口函数