From cb23dfabb482835b8adae8038e62009bef65dc88 Mon Sep 17 00:00:00 2001 From: luozihao <1165977584@qq.com> Date: Thu, 7 Sep 2023 15:10:21 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=89=A9=E5=8C=96=E8=A7=86?= =?UTF-8?q?=E5=9B=BE=E5=88=B7=E6=96=B0=E6=9D=83=E9=99=90=E6=A3=80=E6=9F=A5?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../optimizer/commands/matview.cpp | 8 ++-- .../optimizer/commands/tablecmds.cpp | 45 +++++++++++++++++++ .../optimizer/rewrite/rewriteHandler.cpp | 2 +- src/include/commands/tablecmds.h | 2 + src/test/regress/expected/matview_single.out | 34 ++++++++++++++ src/test/regress/sql/matview_single.sql | 32 +++++++++++++ 6 files changed, 118 insertions(+), 5 deletions(-) diff --git a/src/gausskernel/optimizer/commands/matview.cpp b/src/gausskernel/optimizer/commands/matview.cpp index 25200d9c2..8d1c8064b 100755 --- a/src/gausskernel/optimizer/commands/matview.cpp +++ b/src/gausskernel/optimizer/commands/matview.cpp @@ -830,7 +830,7 @@ ObjectAddress ExecRefreshMatViewInc(RefreshMatViewStmt *stmt, const char *queryS matviewOid = RangeVarGetRelidExtended(stmt->relation, ExclusiveLock, false, false, false, true, - RangeVarCallbackOwnsTable, NULL); + RangeVarCallbackOwnsMatView, NULL); Oid mapid = DatumGetObjectId(get_matview_mapid(matviewOid)); Datum oldTime = get_matview_refreshtime(matviewOid, &isTimeNULL); @@ -946,7 +946,7 @@ ObjectAddress ExecRefreshIncMatViewAll(RefreshMatViewStmt *stmt, const char *que matviewOid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock, false, false, false, true, - RangeVarCallbackOwnsTable, NULL); + RangeVarCallbackOwnsMatView, NULL); mapid = DatumGetObjectId(get_matview_mapid(matviewOid)); matviewRel = heap_open(matviewOid, AccessExclusiveLock); @@ -1055,7 +1055,7 @@ ObjectAddress ExecRefreshCtasMatViewAll(RefreshMatViewStmt *stmt, const char *qu */ matviewOid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock, false, false, false, true, - RangeVarCallbackOwnsTable, NULL); + RangeVarCallbackOwnsMatView, NULL); matviewRel = heap_open(matviewOid, NoLock); /* @@ -1168,7 +1168,7 @@ bool isIncMatView(RangeVar *rv) Oid matviewOid = RangeVarGetRelidExtended(rv, NoLock, false, false, false, true, - RangeVarCallbackOwnsTable, NULL); + RangeVarCallbackOwnsMatView, NULL); Relation matviewRel = heap_open(matviewOid, AccessShareLock); /* Make sure it is a materialized view. */ diff --git a/src/gausskernel/optimizer/commands/tablecmds.cpp b/src/gausskernel/optimizer/commands/tablecmds.cpp index 337c62dd6..f5b9d406e 100755 --- a/src/gausskernel/optimizer/commands/tablecmds.cpp +++ b/src/gausskernel/optimizer/commands/tablecmds.cpp @@ -21920,6 +21920,51 @@ void RangeVarCallbackOwnsTable(const RangeVar* relation, Oid relId, Oid oldRelId } } +/* + * This is intended as a callback for RangeVarGetRelidExtended(). It allows + * the relation to be locked only if (1) it's a materialized view and + * (2) the current user is the owner (or the superuser). + * This meets the permission-checking needs of and REFRESH MATERIALIZED VIEW; + * we expose it here so that it can be used by all. + */ +void RangeVarCallbackOwnsMatView(const RangeVar* relation, Oid relId, Oid oldRelId, bool target_is_partition, void* arg) +{ + char relkind; + + /* Nothing to do if the relation was not found. */ + if (!OidIsValid(relId)) { + return; + } + + /* + * If the relation does exist, check whether it's an index. But note that + * the relation might have been dropped between the time we did the name + * lookup and now. In that case, there's nothing to do. + */ + relkind = get_rel_relkind(relId); + if (!relkind) { + return; + } + if (relkind != RELKIND_RELATION && + relkind != RELKIND_TOASTVALUE && + relkind != RELKIND_MATVIEW) { + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("\"%s\" is not a table or materialized view", relation->relname))); + } + + /* Check permissions */ + AclResult aclresult = pg_class_aclcheck(relId, GetUserId(), ACL_INSERT | ACL_DELETE); + if (aclresult != ACLCHECK_OK) { + aclcheck_error(aclresult, ACL_KIND_CLASS, relation->relname); + } + + bool is_owner = pg_class_ownercheck(relId, GetUserId()); + if (!is_owner) { + aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS, relation->relname); + } +} + /* * Callback to RangeVarGetRelidExtended(), similar to * RangeVarCallbackOwnsTable() but without checks on the type of the relation. diff --git a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp index ece65fcf5..38073a378 100644 --- a/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp +++ b/src/gausskernel/optimizer/rewrite/rewriteHandler.cpp @@ -4974,7 +4974,7 @@ List *QueryRewriteRefresh(Query *parse_tree) */ matviewOid = RangeVarGetRelidExtended(stmt->relation, AccessExclusiveLock, false, false, false, false, - RangeVarCallbackOwnsTable, NULL); + RangeVarCallbackOwnsMatView, NULL); matviewRel = heap_open(matviewOid, NoLock); /* Make sure it is a materialized view. */ diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h index aa35104f9..b0a0339d3 100644 --- a/src/include/commands/tablecmds.h +++ b/src/include/commands/tablecmds.h @@ -181,6 +181,8 @@ extern void DropTableThrowErrorExternal(RangeVar* relation, ObjectType removeTyp extern void RangeVarCallbackOwnsTable( const RangeVar* relation, Oid relId, Oid oldRelId, bool target_is_partition, void* arg); +extern void RangeVarCallbackOwnsMatView( + const RangeVar* relation, Oid relId, Oid oldRelId, bool target_is_partition, void* arg); extern void RangeVarCallbackOwnsRelation( const RangeVar* relation, Oid relId, Oid oldRelId, bool target_is_partition, void* noCatalogs); extern void checkPartNotInUse(Partition part, const char* stmt); diff --git a/src/test/regress/expected/matview_single.out b/src/test/regress/expected/matview_single.out index 72131ba65..4d3c4042e 100644 --- a/src/test/regress/expected/matview_single.out +++ b/src/test/regress/expected/matview_single.out @@ -141,5 +141,39 @@ drop table test_syn cascade; NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to materialized view mv_test_syn drop cascades to materialized view imv_test_syn +-- test about the privileges of refresh +create table t (id int); +insert into t select generate_series(1,10); +create materialized view mv_t as select * from t; +create user testuser with password 'Gauss@123'; +grant usage on schema public to testuser; +grant select on t to testuser; +grant select on mv_t to testuser; +set role testuser password 'Gauss@123'; +-- failed, permission denied +refresh materialized view mv_t; +ERROR: permission denied for relation mv_t +DETAIL: N/A +reset role; +grant delete,insert on mv_t to testuser; +set role testuser password 'Gauss@123'; +-- failed, permission denied +refresh materialized view mv_t; +ERROR: must be owner of relation mv_t +DETAIL: N/A +reset role; +grant index on mv_t to testuser; +set role testuser password 'Gauss@123'; +-- failed, permission denied +refresh materialized view mv_t; +ERROR: must be owner of relation mv_t +DETAIL: N/A +reset role; +alter table mv_t owner to testuser; +set role testuser password 'Gauss@123'; +-- success +refresh materialized view mv_t; +reset role; +drop user testuser cascade; \c regression drop database test_imv_db; diff --git a/src/test/regress/sql/matview_single.sql b/src/test/regress/sql/matview_single.sql index 56eca85d1..6f1502b9d 100644 --- a/src/test/regress/sql/matview_single.sql +++ b/src/test/regress/sql/matview_single.sql @@ -72,5 +72,37 @@ drop synonym s_mv_test_syn; drop synonym s_imv_test_syn; drop table test_syn cascade; +-- test about the privileges of refresh +create table t (id int); +insert into t select generate_series(1,10); +create materialized view mv_t as select * from t; +create user testuser with password 'Gauss@123'; +grant usage on schema public to testuser; +grant select on t to testuser; +grant select on mv_t to testuser; + +set role testuser password 'Gauss@123'; +-- failed, permission denied +refresh materialized view mv_t; +reset role; +grant delete,insert on mv_t to testuser; +set role testuser password 'Gauss@123'; +-- failed, permission denied +refresh materialized view mv_t; +reset role; +grant index on mv_t to testuser; +set role testuser password 'Gauss@123'; +-- failed, permission denied +refresh materialized view mv_t; + +reset role; +alter table mv_t owner to testuser; +set role testuser password 'Gauss@123'; +-- success +refresh materialized view mv_t; + +reset role; +drop user testuser cascade; + \c regression drop database test_imv_db;