在 Postgresql Foreign Data Wrapper 中,如何 return 自定义 TupleTableSlot 中的行数据?

In a Postgresql Foreign Data Wrapper, how to return custom row data in a TupleTableSlot?

我正在为 Postgresql 编写一个外部数据包装器并尝试 return 虚拟数据,但是从外部 table.

选择时出现内存访问错误

我使用准系统 FDW,它 return 在 IterateForeignScan() 中包含三行数据。我使用一个小的 SQL 脚本访问 FDW,我在其中创建了一个具有三列和适当数据类型的外部 table 和 SELECT 整个 table.

通过调试输出,我确定了导致内存访问错误的行,但我不知道为什么会发生错误。每一个帮助表示赞赏:)。

我的 SQL 脚本,用于访问 FDW:

-- creates the bachelor_fdw as extension

CREATE EXTENSION IF NOT EXISTS bachelor_fdw;

DROP SERVER IF EXISTS test1 CASCADE;
CREATE SERVER test1
 FOREIGN DATA WRAPPER bachelor_fdw;

CREATE USER MAPPING FOR postgres
  SERVER test1
  OPTIONS (user 'postgres', password '123456');

DROP FOREIGN TABLE IF EXISTS pg1_sf1_region CASCADE;

-- IMPORT FOREIGN SCHEMA public LIMIT TO (pg1_sf1_region) FROM SERVER test1 INTO public;
CREATE FOREIGN TABLE IF NOT EXISTS pg1_sf1_region(
    ID  integer NOT NULL,
    vorname varchar(20) NOT NULL,
    nachname varchar(20) NOT NULL)
SERVER test1;


SELECT * FROM pg1_sf1_region;

我的 FDW 中的 IterateForeignScan() 函数。调用 heap_form_tuple():

时出现错误
static TupleTableSlot *bachelorIterateForeignScan(ForeignScanState *node){
    ForeignScan *plan = (ForeignScan *) node->ss.ps.plan;
    TupleTableSlot *slot = node->ss.ss_ScanTupleSlot;
    Datum *values;
    TupleDesc tDescFromNode = node->ss.ss_currentRelation->rd_att;
    HeapTuple tuple;
    int dummycounter;
    bool *isnull = palloc0(sizeof(bool)*3);
    isnull[0]=false;
    isnull[1]=false;
    isnull[2]=false;

    // dummy data array
    values = (Datum *) palloc0(sizeof(Datum)*3);

    elog_debug("%s",__func__);

    dummycounter =  linitial_int(plan->fdw_private);


    if( dummycounter > 0){
        if(dummycounter == 1){
            values[0] = Int32GetDatum(3);
            values[1] = CStringGetDatum("Antonia");
            values[2] = CStringGetDatum("Neumann");
        }
        else if(dummycounter == 2){
            values[0] = Int32GetDatum(2);
            values[1] = CStringGetDatum("Karl");
            values[2] = CStringGetDatum("Hermann");
        }
        else if(dummycounter == 3){
            values[0] = Int32GetDatum(1);
            values[1] = CStringGetDatum("Hugo");
            values[2] = CStringGetDatum("Hunter");
        }
        list_head(plan->fdw_private)->data.int_value--;

        ExecClearTuple(slot);
        elog_debug("while tuple creation");

        tuple = heap_form_tuple(tDescFromNode, values, isnull);

        elog_debug("while tuple storing");
        ExecStoreHeapTuple(tuple, slot, false);
        elog_debug("Tuple returned");
        return slot;
    }
    else return NULL;
}

postgresql 日志中的错误消息显示为:“服务器进程 (PID 12310) 被信号 11 终止:Speicherzugriffsfehler”(内存访问错误)

编辑

然而,当从 cstrings 而不是数据 *:

构建元组时,它是有效的
char **cstringvalues = (char **) palloc0(sizeof(char *)*3);
for(int i = 0; i < 3; i++){
    cstringvalues[i] = (char *) palloc(sizeof(char) * 10);
}

...

if( dummycounter > 0){
        if(dummycounter == 1){
            strcpy(cstringvalues[0], "3");
            strcpy(cstringvalues[1], "Antonia");
            strcpy(cstringvalues[2], "Neumann");
            }
        else if(dummycounter == 2){
            strcpy(cstringvalues[0], "2");
            strcpy(cstringvalues[1], "Karl");
            strcpy(cstringvalues[2], "Hermann");
        }
        else if(dummycounter == 3){
            strcpy(cstringvalues[0], "1");
            strcpy(cstringvalues[1], "Hugo");
            strcpy(cstringvalues[2], "Hunter");
        }
        list_head(plan->fdw_private)->data.int_value--;

        ExecClearTuple(slot);

        attin = TupleDescGetAttInMetadata(tDescFromNode);
        elog_debug("while tuple creation");
        tuple = BuildTupleFromCStrings(attin,cstringvalues);
        elog_debug("while tuple storing");
        ExecStoreHeapTuple(tuple, slot, false);
        elog_debug("Tuple returned");
        return slot;

    }
    else return NULL;

我的猜测是,问题在于外部 table 被定义为具有 varchar 列,但您尝试存储 cstring.

尝试使用 CStringGetTextDatum 而不是 CStringGetDatum