diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index bc1a826d38c48256db6ba29c957805ac471690db..2a8f978f85c34a3e893fd61b9ce05873bc32d2bd 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.197 2009/02/09 20:57:59 alvherre Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.198 2009/02/24 10:06:31 petere Exp $ --> <!-- Documentation of the system catalogs, directed toward PostgreSQL developers --> @@ -2466,10 +2466,16 @@ </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> diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml index f7f7d649563162c7e1a04b7d8e3cdb63daa66811..5ea6da68a6843bee33a68f6d6d2de3fce4b25e3a 100644 --- a/doc/src/sgml/keywords.sgml +++ b/doc/src/sgml/keywords.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.22 2008/12/19 16:25:16 petere Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.23 2009/02/24 10:06:31 petere Exp $ --> <appendix id="sql-keywords-appendix"> <title><acronym>SQL</acronym> Key Words</title> @@ -2687,14 +2687,6 @@ <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> diff --git a/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml b/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml index 877c475517064f4eaa421b47740bde1629c272cc..155c8944375035f74f0cbfdceb226155b6fe3e1c 100644 --- a/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml +++ b/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml,v 1.2 2009/02/24 10:06:32 petere Exp $ PostgreSQL documentation --> @@ -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> diff --git a/doc/src/sgml/ref/create_foreign_data_wrapper.sgml b/doc/src/sgml/ref/create_foreign_data_wrapper.sgml index d46e8e664065016fd69cdfdb95c70d0886bd1ab7..b881710388048cb7493ccf84b1c729f8e9a50522 100644 --- a/doc/src/sgml/ref/create_foreign_data_wrapper.sgml +++ b/doc/src/sgml/ref/create_foreign_data_wrapper.sgml @@ -1,5 +1,5 @@ <!-- -$PostgreSQL: pgsql/doc/src/sgml/ref/create_foreign_data_wrapper.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $ +$PostgreSQL: pgsql/doc/src/sgml/ref/create_foreign_data_wrapper.sgml,v 1.2 2009/02/24 10:06:32 petere Exp $ PostgreSQL documentation --> @@ -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> diff --git a/src/Makefile b/src/Makefile index 13cbeb973456f9aa94e3c4435fd89bbfcc11c15c..7b00776c4bdbc197ae3a6014e4a7b7565b536080 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,7 +4,7 @@ # # Copyright (c) 1994, Regents of the University of California # -# $PostgreSQL: pgsql/src/Makefile,v 1.44 2008/12/19 16:25:16 petere Exp $ +# $PostgreSQL: pgsql/src/Makefile,v 1.45 2009/02/24 10:06:32 petere Exp $ # #------------------------------------------------------------------------- @@ -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 $@ diff --git a/src/backend/catalog/information_schema.sql b/src/backend/catalog/information_schema.sql index 4206e9eaf525b7c32adba75b9667b641b3e8fa37..80132e27ea477b4f707f09bd0fd0db10438c4bc1 100644 --- a/src/backend/catalog/information_schema.sql +++ b/src/backend/catalog/information_schema.sql @@ -4,7 +4,7 @@ * * Copyright (c) 2003-2009, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.52 2009/02/14 20:48:36 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.53 2009/02/24 10:06:32 petere Exp $ */ /* @@ -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; diff --git a/src/backend/commands/foreigncmds.c b/src/backend/commands/foreigncmds.c index 0967001aa3f61fcb73d9d86d3d5cec7e26d0f932..24052556a4b000d126c35d8d44efc51c629d8c35 100644 --- a/src/backend/commands/foreigncmds.c +++ b/src/backend/commands/foreigncmds.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.5 2009/01/20 09:10:20 petere Exp $ + * $PostgreSQL: pgsql/src/backend/commands/foreigncmds.c,v 1.6 2009/02/24 10:06:32 petere Exp $ * *------------------------------------------------------------------------- */ @@ -20,11 +20,13 @@ #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; diff --git a/src/backend/foreign/Makefile b/src/backend/foreign/Makefile index b3cc209c1611feefaaba5381aa84c4f860d9bc6d..dff0c775403b43efb7371bd22fdbfb13c40fbb62 100644 --- a/src/backend/foreign/Makefile +++ b/src/backend/foreign/Makefile @@ -4,7 +4,7 @@ # Makefile for foreign # # IDENTIFICATION -# $PostgreSQL: pgsql/src/backend/foreign/Makefile,v 1.1 2008/12/19 16:25:17 petere Exp $ +# $PostgreSQL: pgsql/src/backend/foreign/Makefile,v 1.2 2009/02/24 10:06:32 petere Exp $ # #------------------------------------------------------------------------- @@ -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 index 8a05ada0197eaf37ca5d64757a29af29b1225762..0000000000000000000000000000000000000000 --- a/src/backend/foreign/dummy/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -#------------------------------------------------------------------------- -# -# Makefile-- -# Makefile for dummy foreign-data wrapper -# -# IDENTIFICATION -# $PostgreSQL: pgsql/src/backend/foreign/dummy/Makefile,v 1.1 2008/12/19 16:25:17 petere Exp $ -# -#------------------------------------------------------------------------- - -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 index a89d68e0ae23dce42e59352df8a1fcd8fcf00054..0000000000000000000000000000000000000000 --- a/src/backend/foreign/dummy/dummy_fdw.c +++ /dev/null @@ -1,24 +0,0 @@ -/*------------------------------------------------------------------------- - * - * dummy_fdw.c - * "dummy" foreign-data wrapper - * - * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group - * - * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/foreign/dummy/dummy_fdw.c,v 1.2 2009/01/01 17:23:42 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#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. - */ diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c index b5b502cc03285535118ec09563d912a7d665ece2..3ec425067773cd1c95f1ad395cb5a4cf5a328c5d 100644 --- a/src/backend/foreign/foreign.c +++ b/src/backend/foreign/foreign.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/foreign/foreign.c,v 1.2 2009/01/01 17:23:42 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/foreign/foreign.c,v 1.3 2009/02/24 10:06:32 petere Exp $ * *------------------------------------------------------------------------- */ @@ -31,66 +31,12 @@ 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 index 40ed90f8d7090f8a234ace8ab139e5e4ffccf424..0000000000000000000000000000000000000000 --- a/src/backend/foreign/postgresql/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -#------------------------------------------------------------------------- -# -# Makefile-- -# Makefile for postgresql foreign-data wrapper -# -# IDENTIFICATION -# $PostgreSQL: pgsql/src/backend/foreign/postgresql/Makefile,v 1.1 2008/12/19 16:25:17 petere Exp $ -# -#------------------------------------------------------------------------- - -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 index 3fb4d2f863140bf19e06276fc367d434865411e5..0000000000000000000000000000000000000000 --- a/src/backend/foreign/postgresql/postgresql_fdw.c +++ /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: pgsql/src/backend/foreign/postgresql/postgresql_fdw.c,v 1.2 2009/01/01 17:23:42 momjian Exp $ - * - *------------------------------------------------------------------------- - */ -#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))); - } - } -} diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index bc4232bdc8bc6de3c24a53da9319ea50cc217e17..2175e0c0fc056e6189a8283b2ffe162985fd0fa4 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.423 2009/02/06 23:43:23 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.424 2009/02/24 10:06:32 petere Exp $ * *------------------------------------------------------------------------- */ @@ -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; diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c index 2b8b542e7494e8abb805c415cf3c505c00cce97e..4d905dc945ef34445e46e939dafb2880fac927e1 100644 --- a/src/backend/nodes/equalfuncs.c +++ b/src/backend/nodes/equalfuncs.c @@ -22,7 +22,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.347 2009/02/02 19:31:39 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.348 2009/02/24 10:06:32 petere Exp $ * *------------------------------------------------------------------------- */ @@ -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; diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 6688324e05ab8f2ba43ed2421f6570ca5bd23b19..3dadbcffdeb24d6afb704f7f4a130fd8cd3e43e3 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.658 2009/02/11 21:11:16 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.659 2009/02/24 10:06:33 petere Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -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 diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c index 3f3388e7fefc75b99fab15024054999c7bc8e840..48218df9c4b03825b3b89b7f5e40c51c46821c78 100644 --- a/src/backend/parser/keywords.c +++ b/src/backend/parser/keywords.c @@ -11,7 +11,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.209 2009/01/01 17:23:45 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.210 2009/02/24 10:06:33 petere Exp $ * *------------------------------------------------------------------------- */ @@ -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}, diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 824f2fb090492eb19ee9cc3283c681e049a563bf..1e971bc37cd05fe8ecbfba46ee33dc52c0a01679 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12,7 +12,7 @@ * by PostgreSQL * * IDENTIFICATION - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.524 2009/02/18 12:07:07 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.525 2009/02/24 10:06:33 petere Exp $ * *------------------------------------------------------------------------- */ @@ -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); diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 9a38645fd532815e6d1887b9ae9c0a523a6a2fe7..6c5e48f273a68008833787feb38696f86c9ab306 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.152 2009/02/18 12:07:07 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.153 2009/02/24 10:06:34 petere Exp $ * *------------------------------------------------------------------------- */ @@ -409,7 +409,7 @@ typedef struct _fdwInfo { DumpableObject dobj; char *rolname; - char *fdwlibrary; + char *fdwvalidator; char *fdwoptions; char *fdwacl; } FdwInfo; diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index beab9ca5281eceffd8848574e27a1826420da3ad..0cc52c8b71a21892b16e87edadee38a9314a2347 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -8,7 +8,7 @@ * * Copyright (c) 2000-2009, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.200 2009/02/23 15:59:55 tgl Exp $ + * $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.201 2009/02/24 10:06:34 petere Exp $ */ #include "postgres_fe.h" @@ -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) { diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index d4b977bd6d2f833a13f37360fe56d7d5b73ddce2..363857542eaa45930cd27fde5897e28d2cb3a3b6 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3,7 +3,7 @@ * * Copyright (c) 2000-2009, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.179 2009/01/01 17:23:55 momjian Exp $ + * $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.180 2009/02/24 10:06:34 petere Exp $ */ /*---------------------------------------------------------------------- @@ -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" */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index 08b2969d96f8798aa6608523272841f252a06c2a..784ba6889193b76345a649674027797967df791d 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.523 2009/02/09 21:18:28 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.524 2009/02/24 10:06:34 petere Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200902092 +#define CATALOG_VERSION_NO 200902242 #endif diff --git a/src/include/catalog/pg_foreign_data_wrapper.h b/src/include/catalog/pg_foreign_data_wrapper.h index c6d905ca1b99e6aceb24333b8e56daf4aab23869..bb7e903db3690bea403834e70d8bd74b902eaa67 100644 --- a/src/include/catalog/pg_foreign_data_wrapper.h +++ b/src/include/catalog/pg_foreign_data_wrapper.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_foreign_data_wrapper.h,v 1.2 2009/01/01 17:23:57 momjian Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_foreign_data_wrapper.h,v 1.3 2009/02/24 10:06:34 petere Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -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 diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index d657e9826c3f4809488d67e289c8162d38a1da36..b0c5be4323f3893a75ba220a5e5da787c259e8e3 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.536 2009/02/06 21:15:11 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.537 2009/02/24 10:06:34 petere Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -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_ )); diff --git a/src/include/foreign/foreign.h b/src/include/foreign/foreign.h index 5792903aa41ddbf8cd89ac8ab4a075863aa97b04..dc5d2af87d09e1a83c30fc425023cd83fa9818a0 100644 --- a/src/include/foreign/foreign.h +++ b/src/include/foreign/foreign.h @@ -6,7 +6,7 @@ * * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/foreign/foreign.h,v 1.2 2009/01/01 17:23:59 momjian Exp $ + * $PostgreSQL: pgsql/src/include/foreign/foreign.h,v 1.3 2009/02/24 10:06:35 petere Exp $ * *------------------------------------------------------------------------- */ @@ -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, diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 23ffaabb4e11aa664115e9bab707238d3845f2ad..a7f1514f617eb0190a22208a8409423d58d20484 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -13,7 +13,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.391 2009/02/11 21:11:16 tgl Exp $ + * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.392 2009/02/24 10:06:35 petere Exp $ * *------------------------------------------------------------------------- */ @@ -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; diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out index 351c2d07822ec979fb05b81a42bca4c12202d709..229d57a09a7081bc005065dcc75a3cd8a9865ca9 100644 --- a/src/test/regress/expected/foreign_data.out +++ b/src/test/regress/expected/foreign_data.out @@ -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; diff --git a/src/test/regress/sql/foreign_data.sql b/src/test/regress/sql/foreign_data.sql index c52fe912c1d128b65ce93fbc871f59cbae567eb3..4318de5c7c7a1557b6c73b5edf3bf3a4b50c8492 100644 --- a/src/test/regress/sql/foreign_data.sql +++ b/src/test/regress/sql/foreign_data.sql @@ -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;