目录
引
研究fdw insert接口调用,找到哪些接口被调用,以及它们的调用时机,作用,参数。在了解这些之后,可以考虑自己实现FDW接口函数,接入到其他数据库。
后面的函数说明并没有完全照搬官方文档,按照自己的理解写出来的,所以会有理解错误,欢迎指正。
研究方法
GDB跟踪 + 源码 + 官方文档
设置postgre_fdw所有接口实现函数为断点,执行单条插入和多条插入,获得接口调用流程。
后面堆栈查看和代码阅读等略过。
GDB跟踪
断点设置
Make breakpoint pending on future shared library load? (y or [n]) Breakpoint 1 (postgresGetForeignRelSize) pending.
(gdb) b postgresGetForeignPaths
Function "postgresGetForeignPaths" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (postgresGetForeignPaths) pending.
(gdb) b postgresGetForeignPlan
Function "postgresGetForeignPlan" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 3 (postgresGetForeignPlan) pending.
(gdb) b postgresBeginForeignScan
Function "postgresBeginForeignScan" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 4 (postgresBeginForeignScan) pending.
(gdb) b postgresIterateForeignScan
Function "postgresIterateForeignScan" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 5 (postgresIterateForeignScan) pending.
(gdb) b postgresReScanForeignScan
Function "postgresReScanForeignScan" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 6 (postgresReScanForeignScan) pending.
(gdb) b postgresEndForeignScan
Function "postgresEndForeignScan" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 7 (postgresEndForeignScan) pending.
(gdb) b postgresAddForeignUpdateTargets
Function "postgresAddForeignUpdateTargets" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 8 (postgresAddForeignUpdateTargets) pending.
(gdb) b postgresPlanForeignModify
Function "postgresPlanForeignModify" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 9 (postgresPlanForeignModify) pending.
(gdb) b postgresBeginForeignModify
Function "postgresBeginForeignModify" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 10 (postgresBeginForeignModify) pending.
(gdb) b postgresExecForeignInsert
Function "postgresExecForeignInsert" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 11 (postgresExecForeignInsert) pending.
(gdb) b postgresExecForeignUpdate
Function "postgresExecForeignUpdate" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 12 (postgresExecForeignUpdate) pending.
(gdb) b postgresExecForeignDelete
Function "postgresExecForeignDelete" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 13 (postgresExecForeignDelete) pending.
(gdb) b postgresEndForeignModify
Function "postgresEndForeignModify" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 14 (postgresEndForeignModify) pending.
(gdb) b postgresIsForeignRelUpdatable
Function "postgresIsForeignRelUpdatable" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 15 (postgresIsForeignRelUpdatable) pending.
(gdb) b postgresPlanDirectModify
Function "postgresPlanDirectModify" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 16 (postgresPlanDirectModify) pending.
(gdb) b postgresBeginDirectModify
Function "postgresBeginDirectModify" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 17 (postgresBeginDirectModify) pending.
(gdb) b postgresIterateDirectModify
Function "postgresIterateDirectModify" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 18 (postgresIterateDirectModify) pending.
(gdb) b postgresEndDirectModify
Function "postgresEndDirectModify" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 19 (postgresEndDirectModify) pending.
(gdb) b postgresRecheckForeignScan
Function "postgresRecheckForeignScan" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 20 (postgresRecheckForeignScan) pending.
(gdb) b postgresExplainForeignScan
Function "postgresExplainForeignScan" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 21 (postgresExplainForeignScan) pending.
(gdb) b postgresExplainForeignModify
Function "postgresExplainForeignModify" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 22 (postgresExplainForeignModify) pending.
(gdb) b postgresExplainDirectModify
Function "postgresExplainDirectModify" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 23 (postgresExplainDirectModify) pending.
(gdb) b postgresAnalyzeForeignTable
Function "postgresAnalyzeForeignTable" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 24 (postgresAnalyzeForeignTable) pending.
(gdb) b postgresImportForeignSchema
Function "postgresImportForeignSchema" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 25 (postgresImportForeignSchema) pending.
(gdb) b postgresGetForeignJoinPaths
Function "postgresGetForeignJoinPaths" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 26 (postgresGetForeignJoinPaths) pending.
(gdb) b postgresGetForeignUpperPaths
Function "postgresGetForeignUpperPaths" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
单条插入
postgres=# \d+ xxfdw
Foreign table "public.xxfdw"
Column | Type | Collation | Nullable | Default | FDW options | Storage | Stats target | Description
--------+---------+-----------+----------+---------+-------------+----------+--------------+-------------
id | integer | | | | | plain | |
name | text | | | | | extended | |
Server: server127
FDW options: (schema_name 'public', table_name 'xx')
insert into xxfdw values (20, 'abc');
Breakpoint 16, 0x00007f0fc8966fa0 in postgresPlanDirectModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 9, 0x00007f0fc8967630 in postgresPlanForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 15, 0x00007f0fc89655f0 in postgresIsForeignRelUpdatable () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 10, 0x00007f0fc8967370 in postgresBeginForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 11, 0x00007f0fc89693b0 in postgresExecForeignInsert () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 14, 0x00007f0fc8965960 in postgresEndForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
多条插入
用JDBC实现多条插入,源码如下
public void loadDataPGfdw(int seq) throws SQLException {
Connection conn = null;
try {
url = "jdbc:postgresql://192.168.55.60:5432/postgres";
usr = "postgres";
psd = "postgres";
Class.forName("org.postgresql.Driver");
System.out.println("Write to PG fdw");
conn = DriverManager.getConnection(url, usr, psd);
conn.setAutoCommit(false);
Statement st = conn.createStatement();
String table = "xxfdw";
String sql = "insert into " + table+ "(id, name) values(?,?)";
Date startTime = new Date();
try(PreparedStatement pStatement = conn.prepareStatement(sql);) {
int rows = 0;
int batchCount = 0;
while(rows++ < 10) {
//写一行
pStatement.setInt(1, rows);
total_bytes += 4;
pStatement.setInt(1, rows);
pStatement.setString(2, "a");
pStatement.addBatch();
batchCount++;
//批量提交
if (batchCount== 10) {
Thread.sleep(1000*30);
pStatement.executeBatch();
conn.commit();
batchCount = 0;
System.out.println("commit batch");
}
}
if (batchCount>0) {
pStatement.executeBatch();
}
st.close();
conn.close();
}
Date endTime = new Date();
System.out.printf("Insert complete, interval=%d\n", endTime.getTime() - startTime.getTime());
} catch (Exception e) {
e.printStackTrace();
} finally {
if(conn != null) {
conn.close();
}
}
}
断点跟踪,循环执行这6个接口,完成多行插入。
Breakpoint 27 (postgresGetForeignUpperPaths) pending.
(gdb) c
Continuing.
Breakpoint 16, 0x00007f0fc8966fa0 in postgresPlanDirectModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 9, 0x00007f0fc8967630 in postgresPlanForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 15, 0x00007f0fc89655f0 in postgresIsForeignRelUpdatable () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 10, 0x00007f0fc8967370 in postgresBeginForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 11, 0x00007f0fc89693b0 in postgresExecForeignInsert () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 14, 0x00007f0fc8965960 in postgresEndForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 16, 0x00007f0fc8966fa0 in postgresPlanDirectModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 9, 0x00007f0fc8967630 in postgresPlanForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 15, 0x00007f0fc89655f0 in postgresIsForeignRelUpdatable () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 10, 0x00007f0fc8967370 in postgresBeginForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 11, 0x00007f0fc89693b0 in postgresExecForeignInsert () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 14, 0x00007f0fc8965960 in postgresEndForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 16, 0x00007f0fc8966fa0 in postgresPlanDirectModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 9, 0x00007f0fc8967630 in postgresPlanForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 15, 0x00007f0fc89655f0 in postgresIsForeignRelUpdatable () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 10, 0x00007f0fc8967370 in postgresBeginForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 11, 0x00007f0fc89693b0 in postgresExecForeignInsert () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 14, 0x00007f0fc8965960 in postgresEndForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 16, 0x00007f0fc8966fa0 in postgresPlanDirectModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 9, 0x00007f0fc8967630 in postgresPlanForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 15, 0x00007f0fc89655f0 in postgresIsForeignRelUpdatable () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 10, 0x00007f0fc8967370 in postgresBeginForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 11, 0x00007f0fc89693b0 in postgresExecForeignInsert () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
Breakpoint 14, 0x00007f0fc8965960 in postgresEndForeignModify () from /usr/local/postgresql/lib/postgres_fdw.so
(gdb) c
Continuing.
...
FDW写入接口说明
接口调用顺序
PlanDirectModify、PlanForeignModify在生成计划树时调用
后4个接口在执行计划树时调用
在Batch insert的时候,每一行都是按照这个顺序6个接口依次执行。
在实际接口实现时,外部数据库连接只在BeginForeignModify 中创建一次,再不关闭,保持长连接。后续的执行不需要重新建立连接。
也就是说,在接下来的insert操作中,只有ExecForeignInsert会访问外部数据库,其他接口都属于内部操作。
FDW insert接口实现考量
PlanDirectModify, 不需要实现,只需要返回false即可。因为这个只针对update和delete.
PlanForeignModify, 需要针对对外部表的目标重写sql语句,记录insert 列的属性
IsForeignRelUpdatable, 设定可insert即可。
BeginForeignModify, 这里要实现对外部数据库的连接;申请资源;
ExecForeignInsert, 实现对外部数据库表的插入
EndForeignModify, 释放在BeginForignModify和ExecForeignInsert中申请的资源