Add the possibility to specify an explicit validator function for foreign-data
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 24 Feb 2009 10:06:36 +0000 (10:06 +0000)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 24 Feb 2009 10:06:36 +0000 (10:06 +0000)
wrappers (similar to procedural languages).  This way we don't need to retain
the nearly empty libraries, and we are more free in how to implement the
wrapper API in the future.

28 files changed:
doc/src/sgml/catalogs.sgml
doc/src/sgml/keywords.sgml
doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
doc/src/sgml/ref/create_foreign_data_wrapper.sgml
src/Makefile
src/backend/catalog/information_schema.sql
src/backend/commands/foreigncmds.c
src/backend/foreign/Makefile
src/backend/foreign/dummy/Makefile [deleted file]
src/backend/foreign/dummy/dummy_fdw.c [deleted file]
src/backend/foreign/foreign.c
src/backend/foreign/postgresql/Makefile [deleted file]
src/backend/foreign/postgresql/postgresql_fdw.c [deleted file]
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/parser/gram.y
src/backend/parser/keywords.c
src/bin/pg_dump/pg_dump.c
src/bin/pg_dump/pg_dump.h
src/bin/psql/describe.c
src/bin/psql/tab-complete.c
src/include/catalog/catversion.h
src/include/catalog/pg_foreign_data_wrapper.h
src/include/catalog/pg_proc.h
src/include/foreign/foreign.h
src/include/nodes/parsenodes.h
src/test/regress/expected/foreign_data.out
src/test/regress/sql/foreign_data.sql

index 362dc89115b5eb1545f39a68779cb20f2445772b..a985474425ce9fb7ac0291d29872dedf46ef5d6b 100644 (file)
      </row>
 
      <row>
-      <entry><structfield>fdwlibrary</structfield></entry>
-      <entry><type>text</type></entry>
-      <entry></entry>
-      <entry>File name of the library implementing this foreign-data wrapper</entry>
+      <entry><structfield>fdwvalidator</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 validator function that is responsible for
+       checking the validity of the generic options given to the
+       foreign-data wrapper, as well as to foreign servers and user
+       mappings using the foreign-data wrapper.  Zero if no validator
+       is provided.
+      </entry>
      </row>
 
      <row>
index 5e80563e155e86f35dee6fe4abb1adaf130c6653..45b3d47a2bc9554bb89d254aba81509ee5bdf02e 100644 (file)
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
-   <row>
-    <entry><token>LIBRARY</token></entry>
-    <entry>non-reserved</entry>
-    <entry>non-reserved</entry>
-    <entry>non-reserved</entry>
-    <entry></entry>
-    <entry></entry>
-   </row>
    <row>
     <entry><token>LIKE</token></entry>
     <entry>reserved (can be function or type)</entry>
index 5c9d3f1478487e828061f2b13a21c0d2e1e28c44..b63b97892534325caf75dd01975392dc2105733d 100644 (file)
@@ -21,7 +21,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
-    [ LIBRARY '<replaceable class="parameter">libraryname</replaceable>' ]
+    [ VALIDATOR <replaceable class="parameter">valfunction</replaceable> | NO VALIDATOR ]
     [ 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>
@@ -58,14 +58,14 @@ ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWN
    </varlistentry>
 
    <varlistentry>
-    <term><replaceable class="parameter">libraryname</replaceable></term>
+    <term><literal>VALIDATOR <replaceable class="parameter">valfunction</replaceable></literal></term>
     <listitem>
      <para>
-      New name of the foreign-data wrapper library.
+      Specifies a new foreign-data wrapper validator function.
      </para>
 
      <para>
-      Note that it is possible that after changing the library, the
+      Note that it is possible that after changing the validator the
       options to the foreign-data wrapper, servers, and user mappings
       have become invalid.   It is up to the user to make sure that
       these options are correct before using the foreign-data
@@ -74,6 +74,16 @@ ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWN
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term><literal>NO VALIDATOR</literal></term>
+    <listitem>
+     <para>
+      This is used to specify that the foreign-data wrapper should no
+      longer have a validator function.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
     <listitem>
@@ -102,10 +112,10 @@ ALTER FOREIGN DATA WRAPPER dbi OPTIONS (ADD foo '1', DROP 'bar');
   </para>
 
   <para>
-   Change the foreign-data wrapper <literal>dbi</> library
-   to <literal>/home/bob/mylibrary.so</>:
+   Change the foreign-data wrapper <literal>dbi</> validator
+   to <literal>bob.myvalidator</>:
 <programlisting>
-ALTER FOREIGN DATA WRAPPER dbi LIBRARY '/home/bob/mylibrary.so';
+ALTER FOREIGN DATA WRAPPER dbi VALIDATOR bob.myvalidator;
 </programlisting>
   </para>
  </refsect1>
@@ -115,8 +125,9 @@ ALTER FOREIGN DATA WRAPPER dbi LIBRARY '/home/bob/mylibrary.so';
 
   <para>
    <command>ALTER FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
-   9075-9 (SQL/MED).  The standard does not specify the <literal>OWNER
-   TO</> variant of the command.
+   9075-9 (SQL/MED).  The standard does not specify the <literal>
+   VALIDATOR</literal> and <literal>OWNER TO</> variants of the
+   command.
   </para>
  </refsect1>
 
index 94e66308269c7f6ae0f9809d6ed7eb019306508a..b321fb94f56850c4a91da285b471507b51e5ccb8 100644 (file)
@@ -21,8 +21,7 @@ PostgreSQL documentation
  <refsynopsisdiv>
 <synopsis>
 CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
-    LIBRARY '<replaceable class="parameter">libraryname</replaceable>'
-    LANGUAGE C
+    [ VALIDATOR <replaceable class="parameter">valfunction</replaceable> | NO VALIDATOR ]
     [ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ]
 </synopsis>
  </refsynopsisdiv>
@@ -59,25 +58,25 @@ CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
    </varlistentry>
 
    <varlistentry>
-    <term><replaceable class="parameter">libraryname</replaceable></term>
+    <term><literal>VALIDATOR <replaceable class="parameter">valfunction</replaceable></literal></term>
     <listitem>
      <para>
-      The name of the shared library implementing the foreign-data
-      wrapper.  The file name is specified in the same way as for
-      shared library names in <xref linkend="sql-createfunction"
-      endterm="sql-createfunction-title">; in particular, one can rely
-      on a search path and automatic addition of the system's standard
-      shared library file name extension.
-     </para>
-    </listitem>
-   </varlistentry>
-
-   <varlistentry>
-    <term><literal>LANGUAGE C</literal></term>
-    <listitem>
-     <para>
-      Currently, only the C programming language is supported for
-      implementing foreign-data wrappers.
+      <replaceable class="parameter">valfunction</replaceable> is the
+      name of a previously registered function that will be called to
+      check the generic options given to the foreign-data wrapper, as
+      well as to foreign servers and user mappings using the
+      foreign-data wrapper.  If no validator function or <literal>NO
+      VALIDATOR</literal> is specified, then options will not be
+      checked at creation time.  (Foreign-data wrappers will possibly
+      ignore or reject invalid option specifications at run time,
+      depending on the implementation.)  The validator function must
+      take two arguments: one of type <type>text[]</type>, which will
+      contain the array of options as stored in the system catalogs,
+      and one of type <type>oid</type>, which will be the OID of the
+      system catalog containing the options, or zero if the context is
+      not known.  The return type is ignored; the function should
+      indicate invalid options using
+      the <function>ereport()</function> function.
      </para>
     </listitem>
    </varlistentry>
@@ -109,18 +108,11 @@ CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
   </para>
 
   <para>
-   The C language API for foreign-data wrappers is currently not
-   documented, stable, or complete.  Would-be authors of functionality
-   interfacing with the SQL/MED functionality are advised to contact
-   the PostgreSQL developers.
-  </para>
-
-  <para>
-   There are currently two foreign-data wrapper libraries
-   provided: <filename>dummy_fdw</filename>, which does nothing and
-   could be useful for testing,
-   and <filename>postgresql_fdw</filename>, which accepts options
-   corresponding to <application>libpq</> connection parameters.
+   There is currently one foreign-data wrapper validator function
+   provided:
+   <filename>postgresql_fdw_validator</filename>, which accepts
+   options corresponding to <application>libpq</> connection
+   parameters.
   </para>
  </refsect1>
 
@@ -128,28 +120,25 @@ CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
   <title>Examples</title>
 
   <para>
-   Create a foreign-data wrapper <literal>dummy</> with
-   library <literal>dummy_fdw</>:
+   Create a foreign-data wrapper <literal>dummy</>:
 <programlisting>
-CREATE FOREIGN DATA WRAPPER dummy LIBRARY 'dummy_fdw' LANGUAGE C;
+CREATE FOREIGN DATA WRAPPER dummy;
 </programlisting>
   </para>
 
   <para>
    Create a foreign-data wrapper <literal>postgresql</> with
-   library <literal>postgresql_fdw</>:
+   validator function <literal>postgresql_fdw_validator</>:
 <programlisting>
-CREATE FOREIGN DATA WRAPPER postgresql LIBRARY 'postgresql_fdw' LANGUAGE C;
+CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
 </programlisting>
   </para>
 
   <para>
-   Create a foreign-data wrapper <literal>mywrapper</> with library
-   <literal>/home/bob/mywrapper.so</> and some options:
+   Create a foreign-data wrapper <literal>mywrapper</> with some
+   options:
 <programlisting>
 CREATE FOREIGN DATA WRAPPER mywrapper
-    LIBRARY '/home/bob/mywrapper.so'
-    LANGUAGE C
     OPTIONS (debug 'true');
 </programlisting>
   </para>
@@ -161,8 +150,9 @@ 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>LIBRARY</literal> clause is not optional in
-   PostgreSQL.
+   the <literal>VALIDATOR</literal> clause is an extension and the
+   clauses <literal>LIBRARY</literal> and <literal>LANGUAGE</literal>
+   are not yet implemented in PostgreSQL.
   </para>
 
   <para>
index 33493a5a8b88fd557450e50855b0f6ecda653ded..acefa7580b04457d2b9b71e7cd2eefa8e023c6a3 100644 (file)
@@ -19,7 +19,6 @@ all install installdirs uninstall distprep:
        $(MAKE) -C backend $@
        $(MAKE) -C backend/utils/mb/conversion_procs $@
        $(MAKE) -C backend/snowball $@
-       $(MAKE) -C backend/foreign $@-fdw
        $(MAKE) -C include $@
        $(MAKE) -C interfaces $@
        $(MAKE) -C bin $@
index 5b5e203339a11ae553e02e5507ab0c4d98b27799..9c5672f3e13692cf3770440b112fede562420952 100644 (file)
@@ -2428,7 +2428,6 @@ CREATE VIEW _pg_foreign_data_wrappers AS
            CAST(current_database() AS sql_identifier) AS foreign_data_wrapper_catalog,
            CAST(fdwname AS sql_identifier) AS foreign_data_wrapper_name,
            CAST(u.rolname AS sql_identifier) AS authorization_identifier,
-           CAST(fdwlibrary AS character_data) AS library_name,
            CAST('c' AS character_data) AS foreign_data_wrapper_language
     FROM pg_foreign_data_wrapper w, pg_authid u
     WHERE u.oid = w.fdwowner
@@ -2458,7 +2457,7 @@ CREATE VIEW foreign_data_wrappers AS
     SELECT foreign_data_wrapper_catalog,
            foreign_data_wrapper_name,
            authorization_identifier,
-           library_name,
+           CAST(NULL AS character_data) AS library_name,
            foreign_data_wrapper_language
     FROM _pg_foreign_data_wrappers w;
 
index 2d371b4f6df5f4ff2ea4a74bedc7d8765b03db1c..84b7ffac4bc3ba97dfbc274273524e2505be09e3 100644 (file)
 #include "catalog/indexing.h"
 #include "catalog/pg_foreign_data_wrapper.h"
 #include "catalog/pg_foreign_server.h"
+#include "catalog/pg_proc.h"
 #include "catalog/pg_type.h"
 #include "catalog/pg_user_mapping.h"
 #include "commands/defrem.h"
 #include "foreign/foreign.h"
 #include "miscadmin.h"
+#include "parser/parse_func.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
 #include "utils/lsyscache.h"
@@ -90,10 +92,11 @@ transformGenericOptions(Datum oldOptions,
                                                List *optionDefList,
                                                GenericOptionFlags flags,
                                                ForeignDataWrapper *fdw,
-                                               OptionListValidatorFunc validateOptionList)
+                                               Oid fdwvalidator)
 {
        List     *resultOptions = untransformRelOptions(oldOptions);
        ListCell *optcell;
+       Datum     result;
 
        foreach(optcell, optionDefList)
        {
@@ -157,10 +160,12 @@ transformGenericOptions(Datum oldOptions,
                }
        }
 
-       if (validateOptionList)
-               validateOptionList(fdw, flags, resultOptions);
+       result = optionListToArray(resultOptions);
 
-       return optionListToArray(resultOptions);
+       if (fdwvalidator)
+               OidFunctionCall2(fdwvalidator, result, 0);
+
+       return result;
 }
 
 
@@ -309,6 +314,21 @@ 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)
+{
+       Oid                     funcargtypes[2];
+
+       funcargtypes[0] = TEXTARRAYOID;
+       funcargtypes[1] = OIDOID;
+       return LookupFuncName(validator, 2, funcargtypes, false);
+       /* return value is ignored, so we don't check the type */
+}
+
+
 /*
  * Create a foreign-data wrapper
  */
@@ -320,9 +340,9 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
        bool                    nulls[Natts_pg_foreign_data_wrapper];
        HeapTuple               tuple;
        Oid                             fdwId;
+       Oid                             fdwvalidator;
        Datum                   fdwoptions;
        Oid                             ownerId;
-       ForeignDataWrapperLibrary  *fdwlib;
 
        /* Must be super user */
        if (!superuser())
@@ -355,18 +375,19 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
        values[Anum_pg_foreign_data_wrapper_fdwname - 1] =
                DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname));
        values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
-       values[Anum_pg_foreign_data_wrapper_fdwlibrary - 1] = CStringGetTextDatum(stmt->library);
-       nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
 
-       /*
-        * See if the FDW library loads at all. We also might want to use it
-        * later for validating the options.
-        */
-       fdwlib = GetForeignDataWrapperLibrary(stmt->library);
+       if (stmt->validator)
+               fdwvalidator = lookup_fdw_validator_func(stmt->validator);
+       else
+               fdwvalidator = InvalidOid;
+
+       values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = fdwvalidator;
+
+       nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
 
        fdwoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
                                                                                 FdwOpt, NULL,
-                                                                                fdwlib->validateOptionList);
+                                                                                fdwvalidator);
 
        if (PointerIsValid(DatumGetPointer(fdwoptions)))
                values[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = fdwoptions;
@@ -380,6 +401,21 @@ CreateForeignDataWrapper(CreateFdwStmt *stmt)
 
        heap_freetuple(tuple);
 
+       if (fdwvalidator)
+       {
+               ObjectAddress myself;
+               ObjectAddress referenced;
+
+               myself.classId = ForeignDataWrapperRelationId;
+               myself.objectId = fdwId;
+               myself.objectSubId = 0;
+
+               referenced.classId = ProcedureRelationId;
+               referenced.objectId = fdwvalidator;
+               referenced.objectSubId = 0;
+               recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+       }
+
        recordDependencyOnOwner(ForeignDataWrapperRelationId, fdwId, ownerId);
 
        heap_close(rel, NoLock);
@@ -400,7 +436,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
        Oid                     fdwId;
        bool            isnull;
        Datum           datum;
-       ForeignDataWrapperLibrary *fdwlib;
+       Oid                     fdwvalidator;
 
        /* Must be super user */
        if (!superuser())
@@ -425,36 +461,33 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
        memset(repl_null, false, sizeof(repl_null));
        memset(repl_repl, false, sizeof(repl_repl));
 
-       if (stmt->library)
+       if (stmt->change_validator)
        {
-               /*
-                * New library specified -- load to see if valid.
-                */
-               fdwlib = GetForeignDataWrapperLibrary(stmt->library);
-
-               repl_val[Anum_pg_foreign_data_wrapper_fdwlibrary - 1] = CStringGetTextDatum(stmt->library);
-               repl_repl[Anum_pg_foreign_data_wrapper_fdwlibrary - 1] = true;
+               fdwvalidator = stmt->validator ? lookup_fdw_validator_func(stmt->validator) : InvalidOid;
+               repl_val[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
+               repl_repl[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = true;
 
                /*
                 * It could be that the options for the FDW, SERVER and USER MAPPING
-                * are no longer valid with the new library.  Warn about this.
+                * are no longer valid with the new validator.  Warn about this.
                 */
-               ereport(WARNING,
-                               (errmsg("changing the foreign-data wrapper library can cause "
-                                               "the options for dependent objects to become invalid")));
+               if (stmt->validator)
+                       ereport(WARNING,
+                                       (errmsg("changing the foreign-data wrapper validator can cause "
+                                                       "the options for dependent objects to become invalid")));
        }
        else
        {
                /*
-                * No LIBRARY clause specified, but we need to load it for validating
+                * Validator is not changed, but we need it for validating
                 * options.
                 */
                datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
                                                                tp,
-                                                               Anum_pg_foreign_data_wrapper_fdwlibrary,
+                                                               Anum_pg_foreign_data_wrapper_fdwvalidator,
                                                                &isnull);
                Assert(!isnull);
-               fdwlib = GetForeignDataWrapperLibrary(TextDatumGetCString(datum));
+               fdwvalidator = DatumGetObjectId(datum);
        }
 
        /*
@@ -472,7 +505,7 @@ AlterForeignDataWrapper(AlterFdwStmt *stmt)
 
                /* Transform the options */
                datum = transformGenericOptions(datum, stmt->options, FdwOpt,
-                                                                               NULL, fdwlib->validateOptionList);
+                                                                               NULL, fdwvalidator);
 
                if (PointerIsValid(DatumGetPointer(datum)))
                        repl_val[Anum_pg_foreign_data_wrapper_fdwoptions - 1] = datum;
@@ -640,7 +673,7 @@ CreateForeignServer(CreateForeignServerStmt *stmt)
        /* Add server options */
        srvoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
                                                                                 ServerOpt, fdw,
-                                                                                fdw->lib->validateOptionList);
+                                                                                fdw->fdwvalidator);
 
        if (PointerIsValid(DatumGetPointer(srvoptions)))
                values[Anum_pg_foreign_server_srvoptions - 1] = srvoptions;
@@ -738,7 +771,7 @@ AlterForeignServer(AlterForeignServerStmt *stmt)
 
                /* Prepare the options array */
                datum = transformGenericOptions(datum, stmt->options, ServerOpt,
-                                                                               fdw, fdw->lib->validateOptionList);
+                                                                               fdw, fdw->fdwvalidator);
 
                if (PointerIsValid(DatumGetPointer(datum)))
                        repl_val[Anum_pg_foreign_server_srvoptions - 1] = datum;
@@ -910,7 +943,7 @@ CreateUserMapping(CreateUserMappingStmt *stmt)
        /* Add user options */
        useoptions = transformGenericOptions(PointerGetDatum(NULL), stmt->options,
                                                                                 UserMappingOpt,
-                                                                                fdw, fdw->lib->validateOptionList);
+                                                                                fdw, fdw->fdwvalidator);
 
        if (PointerIsValid(DatumGetPointer(useoptions)))
                values[Anum_pg_user_mapping_umoptions - 1] = useoptions;
@@ -1005,7 +1038,7 @@ AlterUserMapping(AlterUserMappingStmt *stmt)
 
                /* Prepare the options array */
                datum = transformGenericOptions(datum, stmt->options, UserMappingOpt,
-                                                                               fdw, fdw->lib->validateOptionList);
+                                                                               fdw, fdw->fdwvalidator);
 
                if (PointerIsValid(DatumGetPointer(datum)))
                        repl_val[Anum_pg_user_mapping_umoptions - 1] = datum;
index 11553b6f76f02152da79f260be5d17c05de6730e..8bee42c26bf424bca3f68b07a785bca0bbd17009 100644 (file)
@@ -15,11 +15,3 @@ include $(top_builddir)/src/Makefile.global
 OBJS= foreign.o
 
 include $(top_srcdir)/src/backend/common.mk
-
-FDW = dummy postgresql
-
-$(addsuffix -fdw,all install installdirs uninstall distprep):
-       for dir in $(FDW); do $(MAKE) -C $$dir `echo $@ | sed 's/-fdw$$//'` || exit; done
-
-clean distclean maintainer-clean:
-       for dir in $(FDW); do $(MAKE) -C $$dir $@ || exit; done
diff --git a/src/backend/foreign/dummy/Makefile b/src/backend/foreign/dummy/Makefile
deleted file mode 100644 (file)
index b3c13b9..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#-------------------------------------------------------------------------
-#
-# Makefile--
-#    Makefile for dummy foreign-data wrapper
-#
-# IDENTIFICATION
-#    $PostgreSQL$
-#
-#-------------------------------------------------------------------------
-
-subdir = src/backend/foreign/dummy
-top_builddir = ../../../..
-include $(top_builddir)/src/Makefile.global
-
-NAME = dummy_fdw
-OBJS = dummy_fdw.o
-
-include $(top_srcdir)/src/Makefile.shlib
-
-all: all-shared-lib
-
-install: all install-lib
-
-installdirs: installdirs-lib
-
-clean distclean maintainer-clean: clean-lib
-       rm -f $(OBJS)
diff --git a/src/backend/foreign/dummy/dummy_fdw.c b/src/backend/foreign/dummy/dummy_fdw.c
deleted file mode 100644 (file)
index 5d3cea6..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * dummy_fdw.c
- *        "dummy" foreign-data wrapper
- *
- * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- *        $PostgreSQL$
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "fmgr.h"
-#include "foreign/foreign.h"
-
-PG_MODULE_MAGIC;
-
-/*
- * This looks like a complete waste right now, but it is useful for
- * testing, and will become more interesting as more parts of the
- * interface are implemented.
- */
index 75f430b05bb2d41749c8740cf44ba09da81de925..45b2e3d741680481445707738ae8441f6bd2264e 100644 (file)
 
 
 extern Datum pg_options_to_table(PG_FUNCTION_ARGS);
+extern Datum postgresql_fdw_validator(PG_FUNCTION_ARGS);
 
 
-/* list of currently loaded foreign-data wrapper interfaces */
-static List *loaded_fdw_interfaces = NIL;
-
-
-/*
- * GetForeignDataWrapperLibrary - return the named FDW library.  If it
- * is already loaded, use that.  Otherwise allocate, initialize, and
- * store in cache.
- */
-ForeignDataWrapperLibrary *
-GetForeignDataWrapperLibrary(const char *libname)
-{
-       MemoryContext                                   oldcontext;
-       void                                               *libhandle = NULL;
-       ForeignDataWrapperLibrary          *fdwl = NULL;
-       ListCell                                           *cell;
-
-       /* See if we have the FDW library is already loaded */
-       foreach (cell, loaded_fdw_interfaces)
-       {
-               fdwl = lfirst(cell);
-               if (strcmp(fdwl->libname, libname) == 0)
-                       return fdwl;
-       }
-
-       /*
-        * We don't have it yet, so load and add.  Attempt a load_file()
-        * first to filter out any missing or unloadable libraries.
-        */
-       load_file(libname, false);
-
-       oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-
-       fdwl = palloc(sizeof(*fdwl));
-       fdwl->libname = pstrdup(libname);
-       loaded_fdw_interfaces = lappend(loaded_fdw_interfaces, fdwl);
-
-       MemoryContextSwitchTo(oldcontext);
-
-       /*
-        * Now look up the foreign data wrapper functions.
-        */
-#define LOOKUP_FUNCTION(name) \
-       (void *)(libhandle ? \
-               lookup_external_function(libhandle, name) \
-               : load_external_function(fdwl->libname, name, false, &libhandle))
-
-       fdwl->validateOptionList = LOOKUP_FUNCTION("_pg_validateOptionList");
-
-       return fdwl;
-}
-
 
 /*
  * GetForeignDataWrapper -  look up the foreign-data wrapper by OID.
- *
- * Here we also deal with loading the FDW library and looking up the
- * actual functions.
  */
 ForeignDataWrapper *
 GetForeignDataWrapper(Oid fdwid)
@@ -114,15 +60,7 @@ GetForeignDataWrapper(Oid fdwid)
        fdw->fdwid = fdwid;
        fdw->owner = fdwform->fdwowner;
        fdw->fdwname = pstrdup(NameStr(fdwform->fdwname));
-
-       /* Extract library name */
-       datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
-                                                       tp,
-                                                       Anum_pg_foreign_data_wrapper_fdwlibrary,
-                                                       &isnull);
-       fdw->fdwlibrary = pstrdup(TextDatumGetCString(datum));
-
-       fdw->lib = GetForeignDataWrapperLibrary(fdw->fdwlibrary);
+       fdw->fdwvalidator = fdwform->fdwvalidator;
 
        /* Extract the options */
        datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
@@ -387,3 +325,100 @@ pg_options_to_table(PG_FUNCTION_ARGS)
 
        return (Datum) 0;
 }
+
+
+/*
+ * Describes the valid options for postgresql FDW, server, and user mapping.
+ */
+struct ConnectionOption {
+       const char         *optname;
+       Oid                             optcontext;             /* Oid of catalog in which option may appear */
+};
+
+/*
+ * Copied from fe-connect.c PQconninfoOptions.
+ *
+ * The list is small - don't bother with bsearch if it stays so.
+ */
+static struct ConnectionOption libpq_conninfo_options[] = {
+       { "authtype",                   ForeignServerRelationId         },
+       { "service",                    ForeignServerRelationId         },
+       { "user",                               UserMappingRelationId           },
+       { "password",                   UserMappingRelationId           },
+       { "connect_timeout",    ForeignServerRelationId         },
+       { "dbname",                             ForeignServerRelationId         },
+       { "host",                               ForeignServerRelationId         },
+       { "hostaddr",                   ForeignServerRelationId         },
+       { "port",                               ForeignServerRelationId         },
+       { "tty",                                ForeignServerRelationId         },
+       { "options",                    ForeignServerRelationId         },
+       { "requiressl",                 ForeignServerRelationId         },
+       { "sslmode",                    ForeignServerRelationId         },
+       { "gsslib",                             ForeignServerRelationId         },
+       { NULL,                                 InvalidOid                                      }
+};
+
+
+/*
+ * Check if the provided option is one of libpq conninfo options.
+ * context is the Oid of the catalog the option came from, or 0 if we
+ * don't care.
+ */
+static bool
+is_conninfo_option(const char *option, Oid context)
+{
+       struct ConnectionOption *opt;
+
+       for (opt = libpq_conninfo_options; opt->optname; opt++)
+               if ((context == opt->optcontext || context == InvalidOid) && strcmp(opt->optname, option) == 0)
+                       return true;
+       return false;
+}
+
+
+/*
+ * Validate the generic option given to SERVER or USER MAPPING.
+ * Raise an ERROR if the option or its value is considered
+ * invalid.
+ *
+ * Valid server options are all libpq conninfo options except
+ * user and password -- these may only appear in USER MAPPING options.
+ */
+Datum
+postgresql_fdw_validator(PG_FUNCTION_ARGS)
+{
+       List* options_list = untransformRelOptions(PG_GETARG_DATUM(0));
+       Oid catalog = PG_GETARG_OID(1);
+
+       ListCell *cell;
+
+       foreach (cell, options_list)
+       {
+               DefElem    *def = lfirst(cell);
+
+               if (!is_conninfo_option(def->defname, catalog))
+               {
+                       struct ConnectionOption  *opt;
+                       StringInfoData          buf;
+
+                       /*
+                        * Unknown option specified, complain about it. Provide a hint
+                        * with list of valid options for the object.
+                        */
+                       initStringInfo(&buf);
+                       for (opt = libpq_conninfo_options; opt->optname; opt++)
+                               if (catalog == InvalidOid || catalog == opt->optcontext)
+                                       appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
+                                                                        opt->optname);
+
+                       ereport(ERROR,
+                                       (errcode(ERRCODE_SYNTAX_ERROR),
+                                        errmsg("invalid option \"%s\"", def->defname),
+                                        errhint("Valid options in this context are: %s", buf.data)));
+
+                       PG_RETURN_BOOL(false);
+               }
+       }
+
+       PG_RETURN_BOOL(true);
+}
diff --git a/src/backend/foreign/postgresql/Makefile b/src/backend/foreign/postgresql/Makefile
deleted file mode 100644 (file)
index 283ac76..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-#-------------------------------------------------------------------------
-#
-# Makefile--
-#    Makefile for postgresql foreign-data wrapper
-#
-# IDENTIFICATION
-#    $PostgreSQL$
-#
-#-------------------------------------------------------------------------
-
-subdir = src/backend/foreign/postgresql
-top_builddir = ../../../..
-include $(top_builddir)/src/Makefile.global
-
-NAME = postgresql_fdw
-OBJS = postgresql_fdw.o
-
-include $(top_srcdir)/src/Makefile.shlib
-
-all: all-shared-lib
-
-install: all install-lib
-
-installdirs: installdirs-lib
-
-clean distclean maintainer-clean: clean-lib
-       rm -f $(OBJS)
diff --git a/src/backend/foreign/postgresql/postgresql_fdw.c b/src/backend/foreign/postgresql/postgresql_fdw.c
deleted file mode 100644 (file)
index b1410fe..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * postgresql_fdw.c
- *        foreign-data wrapper for postgresql (libpq) connections.
- *
- * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
- *
- * IDENTIFICATION
- *        $PostgreSQL$
- *
- *-------------------------------------------------------------------------
- */
-#include "postgres.h"
-
-#include "fmgr.h"
-#include "lib/stringinfo.h"
-#include "nodes/value.h"
-#include "nodes/parsenodes.h"
-#include "nodes/makefuncs.h"
-#include "foreign/foreign.h"
-
-PG_MODULE_MAGIC;
-
-
-/*
- * Describes the valid options for postgresql FDW, server and user mapping.
- */
-typedef struct ConnectionOptions {
-       const char                 *optname;            /* Option name */
-       GenericOptionFlags      optflags;               /* Option usage bitmap */
-} ConnectionOptions;
-
-/*
- * Copied from fe-connect.c PQconninfoOptions.
- *
- * The list is small - don't bother with bsearch if it stays so.
- */
-static ConnectionOptions libpq_conninfo_options[] = {
-       { "authtype",                   ServerOpt               },
-       { "service",                    ServerOpt               },
-       { "user",                               UserMappingOpt  },
-       { "password",                   UserMappingOpt  },
-       { "connect_timeout",    ServerOpt               },
-       { "dbname",                             ServerOpt               },
-       { "host",                               ServerOpt               },
-       { "hostaddr",                   ServerOpt               },
-       { "port",                               ServerOpt               },
-       { "tty",                                ServerOpt               },
-       { "options",                    ServerOpt               },
-       { "requiressl",                 ServerOpt               },
-       { "sslmode",                    ServerOpt               },
-       { "gsslib",                             ServerOpt               },
-       { NULL,                                 InvalidOpt              }
-};
-
-void _PG_fini(void);
-
-
-/*
- * Check if the provided option is one of libpq conninfo options.
- * We look at only options with matching flags.
- */
-static bool
-is_conninfo_option(const char *option, GenericOptionFlags flags)
-{
-       ConnectionOptions *opt;
-
-       for (opt = libpq_conninfo_options; opt->optname != NULL; opt++)
-               if (flags & opt->optflags && strcmp(opt->optname, option) == 0)
-                       return true;
-       return false;
-}
-
-/*
- * Validate the generic option given to SERVER or USER MAPPING.
- * Raise an ERROR if the option or its value is considered
- * invalid.
- *
- * Valid server options are all libpq conninfo options except
- * user and password -- these may only appear in USER MAPPING options.
- */
-void
-_pg_validateOptionList(ForeignDataWrapper *fdw, GenericOptionFlags flags,
-                                  List *options)
-{
-       ListCell *cell;
-
-       foreach (cell, options)
-       {
-               DefElem    *def = lfirst(cell);
-
-               if (!is_conninfo_option(def->defname, flags))
-               {
-                       ConnectionOptions  *opt;
-                       StringInfoData          buf;
-                       const char                 *objtype;
-
-                       /*
-                        * Unknown option specified, complain about it. Provide a hint
-                        * with list of valid options for the object.
-                        */
-                       initStringInfo(&buf);
-                       for (opt = libpq_conninfo_options; opt->optname != NULL; opt++)
-                               if (flags & opt->optflags)
-                                       appendStringInfo(&buf, "%s%s", (buf.len > 0) ? ", " : "",
-                                                                        opt->optname);
-
-                       if (flags & ServerOpt)
-                               objtype = "server";
-                       else if (flags & UserMappingOpt)
-                               objtype = "user mapping";
-                       else if (flags & FdwOpt)
-                               objtype = "foreign-data wrapper";
-                       else
-                               objtype = "???";
-
-                       ereport(ERROR,
-                                       (errcode(ERRCODE_SYNTAX_ERROR),
-                                        errmsg("invalid option \"%s\" to %s", def->defname, objtype),
-                                        errhint("valid %s options are: %s", objtype, buf.data)));
-               }
-       }
-}
index e719a174933119458e102ad2cbf3e68b4fc2d212..b522bc884d8d9119f0658e4eb5bab639b1d43b88 100644 (file)
@@ -2994,7 +2994,7 @@ _copyCreateFdwStmt(CreateFdwStmt *from)
        CreateFdwStmt *newnode = makeNode(CreateFdwStmt);
 
        COPY_STRING_FIELD(fdwname);
-       COPY_STRING_FIELD(library);
+       COPY_NODE_FIELD(validator);
        COPY_NODE_FIELD(options);
 
        return newnode;
@@ -3006,7 +3006,8 @@ _copyAlterFdwStmt(AlterFdwStmt *from)
        AlterFdwStmt *newnode = makeNode(AlterFdwStmt);
 
        COPY_STRING_FIELD(fdwname);
-       COPY_STRING_FIELD(library);
+       COPY_NODE_FIELD(validator);
+       COPY_SCALAR_FIELD(change_validator);
        COPY_NODE_FIELD(options);
 
        return newnode;
index 4da928b79523a96c01625ad412cb5f486044a676..ac20256c85dea6588394455170eee66cf704f07e 100644 (file)
@@ -1548,7 +1548,7 @@ static bool
 _equalCreateFdwStmt(CreateFdwStmt *a, CreateFdwStmt *b)
 {
        COMPARE_STRING_FIELD(fdwname);
-       COMPARE_STRING_FIELD(library);
+       COMPARE_NODE_FIELD(validator);
        COMPARE_NODE_FIELD(options);
 
        return true;
@@ -1558,7 +1558,8 @@ static bool
 _equalAlterFdwStmt(AlterFdwStmt *a, AlterFdwStmt *b)
 {
        COMPARE_STRING_FIELD(fdwname);
-       COMPARE_STRING_FIELD(library);
+       COMPARE_NODE_FIELD(validator);
+       COMPARE_SCALAR_FIELD(change_validator);
        COMPARE_NODE_FIELD(options);
 
        return true;
index 9fdfced7a8ad3e1bb833f1aa9cca1f8a33361abe..920479435df54c07e821510bffbd06932aa34b96 100644 (file)
@@ -254,7 +254,7 @@ static TypeName *TableFuncTypeName(List *columns);
                                index_name name file_name cluster_index_specification
 
 %type <list>   func_name handler_name qual_Op qual_all_Op subquery_Op
-                               opt_class opt_validator
+                               opt_class opt_validator validator_clause
 
 %type <range>  qualified_name OptConstrFromTable
 
@@ -469,7 +469,7 @@ static TypeName *TableFuncTypeName(List *columns);
        KEY
 
        LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEAST LEFT LEVEL
-       LIBRARY LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
+       LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
        LOCK_P LOGIN_P
 
        MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
@@ -2724,8 +2724,13 @@ handler_name:
                        | name attrs                            { $$ = lcons(makeString($1), $2); }
                ;
 
-opt_validator:
+validator_clause:
                        VALIDATOR handler_name                                  { $$ = $2; }
+                       | NO VALIDATOR                                                  { $$ = NIL; }
+               ;
+
+opt_validator:
+                       validator_clause                                                { $$ = $1; }
                        | /*EMPTY*/                                                             { $$ = NIL; }
                ;
 
@@ -2808,23 +2813,17 @@ DropTableSpaceStmt: DROP TABLESPACE name
 /*****************************************************************************
  *
  *             QUERY:
- *             CREATE FOREIGN DATA WRAPPER name LIBRARY 'library_name' LANGUAGE C
+ *             CREATE FOREIGN DATA WRAPPER name [ VALIDATOR name ]
  *
  *****************************************************************************/
 
-CreateFdwStmt: CREATE FOREIGN DATA_P WRAPPER name LIBRARY Sconst LANGUAGE ColId create_generic_options
+CreateFdwStmt: CREATE FOREIGN DATA_P WRAPPER name opt_validator create_generic_options
                                {
                                        CreateFdwStmt *n = makeNode(CreateFdwStmt);
                                        n->fdwname = $5;
-                                       n->library = $7;
-                                       n->options = $10;
+                                       n->validator = $6;
+                                       n->options = $7;
                                        $$ = (Node *) n;
-
-                                       if (pg_strcasecmp($9, "C") != 0)
-                                               ereport(ERROR,
-                                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                                errmsg("language for foreign-data wrapper must be C"),
-                                                                scanner_errposition(@9)));
                                }
                ;
 
@@ -2860,19 +2859,21 @@ DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
  *
  ****************************************************************************/
 
-AlterFdwStmt: ALTER FOREIGN DATA_P WRAPPER name LIBRARY Sconst alter_generic_options
+AlterFdwStmt: ALTER FOREIGN DATA_P WRAPPER name validator_clause alter_generic_options
                                {
                                        AlterFdwStmt *n = makeNode(AlterFdwStmt);
                                        n->fdwname = $5;
-                                       n->library = $7;
-                                       n->options = $8;
+                                       n->validator = $6;
+                                       n->change_validator = true;
+                                       n->options = $7;
                                        $$ = (Node *) n;
                                }
-                       | ALTER FOREIGN DATA_P WRAPPER name LIBRARY Sconst
+                       | ALTER FOREIGN DATA_P WRAPPER name validator_clause
                                {
                                        AlterFdwStmt *n = makeNode(AlterFdwStmt);
                                        n->fdwname = $5;
-                                       n->library = $7;
+                                       n->validator = $6;
+                                       n->change_validator = true;
                                        $$ = (Node *) n;
                                }
                        | ALTER FOREIGN DATA_P WRAPPER name alter_generic_options
@@ -10231,7 +10232,6 @@ unreserved_keyword:
                        | INVOKER
                        | ISOLATION
                        | KEY
-                       | LIBRARY
                        | LANCOMPILER
                        | LANGUAGE
                        | LARGE_P
index 47b2458f3801d6bebcf9247e77070a44e11ca74d..888c6b8fc3db0ba8bbd890cff839bf1fe6e2ccd9 100644 (file)
@@ -230,7 +230,6 @@ const ScanKeyword ScanKeywords[] = {
        {"least", LEAST, COL_NAME_KEYWORD},
        {"left", LEFT, TYPE_FUNC_NAME_KEYWORD},
        {"level", LEVEL, UNRESERVED_KEYWORD},
-       {"library", LIBRARY, UNRESERVED_KEYWORD},
        {"like", LIKE, TYPE_FUNC_NAME_KEYWORD},
        {"limit", LIMIT, RESERVED_KEYWORD},
        {"listen", LISTEN, UNRESERVED_KEYWORD},
index 32a8ae6c2fc3198eeb0527ad2b5fb321c1e20291..2ef634d739f87452b82c822529cc77bc49bee690 100644 (file)
@@ -5394,7 +5394,7 @@ getForeignDataWrappers(int *numForeignDataWrappers)
        int                     i_oid;
        int                     i_fdwname;
        int                     i_rolname;
-       int                     i_fdwlibrary;
+       int                     i_fdwvalidator;
        int                     i_fdwacl;
        int                     i_fdwoptions;
 
@@ -5409,7 +5409,7 @@ getForeignDataWrappers(int *numForeignDataWrappers)
        selectSourceSchema("pg_catalog");
 
        appendPQExpBuffer(query, "SELECT oid, fdwname, "
-                                         "(%s fdwowner) AS rolname, fdwlibrary, fdwacl,"
+                                         "(%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 "
@@ -5427,7 +5427,7 @@ getForeignDataWrappers(int *numForeignDataWrappers)
        i_oid = PQfnumber(res, "oid");
        i_fdwname = PQfnumber(res, "fdwname");
        i_rolname = PQfnumber(res, "rolname");
-       i_fdwlibrary = PQfnumber(res, "fdwlibrary");
+       i_fdwvalidator = PQfnumber(res, "fdwvalidator");
        i_fdwacl = PQfnumber(res, "fdwacl");
        i_fdwoptions = PQfnumber(res, "fdwoptions");
 
@@ -5439,7 +5439,7 @@ getForeignDataWrappers(int *numForeignDataWrappers)
                fdwinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_fdwname));
                fdwinfo[i].dobj.namespace = NULL;
                fdwinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
-               fdwinfo[i].fdwlibrary = strdup(PQgetvalue(res, i, i_fdwlibrary));
+               fdwinfo[i].fdwvalidator = strdup(PQgetvalue(res, i, i_fdwvalidator));
                fdwinfo[i].fdwoptions = strdup(PQgetvalue(res, i, i_fdwoptions));
                fdwinfo[i].fdwacl = strdup(PQgetvalue(res, i, i_fdwacl));
 
@@ -9308,8 +9308,13 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
        q = createPQExpBuffer();
        delq = createPQExpBuffer();
 
-       appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s LIBRARY '%s' LANGUAGE C",
-                                         fmtId(fdwinfo->dobj.name), fdwinfo->fdwlibrary);
+       appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s",
+                                         fmtId(fdwinfo->dobj.name));
+
+       if (fdwinfo->fdwvalidator && strcmp(fdwinfo->fdwvalidator, "-") != 0)
+               appendPQExpBuffer(q, " VALIDATOR %s",
+                                                 fdwinfo->fdwvalidator);
+
        if (fdwinfo->fdwoptions && strlen(fdwinfo->fdwoptions) > 0)
                appendPQExpBuffer(q, " OPTIONS (%s)", fdwinfo->fdwoptions);
 
index 8949f01482773e770ce5931641f9a2626ef8d2bf..067f005500fe64aa956c31bacf5b209acf8456d3 100644 (file)
@@ -409,7 +409,7 @@ typedef struct _fdwInfo
 {
        DumpableObject dobj;
        char       *rolname;
-       char       *fdwlibrary;
+       char       *fdwvalidator;
        char       *fdwoptions;
        char       *fdwacl;
 } FdwInfo;
index fb61fd522bfe0629325080c0a867520541ffc6a6..e21add728f1b4a02a1825137918933544cf848f6 100644 (file)
@@ -2894,10 +2894,10 @@ listForeignDataWrappers(const char *pattern, bool verbose)
        printfPQExpBuffer(&buf,
                                          "SELECT fdwname AS \"%s\",\n"
                                          "  pg_catalog.pg_get_userbyid(fdwowner) AS \"%s\",\n"
-                                         "  fdwlibrary AS \"%s\"",
+                                         "  fdwvalidator::pg_catalog.regproc AS \"%s\"",
                                          gettext_noop("Name"),
                                          gettext_noop("Owner"),
-                                         gettext_noop("Library"));
+                                         gettext_noop("Validator"));
 
        if (verbose)
        {
index ecbe2a63cacf10fb9027d8dff86acc4599dbad41..6241cfec0408ce3c10f45fee673c8bfe541fd5a0 100644 (file)
@@ -749,7 +749,7 @@ psql_completion(char *text, int start, int end)
                         pg_strcasecmp(prev2_wd, "WRAPPER") == 0)
        {
                static const char *const list_ALTER_FDW[] =
-               {"LIBRARY", "OPTIONS", "OWNER TO", NULL};
+               {"VALIDATOR", "OPTIONS", "OWNER TO", NULL};
 
                COMPLETE_WITH_LIST(list_ALTER_FDW);
        }
@@ -1258,12 +1258,7 @@ psql_completion(char *text, int start, int end)
                         pg_strcasecmp(prev4_wd, "FOREIGN") == 0 &&
                         pg_strcasecmp(prev3_wd, "DATA") == 0 &&
                         pg_strcasecmp(prev2_wd, "WRAPPER") == 0)
-               COMPLETE_WITH_CONST("LIBRARY");
-
-       else if (pg_strcasecmp(prev5_wd, "DATA") == 0 &&
-                        pg_strcasecmp(prev4_wd, "WRAPPER") == 0 &&
-                        pg_strcasecmp(prev2_wd, "LIBRARY") == 0)
-               COMPLETE_WITH_CONST("LANGUAGE C");
+               COMPLETE_WITH_CONST("VALIDATOR");
 
        /* CREATE INDEX */
        /* First off we complete CREATE UNIQUE with "INDEX" */
index 06490e0da8f1751105799fbfb41e0e849858bc68..3186538449b328bd5a11dc0314c916d75a7db4c7 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     200902092
+#define CATALOG_VERSION_NO     200902242
 
 #endif
index 280102f13071cb7393c777d8e1c86476795ff2d3..73ff3bd2ae327bcf208d4b50bb3fd9f4d5f89650 100644 (file)
@@ -32,10 +32,10 @@ CATALOG(pg_foreign_data_wrapper,2328)
 {
        NameData        fdwname;                /* foreign-data wrapper name */
        Oid                     fdwowner;               /* FDW owner */
+       Oid                     fdwvalidator;   /* optional validation function */
 
        /* VARIABLE LENGTH FIELDS start here. */
 
-       text            fdwlibrary;             /* FDW shared library location */
        aclitem         fdwacl[1];              /* access permissions */
        text            fdwoptions[1];  /* FDW options */
 } FormData_pg_foreign_data_wrapper;
@@ -55,7 +55,7 @@ typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
 #define Natts_pg_foreign_data_wrapper                          5
 #define Anum_pg_foreign_data_wrapper_fdwname           1
 #define Anum_pg_foreign_data_wrapper_fdwowner          2
-#define Anum_pg_foreign_data_wrapper_fdwlibrary                3
+#define Anum_pg_foreign_data_wrapper_fdwvalidator      3
 #define Anum_pg_foreign_data_wrapper_fdwacl                    4
 #define Anum_pg_foreign_data_wrapper_fdwoptions                5
 
index 9a054a27b0627c3b795e432f53a753d7f2ae5d88..4479ea468005af770f07bdb499fe788f4393e3f3 100644 (file)
@@ -3682,6 +3682,8 @@ DESCR("total disk space usage for the specified table and associated indexes and
 DATA(insert OID = 2288 ( pg_size_pretty                        PGNSP PGUID 12 1 0 0 f f f t f v 1 0 25 "20" _null_ _null_ _null_ _null_ pg_size_pretty _null_ _null_ _null_ ));
 DESCR("convert a long int to a human readable text using size units");
 
+DATA(insert OID = 2316 ( postgresql_fdw_validator PGNSP PGUID 12 1 0 0 f f f t f i 2 0 16 "1009 26" _null_ _null_ _null_ _null_ postgresql_fdw_validator _null_ _null_ _null_));
+
 DATA(insert OID = 2290 (  record_in                    PGNSP PGUID 12 1 0 0 f f f t f v 3 0 2249 "2275 26 23" _null_ _null_ _null_ _null_      record_in _null_ _null_ _null_ ));
 DESCR("I/O");
 DATA(insert OID = 2291 (  record_out           PGNSP PGUID 12 1 0 0 f f f t f v 1 0 2275 "2249" _null_ _null_ _null_ _null_ record_out _null_ _null_ _null_ ));
index 2c6ed994bffb616d28d380bac393df3313bdd8df..e068e682a3e618bd2b0da0d6fa1f102a752aeb3f 100644 (file)
@@ -33,17 +33,13 @@ typedef enum {
        FdwOpt = 4,                                     /* options for FOREIGN DATA WRAPPER */
 } GenericOptionFlags;
 
-typedef struct ForeignDataWrapperLibrary ForeignDataWrapperLibrary;
-
 typedef struct ForeignDataWrapper
 {
        Oid             fdwid;                          /* FDW Oid */
        Oid             owner;                          /* FDW owner user Oid */
        char   *fdwname;                        /* Name of the FDW */
-       char   *fdwlibrary;                     /* Library name */
+       Oid             fdwvalidator;
        List   *options;                        /* fdwoptions as DefElem list */
-
-       ForeignDataWrapperLibrary *lib; /* interface to the FDW functions */
 } ForeignDataWrapper;
 
 typedef struct ForeignServer
@@ -65,25 +61,6 @@ typedef struct UserMapping
 } UserMapping;
 
 
-/*
- * Foreign-data wrapper library function types.
- */
-typedef void (*OptionListValidatorFunc)(ForeignDataWrapper *,
-                                                                               GenericOptionFlags,
-                                                                               List *);
-
-/*
- * Interface functions to the foreign-data wrapper. This is decoupled
- * from the FDW as there maybe several FDW-s accessing the same library.
- */
-struct ForeignDataWrapperLibrary
-{
-       char       *libname;            /* name of the library file */
-
-       OptionListValidatorFunc validateOptionList;
-};
-
-
 extern ForeignServer *GetForeignServer(Oid serverid);
 extern ForeignServer *GetForeignServerByName(const char *name, bool missing_ok);
 extern Oid GetForeignServerOidByName(const char *name, bool missing_ok);
@@ -92,7 +69,6 @@ extern ForeignDataWrapper *GetForeignDataWrapper(Oid fdwid);
 extern ForeignDataWrapper *GetForeignDataWrapperByName(const char *name,
                                                                                                           bool missing_ok);
 extern Oid GetForeignDataWrapperOidByName(const char *name, bool missing_ok);
-extern ForeignDataWrapperLibrary *GetForeignDataWrapperLibrary(const char *libname);
 
 /* Foreign data wrapper interface functions */
 extern void _pg_validateOptionList(ForeignDataWrapper *fdw,
index 8392c351635e3c5fbeda6af6a4266282f35f5705..3fc17b5a707baa30d9b8387ffffda046c37a8083 100644 (file)
@@ -1468,7 +1468,7 @@ typedef struct CreateFdwStmt
 {
        NodeTag         type;
        char       *fdwname;            /* foreign-data wrapper name */
-       char       *library;            /* libray name */
+       List       *validator;          /* optional validator function (qual. name) */
        List       *options;            /* generic options to FDW */
 } CreateFdwStmt;
 
@@ -1476,7 +1476,8 @@ typedef struct AlterFdwStmt
 {
        NodeTag         type;
        char       *fdwname;            /* foreign-data wrapper name */
-       char       *library;            /* libray name */
+       List       *validator;          /* optional validator function (qual. name) */
+       bool            change_validator;
        List       *options;            /* generic options to FDW */
 } AlterFdwStmt;
 
index 351c2d07822ec979fb05b81a42bca4c12202d709..229d57a09a7081bc005065dcc75a3cd8a9865ca9 100644 (file)
@@ -13,14 +13,14 @@ CREATE ROLE regress_test_role2;
 CREATE ROLE regress_test_role_super SUPERUSER;
 CREATE ROLE regress_test_indirect;
 CREATE ROLE unprivileged_role;
-CREATE FOREIGN DATA WRAPPER dummy LIBRARY 'dummy_fdw' LANGUAGE C;
-CREATE FOREIGN DATA WRAPPER postgresql LIBRARY 'postgresql_fdw' LANGUAGE C;
+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, fdwlibrary, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
-  fdwname   |   fdwlibrary   | fdwoptions 
-------------+----------------+------------
- dummy      | dummy_fdw      | 
- postgresql | postgresql_fdw | 
+SELECT fdwname, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+  fdwname   |       fdwvalidator       | fdwoptions 
+------------+--------------------------+------------
+ dummy      | -                        | 
+ postgresql | postgresql_fdw_validator | 
 (2 rows)
 
 SELECT srvname, srvoptions FROM pg_foreign_server;
@@ -34,78 +34,75 @@ SELECT * FROM pg_user_mapping;
 (0 rows)
 
 -- CREATE FOREIGN DATA WRAPPER
-CREATE FOREIGN DATA WRAPPER foo LIBRARY '' LANGUAGE C;            -- ERROR
-ERROR:  could not access file "": No such file or directory
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'plpgsql' LANGUAGE C;
-DROP FOREIGN DATA WRAPPER foo;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C;
+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       |    Library     
-------------+-------------------+----------------
- dummy      | foreign_data_user | dummy_fdw
- foo        | foreign_data_user | dummy_fdw
- postgresql | foreign_data_user | postgresql_fdw
+               List of foreign-data wrappers
+    Name    |       Owner       |        Validator         
+------------+-------------------+--------------------------
+ dummy      | foreign_data_user | -
+ foo        | foreign_data_user | -
+ postgresql | foreign_data_user | postgresql_fdw_validator
 (3 rows)
 
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C; -- duplicate
+CREATE FOREIGN DATA WRAPPER foo; -- duplicate
 ERROR:  foreign-data wrapper "foo" already exists
-CREATE FOREIGN DATA WRAPPER "Foo" LIBRARY 'dummy_fdw' LANGUAGE C;
-DROP FOREIGN DATA WRAPPER "Foo";
 DROP FOREIGN DATA WRAPPER foo;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C OPTIONS (testing '1');
+CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1');
 \dew+
-                           List of foreign-data wrappers
-    Name    |       Owner       |    Library     | Access privileges |   Options   
-------------+-------------------+----------------+-------------------+-------------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- foo        | foreign_data_user | dummy_fdw      |                   | {testing=1}
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                                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 |                   | 
 (3 rows)
 
 DROP FOREIGN DATA WRAPPER foo;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C OPTIONS (testing '1', testing '2');   -- ERROR
+CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', testing '2');   -- ERROR
 ERROR:  option "testing" provided more than once
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C OPTIONS (testing '1', another '2');
+CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', another '2');
 \dew+
-                                List of foreign-data wrappers
-    Name    |       Owner       |    Library     | Access privileges |        Options        
-------------+-------------------+----------------+-------------------+-----------------------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- foo        | foreign_data_user | dummy_fdw      |                   | {testing=1,another=2}
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                                     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 |                   | 
 (3 rows)
 
 DROP FOREIGN DATA WRAPPER foo;
 SET ROLE regress_test_role;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C; -- ERROR
+CREATE FOREIGN DATA WRAPPER foo; -- ERROR
 ERROR:  permission denied to create foreign-data wrapper "foo"
 HINT:  Must be superuser to create a foreign-data wrapper.
 RESET ROLE;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'postgresql_fdw' LANGUAGE C;
+CREATE FOREIGN DATA WRAPPER foo VALIDATOR postgresql_fdw_validator;
 \dew+
-                         List of foreign-data wrappers
-    Name    |       Owner       |    Library     | Access privileges | Options 
-------------+-------------------+----------------+-------------------+---------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- foo        | foreign_data_user | postgresql_fdw |                   | 
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                              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 |                   | 
 (3 rows)
 
 -- ALTER FOREIGN DATA WRAPPER
-ALTER FOREIGN DATA WRAPPER foo LIBRARY '';                  -- ERROR
-ERROR:  could not access file "": No such file or directory
-ALTER FOREIGN DATA WRAPPER foo LIBRARY 'plpgsql';
-WARNING:  changing the foreign-data wrapper library can cause the options for dependent objects to become invalid
-ALTER FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw';
-WARNING:  changing the foreign-data wrapper library can cause the options for dependent objects to become invalid
+ALTER FOREIGN DATA WRAPPER foo;                             -- ERROR
+ERROR:  syntax error at or near ";"
+LINE 1: ALTER FOREIGN DATA WRAPPER foo;
+                                      ^
+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       |    Library     | Access privileges | Options 
-------------+-------------------+----------------+-------------------+---------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- foo        | foreign_data_user | dummy_fdw      |                   | 
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                              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 |                   | 
 (3 rows)
 
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '1', b '2');
@@ -115,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       |    Library     | Access privileges |  Options  
-------------+-------------------+----------------+-------------------+-----------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- foo        | foreign_data_user | dummy_fdw      |                   | {a=1,b=2}
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                               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 |                   | 
 (3 rows)
 
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP a, SET b '3', ADD c '4');
 \dew+
-                          List of foreign-data wrappers
-    Name    |       Owner       |    Library     | Access privileges |  Options  
-------------+-------------------+----------------+-------------------+-----------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- foo        | foreign_data_user | dummy_fdw      |                   | {b=3,c=4}
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                               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 |                   | 
 (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       |    Library     | Access privileges |    Options    
-------------+-------------------+----------------+-------------------+---------------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- foo        | foreign_data_user | dummy_fdw      |                   | {b=3,c=4,a=2}
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                                 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 |                   | 
 (3 rows)
 
 SET ROLE regress_test_role;
@@ -152,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       |    Library     | Access privileges |      Options      
-------------+-------------------+----------------+-------------------+-------------------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- foo        | foreign_data_user | dummy_fdw      |                   | {b=3,c=4,a=2,d=5}
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                                   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 |                   | 
 (3 rows)
 
 ALTER FOREIGN DATA WRAPPER foo OWNER TO regress_test_role;  -- ERROR
@@ -171,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          |    Library     | Access privileges |      Options      
-------------+-------------------------+----------------+-------------------+-------------------
- dummy      | foreign_data_user       | dummy_fdw      |                   | 
- foo        | regress_test_role_super | dummy_fdw      |                   | {b=3,c=4,a=2,d=5}
- postgresql | foreign_data_user       | postgresql_fdw |                   | 
+                                      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 |                   | 
 (3 rows)
 
 -- DROP FOREIGN DATA WRAPPER
@@ -185,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          |    Library     | Access privileges |      Options      
-------------+-------------------------+----------------+-------------------+-------------------
- dummy      | foreign_data_user       | dummy_fdw      |                   | 
- foo        | regress_test_role_super | dummy_fdw      |                   | {b=3,c=4,a=2,d=5}
- postgresql | foreign_data_user       | postgresql_fdw |                   | 
+                                      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 |                   | 
 (3 rows)
 
 DROP ROLE regress_test_role_super;                          -- ERROR
@@ -205,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       |    Library     | Access privileges | Options 
-------------+-------------------+----------------+-------------------+---------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                              List of foreign-data wrappers
+    Name    |       Owner       |        Validator         | Access privileges | Options 
+------------+-------------------+--------------------------+-------------------+---------
+ dummy      | foreign_data_user | -                        |                   | 
+ postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
 (2 rows)
 
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C;
+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       |    Library     | Access privileges | Options 
-------------+-------------------+----------------+-------------------+---------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- foo        | foreign_data_user | dummy_fdw      |                   | 
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                              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 |                   | 
 (3 rows)
 
 \des+
@@ -253,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       |    Library     | Access privileges | Options 
-------------+-------------------+----------------+-------------------+---------
- dummy      | foreign_data_user | dummy_fdw      |                   | 
- postgresql | foreign_data_user | postgresql_fdw |                   | 
+                              List of foreign-data wrappers
+    Name    |       Owner       |        Validator         | Access privileges | Options 
+------------+-------------------+--------------------------+-------------------+---------
+ dummy      | foreign_data_user | -                        |                   | 
+ postgresql | foreign_data_user | postgresql_fdw_validator |                   | 
 (2 rows)
 
 \des+
@@ -275,7 +272,7 @@ drop cascades to user mapping for foreign_data_user
 -- exercise CREATE SERVER
 CREATE SERVER s1 FOREIGN DATA WRAPPER foo;                  -- ERROR
 ERROR:  foreign-data wrapper "foo" does not exist
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C OPTIONS (test_wrapper 'true');
+CREATE FOREIGN DATA WRAPPER foo OPTIONS (test_wrapper 'true');
 CREATE SERVER s1 FOREIGN DATA WRAPPER foo;
 CREATE SERVER s1 FOREIGN DATA WRAPPER foo;                  -- ERROR
 ERROR:  server "s1" already exists
@@ -286,8 +283,8 @@ CREATE SERVER s5 VERSION '15.0' FOREIGN DATA WRAPPER foo;
 CREATE SERVER s6 VERSION '16.0' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
 CREATE SERVER s7 TYPE 'oracle' VERSION '17.0' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
 CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (foo '1'); -- ERROR
-ERROR:  invalid option "foo" to server
-HINT:  valid server options are: authtype, service, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
+ERROR:  invalid option "foo"
+HINT:  Valid options in this context are: authtype, service, user, password, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
 CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (host 'localhost', dbname 's8db');
 \des+
                                                 List of foreign servers
@@ -397,8 +394,8 @@ ALTER SERVER s1 OWNER TO regress_test_role2;                -- ERROR
 ERROR:  permission denied for foreign-data wrapper foo
 RESET ROLE;
 ALTER SERVER s8 OPTIONS (foo '1');                          -- ERROR option validation
-ERROR:  invalid option "foo" to server
-HINT:  valid server options are: authtype, service, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
+ERROR:  invalid option "foo"
+HINT:  Valid options in this context are: authtype, service, user, password, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
 ALTER SERVER s8 OPTIONS (connect_timeout '30', SET dbname 'db1', DROP host);
 SET ROLE regress_test_role;
 ALTER SERVER s1 OWNER TO regress_test_indirect;             -- ERROR
@@ -536,8 +533,8 @@ CREATE USER MAPPING FOR user SERVER s4;                     -- ERROR duplicate
 ERROR:  user mapping "foreign_data_user" already exists for server s4
 CREATE USER MAPPING FOR public SERVER s4 OPTIONS (mapping 'is public');
 CREATE USER MAPPING FOR user SERVER s8 OPTIONS (username 'test', password 'secret');    -- ERROR
-ERROR:  invalid option "username" to user mapping
-HINT:  valid user mapping options are: user, password
+ERROR:  invalid option "username"
+HINT:  Valid options in this context are: authtype, service, user, password, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
 CREATE USER MAPPING FOR user SERVER s8 OPTIONS (user 'test', password 'secret');
 ALTER SERVER s5 OWNER TO regress_test_role;
 ALTER SERVER s6 OWNER TO regress_test_indirect;
@@ -575,8 +572,8 @@ ERROR:  server "ss4" does not exist
 ALTER USER MAPPING FOR public SERVER s5 OPTIONS (gotcha 'true');            -- ERROR
 ERROR:  user mapping "public" does not exist for the server
 ALTER USER MAPPING FOR current_user SERVER s8 OPTIONS (username 'test');    -- ERROR
-ERROR:  invalid option "username" to user mapping
-HINT:  valid user mapping options are: user, password
+ERROR:  invalid option "username"
+HINT:  Valid options in this context are: authtype, service, user, password, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib
 ALTER USER MAPPING FOR current_user SERVER s8 OPTIONS (DROP user, SET password 'public');
 SET ROLE regress_test_role;
 ALTER USER MAPPING FOR current_user SERVER s5 OPTIONS (ADD modified '1');
@@ -632,11 +629,11 @@ DROP SERVER s7;
 
 -- Information schema
 SELECT * FROM information_schema.foreign_data_wrappers ORDER BY 1, 2;
- foreign_data_wrapper_catalog | foreign_data_wrapper_name | authorization_identifier |  library_name  | foreign_data_wrapper_language 
-------------------------------+---------------------------+--------------------------+----------------+-------------------------------
- regression                   | dummy                     | foreign_data_user        | dummy_fdw      | c
- regression                   | foo                       | foreign_data_user        | dummy_fdw      | c
- regression                   | postgresql                | foreign_data_user        | postgresql_fdw | c
+ foreign_data_wrapper_catalog | foreign_data_wrapper_name | authorization_identifier | library_name | foreign_data_wrapper_language 
+------------------------------+---------------------------+--------------------------+--------------+-------------------------------
+ regression                   | dummy                     | foreign_data_user        |              | c
+ regression                   | foo                       | foreign_data_user        |              | c
+ regression                   | postgresql                | foreign_data_user        |              | c
 (3 rows)
 
 SELECT * FROM information_schema.foreign_data_wrapper_options ORDER BY 1, 2, 3;
@@ -847,13 +844,11 @@ GRANT USAGE ON FOREIGN SERVER s4 TO regress_test_role;
 DROP USER MAPPING FOR public SERVER s4;
 ALTER SERVER s6 OPTIONS (DROP host, DROP dbname);
 ALTER USER MAPPING FOR regress_test_role SERVER s6 OPTIONS (DROP username);
-ALTER FOREIGN DATA WRAPPER foo LIBRARY 'plpgsql';
-WARNING:  changing the foreign-data wrapper library can cause the options for dependent objects to become invalid
-ALTER FOREIGN DATA WRAPPER foo LIBRARY 'default_fdw';
-ERROR:  could not access file "default_fdw": No such file or directory
+ALTER FOREIGN DATA WRAPPER foo VALIDATOR postgresql_fdw_validator;
+WARNING:  changing the foreign-data wrapper validator can cause the options for dependent objects to become invalid
 -- Privileges
 SET ROLE unprivileged_role;
-CREATE FOREIGN DATA WRAPPER foobar LIBRARY 'dummy_fdw' LANGUAGE C; -- ERROR
+CREATE FOREIGN DATA WRAPPER foobar;                             -- ERROR
 ERROR:  permission denied to create foreign-data wrapper "foobar"
 HINT:  Must be superuser to create a foreign-data wrapper.
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (gotcha 'true');         -- ERROR
@@ -887,7 +882,7 @@ RESET ROLE;
 GRANT USAGE ON FOREIGN DATA WRAPPER postgresql TO unprivileged_role;
 GRANT USAGE ON FOREIGN DATA WRAPPER foo TO unprivileged_role WITH GRANT OPTION;
 SET ROLE unprivileged_role;
-CREATE FOREIGN DATA WRAPPER foobar LIBRARY 'dummy_fdw' LANGUAGE C; -- ERROR
+CREATE FOREIGN DATA WRAPPER foobar;                             -- ERROR
 ERROR:  permission denied to create foreign-data wrapper "foobar"
 HINT:  Must be superuser to create a foreign-data wrapper.
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (gotcha 'true');         -- ERROR
@@ -982,9 +977,9 @@ DROP FOREIGN DATA WRAPPER dummy CASCADE;
 \c
 DROP ROLE foreign_data_user;
 -- At this point we should have no wrappers, no servers, and no mappings.
-SELECT fdwname, fdwlibrary, fdwoptions FROM pg_foreign_data_wrapper;
- fdwname | fdwlibrary | fdwoptions 
----------+------------+------------
+SELECT fdwname, fdwvalidator, fdwoptions FROM pg_foreign_data_wrapper;
+ fdwname | fdwvalidator | fdwoptions 
+---------+--------------+------------
 (0 rows)
 
 SELECT srvname, srvoptions FROM pg_foreign_server;
index c52fe912c1d128b65ce93fbc871f59cbae567eb3..4318de5c7c7a1557b6c73b5edf3bf3a4b50c8492 100644 (file)
@@ -20,44 +20,40 @@ CREATE ROLE regress_test_role_super SUPERUSER;
 CREATE ROLE regress_test_indirect;
 CREATE ROLE unprivileged_role;
 
-CREATE FOREIGN DATA WRAPPER dummy LIBRARY 'dummy_fdw' LANGUAGE C;
-CREATE FOREIGN DATA WRAPPER postgresql LIBRARY 'postgresql_fdw' LANGUAGE C;
+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, fdwlibrary, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+SELECT fdwname, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
 SELECT srvname, srvoptions FROM pg_foreign_server;
 SELECT * FROM pg_user_mapping;
 
 -- CREATE FOREIGN DATA WRAPPER
-CREATE FOREIGN DATA WRAPPER foo LIBRARY '' LANGUAGE C;            -- ERROR
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'plpgsql' LANGUAGE C;
-DROP FOREIGN DATA WRAPPER foo;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C;
+CREATE FOREIGN DATA WRAPPER foo VALIDATOR bar;            -- ERROR
+CREATE FOREIGN DATA WRAPPER foo;
 \dew
 
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C; -- duplicate
-CREATE FOREIGN DATA WRAPPER "Foo" LIBRARY 'dummy_fdw' LANGUAGE C;
-DROP FOREIGN DATA WRAPPER "Foo";
+CREATE FOREIGN DATA WRAPPER foo; -- duplicate
 DROP FOREIGN DATA WRAPPER foo;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C OPTIONS (testing '1');
+CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1');
 \dew+
 
 DROP FOREIGN DATA WRAPPER foo;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C OPTIONS (testing '1', testing '2');   -- ERROR
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C OPTIONS (testing '1', another '2');
+CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', testing '2');   -- ERROR
+CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', another '2');
 \dew+
 
 DROP FOREIGN DATA WRAPPER foo;
 SET ROLE regress_test_role;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C; -- ERROR
+CREATE FOREIGN DATA WRAPPER foo; -- ERROR
 RESET ROLE;
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'postgresql_fdw' LANGUAGE C;
+CREATE FOREIGN DATA WRAPPER foo VALIDATOR postgresql_fdw_validator;
 \dew+
 
 -- ALTER FOREIGN DATA WRAPPER
-ALTER FOREIGN DATA WRAPPER foo LIBRARY '';                  -- ERROR
-ALTER FOREIGN DATA WRAPPER foo LIBRARY 'plpgsql';
-ALTER FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw';
+ALTER FOREIGN DATA WRAPPER foo;                             -- ERROR
+ALTER FOREIGN DATA WRAPPER foo VALIDATOR bar;               -- ERROR
+ALTER FOREIGN DATA WRAPPER foo NO VALIDATOR;
 \dew+
 
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '1', b '2');
@@ -101,7 +97,7 @@ DROP FOREIGN DATA WRAPPER foo;
 DROP ROLE regress_test_role_super;
 \dew+
 
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C;
+CREATE FOREIGN DATA WRAPPER foo;
 CREATE SERVER s1 FOREIGN DATA WRAPPER foo;
 CREATE USER MAPPING FOR current_user SERVER s1;
 \dew+
@@ -118,7 +114,7 @@ DROP FOREIGN DATA WRAPPER foo CASCADE;
 
 -- exercise CREATE SERVER
 CREATE SERVER s1 FOREIGN DATA WRAPPER foo;                  -- ERROR
-CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C OPTIONS (test_wrapper 'true');
+CREATE FOREIGN DATA WRAPPER foo OPTIONS (test_wrapper 'true');
 CREATE SERVER s1 FOREIGN DATA WRAPPER foo;
 CREATE SERVER s1 FOREIGN DATA WRAPPER foo;                  -- ERROR
 CREATE SERVER s2 FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
@@ -313,12 +309,11 @@ GRANT USAGE ON FOREIGN SERVER s4 TO regress_test_role;
 DROP USER MAPPING FOR public SERVER s4;
 ALTER SERVER s6 OPTIONS (DROP host, DROP dbname);
 ALTER USER MAPPING FOR regress_test_role SERVER s6 OPTIONS (DROP username);
-ALTER FOREIGN DATA WRAPPER foo LIBRARY 'plpgsql';
-ALTER FOREIGN DATA WRAPPER foo LIBRARY 'default_fdw';
+ALTER FOREIGN DATA WRAPPER foo VALIDATOR postgresql_fdw_validator;
 
 -- Privileges
 SET ROLE unprivileged_role;
-CREATE FOREIGN DATA WRAPPER foobar LIBRARY 'dummy_fdw' LANGUAGE C; -- ERROR
+CREATE FOREIGN DATA WRAPPER foobar;                             -- ERROR
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (gotcha 'true');         -- ERROR
 ALTER FOREIGN DATA WRAPPER foo OWNER TO unprivileged_role;      -- ERROR
 DROP FOREIGN DATA WRAPPER foo;                                  -- ERROR
@@ -336,7 +331,7 @@ RESET ROLE;
 GRANT USAGE ON FOREIGN DATA WRAPPER postgresql TO unprivileged_role;
 GRANT USAGE ON FOREIGN DATA WRAPPER foo TO unprivileged_role WITH GRANT OPTION;
 SET ROLE unprivileged_role;
-CREATE FOREIGN DATA WRAPPER foobar LIBRARY 'dummy_fdw' LANGUAGE C; -- ERROR
+CREATE FOREIGN DATA WRAPPER foobar;                             -- ERROR
 ALTER FOREIGN DATA WRAPPER foo OPTIONS (gotcha 'true');         -- ERROR
 DROP FOREIGN DATA WRAPPER foo;                                  -- ERROR
 GRANT USAGE ON FOREIGN DATA WRAPPER postgresql TO regress_test_role; -- WARNING
@@ -391,6 +386,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, fdwlibrary, fdwoptions FROM pg_foreign_data_wrapper;
+SELECT fdwname, fdwvalidator, fdwoptions FROM pg_foreign_data_wrapper;
 SELECT srvname, srvoptions FROM pg_foreign_server;
 SELECT * FROM pg_user_mapping;