foreign_table_privs_v1.patch

text/plain

Filename: foreign_table_privs_v1.patch
Type: text/plain
Part: 0
Message: Re: Foreign table permissions and cloning

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v1
File+
doc/src/sgml/ref/grant.sgml 0 0
doc/src/sgml/ref/revoke.sgml 0 0
src/backend/catalog/aclchk.c 0 0
src/backend/parser/gram.y 0 0
src/test/regress/expected/foreign_data.out 0 0
src/test/regress/sql/foreign_data.sql 0 0
diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml
index 72ecc45..3ad9fab 100644
*** a/doc/src/sgml/ref/grant.sgml
--- b/doc/src/sgml/ref/grant.sgml
*************** GRANT { { SELECT | INSERT | UPDATE | REF
*** 32,37 ****
--- 32,46 ----
      ON [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...]
      TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
  
+ GRANT { SELECT | ALL [ PRIVILEGES ] }
+     ON { FOREIGN TABLE <replaceable class="PARAMETER">foreign_table_name</replaceable> [, ...]
+          | ALL FOREIGN TABLES IN SCHEMA <replaceable class="PARAMETER">schema_name</replaceable> [, ...] }
+     TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+ 
+ GRANT { SELECT | ALL [ PRIVILEGES ] } ( <replaceable class="PARAMETER">column</replaceable> [, ...] )
+     ON FOREIGN TABLE <replaceable class="PARAMETER">foreign_table_name</replaceable> [, ...]
+     TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+ 
  GRANT { { USAGE | SELECT | UPDATE }
      [, ...] | ALL [ PRIVILEGES ] }
      ON { SEQUENCE <replaceable class="PARAMETER">sequence_name</replaceable> [, ...]
*************** GRANT <replaceable class="PARAMETER">rol
*** 81,87 ****
    <para>
     The <command>GRANT</command> command has two basic variants: one
     that grants privileges on a database object (table, column, view, sequence,
!    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.
--- 90,96 ----
    <para>
     The <command>GRANT</command> command has two basic variants: one
     that grants privileges on a database object (table, column, view, sequence,
!    foreign table, 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.
*************** GRANT <replaceable class="PARAMETER">rol
*** 100,107 ****
    <para>
     There is also an option to grant privileges on all objects of the same
     type within one or more schemas.  This functionality is currently supported
!    only for tables, sequences, and functions (but note that <literal>ALL
!    TABLES</> is considered to include views).
    </para>
  
    <para>
--- 109,116 ----
    <para>
     There is also an option to grant privileges on all objects of the same
     type within one or more schemas.  This functionality is currently supported
!    only for tables, sequences, functions and foreign tables (but note that
!    <literal>ALL TABLES</> is considered to include views).
    </para>
  
    <para>
diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml
index 204c986..70702bd 100644
*** a/doc/src/sgml/ref/revoke.sgml
--- b/doc/src/sgml/ref/revoke.sgml
*************** REVOKE [ GRANT OPTION FOR ]
*** 37,42 ****
--- 37,56 ----
      [ CASCADE | RESTRICT ]
  
  REVOKE [ GRANT OPTION FOR ]
+     { SELECT | ALL [ PRIVILEGES ] }
+     ON { FOREIGN TABLE <replaceable class="PARAMETER">foreign_table_name</replaceable> [, ...]
+          | ALL FOREIGN TABLES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }
+     FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+     [ CASCADE | RESTRICT ]
+ 
+ REVOKE [ GRANT OPTION FOR ]
+     { SELECT ( <replaceable class="PARAMETER">column</replaceable> [, ...] )
+       | ALL [ PRIVILEGES ] ( <replaceable class="PARAMETER">column</replaceable> [, ...] ) }
+     ON FOREIGN TABLE <replaceable class="PARAMETER">foreign_table_name</replaceable> [, ...]
+     FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+     [ CASCADE | RESTRICT ]
+ 
+ REVOKE [ GRANT OPTION FOR ]
      { { USAGE | SELECT | UPDATE }
      [, ...] | ALL [ PRIVILEGES ] }
      ON { SEQUENCE <replaceable class="PARAMETER">sequence_name</replaceable> [, ...]
diff --git a/src/backend/catalog/aclchk.c b/src/backend/catalog/aclchk.c
index 693b634..5aa9977 100644
*** a/src/backend/catalog/aclchk.c
--- b/src/backend/catalog/aclchk.c
*************** ExecuteGrantStmt(GrantStmt *stmt)
*** 518,524 ****
  			 */
  			if (privnode->cols)
  			{
! 				if (stmt->objtype != ACL_OBJECT_RELATION)
  					ereport(ERROR,
  							(errcode(ERRCODE_INVALID_GRANT_OPERATION),
  							 errmsg("column privileges are only valid for relations")));
--- 518,525 ----
  			 */
  			if (privnode->cols)
  			{
! 				if (stmt->objtype != ACL_OBJECT_RELATION &&
! 					stmt->objtype != ACL_OBJECT_FOREIGN_TABLE)
  					ereport(ERROR,
  							(errcode(ERRCODE_INVALID_GRANT_OPERATION),
  							 errmsg("column privileges are only valid for relations")));
*************** objectsInSchemaToOids(GrantObjectType ob
*** 729,746 ****
  		switch (objtype)
  		{
  			case ACL_OBJECT_RELATION:
! 				/* Process regular tables, views and foreign tables */
  				objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
  				objects = list_concat(objects, objs);
  				objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
  				objects = list_concat(objects, objs);
- 				objs = getRelationsInNamespace(namespaceId, RELKIND_FOREIGN_TABLE);
- 				objects = list_concat(objects, objs);
  				break;
  			case ACL_OBJECT_SEQUENCE:
  				objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
  				objects = list_concat(objects, objs);
  				break;
  			case ACL_OBJECT_FUNCTION:
  				{
  					ScanKeyData key[1];
--- 730,750 ----
  		switch (objtype)
  		{
  			case ACL_OBJECT_RELATION:
! 				/* Process regular tables and views */
  				objs = getRelationsInNamespace(namespaceId, RELKIND_RELATION);
  				objects = list_concat(objects, objs);
  				objs = getRelationsInNamespace(namespaceId, RELKIND_VIEW);
  				objects = list_concat(objects, objs);
  				break;
  			case ACL_OBJECT_SEQUENCE:
  				objs = getRelationsInNamespace(namespaceId, RELKIND_SEQUENCE);
  				objects = list_concat(objects, objs);
  				break;
+ 			case ACL_OBJECT_FOREIGN_TABLE:
+ 				objs = getRelationsInNamespace(namespaceId,
+ 											   RELKIND_FOREIGN_TABLE);
+ 				objects = list_concat(objects, objs);
+ 				break;
  			case ACL_OBJECT_FUNCTION:
  				{
  					ScanKeyData key[1];
*************** ExecGrant_Relation(InternalGrant *istmt)
*** 1938,1944 ****
  			AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
  
  			if (col_privs->priv_name == NULL)
! 				this_privileges = ACL_ALL_RIGHTS_COLUMN;
  			else
  				this_privileges = string_to_privilege(col_privs->priv_name);
  
--- 1942,1957 ----
  			AccessPriv *col_privs = (AccessPriv *) lfirst(cell_colprivs);
  
  			if (col_privs->priv_name == NULL)
! 			{
! 				/*
! 				 * Columns of a foreign table accept same privilege as foreign
! 				 * table itself.
! 				 */
! 				if (pg_class_tuple->relkind == RELKIND_FOREIGN_TABLE)
! 					this_privileges = ACL_ALL_RIGHTS_FOREIGN_TABLE;
! 				else
! 					this_privileges = ACL_ALL_RIGHTS_COLUMN;
! 			}
  			else
  				this_privileges = string_to_privilege(col_privs->priv_name);
  
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a22ab66..5ad69e0 100644
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
*************** privilege_target:
*** 5463,5468 ****
--- 5463,5476 ----
  					n->objs = $5;
  					$$ = n;
  				}
+ 			| ALL FOREIGN TABLES IN_P SCHEMA name_list
+ 				{
+ 					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ 					n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
+ 					n->objtype = ACL_OBJECT_FOREIGN_TABLE;
+ 					n->objs = $6;
+ 					$$ = n;
+ 				}
  			| ALL FUNCTIONS IN_P SCHEMA name_list
  				{
  					PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
diff --git a/src/test/regress/expected/foreign_data.out b/src/test/regress/expected/foreign_data.out
index c05bcab..4e284a5 100644
*** a/src/test/regress/expected/foreign_data.out
--- b/src/test/regress/expected/foreign_data.out
*************** SELECT * FROM ft1;                      
*** 675,680 ****
--- 675,811 ----
  ERROR:  foreign-data wrapper "dummy" has no handler
  EXPLAIN SELECT * FROM ft1;                                      -- ERROR
  ERROR:  foreign-data wrapper "dummy" has no handler
+ -- GRANT FOREIGN TABLE
+ GRANT SELECT ON FOREIGN TABLE ft1 TO foreign_data_user;
+ GRANT SELECT (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;
+ GRANT INSERT ON FOREIGN TABLE ft1 TO foreign_data_user;         -- ERROR
+ ERROR:  invalid privilege type INSERT for foreign table
+ GRANT INSERT (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;    -- WARNING
+ WARNING:  foreign table "ft1" only supports SELECT column privileges
+ GRANT UPDATE ON FOREIGN TABLE ft1 TO foreign_data_user;         -- ERROR
+ ERROR:  invalid privilege type UPDATE for foreign table
+ GRANT UPDATE (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;    -- WARNING
+ WARNING:  foreign table "ft1" only supports SELECT column privileges
+ GRANT DELETE ON FOREIGN TABLE ft1 TO foreign_data_user;         -- ERROR
+ ERROR:  invalid privilege type DELETE for foreign table
+ GRANT TRUNCATE ON FOREIGN TABLE ft1 TO foreign_data_user;       -- ERROR
+ ERROR:  invalid privilege type TRUNCATE for foreign table
+ GRANT REFERENCES ON FOREIGN TABLE ft1 TO foreign_data_user;     -- ERROR
+ ERROR:  invalid privilege type REFERENCES for foreign table
+ GRANT REFERENCES (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;-- WARNING
+ WARNING:  foreign table "ft1" only supports SELECT column privileges
+ GRANT TRIGGER ON FOREIGN TABLE ft1 TO foreign_data_user;        -- ERROR
+ ERROR:  invalid privilege type TRIGGER for foreign table
+ GRANT USAGE ON FOREIGN TABLE ft1 TO foreign_data_user;          -- ERROR
+ ERROR:  invalid privilege type USAGE for foreign table
+ GRANT EXECUTE ON FOREIGN TABLE ft1 TO foreign_data_user;        -- ERROR
+ ERROR:  invalid privilege type EXECUTE for foreign table
+ -- omitting FOREIGN TABLE
+ GRANT SELECT ON ft1 TO foreign_data_user;
+ GRANT SELECT (c1) ON ft1 TO foreign_data_user;
+ GRANT INSERT ON ft1 TO foreign_data_user;                       -- ERROR
+ ERROR:  foreign table "ft1" only supports SELECT privileges
+ GRANT INSERT (c1) ON ft1 TO foreign_data_user;                  -- WARNING
+ WARNING:  foreign table "ft1" only supports SELECT column privileges
+ GRANT UPDATE ON ft1 TO foreign_data_user;                       -- ERROR
+ ERROR:  foreign table "ft1" only supports SELECT privileges
+ GRANT UPDATE (c1) ON ft1 TO foreign_data_user;                  -- WARNING
+ WARNING:  foreign table "ft1" only supports SELECT column privileges
+ GRANT DELETE ON ft1 TO foreign_data_user;                       -- ERROR
+ ERROR:  foreign table "ft1" only supports SELECT privileges
+ GRANT TRUNCATE ON ft1 TO foreign_data_user;                     -- ERROR
+ ERROR:  foreign table "ft1" only supports SELECT privileges
+ GRANT REFERENCES ON ft1 TO foreign_data_user;                   -- ERROR
+ ERROR:  foreign table "ft1" only supports SELECT privileges
+ GRANT REFERENCES (c1) ON ft1 TO foreign_data_user              ;-- WARNING
+ WARNING:  foreign table "ft1" only supports SELECT column privileges
+ GRANT TRIGGER ON ft1 TO foreign_data_user;                      -- ERROR
+ ERROR:  foreign table "ft1" only supports SELECT privileges
+ GRANT USAGE ON ft1 TO foreign_data_user;                        -- ERROR
+ ERROR:  foreign table "ft1" only supports SELECT privileges
+ GRANT EXECUTE ON ft1 TO foreign_data_user;                      -- ERROR
+ ERROR:  invalid privilege type EXECUTE for relation
+ \dp ft1
+                                                 Access privileges
+  Schema | Name |     Type      |           Access privileges           |        Column access privileges         
+ --------+------+---------------+---------------------------------------+-----------------------------------------
+  public | ft1  | foreign table | foreign_data_user=r/foreign_data_user | c1:                                    +
+         |      |               |                                       |   foreign_data_user=r/foreign_data_user
+ (1 row)
+ 
+ REVOKE SELECT ON FOREIGN TABLE ft1 FROM foreign_data_user;
+ REVOKE SELECT (c1) ON FOREIGN TABLE ft1 FROM foreign_data_user;
+ REVOKE INSERT ON FOREIGN TABLE ft1 FROM foreign_data_user;      -- ERROR
+ ERROR:  invalid privilege type INSERT for foreign table
+ REVOKE UPDATE ON FOREIGN TABLE ft1 FROM foreign_data_user;      -- ERROR
+ ERROR:  invalid privilege type UPDATE for foreign table
+ REVOKE DELETE ON FOREIGN TABLE ft1 FROM foreign_data_user;      -- ERROR
+ ERROR:  invalid privilege type DELETE for foreign table
+ REVOKE TRUNCATE ON FOREIGN TABLE ft1 FROM foreign_data_user;    -- ERROR
+ ERROR:  invalid privilege type TRUNCATE for foreign table
+ REVOKE REFERENCES ON FOREIGN TABLE ft1 FROM foreign_data_user;  -- ERROR
+ ERROR:  invalid privilege type REFERENCES for foreign table
+ REVOKE TRIGGER ON FOREIGN TABLE ft1 FROM foreign_data_user;     -- ERROR
+ ERROR:  invalid privilege type TRIGGER for foreign table
+ REVOKE USAGE ON FOREIGN TABLE ft1 FROM foreign_data_user;       -- ERROR
+ ERROR:  invalid privilege type USAGE for foreign table
+ REVOKE EXECUTE ON FOREIGN TABLE ft1 FROM foreign_data_user;     -- ERROR
+ ERROR:  invalid privilege type EXECUTE for foreign table
+ \dp ft1
+                               Access privileges
+  Schema | Name |     Type      | Access privileges | Column access privileges 
+ --------+------+---------------+-------------------+--------------------------
+  public | ft1  | foreign table |                   | 
+ (1 row)
+ 
+ -- GRANT/REVOKE ALL
+ GRANT ALL ON FOREIGN TABLE ft1 TO foreign_data_user;
+ GRANT ALL (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;
+ \dp ft1
+                                                 Access privileges
+  Schema | Name |     Type      |           Access privileges           |        Column access privileges         
+ --------+------+---------------+---------------------------------------+-----------------------------------------
+  public | ft1  | foreign table | foreign_data_user=r/foreign_data_user | c1:                                    +
+         |      |               |                                       |   foreign_data_user=r/foreign_data_user
+ (1 row)
+ 
+ REVOKE ALL ON FOREIGN TABLE ft1 FROM foreign_data_user;
+ REVOKE ALL (c1) ON FOREIGN TABLE ft1 FROM foreign_data_user;
+ \dp ft1
+                               Access privileges
+  Schema | Name |     Type      | Access privileges | Column access privileges 
+ --------+------+---------------+-------------------+--------------------------
+  public | ft1  | foreign table |                   | 
+ (1 row)
+ 
+ -- GRANT ALL FOREIGN TABLES IN SCHEMA
+ ALTER FOREIGN TABLE ft1 SET SCHEMA foreign_schema;
+ CREATE FOREIGN TABLE foreign_schema.ft2 (c1 int) SERVER sc;
+ GRANT SELECT ON ALL FOREIGN TABLES IN SCHEMA foreign_schema TO foreign_data_user;
+ GRANT SELECT (c1) ON ALL FOREIGN TABLES IN SCHEMA foreign_schema TO foreign_data_user;
+ GRANT UPDATE ON ALL TABLES IN SCHEMA foreign_schema TO foreign_data_user;
+ \dp foreign_schema.ft*
+                                                     Access privileges
+      Schema     | Name |     Type      |           Access privileges           |        Column access privileges         
+ ----------------+------+---------------+---------------------------------------+-----------------------------------------
+  foreign_schema | ft1  | foreign table | foreign_data_user=r/foreign_data_user | c1:                                    +
+                 |      |               |                                       |   foreign_data_user=r/foreign_data_user
+  foreign_schema | ft2  | foreign table | foreign_data_user=r/foreign_data_user | c1:                                    +
+                 |      |               |                                       |   foreign_data_user=r/foreign_data_user
+ (2 rows)
+ 
+ REVOKE SELECT ON ALL FOREIGN TABLES IN SCHEMA foreign_schema FROM foreign_data_user;
+ REVOKE SELECT (c1) ON ALL FOREIGN TABLES IN SCHEMA foreign_schema FROM foreign_data_user;
+ \dp foreign_schema.ft*
+                                   Access privileges
+      Schema     | Name |     Type      | Access privileges | Column access privileges 
+ ----------------+------+---------------+-------------------+--------------------------
+  foreign_schema | ft1  | foreign table |                   | 
+  foreign_schema | ft2  | foreign table |                   | 
+ (2 rows)
+ 
+ ALTER FOREIGN TABLE foreign_schema.ft1 SET SCHEMA public;
+ DROP FOREIGN TABLE foreign_schema.ft2;
  -- ALTER FOREIGN TABLE
  COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
  COMMENT ON FOREIGN TABLE ft1 IS NULL;
diff --git a/src/test/regress/sql/foreign_data.sql b/src/test/regress/sql/foreign_data.sql
index 0d12b98..ddd1cf0 100644
*** a/src/test/regress/sql/foreign_data.sql
--- b/src/test/regress/sql/foreign_data.sql
*************** CREATE INDEX id_ft1_c2 ON ft1 (c2);     
*** 276,281 ****
--- 276,341 ----
  SELECT * FROM ft1;                                              -- ERROR
  EXPLAIN SELECT * FROM ft1;                                      -- ERROR
  
+ -- GRANT FOREIGN TABLE
+ GRANT SELECT ON FOREIGN TABLE ft1 TO foreign_data_user;
+ GRANT SELECT (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;
+ GRANT INSERT ON FOREIGN TABLE ft1 TO foreign_data_user;         -- ERROR
+ GRANT INSERT (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;    -- WARNING
+ GRANT UPDATE ON FOREIGN TABLE ft1 TO foreign_data_user;         -- ERROR
+ GRANT UPDATE (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;    -- WARNING
+ GRANT DELETE ON FOREIGN TABLE ft1 TO foreign_data_user;         -- ERROR
+ GRANT TRUNCATE ON FOREIGN TABLE ft1 TO foreign_data_user;       -- ERROR
+ GRANT REFERENCES ON FOREIGN TABLE ft1 TO foreign_data_user;     -- ERROR
+ GRANT REFERENCES (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;-- WARNING
+ GRANT TRIGGER ON FOREIGN TABLE ft1 TO foreign_data_user;        -- ERROR
+ GRANT USAGE ON FOREIGN TABLE ft1 TO foreign_data_user;          -- ERROR
+ GRANT EXECUTE ON FOREIGN TABLE ft1 TO foreign_data_user;        -- ERROR
+ -- omitting FOREIGN TABLE
+ GRANT SELECT ON ft1 TO foreign_data_user;
+ GRANT SELECT (c1) ON ft1 TO foreign_data_user;
+ GRANT INSERT ON ft1 TO foreign_data_user;                       -- ERROR
+ GRANT INSERT (c1) ON ft1 TO foreign_data_user;                  -- WARNING
+ GRANT UPDATE ON ft1 TO foreign_data_user;                       -- ERROR
+ GRANT UPDATE (c1) ON ft1 TO foreign_data_user;                  -- WARNING
+ GRANT DELETE ON ft1 TO foreign_data_user;                       -- ERROR
+ GRANT TRUNCATE ON ft1 TO foreign_data_user;                     -- ERROR
+ GRANT REFERENCES ON ft1 TO foreign_data_user;                   -- ERROR
+ GRANT REFERENCES (c1) ON ft1 TO foreign_data_user              ;-- WARNING
+ GRANT TRIGGER ON ft1 TO foreign_data_user;                      -- ERROR
+ GRANT USAGE ON ft1 TO foreign_data_user;                        -- ERROR
+ GRANT EXECUTE ON ft1 TO foreign_data_user;                      -- ERROR
+ \dp ft1
+ REVOKE SELECT ON FOREIGN TABLE ft1 FROM foreign_data_user;
+ REVOKE SELECT (c1) ON FOREIGN TABLE ft1 FROM foreign_data_user;
+ REVOKE INSERT ON FOREIGN TABLE ft1 FROM foreign_data_user;      -- ERROR
+ REVOKE UPDATE ON FOREIGN TABLE ft1 FROM foreign_data_user;      -- ERROR
+ REVOKE DELETE ON FOREIGN TABLE ft1 FROM foreign_data_user;      -- ERROR
+ REVOKE TRUNCATE ON FOREIGN TABLE ft1 FROM foreign_data_user;    -- ERROR
+ REVOKE REFERENCES ON FOREIGN TABLE ft1 FROM foreign_data_user;  -- ERROR
+ REVOKE TRIGGER ON FOREIGN TABLE ft1 FROM foreign_data_user;     -- ERROR
+ REVOKE USAGE ON FOREIGN TABLE ft1 FROM foreign_data_user;       -- ERROR
+ REVOKE EXECUTE ON FOREIGN TABLE ft1 FROM foreign_data_user;     -- ERROR
+ \dp ft1
+ -- GRANT/REVOKE ALL
+ GRANT ALL ON FOREIGN TABLE ft1 TO foreign_data_user;
+ GRANT ALL (c1) ON FOREIGN TABLE ft1 TO foreign_data_user;
+ \dp ft1
+ REVOKE ALL ON FOREIGN TABLE ft1 FROM foreign_data_user;
+ REVOKE ALL (c1) ON FOREIGN TABLE ft1 FROM foreign_data_user;
+ \dp ft1
+ -- GRANT ALL FOREIGN TABLES IN SCHEMA
+ ALTER FOREIGN TABLE ft1 SET SCHEMA foreign_schema;
+ CREATE FOREIGN TABLE foreign_schema.ft2 (c1 int) SERVER sc;
+ GRANT SELECT ON ALL FOREIGN TABLES IN SCHEMA foreign_schema TO foreign_data_user;
+ GRANT SELECT (c1) ON ALL FOREIGN TABLES IN SCHEMA foreign_schema TO foreign_data_user;
+ GRANT UPDATE ON ALL TABLES IN SCHEMA foreign_schema TO foreign_data_user;
+ \dp foreign_schema.ft*
+ REVOKE SELECT ON ALL FOREIGN TABLES IN SCHEMA foreign_schema FROM foreign_data_user;
+ REVOKE SELECT (c1) ON ALL FOREIGN TABLES IN SCHEMA foreign_schema FROM foreign_data_user;
+ \dp foreign_schema.ft*
+ ALTER FOREIGN TABLE foreign_schema.ft1 SET SCHEMA public;
+ DROP FOREIGN TABLE foreign_schema.ft2;
+ 
  -- ALTER FOREIGN TABLE
  COMMENT ON FOREIGN TABLE ft1 IS 'foreign table';
  COMMENT ON FOREIGN TABLE ft1 IS NULL;