mirror of
https://github.com/postgres/postgres.git
synced 2025-04-22 23:02:54 +03:00
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:
parent
1eec10a2de
commit
cae565e503
@ -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>
|
||||
|
||||
|
@ -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>
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
132
doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
Normal file
132
doc/src/sgml/ref/alter_foreign_data_wrapper.sgml
Normal 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>
|
123
doc/src/sgml/ref/alter_server.sgml
Normal file
123
doc/src/sgml/ref/alter_server.sgml
Normal 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>
|
119
doc/src/sgml/ref/alter_user_mapping.sgml
Normal file
119
doc/src/sgml/ref/alter_user_mapping.sgml
Normal 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>
|
185
doc/src/sgml/ref/create_foreign_data_wrapper.sgml
Normal file
185
doc/src/sgml/ref/create_foreign_data_wrapper.sgml
Normal 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>
|
140
doc/src/sgml/ref/create_server.sgml
Normal file
140
doc/src/sgml/ref/create_server.sgml
Normal 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>
|
111
doc/src/sgml/ref/create_user_mapping.sgml
Normal file
111
doc/src/sgml/ref/create_user_mapping.sgml
Normal 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>
|
112
doc/src/sgml/ref/drop_foreign_data_wrapper.sgml
Normal file
112
doc/src/sgml/ref/drop_foreign_data_wrapper.sgml
Normal 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>
|
112
doc/src/sgml/ref/drop_server.sgml
Normal file
112
doc/src/sgml/ref/drop_server.sgml
Normal 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>
|
104
doc/src/sgml/ref/drop_user_mapping.sgml
Normal file
104
doc/src/sgml/ref/drop_user_mapping.sgml
Normal 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>
|
@ -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>
|
||||
|
||||
|
@ -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=>
|
||||
</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>
|
||||
|
@ -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> [, ...] ] ) [, ...]
|
||||
|
@ -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;
|
||||
|
@ -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 $@
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 \
|
||||
)
|
||||
|
||||
|
@ -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).
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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);
|
||||
|
1102
src/backend/commands/foreigncmds.c
Normal file
1102
src/backend/commands/foreigncmds.c
Normal file
File diff suppressed because it is too large
Load Diff
25
src/backend/foreign/Makefile
Normal file
25
src/backend/foreign/Makefile
Normal 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
|
27
src/backend/foreign/dummy/Makefile
Normal file
27
src/backend/foreign/dummy/Makefile
Normal 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)
|
24
src/backend/foreign/dummy/dummy_fdw.c
Normal file
24
src/backend/foreign/dummy/dummy_fdw.c
Normal 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.
|
||||
*/
|
389
src/backend/foreign/foreign.c
Normal file
389
src/backend/foreign/foreign.c
Normal 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;
|
||||
}
|
27
src/backend/foreign/postgresql/Makefile
Normal file
27
src/backend/foreign/postgresql/Makefile
Normal 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)
|
123
src/backend/foreign/postgresql/postgresql_fdw.c
Normal file
123
src/backend/foreign/postgresql/postgresql_fdw.c
Normal 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)));
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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},
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
77
src/backend/utils/cache/syscache.c
vendored
77
src/backend/utils/cache/syscache.c
vendored
@ -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
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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 */
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)",
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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"));
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
62
src/include/catalog/pg_foreign_data_wrapper.h
Normal file
62
src/include/catalog/pg_foreign_data_wrapper.h
Normal 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 */
|
65
src/include/catalog/pg_foreign_server.h
Normal file
65
src/include/catalog/pg_foreign_server.h
Normal 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 */
|
@ -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
|
||||
|
58
src/include/catalog/pg_user_mapping.h
Normal file
58
src/include/catalog/pg_user_mapping.h
Normal 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 */
|
@ -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);
|
||||
|
101
src/include/foreign/foreign.h
Normal file
101
src/include/foreign/foreign.h
Normal 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 */
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
* ----------------------
|
||||
|
@ -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 */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
1008
src/test/regress/expected/foreign_data.out
Normal file
1008
src/test/regress/expected/foreign_data.out
Normal file
File diff suppressed because it is too large
Load Diff
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
396
src/test/regress/sql/foreign_data.sql
Normal file
396
src/test/regress/sql/foreign_data.sql
Normal 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;
|
Loading…
x
Reference in New Issue
Block a user