On 26 February 2016 at 00:55, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> Dean Rasheed <dean.a.rasheed@gmail.com> writes:
>> Debugging it, I have a theory as to the cause of the problem, which I
>> think is in security_barrier_replace_vars() --- when it finds a
>> matching Var that needs to be added to the targetlist that it is
>> building, it copies the existing Var and modifies it:
>
>> /* New variable for subquery targetlist */
>> newvar = copyObject(var);
>> newvar->varno = newvar->varnoold = 1;
>> ...
>
>> However, the Var found comes from a sublink subquery in the outer
>> query, and so has varlevelsup = 1, but newvar is for the new subquery
>> being built, so it needs to have varlevelsup set to 0, which that code
>> fails to do.
>
Sorry, part of that description was inaccurate. The Var found is in a
sublink subquery in the *current* query, not an outer query. This code
of course never examines outer queries.
> Offhand, I'd think it more likely that this code should not be touching
> outer-level vars at all? There are few if any situations where it makes
> sense to suppose that a Var of one level should be transformed into a Var
> of a different level.
>
That's not really what it's doing. What's happenning here is that
expand_security_qual() is going to replace an RTE that has security
quals with a security barrier subquery RTE. So it searches the query
containing the RTE for any Vars that refer to it, in order to ensure
that the new RTE's subquery exposes the required columns, and the Vars
referring to that RTE are adjusted accordingly (not touching their
levels). In this case, the Var found is in the query's WHERE clause,
buried inside a sublink subquery, and so it has varlevelsup = 1. The
bug is simply that in building the *new* Var for the targetlist of the
new RTE subquery, it's copying the old Var but neglecting to set
varlevelsup to 0 on the new Var.
I just did a quick test, and setting newvar->varlevelsup to 0 does
indeed appear to fix the reported problem, and the SB views variant of
it.
Regards,
Dean