Re: INSERT ... ON CONFLICT UPDATE and RLS - Mailing list pgsql-hackers

From Dean Rasheed
Subject Re: INSERT ... ON CONFLICT UPDATE and RLS
Date
Msg-id CAEZATCXXY+kF2aP=JyiKvUJ=--4Q3gVPDi2DWWVZzB2gFNN-cw@mail.gmail.com
Whole thread Raw
In response to Re: INSERT ... ON CONFLICT UPDATE and RLS  (Stephen Frost <sfrost@snowman.net>)
Responses Re: INSERT ... ON CONFLICT UPDATE and RLS
List pgsql-hackers
On 9 January 2015 at 20:26, Stephen Frost <sfrost@snowman.net> wrote:
> Where this leaves me, at least, is feeling like we should always apply
> the INSERT WITH CHECK policy, then if there is a conflict, check the
> UPDATE USING policy and throw an error if the row isn't visible but
> otherwise perform the UPDATE and then check the UPDATE WITH CHECK
> policy.

Yeah, I can see the logic in that, but I'm starting to question the
final "then" in the above, i.e., the order in which the checks are
done.

Currently we're applying RLS CHECKs after the INSERT or UPDATE, like
WITH CHECK OPTIONs on views. The SQL spec says that WITH CHECK OPTIONs
on views have to be applied after the INSERT/UPDATE on the base
relation, but we're free to do something different for RLS CHECKs if
that makes more sense. If we want RLS to be more like column-level
privilege checking, then it does make sense to do the checks sooner,
so perhaps we should be checking the RLS policies before the
INSERT/UPDATE, like CHECK constraints.

Doing that, it makes sense to first check INSERT CHECK policies,
potentially throwing an error before any PK conflict is detected, so
an error would result even in the INSERT .. ON CONFLICT IGNORE case.
That way INSERT CHECK policies would always be applied regardless of
the path taken, as you suggest.

I would still say that the RLS UPDATE USING/CHECK policies should only
be applied if the UPDATE path is taken (before the UPDATE is applied),
and they need to be applied to the (old/new) update tuples only. It's
a bit like there is a WHERE <record already exists> clause attached to
the UPDATE. The RLS UPDATE policies should only be applied to the rows
affected by the UPDATE.

> I see your point that this runs counter to the 'mod_count'
> example use-case and could cause problems for users using RLS with such
> a strategy.  For my part, I expect users of RLS to expect errors in such
> a case rather than allowing it, but it's certainly a judgement call.
>

Actually I don't think this is a problem for the mod_count example.
This isn't the same as AND'ing together the INSERT and UPDATE quals,
because each set of policies is being applied to a different tuple.
There are 3 tuples in play here:-

1). The insert tuple, which has INSERT CHECK polcies applied to it
2). The existing (old) update tuple, which has UPDATE USING policies
applied to it
3). The (new) update tuple, which has UPDATE CHECK policies applied to it


NOTE: If we do change RLS CHECKs to be executed prior to modifying any
data, that's potentially a change that could be made independently of
the UPSERT patch. We should also probably then stop referring to them
as WITH CHECK OPTIONs in the docs and in error messages because
they're not the same thing, and the code might be neater if they had
their own data-structure rather than overloading WithCheckOption.

Regards,
Dean



pgsql-hackers by date:

Previous
From: "Erik Rijkers"
Date:
Subject: Re: POLA violation with \c service=
Next
From: Michael Paquier
Date:
Subject: Re: Fixing memory leak in pg_upgrade