Re: UPDATE on Domain Array that is based on a composite key crashes - Mailing list pgsql-hackers

From Japin Li
Subject Re: UPDATE on Domain Array that is based on a composite key crashes
Date
Msg-id MEYP282MB16699508FCEE1679C993C87BB6BD9@MEYP282MB1669.AUSP282.PROD.OUTLOOK.COM
Whole thread Raw
In response to Re: UPDATE on Domain Array that is based on a composite key crashes  (Zhihong Yu <zyu@yugabyte.com>)
List pgsql-hackers
On Tue, 19 Oct 2021 at 23:17, Zhihong Yu <zyu@yugabyte.com> wrote:
> On Tue, Oct 19, 2021 at 2:12 AM Zhihong Yu <zyu@yugabyte.com> wrote:
>
>>
>>
>> On Tue, Oct 19, 2021 at 12:39 AM Onder Kalaci <onderk@microsoft.com>
>> wrote:
>>
>>> Hi hackers,
>>>
>>>
>>>
>>> I couldn’t find a similar report to this one, so starting a new thread. I
>>> can reproduce this on v14.0 as well as PostgreSQL 12.5 (not tried below
>>> versions).
>>>
>>>
>>>
>>> Steps to reproduce:
>>>
>>>
>>>
>>> CREATE TYPE two_ints as (if1 int, if2 int);
>>>
>>> CREATE DOMAIN domain AS two_ints CHECK ((VALUE).if1 > 0);
>>>
>>> CREATE TABLE domain_indirection_test (f1 int, f3 domain, domain_array
>>> domain[]);
>>>
>>> INSERT INTO domain_indirection_test (f1,f3.if1) VALUES (0, 1);
>>>
>>> UPDATE domain_indirection_test SET domain_array[0].if2 = 5;
>>>
>>> server closed the connection unexpectedly
>>>
>>>                 This probably means the server terminated abnormally
>>>
>>>                 before or while processing the request.
>>>
>>> The connection to the server was lost. Attempting reset: Failed.
>>>
>>> Time: 3.990 ms
>>>
>>> @:-!>
>>>
>>>
>>>
>>>
>>>
>>> The backtrace on PG 12.5 (As far as I remember, PG14 looks very similar) :
>>>
>>>
>>>
>>> (lldb) bt
>>>
>>> * thread #1, queue = 'com.apple.main-thread', stop reason =
>>> EXC_BAD_ACCESS (code=1, address=0x0)
>>>
>>>   * frame #0: 0x00000001036584b7
>>> postgres`pg_detoast_datum(datum=0x0000000000000000) at fmgr.c:1741:6
>>>
>>>     frame #1: 0x0000000103439a86
>>> postgres`ExecEvalFieldStoreDeForm(state=<unavailable>,
>>> op=0x00007f9212045df8, econtext=<unavailable>) at execExprInterp.c:3025:12
>>>
>>>     frame #2: 0x000000010343834e
>>> postgres`ExecInterpExpr(state=<unavailable>, econtext=<unavailable>,
>>> isnull=0x00007ffeec91fdc7) at execExprInterp.c:1337:4
>>>
>>>     frame #3: 0x000000010343742b
>>> postgres`ExecInterpExprStillValid(state=0x00007f921181db18,
>>> econtext=0x00007f921181d670, isNull=<unavailable>) at
>>> execExprInterp.c:1778:9
>>>
>>>     frame #4: 0x0000000103444e0d
>>> postgres`ExecEvalExprSwitchContext(state=0x00007f921181db18,
>>> econtext=0x00007f921181d670, isNull=<unavailable>) at executor.h:310:13
>>>
>>>     frame #5: 0x0000000103444cf0
>>> postgres`ExecProject(projInfo=0x00007f921181db10) at executor.h:344:9
>>>
>>>     frame #6: 0x0000000103444af6
>>> postgres`ExecScan(node=0x00007f921181d560, accessMtd=(postgres`SeqNext at
>>> nodeSeqscan.c:51), recheckMtd=(postgres`SeqRecheck at nodeSeqscan.c:90)) at
>>> execScan.c:239:12
>>>
>>>     frame #7: 0x0000000103461d17
>>> postgres`ExecSeqScan(pstate=<unavailable>) at nodeSeqscan.c:112:9
>>>
>>>     frame #8: 0x000000010344375c
>>> postgres`ExecProcNodeFirst(node=0x00007f921181d560) at execProcnode.c:445:9
>>>
>>>     frame #9: 0x000000010345eefe
>>> postgres`ExecProcNode(node=0x00007f921181d560) at executor.h:242:9
>>>
>>>     frame #10: 0x000000010345e74f
>>> postgres`ExecModifyTable(pstate=0x00007f921181d090) at
>>> nodeModifyTable.c:2079:14
>>>
>>>     frame #11: 0x000000010344375c
>>> postgres`ExecProcNodeFirst(node=0x00007f921181d090) at execProcnode.c:445:9
>>>
>>>     frame #12: 0x000000010343f25e
>>> postgres`ExecProcNode(node=0x00007f921181d090) at executor.h:242:9
>>>
>>>     frame #13: 0x000000010343d80d
>>> postgres`ExecutePlan(estate=0x00007f921181cd10,
>>> planstate=0x00007f921181d090, use_parallel_mode=<unavailable>,
>>> operation=CMD_UPDATE, sendTuples=false, numberTuples=0,
>>> direction=ForwardScanDirection, dest=0x00007f9211818c38,
>>> execute_once=<unavailable>) at execMain.c:1646:10
>>>
>>>     frame #14: 0x000000010343d745
>>> postgres`standard_ExecutorRun(queryDesc=0x00007f921180e310,
>>> direction=ForwardScanDirection, count=0, execute_once=true) at
>>> execMain.c:364:3
>>>
>>>     frame #15: 0x000000010343d67c
>>> postgres`ExecutorRun(queryDesc=0x00007f921180e310,
>>> direction=ForwardScanDirection, count=0, execute_once=<unavailable>) at
>>> execMain.c:308:3
>>>
>>>     frame #16: 0x00000001035784a8
>>> postgres`ProcessQuery(plan=<unavailable>, sourceText=<unavailable>,
>>> params=<unavailable>, queryEnv=0x0000000000000000, dest=<unavailable>,
>>> completionTag="") at pquery.c:161:2
>>>
>>>     frame #17: 0x0000000103577c5e
>>> postgres`PortalRunMulti(portal=0x00007f9215024110, isTopLevel=true,
>>> setHoldSnapshot=false, dest=0x00007f9211818c38, altdest=0x00007f9211818c38,
>>> completionTag="") at pquery.c:0
>>>
>>>     frame #18: 0x000000010357763d
>>> postgres`PortalRun(portal=0x00007f9215024110, count=9223372036854775807,
>>> isTopLevel=<unavailable>, run_once=<unavailable>, dest=0x00007f9211818c38,
>>> altdest=0x00007f9211818c38, completionTag="") at pquery.c:796:5
>>>
>>>     frame #19: 0x0000000103574f87
>>> postgres`exec_simple_query(query_string="UPDATE domain_indirection_test SET
>>> domain_array[0].if2 = 5;") at postgres.c:1215:10
>>>
>>>     frame #20: 0x00000001035746b8
>>> postgres`PostgresMain(argc=<unavailable>, argv=<unavailable>,
>>> dbname=<unavailable>, username=<unavailable>) at postgres.c:0
>>>
>>>     frame #21: 0x000000010350d712 postgres`BackendRun(port=<unavailable>)
>>> at postmaster.c:4494:2
>>>
>>>     frame #22: 0x000000010350cffa
>>> postgres`BackendStartup(port=<unavailable>) at postmaster.c:4177:3
>>>
>>>     frame #23: 0x000000010350c59c postgres`ServerLoop at
>>> postmaster.c:1725:7
>>>
>>>     frame #24: 0x000000010350ac8d postgres`PostmasterMain(argc=3,
>>> argv=0x00007f9210d049c0) at postmaster.c:1398:11
>>>
>>>     frame #25: 0x000000010347fbdd postgres`main(argc=<unavailable>,
>>> argv=<unavailable>) at main.c:228:3
>>>
>>>     frame #26: 0x00007fff204e8f3d libdyld.dylib`start + 1
>>>
>>>
>>>
>>>
>>>
>>> Thanks,
>>>
>>> Onder KALACI
>>>
>>> Software Engineer at Microsoft &
>>>
>>> Developing the Citus database extension for PostgreSQL
>>>
>>
>>  Hi,
>>  It seems the following change would fix the crash:
>>
>> diff --git a/src/postgres/src/backend/executor/execExprInterp.c
>> b/src/postgres/src/backend/executor/execExprInterp.c
>> index 622cab9d4..50cb4f014 100644
>> --- a/src/postgres/src/backend/executor/execExprInterp.c
>> +++ b/src/postgres/src/backend/executor/execExprInterp.c
>> @@ -3038,6 +3038,9 @@ ExecEvalFieldStoreDeForm(ExprState *state,
>> ExprEvalStep *op, ExprContext *econte
>>          HeapTupleHeader tuphdr;
>>          HeapTupleData tmptup;
>>
>> +        if (DatumGetPointer(tupDatum) == NULL) {
>> +            return;
>> +        }
>>          tuphdr = DatumGetHeapTupleHeader(tupDatum);
>>          tmptup.t_len = HeapTupleHeaderGetDatumLength(tuphdr);
>>          ItemPointerSetInvalid(&(tmptup.t_self));
>>
>> Here is the result after the update statement:
>>
>> # UPDATE domain_indirection_test SET domain_array[0].if2 = 5;
>> UPDATE 1
>> # select * from domain_indirection_test;
>>  f1 |  f3  |  domain_array
>> ----+------+----------------
>>   0 | (1,) | [0:0]={"(,5)"}
>> (1 row)
>>
>> Cheers
>>
> Hi,
> Here is the patch.

Thanks for your updated the patch.  A minor code style, we can remove the
braces when there is only one statement, this is more consenting with the
codebase.  Others looks good to me.

> If the new test should be placed in a different .sql file, please let me
> know.
>

> The update issue Japin mentioned seems to be orthogonal to the crash.
>

I start a new thread to discuss it [1].

[1] https://www.postgresql.org/message-id/MEYP282MB1669BED5CEFE711E00C7421EB6BD9@MEYP282MB1669.AUSP282.PROD.OUTLOOK.COM


--
Regrads,
Japin Li.
ChengDu WenWu Information Technology Co.,Ltd.



pgsql-hackers by date:

Previous
From: Robert Haas
Date:
Subject: Re: XTS cipher mode for cluster file encryption
Next
From: Tom Lane
Date:
Subject: Re: UPDATE on Domain Array that is based on a composite key crashes