Thread

Commits

  1. Fix table rewrites that include a column without a default.

  1. BUG #16038: Alter table - SegFault

    The Post Office <noreply@postgresql.org> — 2019-10-04T13:29:46Z

    The following bug has been logged on the website:
    
    Bug reference:      16038
    Logged by:          death lock
    Email address:      deathlock13@gmail.com
    PostgreSQL version: 12.0
    Operating system:   WinXP (VisualStudio 2013) , Debian11 gcc9
    Description:        
    
    create schema if not exists test ;
    drop table test.testa;
    CREATE TABLE test.testa (
        code character varying(2) NOT NULL,
        namez character varying(255) NOT NULL,
        descr character varying(1024),
        wersja numeric(1,0),
        modt timestamp without time zone,
        crtt timestamp without time zone,
        crt integer,
        mod integer,
        -- ida numeric(10,0) DEFAULT nextval(('test.sq_testa'::text)::regclass)
    NOT NULL,
        -- fk_tmp character varying(20),
        CONSTRAINT test_pk PRIMARY KEY (code)
    );
    
    INSERT INTO test.testa VALUES ('0', 'AA', NULL, NULL, '2018-02-19
    09:40:38.776875', '2008-05-20 10:06:28.171', 1001, 1001 /*,  1, 'DUMMYA'
    */);
    -- INSERT INTO test.testa VALUES ('1', 'BB', NULL, NULL, '2018-02-19
    09:40:38.776875', '2008-05-20 10:06:28.171', 1001, 1001 /*,  2, 'DUMMYB'
    */);
    
    drop sequence if exists test.sq_testb;
    create SEQUENCE test.sq_testb;
    
    alter table test.testa
    add column idb numeric(10,0) NOT NULL DEFAULT nextval('test.sq_testb'),
    add column fk_tmpb varchar(20);
    
    server process (PID 21884) was terminated by signal 11: Segmentation fault
    - empty table - alter goes ok , split alter into 2 add col - works too
    
    
  2. Re: BUG #16038: Alter table - SegFault

    Alvaro Herrera <alvherre@2ndquadrant.com> — 2019-10-04T14:43:52Z

    On 2019-Oct-04, PG Bug reporting form wrote:
    
    > alter table test.testa
    > add column idb numeric(10,0) NOT NULL DEFAULT nextval('test.sq_testb'),
    > add column fk_tmpb varchar(20);
    > 
    > server process (PID 21884) was terminated by signal 11: Segmentation fault
    > - empty table - alter goes ok , split alter into 2 add col - works too
    
    Hmm, confirmed, here's the stack trace:
    
    #0  0x0000561459590e9f in heap_compute_data_size (tupleDesc=tupleDesc@entry=0x7faa37b16618, 
        values=values@entry=0x56145b26ba30, isnull=isnull@entry=0x56145b26ba80)
        at /pgsql/source/REL_12_STABLE/src/backend/access/common/heaptuple.c:138
    #1  0x000056145959232b in heap_form_tuple (tupleDescriptor=0x7faa37b16618, values=0x56145b26ba30, 
        isnull=0x56145b26ba80) at /pgsql/source/REL_12_STABLE/src/backend/access/common/heaptuple.c:1061
    #2  0x000056145975f881 in tts_buffer_heap_materialize (slot=0x56145b26b9c0)
        at /pgsql/source/REL_12_STABLE/src/backend/executor/execTuples.c:713
    #3  0x0000561459761083 in ExecFetchSlotHeapTuple (slot=0x56145b26b9c0, materialize=<optimized out>, 
        shouldFree=0x7ffffc491bbf) at /pgsql/source/REL_12_STABLE/src/backend/executor/execTuples.c:1618
    #4  0x00005614595e09c4 in heapam_tuple_insert (relation=0x7faa37b159e0, slot=0x56145b26b9c0, cid=8, 
        options=2, bistate=0x56145b26bd68)
        at /pgsql/source/REL_12_STABLE/src/backend/access/heap/heapam_handler.c:250
    #5  0x0000561459715614 in table_tuple_insert (bistate=0x56145b26bd68, options=2, cid=8, 
        slot=0x56145b26b9c0, rel=0x7faa37b159e0)
        at /pgsql/source/REL_12_STABLE/src/include/access/tableam.h:1126
    #6  ATRewriteTable (tab=tab@entry=0x56145b25b5d8, OIDNewHeap=OIDNewHeap@entry=16396, 
        lockmode=lockmode@entry=8) at /pgsql/source/REL_12_STABLE/src/backend/commands/tablecmds.c:5039
    #7  0x000056145972a9b8 in ATRewriteTables (lockmode=8, wqueue=0x7ffffc491d08, 
        parsetree=0x56145b24d7c0) at /pgsql/source/REL_12_STABLE/src/backend/commands/tablecmds.c:4641
    #8  ATController (parsetree=parsetree@entry=0x56145b24d7c0, rel=<optimized out>, 
        cmds=<optimized out>, recurse=<optimized out>, lockmode=lockmode@entry=8)
        at /pgsql/source/REL_12_STABLE/src/backend/commands/tablecmds.c:3848
    
    -- 
    Álvaro Herrera                https://www.2ndQuadrant.com/
    PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
    
    
    
    
  3. Re: BUG #16038: Alter table - SegFault

    Andres Freund <andres@anarazel.de> — 2019-10-04T15:26:24Z

    Hi,
    
    On 2019-10-04 11:43:52 -0300, Alvaro Herrera wrote:
    > On 2019-Oct-04, PG Bug reporting form wrote:
    > 
    > > alter table test.testa
    > > add column idb numeric(10,0) NOT NULL DEFAULT nextval('test.sq_testb'),
    > > add column fk_tmpb varchar(20);
    > > 
    > > server process (PID 21884) was terminated by signal 11: Segmentation fault
    > > - empty table - alter goes ok , split alter into 2 add col - works too
    > 
    > Hmm, confirmed, here's the stack trace:
    
    The trailing attributes in the new slot in AtRewriteTable() aren't
    necessarily set to isnull=true. So to trigger the problem, one needs a
    rewrite triggered by *another* column (otherwise we'll not hit this
    path), combined with a new column that doesn't have a default value.  I
    think that's probably my bug.
    
    This seems to fix the problem:
    
    diff --git i/src/backend/commands/tablecmds.c w/src/backend/commands/tablecmds.c
    index 05593f33162..6f72b08a87d 100644
    --- i/src/backend/commands/tablecmds.c
    +++ w/src/backend/commands/tablecmds.c
    @@ -4890,6 +4890,14 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
                                                    table_slot_callbacks(oldrel));
                 newslot = MakeSingleTupleTableSlot(newTupDesc,
                                                    table_slot_callbacks(newrel));
    +
    +            /*
    +             * Set all columns in the new slot to NULL initially, to ensure
    +             * columns added as part of the rewrite are initialized to
    +             * NULL. That's necessary as tab->newvals will not contain an
    +             * expression for columns with a NULL default.
    +             */
    +            ExecStoreAllNullTuple(newslot);
             }
             else
             {
    
    
    Greetings,
    
    Andres Freund
    
    
    
    
  4. Re: BUG #16038: Alter table - SegFault

    Andres Freund <andres@anarazel.de> — 2019-10-10T05:21:33Z

    Hi,
    
    On 2019-10-04 08:26:24 -0700, Andres Freund wrote:
    > On 2019-10-04 11:43:52 -0300, Alvaro Herrera wrote:
    > > On 2019-Oct-04, PG Bug reporting form wrote:
    > > 
    > > > alter table test.testa
    > > > add column idb numeric(10,0) NOT NULL DEFAULT nextval('test.sq_testb'),
    > > > add column fk_tmpb varchar(20);
    > > > 
    > > > server process (PID 21884) was terminated by signal 11: Segmentation fault
    > > > - empty table - alter goes ok , split alter into 2 add col - works too
    
    Thanks for the bug report!  I've pushed a fix, which will be included in
    the next minor release. If you need a workaround until then, you can
    avoid the crash by only adding one column add a time.
    
    
    
    > > Hmm, confirmed, here's the stack trace:
    > 
    > The trailing attributes in the new slot in AtRewriteTable() aren't
    > necessarily set to isnull=true. So to trigger the problem, one needs a
    > rewrite triggered by *another* column (otherwise we'll not hit this
    > path), combined with a new column that doesn't have a default value.  I
    > think that's probably my bug.
    > 
    > This seems to fix the problem:
    > 
    > diff --git i/src/backend/commands/tablecmds.c w/src/backend/commands/tablecmds.c
    > index 05593f33162..6f72b08a87d 100644
    > --- i/src/backend/commands/tablecmds.c
    > +++ w/src/backend/commands/tablecmds.c
    > @@ -4890,6 +4890,14 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
    >                                                 table_slot_callbacks(oldrel));
    >              newslot = MakeSingleTupleTableSlot(newTupDesc,
    >                                                 table_slot_callbacks(newrel));
    > +
    > +            /*
    > +             * Set all columns in the new slot to NULL initially, to ensure
    > +             * columns added as part of the rewrite are initialized to
    > +             * NULL. That's necessary as tab->newvals will not contain an
    > +             * expression for columns with a NULL default.
    > +             */
    > +            ExecStoreAllNullTuple(newslot);
    >          }
    
    Pushed, after adding some tests.
    
    Greetings,
    
    Andres Freund