Re: COPY FROM with RLS

From: jian he <jian(dot)universality(at)gmail(dot)com>
To: Bryan Green <dbryan(dot)green(at)gmail(dot)com>
Cc: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: COPY FROM with RLS
Date: 2026-09-23 19:05:37
Message-ID: CACJufxEX3GD9XaG63M76fr-_QTt9ezVeSS3XvW=ZGhgr7K9LDg@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Fri, Sep 11, 2026 at 1:21 AM Bryan Green <dbryan(dot)green(at)gmail(dot)com> wrote:
>
> v15 checks out on the v3 items. Crash is gone on both an assert and a
> non-assert build, context is right, the rule cases error instead of
> redirecting, and quoting is fixed.
>
> The new one is the result of a forgotten guard. The WCO quals aren't in
> the volatile test that forces CIM_SINGLE, so under multi-insert a
> self-referential policy doesn't see the still-buffered rows and accepts
> ones a plain INSERT would reject.
>
> CREATE FUNCTION under_quota(o text) RETURNS bool LANGUAGE plpgsql VOLATILE
> AS $$ BEGIN RETURN (SELECT count(*) FROM q WHERE owner = o) < 3; END $$;
> CREATE POLICY ins ON q FOR INSERT WITH CHECK (under_quota(owner));
>
> INSERT of ten rows stops at the fourth. COPY takes all ten. A no-op
> BEFORE ROW trigger makes COPY stop at four as well, so it's the
> batching. Probably wants ri_WithCheckOptions in that CIM_SINGLE test,
> or just forced under RLS.
>

+ foreach_node(WithCheckOption, wco, resultRelInfo->ri_WithCheckOptions)
+ {
+ if (contain_subplans(wco->qual) ||
+ contain_volatile_functions(wco->qual))
+ {
+ volatile_wco = true;
+ break;
+ }
+ }
Make volatile expression and sub-select fall back to CIM_SINGLE should be fine.

> The wording "any rule that would apply to an INSERT" isn't quite right
> either. A conditional DO INSTEAD NOTHING stays one QSRC_ORIGINAL query
> and slips the three screens, so COPY inserts the row that would have
> dropped under INSERT with the rule.
>

We can use RelationData->rd_rules to check if a relation has rules
defined on it or not.

> Also, relname_only wraps the whole ExecWithCheckOptions call, so a
> non-violation error from a policy expression loses the "line x". This
> is because relname_only is true for anything the call raises, including
> errors that are not due to policy rejection. Maybe set the flag only
> around the violation report instead of the whole evaluation?
>
I am not sure about "non-violation error from a policy expression".
Currently check constraint violations produce an error line, but RLS
violations do not.

--
jian
https://www.enterprisedb.com/

Attachment Content-Type Size
v16-0001-COPY-FROM-with-RLS.patch text/x-patch 35.3 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Nathan Bossart 2026-09-23 19:10:29 Re: add list of major features to the v19 release notes
Previous Message Masahiko Sawada 2026-09-23 19:04:15 Re: Add REPACK progress phases for logical decoding setup