postgresqlpostgresql-12libpqlibpqxxpostgresql-extensions

libpqxx C Aggregate Extension returns wrong data?


I am learning how to create C aggregate extensions and using libpqxx with C++ on the client side to process the data.

My toy aggregate extension has one argument of type bytea, and the state is also of type bytea. The following is the simplest example of my problem:

Server side:

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 );

}

Client side:

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( $1 )  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;
}

The result on the client side prints :

Result Size: 258
Raw Result Data: 5c783030303030303030303030303030...

Where the 30 pattern repeats until the end of the string and the printed string in hex is 512 bytes.

I expected to receive an array of length 128 bytes where every byte is set to zero. What am I doing wrong?

The libpqxx version is 7.2 and PostgreSQL 12 on Ubuntu 20.04.

Addendum

Installation of the extesion sql statement;

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" 
);

Solution

  • The answer appears to be that the bytea type data on the client side must be retrieved as follows in the libpqxx library as of 7.0 (Not tested in earlier versions):

    row[ "simple_func" ].as<std::basic_string<std::byte>>()
    

    This retrieves the right bytea data without any conversions, string idiosyncrasies or unexpected behavior like I was seeing.