-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 07/28/2015 12:32 AM, Dean Rasheed wrote: >> On 07/27/2015 03:05 PM, Stephen Frost wrote: >>> AFK at the moment, but my thinking was that we should avoid >>> having the error message change based on what a GUC is set to. >>> I agree that there should be comments which explain that. > > Except it's already dependent on the GUC if it's set to FORCE.
Dean is correct. See test case below... >> I changed back to using GetUserId() for the call to >> check_enable_rls() at those three call sites, and added to the >> comments to explain why. >> > > I'm not entirely convinced about this. The more I think about it, > the more I think that if we know the user has BYPASSRLS, and > they've set row_security to OFF, then they ought to get the more > detailed error message, as they would if there was no RLS. That > error detail is highly useful, and we know the user has been > granted privilege by a superuser, and that they have direct access > to the underlying table in this context, so we're not leaking any > info that they cannot directly SELECT anyway. Agreed -- this patch version goes back to using InvalidOid at those three call sites and the behavior is what I now believe to be correct. Here is a test case to illustrate: 8<-------------------- BEGIN; CREATE ROLE alice; CREATE ROLE bob WITH BYPASSRLS; SET SESSION AUTHORIZATION alice; CREATE TABLE t1 (id int primary key, f1 text); INSERT INTO t1 VALUES(1,'a'); CREATE TABLE t2 (id int primary key, f1 text, t1_id int REFERENCES t1(id)); GRANT ALL ON t2 TO bob; ALTER TABLE t2 ENABLE ROW LEVEL SECURITY; CREATE POLICY P ON t2 TO alice, bob USING (true); SET SESSION AUTHORIZATION bob; INSERT INTO t2 VALUES(1,'a',1); -- should succeed SAVEPOINT q; INSERT INTO t2 VALUES(2,'b',2); -- should fail, no details ROLLBACK TO q; SET row_security = OFF; SAVEPOINT q; INSERT INTO t2 VALUES(2,'b',2); -- should fail, full details ROLLBACK TO q; SET SESSION AUTHORIZATION alice; SAVEPOINT q; INSERT INTO t2 VALUES(2,'b',2); -- should fail, full details ROLLBACK TO q; SET row_security = FORCE; SAVEPOINT q; INSERT INTO t2 VALUES(2,'b',2); -- should fail, no details ROLLBACK TO q; ROLLBACK; 8<-------------------- I'm going to commit the attached in the next few hours unless someone has serious objections. We can always revisit the specific behavior of those messages separately if we change our minds... Joe -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.22 (GNU/Linux) iQIcBAEBAgAGBQJVt8dQAAoJEDfy90M199hl1ncQAI/XUZ3VSoW0Vegf09Y2DqlJ f8lGnwSf+djSXgKVrUsKQsuLn7c+Ac9fqoRUQJMuCcOvnu7auljzaMjuMjrXhOIC hhiP8QyYUoEMF+5Sggh/A532rFXRbI1R/g9eu8TTT9vJGkITVMGAucizSY+fPiBg gH3JyuCVaIZbvlVv0OkqPXPiP1VR/7bDTBcIbv56XHOk1AavNlUMW5BWWR0/9Mt8 VMh9ri3eQ5beKxrDhAZ+39ddlQzk9yJsN5pd/Pu0zPNxwBcvTNra0ZZGv7PoPwUF 7F98A1bL/NWFDdFuOI2E61/a5lA70t5HV4UTPPugQr82NhBS9JdpxgqA8W7B9+P9 4TKqmmYIvOcxM+TtglIlyr+JBwfJERw8j3+IcnM3mjLnkyflNbX2kbOF0B5Ghpt/ EzrVIJi/Pl3ctm+9r/oQYiwo/6Qsy8hco9QLCY4GVhBEE93Wr8P6NVlcjzyocMRs FBjgvxeL/1wL8g3Q8ZDsAVOu9Ld0OCGEkA27XRS3sXbZfHroeTNW5aUqvKIzFkKB gsr09pIVtdd7ysEdxxHZpELaU8H2rcA5O8b380HauIi41GaDc5E0XLXJSu6dIWCP x/Em3qTpt74YgZiqsbs3a21Ak5n8fBdTMyXhmPQbXctllALI3Kj7bbyqoeGywpxi PKhGDzgw+M7OQzfWS7UF =e5Qo -----END PGP SIGNATURE-----
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index 98d1497..fd82ea4 100644 *** a/doc/src/sgml/func.sgml --- b/doc/src/sgml/func.sgml *************** SET search_path TO <replaceable>schema</ *** 15259,15264 **** --- 15259,15270 ---- <entry><type>boolean</type></entry> <entry>does current user have privilege for role</entry> </row> + <row> + <entry><literal><function>row_security_active</function>(<parameter>table</parameter>)</literal> + </entry> + <entry><type>boolean</type></entry> + <entry>does current user have row level security active for table</entry> + </row> </tbody> </tgroup> </table> *************** SET search_path TO <replaceable>schema</ *** 15299,15304 **** --- 15305,15313 ---- <indexterm> <primary>pg_has_role</primary> </indexterm> + <indexterm> + <primary>row_security_active</primary> + </indexterm> <para> <function>has_table_privilege</function> checks whether a user *************** SELECT has_function_privilege('joeuser', *** 15462,15467 **** --- 15471,15483 ---- are immediately available without doing <command>SET ROLE</>. </para> + <para> + <function>row_security_active</function> checks whether row level + security is active for the specified table in the context of the + <function>current_user</function> and environment. The table can + be specified by name or by OID. + </para> + <para> <xref linkend="functions-info-schema-table"> shows functions that determine whether a certain object is <firstterm>visible</> in the diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c index 1043362..aa5b28c 100644 *** a/src/backend/access/index/genam.c --- b/src/backend/access/index/genam.c *************** BuildIndexValueDescription(Relation inde *** 204,210 **** Assert(indexrelid == idxrec->indexrelid); /* RLS check- if RLS is enabled then we don't return anything. */ ! if (check_enable_rls(indrelid, GetUserId(), true) == RLS_ENABLED) { ReleaseSysCache(ht_idx); return NULL; --- 204,210 ---- Assert(indexrelid == idxrec->indexrelid); /* RLS check- if RLS is enabled then we don't return anything. */ ! if (check_enable_rls(indrelid, InvalidOid, true) == RLS_ENABLED) { ReleaseSysCache(ht_idx); return NULL; diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index e82a53a..c0bd6fa 100644 *** a/src/backend/catalog/system_views.sql --- b/src/backend/catalog/system_views.sql *************** CREATE VIEW pg_indexes AS *** 150,156 **** LEFT JOIN pg_tablespace T ON (T.oid = I.reltablespace) WHERE C.relkind IN ('r', 'm') AND I.relkind = 'i'; ! CREATE VIEW pg_stats AS SELECT nspname AS schemaname, relname AS tablename, --- 150,156 ---- LEFT JOIN pg_tablespace T ON (T.oid = I.reltablespace) WHERE C.relkind IN ('r', 'm') AND I.relkind = 'i'; ! CREATE VIEW pg_stats WITH (security_barrier) AS SELECT nspname AS schemaname, relname AS tablename, *************** CREATE VIEW pg_stats AS *** 211,217 **** FROM pg_statistic s JOIN pg_class c ON (c.oid = s.starelid) JOIN pg_attribute a ON (c.oid = attrelid AND attnum = s.staattnum) LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace) ! WHERE NOT attisdropped AND has_column_privilege(c.oid, a.attnum, 'select'); REVOKE ALL on pg_statistic FROM public; --- 211,219 ---- FROM pg_statistic s JOIN pg_class c ON (c.oid = s.starelid) JOIN pg_attribute a ON (c.oid = attrelid AND attnum = s.staattnum) LEFT JOIN pg_namespace n ON (n.oid = c.relnamespace) ! WHERE NOT attisdropped ! AND has_column_privilege(c.oid, a.attnum, 'select') ! AND (c.relrowsecurity = false OR NOT row_security_active(c.oid)); REVOKE ALL on pg_statistic FROM public; diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c index a1561ce..2c65a90 100644 *** a/src/backend/executor/execMain.c --- b/src/backend/executor/execMain.c *************** ExecBuildSlotValueDescription(Oid reloid *** 1874,1880 **** * then don't return anything. Otherwise, go through normal permission * checks. */ ! if (check_enable_rls(reloid, GetUserId(), true) == RLS_ENABLED) return NULL; initStringInfo(&buf); --- 1874,1880 ---- * then don't return anything. Otherwise, go through normal permission * checks. */ ! if (check_enable_rls(reloid, InvalidOid, true) == RLS_ENABLED) return NULL; initStringInfo(&buf); diff --git a/src/backend/rewrite/rowsecurity.c b/src/backend/rewrite/rowsecurity.c index aaf0061..2386cf0 100644 *** a/src/backend/rewrite/rowsecurity.c --- b/src/backend/rewrite/rowsecurity.c *************** get_row_security_policies(Query *root, C *** 107,113 **** Relation rel; Oid user_id; - int sec_context; int rls_status; bool defaultDeny = false; --- 107,112 ---- *************** get_row_security_policies(Query *root, C *** 117,138 **** *hasRowSecurity = false; *hasSubLinks = false; ! /* This is just to get the security context */ ! GetUserIdAndSecContext(&user_id, &sec_context); /* Switch to checkAsUser if it's set */ user_id = rte->checkAsUser ? rte->checkAsUser : GetUserId(); - /* - * If this is not a normal relation, or we have been told to explicitly - * skip RLS (perhaps because this is an FK check) then just return - * immediately. - */ - if (rte->relid < FirstNormalObjectId - || rte->relkind != RELKIND_RELATION - || (sec_context & SECURITY_ROW_LEVEL_DISABLED)) - return; - /* Determine the state of RLS for this, pass checkAsUser explicitly */ rls_status = check_enable_rls(rte->relid, rte->checkAsUser, false); --- 116,128 ---- *hasRowSecurity = false; *hasSubLinks = false; ! /* If this is not a normal relation, just return immediately */ ! if (rte->relkind != RELKIND_RELATION) ! return; /* Switch to checkAsUser if it's set */ user_id = rte->checkAsUser ? rte->checkAsUser : GetUserId(); /* Determine the state of RLS for this, pass checkAsUser explicitly */ rls_status = check_enable_rls(rte->relid, rte->checkAsUser, false); diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index 88dd3fa..61edde9 100644 *** a/src/backend/utils/adt/ri_triggers.c --- b/src/backend/utils/adt/ri_triggers.c *************** ri_ReportViolation(const RI_ConstraintIn *** 3243,3249 **** * privileges. */ ! if (check_enable_rls(rel_oid, GetUserId(), true) != RLS_ENABLED) { aclresult = pg_class_aclcheck(rel_oid, GetUserId(), ACL_SELECT); if (aclresult != ACLCHECK_OK) --- 3243,3249 ---- * privileges. */ ! if (check_enable_rls(rel_oid, InvalidOid, true) != RLS_ENABLED) { aclresult = pg_class_aclcheck(rel_oid, GetUserId(), ACL_SELECT); if (aclresult != ACLCHECK_OK) *************** ri_ReportViolation(const RI_ConstraintIn *** 3264,3269 **** --- 3264,3271 ---- } } } + else + has_perm = false; if (has_perm) { diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index e6808e7..525794f 100644 *** a/src/backend/utils/cache/plancache.c --- b/src/backend/utils/cache/plancache.c *************** CreateCachedPlan(Node *raw_parse_tree, *** 153,160 **** CachedPlanSource *plansource; MemoryContext source_context; MemoryContext oldcxt; - Oid user_id; - int security_context; Assert(query_string != NULL); /* required as of 8.4 */ --- 153,158 ---- *************** CreateCachedPlan(Node *raw_parse_tree, *** 177,184 **** */ oldcxt = MemoryContextSwitchTo(source_context); - GetUserIdAndSecContext(&user_id, &security_context); - plansource = (CachedPlanSource *) palloc0(sizeof(CachedPlanSource)); plansource->magic = CACHEDPLANSOURCE_MAGIC; plansource->raw_parse_tree = copyObject(raw_parse_tree); --- 175,180 ---- *************** CreateCachedPlan(Node *raw_parse_tree, *** 208,215 **** plansource->total_custom_cost = 0; plansource->num_custom_plans = 0; plansource->hasRowSecurity = false; ! plansource->rowSecurityDisabled ! = (security_context & SECURITY_ROW_LEVEL_DISABLED) != 0; plansource->row_security_env = row_security; plansource->planUserId = InvalidOid; --- 204,210 ---- plansource->total_custom_cost = 0; plansource->num_custom_plans = 0; plansource->hasRowSecurity = false; ! plansource->rowSecurityDisabled = InRowLevelSecurityDisabled(); plansource->row_security_env = row_security; plansource->planUserId = InvalidOid; diff --git a/src/backend/utils/init/miscinit.c b/src/backend/utils/init/miscinit.c index acc4752..ac3e764 100644 *** a/src/backend/utils/init/miscinit.c --- b/src/backend/utils/init/miscinit.c *************** GetAuthenticatedUserId(void) *** 341,347 **** * GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID * and the SecurityRestrictionContext flags. * ! * Currently there are two valid bits in SecurityRestrictionContext: * * SECURITY_LOCAL_USERID_CHANGE indicates that we are inside an operation * that is temporarily changing CurrentUserId via these functions. This is --- 341,347 ---- * GetUserIdAndSecContext/SetUserIdAndSecContext - get/set the current user ID * and the SecurityRestrictionContext flags. * ! * Currently there are three valid bits in SecurityRestrictionContext: * * SECURITY_LOCAL_USERID_CHANGE indicates that we are inside an operation * that is temporarily changing CurrentUserId via these functions. This is *************** GetAuthenticatedUserId(void) *** 359,364 **** --- 359,367 ---- * where the called functions are really supposed to be side-effect-free * anyway, such as VACUUM/ANALYZE/REINDEX. * + * SECURITY_ROW_LEVEL_DISABLED indicates that we are inside an operation that + * needs to bypass row level security checks, for example FK checks. + * * Unlike GetUserId, GetUserIdAndSecContext does *not* Assert that the current * value of CurrentUserId is valid; nor does SetUserIdAndSecContext require * the new value to be valid. In fact, these routines had better not *************** InSecurityRestrictedOperation(void) *** 401,406 **** --- 404,418 ---- return (SecurityRestrictionContext & SECURITY_RESTRICTED_OPERATION) != 0; } + /* + * InRowLevelSecurityDisabled - are we inside a RLS-disabled operation? + */ + bool + InRowLevelSecurityDisabled(void) + { + return (SecurityRestrictionContext & SECURITY_ROW_LEVEL_DISABLED) != 0; + } + /* * These are obsolete versions of Get/SetUserIdAndSecContext that are diff --git a/src/backend/utils/misc/rls.c b/src/backend/utils/misc/rls.c index 44cb374..7b8d51d 100644 *** a/src/backend/utils/misc/rls.c --- b/src/backend/utils/misc/rls.c *************** *** 16,24 **** --- 16,27 ---- #include "access/htup.h" #include "access/htup_details.h" + #include "access/transam.h" #include "catalog/pg_class.h" + #include "catalog/namespace.h" #include "miscadmin.h" #include "utils/acl.h" + #include "utils/builtins.h" #include "utils/elog.h" #include "utils/rls.h" #include "utils/syscache.h" *************** extern int check_enable_rls(Oid relid, O *** 37,43 **** * for the table and the plan cache needs to be invalidated if the environment * changes. * ! * Handle checking as another role via checkAsUser (for views, etc). * * If noError is set to 'true' then we just return RLS_ENABLED instead of doing * an ereport() if the user has attempted to bypass RLS and they are not --- 40,49 ---- * for the table and the plan cache needs to be invalidated if the environment * changes. * ! * Handle checking as another role via checkAsUser (for views, etc). Note that ! * if *not* checking as another role, the caller should pass InvalidOid rather ! * than GetUserId(). Otherwise the check for row_security = OFF is skipped, and ! * so we may falsely report that RLS is active when the user has bypassed it. * * If noError is set to 'true' then we just return RLS_ENABLED instead of doing * an ereport() if the user has attempted to bypass RLS and they are not *************** check_enable_rls(Oid relid, Oid checkAsU *** 53,58 **** --- 59,75 ---- bool relrowsecurity; Oid user_id = checkAsUser ? checkAsUser : GetUserId(); + /* Nothing to do for built-in relations */ + if (relid < FirstNormalObjectId) + return RLS_NONE; + + /* + * Check if we have been told to explicitly skip RLS (perhaps because this + * is a foreign key check) + */ + if (InRowLevelSecurityDisabled()) + return RLS_NONE; + tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid)); if (!HeapTupleIsValid(tuple)) return RLS_NONE; *************** check_enable_rls(Oid relid, Oid checkAsU *** 111,113 **** --- 128,164 ---- /* RLS should be fully enabled for this relation. */ return RLS_ENABLED; } + + /* + * row_security_active + * + * check_enable_rls wrapped as a SQL callable function except + * RLS_NONE_ENV and RLS_NONE are the same for this purpose. + */ + Datum + row_security_active(PG_FUNCTION_ARGS) + { + /* By OID */ + Oid tableoid = PG_GETARG_OID(0); + int rls_status; + + rls_status = check_enable_rls(tableoid, InvalidOid, true); + PG_RETURN_BOOL(rls_status == RLS_ENABLED); + } + + Datum + row_security_active_name(PG_FUNCTION_ARGS) + { + /* By qualified name */ + text *tablename = PG_GETARG_TEXT_P(0); + RangeVar *tablerel; + Oid tableoid; + int rls_status; + + /* Look up table name. Can't lock it - we might not have privileges. */ + tablerel = makeRangeVarFromNameList(textToQualifiedNameList(tablename)); + tableoid = RangeVarGetRelid(tablerel, NoLock, false); + + rls_status = check_enable_rls(tableoid, InvalidOid, true); + PG_RETURN_BOOL(rls_status == RLS_ENABLED); + } diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 09bf143..2563bb9 100644 *** a/src/include/catalog/pg_proc.h --- b/src/include/catalog/pg_proc.h *************** DESCR("get progress for all replication *** 5343,5348 **** --- 5343,5354 ---- #define PROVOLATILE_STABLE 's' /* does not change within a scan */ #define PROVOLATILE_VOLATILE 'v' /* can change even within a scan */ + /* rls */ + DATA(insert OID = 3298 ( row_security_active PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 16 "26" _null_ _null_ _null_ _null_ _null_ row_security_active _null_ _null_ _null_ )); + DESCR("row security for current context active on table by table oid"); + DATA(insert OID = 3299 ( row_security_active PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 16 "25" _null_ _null_ _null_ _null_ _null_ row_security_active_name _null_ _null_ _null_ )); + DESCR("row security for current context active on table by table name"); + /* * Symbolic values for proargmodes column. Note that these must agree with * the FunctionParameterMode enum in parsenodes.h; we declare them here to diff --git a/src/include/miscadmin.h b/src/include/miscadmin.h index b539167..e0cc69f 100644 *** a/src/include/miscadmin.h --- b/src/include/miscadmin.h *************** extern void GetUserIdAndSecContext(Oid * *** 305,310 **** --- 305,311 ---- extern void SetUserIdAndSecContext(Oid userid, int sec_context); extern bool InLocalUserIdChange(void); extern bool InSecurityRestrictedOperation(void); + extern bool InRowLevelSecurityDisabled(void); extern void GetUserIdAndContext(Oid *userid, bool *sec_def_context); extern void SetUserIdAndContext(Oid userid, bool sec_def_context); extern void InitializeSessionUserId(const char *rolename, Oid useroid); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 49caa56..fc1679e 100644 *** a/src/include/utils/builtins.h --- b/src/include/utils/builtins.h *************** extern Datum set_config_by_name(PG_FUNCT *** 1121,1126 **** --- 1121,1130 ---- extern Datum show_all_settings(PG_FUNCTION_ARGS); extern Datum show_all_file_settings(PG_FUNCTION_ARGS); + /* rls.c */ + extern Datum row_security_active(PG_FUNCTION_ARGS); + extern Datum row_security_active_name(PG_FUNCTION_ARGS); + /* lockfuncs.c */ extern Datum pg_lock_status(PG_FUNCTION_ARGS); extern Datum pg_advisory_lock_int8(PG_FUNCTION_ARGS); diff --git a/src/test/regress/expected/rowsecurity.out b/src/test/regress/expected/rowsecurity.out index 72361e8..fd8e180 100644 *** a/src/test/regress/expected/rowsecurity.out --- b/src/test/regress/expected/rowsecurity.out *************** SELECT * FROM document d FULL OUTER JOIN *** 307,313 **** DELETE FROM category WHERE cid = 33; -- fails with FK violation ERROR: update or delete on table "category" violates foreign key constraint "document_cid_fkey" on table "document" ! DETAIL: Key (cid)=(33) is still referenced from table "document". -- can insert FK referencing invisible PK SET SESSION AUTHORIZATION rls_regress_user2; SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid; --- 307,313 ---- DELETE FROM category WHERE cid = 33; -- fails with FK violation ERROR: update or delete on table "category" violates foreign key constraint "document_cid_fkey" on table "document" ! DETAIL: Key is still referenced from table "document". -- can insert FK referencing invisible PK SET SESSION AUTHORIZATION rls_regress_user2; SELECT * FROM document d FULL OUTER JOIN category c on d.cid = c.cid; *************** SELECT * FROM current_check; *** 2887,2896 **** COMMIT; -- -- Collation support -- BEGIN; ! SET row_security = force; CREATE TABLE coll_t (c) AS VALUES ('bar'::text); CREATE POLICY coll_p ON coll_t USING (c < ('foo'::text COLLATE "C")); ALTER TABLE coll_t ENABLE ROW LEVEL SECURITY; --- 2887,2930 ---- COMMIT; -- + -- check pg_stats view filtering + -- + SET row_security TO ON; + SET SESSION AUTHORIZATION rls_regress_user0; + ANALYZE current_check; + -- Stats visible + SELECT row_security_active('current_check'); + row_security_active + --------------------- + f + (1 row) + + SELECT most_common_vals FROM pg_stats where tablename = 'current_check'; + most_common_vals + --------------------- + + + {rls_regress_user1} + (3 rows) + + SET SESSION AUTHORIZATION rls_regress_user1; + -- Stats not visible + SELECT row_security_active('current_check'); + row_security_active + --------------------- + t + (1 row) + + SELECT most_common_vals FROM pg_stats where tablename = 'current_check'; + most_common_vals + ------------------ + (0 rows) + + -- -- Collation support -- BEGIN; ! SET row_security TO FORCE; CREATE TABLE coll_t (c) AS VALUES ('bar'::text); CREATE POLICY coll_p ON coll_t USING (c < ('foo'::text COLLATE "C")); ALTER TABLE coll_t ENABLE ROW LEVEL SECURITY; diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index 1e5b0b9..6206c81 100644 *** a/src/test/regress/expected/rules.out --- b/src/test/regress/expected/rules.out *************** pg_stats| SELECT n.nspname AS schemaname *** 2061,2067 **** JOIN pg_class c ON ((c.oid = s.starelid))) JOIN pg_attribute a ON (((c.oid = a.attrelid) AND (a.attnum = s.staattnum)))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) ! WHERE ((NOT a.attisdropped) AND has_column_privilege(c.oid, a.attnum, 'select'::text)); pg_tables| SELECT n.nspname AS schemaname, c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, --- 2061,2067 ---- JOIN pg_class c ON ((c.oid = s.starelid))) JOIN pg_attribute a ON (((c.oid = a.attrelid) AND (a.attnum = s.staattnum)))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) ! WHERE ((NOT a.attisdropped) AND has_column_privilege(c.oid, a.attnum, 'select'::text) AND ((c.relrowsecurity = false) OR (NOT row_security_active(c.oid)))); pg_tables| SELECT n.nspname AS schemaname, c.relname AS tablename, pg_get_userbyid(c.relowner) AS tableowner, diff --git a/src/test/regress/sql/rowsecurity.sql b/src/test/regress/sql/rowsecurity.sql index f588fa2..32f10d8 100644 *** a/src/test/regress/sql/rowsecurity.sql --- b/src/test/regress/sql/rowsecurity.sql *************** SELECT * FROM current_check; *** 1190,1199 **** COMMIT; -- -- Collation support -- BEGIN; ! SET row_security = force; CREATE TABLE coll_t (c) AS VALUES ('bar'::text); CREATE POLICY coll_p ON coll_t USING (c < ('foo'::text COLLATE "C")); ALTER TABLE coll_t ENABLE ROW LEVEL SECURITY; --- 1190,1214 ---- COMMIT; -- + -- check pg_stats view filtering + -- + SET row_security TO ON; + SET SESSION AUTHORIZATION rls_regress_user0; + ANALYZE current_check; + -- Stats visible + SELECT row_security_active('current_check'); + SELECT most_common_vals FROM pg_stats where tablename = 'current_check'; + + SET SESSION AUTHORIZATION rls_regress_user1; + -- Stats not visible + SELECT row_security_active('current_check'); + SELECT most_common_vals FROM pg_stats where tablename = 'current_check'; + + -- -- Collation support -- BEGIN; ! SET row_security TO FORCE; CREATE TABLE coll_t (c) AS VALUES ('bar'::text); CREATE POLICY coll_p ON coll_t USING (c < ('foo'::text COLLATE "C")); ALTER TABLE coll_t ENABLE ROW LEVEL SECURITY;
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers