On 3/7/21 2:35 PM, Zhihong Yu wrote: > Joe: > I don't seem to find attachment. > > Maybe attach again ?
Oops -- I did forget that, didn't I. This time patch is attached :-) Joe -- Crunchy Data - http://crunchydata.com PostgreSQL Support for Secure Enterprises Consulting, Training, & Open Source Development
diff --git a/src/backend/utils/adt/acl.c b/src/backend/utils/adt/acl.c index c7f029e..152d1da 100644 *** a/src/backend/utils/adt/acl.c --- b/src/backend/utils/adt/acl.c *************** column_privilege_check(Oid tableoid, Att *** 2460,2484 **** return -1; /* ! * First check if we have the privilege at the table level. We check ! * existence of the pg_class row before risking calling pg_class_aclcheck. ! * Note: it might seem there's a race condition against concurrent DROP, ! * but really it's safe because there will be no syscache flush between ! * here and there. So if we see the row in the syscache, so will ! * pg_class_aclcheck. ! */ ! if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid))) ! return -1; ! ! aclresult = pg_class_aclcheck(tableoid, roleid, mode); ! ! if (aclresult == ACLCHECK_OK) ! return true; ! ! /* ! * No table privilege, so try per-column privileges. Again, we have to ! * check for dropped attribute first, and we rely on the syscache not to ! * notice a concurrent drop before pg_attribute_aclcheck fetches the row. */ attTuple = SearchSysCache2(ATTNUM, ObjectIdGetDatum(tableoid), --- 2460,2468 ---- return -1; /* ! * We have to check for dropped attribute first, and we rely on the ! * syscache not to notice a concurrent drop before pg_attribute_aclcheck ! * fetches the row. */ attTuple = SearchSysCache2(ATTNUM, ObjectIdGetDatum(tableoid), *************** column_privilege_check(Oid tableoid, Att *** 2493,2498 **** --- 2477,2499 ---- } ReleaseSysCache(attTuple); + /* + * Now check if we have the privilege at the table level. We check + * existence of the pg_class row before risking calling pg_class_aclcheck. + * Note: it might seem there's a race condition against concurrent DROP, + * but really it's safe because there will be no syscache flush between + * here and there. So if we see the row in the syscache, so will + * pg_class_aclcheck. + */ + if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(tableoid))) + return -1; + + aclresult = pg_class_aclcheck(tableoid, roleid, mode); + + if (aclresult == ACLCHECK_OK) + return true; + + /* no table privilege, so try per-column privilege */ aclresult = pg_attribute_aclcheck(tableoid, attnum, roleid, mode); return (aclresult == ACLCHECK_OK); diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out index 46a69fc..d60ea53 100644 *** a/src/test/regress/expected/privileges.out --- b/src/test/regress/expected/privileges.out *************** select has_column_privilege('mytable','. *** 1362,1368 **** select has_column_privilege('mytable',2::int2,'select'); has_column_privilege ---------------------- ! t (1 row) revoke select on table mytable from regress_priv_user3; --- 1362,1374 ---- select has_column_privilege('mytable',2::int2,'select'); has_column_privilege ---------------------- ! ! (1 row) ! ! select has_column_privilege('mytable',99::int2,'select'); ! has_column_privilege ! ---------------------- ! (1 row) revoke select on table mytable from regress_priv_user3; diff --git a/src/test/regress/sql/privileges.sql b/src/test/regress/sql/privileges.sql index 6277140..766eeae 100644 *** a/src/test/regress/sql/privileges.sql --- b/src/test/regress/sql/privileges.sql *************** alter table mytable drop column f2; *** 836,841 **** --- 836,842 ---- select has_column_privilege('mytable','f2','select'); select has_column_privilege('mytable','........pg.dropped.2........','select'); select has_column_privilege('mytable',2::int2,'select'); + select has_column_privilege('mytable',99::int2,'select'); revoke select on table mytable from regress_priv_user3; select has_column_privilege('mytable',2::int2,'select'); drop table mytable;