@@ -2059,6 +2059,295 @@ DROP TABLE multip;
20592059statement ok
20602060DROP USER multi_user;
20612061
2062- subtest multiple_insert_policies
2062+ # This is another test for multiple policies. But the focus here is how multiple
2063+ # policies are applied when they apply for other commands. For example, having
2064+ # a policy that applies to SELECT and a policy that applies to DELETE.
2065+ subtest multi_policies_multi_cmd
2066+
2067+ statement ok
2068+ create table r1 (c1 int);
2069+
2070+ statement ok
2071+ alter table r1 enable row level security;
2072+
2073+ statement ok
2074+ insert into r1 values (0),(1),(2),(3),(4),(5),(22);
2075+
2076+ statement ok
2077+ create policy sel1 on r1 for select using (c1 % 2 = 0);
2078+
2079+ statement ok
2080+ create policy upd1 on r1 for update using (c1 between 0 and 20);
2081+
2082+ statement ok
2083+ create user r1_user;
2084+
2085+ statement ok
2086+ grant all on r1 to r1_user;
2087+
2088+ statement ok
2089+ set role r1_user;
2090+
2091+ # UPDATE should only apply to the combination of both policies.
2092+ statement ok
2093+ update r1 set c1 = c1 ;
2094+
2095+ query I rowsort
2096+ update r1 set c1 = c1 returning c1;
2097+ ----
2098+ 0
2099+ 2
2100+ 4
2101+
2102+ statement error pq: new row violates row-level security policy for table "r1"
2103+ update r1 set c1 = c1 + 1;
2104+
2105+ statement error pq: new row violates row-level security policy for table "r1"
2106+ update r1 set c1 = c1 + 1 where c1 between 1 and 3;
2107+
2108+ statement ok
2109+ update r1 set c1 = c1 + 2 where c1 between 1 and 10;
2110+
2111+ query I rowsort
2112+ update r1 set c1 = c1 + 2 where c1 between 1 and 10 returning c1;
2113+ ----
2114+ 6
2115+ 8
2116+
2117+ query I
2118+ update r1 set c1 = c1 + 2 where c1 > 20 returning c1;
2119+ ----
2120+
2121+ query I rowsort
2122+ SELECT * FROM r1;
2123+ ----
2124+ 0
2125+ 6
2126+ 8
2127+ 22
2128+
2129+ statement ok
2130+ SET ROLE root;
2131+
2132+ query I rowsort
2133+ SELECT * FROM r1;
2134+ ----
2135+ 0
2136+ 1
2137+ 3
2138+ 5
2139+ 6
2140+ 8
2141+ 22
2142+
2143+ statement ok
2144+ DROP TABLE r1;
2145+
2146+ # Do another test of select and update policies, but use simple expressions and
2147+ # try out different combinations of those expressions.
2148+ statement ok
2149+ CREATE TABLE cnt (counter INT);
2150+
2151+ statement ok
2152+ INSERT INTO cnt VALUES (1);
2153+
2154+ statement ok
2155+ GRANT ALL ON cnt TO r1_user;
2156+
2157+ statement ok
2158+ ALTER TABLE cnt ENABLE ROW LEVEL SECURITY, FORCE ROW LEVEL SECURITY;
2159+
2160+ statement ok
2161+ ALTER TABLE cnt OWNER TO r1_user;
2162+
2163+ statement ok
2164+ SET ROLE r1_user;
2165+
2166+ statement ok
2167+ CREATE POLICY upd1 ON cnt FOR UPDATE USING (true);
2168+
2169+ # Only an UPDATE policy and no SELECT policy. Nothing is updated.
2170+ query I
2171+ UPDATE cnt SET counter = counter + 1 RETURNING counter;
2172+ ----
2173+
2174+ # Now create only a SELECT policy. Same behaviour as before.
2175+ statement ok
2176+ DROP POLICY upd1 ON cnt;
2177+
2178+ statement ok
2179+ CREATE POLICY sel1 ON cnt FOR SELECT USING (true);
2180+
2181+ query I
2182+ SELECT * FROM cnt;
2183+ ----
2184+ 1
2185+
2186+ # Any locking modes on the query will cause the UPDATE policies to be applied,
2187+ # which will filter out the row.
2188+ query I
2189+ SELECT * FROM cnt FOR UPDATE;
2190+ ----
2191+
2192+
2193+ query I
2194+ SELECT * FROM cnt FOR SHARE;
2195+ ----
2196+
2197+
2198+ let $cnt_oid
2199+ SELECT 'cnt'::REGCLASS::OID;
2200+
2201+ query I
2202+ SELECT * FROM [$cnt_oid as t];
2203+ ----
2204+ 1
2205+
2206+ query I
2207+ SELECT * FROM [$cnt_oid as t] FOR UPDATE;
2208+ ----
2209+
2210+ query I
2211+ SELECT * FROM [$cnt_oid as t] FOR SHARE;
2212+ ----
2213+
2214+ # Update with a SELECT policy but no UPDATE policy. Nothing should be returned.
2215+ query I
2216+ UPDATE cnt SET counter = counter + 1 RETURNING counter;
2217+ ----
2218+
2219+ # Now add a SELECT policy, but it still filters everything out.
2220+ statement ok
2221+ CREATE POLICY upd1 ON cnt FOR UPDATE USING (false);
2222+
2223+ # Same as before, no update occurs because the reading of existing rows filters
2224+ # everything out.
2225+ query I
2226+ UPDATE cnt SET counter = counter + 1 RETURNING counter;
2227+ ----
2228+
2229+ # Now replace the UPDATE policy with one that allows everything.
2230+ statement ok
2231+ DROP POLICY upd1 ON cnt;
2232+
2233+ statement ok
2234+ CREATE POLICY upd1 ON cnt FOR UPDATE USING (true);
2235+
2236+ query I
2237+ UPDATE cnt SET counter = counter + 1 RETURNING counter;
2238+ ----
2239+ 2
2240+
2241+ # Update the UPDATE policy so that it allows old rows but blocks all new rows.
2242+ statement ok
2243+ DROP POLICY upd1 ON cnt;
2244+
2245+ statement ok
2246+ CREATE POLICY upd1 ON cnt FOR UPDATE USING (true) WITH CHECK (false);
2247+
2248+ # We are able to read the row but cannot write a new row as it violates the
2249+ # update policy.
2250+ statement error pq: new row violates row-level security policy for table "cnt"
2251+ UPDATE cnt SET counter = counter + 1 RETURNING counter;
2252+
2253+ # Verify that select policy (true) with no delete policy will not delete anything.
2254+ query I
2255+ delete from cnt where counter is not null returning counter;
2256+ ----
2257+
2258+ statement ok
2259+ delete from cnt;
2260+
2261+ query I
2262+ select counter from cnt;
2263+ ----
2264+ 2
2265+
2266+ # Now change the select policy to be always false, and delete policy to be always true.
2267+ statement ok
2268+ DROP POLICY sel1 ON cnt;
2269+
2270+ statement ok
2271+ CREATE POLICY sel1 ON cnt FOR SELECT USING (false);
2272+
2273+ statement ok
2274+ CREATE POLICY del1 ON cnt FOR DELETE USING (true);
2275+
2276+ query I
2277+ delete from cnt where counter > 0 returning counter;
2278+ ----
2279+
2280+ statement ok
2281+ delete from cnt;
2282+
2283+ statement ok
2284+ ALTER TABLE cnt NO FORCE ROW LEVEL SECURITY;
2285+
2286+ query I
2287+ SELECT counter FROM cnt;
2288+ ----
2289+ 2
2290+
2291+ # Drop the select policy entirely. It should be no different than a deny-all select policy.
2292+ statement ok
2293+ DROP POLICY sel1 ON cnt;
2294+
2295+ statement ok
2296+ ALTER TABLE cnt FORCE ROW LEVEL SECURITY;
2297+
2298+ query I
2299+ delete from cnt where counter > 0 returning counter;
2300+ ----
2301+
2302+ statement ok
2303+ delete from cnt;
2304+
2305+ statement ok
2306+ ALTER TABLE cnt NO FORCE ROW LEVEL SECURITY;
2307+
2308+ query I
2309+ SELECT counter FROM cnt;
2310+ ----
2311+ 2
2312+
2313+ statement ok
2314+ ALTER TABLE cnt FORCE ROW LEVEL SECURITY;
2315+
2316+ # Now change the select policy to always return true, and delete policy to always return false.
2317+ statement ok
2318+ DROP POLICY del1 ON cnt;
2319+
2320+ statement ok
2321+ CREATE POLICY sel1 ON cnt FOR SELECT USING (true);
2322+
2323+ statement ok
2324+ CREATE POLICY del1 ON cnt FOR DELETE USING (false);
2325+
2326+ query I
2327+ DELETE FROM cnt WHERE counter > 0 RETURNING counter;
2328+ ----
2329+
2330+ statement ok
2331+ DELETE FROM cnt;
2332+
2333+ statement ok
2334+ ALTER TABLE cnt NO FORCE ROW LEVEL SECURITY;
2335+
2336+ query I
2337+ SELECT counter FROM cnt;
2338+ ----
2339+ 2
2340+
2341+ statement ok
2342+ ALTER TABLE cnt NO FORCE ROW LEVEL SECURITY;
2343+
2344+ statement ok
2345+ SET ROLE root
2346+
2347+ statement ok
2348+ DROP TABLE cnt;
2349+
2350+ statement ok
2351+ DROP USER r1_user;
20632352
20642353subtest end
0 commit comments