Add HANDLER function support to FOREIGN DATA WRAPPER. fdw_handler
authorShigeru Hanada <[email protected]>
Mon, 7 Feb 2011 04:55:40 +0000 (13:55 +0900)
committerShigeru Hanada <[email protected]>
Tue, 8 Feb 2011 08:48:05 +0000 (17:48 +0900)
20 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
doc/src/sgml/ref/create_foreign_data_wrapper.sgml
src/backend/commands/foreigncmds.c
src/backend/foreign/foreign.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/utils/adt/pseudotypes.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/bin/psql/describe.c
src/include/catalog/pg_foreign_data_wrapper.h
src/include/catalog/pg_proc.h
src/include/catalog/pg_type.h
src/include/foreign/foreign.h
src/include/nodes/parsenodes.h
src/include/utils/builtins.h
src/test/regress/expected/foreign_data.out
src/test/regress/sql/foreign_data.sql

index be132f2eb7b0ba610f74e96789a7314acb5e87ca..f4cb8857a77daa4992483365212f7d25fc3e5509 100644 (file)
       </entry>
      </row>
 
+     <row>
+      <entry><structfield>fdwhandler</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
+      <entry>
+       References a handler function that is responsible for
+       supplying foreign-data wrapper routines.
+       Zero if no handler is provided.
+      </entry>
+     </row>
+
      <row>
       <entry><structfield>fdwacl</structfield></entry>
       <entry><type>aclitem[]</type></entry>
index 4e9e8a2e28a323557c2da07ce1c50eda0f0f64c4..7e17ef3e236329847ed1891966defde18e801acf 100644 (file)
@@ -23,6 +23,7 @@ PostgreSQL documentation
 <synopsis>
 ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
     [ VALIDATOR <replaceable class="parameter">valfunction</replaceable> | NO VALIDATOR ]
+    [ HANDLER <replaceable class="parameter">handler</replaceable> | NO HANDLER ]
     [ OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ]) ]
 ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
 </synopsis>
@@ -85,6 +86,29 @@ ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWN
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>HANDLER <replaceable class="parameter">handler</replaceable></literal></term>
+    <listitem>
+     <para>
+      Specifies a new foreign-data wrapper handler function.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><literal>NO HANDLER</literal></term>
+    <listitem>
+     <para>
+      This is used to specify that the foreign-data wrapper should no
+      longer have a handler function.
+     </para>
+     <para>
+      Note that foreign tables which uses a foreign-data wrapper with no
+      handler can't be used in a SELECT statement.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
     <listitem>
@@ -127,8 +151,8 @@ ALTER FOREIGN DATA WRAPPER dbi VALIDATOR bob.myvalidator;
   <para>
    <command>ALTER FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
    9075-9 (SQL/MED).  The standard does not specify the <literal>
-   VALIDATOR</literal> and <literal>OWNER TO</> variants of the
-   command.
+   VALIDATOR</literal>, <literal>HANDLER</> and <literal>OWNER TO</>
+   variants of the command.
   </para>
  </refsect1>
 
index f626d56665b25722987107b8c6effb6ca0657de1..d70321ba7726b22c7afcff4fd5910363c58d3e28 100644 (file)
@@ -23,6 +23,7 @@ PostgreSQL documentation
 <synopsis>
 CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
     [ VALIDATOR <replaceable class="parameter">valfunction</replaceable> | NO VALIDATOR ]
+    [ HANDLER <replaceable class="parameter">handler</replaceable> | NO HANDLER ]
     [ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ]
 </synopsis>
  </refsynopsisdiv>
@@ -81,6 +82,19 @@ CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>HANDLER <replaceable class="parameter">handler</replaceable></literal></term>
+    <listitem>
+     <para>
+      <replaceable class="parameter">handler</replaceable> is the
+      name of a previously registered function that will be called to
+      retrieve a set of functions for foreign tables.
+      The handler function must take no arguments.
+      The return type must be <type>fdw_handler</type>.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] )</literal></term>
     <listitem>
@@ -151,8 +165,8 @@ CREATE FOREIGN DATA WRAPPER mywrapper
 
   <para>
    <command>CREATE FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
-   9075-9 (SQL/MED), with the exception that
-   the <literal>VALIDATOR</literal> clause is an extension and the
+   9075-9 (SQL/MED), with the exception that the <literal>VALIDATOR</literal>
+   and <literal>HANDLER</literal> clauses are extensions and the
    clauses <literal>LIBRARY</literal> and <literal>LANGUAGE</literal>
    are not yet implemented in PostgreSQL.
   </para>
index 3a0ea9a632395544f0714976b9441d9815c06301..e9248f64c032576186915da75f4d5d5c4017766c 100644 (file)
@@ -317,16 +317,69 @@ AlterForeignServerOwner(const char *name, Oid newOwnerId)
  * Convert a validator function name passed from the parser to an Oid.
  */
 static Oid
-lookup_fdw_validator_func(List *validator)
+lookup_fdw_validator_func(DefElem *validator)
 {
    Oid         funcargtypes[2];
 
+   if (validator == NULL || validator->arg == NULL)
+       return InvalidOid;
+
    funcargtypes[0] = TEXTARRAYOID;
    funcargtypes[1] = OIDOID;
-   return LookupFuncName(validator, 2, funcargtypes, false);
+   return LookupFuncName((List *) validator->arg, 2, funcargtypes, false);
    /* return value is ignored, so we don't check the type */
 }
 
+static Oid
+lookup_fdw_handler_func(DefElem *handler)
+{
+   Oid handlerOid;
+
+   if (handler == NULL || handler->arg == NULL)
+       return InvalidOid;
+
+   /* check that handler have correct return type */
+   handlerOid = LookupFuncName((List *) handler->arg, 0, NULL, false);
+   if (get_func_rettype(handlerOid) != FDW_HANDLEROID)
+   {
+       ereport(ERROR,
+           (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+            errmsg("function %s must return type \"fdw_handler\"",
+               NameListToString((List *) handler->arg))));
+   }
+
+   return handlerOid;
+}
+
+static void
+parse_func_options(List *func_options, DefElem **validator, DefElem **handler)
+{
+   ListCell       *cell;
+
+   *validator = NULL;
+   *handler = NULL;
+   foreach (cell, func_options)
+   {
+       DefElem    *def = lfirst(cell);
+
+       if (pg_strcasecmp(def->defname, "validator") == 0)
+       {
+           if (*validator)
+               ereport(ERROR, (errmsg("duplicated VALIDATOR")));
+           *validator = def;
+       }
+       else if (pg_strcasecmp(def->defname, "handler") == 0)
+       {
+           if (*handler)
+               ereport(ERROR, (errmsg("duplicated HANDLER")));
+           *handler = def;
+       }
+       else
+       {
+           ereport(ERROR, (errmsg("invalid option")));
+       }
+   }
+}
 
 /*
  * Create a foreign-data wrapper
@@ -339,7 +392,10 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
    bool        nulls[Natts_pg_foreign_data_wrapper];
    HeapTuple   tuple;
    Oid         fdwId;
+   DefElem    *defvalidator;
+   DefElem    *defhandler;
    Oid         fdwvalidator;
+   Oid         fdwhandler;
    Datum       fdwoptions;
    Oid         ownerId;
 
@@ -375,12 +431,13 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
        DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname));
    values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
 
-   if (stmt->validator)
-       fdwvalidator = lookup_fdw_validator_func(stmt->validator);
-   else
-       fdwvalidator = InvalidOid;
+   /* determine which validator to be used (or not used at all) */
+   parse_func_options(stmt->func_options, &defvalidator, &defhandler);
+   fdwvalidator = lookup_fdw_validator_func(defvalidator);
+   fdwhandler = lookup_fdw_handler_func(defhandler);
 
    values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = fdwvalidator;
+   values[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = fdwhandler;
 
    nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
 
@@ -416,6 +473,21 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
        recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
    }
 
+   if (fdwhandler != InvalidOid)
+   {
+       ObjectAddress myself;
+       ObjectAddress referenced;
+
+       myself.classId = ForeignDataWrapperRelationId;
+       myself.objectId = fdwId;
+       myself.objectSubId = 0;
+
+       referenced.classId = ProcedureRelationId;
+       referenced.objectId = fdwhandler;
+       referenced.objectSubId = 0;
+       recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+   }
+
    recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId);
 
    /* Post creation hook for new foreign data wrapper */
@@ -440,7 +512,10 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
    Oid         fdwId;
    bool        isnull;
    Datum       datum;
+   DefElem    *defvalidator;
+   DefElem    *defhandler;
    Oid         fdwvalidator;
+   Oid         fdwhandler;
 
    /* Must be super user */
    if (!superuser())
@@ -464,9 +539,11 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
    memset(repl_null, false, sizeof(repl_null));
    memset(repl_repl, false, sizeof(repl_repl));
 
-   if (stmt->change_validator)
+   parse_func_options(stmt->func_options, &defvalidator, &defhandler);
+
+   if (defvalidator)
    {
-       fdwvalidator = stmt->validator ? lookup_fdw_validator_func(stmt->validator) : InvalidOid;
+       fdwvalidator = lookup_fdw_validator_func(defvalidator);
        repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
        repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = true;
 
@@ -474,7 +551,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
         * It could be that the options for the FDW, SERVER and USER MAPPING
         * are no longer valid with the new validator.  Warn about this.
         */
-       if (stmt->validator)
+       if (defvalidator->arg)
            ereport(WARNING,
             (errmsg("changing the foreign-data wrapper validator can cause "
                     "the options for dependent objects to become invalid")));
@@ -492,6 +569,34 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
        fdwvalidator = DatumGetObjectId(datum);
    }
 
+   if (defhandler)
+   {
+       fdwhandler = lookup_fdw_handler_func(defhandler);
+       repl_val[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
+       repl_repl[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = true;
+
+       /*
+        * It could be that the behavior of accessing foreign table changes
+        * with the new handler.  Warn about this.
+        */
+       if (defhandler->arg)
+           ereport(WARNING,
+            (errmsg("changing the foreign-data wrapper handler would change "
+                    "the behavior of accessing foreign tables")));
+   }
+   else
+   {
+       /*
+        * Validator is not changed, but we need it for validating options.
+        */
+       datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
+                               tp,
+                               Anum_pg_foreign_data_wrapper_fdwhandler,
+                               &isnull);
+       Assert(!isnull);
+       fdwhandler = DatumGetObjectId(datum);
+   }
+
    /*
     * Options specified, validate and update.
     */
index 6cfddf317a7391895bbf2a968778657ca77aa222..a708efa6670693b4a8cd37daf9837751e33e69f3 100644 (file)
@@ -60,6 +60,7 @@ GetForeignDataWrapper(Oid fdwid)
    fdw->owner = fdwform->fdwowner;
    fdw->fdwname = pstrdup(NameStr(fdwform->fdwname));
    fdw->fdwvalidator = fdwform->fdwvalidator;
+   fdw->fdwhandler = fdwform->fdwhandler;
 
    /* Extract the options */
    datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
index 662916d2108438cde39c90708b6d1623e7b2a6ca..33782a5b9e3830b705b3da723179d175c875cce9 100644 (file)
@@ -3202,7 +3202,7 @@ _copyCreateFdwStmt(CreateFdwStmt *from)
    CreateFdwStmt *newnode = makeNode(CreateFdwStmt);
 
    COPY_STRING_FIELD(fdwname);
-   COPY_NODE_FIELD(validator);
+   COPY_NODE_FIELD(func_options);
    COPY_NODE_FIELD(options);
 
    return newnode;
@@ -3214,8 +3214,7 @@ _copyAlterFdwStmt(AlterFdwStmt *from)
    AlterFdwStmt *newnode = makeNode(AlterFdwStmt);
 
    COPY_STRING_FIELD(fdwname);
-   COPY_NODE_FIELD(validator);
-   COPY_SCALAR_FIELD(change_validator);
+   COPY_NODE_FIELD(func_options);
    COPY_NODE_FIELD(options);
 
    return newnode;
index b7dc450447367e395b2fdfdbc328476a5a912bed..26df9acd6b6dc75843cf9226d914066528aafa6b 100644 (file)
@@ -1629,7 +1629,7 @@ static bool
 _equalCreateFdwStmt(CreateFdwStmt *a, CreateFdwStmt *b)
 {
    COMPARE_STRING_FIELD(fdwname);
-   COMPARE_NODE_FIELD(validator);
+   COMPARE_NODE_FIELD(func_options);
    COMPARE_NODE_FIELD(options);
 
    return true;
@@ -1639,8 +1639,7 @@ static bool
 _equalAlterFdwStmt(AlterFdwStmt *a, AlterFdwStmt *b)
 {
    COMPARE_STRING_FIELD(fdwname);
-   COMPARE_NODE_FIELD(validator);
-   COMPARE_SCALAR_FIELD(change_validator);
+   COMPARE_NODE_FIELD(func_options);
    COMPARE_NODE_FIELD(options);
 
    return true;
index 21782824ca1cdb7d2b64cfeb4180374f4bb5e66f..9e0c148ad4484c624a9b0bff0998a275c2226bd8 100644 (file)
@@ -306,6 +306,9 @@ static RangeVar *makeRangeVarFromAnyName(List *names, int position, core_yyscan_
                create_generic_options alter_generic_options
                relation_expr_list dostmt_opt_list
 
+%type <list>   opt_func_options func_options
+%type <defelt> fdw_option
+
 %type <range>  OptTempTableName
 %type <into>   into_clause create_as_target
 
@@ -3196,16 +3199,33 @@ DropTableSpaceStmt: DROP TABLESPACE name
  *
  *****************************************************************************/
 
-CreateFdwStmt: CREATE FOREIGN DATA_P WRAPPER name opt_validator create_generic_options
+CreateFdwStmt: CREATE FOREIGN DATA_P WRAPPER name opt_func_options create_generic_options
                {
                    CreateFdwStmt *n = makeNode(CreateFdwStmt);
                    n->fdwname = $5;
-                   n->validator = $6;
+                   n->func_options = $6;
                    n->options = $7;
                    $$ = (Node *) n;
                }
        ;
 
+fdw_option:
+           VALIDATOR handler_name              { $$ = makeDefElem("validator", (Node *)$2); }
+           | NO VALIDATOR                      { $$ = makeDefElem("validator", NULL); }
+           | HANDLER handler_name              { $$ = makeDefElem("handler", (Node *)$2); }
+           | NO HANDLER                        { $$ = makeDefElem("handler", NULL); }
+       ;
+
+func_options:
+           fdw_option                          { $$ = list_make1($1); }
+           | func_options fdw_option           { $$ = lappend($1, $2); }
+       ;
+
+opt_func_options:
+           func_options                        { $$ = $1; }
+           | /*EMPTY*/                         { $$ = NIL; }
+       ;
+
 /*****************************************************************************
  *
  *         QUERY :
@@ -3238,28 +3258,20 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
  *
  ****************************************************************************/
 
-AlterFdwStmt: ALTER FOREIGN DATA_P WRAPPER name validator_clause alter_generic_options
+AlterFdwStmt: ALTER FOREIGN DATA_P WRAPPER name opt_func_options alter_generic_options
                {
                    AlterFdwStmt *n = makeNode(AlterFdwStmt);
                    n->fdwname = $5;
-                   n->validator = $6;
-                   n->change_validator = true;
+                   n->func_options = $6;
                    n->options = $7;
                    $$ = (Node *) n;
                }
-           | ALTER FOREIGN DATA_P WRAPPER name validator_clause
+           | ALTER FOREIGN DATA_P WRAPPER name func_options
                {
                    AlterFdwStmt *n = makeNode(AlterFdwStmt);
                    n->fdwname = $5;
-                   n->validator = $6;
-                   n->change_validator = true;
-                   $$ = (Node *) n;
-               }
-           | ALTER FOREIGN DATA_P WRAPPER name alter_generic_options
-               {
-                   AlterFdwStmt *n = makeNode(AlterFdwStmt);
-                   n->fdwname = $5;
-                   n->options = $6;
+                   n->func_options = $6;
+                   n->options = NIL;
                    $$ = (Node *) n;
                }
        ;
index 2be0696f6093890fffdb4cd49d9b6bc487c1bfab..779844d16121a3e66c4cf56b2478c23919800416 100644 (file)
@@ -453,3 +453,29 @@ pg_node_tree_send(PG_FUNCTION_ARGS)
 {
    return textsend(fcinfo);
 }
+
+/*
+ * fdw_handler_in      - input routine for pseudo-type FDW_HANDLER.
+ */
+Datum
+fdw_handler_in(PG_FUNCTION_ARGS)
+{
+   ereport(ERROR,
+           (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+            errmsg("cannot accept a value of type fdw_handler")));
+
+   PG_RETURN_VOID();           /* keep compiler quiet */
+}
+
+/*
+ * fdw_handler_out     - output routine for pseudo-type FDW_HANDLER.
+ */
+Datum
+fdw_handler_out(PG_FUNCTION_ARGS)
+{
+   ereport(ERROR,
+           (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+            errmsg("cannot display a value of type fdw_handler")));
+
+   PG_RETURN_VOID();           /* keep compiler quiet */
+}
index d3eb7662880b3dda57f052d7fbbd22392a8cb562..8baf79f1c66c0dd9caf0ac49053a7e232bd05465 100644 (file)
@@ -5985,6 +5985,7 @@ getForeignDataWrappers(int *numForeignDataWrappers)
    int         i_fdwname;
    int         i_rolname;
    int         i_fdwvalidator;
+   int         i_fdwhandler;
    int         i_fdwacl;
    int         i_fdwoptions;
 
@@ -5998,13 +5999,27 @@ getForeignDataWrappers(int *numForeignDataWrappers)
    /* Make sure we are in proper schema */
    selectSourceSchema("pg_catalog");
 
-   appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
-       "(%s fdwowner) AS rolname, fdwvalidator::pg_catalog.regproc, fdwacl,"
-                     "array_to_string(ARRAY("
-        "      SELECT option_name || ' ' || quote_literal(option_value) "
-      "        FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
-                     "FROM pg_foreign_data_wrapper",
-                     username_subquery);
+   if (g_fout->remoteVersion >= 90100)
+   {
+       appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
+           "(%s fdwowner) AS rolname, fdwvalidator::pg_catalog.regproc, "
+           "fdwhandler::pg_catalog.regproc, fdwacl,"
+                         "array_to_string(ARRAY("
+            "      SELECT option_name || ' ' || quote_literal(option_value) "
+          "        FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
+                         "FROM pg_foreign_data_wrapper",
+                         username_subquery);
+   }
+   else
+   {
+       appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
+           "(%s fdwowner) AS rolname, fdwvalidator::pg_catalog.regproc, fdwacl,"
+                         "array_to_string(ARRAY("
+            "      SELECT option_name || ' ' || quote_literal(option_value) "
+          "        FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
+                         "FROM pg_foreign_data_wrapper",
+                         username_subquery);
+   }
 
    res = PQexec(g_conn, query->data);
    check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
@@ -6019,6 +6034,8 @@ getForeignDataWrappers(int *numForeignDataWrappers)
    i_fdwname = PQfnumber(res, "fdwname");
    i_rolname = PQfnumber(res, "rolname");
    i_fdwvalidator = PQfnumber(res, "fdwvalidator");
+   if (g_fout->remoteVersion >= 90100)
+       i_fdwhandler = PQfnumber(res, "fdwhandler");
    i_fdwacl = PQfnumber(res, "fdwacl");
    i_fdwoptions = PQfnumber(res, "fdwoptions");
 
@@ -6032,6 +6049,10 @@ getForeignDataWrappers(int *numForeignDataWrappers)
        fdwinfo[i].dobj.namespace = NULL;
        fdwinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
        fdwinfo[i].fdwvalidator = strdup(PQgetvalue(res, i, i_fdwvalidator));
+       if (g_fout->remoteVersion >= 90100)
+           fdwinfo[i].fdwhandler = strdup(PQgetvalue(res, i, i_fdwhandler));
+       else
+           fdwinfo[i].fdwhandler = NULL;
        fdwinfo[i].fdwoptions = strdup(PQgetvalue(res, i, i_fdwoptions));
        fdwinfo[i].fdwacl = strdup(PQgetvalue(res, i, i_fdwacl));
 
@@ -10337,6 +10358,11 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
        appendPQExpBuffer(q, " VALIDATOR %s",
                          fdwinfo->fdwvalidator);
 
+   if (g_fout->remoteVersion >= 90100 && fdwinfo->fdwhandler &&
+       strcmp(fdwinfo->fdwhandler, "-") != 0)
+       appendPQExpBuffer(q, " HANDLER %s",
+                         fdwinfo->fdwhandler);
+
    if (fdwinfo->fdwoptions && strlen(fdwinfo->fdwoptions) > 0)
        appendPQExpBuffer(q, " OPTIONS (%s)", fdwinfo->fdwoptions);
 
index 43fd1ade27f0bf1ec8127c5526e65bdb14343ab3..c630a1d06f6c1257f7252051a4c33b212196d681 100644 (file)
@@ -421,6 +421,7 @@ typedef struct _fdwInfo
    DumpableObject dobj;
    char       *rolname;
    char       *fdwvalidator;
+   char       *fdwhandler;
    char       *fdwoptions;
    char       *fdwacl;
 } FdwInfo;
index ada04de451fe601db3b4a4eea24089b6a3e261f7..57718eb9b765fbaabc425fa8586a828a99c69571 100644 (file)
@@ -3480,9 +3480,11 @@ listForeignDataWrappers(const char *pattern, bool verbose)
    printfPQExpBuffer(&buf,
                      "SELECT fdwname AS \"%s\",\n"
                      "  pg_catalog.pg_get_userbyid(fdwowner) AS \"%s\",\n"
+                     "  fdwhandler::pg_catalog.regproc AS \"%s\",\n"
                      "  fdwvalidator::pg_catalog.regproc AS \"%s\"",
                      gettext_noop("Name"),
                      gettext_noop("Owner"),
+                     gettext_noop("Handler"),
                      gettext_noop("Validator"));
 
    if (verbose)
index a83556df151e62dddf50064afb58707e43c1cb12..971326cdaed51b12b31171bd54bf21dec1f0a016 100644 (file)
@@ -33,6 +33,7 @@ CATALOG(pg_foreign_data_wrapper,2328)
    NameData    fdwname;        /* foreign-data wrapper name */
    Oid         fdwowner;       /* FDW owner */
    Oid         fdwvalidator;   /* optional validation function */
+   Oid         fdwhandler;     /* foreign-data routines function */
 
    /* VARIABLE LENGTH FIELDS start here. */
 
@@ -52,11 +53,12 @@ typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
  * ----------------
  */
 
-#define Natts_pg_foreign_data_wrapper              5
+#define Natts_pg_foreign_data_wrapper              6
 #define Anum_pg_foreign_data_wrapper_fdwname       1
 #define Anum_pg_foreign_data_wrapper_fdwowner      2
 #define Anum_pg_foreign_data_wrapper_fdwvalidator  3
-#define Anum_pg_foreign_data_wrapper_fdwacl            4
-#define Anum_pg_foreign_data_wrapper_fdwoptions        5
+#define Anum_pg_foreign_data_wrapper_fdwhandler        4
+#define Anum_pg_foreign_data_wrapper_fdwacl            5
+#define Anum_pg_foreign_data_wrapper_fdwoptions        6
 
 #endif   /* PG_FOREIGN_DATA_WRAPPER_H */
index f8b5d4da3da64f5b6221e4256e3468524742f0e7..05fc57c633ecc89ff4c5b20893f3e1cc1fc0d828 100644 (file)
@@ -3899,6 +3899,10 @@ DATA(insert OID = 2777 (  anynonarray_in PGNSP PGUID 12 1 0 0 f f f t f i 1 0 27
 DESCR("I/O");
 DATA(insert OID = 2778 (  anynonarray_out  PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2275 "2776" _null_ _null_ _null_ _null_ anynonarray_out _null_ _null_ _null_ ));
 DESCR("I/O");
+DATA(insert OID = 3116 (  fdw_handler_in   PGNSP PGUID 12 1 0 0 f f f f f i 1 0 3115 "2275" _null_ _null_ _null_ _null_ fdw_handler_in _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 3117 (  fdw_handler_out  PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2275 "3115" _null_ _null_ _null_ _null_ fdw_handler_out _null_ _null_ _null_ ));
+DESCR("I/O");
 
 /* cryptographic */
 DATA(insert OID =  2311 (  md5    PGNSP PGUID 12 1 0 0 f f f t f i 1 0 25 "25" _null_ _null_ _null_ _null_ md5_text _null_ _null_ _null_ ));
index 620f7b4612b61746df2f0121e20c329886d0e044..ee40705160d8d9d52d734e0e67ac49e4838634f4 100644 (file)
@@ -623,6 +623,8 @@ DATA(insert OID = 2776 ( anynonarray    PGNSP PGUID  4 t p P f t \054 0 0 0 anynona
 #define ANYNONARRAYOID 2776
 DATA(insert OID = 3500 ( anyenum       PGNSP PGUID  4 t p P f t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 _null_ _null_ ));
 #define ANYENUMOID     3500
+DATA(insert OID = 3115 ( fdw_handler   PGNSP PGUID  4 t p P f t \054 0 0 0 fdw_handler_in fdw_handler_out - - - - - i p f 0 -1 0 _null_ _null_ ));
+#define FDW_HANDLEROID     3115
 
 
 /*
index f3037a442a376a2a8f1bd71f9bde9bef2a998a03..7d80a6a2895d05384bd354a68e0cb4da3e12e87d 100644 (file)
@@ -38,6 +38,7 @@ typedef struct ForeignDataWrapper
    Oid         owner;          /* FDW owner user Oid */
    char       *fdwname;        /* Name of the FDW */
    Oid         fdwvalidator;
+   Oid         fdwhandler;
    List       *options;        /* fdwoptions as DefElem list */
 } ForeignDataWrapper;
 
index d7d1b0a6fdf72c6b009e1d0ad4c2ef7bb4b44b78..583b54cd2fc764010b8f5e3b425f5bad524b65e6 100644 (file)
@@ -1531,7 +1531,7 @@ typedef struct CreateFdwStmt
 {
    NodeTag     type;
    char       *fdwname;        /* foreign-data wrapper name */
-   List       *validator;      /* optional validator function (qual. name) */
+   List       *func_options;   /* VALIDATOR/HANDLER conbination */
    List       *options;        /* generic options to FDW */
 } CreateFdwStmt;
 
@@ -1539,8 +1539,7 @@ typedef struct AlterFdwStmt
 {
    NodeTag     type;
    char       *fdwname;        /* foreign-data wrapper name */
-   List       *validator;      /* optional validator function (qual. name) */
-   bool        change_validator;
+   List       *func_options;   /* VALIDATOR/HANDLER conbination */
    List       *options;        /* generic options to FDW */
 } AlterFdwStmt;
 
index 4cb6c5c17a57d3e91cd9128fd3c9bf32e85f33f2..eaaf7d0651a3c30d2d7fb56a8d087e600aab34de 100644 (file)
@@ -518,6 +518,8 @@ extern Datum pg_node_tree_in(PG_FUNCTION_ARGS);
 extern Datum pg_node_tree_out(PG_FUNCTION_ARGS);
 extern Datum pg_node_tree_recv(PG_FUNCTION_ARGS);
 extern Datum pg_node_tree_send(PG_FUNCTION_ARGS);
+extern Datum fdw_handler_in(PG_FUNCTION_ARGS);
+extern Datum fdw_handler_out(PG_FUNCTION_ARGS);
 
 /* regexp.c */
 extern Datum nameregexeq(PG_FUNCTION_ARGS);
index d6c650be14d0488ffc0260e73e45a8a45e513425..fe3ce428672ef4e8fca4bcd923230d110495e261 100644 (file)
@@ -16,11 +16,11 @@ CREATE ROLE unprivileged_role;
 CREATE FOREIGN DATA WRAPPER dummy;
 CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
 -- At this point we should have 2 built-in wrappers and no servers.
-SELECT fdwname, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
-  fdwname   |       fdwvalidator       | fdwoptions 
-------------+--------------------------+------------
- dummy      | -                        | 
- postgresql | postgresql_fdw_validator | 
+SELECT fdwname, fdwvalidator::regproc, fdwhandler::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+  fdwname   |       fdwvalidator       | fdwhandler | fdwoptions 
+------------+--------------------------+------------+------------
+ dummy      | -                        | -          | 
+ postgresql | postgresql_fdw_validator | -          | 
 (2 rows)
 
 SELECT srvname, srvoptions FROM pg_foreign_server;
@@ -38,12 +38,12 @@ CREATE FOREIGN DATA WRAPPER foo VALIDATOR bar;            -- ERROR
 ERROR:  function bar(text[], oid) does not exist
 CREATE FOREIGN DATA WRAPPER foo;
 \dew
-               List of foreign-data wrappers
-    Name    |       Owner       |        Validator         
-------------+-------------------+--------------------------
- dummy      | foreign_data_user | -
- foo        | foreign_data_user | -
- postgresql | foreign_data_user | postgresql_fdw_validator
+                    List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         
+------------+-------------------+---------+--------------------------
+ dummy      | foreign_data_user | -       | -
+ foo        | foreign_data_user | -       | -
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator
 (3 rows)
 
 CREATE FOREIGN DATA WRAPPER foo; -- duplicate
@@ -51,12 +51,12 @@ ERROR:  foreign-data wrapper "foo" already exists
 DROP FOREIGN DATA WRAPPER foo;
 CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1');
 \dew+
-                                List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges |   Options   
-------------+-------------------+--------------------------+-------------------+-------------
- dummy      | foreign_data_user | -                        |                   | 
- foo        | foreign_data_user | -                        |                   | {testing=1}
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                     List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges |   Options   
+------------+-------------------+---------+--------------------------+-------------------+-------------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ foo        | foreign_data_user | -       | -                        |                   | {testing=1}
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 DROP FOREIGN DATA WRAPPER foo;
@@ -64,12 +64,12 @@ CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', testing '2');   -- ERROR
 ERROR:  option "testing" provided more than once
 CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', another '2');
 \dew+
-                                     List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges |        Options        
-------------+-------------------+--------------------------+-------------------+-----------------------
- dummy      | foreign_data_user | -                        |                   | 
- foo        | foreign_data_user | -                        |                   | {testing=1,another=2}
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                          List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges |        Options        
+------------+-------------------+---------+--------------------------+-------------------+-----------------------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ foo        | foreign_data_user | -       | -                        |                   | {testing=1,another=2}
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 DROP FOREIGN DATA WRAPPER foo;
@@ -80,12 +80,12 @@ HINT:  Must be superuser to create a foreign-data wrapper.
 RESET ROLE;
 CREATE FOREIGN DATA WRAPPER foo VALIDATOR postgresql_fdw_validator;
 \dew+
-                              List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges | Options 
-------------+-------------------+--------------------------+-------------------+---------
- dummy      | foreign_data_user | -                        |                   | 
- foo        | foreign_data_user | postgresql_fdw_validator |                   | 
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                   List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges | Options 
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ foo        | foreign_data_user | -       | postgresql_fdw_validator |                   | 
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 -- ALTER FOREIGN DATA WRAPPER
@@ -97,12 +97,12 @@ ALTER FOREIGN DATA WRAPPER foo VALIDATOR bar;               -- ERROR
 ERROR:  function bar(text[], oid) does not exist
 ALTER FOREIGN DATA WRAPPER foo NO VALIDATOR;
 \dew+
-                              List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges | Options 
-------------+-------------------+--------------------------+-------------------+---------
- dummy      | foreign_data_user | -                        |                   | 
- foo        | foreign_data_user | -                        |                   | 
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                   List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges | Options 
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ foo        | foreign_data_user | -       | -                        |                   | 
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '1', b '2');
@@ -112,34 +112,34 @@ ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP c);            -- ERROR
 ERROR:  option "c" not found
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD x '1', DROP x);
 \dew+
-                               List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges |  Options  
-------------+-------------------+--------------------------+-------------------+-----------
- dummy      | foreign_data_user | -                        |                   | 
- foo        | foreign_data_user | -                        |                   | {a=1,b=2}
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                    List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges |  Options  
+------------+-------------------+---------+--------------------------+-------------------+-----------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ foo        | foreign_data_user | -       | -                        |                   | {a=1,b=2}
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP a, SET b '3', ADD c '4');
 \dew+
-                               List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges |  Options  
-------------+-------------------+--------------------------+-------------------+-----------
- dummy      | foreign_data_user | -                        |                   | 
- foo        | foreign_data_user | -                        |                   | {b=3,c=4}
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                    List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges |  Options  
+------------+-------------------+---------+--------------------------+-------------------+-----------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ foo        | foreign_data_user | -       | -                        |                   | {b=3,c=4}
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '2');
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (b '4');             -- ERROR
 ERROR:  option "b" provided more than once
 \dew+
-                                 List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges |    Options    
-------------+-------------------+--------------------------+-------------------+---------------
- dummy      | foreign_data_user | -                        |                   | 
- foo        | foreign_data_user | -                        |                   | {b=3,c=4,a=2}
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                      List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges |    Options    
+------------+-------------------+---------+--------------------------+-------------------+---------------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ foo        | foreign_data_user | -       | -                        |                   | {b=3,c=4,a=2}
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 SET ROLE regress_test_role;
@@ -149,12 +149,12 @@ HINT:  Must be superuser to alter a foreign-data wrapper.
 SET ROLE regress_test_role_super;
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD d '5');
 \dew+
-                                   List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges |      Options      
-------------+-------------------+--------------------------+-------------------+-------------------
- dummy      | foreign_data_user | -                        |                   | 
- foo        | foreign_data_user | -                        |                   | {b=3,c=4,a=2,d=5}
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                        List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges |      Options      
+------------+-------------------+---------+--------------------------+-------------------+-------------------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ foo        | foreign_data_user | -       | -                        |                   | {b=3,c=4,a=2,d=5}
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 ALTER FOREIGN DATA WRAPPER foo OWNER TO regress_test_role;  -- ERROR
@@ -168,12 +168,12 @@ ERROR:  permission denied to alter foreign-data wrapper "foo"
 HINT:  Must be superuser to alter a foreign-data wrapper.
 RESET ROLE;
 \dew+
-                                      List of foreign-data wrappers
-    Name    |          Owner          |        Validator         | Access privileges |      Options      
-------------+-------------------------+--------------------------+-------------------+-------------------
- dummy      | foreign_data_user       | -                        |                   | 
- foo        | regress_test_role_super | -                        |                   | {b=3,c=4,a=2,d=5}
- postgresql | foreign_data_user       | postgresql_fdw_validator |                   | 
+                                           List of foreign-data wrappers
+    Name    |          Owner          | Handler |        Validator         | Access privileges |      Options      
+------------+-------------------------+---------+--------------------------+-------------------+-------------------
+ dummy      | foreign_data_user       | -       | -                        |                   | 
+ foo        | regress_test_role_super | -       | -                        |                   | {b=3,c=4,a=2,d=5}
+ postgresql | foreign_data_user       | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 -- DROP FOREIGN DATA WRAPPER
@@ -182,12 +182,12 @@ ERROR:  foreign-data wrapper "nonexistent" does not exist
 DROP FOREIGN DATA WRAPPER IF EXISTS nonexistent;
 NOTICE:  foreign-data wrapper "nonexistent" does not exist, skipping
 \dew+
-                                      List of foreign-data wrappers
-    Name    |          Owner          |        Validator         | Access privileges |      Options      
-------------+-------------------------+--------------------------+-------------------+-------------------
- dummy      | foreign_data_user       | -                        |                   | 
- foo        | regress_test_role_super | -                        |                   | {b=3,c=4,a=2,d=5}
- postgresql | foreign_data_user       | postgresql_fdw_validator |                   | 
+                                           List of foreign-data wrappers
+    Name    |          Owner          | Handler |        Validator         | Access privileges |      Options      
+------------+-------------------------+---------+--------------------------+-------------------+-------------------
+ dummy      | foreign_data_user       | -       | -                        |                   | 
+ foo        | regress_test_role_super | -       | -                        |                   | {b=3,c=4,a=2,d=5}
+ postgresql | foreign_data_user       | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 DROP ROLE regress_test_role_super;                          -- ERROR
@@ -202,23 +202,23 @@ ALTER ROLE regress_test_role_super SUPERUSER;
 DROP FOREIGN DATA WRAPPER foo;
 DROP ROLE regress_test_role_super;
 \dew+
-                              List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges | Options 
-------------+-------------------+--------------------------+-------------------+---------
- dummy      | foreign_data_user | -                        |                   | 
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                   List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges | Options 
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (2 rows)
 
 CREATE FOREIGN DATA WRAPPER foo;
 CREATE SERVER s1 FOREIGN DATA WRAPPER foo;
 CREATE USER MAPPING FOR current_user SERVER s1;
 \dew+
-                              List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges | Options 
-------------+-------------------+--------------------------+-------------------+---------
- dummy      | foreign_data_user | -                        |                   | 
- foo        | foreign_data_user | -                        |                   | 
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                   List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges | Options 
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ foo        | foreign_data_user | -       | -                        |                   | 
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (3 rows)
 
 \des+
@@ -250,11 +250,11 @@ NOTICE:  drop cascades to 2 other objects
 DETAIL:  drop cascades to server s1
 drop cascades to user mapping for foreign_data_user
 \dew+
-                              List of foreign-data wrappers
-    Name    |       Owner       |        Validator         | Access privileges | Options 
-------------+-------------------+--------------------------+-------------------+---------
- dummy      | foreign_data_user | -                        |                   | 
- postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
+                                   List of foreign-data wrappers
+    Name    |       Owner       | Handler |        Validator         | Access privileges | Options 
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy      | foreign_data_user | -       | -                        |                   | 
+ postgresql | foreign_data_user | -       | postgresql_fdw_validator |                   | 
 (2 rows)
 
 \des+
@@ -1105,9 +1105,9 @@ NOTICE:  drop cascades to server sc
 \c
 DROP ROLE foreign_data_user;
 -- At this point we should have no wrappers, no servers, and no mappings.
-SELECT fdwname, fdwvalidator, fdwoptions FROM pg_foreign_data_wrapper;
- fdwname | fdwvalidator | fdwoptions 
----------+--------------+------------
+SELECT fdwname, fdwvalidator, fdwhandler, fdwoptions FROM pg_foreign_data_wrapper;
+ fdwname | fdwvalidator | fdwhandler | fdwoptions 
+---------+--------------+------------+------------
 (0 rows)
 
 SELECT srvname, srvoptions FROM pg_foreign_server;
index 86b698a1b616420946138a08d84b4c81a8642a7e..5f54272234547111e16a3dc4ad9d149783e025a0 100644 (file)
@@ -24,7 +24,7 @@ CREATE FOREIGN DATA WRAPPER dummy;
 CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
 
 -- At this point we should have 2 built-in wrappers and no servers.
-SELECT fdwname, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+SELECT fdwname, fdwvalidator::regproc, fdwhandler::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
 SELECT srvname, srvoptions FROM pg_foreign_server;
 SELECT * FROM pg_user_mapping;
 
@@ -453,6 +453,6 @@ DROP FOREIGN DATA WRAPPER dummy CASCADE;
 DROP ROLE foreign_data_user;
 
 -- At this point we should have no wrappers, no servers, and no mappings.
-SELECT fdwname, fdwvalidator, fdwoptions FROM pg_foreign_data_wrapper;
+SELECT fdwname, fdwvalidator, fdwhandler, fdwoptions FROM pg_foreign_data_wrapper;
 SELECT srvname, srvoptions FROM pg_foreign_server;
 SELECT * FROM pg_user_mapping;