!4102 修复物化视图刷新权限检查的问题
Merge pull request !4102 from Cross-罗/privileges_mat
This commit is contained in:
@ -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. */
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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. */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
Reference in New Issue
Block a user