我正在为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
答案 0 :(得分:0)
这是一个想法
#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。
答案 1 :(得分:0)
我找到了一个解决方案,感谢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));