<entry>Owner of the foreign-data wrapper</entry>
</row>
+ <row>
+ <entry><structfield>fdwhandler</structfield></entry>
+ <entry><type>oid</type></entry>
+ <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
+ <entry>
+ References a handler function that is responsible for
+ supplying execution routines for the foreign-data wrapper.
+ Zero if no handler is provided
+ </entry>
+ </row>
+
<row>
<entry><structfield>fdwvalidator</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry>
<entry>
References a validator function that is responsible for
- checking the validity of the generic options given to the
- foreign-data wrapper, as well as to foreign servers and user
+ checking the validity of the options given to the
+ foreign-data wrapper, as well as options for foreign servers and user
mappings using the foreign-data wrapper. Zero if no validator
- is provided.
+ is provided
</entry>
</row>
<para>
The catalog <structname>pg_foreign_server</structname> stores
- foreign server definitions. A foreign server describes the
- connection to a remote server, managing external data. Foreign
+ foreign server definitions. A foreign server describes a source
+ of external data, such as a remote server. Foreign
servers are accessed via foreign-data wrappers.
</para>
<entry><structfield>srvfdw</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-foreign-data-wrapper"><structname>pg_foreign_data_wrapper</structname></link>.oid</literal></entry>
- <entry>The OID of the foreign-data wrapper of this foreign server</entry>
+ <entry>OID of the foreign-data wrapper of this foreign server</entry>
</row>
<row>
</indexterm>
<para>
- The catalog <structname>pg_foreign_table</structname> contains part
- of the information about foreign tables.
- The rest is mostly in <structname>pg_class</structname>.
+ The catalog <structname>pg_foreign_table</structname> contains
+ auxiliary information about foreign tables. A foreign table is
+ primarily represented by a <structname>pg_class</structname> entry,
+ just like a regular table. Its <structname>pg_foreign_table</structname>
+ entry contains the information that is pertinent only to foreign tables
+ and not any other kind of relation.
</para>
<table>
<entry><structfield>ftrelid</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
- <entry>The OID of the <structname>pg_class</> entry for this foreign table</entry>
+ <entry>OID of the <structname>pg_class</> entry for this foreign table</entry>
</row>
<row>
<entry><structfield>ftserver</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-foreign-server"><structname>pg_foreign_server</structname></link>.oid</literal></entry>
- <entry>The OID of the foreign server for this foreign table</entry>
+ <entry>OID of the foreign server for this foreign table</entry>
</row>
<row>
<entry><type>text[]</type></entry>
<entry></entry>
<entry>
- Foreign table options, as <quote>keyword=value</> strings.
+ Foreign table options, as <quote>keyword=value</> strings
</entry>
</row>
</tbody>
<primary>language_handler</primary>
</indexterm>
+ <indexterm zone="datatype-pseudo">
+ <primary>fdw_handler</primary>
+ </indexterm>
+
<indexterm zone="datatype-pseudo">
<primary>cstring</primary>
</indexterm>
<entry>A procedural language call handler is declared to return <type>language_handler</>.</entry>
</row>
+ <row>
+ <entry><type>fdw_handler</></entry>
+ <entry>A foreign-data wrapper handler is declared to return <type>fdw_handler</>.</entry>
+ </row>
+
<row>
<entry><type>record</></entry>
<entry>Identifies a function returning an unspecified row type.</entry>
<refsynopsisdiv>
<synopsis>
ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
- [ VALIDATOR <replaceable class="parameter">valfunction</replaceable> | NO VALIDATOR ]
+ [ HANDLER <replaceable class="parameter">handler_function</replaceable> | NO HANDLER ]
+ [ VALIDATOR <replaceable class="parameter">validator_function</replaceable> | NO VALIDATOR ]
[ OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ]) ]
ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable> OWNER TO <replaceable>new_owner</replaceable>
</synopsis>
<para>
<command>ALTER FOREIGN DATA WRAPPER</command> changes the
definition of a foreign-data wrapper. The first form of the
- command changes the library or the generic options of the
+ command changes the support functions or the generic options of the
foreign-data wrapper (at least one clause is required). The second
form changes the owner of the foreign-data wrapper.
</para>
</varlistentry>
<varlistentry>
- <term><literal>VALIDATOR <replaceable class="parameter">valfunction</replaceable></literal></term>
+ <term><literal>HANDLER <replaceable class="parameter">handler_function</replaceable></literal></term>
<listitem>
<para>
- Specifies a new foreign-data wrapper validator function.
+ Specifies a new handler function for the foreign-data wrapper.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>NO HANDLER</literal></term>
+ <listitem>
+ <para>
+ This is used to specify that the foreign-data wrapper should no
+ longer have a handler function.
+ </para>
+ <para>
+ Note that foreign tables that use a foreign-data wrapper with no
+ handler cannot be accessed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>VALIDATOR <replaceable class="parameter">validator_function</replaceable></literal></term>
+ <listitem>
+ <para>
+ Specifies a new validator function for the foreign-data wrapper.
</para>
<para>
specify the action to be performed. <literal>ADD</> is assumed
if no operation is explicitly specified. Option names must be
unique; names and values are also validated using the foreign
- data wrapper library.
+ data wrapper's validator function, if any.
</para>
</listitem>
</varlistentry>
<para>
<command>ALTER FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
- 9075-9 (SQL/MED). The standard does not specify the <literal>
- VALIDATOR</literal> and <literal>OWNER TO</> variants of the
- command.
+ 9075-9 (SQL/MED), except that the <literal>HANDLER</literal>,
+ <literal>VALIDATOR</> and <literal>OWNER TO</> clauses are extensions.
</para>
</refsect1>
<refsynopsisdiv>
<synopsis>
CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
- [ VALIDATOR <replaceable class="parameter">valfunction</replaceable> | NO VALIDATOR ]
+ [ HANDLER <replaceable class="parameter">handler_function</replaceable> | NO HANDLER ]
+ [ VALIDATOR <replaceable class="parameter">validator_function</replaceable> | NO VALIDATOR ]
[ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ]
</synopsis>
</refsynopsisdiv>
</varlistentry>
<varlistentry>
- <term><literal>VALIDATOR <replaceable class="parameter">valfunction</replaceable></literal></term>
+ <term><literal>HANDLER <replaceable class="parameter">handler_function</replaceable></literal></term>
<listitem>
<para>
- <replaceable class="parameter">valfunction</replaceable> is the
+ <replaceable class="parameter">handler_function</replaceable> is the
+ name of a previously registered function that will be called to
+ retrieve the execution functions for foreign tables.
+ The handler function must take no arguments, and
+ its return type must be <type>fdw_handler</type>.
+ </para>
+
+ <para>
+ It is possible to create a foreign-data wrapper with no handler
+ function, but foreign tables using such a wrapper can only be declared,
+ not accessed.
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><literal>VALIDATOR <replaceable class="parameter">validator_function</replaceable></literal></term>
+ <listitem>
+ <para>
+ <replaceable class="parameter">validator_function</replaceable> is the
name of a previously registered function that will be called to
check the generic options given to the foreign-data wrapper, as
- well as to foreign servers and user mappings using the
+ well as options for foreign servers and user mappings using the
foreign-data wrapper. If no validator function or <literal>NO
VALIDATOR</literal> is specified, then options will not be
checked at creation time. (Foreign-data wrappers will possibly
contain the array of options as stored in the system catalogs,
and one of type <type>oid</type>, which will be the OID of the
system catalog containing the options. The return type is ignored;
- the function should indicate invalid options using the
- <function>ereport()</function> function.
+ the function should report invalid options using the
+ <function>ereport(ERROR)</function> function.
</para>
</listitem>
</varlistentry>
<para>
This clause specifies options for the new foreign-data wrapper.
The allowed option names and values are specific to each foreign
- data wrapper and are validated using the foreign-data wrapper
- library. Option names must be unique.
+ data wrapper and are validated using the foreign-data wrapper's
+ validator function. Option names must be unique.
</para>
</listitem>
</varlistentry>
<title>Examples</title>
<para>
- Create a foreign-data wrapper <literal>dummy</>:
+ Create a useless foreign-data wrapper <literal>dummy</>:
<programlisting>
CREATE FOREIGN DATA WRAPPER dummy;
</programlisting>
</para>
<para>
- Create a foreign-data wrapper <literal>postgresql</> with
- validator function <literal>postgresql_fdw_validator</>:
+ Create a foreign-data wrapper <literal>file</> with
+ handler function <literal>file_fdw_handler</>:
<programlisting>
-CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
+CREATE FOREIGN DATA WRAPPER file HANDLER file_fdw_handler;
</programlisting>
</para>
<para>
<command>CREATE FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
- 9075-9 (SQL/MED), with the exception that
- the <literal>VALIDATOR</literal> clause is an extension and the
+ 9075-9 (SQL/MED), with the exception that the <literal>HANDLER</literal>
+ and <literal>VALIDATOR</literal> clauses are extensions and the standard
clauses <literal>LIBRARY</literal> and <literal>LANGUAGE</literal>
- are not yet implemented in PostgreSQL.
+ are not implemented in PostgreSQL.
</para>
<para>
result = optionListToArray(resultOptions);
- if (fdwvalidator)
+ if (OidIsValid(fdwvalidator) && DatumGetPointer(result) != NULL)
OidFunctionCall2(fdwvalidator, result, ObjectIdGetDatum(catalogId));
return result;
newOwnerId);
}
- heap_close(rel, NoLock);
heap_freetuple(tup);
+
+ heap_close(rel, RowExclusiveLock);
}
newOwnerId);
}
- heap_close(rel, NoLock);
heap_freetuple(tup);
+
+ heap_close(rel, RowExclusiveLock);
}
+/*
+ * Convert a handler function name passed from the parser to an Oid.
+ */
+static Oid
+lookup_fdw_handler_func(DefElem *handler)
+{
+ Oid handlerOid;
+
+ if (handler == NULL || handler->arg == NULL)
+ return InvalidOid;
+
+ /* handlers have no arguments */
+ handlerOid = LookupFuncName((List *) handler->arg, 0, NULL, false);
+
+ /* check that handler has correct return type */
+ if (get_func_rettype(handlerOid) != FDW_HANDLEROID)
+ ereport(ERROR,
+ (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ errmsg("function %s must return type \"fdw_handler\"",
+ NameListToString((List *) handler->arg))));
+
+ return handlerOid;
+}
+
/*
* Convert a validator function name passed from the parser to an Oid.
*/
static Oid
-lookup_fdw_validator_func(List *validator)
+lookup_fdw_validator_func(DefElem *validator)
{
Oid funcargtypes[2];
+ if (validator == NULL || validator->arg == NULL)
+ return InvalidOid;
+
+ /* validators take text[], oid */
funcargtypes[0] = TEXTARRAYOID;
funcargtypes[1] = OIDOID;
- return LookupFuncName(validator, 2, funcargtypes, false);
- /* return value is ignored, so we don't check the type */
+
+ return LookupFuncName((List *) validator->arg, 2, funcargtypes, false);
+ /* validator's return value is ignored, so we don't check the type */
}
+/*
+ * Process function options of CREATE/ALTER FDW
+ */
+static void
+parse_func_options(List *func_options,
+ bool *handler_given, Oid *fdwhandler,
+ bool *validator_given, Oid *fdwvalidator)
+{
+ ListCell *cell;
+
+ *handler_given = false;
+ *validator_given = false;
+ /* return InvalidOid if not given */
+ *fdwhandler = InvalidOid;
+ *fdwvalidator = InvalidOid;
+
+ foreach(cell, func_options)
+ {
+ DefElem *def = (DefElem *) lfirst(cell);
+
+ if (strcmp(def->defname, "handler") == 0)
+ {
+ if (*handler_given)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ *handler_given = true;
+ *fdwhandler = lookup_fdw_handler_func(def);
+ }
+ else if (strcmp(def->defname, "validator") == 0)
+ {
+ if (*validator_given)
+ ereport(ERROR,
+ (errcode(ERRCODE_SYNTAX_ERROR),
+ errmsg("conflicting or redundant options")));
+ *validator_given = true;
+ *fdwvalidator = lookup_fdw_validator_func(def);
+ }
+ else
+ elog(ERROR, "option \"%s\" not recognized",
+ def->defname);
+ }
+}
/*
* Create a foreign-data wrapper
bool nulls[Natts_pg_foreign_data_wrapper];
HeapTuple tuple;
Oid fdwId;
+ bool handler_given;
+ bool validator_given;
+ Oid fdwhandler;
Oid fdwvalidator;
Datum fdwoptions;
Oid ownerId;
DirectFunctionCall1(namein, CStringGetDatum(stmt->fdwname));
values[Anum_pg_foreign_data_wrapper_fdwowner - 1] = ObjectIdGetDatum(ownerId);
- if (stmt->validator)
- fdwvalidator = lookup_fdw_validator_func(stmt->validator);
- else
- fdwvalidator = InvalidOid;
+ /* Lookup handler and validator functions, if given */
+ parse_func_options(stmt->func_options,
+ &handler_given, &fdwhandler,
+ &validator_given, &fdwvalidator);
- values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = fdwvalidator;
+ values[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
+ values[Anum_pg_foreign_data_wrapper_fdwvalidator - 1] = ObjectIdGetDatum(fdwvalidator);
nulls[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
myself.objectId = fdwId;
myself.objectSubId = 0;
- if (fdwvalidator)
+ if (OidIsValid(fdwhandler))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = fdwhandler;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(fdwvalidator))
{
referenced.classId = ProcedureRelationId;
referenced.objectId = fdwvalidator;
InvokeObjectAccessHook(OAT_POST_CREATE,
ForeignDataWrapperRelationId, fdwId, 0);
- heap_close(rel, NoLock);
+ heap_close(rel, RowExclusiveLock);
}
{
Relation rel;
HeapTuple tp;
+ Form_pg_foreign_data_wrapper fdwForm;
Datum repl_val[Natts_pg_foreign_data_wrapper];
bool repl_null[Natts_pg_foreign_data_wrapper];
bool repl_repl[Natts_pg_foreign_data_wrapper];
Oid fdwId;
bool isnull;
Datum datum;
+ bool handler_given;
+ bool validator_given;
+ Oid fdwhandler;
Oid fdwvalidator;
/* Must be super user */
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("foreign-data wrapper \"%s\" does not exist", stmt->fdwname)));
+ fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
fdwId = HeapTupleGetOid(tp);
memset(repl_val, 0, sizeof(repl_val));
memset(repl_null, false, sizeof(repl_null));
memset(repl_repl, false, sizeof(repl_repl));
- if (stmt->change_validator)
+ parse_func_options(stmt->func_options,
+ &handler_given, &fdwhandler,
+ &validator_given, &fdwvalidator);
+
+ if (handler_given)
+ {
+ repl_val[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = ObjectIdGetDatum(fdwhandler);
+ repl_repl[Anum_pg_foreign_data_wrapper_fdwhandler - 1] = true;
+
+ /*
+ * It could be that the behavior of accessing foreign table changes
+ * with the new handler. Warn about this.
+ */
+ ereport(WARNING,
+ (errmsg("changing the foreign-data wrapper handler can change behavior of existing foreign tables")));
+ }
+
+ if (validator_given)
{
- 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 validator. Warn about this.
*/
- if (stmt->validator)
+ if (OidIsValid(fdwvalidator))
ereport(WARNING,
- (errmsg("changing the foreign-data wrapper validator can cause "
- "the options for dependent objects to become invalid")));
+ (errmsg("changing the foreign-data wrapper validator can cause "
+ "the options for dependent objects to become invalid")));
}
else
{
/*
* Validator is not changed, but we need it for validating options.
*/
- datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
- tp,
- Anum_pg_foreign_data_wrapper_fdwvalidator,
- &isnull);
- Assert(!isnull);
- fdwvalidator = DatumGetObjectId(datum);
+ fdwvalidator = fdwForm->fdwvalidator;
}
/*
- * Options specified, validate and update.
+ * If options specified, validate and update.
*/
if (stmt->options)
{
simple_heap_update(rel, &tp->t_self, tp);
CatalogUpdateIndexes(rel, tp);
- heap_close(rel, RowExclusiveLock);
heap_freetuple(tp);
+
+ /* Update function dependencies if we changed them */
+ if (handler_given || validator_given)
+ {
+ ObjectAddress myself;
+ ObjectAddress referenced;
+
+ /*
+ * Flush all existing dependency records of this FDW on functions;
+ * we assume there can be none other than the ones we are fixing.
+ */
+ deleteDependencyRecordsForClass(ForeignDataWrapperRelationId,
+ fdwId,
+ ProcedureRelationId,
+ DEPENDENCY_NORMAL);
+
+ /* And build new ones. */
+ myself.classId = ForeignDataWrapperRelationId;
+ myself.objectId = fdwId;
+ myself.objectSubId = 0;
+
+ if (OidIsValid(fdwhandler))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = fdwhandler;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+
+ if (OidIsValid(fdwvalidator))
+ {
+ referenced.classId = ProcedureRelationId;
+ referenced.objectId = fdwvalidator;
+ referenced.objectSubId = 0;
+ recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ }
+ }
+
+ heap_close(rel, RowExclusiveLock);
}
/* Post creation hook for new foreign server */
InvokeObjectAccessHook(OAT_POST_CREATE, ForeignServerRelationId, srvId, 0);
- heap_close(rel, NoLock);
+ heap_close(rel, RowExclusiveLock);
}
simple_heap_update(rel, &tp->t_self, tp);
CatalogUpdateIndexes(rel, tp);
- heap_close(rel, RowExclusiveLock);
heap_freetuple(tp);
+
+ heap_close(rel, RowExclusiveLock);
}
/* Post creation hook for new user mapping */
InvokeObjectAccessHook(OAT_POST_CREATE, UserMappingRelationId, umId, 0);
- heap_close(rel, NoLock);
+ heap_close(rel, RowExclusiveLock);
}
simple_heap_update(rel, &tp->t_self, tp);
CatalogUpdateIndexes(rel, tp);
- heap_close(rel, RowExclusiveLock);
heap_freetuple(tp);
+
+ heap_close(rel, RowExclusiveLock);
}
Datum values[Natts_pg_foreign_table];
bool nulls[Natts_pg_foreign_table];
HeapTuple tuple;
- Oid ftId;
AclResult aclresult;
ObjectAddress myself;
ObjectAddress referenced;
tuple = heap_form_tuple(ftrel->rd_att, values, nulls);
- /* pg_foreign_table don't have OID */
- ftId = simple_heap_insert(ftrel, tuple);
-
+ simple_heap_insert(ftrel, tuple);
CatalogUpdateIndexes(ftrel, tuple);
heap_freetuple(tuple);
referenced.objectSubId = 0;
recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
- heap_close(ftrel, NoLock);
+ heap_close(ftrel, RowExclusiveLock);
}
fdw->fdwid = fdwid;
fdw->owner = fdwform->fdwowner;
fdw->fdwname = pstrdup(NameStr(fdwform->fdwname));
+ fdw->fdwhandler = fdwform->fdwhandler;
fdw->fdwvalidator = fdwform->fdwvalidator;
/* Extract the options */
CreateFdwStmt *newnode = makeNode(CreateFdwStmt);
COPY_STRING_FIELD(fdwname);
- COPY_NODE_FIELD(validator);
+ COPY_NODE_FIELD(func_options);
COPY_NODE_FIELD(options);
return newnode;
AlterFdwStmt *newnode = makeNode(AlterFdwStmt);
COPY_STRING_FIELD(fdwname);
- COPY_NODE_FIELD(validator);
- COPY_SCALAR_FIELD(change_validator);
+ COPY_NODE_FIELD(func_options);
COPY_NODE_FIELD(options);
return newnode;
_equalCreateFdwStmt(CreateFdwStmt *a, CreateFdwStmt *b)
{
COMPARE_STRING_FIELD(fdwname);
- COMPARE_NODE_FIELD(validator);
+ COMPARE_NODE_FIELD(func_options);
COMPARE_NODE_FIELD(options);
return true;
_equalAlterFdwStmt(AlterFdwStmt *a, AlterFdwStmt *b)
{
COMPARE_STRING_FIELD(fdwname);
- COMPARE_NODE_FIELD(validator);
- COMPARE_SCALAR_FIELD(change_validator);
+ COMPARE_NODE_FIELD(func_options);
COMPARE_NODE_FIELD(options);
return true;
create_generic_options alter_generic_options
relation_expr_list dostmt_opt_list
+%type <list> opt_fdw_options fdw_options
+%type <defelt> fdw_option
+
%type <range> OptTempTableName
%type <into> into_clause create_as_target
/*****************************************************************************
*
* QUERY:
- * CREATE FOREIGN DATA WRAPPER name [ VALIDATOR name ]
+ * CREATE FOREIGN DATA WRAPPER name options
*
*****************************************************************************/
-CreateFdwStmt: CREATE FOREIGN DATA_P WRAPPER name opt_validator create_generic_options
+CreateFdwStmt: CREATE FOREIGN DATA_P WRAPPER name opt_fdw_options create_generic_options
{
CreateFdwStmt *n = makeNode(CreateFdwStmt);
n->fdwname = $5;
- n->validator = $6;
+ n->func_options = $6;
n->options = $7;
$$ = (Node *) n;
}
;
+fdw_option:
+ HANDLER handler_name { $$ = makeDefElem("handler", (Node *)$2); }
+ | NO HANDLER { $$ = makeDefElem("handler", NULL); }
+ | VALIDATOR handler_name { $$ = makeDefElem("validator", (Node *)$2); }
+ | NO VALIDATOR { $$ = makeDefElem("validator", NULL); }
+ ;
+
+fdw_options:
+ fdw_option { $$ = list_make1($1); }
+ | fdw_options fdw_option { $$ = lappend($1, $2); }
+ ;
+
+opt_fdw_options:
+ fdw_options { $$ = $1; }
+ | /*EMPTY*/ { $$ = NIL; }
+ ;
+
/*****************************************************************************
*
* QUERY :
/*****************************************************************************
*
* QUERY :
- * ALTER FOREIGN DATA WRAPPER name
+ * ALTER FOREIGN DATA WRAPPER name options
*
****************************************************************************/
-AlterFdwStmt: ALTER FOREIGN DATA_P WRAPPER name validator_clause alter_generic_options
+AlterFdwStmt: ALTER FOREIGN DATA_P WRAPPER name opt_fdw_options alter_generic_options
{
AlterFdwStmt *n = makeNode(AlterFdwStmt);
n->fdwname = $5;
- n->validator = $6;
- n->change_validator = true;
+ n->func_options = $6;
n->options = $7;
$$ = (Node *) n;
}
- | ALTER FOREIGN DATA_P WRAPPER name validator_clause
+ | ALTER FOREIGN DATA_P WRAPPER name fdw_options
{
AlterFdwStmt *n = makeNode(AlterFdwStmt);
n->fdwname = $5;
- n->validator = $6;
- n->change_validator = true;
- $$ = (Node *) n;
- }
- | ALTER FOREIGN DATA_P WRAPPER name alter_generic_options
- {
- AlterFdwStmt *n = makeNode(AlterFdwStmt);
- n->fdwname = $5;
- n->options = $6;
+ n->func_options = $6;
+ n->options = NIL;
$$ = (Node *) n;
}
;
}
+/*
+ * fdw_handler_in - input routine for pseudo-type FDW_HANDLER.
+ */
+Datum
+fdw_handler_in(PG_FUNCTION_ARGS)
+{
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot accept a value of type fdw_handler")));
+
+ PG_RETURN_VOID(); /* keep compiler quiet */
+}
+
+/*
+ * fdw_handler_out - output routine for pseudo-type FDW_HANDLER.
+ */
+Datum
+fdw_handler_out(PG_FUNCTION_ARGS)
+{
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot display a value of type fdw_handler")));
+
+ PG_RETURN_VOID(); /* keep compiler quiet */
+}
+
+
/*
* internal_in - input routine for pseudo-type INTERNAL.
*/
int i_oid;
int i_fdwname;
int i_rolname;
+ int i_fdwhandler;
int i_fdwvalidator;
int i_fdwacl;
int i_fdwoptions;
/* Make sure we are in proper schema */
selectSourceSchema("pg_catalog");
- appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
- "(%s fdwowner) AS rolname, fdwvalidator::pg_catalog.regproc, fdwacl,"
- "array_to_string(ARRAY("
- " SELECT option_name || ' ' || quote_literal(option_value) "
- " FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
- "FROM pg_foreign_data_wrapper",
- username_subquery);
+ if (g_fout->remoteVersion >= 90100)
+ {
+ appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
+ "(%s fdwowner) AS rolname, "
+ "fdwhandler::pg_catalog.regproc, "
+ "fdwvalidator::pg_catalog.regproc, fdwacl, "
+ "array_to_string(ARRAY("
+ " SELECT option_name || ' ' || quote_literal(option_value) "
+ " FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
+ "FROM pg_foreign_data_wrapper",
+ username_subquery);
+ }
+ else
+ {
+ appendPQExpBuffer(query, "SELECT tableoid, oid, fdwname, "
+ "(%s fdwowner) AS rolname, "
+ "'-' AS fdwhandler, "
+ "fdwvalidator::pg_catalog.regproc, fdwacl, "
+ "array_to_string(ARRAY("
+ " SELECT option_name || ' ' || quote_literal(option_value) "
+ " FROM pg_options_to_table(fdwoptions)), ', ') AS fdwoptions "
+ "FROM pg_foreign_data_wrapper",
+ username_subquery);
+ }
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
i_oid = PQfnumber(res, "oid");
i_fdwname = PQfnumber(res, "fdwname");
i_rolname = PQfnumber(res, "rolname");
+ i_fdwhandler = PQfnumber(res, "fdwhandler");
i_fdwvalidator = PQfnumber(res, "fdwvalidator");
i_fdwacl = PQfnumber(res, "fdwacl");
i_fdwoptions = PQfnumber(res, "fdwoptions");
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].fdwhandler = strdup(PQgetvalue(res, i, i_fdwhandler));
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));
-
/* Decide whether we want to dump it */
selectDumpableObject(&(fdwinfo[i].dobj));
}
appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s",
qfdwname);
- if (fdwinfo->fdwvalidator && strcmp(fdwinfo->fdwvalidator, "-") != 0)
- appendPQExpBuffer(q, " VALIDATOR %s",
- fdwinfo->fdwvalidator);
+ if (strcmp(fdwinfo->fdwhandler, "-") != 0)
+ appendPQExpBuffer(q, " HANDLER %s", fdwinfo->fdwhandler);
+
+ if (strcmp(fdwinfo->fdwvalidator, "-") != 0)
+ appendPQExpBuffer(q, " VALIDATOR %s", fdwinfo->fdwvalidator);
- if (fdwinfo->fdwoptions && strlen(fdwinfo->fdwoptions) > 0)
+ if (strlen(fdwinfo->fdwoptions) > 0)
appendPQExpBuffer(q, " OPTIONS (%s)", fdwinfo->fdwoptions);
appendPQExpBuffer(q, ";\n");
{
DumpableObject dobj;
char *rolname;
+ char *fdwhandler;
char *fdwvalidator;
char *fdwoptions;
char *fdwacl;
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
"SELECT fdwname AS \"%s\",\n"
- " pg_catalog.pg_get_userbyid(fdwowner) AS \"%s\",\n"
- " fdwvalidator::pg_catalog.regproc AS \"%s\"",
+ " pg_catalog.pg_get_userbyid(fdwowner) AS \"%s\",\n",
gettext_noop("Name"),
- gettext_noop("Owner"),
+ gettext_noop("Owner"));
+ if (pset.sversion >= 90100)
+ appendPQExpBuffer(&buf,
+ " fdwhandler::pg_catalog.regproc AS \"%s\",\n",
+ gettext_noop("Handler"));
+ appendPQExpBuffer(&buf,
+ " fdwvalidator::pg_catalog.regproc AS \"%s\"",
gettext_noop("Validator"));
if (verbose)
*/
/* yyyymmddN */
-#define CATALOG_VERSION_NO 201102181
+#define CATALOG_VERSION_NO 201102191
#endif
{
NameData fdwname; /* foreign-data wrapper name */
Oid fdwowner; /* FDW owner */
- Oid fdwvalidator; /* optional validation function */
+ Oid fdwhandler; /* handler function, or 0 if none */
+ Oid fdwvalidator; /* option validation function, or 0 if none */
/* VARIABLE LENGTH FIELDS start here. */
* ----------------
*/
-#define Natts_pg_foreign_data_wrapper 5
+#define Natts_pg_foreign_data_wrapper 6
#define Anum_pg_foreign_data_wrapper_fdwname 1
#define Anum_pg_foreign_data_wrapper_fdwowner 2
-#define Anum_pg_foreign_data_wrapper_fdwvalidator 3
-#define Anum_pg_foreign_data_wrapper_fdwacl 4
-#define Anum_pg_foreign_data_wrapper_fdwoptions 5
+#define Anum_pg_foreign_data_wrapper_fdwhandler 3
+#define Anum_pg_foreign_data_wrapper_fdwvalidator 4
+#define Anum_pg_foreign_data_wrapper_fdwacl 5
+#define Anum_pg_foreign_data_wrapper_fdwoptions 6
#endif /* PG_FOREIGN_DATA_WRAPPER_H */
DESCR("I/O");
DATA(insert OID = 2778 ( anynonarray_out PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2275 "2776" _null_ _null_ _null_ _null_ anynonarray_out _null_ _null_ _null_ ));
DESCR("I/O");
+DATA(insert OID = 3116 ( fdw_handler_in PGNSP PGUID 12 1 0 0 f f f f f i 1 0 3115 "2275" _null_ _null_ _null_ _null_ fdw_handler_in _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 3117 ( fdw_handler_out PGNSP PGUID 12 1 0 0 f f f t f i 1 0 2275 "3115" _null_ _null_ _null_ _null_ fdw_handler_out _null_ _null_ _null_ ));
+DESCR("I/O");
/* cryptographic */
DATA(insert OID = 2311 ( md5 PGNSP PGUID 12 1 0 0 f f f t f i 1 0 25 "25" _null_ _null_ _null_ _null_ md5_text _null_ _null_ _null_ ));
#define ANYNONARRAYOID 2776
DATA(insert OID = 3500 ( anyenum PGNSP PGUID 4 t p P f t \054 0 0 0 anyenum_in anyenum_out - - - - - i p f 0 -1 0 0 _null_ _null_ ));
#define ANYENUMOID 3500
+DATA(insert OID = 3115 ( fdw_handler PGNSP PGUID 4 t p P f t \054 0 0 0 fdw_handler_in fdw_handler_out - - - - - i p f 0 -1 0 0 _null_ _null_ ));
+#define FDW_HANDLEROID 3115
/*
Oid fdwid; /* FDW Oid */
Oid owner; /* FDW owner user Oid */
char *fdwname; /* Name of the FDW */
- Oid fdwvalidator;
+ Oid fdwhandler; /* Oid of handler function, or 0 */
+ Oid fdwvalidator; /* Oid of validator function, or 0 */
List *options; /* fdwoptions as DefElem list */
} ForeignDataWrapper;
{
NodeTag type;
char *fdwname; /* foreign-data wrapper name */
- List *validator; /* optional validator function (qual. name) */
+ List *func_options; /* HANDLER/VALIDATOR options */
List *options; /* generic options to FDW */
} CreateFdwStmt;
{
NodeTag type;
char *fdwname; /* foreign-data wrapper name */
- List *validator; /* optional validator function (qual. name) */
- bool change_validator;
+ List *func_options; /* HANDLER/VALIDATOR options */
List *options; /* generic options to FDW */
} AlterFdwStmt;
extern Datum trigger_out(PG_FUNCTION_ARGS);
extern Datum language_handler_in(PG_FUNCTION_ARGS);
extern Datum language_handler_out(PG_FUNCTION_ARGS);
+extern Datum fdw_handler_in(PG_FUNCTION_ARGS);
+extern Datum fdw_handler_out(PG_FUNCTION_ARGS);
extern Datum internal_in(PG_FUNCTION_ARGS);
extern Datum internal_out(PG_FUNCTION_ARGS);
extern Datum opaque_in(PG_FUNCTION_ARGS);
CREATE FOREIGN DATA WRAPPER dummy;
CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
-- At this point we should have 2 built-in wrappers and no servers.
-SELECT fdwname, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
- fdwname | fdwvalidator | fdwoptions
-------------+--------------------------+------------
- dummy | - |
- postgresql | postgresql_fdw_validator |
+SELECT fdwname, fdwhandler::regproc, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+ fdwname | fdwhandler | fdwvalidator | fdwoptions
+------------+------------+--------------------------+------------
+ dummy | - | - |
+ postgresql | - | postgresql_fdw_validator |
(2 rows)
SELECT srvname, srvoptions FROM pg_foreign_server;
ERROR: function bar(text[], oid) does not exist
CREATE FOREIGN DATA WRAPPER foo;
\dew
- List of foreign-data wrappers
- Name | Owner | Validator
-------------+-------------------+--------------------------
- dummy | foreign_data_user | -
- foo | foreign_data_user | -
- postgresql | foreign_data_user | postgresql_fdw_validator
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator
+------------+-------------------+---------+--------------------------
+ dummy | foreign_data_user | - | -
+ foo | foreign_data_user | - | -
+ postgresql | foreign_data_user | - | postgresql_fdw_validator
(3 rows)
CREATE FOREIGN DATA WRAPPER foo; -- duplicate
DROP FOREIGN DATA WRAPPER foo;
CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1');
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+-------------
- dummy | foreign_data_user | - | |
- foo | foreign_data_user | - | | {testing=1}
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+-------------
+ dummy | foreign_data_user | - | - | |
+ foo | foreign_data_user | - | - | | {testing=1}
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
DROP FOREIGN DATA WRAPPER foo;
ERROR: option "testing" provided more than once
CREATE FOREIGN DATA WRAPPER foo OPTIONS (testing '1', another '2');
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+-----------------------
- dummy | foreign_data_user | - | |
- foo | foreign_data_user | - | | {testing=1,another=2}
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+-----------------------
+ dummy | foreign_data_user | - | - | |
+ foo | foreign_data_user | - | - | | {testing=1,another=2}
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
DROP FOREIGN DATA WRAPPER foo;
RESET ROLE;
CREATE FOREIGN DATA WRAPPER foo VALIDATOR postgresql_fdw_validator;
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+---------
- dummy | foreign_data_user | - | |
- foo | foreign_data_user | postgresql_fdw_validator | |
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy | foreign_data_user | - | - | |
+ foo | foreign_data_user | - | postgresql_fdw_validator | |
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
-- ALTER FOREIGN DATA WRAPPER
ERROR: function bar(text[], oid) does not exist
ALTER FOREIGN DATA WRAPPER foo NO VALIDATOR;
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+---------
- dummy | foreign_data_user | - | |
- foo | foreign_data_user | - | |
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy | foreign_data_user | - | - | |
+ foo | foreign_data_user | - | - | |
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '1', b '2');
ERROR: option "c" not found
ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD x '1', DROP x);
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+-----------
- dummy | foreign_data_user | - | |
- foo | foreign_data_user | - | | {a=1,b=2}
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+-----------
+ dummy | foreign_data_user | - | - | |
+ foo | foreign_data_user | - | - | | {a=1,b=2}
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP a, SET b '3', ADD c '4');
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+-----------
- dummy | foreign_data_user | - | |
- foo | foreign_data_user | - | | {b=3,c=4}
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+-----------
+ dummy | foreign_data_user | - | - | |
+ foo | foreign_data_user | - | - | | {b=3,c=4}
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '2');
ALTER FOREIGN DATA WRAPPER foo OPTIONS (b '4'); -- ERROR
ERROR: option "b" provided more than once
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+---------------
- dummy | foreign_data_user | - | |
- foo | foreign_data_user | - | | {b=3,c=4,a=2}
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+---------------
+ dummy | foreign_data_user | - | - | |
+ foo | foreign_data_user | - | - | | {b=3,c=4,a=2}
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
SET ROLE regress_test_role;
SET ROLE regress_test_role_super;
ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD d '5');
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+-------------------
- dummy | foreign_data_user | - | |
- foo | foreign_data_user | - | | {b=3,c=4,a=2,d=5}
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+-------------------
+ dummy | foreign_data_user | - | - | |
+ foo | foreign_data_user | - | - | | {b=3,c=4,a=2,d=5}
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
ALTER FOREIGN DATA WRAPPER foo OWNER TO regress_test_role; -- ERROR
HINT: Must be superuser to alter a foreign-data wrapper.
RESET ROLE;
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------------+--------------------------+-------------------+-------------------
- dummy | foreign_data_user | - | |
- foo | regress_test_role_super | - | | {b=3,c=4,a=2,d=5}
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------------+---------+--------------------------+-------------------+-------------------
+ dummy | foreign_data_user | - | - | |
+ foo | regress_test_role_super | - | - | | {b=3,c=4,a=2,d=5}
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
-- DROP FOREIGN DATA WRAPPER
DROP FOREIGN DATA WRAPPER IF EXISTS nonexistent;
NOTICE: foreign-data wrapper "nonexistent" does not exist, skipping
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------------+--------------------------+-------------------+-------------------
- dummy | foreign_data_user | - | |
- foo | regress_test_role_super | - | | {b=3,c=4,a=2,d=5}
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------------+---------+--------------------------+-------------------+-------------------
+ dummy | foreign_data_user | - | - | |
+ foo | regress_test_role_super | - | - | | {b=3,c=4,a=2,d=5}
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
DROP ROLE regress_test_role_super; -- ERROR
DROP FOREIGN DATA WRAPPER foo;
DROP ROLE regress_test_role_super;
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+---------
- dummy | foreign_data_user | - | |
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy | foreign_data_user | - | - | |
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(2 rows)
CREATE FOREIGN DATA WRAPPER foo;
CREATE SERVER s1 FOREIGN DATA WRAPPER foo;
CREATE USER MAPPING FOR current_user SERVER s1;
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+---------
- dummy | foreign_data_user | - | |
- foo | foreign_data_user | - | |
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy | foreign_data_user | - | - | |
+ foo | foreign_data_user | - | - | |
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(3 rows)
\des+
DETAIL: drop cascades to server s1
drop cascades to user mapping for foreign_data_user
\dew+
- List of foreign-data wrappers
- Name | Owner | Validator | Access privileges | Options
-------------+-------------------+--------------------------+-------------------+---------
- dummy | foreign_data_user | - | |
- postgresql | foreign_data_user | postgresql_fdw_validator | |
+ List of foreign-data wrappers
+ Name | Owner | Handler | Validator | Access privileges | Options
+------------+-------------------+---------+--------------------------+-------------------+---------
+ dummy | foreign_data_user | - | - | |
+ postgresql | foreign_data_user | - | postgresql_fdw_validator | |
(2 rows)
\des+
CREATE INDEX id_ft1_c2 ON ft1 (c2); -- ERROR
ERROR: "ft1" is not a table
+SELECT * FROM ft1; -- ERROR
+ERROR: foreign table scans are not yet supported
+EXPLAIN SELECT * FROM ft1; -- ERROR
+ERROR: foreign table scans are not yet supported
-- ALTER FOREIGN TABLE
COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
COMMENT ON FOREIGN TABLE ft1 IS NULL;
\c
DROP ROLE foreign_data_user;
-- At this point we should have no wrappers, no servers, and no mappings.
-SELECT fdwname, fdwvalidator, fdwoptions FROM pg_foreign_data_wrapper;
- fdwname | fdwvalidator | fdwoptions
----------+--------------+------------
+SELECT fdwname, fdwhandler, fdwvalidator, fdwoptions FROM pg_foreign_data_wrapper;
+ fdwname | fdwhandler | fdwvalidator | fdwoptions
+---------+------------+--------------+------------
(0 rows)
SELECT srvname, srvoptions FROM pg_foreign_server;
CREATE FOREIGN DATA WRAPPER postgresql VALIDATOR postgresql_fdw_validator;
-- At this point we should have 2 built-in wrappers and no servers.
-SELECT fdwname, fdwvalidator::regproc, fdwoptions FROM pg_foreign_data_wrapper ORDER BY 1, 2, 3;
+SELECT fdwname, fdwhandler::regproc, 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;
\d+ ft1
\det+
CREATE INDEX id_ft1_c2 ON ft1 (c2); -- ERROR
+SELECT * FROM ft1; -- ERROR
+EXPLAIN SELECT * FROM ft1; -- ERROR
-- ALTER FOREIGN TABLE
COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
DROP ROLE foreign_data_user;
-- At this point we should have no wrappers, no servers, and no mappings.
-SELECT fdwname, fdwvalidator, fdwoptions FROM pg_foreign_data_wrapper;
+SELECT fdwname, fdwhandler, fdwvalidator, fdwoptions FROM pg_foreign_data_wrapper;
SELECT srvname, srvoptions FROM pg_foreign_server;
SELECT * FROM pg_user_mapping;