跟我一起读postgresql源码(十)——Executor(查询执行模块之——Scan节点(下)) (4)

如下所示,WorkTableScan节点扩展定义了wtParam用于同RecursiveUnion节点间的通信,而 WorkTableScanState 节点的 rustate 字段中记录了 RecursiveUnionState结构的指针,以便WorkTableScan在执行过程中可以从缓存结构中获取元组。

typedef struct WorkTableScan { Scan scan; int wtParam; /* ID of Param representing work table */ } WorkTableScan;

节点状态:

typedef struct WorkTableScanState { ScanState ss; /* its first field is NodeTag */ RecursiveUnionState *rustate; } WorkTableScanState; 13.ForeignScan节点

如果用过postgres_fdw或者dblink这些PostgreSQL提供了外部数据包装器,那么就大概能知道这个Scan节点的用途:扫描外部Postgresql数据表。

如果你对postgres_fdw有兴趣,这里是网址,拿去不谢:

ForeignScan节点的信息如下,主要在Scan之外扩展了外部数据相关的一些信息。fdw_exprs和fdw_private都在外部数据包装器的控制下,但是fdw_exprs被假定为包含表达式树并且将由规划器相应地进行后处理; fdw_private不会。
fdw_scan_tlist是描述由FDW返回的扫描元组的内容的目标列表;如果扫描元组与外部表的声明行类型匹配,则可以为NIL,这对于简单的外部表扫描来说是正常情况。(如果计划节点表示外部联接,则需要fdw_scan_tlist,因为系统目录中没有可用的rowtype)
fdw_scan_tlist永远不会被执行;它只是持有描述扫描元组列中的内容的表达式树。
fdw_recheck_quals应该包含核心系统传递给FDW但是没有被添加到scan.plan.qual中的条件,也就是说,这些条件需要在FDW中做判断(这些条件是要在recheck中做判断的)。

typedef struct ForeignScan { Scan scan; Oid fs_server; /* OID of foreign server */ List *fdw_exprs; /* expressions that FDW may evaluate */ List *fdw_private; /* private data for FDW */ List *fdw_scan_tlist; /* optional tlist describing scan tuple */ List *fdw_recheck_quals; /* original quals not in scan.plan.qual */ Bitmapset *fs_relids; /* RTIs generated by this scan */ bool fsSystemCol; /* true if any "system column" is needed */ } ForeignScan;

还有一个数据结构也要特别关注,它保持了外部数据包装器处理程序返回函数,即它提供供PLANNER和EXECUTOR使用的回调函数的指针。

src/include/foreign/fdwapi.h typedef struct FdwRoutine

下面是ForeignScan的状态节点ForeignScanState,它在ScanState之外扩展了需要recheck的列表字段fdw_recheck_quals、外部数据包装器处理程序返回函数集合结构体FdwRoutine和外部数据包装器状态fdw_state。
在初始化时,ExecInitForeignScan函数除了做一般的初始化之外,还对ForeignScanState的fdwroutine字段做了初始化,获取函数指针和扫描关系表。

typedef struct ForeignScanState { ScanState ss; /* its first field is NodeTag */ List *fdw_recheck_quals; /* original quals not in ss.ps.qual */ /* use struct pointer to avoid including fdwapi.h here */ struct FdwRoutine *fdwroutine; void *fdw_state; /* foreign-data wrapper can keep state here */ } ForeignScanState;

ForeignScan节点的执行(ExecForeignScan 函数)通过将ForeignNext传递给 ExecScan函数处理来实现的。ForeignNext实际则是调用fdwroutine->IterateForeignScan在外部数据源上扫描每次获得一个元组。

关于函数ForeignRecheck,还记得上面说的fdw_recheck_quals字段么?这里调用ExecQual函数使用fdw_recheck_quals字段中的条件来做recheck。

最后,扫描结束后,调用fdwroutine->EndForeignScan关闭扫描,并且关闭外部表ExecCloseScanRelation(node->ss.ss_currentRelation)。

14.CustomScan节点

从Custom这个单词我们就可以知道,这是postgres开放的自定义Scan方法的接口。这个节点只提供了一个空壳子,我们看下:

typedef struct CustomScan { Scan scan; uint32 flags; /* mask of CUSTOMPATH_* flags, see relation.h */ List *custom_plans; /* list of Plan nodes, if any */ List *custom_exprs; /* expressions that custom code may evaluate */ List *custom_private; /* private data for custom code */ List *custom_scan_tlist; /* optional tlist describing scan * tuple */ Bitmapset *custom_relids; /* RTIs generated by this scan */ const CustomScanMethods *methods; } CustomScan;

留给用户自己去扩展,同时,CustomScanState状态节点也是一样,里面只有一些函数指针和预设的一些属性,你可以使用,也可以把CustomScanState作为你要扩展的Scan方法的State的一个属性,可以说还是很灵活的。

因此,不多说这个了,希望能在网上看到关于这方面做扩展的例子~

Scan节点就这么结束了。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzggxd.html