postgres中外部表的应用如下:
但是许多在github上的fdw开源代码都是基于9.3以及9.4版本开发,原作者没有随着pg的版本升级而将外部表扩展升级,那只能靠自己去手动修改源码来让这些扩展能够使用。
typedef struct FdwRoutine此结构是外部表当中的关键,结构体内部挂接的都是读写外部表的钩子函数(函数指针),在内核部分是如果判断读写的表是外部表,就会走外部表的case分支。
如何9.5以前的外部表使其能够使用呢
一、fdwRoutine->GetForeignPlan结构体中的函数指针在9.5之前都是6个参数,9.5含9.5之后变成了7个参数
因此需要将fdwRoutine->GetForeignPlan = xxxxGetForeignPlan; 这个函数的实现修改正确了,一般新增参数用NULL或者nill去替代,特殊情况,还需要研读源码。
还要注意了在函数体中也会常调用make_foreignscan,此函数也需要修改,修改如下
#if PG_VERSION_NUM >= 90500 static ForeignScan * XXXGetForeignPlan(PlannerInfo *root, RelOptInfo *baserel, Oid foreignTableId, ForeignPath *bestPath, List *targetList, List *scanClauses, Plan *outerPlan) #else static ForeignScan * XXXGetForeignPlan(PlannerInfo *root, RelOptInfo *baserel, Oid foreignTableId, ForeignPath *bestPath, List *targetList, List *scanClauses) #endif { ...... ...... #if PG_VERSION_NUM >= 90500 foreignScan = make_foreignscan(targetList, scanClauses, baserel->relid, NIL, /* no expressions to evaluate */ foreignPrivateList, NIL, NIL, NULL); /* no outer path */ #else foreignScan = make_foreignscan(targetList, scanClauses, baserel->relid, NIL, /* no expressions to evaluate */ foreignPrivateList); #endif ...... ...... return foreignScan; }
二、fdwRoutine->GetForeignPaths这个函数指针一般会调用create_foreignscan_path这个函数,此函数不同版本参数也不同,在调用处修改为
#if PG_VERSION_NUM >= 90600 foreignScanPath = (Path *) create_foreignscan_path(root, baserel, NULL, /* path target */ baserel->rows, startupCost, totalCost, NIL, /* no known ordering */ NULL, /* not parameterized */ NULL, /* no outer path */ NIL); /* no fdw_private */ #elif PG_VERSION_NUM >= 90500 foreignScanPath = (Path *) create_foreignscan_path(root, baserel, baserel->rows, startupCost, totalCost, NIL, /* no known ordering */ NULL, /* not parameterized */ NULL, /* no outer path */ NIL); /* no fdw_private */ #else foreignScanPath = (Path *) create_foreignscan_path(root, baserel, baserel->rows, startupCost, totalCost, NIL, /* no known ordering */ NULL, /* not parameterized */ NIL); /* no fdw_private */ #endif
三、typedef struct RelOptInfo结构体中的targetlist改变了,修改如下
#if PG_VERSION_NUM >= 90600 List *targetColumnList = baserel->reltarget->exprs; #else List *targetColumnList = baserel->reltargetlist; #endif
四、pull_var_clause()函数的改变,修改如下
#if PG_VERSION_NUM >= 90600 targetVarList = pull_var_clause(targetExpr, PVC_RECURSE_AGGREGATES | PVC_RECURSE_PLACEHOLDERS); #else targetVarList = pull_var_clause(targetExpr, PVC_RECURSE_AGGREGATES, PVC_RECURSE_PLACEHOLDERS); #endif
五、头文件使用,像cstore_fdw中就存在,pg_lzcompress.h关于压缩的头文件,内核部分将这个头文件更改了目录,修改如下
#if PG_VERSION_NUM >= 90600 #include "common/pg_lzcompress.h" #else #include "utils/pg_lzcompress.h" #endif
按照以上步骤修改,现有的pg版本都可适用!!(如有问题,欢迎一起讨论)