Robert Haas <robertmhaas@gmail.com> writes:
> There are a lot of things that are understandably forbidden in a
> read-only transaction, but one would not expect SELECT to be among
> them. And yet, one can get the system to complain about precisely
> that:
> ... This seems to be the result of this code in ExecCheckXactReadOnly:
> if ((rte->requiredPerms & (~ACL_SELECT)) == 0)
> continue;
> ...
> PreventCommandIfReadOnly(CreateCommandTag((Node *) plannedstmt));
> There's nothing obviously stupid about that, but the results in this
> case don't make much sense.
What's going on here is that we're checking the SELECT that is added
by the rule, and per TFM that executes before the UPDATE, so you get
this error first rather than one complaining about UPDATE (which you
would get later if this one hadn't interfered).
It's visible at this level that this PlannedStmt isn't the main query
(because it has canSetTag = 0), but that does not help much because
we have no very convenient way to find the main querytree. Anyway
you can construct related scenarios where the tag for the current
PlannedStmt probably *is* the thing to use, so I'm disinclined to
try to fix it by locating the main querytree to use the tag for that.
I think a more realistic way to fix it is to adjust rule expansion so that
the RTE generated for rules_src in the added query is marked with only the
privileges required for that query --- I imagine right now, we're just
copying the requiredPerms verbatim from the original query. There's
certainly no other obvious reason why an RTE in a SELECT (VALUES)
querytree would have the ACL_UPDATE bit set, as this one does.
regards, tom lane