Re: COPY FROM WHEN condition

From: Tomas Vondra <tomas(dot)vondra(at)2ndquadrant(dot)com>
To: Andres Freund <andres(at)anarazel(dot)de>
Cc: Surafel Temesgen <surafel3000(at)gmail(dot)com>, alvherre(at)2ndquadrant(dot)com, Adam Berlin <berlin(dot)ab(at)gmail(dot)com>, pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: COPY FROM WHEN condition
Date: 2019-01-21 15:22:11
Message-ID: f66a0132-c707-0a3e-fb53-5880ec06bf28@2ndquadrant.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On 1/21/19 4:33 AM, Tomas Vondra wrote:
>
>
> On 1/21/19 3:12 AM, Andres Freund wrote:
>> On 2019-01-20 18:08:05 -0800, Andres Freund wrote:
>>> On 2019-01-20 21:00:21 -0500, Tomas Vondra wrote:
>>>>
>>>>
>>>> On 1/20/19 8:24 PM, Andres Freund wrote:
>>>>> Hi,
>>>>>
>>>>> On 2019-01-20 00:24:05 +0100, Tomas Vondra wrote:
>>>>>> On 1/14/19 10:25 PM, Tomas Vondra wrote:
>>>>>>> On 12/13/18 8:09 AM, Surafel Temesgen wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> On Wed, Dec 12, 2018 at 9:28 PM Tomas Vondra
>>>>>>>> <tomas(dot)vondra(at)2ndquadrant(dot)com <mailto:tomas(dot)vondra(at)2ndquadrant(dot)com>> wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>> Can you also update the docs to mention that the functions called from
>>>>>>>> the WHERE clause does not see effects of the COPY itself?
>>>>>>>>
>>>>>>>>
>>>>>>>> /Of course, i  also add same comment to insertion method selection
>>>>>>>> /
>>>>>>>
>>>>>>> FWIW I've marked this as RFC and plan to get it committed this week.
>>>>>>>
>>>>>>
>>>>>> Pushed, thanks for the patch.
>>>>>
>>>>> While rebasing the pluggable storage patch ontop of this I noticed that
>>>>> the qual appears to be evaluated in query context. Isn't that a bad
>>>>> idea? ISMT it should have been evaluated a few lines above, before the:
>>>>>
>>>>> /* Triggers and stuff need to be invoked in query context. */
>>>>> MemoryContextSwitchTo(oldcontext);
>>>>>
>>>>> Yes, that'd require moving the ExecStoreHeapTuple(), but that seems ok?
>>>>>
>>>>
>>>> Yes, I agree. It's a bit too late for me to hack and push stuff, but I'll
>>>> fix that tomorrow.
>>>
>>> NP. On second thought, the problem is probably smaller than I thought at
>>> first, because ExecQual() switches to the econtext's per-tuple memory
>>> context. But it's only reset once for each batch, so there's some
>>> wastage. At least worth a comment.
>>
>> I'm tired, but perhaps its actually worse - what's being reset currently
>> is the ESTate's per-tuple context:
>>
>> if (nBufferedTuples == 0)
>> {
>> /*
>> * Reset the per-tuple exprcontext. We can only do this if the
>> * tuple buffer is empty. (Calling the context the per-tuple
>> * memory context is a bit of a misnomer now.)
>> */
>> ResetPerTupleExprContext(estate);
>> }
>>
>> but the quals are evaluated in the ExprContext's:
>>
>> ExecQual(ExprState *state, ExprContext *econtext)
>> ...
>> ret = ExecEvalExprSwitchContext(state, econtext, &isnull);
>>
>>
>> which is created with:
>>
>> /* Get an EState's per-output-tuple exprcontext, making it if first use */
>> #define GetPerTupleExprContext(estate) \
>> ((estate)->es_per_tuple_exprcontext ? \
>> (estate)->es_per_tuple_exprcontext : \
>> MakePerTupleExprContext(estate))
>>
>> and creates its own context:
>> /*
>> * Create working memory for expression evaluation in this context.
>> */
>> econtext->ecxt_per_tuple_memory =
>> AllocSetContextCreate(estate->es_query_cxt,
>> "ExprContext",
>> ALLOCSET_DEFAULT_SIZES);
>>
>> so this is currently just never reset.
>
> Actually, no. The ResetPerTupleExprContext boils down to
>
> MemoryContextReset((econtext)->ecxt_per_tuple_memory)
>
> and ExecEvalExprSwitchContext does this
>
> MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
>
> So it's resetting the right context, although only on batch boundary.
> But now I see 31f38174 does this:
>
> else if (cstate->whereClause != NULL ||
> contain_volatile_functions(cstate->whereClause))
> {
> ...
> insertMethod = CIM_SINGLE;
> }
>
> so it does not do batching with WHERE. But the condition seems wrong, I
> guess it should be && instead of ||. Will investigate in the morning.
>

I think the condition can be just

if (contain_volatile_functions(cstate->whereClause)) { ... }

Per the attached patch. Surafel, do you agree?

>> Seems just using ExecQualAndReset() ought to be sufficient?
>>
>
> That may still be the right thing to do.
>

Actually, no, because that would reset the context far too early (and
it's easy to trigger segfaults). So the reset would have to happen after
processing the row, not this early.

But I think the current behavior is actually OK, as it matches what we
do for defexprs. And the comment before ResetPerTupleExprContext says this:

/*
* Reset the per-tuple exprcontext. We can only do this if the
* tuple buffer is empty. (Calling the context the per-tuple
* memory context is a bit of a misnomer now.)
*/

So the per-tuple context is not quite per-tuple anyway. Sure, we might
rework that but I don't think that's an issue in this patch.

regards

--
Tomas Vondra http://www.2ndQuadrant.com
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

Attachment Content-Type Size
copy-when-fix.patch text/x-patch 501 bytes

In response to

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2019-01-21 15:27:56 Re: Early WIP/PoC for inlining CTEs
Previous Message Oleg Bartunov 2019-01-21 15:04:48 Re: jsonpath