On Thu, Mar 2, 2017 at 10:27 AM, David Steele <da...@pgmasters.net> wrote:

> It looks like this patch is still waiting on an update for tab
> completion in psql.


Hi All,

Sorry about the long delay... It was so simple to add it to tab-complete.c
that is a shame I didn't do it before, very sorry about that.

Attached the new version of the patch that is basically the same as
previously with the addition to tab completion for psql and rebased with
master.

Hope it is enough. Thank you all.

-- 
Matheus de Oliveira
diff --git a/doc/src/sgml/ref/alter_default_privileges.sgml b/doc/src/sgml/ref/alter_default_privileges.sgml
index 04064d3..e3363f8 100644
*** a/doc/src/sgml/ref/alter_default_privileges.sgml
--- b/doc/src/sgml/ref/alter_default_privileges.sgml
***************
*** 46,51 **** GRANT { USAGE | ALL [ PRIVILEGES ] }
--- 46,55 ----
      ON TYPES
      TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
  
+ GRANT { USAGE | CREATE | ALL [ PRIVILEGES ] }
+     ON SCHEMAS
+     TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
+ 
  REVOKE [ GRANT OPTION FOR ]
      { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
      [, ...] | ALL [ PRIVILEGES ] }
***************
*** 71,76 **** REVOKE [ GRANT OPTION FOR ]
--- 75,86 ----
      ON TYPES
      FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
      [ CASCADE | RESTRICT ]
+ 
+ REVOKE [ GRANT OPTION FOR ]
+     { USAGE | CREATE | ALL [ PRIVILEGES ] }
+     ON SCHEMAS
+     FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
+     [ CASCADE | RESTRICT ]
  </synopsis>
   </refsynopsisdiv>
  
***************
*** 81,88 **** REVOKE [ GRANT OPTION FOR ]
     <command>ALTER DEFAULT PRIVILEGES</> allows you to set the privileges
     that will be applied to objects created in the future.  (It does not
     affect privileges assigned to already-existing objects.)  Currently,
!    only the privileges for tables (including views and foreign tables),
!    sequences, functions, and types (including domains) can be altered.
    </para>
  
    <para>
--- 91,99 ----
     <command>ALTER DEFAULT PRIVILEGES</> allows you to set the privileges
     that will be applied to objects created in the future.  (It does not
     affect privileges assigned to already-existing objects.)  Currently,
!    only the privileges for schemas, tables (including views and foreign
!    tables), sequences, functions, and types (including domains) can be
!    altered.
    </para>
  
    <para>
***************
*** 125,130 **** REVOKE [ GRANT OPTION FOR ]
--- 136,143 ----
        are altered for objects later created in that schema.
        If <literal>IN SCHEMA</> is omitted, the global default privileges
        are altered.
+       <literal>IN SCHEMA</> is not allowed when using <literal>ON SCHEMAS</>
+       as schemas can't be nested.
       </para>
      </listitem>
     </varlistentry>
diff --git a/src/backend/catalog/aclchk.c b/src/backeindex d01930f..2d535c2 100644
*** a/src/backend/catalog/aclchk.c
--- b/src/backend/catalog/aclchk.c
***************
*** 959,964 **** ExecAlterDefaultPrivilegesStmt(ParseState *pstate, AlterDefaultPrivilegesStmt *s
--- 959,968 ----
  			all_privileges = ACL_ALL_RIGHTS_TYPE;
  			errormsg = gettext_noop("invalid privilege type %s for type");
  			break;
+ 		case ACL_OBJECT_NAMESPACE:
+ 			all_privileges = ACL_ALL_RIGHTS_NAMESPACE;
+ 			errormsg = gettext_noop("invalid privilege type %s for schema");
+ 			break;
  		default:
  			elog(ERROR, "unrecognized GrantStmt.objtype: %d",
  				 (int) action->objtype);
***************
*** 1146,1151 **** SetDefaultACL(InternalDefaultACL *iacls)
--- 1150,1165 ----
  				this_privileges = ACL_ALL_RIGHTS_TYPE;
  			break;
  
+ 		case ACL_OBJECT_NAMESPACE:
+ 			if (OidIsValid(iacls->nspid))
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_INVALID_GRANT_OPERATION),
+ 						 errmsg("cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS")));
+ 			objtype = DEFACLOBJ_NAMESPACE;
+ 			if (iacls->all_privs && this_privileges == ACL_NO_RIGHTS)
+ 				this_privileges = ACL_ALL_RIGHTS_NAMESPACE;
+ 			break;
+ 
  		default:
  			elog(ERROR, "unrecognized objtype: %d",
  				 (int) iacls->objtype);
***************
*** 1369,1374 **** RemoveRoleFromObjectACL(Oid roleid, Oid classid, Oid objid)
--- 1383,1391 ----
  			case DEFACLOBJ_TYPE:
  				iacls.objtype = ACL_OBJECT_TYPE;
  				break;
+ 			case DEFACLOBJ_NAMESPACE:
+ 				iacls.objtype = ACL_OBJECT_NAMESPACE;
+ 				break;
  			default:
  				/* Shouldn't get here */
  				elog(ERROR, "unexpected default ACL type: %d",
***************
*** 5259,5264 **** get_user_default_acl(GrantObjectType objtype, Oid ownerId, Oid nsp_oid)
--- 5276,5285 ----
  			defaclobjtype = DEFACLOBJ_TYPE;
  			break;
  
+ 		case ACL_OBJECT_NAMESPACE:
+ 			defaclobjtype = DEFACLOBJ_NAMESPACE;
+ 			break;
+ 
  		default:
  			return NULL;
  	}
diff --git a/src/backend/catalog/obindex 2948d64..1eb7930 100644
*** a/src/backend/catalog/objectaddress.c
--- b/src/backend/catalog/objectaddress.c
***************
*** 1843,1853 **** get_object_address_defacl(List *object, bool missing_ok)
  		case DEFACLOBJ_TYPE:
  			objtype_str = "types";
  			break;
  		default:
  			ereport(ERROR,
  					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  				  errmsg("unrecognized default ACL object type %c", objtype),
! 					 errhint("Valid object types are \"r\", \"S\", \"f\", and \"T\".")));
  	}
  
  	/*
--- 1843,1856 ----
  		case DEFACLOBJ_TYPE:
  			objtype_str = "types";
  			break;
+ 		case DEFACLOBJ_NAMESPACE:
+ 			objtype_str = "schemas";
+ 			break;
  		default:
  			ereport(ERROR,
  					(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
  				  errmsg("unrecognized default ACL object type %c", objtype),
! 					 errhint("Valid object types are \"r\", \"S\", \"f\", \"T\" and \"s\".")));
  	}
  
  	/*
***************
*** 3255,3260 **** getObjectDescription(const ObjectAddress *object)
--- 3258,3268 ----
  										 _("default privileges on new types belonging to role %s"),
  							   GetUserNameFromId(defacl->defaclrole, false));
  						break;
+ 					case DEFACLOBJ_NAMESPACE:
+ 						appendStringInfo(&buffer,
+ 										 _("default privileges on new schemas belonging to role %s"),
+ 							   GetUserNameFromId(defacl->defaclrole, false));
+ 						break;
  					default:
  						/* shouldn't get here */
  						appendStringInfo(&buffer,
***************
*** 4762,4767 **** getObjectIdentityParts(const ObjectAddress *object,
--- 4770,4779 ----
  						appendStringInfoString(&buffer,
  											   " on types");
  						break;
+ 					case DEFACLOBJ_NAMESPACE:
+ 						appendStringInfoString(&buffer,
+ 											   " on schemas");
+ 						break;
  				}
  
  				if (objname)
diff --git a/src/backend/catalog/pg_namespindex 5672536..613b963 100644
*** a/src/backend/catalog/pg_namespace.c
--- b/src/backend/catalog/pg_namespace.c
***************
*** 31,40 ****
   * Create a namespace (schema) with the given name and owner OID.
   *
   * If isTemp is true, this schema is a per-backend schema for holding
!  * temporary tables.  Currently, the only effect of that is to prevent it
!  * from being linked as a member of any active extension.  (If someone
!  * does CREATE TEMP TABLE in an extension script, we don't want the temp
!  * schema to become part of the extension.)
   * ---------------
   */
  Oid
--- 31,41 ----
   * Create a namespace (schema) with the given name and owner OID.
   *
   * If isTemp is true, this schema is a per-backend schema for holding
!  * temporary tables.  Currently, it is used to prevent it from being
!  * linked as a member of any active extension.  (If someone does CREATE
!  * TEMP TABLE in an extension script, we don't want the temp schema to
!  * become part of the extension). And to avoid checking for default ACL
!  * for temp namespace (as it is not necessary).
   * ---------------
   */
  Oid
***************
*** 49,54 **** NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
--- 50,56 ----
  	TupleDesc	tupDesc;
  	ObjectAddress myself;
  	int			i;
+ 	Acl			*nspacl;
  
  	/* sanity checks */
  	if (!nspName)
***************
*** 60,65 **** NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
--- 62,73 ----
  				(errcode(ERRCODE_DUPLICATE_SCHEMA),
  				 errmsg("schema \"%s\" already exists", nspName)));
  
+ 	if (!isTemp)
+ 		nspacl = get_user_default_acl(ACL_OBJECT_NAMESPACE, ownerId,
+ 									  InvalidOid);
+ 	else
+ 		nspacl = NULL;
+ 
  	/* initialize nulls and values */
  	for (i = 0; i < Natts_pg_namespace; i++)
  	{
***************
*** 69,75 **** NamespaceCreate(const char *nspName, Oid ownerId, bool isTemp)
  	namestrcpy(&nname, nspName);
  	values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
  	values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
! 	nulls[Anum_pg_namespace_nspacl - 1] = true;
  
  	nspdesc = heap_open(NamespaceRelationId, RowExclusiveLock);
  	tupDesc = nspdesc->rd_att;
--- 77,86 ----
  	namestrcpy(&nname, nspName);
  	values[Anum_pg_namespace_nspname - 1] = NameGetDatum(&nname);
  	values[Anum_pg_namespace_nspowner - 1] = ObjectIdGetDatum(ownerId);
! 	if (nspacl != NULL)
! 		values[Anum_pg_namespace_nspacl - 1] = PointerGetDatum(nspacl);
! 	else
! 		nulls[Anum_pg_namespace_nspacl - 1] = true;
  
  	nspdesc = heap_open(NamespaceRelationId, RowExclusiveLock);
  	tupDesc = nspdesc->rd_att;
diff --git a/src/backend/parser/gram.y b/index 19dd77d..20865c0 100644
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
***************
*** 668,674 **** static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
  	RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP
  	ROW ROWS RULE
  
! 	SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES
  	SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHOW
  	SIMILAR SIMPLE SKIP SLOT SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P
  	START STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P
--- 668,674 ----
  	RESET RESTART RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROLLUP
  	ROW ROWS RULE
  
! 	SAVEPOINT SCHEMA SCHEMAS SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES
  	SERIALIZABLE SERVER SESSION SESSION_USER SET SETS SETOF SHARE SHOW
  	SIMILAR SIMPLE SKIP SLOT SMALLINT SNAPSHOT SOME SQL_P STABLE STANDALONE_P
  	START STATEMENT STATISTICS STDIN STDOUT STORAGE STRICT_P STRIP_P
***************
*** 7035,7040 **** defacl_privilege_target:
--- 7035,7041 ----
  			| FUNCTIONS		{ $$ = ACL_OBJECT_FUNCTION; }
  			| SEQUENCES		{ $$ = ACL_OBJECT_SEQUENCE; }
  			| TYPES_P		{ $$ = ACL_OBJECT_TYPE; }
+ 			| SCHEMAS		{ $$ = ACL_OBJECT_NAMESPACE; }
  		;
  
  
***************
*** 14713,14718 **** unreserved_keyword:
--- 14714,14720 ----
  			| RULE
  			| SAVEPOINT
  			| SCHEMA
+ 			| SCHEMAS
  			| SCROLL
  			| SEARCH
  			| SECOND_P
diff --git a/src/bin/pg_dump/dumindex b41f2b9..c74153a 100644
*** a/src/bin/pg_dump/dumputils.c
--- b/src/bin/pg_dump/dumputils.c
***************
*** 520,526 **** do { \
  		CONVERT_PRIV('X', "EXECUTE");
  	else if (strcmp(type, "LANGUAGE") == 0)
  		CONVERT_PRIV('U', "USAGE");
! 	else if (strcmp(type, "SCHEMA") == 0)
  	{
  		CONVERT_PRIV('C', "CREATE");
  		CONVERT_PRIV('U', "USAGE");
--- 520,528 ----
  		CONVERT_PRIV('X', "EXECUTE");
  	else if (strcmp(type, "LANGUAGE") == 0)
  		CONVERT_PRIV('U', "USAGE");
! 	else if (strcmp(type, "SCHEMA") == 0 ||
! 			 strcmp(type, "SCHEMAS") == 0
! 			)
  	{
  		CONVERT_PRIV('C', "CREATE");
  		CONVERT_PRIV('U', "USAGE");
diff --git a/src/bin/pg_dump/pg_duindex ba34cc1..262f553 100644
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 14295,14300 **** dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
--- 14295,14303 ----
  		case DEFACLOBJ_TYPE:
  			type = "TYPES";
  			break;
+ 		case DEFACLOBJ_NAMESPACE:
+ 			type = "SCHEMAS";
+ 			break;
  		default:
  			/* shouldn't get here */
  			exit_horribly(NULL,
diff --git a/src/bin/psql/descriindex bcf6752..b0f3e5e 100644
*** a/src/bin/psql/describe.c
--- b/src/bin/psql/describe.c
***************
*** 1028,1034 **** listDefaultACLs(const char *pattern)
  	printfPQExpBuffer(&buf,
  			   "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
  					  "  n.nspname AS \"%s\",\n"
! 					  "  CASE d.defaclobjtype WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n"
  					  "  ",
  					  gettext_noop("Owner"),
  					  gettext_noop("Schema"),
--- 1028,1034 ----
  	printfPQExpBuffer(&buf,
  			   "SELECT pg_catalog.pg_get_userbyid(d.defaclrole) AS \"%s\",\n"
  					  "  n.nspname AS \"%s\",\n"
! 					  "  CASE d.defaclobjtype WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' WHEN '%c' THEN '%s' END AS \"%s\",\n"
  					  "  ",
  					  gettext_noop("Owner"),
  					  gettext_noop("Schema"),
***************
*** 1040,1045 **** listDefaultACLs(const char *pattern)
--- 1040,1047 ----
  					  gettext_noop("function"),
  					  DEFACLOBJ_TYPE,
  					  gettext_noop("type"),
+ 					  DEFACLOBJ_NAMESPACE,
+ 					  gettext_noop("schema"),
  					  gettext_noop("Type"));
  
  	printACLColumn(&buf, "d.defaclacl");
diff --git a/src/bin/psql/tab-index f749406..dc2794d 100644
*** a/src/bin/psql/tab-complete.c
--- b/src/bin/psql/tab-complete.c
***************
*** 2796,2802 **** psql_completion(const char *text, int start, int end)
  		 * to the kinds of objects supported.
  		 */
  		if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
! 			COMPLETE_WITH_LIST4("TABLES", "SEQUENCES", "FUNCTIONS", "TYPES");
  		else
  			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
  								   " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
--- 2796,2802 ----
  		 * to the kinds of objects supported.
  		 */
  		if (HeadMatches3("ALTER","DEFAULT","PRIVILEGES"))
! 			COMPLETE_WITH_LIST5("TABLES", "SEQUENCES", "FUNCTIONS", "TYPES", "SCHEMAS");
  		else
  			COMPLETE_WITH_SCHEMA_QUERY(Query_for_list_of_tsvmf,
  								   " UNION SELECT 'ALL FUNCTIONS IN SCHEMA'"
diff --git a/src/include/catalog/pindex 42fb224..78bbeb6 100644
*** a/src/include/catalog/pg_default_acl.h
--- b/src/include/catalog/pg_default_acl.h
***************
*** 70,74 **** typedef FormData_pg_default_acl *Form_pg_default_acl;
--- 70,75 ----
  #define DEFACLOBJ_SEQUENCE		'S'		/* sequence */
  #define DEFACLOBJ_FUNCTION		'f'		/* function */
  #define DEFACLOBJ_TYPE			'T'		/* type */
+ #define DEFACLOBJ_NAMESPACE		'n'		/* namespace */
  
  #endif   /* PG_DEFAULT_ACL_H */
diff --git a/src/include/parser/kwlist.h b/index 6cd36c7..cd21a78 100644
*** a/src/include/parser/kwlist.h
--- b/src/include/parser/kwlist.h
***************
*** 344,349 **** PG_KEYWORD("rows", ROWS, UNRESERVED_KEYWORD)
--- 344,350 ----
  PG_KEYWORD("rule", RULE, UNRESERVED_KEYWORD)
  PG_KEYWORD("savepoint", SAVEPOINT, UNRESERVED_KEYWORD)
  PG_KEYWORD("schema", SCHEMA, UNRESERVED_KEYWORD)
+ PG_KEYWORD("schemas", SCHEMAS, UNRESERVED_KEYWORD)
  PG_KEYWORD("scroll", SCROLL, UNRESERVED_KEYWORD)
  PG_KEYWORD("search", SEARCH, UNRESERVED_KEYWORD)
  PG_KEYWORD("second", SECOND_P, UNRESERVED_KEYWORD)
diff --git a/src/test/regress/expeindex f349980..c6e7031 100644
*** a/src/test/regress/expected/privileges.out
--- b/src/test/regress/expected/privileges.out
***************
*** 1356,1361 **** SELECT has_table_privilege('regress_user1', 'testns.acltest1', 'INSERT'); -- no
--- 1356,1419 ----
  (1 row)
  
  ALTER DEFAULT PRIVILEGES FOR ROLE regress_user1 REVOKE EXECUTE ON FUNCTIONS FROM public;
+ ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT USAGE ON SCHEMAS TO regress_user2; -- error
+ ERROR:  cannot use IN SCHEMA clause when using GRANT/REVOKE ON SCHEMAS
+ ALTER DEFAULT PRIVILEGES GRANT USAGE ON SCHEMAS TO regress_user2;
+ CREATE SCHEMA testns2;
+ SELECT has_schema_privilege('regress_user2', 'testns2', 'USAGE'); -- yes
+  has_schema_privilege 
+ ----------------------
+  t
+ (1 row)
+ 
+ SELECT has_schema_privilege('regress_user2', 'testns2', 'CREATE'); -- no
+  has_schema_privilege 
+ ----------------------
+  f
+ (1 row)
+ 
+ ALTER DEFAULT PRIVILEGES REVOKE USAGE ON SCHEMAS FROM regress_user2;
+ CREATE SCHEMA testns3;
+ SELECT has_schema_privilege('regress_user2', 'testns3', 'USAGE'); -- no
+  has_schema_privilege 
+ ----------------------
+  f
+ (1 row)
+ 
+ SELECT has_schema_privilege('regress_user2', 'testns3', 'CREATE'); -- no
+  has_schema_privilege 
+ ----------------------
+  f
+ (1 row)
+ 
+ ALTER DEFAULT PRIVILEGES GRANT ALL ON SCHEMAS TO regress_user2;
+ CREATE SCHEMA testns4;
+ SELECT has_schema_privilege('regress_user2', 'testns4', 'USAGE'); -- yes
+  has_schema_privilege 
+ ----------------------
+  t
+ (1 row)
+ 
+ SELECT has_schema_privilege('regress_user2', 'testns4', 'CREATE'); -- yes
+  has_schema_privilege 
+ ----------------------
+  t
+ (1 row)
+ 
+ ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM regress_user2;
+ CREATE SCHEMA testns5;
+ SELECT has_schema_privilege('regress_user2', 'testns5', 'USAGE'); -- no
+  has_schema_privilege 
+ ----------------------
+  f
+ (1 row)
+ 
+ SELECT has_schema_privilege('regress_user2', 'testns5', 'CREATE'); -- no
+  has_schema_privilege 
+ ----------------------
+  f
+ (1 row)
+ 
  SET ROLE regress_user1;
  CREATE FUNCTION testns.foo() RETURNS int AS 'select 1' LANGUAGE sql;
  SELECT has_function_privilege('regress_user2', 'testns.foo()', 'EXECUTE'); -- no
***************
*** 1403,1408 **** SELECT count(*)
--- 1461,1470 ----
  
  DROP SCHEMA testns CASCADE;
  NOTICE:  drop cascades to table testns.acltest1
+ DROP SCHEMA testns2 CASCADE;
+ DROP SCHEMA testns3 CASCADE;
+ DROP SCHEMA testns4 CASCADE;
+ DROP SCHEMA testns5 CASCADE;
  SELECT d.*     -- check that entries went away
    FROM pg_default_acl d LEFT JOIN pg_namespace n ON defaclnamespace = n.oid
    WHERE nspname IS NULL AND defaclnamespace != 0;
diff --git a/src/test/regress/sql/privileges.sqindex 166e903..3821595 100644
*** a/src/test/regress/sql/privileges.sql
--- b/src/test/regress/sql/privileges.sql
***************
*** 816,821 **** SELECT has_table_privilege('regress_user1', 'testns.acltest1', 'INSERT'); -- no
--- 816,851 ----
  
  ALTER DEFAULT PRIVILEGES FOR ROLE regress_user1 REVOKE EXECUTE ON FUNCTIONS FROM public;
  
+ ALTER DEFAULT PRIVILEGES IN SCHEMA testns GRANT USAGE ON SCHEMAS TO regress_user2; -- error
+ 
+ ALTER DEFAULT PRIVILEGES GRANT USAGE ON SCHEMAS TO regress_user2;
+ 
+ CREATE SCHEMA testns2;
+ 
+ SELECT has_schema_privilege('regress_user2', 'testns2', 'USAGE'); -- yes
+ SELECT has_schema_privilege('regress_user2', 'testns2', 'CREATE'); -- no
+ 
+ ALTER DEFAULT PRIVILEGES REVOKE USAGE ON SCHEMAS FROM regress_user2;
+ 
+ CREATE SCHEMA testns3;
+ 
+ SELECT has_schema_privilege('regress_user2', 'testns3', 'USAGE'); -- no
+ SELECT has_schema_privilege('regress_user2', 'testns3', 'CREATE'); -- no
+ 
+ ALTER DEFAULT PRIVILEGES GRANT ALL ON SCHEMAS TO regress_user2;
+ 
+ CREATE SCHEMA testns4;
+ 
+ SELECT has_schema_privilege('regress_user2', 'testns4', 'USAGE'); -- yes
+ SELECT has_schema_privilege('regress_user2', 'testns4', 'CREATE'); -- yes
+ 
+ ALTER DEFAULT PRIVILEGES REVOKE ALL ON SCHEMAS FROM regress_user2;
+ 
+ CREATE SCHEMA testns5;
+ 
+ SELECT has_schema_privilege('regress_user2', 'testns5', 'USAGE'); -- no
+ SELECT has_schema_privilege('regress_user2', 'testns5', 'CREATE'); -- no
+ 
  SET ROLE regress_user1;
  
  CREATE FUNCTION testns.foo() RETURNS int AS 'select 1' LANGUAGE sql;
***************
*** 853,858 **** SELECT count(*)
--- 883,892 ----
    WHERE nspname = 'testns';
  
  DROP SCHEMA testns CASCADE;
+ DROP SCHEMA testns2 CASCADE;
+ DROP SCHEMA testns3 CASCADE;
+ DROP SCHEMA testns4 CASCADE;
+ DROP SCHEMA testns5 CASCADE;
  
  SELECT d.*     -- check that entries went away
    FROM pg_default_acl d LEFT JOIN pg_namespace n ON defaclnamespace = n.oid
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to