diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index bc1a826d38c..2a8f978f85c 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,4 +1,4 @@ - + @@ -2466,10 +2466,16 @@ - fdwlibrary - text - - File name of the library implementing this foreign-data wrapper + fdwvalidator + oid + pg_proc.oid + + 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. + diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml index f7f7d649563..5ea6da68a68 100644 --- a/doc/src/sgml/keywords.sgml +++ b/doc/src/sgml/keywords.sgml @@ -1,4 +1,4 @@ - + <acronym>SQL</acronym> Key Words @@ -2687,14 +2687,6 @@ reserved reserved - - LIBRARY - non-reserved - non-reserved - non-reserved - - - LIKE reserved (can be function or type) diff --git a/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml b/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml index 877c4755170..155c8944375 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 @@ @@ -21,7 +21,7 @@ PostgreSQL documentation ALTER FOREIGN DATA WRAPPER name - [ LIBRARY 'libraryname' ] + [ VALIDATOR valfunction | NO VALIDATOR ] [ OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ]) ] ALTER FOREIGN DATA WRAPPER name OWNER TO new_owner @@ -58,14 +58,14 @@ ALTER FOREIGN DATA WRAPPER name OWN - libraryname + VALIDATOR valfunction - New name of the foreign-data wrapper library. + Specifies a new foreign-data wrapper validator function. - 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 name OWN + + NO VALIDATOR + + + This is used to specify that the foreign-data wrapper should no + longer have a validator function. + + + + OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ] ) @@ -102,10 +112,10 @@ ALTER FOREIGN DATA WRAPPER dbi OPTIONS (ADD foo '1', DROP 'bar'); - Change the foreign-data wrapper dbi library - to /home/bob/mylibrary.so: + Change the foreign-data wrapper dbi validator + to bob.myvalidator: -ALTER FOREIGN DATA WRAPPER dbi LIBRARY '/home/bob/mylibrary.so'; +ALTER FOREIGN DATA WRAPPER dbi VALIDATOR bob.myvalidator; @@ -115,8 +125,9 @@ ALTER FOREIGN DATA WRAPPER dbi LIBRARY '/home/bob/mylibrary.so'; ALTER FOREIGN DATA WRAPPER conforms to ISO/IEC - 9075-9 (SQL/MED). The standard does not specify the OWNER - TO variant of the command. + 9075-9 (SQL/MED). The standard does not specify the + VALIDATOR and OWNER TO variants of the + command. diff --git a/doc/src/sgml/ref/create_foreign_data_wrapper.sgml b/doc/src/sgml/ref/create_foreign_data_wrapper.sgml index d46e8e66406..b8817103880 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 @@ @@ -21,8 +21,7 @@ PostgreSQL documentation CREATE FOREIGN DATA WRAPPER name - LIBRARY 'libraryname' - LANGUAGE C + [ VALIDATOR valfunction | NO VALIDATOR ] [ OPTIONS ( option 'value' [, ... ] ) ] @@ -59,25 +58,25 @@ CREATE FOREIGN DATA WRAPPER name - libraryname + VALIDATOR valfunction - 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 ; in particular, one can rely - on a search path and automatic addition of the system's standard - shared library file name extension. - - - - - - LANGUAGE C - - - Currently, only the C programming language is supported for - implementing foreign-data wrappers. + valfunction 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 NO + VALIDATOR 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 text[], which will + contain the array of options as stored in the system catalogs, + and one of type oid, 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 ereport() function. @@ -109,18 +108,11 @@ CREATE FOREIGN DATA WRAPPER name - 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. - - - - There are currently two foreign-data wrapper libraries - provided: dummy_fdw, which does nothing and - could be useful for testing, - and postgresql_fdw, which accepts options - corresponding to libpq connection parameters. + There is currently one foreign-data wrapper validator function + provided: + postgresql_fdw_validator, which accepts + options corresponding to libpq connection + parameters. @@ -128,28 +120,25 @@ CREATE FOREIGN DATA WRAPPER name Examples - Create a foreign-data wrapper dummy with - library dummy_fdw: + Create a foreign-data wrapper dummy: -CREATE FOREIGN DATA WRAPPER dummy LIBRARY 'dummy_fdw' LANGUAGE C; +CREATE FOREIGN DATA WRAPPER dummy; Create a foreign-data wrapper postgresql with - library postgresql_fdw: + validator function postgresql_fdw_validator: -CREATE FOREIGN DATA WRAPPER postgresql LIBRARY 'postgresql_fdw' LANGUAGE C; +CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator; - Create a foreign-data wrapper mywrapper with library - /home/bob/mywrapper.so and some options: + Create a foreign-data wrapper mywrapper with some + options: CREATE FOREIGN DATA WRAPPER mywrapper - LIBRARY '/home/bob/mywrapper.so' - LANGUAGE C OPTIONS (debug 'true'); @@ -161,8 +150,9 @@ CREATE FOREIGN DATA WRAPPER mywrapper CREATE FOREIGN DATA WRAPPER conforms to ISO/IEC 9075-9 (SQL/MED), with the exception that - the LIBRARY clause is not optional in - PostgreSQL. + the VALIDATOR clause is an extension and the + clauses LIBRARY and LANGUAGE + are not yet implemented in PostgreSQL. diff --git a/src/Makefile b/src/Makefile index 13cbeb97345..7b00776c4bd 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 4206e9eaf52..80132e27ea4 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 0967001aa3f..24052556a4b 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 b3cc209c161..dff0c775403 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 8a05ada0197..00000000000 --- 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 a89d68e0ae2..00000000000 --- 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 b5b502cc032..3ec42506777 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 40ed90f8d70..00000000000 --- 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 3fb4d2f8631..00000000000 --- 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 bc4232bdc8b..2175e0c0fc0 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 2b8b542e749..4d905dc945e 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 6688324e05a..3dadbcffdeb 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 func_name handler_name qual_Op qual_all_Op subquery_Op - opt_class opt_validator + opt_class opt_validator validator_clause %type 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 3f3388e7fef..48218df9c4b 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 824f2fb0904..1e971bc37cd 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 9a38645fd53..6c5e48f273a 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 beab9ca5281..0cc52c8b71a 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 d4b977bd6d2..363857542ea 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 08b2969d96f..784ba688919 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 c6d905ca1b9..bb7e903db36 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 d657e9826c3..b0c5be4323f 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 5792903aa41..dc5d2af87d0 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 23ffaabb4e1..a7f1514f617 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 351c2d07822..229d57a09a7 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'); -\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 | | -(3 rows) - -DROP FOREIGN DATA WRAPPER foo; -CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C 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'); \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 | | + 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 OPTIONS (testing '1', testing '2'); -- ERROR +ERROR: option "testing" provided more than once +CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', another '2'); +\dew+ + List of foreign-data wrappers + Name | Owner | Validator | Access privileges | Options +------------+-------------------+--------------------------+-------------------+----------------------- + dummy | foreign_data_user | - | | + foo | foreign_data_user | - | | {testing=1,another=2} + postgresql | foreign_data_user | postgresql_fdw_validator | | (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 c52fe912c1d..4318de5c7c7 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;