SQL/MED catalog manipulation facilities

This doesn't do any remote or external things yet, but it gives modules
like plproxy and dblink a standardized and future-proof system for
managing their connection information.

Martin Pihlak and Peter Eisentraut
This commit is contained in:
Peter Eisentraut 2008-12-19 16:25:19 +00:00
parent 1eec10a2de
commit cae565e503
76 changed files with 8452 additions and 125 deletions

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.184 2008/12/18 18:20:33 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.185 2008/12/19 16:25:16 petere Exp $ -->
<!--
Documentation of the system catalogs, directed toward PostgreSQL developers
-->
@ -133,6 +133,16 @@
<entry>enum label and value definitions</entry>
</row>
<row>
<entry><link linkend="catalog-pg-foreign-data-wrapper"><structname>pg_foreign_data_wrapper</structname></link></entry>
<entry>foreign-data wrapper definitions</entry>
</row>
<row>
<entry><link linkend="catalog-pg-foreign-server"><structname>pg_foreign_server</structname></link></entry>
<entry>foreign server definitions</entry>
</row>
<row>
<entry><link linkend="catalog-pg-index"><structname>pg_index</structname></link></entry>
<entry>additional index information</entry>
@ -247,6 +257,11 @@
<entry><link linkend="catalog-pg-type"><structname>pg_type</structname></link></entry>
<entry>data types</entry>
</row>
<row>
<entry><link linkend="catalog-pg-user-mapping"><structname>pg_user_mapping</structname></link></entry>
<entry>mappings of users to foreign servers</entry>
</row>
</tbody>
</tgroup>
</table>
@ -2552,6 +2567,229 @@
</sect1>
<sect1 id="catalog-pg-foreign-data-wrapper">
<title><structname>pg_foreign_data_wrapper</structname></title>
<indexterm zone="catalog-pg-foreign-data-wrapper">
<primary>pg_foreign_data_wrapper</primary>
</indexterm>
<para>
The catalog <structname>pg_foreign_data_wrapper</structname> stores
foreign-data wrapper definitions. A foreign-data wrapper is the
mechanism by which external data, residing on foreign servers, is
accessed.
</para>
<table>
<title><structname>pg_foreign_data_wrapper</> Columns</title>
<tgroup cols=4>
<thead>
<row>
<entry>Name</entry>
<entry>Type</entry>
<entry>References</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><structfield>fdwname</structfield></entry>
<entry><type>name</type></entry>
<entry></entry>
<entry>Name of the foreign-data wrapper</entry>
</row>
<row>
<entry><structfield>fdwowner</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
<entry>Owner of the foreign-data wrapper</entry>
</row>
<row>
<entry><structfield>fdwlibrary</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>File name of the library implementing this foreign-data wrapper</entry>
</row>
<row>
<entry><structfield>fdwacl</structfield></entry>
<entry><type>aclitem[]</type></entry>
<entry></entry>
<entry>
Access privileges; see
<xref linkend="sql-grant" endterm="sql-grant-title"> and
<xref linkend="sql-revoke" endterm="sql-revoke-title">
for details
</entry>
</row>
<row>
<entry><structfield>fdwoptions</structfield></entry>
<entry><type>text[]</type></entry>
<entry></entry>
<entry>
Foreign-data wrapper specific options, as <quote>keyword=value</> strings
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="catalog-pg-foreign-server">
<title><structname>pg_foreign_server</structname></title>
<indexterm zone="catalog-pg-foreign-server">
<primary>pg_foreign_server</primary>
</indexterm>
<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
servers are accessed via foreign-data wrappers.
</para>
<table>
<title><structname>pg_foreign_server</> Columns</title>
<tgroup cols=4>
<thead>
<row>
<entry>Name</entry>
<entry>Type</entry>
<entry>References</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><structfield>srvname</structfield></entry>
<entry><type>name</type></entry>
<entry></entry>
<entry>Name of the foreign server</entry>
</row>
<row>
<entry><structfield>srvowner</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
<entry>Owner of the foreign server</entry>
</row>
<row>
<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>
</row>
<row>
<entry><structfield>srvtype</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>Type of the server (optional)</entry>
</row>
<row>
<entry><structfield>srvversion</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>Version of the server (optional)</entry>
</row>
<row>
<entry><structfield>srvacl</structfield></entry>
<entry><type>aclitem[]</type></entry>
<entry></entry>
<entry>
Access privileges; see
<xref linkend="sql-grant" endterm="sql-grant-title"> and
<xref linkend="sql-revoke" endterm="sql-revoke-title">
for details
</entry>
</row>
<row>
<entry><structfield>srvoptions</structfield></entry>
<entry><type>text[]</type></entry>
<entry></entry>
<entry>
Foreign server specific options, as <quote>keyword=value</> strings.
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="catalog-pg-user-mapping">
<title><structname>pg_user_mapping</structname></title>
<indexterm zone="catalog-pg-user-mapping">
<primary>pg_user_mapping</primary>
</indexterm>
<para>
The catalog <structname>pg_user_mapping</structname> stores
the mappings from local user to remote. Access to this catalog is
restricted from normal users, use the view
<link linkend="view-pg-user-mappings"><structname>pg_user_mappings</structname></link>
instead.
</para>
<table>
<title><structname>pg_user_mapping</> Columns</title>
<tgroup cols=4>
<thead>
<row>
<entry>Name</entry>
<entry>Type</entry>
<entry>References</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><structfield>umuser</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
<entry>OID of the local role being mapped, 0 if the user mapping is public</entry>
</row>
<row>
<entry><structfield>umserver</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 that contains this mapping
</entry>
</row>
<row>
<entry><structfield>umoptions</structfield></entry>
<entry><type>text[]</type></entry>
<entry></entry>
<entry>
User mapping specific options, as <quote>keyword=value</> strings.
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="catalog-pg-index">
<title><structname>pg_index</structname></title>
@ -7019,6 +7257,91 @@
</sect1>
<sect1 id="view-pg-user-mappings">
<title><structname>pg_user_mappings</structname></title>
<indexterm zone="view-pg-user-mappings">
<primary>pg_user_mappings</primary>
</indexterm>
<para>
The view <structname>pg_user_mappings</structname> provides access
to information about user mappings. This is essentially a publicly
readable view of
<link linkend="catalog-pg-user-mapping"><structname>pg_user_mapping</structname></link>
that leaves out the options field if the user has no rights to use
it.
</para>
<table>
<title><structname>pg_user_mappings</> Columns</title>
<tgroup cols=3>
<thead>
<row>
<entry>Name</entry>
<entry>Type</entry>
<entry>References</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><structfield>umid</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-user-mapping"><structname>pg_user_mapping</structname></link>.oid</literal></entry>
<entry>OID of the user mapping</entry>
</row>
<row>
<entry><structfield>srvid</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 that contains this mapping
</entry>
</row>
<row>
<entry><structfield>srvname</structfield></entry>
<entry><type>text</type></entry>
<entry></entry>
<entry>
Name of the foreign server
</entry>
</row>
<row>
<entry><structfield>umuser</structfield></entry>
<entry><type>oid</type></entry>
<entry><literal><link linkend="catalog-pg-authid"><structname>pg_authid</structname></link>.oid</literal></entry>
<entry>OID of the local role being mapped, 0 if the user mapping is public</entry>
</row>
<row>
<entry><structfield>usename</structfield></entry>
<entry><type>name</type></entry>
<entry></entry>
<entry>Name of the local user to be mapped</entry>
</row>
<row>
<entry><structfield>umoptions</structfield></entry>
<entry><type>text[]</type></entry>
<entry></entry>
<entry>
User mapping specific options, as <quote>keyword=value</>
strings, if the current user is the owner of the foreign
server, else null.
</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="view-pg-views">
<title><structname>pg_views</structname></title>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/features.sgml,v 2.29 2008/11/27 12:12:02 petere Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/features.sgml,v 2.30 2008/12/19 16:25:16 petere Exp $ -->
<appendix id="features">
<title>SQL Conformance</title>
@ -71,11 +71,11 @@
</para>
<para>
The <productname>PostgreSQL</productname> core covers parts 1, 2,
The <productname>PostgreSQL</productname> core covers parts 1, 2, 9,
11, and 14. Part 3 is covered by the ODBC driver, and part 13 is
covered by the PL/Java plug-in, but exact conformance is currently
not being verified for these components. There are currently no
implementations of parts 4, 9, and 10
implementations of parts 4 and 10
for <productname>PostgreSQL</productname>.
</para>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.462 2008/12/18 18:20:33 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.463 2008/12/19 16:25:16 petere Exp $ -->
<chapter id="functions">
<title>Functions and Operators</title>
@ -11335,6 +11335,21 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
<entry><type>boolean</type></entry>
<entry>does current user have privilege for database</entry>
</row>
<row>
<entry><literal><function>has_foreign_data_wrapper_privilege</function>(<parameter>user</parameter>,
<parameter>fdw</parameter>,
<parameter>privilege</parameter>)</literal>
</entry>
<entry><type>boolean</type></entry>
<entry>does user have privilege for foreign-data wrapper</entry>
</row>
<row>
<entry><literal><function>has_foreign_data_wrapper_privilege</function>(<parameter>fdw</parameter>,
<parameter>privilege</parameter>)</literal>
</entry>
<entry><type>boolean</type></entry>
<entry>does current user have privilege for foreign-data wrapper</entry>
</row>
<row>
<entry><literal><function>has_function_privilege</function>(<parameter>user</parameter>,
<parameter>function</parameter>,
@ -11380,6 +11395,21 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
<entry><type>boolean</type></entry>
<entry>does current user have privilege for schema</entry>
</row>
<row>
<entry><literal><function>has_server_privilege</function>(<parameter>user</parameter>,
<parameter>server</parameter>,
<parameter>privilege</parameter>)</literal>
</entry>
<entry><type>boolean</type></entry>
<entry>does user have privilege for foreign server</entry>
</row>
<row>
<entry><literal><function>has_server_privilege</function>(<parameter>server</parameter>,
<parameter>privilege</parameter>)</literal>
</entry>
<entry><type>boolean</type></entry>
<entry>does current user have privilege for foreign server</entry>
</row>
<row>
<entry><literal><function>has_table_privilege</function>(<parameter>user</parameter>,
<parameter>table</parameter>,
@ -11435,12 +11465,18 @@ SET search_path TO <replaceable>schema</> <optional>, <replaceable>schema</>, ..
<indexterm>
<primary>has_function_privilege</primary>
</indexterm>
<indexterm>
<primary>has_foreign_data_wrapper_privilege</primary>
</indexterm>
<indexterm>
<primary>has_language_privilege</primary>
</indexterm>
<indexterm>
<primary>has_schema_privilege</primary>
</indexterm>
<indexterm>
<primary>has_server_privilege</primary>
</indexterm>
<indexterm>
<primary>has_table_privilege</primary>
</indexterm>
@ -11478,6 +11514,14 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
</programlisting>
</para>
<para>
<function>has_foreign_data_wrapper_privilege</function> checks whether a user
can access a foreign-data wrapper in a particular way. The possibilities for its
arguments are analogous to <function>has_table_privilege</function>.
The desired access privilege type must evaluate to
<literal>USAGE</literal>.
</para>
<para>
<function>has_language_privilege</function> checks whether a user
can access a procedural language in a particular way. The possibilities
@ -11495,6 +11539,14 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute');
<literal>USAGE</literal>.
</para>
<para>
<function>has_server_privilege</function> checks whether a user
can access a foreign server in a particular way. The possibilities for its
arguments are analogous to <function>has_table_privilege</function>.
The desired access privilege type must evaluate to
<literal>USAGE</literal>.
</para>
<para>
<function>has_table_privilege</function> checks whether a user
can access a table in a particular way. The user can be

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/information_schema.sgml,v 1.35 2008/11/25 20:47:42 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/information_schema.sgml,v 1.36 2008/12/19 16:25:16 petere Exp $ -->
<chapter id="information-schema">
<title>The Information Schema</title>
@ -2145,6 +2145,237 @@ ORDER BY c.ordinal_position;
</table>
</sect1>
<sect1 id="infoschema-foreign-data-wrapper-options">
<title><literal>foreign_data_wrapper_options</literal></title>
<para>
The view <literal>foreign_data_wrapper_options</literal> contains
all the options defined for foreign-data wrappers in the current
database. Only those foreign-data wrappers are shown that the
current user has access to (by way of being the owner or having
some privilege).
</para>
<table>
<title><literal>foreign_data_wrapper_options</literal> Columns</title>
<tgroup cols="3">
<thead>
<row>
<entry>Name</entry>
<entry>Data Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>foreign_data_wrapper_catalog</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the database that the foreign-data wrapper is defined in (always the current database)</entry>
</row>
<row>
<entry><literal>foreign_data_wrapper_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the foreign-data wrapper</entry>
</row>
<row>
<entry><literal>option_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of an option</entry>
</row>
<row>
<entry><literal>option_value</literal></entry>
<entry><type>character_data</type></entry>
<entry>Value of the option</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="infoschema-foreign-data-wrappers">
<title><literal>foreign_data_wrappers</literal></title>
<para>
The view <literal>foreign_data_wrappers</literal> contains all
foreign-data wrappers defined in the current database. Only those
foreign-data wrappers are shown that the current user has access to
(by way of being the owner or having some privilege).
</para>
<table>
<title><literal>foreign_data_wrappers</literal> Columns</title>
<tgroup cols="3">
<thead>
<row>
<entry>Name</entry>
<entry>Data Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>foreign_data_wrapper_catalog</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the database that contains the foreign-data
wrapper (always the current database)</entry>
</row>
<row>
<entry><literal>foreign_data_wrapper_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the foreign-data wrapper</entry>
</row>
<row>
<entry><literal>authorization_identifier</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the owner of the foreign server</entry>
</row>
<row>
<entry><literal>library_name</literal></entry>
<entry><type>character_data</type></entry>
<entry>File name of the library that implementing this foreign-data wrapper</entry>
</row>
<row>
<entry><literal>foreign_data_wrapper_language</literal></entry>
<entry><type>character_data</type></entry>
<entry>Language used to implement this foreign-data wrapper</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="infoschema-foreign-server-options">
<title><literal>foreign_server_options</literal></title>
<para>
The view <literal>foreign_server_options</literal> contains all the
options defined for foreign servers in the current database. Only
those foreign servers are shown that the current user has access to
(by way of being the owner or having some privilege).
</para>
<table>
<title><literal>foreign_server_options</literal> Columns</title>
<tgroup cols="3">
<thead>
<row>
<entry>Name</entry>
<entry>Data Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>foreign_server_catalog</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the database that the foreign server is defined in (always the current database)</entry>
</row>
<row>
<entry><literal>foreign_server_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the foreign server</entry>
</row>
<row>
<entry><literal>option_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of an option</entry>
</row>
<row>
<entry><literal>option_value</literal></entry>
<entry><type>character_data</type></entry>
<entry>Value of the option</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="infoschema-foreign-servers">
<title><literal>foreign_servers</literal></title>
<para>
The view <literal>foreign_servers</literal> contains all foreign
servers defined in the current database. Only those foreign
servers are shown that the current user has access to (by way of
being the owner or having some privilege).
</para>
<table>
<title><literal>foreign_servers</literal> Columns</title>
<tgroup cols="3">
<thead>
<row>
<entry>Name</entry>
<entry>Data Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>foreign_server_catalog</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the database that the foreign server is defined in (always the current database)</entry>
</row>
<row>
<entry><literal>foreign_server_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the foreign server</entry>
</row>
<row>
<entry><literal>foreign_data_wrapper_catalog</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the database that contains the foreign-data
wrapper used by the foreign server (always the current database)</entry>
</row>
<row>
<entry><literal>foreign_data_wrapper_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the foreign-data wrapper used by the foreign server</entry>
</row>
<row>
<entry><literal>foreign_server_type</literal></entry>
<entry><type>character_data</type></entry>
<entry>Foreign server type information, if specified upon creation</entry>
</row>
<row>
<entry><literal>foreign_server_version</literal></entry>
<entry><type>character_data</type></entry>
<entry>Foreign server version information, if specified upon creation</entry>
</row>
<row>
<entry><literal>authorization_identifier</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the owner of the foreign server</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="infoschema-key-column-usage">
<title><literal>key_column_usage</literal></title>
@ -2848,15 +3079,11 @@ ORDER BY c.ordinal_position;
<title><literal>role_usage_grants</literal></title>
<para>
The view <literal>role_usage_grants</literal> is meant to identify
The view <literal>role_usage_grants</literal> identifies
<literal>USAGE</literal> privileges granted on various kinds of
objects to a currently enabled role or by a currently enabled role.
In <productname>PostgreSQL</productname>, this currently only
applies to domains, and since domains do not have real privileges
in <productname>PostgreSQL</productname>, this view is empty.
objects where the grantor or grantee is a currently enabled role.
Further information can be found under
<literal>usage_privileges</literal>. In the future, this view might
contain more useful information.
<literal>usage_privileges</literal>.
</para>
<table>
@ -2875,13 +3102,13 @@ ORDER BY c.ordinal_position;
<row>
<entry><literal>grantor</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>In the future, the name of the role that granted the privilege</entry>
<entry>The name of the role that granted the privilege</entry>
</row>
<row>
<entry><literal>grantee</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>In the future, the name of the role that the privilege was granted to</entry>
<entry>The name of the role that the privilege was granted to</entry>
</row>
<row>
@ -2893,7 +3120,8 @@ ORDER BY c.ordinal_position;
<row>
<entry><literal>object_schema</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the schema containing the object</entry>
<entry>Name of the schema containing the object, if applicable,
else an empty string</entry>
</row>
<row>
@ -2905,7 +3133,7 @@ ORDER BY c.ordinal_position;
<row>
<entry><literal>object_type</literal></entry>
<entry><type>character_data</type></entry>
<entry>In the future, the type of the object</entry>
<entry><literal>DOMAIN</literal> or <literal>FOREIGN DATA WRAPPER</literal> or <literal>FOREIGN SERVER</literal></entry>
</row>
<row>
@ -4718,15 +4946,20 @@ ORDER BY c.ordinal_position;
<title><literal>usage_privileges</literal></title>
<para>
The view <literal>usage_privileges</literal> is meant to identify
The view <literal>usage_privileges</literal> identifies
<literal>USAGE</literal> privileges granted on various kinds of
objects to a currently enabled role or by a currently enabled role.
In <productname>PostgreSQL</productname>, this currently only
applies to domains, and since domains do not have real privileges
In <productname>PostgreSQL</productname>, this currently applies to
domains, foreign-data wrappers, and foreign servers. There is one
row for each combination of object, grantor, and grantee.
</para>
<para>
Since domains do not have real privileges
in <productname>PostgreSQL</productname>, this view shows implicit
<literal>USAGE</literal> privileges granted to
<literal>PUBLIC</literal> for all domains. In the future, this
view might contain more useful information.
non-grantable <literal>USAGE</literal> privileges granted by the
owner to <literal>PUBLIC</literal> for all domains. The other
object types, however, show real privileges.
</para>
<table>
@ -4745,13 +4978,13 @@ ORDER BY c.ordinal_position;
<row>
<entry><literal>grantor</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Currently set to the name of the owner of the object</entry>
<entry>Name of the role that granted the privilege</entry>
</row>
<row>
<entry><literal>grantee</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Currently always <literal>PUBLIC</literal></entry>
<entry>Name of the role that the privilege was granted to</entry>
</row>
<row>
@ -4763,7 +4996,8 @@ ORDER BY c.ordinal_position;
<row>
<entry><literal>object_schema</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the schema containing the object</entry>
<entry>Name of the schema containing the object, if applicable,
else an empty string</entry>
</row>
<row>
@ -4775,7 +5009,7 @@ ORDER BY c.ordinal_position;
<row>
<entry><literal>object_type</literal></entry>
<entry><type>character_data</type></entry>
<entry>Currently always <literal>DOMAIN</literal></entry>
<entry><literal>DOMAIN</literal> or <literal>FOREIGN DATA WRAPPER</literal> or <literal>FOREIGN SERVER</literal></entry>
</row>
<row>
@ -4787,7 +5021,115 @@ ORDER BY c.ordinal_position;
<row>
<entry><literal>is_grantable</literal></entry>
<entry><type>character_data</type></entry>
<entry>Currently always <literal>NO</literal></entry>
<entry><literal>YES</literal> if the privilege is grantable, <literal>NO</literal> if not</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="infoschema-user-mapping-options">
<title><literal>user_mapping_options</literal></title>
<para>
The view <literal>user_mapping_options</literal> contains all the
options defined for user mappings in the current database. Only
those user mappings are shown where the current user has access to
the corresponding foreign server (by way of being the owner or
having some privilege).
</para>
<table>
<title><literal>user_mapping_options</literal> Columns</title>
<tgroup cols="3">
<thead>
<row>
<entry>Name</entry>
<entry>Data Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>authorization_identifier</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the user being mapped,
or <literal>PUBLIC</literal> if the mapping is public</entry>
</row>
<row>
<entry><literal>foreign_server_catalog</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the database that the foreign server used by this
mapping is defined in (always the current database)</entry>
</row>
<row>
<entry><literal>foreign_server_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the foreign server used by this mapping</entry>
</row>
<row>
<entry><literal>option_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of an option</entry>
</row>
<row>
<entry><literal>option_value</literal></entry>
<entry><type>character_data</type></entry>
<entry>Value of the option</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1 id="infoschema-user-mappings">
<title><literal>user_mappings</literal></title>
<para>
The view <literal>user_mappings</literal> contains all user
mappings defined in the current database. Only those user mappings
are shown where the current user has access to the corresponding
foreign server (by way of being the owner or having some
privilege).
</para>
<table>
<title><literal>user_mappings</literal> Columns</title>
<tgroup cols="3">
<thead>
<row>
<entry>Name</entry>
<entry>Data Type</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry><literal>authorization_identifier</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the user being mapped,
or <literal>PUBLIC</literal> if the mapping is public</entry>
</row>
<row>
<entry><literal>foreign_server_catalog</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the database that the foreign server used by this
mapping is defined in (always the current database)</entry>
</row>
<row>
<entry><literal>foreign_server_name</literal></entry>
<entry><type>sql_identifier</type></entry>
<entry>Name of the foreign server used by this mapping</entry>
</row>
</tbody>
</tgroup>

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.21 2008/12/03 12:39:57 petere Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.22 2008/12/19 16:25:16 petere Exp $ -->
<appendix id="sql-keywords-appendix">
<title><acronym>SQL</acronym> Key Words</title>
@ -2687,6 +2687,14 @@
<entry>reserved</entry>
<entry>reserved</entry>
</row>
<row>
<entry><token>LIBRARY</token></entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
<entry></entry>
<entry></entry>
</row>
<row>
<entry><token>LIKE</token></entry>
<entry>reserved (can be function or type)</entry>
@ -2818,8 +2826,8 @@
<row>
<entry><token>MAPPING</token></entry>
<entry>non-reserved</entry>
<entry></entry>
<entry></entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
<entry></entry>
<entry></entry>
</row>
@ -3441,7 +3449,7 @@
</row>
<row>
<entry><token>OPTIONS</token></entry>
<entry></entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
@ -4455,6 +4463,14 @@
<entry>non-reserved</entry>
<entry>non-reserved</entry>
</row>
<row>
<entry><token>SERVER</token></entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
<entry></entry>
<entry></entry>
</row>
<row>
<entry><token>SERVER_NAME</token></entry>
<entry></entry>
@ -5583,6 +5599,14 @@
<entry>reserved</entry>
<entry>reserved</entry>
</row>
<row>
<entry><token>WRAPPER</token></entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
<entry>non-reserved</entry>
<entry></entry>
<entry></entry>
</row>
<row>
<entry><token>WRITE</token></entry>
<entry>non-reserved</entry>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.73 2008/03/27 17:24:16 momjian Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/allfiles.sgml,v 1.74 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
Complete list of usable sgml source files in this directory.
-->
@ -10,6 +10,7 @@ Complete list of usable sgml source files in this directory.
<!entity alterConversion system "alter_conversion.sgml">
<!entity alterDatabase system "alter_database.sgml">
<!entity alterDomain system "alter_domain.sgml">
<!entity alterForeignDataWrapper system "alter_foreign_data_wrapper.sgml">
<!entity alterFunction system "alter_function.sgml">
<!entity alterGroup system "alter_group.sgml">
<!entity alterIndex system "alter_index.sgml">
@ -19,6 +20,7 @@ Complete list of usable sgml source files in this directory.
<!entity alterOperatorFamily system "alter_opfamily.sgml">
<!entity alterRole system "alter_role.sgml">
<!entity alterSchema system "alter_schema.sgml">
<!entity alterServer system "alter_server.sgml">
<!entity alterSequence system "alter_sequence.sgml">
<!entity alterTable system "alter_table.sgml">
<!entity alterTableSpace system "alter_tablespace.sgml">
@ -29,6 +31,7 @@ Complete list of usable sgml source files in this directory.
<!entity alterTrigger system "alter_trigger.sgml">
<!entity alterType system "alter_type.sgml">
<!entity alterUser system "alter_user.sgml">
<!entity alterUserMapping system "alter_user_mapping.sgml">
<!entity alterView system "alter_view.sgml">
<!entity analyze system "analyze.sgml">
<!entity begin system "begin.sgml">
@ -45,6 +48,7 @@ Complete list of usable sgml source files in this directory.
<!entity createConversion system "create_conversion.sgml">
<!entity createDatabase system "create_database.sgml">
<!entity createDomain system "create_domain.sgml">
<!entity createForeignDataWrapper system "create_foreign_data_wrapper.sgml">
<!entity createFunction system "create_function.sgml">
<!entity createGroup system "create_group.sgml">
<!entity createIndex system "create_index.sgml">
@ -56,6 +60,7 @@ Complete list of usable sgml source files in this directory.
<!entity createRule system "create_rule.sgml">
<!entity createSchema system "create_schema.sgml">
<!entity createSequence system "create_sequence.sgml">
<!entity createServer system "create_server.sgml">
<!entity createTable system "create_table.sgml">
<!entity createTableAs system "create_table_as.sgml">
<!entity createTableSpace system "create_tablespace.sgml">
@ -66,6 +71,7 @@ Complete list of usable sgml source files in this directory.
<!entity createTSTemplate system "create_tstemplate.sgml">
<!entity createType system "create_type.sgml">
<!entity createUser system "create_user.sgml">
<!entity createUserMapping system "create_user_mapping.sgml">
<!entity createView system "create_view.sgml">
<!entity deallocate system "deallocate.sgml">
<!entity declare system "declare.sgml">
@ -76,6 +82,7 @@ Complete list of usable sgml source files in this directory.
<!entity dropConversion system "drop_conversion.sgml">
<!entity dropDatabase system "drop_database.sgml">
<!entity dropDomain system "drop_domain.sgml">
<!entity dropForeignDataWrapper system "drop_foreign_data_wrapper.sgml">
<!entity dropFunction system "drop_function.sgml">
<!entity dropGroup system "drop_group.sgml">
<!entity dropIndex system "drop_index.sgml">
@ -88,6 +95,7 @@ Complete list of usable sgml source files in this directory.
<!entity dropRule system "drop_rule.sgml">
<!entity dropSchema system "drop_schema.sgml">
<!entity dropSequence system "drop_sequence.sgml">
<!entity dropServer system "drop_server.sgml">
<!entity dropTable system "drop_table.sgml">
<!entity dropTableSpace system "drop_tablespace.sgml">
<!entity dropTrigger system "drop_trigger.sgml">
@ -97,6 +105,7 @@ Complete list of usable sgml source files in this directory.
<!entity dropTSTemplate system "drop_tstemplate.sgml">
<!entity dropType system "drop_type.sgml">
<!entity dropUser system "drop_user.sgml">
<!entity dropUserMapping system "drop_user_mapping.sgml">
<!entity dropView system "drop_view.sgml">
<!entity end system "end.sgml">
<!entity execute system "execute.sgml">

View File

@ -0,0 +1,132 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_foreign_data_wrapper.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
<refentry id="SQL-ALTERFOREIGNDATAWRAPPER">
<refmeta>
<refentrytitle id="sql-alterforeigndatawrapper-title">ALTER FOREIGN DATA WRAPPER</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>ALTER FOREIGN DATA WRAPPER</refname>
<refpurpose>change the definition of a foreign-data wrapper</refpurpose>
</refnamediv>
<indexterm zone="sql-alterforeigndatawrapper">
<primary>ALTER FOREIGN DATA WRAPPER</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
ALTER FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
[ LIBRARY '<replaceable class="parameter">libraryname</replaceable>' ]
[ 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>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<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
foreign-data wrapper (at least one clause is required). The second
form changes the owner of the foreign-data wrapper.
</para>
<para>
Only superusers can alter foreign-data wrappers. Additionally,
only superusers can own foreign-data wrappers.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><replaceable class="parameter">name</replaceable></term>
<listitem>
<para>
The name of an existing foreign-data wrapper.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">libraryname</replaceable></term>
<listitem>
<para>
New name of the foreign-data wrapper library.
</para>
<para>
Note that it is possible that after changing the library, 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
wrapper.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
<listitem>
<para>
Change options for the foreign-data
wrapper. <literal>ADD</>, <literal>SET</>, and <literal>DROP</>
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.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Change a foreign-data wrapper <literal>dbi</>, add
option <literal>foo</>, drop <literal>bar</>:
<programlisting>
ALTER FOREIGN DATA WRAPPER dbi OPTIONS (ADD foo '1', DROP 'bar');
</programlisting>
</para>
<para>
Change the foreign-data wrapper <literal>dbi</> library
to <literal>/home/bob/mylibrary.so</>:
<programlisting>
ALTER FOREIGN DATA WRAPPER dbi LIBRARY '/home/bob/mylibrary.so';
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>ALTER FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
9075-9 (SQL/MED). The standard does not specify the <literal>OWNER
TO</> variant of the command.
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-createforeigndatawrapper" endterm="sql-createforeigndatawrapper-title"></member>
<member><xref linkend="sql-dropforeigndatawrapper" endterm="sql-dropforeigndatawrapper-title"></member>
</simplelist>
</refsect1>
</refentry>

View File

@ -0,0 +1,123 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_server.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
<refentry id="SQL-ALTERSERVER">
<refmeta>
<refentrytitle id="sql-alterserver-title">ALTER SERVER</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>ALTER SERVER</refname>
<refpurpose>change the definition of a foreign server</refpurpose>
</refnamediv>
<indexterm zone="sql-alterserver">
<primary>ALTER SERVER</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
ALTER SERVER <replaceable class="parameter">servername</replaceable> [ VERSION 'newversion' ]
[ OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] ) ]
ALTER SERVER <replaceable class="PARAMETER">servername</replaceable> OWNER TO <replaceable>new_owner</replaceable>
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>ALTER SERVER</command> changes the definition of a foreign
server. The first form changes the server version string or the
generic options of the server (at least one clause is required).
The second form changes the owner of the server.
</para>
<para>
To alter the server you must be the owner of the server.
Additionally to alter the owner, you must own the server and also
be a direct or indirect member of the new owning role, and you must
have <literal>USAGE</> privilege on the server's foreign-data
wrapper. (Note that superusers satisfy all these criteria
automatically.)
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><replaceable class="parameter">servername</replaceable></term>
<listitem>
<para>
The name of an existing server.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">serverversion</replaceable></term>
<listitem>
<para>
New server version.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
<listitem>
<para>
Change options for the
server. <literal>ADD</>, <literal>SET</>, and <literal>DROP</>
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 server's
foreign-data wrapper library.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Alter server <literal>foo</>, add connection options:
<programlisting>
ALTER SERVER foo OPTIONS (host 'foo', dbname 'foodb');
</programlisting>
</para>
<para>
Alter server <literal>foo</>, change version,
change <literal>host</> option:
<programlisting>
ALTER SERVER foo VERSION '8.4' OPTIONS (SET host 'baz');
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>ALTER SERVER</command> conforms to ISO/IEC 9075-9 (SQL/MED).
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-createserver" endterm="sql-createserver-title"></member>
<member><xref linkend="sql-dropserver" endterm="sql-dropserver-title"></member>
</simplelist>
</refsect1>
</refentry>

View File

@ -0,0 +1,119 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_user_mapping.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
<refentry id="SQL-ALTERUSERMAPPING">
<refmeta>
<refentrytitle id="sql-alterusermapping-title">ALTER USER MAPPING</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>ALTER USER MAPPING</refname>
<refpurpose>change the definition of a user mapping</refpurpose>
</refnamediv>
<indexterm zone="sql-alterusermapping">
<primary>ALTER USER MAPPING</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
ALTER USER MAPPING FOR { <replaceable class="parameter">username</replaceable> | USER | CURRENT_USER | PUBLIC }
SERVER <replaceable class="parameter">servername</replaceable>
OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>ALTER USER MAPPING</command> changes the definition of a
user mapping. Only the owner of the server can change the user
mappings of that server.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><replaceable class="parameter">username</replaceable></term>
<listitem>
<para>
User name of the mapping. <literal>CURRENT_USER</>
and <literal>USER</> match the name of the current
user. <literal>PUBLIC</> is used to match all present and future
user names in the system.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">servername</replaceable></term>
<listitem>
<para>
Server name of the user mapping.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>OPTIONS ( [ ADD | SET | DROP ] <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
<listitem>
<para>
Change options for the user mapping. The new options override
any previously specified
options. <literal>ADD</>, <literal>SET</>, and <literal>DROP</>
specify the action to be performed. <literal>ADD</> is assumed
if no operation is explicitly specified. Option names must be
unique; options are also validated by the server's foreign-data
wrapper.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Change the password for user mapping <literal>bob</>, server<literal> foo</>:
<programlisting>
ALTER USER MAPPING FOR bob SERVER foo OPTIONS (user 'bob', password 'public');
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>ALTER USER MAPPING</command> conforms to ISO/IEC 9075-9
(SQL/MED). There is a subtle syntax issue: The standard omits
the <literal>FOR</literal> key word. Since both <literal>CREATE
USER MAPPING</literal> and <literal>DROP USER MAPPING</literal> use
<literal>FOR</literal> in analogous positions, and IBM DB2 (being
the other major SQL/MED implementation) also requires it
for <literal>ALTER USER MAPPING</literal>, PostgreSQL diverges from
the standard here in the interest of consistency and
interoperability.
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-createusermapping" endterm="sql-createusermapping-title"></member>
<member><xref linkend="sql-dropusermapping" endterm="sql-dropusermapping-title"></member>
</simplelist>
</refsect1>
</refentry>

View File

@ -0,0 +1,185 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_foreign_data_wrapper.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
<refentry id="SQL-CREATEFOREIGNDATAWRAPPER">
<refmeta>
<refentrytitle id="sql-createforeigndatawrapper-title">CREATE FOREIGN DATA WRAPPER</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>CREATE FOREIGN DATA WRAPPER</refname>
<refpurpose>define a new foreign-data wrapper</refpurpose>
</refnamediv>
<indexterm zone="sql-createforeigndatawrapper">
<primary>CREATE FOREIGN DATA WRAPPER</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
CREATE FOREIGN DATA WRAPPER <replaceable class="parameter">name</replaceable>
LIBRARY '<replaceable class="parameter">libraryname</replaceable>'
LANGUAGE C
[ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ]
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>CREATE FOREIGN DATA WRAPPER</command> creates a new
foreign-data wrapper. The user who defines a foreign-data wrapper
becomes its owner.
</para>
<para>
The foreign-data wrapper name must be unique within the database.
</para>
<para>
Only superusers can create foreign-data wrappers.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><replaceable class="parameter">name</replaceable></term>
<listitem>
<para>
The name of the foreign-data wrapper to be created.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">libraryname</replaceable></term>
<listitem>
<para>
The name of the shared library implementing the foreign-data
wrapper. The file name is specified in the same way as for
shared library names in <xref linkend="sql-createfunction"
endterm="sql-createfunction-title">; in particular, one can rely
on a search path and automatic addition of the system's standard
shared library file name extension.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>LANGUAGE C</literal></term>
<listitem>
<para>
Currently, only the C programming language is supported for
implementing foreign-data wrappers.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>OPTIONS ( <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
<listitem>
<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.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Notes</title>
<para>
At the moment, the foreign-data wrapper functionality is very
rudimentary. The purpose of foreign-data wrappers, foreign
servers, and user mappings is to store this information in a
standard way so that it can be queried by interested applications.
The functionality to actually query external data does not exist
yet.
</para>
<para>
The C language API for foreign-data wrappers is currently not
documented, stable, or complete. Would-be authors of functionality
interfacing with the SQL/MED functionality are advised to contact
the PostgreSQL developers.
</para>
<para>
There are currently two foreign-data wrapper libraries
provided: <filename>dummy_fdw</filename>, which does nothing and
could be useful for testing,
and <filename>postgresql_fdw</filename>, which accepts options
corresponding to <application>libpq</> connection parameters.
</para>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Create a foreign-data wrapper <literal>dummy</> with
library <literal>dummy_fdw</>:
<programlisting>
CREATE FOREIGN DATA WRAPPER dummy LIBRARY 'dummy_fdw' LANGUAGE C;
</programlisting>
</para>
<para>
Create a foreign-data wrapper <literal>postgresql</> with
library <literal>postgresql_fdw</>:
<programlisting>
CREATE FOREIGN DATA WRAPPER postgresql LIBRARY 'postgresql_fdw' LANGUAGE C;
</programlisting>
</para>
<para>
Create a foreign-data wrapper <literal>mywrapper</> with library
<literal>/home/bob/mywrapper.so</> and some options:
<programlisting>
CREATE FOREIGN DATA WRAPPER mywrapper
LIBRARY '/home/bob/mywrapper.so'
LANGUAGE C
OPTIONS (debug 'true');
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>CREATE FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
9075-9 (SQL/MED), with the exception that
the <literal>LIBRARY</literal> clause is not optional in
PostgreSQL.
</para>
<para>
Note, however, that the SQL/MED functionality as a whole is not yet
conforming.
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-alterforeigndatawrapper" endterm="sql-alterforeigndatawrapper-title"></member>
<member><xref linkend="sql-dropforeigndatawrapper" endterm="sql-dropforeigndatawrapper-title"></member>
<member><xref linkend="sql-createserver" endterm="sql-createserver-title"></member>
<member><xref linkend="sql-createusermapping" endterm="sql-createusermapping-title"></member>
</simplelist>
</refsect1>
</refentry>

View File

@ -0,0 +1,140 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_server.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
<refentry id="SQL-CREATESERVER">
<refmeta>
<refentrytitle id="sql-createserver-title">CREATE SERVER</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>CREATE SERVER</refname>
<refpurpose>define a new foreign server</refpurpose>
</refnamediv>
<indexterm zone="sql-createserver">
<primary>CREATE SERVER</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
CREATE SERVER <replaceable class="parameter">servername</replaceable> [ TYPE 'servertype' ] [ VERSION 'serverversion' ]
FOREIGN DATA WRAPPER <replaceable class="parameter">fdwname</replaceable>
[ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [, ... ] ) ]
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>CREATE SERVER</command> defines a new foreign server. The
user who defines the server becomes its owner.
</para>
<para>
The server name must be unique within database.
</para>
<para>
Creating a server requires <literal>USAGE</> privilege on the
foreign-data wrapper being used.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><replaceable class="parameter">servername</replaceable></term>
<listitem>
<para>
The name of the foreign server to be created.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">servertype</replaceable></term>
<listitem>
<para>
Optional server type.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">serverversion</replaceable></term>
<listitem>
<para>
Optional server version.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">fdwname</replaceable></term>
<listitem>
<para>
The name of the foreign-data wrapper that manages the server.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>OPTIONS ( <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
<listitem>
<para>
This clause specifies the options for the server. The options
typically define the connection details of the server, but the
actual names and values are dependent on the server's
foreign-data wrapper.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Create a server <literal>foo</> that uses the built-in foreign-data
wrapper <literal>default</>:
<programlisting>
CREATE SERVER foo FOREIGN DATA WRAPPER "default";
</programlisting>
</para>
<para>
Create a server <literal>myserver</> that uses the
foreign-data wrapper <literal>pgsql</>:
<programlisting>
CREATE SERVER myserver FOREIGN DATA WRAPPER pgsql OPTIONS (host 'foo', dbname 'foodb', port '5432');
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>CREATE SERVER</command> conforms to ISO/IEC 9075-9 (SQL/MED).
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-alterserver" endterm="sql-alterserver-title"></member>
<member><xref linkend="sql-dropserver" endterm="sql-dropserver-title"></member>
<member><xref linkend="sql-createforeigndatawrapper" endterm="sql-createforeigndatawrapper-title"></member>
<member><xref linkend="sql-createusermapping" endterm="sql-createusermapping-title"></member>
</simplelist>
</refsect1>
</refentry>

View File

@ -0,0 +1,111 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/create_user_mapping.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
<refentry id="SQL-CREATEUSERMAPPING">
<refmeta>
<refentrytitle id="sql-createusermapping-title">CREATE USER MAPPING</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>CREATE USER MAPPING</refname>
<refpurpose>define a new mapping of a user to a foreign server</refpurpose>
</refnamediv>
<indexterm zone="sql-createusermapping">
<primary>CREATE USER MAPPING</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
CREATE USER MAPPING FOR { <replaceable class="parameter">username</replaceable> | USER | CURRENT_USER | PUBLIC }
SERVER <replaceable class="parameter">servername</replaceable>
[ OPTIONS ( <replaceable class="PARAMETER">option</replaceable> '<replaceable class="PARAMETER">value</replaceable>' [ , ... ] ) ]
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>CREATE USER MAPPING</command> defines a mapping of a user
to a foreign server. You must be the owner of the server to define
user mappings for it.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><replaceable class="parameter">username</replaceable></term>
<listitem>
<para>
The name of an existing user that is mapped to foreign server.
<literal>CURRENT_USER</> and <literal>USER</> match the name of
the current user. <literal>PUBLIC</> is used to match all
present and future user names in the system.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">servername</replaceable></term>
<listitem>
<para>
The name of an existing server for which the user mapping is
to be created.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>OPTIONS ( <replaceable class="PARAMETER">option</replaceable> ['<replaceable class="PARAMETER">value</replaceable>'] [, ... ] )</literal></term>
<listitem>
<para>
This clause specifies the options of the user mapping. The
options typically define the actual user name and password of
the mapping. Option names must be unque. The allowed option
names and values are specific to the server's foreign-data wrapper.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Create a user mapping for user <literal>bob</>, server <literal>foo</>:
<programlisting>
CREATE USER MAPPING FOR bob SERVER foo OPTIONS (user 'bob', password 'secret');
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>CREATE USER MAPPING</command> conforms to ISO/IEC 9075-9 (SQL/MED).
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-alterusermapping" endterm="sql-alterusermapping-title"></member>
<member><xref linkend="sql-dropusermapping" endterm="sql-dropusermapping-title"></member>
<member><xref linkend="sql-createforeigndatawrapper" endterm="sql-createforeigndatawrapper-title"></member>
<member><xref linkend="sql-createserver" endterm="sql-createserver-title"></member>
</simplelist>
</refsect1>
</refentry>

View File

@ -0,0 +1,112 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/drop_foreign_data_wrapper.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
<refentry id="SQL-DROPFOREIGNDATAWRAPPER">
<refmeta>
<refentrytitle id="sql-dropforeigndatawrapper-title">DROP FOREIGN DATA WRAPPER</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>DROP FOREIGN DATA WRAPPER</refname>
<refpurpose>remove a foreign-data wrapper</refpurpose>
</refnamediv>
<indexterm zone="sql-dropforeigndatawrapper">
<primary>DROP FOREIGN DATA WRAPPER</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
DROP FOREIGN DATA WRAPPER [ IF EXISTS ] <replaceable class="parameter">name</replaceable> [ CASCADE | RESTRICT ]
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>DROP FOREIGN DATA WRAPPER</command> removes an existing
foreign-data wrapper. To execute this command, the current user
must be the owner of the foreign-data wrapper.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><literal>IF EXISTS</literal></term>
<listitem>
<para>
Do not throw an error if the foreign-data wrapper does not
exist. A notice is issued in this case.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">name</replaceable></term>
<listitem>
<para>
The name of an existing foreign-data wrapper.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>CASCADE</literal></term>
<listitem>
<para>
Automatically drop objects that depend on the foreign-data
wrapper (such as servers).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>RESTRICT</literal></term>
<listitem>
<para>
Refuse to drop the foreign-data wrappers if any objects depend
on it. This is the default.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Drop the foreign-data wrapper <literal>dbi</>:
<programlisting>
DROP FOREIGN DATA WRAPPER dbi;
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>DROP FOREIGN DATA WRAPPER</command> conforms to ISO/IEC
9075-9 (SQL/MED). The <literal>IF EXISTS</> clause is
a <productname>PostgreSQL</> extension.
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-createforeigndatawrapper" endterm="sql-createforeigndatawrapper-title"></member>
<member><xref linkend="sql-alterforeigndatawrapper" endterm="sql-alterforeigndatawrapper-title"></member>
</simplelist>
</refsect1>
</refentry>

View File

@ -0,0 +1,112 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/drop_server.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
<refentry id="SQL-DROPSERVER">
<refmeta>
<refentrytitle id="sql-dropserver-title">DROP SERVER</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>DROP SERVER</refname>
<refpurpose>remove a foreign server descriptor</refpurpose>
</refnamediv>
<indexterm zone="sql-dropserver">
<primary>DROP SERVER</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
DROP SERVER [ IF EXISTS ] <replaceable class="parameter">servername</replaceable> [ CASCADE | RESTRICT ]
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>DROP SERVER</command> removes an existing foreign server
descriptor. To execute this command, the current user must be the
owner of the server.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><literal>IF EXISTS</literal></term>
<listitem>
<para>
Do not throw an error if the server does not exist. A notice is
issued in this case.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">servername</replaceable></term>
<listitem>
<para>
The name of an existing server.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>CASCADE</literal></term>
<listitem>
<para>
Automatically drop objects that depend on the server (such as
user mappings).
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>RESTRICT</literal></term>
<listitem>
<para>
Refuse to drop the server if any objects depend on it. This is
the default.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Drop a server <literal>foo</> if it exists:
<programlisting>
DROP SERVER IF EXISTS foo;
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>DROP SERVER</command> conforms to ISO/IEC 9075-9
(SQL/MED). The <literal>IF EXISTS</> clause is
a <productname>PostgreSQL</> extension.
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-createserver" endterm="sql-createserver-title"></member>
<member><xref linkend="sql-alterserver" endterm="sql-alterserver-title"></member>
</simplelist>
</refsect1>
</refentry>

View File

@ -0,0 +1,104 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/drop_user_mapping.sgml,v 1.1 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
<refentry id="SQL-DROPUSERMAPPING">
<refmeta>
<refentrytitle id="sql-dropusermapping-title">DROP USER MAPPING</refentrytitle>
<refmiscinfo>SQL - Language Statements</refmiscinfo>
</refmeta>
<refnamediv>
<refname>DROP USER MAPPING</refname>
<refpurpose>remove a user mapping for a foreign server</refpurpose>
</refnamediv>
<indexterm zone="sql-dropusermapping">
<primary>DROP USER MAPPING</primary>
</indexterm>
<refsynopsisdiv>
<synopsis>
DROP USER MAPPING [ IF EXISTS ] FOR { <replaceable class="parameter">username</replaceable> | USER | CURRENT_USER | PUBLIC } SERVER <replaceable class="parameter">servername</replaceable>
</synopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para>
<command>DROP USER MAPPING</command> removes an existing user
mapping from foreign server. To execute this command, the current
user must be the owner of the server containing the mapping.
</para>
</refsect1>
<refsect1>
<title>Parameters</title>
<variablelist>
<varlistentry>
<term><literal>IF EXISTS</literal></term>
<listitem>
<para>
Do not throw an error if the user mapping does not exist. A
notice is issued in this case.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">username</replaceable></term>
<listitem>
<para>
User name of the mapping. <literal>CURRENT_USER</>
and <literal>USER</> match the name of the current
user. <literal>PUBLIC</> is used to match all present and
future user names in the system.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><replaceable class="parameter">servername</replaceable></term>
<listitem>
<para>
Server name of the user mapping.
</para>
</listitem>
</varlistentry>
</variablelist>
</refsect1>
<refsect1>
<title>Examples</title>
<para>
Drop a user mapping <literal>bob</>, server <literal>foo</> if it exists:
<programlisting>
DROP USER MAPPING IF EXISTS FOR bob SERVER foo;
</programlisting>
</para>
</refsect1>
<refsect1>
<title>Compatibility</title>
<para>
<command>DROP USER MAPPING</command> conforms to ISO/IEC 9075-9
(SQL/MED). The <literal>IF EXISTS</> clause is
a <productname>PostgreSQL</> extension.
</para>
</refsect1>
<refsect1>
<title>See Also</title>
<simplelist type="inline">
<member><xref linkend="sql-createusermapping" endterm="sql-createusermapping-title"></member>
<member><xref linkend="sql-alterusermapping" endterm="sql-alterusermapping-title"></member>
</simplelist>
</refsect1>
</refentry>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.72 2008/11/14 10:22:47 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.73 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
@ -35,6 +35,14 @@ GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
ON DATABASE <replaceable>dbname</replaceable> [, ...]
TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN DATA WRAPPER <replaceable>fdwname</> [, ...]
TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN SERVER <replaceable>servername</> [, ...]
TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { EXECUTE | ALL [ PRIVILEGES ] }
ON FUNCTION <replaceable>funcname</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) [, ...]
TO { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
@ -61,10 +69,10 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
<para>
The <command>GRANT</command> command has two basic variants: one
that grants privileges on a database object (table, view, sequence,
database, function, procedural language, schema, or tablespace),
and one that grants membership in a role. These variants are
similar in many ways, but they are different enough to be described
separately.
database, foreign-data wrapper, foreign server, function,
procedural language, schema, or tablespace), and one that grants
membership in a role. These variants are similar in many ways, but
they are different enough to be described separately.
</para>
<para>
@ -299,6 +307,14 @@ GRANT <replaceable class="PARAMETER">role</replaceable> [, ...] TO <replaceable
For sequences, this privilege allows the use of the
<function>currval</function> and <function>nextval</function> functions.
</para>
<para>
For foreign-data wrappers, this privilege enables the grantee
to create new servers using that foreign-data wrapper.
</para>
<para>
For servers, this privilege enables the grantee to query the
options of the server and associated user mappings.
</para>
</listitem>
</varlistentry>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.213 2008/12/01 09:20:37 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/psql-ref.sgml,v 1.214 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
@ -946,6 +946,64 @@ testdb=&gt;
</varlistentry>
<varlistentry>
<term><literal>\des [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
<term><literal>\des+ [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
<listitem>
<para>
Lists all foreign servers (mnemonic: <quote>external
servers</quote>).
If <replaceable class="parameter">pattern</replaceable> is
specified, only those servers whose name matches the pattern
are listed. If the form <literal>\des+</literal> is used, a
full desription of each server is shown, including the
server's ACL, type, version, and options.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>\deu [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
<term><literal>\deu+ [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
<listitem>
<para>
Lists all user mappings (mnemonic: <quote>external
users</quote>).
If <replaceable class="parameter">pattern</replaceable> is
specified, only those mappings whose user names match the
pattern are listed. If the form <literal>\deu+</literal> is
used, additional information about each mapping is shown.
</para>
<caution>
<para>
<literal>\deu+</literal> might also display the user name and
password of the remote user, so care should be taken not to
disclose them.
</para>
</caution>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>\dew [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
<term><literal>\dew+ [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
<listitem>
<para>
Lists all foreign-data wrappers (mnemonic: <quote>external
wrappers</quote>).
If <replaceable class="parameter">pattern</replaceable> is
specified, only those foreign-data wrappers whose name matches
the pattern are listed. If the form <literal>\dew+</literal>
is used, the ACL and options of the foreign-data wrapper are
also shown.
</para>
</listitem>
</varlistentry>
<varlistentry>
<term><literal>\df [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>
<term><literal>\df+ [ <replaceable class="parameter">pattern</replaceable> ]</literal></term>

View File

@ -1,5 +1,5 @@
<!--
$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.49 2008/11/14 10:22:47 petere Exp $
$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.50 2008/12/19 16:25:16 petere Exp $
PostgreSQL documentation
-->
@ -41,6 +41,18 @@ REVOKE [ GRANT OPTION FOR ]
FROM { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN DATA WRAPPER <replaceable>fdwname</replaceable> [, ...]
FROM { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ USAGE | ALL [ PRIVILEGES ] }
ON FOREIGN SERVER <replaceable>servername</replaceable> [, ...]
FROM { [ GROUP ] <replaceable class="PARAMETER">rolename</replaceable> | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ EXECUTE | ALL [ PRIVILEGES ] }
ON FUNCTION <replaceable>funcname</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">argname</replaceable> ] <replaceable class="parameter">argtype</replaceable> [, ...] ] ) [, ...]

View File

@ -1,4 +1,4 @@
<!-- $PostgreSQL: pgsql/doc/src/sgml/reference.sgml,v 1.66 2008/03/27 17:24:16 momjian Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/reference.sgml,v 1.67 2008/12/19 16:25:16 petere Exp $ -->
<part id="reference">
<title>Reference</title>
@ -38,6 +38,7 @@
&alterConversion;
&alterDatabase;
&alterDomain;
&alterForeignDataWrapper;
&alterFunction;
&alterGroup;
&alterIndex;
@ -48,6 +49,7 @@
&alterRole;
&alterSchema;
&alterSequence;
&alterServer;
&alterTable;
&alterTableSpace;
&alterTSConfig;
@ -57,6 +59,7 @@
&alterTrigger;
&alterType;
&alterUser;
&alterUserMapping;
&alterView;
&analyze;
&begin;
@ -73,6 +76,7 @@
&createConversion;
&createDatabase;
&createDomain;
&createForeignDataWrapper;
&createFunction;
&createGroup;
&createIndex;
@ -84,6 +88,7 @@
&createRule;
&createSchema;
&createSequence;
&createServer;
&createTable;
&createTableAs;
&createTableSpace;
@ -94,6 +99,7 @@
&createTrigger;
&createType;
&createUser;
&createUserMapping;
&createView;
&deallocate;
&declare;
@ -104,6 +110,7 @@
&dropConversion;
&dropDatabase;
&dropDomain;
&dropForeignDataWrapper;
&dropFunction;
&dropGroup;
&dropIndex;
@ -116,6 +123,7 @@
&dropRule;
&dropSchema;
&dropSequence;
&dropServer;
&dropTable;
&dropTableSpace;
&dropTSConfig;
@ -125,6 +133,7 @@
&dropTrigger;
&dropType;
&dropUser;
&dropUserMapping;
&dropView;
&end;
&execute;

View File

@ -4,7 +4,7 @@
#
# Copyright (c) 1994, Regents of the University of California
#
# $PostgreSQL: pgsql/src/Makefile,v 1.43 2008/03/18 16:24:50 petere Exp $
# $PostgreSQL: pgsql/src/Makefile,v 1.44 2008/12/19 16:25:16 petere Exp $
#
#-------------------------------------------------------------------------
@ -19,6 +19,7 @@ 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 $@

View File

@ -5,7 +5,7 @@
# Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
# $PostgreSQL: pgsql/src/backend/Makefile,v 1.130 2008/08/29 13:02:32 petere Exp $
# $PostgreSQL: pgsql/src/backend/Makefile,v 1.131 2008/12/19 16:25:16 petere Exp $
#
#-------------------------------------------------------------------------
@ -14,7 +14,7 @@ subdir = src/backend
top_builddir = ../..
include $(top_builddir)/src/Makefile.global
SUBDIRS = access bootstrap catalog parser commands executor lib libpq \
SUBDIRS = access bootstrap catalog parser commands executor foreign lib libpq \
main nodes optimizer port postmaster regex rewrite \
storage tcop tsearch utils $(top_builddir)/src/timezone

View File

@ -2,7 +2,7 @@
#
# Makefile for backend/catalog
#
# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.67 2008/11/19 10:34:51 heikki Exp $
# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.68 2008/12/19 16:25:16 petere Exp $
#
#-------------------------------------------------------------------------
@ -36,6 +36,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
pg_authid.h pg_auth_members.h pg_shdepend.h pg_shdescription.h \
pg_ts_config.h pg_ts_config_map.h pg_ts_dict.h \
pg_ts_parser.h pg_ts_template.h \
pg_foreign_data_wrapper.h pg_foreign_server.h pg_user_mapping.h \
toasting.h indexing.h \
)

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.149 2008/11/02 01:45:27 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.150 2008/12/19 16:25:16 petere Exp $
*
* NOTES
* See acl.h.
@ -27,6 +27,8 @@
#include "catalog/pg_authid.h"
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
@ -38,6 +40,7 @@
#include "catalog/pg_ts_config.h"
#include "catalog/pg_ts_dict.h"
#include "commands/dbcommands.h"
#include "foreign/foreign.h"
#include "miscadmin.h"
#include "parser/parse_func.h"
#include "utils/acl.h"
@ -50,6 +53,8 @@
static void ExecGrant_Relation(InternalGrant *grantStmt);
static void ExecGrant_Database(InternalGrant *grantStmt);
static void ExecGrant_Fdw(InternalGrant *grantStmt);
static void ExecGrant_ForeignServer(InternalGrant *grantStmt);
static void ExecGrant_Function(InternalGrant *grantStmt);
static void ExecGrant_Language(InternalGrant *grantStmt);
static void ExecGrant_Namespace(InternalGrant *grantStmt);
@ -188,6 +193,12 @@ restrict_and_check_grant(bool is_grant, AclMode avail_goptions, bool all_privs,
case ACL_KIND_TABLESPACE:
whole_mask = ACL_ALL_RIGHTS_TABLESPACE;
break;
case ACL_KIND_FDW:
whole_mask = ACL_ALL_RIGHTS_FDW;
break;
case ACL_KIND_FOREIGN_SERVER:
whole_mask = ACL_ALL_RIGHTS_FOREIGN_SERVER;
break;
default:
elog(ERROR, "unrecognized object kind: %d", objkind);
/* not reached, but keep compiler quiet */
@ -323,6 +334,14 @@ ExecuteGrantStmt(GrantStmt *stmt)
all_privileges = ACL_ALL_RIGHTS_TABLESPACE;
errormsg = gettext_noop("invalid privilege type %s for tablespace");
break;
case ACL_OBJECT_FDW:
all_privileges = ACL_ALL_RIGHTS_FDW;
errormsg = gettext_noop("invalid privilege type %s for foreign-data wrapper");
break;
case ACL_OBJECT_FOREIGN_SERVER:
all_privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
errormsg = gettext_noop("invalid privilege type %s for foreign server");
break;
default:
/* keep compiler quiet */
all_privileges = ACL_NO_RIGHTS;
@ -380,6 +399,12 @@ ExecGrantStmt_oids(InternalGrant *istmt)
case ACL_OBJECT_DATABASE:
ExecGrant_Database(istmt);
break;
case ACL_OBJECT_FDW:
ExecGrant_Fdw(istmt);
break;
case ACL_OBJECT_FOREIGN_SERVER:
ExecGrant_ForeignServer(istmt);
break;
case ACL_OBJECT_FUNCTION:
ExecGrant_Function(istmt);
break;
@ -520,6 +545,24 @@ objectNamesToOids(GrantObjectType objtype, List *objnames)
heap_close(relation, AccessShareLock);
}
break;
case ACL_OBJECT_FDW:
foreach(cell, objnames)
{
char *fdwname = strVal(lfirst(cell));
Oid fdwid = GetForeignDataWrapperOidByName(fdwname, false);
objects = lappend_oid(objects, fdwid);
}
break;
case ACL_OBJECT_FOREIGN_SERVER:
foreach(cell, objnames)
{
char *srvname = strVal(lfirst(cell));
Oid srvid = GetForeignServerOidByName(srvname, false);
objects = lappend_oid(objects, srvid);
}
break;
default:
elog(ERROR, "unrecognized GrantStmt.objtype: %d",
(int) objtype);
@ -840,6 +883,239 @@ ExecGrant_Database(InternalGrant *istmt)
heap_close(relation, RowExclusiveLock);
}
static void
ExecGrant_Fdw(InternalGrant *istmt)
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_FDW;
relation = heap_open(ForeignDataWrapperRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid fdwid = lfirst_oid(cell);
Form_pg_foreign_data_wrapper pg_fdw_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple tuple;
HeapTuple newtuple;
Datum values[Natts_pg_foreign_data_wrapper];
bool nulls[Natts_pg_foreign_data_wrapper];
bool replaces[Natts_pg_foreign_data_wrapper];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
tuple = SearchSysCache(FOREIGNDATAWRAPPEROID,
ObjectIdGetDatum(fdwid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
pg_fdw_tuple = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_fdw_tuple->fdwowner;
aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
Anum_pg_foreign_data_wrapper_fdwacl,
&isNull);
if (isNull)
old_acl = acldefault(ACL_OBJECT_FDW, ownerId);
else
old_acl = DatumGetAclPCopy(aclDatum);
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
fdwid, grantorId, ACL_KIND_FDW,
NameStr(pg_fdw_tuple->fdwname));
/*
* Generate new ACL.
*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
noldmembers = aclmembers(old_acl, &oldmembers);
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_foreign_data_wrapper_fdwacl - 1] = true;
values[Anum_pg_foreign_data_wrapper_fdwacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(ForeignDataWrapperRelationId, HeapTupleGetOid(tuple),
ownerId, istmt->is_grant,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
static void ExecGrant_ForeignServer(InternalGrant *istmt)
{
Relation relation;
ListCell *cell;
if (istmt->all_privs && istmt->privileges == ACL_NO_RIGHTS)
istmt->privileges = ACL_ALL_RIGHTS_FOREIGN_SERVER;
relation = heap_open(ForeignServerRelationId, RowExclusiveLock);
foreach(cell, istmt->objects)
{
Oid srvid = lfirst_oid(cell);
Form_pg_foreign_server pg_server_tuple;
Datum aclDatum;
bool isNull;
AclMode avail_goptions;
AclMode this_privileges;
Acl *old_acl;
Acl *new_acl;
Oid grantorId;
Oid ownerId;
HeapTuple tuple;
HeapTuple newtuple;
Datum values[Natts_pg_foreign_server];
bool nulls[Natts_pg_foreign_server];
bool replaces[Natts_pg_foreign_server];
int noldmembers;
int nnewmembers;
Oid *oldmembers;
Oid *newmembers;
tuple = SearchSysCache(FOREIGNSERVEROID,
ObjectIdGetDatum(srvid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
elog(ERROR, "cache lookup failed for foreign server %u", srvid);
pg_server_tuple = (Form_pg_foreign_server) GETSTRUCT(tuple);
/*
* Get owner ID and working copy of existing ACL. If there's no ACL,
* substitute the proper default.
*/
ownerId = pg_server_tuple->srvowner;
aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
Anum_pg_foreign_server_srvacl,
&isNull);
if (isNull)
old_acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
else
old_acl = DatumGetAclPCopy(aclDatum);
/* Determine ID to do the grant as, and available grant options */
select_best_grantor(GetUserId(), istmt->privileges,
old_acl, ownerId,
&grantorId, &avail_goptions);
/*
* Restrict the privileges to what we can actually grant, and emit the
* standards-mandated warning and error messages.
*/
this_privileges =
restrict_and_check_grant(istmt->is_grant, avail_goptions,
istmt->all_privs, istmt->privileges,
srvid, grantorId, ACL_KIND_FOREIGN_SERVER,
NameStr(pg_server_tuple->srvname));
/*
* Generate new ACL.
*
* We need the members of both old and new ACLs so we can correct the
* shared dependency information.
*/
noldmembers = aclmembers(old_acl, &oldmembers);
new_acl = merge_acl_with_grant(old_acl, istmt->is_grant,
istmt->grant_option, istmt->behavior,
istmt->grantees, this_privileges,
grantorId, ownerId);
nnewmembers = aclmembers(new_acl, &newmembers);
/* finished building new ACL value, now insert it */
MemSet(values, 0, sizeof(values));
MemSet(nulls, false, sizeof(nulls));
MemSet(replaces, false, sizeof(replaces));
replaces[Anum_pg_foreign_server_srvacl - 1] = true;
values[Anum_pg_foreign_server_srvacl - 1] = PointerGetDatum(new_acl);
newtuple = heap_modify_tuple(tuple, RelationGetDescr(relation), values,
nulls, replaces);
simple_heap_update(relation, &newtuple->t_self, newtuple);
/* keep the catalog indexes up to date */
CatalogUpdateIndexes(relation, newtuple);
/* Update the shared dependency ACL info */
updateAclDependencies(ForeignServerRelationId, HeapTupleGetOid(tuple),
ownerId, istmt->is_grant,
noldmembers, oldmembers,
nnewmembers, newmembers);
ReleaseSysCache(tuple);
pfree(new_acl);
/* prevent error when processing duplicate objects */
CommandCounterIncrement();
}
heap_close(relation, RowExclusiveLock);
}
static void
ExecGrant_Function(InternalGrant *istmt)
{
@ -1428,7 +1704,11 @@ static const char *const no_priv_msg[MAX_ACL_KIND] =
/* ACL_KIND_TSDICTIONARY */
gettext_noop("permission denied for text search dictionary %s"),
/* ACL_KIND_TSCONFIGURATION */
gettext_noop("permission denied for text search configuration %s")
gettext_noop("permission denied for text search configuration %s"),
/* ACL_KIND_FDW */
gettext_noop("permission denied for foreign-data wrapper %s"),
/* ACL_KIND_FOREIGN_SERVER */
gettext_noop("permission denied for foreign server %s")
};
static const char *const not_owner_msg[MAX_ACL_KIND] =
@ -1460,7 +1740,11 @@ static const char *const not_owner_msg[MAX_ACL_KIND] =
/* ACL_KIND_TSDICTIONARY */
gettext_noop("must be owner of text search dictionary %s"),
/* ACL_KIND_TSCONFIGURATION */
gettext_noop("must be owner of text search configuration %s")
gettext_noop("must be owner of text search configuration %s"),
/* ACL_KIND_FDW */
gettext_noop("must be owner of foreign-data wrapper %s"),
/* ACL_KIND_FOREIGN_SERVER */
gettext_noop("must be owner of foreign server %s")
};
@ -1534,6 +1818,10 @@ pg_aclmask(AclObjectKind objkind, Oid table_oid, Oid roleid,
return pg_namespace_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_TABLESPACE:
return pg_tablespace_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_FDW:
return pg_foreign_data_wrapper_aclmask(table_oid, roleid, mask, how);
case ACL_KIND_FOREIGN_SERVER:
return pg_foreign_server_aclmask(table_oid, roleid, mask, how);
default:
elog(ERROR, "unrecognized objkind: %d",
(int) objkind);
@ -1962,6 +2250,131 @@ pg_tablespace_aclmask(Oid spc_oid, Oid roleid,
return result;
}
/*
* Exported routine for examining a user's privileges for a foreign
* data wrapper
*/
AclMode
pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
AclMode mask, AclMaskHow how)
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
Form_pg_foreign_data_wrapper fdwForm;
/* Bypass permission checks for superusers */
if (superuser_arg(roleid))
return mask;
/*
* Must get the FDW's tuple from pg_foreign_data_wrapper
*/
tuple = SearchSysCache(FOREIGNDATAWRAPPEROID,
ObjectIdGetDatum(fdw_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errmsg("foreign-data wrapper with OID %u does not exist",
fdw_oid)));
fdwForm = (Form_pg_foreign_data_wrapper) GETSTRUCT(tuple);
/*
* Normal case: get the FDW's ACL from pg_foreign_data_wrapper
*/
ownerId = fdwForm->fdwowner;
aclDatum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID, tuple,
Anum_pg_foreign_data_wrapper_fdwacl, &isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_FDW, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast rel's ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
/*
* Exported routine for examining a user's privileges for a foreign
* server.
*/
AclMode
pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
AclMode mask, AclMaskHow how)
{
AclMode result;
HeapTuple tuple;
Datum aclDatum;
bool isNull;
Acl *acl;
Oid ownerId;
Form_pg_foreign_server srvForm;
/* Bypass permission checks for superusers */
if (superuser_arg(roleid))
return mask;
/*
* Must get the FDW's tuple from pg_foreign_data_wrapper
*/
tuple = SearchSysCache(FOREIGNSERVEROID,
ObjectIdGetDatum(srv_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errmsg("foreign server with OID %u does not exist",
srv_oid)));
srvForm = (Form_pg_foreign_server) GETSTRUCT(tuple);
/*
* Normal case: get the foreign server's ACL from pg_foreign_server
*/
ownerId = srvForm->srvowner;
aclDatum = SysCacheGetAttr(FOREIGNSERVEROID, tuple,
Anum_pg_foreign_server_srvacl, &isNull);
if (isNull)
{
/* No ACL, so build default ACL */
acl = acldefault(ACL_OBJECT_FOREIGN_SERVER, ownerId);
aclDatum = (Datum) 0;
}
else
{
/* detoast rel's ACL if necessary */
acl = DatumGetAclP(aclDatum);
}
result = aclmask(acl, roleid, ownerId, mask, how);
/* if we have a detoasted copy, free it */
if (acl && (Pointer) acl != DatumGetPointer(aclDatum))
pfree(acl);
ReleaseSysCache(tuple);
return result;
}
/*
* Exported routine for checking a user's access privileges to a table
@ -2039,6 +2452,31 @@ pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
return ACLCHECK_NO_PRIV;
}
/*
* Exported routine for checking a user's access privileges to a foreign
* data wrapper
*/
AclResult
pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode)
{
if (pg_foreign_data_wrapper_aclmask(fdw_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
/*
* Exported routine for checking a user's access privileges to a foreign
* server
*/
AclResult
pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode)
{
if (pg_foreign_server_aclmask(srv_oid, roleid, mode, ACLMASK_ANY) != 0)
return ACLCHECK_OK;
else
return ACLCHECK_NO_PRIV;
}
/*
* Ownership check for a relation (specified by OID).
@ -2364,6 +2802,34 @@ pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid)
return has_privs_of_role(roleid, ownerId);
}
/*
* Ownership check for a foreign server (specified by OID).
*/
bool
pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid)
{
HeapTuple tuple;
Oid ownerId;
/* Superusers bypass all permission checking. */
if (superuser_arg(roleid))
return true;
tuple = SearchSysCache(FOREIGNSERVEROID,
ObjectIdGetDatum(srv_oid),
0, 0, 0);
if (!HeapTupleIsValid(tuple))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("foreign server with OID %u does not exist",
srv_oid)));
ownerId = ((Form_pg_foreign_server) GETSTRUCT(tuple))->srvowner;
ReleaseSysCache(tuple);
return has_privs_of_role(roleid, ownerId);
}
/*
* Ownership check for a database (specified by OID).

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.82 2008/11/10 21:49:16 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/catalog/dependency.c,v 1.83 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -33,6 +33,8 @@
#include "catalog/pg_conversion_fn.h"
#include "catalog/pg_database.h"
#include "catalog/pg_depend.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
@ -47,6 +49,7 @@
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
#include "commands/comment.h"
#include "commands/dbcommands.h"
#include "commands/defrem.h"
@ -55,6 +58,7 @@
#include "commands/tablespace.h"
#include "commands/trigger.h"
#include "commands/typecmds.h"
#include "foreign/foreign.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "parser/parsetree.h"
@ -1105,6 +1109,18 @@ doDeletion(const ObjectAddress *object)
RemoveTSConfigurationById(object->objectId);
break;
case OCLASS_USER_MAPPING:
RemoveUserMappingById(object->objectId);
break;
case OCLASS_FOREIGN_SERVER:
RemoveForeignServerById(object->objectId);
break;
case OCLASS_FDW:
RemoveForeignDataWrapperById(object->objectId);
break;
/* OCLASS_ROLE, OCLASS_DATABASE, OCLASS_TBLSPACE not handled */
default:
@ -2005,6 +2021,18 @@ getObjectClass(const ObjectAddress *object)
case TableSpaceRelationId:
Assert(object->objectSubId == 0);
return OCLASS_TBLSPACE;
case ForeignDataWrapperRelationId:
Assert(object->objectSubId == 0);
return OCLASS_FDW;
case ForeignServerRelationId:
Assert(object->objectSubId == 0);
return OCLASS_FOREIGN_SERVER;
case UserMappingRelationId:
Assert(object->objectSubId == 0);
return OCLASS_USER_MAPPING;
}
/* shouldn't get here */
@ -2501,6 +2529,50 @@ getObjectDescription(const ObjectAddress *object)
break;
}
case OCLASS_FDW:
{
ForeignDataWrapper *fdw;
fdw = GetForeignDataWrapper(object->objectId);
appendStringInfo(&buffer, _("foreign-data wrapper %s"), fdw->fdwname);
break;
}
case OCLASS_FOREIGN_SERVER:
{
ForeignServer *srv;
srv = GetForeignServer(object->objectId);
appendStringInfo(&buffer, _("server %s"), srv->servername);
break;
}
case OCLASS_USER_MAPPING:
{
HeapTuple tup;
Oid useid;
char *usename;
tup = SearchSysCache(USERMAPPINGOID,
ObjectIdGetDatum(object->objectId),
0, 0, 0);
if (!HeapTupleIsValid(tup))
elog(ERROR, "cache lookup failed for user mapping %u",
object->objectId);
useid = ((Form_pg_user_mapping) GETSTRUCT(tup))->umuser;
ReleaseSysCache(tup);
if (OidIsValid(useid))
usename = GetUserNameFromId(useid);
else
usename = "public";
appendStringInfo(&buffer, _("user mapping for %s"), usename);
break;
}
default:
appendStringInfo(&buffer, "unrecognized object %u %u %d",
object->classId,

View File

@ -4,7 +4,7 @@
*
* Copyright (c) 2003-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.46 2008/09/08 00:47:40 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/information_schema.sql,v 1.47 2008/12/19 16:25:17 petere Exp $
*/
/*
@ -1244,19 +1244,53 @@ GRANT SELECT ON role_table_grants TO PUBLIC;
* ROLE_USAGE_GRANTS view
*/
-- See USAGE_PRIVILEGES.
CREATE VIEW role_usage_grants AS
SELECT CAST(null AS sql_identifier) AS grantor,
CAST(null AS sql_identifier) AS grantee,
CAST(current_database() AS sql_identifier) AS object_catalog,
CAST(null AS sql_identifier) AS object_schema,
CAST(null AS sql_identifier) AS object_name,
CAST(null AS character_data) AS object_type,
CAST('USAGE' AS character_data) AS privilege_type,
CAST(null AS character_data) AS is_grantable
WHERE false;
/* foreign-data wrappers */
SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
CAST(g_grantee.rolname AS sql_identifier) AS grantee,
CAST(current_database() AS sql_identifier) AS object_catalog,
CAST('' AS sql_identifier) AS object_schema,
CAST(fdw.fdwname AS sql_identifier) AS object_name,
CAST('FOREIGN DATA WRAPPER' AS character_data) AS object_type,
CAST('USAGE' AS character_data) AS privilege_type,
CAST(
CASE WHEN aclcontains(fdw.fdwacl,
makeaclitem(g_grantee.oid, u_grantor.oid, 'USAGE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_foreign_data_wrapper fdw,
pg_authid u_grantor,
pg_authid g_grantee
WHERE aclcontains(fdw.fdwacl,
makeaclitem(g_grantee.oid, u_grantor.oid, 'USAGE', false))
AND (u_grantor.rolname IN (SELECT role_name FROM enabled_roles)
OR g_grantee.rolname IN (SELECT role_name FROM enabled_roles))
UNION ALL
/* foreign server */
SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
CAST(g_grantee.rolname AS sql_identifier) AS grantee,
CAST(current_database() AS sql_identifier) AS object_catalog,
CAST('' AS sql_identifier) AS object_schema,
CAST(srv.srvname AS sql_identifier) AS object_name,
CAST('FOREIGN SERVER' AS character_data) AS object_type,
CAST('USAGE' AS character_data) AS privilege_type,
CAST(
CASE WHEN aclcontains(srv.srvacl,
makeaclitem(g_grantee.oid, u_grantor.oid, 'USAGE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_foreign_server srv,
pg_authid u_grantor,
pg_authid g_grantee
WHERE aclcontains(srv.srvacl,
makeaclitem(g_grantee.oid, u_grantor.oid, 'USAGE', false))
AND (u_grantor.rolname IN (SELECT role_name FROM enabled_roles)
OR g_grantee.rolname IN (SELECT role_name FROM enabled_roles));
GRANT SELECT ON role_usage_grants TO PUBLIC;
@ -2007,11 +2041,10 @@ GRANT SELECT ON triggers TO PUBLIC;
* USAGE_PRIVILEGES view
*/
-- Of the things currently implemented in PostgreSQL, usage privileges
-- apply only to domains. Since domains have no real privileges, we
-- represent all domains with implicit usage privilege here.
CREATE VIEW usage_privileges AS
/* domains */
-- Domains have no real privileges, so we represent all domains with implicit usage privilege here.
SELECT CAST(u.rolname AS sql_identifier) AS grantor,
CAST('PUBLIC' AS sql_identifier) AS grantee,
CAST(current_database() AS sql_identifier) AS object_catalog,
@ -2027,7 +2060,65 @@ CREATE VIEW usage_privileges AS
WHERE u.oid = t.typowner
AND t.typnamespace = n.oid
AND t.typtype = 'd';
AND t.typtype = 'd'
UNION ALL
/* foreign-data wrappers */
SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
CAST(grantee.rolname AS sql_identifier) AS grantee,
CAST(current_database() AS sql_identifier) AS object_catalog,
CAST('' AS sql_identifier) AS object_schema,
CAST(fdw.fdwname AS sql_identifier) AS object_name,
CAST('FOREIGN DATA WRAPPER' AS character_data) AS object_type,
CAST('USAGE' AS character_data) AS privilege_type,
CAST(
CASE WHEN aclcontains(fdw.fdwacl,
makeaclitem(grantee.oid, u_grantor.oid, 'USAGE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_foreign_data_wrapper fdw,
pg_authid u_grantor,
(
SELECT oid, rolname FROM pg_authid
UNION ALL
SELECT 0::oid, 'PUBLIC'
) AS grantee (oid, rolname)
WHERE aclcontains(fdw.fdwacl,
makeaclitem(grantee.oid, u_grantor.oid, 'USAGE', false))
AND (pg_has_role(u_grantor.oid, 'USAGE')
OR pg_has_role(grantee.oid, 'USAGE')
OR grantee.rolname = 'PUBLIC')
UNION ALL
/* foreign servers */
SELECT CAST(u_grantor.rolname AS sql_identifier) AS grantor,
CAST(grantee.rolname AS sql_identifier) AS grantee,
CAST(current_database() AS sql_identifier) AS object_catalog,
CAST('' AS sql_identifier) AS object_schema,
CAST(srv.srvname AS sql_identifier) AS object_name,
CAST('FOREIGN SERVER' AS character_data) AS object_type,
CAST('USAGE' AS character_data) AS privilege_type,
CAST(
CASE WHEN aclcontains(srv.srvacl,
makeaclitem(grantee.oid, u_grantor.oid, 'USAGE', true))
THEN 'YES' ELSE 'NO' END AS character_data) AS is_grantable
FROM pg_foreign_server srv,
pg_authid u_grantor,
(
SELECT oid, rolname FROM pg_authid
UNION ALL
SELECT 0::oid, 'PUBLIC'
) AS grantee (oid, rolname)
WHERE aclcontains(srv.srvacl,
makeaclitem(grantee.oid, u_grantor.oid, 'USAGE', false))
AND (pg_has_role(u_grantor.oid, 'USAGE')
OR pg_has_role(grantee.oid, 'USAGE')
OR grantee.rolname = 'PUBLIC');
GRANT SELECT ON usage_privileges TO PUBLIC;
@ -2313,3 +2404,139 @@ CREATE VIEW element_types AS
FROM data_type_privileges );
GRANT SELECT ON element_types TO PUBLIC;
-- SQL/MED views; these use section numbers from part 9 of the standard.
/* Base view for foreign-data wrappers */
CREATE VIEW _pg_foreign_data_wrappers AS
SELECT w.oid,
w.fdwowner,
w.fdwoptions,
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
AND (pg_has_role(fdwowner, 'USAGE')
OR has_foreign_data_wrapper_privilege(w.oid, 'USAGE'));
/*
* 24.4
* FOREIGN_DATA_WRAPPER_OPTIONS view
*/
CREATE VIEW foreign_data_wrapper_options AS
SELECT foreign_data_wrapper_catalog,
foreign_data_wrapper_name,
CAST((pg_options_to_table(w.fdwoptions)).option_name AS sql_identifier) AS option_name,
CAST((pg_options_to_table(w.fdwoptions)).option_value AS character_data) AS option_value
FROM _pg_foreign_data_wrappers w;
GRANT SELECT ON foreign_data_wrapper_options TO PUBLIC;
/*
* 24.5
* FOREIGN_DATA_WRAPPERS view
*/
CREATE VIEW foreign_data_wrappers AS
SELECT foreign_data_wrapper_catalog,
foreign_data_wrapper_name,
authorization_identifier,
library_name,
foreign_data_wrapper_language
FROM _pg_foreign_data_wrappers w;
GRANT SELECT ON foreign_data_wrappers TO PUBLIC;
/* Base view for foreign servers */
CREATE VIEW _pg_foreign_servers AS
SELECT s.oid,
s.srvoptions,
CAST(current_database() AS sql_identifier) AS foreign_server_catalog,
CAST(srvname AS sql_identifier) AS foreign_server_name,
w.foreign_data_wrapper_catalog,
w.foreign_data_wrapper_name,
CAST(srvtype AS character_data) AS foreign_server_type,
CAST(srvversion AS character_data) AS foreign_server_version,
CAST(u.rolname AS sql_identifier) AS authorization_identifier
FROM pg_foreign_server s, _pg_foreign_data_wrappers w, pg_authid u
WHERE w.oid = s.srvfdw
AND u.oid = s.srvowner
AND (pg_has_role(s.srvowner, 'USAGE')
OR has_server_privilege(s.oid, 'USAGE'));
/*
* 24.6
* FOREIGN_SERVER_OPTIONS view
*/
CREATE VIEW foreign_server_options AS
SELECT foreign_server_catalog,
foreign_server_name,
CAST((pg_options_to_table(s.srvoptions)).option_name AS sql_identifier) AS option_name,
CAST((pg_options_to_table(s.srvoptions)).option_value AS character_data) AS option_value
FROM _pg_foreign_servers s;
GRANT SELECT ON TABLE foreign_server_options TO PUBLIC;
/*
* 24.7
* FOREIGN_SERVERS view
*/
CREATE VIEW foreign_servers AS
SELECT foreign_server_catalog,
foreign_server_name,
foreign_data_wrapper_catalog,
foreign_data_wrapper_name,
foreign_server_type,
foreign_server_version,
authorization_identifier
FROM _pg_foreign_servers;
GRANT SELECT ON foreign_servers TO PUBLIC;
/* Base view for user mappings */
CREATE VIEW _pg_user_mappings AS
SELECT um.oid,
um.umoptions,
CAST(COALESCE(u.rolname,'PUBLIC') AS sql_identifier ) AS authorization_identifier,
s.foreign_server_catalog,
s.foreign_server_name
FROM pg_user_mapping um LEFT JOIN pg_authid u ON (u.oid = um.umuser),
_pg_foreign_servers s
WHERE s.oid = um.umserver;
/*
* 24.12
* USER_MAPPING_OPTIONS view
*/
CREATE VIEW user_mapping_options AS
SELECT authorization_identifier,
foreign_server_catalog,
foreign_server_name,
CAST((pg_options_to_table(um.umoptions)).option_name AS sql_identifier) AS option_name,
CAST((pg_options_to_table(um.umoptions)).option_value AS character_data) AS option_value
FROM _pg_user_mappings um;
GRANT SELECT ON user_mapping_options TO PUBLIC;
/*
* 24.13
* USER_MAPPINGS view
*/
CREATE VIEW user_mappings AS
SELECT authorization_identifier,
foreign_server_catalog,
foreign_server_name
FROM _pg_user_mappings;
GRANT SELECT ON user_mappings TO PUBLIC;

View File

@ -487,6 +487,31 @@ T652 SQL-dynamic statements in SQL routines NO
T653 SQL-schema statements in external routines NO
T654 SQL-dynamic statements in external routines NO
T655 Cyclically dependent routines NO
M001 Datalinks NO
M002 Datalinks via SQL/CLI NO
M003 Datalinks via Embedded SQL NO
M004 Foreign data support NO
M005 Foreign schema support NO
M006 GetSQLString routine NO
M007 TransmitRequest NO
M009 GetOpts and GetStatistics routines NO
M010 Foreign data wrapper support NO
M011 Datalinks via Ada NO
M012 Datalinks via C NO
M013 Datalinks via COBOL NO
M014 Datalinks via Fortran NO
M015 Datalinks via M NO
M016 Datalinks via Pascal NO
M017 Datalinks via PL/I NO
M018 Foreign data wrapper interface routines in Ada NO
M019 Foreign data wrapper interface routines in C NO
M020 Foreign data wrapper interface routines in COBOL NO
M021 Foreign data wrapper interface routines in Fortran NO
M022 Foreign data wrapper interface routines in MUMPS NO
M023 Foreign data wrapper interface routines in Pascal NO
M024 Foreign data wrapper interface routines in PL/I NO
M030 SQL-server foreign data support NO
M031 Foreign data wrapper general routines NO
X010 XML type YES
X011 Arrays of XML type YES
X012 Multisets of XML type NO

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 1996-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.56 2008/11/09 21:24:32 tgl Exp $
* $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.57 2008/12/19 16:25:17 petere Exp $
*/
CREATE VIEW pg_roles AS
@ -381,6 +381,28 @@ CREATE VIEW pg_stat_bgwriter AS
pg_stat_get_buf_written_backend() AS buffers_backend,
pg_stat_get_buf_alloc() AS buffers_alloc;
CREATE VIEW pg_user_mappings AS
SELECT
U.oid AS umid,
S.oid AS srvid,
S.srvname AS srvname,
U.umuser AS umuser,
CASE WHEN U.umuser = 0 THEN
'public'
ELSE
A.rolname
END AS usename,
CASE WHEN pg_has_role(S.srvowner, 'USAGE') OR has_server_privilege(S.oid, 'USAGE') THEN
U.umoptions
ELSE
NULL
END AS umoptions
FROM pg_user_mapping U
LEFT JOIN pg_authid A ON (A.oid = U.umuser) JOIN
pg_foreign_server S ON (U.umserver = S.oid);
REVOKE ALL on pg_user_mapping FROM public;
-- Tsearch debug function. Defined here because it'd be pretty unwieldy
-- to put it into pg_proc.h

View File

@ -4,7 +4,7 @@
# Makefile for backend/commands
#
# IDENTIFICATION
# $PostgreSQL: pgsql/src/backend/commands/Makefile,v 1.38 2008/02/19 10:30:07 petere Exp $
# $PostgreSQL: pgsql/src/backend/commands/Makefile,v 1.39 2008/12/19 16:25:17 petere Exp $
#
#-------------------------------------------------------------------------
@ -14,7 +14,7 @@ include $(top_builddir)/src/Makefile.global
OBJS = aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o \
conversioncmds.o copy.o \
dbcommands.o define.o discard.o explain.o functioncmds.o \
dbcommands.o define.o discard.o explain.o foreigncmds.o functioncmds.o \
indexcmds.o lockcmds.o operatorcmds.o opclasscmds.o \
portalcmds.o prepare.o proclang.o \
schemacmds.o sequence.o tablecmds.o tablespace.o trigger.o \

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.29 2008/06/15 01:25:53 tgl Exp $
* $PostgreSQL: pgsql/src/backend/commands/alter.c,v 1.30 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -270,6 +270,15 @@ ExecAlterOwnerStmt(AlterOwnerStmt *stmt)
AlterTSConfigurationOwner(stmt->object, newowner);
break;
case OBJECT_FDW:
AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)),
newowner);
break;
case OBJECT_FOREIGN_SERVER:
AlterForeignServerOwner(strVal(linitial(stmt->object)), newowner);
break;
default:
elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
(int) stmt->objectType);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,25 @@
#-------------------------------------------------------------------------
#
# Makefile--
# Makefile for foreign
#
# IDENTIFICATION
# $PostgreSQL: pgsql/src/backend/foreign/Makefile,v 1.1 2008/12/19 16:25:17 petere Exp $
#
#-------------------------------------------------------------------------
subdir = src/backend/foreign
top_builddir = ../../..
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

View File

@ -0,0 +1,27 @@
#-------------------------------------------------------------------------
#
# 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)

View File

@ -0,0 +1,24 @@
/*-------------------------------------------------------------------------
*
* dummy_fdw.c
* "dummy" foreign-data wrapper
*
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/foreign/dummy/dummy_fdw.c,v 1.1 2008/12/19 16:25:17 petere 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.
*/

View File

@ -0,0 +1,389 @@
/*-------------------------------------------------------------------------
*
* foreign.c
* support for foreign-data wrappers, servers and user mappings.
*
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/foreign/foreign.c,v 1.1 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "access/reloptions.h"
#include "catalog/namespace.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
#include "foreign/foreign.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/parsenodes.h"
#include "utils/acl.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/syscache.h"
extern Datum pg_options_to_table(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)
{
Form_pg_foreign_data_wrapper fdwform;
ForeignDataWrapper *fdw;
Datum datum;
HeapTuple tp;
bool isnull;
tp = SearchSysCache(FOREIGNDATAWRAPPEROID,
ObjectIdGetDatum(fdwid),
0, 0, 0);
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for foreign-data wrapper %u", fdwid);
fdwform = (Form_pg_foreign_data_wrapper) GETSTRUCT(tp);
fdw = palloc(sizeof(ForeignDataWrapper));
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);
/* Extract the options */
datum = SysCacheGetAttr(FOREIGNDATAWRAPPEROID,
tp,
Anum_pg_foreign_data_wrapper_fdwoptions,
&isnull);
fdw->options = untransformRelOptions(datum);
ReleaseSysCache(tp);
return fdw;
}
/*
* GetForeignDataWrapperOidByName - look up the foreign-data wrapper
* OID by name.
*/
Oid
GetForeignDataWrapperOidByName(const char *fdwname, bool missing_ok)
{
Oid fdwId;
fdwId = GetSysCacheOid(FOREIGNDATAWRAPPERNAME,
CStringGetDatum(fdwname),
0, 0, 0);
if (!OidIsValid(fdwId) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("foreign-data wrapper \"%s\" does not exist", fdwname)));
return fdwId;
}
/*
* GetForeignDataWrapperByName - look up the foreign-data wrapper
* definition by name.
*/
ForeignDataWrapper *
GetForeignDataWrapperByName(const char *fdwname, bool missing_ok)
{
Oid fdwId = GetForeignDataWrapperOidByName(fdwname, missing_ok);
if (!OidIsValid(fdwId) && missing_ok)
return NULL;
return GetForeignDataWrapper(fdwId);
}
/*
* GetForeignServer - look up the foreign server definition.
*/
ForeignServer *
GetForeignServer(Oid serverid)
{
Form_pg_foreign_server serverform;
ForeignServer *server;
HeapTuple tp;
Datum datum;
bool isnull;
tp = SearchSysCache(FOREIGNSERVEROID,
ObjectIdGetDatum(serverid),
0, 0, 0);
if (!HeapTupleIsValid(tp))
elog(ERROR, "cache lookup failed for foreign server %u", serverid);
serverform = (Form_pg_foreign_server) GETSTRUCT(tp);
server = palloc(sizeof(ForeignServer));
server->serverid = serverid;
server->servername = pstrdup(NameStr(serverform->srvname));
server->owner = serverform->srvowner;
server->fdwid = serverform->srvfdw;
/* Extract server type */
datum = SysCacheGetAttr(FOREIGNSERVEROID,
tp,
Anum_pg_foreign_server_srvtype,
&isnull);
server->servertype = isnull ? NULL : pstrdup(TextDatumGetCString(datum));
/* Extract server version */
datum = SysCacheGetAttr(FOREIGNSERVEROID,
tp,
Anum_pg_foreign_server_srvversion,
&isnull);
server->serverversion = isnull ? NULL : pstrdup(TextDatumGetCString(datum));
/* Extract the srvoptions */
datum = SysCacheGetAttr(FOREIGNSERVEROID,
tp,
Anum_pg_foreign_server_srvoptions,
&isnull);
/* untransformRelOptions does exactly what we want - avoid duplication */
server->options = untransformRelOptions(datum);
ReleaseSysCache(tp);
return server;
}
/*
* GetForeignServerByName - look up the foreign server oid by name.
*/
Oid
GetForeignServerOidByName(const char *srvname, bool missing_ok)
{
Oid serverid;
serverid = GetSysCacheOid(FOREIGNSERVERNAME,
CStringGetDatum(srvname),
0, 0, 0);
if (!OidIsValid(serverid) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("server \"%s\" does not exist", srvname)));
return serverid;
}
/*
* GetForeignServerByName - look up the foreign server definition by name.
*/
ForeignServer *
GetForeignServerByName(const char *srvname, bool missing_ok)
{
Oid serverid = GetForeignServerOidByName(srvname, missing_ok);
if (!OidIsValid(serverid) && missing_ok)
return NULL;
return GetForeignServer(serverid);
}
/*
* GetUserMapping - look up the user mapping.
*
* If no mapping is found for the supplied user, we also look for
* PUBLIC mappings (userid == InvalidOid).
*/
UserMapping *
GetUserMapping(Oid userid, Oid serverid)
{
Form_pg_user_mapping umform;
Datum datum;
HeapTuple tp;
bool isnull;
UserMapping *um;
tp = SearchSysCache(USERMAPPINGUSERSERVER,
ObjectIdGetDatum(userid),
ObjectIdGetDatum(serverid),
0, 0);
if (!HeapTupleIsValid(tp))
{
/* Not found for the specific user -- try PUBLIC */
tp = SearchSysCache(USERMAPPINGUSERSERVER,
ObjectIdGetDatum(InvalidOid),
ObjectIdGetDatum(serverid),
0, 0);
}
if (!HeapTupleIsValid(tp))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("user mapping not found for \"%s\"",
MappingUserName(userid))));
umform = (Form_pg_user_mapping) GETSTRUCT(tp);
/* Extract the umoptions */
datum = SysCacheGetAttr(USERMAPPINGUSERSERVER,
tp,
Anum_pg_user_mapping_umoptions,
&isnull);
um = palloc(sizeof(UserMapping));
um->userid = userid;
um->serverid = serverid;
um->options = untransformRelOptions(datum);
ReleaseSysCache(tp);
return um;
}
/*
* deflist_to_tuplestore - Helper function to convert DefElem list to
* tuplestore usable in SRF.
*/
static void
deflist_to_tuplestore(ReturnSetInfo *rsinfo, List *options)
{
ListCell *cell;
TupleDesc tupdesc;
Tuplestorestate *tupstore;
Datum values[2];
bool nulls[2] = { 0 };
MemoryContext per_query_ctx;
MemoryContext oldcontext;
/* check to see if caller supports us returning a tuplestore */
if (rsinfo == NULL || !IsA(rsinfo, ReturnSetInfo))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("set-valued function called in context that cannot accept a set")));
if (!(rsinfo->allowedModes & SFRM_Materialize))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("materialize mode required, but it is not allowed in this context")));
per_query_ctx = rsinfo->econtext->ecxt_per_query_memory;
oldcontext = MemoryContextSwitchTo(per_query_ctx);
/*
* Now prepare the result set.
*/
tupdesc = CreateTupleDescCopy(rsinfo->expectedDesc);
tupstore = tuplestore_begin_heap(true, false, work_mem);
rsinfo->returnMode = SFRM_Materialize;
rsinfo->setResult = tupstore;
rsinfo->setDesc = tupdesc;
foreach (cell, options)
{
DefElem *def = lfirst(cell);
values[0] = CStringGetTextDatum(def->defname);
values[1] = CStringGetTextDatum(((Value *)def->arg)->val.str);
tuplestore_putvalues(tupstore, tupdesc, values, nulls);
}
/* clean up and return the tuplestore */
tuplestore_donestoring(tupstore);
MemoryContextSwitchTo(oldcontext);
}
/*
* Convert options array to name/value table. Useful for information
* schema and pg_dump.
*/
Datum
pg_options_to_table(PG_FUNCTION_ARGS)
{
Datum array = PG_GETARG_DATUM(0);
deflist_to_tuplestore((ReturnSetInfo *) fcinfo->resultinfo, untransformRelOptions(array));
return (Datum) 0;
}

View File

@ -0,0 +1,27 @@
#-------------------------------------------------------------------------
#
# 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)

View File

@ -0,0 +1,123 @@
/*-------------------------------------------------------------------------
*
* postgresql_fdw.c
* foreign-data wrapper for postgresql (libpq) connections.
*
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/foreign/postgresql/postgresql_fdw.c,v 1.1 2008/12/19 16:25:17 petere 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)));
}
}
}

View File

@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.415 2008/12/04 17:51:26 petere Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.416 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -2033,6 +2033,17 @@ _copyDefElem(DefElem *from)
return newnode;
}
static OptionDefElem *
_copyOptionDefElem(OptionDefElem *from)
{
OptionDefElem *newnode = makeNode(OptionDefElem);
COPY_SCALAR_FIELD(alter_op);
COPY_NODE_FIELD(def);
return newnode;
}
static LockingClause *
_copyLockingClause(LockingClause *from)
{
@ -2869,6 +2880,117 @@ _copyDropTableSpaceStmt(DropTableSpaceStmt *from)
return newnode;
}
static CreateFdwStmt *
_copyCreateFdwStmt(CreateFdwStmt *from)
{
CreateFdwStmt *newnode = makeNode(CreateFdwStmt);
COPY_STRING_FIELD(fdwname);
COPY_STRING_FIELD(library);
COPY_NODE_FIELD(options);
return newnode;
}
static AlterFdwStmt *
_copyAlterFdwStmt(AlterFdwStmt *from)
{
AlterFdwStmt *newnode = makeNode(AlterFdwStmt);
COPY_STRING_FIELD(fdwname);
COPY_STRING_FIELD(library);
COPY_NODE_FIELD(options);
return newnode;
}
static DropFdwStmt *
_copyDropFdwStmt(DropFdwStmt *from)
{
DropFdwStmt *newnode = makeNode(DropFdwStmt);
COPY_STRING_FIELD(fdwname);
COPY_SCALAR_FIELD(missing_ok);
COPY_SCALAR_FIELD(behavior);
return newnode;
}
static CreateForeignServerStmt *
_copyCreateForeignServerStmt(CreateForeignServerStmt *from)
{
CreateForeignServerStmt *newnode = makeNode(CreateForeignServerStmt);
COPY_STRING_FIELD(servername);
COPY_STRING_FIELD(servertype);
COPY_STRING_FIELD(version);
COPY_STRING_FIELD(fdwname);
COPY_NODE_FIELD(options);
return newnode;
}
static AlterForeignServerStmt *
_copyAlterForeignServerStmt(AlterForeignServerStmt *from)
{
AlterForeignServerStmt *newnode = makeNode(AlterForeignServerStmt);
COPY_STRING_FIELD(servername);
COPY_STRING_FIELD(version);
COPY_NODE_FIELD(options);
COPY_SCALAR_FIELD(has_version);
return newnode;
}
static DropForeignServerStmt *
_copyDropForeignServerStmt(DropForeignServerStmt *from)
{
DropForeignServerStmt *newnode = makeNode(DropForeignServerStmt);
COPY_STRING_FIELD(servername);
COPY_SCALAR_FIELD(missing_ok);
COPY_SCALAR_FIELD(behavior);
return newnode;
}
static CreateUserMappingStmt *
_copyCreateUserMappingStmt(CreateUserMappingStmt *from)
{
CreateUserMappingStmt *newnode = makeNode(CreateUserMappingStmt);
COPY_STRING_FIELD(username);
COPY_STRING_FIELD(servername);
COPY_NODE_FIELD(options);
return newnode;
}
static AlterUserMappingStmt *
_copyAlterUserMappingStmt(AlterUserMappingStmt *from)
{
AlterUserMappingStmt *newnode = makeNode(AlterUserMappingStmt);
COPY_STRING_FIELD(username);
COPY_STRING_FIELD(servername);
COPY_NODE_FIELD(options);
return newnode;
}
static DropUserMappingStmt *
_copyDropUserMappingStmt(DropUserMappingStmt *from)
{
DropUserMappingStmt *newnode = makeNode(DropUserMappingStmt);
COPY_STRING_FIELD(username);
COPY_STRING_FIELD(servername);
COPY_SCALAR_FIELD(missing_ok);
return newnode;
}
static CreateTrigStmt *
_copyCreateTrigStmt(CreateTrigStmt *from)
{
@ -3696,6 +3818,33 @@ copyObject(void *from)
case T_DropTableSpaceStmt:
retval = _copyDropTableSpaceStmt(from);
break;
case T_CreateFdwStmt:
retval = _copyCreateFdwStmt(from);
break;
case T_AlterFdwStmt:
retval = _copyAlterFdwStmt(from);
break;
case T_DropFdwStmt:
retval = _copyDropFdwStmt(from);
break;
case T_CreateForeignServerStmt:
retval = _copyCreateForeignServerStmt(from);
break;
case T_AlterForeignServerStmt:
retval = _copyAlterForeignServerStmt(from);
break;
case T_DropForeignServerStmt:
retval = _copyDropForeignServerStmt(from);
break;
case T_CreateUserMappingStmt:
retval = _copyCreateUserMappingStmt(from);
break;
case T_AlterUserMappingStmt:
retval = _copyAlterUserMappingStmt(from);
break;
case T_DropUserMappingStmt:
retval = _copyDropUserMappingStmt(from);
break;
case T_CreateTrigStmt:
retval = _copyCreateTrigStmt(from);
break;
@ -3823,6 +3972,9 @@ copyObject(void *from)
case T_DefElem:
retval = _copyDefElem(from);
break;
case T_OptionDefElem:
retval = _copyOptionDefElem(from);
break;
case T_LockingClause:
retval = _copyLockingClause(from);
break;

View File

@ -22,7 +22,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.340 2008/12/04 17:51:26 petere Exp $
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.341 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -1518,6 +1518,99 @@ _equalDropTableSpaceStmt(DropTableSpaceStmt *a, DropTableSpaceStmt *b)
return true;
}
static bool
_equalCreateFdwStmt(CreateFdwStmt *a, CreateFdwStmt *b)
{
COMPARE_STRING_FIELD(fdwname);
COMPARE_STRING_FIELD(library);
COMPARE_NODE_FIELD(options);
return true;
}
static bool
_equalAlterFdwStmt(AlterFdwStmt *a, AlterFdwStmt *b)
{
COMPARE_STRING_FIELD(fdwname);
COMPARE_STRING_FIELD(library);
COMPARE_NODE_FIELD(options);
return true;
}
static bool
_equalDropFdwStmt(DropFdwStmt *a, DropFdwStmt *b)
{
COMPARE_STRING_FIELD(fdwname);
COMPARE_SCALAR_FIELD(missing_ok);
COMPARE_SCALAR_FIELD(behavior);
return true;
}
static bool
_equalCreateForeignServerStmt(CreateForeignServerStmt *a, CreateForeignServerStmt *b)
{
COMPARE_STRING_FIELD(servername);
COMPARE_STRING_FIELD(servertype);
COMPARE_STRING_FIELD(version);
COMPARE_STRING_FIELD(fdwname);
COMPARE_NODE_FIELD(options);
return true;
}
static bool
_equalAlterForeignServerStmt(AlterForeignServerStmt *a, AlterForeignServerStmt *b)
{
COMPARE_STRING_FIELD(servername);
COMPARE_STRING_FIELD(version);
COMPARE_NODE_FIELD(options);
COMPARE_SCALAR_FIELD(has_version);
return true;
}
static bool
_equalDropForeignServerStmt(DropForeignServerStmt *a, DropForeignServerStmt *b)
{
COMPARE_STRING_FIELD(servername);
COMPARE_SCALAR_FIELD(missing_ok);
COMPARE_SCALAR_FIELD(behavior);
return true;
}
static bool
_equalCreateUserMappingStmt(CreateUserMappingStmt *a, CreateUserMappingStmt *b)
{
COMPARE_STRING_FIELD(username);
COMPARE_STRING_FIELD(servername);
COMPARE_NODE_FIELD(options);
return true;
}
static bool
_equalAlterUserMappingStmt(AlterUserMappingStmt *a, AlterUserMappingStmt *b)
{
COMPARE_STRING_FIELD(username);
COMPARE_STRING_FIELD(servername);
COMPARE_NODE_FIELD(options);
return true;
}
static bool
_equalDropUserMappingStmt(DropUserMappingStmt *a, DropUserMappingStmt *b)
{
COMPARE_STRING_FIELD(username);
COMPARE_STRING_FIELD(servername);
COMPARE_SCALAR_FIELD(missing_ok);
return true;
}
static bool
_equalCreateTrigStmt(CreateTrigStmt *a, CreateTrigStmt *b)
{
@ -1956,6 +2049,15 @@ _equalDefElem(DefElem *a, DefElem *b)
return true;
}
static bool
_equalOptionDefElem(OptionDefElem *a, OptionDefElem *b)
{
COMPARE_SCALAR_FIELD(alter_op);
COMPARE_NODE_FIELD(def);
return true;
}
static bool
_equalLockingClause(LockingClause *a, LockingClause *b)
{
@ -2534,6 +2636,33 @@ equal(void *a, void *b)
case T_DropTableSpaceStmt:
retval = _equalDropTableSpaceStmt(a, b);
break;
case T_CreateFdwStmt:
retval = _equalCreateFdwStmt(a, b);
break;
case T_AlterFdwStmt:
retval = _equalAlterFdwStmt(a, b);
break;
case T_DropFdwStmt:
retval = _equalDropFdwStmt(a, b);
break;
case T_CreateForeignServerStmt:
retval = _equalCreateForeignServerStmt(a, b);
break;
case T_AlterForeignServerStmt:
retval = _equalAlterForeignServerStmt(a, b);
break;
case T_DropForeignServerStmt:
retval = _equalDropForeignServerStmt(a, b);
break;
case T_CreateUserMappingStmt:
retval = _equalCreateUserMappingStmt(a, b);
break;
case T_AlterUserMappingStmt:
retval = _equalAlterUserMappingStmt(a, b);
break;
case T_DropUserMappingStmt:
retval = _equalDropUserMappingStmt(a, b);
break;
case T_CreateTrigStmt:
retval = _equalCreateTrigStmt(a, b);
break;
@ -2661,6 +2790,9 @@ equal(void *a, void *b)
case T_DefElem:
retval = _equalDefElem(a, b);
break;
case T_OptionDefElem:
retval = _equalOptionDefElem(a, b);
break;
case T_LockingClause:
retval = _equalLockingClause(a, b);
break;

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.60 2008/09/01 20:42:44 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.61 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -361,3 +361,16 @@ makeDefElem(char *name, Node *arg)
res->arg = arg;
return res;
}
/*
* makeOptionDefElem -
* build an OptionDefElem node
*/
OptionDefElem *
makeOptionDefElem(int op, DefElem *def)
{
OptionDefElem *res = makeNode(OptionDefElem);
res->alter_op = op;
res->def = def;
return res;
}

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.645 2008/12/18 18:20:34 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.646 2008/12/19 16:25:17 petere Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@ -156,6 +156,7 @@ static TypeName *TableFuncTypeName(List *columns);
FunctionParameterMode fun_param_mode;
FuncWithArgs *funwithargs;
DefElem *defelt;
OptionDefElem *optdef;
SortBy *sortby;
JoinExpr *jexpr;
IndexElem *ielem;
@ -172,19 +173,22 @@ static TypeName *TableFuncTypeName(List *columns);
}
%type <node> stmt schema_stmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterGroupStmt
AlterDatabaseStmt AlterDatabaseSetStmt AlterDomainStmt AlterFdwStmt
AlterForeignServerStmt AlterGroupStmt
AlterObjectSchemaStmt AlterOwnerStmt AlterSeqStmt AlterTableStmt
AlterUserStmt AlterUserSetStmt AlterRoleStmt AlterRoleSetStmt
AlterUserStmt AlterUserMappingStmt AlterUserSetStmt AlterRoleStmt AlterRoleSetStmt
AnalyzeStmt ClosePortalStmt ClusterStmt CommentStmt
ConstraintsSetStmt CopyStmt CreateAsStmt CreateCastStmt
CreateDomainStmt CreateGroupStmt CreateOpClassStmt
CreateOpFamilyStmt AlterOpFamilyStmt CreatePLangStmt
CreateSchemaStmt CreateSeqStmt CreateStmt CreateTableSpaceStmt
CreateAssertStmt CreateTrigStmt CreateUserStmt CreateRoleStmt
CreateFdwStmt CreateForeignServerStmt CreateAssertStmt CreateTrigStmt
CreateUserStmt CreateUserMappingStmt CreateRoleStmt
CreatedbStmt DeclareCursorStmt DefineStmt DeleteStmt DiscardStmt
DropGroupStmt DropOpClassStmt DropOpFamilyStmt DropPLangStmt DropStmt
DropAssertStmt DropTrigStmt DropRuleStmt DropCastStmt DropRoleStmt
DropUserStmt DropdbStmt DropTableSpaceStmt ExplainStmt FetchStmt
DropUserStmt DropdbStmt DropTableSpaceStmt DropFdwStmt
DropForeignServerStmt DropUserMappingStmt ExplainStmt FetchStmt
GrantStmt GrantRoleStmt IndexStmt InsertStmt ListenStmt LoadStmt
LockStmt NotifyStmt ExplainableStmt PreparableStmt
CreateFunctionStmt AlterFunctionStmt ReindexStmt RemoveAggrStmt
@ -222,6 +226,10 @@ static TypeName *TableFuncTypeName(List *columns);
%type <list> OptRoleList
%type <defelt> OptRoleElem
%type <str> opt_type
%type <str> foreign_server_version opt_foreign_server_version
%type <str> auth_ident
%type <str> OptSchemaName
%type <list> OptSchemaEltList
@ -274,6 +282,7 @@ static TypeName *TableFuncTypeName(List *columns);
prep_type_clause
execute_param_clause using_clause returning_clause
enum_val_list table_func_column_list
create_generic_options alter_generic_options
%type <range> OptTempTableName
%type <into> into_clause create_as_target
@ -342,6 +351,12 @@ static TypeName *TableFuncTypeName(List *columns);
%type <range> relation_expr_opt_alias
%type <target> target_el single_set_clause set_target insert_column_item
%type <str> generic_option_name
%type <node> generic_option_arg
%type <defelt> generic_option_elem
%type <optdef> alter_generic_option_elem
%type <list> generic_option_list alter_generic_option_list
%type <typnam> Typename SimpleTypename ConstTypename
GenericType Numeric opt_float
Character ConstCharacter
@ -436,7 +451,7 @@ static TypeName *TableFuncTypeName(List *columns);
KEY
LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEAST LEFT LEVEL
LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
LIBRARY LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
LOCK_P LOGIN_P
MAPPING MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
@ -445,7 +460,7 @@ static TypeName *TableFuncTypeName(List *columns);
NOCREATEROLE NOCREATEUSER NOINHERIT NOLOGIN_P NONE NOSUPERUSER
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF NULLS_P NUMERIC
OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR
OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OPTIONS OR
ORDER OUT_P OUTER_P OVERLAPS OVERLAY OWNED OWNER
PARSER PARTIAL PASSWORD PLACING PLANS POSITION
@ -459,7 +474,7 @@ static TypeName *TableFuncTypeName(List *columns);
REVOKE RIGHT ROLE ROLLBACK ROW ROWS RULE
SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE
SERIALIZABLE SESSION SESSION_USER SET SETOF SHARE
SERIALIZABLE SERVER SESSION SESSION_USER SET SETOF SHARE
SHOW SIMILAR SIMPLE SMALLINT SOME STABLE STANDALONE_P START STATEMENT
STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P SUBSTRING SUPERUSER_P
SYMMETRIC SYSID SYSTEM_P
@ -474,7 +489,7 @@ static TypeName *TableFuncTypeName(List *columns);
VACUUM VALID VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING
VERBOSE VERSION_P VIEW VOLATILE
WHEN WHERE WHITESPACE_P WITH WITHOUT WORK WRITE
WHEN WHERE WHITESPACE_P WITH WITHOUT WORK WRAPPER WRITE
XML_P XMLATTRIBUTES XMLCONCAT XMLELEMENT XMLFOREST XMLPARSE
XMLPI XMLROOT XMLSERIALIZE
@ -562,6 +577,8 @@ stmt :
AlterDatabaseStmt
| AlterDatabaseSetStmt
| AlterDomainStmt
| AlterFdwStmt
| AlterForeignServerStmt
| AlterFunctionStmt
| AlterGroupStmt
| AlterObjectSchemaStmt
@ -572,6 +589,7 @@ stmt :
| AlterRoleStmt
| AlterTSConfigurationStmt
| AlterTSDictionaryStmt
| AlterUserMappingStmt
| AlterUserSetStmt
| AlterUserStmt
| AnalyzeStmt
@ -586,6 +604,8 @@ stmt :
| CreateCastStmt
| CreateConversionStmt
| CreateDomainStmt
| CreateFdwStmt
| CreateForeignServerStmt
| CreateFunctionStmt
| CreateGroupStmt
| CreateOpClassStmt
@ -599,6 +619,7 @@ stmt :
| CreateTrigStmt
| CreateRoleStmt
| CreateUserStmt
| CreateUserMappingStmt
| CreatedbStmt
| DeallocateStmt
| DeclareCursorStmt
@ -607,6 +628,8 @@ stmt :
| DiscardStmt
| DropAssertStmt
| DropCastStmt
| DropFdwStmt
| DropForeignServerStmt
| DropGroupStmt
| DropOpClassStmt
| DropOpFamilyStmt
@ -618,6 +641,7 @@ stmt :
| DropTrigStmt
| DropRoleStmt
| DropUserStmt
| DropUserMappingStmt
| DropdbStmt
| ExecuteStmt
| ExplainStmt
@ -2715,6 +2739,313 @@ DropTableSpaceStmt: DROP TABLESPACE name
}
;
/*****************************************************************************
*
* QUERY:
* CREATE FOREIGN DATA WRAPPER name LIBRARY 'library_name' LANGUAGE C
*
*****************************************************************************/
CreateFdwStmt: CREATE FOREIGN DATA_P WRAPPER name LIBRARY Sconst LANGUAGE ColId create_generic_options
{
CreateFdwStmt *n = makeNode(CreateFdwStmt);
n->fdwname = $5;
n->library = $7;
n->options = $10;
$$ = (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)));
}
;
/*****************************************************************************
*
* QUERY :
* DROP FOREIGN DATA WRAPPER name
*
****************************************************************************/
DropFdwStmt: DROP FOREIGN DATA_P WRAPPER name opt_drop_behavior
{
DropFdwStmt *n = makeNode(DropFdwStmt);
n->fdwname = $5;
n->missing_ok = false;
n->behavior = $6;
$$ = (Node *) n;
}
| DROP FOREIGN DATA_P WRAPPER IF_P EXISTS name opt_drop_behavior
{
DropFdwStmt *n = makeNode(DropFdwStmt);
n->fdwname = $7;
n->missing_ok = true;
n->behavior = $8;
$$ = (Node *) n;
}
;
/*****************************************************************************
*
* QUERY :
* ALTER FOREIGN DATA WRAPPER name
*
****************************************************************************/
AlterFdwStmt: ALTER FOREIGN DATA_P WRAPPER name LIBRARY Sconst alter_generic_options
{
AlterFdwStmt *n = makeNode(AlterFdwStmt);
n->fdwname = $5;
n->library = $7;
n->options = $8;
$$ = (Node *) n;
}
| ALTER FOREIGN DATA_P WRAPPER name LIBRARY Sconst
{
AlterFdwStmt *n = makeNode(AlterFdwStmt);
n->fdwname = $5;
n->library = $7;
$$ = (Node *) n;
}
| ALTER FOREIGN DATA_P WRAPPER name alter_generic_options
{
AlterFdwStmt *n = makeNode(AlterFdwStmt);
n->fdwname = $5;
n->options = $6;
$$ = (Node *) n;
}
;
/* Options definition for CREATE FDW, SERVER and USER MAPPING */
create_generic_options:
OPTIONS '(' generic_option_list ')' { $$ = $3; }
| /*EMPTY*/ { $$ = NIL; }
;
generic_option_list: generic_option_elem
{
$$ = list_make1(makeOptionDefElem(ALTER_OPT_ADD, $1));
}
| generic_option_list ',' generic_option_elem
{
$$ = lappend($1, makeOptionDefElem(ALTER_OPT_ADD, $3));
}
;
/* Options definition for ALTER FDW, SERVER and USER MAPPING */
alter_generic_options:
OPTIONS '(' alter_generic_option_list ')' { $$ = $3; }
;
alter_generic_option_list:
alter_generic_option_elem
{
$$ = list_make1($1);
}
| generic_option_elem
{
$$ = list_make1(makeOptionDefElem(ALTER_OPT_ADD, $1));
}
| alter_generic_option_list ',' alter_generic_option_elem
{
$$ = lappend($1, $3);
}
| alter_generic_option_list ',' generic_option_elem
{
$$ = lappend($1, makeOptionDefElem(ALTER_OPT_ADD, $3));
}
;
alter_generic_option_elem:
ADD_P generic_option_elem
{
$$ = makeOptionDefElem(ALTER_OPT_ADD, $2);
}
| SET generic_option_elem
{
$$ = makeOptionDefElem(ALTER_OPT_SET, $2);
}
| DROP generic_option_name
{
$$ = makeOptionDefElem(ALTER_OPT_DROP,
makeDefElem($2, NULL));
}
;
generic_option_elem:
generic_option_name generic_option_arg { $$ = makeDefElem($1, $2); }
;
generic_option_name:
attr_name { $$ = $1; }
;
generic_option_arg:
Sconst { $$ = (Node *)makeString($1); }
;
/*****************************************************************************
*
* QUERY:
* CREATE SERVER name [TYPE] [VERSION] [OPTIONS]
*
*****************************************************************************/
CreateForeignServerStmt: CREATE SERVER name opt_type opt_foreign_server_version
FOREIGN DATA_P WRAPPER name create_generic_options
{
CreateForeignServerStmt *n = makeNode(CreateForeignServerStmt);
n->servername = $3;
n->servertype = $4;
n->version = $5;
n->fdwname = $9;
n->options = $10;
$$ = (Node *) n;
}
;
opt_type:
TYPE_P Sconst { $$ = $2; }
| /*EMPTY*/ { $$ = NULL; }
;
foreign_server_version:
VERSION_P Sconst { $$ = $2; }
| VERSION_P NULL_P { $$ = NULL; }
;
opt_foreign_server_version:
foreign_server_version { $$ = $1; }
| /*EMPTY*/ { $$ = NULL; }
;
/*****************************************************************************
*
* QUERY :
* DROP SERVER name
*
****************************************************************************/
DropForeignServerStmt: DROP SERVER name opt_drop_behavior
{
DropForeignServerStmt *n = makeNode(DropForeignServerStmt);
n->servername = $3;
n->missing_ok = false;
n->behavior = $4;
$$ = (Node *) n;
}
| DROP SERVER IF_P EXISTS name opt_drop_behavior
{
DropForeignServerStmt *n = makeNode(DropForeignServerStmt);
n->servername = $5;
n->missing_ok = true;
n->behavior = $6;
$$ = (Node *) n;
}
;
/*****************************************************************************
*
* QUERY :
* ALTER SERVER name [VERSION] [OPTIONS]
*
****************************************************************************/
AlterForeignServerStmt: ALTER SERVER name foreign_server_version alter_generic_options
{
AlterForeignServerStmt *n = makeNode(AlterForeignServerStmt);
n->servername = $3;
n->version = $4;
n->options = $5;
n->has_version = true;
$$ = (Node *) n;
}
| ALTER SERVER name foreign_server_version
{
AlterForeignServerStmt *n = makeNode(AlterForeignServerStmt);
n->servername = $3;
n->version = $4;
n->has_version = true;
$$ = (Node *) n;
}
| ALTER SERVER name alter_generic_options
{
AlterForeignServerStmt *n = makeNode(AlterForeignServerStmt);
n->servername = $3;
n->options = $4;
$$ = (Node *) n;
}
;
/*****************************************************************************
*
* QUERY:
* CREATE USER MAPPING FOR auth_ident SERVER name [OPTIONS]
*
*****************************************************************************/
CreateUserMappingStmt: CREATE USER MAPPING FOR auth_ident SERVER name create_generic_options
{
CreateUserMappingStmt *n = makeNode(CreateUserMappingStmt);
n->username = $5;
n->servername = $7;
n->options = $8;
$$ = (Node *) n;
}
;
/* User mapping authorization identifier */
auth_ident:
CURRENT_USER { $$ = "current_user"; }
| USER { $$ = "current_user"; }
| RoleId { $$ = (strcmp($1, "public") == 0) ? NULL : $1 }
;
/*****************************************************************************
*
* QUERY :
* DROP USER MAPPING FOR auth_ident SERVER name
*
****************************************************************************/
DropUserMappingStmt: DROP USER MAPPING FOR auth_ident SERVER name
{
DropUserMappingStmt *n = makeNode(DropUserMappingStmt);
n->username = $5;
n->servername = $7;
n->missing_ok = false;
$$ = (Node *) n;
}
| DROP USER MAPPING IF_P EXISTS FOR auth_ident SERVER name
{
DropUserMappingStmt *n = makeNode(DropUserMappingStmt);
n->username = $7;
n->servername = $9;
n->missing_ok = true;
$$ = (Node *) n;
}
;
/*****************************************************************************
*
* QUERY :
* ALTER USER MAPPING FOR auth_ident SERVER name OPTIONS
*
****************************************************************************/
AlterUserMappingStmt: ALTER USER MAPPING FOR auth_ident SERVER name alter_generic_options
{
AlterUserMappingStmt *n = makeNode(AlterUserMappingStmt);
n->username = $5;
n->servername = $7;
n->options = $8;
$$ = (Node *) n;
}
;
/*****************************************************************************
*
* QUERIES :
@ -3912,6 +4243,20 @@ privilege_target:
n->objs = $2;
$$ = n;
}
| FOREIGN DATA_P WRAPPER name_list
{
PrivTarget *n = makeNode(PrivTarget);
n->objtype = ACL_OBJECT_FDW;
n->objs = $4;
$$ = n;
}
| FOREIGN SERVER name_list
{
PrivTarget *n = makeNode(PrivTarget);
n->objtype = ACL_OBJECT_FOREIGN_SERVER;
n->objs = $3;
$$ = n;
}
| FUNCTION function_with_argtypes_list
{
PrivTarget *n = makeNode(PrivTarget);
@ -5123,6 +5468,22 @@ AlterOwnerStmt: ALTER AGGREGATE func_name aggr_args OWNER TO RoleId
n->newowner = $8;
$$ = (Node *)n;
}
| ALTER FOREIGN DATA_P WRAPPER name OWNER TO RoleId
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_FDW;
n->object = list_make1(makeString($5));
n->newowner = $8;
$$ = (Node *)n;
}
| ALTER SERVER name OWNER TO RoleId
{
AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
n->objectType = OBJECT_FOREIGN_SERVER;
n->object = list_make1(makeString($3));
n->newowner = $6;
$$ = (Node *)n;
}
;
@ -9556,6 +9917,7 @@ unreserved_keyword:
| INVOKER
| ISOLATION
| KEY
| LIBRARY
| LANCOMPILER
| LANGUAGE
| LARGE_P
@ -9594,6 +9956,7 @@ unreserved_keyword:
| OIDS
| OPERATOR
| OPTION
| OPTIONS
| OWNED
| OWNER
| PARSER
@ -9629,6 +9992,7 @@ unreserved_keyword:
| ROWS
| RULE
| SAVEPOINT
| SERVER
| SCHEMA
| SCROLL
| SEARCH
@ -9681,6 +10045,7 @@ unreserved_keyword:
| WHITESPACE_P
| WITHOUT
| WORK
| WRAPPER
| WRITE
| XML_P
| YEAR_P

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.205 2008/10/27 09:37:47 petere Exp $
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.206 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -229,6 +229,7 @@ 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},
@ -281,6 +282,7 @@ const ScanKeyword ScanKeywords[] = {
{"only", ONLY, RESERVED_KEYWORD},
{"operator", OPERATOR, UNRESERVED_KEYWORD},
{"option", OPTION, UNRESERVED_KEYWORD},
{"options", OPTIONS, UNRESERVED_KEYWORD},
{"or", OR, RESERVED_KEYWORD},
{"order", ORDER, RESERVED_KEYWORD},
{"out", OUT_P, COL_NAME_KEYWORD},
@ -339,6 +341,7 @@ const ScanKeyword ScanKeywords[] = {
{"select", SELECT, RESERVED_KEYWORD},
{"sequence", SEQUENCE, UNRESERVED_KEYWORD},
{"serializable", SERIALIZABLE, UNRESERVED_KEYWORD},
{"server", SERVER, UNRESERVED_KEYWORD},
{"session", SESSION, UNRESERVED_KEYWORD},
{"session_user", SESSION_USER, RESERVED_KEYWORD},
{"set", SET, UNRESERVED_KEYWORD},
@ -411,6 +414,7 @@ const ScanKeyword ScanKeywords[] = {
{"with", WITH, RESERVED_KEYWORD},
{"without", WITHOUT, UNRESERVED_KEYWORD},
{"work", WORK, UNRESERVED_KEYWORD},
{"wrapper", WRAPPER, UNRESERVED_KEYWORD},
{"write", WRITE, UNRESERVED_KEYWORD},
{"xml", XML_P, UNRESERVED_KEYWORD},
{"xmlattributes", XMLATTRIBUTES, COL_NAME_KEYWORD},

View File

@ -10,7 +10,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.302 2008/12/04 17:51:26 petere Exp $
* $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.303 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -203,6 +203,15 @@ check_xact_readonly(Node *parsetree)
case T_ReassignOwnedStmt:
case T_AlterTSDictionaryStmt:
case T_AlterTSConfigurationStmt:
case T_CreateFdwStmt:
case T_AlterFdwStmt:
case T_DropFdwStmt:
case T_CreateForeignServerStmt:
case T_AlterForeignServerStmt:
case T_DropForeignServerStmt:
case T_CreateUserMappingStmt:
case T_AlterUserMappingStmt:
case T_DropUserMappingStmt:
ereport(ERROR,
(errcode(ERRCODE_READ_ONLY_SQL_TRANSACTION),
errmsg("transaction is read-only")));
@ -452,6 +461,42 @@ ProcessUtility(Node *parsetree,
DropTableSpace((DropTableSpaceStmt *) parsetree);
break;
case T_CreateFdwStmt:
CreateForeignDataWrapper((CreateFdwStmt *) parsetree);
break;
case T_AlterFdwStmt:
AlterForeignDataWrapper((AlterFdwStmt *) parsetree);
break;
case T_DropFdwStmt:
RemoveForeignDataWrapper((DropFdwStmt *) parsetree);
break;
case T_CreateForeignServerStmt:
CreateForeignServer((CreateForeignServerStmt *) parsetree);
break;
case T_AlterForeignServerStmt:
AlterForeignServer((AlterForeignServerStmt *) parsetree);
break;
case T_DropForeignServerStmt:
RemoveForeignServer((DropForeignServerStmt *) parsetree);
break;
case T_CreateUserMappingStmt:
CreateUserMapping((CreateUserMappingStmt *) parsetree);
break;
case T_AlterUserMappingStmt:
AlterUserMapping((AlterUserMappingStmt *) parsetree);
break;
case T_DropUserMappingStmt:
RemoveUserMapping((DropUserMappingStmt *) parsetree);
break;
case T_DropStmt:
{
DropStmt *stmt = (DropStmt *) parsetree;
@ -1310,6 +1355,42 @@ CreateCommandTag(Node *parsetree)
tag = "DROP TABLESPACE";
break;
case T_CreateFdwStmt:
tag = "CREATE FOREIGN DATA WRAPPER";
break;
case T_AlterFdwStmt:
tag = "ALTER FOREIGN DATA WRAPPER";
break;
case T_DropFdwStmt:
tag = "DROP FOREIGN DATA WRAPPER";
break;
case T_CreateForeignServerStmt:
tag = "CREATE SERVER";
break;
case T_AlterForeignServerStmt:
tag = "ALTER SERVER";
break;
case T_DropForeignServerStmt:
tag = "DROP SERVER";
break;
case T_CreateUserMappingStmt:
tag = "CREATE USER MAPPING";
break;
case T_AlterUserMappingStmt:
tag = "ALTER USER MAPPING";
break;
case T_DropUserMappingStmt:
tag = "DROP USER MAPPING";
break;
case T_DropStmt:
switch (((DropStmt *) parsetree)->removeType)
{
@ -1523,6 +1604,12 @@ CreateCommandTag(Node *parsetree)
case OBJECT_TSDICTIONARY:
tag = "ALTER TEXT SEARCH DICTIONARY";
break;
case OBJECT_FDW:
tag = "ALTER FOREIGN DATA WRAPPER";
break;
case OBJECT_FOREIGN_SERVER:
tag = "ALTER SERVER";
break;
default:
tag = "???";
break;
@ -2037,6 +2124,18 @@ GetCommandLogLevel(Node *parsetree)
lev = LOGSTMT_DDL;
break;
case T_CreateFdwStmt:
case T_AlterFdwStmt:
case T_DropFdwStmt:
case T_CreateForeignServerStmt:
case T_AlterForeignServerStmt:
case T_DropForeignServerStmt:
case T_CreateUserMappingStmt:
case T_AlterUserMappingStmt:
case T_DropUserMappingStmt:
lev = LOGSTMT_DDL;
break;
case T_DropStmt:
lev = LOGSTMT_DDL;
break;

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.143 2008/12/15 18:09:41 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/acl.c,v 1.144 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -22,6 +22,7 @@
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
#include "commands/tablespace.h"
#include "foreign/foreign.h"
#include "miscadmin.h"
#include "utils/acl.h"
#include "utils/builtins.h"
@ -577,6 +578,14 @@ acldefault(GrantObjectType objtype, Oid ownerId)
world_default = ACL_NO_RIGHTS;
owner_default = ACL_ALL_RIGHTS_TABLESPACE;
break;
case ACL_OBJECT_FDW:
world_default = ACL_NO_RIGHTS;
owner_default = ACL_ALL_RIGHTS_FDW;
break;
case ACL_OBJECT_FOREIGN_SERVER:
world_default = ACL_NO_RIGHTS;
owner_default = ACL_ALL_RIGHTS_FOREIGN_SERVER;
break;
default:
elog(ERROR, "unrecognized objtype: %d", (int) objtype);
world_default = ACL_NO_RIGHTS; /* keep compiler quiet */
@ -1823,6 +1832,156 @@ convert_database_priv_string(text *priv_type_text)
}
/*
* has_foreign_data_wrapper_privilege variants
* These are all named "has_foreign_data_wrapper_privilege" at the SQL level.
* They take various combinations of foreign-data wrapper name,
* fdw OID, user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not. The variants that take an OID return
* NULL if the OID doesn't exist.
*/
/*
* has_foreign_data_wrapper_privilege
* Check user privileges on a foreign-data wrapper.
*/
static Datum
has_foreign_data_wrapper_privilege(Oid roleid, Oid fdwid, text *priv_type_text)
{
AclResult aclresult;
AclMode mode = ACL_NO_RIGHTS;
char *priv_type = text_to_cstring(priv_type_text);
if (pg_strcasecmp(priv_type, "USAGE") == 0)
mode = ACL_USAGE;
else if (pg_strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
mode = ACL_GRANT_OPTION_FOR(ACL_USAGE);
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized privilege type: \"%s\"", priv_type)));
aclresult = pg_foreign_data_wrapper_aclcheck(fdwid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
* has_foreign_data_wrapper_privilege_name_name
* Check user privileges on a foreign-data wrapper given
* name username, text fdwname, and text priv name.
*/
Datum
has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
char *fdwname = text_to_cstring(PG_GETARG_TEXT_P(1));
text *priv_type_text = PG_GETARG_TEXT_P(2);
return has_foreign_data_wrapper_privilege(get_roleid_checked(NameStr(*username)),
GetForeignDataWrapperOidByName(fdwname, false),
priv_type_text);
}
/*
* has_foreign_data_wrapper_privilege_name
* Check user privileges on a foreign-data wrapper given
* text fdwname and text priv name.
* current_user is assumed
*/
Datum
has_foreign_data_wrapper_privilege_name(PG_FUNCTION_ARGS)
{
char *fdwname = text_to_cstring(PG_GETARG_TEXT_P(0));
text *priv_type_text = PG_GETARG_TEXT_P(1);
return has_foreign_data_wrapper_privilege(GetUserId(),
GetForeignDataWrapperOidByName(fdwname, false),
priv_type_text);
}
/*
* has_foreign_data_wrapper_privilege_name_id
* Check user privileges on a foreign-data wrapper given
* name usename, foreign-data wrapper oid, and text priv name.
*/
Datum
has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Oid fdwid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
if (!SearchSysCacheExists(FOREIGNDATAWRAPPEROID,
ObjectIdGetDatum(fdwid),
0, 0, 0))
PG_RETURN_NULL();
return has_foreign_data_wrapper_privilege(get_roleid_checked(NameStr(*username)),
fdwid, priv_type_text);
}
/*
* has_foreign_data_wrapper_privilege_id
* Check user privileges on a foreign-data wrapper given
* foreign-data wrapper oid, and text priv name.
* current_user is assumed
*/
Datum
has_foreign_data_wrapper_privilege_id(PG_FUNCTION_ARGS)
{
Oid fdwid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
if (!SearchSysCacheExists(FOREIGNDATAWRAPPEROID,
ObjectIdGetDatum(fdwid),
0, 0, 0))
PG_RETURN_NULL();
return has_foreign_data_wrapper_privilege(GetUserId(), fdwid,
priv_type_text);
}
/*
* has_foreign_data_wrapper_privilege_id_name
* Check user privileges on a foreign-data wrapper given
* roleid, text fdwname, and text priv name.
*/
Datum
has_foreign_data_wrapper_privilege_id_name(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
char *fdwname = text_to_cstring(PG_GETARG_TEXT_P(1));
text *priv_type_text = PG_GETARG_TEXT_P(2);
return has_foreign_data_wrapper_privilege(roleid,
GetForeignDataWrapperOidByName(fdwname, false),
priv_type_text);
}
/*
* has_foreign_data_wrapper_privilege_id_id
* Check user privileges on a foreign-data wrapper given
* roleid, fdw oid, and text priv name.
*/
Datum
has_foreign_data_wrapper_privilege_id_id(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
Oid fdwid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
if (!SearchSysCacheExists(FOREIGNDATAWRAPPEROID,
ObjectIdGetDatum(fdwid),
0, 0, 0))
PG_RETURN_NULL();
return has_foreign_data_wrapper_privilege(roleid, fdwid, priv_type_text);
}
/*
* has_function_privilege variants
* These are all named "has_function_privilege" at the SQL level.
@ -2466,6 +2625,154 @@ convert_schema_priv_string(text *priv_type_text)
return ACL_NO_RIGHTS; /* keep compiler quiet */
}
/*
* has_server_privilege variants
* These are all named "has_server_privilege" at the SQL level.
* They take various combinations of foreign server name,
* server OID, user name, user OID, or implicit user = current_user.
*
* The result is a boolean value: true if user has the indicated
* privilege, false if not.
*/
/*
* has_server_privilege
* Check user privileges on a foreign server.
*/
static Datum
has_server_privilege(Oid roleid, Oid serverid, text *priv_type_text)
{
AclResult aclresult;
AclMode mode = ACL_NO_RIGHTS;
char *priv_type = text_to_cstring(priv_type_text);
if (pg_strcasecmp(priv_type, "USAGE") == 0)
mode = ACL_USAGE;
else if (pg_strcasecmp(priv_type, "USAGE WITH GRANT OPTION") == 0)
mode = ACL_GRANT_OPTION_FOR(ACL_USAGE);
else
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("unrecognized privilege type: \"%s\"", priv_type)));
aclresult = pg_foreign_server_aclcheck(serverid, roleid, mode);
PG_RETURN_BOOL(aclresult == ACLCHECK_OK);
}
/*
* has_server_privilege_name_name
* Check user privileges on a foreign server given
* name username, text servername, and text priv name.
*/
Datum
has_server_privilege_name_name(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
char *servername = text_to_cstring(PG_GETARG_TEXT_P(1));
text *priv_type_text = PG_GETARG_TEXT_P(2);
return has_server_privilege(get_roleid_checked(NameStr(*username)),
GetForeignServerOidByName(servername, false),
priv_type_text);
}
/*
* has_server_privilege_name
* Check user privileges on a foreign server given
* text servername and text priv name.
* current_user is assumed
*/
Datum
has_server_privilege_name(PG_FUNCTION_ARGS)
{
char *servername = text_to_cstring(PG_GETARG_TEXT_P(0));
text *priv_type_text = PG_GETARG_TEXT_P(1);
return has_server_privilege(GetUserId(),
GetForeignServerOidByName(servername, false),
priv_type_text);
}
/*
* has_server_privilege_name_id
* Check user privileges on a foreign server given
* name usename, foreign server oid, and text priv name.
*/
Datum
has_server_privilege_name_id(PG_FUNCTION_ARGS)
{
Name username = PG_GETARG_NAME(0);
Oid serverid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
if (!SearchSysCacheExists(FOREIGNSERVEROID,
ObjectIdGetDatum(serverid),
0, 0, 0))
PG_RETURN_NULL();
return has_server_privilege(get_roleid_checked(NameStr(*username)), serverid,
priv_type_text);
}
/*
* has_server_privilege_id
* Check user privileges on a foreign server given
* server oid, and text priv name.
* current_user is assumed
*/
Datum
has_server_privilege_id(PG_FUNCTION_ARGS)
{
Oid serverid = PG_GETARG_OID(0);
text *priv_type_text = PG_GETARG_TEXT_P(1);
if (!SearchSysCacheExists(FOREIGNSERVEROID,
ObjectIdGetDatum(serverid),
0, 0, 0))
PG_RETURN_NULL();
return has_server_privilege(GetUserId(), serverid, priv_type_text);
}
/*
* has_server_privilege_id_name
* Check user privileges on a foreign server given
* roleid, text servername, and text priv name.
*/
Datum
has_server_privilege_id_name(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
char *servername = text_to_cstring(PG_GETARG_TEXT_P(1));
text *priv_type_text = PG_GETARG_TEXT_P(2);
return has_server_privilege(roleid,
GetForeignServerOidByName(servername, false),
priv_type_text);
}
/*
* has_server_privilege_id_id
* Check user privileges on a foreign server given
* roleid, server oid, and text priv name.
*/
Datum
has_server_privilege_id_id(PG_FUNCTION_ARGS)
{
Oid roleid = PG_GETARG_OID(0);
Oid serverid = PG_GETARG_OID(1);
text *priv_type_text = PG_GETARG_TEXT_P(2);
if (!SearchSysCacheExists(FOREIGNSERVEROID,
ObjectIdGetDatum(serverid),
0, 0, 0))
PG_RETURN_NULL();
return has_server_privilege(roleid, serverid, priv_type_text);
}
/*
* has_tablespace_privilege variants
* These are all named "has_tablespace_privilege" at the SQL level.

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.117 2008/06/19 00:46:05 alvherre Exp $
* $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.118 2008/12/19 16:25:17 petere Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
@ -32,6 +32,8 @@
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_enum.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_language.h"
#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
@ -46,6 +48,7 @@
#include "catalog/pg_ts_parser.h"
#include "catalog/pg_ts_template.h"
#include "catalog/pg_type.h"
#include "catalog/pg_user_mapping.h"
#include "utils/rel.h"
#include "utils/syscache.h"
@ -365,6 +368,54 @@ static const struct cachedesc cacheinfo[] = {
},
256
},
{ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPERNAME */
ForeignDataWrapperNameIndexId,
0,
1,
{
Anum_pg_foreign_data_wrapper_fdwname,
0,
0,
0
},
8
},
{ForeignDataWrapperRelationId, /* FOREIGNDATAWRAPPEROID */
ForeignDataWrapperOidIndexId,
0,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
},
8
},
{ForeignServerRelationId, /* FOREIGNSERVERNAME */
ForeignServerNameIndexId,
0,
1,
{
Anum_pg_foreign_server_srvname,
0,
0,
0
},
32
},
{ForeignServerRelationId, /* FOREIGNSERVEROID */
ForeignServerOidIndexId,
0,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
},
32
},
{IndexRelationId, /* INDEXRELID */
IndexRelidIndexId,
Anum_pg_index_indrelid,
@ -676,6 +727,30 @@ static const struct cachedesc cacheinfo[] = {
0
},
1024
},
{UserMappingRelationId, /* USERMAPPINGOID */
UserMappingOidIndexId,
0,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
},
128
},
{UserMappingRelationId, /* USERMAPPINGUSERSERVER */
UserMappingUserServerIndexId,
0,
2,
{
Anum_pg_user_mapping_umuser,
Anum_pg_user_mapping_umserver,
0,
0
},
128
}
};

View File

@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.104 2008/05/09 23:32:04 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/common.c,v 1.105 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -91,6 +91,8 @@ getSchemaData(int *numTablesPtr)
TSTemplateInfo *tmplinfo;
TSDictInfo *dictinfo;
TSConfigInfo *cfginfo;
FdwInfo *fdwinfo;
ForeignServerInfo *srvinfo;
int numNamespaces;
int numAggregates;
int numInherits;
@ -104,6 +106,8 @@ getSchemaData(int *numTablesPtr)
int numTSTemplates;
int numTSDicts;
int numTSConfigs;
int numForeignDataWrappers;
int numForeignServers;
if (g_verbose)
write_msg(NULL, "reading schemas\n");
@ -154,6 +158,14 @@ getSchemaData(int *numTablesPtr)
write_msg(NULL, "reading user-defined text search configurations\n");
cfginfo = getTSConfigurations(&numTSConfigs);
if (g_verbose)
write_msg(NULL, "reading user-defined foreign-data wrappers\n");
fdwinfo = getForeignDataWrappers(&numForeignDataWrappers);
if (g_verbose)
write_msg(NULL, "reading user-defined foreign servers\n");
srvinfo = getForeignServers(&numForeignServers);
if (g_verbose)
write_msg(NULL, "reading user-defined operator families\n");
opfinfo = getOpfamilies(&numOpfamilies);

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.41 2008/09/08 00:47:40 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/dumputils.c,v 1.42 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -687,6 +687,10 @@ do { \
}
else if (strcmp(type, "TABLESPACE") == 0)
CONVERT_PRIV('C', "CREATE");
else if (strcmp(type, "FOREIGN DATA WRAPPER") == 0)
CONVERT_PRIV('U', "USAGE");
else if (strcmp(type, "SERVER") == 0)
CONVERT_PRIV('U', "USAGE");
else
abort();

View File

@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.158 2008/09/05 23:53:42 momjian Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.159 2008/12/19 16:25:17 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -2479,7 +2479,10 @@ _getObjectDescription(PQExpBuffer buf, TocEntry *te, ArchiveHandle *AH)
/* objects named by just a name */
if (strcmp(type, "DATABASE") == 0 ||
strcmp(type, "PROCEDURAL LANGUAGE") == 0 ||
strcmp(type, "SCHEMA") == 0)
strcmp(type, "SCHEMA") == 0 ||
strcmp(type, "FOREIGN DATA WRAPPER") == 0 ||
strcmp(type, "SERVER") == 0 ||
strcmp(type, "USER MAPPING") == 0)
{
appendPQExpBuffer(buf, "%s %s", type, fmtId(te->tag));
return;
@ -2636,7 +2639,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
strcmp(te->desc, "VIEW") == 0 ||
strcmp(te->desc, "SEQUENCE") == 0 ||
strcmp(te->desc, "TEXT SEARCH DICTIONARY") == 0 ||
strcmp(te->desc, "TEXT SEARCH CONFIGURATION") == 0)
strcmp(te->desc, "TEXT SEARCH CONFIGURATION") == 0 ||
strcmp(te->desc, "FOREIGN DATA WRAPPER") == 0 ||
strcmp(te->desc, "SERVER") == 0)
{
PQExpBuffer temp = createPQExpBuffer();
@ -2653,7 +2658,8 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
strcmp(te->desc, "FK CONSTRAINT") == 0 ||
strcmp(te->desc, "INDEX") == 0 ||
strcmp(te->desc, "RULE") == 0 ||
strcmp(te->desc, "TRIGGER") == 0)
strcmp(te->desc, "TRIGGER") == 0 ||
strcmp(te->desc, "USER MAPPING") == 0)
{
/* these object types don't have separate owners */
}

View File

@ -12,7 +12,7 @@
* by PostgreSQL
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.508 2008/12/18 18:20:34 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.509 2008/12/19 16:25:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -158,6 +158,11 @@ static void dumpTSParser(Archive *fout, TSParserInfo *prsinfo);
static void dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo);
static void dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo);
static void dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo);
static void dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo);
static void dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo);
static void dumpUserMappings(Archive *fout, const char *target,
const char *servername, const char *namespace,
const char *owner, CatalogId catalogId, DumpId dumpId);
static void dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
const char *type, const char *name,
@ -5269,6 +5274,165 @@ getTSConfigurations(int *numTSConfigs)
return cfginfo;
}
/*
* getForeignDataWrappers:
* read all foreign-data wrappers in the system catalogs and return
* them in the FdwInfo* structure
*
* numForeignDataWrappers is set to the number of fdws read in
*/
FdwInfo *
getForeignDataWrappers(int *numForeignDataWrappers)
{
PGresult *res;
int ntups;
int i;
PQExpBuffer query = createPQExpBuffer();
FdwInfo *fdwinfo;
int i_oid;
int i_fdwname;
int i_rolname;
int i_fdwlibrary;
int i_fdwacl;
int i_fdwoptions;
/* Before 8.4, there are no foreign-data wrappers */
if (g_fout->remoteVersion < 80400)
{
*numForeignDataWrappers = 0;
return NULL;
}
/* Make sure we are in proper schema */
selectSourceSchema("pg_catalog");
appendPQExpBuffer(query, "SELECT oid, fdwname, "
"(%s fdwowner) as rolname, fdwlibrary, 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);
ntups = PQntuples(res);
*numForeignDataWrappers = ntups;
fdwinfo = (FdwInfo *) malloc(ntups * sizeof(FdwInfo));
i_oid = PQfnumber(res, "oid");
i_fdwname = PQfnumber(res, "fdwname");
i_rolname = PQfnumber(res, "rolname");
i_fdwlibrary = PQfnumber(res, "fdwlibrary");
i_fdwacl = PQfnumber(res, "fdwacl");
i_fdwoptions = PQfnumber(res, "fdwoptions");
for (i = 0; i < ntups; i++)
{
fdwinfo[i].dobj.objType = DO_FDW;
fdwinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&fdwinfo[i].dobj);
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].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));
}
PQclear(res);
destroyPQExpBuffer(query);
return fdwinfo;
}
/*
* getForeignServers:
* read all foreign servers in the system catalogs and return
* them in the ForeignServerInfo * structure
*
* numForeignServers is set to the number of servers read in
*/
ForeignServerInfo *
getForeignServers(int *numForeignServers)
{
PGresult *res;
int ntups;
int i;
PQExpBuffer query = createPQExpBuffer();
ForeignServerInfo *srvinfo;
int i_oid;
int i_srvname;
int i_rolname;
int i_srvfdw;
int i_srvtype;
int i_srvversion;
int i_srvacl;
int i_srvoptions;
/* Before 8.4, there are no foreign servers */
if (g_fout->remoteVersion < 80400)
{
*numForeignServers = 0;
return NULL;
}
/* Make sure we are in proper schema */
selectSourceSchema("pg_catalog");
appendPQExpBuffer(query, "SELECT oid, srvname, "
"(%s srvowner) as rolname, "
"srvfdw, srvtype, srvversion, srvacl,"
"array_to_string(ARRAY(select option_name || ' ' || quote_literal(option_value) from pg_options_to_table(srvoptions)), ', ') as srvoptions "
"FROM pg_foreign_server",
username_subquery);
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
*numForeignServers = ntups;
srvinfo = (ForeignServerInfo *) malloc(ntups * sizeof(ForeignServerInfo));
i_oid = PQfnumber(res, "oid");
i_srvname = PQfnumber(res, "srvname");
i_rolname = PQfnumber(res, "rolname");
i_srvfdw = PQfnumber(res, "srvfdw");
i_srvtype = PQfnumber(res, "srvtype");
i_srvversion = PQfnumber(res, "srvversion");
i_srvacl = PQfnumber(res, "srvacl");
i_srvoptions = PQfnumber(res, "srvoptions");
for (i = 0; i < ntups; i++)
{
srvinfo[i].dobj.objType = DO_FOREIGN_SERVER;
srvinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
AssignDumpId(&srvinfo[i].dobj);
srvinfo[i].dobj.name = strdup(PQgetvalue(res, i, i_srvname));
srvinfo[i].dobj.namespace = NULL;
srvinfo[i].rolname = strdup(PQgetvalue(res, i, i_rolname));
srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw));
srvinfo[i].srvtype = strdup(PQgetvalue(res, i, i_srvtype));
srvinfo[i].srvversion = strdup(PQgetvalue(res, i, i_srvversion));
srvinfo[i].srvoptions = strdup(PQgetvalue(res, i, i_srvoptions));
srvinfo[i].srvacl = strdup(PQgetvalue(res, i, i_srvacl));
/* Decide whether we want to dump it */
selectDumpableObject(&(srvinfo[i].dobj));
}
PQclear(res);
destroyPQExpBuffer(query);
return srvinfo;
}
/*
* dumpComment --
@ -5671,6 +5835,12 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
case DO_TSCONFIG:
dumpTSConfig(fout, (TSConfigInfo *) dobj);
break;
case DO_FDW:
dumpForeignDataWrapper(fout, (FdwInfo *) dobj);
break;
case DO_FOREIGN_SERVER:
dumpForeignServer(fout, (ForeignServerInfo *) dobj);
break;
case DO_BLOBS:
ArchiveEntry(fout, dobj->catId, dobj->dumpId,
dobj->name, NULL, NULL, "",
@ -8977,6 +9147,224 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
destroyPQExpBuffer(query);
}
/*
* dumpForeignDataWrapper
* write out a single foreign-data wrapper definition
*/
static void
dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
{
PQExpBuffer q;
PQExpBuffer delq;
char *namecopy;
/* Skip if not to be dumped */
if (!fdwinfo->dobj.dump || dataOnly)
return;
q = createPQExpBuffer();
delq = createPQExpBuffer();
appendPQExpBuffer(q, "CREATE FOREIGN DATA WRAPPER %s LIBRARY '%s' LANGUAGE C",
fmtId(fdwinfo->dobj.name), fdwinfo->fdwlibrary);
if (fdwinfo->fdwoptions && strlen(fdwinfo->fdwoptions) > 0)
appendPQExpBuffer(q, " OPTIONS (%s)", fdwinfo->fdwoptions);
appendPQExpBuffer(q, ";\n");
appendPQExpBuffer(delq, "DROP FOREIGN DATA WRAPPER %s;\n",
fmtId(fdwinfo->dobj.name));
ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
fdwinfo->dobj.name,
NULL,
NULL,
fdwinfo->rolname,
false, "FOREIGN DATA WRAPPER", q->data, delq->data, NULL,
fdwinfo->dobj.dependencies, fdwinfo->dobj.nDeps,
NULL, NULL);
/* Handle the ACL */
namecopy = strdup(fmtId(fdwinfo->dobj.name));
dumpACL(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
"FOREIGN DATA WRAPPER",
namecopy, fdwinfo->dobj.name,
NULL, fdwinfo->rolname,
fdwinfo->fdwacl);
free(namecopy);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
}
/*
* dumpForeignServer
* write out a foreign server definition
*/
static void
dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
{
PQExpBuffer q;
PQExpBuffer delq;
PQExpBuffer query;
PGresult *res;
int ntups;
char *namecopy;
char *fdwname;
/* Skip if not to be dumped */
if (!srvinfo->dobj.dump || dataOnly)
return;
q = createPQExpBuffer();
delq = createPQExpBuffer();
query = createPQExpBuffer();
/* look up the foreign-data wrapper */
appendPQExpBuffer(query, "SELECT fdwname "
"FROM pg_foreign_data_wrapper w "
"WHERE w.oid = '%u'",
srvinfo->srvfdw);
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
if (ntups != 1)
{
write_msg(NULL, "query returned %d rows instead of one: %s\n",
ntups, query->data);
exit_nicely();
}
fdwname = PQgetvalue(res, 0, 0);
appendPQExpBuffer(q, "CREATE SERVER %s", fmtId(srvinfo->dobj.name));
if (srvinfo->srvtype && strlen(srvinfo->srvtype) > 0)
appendPQExpBuffer(q, " TYPE '%s'", srvinfo->srvtype);
if (srvinfo->srvversion && strlen(srvinfo->srvversion) > 0)
appendPQExpBuffer(q, " VERSION '%s'", srvinfo->srvversion);
appendPQExpBuffer(q, " FOREIGN DATA WRAPPER ");
appendPQExpBuffer(q, "%s", fmtId(fdwname));
if (srvinfo->srvoptions && strlen(srvinfo->srvoptions) > 0)
appendPQExpBuffer(q, " OPTIONS (%s)", srvinfo->srvoptions);
appendPQExpBuffer(q, ";\n");
appendPQExpBuffer(delq, "DROP SERVER %s;\n",
fmtId(srvinfo->dobj.name));
ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
srvinfo->dobj.name,
NULL,
NULL,
srvinfo->rolname,
false, "SERVER", q->data, delq->data, NULL,
srvinfo->dobj.dependencies, srvinfo->dobj.nDeps,
NULL, NULL);
/* Handle the ACL */
namecopy = strdup(fmtId(srvinfo->dobj.name));
dumpACL(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
"SERVER",
namecopy, srvinfo->dobj.name,
NULL, srvinfo->rolname,
srvinfo->srvacl);
free(namecopy);
/* Dump user mappings */
resetPQExpBuffer(q);
appendPQExpBuffer(q, "SERVER %s", fmtId(srvinfo->dobj.name));
dumpUserMappings(fout, q->data,
srvinfo->dobj.name, NULL,
srvinfo->rolname,
srvinfo->dobj.catId, srvinfo->dobj.dumpId);
destroyPQExpBuffer(q);
destroyPQExpBuffer(delq);
}
/*
* dumpUserMappings
*
* This routine is used to dump any user mappings associated with the
* server handed to this routine. Should be called after ArchiveEntry()
* for the server.
*/
static void
dumpUserMappings(Archive *fout, const char *target,
const char *servername, const char *namespace,
const char *owner,
CatalogId catalogId, DumpId dumpId)
{
PQExpBuffer q;
PQExpBuffer delq;
PQExpBuffer query;
PQExpBuffer tag;
PGresult *res;
int ntups;
int i_umuser;
int i_umoptions;
int i;
q = createPQExpBuffer();
tag = createPQExpBuffer();
delq = createPQExpBuffer();
query = createPQExpBuffer();
appendPQExpBuffer(query,
"SELECT (%s umuser) AS umuser, "
"array_to_string(ARRAY(SELECT option_name || ' ' || quote_literal(option_value) FROM pg_options_to_table(umoptions)), ', ') AS umoptions\n"
"FROM pg_user_mapping WHERE umserver=%u",
username_subquery,
catalogId.oid);
res = PQexec(g_conn, query->data);
check_sql_result(res, g_conn, query->data, PGRES_TUPLES_OK);
ntups = PQntuples(res);
i_umuser = PQfnumber(res, "umuser");
i_umoptions = PQfnumber(res, "umoptions");
for (i = 0; i < ntups; i++)
{
char *umuser;
char *umoptions;
umuser = PQgetvalue(res, i, i_umuser);
umoptions = PQgetvalue(res, i, i_umoptions);
resetPQExpBuffer(q);
appendPQExpBuffer(q, "CREATE USER MAPPING FOR %s", fmtId(umuser));
appendPQExpBuffer(q, " SERVER %s", fmtId(servername));
if (umoptions && strlen(umoptions) > 0)
appendPQExpBuffer(q, " OPTIONS (%s)", umoptions);
appendPQExpBuffer(q, ";\n");
resetPQExpBuffer(delq);
appendPQExpBuffer(delq, "DROP USER MAPPING FOR %s SERVER %s;\n", fmtId(umuser), fmtId(servername));
resetPQExpBuffer(tag);
appendPQExpBuffer(tag, "USER MAPPING %s %s", fmtId(umuser), target);
ArchiveEntry(fout, nilCatalogId, createDumpId(),
tag->data,
namespace,
NULL,
owner, false,
"USER MAPPING", q->data,
delq->data, NULL,
&dumpId, 1,
NULL, NULL);
}
PQclear(res);
destroyPQExpBuffer(query);
destroyPQExpBuffer(delq);
destroyPQExpBuffer(q);
}
/*----------
* Write out grant/revoke information

View File

@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2008, 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.143 2008/11/09 21:24:33 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.144 2008/12/19 16:25:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -131,6 +131,8 @@ typedef enum
DO_TSDICT,
DO_TSTEMPLATE,
DO_TSCONFIG,
DO_FDW,
DO_FOREIGN_SERVER,
DO_BLOBS,
DO_BLOB_COMMENTS
} DumpableObjectType;
@ -418,6 +420,26 @@ typedef struct _cfgInfo
Oid cfgparser;
} TSConfigInfo;
typedef struct _fdwInfo
{
DumpableObject dobj;
char *rolname;
char *fdwlibrary;
char *fdwoptions;
char *fdwacl;
} FdwInfo;
typedef struct _foreignServerInfo
{
DumpableObject dobj;
char *rolname;
Oid srvfdw;
char *srvtype;
char *srvversion;
char *srvacl;
char *srvoptions;
} ForeignServerInfo;
/* global decls */
extern bool force_quotes; /* double-quotes for identifiers flag */
extern bool g_verbose; /* verbose flag */
@ -500,5 +522,7 @@ extern TSParserInfo *getTSParsers(int *numTSParsers);
extern TSDictInfo *getTSDictionaries(int *numTSDicts);
extern TSTemplateInfo *getTSTemplates(int *numTSTemplates);
extern TSConfigInfo *getTSConfigurations(int *numTSConfigs);
extern FdwInfo *getForeignDataWrappers(int *numForeignDataWrappers);
extern ForeignServerInfo *getForeignServers(int *numForeignServers);
#endif /* PG_DUMP_H */

View File

@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.21 2008/09/08 15:26:23 tgl Exp $
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump_sort.c,v 1.22 2008/12/19 16:25:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -50,6 +50,8 @@ static const int oldObjectTypePriority[] =
4, /* DO_TSDICT */
3, /* DO_TSTEMPLATE */
5, /* DO_TSCONFIG */
3, /* DO_FDW */
4, /* DO_FOREIGN_SERVER */
10, /* DO_BLOBS */
11 /* DO_BLOB_COMMENTS */
};
@ -84,6 +86,8 @@ static const int newObjectTypePriority[] =
6, /* DO_TSDICT */
5, /* DO_TSTEMPLATE */
7, /* DO_TSCONFIG */
3, /* DO_FDW */
4, /* DO_FOREIGN_SERVER */
14, /* DO_BLOBS */
15 /* DO_BLOB_COMMENTS */
};
@ -1123,6 +1127,16 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
"TEXT SEARCH CONFIGURATION %s (ID %d OID %u)",
obj->name, obj->dumpId, obj->catId.oid);
return;
case DO_FDW:
snprintf(buf, bufsize,
"FOREIGN DATA WRAPPER %s (ID %d OID %u)",
obj->name, obj->dumpId, obj->catId.oid);
return;
case DO_FOREIGN_SERVER:
snprintf(buf, bufsize,
"FOREIGN SERVER %s (ID %d OID %u)",
obj->name, obj->dumpId, obj->catId.oid);
return;
case DO_BLOBS:
snprintf(buf, bufsize,
"BLOBS (ID %d)",

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.198 2008/11/21 20:14:27 mha Exp $
* $PostgreSQL: pgsql/src/bin/psql/command.c,v 1.199 2008/12/19 16:25:18 petere Exp $
*/
#include "postgres_fe.h"
#include "command.h"
@ -416,7 +416,23 @@ exec_command(const char *cmd,
break;
}
break;
case 'e': /* SQL/MED subsystem */
switch(cmd[2])
{
case 's':
success = listForeignServers(pattern, show_verbose);
break;
case 'u':
success = listUserMappings(pattern, show_verbose);
break;
case 'w':
success = listForeignDataWrappers(pattern, show_verbose);
break;
default:
status = PSQL_CMD_UNKNOWN;
break;
}
break;
default:
status = PSQL_CMD_UNKNOWN;
}

View File

@ -8,7 +8,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.189 2008/12/19 14:39:58 alvherre Exp $
* $PostgreSQL: pgsql/src/bin/psql/describe.c,v 1.190 2008/12/19 16:25:18 petere Exp $
*/
#include "postgres_fe.h"
@ -2785,3 +2785,156 @@ describeOneTSConfig(const char *oid, const char *nspname, const char *cfgname,
PQclear(res);
return true;
}
/*
* \dew
*
* Describes foreign-data wrappers
*/
bool
listForeignDataWrappers(const char *pattern, bool verbose)
{
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
"SELECT fdwname AS \"%s\",\n"
" pg_catalog.pg_get_userbyid(fdwowner) AS \"%s\",\n"
" fdwlibrary AS \"%s\"\n",
gettext_noop("Name"),
gettext_noop("Owner"),
gettext_noop("Library"));
if (verbose)
appendPQExpBuffer(&buf,
",\n fdwacl AS \"%s\","
" fdwoptions AS \"%s\"",
gettext_noop("Access privileges"),
gettext_noop("Options"));
appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_foreign_data_wrapper WHERE 1=1\n");
processSQLNamePattern(pset.db, &buf, pattern, true, false,
NULL, "fdwname", NULL, NULL);
appendPQExpBuffer(&buf, "ORDER BY 1;");
res = PSQLexec(buf.data, false);
termPQExpBuffer(&buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = _("List of foreign-data wrappers");
myopt.translate_header = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile);
PQclear(res);
return true;
}
/*
* \des
*
* Describes servers.
*/
bool
listForeignServers(const char *pattern, bool verbose)
{
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
"SELECT s.srvname AS \"%s\",\n"
" pg_catalog.pg_get_userbyid(s.srvowner) AS \"%s\",\n"
" f.fdwname AS \"%s\"\n",
gettext_noop("Name"),
gettext_noop("Owner"),
gettext_noop("Foreign-data wrapper"));
if (verbose)
appendPQExpBuffer(&buf,
",\n s.srvacl AS \"%s\","
" s.srvtype AS \"%s\","
" s.srvversion AS \"%s\","
" s.srvoptions AS \"%s\"",
gettext_noop("Access privileges"),
gettext_noop("Type"),
gettext_noop("Version"),
gettext_noop("Options"));
appendPQExpBuffer(&buf,
"\nFROM pg_foreign_server s\n"
"JOIN pg_catalog.pg_foreign_data_wrapper f ON f.oid=s.srvfdw\n");
processSQLNamePattern(pset.db, &buf, pattern, true, false,
NULL, "s.srvname", NULL, NULL);
appendPQExpBuffer(&buf, "ORDER BY 1;");
res = PSQLexec(buf.data, false);
termPQExpBuffer(&buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = _("List of foreign servers");
myopt.translate_header = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile);
PQclear(res);
return true;
}
/*
* \deu
*
* Describes user mappings.
*/
bool
listUserMappings(const char *pattern, bool verbose)
{
PQExpBufferData buf;
PGresult *res;
printQueryOpt myopt = pset.popt;
initPQExpBuffer(&buf);
printfPQExpBuffer(&buf,
"SELECT um.srvname AS \"%s\",\n"
" um.usename AS \"%s\"",
gettext_noop("Server"),
gettext_noop("Username"));
if (verbose)
appendPQExpBuffer(&buf,
",\n um.umoptions AS \"%s\"",
gettext_noop("Options"));
appendPQExpBuffer(&buf, "\nFROM pg_catalog.pg_user_mappings um WHERE 1=1\n");
processSQLNamePattern(pset.db, &buf, pattern, true, false,
NULL, "um.srvname", "um.usename", NULL);
appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
res = PSQLexec(buf.data, false);
termPQExpBuffer(&buf);
if (!res)
return false;
myopt.nullPrint = NULL;
myopt.title = _("List of user mappings");
myopt.translate_header = true;
printQuery(res, &myopt, pset.queryFout, pset.logfile);
PQclear(res);
return true;
}

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/describe.h,v 1.35 2008/01/01 19:45:56 momjian Exp $
* $PostgreSQL: pgsql/src/bin/psql/describe.h,v 1.36 2008/12/19 16:25:18 petere Exp $
*/
#ifndef DESCRIBE_H
#define DESCRIBE_H
@ -66,5 +66,14 @@ extern bool listCasts(const char *pattern);
/* \dn */
extern bool listSchemas(const char *pattern, bool verbose);
/* \dew */
extern bool listForeignDataWrappers(const char *pattern, bool verbose);
/* \des */
extern bool listForeignServers(const char *pattern, bool verbose);
/* \deu */
extern bool listUserMappings(const char *pattern, bool verbose);
#endif /* DESCRIBE_H */

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.131 2008/11/06 15:18:36 tgl Exp $
* $PostgreSQL: pgsql/src/bin/psql/help.c,v 1.132 2008/12/19 16:25:18 petere Exp $
*/
#include "postgres_fe.h"
@ -203,6 +203,9 @@ slashUsage(unsigned short int pager)
fprintf(output, _(" \\dC [PATTERN] list casts\n"));
fprintf(output, _(" \\dd [PATTERN] show comment for object\n"));
fprintf(output, _(" \\dD [PATTERN] list domains\n"));
fprintf(output, _(" \\des [PATTERN] list foreign servers (add \"+\" for more detail)\n"));
fprintf(output, _(" \\deu [PATTERN] list user mappings (add \"+\" for more detail)\n"));
fprintf(output, _(" \\dew [PATTERN] list foreign-data wrappers (add \"+\" for more detail)\n"));
fprintf(output, _(" \\df [PATTERN] list functions (add \"+\" for more detail)\n"));
fprintf(output, _(" \\dF [PATTERN] list text search configurations (add \"+\" for more detail)\n"));
fprintf(output, _(" \\dFd [PATTERN] list text search dictionaries (add \"+\" for more detail)\n"));

View File

@ -3,7 +3,7 @@
*
* Copyright (c) 2000-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.177 2008/11/20 14:04:46 petere Exp $
* $PostgreSQL: pgsql/src/bin/psql/tab-complete.c,v 1.178 2008/12/19 16:25:18 petere Exp $
*/
/*----------------------------------------------------------------------
@ -497,6 +497,21 @@ static const SchemaQuery Query_for_list_of_views = {
"SELECT pg_catalog.quote_ident(tmplname) FROM pg_catalog.pg_ts_template "\
" WHERE substring(pg_catalog.quote_ident(tmplname),1,%d)='%s'"
#define Query_for_list_of_fdws \
" SELECT pg_catalog.quote_ident(fdwname) "\
" FROM pg_catalog.pg_foreign_data_wrapper "\
" WHERE substring(pg_catalog.quote_ident(fdwname),1,%d)='%s'"
#define Query_for_list_of_servers \
" SELECT pg_catalog.quote_ident(srvname) "\
" FROM pg_catalog.pg_foreign_server "\
" WHERE substring(pg_catalog.quote_ident(srvname),1,%d)='%s'"
#define Query_for_list_of_user_mappings \
" SELECT pg_catalog.quote_ident(usename) "\
" FROM pg_catalog.pg_user_mappings "\
" WHERE substring(pg_catalog.quote_ident(usename),1,%d)='%s'"
/*
* This is a list of all "things" in Pgsql, which can show up after CREATE or
* DROP; and there is also a query to get a list of them.
@ -525,6 +540,7 @@ static const pgsql_thing_t words_after_create[] = {
{"DATABASE", Query_for_list_of_databases},
{"DICTIONARY", Query_for_list_of_ts_dictionaries, NULL, true},
{"DOMAIN", NULL, &Query_for_list_of_domains},
{"FOREIGN DATA WRAPPER", NULL, NULL},
{"FUNCTION", NULL, &Query_for_list_of_functions},
{"GROUP", Query_for_list_of_roles},
{"LANGUAGE", Query_for_list_of_languages},
@ -536,6 +552,7 @@ static const pgsql_thing_t words_after_create[] = {
{"RULE", "SELECT pg_catalog.quote_ident(rulename) FROM pg_catalog.pg_rules WHERE substring(pg_catalog.quote_ident(rulename),1,%d)='%s'"},
{"SCHEMA", Query_for_list_of_schemas},
{"SEQUENCE", NULL, &Query_for_list_of_sequences},
{"SERVER", Query_for_list_of_servers},
{"TABLE", NULL, &Query_for_list_of_tables},
{"TABLESPACE", Query_for_list_of_tablespaces},
{"TEMP", NULL, NULL}, /* for CREATE TEMP TABLE ... */
@ -545,6 +562,7 @@ static const pgsql_thing_t words_after_create[] = {
{"TYPE", NULL, &Query_for_list_of_datatypes},
{"UNIQUE", NULL, NULL}, /* for CREATE UNIQUE INDEX ... */
{"USER", Query_for_list_of_roles},
{"USER MAPPING FOR", NULL, NULL},
{"VIEW", NULL, &Query_for_list_of_views},
{NULL, NULL, NULL, false} /* end of list */
};
@ -621,7 +639,7 @@ psql_completion(char *text, int start, int end)
static const char *const backslash_commands[] = {
"\\a", "\\connect", "\\C", "\\cd", "\\copy", "\\copyright",
"\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\dD", "\\df",
"\\d", "\\da", "\\db", "\\dc", "\\dC", "\\dd", "\\dD", "\\des", "\\deu", "\\dew", "\\df",
"\\dF", "\\dFd", "\\dFp", "\\dFt", "\\dg", "\\di", "\\dl",
"\\dn", "\\do", "\\dp", "\\ds", "\\dS", "\\dt", "\\dT", "\\dv", "\\du",
"\\e", "\\echo", "\\encoding",
@ -686,9 +704,9 @@ psql_completion(char *text, int start, int end)
pg_strcasecmp(prev3_wd, "TABLE") != 0)
{
static const char *const list_ALTER[] =
{"AGGREGATE", "CONVERSION", "DATABASE", "DOMAIN", "FUNCTION",
"GROUP", "INDEX", "LANGUAGE", "OPERATOR", "ROLE", "SCHEMA", "SEQUENCE", "TABLE",
"TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE", "USER", "VIEW", NULL};
{"AGGREGATE", "CONVERSION", "DATABASE", "DOMAIN", "FOREIGN DATA WRAPPER", "FUNCTION",
"GROUP", "INDEX", "LANGUAGE", "OPERATOR", "ROLE", "SCHEMA", "SERVER", "SEQUENCE", "TABLE",
"TABLESPACE", "TEXT SEARCH", "TRIGGER", "TYPE", "USER", "USER MAPPING FOR", "VIEW", NULL};
COMPLETE_WITH_LIST(list_ALTER);
}
@ -724,6 +742,18 @@ psql_completion(char *text, int start, int end)
COMPLETE_WITH_LIST(list_ALTERDATABASE);
}
/* ALTER FOREIGN DATA WRAPPER <name> */
else if (pg_strcasecmp(prev5_wd, "ALTER") == 0 &&
pg_strcasecmp(prev4_wd, "FOREIGN") == 0 &&
pg_strcasecmp(prev3_wd, "DATA") == 0 &&
pg_strcasecmp(prev2_wd, "WRAPPER") == 0)
{
static const char *const list_ALTER_FDW[] =
{"LIBRARY", "OPTIONS", "OWNER TO", NULL};
COMPLETE_WITH_LIST(list_ALTER_FDW);
}
/* ALTER INDEX <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
pg_strcasecmp(prev2_wd, "INDEX") == 0)
@ -746,6 +776,7 @@ psql_completion(char *text, int start, int end)
/* ALTER USER,ROLE <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
!(pg_strcasecmp(prev2_wd, "USER") == 0 && pg_strcasecmp(prev_wd, "MAPPING") == 0) &&
(pg_strcasecmp(prev2_wd, "USER") == 0 ||
pg_strcasecmp(prev2_wd, "ROLE") == 0))
{
@ -814,6 +845,15 @@ psql_completion(char *text, int start, int end)
COMPLETE_WITH_LIST(list_ALTERSEQUENCE2);
}
/* ALTER SERVER <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
pg_strcasecmp(prev2_wd, "SERVER") == 0)
{
static const char *const list_ALTER_SERVER[] =
{"VERSION", "OPTIONS", "OWNER TO", NULL};
COMPLETE_WITH_LIST(list_ALTER_SERVER);
}
/* ALTER VIEW <name> */
else if (pg_strcasecmp(prev3_wd, "ALTER") == 0 &&
pg_strcasecmp(prev2_wd, "VIEW") == 0)
@ -1213,6 +1253,18 @@ psql_completion(char *text, int start, int end)
pg_strcasecmp(prev_wd, "TEMPLATE") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_template_databases);
/* CREATE FOREIGN DATA WRAPPER */
else if (pg_strcasecmp(prev5_wd, "CREATE") == 0 &&
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");
/* CREATE INDEX */
/* First off we complete CREATE UNIQUE with "INDEX" */
else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
@ -1289,6 +1341,16 @@ psql_completion(char *text, int start, int end)
pg_strcasecmp(prev_wd, "TO") == 0)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tables, NULL);
/* CREATE SERVER <name> */
else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
pg_strcasecmp(prev2_wd, "SERVER") == 0)
{
static const char *const list_CREATE_SERVER[] =
{"TYPE", "VERSION", "FOREIGN DATA WRAPPER", NULL};
COMPLETE_WITH_LIST(list_CREATE_SERVER);
}
/* CREATE TABLE */
/* Complete "CREATE TEMP/TEMPORARY" with the possible temp objects */
else if (pg_strcasecmp(prev2_wd, "CREATE") == 0 &&
@ -1357,6 +1419,7 @@ psql_completion(char *text, int start, int end)
/* CREATE ROLE,USER,GROUP */
else if (pg_strcasecmp(prev3_wd, "CREATE") == 0 &&
!(pg_strcasecmp(prev2_wd, "USER") == 0 && pg_strcasecmp(prev_wd, "MAPPING") == 0) &&
(pg_strcasecmp(prev2_wd, "ROLE") == 0 ||
pg_strcasecmp(prev2_wd, "GROUP") == 0 || pg_strcasecmp(prev2_wd, "USER") == 0))
{
@ -1472,12 +1535,17 @@ psql_completion(char *text, int start, int end)
pg_strcasecmp(prev2_wd, "LANGUAGE") == 0 ||
pg_strcasecmp(prev2_wd, "SCHEMA") == 0 ||
pg_strcasecmp(prev2_wd, "SEQUENCE") == 0 ||
pg_strcasecmp(prev2_wd, "SERVER") == 0 ||
pg_strcasecmp(prev2_wd, "TABLE") == 0 ||
pg_strcasecmp(prev2_wd, "TYPE") == 0 ||
pg_strcasecmp(prev2_wd, "VIEW") == 0)) ||
(pg_strcasecmp(prev4_wd, "DROP") == 0 &&
pg_strcasecmp(prev3_wd, "AGGREGATE") == 0 &&
prev_wd[strlen(prev_wd) - 1] == ')') ||
(pg_strcasecmp(prev5_wd, "DROP") == 0 &&
pg_strcasecmp(prev4_wd, "FOREIGN") == 0 &&
pg_strcasecmp(prev3_wd, "DATA") == 0 &&
pg_strcasecmp(prev2_wd, "WRAPPER") == 0) ||
(pg_strcasecmp(prev5_wd, "DROP") == 0 &&
pg_strcasecmp(prev4_wd, "TEXT") == 0 &&
pg_strcasecmp(prev3_wd, "SEARCH") == 0 &&
@ -1607,6 +1675,14 @@ psql_completion(char *text, int start, int end)
COMPLETE_WITH_LIST(list_FROMIN);
}
/* FOREIGN DATA WRAPPER */
/* applies in ALTER/DROP FDW and in CREATE SERVER */
else if (pg_strcasecmp(prev4_wd, "CREATE") != 0 &&
pg_strcasecmp(prev3_wd, "FOREIGN") == 0 &&
pg_strcasecmp(prev2_wd, "DATA") == 0 &&
pg_strcasecmp(prev_wd, "WRAPPER") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
/* GRANT && REVOKE*/
/* Complete GRANT/REVOKE with a list of privileges */
else if (pg_strcasecmp(prev_wd, "GRANT") == 0 ||
@ -1640,6 +1716,8 @@ psql_completion(char *text, int start, int end)
pg_strcasecmp(prev_wd, "ON") == 0)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsv,
" UNION SELECT 'DATABASE'"
" UNION SELECT 'FOREIGN DATA WRAPPER'"
" UNION SELECT 'FOREIGN SERVER'"
" UNION SELECT 'FUNCTION'"
" UNION SELECT 'LANGUAGE'"
" UNION SELECT 'SCHEMA'"
@ -1759,6 +1837,10 @@ psql_completion(char *text, int start, int end)
else if (pg_strcasecmp(prev_wd, "NOTIFY") == 0)
COMPLETE_WITH_QUERY("SELECT pg_catalog.quote_ident(relname) FROM pg_catalog.pg_listener WHERE substring(pg_catalog.quote_ident(relname),1,%d)='%s'");
/* OPTIONS */
else if (pg_strcasecmp(prev_wd, "OPTIONS") == 0)
COMPLETE_WITH_CONST("(");
/* OWNER TO - complete with available roles */
else if (pg_strcasecmp(prev2_wd, "OWNER") == 0 &&
pg_strcasecmp(prev_wd, "TO") == 0)
@ -2012,6 +2094,32 @@ psql_completion(char *text, int start, int end)
pg_strcasecmp(prev4_wd, "UPDATE") == 0)
COMPLETE_WITH_CONST("=");
/* USER MAPPING */
else if ((pg_strcasecmp(prev3_wd, "ALTER") == 0 ||
pg_strcasecmp(prev3_wd, "CREATE") == 0 ||
pg_strcasecmp(prev3_wd, "DROP") == 0) &&
pg_strcasecmp(prev2_wd, "USER") == 0 &&
pg_strcasecmp(prev_wd, "MAPPING") == 0)
COMPLETE_WITH_CONST("FOR");
else if (pg_strcasecmp(prev4_wd, "CREATE") == 0 &&
pg_strcasecmp(prev3_wd, "USER") == 0 &&
pg_strcasecmp(prev2_wd, "MAPPING") == 0 &&
pg_strcasecmp(prev_wd, "FOR") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_roles);
else if ((pg_strcasecmp(prev4_wd, "ALTER") == 0 ||
pg_strcasecmp(prev4_wd, "DROP") == 0) &&
pg_strcasecmp(prev3_wd, "USER") == 0 &&
pg_strcasecmp(prev2_wd, "MAPPING") == 0 &&
pg_strcasecmp(prev_wd, "FOR") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
else if ((pg_strcasecmp(prev5_wd, "CREATE") == 0 ||
pg_strcasecmp(prev5_wd, "ALTER") == 0 ||
pg_strcasecmp(prev5_wd, "DROP") == 0) &&
pg_strcasecmp(prev4_wd, "USER") == 0 &&
pg_strcasecmp(prev3_wd, "MAPPING") == 0 &&
pg_strcasecmp(prev2_wd, "FOR") == 0)
COMPLETE_WITH_CONST("SERVER");
/*
* VACUUM [ FULL | FREEZE ] [ VERBOSE ] [ table ]
* VACUUM [ FULL | FREEZE ] [ VERBOSE ] ANALYZE [ table [ (column [, ...] ) ] ]
@ -2088,6 +2196,12 @@ psql_completion(char *text, int start, int end)
COMPLETE_WITH_QUERY(Query_for_list_of_tablespaces);
else if (strcmp(prev_wd, "\\dD") == 0)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_domains, NULL);
else if (strcmp(prev_wd, "\\des") == 0 || strcmp(prev_wd, "\\des+") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_servers);
else if (strcmp(prev_wd, "\\deu") == 0 || strcmp(prev_wd, "\\deu+") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_user_mappings);
else if (strcmp(prev_wd, "\\dew") == 0 || strcmp(prev_wd, "\\dew+") == 0)
COMPLETE_WITH_QUERY(Query_for_list_of_fdws);
else if (strcmp(prev_wd, "\\df") == 0 || strcmp(prev_wd, "\\df+") == 0)
COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_functions, NULL);
else if (strcmp(prev_wd, "\\dF") == 0 || strcmp(prev_wd, "\\dF+") == 0)

View File

@ -4,7 +4,7 @@
* "Catalog version number" for PostgreSQL.
*
* The catalog version number is used to flag incompatible changes in
* the PostgreSQL system catalogs. Whenever anyone changes the format of
* the PostgreSQL system catalogs. Whenever anyone changes the format of
* a system catalog relation, or adds, deletes, or modifies standard
* catalog entries in such a way that an updated backend wouldn't work
* with an old database (or vice versa), the catalog version number
@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.511 2008/12/04 17:51:27 petere Exp $
* $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.512 2008/12/19 16:25:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -53,6 +53,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 200812041
#define CATALOG_VERSION_NO 200812191
#endif

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.36 2008/06/08 22:41:04 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.37 2008/12/19 16:25:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -143,6 +143,9 @@ typedef enum ObjectClass
OCLASS_ROLE, /* pg_authid */
OCLASS_DATABASE, /* pg_database */
OCLASS_TBLSPACE, /* pg_tablespace */
OCLASS_FDW, /* pg_foreign_data_wrapper */
OCLASS_FOREIGN_SERVER, /* pg_foreign_server */
OCLASS_USER_MAPPING, /* pg_user_mapping */
MAX_OCLASS /* MUST BE LAST */
} ObjectClass;

View File

@ -8,7 +8,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.103 2008/06/19 00:46:06 alvherre Exp $
* $PostgreSQL: pgsql/src/include/catalog/indexing.h,v 1.104 2008/12/19 16:25:18 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -252,6 +252,24 @@ DECLARE_UNIQUE_INDEX(pg_type_oid_index, 2703, on pg_type using btree(oid oid_ops
DECLARE_UNIQUE_INDEX(pg_type_typname_nsp_index, 2704, on pg_type using btree(typname name_ops, typnamespace oid_ops));
#define TypeNameNspIndexId 2704
DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_oid_index, 112, on pg_foreign_data_wrapper using btree(oid oid_ops));
#define ForeignDataWrapperOidIndexId 112
DECLARE_UNIQUE_INDEX(pg_foreign_data_wrapper_name_index, 548, on pg_foreign_data_wrapper using btree(fdwname name_ops));
#define ForeignDataWrapperNameIndexId 548
DECLARE_UNIQUE_INDEX(pg_foreign_server_oid_index, 113, on pg_foreign_server using btree(oid oid_ops));
#define ForeignServerOidIndexId 113
DECLARE_UNIQUE_INDEX(pg_foreign_server_name_index, 549, on pg_foreign_server using btree(srvname name_ops));
#define ForeignServerNameIndexId 549
DECLARE_UNIQUE_INDEX(pg_user_mapping_oid_index, 174, on pg_user_mapping using btree(oid oid_ops));
#define UserMappingOidIndexId 174
DECLARE_UNIQUE_INDEX(pg_user_mapping_user_server_index, 175, on pg_user_mapping using btree(umuser oid_ops, umserver oid_ops));
#define UserMappingUserServerIndexId 175
/* last step of initialization script: build the indexes declared above */
BUILD_INDICES

View File

@ -0,0 +1,62 @@
/*-------------------------------------------------------------------------
*
* pg_foreign_data_wrapper.h
* definition of the system "foreign-data wrapper" relation (pg_foreign_data_wrapper)
* along with the relation's initial contents.
*
*
* Portions Copyright (c) 1996-2008, 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.1 2008/12/19 16:25:18 petere Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
* information from the DATA() statements.
*
*-------------------------------------------------------------------------
*/
#ifndef PG_FOREIGN_DATA_WRAPPER_H
#define PG_FOREIGN_DATA_WRAPPER_H
#include "catalog/genbki.h"
/* ----------------
* pg_foreign_data_wrapper definition. cpp turns this into
* typedef struct FormData_pg_foreign_data_wrapper
* ----------------
*/
#define ForeignDataWrapperRelationId 2328
CATALOG(pg_foreign_data_wrapper,2328)
{
NameData fdwname; /* foreign-data wrapper name */
Oid fdwowner; /* FDW owner */
/* 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;
/* ----------------
* Form_pg_fdw corresponds to a pointer to a tuple with
* the format of pg_fdw relation.
* ----------------
*/
typedef FormData_pg_foreign_data_wrapper *Form_pg_foreign_data_wrapper;
/* ----------------
* compiler constants for pg_fdw
* ----------------
*/
#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_fdwacl 4
#define Anum_pg_foreign_data_wrapper_fdwoptions 5
#endif /* PG_FOREIGN_DATA_WRAPPER_H */

View File

@ -0,0 +1,65 @@
/*-------------------------------------------------------------------------
*
* pg_foreign_server.h
* definition of the system "foreign server" relation (pg_foreign_server)
*
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_foreign_server.h,v 1.1 2008/12/19 16:25:18 petere Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
* information from the DATA() statements.
*
*-------------------------------------------------------------------------
*/
#ifndef PG_FOREIGN_SERVER_H
#define PG_FOREIGN_SERVER_H
#include "catalog/genbki.h"
/* ----------------
* pg_foreign_server definition. cpp turns this into
* typedef struct FormData_pg_foreign_server
* ----------------
*/
#define ForeignServerRelationId 1417
CATALOG(pg_foreign_server,1417)
{
NameData srvname; /* foreign server name */
Oid srvowner; /* server owner */
Oid srvfdw; /* server FDW */
/*
* VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
*/
text srvtype;
text srvversion;
aclitem srvacl[1]; /* access permissions */
text srvoptions[1]; /* FDW-specific options */
} FormData_pg_foreign_server;
/* ----------------
* Form_pg_foreign_server corresponds to a pointer to a tuple with
* the format of pg_foreign_server relation.
* ----------------
*/
typedef FormData_pg_foreign_server *Form_pg_foreign_server;
/* ----------------
* compiler constants for pg_foreign_server
* ----------------
*/
#define Natts_pg_foreign_server 7
#define Anum_pg_foreign_server_srvname 1
#define Anum_pg_foreign_server_srvowner 2
#define Anum_pg_foreign_server_srvfdw 3
#define Anum_pg_foreign_server_srvtype 4
#define Anum_pg_foreign_server_srvversion 5
#define Anum_pg_foreign_server_srvacl 6
#define Anum_pg_foreign_server_srvoptions 7
#endif /* PG_FOREIGN_SERVER_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.531 2008/12/18 18:20:34 tgl Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.532 2008/12/19 16:25:18 petere Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
@ -3582,6 +3582,32 @@ DESCR("current user privilege on tablespace by tablespace name");
DATA(insert OID = 2395 ( has_tablespace_privilege PGNSP PGUID 12 1 0 0 f f t f s 2 0 16 "26 25" _null_ _null_ _null_ _null_ has_tablespace_privilege_id _null_ _null_ _null_ ));
DESCR("current user privilege on tablespace by tablespace oid");
DATA(insert OID = 3000 ( has_foreign_data_wrapper_privilege PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_name_name _null_ _null_ _null_ ));
DESCR("user privilege on foreign data wrapper by username, foreign data wrapper name");
DATA(insert OID = 3001 ( has_foreign_data_wrapper_privilege PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_name_id _null_ _null_ _null_ ));
DESCR("user privilege on foreign data wrapper by username, foreign data wrapper oid");
DATA(insert OID = 3002 ( has_foreign_data_wrapper_privilege PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_id_name _null_ _null_ _null_ ));
DESCR("user privilege on foreign data wrapper by user oid, foreign data wrapper name");
DATA(insert OID = 3003 ( has_foreign_data_wrapper_privilege PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_id_id _null_ _null_ _null_ ));
DESCR("user privilege on foreign data wrapper by user oid, foreign data wrapper oid");
DATA(insert OID = 3004 ( has_foreign_data_wrapper_privilege PGNSP PGUID 12 1 0 0 f f t f s 2 0 16 "25 25" _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_name _null_ _null_ _null_ ));
DESCR("current user privilege on foreign data wrapper by foreign data wrapper name");
DATA(insert OID = 3005 ( has_foreign_data_wrapper_privilege PGNSP PGUID 12 1 0 0 f f t f s 2 0 16 "26 25" _null_ _null_ _null_ _null_ has_foreign_data_wrapper_privilege_id _null_ _null_ _null_ ));
DESCR("current user privilege on foreign data wrapper by foreign data wrapper oid");
DATA(insert OID = 3006 ( has_server_privilege PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "19 25 25" _null_ _null_ _null_ _null_ has_server_privilege_name_name _null_ _null_ _null_ ));
DESCR("user privilege on server by username, server name");
DATA(insert OID = 3007 ( has_server_privilege PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ has_server_privilege_name_id _null_ _null_ _null_ ));
DESCR("user privilege on server by username, server oid");
DATA(insert OID = 3008 ( has_server_privilege PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "26 25 25" _null_ _null_ _null_ _null_ has_server_privilege_id_name _null_ _null_ _null_ ));
DESCR("user privilege on server by user oid, server name");
DATA(insert OID = 3009 ( has_server_privilege PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "26 26 25" _null_ _null_ _null_ _null_ has_server_privilege_id_id _null_ _null_ _null_ ));
DESCR("user privilege on server by user oid, server oid");
DATA(insert OID = 3010 ( has_server_privilege PGNSP PGUID 12 1 0 0 f f t f s 2 0 16 "25 25" _null_ _null_ _null_ _null_ has_server_privilege_name _null_ _null_ _null_ ));
DESCR("current user privilege on server by server name");
DATA(insert OID = 3011 ( has_server_privilege PGNSP PGUID 12 1 0 0 f f t f s 2 0 16 "26 25" _null_ _null_ _null_ _null_ has_server_privilege_id _null_ _null_ _null_ ));
DESCR("current user privilege on server by server oid");
DATA(insert OID = 2705 ( pg_has_role PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "19 19 25" _null_ _null_ _null_ _null_ pg_has_role_name_name _null_ _null_ _null_ ));
DESCR("user privilege on role by username, role name");
DATA(insert OID = 2706 ( pg_has_role PGNSP PGUID 12 1 0 0 f f t f s 3 0 16 "19 26 25" _null_ _null_ _null_ _null_ pg_has_role_name_id _null_ _null_ _null_ ));
@ -4604,6 +4630,9 @@ DESCR("record greater than or equal");
DATA(insert OID = 2987 ( btrecordcmp PGNSP PGUID 12 1 0 0 f f t f i 2 0 23 "2249 2249" _null_ _null_ _null_ _null_ btrecordcmp _null_ _null_ _null_ ));
DESCR("btree less-equal-greater");
DATA(insert OID = 2998 ( pg_options_to_table PGNSP PGUID 12 1 3 0 f f t t s 1 0 2249 "1009" "{1009,25,25}" "{i,o,o}" "{options_array,option_name,option_value}" _null_ pg_options_to_table _null_ _null_ _null_ ));
DESCR("convert generic options array to name/value table");
/*
* Symbolic values for provolatile column: these indicate whether the result

View File

@ -0,0 +1,58 @@
/*-------------------------------------------------------------------------
*
* pg_user_mapping.h
* definition of the system "user mapping" relation (pg_user_mapping)
*
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_user_mapping.h,v 1.1 2008/12/19 16:25:19 petere Exp $
*
* NOTES
* the genbki.sh script reads this file and generates .bki
* information from the DATA() statements.
*
*-------------------------------------------------------------------------
*/
#ifndef PG_USER_MAPPING_H
#define PG_USER_MAPPING_H
#include "catalog/genbki.h"
/* ----------------
* pg_user_mapping definition. cpp turns this into
* typedef struct FormData_pg_user_mapping
* ----------------
*/
#define UserMappingRelationId 1418
CATALOG(pg_user_mapping,1418)
{
Oid umuser; /* Id of the user, InvalidOid if PUBLIC is wanted */
Oid umserver; /* server of this mapping */
/*
* VARIABLE LENGTH FIELDS start here. These fields may be NULL, too.
*/
text umoptions[1]; /* user mapping options */
} FormData_pg_user_mapping;
/* ----------------
* Form_pg_user_mapping corresponds to a pointer to a tuple with
* the format of pg_user_mapping relation.
* ----------------
*/
typedef FormData_pg_user_mapping *Form_pg_user_mapping;
/* ----------------
* compiler constants for pg_user_mapping
* ----------------
*/
#define Natts_pg_user_mapping 3
#define Anum_pg_user_mapping_umuser 1
#define Anum_pg_user_mapping_umserver 2
#define Anum_pg_user_mapping_umoptions 3
#endif /* PG_USER_MAPPING_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.90 2008/12/04 17:51:27 petere Exp $
* $PostgreSQL: pgsql/src/include/commands/defrem.h,v 1.91 2008/12/19 16:25:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -118,6 +118,22 @@ extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId);
extern text *serialize_deflist(List *deflist);
extern List *deserialize_deflist(Datum txt);
/* commands/foreigncmds.c */
extern void AlterForeignServerOwner(const char *name, Oid newOwnerId);
extern void AlterForeignDataWrapperOwner(const char *name, Oid newOwnerId);
extern void CreateForeignDataWrapper(CreateFdwStmt *stmt);
extern void AlterForeignDataWrapper(AlterFdwStmt *stmt);
extern void RemoveForeignDataWrapper(DropFdwStmt *stmt);
extern void RemoveForeignDataWrapperById(Oid fdwId);
extern void CreateForeignServer(CreateForeignServerStmt *stmt);
extern void AlterForeignServer(AlterForeignServerStmt *stmt);
extern void RemoveForeignServer(DropForeignServerStmt *stmt);
extern void RemoveForeignServerById(Oid srvId);
extern void CreateUserMapping(CreateUserMappingStmt *stmt);
extern void AlterUserMapping(AlterUserMappingStmt *stmt);
extern void RemoveUserMapping(DropUserMappingStmt *stmt);
extern void RemoveUserMappingById(Oid umId);
/* support routines in commands/define.c */
extern char *case_translate_language_name(const char *input);

View File

@ -0,0 +1,101 @@
/*-------------------------------------------------------------------------
*
* foreign.h
* support for foreign-data wrappers, servers and user mappings.
*
*
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
*
* $PostgreSQL: pgsql/src/include/foreign/foreign.h,v 1.1 2008/12/19 16:25:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
#ifndef FOREIGN_H
#define FOREIGN_H
#include "nodes/parsenodes.h"
#include "nodes/pg_list.h"
/* Helper for obtaining username for user mapping */
#define MappingUserName(userid) \
(OidIsValid(userid) ? GetUserNameFromId(userid) : "public")
/*
* Generic option types for validation.
* NB! Thes are treated as flags, so use only powers of two here.
*/
typedef enum {
InvalidOpt = 0,
ServerOpt = 1, /* options applicable to SERVER */
UserMappingOpt = 2, /* options for USER MAPPING */
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 */
List *options; /* fdwoptions as DefElem list */
ForeignDataWrapperLibrary *lib; /* interface to the FDW functions */
} ForeignDataWrapper;
typedef struct ForeignServer
{
Oid serverid; /* server Oid */
Oid fdwid; /* foreign-data wrapper */
Oid owner; /* server owner user Oid */
char *servername; /* name of the server */
char *servertype; /* server type, optional */
char *serverversion; /* server version, optional */
List *options; /* srvoptions as DefElem list */
} ForeignServer;
typedef struct UserMapping
{
Oid userid; /* local user Oid */
Oid serverid; /* server Oid */
List *options; /* useoptions as DefElem list */
} 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);
extern UserMapping *GetUserMapping(Oid userid, Oid serverid);
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,
GenericOptionFlags flags, List *options);
#endif /* FOREIGN_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.63 2008/09/01 20:42:45 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.64 2008/12/19 16:25:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -67,4 +67,6 @@ extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype,
extern DefElem *makeDefElem(char *name, Node *arg);
extern OptionDefElem *makeOptionDefElem(int op, DefElem *def);
#endif /* MAKEFUNC_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.215 2008/11/22 22:47:06 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.216 2008/12/19 16:25:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -325,6 +325,15 @@ typedef enum NodeTag
T_CreateEnumStmt,
T_AlterTSDictionaryStmt,
T_AlterTSConfigurationStmt,
T_CreateFdwStmt,
T_AlterFdwStmt,
T_DropFdwStmt,
T_CreateForeignServerStmt,
T_AlterForeignServerStmt,
T_DropForeignServerStmt,
T_CreateUserMappingStmt,
T_AlterUserMappingStmt,
T_DropUserMappingStmt,
/*
* TAGS FOR PARSE TREE NODES (parsenodes.h)
@ -348,6 +357,7 @@ typedef enum NodeTag
T_IndexElem,
T_Constraint,
T_DefElem,
T_OptionDefElem,
T_RangeTblEntry,
T_SortGroupClause,
T_FkConstraint,

View File

@ -13,7 +13,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.383 2008/12/18 18:20:35 tgl Exp $
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.384 2008/12/19 16:25:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -49,6 +49,13 @@ typedef enum SortByNulls
SORTBY_NULLS_LAST
} SortByNulls;
/* Alter operations for generic options */
typedef enum AlterOptionOp
{
ALTER_OPT_DROP = -1,
ALTER_OPT_SET,
ALTER_OPT_ADD
} AlterOptionOp;
/*
* Grantable rights are encoded so that we can OR them together in a bitmask.
@ -67,7 +74,7 @@ typedef uint32 AclMode; /* a bitmask of privilege bits */
#define ACL_REFERENCES (1<<5)
#define ACL_TRIGGER (1<<6)
#define ACL_EXECUTE (1<<7) /* for functions */
#define ACL_USAGE (1<<8) /* for languages and namespaces */
#define ACL_USAGE (1<<8) /* for languages, namespaces, FDWs, and servers */
#define ACL_CREATE (1<<9) /* for namespaces and databases */
#define ACL_CREATE_TEMP (1<<10) /* for databases */
#define ACL_CONNECT (1<<11) /* for databases */
@ -466,6 +473,17 @@ typedef struct DefElem
Node *arg; /* a (Value *) or a (TypeName *) */
} DefElem;
/*
* Option definition. Used in options definition lists, with optional alter
* operation.
*/
typedef struct OptionDefElem
{
NodeTag type;
AlterOptionOp alter_op; /* Alter operation: ADD/SET/DROP */
DefElem *def; /* The actual definition */
} OptionDefElem;
/*
* LockingClause - raw representation of FOR UPDATE/SHARE options
*
@ -930,6 +948,8 @@ typedef enum ObjectType
OBJECT_CONVERSION,
OBJECT_DATABASE,
OBJECT_DOMAIN,
OBJECT_FDW,
OBJECT_FOREIGN_SERVER,
OBJECT_FUNCTION,
OBJECT_INDEX,
OBJECT_LANGUAGE,
@ -1076,6 +1096,8 @@ typedef enum GrantObjectType
ACL_OBJECT_RELATION, /* table, view */
ACL_OBJECT_SEQUENCE, /* sequence */
ACL_OBJECT_DATABASE, /* database */
ACL_OBJECT_FDW, /* foreign-data wrapper */
ACL_OBJECT_FOREIGN_SERVER, /* foreign server */
ACL_OBJECT_FUNCTION, /* function */
ACL_OBJECT_LANGUAGE, /* procedural language */
ACL_OBJECT_NAMESPACE, /* namespace */
@ -1328,6 +1350,96 @@ typedef struct DropTableSpaceStmt
bool missing_ok; /* skip error if missing? */
} DropTableSpaceStmt;
/* ----------------------
* Create/Drop FOREIGN DATA WRAPPER Statements
* ----------------------
*/
typedef struct CreateFdwStmt
{
NodeTag type;
char *fdwname; /* foreign-data wrapper name */
char *library; /* libray name */
List *options; /* generic options to FDW */
} CreateFdwStmt;
typedef struct AlterFdwStmt
{
NodeTag type;
char *fdwname; /* foreign-data wrapper name */
char *library; /* libray name */
List *options; /* generic options to FDW */
} AlterFdwStmt;
typedef struct DropFdwStmt
{
NodeTag type;
char *fdwname; /* foreign-data wrapper name */
bool missing_ok; /* don't complain if missing */
DropBehavior behavior; /* drop behavior - cascade/restrict */
} DropFdwStmt;
/* ----------------------
* Create/Drop FOREIGN SERVER Statements
* ----------------------
*/
typedef struct CreateForeignServerStmt
{
NodeTag type;
char *servername; /* server name */
char *servertype; /* optional server type */
char *version; /* optional server version */
char *fdwname; /* FDW name */
List *options; /* generic options to server */
} CreateForeignServerStmt;
typedef struct AlterForeignServerStmt
{
NodeTag type;
char *servername; /* server name */
char *version; /* optional server version */
List *options; /* generic options to server */
bool has_version; /* version specified */
} AlterForeignServerStmt;
typedef struct DropForeignServerStmt
{
NodeTag type;
char *servername; /* server name */
bool missing_ok; /* ignore missing servers */
DropBehavior behavior; /* drop behavior - cascade/restrict */
} DropForeignServerStmt;
/* ----------------------
* Create/Drop USER MAPPING Statements
* ----------------------
*/
typedef struct CreateUserMappingStmt
{
NodeTag type;
char *username; /* username or PUBLIC/CURRENT_USER */
char *servername; /* server name */
List *options; /* generic options to server */
} CreateUserMappingStmt;
typedef struct AlterUserMappingStmt
{
NodeTag type;
char *username; /* username or PUBLIC/CURRENT_USER */
char *servername; /* server name */
List *options; /* generic options to server */
} AlterUserMappingStmt;
typedef struct DropUserMappingStmt
{
NodeTag type;
char *username; /* username or PUBLIC/CURRENT_USER */
char *servername; /* server name */
bool missing_ok; /* ignore missing mappings */
} DropUserMappingStmt;
/* ----------------------
* Create/Drop TRIGGER Statements
* ----------------------

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.104 2008/09/08 00:47:41 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/acl.h,v 1.105 2008/12/19 16:25:19 petere Exp $
*
* NOTES
* An ACL array is simply an array of AclItems, representing the union
@ -146,6 +146,8 @@ typedef ArrayType Acl;
#define ACL_ALL_RIGHTS_RELATION (ACL_INSERT|ACL_SELECT|ACL_UPDATE|ACL_DELETE|ACL_TRUNCATE|ACL_REFERENCES|ACL_TRIGGER)
#define ACL_ALL_RIGHTS_SEQUENCE (ACL_USAGE|ACL_SELECT|ACL_UPDATE)
#define ACL_ALL_RIGHTS_DATABASE (ACL_CREATE|ACL_CREATE_TEMP|ACL_CONNECT)
#define ACL_ALL_RIGHTS_FDW (ACL_USAGE)
#define ACL_ALL_RIGHTS_FOREIGN_SERVER (ACL_USAGE)
#define ACL_ALL_RIGHTS_FUNCTION (ACL_EXECUTE)
#define ACL_ALL_RIGHTS_LANGUAGE (ACL_USAGE)
#define ACL_ALL_RIGHTS_NAMESPACE (ACL_USAGE|ACL_CREATE)
@ -184,6 +186,8 @@ typedef enum AclObjectKind
ACL_KIND_TABLESPACE, /* pg_tablespace */
ACL_KIND_TSDICTIONARY, /* pg_ts_dict */
ACL_KIND_TSCONFIGURATION, /* pg_ts_config */
ACL_KIND_FDW, /* pg_foreign_data_wrapper */
ACL_KIND_FOREIGN_SERVER, /* pg_foreign_server */
MAX_ACL_KIND /* MUST BE LAST */
} AclObjectKind;
@ -261,6 +265,10 @@ extern AclMode pg_namespace_aclmask(Oid nsp_oid, Oid roleid,
AclMode mask, AclMaskHow how);
extern AclMode pg_tablespace_aclmask(Oid spc_oid, Oid roleid,
AclMode mask, AclMaskHow how);
extern AclMode pg_foreign_data_wrapper_aclmask(Oid fdw_oid, Oid roleid,
AclMode mask, AclMaskHow how);
extern AclMode pg_foreign_server_aclmask(Oid srv_oid, Oid roleid,
AclMode mask, AclMaskHow how);
extern AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode);
extern AclResult pg_database_aclcheck(Oid db_oid, Oid roleid, AclMode mode);
@ -268,6 +276,8 @@ extern AclResult pg_proc_aclcheck(Oid proc_oid, Oid roleid, AclMode mode);
extern AclResult pg_language_aclcheck(Oid lang_oid, Oid roleid, AclMode mode);
extern AclResult pg_namespace_aclcheck(Oid nsp_oid, Oid roleid, AclMode mode);
extern AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode);
extern AclResult pg_foreign_data_wrapper_aclcheck(Oid fdw_oid, Oid roleid, AclMode mode);
extern AclResult pg_foreign_server_aclcheck(Oid srv_oid, Oid roleid, AclMode mode);
extern void aclcheck_error(AclResult aclerr, AclObjectKind objectkind,
const char *objectname);
@ -286,5 +296,6 @@ extern bool pg_database_ownercheck(Oid db_oid, Oid roleid);
extern bool pg_conversion_ownercheck(Oid conv_oid, Oid roleid);
extern bool pg_ts_dict_ownercheck(Oid dict_oid, Oid roleid);
extern bool pg_ts_config_ownercheck(Oid cfg_oid, Oid roleid);
extern bool pg_foreign_server_ownercheck(Oid srv_oid, Oid roleid);
#endif /* ACL_H */

View File

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.327 2008/12/04 17:51:28 petere Exp $
* $PostgreSQL: pgsql/src/include/utils/builtins.h,v 1.328 2008/12/19 16:25:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -34,6 +34,12 @@ extern Datum has_database_privilege_id_name(PG_FUNCTION_ARGS);
extern Datum has_database_privilege_id_id(PG_FUNCTION_ARGS);
extern Datum has_database_privilege_name(PG_FUNCTION_ARGS);
extern Datum has_database_privilege_id(PG_FUNCTION_ARGS);
extern Datum has_foreign_data_wrapper_privilege_name_name(PG_FUNCTION_ARGS);
extern Datum has_foreign_data_wrapper_privilege_name_id(PG_FUNCTION_ARGS);
extern Datum has_foreign_data_wrapper_privilege_id_name(PG_FUNCTION_ARGS);
extern Datum has_foreign_data_wrapper_privilege_id_id(PG_FUNCTION_ARGS);
extern Datum has_foreign_data_wrapper_privilege_name(PG_FUNCTION_ARGS);
extern Datum has_foreign_data_wrapper_privilege_id(PG_FUNCTION_ARGS);
extern Datum has_function_privilege_name_name(PG_FUNCTION_ARGS);
extern Datum has_function_privilege_name_id(PG_FUNCTION_ARGS);
extern Datum has_function_privilege_id_name(PG_FUNCTION_ARGS);
@ -52,6 +58,12 @@ extern Datum has_schema_privilege_id_name(PG_FUNCTION_ARGS);
extern Datum has_schema_privilege_id_id(PG_FUNCTION_ARGS);
extern Datum has_schema_privilege_name(PG_FUNCTION_ARGS);
extern Datum has_schema_privilege_id(PG_FUNCTION_ARGS);
extern Datum has_server_privilege_name_name(PG_FUNCTION_ARGS);
extern Datum has_server_privilege_name_id(PG_FUNCTION_ARGS);
extern Datum has_server_privilege_id_name(PG_FUNCTION_ARGS);
extern Datum has_server_privilege_id_id(PG_FUNCTION_ARGS);
extern Datum has_server_privilege_name(PG_FUNCTION_ARGS);
extern Datum has_server_privilege_id(PG_FUNCTION_ARGS);
extern Datum has_tablespace_privilege_name_name(PG_FUNCTION_ARGS);
extern Datum has_tablespace_privilege_name_id(PG_FUNCTION_ARGS);
extern Datum has_tablespace_privilege_id_name(PG_FUNCTION_ARGS);

View File

@ -9,7 +9,7 @@
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.72 2008/05/07 01:04:49 tgl Exp $
* $PostgreSQL: pgsql/src/include/utils/syscache.h,v 1.73 2008/12/19 16:25:19 petere Exp $
*
*-------------------------------------------------------------------------
*/
@ -51,6 +51,10 @@ enum SysCacheIdentifier
DATABASEOID,
ENUMOID,
ENUMTYPOIDNAME,
FOREIGNDATAWRAPPERNAME,
FOREIGNDATAWRAPPEROID,
FOREIGNSERVERNAME,
FOREIGNSERVEROID,
INDEXRELID,
LANGNAME,
LANGOID,
@ -76,7 +80,9 @@ enum SysCacheIdentifier
TSTEMPLATENAMENSP,
TSTEMPLATEOID,
TYPENAMENSP,
TYPEOID
TYPEOID,
USERMAPPINGOID,
USERMAPPINGUSERSERVER
};
extern void InitCatalogCache(void);

File diff suppressed because it is too large Load Diff

View File

@ -1313,6 +1313,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
pg_timezone_abbrevs | SELECT pg_timezone_abbrevs.abbrev, pg_timezone_abbrevs.utc_offset, pg_timezone_abbrevs.is_dst FROM pg_timezone_abbrevs() pg_timezone_abbrevs(abbrev, utc_offset, is_dst);
pg_timezone_names | SELECT pg_timezone_names.name, pg_timezone_names.abbrev, pg_timezone_names.utc_offset, pg_timezone_names.is_dst FROM pg_timezone_names() pg_timezone_names(name, abbrev, utc_offset, is_dst);
pg_user | SELECT pg_shadow.usename, pg_shadow.usesysid, pg_shadow.usecreatedb, pg_shadow.usesuper, pg_shadow.usecatupd, '********'::text AS passwd, pg_shadow.valuntil, pg_shadow.useconfig FROM pg_shadow;
pg_user_mappings | SELECT u.oid AS umid, s.oid AS srvid, s.srvname, u.umuser, CASE WHEN (u.umuser = (0)::oid) THEN 'public'::name ELSE a.rolname END AS usename, CASE WHEN (pg_has_role(s.srvowner, 'USAGE'::text) OR has_server_privilege(s.oid, 'USAGE'::text)) THEN u.umoptions ELSE NULL::text[] END AS umoptions FROM ((pg_user_mapping u LEFT JOIN pg_authid a ON ((a.oid = u.umuser))) JOIN pg_foreign_server s ON ((u.umserver = s.oid)));
pg_views | SELECT n.nspname AS schemaname, c.relname AS viewname, pg_get_userbyid(c.relowner) AS viewowner, pg_get_viewdef(c.oid) AS definition FROM (pg_class c LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (c.relkind = 'v'::"char");
rtest_v1 | SELECT rtest_t1.a, rtest_t1.b FROM rtest_t1;
rtest_vcomp | SELECT x.part, (x.size * y.factor) AS size_in_cm FROM rtest_comp x, rtest_unitfact y WHERE (x.unit = y.unit);
@ -1328,7 +1329,7 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem
shoelace_obsolete | SELECT shoelace.sl_name, shoelace.sl_avail, shoelace.sl_color, shoelace.sl_len, shoelace.sl_unit, shoelace.sl_len_cm FROM shoelace WHERE (NOT (EXISTS (SELECT shoe.shoename FROM shoe WHERE (shoe.slcolor = shoelace.sl_color))));
street | SELECT r.name, r.thepath, c.cname FROM ONLY road r, real_city c WHERE (c.outline ## r.thepath);
toyemp | SELECT emp.name, emp.age, emp.location, (12 * emp.salary) AS annualsal FROM emp;
(50 rows)
(51 rows)
SELECT tablename, rulename, definition FROM pg_rules
ORDER BY tablename, rulename;

View File

@ -99,6 +99,8 @@ SELECT relname, relhasindex
pg_depend | t
pg_description | t
pg_enum | t
pg_foreign_data_wrapper | t
pg_foreign_server | t
pg_index | t
pg_inherits | t
pg_language | t
@ -122,6 +124,7 @@ SELECT relname, relhasindex
pg_ts_parser | t
pg_ts_template | t
pg_type | t
pg_user_mapping | t
point_tbl | f
polygon_tbl | t
ramp | f
@ -149,7 +152,7 @@ SELECT relname, relhasindex
timetz_tbl | f
tinterval_tbl | f
varchar_tbl | f
(138 rows)
(141 rows)
--
-- another sanity check: every system catalog that has OIDs should have

View File

@ -1,5 +1,5 @@
# ----------
# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.50 2008/10/31 09:17:16 heikki Exp $
# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.51 2008/12/19 16:25:19 petere Exp $
#
# By convention, we put no more than twenty tests in any one parallel group;
# this limits the number of connections needed to run the tests.
@ -77,7 +77,7 @@ test: misc
# ----------
# Another group of parallel tests
# ----------
test: select_views portals_p2 rules foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts
test: select_views portals_p2 rules foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts foreign_data
# ----------
# Another group of parallel tests

View File

@ -1,4 +1,4 @@
# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.47 2008/10/31 09:17:16 heikki Exp $
# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.48 2008/12/19 16:25:19 petere Exp $
# This should probably be in an order similar to parallel_schedule.
test: boolean
test: char
@ -108,6 +108,7 @@ test: prepare
test: without_oid
test: conversion
test: tsdicts
test: foreign_data
test: truncate
test: alter_table
test: sequence

View File

@ -0,0 +1,396 @@
--
-- Test foreign-data wrapper and server management.
--
-- Clean up in case a prior regression run failed
-- Suppress NOTICE messages when roles don't exist
SET client_min_messages TO 'error';
DROP ROLE IF EXISTS foreign_data_user, regress_test_role, regress_test_role2, regress_test_role_super, regress_test_indirect, unpriviled_role;
RESET client_min_messages;
CREATE ROLE foreign_data_user LOGIN SUPERUSER;
SET SESSION AUTHORIZATION 'foreign_data_user';
CREATE ROLE regress_test_role;
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;
-- 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 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;
\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";
DROP FOREIGN DATA WRAPPER foo;
CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C 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');
\dew+
DROP FOREIGN DATA WRAPPER foo;
SET ROLE regress_test_role;
CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C; -- ERROR
RESET ROLE;
CREATE FOREIGN DATA WRAPPER foo LIBRARY 'postgresql_fdw' LANGUAGE C;
\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';
\dew+
ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '1', b '2');
ALTER FOREIGN DATA WRAPPER foo OPTIONS (SET c '4'); -- ERROR
ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP c); -- ERROR
ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD x '1', DROP x);
\dew+
ALTER FOREIGN DATA WRAPPER foo OPTIONS (DROP a, SET b '3', ADD c '4');
\dew+
ALTER FOREIGN DATA WRAPPER foo OPTIONS (a '2');
ALTER FOREIGN DATA WRAPPER foo OPTIONS (b '4'); -- ERROR
\dew+
SET ROLE regress_test_role;
ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD d '5'); -- ERROR
SET ROLE regress_test_role_super;
ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD d '5');
\dew+
ALTER FOREIGN DATA WRAPPER foo OWNER TO regress_test_role; -- ERROR
ALTER FOREIGN DATA WRAPPER foo OWNER TO regress_test_role_super;
ALTER ROLE regress_test_role_super NOSUPERUSER;
SET ROLE regress_test_role_super;
ALTER FOREIGN DATA WRAPPER foo OPTIONS (ADD e '6'); -- ERROR
RESET ROLE;
\dew+
-- DROP FOREIGN DATA WRAPPER
DROP FOREIGN DATA WRAPPER nonexistent; -- ERROR
DROP FOREIGN DATA WRAPPER IF EXISTS nonexistent;
\dew+
DROP ROLE regress_test_role_super; -- ERROR
SET ROLE regress_test_role_super;
DROP FOREIGN DATA WRAPPER foo; -- ERROR
RESET ROLE;
ALTER ROLE regress_test_role_super SUPERUSER;
DROP FOREIGN DATA WRAPPER foo;
DROP ROLE regress_test_role_super;
\dew+
CREATE FOREIGN DATA WRAPPER foo LIBRARY 'dummy_fdw' LANGUAGE C;
CREATE SERVER s1 FOREIGN DATA WRAPPER foo;
CREATE USER MAPPING FOR current_user SERVER s1;
\dew+
\des+
\deu+
DROP FOREIGN DATA WRAPPER foo; -- ERROR
SET ROLE regress_test_role;
DROP FOREIGN DATA WRAPPER foo CASCADE; -- ERROR
RESET ROLE;
DROP FOREIGN DATA WRAPPER foo CASCADE;
\dew+
\des+
\deu+
-- 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 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');
CREATE SERVER s3 TYPE 'oracle' FOREIGN DATA WRAPPER foo;
CREATE SERVER s4 TYPE 'oracle' FOREIGN DATA WRAPPER foo OPTIONS (host 'a', dbname 'b');
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 "S6" FOREIGN DATA WRAPPER foo OPTIONS (mixed_case_names 'true');
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
CREATE SERVER s8 FOREIGN DATA WRAPPER postgresql OPTIONS (host 'localhost', dbname 's8db');
\des+
SET ROLE regress_test_role;
CREATE SERVER st1 FOREIGN DATA WRAPPER foo; -- ERROR: no usage on FDW
RESET ROLE;
GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_role;
SET ROLE regress_test_role;
CREATE SERVER st1 FOREIGN DATA WRAPPER foo;
RESET ROLE;
\des+
REVOKE USAGE ON FOREIGN DATA WRAPPER foo FROM regress_test_role;
GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_indirect;
SET ROLE regress_test_role;
CREATE SERVER st2 FOREIGN DATA WRAPPER foo; -- ERROR
RESET ROLE;
GRANT regress_test_indirect TO regress_test_role;
SET ROLE regress_test_role;
CREATE SERVER st2 FOREIGN DATA WRAPPER foo;
\des+
RESET ROLE;
REVOKE regress_test_indirect FROM regress_test_role;
-- ALTER SERVER
ALTER SERVER s0; -- ERROR
ALTER SERVER s0 OPTIONS (a '1'); -- ERROR
ALTER SERVER s1 VERSION '1.0' OPTIONS (servername 's1');
ALTER SERVER s2 VERSION '1.1';
ALTER SERVER s3 OPTIONS (tnsname 'orcl', port '1521');
GRANT USAGE ON FOREIGN SERVER s1 TO regress_test_role;
GRANT USAGE ON FOREIGN SERVER s6 TO regress_test_role2 WITH GRANT OPTION;
\des+
SET ROLE regress_test_role;
ALTER SERVER s1 VERSION '1.1'; -- ERROR
ALTER SERVER s1 OWNER TO regress_test_role; -- ERROR
RESET ROLE;
ALTER SERVER s1 OWNER TO regress_test_role;
GRANT regress_test_role2 TO regress_test_role;
SET ROLE regress_test_role;
ALTER SERVER s1 VERSION '1.1';
ALTER SERVER s1 OWNER TO regress_test_role2; -- ERROR
RESET ROLE;
ALTER SERVER s8 OPTIONS (foo '1'); -- ERROR option validation
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
RESET ROLE;
GRANT regress_test_indirect TO regress_test_role;
SET ROLE regress_test_role;
ALTER SERVER s1 OWNER TO regress_test_indirect;
RESET ROLE;
GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_indirect;
SET ROLE regress_test_role;
ALTER SERVER s1 OWNER TO regress_test_indirect;
RESET ROLE;
DROP ROLE regress_test_indirect; -- ERROR
\des+
-- DROP SERVER
DROP SERVER nonexistent; -- ERROR
DROP SERVER IF EXISTS nonexistent;
\des
SET ROLE regress_test_role;
DROP SERVER s2; -- ERROR
DROP SERVER s1;
RESET ROLE;
\des
ALTER SERVER s2 OWNER TO regress_test_role;
SET ROLE regress_test_role;
DROP SERVER s2;
RESET ROLE;
\des
CREATE USER MAPPING FOR current_user SERVER s3;
\deu
DROP SERVER s3; -- ERROR
DROP SERVER s3 CASCADE;
\des
\deu
-- CREATE USER MAPPING
CREATE USER MAPPING FOR baz SERVER s1; -- ERROR
CREATE USER MAPPING FOR current_user SERVER s1; -- ERROR
CREATE USER MAPPING FOR current_user SERVER s4;
CREATE USER MAPPING FOR user SERVER s4; -- ERROR duplicate
CREATE USER MAPPING FOR public SERVER s4 OPTIONS (mapping 'is public');
CREATE USER MAPPING FOR user SERVER s8 OPTIONS (username 'test', password 'secret'); -- ERROR
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;
SET ROLE regress_test_role;
CREATE USER MAPPING FOR current_user SERVER s5;
CREATE USER MAPPING FOR current_user SERVER s6 OPTIONS (username 'test');
CREATE USER MAPPING FOR current_user SERVER s7; -- ERROR
CREATE USER MAPPING FOR public SERVER s8; -- ERROR
RESET ROLE;
CREATE USER MAPPING FOR current_user SERVER "S6" OPTIONS (username 'test_mixed_case');
ALTER SERVER st1 OWNER TO regress_test_indirect;
SET ROLE regress_test_role;
CREATE USER MAPPING FOR current_user SERVER st1 OPTIONS (username 'bob', password 'boo');
CREATE USER MAPPING FOR public SERVER st1;
RESET ROLE;
\deu
-- ALTER USER MAPPING
ALTER USER MAPPING FOR bob SERVER s4 OPTIONS (gotcha 'true'); -- ERROR
ALTER USER MAPPING FOR user SERVER ss4 OPTIONS (gotcha 'true'); -- ERROR
ALTER USER MAPPING FOR public SERVER s5 OPTIONS (gotcha 'true'); -- ERROR
ALTER USER MAPPING FOR current_user SERVER s8 OPTIONS (username 'test'); -- ERROR
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');
ALTER USER MAPPING FOR public SERVER s4 OPTIONS (ADD modified '1'); -- ERROR
ALTER USER MAPPING FOR public SERVER st1 OPTIONS (ADD modified '1');
RESET ROLE;
\deu+
-- DROP USER MAPPING
DROP USER MAPPING FOR bob SERVER s4; -- ERROR
DROP USER MAPPING FOR user SERVER ss4;
DROP USER MAPPING FOR public SERVER s7; -- ERROR
DROP USER MAPPING IF EXISTS FOR bob SERVER s4;
DROP USER MAPPING IF EXISTS FOR user SERVER ss4;
DROP USER MAPPING IF EXISTS FOR public SERVER s7;
CREATE USER MAPPING FOR public SERVER s8;
SET ROLE regress_test_role;
DROP USER MAPPING FOR public SERVER s8; -- ERROR
RESET ROLE;
DROP SERVER s7;
\deu
-- Information schema
SELECT * FROM information_schema.foreign_data_wrappers ORDER BY 1, 2;
SELECT * FROM information_schema.foreign_data_wrapper_options ORDER BY 1, 2, 3;
SELECT * FROM information_schema.foreign_servers ORDER BY 1, 2;
SELECT * FROM information_schema.foreign_server_options ORDER BY 1, 2, 3;
SELECT * FROM information_schema.user_mappings ORDER BY 1, 2, 3;
SELECT * FROM information_schema.user_mapping_options ORDER BY 1, 2, 3, 4;
SELECT * FROM information_schema.usage_privileges WHERE object_type LIKE 'FOREIGN%' ORDER BY 1, 2, 3, 4, 5;
SELECT * FROM information_schema.role_usage_grants WHERE object_type LIKE 'FOREIGN%' ORDER BY 1, 2, 3, 4, 5;
SET ROLE regress_test_role;
SELECT * FROM information_schema.user_mapping_options ORDER BY 1, 2, 3, 4;
SELECT * FROM information_schema.usage_privileges WHERE object_type LIKE 'FOREIGN%' ORDER BY 1, 2, 3, 4, 5;
SELECT * FROM information_schema.role_usage_grants WHERE object_type LIKE 'FOREIGN%' ORDER BY 1, 2, 3, 4, 5;
DROP USER MAPPING FOR current_user SERVER st1;
RESET ROLE;
-- has_foreign_data_wrapper_privilege
SELECT has_foreign_data_wrapper_privilege('regress_test_role',
(SELECT oid FROM pg_foreign_data_wrapper WHERE fdwname='foo'), 'USAGE');
SELECT has_foreign_data_wrapper_privilege('regress_test_role', 'foo', 'USAGE');
SELECT has_foreign_data_wrapper_privilege(
(SELECT oid FROM pg_roles WHERE rolname='regress_test_role'),
(SELECT oid FROM pg_foreign_data_wrapper WHERE fdwname='foo'), 'USAGE');
SELECT has_foreign_data_wrapper_privilege(
(SELECT oid FROM pg_foreign_data_wrapper WHERE fdwname='foo'), 'USAGE');
SELECT has_foreign_data_wrapper_privilege(
(SELECT oid FROM pg_roles WHERE rolname='regress_test_role'), 'foo', 'USAGE');
SELECT has_foreign_data_wrapper_privilege('foo', 'USAGE');
GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_role;
SELECT has_foreign_data_wrapper_privilege('regress_test_role', 'foo', 'USAGE');
-- has_server_privilege
SELECT has_server_privilege('regress_test_role',
(SELECT oid FROM pg_foreign_server WHERE srvname='s8'), 'USAGE');
SELECT has_server_privilege('regress_test_role', 's8', 'USAGE');
SELECT has_server_privilege(
(SELECT oid FROM pg_roles WHERE rolname='regress_test_role'),
(SELECT oid FROM pg_foreign_server WHERE srvname='s8'), 'USAGE');
SELECT has_server_privilege(
(SELECT oid FROM pg_foreign_server WHERE srvname='s8'), 'USAGE');
SELECT has_server_privilege(
(SELECT oid FROM pg_roles WHERE rolname='regress_test_role'), 's8', 'USAGE');
SELECT has_server_privilege('s8', 'USAGE');
GRANT USAGE ON FOREIGN SERVER s8 TO regress_test_role;
SELECT has_server_privilege('regress_test_role', 's8', 'USAGE');
REVOKE USAGE ON FOREIGN SERVER s8 FROM regress_test_role;
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';
-- Privileges
SET ROLE unprivileged_role;
CREATE FOREIGN DATA WRAPPER foobar LIBRARY 'dummy_fdw' LANGUAGE C; -- 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
GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_role; -- ERROR
CREATE SERVER s9 FOREIGN DATA WRAPPER foo; -- ERROR
ALTER SERVER s4 VERSION '0.5'; -- ERROR
ALTER SERVER s4 OWNER TO unprivileged_role; -- ERROR
DROP SERVER s4; -- ERROR
GRANT USAGE ON FOREIGN SERVER s4 TO regress_test_role; -- ERROR
CREATE USER MAPPING FOR public SERVER s4; -- ERROR
ALTER USER MAPPING FOR regress_test_role SERVER s6 OPTIONS (gotcha 'true'); -- ERROR
DROP USER MAPPING FOR regress_test_role SERVER s6; -- ERROR
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
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
GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_role;
CREATE SERVER s9 FOREIGN DATA WRAPPER postgresql;
ALTER SERVER s6 VERSION '0.5'; -- ERROR
DROP SERVER s6; -- ERROR
GRANT USAGE ON FOREIGN SERVER s6 TO regress_test_role; -- ERROR
GRANT USAGE ON FOREIGN SERVER s9 TO regress_test_role;
CREATE USER MAPPING FOR public SERVER s6; -- ERROR
CREATE USER MAPPING FOR public SERVER s9;
ALTER USER MAPPING FOR regress_test_role SERVER s6 OPTIONS (gotcha 'true'); -- ERROR
DROP USER MAPPING FOR regress_test_role SERVER s6; -- ERROR
RESET ROLE;
REVOKE USAGE ON FOREIGN DATA WRAPPER foo FROM unprivileged_role; -- ERROR
REVOKE USAGE ON FOREIGN DATA WRAPPER foo FROM unprivileged_role CASCADE;
SET ROLE unprivileged_role;
GRANT USAGE ON FOREIGN DATA WRAPPER foo TO regress_test_role; -- ERROR
CREATE SERVER s10 FOREIGN DATA WRAPPER foo; -- ERROR
ALTER SERVER s9 VERSION '1.1';
GRANT USAGE ON FOREIGN SERVER s9 TO regress_test_role;
CREATE USER MAPPING FOR current_user SERVER s9;
DROP SERVER s9 CASCADE;
RESET ROLE;
CREATE SERVER s9 FOREIGN DATA WRAPPER foo;
GRANT USAGE ON FOREIGN SERVER s9 TO unprivileged_role;
SET ROLE unprivileged_role;
ALTER SERVER s9 VERSION '1.2'; -- ERROR
GRANT USAGE ON FOREIGN SERVER s9 TO regress_test_role; -- WARNING
CREATE USER MAPPING FOR current_user SERVER s9; -- ERROR
DROP SERVER s9 CASCADE; -- ERROR
RESET ROLE;
-- Cleanup
DROP ROLE regress_test_role; -- ERROR
DROP SERVER s5 CASCADE;
DROP SERVER st1 CASCADE;
DROP SERVER st2;
DROP USER MAPPING FOR regress_test_role SERVER s6;
DROP FOREIGN DATA WRAPPER foo CASCADE;
DROP SERVER s8 CASCADE;
DROP ROLE regress_test_indirect;
DROP ROLE regress_test_role;
DROP ROLE unprivileged_role; -- ERROR
REVOKE ALL ON FOREIGN DATA WRAPPER postgresql FROM unprivileged_role;
DROP ROLE unprivileged_role;
DROP ROLE regress_test_role2;
DROP FOREIGN DATA WRAPPER postgresql CASCADE;
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;
SELECT srvname, srvoptions FROM pg_foreign_server;
SELECT * FROM pg_user_mapping;