在 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
。
我正在为 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
。