libpqxx C 聚合扩展 returns 错误数据?
libpqxx C Aggregate Extension returns wrong data?
我正在学习如何创建 C 聚合扩展以及如何在客户端使用 libpqxx 和 C++ 来处理数据。
我的玩具聚合扩展有一个 bytea
类型的参数,状态也是 bytea
类型的。以下是我的问题的最简单示例:
服务器端:
PG_FUNCTION_INFO_V1( simple_func );
Datum simple_func( PG_FUNCTION_ARGS ){
bytea *new_state = (bytea *) palloc( 128 + VARHDRSZ );
memset(new_state, 0, 128 + VARHDRSZ );
SET_VARSIZE( new_state,128 + VARHDRSZ );
PG_RETURN_BYTEA_P( new_state );
}
客户端:
std::basic_string< std::byte > buffer;
pqxx::connection c{"postgresql://user:simplepassword@localhost/contrib_regression"};
pqxx::work w(c);
c.prepare( "simple_func", "SELECT simple_func( ) FROM table" );
pqxx::result r = w.exec_prepared( "simple_func", buffer );
for (auto row: r){
cout << " Result Size: " << row[ "simple_func" ].size() << endl;
cout << "Raw Result Data: ";
for( int jj=0; jj < row[ "simple_func" ].size(); jj++ ) printf( "%02" PRIx8, (uint8_t) row[ "simple_func" ].c_str()[jj] ) ;
cout << endl;
}
客户端打印结果:
Result Size: 258
Raw Result Data: 5c783030303030303030303030303030...
其中 30
模式重复,直到字符串结束,打印的十六进制字符串为 512 字节。
我希望收到一个长度为 128 字节的数组,其中每个字节都设置为零。我做错了什么?
libpqxx 版本为 7.2,PostgreSQL 12 在 Ubuntu 20.04 上。
附录
安装扩展 sql 语句;
CREATE OR REPLACE FUNCTION agg_simple_func( state bytea, arg1 bytea)
RETURNS bytea
AS '$libdir/agg_simple_func'
LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE AGGREGATE simple_func( arg1 bytea)
(
sfunc = agg_simple_func,
stype = bytea,
initcond = "\xFFFF"
);
我建议您一一解决这些问题:首先让函数正常工作,在交互式查询中使用 psql
测试它,然后编写客户端代码(反之亦然)。
我不能谈论 libpqxx,但我不得不抱怨你的功能:你提供的东西甚至无法编译,因为你把 DATUM
写成大写而忘记了 headers 和其他重要的东西。
此函数将编译并 运行 如您所愿:
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(simplest_func);
Datum simplest_func(PG_FUNCTION_ARGS) {
bytea *new_state = (bytea *) palloc(128 + VARHDRSZ);
memset(new_state, 0, 128 + VARHDRSZ);
SET_VARSIZE(new_state, 128 + VARHDRSZ);
PG_RETURN_BYTEA_P(new_state);
}
memset
将以这种方式工作,但是设置 varlena
的值的更好、更惯用和更可靠的方法是
memset(VARDATA(new_state), 0, 128);
我不知道你是如何得到结果的,但由于你提供的代码无法编译,我不知道你的函数到底是什么样子。
答案似乎是客户端的 bytea 类型数据必须在 7.0 的 libpqxx 库中按如下方式检索(未在早期版本中测试):
row[ "simple_func" ].as<std::basic_string<std::byte>>()
这会检索到正确的 bytea 数据,没有任何转换、字符串特性或我所看到的意外行为。
我正在学习如何创建 C 聚合扩展以及如何在客户端使用 libpqxx 和 C++ 来处理数据。
我的玩具聚合扩展有一个 bytea
类型的参数,状态也是 bytea
类型的。以下是我的问题的最简单示例:
服务器端:
PG_FUNCTION_INFO_V1( simple_func );
Datum simple_func( PG_FUNCTION_ARGS ){
bytea *new_state = (bytea *) palloc( 128 + VARHDRSZ );
memset(new_state, 0, 128 + VARHDRSZ );
SET_VARSIZE( new_state,128 + VARHDRSZ );
PG_RETURN_BYTEA_P( new_state );
}
客户端:
std::basic_string< std::byte > buffer;
pqxx::connection c{"postgresql://user:simplepassword@localhost/contrib_regression"};
pqxx::work w(c);
c.prepare( "simple_func", "SELECT simple_func( ) FROM table" );
pqxx::result r = w.exec_prepared( "simple_func", buffer );
for (auto row: r){
cout << " Result Size: " << row[ "simple_func" ].size() << endl;
cout << "Raw Result Data: ";
for( int jj=0; jj < row[ "simple_func" ].size(); jj++ ) printf( "%02" PRIx8, (uint8_t) row[ "simple_func" ].c_str()[jj] ) ;
cout << endl;
}
客户端打印结果:
Result Size: 258
Raw Result Data: 5c783030303030303030303030303030...
其中 30
模式重复,直到字符串结束,打印的十六进制字符串为 512 字节。
我希望收到一个长度为 128 字节的数组,其中每个字节都设置为零。我做错了什么?
libpqxx 版本为 7.2,PostgreSQL 12 在 Ubuntu 20.04 上。
附录
安装扩展 sql 语句;
CREATE OR REPLACE FUNCTION agg_simple_func( state bytea, arg1 bytea)
RETURNS bytea
AS '$libdir/agg_simple_func'
LANGUAGE C IMMUTABLE STRICT;
CREATE OR REPLACE AGGREGATE simple_func( arg1 bytea)
(
sfunc = agg_simple_func,
stype = bytea,
initcond = "\xFFFF"
);
我建议您一一解决这些问题:首先让函数正常工作,在交互式查询中使用 psql
测试它,然后编写客户端代码(反之亦然)。
我不能谈论 libpqxx,但我不得不抱怨你的功能:你提供的东西甚至无法编译,因为你把 DATUM
写成大写而忘记了 headers 和其他重要的东西。
此函数将编译并 运行 如您所愿:
#include "postgres.h"
#include "fmgr.h"
PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(simplest_func);
Datum simplest_func(PG_FUNCTION_ARGS) {
bytea *new_state = (bytea *) palloc(128 + VARHDRSZ);
memset(new_state, 0, 128 + VARHDRSZ);
SET_VARSIZE(new_state, 128 + VARHDRSZ);
PG_RETURN_BYTEA_P(new_state);
}
memset
将以这种方式工作,但是设置 varlena
的值的更好、更惯用和更可靠的方法是
memset(VARDATA(new_state), 0, 128);
我不知道你是如何得到结果的,但由于你提供的代码无法编译,我不知道你的函数到底是什么样子。
答案似乎是客户端的 bytea 类型数据必须在 7.0 的 libpqxx 库中按如下方式检索(未在早期版本中测试):
row[ "simple_func" ].as<std::basic_string<std::byte>>()
这会检索到正确的 bytea 数据,没有任何转换、字符串特性或我所看到的意外行为。