【问题标题】:How to access large objects in Postgresql c-language functions?如何访问 Postgresql c 语言函数中的大对象?
【发布时间】:2015-02-17 04:46:51
【问题描述】:

我正在为 postgresql 9.3.5 编写 c-language 用户定义函数。我没有使用 pl/pgsql 或 pl/python,因为它的一部分需要用 C 编写以提高速度。

函数获取一个现有的 OID 作为参数。如何从 c 语言函数中访问和修改 OID 数据?我找不到任何文档!

到目前为止,我在函数中所拥有的只是读取参数的部分:

#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;

Datum tsdb_write_lob(PG_FUNCTION_ARGS) ;

PG_FUNCTION_INFO_V1(tsdb_write_lob);



Datum tsdb_write_lob(PG_FUNCTION_ARGS) {
    int16 arg_dataformat = PG_GETARG_INT16(0);
    int16 arg_granularity_days = PG_GETARG_INT16(1);
    Oid arg_dataoid = PG_GETARG_OID(2);

   ereport( INFO, (errcode( ERRCODE_SUCCESSFUL_COMPLETION ),
                errmsg("Arguments were: %d, %d, %ld\n",arg_dataformat,arg_granularity_days,arg_dataoid)));


   /*TODO:
    * open oid (lo_open ?)
    * read data
    * decompress data
    * parse data
    * add new data
    * compress data
    * save to same oid
    */



    PG_RETURN_VOID();
}

更新: 这似乎是一个例子:

https://github.com/postgres/postgres/blob/master/src/backend/libpq/be-fsstubs.c

【问题讨论】:

  • 你能展示你目前拥有的东西吗?我真的觉得这很有趣,并且最近在 c 中为 PostgreSQL 做了一些扩展,所以我可以帮助你。
  • 奇怪的是,用于开发 postgresql 函数的文档很少。这是运气和谷歌技能的结合。
  • 是的,postgresql 的文档中几乎没有好的示例。我正要问你,你说的open oid是什么意思?
  • @iharob 相当于 lo_open()。我在 15 年前才找到这个模糊的答案:postgresql.org/message-id/7886.992327525@sss.pgh.pa.us
  • 我会尝试在源代码中找到合适的函数。

标签: c postgresql


【解决方案1】:

这是一个想法

#include <postgres.h>
#include <utils/rel.h>
#include <utils/array.h>
#include <commands/trigger.h>
#include <executor/spi.h>

PG_MODULE_MAGIC;

Datum tsdb_write_lob(PG_FUNCTION_ARGS) ;

extern SPITupleTable *SPI_tuptable;

PG_FUNCTION_INFO_V1(tsdb_write_lob);
Datum tsdb_write_lob(PG_FUNCTION_ARGS) {
{
    int16 arg_dataformat       = PG_GETARG_INT16(0);
    int16 arg_granularity_days = PG_GETARG_INT16(1);
    Oid   arg_dataoid          = PG_GETARG_OID(2);
    char  command[128];

    if (SPI_ERROR_CONNECT == SPI_connect())
        PG_RETURN_VOID();
    snprintf(command, sizeof(command), "SELECT lo_open(INV_READ, %d)", arg_dataoid);
    if (SPI_OK_SELECT != SPI_execute(command, false, 0))
        PG_RETURN_VOID();
    .
    .
    .
    /* do loread here the same way by using SPI_execute("SELECT loread ...") */
    SPI_finish();

    PG_RETURN_VOID();
}

您需要阅读SPI_tubtable 指针以了解如何解析查询,以及整个SPI Server Programming Interface

【讨论】:

  • 我现在没有足够的时间,但是今晚晚些时候我会回来检查它是如何工作的,如果可能的话,会为您提供更多帮助。
  • 感谢您的意见。我想解析 SQL 语句效率不是很高,因为这个函数每秒要调用数千次。
【解决方案2】:

感谢 pgsql 邮件列表,我找到了解决方案:

int inv_fd;
Oid arg_dataoid = PG_GETARG_OID(0);
...

//open        
inv_fd = DatumGetInt32(DirectFunctionCall2(lo_open, arg_dataoid, Int32GetDatum(INV_READ|INV_WRITE)));


if (inv_fd < 0) {
    elog(ERROR, "lo_open: lookup failed for oid:%ld", DatumGetInt64(arg_dataoid));
    PG_RETURN_INT32(-1);
}

//write
if ( lo_write(inv_fd, cstr, nbytes ) != nbytes)
        elog(ERROR, "error while writing large object");

//close LO
DirectFunctionCall1(lo_close, Int32GetDatum(inv_fd));

可以在herehere 找到许多其他 lo* 函数的示例

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-20
    • 1970-01-01
    • 1970-01-01
    • 2022-06-10
    • 1970-01-01
    相关资源
    最近更新 更多