On Tue, Nov 22, 2022 at 3:44 PM Richard Guo <guofengli...@gmail.com> wrote:

> On Wed, Nov 16, 2022 at 7:38 AM Sergey Shinderuk <
> s.shinde...@postgrespro.ru> wrote:
>
>> The failing query is:
>> SELECT * FROM
>>    (SELECT *,
>>            count(salary) OVER (PARTITION BY depname || '') c1, -- w1
>>            row_number() OVER (PARTITION BY depname) rn, -- w2
>>            count(*) OVER (PARTITION BY depname) c2, -- w2
>>            count(*) OVER (PARTITION BY '' || depname) c3 -- w3
>>     FROM empsalary
>> ) e WHERE rn <= 1 AND c1 <= 3;
>> As far as I understand, ExecWindowAgg for the intermediate WindowAgg
>> node switches into pass-through mode, stops evaluating row_number(), and
>> returns the previous value instead. But if int8 is passed by reference,
>> the previous value stored in econtext->ecxt_aggvalues becomes a dangling
>> pointer when the per-output-tuple memory context is reset.
>
>
> Yeah, you're right.  In this example the window function row_number()
> goes into pass-through mode after the second evaluation because its
> run condition does not hold true any more.  The remaining run would just
> return the result from the second evaluation, which is stored in
> econtext->ecxt_aggvalues[wfuncno].
>
> If int8 is configured as pass-by-ref, the precomputed value from the
> second evaluation is actually located in a memory area from context
> ecxt_per_tuple_memory, with its pointer stored in ecxt_aggvalues.  As
> this memory context is reset once per tuple, we would be prone to wrong
> results.
>

Regarding how to fix this problem, firstly I believe we need to evaluate
window functions in the per-tuple memory context, as the HEAD does.
When we decide we need to go into pass-through mode, I'm thinking that
we can just copy out the results of the last evaluation to the per-query
memory context, while still storing their pointers in ecxt_aggvalues.

Does this idea work?

Thanks
Richard

Reply via email to