From 0bbd1f5bde08d04b8ac49acdbc5319008f26458a Mon Sep 17 00:00:00 2001 From: Daniel Gustafsson Date: Fri, 8 Nov 2019 16:40:39 +0100 Subject: [PATCH 2/2] Provide a testcase for dumping foreign data --- src/test/modules/test_pg_dump/Makefile | 10 +- .../expected/test_pg_dump_fdw.out | 19 +++ .../test_pg_dump/sql/test_pg_dump_fdw.sql | 7 + src/test/modules/test_pg_dump/t/001_base.pl | 57 +++++++ .../test_pg_dump/test_pg_dump_fdw--1.0.sql | 9 + .../modules/test_pg_dump/test_pg_dump_fdw.c | 155 ++++++++++++++++++ .../test_pg_dump/test_pg_dump_fdw.control | 5 + 7 files changed, 257 insertions(+), 5 deletions(-) create mode 100644 src/test/modules/test_pg_dump/expected/test_pg_dump_fdw.out create mode 100644 src/test/modules/test_pg_dump/sql/test_pg_dump_fdw.sql create mode 100644 src/test/modules/test_pg_dump/test_pg_dump_fdw--1.0.sql create mode 100644 src/test/modules/test_pg_dump/test_pg_dump_fdw.c create mode 100644 src/test/modules/test_pg_dump/test_pg_dump_fdw.control diff --git a/src/test/modules/test_pg_dump/Makefile b/src/test/modules/test_pg_dump/Makefile index 6123b994f6..6f95a83b57 100644 --- a/src/test/modules/test_pg_dump/Makefile +++ b/src/test/modules/test_pg_dump/Makefile @@ -1,12 +1,12 @@ # src/test/modules/test_pg_dump/Makefile -MODULE = test_pg_dump -PGFILEDESC = "test_pg_dump - Test pg_dump with an extension" +MODULES = test_pg_dump_fdw +PGFILEDESC = "test_pg_dump - Test pg_dump with extensions" -EXTENSION = test_pg_dump -DATA = test_pg_dump--1.0.sql +EXTENSION = test_pg_dump_fdw test_pg_dump +DATA = test_pg_dump_fdw--1.0.sql test_pg_dump--1.0.sql -REGRESS = test_pg_dump +REGRESS = test_pg_dump test_pg_dump_fdw TAP_TESTS = 1 ifdef USE_PGXS diff --git a/src/test/modules/test_pg_dump/expected/test_pg_dump_fdw.out b/src/test/modules/test_pg_dump/expected/test_pg_dump_fdw.out new file mode 100644 index 0000000000..dc1b6267ee --- /dev/null +++ b/src/test/modules/test_pg_dump/expected/test_pg_dump_fdw.out @@ -0,0 +1,19 @@ +CREATE EXTENSION test_pg_dump_fdw; +CREATE SERVER pg_dump_fdw FOREIGN DATA WRAPPER test_pg_dump_fdw; +CREATE FOREIGN TABLE test_pg_dump_fdw_t (a INTEGER, b INTEGER) SERVER pg_dump_fdw; +SELECT * FROM test_pg_dump_fdw_t; + a | b +----+---- + 0 | 0 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 10 | 10 +(11 rows) + diff --git a/src/test/modules/test_pg_dump/sql/test_pg_dump_fdw.sql b/src/test/modules/test_pg_dump/sql/test_pg_dump_fdw.sql new file mode 100644 index 0000000000..06ad1d51a0 --- /dev/null +++ b/src/test/modules/test_pg_dump/sql/test_pg_dump_fdw.sql @@ -0,0 +1,7 @@ +CREATE EXTENSION test_pg_dump_fdw; + +CREATE SERVER pg_dump_fdw FOREIGN DATA WRAPPER test_pg_dump_fdw; + +CREATE FOREIGN TABLE test_pg_dump_fdw_t (a INTEGER, b INTEGER) SERVER pg_dump_fdw; + +SELECT * FROM test_pg_dump_fdw_t; diff --git a/src/test/modules/test_pg_dump/t/001_base.pl b/src/test/modules/test_pg_dump/t/001_base.pl index fb4ecf8aca..6c57d39a56 100644 --- a/src/test/modules/test_pg_dump/t/001_base.pl +++ b/src/test/modules/test_pg_dump/t/001_base.pl @@ -135,6 +135,13 @@ my %pgdump_runs = ( "$tempdir/defaults_tar_format.tar", ], }, + include_foreign_data => { + dump_cmd => [ + 'pg_dump', + '--include-foreign-data=test_pg_dump_fdw_server', + "--file=$tempdir/include_foreign_data.sql", + ], + }, pg_dumpall_globals => { dump_cmd => [ 'pg_dumpall', '--no-sync', @@ -220,6 +227,7 @@ my %full_runs = ( createdb => 1, defaults => 1, no_privs => 1, + include_foreign_data => 1, no_owner => 1,); my %tests = ( @@ -537,6 +545,55 @@ my %tests = ( schema_only => 1, section_pre_data => 1, }, + }, + + 'CREATE EXTENSION test_pg_dump_fdw' => { + create_order => 2, + create_sql => 'CREATE EXTENSION test_pg_dump_fdw;', + regexp => qr/^ + \QCREATE EXTENSION IF NOT EXISTS test_pg_dump_fdw WITH SCHEMA public;\E + \n/xm, + like => { + %full_runs, + include_foreign_data => 1, + schema_only => 1, + section_pre_data => 1, + }, + unlike => { binary_upgrade => 1, }, + }, + + 'CREATE SERVER test_pg_dump_fdw_server FOREIGN DATA WRAPPER test_pg_dump_fdw' => { + create_order => 3, + create_sql => 'CREATE SERVER test_pg_dump_fdw_server FOREIGN DATA WRAPPER test_pg_dump_fdw;', + regexp => qr/^ + \QCREATE SERVER test_pg_dump_fdw_server FOREIGN DATA WRAPPER test_pg_dump_fdw;\E + \n/xm, + like => { + %full_runs, + include_foreign_data => 1, + schema_only => 1, + section_pre_data => 1, + }, + }, + + 'include foreign data' => { + create_order => 9, + create_sql => 'CREATE FOREIGN TABLE t (a INTEGER, b INTEGER) SERVER test_pg_dump_fdw_server;', + regexp => qr/^ + \QCOPY public.t (a, b) FROM stdin;\E\n + \Q0 0\E\n + \Q1 1\E\n + \Q2 2\E\n + \Q3 3\E\n + \Q4 4\E\n + \Q5 5\E\n + \Q6 6\E\n + \Q7 7\E\n + \Q8 8\E\n + \Q9 9\E\n + \Q10 10\E\n + /xm, + like => { include_foreign_data => 1, }, },); ######################################### diff --git a/src/test/modules/test_pg_dump/test_pg_dump_fdw--1.0.sql b/src/test/modules/test_pg_dump/test_pg_dump_fdw--1.0.sql new file mode 100644 index 0000000000..88931393d0 --- /dev/null +++ b/src/test/modules/test_pg_dump/test_pg_dump_fdw--1.0.sql @@ -0,0 +1,9 @@ +\echo Use "CREATE EXTENSION test_pg_dump_fdw" to load this file. \quit + +CREATE FUNCTION test_pg_dump_fdw_handler() +RETURNS fdw_handler +AS 'MODULE_PATHNAME' +LANGUAGE C STRICT; + +CREATE FOREIGN DATA WRAPPER test_pg_dump_fdw +HANDLER test_pg_dump_fdw_handler; diff --git a/src/test/modules/test_pg_dump/test_pg_dump_fdw.c b/src/test/modules/test_pg_dump/test_pg_dump_fdw.c new file mode 100644 index 0000000000..72e4c01ea8 --- /dev/null +++ b/src/test/modules/test_pg_dump/test_pg_dump_fdw.c @@ -0,0 +1,155 @@ +#include "postgres.h" + +#include "catalog/pg_type.h" +#include "foreign/fdwapi.h" +#include "foreign/foreign.h" +#include "optimizer/pathnode.h" +#include "optimizer/planmain.h" +#include "optimizer/restrictinfo.h" + +static int curr_row = 0; + +PG_MODULE_MAGIC; + +PG_FUNCTION_INFO_V1(test_pg_dump_fdw_handler); + +static void dumptestGetForeignRelSize(PlannerInfo *root, + RelOptInfo *baserel, + Oid foreigntableid); +static void dumptestGetForeignPaths(PlannerInfo *root, + RelOptInfo *baserel, + Oid foreigntableid); +static ForeignScan * dumptestGetForeignPlan(PlannerInfo *root, + RelOptInfo *baserel, + Oid foreigntableid, + ForeignPath *best_path, + List *tlist, + List *scan_clauses, + Plan *outer_plan); +static void dumptestBeginForeignScan(ForeignScanState *node, + int eflags); +static TupleTableSlot * dumptestIterateForeignScan(ForeignScanState *node); +static void dumptestReScanForeignScan(ForeignScanState *node); +static void dumptestEndForeignScan(ForeignScanState *node); + +/* + * Handler function + */ +Datum +test_pg_dump_fdw_handler(PG_FUNCTION_ARGS) +{ + FdwRoutine *fdwroutine = makeNode(FdwRoutine); + + fdwroutine->GetForeignRelSize = dumptestGetForeignRelSize; + fdwroutine->GetForeignPaths = dumptestGetForeignPaths; + fdwroutine->GetForeignPlan = dumptestGetForeignPlan; + fdwroutine->BeginForeignScan = dumptestBeginForeignScan; + fdwroutine->IterateForeignScan = dumptestIterateForeignScan; + fdwroutine->ReScanForeignScan = dumptestReScanForeignScan; + fdwroutine->EndForeignScan = dumptestEndForeignScan; + + PG_RETURN_POINTER(fdwroutine); +} + +static void +dumptestGetForeignRelSize(PlannerInfo *root, + RelOptInfo *baserel, + Oid foreigntableid) +{ + baserel->rows = 1; +} + +static void +dumptestGetForeignPaths(PlannerInfo *root, + RelOptInfo *baserel, + Oid foreigntableid) +{ + add_path(baserel, (Path *) + create_foreignscan_path(root, baserel, + NULL /* default pathtarget */, + baserel->rows, + 1, + 1, + NIL, + baserel->lateral_relids, + NULL, + NIL)); +} + +static ForeignScan * +dumptestGetForeignPlan(PlannerInfo *root, + RelOptInfo *baserel, + Oid foreigntableid, + ForeignPath *best_path, + List *tlist, + List *scan_clauses, + Plan *outer_plan) +{ + scan_clauses = extract_actual_clauses(scan_clauses, false); + + return make_foreignscan(tlist, + scan_clauses, + baserel->relid, + NIL, + best_path->fdw_private, + NIL, + NIL, + outer_plan); +} + +static void +dumptestBeginForeignScan(ForeignScanState *node, int eflags) +{ + TupleDesc desc; + + desc = node->ss.ss_ScanTupleSlot->tts_tupleDescriptor; + + for (int i = 0; i < desc->natts; i++) + { + if (desc->attrs[i].atttypid != INT4OID) + ereport(ERROR, + (errcode(ERRCODE_FDW_INVALID_DATA_TYPE), + errmsg("test_pg_dump_fdw only supports INT4 columns"))); + } +} + +static TupleTableSlot * +dumptestIterateForeignScan(ForeignScanState *node) +{ + TupleTableSlot *slot; + TupleDesc desc; + + /* limit the testcase to contain 10 rows */ + if (curr_row > 10) + return NULL; + + slot = node->ss.ss_ScanTupleSlot; + desc = slot->tts_tupleDescriptor; + + ExecClearTuple(slot); + + for (int i = 0; i < desc->natts; i++) + { + slot->tts_isnull[i] = false; + slot->tts_values[i] = Int32GetDatum(curr_row); + } + + ExecStoreVirtualTuple(slot); + curr_row++; + + return slot; +} + +static void +dumptestReScanForeignScan(ForeignScanState *node) +{ + (void) node; + curr_row = 0; +} + +static void +dumptestEndForeignScan(ForeignScanState *node) +{ + (void) node; + curr_row = 0; +} diff --git a/src/test/modules/test_pg_dump/test_pg_dump_fdw.control b/src/test/modules/test_pg_dump/test_pg_dump_fdw.control new file mode 100644 index 0000000000..cc4a37c441 --- /dev/null +++ b/src/test/modules/test_pg_dump/test_pg_dump_fdw.control @@ -0,0 +1,5 @@ +# test_pg_dump_fdw +comment = 'hardcoded foreign-data wrapper for testing dumping foreign data' +default_version = '1.0' +module_pathname = '$libdir/test_pg_dump_fdw' +relocatable = true -- 2.21.0 (Apple Git-122.2)