move_validator.patch
text/plain
Filename: move_validator.patch
Type: text/plain
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| contrib/dblink/dblink--1.0--1.1.sql | 0 | 0 |
| contrib/dblink/dblink--1.1.sql | 0 | 0 |
| contrib/dblink/dblink.c | 0 | 0 |
| contrib/dblink/dblink.control | 0 | 0 |
| contrib/dblink/dblink.h | 0 | 0 |
| contrib/dblink/expected/dblink.out | 0 | 0 |
| contrib/dblink/Makefile | 0 | 0 |
| contrib/dblink/sql/dblink.sql | 0 | 0 |
| doc/src/sgml/dblink.sgml | 0 | 0 |
| doc/src/sgml/ref/create_foreign_data_wrapper.sgml | 0 | 0 |
| src/backend/foreign/foreign.c | 0 | 0 |
| src/include/catalog/pg_proc.h | 0 | 0 |
| src/test/regress/expected/foreign_data.out | 0 | 0 |
| src/test/regress/sql/foreign_data.sql | 0 | 0 |
diff --git a/contrib/dblink/Makefile b/contrib/dblink/Makefile
index ac63748..a27db88 100644
*** a/contrib/dblink/Makefile
--- b/contrib/dblink/Makefile
*************** SHLIB_LINK = $(libpq)
*** 7,13 ****
SHLIB_PREREQS = submake-libpq
EXTENSION = dblink
! DATA = dblink--1.0.sql dblink--unpackaged--1.0.sql
REGRESS = dblink
--- 7,13 ----
SHLIB_PREREQS = submake-libpq
EXTENSION = dblink
! DATA = dblink--1.1.sql dblink--1.0--1.1.sql dblink--unpackaged--1.0.sql
REGRESS = dblink
diff --git a/contrib/dblink/dblink--1.0--1.1.sql b/contrib/dblink/dblink--1.0--1.1.sql
index ...3dd02a0 .
*** a/contrib/dblink/dblink--1.0--1.1.sql
--- b/contrib/dblink/dblink--1.0--1.1.sql
***************
*** 0 ****
--- 1,17 ----
+ /* contrib/dblink/dblink--1.0--1.1.sql */
+
+ -- complain if script is sourced in psql, rather than via ALTER EXTENSION
+ \echo Use "ALTER EXTENSION dblink UPDATE" to load this file. \quit
+
+ /* First we have to create validator function */
+ CREATE FUNCTION dblink_fdw_validator(
+ options text[],
+ catalog oid
+ )
+ RETURNS boolean
+ AS 'MODULE_PATHNAME', 'dblink_fdw_validator'
+ LANGUAGE C STRICT;
+
+ /* Then we add the validator */
+ ALTER EXTENSION dblink ADD FUNCTION dblink_fdw_validator(text[], oid);
+
diff --git a/contrib/dblink/dblink--1.1.sql b/contrib/dblink/dblink--1.1.sql
index ...ec02498 .
*** a/contrib/dblink/dblink--1.1.sql
--- b/contrib/dblink/dblink--1.1.sql
***************
*** 0 ****
--- 1,231 ----
+ /* contrib/dblink/dblink--1.1.sql */
+
+ -- complain if script is sourced in psql, rather than via CREATE EXTENSION
+ \echo Use "CREATE EXTENSION dblink" to load this file. \quit
+
+ -- dblink_connect now restricts non-superusers to password
+ -- authenticated connections
+ CREATE FUNCTION dblink_connect (text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_connect'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_connect (text, text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_connect'
+ LANGUAGE C STRICT;
+
+ -- dblink_connect_u allows non-superusers to use
+ -- non-password authenticated connections, but initially
+ -- privileges are revoked from public
+ CREATE FUNCTION dblink_connect_u (text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_connect'
+ LANGUAGE C STRICT SECURITY DEFINER;
+
+ CREATE FUNCTION dblink_connect_u (text, text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_connect'
+ LANGUAGE C STRICT SECURITY DEFINER;
+
+ REVOKE ALL ON FUNCTION dblink_connect_u (text) FROM public;
+ REVOKE ALL ON FUNCTION dblink_connect_u (text, text) FROM public;
+
+ CREATE FUNCTION dblink_disconnect ()
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_disconnect'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_disconnect (text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_disconnect'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_open (text, text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_open'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_open (text, text, boolean)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_open'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_open (text, text, text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_open'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_open (text, text, text, boolean)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_open'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_fetch (text, int)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_fetch'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_fetch (text, int, boolean)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_fetch'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_fetch (text, text, int)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_fetch'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_fetch (text, text, int, boolean)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_fetch'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_close (text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_close'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_close (text, boolean)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_close'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_close (text, text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_close'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_close (text, text, boolean)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_close'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink (text, text)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_record'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink (text, text, boolean)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_record'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink (text)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_record'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink (text, boolean)
+ RETURNS setof record
+ AS 'MODULE_PATHNAME','dblink_record'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_exec (text, text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_exec'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_exec (text, text, boolean)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_exec'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_exec (text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_exec'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_exec (text,boolean)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_exec'
+ LANGUAGE C STRICT;
+
+ CREATE TYPE dblink_pkey_results AS (position int, colname text);
+
+ CREATE FUNCTION dblink_get_pkey (text)
+ RETURNS setof dblink_pkey_results
+ AS 'MODULE_PATHNAME','dblink_get_pkey'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_build_sql_insert (text, int2vector, int, _text, _text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_build_sql_insert'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_build_sql_delete (text, int2vector, int, _text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_build_sql_delete'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_build_sql_update (text, int2vector, int, _text, _text)
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_build_sql_update'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_current_query ()
+ RETURNS text
+ AS 'MODULE_PATHNAME','dblink_current_query'
+ LANGUAGE C;
+
+ CREATE FUNCTION dblink_send_query(text, text)
+ RETURNS int4
+ AS 'MODULE_PATHNAME', 'dblink_send_query'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_is_busy(text)
+ RETURNS int4
+ AS 'MODULE_PATHNAME', 'dblink_is_busy'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_get_result(text)
+ RETURNS SETOF record
+ AS 'MODULE_PATHNAME', 'dblink_get_result'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_get_result(text, bool)
+ RETURNS SETOF record
+ AS 'MODULE_PATHNAME', 'dblink_get_result'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_get_connections()
+ RETURNS text[]
+ AS 'MODULE_PATHNAME', 'dblink_get_connections'
+ LANGUAGE C;
+
+ CREATE FUNCTION dblink_cancel_query(text)
+ RETURNS text
+ AS 'MODULE_PATHNAME', 'dblink_cancel_query'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_error_message(text)
+ RETURNS text
+ AS 'MODULE_PATHNAME', 'dblink_error_message'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_get_notify(
+ OUT notify_name TEXT,
+ OUT be_pid INT4,
+ OUT extra TEXT
+ )
+ RETURNS setof record
+ AS 'MODULE_PATHNAME', 'dblink_get_notify'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_get_notify(
+ conname TEXT,
+ OUT notify_name TEXT,
+ OUT be_pid INT4,
+ OUT extra TEXT
+ )
+ RETURNS setof record
+ AS 'MODULE_PATHNAME', 'dblink_get_notify'
+ LANGUAGE C STRICT;
+
+ CREATE FUNCTION dblink_fdw_validator(
+ options text[],
+ catalog oid
+ )
+ RETURNS boolean
+ AS 'MODULE_PATHNAME', 'dblink_fdw_validator'
+ LANGUAGE C STRICT;
diff --git a/contrib/dblink/dblink.c b/contrib/dblink/dblink.c
index 36a8e3e..1687c53 100644
*** a/contrib/dblink/dblink.c
--- b/contrib/dblink/dblink.c
***************
*** 36,43 ****
--- 36,46 ----
#include "libpq-fe.h"
#include "funcapi.h"
+ #include "access/reloptions.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
+ #include "catalog/pg_foreign_server.h"
+ #include "catalog/pg_user_mapping.h"
#include "catalog/pg_type.h"
#include "executor/spi.h"
#include "foreign/foreign.h"
*************** validate_pkattnums(Relation rel,
*** 2411,2413 ****
--- 2414,2516 ----
errmsg("invalid attribute number %d", pkattnum)));
}
}
+
+
+ /*
+ * 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 && 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.
+ */
+ PG_FUNCTION_INFO_V1(dblink_fdw_validator);
+ Datum
+ dblink_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 == 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/contrib/dblink/dblink.control b/contrib/dblink/dblink.control
index 4333a9b..39f439a 100644
*** a/contrib/dblink/dblink.control
--- b/contrib/dblink/dblink.control
***************
*** 1,5 ****
# dblink extension
comment = 'connect to other PostgreSQL databases from within a database'
! default_version = '1.0'
module_pathname = '$libdir/dblink'
relocatable = true
--- 1,5 ----
# dblink extension
comment = 'connect to other PostgreSQL databases from within a database'
! default_version = '1.1'
module_pathname = '$libdir/dblink'
relocatable = true
diff --git a/contrib/dblink/dblink.h b/contrib/dblink/dblink.h
index 935d283..fd11658 100644
*** a/contrib/dblink/dblink.h
--- b/contrib/dblink/dblink.h
*************** extern Datum dblink_build_sql_delete(PG_
*** 58,62 ****
--- 58,63 ----
extern Datum dblink_build_sql_update(PG_FUNCTION_ARGS);
extern Datum dblink_current_query(PG_FUNCTION_ARGS);
extern Datum dblink_get_notify(PG_FUNCTION_ARGS);
+ extern Datum dblink_fdw_validator(PG_FUNCTION_ARGS);
#endif /* DBLINK_H */
diff --git a/contrib/dblink/expected/dblink.out b/contrib/dblink/expected/dblink.out
index 511dd5e..0605354 100644
*** a/contrib/dblink/expected/dblink.out
--- b/contrib/dblink/expected/dblink.out
*************** SELECT dblink_disconnect('dtest1');
*** 785,792 ****
-- test foreign data wrapper functionality
CREATE USER dblink_regression_test;
! CREATE FOREIGN DATA WRAPPER postgresql;
! CREATE SERVER fdtest FOREIGN DATA WRAPPER postgresql OPTIONS (dbname 'contrib_regression');
CREATE USER MAPPING FOR public SERVER fdtest;
GRANT USAGE ON FOREIGN SERVER fdtest TO dblink_regression_test;
GRANT EXECUTE ON FUNCTION dblink_connect_u(text, text) TO dblink_regression_test;
--- 785,792 ----
-- test foreign data wrapper functionality
CREATE USER dblink_regression_test;
! CREATE FOREIGN DATA WRAPPER dblink_fdw VALIDATOR dblink_fdw_validator;
! CREATE SERVER fdtest FOREIGN DATA WRAPPER dblink_fdw OPTIONS (dbname 'contrib_regression');
CREATE USER MAPPING FOR public SERVER fdtest;
GRANT USAGE ON FOREIGN SERVER fdtest TO dblink_regression_test;
GRANT EXECUTE ON FUNCTION dblink_connect_u(text, text) TO dblink_regression_test;
*************** REVOKE EXECUTE ON FUNCTION dblink_connec
*** 825,831 ****
DROP USER dblink_regression_test;
DROP USER MAPPING FOR public SERVER fdtest;
DROP SERVER fdtest;
! DROP FOREIGN DATA WRAPPER postgresql;
-- test asynchronous notifications
SELECT dblink_connect('dbname=contrib_regression');
dblink_connect
--- 825,831 ----
DROP USER dblink_regression_test;
DROP USER MAPPING FOR public SERVER fdtest;
DROP SERVER fdtest;
! DROP FOREIGN DATA WRAPPER dblink_fdw;
-- test asynchronous notifications
SELECT dblink_connect('dbname=contrib_regression');
dblink_connect
diff --git a/contrib/dblink/sql/dblink.sql b/contrib/dblink/sql/dblink.sql
index 8c8ffe2..288ebf8 100644
*** a/contrib/dblink/sql/dblink.sql
--- b/contrib/dblink/sql/dblink.sql
*************** SELECT dblink_disconnect('dtest1');
*** 361,368 ****
-- test foreign data wrapper functionality
CREATE USER dblink_regression_test;
! CREATE FOREIGN DATA WRAPPER postgresql;
! CREATE SERVER fdtest FOREIGN DATA WRAPPER postgresql OPTIONS (dbname 'contrib_regression');
CREATE USER MAPPING FOR public SERVER fdtest;
GRANT USAGE ON FOREIGN SERVER fdtest TO dblink_regression_test;
GRANT EXECUTE ON FUNCTION dblink_connect_u(text, text) TO dblink_regression_test;
--- 361,368 ----
-- test foreign data wrapper functionality
CREATE USER dblink_regression_test;
! CREATE FOREIGN DATA WRAPPER dblink_fdw VALIDATOR dblink_fdw_validator;
! CREATE SERVER fdtest FOREIGN DATA WRAPPER dblink_fdw OPTIONS (dbname 'contrib_regression');
CREATE USER MAPPING FOR public SERVER fdtest;
GRANT USAGE ON FOREIGN SERVER fdtest TO dblink_regression_test;
GRANT EXECUTE ON FUNCTION dblink_connect_u(text, text) TO dblink_regression_test;
*************** REVOKE EXECUTE ON FUNCTION dblink_connec
*** 381,387 ****
DROP USER dblink_regression_test;
DROP USER MAPPING FOR public SERVER fdtest;
DROP SERVER fdtest;
! DROP FOREIGN DATA WRAPPER postgresql;
-- test asynchronous notifications
SELECT dblink_connect('dbname=contrib_regression');
--- 381,387 ----
DROP USER dblink_regression_test;
DROP USER MAPPING FOR public SERVER fdtest;
DROP SERVER fdtest;
! DROP FOREIGN DATA WRAPPER dblink_fdw;
-- test asynchronous notifications
SELECT dblink_connect('dbname=contrib_regression');
diff --git a/doc/src/sgml/dblink.sgml b/doc/src/sgml/dblink.sgml
index 855495c..613f447 100644
*** a/doc/src/sgml/dblink.sgml
--- b/doc/src/sgml/dblink.sgml
*************** dblink_connect(text connname, text conns
*** 47,55 ****
<para>
The connection string may also be the name of an existing foreign
server. It is recommended to use
! the <function>postgresql_fdw_validator</function> when defining
! the corresponding foreign-data wrapper. See the example below, as
! well as the following:
<simplelist type="inline">
<member><xref linkend="sql-createforeigndatawrapper"></member>
<member><xref linkend="sql-createserver"></member>
--- 47,58 ----
<para>
The connection string may also be the name of an existing foreign
server. It is recommended to use
! the <function>dblink_fdw_validator</function> when defining
! the corresponding foreign-data wrapper.
! This validator function was added in <productname>PostgreSQL</> 9.2, and
! it has been called <function>postgresql_fdw_validator</function> in older
! versions.
! See the example below, as well as the following:
<simplelist type="inline">
<member><xref linkend="sql-createforeigndatawrapper"></member>
<member><xref linkend="sql-createserver"></member>
*************** SELECT dblink_connect('myconn', 'dbname=
*** 136,143 ****
-- DETAIL: Non-superuser cannot connect if the server does not request a password.
-- HINT: Target server's authentication method must be changed.
CREATE USER dblink_regression_test WITH PASSWORD 'secret';
! CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
! CREATE SERVER fdtest FOREIGN DATA WRAPPER postgresql OPTIONS (hostaddr '127.0.0.1', dbname 'contrib_regression');
CREATE USER MAPPING FOR dblink_regression_test SERVER fdtest OPTIONS (user 'dblink_regression_test', password 'secret');
GRANT USAGE ON FOREIGN SERVER fdtest TO dblink_regression_test;
--- 139,146 ----
-- DETAIL: Non-superuser cannot connect if the server does not request a password.
-- HINT: Target server's authentication method must be changed.
CREATE USER dblink_regression_test WITH PASSWORD 'secret';
! CREATE FOREIGN DATA WRAPPER dblink_fdw VALIDATOR dblink_fdw_validator;
! CREATE SERVER fdtest FOREIGN DATA WRAPPER dblink_fdw OPTIONS (hostaddr '127.0.0.1', dbname 'contrib_regression');
CREATE USER MAPPING FOR dblink_regression_test SERVER fdtest OPTIONS (user 'dblink_regression_test', password 'secret');
GRANT USAGE ON FOREIGN SERVER fdtest TO dblink_regression_test;
*************** REVOKE SELECT ON TABLE foo FROM dblink_
*** 173,179 ****
DROP USER MAPPING FOR dblink_regression_test SERVER fdtest;
DROP USER dblink_regression_test;
DROP SERVER fdtest;
! DROP FOREIGN DATA WRAPPER postgresql;
</screen>
</refsect1>
</refentry>
--- 176,182 ----
DROP USER MAPPING FOR dblink_regression_test SERVER fdtest;
DROP USER dblink_regression_test;
DROP SERVER fdtest;
! DROP FOREIGN DATA WRAPPER dblink_fdw;
</screen>
</refsect1>
</refentry>
diff --git a/doc/src/sgml/ref/create_foreign_data_wrapper.sgml b/doc/src/sgml/ref/create_foreign_data_wrapper.sgml
index 804fb47..0d346fd 100644
*** a/doc/src/sgml/ref/create_foreign_data_wrapper.sgml
--- b/doc/src/sgml/ref/create_foreign_data_wrapper.sgml
*************** CREATE FOREIGN DATA WRAPPER <replaceable
*** 123,133 ****
</para>
<para>
! There is one built-in foreign-data wrapper validator function
! provided:
! <filename>postgresql_fdw_validator</filename>, which accepts
options corresponding to <application>libpq</> connection
! parameters.
</para>
</refsect1>
--- 123,134 ----
</para>
<para>
! Until <productname>PostgreSQL</productname> 9.1, there was one built-in
! foreign-data wrapper validator function provided:
! <function>postgresql_fdw_validator</function>, which accepts
options corresponding to <application>libpq</> connection
! parameters. But it has been moved to <filename>contrib/dblink</> with
! renaming to <function>dblink_fdw_validator</function>.
</para>
</refsect1>
diff --git a/src/backend/foreign/foreign.c b/src/backend/foreign/foreign.c
index c4c2a61..6831c70 100644
*** a/src/backend/foreign/foreign.c
--- b/src/backend/foreign/foreign.c
***************
*** 25,31 ****
extern Datum pg_options_to_table(PG_FUNCTION_ARGS);
- extern Datum postgresql_fdw_validator(PG_FUNCTION_ARGS);
--- 25,30 ----
*************** pg_options_to_table(PG_FUNCTION_ARGS)
*** 401,504 ****
/*
- * 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 && 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 == 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);
- }
-
- /*
* get_foreign_data_wrapper_oid - given a FDW name, look up the OID
*
* If missing_ok is false, throw an error if name not found. If true, just
--- 400,405 ----
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 8700d0d..8970998 100644
*** a/src/include/catalog/pg_proc.h
--- b/src/include/catalog/pg_proc.h
*************** DESCR("filenode identifier of relation")
*** 3399,3407 ****
DATA(insert OID = 3034 ( pg_relation_filepath PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 25 "2205" _null_ _null_ _null_ _null_ pg_relation_filepath _null_ _null_ _null_ ));
DESCR("file path of relation");
- DATA(insert OID = 2316 ( postgresql_fdw_validator PGNSP PGUID 12 1 0 0 0 f f f f t f i 2 0 16 "1009 26" _null_ _null_ _null_ _null_ postgresql_fdw_validator _null_ _null_ _null_));
- DESCR("(internal)");
-
DATA(insert OID = 2290 ( record_in PGNSP PGUID 12 1 0 0 0 f f f f t f s 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 0 f f f f t f s 1 0 2275 "2249" _null_ _null_ _null_ _null_ record_out _null_ _null_ _null_ ));
--- 3399,3404 ----
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index ba86883..161fbe7 100644
*** a/src/test/regress/expected/foreign_data.out
--- b/src/test/regress/expected/foreign_data.out
*************** CREATE ROLE regress_test_role2;
*** 13,18 ****
--- 13,33 ----
CREATE ROLE regress_test_role_super SUPERUSER;
CREATE ROLE regress_test_indirect;
CREATE ROLE unprivileged_role;
+ -- validator for this test
+ CREATE FUNCTION postgresql_fdw_validator(text[], oid) RETURNS boolean AS $$
+ DECLARE
+ BEGIN
+ IF $1::text LIKE '%foo%' THEN
+ RAISE 'invalid option "foo"'
+ USING HINT = 'Valid options in this context are: authtype, service, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib';
+ ELSIF $1::text LIKE '%username%' THEN
+ RAISE 'invalid option "username"'
+ USING HINT = 'Valid options in this context are: user, password';
+ END IF;
+
+ RETURN true;
+ END
+ $$ LANGUAGE plpgsql;
CREATE FOREIGN DATA WRAPPER dummy;
COMMENT ON FOREIGN DATA WRAPPER dummy IS 'useless';
CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
*************** DROP FOREIGN DATA WRAPPER postgresql CAS
*** 1201,1206 ****
--- 1216,1222 ----
DROP FOREIGN DATA WRAPPER dummy CASCADE;
NOTICE: drop cascades to server s0
\c
+ DROP FUNCTION postgresql_fdw_validator(text[], oid);
DROP ROLE foreign_data_user;
-- At this point we should have no wrappers, no servers, and no mappings.
SELECT fdwname, fdwhandler, fdwvalidator, fdwoptions FROM pg_foreign_data_wrapper;
diff --git a/src/test/regress/sql/foreign_data.sql b/src/test/regress/sql/foreign_data.sql
index 0c95672..9cf9ca7 100644
*** a/src/test/regress/sql/foreign_data.sql
--- b/src/test/regress/sql/foreign_data.sql
*************** CREATE ROLE regress_test_role_super SUPE
*** 20,25 ****
--- 20,41 ----
CREATE ROLE regress_test_indirect;
CREATE ROLE unprivileged_role;
+ -- validator for this test
+ CREATE FUNCTION postgresql_fdw_validator(text[], oid) RETURNS boolean AS $$
+ DECLARE
+ BEGIN
+ IF $1::text LIKE '%foo%' THEN
+ RAISE 'invalid option "foo"'
+ USING HINT = 'Valid options in this context are: authtype, service, connect_timeout, dbname, host, hostaddr, port, tty, options, requiressl, sslmode, gsslib';
+ ELSIF $1::text LIKE '%username%' THEN
+ RAISE 'invalid option "username"'
+ USING HINT = 'Valid options in this context are: user, password';
+ END IF;
+
+ RETURN true;
+ END
+ $$ LANGUAGE plpgsql;
+
CREATE FOREIGN DATA WRAPPER dummy;
COMMENT ON FOREIGN DATA WRAPPER dummy IS 'useless';
CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
*************** DROP ROLE regress_test_role2;
*** 495,500 ****
--- 511,517 ----
DROP FOREIGN DATA WRAPPER postgresql CASCADE;
DROP FOREIGN DATA WRAPPER dummy CASCADE;
\c
+ DROP FUNCTION postgresql_fdw_validator(text[], oid);
DROP ROLE foreign_data_user;
-- At this point we should have no wrappers, no servers, and no mappings.