Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oVHI2-00014U-2O for pgsql-hackers@arkaria.postgresql.org; Mon, 05 Sep 2022 18:57:46 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1oVHH1-0001tY-S7 for pgsql-hackers@arkaria.postgresql.org; Mon, 05 Sep 2022 18:56:43 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1oVHH1-0001tP-49 for pgsql-hackers@lists.postgresql.org; Mon, 05 Sep 2022 18:56:43 +0000 Received: from mail-pg1-x533.google.com ([2607:f8b0:4864:20::533]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1oVHGt-0007Ha-0u for pgsql-hackers@postgresql.org; Mon, 05 Sep 2022 18:56:42 +0000 Received: by mail-pg1-x533.google.com with SMTP id c24so8683045pgg.11 for ; Mon, 05 Sep 2022 11:56:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:from:to:cc:subject:date; bh=zwygSFWEX+6RYQCO+UIcLQrv8EP8Y0PflaeCo16Vyak=; b=c2vstQ97srv/tYFSP1wonuliqvfxGC3hmkmJ2gjm/LeBnqnPU/Ee6K+YKh+1yP19/k mdU3exF7jsq7vK68q0aOES3msJ8MoFVmgw6fveZqC+ZqLyZae0pvNz3te2XzzcOP3Pon p4/5PV/BH1c1yxM5qKGX3gW629Q9EubQFEYM5lPdWY8aU21pSwia7iWIIV36mXInCwij mRJNYm+4v6ZB7m7tq4nAJbnc+86TE1Zf9f8ORpivBaMUxb/POf1Ch/CaxuU7pE0PyRdH ZCN6j4eQ4JoReA95UTvNL4028L30FfJ5otYKzBFtfbjh9WwurVDJX8Njs56nfH1QGGsM +/bg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=in-reply-to:content-disposition:mime-version:references:message-id :subject:cc:to:from:date:x-gm-message-state:from:to:cc:subject:date; bh=zwygSFWEX+6RYQCO+UIcLQrv8EP8Y0PflaeCo16Vyak=; b=u4RZ6YIV381ncOTxO0aLJ1YlW496CZHG1M005Yj6suqJkEy0fDtdJQB4u8/bZkHmCM KXWMQCW4nbO+rmvxPZjlhUAkb26x5akxOH3PKa/TxAgNV3tDbuz5uxQOts5J1OKFJt5L VBFWKsDQwUN/JkWgNzmOV+xJTQscfGqoy81i1I26SDBTIYFUqGrnyOrcOSfkXt0IUd0L AK/hBTRLIywk3ixGcKZCq1nkgrR4ysPI/1IRxjTzDtLZgA+oDFqZa6Nk7i2uSPhb01o6 18RjIc2E0ZhvnZvdYxVMIaOy8C1p9rWfGrEmXBTmlVJUdGe9LMWmlB65mcey7lElW5Pf f/mg== X-Gm-Message-State: ACgBeo0HyRRzsC3OwdcN/9u0CT4xvPfeoaDNUuGJ+0M3J195oLomxG4Y hLYK9w0ztIS3C/2Yr+cNoyo= X-Google-Smtp-Source: AA6agR778Dbat32MjQmmm8hmklBnmyqz1zjAOiMRGl3iOsJfTe9kSmwQDC3K8/MoQZhzi4lCgkW+Yw== X-Received: by 2002:a63:1b59:0:b0:434:883:b055 with SMTP id b25-20020a631b59000000b004340883b055mr11618444pgm.50.1662404193802; Mon, 05 Sep 2022 11:56:33 -0700 (PDT) Received: from nathanxps13 ([50.47.162.83]) by smtp.gmail.com with ESMTPSA id n13-20020a170903110d00b0016d72804664sm7915338plh.205.2022.09.05.11.56.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 05 Sep 2022 11:56:32 -0700 (PDT) Date: Mon, 5 Sep 2022 11:56:30 -0700 From: Nathan Bossart To: Stephen Frost Cc: Robert Haas , "David G. Johnston" , Kyotaro Horiguchi , Bharath Rupireddy , "pgsql-hackers@postgresql.org" Subject: Re: predefined role(s) for VACUUM and ANALYZE Message-ID: <20220905185630.GA1961927@nathanxps13> References: <20220722203735.GB3996698@nathanxps13> <20220725164049.GA4091959@nathanxps13> <20220726.104712.912995710251150228.horikyota.ntt@gmail.com> <20220823234647.GB31055@tamriel.snowman.net> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="PEIAKu/WMn1b1Hv9" Content-Disposition: inline In-Reply-To: <20220823234647.GB31055@tamriel.snowman.net> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --PEIAKu/WMn1b1Hv9 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Here is a first attempt at allowing users to grant VACUUM or ANALYZE per-relation. Overall, this seems pretty straightforward. I needed to adjust the permissions logic for VACUUM/ANALYZE a bit, which causes some extra WARNING messages for VACUUM (ANALYZE) in some cases, but this didn't seem particularly worrisome. It may be desirable to allow granting ANALYZE on specific columns or to allow granting VACUUM/ANALYZE at the schema or database level, but that is left as a future exercise. On Tue, Aug 23, 2022 at 07:46:47PM -0400, Stephen Frost wrote: > I've long felt that we should redefine the way the ACLs work to have a > distinct set of bits for each object type. We don't need to support a > CONNECT bit on a table, yet we do today and we expend quite a few bits > in that way. Having that handled on a per-object-type basis instead > would allow us to get quite a bit more mileage out of the existing 32bit > field before having to introduce more complicated storage methods like > using a bit to tell us to go look up more ACLs somewhere else. There are 2 bits remaining at the moment, so I didn't redesign the ACL system in the attached patch. However, I did some research on a couple options. Using a distinct set of bits for each catalog table should free up a handful of bits, which should indeed kick the can down the road a little. Another easy option is to simply make AclMode a uint64, which would immediately free up another 16 privilege bits. I was able to get this approach building and passing tests in a few minutes, but there might be performance/space concerns. -- Nathan Bossart Amazon Web Services: https://aws.amazon.com --PEIAKu/WMn1b1Hv9 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v3-0001-Allow-granting-VACUUM-and-ANALYZE-privileges-on-r.patch" From f19eea3f3148916a79d002094ca4eb4aa98af753 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Sat, 3 Sep 2022 23:31:38 -0700 Subject: [PATCH v3 1/1] Allow granting VACUUM and ANALYZE privileges on relations. --- doc/src/sgml/ddl.sgml | 49 ++++++++--- doc/src/sgml/func.sgml | 3 +- .../sgml/ref/alter_default_privileges.sgml | 4 +- doc/src/sgml/ref/analyze.sgml | 3 +- doc/src/sgml/ref/grant.sgml | 4 +- doc/src/sgml/ref/revoke.sgml | 2 +- doc/src/sgml/ref/vacuum.sgml | 3 +- src/backend/catalog/aclchk.c | 8 ++ src/backend/commands/analyze.c | 2 +- src/backend/commands/vacuum.c | 24 ++++-- src/backend/parser/gram.y | 7 ++ src/backend/utils/adt/acl.c | 16 ++++ src/bin/pg_dump/dumputils.c | 2 + src/bin/pg_dump/t/002_pg_dump.pl | 2 +- src/bin/psql/tab-complete.c | 4 +- src/include/nodes/parsenodes.h | 4 +- src/include/utils/acl.h | 6 +- src/test/regress/expected/dependency.out | 22 ++--- src/test/regress/expected/privileges.out | 86 ++++++++++++++----- src/test/regress/expected/rowsecurity.out | 34 ++++---- src/test/regress/expected/vacuum.out | 6 ++ src/test/regress/sql/dependency.sql | 2 +- src/test/regress/sql/privileges.sql | 40 +++++++++ 23 files changed, 249 insertions(+), 84 deletions(-) diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 03c0193709..ed034a6b1d 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -1691,8 +1691,9 @@ ALTER TABLE products RENAME TO items; INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, TRIGGER, CREATE, CONNECT, TEMPORARY, - EXECUTE, USAGE, SET - and ALTER SYSTEM. + EXECUTE, USAGE, SET, + ALTER SYSTEM, VACUUM, and + ANALYZE. The privileges applicable to a particular object vary depending on the object's type (table, function, etc.). More detail about the meanings of these privileges appears below. @@ -1982,7 +1983,25 @@ REVOKE ALL ON accounts FROM PUBLIC; - + + + VACUUM + + + Allows VACUUM on a relation. + + + + + + ANALYZE + + + Allows ANALYZE on a relation. + + + + The privileges required by other commands are listed on the reference page of the respective command. @@ -2131,6 +2150,16 @@ REVOKE ALL ON accounts FROM PUBLIC; A PARAMETER + + VACUUM + v + TABLE + + + ANALYZE + z + TABLE + @@ -2221,7 +2250,7 @@ REVOKE ALL ON accounts FROM PUBLIC; TABLE (and table-like objects) - arwdDxt + arwdDxtvz none \dp @@ -2279,12 +2308,12 @@ GRANT SELECT (col1), UPDATE (col1) ON mytable TO miriam_rw; would show: => \dp mytable - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------+---------+-------+-----------------------+-----------------------+---------- - public | mytable | table | miriam=arwdDxt/miriam+| col1: +| - | | | =r/miriam +| miriam_rw=rw/miriam | - | | | admin=arw/miriam | | + Access privileges + Schema | Name | Type | Access privileges | Column privileges | Policies +--------+---------+-------+-------------------------+-----------------------+---------- + public | mytable | table | miriam=arwdDxtvz/miriam+| col1: +| + | | | =r/miriam +| miriam_rw=rw/miriam | + | | | admin=arw/miriam | | (1 row) diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 67eb380632..8be800767d 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -22962,7 +22962,8 @@ SELECT has_function_privilege('joeuser', 'myfunc(int, text)', 'execute'); are SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, - and TRIGGER. + TRIGGER, VACUUM and + ANALYZE. diff --git a/doc/src/sgml/ref/alter_default_privileges.sgml b/doc/src/sgml/ref/alter_default_privileges.sgml index f1d54f5aa3..0da295daff 100644 --- a/doc/src/sgml/ref/alter_default_privileges.sgml +++ b/doc/src/sgml/ref/alter_default_privileges.sgml @@ -28,7 +28,7 @@ ALTER DEFAULT PRIVILEGES where abbreviated_grant_or_revoke is one of: -GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } +GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | VACUUM | ANALYZE } [, ...] | ALL [ PRIVILEGES ] } ON TABLES TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] @@ -51,7 +51,7 @@ GRANT { USAGE | CREATE | ALL [ PRIVILEGES ] } TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] REVOKE [ GRANT OPTION FOR ] - { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } + { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | VACUUM | ANALYZE } [, ...] | ALL [ PRIVILEGES ] } ON TABLES FROM { [ GROUP ] role_name | PUBLIC } [, ...] diff --git a/doc/src/sgml/ref/analyze.sgml b/doc/src/sgml/ref/analyze.sgml index 2ba115d1ad..400ea30cd0 100644 --- a/doc/src/sgml/ref/analyze.sgml +++ b/doc/src/sgml/ref/analyze.sgml @@ -149,7 +149,8 @@ ANALYZE [ VERBOSE ] [ table_and_columns To analyze a table, one must ordinarily be the table's owner or a - superuser. However, database owners are allowed to + superuser or have the ANALYZE privilege on the table. + However, database owners are allowed to analyze all tables in their databases, except shared catalogs. (The restriction for shared catalogs means that a true database-wide ANALYZE can only be performed by a superuser.) diff --git a/doc/src/sgml/ref/grant.sgml b/doc/src/sgml/ref/grant.sgml index dea19cd348..f6234d975a 100644 --- a/doc/src/sgml/ref/grant.sgml +++ b/doc/src/sgml/ref/grant.sgml @@ -21,7 +21,7 @@ PostgreSQL documentation -GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } +GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | VACUUM | ANALYZE } [, ...] | ALL [ PRIVILEGES ] } ON { [ TABLE ] table_name [, ...] | ALL TABLES IN SCHEMA schema_name [, ...] } @@ -193,6 +193,8 @@ GRANT role_name [, ...] TO USAGE SET ALTER SYSTEM + VACUUM + ANALYZE Specific types of privileges, as defined in . diff --git a/doc/src/sgml/ref/revoke.sgml b/doc/src/sgml/ref/revoke.sgml index 4fd4bfb3d7..ece1aa721f 100644 --- a/doc/src/sgml/ref/revoke.sgml +++ b/doc/src/sgml/ref/revoke.sgml @@ -22,7 +22,7 @@ PostgreSQL documentation REVOKE [ GRANT OPTION FOR ] - { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } + { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER | VACUUM | ANALYZE } [, ...] | ALL [ PRIVILEGES ] } ON { [ TABLE ] table_name [, ...] | ALL TABLES IN SCHEMA schema_name [, ...] } diff --git a/doc/src/sgml/ref/vacuum.sgml b/doc/src/sgml/ref/vacuum.sgml index c582021d29..70c0d81346 100644 --- a/doc/src/sgml/ref/vacuum.sgml +++ b/doc/src/sgml/ref/vacuum.sgml @@ -357,7 +357,8 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ rd_rel, - params->options & VACOPT_ANALYZE)) + VACOPT_ANALYZE)) { relation_close(onerel, ShareUpdateExclusiveLock); return; diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index 7ccde07de9..562a6686af 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -547,16 +547,16 @@ vacuum(List *relations, VacuumParams *params, } /* - * Check if a given relation can be safely vacuumed or analyzed. If the - * user is not the relation owner, issue a WARNING log message and return - * false to let the caller decide what to do with this relation. This - * routine is used to decide if a relation can be processed for VACUUM or - * ANALYZE. + * Check if the current user has privileges to vacuum or analyze the relation. + * If not, issue a WARNING log message and return false to let the caller + * decide what to do with this relation. This routine is used to decide if a + * relation can be processed for VACUUM or ANALYZE. */ bool vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, bits32 options) { char *relname; + AclMode mode = 0; Assert((options & (VACOPT_VACUUM | VACOPT_ANALYZE)) != 0); @@ -566,13 +566,19 @@ vacuum_is_relation_owner(Oid relid, Form_pg_class reltuple, bits32 options) * We allow the user to vacuum or analyze a table if he is superuser, the * table owner, or the database owner (but in the latter case, only if * it's not a shared relation). pg_class_ownercheck includes the - * superuser case. + * superuser case. The user might also have been granted privileges to + * vacuum or analyze the table. * * Note we choose to treat permissions failure as a WARNING and keep * trying to vacuum or analyze the rest of the DB --- is this appropriate? */ + if (options & VACOPT_VACUUM) + mode |= ACL_VACUUM; + if (options & VACOPT_ANALYZE) + mode |= ACL_ANALYZE; if (pg_class_ownercheck(relid, GetUserId()) || - (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !reltuple->relisshared)) + (pg_database_ownercheck(MyDatabaseId, GetUserId()) && !reltuple->relisshared) || + pg_class_aclcheck(relid, GetUserId(), mode) == ACLCHECK_OK) return true; relname = NameStr(reltuple->relname); @@ -1914,12 +1920,12 @@ vacuum_rel(Oid relid, RangeVar *relation, VacuumParams *params) */ if (!vacuum_is_relation_owner(RelationGetRelid(rel), rel->rd_rel, - params->options & VACOPT_VACUUM)) + VACOPT_VACUUM)) { relation_close(rel, lmode); PopActiveSnapshot(); CommitTransactionCommand(); - return false; + return true; /* user may have the ANALYZE privilege */ } /* diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index 0492ff9a66..7b2426bc52 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -7485,6 +7485,13 @@ privilege: SELECT opt_column_list n->cols = NIL; $$ = n; } + | analyze_keyword + { + AccessPriv *n = makeNode(AccessPriv); + n->priv_name = pstrdup("analyze"); + n->cols = NIL; + $$ = n; + } | ColId opt_column_list { AccessPriv *n = makeNode(AccessPriv); diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index fd71a9b13e..b4b4a5e6fa 100644 --- a/src/backend/utils/adt/acl.c +++ b/src/backend/utils/adt/acl.c @@ -314,6 +314,12 @@ aclparse(const char *s, AclItem *aip) case ACL_ALTER_SYSTEM_CHR: read = ACL_ALTER_SYSTEM; break; + case ACL_VACUUM_CHR: + read = ACL_VACUUM; + break; + case ACL_ANALYZE_CHR: + read = ACL_ANALYZE; + break; case 'R': /* ignore old RULE privileges */ read = 0; break; @@ -1588,6 +1594,8 @@ makeaclitem(PG_FUNCTION_ARGS) {"CONNECT", ACL_CONNECT}, {"SET", ACL_SET}, {"ALTER SYSTEM", ACL_ALTER_SYSTEM}, + {"VACUUM", ACL_VACUUM}, + {"ANALYZE", ACL_ANALYZE}, {"RULE", 0}, /* ignore old RULE privileges */ {NULL, 0} }; @@ -1696,6 +1704,10 @@ convert_aclright_to_string(int aclright) return "SET"; case ACL_ALTER_SYSTEM: return "ALTER SYSTEM"; + case ACL_VACUUM: + return "VACUUM"; + case ACL_ANALYZE: + return "ANALYZE"; default: elog(ERROR, "unrecognized aclright: %d", aclright); return NULL; @@ -2005,6 +2017,10 @@ convert_table_priv_string(text *priv_type_text) {"REFERENCES WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_REFERENCES)}, {"TRIGGER", ACL_TRIGGER}, {"TRIGGER WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_TRIGGER)}, + {"VACUUM", ACL_VACUUM}, + {"VACUUM WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_VACUUM)}, + {"ANALYZE", ACL_ANALYZE}, + {"ANALYZE WITH GRANT OPTION", ACL_GRANT_OPTION_FOR(ACL_ANALYZE)}, {"RULE", 0}, /* ignore old RULE privileges */ {"RULE WITH GRANT OPTION", 0}, {NULL, 0} diff --git a/src/bin/pg_dump/dumputils.c b/src/bin/pg_dump/dumputils.c index 6e501a5413..9311417f18 100644 --- a/src/bin/pg_dump/dumputils.c +++ b/src/bin/pg_dump/dumputils.c @@ -457,6 +457,8 @@ do { \ CONVERT_PRIV('d', "DELETE"); CONVERT_PRIV('t', "TRIGGER"); CONVERT_PRIV('D', "TRUNCATE"); + CONVERT_PRIV('v', "VACUUM"); + CONVERT_PRIV('z', "ANALYZE"); } } diff --git a/src/bin/pg_dump/t/002_pg_dump.pl b/src/bin/pg_dump/t/002_pg_dump.pl index 2873b662fb..f015fe2194 100644 --- a/src/bin/pg_dump/t/002_pg_dump.pl +++ b/src/bin/pg_dump/t/002_pg_dump.pl @@ -566,7 +566,7 @@ my %tests = ( \QREVOKE ALL ON TABLES FROM regress_dump_test_role;\E\n \QALTER DEFAULT PRIVILEGES \E \QFOR ROLE regress_dump_test_role \E - \QGRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,UPDATE ON TABLES TO regress_dump_test_role;\E + \QGRANT INSERT,REFERENCES,DELETE,TRIGGER,TRUNCATE,VACUUM,ANALYZE,UPDATE ON TABLES TO regress_dump_test_role;\E /xm, like => { %full_runs, section_post_data => 1, }, unlike => { no_privs => 1, }, diff --git a/src/bin/psql/tab-complete.c b/src/bin/psql/tab-complete.c index 62a39779b9..db61bbc4d4 100644 --- a/src/bin/psql/tab-complete.c +++ b/src/bin/psql/tab-complete.c @@ -3738,7 +3738,7 @@ psql_completion(const char *text, int start, int end) if (HeadMatches("ALTER", "DEFAULT", "PRIVILEGES")) COMPLETE_WITH("SELECT", "INSERT", "UPDATE", "DELETE", "TRUNCATE", "REFERENCES", "TRIGGER", - "EXECUTE", "USAGE", "ALL"); + "EXECUTE", "USAGE", "VACUUM", "ANALYZE", "ALL"); else COMPLETE_WITH_QUERY_PLUS(Query_for_list_of_roles, "GRANT", @@ -3756,6 +3756,8 @@ psql_completion(const char *text, int start, int end) "USAGE", "SET", "ALTER SYSTEM", + "VACUUM", + "ANALYZE", "ALL"); } diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h index 6958306a7d..8315b3b356 100644 --- a/src/include/nodes/parsenodes.h +++ b/src/include/nodes/parsenodes.h @@ -94,7 +94,9 @@ typedef uint32 AclMode; /* a bitmask of privilege bits */ #define ACL_CONNECT (1<<11) /* for databases */ #define ACL_SET (1<<12) /* for configuration parameters */ #define ACL_ALTER_SYSTEM (1<<13) /* for configuration parameters */ -#define N_ACL_RIGHTS 14 /* 1 plus the last 1< 44); \dp - Access privileges - Schema | Name | Type | Access privileges | Column privileges | Policies ---------------------+----------+-------+---------------------------------------------+-------------------+-------------------------------------------- - regress_rls_schema | category | table | regress_rls_alice=arwdDxt/regress_rls_alice+| | - | | | =arwdDxt/regress_rls_alice | | - regress_rls_schema | document | table | regress_rls_alice=arwdDxt/regress_rls_alice+| | p1: + - | | | =arwdDxt/regress_rls_alice | | (u): (dlevel <= ( SELECT uaccount.seclv + - | | | | | FROM uaccount + - | | | | | WHERE (uaccount.pguser = CURRENT_USER)))+ - | | | | | p2r (RESTRICTIVE): + - | | | | | (u): ((cid <> 44) AND (cid < 50)) + - | | | | | to: regress_rls_dave + - | | | | | p1r (RESTRICTIVE): + - | | | | | (u): (cid <> 44) + - | | | | | to: regress_rls_dave - regress_rls_schema | uaccount | table | regress_rls_alice=arwdDxt/regress_rls_alice+| | - | | | =r/regress_rls_alice | | + Access privileges + Schema | Name | Type | Access privileges | Column privileges | Policies +--------------------+----------+-------+-----------------------------------------------+-------------------+-------------------------------------------- + regress_rls_schema | category | table | regress_rls_alice=arwdDxtvz/regress_rls_alice+| | + | | | =arwdDxtvz/regress_rls_alice | | + regress_rls_schema | document | table | regress_rls_alice=arwdDxtvz/regress_rls_alice+| | p1: + + | | | =arwdDxtvz/regress_rls_alice | | (u): (dlevel <= ( SELECT uaccount.seclv + + | | | | | FROM uaccount + + | | | | | WHERE (uaccount.pguser = CURRENT_USER)))+ + | | | | | p2r (RESTRICTIVE): + + | | | | | (u): ((cid <> 44) AND (cid < 50)) + + | | | | | to: regress_rls_dave + + | | | | | p1r (RESTRICTIVE): + + | | | | | (u): (cid <> 44) + + | | | | | to: regress_rls_dave + regress_rls_schema | uaccount | table | regress_rls_alice=arwdDxtvz/regress_rls_alice+| | + | | | =r/regress_rls_alice | | (3 rows) \d document diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out index c63a157e5f..fd1feccee5 100644 --- a/src/test/regress/expected/vacuum.out +++ b/src/test/regress/expected/vacuum.out @@ -336,7 +336,9 @@ WARNING: skipping "vacowned_part2" --- only table or database owner can analyze VACUUM (ANALYZE) vacowned_parted; WARNING: skipping "vacowned_parted" --- only table or database owner can vacuum it WARNING: skipping "vacowned_part1" --- only table or database owner can vacuum it +WARNING: skipping "vacowned_part1" --- only table or database owner can analyze it WARNING: skipping "vacowned_part2" --- only table or database owner can vacuum it +WARNING: skipping "vacowned_part2" --- only table or database owner can analyze it VACUUM (ANALYZE) vacowned_part1; WARNING: skipping "vacowned_part1" --- only table or database owner can vacuum it VACUUM (ANALYZE) vacowned_part2; @@ -358,6 +360,7 @@ ANALYZE vacowned_part2; WARNING: skipping "vacowned_part2" --- only table or database owner can analyze it VACUUM (ANALYZE) vacowned_parted; WARNING: skipping "vacowned_part2" --- only table or database owner can vacuum it +WARNING: skipping "vacowned_part2" --- only table or database owner can analyze it VACUUM (ANALYZE) vacowned_part1; VACUUM (ANALYZE) vacowned_part2; WARNING: skipping "vacowned_part2" --- only table or database owner can vacuum it @@ -380,6 +383,7 @@ WARNING: skipping "vacowned_part2" --- only table or database owner can analyze VACUUM (ANALYZE) vacowned_parted; WARNING: skipping "vacowned_parted" --- only table or database owner can vacuum it WARNING: skipping "vacowned_part2" --- only table or database owner can vacuum it +WARNING: skipping "vacowned_part2" --- only table or database owner can analyze it VACUUM (ANALYZE) vacowned_part1; VACUUM (ANALYZE) vacowned_part2; WARNING: skipping "vacowned_part2" --- only table or database owner can vacuum it @@ -404,7 +408,9 @@ ANALYZE vacowned_part2; WARNING: skipping "vacowned_part2" --- only table or database owner can analyze it VACUUM (ANALYZE) vacowned_parted; WARNING: skipping "vacowned_part1" --- only table or database owner can vacuum it +WARNING: skipping "vacowned_part1" --- only table or database owner can analyze it WARNING: skipping "vacowned_part2" --- only table or database owner can vacuum it +WARNING: skipping "vacowned_part2" --- only table or database owner can analyze it VACUUM (ANALYZE) vacowned_part1; WARNING: skipping "vacowned_part1" --- only table or database owner can vacuum it VACUUM (ANALYZE) vacowned_part2; diff --git a/src/test/regress/sql/dependency.sql b/src/test/regress/sql/dependency.sql index 2559c62d0b..99b905a938 100644 --- a/src/test/regress/sql/dependency.sql +++ b/src/test/regress/sql/dependency.sql @@ -21,7 +21,7 @@ REVOKE SELECT ON deptest FROM GROUP regress_dep_group; DROP GROUP regress_dep_group; -- can't drop the user if we revoke the privileges partially -REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES ON deptest FROM regress_dep_user; +REVOKE SELECT, INSERT, UPDATE, DELETE, TRUNCATE, REFERENCES, VACUUM, ANALYZE ON deptest FROM regress_dep_user; DROP USER regress_dep_user; -- now we are OK to drop him diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql index 4ad366470d..a8ebcc8b85 100644 --- a/src/test/regress/sql/privileges.sql +++ b/src/test/regress/sql/privileges.sql @@ -1813,3 +1813,43 @@ DROP ROLE regress_group; DROP ROLE regress_group_direct_manager; DROP ROLE regress_group_indirect_manager; DROP ROLE regress_group_member; + +-- VACUUM and ANALYZE +CREATE ROLE regress_no_priv; +CREATE ROLE regress_only_vacuum; +CREATE ROLE regress_only_analyze; +CREATE ROLE regress_both; + +CREATE TABLE vacanalyze_test (a INT); +GRANT VACUUM ON vacanalyze_test TO regress_only_vacuum, regress_both; +GRANT ANALYZE ON vacanalyze_test TO regress_only_analyze, regress_both; + +SET ROLE regress_no_priv; +VACUUM vacanalyze_test; +ANALYZE vacanalyze_test; +VACUUM (ANALYZE) vacanalyze_test; +RESET ROLE; + +SET ROLE regress_only_vacuum; +VACUUM vacanalyze_test; +ANALYZE vacanalyze_test; +VACUUM (ANALYZE) vacanalyze_test; +RESET ROLE; + +SET ROLE regress_only_analyze; +VACUUM vacanalyze_test; +ANALYZE vacanalyze_test; +VACUUM (ANALYZE) vacanalyze_test; +RESET ROLE; + +SET ROLE regress_both; +VACUUM vacanalyze_test; +ANALYZE vacanalyze_test; +VACUUM (ANALYZE) vacanalyze_test; +RESET ROLE; + +DROP TABLE vacanalyze_test; +DROP ROLE regress_no_priv; +DROP ROLE regress_only_vacuum; +DROP ROLE regress_only_analyze; +DROP ROLE regress_both; -- 2.25.1 --PEIAKu/WMn1b1Hv9--