It seems that postgres with enabled row level security on a table cannot properly optimize queries. The following example sql demonstrates the issue:
begin transaction;
create table entries (id int primary key);
alter table entries enable row level security;
create policy entries_policy on entries for all using (
current_setting('app.can_read_entries')::boolean = true
);
create role authenticated;
grant usage on schema public to authenticated;
grant select on all tables in schema public to authenticated;
set local app.can_read_entries = true;
explain
select * from entries
where (
current_setting('app.can_read_entries')::boolean = true
);
set local role 'authenticated';
explain
select * from entries;
rollback;
The execution plan as superadmin will be
Result (cost=0.01..35.51 rows=2550 width=4)
One-Time Filter: (current_setting('app.can_read_entries'::text))::boolean
-> Seq Scan on entries (cost=0.01..35.51 rows=2550 width=4)
whereas with row level security it will be
Seq Scan on entries (cost=0.00..54.63 rows=1275 width=4)
Filter: (current_setting('app.can_read_entries'::text))::boolean
I already read about the leakproof attribute on functions and tried setting the leakproof attribute on current_setting
and even went and tried update pg_proc set proleakproof = true;
.
However, no matter what I try, postgres will not properly optimize the query with row level security.