【问题标题】:Postgres custom type mapping to C struct?Postgres自定义类型映射到C结构?
【发布时间】:2020-09-14 17:05:54
【问题描述】:

我正在编写一个自定义 Postgres C AGGREGATE 扩展。我想知道如何正确地将 PSQL 中定义的类型映射到 C 中定义的结构。我已经尽我所能尝试做到这一点,但我没有得到结果,我在测试时得到一个空行。

C 结构具有以下形式:

typedef struct {
    int64_t row_idx;     //Row number in the processing order (NOT thread safe)
    int64_t data1_size;   
    int64_t data2_size;     
    char data2[ 1<<10 ];    
    char data1[ 1<<10 ];    
} search_state;

我不确定是否更好地获取数据的 char 指针,或者是否像上面那样预先静态分配。我已经尝试了两种方法来达到同样的效果;我知道使用 pmalloc 分配以保留对行的调用之间的数据。我也尝试过使用 postgres 类型“文本”,但在聚合结束时我仍然没有得到任何数据,结果只是没有行。

在 Psql 方面我有:

CREATE TYPE search_state AS (
    row_idx    int8,
    data1_size int8,
    data2_size int8,
    data1      char[1<<10],
    data2      char[1<<10]
);

再次,我尝试了 data1 或 data2 的文本类型,但我不知道如何使其工作。

问题是,如上所示,在 psql 中获取一个精确映射到 C 中的结构的类型的正确方法是什么?看来我的问题是由于我在 C 中修改结构时 postgres 无法找到数据。

在聚合期间使用此结构作为中间状态的函数类似于:

 Datum fancy_select(PG_FUNCTION_ARGS){
        //Get the Postgres C-Extension Parameters
        search_state *state   = (search_state * ) PG_GETARG_POINTER(0);
        char *inputText       = PG_GETARG_CSTRING(1);
        uint64_t numeric_id   = PG_GETARG_INT64(2);

        //Make object to store state from now on.
        search_state *new_state   = (search_state *) palloc( 2*(1<<10) + 8*3 );

        //Small Test updating the state
        new_state->row_idx    = 1;
        new_state->data1[0]   = 'T'
        new_state->data1[1]   = '\0'
        new_state->data2[0]   = 'H'
        new_state->data2[1]   = '\0'
        new_state->data1_size = strlen( new_state->data1 ) ;
        new_state->data2_size = strlen( new_state->data2 ) ;

        //Return state
        PG_RETURN_POINTER( new_state );
   };
}

这个聚合有一个最终函数,它本质上接受结构,获取 data1,然后返回最后存储在那里的文本。我还应该提到,这个扩展是用 C++ 编写的,而不是普通的 C,但我使用尽可能多的 C 和尽可能少的 C++。

注意 1: 使用不同的结构进行测试,行为范围从返回 initcond、根本没有行和以下消息:

ERROR:  type with OID 0 does not exist
CONTEXT:  PL/pgSQL function final_func(search_state) while storing call arguments into local variables

【问题讨论】:

    标签: c++ c postgresql postgresql-12


    【解决方案1】:

    我可以给你一些建议。

    首先,我假设您知道caveats when writing server code in C++

    你的数据类型的内部表示可以是任何东西,但我不会分配比需要更多的内存。

    内部和外部表示之间的映射完全取决于您,并且由您编写的类型输入和输出函数确定。

    但如果你只想写一个聚合函数,我不明白为什么你需要用 C 写的特殊类型。

    我只是

    CREATE TYPE search_state AS (
       row_idx bigint,
       data2 text,
       data1 text
    );
    

    并将此复合类型与您的函数一起使用。在您的 C 代码中获取该类型的组件并不难,并且可以省去您编写大量样板代码的麻烦。

    【讨论】:

    • 我给出的例子简单明了。真正的代码很复杂,字符串数据有很多花哨的计算,由于依赖关系和花哨的库,需要在 C++ 中进行扩展。
    • 我认为是后者。但我不明白为什么这需要用 C 编写的类型。
    • 你能写一个简单的例子,说明如何在聚合函数中从 C/C++ 中写入/读取该类型的 data1、data2 吗?
    • 所以,这种方法的复杂性对我来说太高了……需要担心很多 postgres 框架的东西……而且没有一个明确的示例/模板可供参考。官方文档在这方面没有帮助。我决定以不同的方式实现这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 2016-04-15
    • 2021-11-20
    • 1970-01-01
    • 2016-08-24
    • 2019-01-25
    相关资源
    最近更新 更多