Implement ExplainForeignScan() for postgresql_fdw.
authorShigeru Hanada <[email protected]>
Thu, 24 Feb 2011 10:12:02 +0000 (19:12 +0900)
committerShigeru Hanada <[email protected]>
Thu, 24 Feb 2011 10:12:02 +0000 (19:12 +0900)
contrib/postgresql_fdw/expected/postgresql_fdw.out
contrib/postgresql_fdw/postgresql_fdw.c
contrib/postgresql_fdw/sql/postgresql_fdw.sql

index cedac5c1e9d81b841f8dacee91cfc7e30f9d5cfb..058627f9cc8f7fed45aed012bc7e52740f1eaf27 100644 (file)
@@ -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
index 20ecabfeaae4f5bb6eb9c4aa04b132b6a66bc499..7211ce4df96b0da3328b08c70d2a499c57f76220 100644 (file)
@@ -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;
index fe97ac5a925b93e64a3dcc666636eff89591f121..23edc534a086573d2d01caa960f8810f011cdb6a 100644 (file)
@@ -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;