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 1pF12w-0005w7-Dp for pgsql-hackers@arkaria.postgresql.org; Mon, 09 Jan 2023 22:55:14 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.92) (envelope-from ) id 1pF12v-0005E7-5g for pgsql-hackers@arkaria.postgresql.org; Mon, 09 Jan 2023 22:55:13 +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 1pF0zs-0008NK-J9 for pgsql-hackers@lists.postgresql.org; Mon, 09 Jan 2023 22:52:04 +0000 Received: from mail-pl1-x62c.google.com ([2607:f8b0:4864:20::62c]) by makus.postgresql.org with esmtps (TLS1.3:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.92) (envelope-from ) id 1pF0zp-0000kp-63 for pgsql-hackers@postgresql.org; Mon, 09 Jan 2023 22:52:03 +0000 Received: by mail-pl1-x62c.google.com with SMTP id jn22so11195555plb.13 for ; Mon, 09 Jan 2023 14:52:01 -0800 (PST) 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:message-id:reply-to; bh=O1gawFJ9p/VPJ+K8Nv70LQ1lFeNkI04OAoJlDCbQmig=; b=cRMQJdzKs5fEfN6lFaU6AZlPY/z7sPw/vkIGG06snYdGFS90DslOBArlND8uisqw0u x/GJuxaGD4nPmEITBubM9sF4n5ZK66I1T/U23gUFKPuArMBwE8wu8wNuCGRMtJdQqCnU yVcMT/sSFqLJtIr5dwpKmQWoii70k/5JYXe1fqjZWoxPvJ0P7zOJ8UQECVi19iC7M+34 okdQBH9+DZef1eOyiBxo22EZqiFk5svbzuGZFi2+8Ep8KPW0cmFPuLTDEzdCQuwVWryW ACqpZh0CLEv9OwGV7R5o3rTQ/yhDNzbpYmynnxGXnVUTpuIxCqra0tdtZmWQqoUvMOyz XPsQ== 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 :message-id:reply-to; bh=O1gawFJ9p/VPJ+K8Nv70LQ1lFeNkI04OAoJlDCbQmig=; b=LxrQDCAfyNU3n12sAvCci/Bl+u196Z8LBRkSOeRdyUH0VRSLrwagLfxLcTKRP+Ouwu xvz9mEkTto2DO7wnZNrLtLf0gNcellZNCtUNkyl/nKp1KFTTwHjyNou/dw2xwsDmN6BS VaSjL3hpuLeiav12yfw4XNHqO1g9XlZuRyQHmrelfnci7qwYSAbEVtxs3VcaHsTIpQNZ vf40yI0Z7n3krsqpo8BVHHt5To2hlHr5FiJWJcRa5m5DkxU782pxm0cagIKZZJzZ9eCX z2GhQpaAGloyuQ8sfQJgq/mUVfld0Uhlbpht3WH2/ZrGzM90UpsjMi/gI7zvuW5+mdU2 hjxA== X-Gm-Message-State: AFqh2kqF3J+YUc4KB8gwjsCER1yO88Y6bzT6gqSVpR9UM/7UrB9xoVMz n54LA3gOirsfDAWd2B3hH+c= X-Google-Smtp-Source: AMrXdXvdf94y+BtyCKf9MlfsuVwRE1WmJkeZIAsytRdB/IcOBRgXa356PypW7+7Zt2Z4BJ31XQK1Lg== X-Received: by 2002:a05:6a20:4291:b0:b0:47e7:6cba with SMTP id o17-20020a056a20429100b000b047e76cbamr91532358pzj.46.1673304720162; Mon, 09 Jan 2023 14:52:00 -0800 (PST) Received: from nathanxps13 ([50.47.162.83]) by smtp.gmail.com with ESMTPSA id d4-20020a17090a8d8400b001fd6066284dsm5933874pjo.6.2023.01.09.14.51.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 09 Jan 2023 14:51:59 -0800 (PST) Date: Mon, 9 Jan 2023 14:51:57 -0800 From: Nathan Bossart To: Ted Yu Cc: Jeff Davis , Pavel Luzanov , Justin Pryzby , pgsql-hackers@postgresql.org Subject: Re: allow granting CLUSTER, REFRESH MATERIALIZED VIEW, and REINDEX Message-ID: <20230109225157.GA1288965@nathanxps13> References: <8f7172da-2b58-3bd0-97ae-5126e2a7970c@postgrespro.ru> <20221214221140.GA1153@telsasoft.com> <295e86c7aeafb8e2623f8eccdc846855bf2c7e0c.camel@j-davis.com> <20221217060408.GA1256247@nathanxps13> <20221218233018.GA1476904@nathanxps13> <20230103234549.GA289060@nathanxps13> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="yrj/dFKFPuw6o+aM" Content-Disposition: inline In-Reply-To: <20230103234549.GA289060@nathanxps13> List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --yrj/dFKFPuw6o+aM Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Tue, Jan 03, 2023 at 03:45:49PM -0800, Nathan Bossart wrote: > I'd like to get this fixed, but I have yet to hear thoughts on the > suggested approach. I'll proceed with adjusting the tests and > documentation shortly unless someone objects. As promised, here is a new version of the patch with adjusted tests and documentation. -- Nathan Bossart Amazon Web Services: https://aws.amazon.com --yrj/dFKFPuw6o+aM Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v4-0001-fix-MAINTAIN-privs.patch" From e46033659ec3fd2bfeac7d816364b72eccb55410 Mon Sep 17 00:00:00 2001 From: Nathan Bossart Date: Mon, 9 Jan 2023 14:29:24 -0800 Subject: [PATCH v4 1/1] fix MAINTAIN privs --- doc/src/sgml/ref/analyze.sgml | 5 ++- doc/src/sgml/ref/cluster.sgml | 20 +++++++-- doc/src/sgml/ref/lock.sgml | 5 ++- doc/src/sgml/ref/reindex.sgml | 9 +++- doc/src/sgml/ref/vacuum.sgml | 8 +++- src/backend/catalog/partition.c | 22 ++++++++++ src/backend/catalog/toasting.c | 32 +++++++++++++++ src/backend/commands/cluster.c | 35 +++++++++++----- src/backend/commands/indexcmds.c | 10 ++--- src/backend/commands/lockcmds.c | 9 ++++ src/backend/commands/tablecmds.c | 41 ++++++++++++++++++- src/backend/commands/vacuum.c | 7 ++-- src/include/catalog/partition.h | 1 + src/include/catalog/pg_class.h | 1 + src/include/catalog/toasting.h | 1 + src/include/commands/tablecmds.h | 1 + .../expected/cluster-conflict-partition.out | 6 ++- .../specs/cluster-conflict-partition.spec | 5 +-- src/test/regress/expected/cluster.out | 4 +- src/test/regress/expected/vacuum.out | 18 -------- src/test/regress/sql/cluster.sql | 2 + 21 files changed, 189 insertions(+), 53 deletions(-) diff --git a/doc/src/sgml/ref/analyze.sgml b/doc/src/sgml/ref/analyze.sgml index a26834da4f..2f94e89cb0 100644 --- a/doc/src/sgml/ref/analyze.sgml +++ b/doc/src/sgml/ref/analyze.sgml @@ -156,7 +156,10 @@ ANALYZE [ VERBOSE ] [ table_and_columnsANALYZE can only be performed by superusers and roles - with privileges of pg_maintain.) + with privileges of pg_maintain.) If a role has + permission to ANALYZE a partitioned table, it is also + permitted to ANALYZE each of its partitions, regardless + of whether the role has the aforementioned privileges on the partition. ANALYZE will skip over any tables that the calling user does not have permission to analyze. diff --git a/doc/src/sgml/ref/cluster.sgml b/doc/src/sgml/ref/cluster.sgml index 145101e6a5..5616293eef 100644 --- a/doc/src/sgml/ref/cluster.sgml +++ b/doc/src/sgml/ref/cluster.sgml @@ -69,10 +69,7 @@ CLUSTER [VERBOSE] CLUSTER without any parameter reclusters all the previously-clustered tables in the current database that the calling user - owns or has the MAINTAIN privilege for, or all such tables - if called by a superuser or a role with privileges of the - pg_maintain - role. This form of CLUSTER cannot be + has privileges for. This form of CLUSTER cannot be executed inside a transaction block. @@ -134,6 +131,21 @@ CLUSTER [VERBOSE] Notes + + To cluster a table, one must have the MAINTAIN privilege + on the table or be the table's owner, a superuser, or a role with + privileges of the + pg_maintain + role. If a role has permission to CLUSTER a partitioned + table, it is also permitted to CLUSTER each of its + partitions, regardless of whether the role has the aforementioned + privileges on the partition. Similarly, if a role has permission to + CLUSTER the main relation of a TOAST + table, it is also permitted to CLUSTER its + TOAST table. CLUSTER will skip over + any tables that the calling user does not have permission to cluster. + + In cases where you are accessing single rows randomly within a table, the actual order of the data in the diff --git a/doc/src/sgml/ref/lock.sgml b/doc/src/sgml/ref/lock.sgml index d9c5bf9a1d..21a9f88c70 100644 --- a/doc/src/sgml/ref/lock.sgml +++ b/doc/src/sgml/ref/lock.sgml @@ -176,7 +176,10 @@ LOCK [ TABLE ] [ ONLY ] name [ * ] or TRUNCATE privileges on the target table. All other forms of LOCK are allowed with table-level UPDATE, DELETE, - or TRUNCATE privileges. + or TRUNCATE privileges. If a role has permission to + lock a partitioned table, it is also permitted to lock each of its + partitions, regardless of whether the role has the aforementioned + privileges on the partition. diff --git a/doc/src/sgml/ref/reindex.sgml b/doc/src/sgml/ref/reindex.sgml index 192513f34e..aa95c8743e 100644 --- a/doc/src/sgml/ref/reindex.sgml +++ b/doc/src/sgml/ref/reindex.sgml @@ -306,7 +306,14 @@ REINDEX [ ( option [, ...] ) ] { DA indexes on shared catalogs will be skipped unless the user owns the catalog (which typically won't be the case), has privileges of the pg_maintain role, or has the MAINTAIN - privilege on the catalog. Of course, superusers can always reindex anything. + privilege on the catalog. If a role has permission to + REINDEX a partitioned table, it is also permitted to + REINDEX each of its partitions, regardless of whether the + role has the aforementioned privileges on the partition. Similarly, if a + role has permission to REINDEX the main relation of a + TOAST table, it is also permitted to + REINDEX its TOAST table. Of course, + superusers can always reindex anything. diff --git a/doc/src/sgml/ref/vacuum.sgml b/doc/src/sgml/ref/vacuum.sgml index 8fa8421847..2e48757882 100644 --- a/doc/src/sgml/ref/vacuum.sgml +++ b/doc/src/sgml/ref/vacuum.sgml @@ -401,7 +401,13 @@ VACUUM [ FULL ] [ FREEZE ] [ VERBOSE ] [ ANALYZE ] [ oid; + systable_endscan(scan); + + table_close(rel, AccessShareLock); + + return result; +} diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c index f11691aff7..0ef0edec63 100644 --- a/src/backend/commands/cluster.c +++ b/src/backend/commands/cluster.c @@ -80,6 +80,7 @@ static void copy_table_data(Oid OIDNewHeap, Oid OIDOldHeap, Oid OIDOldIndex, static List *get_tables_to_cluster(MemoryContext cluster_context); static List *get_tables_to_cluster_partitioned(MemoryContext cluster_context, Oid indexOid); +static bool cluster_is_permitted_for_relation(Oid relid, Oid userid); /*--------------------------------------------------------------------------- @@ -366,8 +367,7 @@ cluster_rel(Oid tableOid, Oid indexOid, ClusterParams *params) if (recheck) { /* Check that the user still has privileges for the relation */ - if (!object_ownercheck(RelationRelationId, tableOid, save_userid) && - pg_class_aclcheck(tableOid, save_userid, ACL_MAINTAIN) != ACLCHECK_OK) + if (!cluster_is_permitted_for_relation(tableOid, save_userid)) { relation_close(OldHeap, AccessExclusiveLock); goto out; @@ -1645,8 +1645,7 @@ get_tables_to_cluster(MemoryContext cluster_context) index = (Form_pg_index) GETSTRUCT(indexTuple); - if (!object_ownercheck(RelationRelationId, index->indrelid, GetUserId()) && - pg_class_aclcheck(index->indrelid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK) + if (!cluster_is_permitted_for_relation(index->indrelid, GetUserId())) continue; /* Use a permanent memory context for the result list */ @@ -1694,12 +1693,11 @@ get_tables_to_cluster_partitioned(MemoryContext cluster_context, Oid indexOid) if (get_rel_relkind(indexrelid) != RELKIND_INDEX) continue; - /* Silently skip partitions which the user has no access to. */ - if (!object_ownercheck(RelationRelationId, relid, GetUserId()) && - pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK && - (!object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()) || - IsSharedRelation(relid))) - continue; + /* + * We already checked that the user has privileges to CLUSTER the + * partitioned table when we locked it earlier, so there's no need to + * check the privileges again here. + */ /* Use a permanent memory context for the result list */ old_context = MemoryContextSwitchTo(cluster_context); @@ -1714,3 +1712,20 @@ get_tables_to_cluster_partitioned(MemoryContext cluster_context, Oid indexOid) return rtcs; } + +/* + * Return whether userid has privileges to CLUSTER relid. If not, this + * function emits a WARNING. + */ +static bool +cluster_is_permitted_for_relation(Oid relid, Oid userid) +{ + if (pg_class_aclcheck(relid, userid, ACL_MAINTAIN) == ACLCHECK_OK || + has_parent_privs(relid, userid, ACL_MAINTAIN)) + return true; + + ereport(WARNING, + (errmsg("permission denied to cluster \"%s\", skipping it", + get_rel_name(relid)))); + return false; +} diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c index 8afc006f89..31195ddb54 100644 --- a/src/backend/commands/indexcmds.c +++ b/src/backend/commands/indexcmds.c @@ -2796,9 +2796,9 @@ RangeVarCallbackForReindexIndex(const RangeVar *relation, /* Check permissions */ table_oid = IndexGetRelation(relId, true); - if (!object_ownercheck(RelationRelationId, relId, GetUserId()) && - OidIsValid(table_oid) && - pg_class_aclcheck(table_oid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK) + if (OidIsValid(table_oid) && + pg_class_aclcheck(table_oid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK && + !has_parent_privs(table_oid, GetUserId(), ACL_MAINTAIN)) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_INDEX, relation->relname); @@ -3016,8 +3016,8 @@ ReindexMultipleTables(const char *objectName, ReindexObjectType objectKind, * permission checks at the beginning of this routine. */ if (classtuple->relisshared && - !object_ownercheck(RelationRelationId, relid, GetUserId()) && - pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK) + pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK && + !has_parent_privs(relid, GetUserId(), ACL_MAINTAIN)) continue; /* diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c index 99e68bff85..8ec13242ad 100644 --- a/src/backend/commands/lockcmds.c +++ b/src/backend/commands/lockcmds.c @@ -19,6 +19,7 @@ #include "catalog/namespace.h" #include "catalog/pg_inherits.h" #include "commands/lockcmds.h" +#include "commands/tablecmds.h" #include "miscadmin.h" #include "nodes/nodeFuncs.h" #include "parser/parse_clause.h" @@ -305,5 +306,13 @@ LockTableAclCheck(Oid reloid, LOCKMODE lockmode, Oid userid) aclresult = pg_class_aclcheck(reloid, userid, aclmask); + /* + * If this is a partition or a TOAST table, check permissions of the parent + * table if needed. + */ + if (aclresult != ACLCHECK_OK && + has_parent_privs(reloid, userid, ACL_MAINTAIN)) + aclresult = ACLCHECK_OK; + return aclresult; } diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 1db3bd9e2e..59493b553a 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -16918,12 +16918,49 @@ RangeVarCallbackMaintainsTable(const RangeVar *relation, errmsg("\"%s\" is not a table or materialized view", relation->relname))); /* Check permissions */ - if (!object_ownercheck(RelationRelationId, relId, GetUserId()) && - pg_class_aclcheck(relId, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK) + if (pg_class_aclcheck(relId, GetUserId(), ACL_MAINTAIN) != ACLCHECK_OK && + !has_parent_privs(relId, GetUserId(), ACL_MAINTAIN)) aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLE, relation->relname); } +/* + * If relid is a partition, return whether userid has any of the privileges + * specified in acl on its partitioned table. + * + * If relid is a TOAST table, return whether userid has any of the privileges + * specified in acl on its main relation. + */ +bool +has_parent_privs(Oid relid, Oid userid, AclMode acl) +{ + /* + * If this is a partition, check the permissions on its partitioned table. + */ + if (get_rel_relispartition(relid)) + { + Oid root = get_partition_root(relid); + + if (OidIsValid(root) && + pg_class_aclcheck(root, userid, acl) == ACLCHECK_OK) + return true; + } + + /* + * If this is a TOAST table, check the permissions on the main relation. + */ + if (get_rel_relkind(relid) == RELKIND_TOASTVALUE) + { + Oid parent = get_toast_parent(relid); + + if (OidIsValid(parent) && + pg_class_aclcheck(parent, userid, acl) == ACLCHECK_OK) + return true; + } + + return false; +} + /* * Callback to RangeVarGetRelidExtended() for TRUNCATE processing. */ diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c index c4ed7efce3..ceb4cbbaf7 100644 --- a/src/backend/commands/vacuum.c +++ b/src/backend/commands/vacuum.c @@ -41,6 +41,7 @@ #include "catalog/pg_namespace.h" #include "commands/cluster.h" #include "commands/defrem.h" +#include "commands/tablecmds.h" #include "commands/vacuum.h" #include "miscadmin.h" #include "nodes/makefuncs.h" @@ -600,9 +601,9 @@ vacuum_is_permitted_for_relation(Oid relid, Form_pg_class reltuple, * - the role has been granted the MAINTAIN privilege on the relation *---------- */ - if (object_ownercheck(RelationRelationId, relid, GetUserId()) || - (object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()) && !reltuple->relisshared) || - pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) == ACLCHECK_OK) + if ((object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()) && !reltuple->relisshared) || + pg_class_aclcheck(relid, GetUserId(), ACL_MAINTAIN) == ACLCHECK_OK || + has_parent_privs(relid, GetUserId(), ACL_MAINTAIN)) return true; relname = NameStr(reltuple->relname); diff --git a/src/include/catalog/partition.h b/src/include/catalog/partition.h index 79ce711802..abe6cf94b5 100644 --- a/src/include/catalog/partition.h +++ b/src/include/catalog/partition.h @@ -20,6 +20,7 @@ #define HASH_PARTITION_SEED UINT64CONST(0x7A5B22367996DCFD) extern Oid get_partition_parent(Oid relid, bool even_if_detached); +extern Oid get_partition_root(Oid relid); extern List *get_partition_ancestors(Oid relid); extern Oid index_get_partition(Relation partition, Oid indexId); extern List *map_partition_varattnos(List *expr, int fromrel_varno, diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h index 2d1bb7af3a..c57500e327 100644 --- a/src/include/catalog/pg_class.h +++ b/src/include/catalog/pg_class.h @@ -155,6 +155,7 @@ typedef FormData_pg_class *Form_pg_class; DECLARE_UNIQUE_INDEX_PKEY(pg_class_oid_index, 2662, ClassOidIndexId, on pg_class using btree(oid oid_ops)); DECLARE_UNIQUE_INDEX(pg_class_relname_nsp_index, 2663, ClassNameNspIndexId, on pg_class using btree(relname name_ops, relnamespace oid_ops)); DECLARE_INDEX(pg_class_tblspc_relfilenode_index, 3455, ClassTblspcRelfilenodeIndexId, on pg_class using btree(reltablespace oid_ops, relfilenode oid_ops)); +DECLARE_INDEX(pg_class_reltoastrelid_index, 2173, ClassToastRelidIndexId, on pg_class using btree(reltoastrelid oid_ops)); #ifdef EXPOSE_TO_CLIENT_CODE diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h index 5880ec6752..69f7fcc613 100644 --- a/src/include/catalog/toasting.h +++ b/src/include/catalog/toasting.h @@ -26,5 +26,6 @@ extern void AlterTableCreateToastTable(Oid relOid, Datum reloptions, LOCKMODE lockmode); extern void BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid); +extern Oid get_toast_parent(Oid relid); #endif /* TOASTING_H */ diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index 2e717fa815..eef7cc6cfe 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -98,6 +98,7 @@ extern void AtEOSubXact_on_commit_actions(bool isCommit, extern void RangeVarCallbackMaintainsTable(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); +extern bool has_parent_privs(Oid relid, Oid userid, AclMode acl); extern void RangeVarCallbackOwnsRelation(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg); diff --git a/src/test/isolation/expected/cluster-conflict-partition.out b/src/test/isolation/expected/cluster-conflict-partition.out index 7acb675c97..8d21276996 100644 --- a/src/test/isolation/expected/cluster-conflict-partition.out +++ b/src/test/isolation/expected/cluster-conflict-partition.out @@ -22,14 +22,16 @@ starting permutation: s1_begin s1_lock_child s2_auth s2_cluster s1_commit s2_res step s1_begin: BEGIN; step s1_lock_child: LOCK cluster_part_tab1 IN SHARE UPDATE EXCLUSIVE MODE; step s2_auth: SET ROLE regress_cluster_part; -step s2_cluster: CLUSTER cluster_part_tab USING cluster_part_ind; +step s2_cluster: CLUSTER cluster_part_tab USING cluster_part_ind; step s1_commit: COMMIT; +step s2_cluster: <... completed> step s2_reset: RESET ROLE; starting permutation: s1_begin s2_auth s1_lock_child s2_cluster s1_commit s2_reset step s1_begin: BEGIN; step s2_auth: SET ROLE regress_cluster_part; step s1_lock_child: LOCK cluster_part_tab1 IN SHARE UPDATE EXCLUSIVE MODE; -step s2_cluster: CLUSTER cluster_part_tab USING cluster_part_ind; +step s2_cluster: CLUSTER cluster_part_tab USING cluster_part_ind; step s1_commit: COMMIT; +step s2_cluster: <... completed> step s2_reset: RESET ROLE; diff --git a/src/test/isolation/specs/cluster-conflict-partition.spec b/src/test/isolation/specs/cluster-conflict-partition.spec index 5091f684a9..ae38cb4ee3 100644 --- a/src/test/isolation/specs/cluster-conflict-partition.spec +++ b/src/test/isolation/specs/cluster-conflict-partition.spec @@ -27,11 +27,8 @@ step s2_auth { SET ROLE regress_cluster_part; } step s2_cluster { CLUSTER cluster_part_tab USING cluster_part_ind; } step s2_reset { RESET ROLE; } -# CLUSTER on the parent waits if locked, passes for all cases. +# CLUSTER waits if locked, passes for all cases. permutation s1_begin s1_lock_parent s2_auth s2_cluster s1_commit s2_reset permutation s1_begin s2_auth s1_lock_parent s2_cluster s1_commit s2_reset - -# When taking a lock on a partition leaf, CLUSTER on the parent skips -# the leaf, passes for all cases. permutation s1_begin s1_lock_child s2_auth s2_cluster s1_commit s2_reset permutation s1_begin s2_auth s1_lock_child s2_cluster s1_commit s2_reset diff --git a/src/test/regress/expected/cluster.out b/src/test/regress/expected/cluster.out index 542c2e098c..2eec483eaa 100644 --- a/src/test/regress/expected/cluster.out +++ b/src/test/regress/expected/cluster.out @@ -352,7 +352,9 @@ INSERT INTO clstr_3 VALUES (1); -- this user can only cluster clstr_1 and clstr_3, but the latter -- has not been clustered SET SESSION AUTHORIZATION regress_clstr_user; +SET client_min_messages = ERROR; -- order of "skipping" warnings may vary CLUSTER; +RESET client_min_messages; SELECT * FROM clstr_1 UNION ALL SELECT * FROM clstr_2 UNION ALL SELECT * FROM clstr_3; @@ -513,7 +515,7 @@ SELECT a.relname, a.relfilenode=b.relfilenode FROM pg_class a -----------+---------- ptnowner | t ptnowner1 | f - ptnowner2 | t + ptnowner2 | f (3 rows) DROP TABLE ptnowner; diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out index d860be0e20..458adee7f8 100644 --- a/src/test/regress/expected/vacuum.out +++ b/src/test/regress/expected/vacuum.out @@ -353,20 +353,14 @@ ALTER TABLE vacowned_parted OWNER TO regress_vacuum; ALTER TABLE vacowned_part1 OWNER TO regress_vacuum; SET ROLE regress_vacuum; VACUUM vacowned_parted; -WARNING: permission denied to vacuum "vacowned_part2", skipping it VACUUM vacowned_part1; VACUUM vacowned_part2; -WARNING: permission denied to vacuum "vacowned_part2", skipping it ANALYZE vacowned_parted; -WARNING: permission denied to analyze "vacowned_part2", skipping it ANALYZE vacowned_part1; ANALYZE vacowned_part2; -WARNING: permission denied to analyze "vacowned_part2", skipping it VACUUM (ANALYZE) vacowned_parted; -WARNING: permission denied to vacuum "vacowned_part2", skipping it VACUUM (ANALYZE) vacowned_part1; VACUUM (ANALYZE) vacowned_part2; -WARNING: permission denied to vacuum "vacowned_part2", skipping it RESET ROLE; -- Only one partition owned by other user. ALTER TABLE vacowned_parted OWNER TO CURRENT_USER; @@ -395,26 +389,14 @@ ALTER TABLE vacowned_parted OWNER TO regress_vacuum; ALTER TABLE vacowned_part1 OWNER TO CURRENT_USER; SET ROLE regress_vacuum; VACUUM vacowned_parted; -WARNING: permission denied to vacuum "vacowned_part1", skipping it -WARNING: permission denied to vacuum "vacowned_part2", skipping it VACUUM vacowned_part1; -WARNING: permission denied to vacuum "vacowned_part1", skipping it VACUUM vacowned_part2; -WARNING: permission denied to vacuum "vacowned_part2", skipping it ANALYZE vacowned_parted; -WARNING: permission denied to analyze "vacowned_part1", skipping it -WARNING: permission denied to analyze "vacowned_part2", skipping it ANALYZE vacowned_part1; -WARNING: permission denied to analyze "vacowned_part1", skipping it ANALYZE vacowned_part2; -WARNING: permission denied to analyze "vacowned_part2", skipping it VACUUM (ANALYZE) vacowned_parted; -WARNING: permission denied to vacuum "vacowned_part1", skipping it -WARNING: permission denied to vacuum "vacowned_part2", skipping it VACUUM (ANALYZE) vacowned_part1; -WARNING: permission denied to vacuum "vacowned_part1", skipping it VACUUM (ANALYZE) vacowned_part2; -WARNING: permission denied to vacuum "vacowned_part2", skipping it RESET ROLE; DROP TABLE vacowned; DROP TABLE vacowned_parted; diff --git a/src/test/regress/sql/cluster.sql b/src/test/regress/sql/cluster.sql index 6cb9c926c0..a4cfaae807 100644 --- a/src/test/regress/sql/cluster.sql +++ b/src/test/regress/sql/cluster.sql @@ -145,7 +145,9 @@ INSERT INTO clstr_3 VALUES (1); -- this user can only cluster clstr_1 and clstr_3, but the latter -- has not been clustered SET SESSION AUTHORIZATION regress_clstr_user; +SET client_min_messages = ERROR; -- order of "skipping" warnings may vary CLUSTER; +RESET client_min_messages; SELECT * FROM clstr_1 UNION ALL SELECT * FROM clstr_2 UNION ALL SELECT * FROM clstr_3; -- 2.25.1 --yrj/dFKFPuw6o+aM--