postgres外部表如何修改源码适配pg升级

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版本都可适用!!(如有问题,欢迎一起讨论)

  

原文地址:https://www.cnblogs.com/lujunfeng/p/6293168.html