SQLite4
Check-in [0866df185c]
Not logged in

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

Overview
Comment:Various fixes so that the "bt" permutation test passes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 0866df185cdaae6a6e15571d4e0fca15a7f5e650
User & Date: dan 2013-11-15 18:47:01
Context
2013-11-15
19:18
Add test file fkey2.test to the list of files used by the "bt" permutation. check-in: 5c2af9e0b7 user: dan tags: trunk
18:47
Various fixes so that the "bt" permutation test passes. check-in: 0866df185c user: dan tags: trunk
09:44
Add a checksum to the database header. check-in: cba26fd7cc user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/bt_log.c.

1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738

1739
1740
1741
1742
1743
1744
1745
int sqlite4BtLogCheckpoint(BtLog *pLog, int nFrameBuffer){
  BtLock *pLock = pLog->pLock;
  int rc;

  /* Take the CHECKPOINTER lock. */
  rc = sqlite4BtLockCkpt(pLock);
  if( rc==SQLITE4_OK ){
    const int pgsz = sqlite4BtPagerPagesize((BtPager*)pLock);
    bt_env *pVfs = pLock->pVfs;
    bt_file *pFd = pLock->pFd;
    BtShm *pShm;                  /* Pointer to shared-memory region */
    u32 iLast;                    /* Last frame to checkpoint */
    BtFrameHdr fhdr;              /* Frame header of frame iLast */
    u32 *aPgno = 0;               /* Array of page numbers to checkpoint */
    int nPgno;                    /* Number of entries in aPgno[] */
    int i;                        /* Used to loop through aPgno[] */
    u8 *aBuf;                     /* Buffer to load page data into */
    u32 iFirstRead;               /* First frame not checkpointed */

    rc = btLogSnapshot(pLog, &pLog->snapshot);


    if( rc==SQLITE4_OK ){
      /* Allocate space to load log data into */
      aBuf = sqlite4_malloc(pLock->pEnv, pgsz);
      if( aBuf==0 ) rc = btErrorBkpt(SQLITE4_NOMEM);
    }
    







|












>







1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
int sqlite4BtLogCheckpoint(BtLog *pLog, int nFrameBuffer){
  BtLock *pLock = pLog->pLock;
  int rc;

  /* Take the CHECKPOINTER lock. */
  rc = sqlite4BtLockCkpt(pLock);
  if( rc==SQLITE4_OK ){
    int pgsz;
    bt_env *pVfs = pLock->pVfs;
    bt_file *pFd = pLock->pFd;
    BtShm *pShm;                  /* Pointer to shared-memory region */
    u32 iLast;                    /* Last frame to checkpoint */
    BtFrameHdr fhdr;              /* Frame header of frame iLast */
    u32 *aPgno = 0;               /* Array of page numbers to checkpoint */
    int nPgno;                    /* Number of entries in aPgno[] */
    int i;                        /* Used to loop through aPgno[] */
    u8 *aBuf;                     /* Buffer to load page data into */
    u32 iFirstRead;               /* First frame not checkpointed */

    rc = btLogSnapshot(pLog, &pLog->snapshot);
    pgsz = pLog->snapshot.pgsz;

    if( rc==SQLITE4_OK ){
      /* Allocate space to load log data into */
      aBuf = sqlite4_malloc(pLock->pEnv, pgsz);
      if( aBuf==0 ) rc = btErrorBkpt(SQLITE4_NOMEM);
    }
    

Changes to src/bt_main.c.

1049
1050
1051
1052
1053
1054
1055






1056
1057
1058
1059
1060
1061

1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
....
1096
1097
1098
1099
1100
1101
1102







1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132

1133
1134
1135
1136
1137
1138
1139
....
2363
2364
2365
2366
2367
2368
2369

2370
2371
2372
2373
2374
2375
2376
    }
  }

  return rc;
}

int sqlite4BtCsrKey(bt_cursor *pCsr, const void **ppK, int *pnK){






  const int pgsz = sqlite4BtPagerPagesize(pCsr->pDb->pPager);
  u8 *aData;
  u8 *pCell;
  int iCell = pCsr->aiCell[pCsr->nPg-1];
  int nK;
  int rc;


  rc = btCsrReseek(pCsr);
  if( rc==SQLITE4_OK ){
    aData = (u8*)sqlite4BtPageData(pCsr->apPage[pCsr->nPg-1]);
    assert( btCellCount(aData, pgsz)>iCell );
    pCell = btCellFind(aData, pgsz, iCell);
    pCell += sqlite4BtVarintGet32(pCell, &nK);

    if( nK==0 ){
      /* type (c) leaf cell */
................................................................................
  u8 *pCell;
  int iCell = pCsr->aiCell[pCsr->nPg-1];
  int nK = 0;
  int nV = 0;

  rc = btCsrReseek(pCsr);
  if( rc==SQLITE4_OK ){







    aData = (u8*)sqlite4BtPageData(pCsr->apPage[pCsr->nPg-1]);
    pCell = btCellFind(aData, pgsz, iCell);
    pCell += sqlite4BtVarintGet32(pCell, &nK);
    if( nK>0 ){
      pCell += nK;
      pCell += sqlite4BtVarintGet32(pCell, &nV);
    }

    if( nV==0 ){
      rc = btCsrBuffer(pCsr, 1);
      if( rc==SQLITE4_OK ){
        u8 *aBuf = (u8*)pCsr->ovfl.buf.p;
        *ppV = &aBuf[pCsr->ovfl.nKey];
        *pnV = pCsr->ovfl.nVal;
      }
    }else{
      *ppV = pCell;
      *pnV = (nV-1);
    }

#ifndef NDEBUG
    if( rc==SQLITE4_OK ){
      const void *pK; int nK;
      rc = sqlite4BtCsrKey(pCsr, &pK, &nK);
      if( rc==SQLITE4_OK ){
        BtLock *pLock = (BtLock*)pCsr->pDb->pPager;
        sqlite4BtDebugKV(pLock, "select", (u8*)pK, nK, (u8*)*ppV, *pnV);
      }
    }
#endif

  }

  return rc;
}

/*
** The argument points to a buffer containing an overflow array. Return
................................................................................

static int btSaveAllCursor(bt_db *pDb, bt_cursor *pCsr){
  int rc = SQLITE4_OK;            /* Return code */
  bt_cursor *p;                   /* Used to iterate through cursors */

  for(p=pDb->pAllCsr; rc==SQLITE4_OK && p; p=p->pNextCsr){
    if( p->nPg>0 ){

      rc = btCsrBuffer(p, 0);
      if( rc==SQLITE4_OK ){
        assert( p->ovfl.buf.p );
        p->bRequireReseek = 1;
        if( p!=pCsr ) btCsrReleaseAll(p);
      }
    }







>
>
>
>
>
>
|
|
|
<
|
<
>

<
<







 







>
>
>
>
>
>
>
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|


|
|
|
|
|
|
|
|

>







 







>







1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064

1065

1066
1067


1068
1069
1070
1071
1072
1073
1074
....
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
....
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
    }
  }

  return rc;
}

int sqlite4BtCsrKey(bt_cursor *pCsr, const void **ppK, int *pnK){
  int rc = SQLITE4_OK;            /* Return code */

  if( pCsr->bRequireReseek ){
    *ppK = (const void*)pCsr->ovfl.buf.p;
    *pnK = pCsr->ovfl.nKey;
  }else{
    const int pgsz = sqlite4BtPagerPagesize(pCsr->pDb->pPager);
    u8 *aData;
    u8 *pCell;

    int nK;

    int iCell = pCsr->aiCell[pCsr->nPg-1];



    aData = (u8*)sqlite4BtPageData(pCsr->apPage[pCsr->nPg-1]);
    assert( btCellCount(aData, pgsz)>iCell );
    pCell = btCellFind(aData, pgsz, iCell);
    pCell += sqlite4BtVarintGet32(pCell, &nK);

    if( nK==0 ){
      /* type (c) leaf cell */
................................................................................
  u8 *pCell;
  int iCell = pCsr->aiCell[pCsr->nPg-1];
  int nK = 0;
  int nV = 0;

  rc = btCsrReseek(pCsr);
  if( rc==SQLITE4_OK ){
    if( pCsr->bSkipNext || pCsr->bSkipPrev ){
      /* The row has been deleted out from under this cursor. So return
      ** NULL for data.  */
      *ppV = 0;
      *pnV = 0;
    }else{

      aData = (u8*)sqlite4BtPageData(pCsr->apPage[pCsr->nPg-1]);
      pCell = btCellFind(aData, pgsz, iCell);
      pCell += sqlite4BtVarintGet32(pCell, &nK);
      if( nK>0 ){
        pCell += nK;
        pCell += sqlite4BtVarintGet32(pCell, &nV);
      }

      if( nV==0 ){
        rc = btCsrBuffer(pCsr, 1);
        if( rc==SQLITE4_OK ){
          u8 *aBuf = (u8*)pCsr->ovfl.buf.p;
          *ppV = &aBuf[pCsr->ovfl.nKey];
          *pnV = pCsr->ovfl.nVal;
        }
      }else{
        *ppV = pCell;
        *pnV = (nV-1);
      }

#ifndef NDEBUG
      if( rc==SQLITE4_OK ){
        const void *pK; int nK;
        rc = sqlite4BtCsrKey(pCsr, &pK, &nK);
        if( rc==SQLITE4_OK ){
          BtLock *pLock = (BtLock*)pCsr->pDb->pPager;
          sqlite4BtDebugKV(pLock, "select", (u8*)pK, nK, (u8*)*ppV, *pnV);
        }
      }
#endif
    }
  }

  return rc;
}

/*
** The argument points to a buffer containing an overflow array. Return
................................................................................

static int btSaveAllCursor(bt_db *pDb, bt_cursor *pCsr){
  int rc = SQLITE4_OK;            /* Return code */
  bt_cursor *p;                   /* Used to iterate through cursors */

  for(p=pDb->pAllCsr; rc==SQLITE4_OK && p; p=p->pNextCsr){
    if( p->nPg>0 ){
      assert( p->bRequireReseek==0 );
      rc = btCsrBuffer(p, 0);
      if( rc==SQLITE4_OK ){
        assert( p->ovfl.buf.p );
        p->bRequireReseek = 1;
        if( p!=pCsr ) btCsrReleaseAll(p);
      }
    }

Changes to src/build.c.

2696
2697
2698
2699
2700
2701
2702

2703

2704
2705
2706
2707
2708
2709
2710
    assert( pName==0 );
    assert( pStart==0 );
    pTab = pParse->pNewTable;
    if( !pTab ) goto exit_create_index;
    iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  }


  sqlite4CodeVerifySchema(pParse, iDb);


  assert( pTab!=0 );
  assert( pParse->nErr==0 );
  assert( IsVirtual(pTab)==0 && IsView(pTab)==0 );

  /* If pCI==0 it means that we are dealing with a PRIMARY KEY or 
  ** UNIQUE constraint.  We have to invent our own name.  */







>
|
>







2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
    assert( pName==0 );
    assert( pStart==0 );
    pTab = pParse->pNewTable;
    if( !pTab ) goto exit_create_index;
    iDb = sqlite4SchemaToIndex(db, pTab->pSchema);
  }

  if( db->init.busy==0 ){
    sqlite4CodeVerifySchema(pParse, iDb);
  }

  assert( pTab!=0 );
  assert( pParse->nErr==0 );
  assert( IsVirtual(pTab)==0 && IsView(pTab)==0 );

  /* If pCI==0 it means that we are dealing with a PRIMARY KEY or 
  ** UNIQUE constraint.  We have to invent our own name.  */

Changes to src/math.c.

419
420
421
422
423
424
425

426

427
428
429
430
431
432
433
434
435
436
      if( c=='.' ){
        /* Permit only a single radix in each number */
        if( seenRadix ) goto finished;
        seenRadix = 1;
        bReal = 1;
      }else if( c=='e' || c=='E' ){
        int f = (flags & (SQLITE4_PREFIX_ONLY|SQLITE4_IGNORE_WHITESPACE));

        if( incr==2 ) f |= SQLITE4_UTF16LE; 

        i += incr;
        if( i>=nIn ) goto finished;
        sqlite4_num exp;
        exp = sqlite4_num_from_text(&zIn[i], nIn-i, f, 0);
        if( sqlite4_num_isnan(exp) ) goto finished;
        if( exp.e || exp.m>999 ) goto finished;
        bReal = 1;
        r.e += (int)(exp.m) * (exp.sign ? -1 : 1);
        i = nIn;
        break;







>

>

<
<







419
420
421
422
423
424
425
426
427
428
429


430
431
432
433
434
435
436
      if( c=='.' ){
        /* Permit only a single radix in each number */
        if( seenRadix ) goto finished;
        seenRadix = 1;
        bReal = 1;
      }else if( c=='e' || c=='E' ){
        int f = (flags & (SQLITE4_PREFIX_ONLY|SQLITE4_IGNORE_WHITESPACE));
        sqlite4_num exp;
        if( incr==2 ) f |= SQLITE4_UTF16LE; 
        if( (i+incr)>=nIn ) goto finished;
        i += incr;


        exp = sqlite4_num_from_text(&zIn[i], nIn-i, f, 0);
        if( sqlite4_num_isnan(exp) ) goto finished;
        if( exp.e || exp.m>999 ) goto finished;
        bReal = 1;
        r.e += (int)(exp.m) * (exp.sign ? -1 : 1);
        i = nIn;
        break;

Changes to src/update.c.

502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, regOld, 0);
    }

    /* Delete the index entries associated with the current record.  */
    j1 = sqlite4VdbeAddOp4(v, OP_NotFound, iCur+iPk, 0, regOldKey, 0, P4_INT32);
    sqlite4GenerateRowIndexDelete(pParse, pTab, 0, iCur, aRegIdx);
  
    /* Delete the old record */
    if( hasFK || bChngPk ){
      sqlite4VdbeAddOp2(v, OP_Delete, iCur+iPk, 0);
    }
    sqlite4VdbeJumpHere(v, j1);

    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, 0, regNew);
    }
  
    /* Insert the new index entries and the new record. */







<
<
<
<
<







502
503
504
505
506
507
508





509
510
511
512
513
514
515
    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, regOld, 0);
    }

    /* Delete the index entries associated with the current record.  */
    j1 = sqlite4VdbeAddOp4(v, OP_NotFound, iCur+iPk, 0, regOldKey, 0, P4_INT32);
    sqlite4GenerateRowIndexDelete(pParse, pTab, 0, iCur, aRegIdx);





    sqlite4VdbeJumpHere(v, j1);

    if( hasFK ){
      sqlite4FkCheck(pParse, pTab, 0, regNew);
    }
  
    /* Insert the new index entries and the new record. */

Changes to test/attach3.test.

83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    SELECT * FROM sqlite_master WHERE name = 'i1';
  }
} {}
do_test attach3-2.3 {
  execsql {
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} "index i1 t3 [expr $AUTOVACUUM?6:5] {CREATE INDEX i1 on t3(e)}"

# Drop the index on the aux database table.
do_test attach3-3.1 {
  execsql {
    DROP INDEX aux.i1;
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} {}
do_test attach3-3.2 {
  execsql {
    CREATE INDEX aux.i1 on t3(e);
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} "index i1 t3 6 {CREATE INDEX i1 on t3(e)}"
do_test attach3-3.3 {
  execsql {
    DROP INDEX i1;
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} {}








|













|







83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
    SELECT * FROM sqlite_master WHERE name = 'i1';
  }
} {}
do_test attach3-2.3 {
  execsql {
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} "index i1 t3 5 {CREATE INDEX i1 on t3(e)}"

# Drop the index on the aux database table.
do_test attach3-3.1 {
  execsql {
    DROP INDEX aux.i1;
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} {}
do_test attach3-3.2 {
  execsql {
    CREATE INDEX aux.i1 on t3(e);
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} {*index i1 t3 [56] {CREATE INDEX i1 on t3(e)}*}
do_test attach3-3.3 {
  execsql {
    DROP INDEX i1;
    SELECT * FROM aux.sqlite_master WHERE name = 'i1';
  }
} {}

Changes to test/exists.test.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# focus of this file is testing the various schema modification statements
# that feature "IF EXISTS" or "IF NOT EXISTS" clauses.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl


foreach jm {rollback wal} {

  set testprefix exists-$jm

  # This block of tests is targeted at CREATE XXX IF NOT EXISTS statements.
  #







<







12
13
14
15
16
17
18

19
20
21
22
23
24
25
# focus of this file is testing the various schema modification statements
# that feature "IF EXISTS" or "IF NOT EXISTS" clauses.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl


foreach jm {rollback wal} {

  set testprefix exists-$jm

  # This block of tests is targeted at CREATE XXX IF NOT EXISTS statements.
  #

Changes to test/index.test.

535
536
537
538
539
540
541

542
543
544
545
546
547
548
    INSERT INTO t1 VALUES('+.125E+04',12);
    INSERT INTO t1 VALUES('-.125E+04',13);
    INSERT INTO t1 VALUES('.125E+0',14);
    INSERT INTO t1 VALUES('.125',15);
    SELECT b FROM t1 ORDER BY a, b;
  }
} {13 14 15 12 8 5 2 1 3 6 10 11 9 4 7}

do_test index-15.3 {
  execsql {
    SELECT b FROM t1 WHERE typeof(a) IN ('integer','real') ORDER BY b;
  }
} {1 2 3 5 6 8 10 11 12 13 14 15}
integrity_check index-15.4








>







535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
    INSERT INTO t1 VALUES('+.125E+04',12);
    INSERT INTO t1 VALUES('-.125E+04',13);
    INSERT INTO t1 VALUES('.125E+0',14);
    INSERT INTO t1 VALUES('.125',15);
    SELECT b FROM t1 ORDER BY a, b;
  }
} {13 14 15 12 8 5 2 1 3 6 10 11 9 4 7}

do_test index-15.3 {
  execsql {
    SELECT b FROM t1 WHERE typeof(a) IN ('integer','real') ORDER BY b;
  }
} {1 2 3 5 6 8 10 11 12 13 14 15}
integrity_check index-15.4

Changes to test/lock_common.tcl.

138
139
140
141
142
143
144





145
146
147
148
149
150
151
  set wrapper ""
  if {[sqlite4 -has-codec] && [info exists ::do_not_use_codec]==0} {
    set wrapper "
      rename sqlite4 sqlite_orig
      proc sqlite4 {args} {[info body sqlite4]}
    "
  }






  set fd [open tf_main.tcl w]
  puts $fd [string map [list %WRAPPER% $wrapper] {
    %WRAPPER%
    set script ""
    while {![eof stdin]} {
      flush stdout







>
>
>
>
>







138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  set wrapper ""
  if {[sqlite4 -has-codec] && [info exists ::do_not_use_codec]==0} {
    set wrapper "
      rename sqlite4 sqlite_orig
      proc sqlite4 {args} {[info body sqlite4]}
    "
  }

  if {[permutation]=="bt"} {
    append wrapper "kv_default bt"
    append wrapper "\n"
  }

  set fd [open tf_main.tcl w]
  puts $fd [string map [list %WRAPPER% $wrapper] {
    %WRAPPER%
    set script ""
    while {![eof stdin]} {
      flush stdout

Changes to test/num.test.

193
194
195
196
197
198
199


200
201
202
203
204
205
206
...
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  2     00000      {sign:0 approx:0 e:0  m:0}
  3     00.000     {sign:0 approx:0 e:-3 m:0}
  4     -1.005     {sign:1 approx:0 e:-3 m:1005}
  5.1   1   {sign:0 approx:0 e:0 m:1}
  5.2   1.0 {sign:0 approx:0 e:-1 m:10}
  5.3   1.  {sign:0 approx:0 e:0 m:1}
  5.4   1e0 {sign:0 approx:0 e:0 m:1}


} {
  do_test num-9.1.$tn { sqlite4_num_from_text $in } [list {*}$out]
}

#-------------------------------------------------------------------------
# Test ignore-whitespace and prefix-only flags
#
................................................................................
#-------------------------------------------------------------------------
# Test from UTF16BE text
#
foreach {tn in len out} {
  0     274    -1   274
  1     3e+484 -1   3e+484
  2     2e1    3     2 
  3     2e1    4     2 
  4     2e1    5     2
  5     2e1    6     20 
} {
  do_test num-9.3.$tn { 
    sqlite4_num_to_text [sqlite4_num_from_text $in $len b]
  } $out
} 

#-------------------------------------------------------------------------
# Test from UTF16LE text
#
foreach {tn in len out} {
  0     4639   -1    4639
  1     5e+388 -1    5e+388 
  2     2e1    3     2 
  3     2e1    4     2 
  4     2e1    5     20
  5     2e1    6     20 
} {
  do_test num-9.4.$tn { 
    sqlite4_num_to_text [sqlite4_num_from_text $in $len l]
  } $out
} 







>
>







 







|
|













|
|







193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
...
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
  2     00000      {sign:0 approx:0 e:0  m:0}
  3     00.000     {sign:0 approx:0 e:-3 m:0}
  4     -1.005     {sign:1 approx:0 e:-3 m:1005}
  5.1   1   {sign:0 approx:0 e:0 m:1}
  5.2   1.0 {sign:0 approx:0 e:-1 m:10}
  5.3   1.  {sign:0 approx:0 e:0 m:1}
  5.4   1e0 {sign:0 approx:0 e:0 m:1}
  5.5   1e1 {sign:0 approx:0 e:1 m:1}
  5.6   1e2 {sign:0 approx:0 e:2 m:1}
} {
  do_test num-9.1.$tn { sqlite4_num_from_text $in } [list {*}$out]
}

#-------------------------------------------------------------------------
# Test ignore-whitespace and prefix-only flags
#
................................................................................
#-------------------------------------------------------------------------
# Test from UTF16BE text
#
foreach {tn in len out} {
  0     274    -1   274
  1     3e+484 -1   3e+484
  2     2e1    3     2 
  3     2e1    4     NaN 
  4     2e1    5     NaN
  5     2e1    6     20 
} {
  do_test num-9.3.$tn { 
    sqlite4_num_to_text [sqlite4_num_from_text $in $len b]
  } $out
} 

#-------------------------------------------------------------------------
# Test from UTF16LE text
#
foreach {tn in len out} {
  0     4639   -1    4639
  1     5e+388 -1    5e+388 
  2     2e1    3     NaN 
  3     2e1    4     NaN 
  4     2e1    5     20
  5     2e1    6     20 
} {
  do_test num-9.4.$tn { 
    sqlite4_num_to_text [sqlite4_num_from_text $in $len l]
  } $out
} 

Changes to test/permutations.test.

241
242
243
244
245
246
247
248


249
250
251
252
253
254
255
  tkt3201.test tkt3292.test tkt3298.test tkt3334.test tkt3346.test
  tkt3419.test tkt3424.test tkt3442.test tkt3461.test tkt3493.test
  tkt3508.test tkt3522.test tkt3527.test tkt3541.test tkt3554.test
  tkt3581.test tkt35xx.test tkt3630.test tkt3718.test tkt3761.test
  tkt3773.test tkt3841.test tkt3871.test tkt3879.test tkt3911.test
  tkt3918.test tkt3922.test tkt3929.test tkt3935.test tkt3997.test
} -initialize {
  kv_default bt


}

test_suite "src4" -prefix "" -description {
} -files {
  simple.test simple2.test
  lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test
  csr1.test







|
>
>







241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
  tkt3201.test tkt3292.test tkt3298.test tkt3334.test tkt3346.test
  tkt3419.test tkt3424.test tkt3442.test tkt3461.test tkt3493.test
  tkt3508.test tkt3522.test tkt3527.test tkt3541.test tkt3554.test
  tkt3581.test tkt35xx.test tkt3630.test tkt3718.test tkt3761.test
  tkt3773.test tkt3841.test tkt3871.test tkt3879.test tkt3911.test
  tkt3918.test tkt3922.test tkt3929.test tkt3935.test tkt3997.test
} -initialize {
  # kv_default bt
  kvwrap uninstall
  kvwrap install bt
}

test_suite "src4" -prefix "" -description {
} -files {
  simple.test simple2.test
  lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test
  csr1.test

Changes to test/pragma3.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28

29
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the PRAGMA command.
#
# $Id: pragma2.test,v 1.4 2007/10/09 08:29:33 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix pragma3

ifcapable !pragma {
  finish_test
  return
}


do_execsql_test 1.0 { CREATE TABLE t1(x) }
do_execsql_test 1.1 { PRAGMA main.lsm_work(1,1); } {0}


finish_test







<










>
|
|
|
>

8
9
10
11
12
13
14

15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the PRAGMA command.
#


set testdir [file dirname $argv0]
source $testdir/tester.tcl
set ::testprefix pragma3

ifcapable !pragma {
  finish_test
  return
}

if {[permutation] != "bt"} {
  do_execsql_test 1.0 { CREATE TABLE t1(x) }
  do_execsql_test 1.1 { PRAGMA main.lsm_work(1,1); } {0}
}

finish_test

Changes to test/test_kv2.c.

260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
...
307
308
309
310
311
312
313


314
315
316
317


318

319
320




321
322
323
324
325
326
327
static int newFileStorage(
  sqlite4_env *pEnv,
  KVStore **ppKVStore,
  const char *zName,
  unsigned openFlags
){

  /* Virtual methods for an LSM data store */
  static const KVStoreMethods kvwrapMethods = {
    1,
    sizeof(KVStoreMethods),
    kvwrapReplace,
    kvwrapOpenCursor,
    kvwrapSeek,
    kvwrapNextEntry,
................................................................................
  }

  *ppKVStore = (KVStore*)pNew;
  return rc;
}

static int kvwrap_install_cmd(Tcl_Interp *interp, int objc, Tcl_Obj **objv){


  if( objc!=2 ){
    Tcl_WrongNumArgs(interp, 2, objv, "");
    return TCL_ERROR;
  }




  if( kvwg.xFactory==0 ){
    sqlite4_env_config(0, SQLITE4_ENVCONFIG_KVSTORE_GET,"main", &kvwg.xFactory);




    sqlite4_env_config(0, SQLITE4_ENVCONFIG_KVSTORE_PUSH,"main",newFileStorage);
  }
  return TCL_OK;
}

static int kvwrap_uninstall_cmd(Tcl_Interp *interp, int objc, Tcl_Obj **objv){
  if( objc!=2 ){







|







 







>
>
|
|


>
>
|
>

|
>
>
>
>







260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
...
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
static int newFileStorage(
  sqlite4_env *pEnv,
  KVStore **ppKVStore,
  const char *zName,
  unsigned openFlags
){

  /* Virtual methods for the new factory */
  static const KVStoreMethods kvwrapMethods = {
    1,
    sizeof(KVStoreMethods),
    kvwrapReplace,
    kvwrapOpenCursor,
    kvwrapSeek,
    kvwrapNextEntry,
................................................................................
  }

  *ppKVStore = (KVStore*)pNew;
  return rc;
}

static int kvwrap_install_cmd(Tcl_Interp *interp, int objc, Tcl_Obj **objv){
  const char *z = "main";

  if( objc!=2 && objc!=3 ){
    Tcl_WrongNumArgs(interp, 2, objv, "?FACTORY?");
    return TCL_ERROR;
  }
  if( objc==3 ){
    z = Tcl_GetString(objv[2]);
  }

  if( kvwg.xFactory==0 ){
    sqlite4_env_config(0, SQLITE4_ENVCONFIG_KVSTORE_GET,z,&kvwg.xFactory);
    if( kvwg.xFactory==0 ){
      Tcl_AppendResult(interp, "no such factory: ", z, 0);
      return TCL_ERROR;
    }
    sqlite4_env_config(0, SQLITE4_ENVCONFIG_KVSTORE_PUSH,"main",newFileStorage);
  }
  return TCL_OK;
}

static int kvwrap_uninstall_cmd(Tcl_Interp *interp, int objc, Tcl_Obj **objv){
  if( objc!=2 ){

Changes to test/tester.tcl.

577
578
579
580
581
582
583


584

585
586
587
588
589
590
591
...
878
879
880
881
882
883
884
885


886
887
888
889
890
891
892
893
894
895
896
897
898
899
900



901
902
903
904
905
906
907
...
914
915
916
917
918
919
920
921


922
923
924
925
926
927
928
  } {
    set testname "${::testprefix}-$testname"
  }
}
    
proc do_execsql_test {testname sql {result {}}} {
  fix_testname testname


  uplevel do_test [list $testname] [list "execsql {$sql}"] [list [list {*}$result]]

}
proc do_catchsql_test {testname sql result} {
  fix_testname testname
  uplevel do_test [list $testname] [list "catchsql {$sql}"] [list $result]
}
proc do_eqp_test {name sql res} {
  uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
................................................................................


  # Set up colors for the different opcodes. Scheme is as follows:
  #
  #   Red:   Opcodes that write to a b-tree.
  #   Blue:  Opcodes that reposition or seek a cursor. 
  #   Green: The ResultRow opcode.
  #


  set R "\033\[31;1m"        ;# Red fg
  set G "\033\[32;1m"        ;# Green fg
  set B "\033\[34;1m"        ;# Red fg
  set D "\033\[39;0m"        ;# Default fg
  foreach opcode {
      Seek SeekGe SeekGt SeekLe SeekLt NotFound Last Rewind
      NoConflict Next Prev VNext VPrev VFilter
  } {
    set color($opcode) $B
  }
  foreach opcode {ResultRow} {
    set color($opcode) $G
  }
  foreach opcode {IdxInsert Insert Delete IdxDelete} {
    set color($opcode) $R



  }

  set bSeenGoto 0
  $db eval "explain $sql" {} {
    set x($addr) 0
    set op($addr) $opcode

................................................................................
     || $opcode=="VNext" || $opcode=="VPrev"
    } {
      for {set i $p2} {$i<$addr} {incr i} {
        incr x($i) 2
      }
    }

    if {$opcode == "Goto" && $p2<$addr && $op($p2)=="Yield"} {


      for {set i [expr $p2+1]} {$i<$addr} {incr i} {
        incr x($i) 2
      }
    }

    if {$opcode == "Halt" && $comment == "End of coroutine"} {
      set linebreak([expr $addr+1]) 1







>
>
|
>







 







|
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
>
>







 







|
>
>







577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
...
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
...
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
  } {
    set testname "${::testprefix}-$testname"
  }
}
    
proc do_execsql_test {testname sql {result {}}} {
  fix_testname testname
  set res [list {*}$result]
  #uplevel integrity_check [list ${testname}.before] 
  uplevel do_test [list $testname] [list "execsql {$sql}"] [list $res]
  #uplevel integrity_check [list ${testname}.after] 
}
proc do_catchsql_test {testname sql result} {
  fix_testname testname
  uplevel do_test [list $testname] [list "catchsql {$sql}"] [list $result]
}
proc do_eqp_test {name sql res} {
  uplevel do_execsql_test $name [list "EXPLAIN QUERY PLAN $sql"] [list $res]
................................................................................


  # Set up colors for the different opcodes. Scheme is as follows:
  #
  #   Red:   Opcodes that write to a b-tree.
  #   Blue:  Opcodes that reposition or seek a cursor. 
  #   Green: The ResultRow opcode.
  # 
  set toTTY [expr {![catch {fconfigure stdout -mode}]}]
  if {$toTTY} {
    set R "\033\[31;1m"        ;# Red fg
    set G "\033\[32;1m"        ;# Green fg
    set B "\033\[34;1m"        ;# Red fg
    set D "\033\[39;0m"        ;# Default fg
    foreach opcode {
        Seek SeekGe SeekGt SeekLe SeekLt NotFound Last Rewind
        NoConflict Next Prev VNext VPrev VFilter
    } {
      set color($opcode) $B
    }
    foreach opcode {ResultRow} {
      set color($opcode) $G
    }
    foreach opcode {IdxInsert Insert Delete IdxDelete} {
      set color($opcode) $R
    }
  } else {
    set D ""
  }

  set bSeenGoto 0
  $db eval "explain $sql" {} {
    set x($addr) 0
    set op($addr) $opcode

................................................................................
     || $opcode=="VNext" || $opcode=="VPrev"
    } {
      for {set i $p2} {$i<$addr} {incr i} {
        incr x($i) 2
      }
    }

    if {$opcode == "Goto" && $p2<$addr && (
      $op($p2)=="Yield" || $op($p2)=="RowSetRead"
    )} {
      for {set i [expr $p2+1]} {$i<$addr} {incr i} {
        incr x($i) 2
      }
    }

    if {$opcode == "Halt" && $comment == "End of coroutine"} {
      set linebreak([expr $addr+1]) 1

Changes to test/update.test.

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
...
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455

456
457
458
459
460
461
462
do_test update-5.6.5 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}

# Repeat the previous sequence of tests with a different index.
#
execsql {PRAGMA synchronous=FULL}
do_test update-6.0 {
  execsql {DROP INDEX idx1}
  execsql {CREATE INDEX idx1 ON test1(f2)}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-6.1 {
  execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
do_test update-6.1.1 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 89 8 257 8 889}
do_test update-6.1.2 {
  execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
} {8 89}
do_test update-6.1.3 {
  execsql {SELECT * FROM test1 WHERE f1==88 ORDER BY f1,f2}
} {}
do_test update-6.2 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
do_test update-6.3 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-6.3.1 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}
do_test update-6.3.2 {
  execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
} {}
do_test update-6.3.3 {
  execsql {SELECT * FROM test1 WHERE f2==88 ORDER BY f1,f2}
} {8 88}
do_test update-6.4 {
  execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
do_test update-6.4.1 {
  execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
} {78 128}
do_test update-6.4.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {778 128}
do_test update-6.4.3 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 128 8 256 8 888}
do_test update-6.5 {
  execsql {UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
do_test update-6.5.1 {
  execsql {SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2}
} {78 128}
do_test update-6.5.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {}
do_test update-6.5.3 {
  execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
} {777 128}
do_test update-6.5.4 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 128 8 256 8 888}
do_test update-6.6 {
  execsql {UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-6.6.1 {
  execsql {SELECT * FROM test1 WHERE f1==77 ORDER BY f1,f2}
} {77 128}
do_test update-6.6.2 {
  execsql {SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2}
} {}
do_test update-6.6.3 {
  execsql {SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2}
} {777 128}
do_test update-6.6.4 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}

# Repeat the previous sequence of tests with multiple
# indices
#
do_test update-7.0 {
  execsql {CREATE INDEX idx2 ON test1(f2)}
  execsql {CREATE INDEX idx3 ON test1(f1,f2)}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-7.1 {
  execsql {UPDATE test1 SET f2=f2+1 WHERE f1==8}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
do_test update-7.1.1 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 89 8 257 8 889}
do_test update-7.1.2 {
  execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
} {8 89}
do_test update-7.1.3 {
  execsql {SELECT * FROM test1 WHERE f1==88 ORDER BY f1,f2}
} {}
do_test update-7.2 {
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
do_test update-7.3 {
  # explain {UPDATE test1 SET f2=f2-1 WHERE f1==8 and F2<300}
  execsql {UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_test update-7.3.1 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}
do_test update-7.3.2 {
  execsql {SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2}
} {}
do_test update-7.3.3 {
  execsql {SELECT * FROM test1 WHERE f2==88 ORDER BY f1,f2}
} {8 88}
do_test update-7.4 {
  execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
................................................................................
  }} msg]
  lappend v $msg
} {1 {no such function: x}}

# Try doing updates on a unique column where the value does not
# really change.
#
do_test update-10.1 {
  execsql {
    DROP TABLE test1;
    CREATE TABLE t1(
       a integer primary key,
       b UNIQUE, 
       c, d,
       e, f,
       UNIQUE(c,d)
    );
    INSERT INTO t1 VALUES(1,2,3,4,5,6);
    INSERT INTO t1 VALUES(2,3,4,4,6,7);
    SELECT * FROM t1
  }
} {1 2 3 4 5 6 2 3 4 4 6 7}
do_test update-10.2 {
  catchsql {
    UPDATE t1 SET a=1, e=9 WHERE f=6;
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 9 6 2 3 4 4 6 7}}
do_test update-10.3 {
  catchsql {
    UPDATE t1 SET a=1, e=10 WHERE f=7;
    SELECT * FROM t1;
  }
} {1 {PRIMARY KEY must be unique}}
do_test update-10.4 {
  catchsql {
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 9 6 2 3 4 4 6 7}}

do_test update-10.5 {
  catchsql {
    UPDATE t1 SET b=2, e=11 WHERE f=6;
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 11 6 2 3 4 4 6 7}}
do_test update-10.6 {







|
|
|
|

|
|
|

|
|

|
|

|
|

|
|
|

|
|
|

|
|

|
|

|
|

|
|
|

|
|

|
|

|
|

|
|
|

|
|

|
|

|
|

|
|

|
|
|

|
|

|
|

|
|

|
|





|
|
|
|

|
|
|

|
|

|
|

|
|

|
|
|

|
<
|
|

|
|

|
|







 







|
<
|
|
|
|
|
|
|
|
|
|
|
<

|
<
|
|
<

|
<
|
|
<

|
<
|
<

>







221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
...
416
417
418
419
420
421
422
423

424
425
426
427
428
429
430
431
432
433
434

435
436

437
438

439
440

441
442

443
444

445

446
447
448
449
450
451
452
453
454
do_test update-5.6.5 {
  execsql {SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2}
} {8 88 8 256 8 888}

# Repeat the previous sequence of tests with a different index.
#
execsql {PRAGMA synchronous=FULL}
do_execsql_test update-6.0 {
  DROP INDEX idx1;
  CREATE INDEX idx1 ON test1(f2);
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_execsql_test update-6.1 {
  UPDATE test1 SET f2=f2+1 WHERE f1==8;
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
do_execsql_test update-6.1.1 {
  SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2;
} {8 89 8 257 8 889}
do_execsql_test update-6.1.2 {
  SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2;
} {8 89}
do_execsql_test update-6.1.3 {
  SELECT * FROM test1 WHERE f1==88 ORDER BY f1,f2;
} {}
do_execsql_test update-6.2 {
  UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800;
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
do_execsql_test update-6.3 {
  UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800;
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_execsql_test update-6.3.1 {
  SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2;
} {8 88 8 256 8 888}
do_execsql_test update-6.3.2 {
  SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2;
} {}
do_execsql_test update-6.3.3 {
  SELECT * FROM test1 WHERE f2==88 ORDER BY f1,f2;
} {8 88}
do_execsql_test update-6.4 {
  UPDATE test1 SET f1=f1+1 WHERE f2==128;
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 778 128}
do_execsql_test update-6.4.1 {
  SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2;
} {78 128}
do_execsql_test update-6.4.2 {
  SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2;
} {778 128}
do_execsql_test update-6.4.3 {
  SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2;
} {8 88 8 128 8 256 8 888}
do_execsql_test update-6.5 {
  UPDATE test1 SET f1=f1-1 WHERE f1>100 and f2==128;
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 8 88 8 128 8 256 8 888 9 512 10 1024 78 128 777 128}
do_execsql_test update-6.5.1 {
  SELECT * FROM test1 WHERE f1==78 ORDER BY f1,f2;
} {78 128}
do_execsql_test update-6.5.2 {
  SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2;
} {}
do_execsql_test update-6.5.3 {
  SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2;
} {777 128}
do_execsql_test update-6.5.4 {
  SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2;
} {8 88 8 128 8 256 8 888}
do_execsql_test update-6.6 {
  UPDATE test1 SET f1=f1-1 WHERE f1<=100 and f2==128;
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_execsql_test update-6.6.1 {
  SELECT * FROM test1 WHERE f1==77 ORDER BY f1,f2;
} {77 128}
do_execsql_test update-6.6.2 {
  SELECT * FROM test1 WHERE f1==778 ORDER BY f1,f2;
} {}
do_execsql_test update-6.6.3 {
  SELECT * FROM test1 WHERE f1==777 ORDER BY f1,f2;
} {777 128}
do_execsql_test update-6.6.4 {
  SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2;
} {8 88 8 256 8 888}

# Repeat the previous sequence of tests with multiple
# indices
#
do_execsql_test update-7.0 {
  CREATE INDEX idx2 ON test1(f2);
  -- CREATE INDEX idx3 ON test1(f1,f2);
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_execsql_test update-7.1 {
  UPDATE test1 SET f2=f2+1 WHERE f1==8;
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 7 128 8 89 8 257 8 889 9 512 10 1024 77 128 777 128}
do_execsql_test update-7.1.1 {
  SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2
} {8 89 8 257 8 889}
do_execsql_test update-7.1.2 {
  SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2
} {8 89}
do_execsql_test update-7.1.3 {
  SELECT * FROM test1 WHERE f1==88 ORDER BY f1,f2
} {}
do_execsql_test update-7.2 {
  UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2>800;
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 7 128 8 89 8 257 8 888 9 512 10 1024 77 128 777 128}
do_execsql_test update-7.3 {

  UPDATE test1 SET f2=f2-1 WHERE f1==8 and f2<800;
  SELECT * FROM test1 ORDER BY f1,f2;
} {6 64 7 128 8 88 8 256 8 888 9 512 10 1024 77 128 777 128}
do_execsql_test update-7.3.1 {
  SELECT * FROM test1 WHERE f1==8 ORDER BY f1,f2
} {8 88 8 256 8 888}
do_execsql_test update-7.3.2 {
  SELECT * FROM test1 WHERE f2==89 ORDER BY f1,f2
} {}
do_test update-7.3.3 {
  execsql {SELECT * FROM test1 WHERE f2==88 ORDER BY f1,f2}
} {8 88}
do_test update-7.4 {
  execsql {UPDATE test1 SET f1=f1+1 WHERE f2==128}
  execsql {SELECT * FROM test1 ORDER BY f1,f2}
................................................................................
  }} msg]
  lappend v $msg
} {1 {no such function: x}}

# Try doing updates on a unique column where the value does not
# really change.
#
do_execsql_test update-10.1 {

  DROP TABLE test1;
  CREATE TABLE t1(
    a integer primary key,
    b UNIQUE, 
    c, d,
    e, f,
    UNIQUE(c,d)
  );
  INSERT INTO t1 VALUES(1,2,3,4,5,6);
  INSERT INTO t1 VALUES(2,3,4,4,6,7);
  SELECT * FROM t1;

} {1 2 3 4 5 6 2 3 4 4 6 7}
do_catchsql_test update-10.2 {

  UPDATE t1 SET a=1, e=9 WHERE f=6;
  SELECT * FROM t1;

} {0 {1 2 3 4 9 6 2 3 4 4 6 7}}
do_catchsql_test update-10.3 {

  UPDATE t1 SET a=1, e=10 WHERE f=7;
  SELECT * FROM t1;

} {1 {PRIMARY KEY must be unique}}
do_catchsql_test update-10.4 {

  SELECT * FROM t1;

} {0 {1 2 3 4 9 6 2 3 4 4 6 7}}

do_test update-10.5 {
  catchsql {
    UPDATE t1 SET b=2, e=11 WHERE f=6;
    SELECT * FROM t1;
  }
} {0 {1 2 3 4 11 6 2 3 4 4 6 7}}
do_test update-10.6 {