SQLite

Check-in [ad816d01d4]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Merge in recent fixes from trunk.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | nulls-last
Files: files | file ages | folders
SHA3-256: ad816d01d4bd3908ff2c574d79d1a29b6d732df308f2f1b1cdf7c0bc7c1bd7cf
User & Date: drh 2019-08-26 20:41:33.731
Context
2019-08-27
19:59
Add support for "ORDER BY ... NULLS FIRST" and "ORDER BY ... NULLS LAST". Use this to fix ticket [f8a7060e]. (check-in: 94085fb3e7 user: dan tags: trunk)
2019-08-26
20:41
Merge in recent fixes from trunk. (Closed-Leaf check-in: ad816d01d4 user: drh tags: nulls-last)
14:57
Tweak the shell tool ".recover" command so that it can recover rows that consist of a rowid and no fields. (check-in: 279ac7fdec user: dan tags: trunk)
2019-08-23
20:33
Move some things in parse.y so that TK_COLUMN and TK_AGG_COLUMN are assigned the same values as they are on trunk for a very small speedup. (check-in: d26fdfa3bc user: dan tags: nulls-last)
Changes
Unified Diff Ignore Whitespace Patch
Changes to ext/fts5/fts5_index.c.
4993
4994
4995
4996
4997
4998
4999



5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
        int nCopy;
        u8 *aCopy;

        i64 iPrev = 0;
        Fts5PoslistWriter writer;
        memset(&writer, 0, sizeof(writer));




        fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
        fts5BufferZero(&tmp);
        sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist);
        if( p->rc ) break;

        sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
        sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
        assert_nc( iPos1>=0 && iPos2>=0 );

        if( iPos1<iPos2 ){







>
>
>


|







4993
4994
4995
4996
4997
4998
4999
5000
5001
5002
5003
5004
5005
5006
5007
5008
5009
5010
5011
5012
        int nCopy;
        u8 *aCopy;

        i64 iPrev = 0;
        Fts5PoslistWriter writer;
        memset(&writer, 0, sizeof(writer));

        /* See the earlier comment in this function for an explanation of why
        ** corrupt input position lists might cause the output to consume
        ** at most 20 bytes of unexpected space. */
        fts5MergeAppendDocid(&out, iLastRowid, i2.iRowid);
        fts5BufferZero(&tmp);
        sqlite3Fts5BufferSize(&p->rc, &tmp, i1.nPoslist + i2.nPoslist + 10 + 10);
        if( p->rc ) break;

        sqlite3Fts5PoslistNext64(a1, i1.nPoslist, &iOff1, &iPos1);
        sqlite3Fts5PoslistNext64(a2, i2.nPoslist, &iOff2, &iPos2);
        assert_nc( iPos1>=0 && iPos2>=0 );

        if( iPos1<iPos2 ){
Changes to ext/fts5/test/fts5corrupt3.test.
9362
9363
9364
9365
9366
9367
9368





























































































































9369
9370
9371
9372
do_catchsql_test 63.2 {
  INSERT INTO t1(t1) VALUES('optimize');
} {/*malformed database schema*/}

do_catchsql_test 63.3 {
  SELECT * FROM t1 WHERE b MATCH 'thead*thead*theSt*';
} {/*malformed database schema*/}






























































































































sqlite3_fts5_may_be_corrupt 0
finish_test








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>




9362
9363
9364
9365
9366
9367
9368
9369
9370
9371
9372
9373
9374
9375
9376
9377
9378
9379
9380
9381
9382
9383
9384
9385
9386
9387
9388
9389
9390
9391
9392
9393
9394
9395
9396
9397
9398
9399
9400
9401
9402
9403
9404
9405
9406
9407
9408
9409
9410
9411
9412
9413
9414
9415
9416
9417
9418
9419
9420
9421
9422
9423
9424
9425
9426
9427
9428
9429
9430
9431
9432
9433
9434
9435
9436
9437
9438
9439
9440
9441
9442
9443
9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
9460
9461
9462
9463
9464
9465
9466
9467
9468
9469
9470
9471
9472
9473
9474
9475
9476
9477
9478
9479
9480
9481
9482
9483
9484
9485
9486
9487
9488
9489
9490
9491
9492
9493
9494
9495
9496
9497
do_catchsql_test 63.2 {
  INSERT INTO t1(t1) VALUES('optimize');
} {/*malformed database schema*/}

do_catchsql_test 63.3 {
  SELECT * FROM t1 WHERE b MATCH 'thead*thead*theSt*';
} {/*malformed database schema*/}

#---------------------------------------------------------------------------
do_test 64.0 {
  sqlite3 db {}
  db deserialize [decode_hexdb {
.open --hexdb
| size 28672 pagesize 4096 filename crash-4470f0b94422f7.db
| page 1 offset 0
|      0: 53 51 4c 69 74 65 20 66 6f 72 6d 61 74 20 33 00   SQLite format 3.
|     16: 10 00 01 01 00 40 20 20 00 00 00 00 00 00 00 06   .....@  ........
|     32: 00 00 00 00 00 00 00 00 00 00 00 06 00 00 00 04   ................
|     96: 00 00 00 00 0d 00 00 00 06 0d e2 00 0f c4 0f 6a   ...............j
|    112: 0e fc 0e 9d 0e 3d 0d e2 00 00 00 00 00 01 00 00   .....=..........
|   3552: 00 00 59 06 06 17 21 21 01 7f 74 61 62 6c 65 74   ..Y...!!..tablet
|   3568: 74 74 5f 63 6f 6e 66 69 67 74 74 74 5f 63 6f 6e   tt_configttt_con
|   3584: 66 69 67 06 43 52 45 41 54 45 20 54 41 42 4c 45   fig.CREATE TABLE
|   3600: 20 27 74 74 74 5f 63 6f 6e 66 69 67 27 28 6b 20    'ttt_config'(k 
|   3616: 50 52 49 4d 41 52 59 20 4b 45 59 2c 20 76 29 20   PRIMARY KEY, v) 
|   3632: 57 49 54 48 4f 55 54 20 52 4f 57 49 44 5e 05 07   WITHOUT ROWID^..
|   3648: 17 23 23 01 81 03 74 61 62 6c 65 74 74 74 5f 64   .##...tablettt_d
|   3664: 6f 63 73 69 7a 65 74 74 74 5f 64 6f 63 73 69 7a   ocsizettt_docsiz
|   3680: 65 05 43 52 45 41 54 45 20 54 41 42 4c 45 20 27   e.CREATE TABLE '
|   3696: 74 74 74 5f 64 6f 63 73 69 7a 65 27 28 69 64 20   ttt_docsize'(id 
|   3712: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20   INTEGER PRIMARY 
|   3728: 4b 45 59 2c 20 73 7a 20 42 4c 4f 42 29 5d 04 07   KEY, sz BLOB)]..
|   3744: 17 23 23 01 81 01 74 61 62 6c 65 74 74 74 5f 63   .##...tablettt_c
|   3760: 6f 6e 74 65 6e 74 74 74 74 5f 63 6f 6e 74 65 6e   ontentttt_conten
|   3776: 74 04 43 52 45 41 54 45 20 54 41 42 4c 45 20 27   t.CREATE TABLE '
|   3792: 74 74 74 5f 63 6f 6e 74 65 6e 74 27 28 69 64 20   ttt_content'(id 
|   3808: 49 4e 54 45 47 45 52 20 50 52 49 4d 41 52 59 20   INTEGER PRIMARY 
|   3824: 4b 45 59 2c 20 63 30 2c 20 63 31 29 6c 03 07 17   KEY, c0, c1)l...
|   3840: 1b 1b 01 81 2f 74 61 62 6c 65 74 74 74 5f 69 64   ..../tablettt_id
|   3856: 78 74 74 74 5f 69 64 78 03 43 52 45 41 54 45 20   xttt_idx.CREATE 
|   3872: 54 41 42 4c 45 20 27 74 74 74 5f 69 64 78 27 28   TABLE 'ttt_idx'(
|   3888: 73 65 67 69 64 2c 20 74 65 72 6d 2c 20 70 67 6e   segid, term, pgn
|   3904: 6f 2c 20 50 52 49 4d 41 52 59 20 4b 45 59 28 73   o, PRIMARY KEY(s
|   3920: 65 67 69 64 2c 20 74 65 72 6d 29 29 20 57 49 54   egid, term)) WIT
|   3936: 48 4f 55 54 20 52 4f 57 49 44 58 02 07 17 1d 1d   HOUT ROWIDX.....
|   3952: 01 81 03 74 61 62 6c 65 74 74 74 5f 64 61 74 61   ...tablettt_data
|   3968: 74 74 74 5f 64 61 74 61 02 43 52 45 41 54 45 20   ttt_data.CREATE 
|   3984: 54 41 42 4c 45 20 27 74 74 74 5f 64 61 74 61 27   TABLE 'ttt_data'
|   4000: 28 69 64 20 49 4e 54 45 47 45 52 20 50 52 49 4d   (id INTEGER PRIM
|   4016: 41 52 59 20 4b 45 59 2c 20 62 6c 6f 63 6b 20 42   ARY KEY, block B
|   4032: 4c 4f 42 29 3a 01 06 17 13 13 08 5f 74 61 62 6c   LOB):......_tabl
|   4048: 65 74 74 74 74 74 74 43 52 45 41 54 45 20 56 49   ettttttCREATE VI
|   4064: 52 54 55 41 4c 20 54 41 42 4c 45 20 74 74 74 20   RTUAL TABLE ttt 
|   4080: 55 53 49 4e 47 20 66 74 73 35 28 61 2c 20 62 29   USING fts5(a, b)
| page 2 offset 4096
|      0: 0d 0f 44 00 05 0e 81 00 0f 1a 0e 81 0f af 0f 58   ..D............X
|     16: 0e 98 00 00 00 00 00 00 00 00 00 00 00 00 00 00   ................
|   3712: 00 15 0a 03 00 30 00 00 00 00 01 03 03 00 03 01   .....0..........
|   3728: 01 01 02 01 01 03 01 01 81 24 8c 80 80 80 80 01   .........$......
|   3744: 04 00 82 4c 00 00 00 9b 02 30 65 03 1a 02 05 05   ...L.....0e.....
|   3760: 07 05 01 01 04 03 03 08 03 03 01 2e 02 05 05 07   ................
|   3776: 05 07 05 07 05 01 01 04 03 03 08 03 03 08 03 03   ................
|   3792: 07 f3 03 02 01 65 03 1e 03 05 05 04 05 05 01 00   .....e..........
|   3808: 03 06 04 04 06 04 03 01 36 03 05 05 04 06 05 04   ........6.......
|   3824: 06 05 04 05 05 01 01 03 06 04 04 06 04 04 06 04   ................
|   3840: 04 06 04 03 03 01 65 03 14 04 05 06 f5 05 01 01   ......e.........
|   3856: 02 08 09 01 20 04 05 07 05 07 05 07 05 05 01 00   .... ...........
|   3872: 02 08 0a 0a 0a 04 01 65 03 02 0a 01 06 0a 0a 0a   .......e........
|   3888: 05 01 65 03 06 01 01 0a 01 0a 01 01 0a 0a 0a 04   ..e.............
|   3904: 2b 31 21 0b 0f ef 00 14 2a 00 00 00 00 01 02 02   +1!.....*.......
|   3920: 00 02 01 01 01 02 01 01 50 88 80 80 80 80 01 04   ........P.......
|   3936: 00 81 24 00 00 00 47 02 30 65 02 1a 02 05 05 07   ..$...G.0e......
|   3952: 05 01 01 04 03 03 08 03 03 02 01 65 02 1e 03 05   ...........e....
|   3968: 05 04 05 05 01 01 03 06 04 04 06 04 03 03 01 65   ...............e
|   3984: 02 14 04 05 07 05 05 01 01 02 08 0a 04 01 65 02   ..............e.
|   4000: 02 0a 05 01 65 02 06 01 01 0a 04 12 14 0f 06 31   ....e..........1
|   4016: 84 80 80 80 80 01 03 00 68 00 00 00 2b 02 30 65   ........h...+.0e
|   4032: 01 10 02 05 05 01 01 04 03 03 02 01 65 01 12 03   ............e...
|   4048: 05 05 01 01 03 06 04 03 03 01 65 01 0e 04 05 05   ..........e.....
|   4064: 01 01 02 08 04 0d 0e 06 01 03 00 12 04 4c 4c 00   .............LL.
|   4080: 00 00 11 24 00 00 00 00 01 01 01 00 01 01 01 01   ...$............
| page 3 offset 8192
|      0: 0a 00 00 00 03 0f ec 00 0f 00 00 00 00 00 00 00   ................
|   4064: 00 00 00 00 00 00 00 00 00 00 00 00 06 04 01 0c   ................
|   4080: 01 03 02 06 04 01 0c 01 02 02 05 04 09 0c 01 02   ................
| page 4 offset 12288
|      0: 0d 00 00 00 04 0e 1a 00 0f c7 0f 5b 0e ef 0e 1a   ...........[....
|   3600: 00 00 00 00 00 00 00 00 00 00 81 52 04 06 00 81   ...........R....
|   3616: 5d 81 55 65 20 65 65 20 65 65 65 20 65 20 65 65   ].Ue ee eee e ee
|   3632: 20 65 65 65 20 65 20 65 65 20 65 65 65 66 20 65    eee e ee eeef e
|   3648: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65   e eee e ee eee e
|   3664: 20 65 65 20 65 65 65 65 20 65 65 20 65 65 65 20    ee eeee ee eee 
|   3680: 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65   e ee eee e ee ee
|   3696: 65 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65   ee ee eee e ee e
|   3712: 65 65 20 65 20 65 65 20 65 65 65 65 65 65 20 65   ee e ee eeeeee e
|   3728: 65 20 65 20 65 20 65 20 65 65 20 65 65 65 20 65   e e e e ee eee e
|   3744: 65 20 65 65 65 65 65 20 65 65 20 65 20 65 1f 65   e eeeee ee e e.e
|   3760: 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65 65    ee eee ee eeeee
|   3776: 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65 65    ee e e e ee eee
|   3792: 20 65 65 20 65 65 65 65 65 20 65 65 20 65 20 65    ee eeeee ee e e
|   3808: 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65 6a    e ee eee ee eej
|   3824: 03 03 ff 75 71 65 20 65 65 1f 65 65 65 20 65 20   ...uqe ee.eee e 
|   3840: 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65 65   ee eee e ee eeee
|   3856: 20 65 65 20 65 65 65 20 65 20 65 65 20 65 65 65    ee eee e ee eee
|   3872: 20 65 20 65 65 20 65 65 65 65 65 65 20 65 65 20    e ee eeeeee ee 
|   3888: 65 20 65 20 65 20 65 65 20 65 65 65 20 65 65 20   e e e ee eee ee 
|   3904: 65 65 65 65 65 20 65 65 20 65 20 65 20 65 20 65   eeeee ee e e e e
|   3920: 65 20 65 65 65 20 65 65 20 65 65 6a 02 04 00 75   e eee ee eej...u
|   3936: 40 65 20 65 65 20 65 65 65 20 65 20 65 65 20 65   @e ee eee e ee e
|   3952: 65 65 20 65 20 65 65 20 65 65 65 65 20 65 65 20   ee e ee eeee ee 
|   3968: 65 65 65 20 65 20 65 65 20 65 65 65 20 65 20 65   eee e ee eee e e
|   3984: 65 20 65 65 65 65 65 65 20 65 65 20 65 20 65 20   e eeeeee ee e e 
|   4000: 65 20 65 65 20 65 65 65 20 65 65 20 65 65 65 65   e ee eee ee eeee
|   4016: 65 20 65 65 20 65 20 65 20 65 20 65 65 20 65 65   e ee e e e ee ee
|   4032: 65 20 65 65 20 65 65 37 01 04 00 41 3f 65 20 65   e ee ee7...A?e e
|   4048: 65 20 65 65 65 20 65 20 65 65 20 65 65 65 20 65   e eee e ee eee e
|   4064: 20 65 65 20 65 65 65 65 65 65 20 65 65 20 65 20    ee eeeeee ee e 
|   4080: 65 20 65 20 65 65 20 65 65 65 20 65 65 20 65 65   e e ee eee ee ee
| page 5 offset 16384
|      0: 0d 00 00 00 04 0f e4 00 0f f9 0f f2 0f eb 0f e4   ................
|   4064: 00 00 00 00 05 04 03 00 10 21 21 05 03 03 00 10   .........!!.....
|   4080: 11 11 05 02 03 00 10 11 11 05 01 03 00 10 09 09   ................
| page 6 offset 20480
|      0: 0a 00 00 00 01 0f f4 00 0f f4 00 00 00 00 00 00   ................
|   4080: 00 00 00 00 0b 03 1b 01 76 65 72 73 69 6f 6e 04   ........version.
| end crash-4470f0b94422f7.db
}]} {}

do_catchsql_test 64.1 {
  SELECT * FROM ttt('e*');
} {1 {database disk image is malformed}}


sqlite3_fts5_may_be_corrupt 0
finish_test

Changes to src/btree.c.
6988
6989
6990
6991
6992
6993
6994

6995
6996
6997
6998
6999
7000
7001
7002
  assert( CORRUPT_DB || pPg->hdrOffset==0 );    /* Never called on page 1 */
  if( iEnd<=iFirst ) return 0;
  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
  pEnd = pCArray->apEnd[k];
  while( 1 /*Exit by break*/ ){
    int sz, rc;
    u8 *pSlot;

    sz = cachedCellSize(pCArray, i);
    if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
      if( (pData - pBegin)<sz ) return 1;
      pData -= sz;
      pSlot = pData;
    }
    /* pSlot and pCArray->apCell[i] will never overlap on a well-formed
    ** database.  But they might for a corrupt database.  Hence use memmove()







>
|







6988
6989
6990
6991
6992
6993
6994
6995
6996
6997
6998
6999
7000
7001
7002
7003
  assert( CORRUPT_DB || pPg->hdrOffset==0 );    /* Never called on page 1 */
  if( iEnd<=iFirst ) return 0;
  for(k=0; pCArray->ixNx[k]<=i && ALWAYS(k<NB*2); k++){}
  pEnd = pCArray->apEnd[k];
  while( 1 /*Exit by break*/ ){
    int sz, rc;
    u8 *pSlot;
    assert( pCArray->szCell[i]!=0 );
    sz = pCArray->szCell[i];
    if( (aData[1]==0 && aData[2]==0) || (pSlot = pageFindSlot(pPg,sz,&rc))==0 ){
      if( (pData - pBegin)<sz ) return 1;
      pData -= sz;
      pSlot = pData;
    }
    /* pSlot and pCArray->apCell[i] will never overlap on a well-formed
    ** database.  But they might for a corrupt database.  Hence use memmove()
7149
7150
7151
7152
7153
7154
7155

7156
7157
7158
7159
7160
7161
7162
    int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
    if( iCell>=0 && iCell<nNew ){
      pCellptr = &pPg->aCellIdx[iCell * 2];
      if( nCell>iCell ){
        memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
      }
      nCell++;

      if( pageInsertArray(
            pPg, pBegin, &pData, pCellptr,
            iCell+iNew, 1, pCArray
      ) ) goto editpage_fail;
    }
  }








>







7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
    int iCell = (iOld + pPg->aiOvfl[i]) - iNew;
    if( iCell>=0 && iCell<nNew ){
      pCellptr = &pPg->aCellIdx[iCell * 2];
      if( nCell>iCell ){
        memmove(&pCellptr[2], pCellptr, (nCell - iCell) * 2);
      }
      nCell++;
      cachedCellSize(pCArray, iCell+iNew);
      if( pageInsertArray(
            pPg, pBegin, &pData, pCellptr,
            iCell+iNew, 1, pCArray
      ) ) goto editpage_fail;
    }
  }

Changes to src/expr.c.
1629
1630
1631
1632
1633
1634
1635




1636
1637
1638
1639
1640
1641
1642
    sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
                    pColumns->nId, n);
    goto vector_append_error;
  }

  for(i=0; i<pColumns->nId; i++){
    Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);




    pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
    if( pList ){
      assert( pList->nExpr==iFirst+i+1 );
      pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
      pColumns->a[i].zName = 0;
    }
  }







>
>
>
>







1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
    sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
                    pColumns->nId, n);
    goto vector_append_error;
  }

  for(i=0; i<pColumns->nId; i++){
    Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
    assert( pSubExpr!=0 || db->mallocFailed );
    assert( pSubExpr==0 || pSubExpr->iTable==0 );
    if( pSubExpr==0 ) continue;
    pSubExpr->iTable = pColumns->nId;
    pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
    if( pList ){
      assert( pList->nExpr==iFirst+i+1 );
      pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
      pColumns->a[i].zName = 0;
    }
  }
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
** or EXISTS operator:
**
**     (SELECT a FROM b)          -- subquery
**     EXISTS (SELECT a FROM b)   -- EXISTS subquery
**
** The pExpr parameter is the SELECT or EXISTS operator to be coded.
**
** The register that holds the result.  For a multi-column SELECT, 
** the result is stored in a contiguous array of registers and the
** return value is the register of the left-most result column.
** Return 0 if an error occurs.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
  int addrOnce = 0;           /* Address of OP_Once at top of subroutine */







|







2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
** or EXISTS operator:
**
**     (SELECT a FROM b)          -- subquery
**     EXISTS (SELECT a FROM b)   -- EXISTS subquery
**
** The pExpr parameter is the SELECT or EXISTS operator to be coded.
**
** Return the register that holds the result.  For a multi-column SELECT, 
** the result is stored in a contiguous array of registers and the
** return value is the register of the left-most result column.
** Return 0 if an error occurs.
*/
#ifndef SQLITE_OMIT_SUBQUERY
int sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
  int addrOnce = 0;           /* Address of OP_Once at top of subroutine */
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
    }
    case TK_SELECT_COLUMN: {
      int n;
      if( pExpr->pLeft->iTable==0 ){
        pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
      }
      assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
      if( pExpr->iTable
       && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) 
      ){
        sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
                                pExpr->iTable, n);
      }
      return pExpr->pLeft->iTable + pExpr->iColumn;
    }
    case TK_IN: {







|
|







3926
3927
3928
3929
3930
3931
3932
3933
3934
3935
3936
3937
3938
3939
3940
3941
    }
    case TK_SELECT_COLUMN: {
      int n;
      if( pExpr->pLeft->iTable==0 ){
        pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft);
      }
      assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
      if( pExpr->iTable!=0
       && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft))
      ){
        sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
                                pExpr->iTable, n);
      }
      return pExpr->pLeft->iTable + pExpr->iColumn;
    }
    case TK_IN: {
Changes to src/shell.c.in.
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
    sqlite3_result_error(context,
      "edit() cannot reopen temp file after edit", -1);
    goto edit_func_end;
  }
  fseek(f, 0, SEEK_END);
  sz = ftell(f);
  rewind(f);
  p = sqlite3_malloc64( sz+(bBin==0) );
  if( p==0 ){
    sqlite3_result_error_nomem(context);
    goto edit_func_end;
  }
  x = fread(p, 1, (size_t)sz, f);
  fclose(f);
  f = 0;







|







1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
    sqlite3_result_error(context,
      "edit() cannot reopen temp file after edit", -1);
    goto edit_func_end;
  }
  fseek(f, 0, SEEK_END);
  sz = ftell(f);
  rewind(f);
  p = sqlite3_malloc64( sz+1 );
  if( p==0 ){
    sqlite3_result_error_nomem(context);
    goto edit_func_end;
  }
  x = fread(p, 1, (size_t)sz, f);
  fclose(f);
  f = 0;
1762
1763
1764
1765
1766
1767
1768
1769

1770
1771
1772
1773
1774
1775
1776
static void eqp_render_level(ShellState *p, int iEqpId){
  EQPGraphRow *pRow, *pNext;
  int n = strlen30(p->sGraph.zPrefix);
  char *z;
  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
    pNext = eqp_next_row(p, iEqpId, pRow);
    z = pRow->zText;
    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix, pNext ? "|--" : "`--", z);

    if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
      memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
      eqp_render_level(p, pRow->iEqpId);
      p->sGraph.zPrefix[n] = 0;
    }
  }
}







|
>







1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
static void eqp_render_level(ShellState *p, int iEqpId){
  EQPGraphRow *pRow, *pNext;
  int n = strlen30(p->sGraph.zPrefix);
  char *z;
  for(pRow = eqp_next_row(p, iEqpId, 0); pRow; pRow = pNext){
    pNext = eqp_next_row(p, iEqpId, pRow);
    z = pRow->zText;
    utf8_printf(p->out, "%s%s%s\n", p->sGraph.zPrefix,
                pNext ? "|--" : "`--", z);
    if( n<(int)sizeof(p->sGraph.zPrefix)-7 ){
      memcpy(&p->sGraph.zPrefix[n], pNext ? "|  " : "   ", 4);
      eqp_render_level(p, pRow->iEqpId);
      p->sGraph.zPrefix[n] = 0;
    }
  }
}
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
          j--;
        }
        z[j++] = c;
      }
      while( j>0 && IsSpace(z[j-1]) ){ j--; }
      z[j] = 0;
      if( strlen30(z)>=79 ){
        for(i=j=0; (c = z[i])!=0; i++){  /* Copy changes from z[i] back to z[j] */
          if( c==cEnd ){
            cEnd = 0;
          }else if( c=='"' || c=='\'' || c=='`' ){
            cEnd = c;
          }else if( c=='[' ){
            cEnd = ']';
          }else if( c=='-' && z[i+1]=='-' ){







|







1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
          j--;
        }
        z[j++] = c;
      }
      while( j>0 && IsSpace(z[j-1]) ){ j--; }
      z[j] = 0;
      if( strlen30(z)>=79 ){
        for(i=j=0; (c = z[i])!=0; i++){ /* Copy from z[i] back to z[j] */
          if( c==cEnd ){
            cEnd = 0;
          }else if( c=='"' || c=='\'' || c=='`' ){
            cEnd = c;
          }else if( c=='[' ){
            cEnd = ']';
          }else if( c=='-' && z[i+1]=='-' ){
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
    raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
    raw_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
    raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
    raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE, bReset);
    raw_printf(pArg->out, "Reprepare operations:                %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
    raw_printf(pArg->out, "Number of times run:                 %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
    raw_printf(pArg->out, "Memory used by prepared stmt:        %d\n", iCur);
  }








|







2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
    raw_printf(pArg->out, "Fullscan Steps:                      %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_SORT, bReset);
    raw_printf(pArg->out, "Sort Operations:                     %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_AUTOINDEX,bReset);
    raw_printf(pArg->out, "Autoindex Inserts:                   %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_VM_STEP, bReset);
    raw_printf(pArg->out, "Virtual Machine Steps:               %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_REPREPARE,bReset);
    raw_printf(pArg->out, "Reprepare operations:                %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_RUN, bReset);
    raw_printf(pArg->out, "Number of times run:                 %d\n", iCur);
    iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset);
    raw_printf(pArg->out, "Memory used by prepared stmt:        %d\n", iCur);
  }

3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
** start of the description of what that command does.
*/
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
  ".archive ...             Manage SQL archives",
  "   Each command must have exactly one of the following options:",
  "     -c, --create               Create a new archive",
  "     -u, --update               Add files or update files with changed mtime",
  "     -i, --insert               Like -u but always add even if mtime unchanged",
  "     -t, --list                 List contents of archive",
  "     -x, --extract              Extract files from archive",
  "   Optional arguments:",
  "     -v, --verbose              Print each filename as it is processed",
  "     -f FILE, --file FILE       Operate on archive FILE (default is current db)",
  "     -a FILE, --append FILE     Operate on FILE opened using the apndvfs VFS",
  "     -C DIR, --directory DIR    Change to directory DIR to read/extract files",
  "     -n, --dryrun               Show the SQL that would have occurred",
  "   Examples:",
  "     .ar -cf archive.sar foo bar  # Create archive.sar from files foo and bar",
  "     .ar -tf archive.sar          # List members of archive.sar",
  "     .ar -xvf archive.sar         # Verbosely extract files from archive.sar",
  "   See also:",
  "      http://sqlite.org/cli.html#sqlar_archive_support",
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
  ".auth ON|OFF             Show authorizer callbacks",
#endif
  ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",
  "       --append            Use the appendvfs",
  "       --async             Write to FILE without a journal and without fsync()",
  ".bail on|off             Stop after hitting an error.  Default OFF",
  ".binary on|off           Turn binary output on or off.  Default OFF",
  ".cd DIRECTORY            Change the working directory to DIRECTORY",
  ".changes on|off          Show number of rows changed by SQL",
  ".check GLOB              Fail if output since .testcase does not match",
  ".clone NEWDB             Clone data into NEWDB from the existing database",
  ".databases               List names and files of attached databases",
  ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
  ".dbinfo ?DB?             Show status information about the database",
  ".dump ?TABLE? ...        Render all database content as SQL",
  "   Options:",
  "     --preserve-rowids      Include ROWID values in the output",
  "     --newlines             Allow unescaped newline characters in output",
  "   TABLE is a LIKE pattern for the tables to dump",
  ".echo on|off             Turn command echo on or off",
  ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",
  "   Other Modes:",
#ifdef SQLITE_DEBUG
  "      test                  Show raw EXPLAIN QUERY PLAN output",
  "      trace                 Like \"full\" but also enable \"PRAGMA vdbe_trace\"",
#endif
  "      trigger               Like \"full\" but also show trigger bytecode",
  ".excel                   Display the output of next command in a spreadsheet",
  ".exit ?CODE?             Exit this program with return-code CODE",
  ".expert                  EXPERIMENTAL. Suggest indexes for specified queries",
/* Because explain mode comes on automatically now, the ".explain" mode
** is removed from the help screen.  It is still supported for legacy, however */
/*".explain ?on|off|auto?   Turn EXPLAIN output mode on or off or to automatic",*/
  ".filectrl CMD ...        Run various sqlite3_file_control() operations",
  "                           Run \".filectrl\" with no arguments for details",
  ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
  ".headers on|off          Turn display of headers on or off",
  ".help ?-all? ?PATTERN?   Show help text for PATTERN",
  ".import FILE TABLE       Import data from FILE into TABLE",
#ifndef SQLITE_OMIT_TEST_CONTROL







|
|




|
|
|


|
|
|








|



















|


|

|

|
|







3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
** start of the description of what that command does.
*/
static const char *(azHelp[]) = {
#if defined(SQLITE_HAVE_ZLIB) && !defined(SQLITE_OMIT_VIRTUALTABLE)
  ".archive ...             Manage SQL archives",
  "   Each command must have exactly one of the following options:",
  "     -c, --create               Create a new archive",
  "     -u, --update               Add or update files with changed mtime",
  "     -i, --insert               Like -u but always add even if unchanged",
  "     -t, --list                 List contents of archive",
  "     -x, --extract              Extract files from archive",
  "   Optional arguments:",
  "     -v, --verbose              Print each filename as it is processed",
  "     -f FILE, --file FILE       Use archive FILE (default is current db)",
  "     -a FILE, --append FILE     Open FILE using the apndvfs VFS",
  "     -C DIR, --directory DIR    Read/extract files from directory DIR",
  "     -n, --dryrun               Show the SQL that would have occurred",
  "   Examples:",
  "     .ar -cf ARCHIVE foo bar  # Create ARCHIVE from files foo and bar",
  "     .ar -tf ARCHIVE          # List members of ARCHIVE",
  "     .ar -xvf ARCHIVE         # Verbosely extract files from ARCHIVE",
  "   See also:",
  "      http://sqlite.org/cli.html#sqlar_archive_support",
#endif
#ifndef SQLITE_OMIT_AUTHORIZATION
  ".auth ON|OFF             Show authorizer callbacks",
#endif
  ".backup ?DB? FILE        Backup DB (default \"main\") to FILE",
  "       --append            Use the appendvfs",
  "       --async             Write to FILE without journal and fsync()",
  ".bail on|off             Stop after hitting an error.  Default OFF",
  ".binary on|off           Turn binary output on or off.  Default OFF",
  ".cd DIRECTORY            Change the working directory to DIRECTORY",
  ".changes on|off          Show number of rows changed by SQL",
  ".check GLOB              Fail if output since .testcase does not match",
  ".clone NEWDB             Clone data into NEWDB from the existing database",
  ".databases               List names and files of attached databases",
  ".dbconfig ?op? ?val?     List or change sqlite3_db_config() options",
  ".dbinfo ?DB?             Show status information about the database",
  ".dump ?TABLE? ...        Render all database content as SQL",
  "   Options:",
  "     --preserve-rowids      Include ROWID values in the output",
  "     --newlines             Allow unescaped newline characters in output",
  "   TABLE is a LIKE pattern for the tables to dump",
  ".echo on|off             Turn command echo on or off",
  ".eqp on|off|full|...     Enable or disable automatic EXPLAIN QUERY PLAN",
  "   Other Modes:",
#ifdef SQLITE_DEBUG
  "      test                  Show raw EXPLAIN QUERY PLAN output",
  "      trace                 Like \"full\" but enable \"PRAGMA vdbe_trace\"",
#endif
  "      trigger               Like \"full\" but also show trigger bytecode",
  ".excel                   Display the output of next command in spreadsheet",
  ".exit ?CODE?             Exit this program with return-code CODE",
  ".expert                  EXPERIMENTAL. Suggest indexes for queries",
/* Because explain mode comes on automatically now, the ".explain" mode
** is removed from the help screen. It is still supported for legacy, however */
/*".explain ?on|off|auto?   Turn EXPLAIN output mode on or off",*/
  ".filectrl CMD ...        Run various sqlite3_file_control() operations",
  "                           Run \".filectrl\" with no arguments for details",
  ".fullschema ?--indent?   Show schema and the content of sqlite_stat tables",
  ".headers on|off          Turn display of headers on or off",
  ".help ?-all? ?PATTERN?   Show help text for PATTERN",
  ".import FILE TABLE       Import data from FILE into TABLE",
#ifndef SQLITE_OMIT_TEST_CONTROL
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586



3587
3588
3589
3590
3591
3592
3593
  "       -e    Invoke system text editor",
  "       -x    Open in a spreadsheet",
  ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",
  "     Options:",
  "        --append        Use appendvfs to append database to the end of FILE",
#ifdef SQLITE_ENABLE_DESERIALIZE
  "        --deserialize   Load into memory useing sqlite3_deserialize()",
  "        --hexdb         Load the output of \"dbtotxt\" as an in-memory database",
  "        --maxsize N     Maximum size for --hexdb or --deserialized database",
#endif
  "        --new           Initialize FILE to an empty database",
  "        --readonly      Open FILE readonly",
  "        --zip           FILE is a ZIP archive",
  ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
  "     If FILE begins with '|' then open it as a pipe.",
  ".parameter CMD ...       Manage SQL parameter bindings",
  "   clear                   Erase all bindings",
  "   init                    Initialize the TEMP table that holds bindings",
  "   list                    List the current parameter bindings",
  "   set PARAMETER VALUE     Given SQL parameter PARAMETER a value of VALUE",
  "                           PARAMETER should start with '$', ':', '@', or '?'",
  "   unset PARAMETER         Remove PARAMETER from the binding table",
  ".print STRING...         Print literal STRING",
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  ".progress N              Invoke progress handler after every N opcodes",
  "   --limit N                 Interrupt after N progress callbacks",
  "   --once                    Do no more than one progress interrupt",
  "   --quiet|-q                No output except at interrupts",
  "   --reset                   Reset the count for each input and interrupt",
#endif
  ".prompt MAIN CONTINUE    Replace the standard prompts",
  ".quit                    Exit this program",
  ".read FILE               Read input from FILE",
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
  ".recover                 Recover as much data as possible from corrupt db.",



#endif
  ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
  ".save FILE               Write in-memory database into FILE",
  ".scanstats on|off        Turn sqlite3_stmt_scanstatus() metrics on or off",
  ".schema ?PATTERN?        Show the CREATE statements matching PATTERN",
  "     Options:",
  "         --indent            Try to pretty-print the schema",







|












|














>
>
>







3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
3585
3586
3587
3588
3589
3590
3591
3592
3593
3594
3595
3596
3597
  "       -e    Invoke system text editor",
  "       -x    Open in a spreadsheet",
  ".open ?OPTIONS? ?FILE?   Close existing database and reopen FILE",
  "     Options:",
  "        --append        Use appendvfs to append database to the end of FILE",
#ifdef SQLITE_ENABLE_DESERIALIZE
  "        --deserialize   Load into memory useing sqlite3_deserialize()",
  "        --hexdb         Load the output of \"dbtotxt\" as an in-memory db",
  "        --maxsize N     Maximum size for --hexdb or --deserialized database",
#endif
  "        --new           Initialize FILE to an empty database",
  "        --readonly      Open FILE readonly",
  "        --zip           FILE is a ZIP archive",
  ".output ?FILE?           Send output to FILE or stdout if FILE is omitted",
  "     If FILE begins with '|' then open it as a pipe.",
  ".parameter CMD ...       Manage SQL parameter bindings",
  "   clear                   Erase all bindings",
  "   init                    Initialize the TEMP table that holds bindings",
  "   list                    List the current parameter bindings",
  "   set PARAMETER VALUE     Given SQL parameter PARAMETER a value of VALUE",
  "                           PARAMETER should start with one of: $ : @ ?",
  "   unset PARAMETER         Remove PARAMETER from the binding table",
  ".print STRING...         Print literal STRING",
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  ".progress N              Invoke progress handler after every N opcodes",
  "   --limit N                 Interrupt after N progress callbacks",
  "   --once                    Do no more than one progress interrupt",
  "   --quiet|-q                No output except at interrupts",
  "   --reset                   Reset the count for each input and interrupt",
#endif
  ".prompt MAIN CONTINUE    Replace the standard prompts",
  ".quit                    Exit this program",
  ".read FILE               Read input from FILE",
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
  ".recover                 Recover as much data as possible from corrupt db.",
  "   --freelist-corrupt       Assume the freelist is corrupt",
  "   --recovery-db NAME       Store recovery metadata in database file NAME",
  "   --lost-and-found TABLE   Alternative name for the lost-and-found table",
#endif
  ".restore ?DB? FILE       Restore content of DB (default \"main\") from FILE",
  ".save FILE               Write in-memory database into FILE",
  ".scanstats on|off        Turn sqlite3_stmt_scanstatus() metrics on or off",
  ".schema ?PATTERN?        Show the CREATE statements matching PATTERN",
  "     Options:",
  "         --indent            Try to pretty-print the schema",
3611
3612
3613
3614
3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
  "     patchset FILE            Write a patchset into FILE",
  "   If ?NAME? is omitted, the first defined session is used.",
#endif
  ".sha3sum ...             Compute a SHA3 hash of database content",
  "    Options:",
  "      --schema              Also hash the sqlite_master table",
  "      --sha3-224            Use the sha3-224 algorithm",
  "      --sha3-256            Use the sha3-256 algorithm.  This is the default.",
  "      --sha3-384            Use the sha3-384 algorithm",
  "      --sha3-512            Use the sha3-512 algorithm",
  "    Any other argument is a LIKE pattern for tables to hash",
#ifndef SQLITE_NOHAVE_SYSTEM
  ".shell CMD ARGS...       Run CMD ARGS... in a system shell",
#endif
  ".show                    Show the current values for various settings",







|







3615
3616
3617
3618
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
  "     patchset FILE            Write a patchset into FILE",
  "   If ?NAME? is omitted, the first defined session is used.",
#endif
  ".sha3sum ...             Compute a SHA3 hash of database content",
  "    Options:",
  "      --schema              Also hash the sqlite_master table",
  "      --sha3-224            Use the sha3-224 algorithm",
  "      --sha3-256            Use the sha3-256 algorithm (default)",
  "      --sha3-384            Use the sha3-384 algorithm",
  "      --sha3-512            Use the sha3-512 algorithm",
  "    Any other argument is a LIKE pattern for tables to hash",
#ifndef SQLITE_NOHAVE_SYSTEM
  ".shell CMD ARGS...       Run CMD ARGS... in a system shell",
#endif
  ".show                    Show the current values for various settings",
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
    }
    *pRc = rc;
  }
}
#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
/*********************************************************************************
** The ".archive" or ".ar" command.
*/
/*
** Structure representing a single ".ar" command.
*/
typedef struct ArCommand ArCommand;
struct ArCommand {







|







5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
    }
    *pRc = rc;
  }
}
#endif /* !defined SQLITE_OMIT_VIRTUALTABLE */

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB)
/******************************************************************************
** The ".archive" or ".ar" command.
*/
/*
** Structure representing a single ".ar" command.
*/
typedef struct ArCommand ArCommand;
struct ArCommand {
5717
5718
5719
5720
5721
5722
5723
5724

5725
5726
5727
5728
5729
5730
5731
            }
            if( pOpt->bArg ){
              if( i<(n-1) ){
                zArg = &z[i+1];
                i = n;
              }else{
                if( iArg>=(nArg-1) ){
                  return arErrorMsg(pAr, "option requires an argument: %c",z[i]);

                }
                zArg = azArg[++iArg];
              }
            }
            if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
          }
        }else if( z[2]=='\0' ){







|
>







5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
            }
            if( pOpt->bArg ){
              if( i<(n-1) ){
                zArg = &z[i+1];
                i = n;
              }else{
                if( iArg>=(nArg-1) ){
                  return arErrorMsg(pAr, "option requires an argument: %c",
                                    z[i]);
                }
                zArg = azArg[++iArg];
              }
            }
            if( arProcessSwitch(pAr, pOpt->eSwitch, zArg) ) return SQLITE_ERROR;
          }
        }else if( z[2]=='\0' ){
6105
6106
6107
6108
6109
6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
  return rc;
}

/*
** Implementation of ".ar" dot command.
*/
static int arDotCommand(
  ShellState *pState,             /* Current shell tool state */
  int fromCmdLine,                /* True if -A command-line option, not .ar cmd */
  char **azArg,                   /* Array of arguments passed to dot command */
  int nArg                        /* Number of entries in azArg[] */
){
  ArCommand cmd;
  int rc;
  memset(&cmd, 0, sizeof(cmd));
  cmd.fromCmdLine = fromCmdLine;
  rc = arParseCommand(azArg, nArg, &cmd);
  if( rc==SQLITE_OK ){







|
|
|
|







6110
6111
6112
6113
6114
6115
6116
6117
6118
6119
6120
6121
6122
6123
6124
6125
6126
6127
  return rc;
}

/*
** Implementation of ".ar" dot command.
*/
static int arDotCommand(
  ShellState *pState,          /* Current shell tool state */
  int fromCmdLine,             /* True if -A command-line option, not .ar cmd */
  char **azArg,                /* Array of arguments passed to dot command */
  int nArg                     /* Number of entries in azArg[] */
){
  ArCommand cmd;
  int rc;
  memset(&cmd, 0, sizeof(cmd));
  cmd.fromCmdLine = fromCmdLine;
  rc = arParseCommand(azArg, nArg, &cmd);
  if( rc==SQLITE_OK ){
6208
6209
6210
6211
6212
6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
    close_db(cmd.db);
  }
  sqlite3_free(cmd.zSrcTable);

  return rc;
}
/* End of the ".archive" or ".ar" command logic
**********************************************************************************/
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
/*
** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
** Otherwise, the SQL statement or statements in zSql are executed using
** database connection db and the error code written to *pRc before







|







6213
6214
6215
6216
6217
6218
6219
6220
6221
6222
6223
6224
6225
6226
6227
    close_db(cmd.db);
  }
  sqlite3_free(cmd.zSrcTable);

  return rc;
}
/* End of the ".archive" or ".ar" command logic
*******************************************************************************/
#endif /* !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_HAVE_ZLIB) */

#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
/*
** If (*pRc) is not SQLITE_OK when this function is called, it is a no-op.
** Otherwise, the SQL statement or statements in zSql are executed using
** database connection db and the error code written to *pRc before
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
      zRecoveryDb = azArg[i];
    }else
    if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
      i++;
      zLostAndFound = azArg[i];
    }
    else{
      raw_printf(stderr, "unexpected option: %s\n", azArg[i]); 
      raw_printf(stderr, "options are:\n");
      raw_printf(stderr, "    --freelist-corrupt\n");
      raw_printf(stderr, "    --recovery-db DATABASE\n");
      raw_printf(stderr, "    --lost-and-found TABLE-NAME\n");
      return 1;
    }
  }

  shellExecPrintf(pState->db, &rc,
    /* Attach an in-memory database named 'recovery'. Create an indexed 
    ** cache of the sqlite_dbptr virtual table. */







|
|
<
<
<







6605
6606
6607
6608
6609
6610
6611
6612
6613



6614
6615
6616
6617
6618
6619
6620
      zRecoveryDb = azArg[i];
    }else
    if( n<=15 && memcmp("-lost-and-found", z, n)==0 && i<(nArg-1) ){
      i++;
      zLostAndFound = azArg[i];
    }
    else{
      utf8_printf(stderr, "unexpected option: %s\n", azArg[i]); 
      showHelp(pState->out, azArg[0]);



      return 1;
    }
  }

  shellExecPrintf(pState->db, &rc,
    /* Attach an in-memory database named 'recovery'. Create an indexed 
    ** cache of the sqlite_dbptr virtual table. */
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
    "      SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
    "        UNION "
    "      SELECT i, p.parent, "
    "        (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
    "    )"
    "    SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
    ") "
    "FROM pages WHERE maxlen > 0 AND i NOT IN freelist;"
    "UPDATE recovery.map AS o SET intkey = ("
    "  SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
    ");"

    /* Extract data from page 1 and any linked pages into table
    ** recovery.schema. With the same schema as an sqlite_master table.  */
    "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"







|







6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
    "      SELECT 0, i, (SELECT pgno FROM recovery.dbptr WHERE child=i)"
    "        UNION "
    "      SELECT i, p.parent, "
    "        (SELECT pgno FROM recovery.dbptr WHERE child=p.parent) FROM p"
    "    )"
    "    SELECT pgno FROM p WHERE (parent IS NULL OR pgno = orig)"
    ") "
    "FROM pages WHERE maxlen IS NOT NULL AND i NOT IN freelist;"
    "UPDATE recovery.map AS o SET intkey = ("
    "  SELECT substr(data, 1, 1)==X'0D' FROM sqlite_dbpage WHERE pgno=o.pgno"
    ");"

    /* Extract data from page 1 and any linked pages into table
    ** recovery.schema. With the same schema as an sqlite_master table.  */
    "CREATE TABLE recovery.schema(type, name, tbl_name, rootpage, sql);"
8463
8464
8465
8466
8467
8468
8469
8470

8471
8472
8473
8474
8475
8476
8477
        appendText(&sSelect, ".sqlite_master", 0);
      }
      sqlite3_finalize(pStmt);
#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
      if( zName ){
        appendText(&sSelect,
           " UNION ALL SELECT shell_module_schema(name),"
           " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list", 0);

      }
#endif
      appendText(&sSelect, ") WHERE ", 0);
      if( zName ){
        char *zQarg = sqlite3_mprintf("%Q", zName);
        int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
                    strchr(zName, '[') != 0;







|
>







8465
8466
8467
8468
8469
8470
8471
8472
8473
8474
8475
8476
8477
8478
8479
8480
        appendText(&sSelect, ".sqlite_master", 0);
      }
      sqlite3_finalize(pStmt);
#ifndef SQLITE_OMIT_INTROSPECTION_PRAGMAS
      if( zName ){
        appendText(&sSelect,
           " UNION ALL SELECT shell_module_schema(name),"
           " 'table', name, name, name, 9e+99, 'main' FROM pragma_module_list",
        0);
      }
#endif
      appendText(&sSelect, ") WHERE ", 0);
      if( zName ){
        char *zQarg = sqlite3_mprintf("%Q", zName);
        int bGlob = strchr(zName, '*') != 0 || strchr(zName, '?') != 0 ||
                    strchr(zName, '[') != 0;
8562
8563
8564
8565
8566
8567
8568
8569

8570
8571
8572
8573
8574
8575
8576
    */
    if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
      FILE *out = 0;
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ) goto session_not_open;
      out = fopen(azCmd[1], "wb");
      if( out==0 ){
        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n", azCmd[1]);

      }else{
        int szChng;
        void *pChng;
        if( azCmd[0][0]=='c' ){
          rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
        }else{
          rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);







|
>







8565
8566
8567
8568
8569
8570
8571
8572
8573
8574
8575
8576
8577
8578
8579
8580
    */
    if( strcmp(azCmd[0],"changeset")==0 || strcmp(azCmd[0],"patchset")==0 ){
      FILE *out = 0;
      if( nCmd!=2 ) goto session_syntax_error;
      if( pSession->p==0 ) goto session_not_open;
      out = fopen(azCmd[1], "wb");
      if( out==0 ){
        utf8_printf(stderr, "ERROR: cannot open \"%s\" for writing\n",
                    azCmd[1]);
      }else{
        int szChng;
        void *pChng;
        if( azCmd[0][0]=='c' ){
          rc = sqlite3session_changeset(pSession->p, &szChng, &pChng);
        }else{
          rc = sqlite3session_patchset(pSession->p, &szChng, &pChng);
8883
8884
8885
8886
8887
8888
8889
8890
8891
8892
8893
8894
8895
8896
8897
8898
        }else
        if( strcmp(z,"debug")==0 ){
          bDebug = 1;
        }else
        {
          utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                      azArg[i], azArg[0]);
          raw_printf(stderr, "Should be one of: --schema"
                             " --sha3-224 --sha3-256 --sha3-384 --sha3-512\n");
          rc = 1;
          goto meta_command_exit;
        }
      }else if( zLike ){
        raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;







|
<







8887
8888
8889
8890
8891
8892
8893
8894

8895
8896
8897
8898
8899
8900
8901
        }else
        if( strcmp(z,"debug")==0 ){
          bDebug = 1;
        }else
        {
          utf8_printf(stderr, "Unknown option \"%s\" on \"%s\"\n",
                      azArg[i], azArg[0]);
          showHelp(p->out, azArg[0]);

          rc = 1;
          goto meta_command_exit;
        }
      }else if( zLike ){
        raw_printf(stderr, "Usage: .sha3sum ?OPTIONS? ?LIKE-PATTERN?\n");
        rc = 1;
        goto meta_command_exit;
9162
9163
9164
9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
#ifndef SQLITE_UNTESTABLE
  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
       const char *zUsage;      /* Usage notes */
    } aCtrl[] = {
      { "always",             SQLITE_TESTCTRL_ALWAYS,        "BOOLEAN"            },
      { "assert",             SQLITE_TESTCTRL_ASSERT,        "BOOLEAN"            },
    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, ""          },*/
    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST,   ""                },*/
      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER,     ""                   },
      { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN"       },
    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, ""                }, */
      { "imposter",           SQLITE_TESTCTRL_IMPOSTER,   "SCHEMA ON/OFF ROOTPAGE"},
      { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN"       },
      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"           },
      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"            },
      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"       },
#ifdef YYCOVERAGE
      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""                 },
#endif
      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "           },
      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""                   },
      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""                   },
      { "prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,     "SEED ?db?"          },
      { "reserve",            SQLITE_TESTCTRL_RESERVE,       "BYTES-OF-RESERVE"   },
    };
    int testctrl = -1;
    int iCtrl = -1;
    int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
    int isOk = 0;
    int i, n2;
    const char *zCmd = 0;







|
|
|
|
|
|
|
|
|
|
|
|

|

|
|
|
|
|







9165
9166
9167
9168
9169
9170
9171
9172
9173
9174
9175
9176
9177
9178
9179
9180
9181
9182
9183
9184
9185
9186
9187
9188
9189
9190
9191
9192
9193
9194
9195
9196
9197
9198
#ifndef SQLITE_UNTESTABLE
  if( c=='t' && n>=8 && strncmp(azArg[0], "testctrl", n)==0 ){
    static const struct {
       const char *zCtrlName;   /* Name of a test-control option */
       int ctrlCode;            /* Integer code for that option */
       const char *zUsage;      /* Usage notes */
    } aCtrl[] = {
      { "always",             SQLITE_TESTCTRL_ALWAYS,        "BOOLEAN"        },
      { "assert",             SQLITE_TESTCTRL_ASSERT,        "BOOLEAN"        },
    /*{ "benign_malloc_hooks",SQLITE_TESTCTRL_BENIGN_MALLOC_HOOKS, ""       },*/
    /*{ "bitvec_test",        SQLITE_TESTCTRL_BITVEC_TEST,   ""             },*/
      { "byteorder",          SQLITE_TESTCTRL_BYTEORDER,     ""               },
      { "extra_schema_checks",SQLITE_TESTCTRL_EXTRA_SCHEMA_CHECKS,"BOOLEAN"   },
    /*{ "fault_install",      SQLITE_TESTCTRL_FAULT_INSTALL, ""             },*/
      { "imposter",         SQLITE_TESTCTRL_IMPOSTER, "SCHEMA ON/OFF ROOTPAGE"},
      { "internal_functions", SQLITE_TESTCTRL_INTERNAL_FUNCTIONS, "BOOLEAN"   },
      { "localtime_fault",    SQLITE_TESTCTRL_LOCALTIME_FAULT,"BOOLEAN"       },
      { "never_corrupt",      SQLITE_TESTCTRL_NEVER_CORRUPT, "BOOLEAN"        },
      { "optimizations",      SQLITE_TESTCTRL_OPTIMIZATIONS, "DISABLE-MASK"   },
#ifdef YYCOVERAGE
      { "parser_coverage",    SQLITE_TESTCTRL_PARSER_COVERAGE, ""             },
#endif
      { "pending_byte",       SQLITE_TESTCTRL_PENDING_BYTE,  "OFFSET  "       },
      { "prng_restore",       SQLITE_TESTCTRL_PRNG_RESTORE,  ""               },
      { "prng_save",          SQLITE_TESTCTRL_PRNG_SAVE,     ""               },
      { "prng_seed",          SQLITE_TESTCTRL_PRNG_SEED,     "SEED ?db?"      },
      { "reserve",            SQLITE_TESTCTRL_RESERVE,      "BYTES-OF-RESERVE"},
    };
    int testctrl = -1;
    int iCtrl = -1;
    int rc2 = 0;    /* 0: usage.  1: %d  2: %x  3: no-output */
    int isOk = 0;
    int i, n2;
    const char *zCmd = 0;
9324
9325
9326
9327
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
            sqlite3_test_control(testctrl, p->out);
            isOk = 3;
          }
#endif
      }
    }
    if( isOk==0 && iCtrl>=0 ){
      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd, aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
      raw_printf(p->out, "%d\n", rc2);
    }else if( isOk==2 ){
      raw_printf(p->out, "0x%08x\n", rc2);
    }
  }else







|







9327
9328
9329
9330
9331
9332
9333
9334
9335
9336
9337
9338
9339
9340
9341
            sqlite3_test_control(testctrl, p->out);
            isOk = 3;
          }
#endif
      }
    }
    if( isOk==0 && iCtrl>=0 ){
      utf8_printf(p->out, "Usage: .testctrl %s %s\n", zCmd,aCtrl[iCtrl].zUsage);
      rc = 1;
    }else if( isOk==1 ){
      raw_printf(p->out, "%d\n", rc2);
    }else if( isOk==2 ){
      raw_printf(p->out, "0x%08x\n", rc2);
    }
  }else
9441
9442
9443
9444
9445
9446
9447
9448

9449
9450
9451
9452
9453
9454
9455
    open_db(p, 0);
    if( strcmp(azArg[1],"login")==0 ){
      if( nArg!=4 ){
        raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3], strlen30(azArg[3]));

      if( rc ){
        utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
        rc = 1;
      }
    }else if( strcmp(azArg[1],"add")==0 ){
      if( nArg!=5 ){
        raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");







|
>







9444
9445
9446
9447
9448
9449
9450
9451
9452
9453
9454
9455
9456
9457
9458
9459
    open_db(p, 0);
    if( strcmp(azArg[1],"login")==0 ){
      if( nArg!=4 ){
        raw_printf(stderr, "Usage: .user login USER PASSWORD\n");
        rc = 1;
        goto meta_command_exit;
      }
      rc = sqlite3_user_authenticate(p->db, azArg[2], azArg[3],
                                     strlen30(azArg[3]));
      if( rc ){
        utf8_printf(stderr, "Authentication failed for user %s\n", azArg[2]);
        rc = 1;
      }
    }else if( strcmp(azArg[1],"add")==0 ){
      if( nArg!=5 ){
        raw_printf(stderr, "Usage: .user add USER PASSWORD ISADMIN\n");
Changes to src/sqliteInt.h.
2469
2470
2471
2472
2473
2474
2475

2476
2477
2478
2479
2480
2481
2482
#if SQLITE_MAX_EXPR_DEPTH>0
  int nHeight;           /* Height of the tree headed by this node */
#endif
  int iTable;            /* TK_COLUMN: cursor number of table holding column
                         ** TK_REGISTER: register number
                         ** TK_TRIGGER: 1 -> new, 0 -> old
                         ** EP_Unlikely:  134217728 times likelihood

                         ** TK_SELECT: 1st register of result vector */
  ynVar iColumn;         /* TK_COLUMN: column index.  -1 for rowid.
                         ** TK_VARIABLE: variable number (always >= 1).
                         ** TK_SELECT_COLUMN: column of the result vector */
  i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
  i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
  u8 op2;                /* TK_REGISTER/TK_TRUTH: original value of Expr.op







>







2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
#if SQLITE_MAX_EXPR_DEPTH>0
  int nHeight;           /* Height of the tree headed by this node */
#endif
  int iTable;            /* TK_COLUMN: cursor number of table holding column
                         ** TK_REGISTER: register number
                         ** TK_TRIGGER: 1 -> new, 0 -> old
                         ** EP_Unlikely:  134217728 times likelihood
                         ** TK_SELECT_COLUMN: Number of columns on the LHS
                         ** TK_SELECT: 1st register of result vector */
  ynVar iColumn;         /* TK_COLUMN: column index.  -1 for rowid.
                         ** TK_VARIABLE: variable number (always >= 1).
                         ** TK_SELECT_COLUMN: column of the result vector */
  i16 iAgg;              /* Which entry in pAggInfo->aCol[] or ->aFunc[] */
  i16 iRightJoinTable;   /* If EP_FromJoin, the right table of the join */
  u8 op2;                /* TK_REGISTER/TK_TRUTH: original value of Expr.op
Changes to test/rowvalue7.test.
51
52
53
54
55
56
57










58
  UPDATE t1 SET (c,d) = (SELECT x,y,z FROM t2 WHERE w=a);
} {1 {2 columns assigned 3 values}}

do_catchsql_test 2.2 {
  UPDATE t1 SET (b,c,d) = (SELECT x,y FROM t2 WHERE w=a);
} {1 {3 columns assigned 2 values}}











finish_test







>
>
>
>
>
>
>
>
>
>

51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
  UPDATE t1 SET (c,d) = (SELECT x,y,z FROM t2 WHERE w=a);
} {1 {2 columns assigned 3 values}}

do_catchsql_test 2.2 {
  UPDATE t1 SET (b,c,d) = (SELECT x,y FROM t2 WHERE w=a);
} {1 {3 columns assigned 2 values}}

# 2019-08-26
# ticket https://www.sqlite.org/src/info/78acc9d40f0786e8
#
do_catchsql_test 3.0 {
  DROP TABLE IF EXISTS t1;
  CREATE TABLE t1(a,b);
  INSERT INTO t1 VALUES(1,2);
  UPDATE t1 SET (a,a,a,b)=(SELECT 99,100);
} {1 {4 columns assigned 2 values}}

finish_test