From: Shigeru Hanada Date: Thu, 24 Feb 2011 10:12:02 +0000 (+0900) Subject: Implement ExplainForeignScan() for postgresql_fdw. X-Git-Url: http://git.postgresql.org/gitweb/static/gitweb.js?a=commitdiff_plain;h=0dcbc9ed414d349985ad9eb23129f3157eea3c77;p=users%2Fhanada%2Fpostgres.git Implement ExplainForeignScan() for postgresql_fdw. --- diff --git a/contrib/postgresql_fdw/expected/postgresql_fdw.out b/contrib/postgresql_fdw/expected/postgresql_fdw.out index cedac5c1e9..058627f9cc 100644 --- a/contrib/postgresql_fdw/expected/postgresql_fdw.out +++ b/contrib/postgresql_fdw/expected/postgresql_fdw.out @@ -8,6 +8,7 @@ SET DATESTYLE = 'Postgres, MDY'; -- install postgresql_fdw module SET client_min_messages = warning; \set ECHO none +RESET client_min_messages; -- define fdw-related objects CREATE SERVER loopback1 FOREIGN DATA WRAPPER postgresql_fdw OPTIONS (dbname 'contrib_regression'); @@ -102,15 +103,20 @@ SELECT * FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY 1,2,3,4,5,6; (3 rows) -- WHERE clause push-down -set client_min_messages = debug1; -SELECT * FROM ft1 WHERE c1 = 1 AND c2 = lower('FOO') AND c3 < now(); -DEBUG: deparsed SQL is "SELECT C1, c2, c3 FROM public.t1 WHERE ((c1 = 1) AND (c2 = 'foo'::text))" +SELECT * FROM ft1 WHERE c1 = 1 AND c2 = lower('FOO') AND c3 < now() and c3 < clock_timestamp(); c1 | c2 | c3 ----+-----+------------ 1 | foo | 01-01-1970 (1 row) -reset client_min_messages; +EXPLAIN (COSTS FALSE) SELECT * FROM ft1 WHERE c1 = 1 AND c2 = lower('FOO') AND c3 < now() and c3 < clock_timestamp(); + QUERY PLAN +--------------------------------------------------------------------------------------------------------- + Foreign Scan on ft1 + Filter: (c3 < clock_timestamp()) + Remote SQL: SELECT c1, c2, c3 FROM public.t1 WHERE ((c3 < now()) AND (c1 = 1) AND (c2 = 'foo'::text)) +(3 rows) + -- clean up DROP FOREIGN DATA WRAPPER postgresql_fdw CASCADE; NOTICE: drop cascades to 6 other objects diff --git a/contrib/postgresql_fdw/postgresql_fdw.c b/contrib/postgresql_fdw/postgresql_fdw.c index 20ecabfeaa..7211ce4df9 100644 --- a/contrib/postgresql_fdw/postgresql_fdw.c +++ b/contrib/postgresql_fdw/postgresql_fdw.c @@ -15,6 +15,7 @@ #include "catalog/pg_namespace.h" #include "catalog/pg_operator.h" #include "catalog/pg_proc.h" +#include "commands/explain.h" #include "foreign/fdwapi.h" #include "foreign/foreign.h" #include "funcapi.h" @@ -82,12 +83,12 @@ static void cleanup_connection(ResourceReleasePhase phase, /* * PostgreSQL specific portion of a foreign query request */ -typedef struct PgsqlFdwExecutionState +typedef struct pgFdwExecutionState { PGconn *conn; /* connection used for the scan */ PGresult *res; /* result of the scan, held until the scan ends */ int nextrow; /* row index to be returned in next fetch */ -} PgsqlFdwExecutionState; +} pgFdwExecutionState; /* @@ -135,6 +136,12 @@ pgPlanForeignScan(Oid foreigntableid, PlannerInfo *root, RelOptInfo *baserel) static void pgExplainForeignScan(ForeignScanState *node, struct ExplainState *es) { + FdwPlan *fdwplan; + char *sql; + + fdwplan = ((ForeignScan *) node->ss.ps.plan)->fdwplan; + sql = strVal(list_nth(fdwplan->fdw_private, 0)); + ExplainPropertyText("Remote SQL", sql, es); } /* @@ -483,7 +490,7 @@ deparseSql(Oid foreigntableid, PlannerInfo *root, RelOptInfo *baserel) static void pgBeginForeignScan(ForeignScanState *node, int eflags) { - PgsqlFdwExecutionState *festate; + pgFdwExecutionState *festate; Oid relid; ForeignTable *table; @@ -507,7 +514,7 @@ pgBeginForeignScan(ForeignScanState *node, int eflags) if (eflags & EXEC_FLAG_EXPLAIN_ONLY) return; - festate = palloc(sizeof(PgsqlFdwExecutionState)); + festate = palloc(sizeof(pgFdwExecutionState)); /* Get connection to external PostgreSQL server. */ relid = RelationGetRelid(node->ss.ss_currentRelation); @@ -598,7 +605,7 @@ static TupleTableSlot * pgIterateForeignScan(ForeignScanState *node) { TupleTableSlot *slot = node->ss.ss_ScanTupleSlot; - PgsqlFdwExecutionState *festate = (PgsqlFdwExecutionState *) node->fdw_state; + pgFdwExecutionState *festate = (pgFdwExecutionState *) node->fdw_state; elog(DEBUG3, "%s() called", __FUNCTION__); @@ -613,13 +620,13 @@ pgIterateForeignScan(ForeignScanState *node) static void pgReScanForeignScan(ForeignScanState *node) { - ((PgsqlFdwExecutionState *) node->fdw_state)->nextrow = 0; + ((pgFdwExecutionState *) node->fdw_state)->nextrow = 0; } static void pgEndForeignScan(ForeignScanState *node) { - PgsqlFdwExecutionState *festate = (PgsqlFdwExecutionState *) node->fdw_state; + pgFdwExecutionState *festate = (pgFdwExecutionState *) node->fdw_state; if (festate == NULL) return; diff --git a/contrib/postgresql_fdw/sql/postgresql_fdw.sql b/contrib/postgresql_fdw/sql/postgresql_fdw.sql index fe97ac5a92..23edc534a0 100644 --- a/contrib/postgresql_fdw/sql/postgresql_fdw.sql +++ b/contrib/postgresql_fdw/sql/postgresql_fdw.sql @@ -12,6 +12,7 @@ SET client_min_messages = warning; \set ECHO none \i postgresql_fdw.sql \set ECHO all +RESET client_min_messages; -- define fdw-related objects CREATE SERVER loopback1 FOREIGN DATA WRAPPER postgresql_fdw @@ -76,9 +77,8 @@ SELECT * FROM ft1 t1 JOIN ft1 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1; -- outer join SELECT * FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY 1,2,3,4,5,6; -- WHERE clause push-down -set client_min_messages = debug1; -SELECT * FROM ft1 WHERE c1 = 1 AND c2 = lower('FOO') AND c3 < now(); -reset client_min_messages; +SELECT * FROM ft1 WHERE c1 = 1 AND c2 = lower('FOO') AND c3 < now() and c3 < clock_timestamp(); +EXPLAIN (COSTS FALSE) SELECT * FROM ft1 WHERE c1 = 1 AND c2 = lower('FOO') AND c3 < now() and c3 < clock_timestamp(); -- clean up DROP FOREIGN DATA WRAPPER postgresql_fdw CASCADE;