<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.78 2009/10/05 19:24:34 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/grant.sgml,v 1.79 2009/10/12 20:39:39 tgl Exp $
PostgreSQL documentation
-->
<synopsis>
GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[,...] | ALL [ PRIVILEGES ] }
- ON [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...]
+ ON { [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...]
+ | ALL TABLES IN SCHEMA <replaceable class="PARAMETER">schema_name</replaceable> [, ...] }
TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { { SELECT | INSERT | UPDATE | REFERENCES } ( <replaceable class="PARAMETER">column</replaceable> [, ...] )
GRANT { { USAGE | SELECT | UPDATE }
[,...] | ALL [ PRIVILEGES ] }
- ON SEQUENCE <replaceable class="PARAMETER">sequence_name</replaceable> [, ...]
+ ON { SEQUENCE <replaceable class="PARAMETER">sequence_name</replaceable> [, ...]
+ | ALL SEQUENCES IN SCHEMA <replaceable class="PARAMETER">schema_name</replaceable> [, ...] }
TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { { CREATE | CONNECT | TEMPORARY | TEMP } [,...] | ALL [ PRIVILEGES ] }
TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { EXECUTE | ALL [ PRIVILEGES ] }
- ON FUNCTION <replaceable>function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) [, ...]
+ ON { FUNCTION <replaceable>function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) [, ...]
+ | ALL FUNCTIONS IN SCHEMA <replaceable class="PARAMETER">schema_name</replaceable> [, ...] }
TO { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...] [ WITH GRANT OPTION ]
GRANT { USAGE | ALL [ PRIVILEGES ] }
to those already granted, if any.
</para>
+ <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>
The key word <literal>PUBLIC</literal> indicates that the
privileges are to be granted to all roles, including those that might
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.52 2009/09/19 10:23:27 petere Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/revoke.sgml,v 1.53 2009/10/12 20:39:39 tgl Exp $
PostgreSQL documentation
-->
REVOKE [ GRANT OPTION FOR ]
{ { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER }
[,...] | ALL [ PRIVILEGES ] }
- ON [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...]
+ ON { [ TABLE ] <replaceable class="PARAMETER">table_name</replaceable> [, ...]
+ | ALL TABLES IN SCHEMA <replaceable>schema_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> [, ...]
+ ON { SEQUENCE <replaceable class="PARAMETER">sequence_name</replaceable> [, ...]
+ | ALL SEQUENCES IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }
FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
REVOKE [ GRANT OPTION FOR ]
{ EXECUTE | ALL [ PRIVILEGES ] }
- ON FUNCTION <replaceable>function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) [, ...]
+ ON { FUNCTION <replaceable>function_name</replaceable> ( [ [ <replaceable class="parameter">argmode</replaceable> ] [ <replaceable class="parameter">arg_name</replaceable> ] <replaceable class="parameter">arg_type</replaceable> [, ...] ] ) [, ...]
+ | ALL FUNCTIONS IN SCHEMA <replaceable>schema_name</replaceable> [, ...] }
FROM { [ GROUP ] <replaceable class="PARAMETER">role_name</replaceable> | PUBLIC } [, ...]
[ CASCADE | RESTRICT ]
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.155 2009/10/05 19:24:35 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/catalog/aclchk.c,v 1.156 2009/10/12 20:39:39 tgl Exp $
*
* NOTES
* See acl.h.
static void SetDefaultACL(InternalDefaultACL *iacls);
static List *objectNamesToOids(GrantObjectType objtype, List *objnames);
+static List *objectsInSchemaToOids(GrantObjectType objtype, List *nspnames);
+static List *getRelationsInNamespace(Oid namespaceId, char relkind);
static void expand_col_privileges(List *colnames, Oid table_oid,
AclMode this_privileges,
AclMode *col_privileges,
*/
istmt.is_grant = stmt->is_grant;
istmt.objtype = stmt->objtype;
- istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
+
+ /* Collect the OIDs of the target objects */
+ switch (stmt->targtype)
+ {
+ case ACL_TARGET_OBJECT:
+ istmt.objects = objectNamesToOids(stmt->objtype, stmt->objects);
+ break;
+ case ACL_TARGET_ALL_IN_SCHEMA:
+ istmt.objects = objectsInSchemaToOids(stmt->objtype, stmt->objects);
+ break;
+ /* ACL_TARGET_DEFAULTS should not be seen here */
+ default:
+ elog(ERROR, "unrecognized GrantStmt.targtype: %d",
+ (int) stmt->targtype);
+ }
+
/* all_privs to be filled below */
/* privileges to be filled below */
istmt.col_privs = NIL; /* may get filled below */
return objects;
}
+/*
+ * objectsInSchemaToOids
+ *
+ * Find all objects of a given type in specified schemas, and make a list
+ * of their Oids. We check USAGE privilege on the schemas, but there is
+ * no privilege checking on the individual objects here.
+ */
+static List *
+objectsInSchemaToOids(GrantObjectType objtype, List *nspnames)
+{
+ List *objects = NIL;
+ ListCell *cell;
+
+ foreach(cell, nspnames)
+ {
+ char *nspname = strVal(lfirst(cell));
+ Oid namespaceId;
+ List *objs;
+
+ namespaceId = LookupExplicitNamespace(nspname);
+
+ switch (objtype)
+ {
+ case ACL_OBJECT_RELATION:
+ /* Process both 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_FUNCTION:
+ {
+ ScanKeyData key[1];
+ Relation rel;
+ HeapScanDesc scan;
+ HeapTuple tuple;
+
+ ScanKeyInit(&key[0],
+ Anum_pg_proc_pronamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(namespaceId));
+
+ rel = heap_open(ProcedureRelationId, AccessShareLock);
+ scan = heap_beginscan(rel, SnapshotNow, 1, key);
+
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ objects = lappend_oid(objects, HeapTupleGetOid(tuple));
+ }
+
+ heap_endscan(scan);
+ heap_close(rel, AccessShareLock);
+ }
+ break;
+ default:
+ /* should not happen */
+ elog(ERROR, "unrecognized GrantStmt.objtype: %d",
+ (int) objtype);
+ }
+ }
+
+ return objects;
+}
+
+/*
+ * getRelationsInNamespace
+ *
+ * Return Oid list of relations in given namespace filtered by relation kind
+ */
+static List *
+getRelationsInNamespace(Oid namespaceId, char relkind)
+{
+ List *relations = NIL;
+ ScanKeyData key[2];
+ Relation rel;
+ HeapScanDesc scan;
+ HeapTuple tuple;
+
+ ScanKeyInit(&key[0],
+ Anum_pg_class_relnamespace,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(namespaceId));
+ ScanKeyInit(&key[1],
+ Anum_pg_class_relkind,
+ BTEqualStrategyNumber, F_CHAREQ,
+ CharGetDatum(relkind));
+
+ rel = heap_open(RelationRelationId, AccessShareLock);
+ scan = heap_beginscan(rel, SnapshotNow, 2, key);
+
+ while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
+ {
+ relations = lappend_oid(relations, HeapTupleGetOid(tuple));
+ }
+
+ heap_endscan(scan);
+ heap_close(rel, AccessShareLock);
+
+ return relations;
+}
+
+
/*
* ALTER DEFAULT PRIVILEGES statement
*/
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.445 2009/10/12 19:49:24 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.446 2009/10/12 20:39:39 tgl Exp $
*
*-------------------------------------------------------------------------
*/
GrantStmt *newnode = makeNode(GrantStmt);
COPY_SCALAR_FIELD(is_grant);
+ COPY_SCALAR_FIELD(targtype);
COPY_SCALAR_FIELD(objtype);
COPY_NODE_FIELD(objects);
COPY_NODE_FIELD(privileges);
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.367 2009/10/12 19:49:24 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.368 2009/10/12 20:39:40 tgl Exp $
*
*-------------------------------------------------------------------------
*/
_equalGrantStmt(GrantStmt *a, GrantStmt *b)
{
COMPARE_SCALAR_FIELD(is_grant);
+ COMPARE_SCALAR_FIELD(targtype);
COMPARE_SCALAR_FIELD(objtype);
COMPARE_NODE_FIELD(objects);
COMPARE_NODE_FIELD(privileges);
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.683 2009/10/12 19:49:24 adunstan Exp $
+ * $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.684 2009/10/12 20:39:41 tgl Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
/* Private struct for the result of privilege_target production */
typedef struct PrivTarget
{
+ GrantTargetType targtype;
GrantObjectType objtype;
List *objs;
} PrivTarget;
EXCLUDING EXCLUSIVE EXECUTE EXISTS EXPLAIN EXTERNAL EXTRACT
FALSE_P FAMILY FETCH FIRST_P FLOAT_P FOLLOWING FOR FORCE FOREIGN FORWARD
- FREEZE FROM FULL FUNCTION
+ FREEZE FROM FULL FUNCTION FUNCTIONS
GLOBAL GRANT GRANTED GREATEST GROUP_P
RELATIVE_P RELEASE RENAME REPEATABLE REPLACE REPLICA RESET RESTART
RESTRICT RETURNING RETURNS REVOKE RIGHT ROLE ROLLBACK ROW ROWS RULE
- SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE
+ SAVEPOINT SCHEMA SCROLL SEARCH SECOND_P SECURITY SELECT SEQUENCE SEQUENCES
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
- TABLE TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN TIME TIMESTAMP
+ TABLE TABLES TABLESPACE TEMP TEMPLATE TEMPORARY TEXT_P THEN TIME TIMESTAMP
TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
TRUNCATE TRUSTED TYPE_P
GrantStmt *n = makeNode(GrantStmt);
n->is_grant = true;
n->privileges = $2;
+ n->targtype = ($4)->targtype;
n->objtype = ($4)->objtype;
n->objects = ($4)->objs;
n->grantees = $6;
n->is_grant = false;
n->grant_option = false;
n->privileges = $2;
+ n->targtype = ($4)->targtype;
n->objtype = ($4)->objtype;
n->objects = ($4)->objs;
n->grantees = $6;
n->is_grant = false;
n->grant_option = true;
n->privileges = $5;
+ n->targtype = ($7)->targtype;
n->objtype = ($7)->objtype;
n->objects = ($7)->objs;
n->grantees = $9;
qualified_name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_RELATION;
n->objs = $1;
$$ = n;
| TABLE qualified_name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_RELATION;
n->objs = $2;
$$ = n;
| SEQUENCE qualified_name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_SEQUENCE;
n->objs = $2;
$$ = n;
| FOREIGN DATA_P WRAPPER name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_FDW;
n->objs = $4;
$$ = n;
| FOREIGN SERVER name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_FOREIGN_SERVER;
n->objs = $3;
$$ = n;
| FUNCTION function_with_argtypes_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_FUNCTION;
n->objs = $2;
$$ = n;
| DATABASE name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_DATABASE;
n->objs = $2;
$$ = n;
| LANGUAGE name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_LANGUAGE;
n->objs = $2;
$$ = n;
| SCHEMA name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_NAMESPACE;
n->objs = $2;
$$ = n;
| TABLESPACE name_list
{
PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_OBJECT;
n->objtype = ACL_OBJECT_TABLESPACE;
n->objs = $2;
$$ = n;
}
+ | ALL TABLES IN_P SCHEMA name_list
+ {
+ PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
+ n->objtype = ACL_OBJECT_RELATION;
+ n->objs = $5;
+ $$ = n;
+ }
+ | ALL SEQUENCES IN_P SCHEMA name_list
+ {
+ PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
+ n->objtype = ACL_OBJECT_SEQUENCE;
+ n->objs = $5;
+ $$ = n;
+ }
+ | ALL FUNCTIONS IN_P SCHEMA name_list
+ {
+ PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget));
+ n->targtype = ACL_TARGET_ALL_IN_SCHEMA;
+ n->objtype = ACL_OBJECT_FUNCTION;
+ n->objs = $5;
+ $$ = n;
+ }
;
GrantStmt *n = makeNode(GrantStmt);
n->is_grant = true;
n->privileges = $2;
+ n->targtype = ACL_TARGET_DEFAULTS;
n->objtype = $4;
n->objects = NIL;
n->grantees = $6;
n->is_grant = false;
n->grant_option = false;
n->privileges = $2;
+ n->targtype = ACL_TARGET_DEFAULTS;
n->objtype = $4;
n->objects = NIL;
n->grantees = $6;
n->is_grant = false;
n->grant_option = true;
n->privileges = $5;
+ n->targtype = ACL_TARGET_DEFAULTS;
n->objtype = $7;
n->objects = NIL;
n->grantees = $9;
| FORCE
| FORWARD
| FUNCTION
+ | FUNCTIONS
| GLOBAL
| GRANTED
| HANDLER
| SECOND_P
| SECURITY
| SEQUENCE
+ | SEQUENCES
| SERIALIZABLE
| SERVER
| SESSION
| SUPERUSER_P
| SYSID
| SYSTEM_P
+ | TABLES
| TABLESPACE
| TEMP
| TEMPLATE
* Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.407 2009/10/12 19:49:24 adunstan Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.408 2009/10/12 20:39:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* Grant|Revoke Statement
* ----------------------
*/
+typedef enum GrantTargetType
+{
+ ACL_TARGET_OBJECT, /* grant on specific named object(s) */
+ ACL_TARGET_ALL_IN_SCHEMA, /* grant on all objects in given schema(s) */
+ ACL_TARGET_DEFAULTS /* ALTER DEFAULT PRIVILEGES */
+} GrantTargetType;
+
typedef enum GrantObjectType
{
ACL_OBJECT_COLUMN, /* column */
{
NodeTag type;
bool is_grant; /* true = GRANT, false = REVOKE */
+ GrantTargetType targtype; /* type of the grant target */
GrantObjectType objtype; /* kind of object being operated on */
List *objects; /* list of RangeVar nodes, FuncWithArgs nodes,
* or plain names (as Value strings) */
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/include/parser/kwlist.h,v 1.4 2009/10/12 19:49:24 adunstan Exp $
+ * $PostgreSQL: pgsql/src/include/parser/kwlist.h,v 1.5 2009/10/12 20:39:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
PG_KEYWORD("from", FROM, RESERVED_KEYWORD)
PG_KEYWORD("full", FULL, TYPE_FUNC_NAME_KEYWORD)
PG_KEYWORD("function", FUNCTION, UNRESERVED_KEYWORD)
+PG_KEYWORD("functions", FUNCTIONS, UNRESERVED_KEYWORD)
PG_KEYWORD("global", GLOBAL, UNRESERVED_KEYWORD)
PG_KEYWORD("grant", GRANT, RESERVED_KEYWORD)
PG_KEYWORD("granted", GRANTED, UNRESERVED_KEYWORD)
PG_KEYWORD("security", SECURITY, UNRESERVED_KEYWORD)
PG_KEYWORD("select", SELECT, RESERVED_KEYWORD)
PG_KEYWORD("sequence", SEQUENCE, UNRESERVED_KEYWORD)
+PG_KEYWORD("sequences", SEQUENCES, UNRESERVED_KEYWORD)
PG_KEYWORD("serializable", SERIALIZABLE, UNRESERVED_KEYWORD)
PG_KEYWORD("server", SERVER, UNRESERVED_KEYWORD)
PG_KEYWORD("session", SESSION, UNRESERVED_KEYWORD)
PG_KEYWORD("sysid", SYSID, UNRESERVED_KEYWORD)
PG_KEYWORD("system", SYSTEM_P, UNRESERVED_KEYWORD)
PG_KEYWORD("table", TABLE, RESERVED_KEYWORD)
+PG_KEYWORD("tables", TABLES, UNRESERVED_KEYWORD)
PG_KEYWORD("tablespace", TABLESPACE, UNRESERVED_KEYWORD)
PG_KEYWORD("temp", TEMP, UNRESERVED_KEYWORD)
PG_KEYWORD("template", TEMPLATE, UNRESERVED_KEYWORD)
--
-- Clean up in case a prior regression run failed
-- Suppress NOTICE messages when users/groups don't exist
-SET client_min_messages TO 'error';
+SET client_min_messages TO 'warning';
DROP ROLE IF EXISTS regressgroup1;
DROP ROLE IF EXISTS regressgroup2;
DROP ROLE IF EXISTS regressuser1;
------------+-----------------+---------------+-----------
(0 rows)
+-- Grant on all objects of given type in a schema
+\c -
+CREATE SCHEMA testns;
+CREATE TABLE testns.t1 (f1 int);
+CREATE TABLE testns.t2 (f1 int);
+SELECT has_table_privilege('regressuser1', 'testns.t1', 'SELECT'); -- false
+ has_table_privilege
+---------------------
+ f
+(1 row)
+
+GRANT ALL ON ALL TABLES IN SCHEMA testns TO regressuser1;
+SELECT has_table_privilege('regressuser1', 'testns.t1', 'SELECT'); -- true
+ has_table_privilege
+---------------------
+ t
+(1 row)
+
+SELECT has_table_privilege('regressuser1', 'testns.t2', 'SELECT'); -- true
+ has_table_privilege
+---------------------
+ t
+(1 row)
+
+REVOKE ALL ON ALL TABLES IN SCHEMA testns FROM regressuser1;
+SELECT has_table_privilege('regressuser1', 'testns.t1', 'SELECT'); -- false
+ has_table_privilege
+---------------------
+ f
+(1 row)
+
+SELECT has_table_privilege('regressuser1', 'testns.t2', 'SELECT'); -- false
+ has_table_privilege
+---------------------
+ f
+(1 row)
+
+CREATE FUNCTION testns.testfunc(int) RETURNS int AS 'select 3 * $1;' LANGUAGE sql;
+SELECT has_function_privilege('regressuser1', 'testns.testfunc(int)', 'EXECUTE'); -- true by default
+ has_function_privilege
+------------------------
+ t
+(1 row)
+
+REVOKE ALL ON ALL FUNCTIONS IN SCHEMA testns FROM PUBLIC;
+SELECT has_function_privilege('regressuser1', 'testns.testfunc(int)', 'EXECUTE'); -- false
+ has_function_privilege
+------------------------
+ f
+(1 row)
+
+SET client_min_messages TO 'warning';
+DROP SCHEMA testns CASCADE;
+RESET client_min_messages;
-- clean up
\c
drop sequence x_seq;
-- Clean up in case a prior regression run failed
-- Suppress NOTICE messages when users/groups don't exist
-SET client_min_messages TO 'error';
+SET client_min_messages TO 'warning';
DROP ROLE IF EXISTS regressgroup1;
DROP ROLE IF EXISTS regressgroup2;
FROM pg_default_acl d LEFT JOIN pg_namespace n ON defaclnamespace = n.oid
WHERE nspname IS NULL AND defaclnamespace != 0;
+
+-- Grant on all objects of given type in a schema
+\c -
+
+CREATE SCHEMA testns;
+CREATE TABLE testns.t1 (f1 int);
+CREATE TABLE testns.t2 (f1 int);
+
+SELECT has_table_privilege('regressuser1', 'testns.t1', 'SELECT'); -- false
+
+GRANT ALL ON ALL TABLES IN SCHEMA testns TO regressuser1;
+
+SELECT has_table_privilege('regressuser1', 'testns.t1', 'SELECT'); -- true
+SELECT has_table_privilege('regressuser1', 'testns.t2', 'SELECT'); -- true
+
+REVOKE ALL ON ALL TABLES IN SCHEMA testns FROM regressuser1;
+
+SELECT has_table_privilege('regressuser1', 'testns.t1', 'SELECT'); -- false
+SELECT has_table_privilege('regressuser1', 'testns.t2', 'SELECT'); -- false
+
+CREATE FUNCTION testns.testfunc(int) RETURNS int AS 'select 3 * $1;' LANGUAGE sql;
+
+SELECT has_function_privilege('regressuser1', 'testns.testfunc(int)', 'EXECUTE'); -- true by default
+
+REVOKE ALL ON ALL FUNCTIONS IN SCHEMA testns FROM PUBLIC;
+
+SELECT has_function_privilege('regressuser1', 'testns.testfunc(int)', 'EXECUTE'); -- false
+
+SET client_min_messages TO 'warning';
+DROP SCHEMA testns CASCADE;
+RESET client_min_messages;
+
+
-- clean up
\c