SQLite

Check-in [e21a181376]
Login

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

Overview
Comment:Minor bugfixes and test case adjustments for version 2 test cases to work with version 3. (CVS 1598)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e21a181376d4115c7dbe614f3f8a1fbf82d77c75
User & Date: danielk1977 2004-06-15 11:40:04.000
Context
2004-06-15
13:36
Memory leak fixes for tests in file select1.test. (CVS 1599) (check-in: 59db58ebd3 user: danielk1977 tags: trunk)
11:40
Minor bugfixes and test case adjustments for version 2 test cases to work with version 3. (CVS 1598) (check-in: e21a181376 user: danielk1977 tags: trunk)
02:44
(1) Vdbe makes a copy of column types. (2) Don't invalidate other cursors when a statement or transaction is rolled back. (3) Update capi2.test for the new API. (CVS 1597) (check-in: 4f5e253082 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/btree.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.169 2004/06/15 02:44:19 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.











|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*
** 2004 April 6
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.170 2004/06/15 11:40:04 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
1510
1511
1512
1513
1514
1515
1516

1517
1518
1519
1520
1521
1522
1523
  }
  pCur->pgnoRoot = (Pgno)iTable;
  if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){
    rc = SQLITE_EMPTY;
    pCur->pPage = 0;
    goto create_cursor_exception;
  }

  rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0);
  if( rc!=SQLITE_OK ){
    goto create_cursor_exception;
  }
  pCur->xCompare = xCmp ? xCmp : dfltCompare;
  pCur->pArg = pArg;
  pCur->pBt = pBt;







>







1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
  }
  pCur->pgnoRoot = (Pgno)iTable;
  if( iTable==1 && sqlite3pager_pagecount(pBt->pPager)==0 ){
    rc = SQLITE_EMPTY;
    pCur->pPage = 0;
    goto create_cursor_exception;
  }
  pCur->pPage = 0;  /* For exit-handler, in case getAndInitPage() fails. */
  rc = getAndInitPage(pBt, pCur->pgnoRoot, &pCur->pPage, 0);
  if( rc!=SQLITE_OK ){
    goto create_cursor_exception;
  }
  pCur->xCompare = xCmp ? xCmp : dfltCompare;
  pCur->pArg = pArg;
  pCur->pBt = pBt;
4248
4249
4250
4251
4252
4253
4254
4255
4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
4266
  int rc = SQLITE_OK;
  Pgno i, nPage, nToPage;

  if( pBtTo->inTrans!=TRANS_WRITE || pBtFrom->inTrans!=TRANS_WRITE ){
    return SQLITE_ERROR;
  }
  if( pBtTo->pCursor ) return SQLITE_BUSY;
  memcpy(pBtTo->pPage1->aData, pBtFrom->pPage1->aData, pBtFrom->usableSize);
  rc = sqlite3pager_overwrite(pBtTo->pPager, 1, pBtFrom->pPage1->aData);
  nToPage = sqlite3pager_pagecount(pBtTo->pPager);
  nPage = sqlite3pager_pagecount(pBtFrom->pPager);
  for(i=2; rc==SQLITE_OK && i<=nPage; i++){
    void *pPage;
    rc = sqlite3pager_get(pBtFrom->pPager, i, &pPage);
    if( rc ) break;
    rc = sqlite3pager_overwrite(pBtTo->pPager, i, pPage);
    if( rc ) break;
    sqlite3pager_unref(pPage);
  }







<
<


|







4249
4250
4251
4252
4253
4254
4255


4256
4257
4258
4259
4260
4261
4262
4263
4264
4265
  int rc = SQLITE_OK;
  Pgno i, nPage, nToPage;

  if( pBtTo->inTrans!=TRANS_WRITE || pBtFrom->inTrans!=TRANS_WRITE ){
    return SQLITE_ERROR;
  }
  if( pBtTo->pCursor ) return SQLITE_BUSY;


  nToPage = sqlite3pager_pagecount(pBtTo->pPager);
  nPage = sqlite3pager_pagecount(pBtFrom->pPager);
  for(i=1; rc==SQLITE_OK && i<=nPage; i++){
    void *pPage;
    rc = sqlite3pager_get(pBtFrom->pPager, i, &pPage);
    if( rc ) break;
    rc = sqlite3pager_overwrite(pBtTo->pPager, i, pPage);
    if( rc ) break;
    sqlite3pager_unref(pPage);
  }
Changes to src/os_mac.c.
393
394
395
396
397
398
399

400
401
402
403
404
405
406
}

/*
** Sync the directory zDirname. This is a no-op on operating systems other
** than UNIX.
*/
int sqlite3OsSyncDirectory(const char *zDirname){

  return SQLITE_OK;
}

/*
** Truncate an open file to a specified size
*/
int sqlite3OsTruncate(OsFile *id, off_t nByte){







>







393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
}

/*
** Sync the directory zDirname. This is a no-op on operating systems other
** than UNIX.
*/
int sqlite3OsSyncDirectory(const char *zDirname){
  SimulateIOError(SQLITE_IOERR);
  return SQLITE_OK;
}

/*
** Truncate an open file to a specified size
*/
int sqlite3OsTruncate(OsFile *id, off_t nByte){
Changes to src/os_unix.c.
623
624
625
626
627
628
629

630

631
632
633
634
635
636
637
/*
** Sync the directory zDirname. This is a no-op on operating systems other
** than UNIX.
*/
int sqlite3OsSyncDirectory(const char *zDirname){
  int fd;
  int r;

  fd = open(zDirname, O_RDONLY|O_BINARY, 0644);

  if( fd<0 ){
    return SQLITE_CANTOPEN; 
  }
  r = fsync(fd);
  close(fd);
  return ((r==0)?SQLITE_OK:SQLITE_IOERR);
}







>

>







623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
/*
** Sync the directory zDirname. This is a no-op on operating systems other
** than UNIX.
*/
int sqlite3OsSyncDirectory(const char *zDirname){
  int fd;
  int r;
  SimulateIOError(SQLITE_IOERR);
  fd = open(zDirname, O_RDONLY|O_BINARY, 0644);
  TRACE3("DIRSYNC %-3d (%s)\n", fd, zDirname);
  if( fd<0 ){
    return SQLITE_CANTOPEN; 
  }
  r = fsync(fd);
  close(fd);
  return ((r==0)?SQLITE_OK:SQLITE_IOERR);
}
Changes to src/os_win.c.
291
292
293
294
295
296
297

298
299
300
301
302
303
304
}

/*
** Sync the directory zDirname. This is a no-op on operating systems other
** than UNIX.
*/
int sqlite3OsSyncDirectory(const char *zDirname){

  return SQLITE_OK;
}

/*
** Truncate an open file to a specified size
*/
int sqlite3OsTruncate(OsFile *id, off_t nByte){







>







291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
}

/*
** Sync the directory zDirname. This is a no-op on operating systems other
** than UNIX.
*/
int sqlite3OsSyncDirectory(const char *zDirname){
  SimulateIOError(SQLITE_IOERR);
  return SQLITE_OK;
}

/*
** Truncate an open file to a specified size
*/
int sqlite3OsTruncate(OsFile *id, off_t nByte){
Changes to src/pager.c.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.127 2004/06/15 01:40:29 drh Exp $
*/
#include "os.h"         /* Must be first to enable large file support */
#include "sqliteInt.h"
#include "pager.h"
#include <assert.h>
#include <string.h>








|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.128 2004/06/15 11:40:09 danielk1977 Exp $
*/
#include "os.h"         /* Must be first to enable large file support */
#include "sqliteInt.h"
#include "pager.h"
#include <assert.h>
#include <string.h>

1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
    pPager->aHash[h] = pPg->pNextHash;
  }
  pPg->pNextHash = pPg->pPrevHash = 0;
}

/*
** This routine is used to truncate an in-memory database.  Delete
** every pages whose pgno is larger than pPager->dbSize and is unreferenced.
** Referenced pages larger than pPager->dbSize are zeroed.
*/
static void memoryTruncate(Pager *pPager){
  PgHdr *pPg;
  PgHdr **ppPg;
  int dbSize = pPager->dbSize;








|







1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
    pPager->aHash[h] = pPg->pNextHash;
  }
  pPg->pNextHash = pPg->pPrevHash = 0;
}

/*
** This routine is used to truncate an in-memory database.  Delete
** all pages whose pgno is larger than pPager->dbSize and is unreferenced.
** Referenced pages larger than pPager->dbSize are zeroed.
*/
static void memoryTruncate(Pager *pPager){
  PgHdr *pPg;
  PgHdr **ppPg;
  int dbSize = pPager->dbSize;

1305
1306
1307
1308
1309
1310
1311
1312



1313
1314
1315
1316
1317
1318
1319
    return SQLITE_OK;
  }
  if( pPager->memDb ){
    pPager->dbSize = nPage;
    memoryTruncate(pPager);
    return SQLITE_OK;
  }
  syncJournal(pPager, 0);



  rc = sqlite3OsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage);
  if( rc==SQLITE_OK ){
    pPager->dbSize = nPage;
  }
  return rc;
}








|
>
>
>







1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
    return SQLITE_OK;
  }
  if( pPager->memDb ){
    pPager->dbSize = nPage;
    memoryTruncate(pPager);
    return SQLITE_OK;
  }
  rc = syncJournal(pPager, 0);
  if( rc!=SQLITE_OK ){
    return rc;
  }
  rc = sqlite3OsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage);
  if( rc==SQLITE_OK ){
    pPager->dbSize = nPage;
  }
  return rc;
}

2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449





2450
2451
2452
2453
2454
2455
2456
int sqlite3pager_rollback(Pager *pPager){
  int rc;
  TRACE2("ROLLBACK %d\n", pPager->fd.h);
  if( pPager->memDb ){
    PgHdr *p;
    for(p=pPager->pAll; p; p=p->pNextAll){
      PgHistory *pHist;
      if( !p->dirty ) continue;
      pHist = PGHDR_TO_HIST(p, pPager);
      if( pHist->pOrig ){
        memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
        TRACE2("ROLLBACK-PAGE %d\n", p->pgno);
      }else{
        TRACE2("PAGE %d is clean\n", p->pgno);
      }
      clearHistory(pHist);
      p->dirty = 0;
      p->inJournal = 0;
      p->inStmt = 0;
      p->pPrevStmt = p->pNextStmt = 0;





    }
    pPager->pStmt = 0;
    pPager->dbSize = pPager->origDbSize;
    memoryTruncate(pPager);
    pPager->stmtInUse = 0;
    pPager->state = PAGER_SHARED;
    return SQLITE_OK;







|












>
>
>
>
>







2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
2453
2454
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
int sqlite3pager_rollback(Pager *pPager){
  int rc;
  TRACE2("ROLLBACK %d\n", pPager->fd.h);
  if( pPager->memDb ){
    PgHdr *p;
    for(p=pPager->pAll; p; p=p->pNextAll){
      PgHistory *pHist;
      if( !p->alwaysRollback && !p->dirty ) continue;
      pHist = PGHDR_TO_HIST(p, pPager);
      if( pHist->pOrig ){
        memcpy(PGHDR_TO_DATA(p), pHist->pOrig, pPager->pageSize);
        TRACE2("ROLLBACK-PAGE %d\n", p->pgno);
      }else{
        TRACE2("PAGE %d is clean\n", p->pgno);
      }
      clearHistory(pHist);
      p->dirty = 0;
      p->inJournal = 0;
      p->inStmt = 0;
      p->pPrevStmt = p->pNextStmt = 0;

      if( pPager->xReiniter ){
        pPager->xReiniter(PGHDR_TO_DATA(p), pPager->pageSize);
      }
      
    }
    pPager->pStmt = 0;
    pPager->dbSize = pPager->origDbSize;
    memoryTruncate(pPager);
    pPager->stmtInUse = 0;
    pPager->state = PAGER_SHARED;
    return SQLITE_OK;
Changes to src/test2.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the pager.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test2.c,v 1.21 2004/06/09 19:03:55 drh Exp $
*/
#include "os.h"
#include "sqliteInt.h"
#include "pager.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the pager.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test2.c,v 1.22 2004/06/15 11:40:09 danielk1977 Exp $
*/
#include "os.h"
#include "sqliteInt.h"
#include "pager.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
    { "page_number",             (Tcl_CmdProc*)page_number         },
    { "fake_big_file",           (Tcl_CmdProc*)fake_big_file       },
  };
  int i;
  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  }
  Tcl_LinkVar(interp, "sqlite3_io_error_pending",
     (char*)&sqlite3_io_error_pending, TCL_LINK_INT);
  sprintf(zBuf, "%d", SQLITE_PAGE_SIZE);
  Tcl_SetVar(interp, "SQLITE_PAGE_SIZE", zBuf, TCL_GLOBAL_ONLY); 
  sprintf(zBuf, "%d", SQLITE_PAGE_RESERVE);
  Tcl_SetVar(interp, "SQLITE_PAGE_RESERVE", zBuf, TCL_GLOBAL_ONLY); 
  sprintf(zBuf, "%d", SQLITE_USABLE_SIZE);
  Tcl_SetVar(interp, "SQLITE_USABLE_SIZE", zBuf, TCL_GLOBAL_ONLY); 
  return TCL_OK;
}







|









547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
    { "page_number",             (Tcl_CmdProc*)page_number         },
    { "fake_big_file",           (Tcl_CmdProc*)fake_big_file       },
  };
  int i;
  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
  }
  Tcl_LinkVar(interp, "sqlite_io_error_pending",
     (char*)&sqlite3_io_error_pending, TCL_LINK_INT);
  sprintf(zBuf, "%d", SQLITE_PAGE_SIZE);
  Tcl_SetVar(interp, "SQLITE_PAGE_SIZE", zBuf, TCL_GLOBAL_ONLY); 
  sprintf(zBuf, "%d", SQLITE_PAGE_RESERVE);
  Tcl_SetVar(interp, "SQLITE_PAGE_RESERVE", zBuf, TCL_GLOBAL_ONLY); 
  sprintf(zBuf, "%d", SQLITE_USABLE_SIZE);
  Tcl_SetVar(interp, "SQLITE_USABLE_SIZE", zBuf, TCL_GLOBAL_ONLY); 
  return TCL_OK;
}
Changes to src/vacuum.c.
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** This file contains code used to implement the VACUUM command.
**
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
** $Id: vacuum.c,v 1.21 2004/06/03 16:08:42 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"

#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
/*
** Generate a random name of 20 character in length.







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
**
*************************************************************************
** This file contains code used to implement the VACUUM command.
**
** Most of the code in this file may be omitted by defining the
** SQLITE_OMIT_VACUUM macro.
**
** $Id: vacuum.c,v 1.22 2004/06/15 11:40:09 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"

#if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM
/*
** Generate a random name of 20 character in length.
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214

215
216
217
218
219
220
221
  */
  pTemp = db->aDb[db->nDb-1].pBt;
  if( sqlite3BtreeIsInTrans(pTemp) ){
    Btree *pMain = db->aDb[0].pBt;
    u32 meta;

    assert( 0==sqlite3BtreeIsInTrans(pMain) );
    rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt, 1, 0);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;

    /* Copy Btree meta values 3 and 4. These correspond to SQL layer meta 
    ** values 2 and 3, the default values of a couple of pragmas.
    */
    rc = sqlite3BtreeGetMeta(pMain, 3, &meta);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;
    rc = sqlite3BtreeUpdateMeta(pTemp, 3, meta);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;
    rc = sqlite3BtreeGetMeta(pMain, 4, &meta);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;
    rc = sqlite3BtreeUpdateMeta(pTemp, 4, meta);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;

    rc = sqlite3BtreeCopyFile(pMain, pTemp);

    rc = sqlite3BtreeCommit(pMain);
  }

end_of_vacuum:
  execSql(db, "DETACH vacuum_db;");
  execSql(db, "ROLLBACK;");
  if( zTemp ){







|















>







192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
  */
  pTemp = db->aDb[db->nDb-1].pBt;
  if( sqlite3BtreeIsInTrans(pTemp) ){
    Btree *pMain = db->aDb[0].pBt;
    u32 meta;

    assert( 0==sqlite3BtreeIsInTrans(pMain) );
    rc = sqlite3BtreeBeginTrans(pMain, 1, 0);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;

    /* Copy Btree meta values 3 and 4. These correspond to SQL layer meta 
    ** values 2 and 3, the default values of a couple of pragmas.
    */
    rc = sqlite3BtreeGetMeta(pMain, 3, &meta);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;
    rc = sqlite3BtreeUpdateMeta(pTemp, 3, meta);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;
    rc = sqlite3BtreeGetMeta(pMain, 4, &meta);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;
    rc = sqlite3BtreeUpdateMeta(pTemp, 4, meta);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;

    rc = sqlite3BtreeCopyFile(pMain, pTemp);
    if( rc!=SQLITE_OK ) goto end_of_vacuum;
    rc = sqlite3BtreeCommit(pMain);
  }

end_of_vacuum:
  execSql(db, "DETACH vacuum_db;");
  execSql(db, "ROLLBACK;");
  if( zTemp ){
Changes to src/vdbe.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.372 2004/06/14 13:14:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.373 2004/06/15 11:40:09 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
4140
4141
4142
4143
4144
4145
4146
4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157

4158
4159
4160
4161
4162
4163
4164
4165
** and put them on the sorter.  The key and data should have been
** made using SortMakeKey and SortMakeRec, respectively.
*/
case OP_SortPut: {
  Mem *pNos = &pTos[-1];
  Sorter *pSorter;
  assert( pNos>=p->aStack );
  Stringify(pNos, db->enc);
  if( Dynamicify(pTos, db->enc) || Dynamicify(pNos, db->enc) ) goto no_mem;
  pSorter = sqliteMallocRaw( sizeof(Sorter) );
  if( pSorter==0 ) goto no_mem;
  pSorter->pNext = p->pSort;
  p->pSort = pSorter;
  assert( pTos->flags & MEM_Dyn );
  pSorter->nKey = pTos->n;
  pSorter->zKey = pTos->z;
  assert( pNos->flags & MEM_Dyn );
  pSorter->nData = pNos->n;

  pSorter->pData = pNos->z;
  pTos -= 2;
  break;
}

/* Opcode: Sort * * P3
**
** Sort all elements on the sorter.  The algorithm is a







<
|







|
|
>
|







4140
4141
4142
4143
4144
4145
4146

4147
4148
4149
4150
4151
4152
4153
4154
4155
4156
4157
4158
4159
4160
4161
4162
4163
4164
4165
** and put them on the sorter.  The key and data should have been
** made using SortMakeKey and SortMakeRec, respectively.
*/
case OP_SortPut: {
  Mem *pNos = &pTos[-1];
  Sorter *pSorter;
  assert( pNos>=p->aStack );

  if( Dynamicify(pTos, db->enc) ) goto no_mem;
  pSorter = sqliteMallocRaw( sizeof(Sorter) );
  if( pSorter==0 ) goto no_mem;
  pSorter->pNext = p->pSort;
  p->pSort = pSorter;
  assert( pTos->flags & MEM_Dyn );
  pSorter->nKey = pTos->n;
  pSorter->zKey = pTos->z;
  pSorter->data.flags = MEM_Null;
  rc = sqlite3VdbeMemMove(&pSorter->data, pNos);
  if( rc!=SQLITE_OK ) goto abort_due_to_error;
  Deephemeralize(&pSorter->data);
  pTos -= 2;
  break;
}

/* Opcode: Sort * * P3
**
** Sort all elements on the sorter.  The algorithm is a
4209
4210
4211
4212
4213
4214
4215
4216
4217
4218
4219
4220

4221
4222
4223
4224
4225
4226
4227
*/
case OP_SortNext: {
  Sorter *pSorter = p->pSort;
  CHECK_FOR_INTERRUPT;
  if( pSorter!=0 ){
    p->pSort = pSorter->pNext;
    pTos++;
    pTos->z = pSorter->pData;
    pTos->n = pSorter->nData;
    pTos->flags = MEM_Blob|MEM_Dyn|MEM_Term;
    pTos->xDel = 0;
    pTos->enc = 0;

    sqliteFree(pSorter->zKey);
    sqliteFree(pSorter);
  }else{
    pc = pOp->p2 - 1;
  }
  break;
}







<
<
|
|
<
>







4209
4210
4211
4212
4213
4214
4215


4216
4217

4218
4219
4220
4221
4222
4223
4224
4225
*/
case OP_SortNext: {
  Sorter *pSorter = p->pSort;
  CHECK_FOR_INTERRUPT;
  if( pSorter!=0 ){
    p->pSort = pSorter->pNext;
    pTos++;


    pTos->flags = MEM_Null;
    rc = sqlite3VdbeMemMove(pTos, &pSorter->data);

    assert( rc==SQLITE_OK );
    sqliteFree(pSorter->zKey);
    sqliteFree(pSorter);
  }else{
    pc = pOp->p2 - 1;
  }
  break;
}
Changes to src/vdbeInt.h.
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
  int payloadSize;      /* Total number of bytes in the record */
  u32 *aType;           /* Type values for all entries in the record */
  u32 *aOffset;         /* Cached offsets to the start of each columns data */
  u8 *aRow;             /* Data for the current row, if all on one page */
};
typedef struct Cursor Cursor;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.
*/
typedef struct Sorter Sorter;
struct Sorter {
  int nKey;           /* Number of bytes in the key */
  char *zKey;         /* The key by which we will sort */
  int nData;          /* Number of bytes in the data */
  char *pData;        /* The data associated with this key */
  Sorter *pNext;      /* Next in the list */
};

/* 
** Number of buckets used for merge-sort.  
*/
#define NSORT 30

/*
** Number of bytes of string storage space available to each stack
** layer without having to malloc.  NBFS is short for Number of Bytes
** For Strings.
*/
#define NBFS 32








<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







91
92
93
94
95
96
97


















98
99
100
101
102
103
104
  int payloadSize;      /* Total number of bytes in the record */
  u32 *aType;           /* Type values for all entries in the record */
  u32 *aOffset;         /* Cached offsets to the start of each columns data */
  u8 *aRow;             /* Data for the current row, if all on one page */
};
typedef struct Cursor Cursor;



















/*
** Number of bytes of string storage space available to each stack
** layer without having to malloc.  NBFS is short for Number of Bytes
** For Strings.
*/
#define NBFS 32

140
141
142
143
144
145
146

















147
148
149
150
151
152
153
  double r;           /* Real value */
  char *z;            /* String or BLOB value */
  char zShort[NBFS];  /* Space for short strings */
  void (*xDel)(void *);  /* If not null, call this function to delete Mem.z */
};
typedef struct Mem Mem;


















/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** No other flags may be set in this case.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.







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







122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
  double r;           /* Real value */
  char *z;            /* String or BLOB value */
  char zShort[NBFS];  /* Space for short strings */
  void (*xDel)(void *);  /* If not null, call this function to delete Mem.z */
};
typedef struct Mem Mem;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.
*/
typedef struct Sorter Sorter;
struct Sorter {
  int nKey;           /* Number of bytes in the key */
  char *zKey;         /* The key by which we will sort */
  Mem data;
  Sorter *pNext;      /* Next in the list */
};

/* 
** Number of buckets used for merge-sort.  
*/
#define NSORT 30

/* One or more of the following flags are set to indicate the validOK
** representations of the value stored in the Mem struct.
**
** If the MEM_Null flag is set, then the value is an SQL NULL value.
** No other flags may be set in this case.
**
** If the MEM_Str flag is set then Mem.z points at a string representation.
373
374
375
376
377
378
379

380
381
382
383
384
385
386
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeIdxRowidLen(int,const u8*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemCopy(Mem*, const Mem*);

int sqlite3VdbeMemNulTerminate(Mem*);
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
void sqlite3VdbeMemSetInt64(Mem*, long long int);
void sqlite3VdbeMemSetDouble(Mem*, double);
void sqlite3VdbeMemSetNull(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemDynamicify(Mem*);







>







372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*);
int sqlite3VdbeIdxRowidLen(int,const u8*);
int sqlite3VdbeExec(Vdbe*);
int sqlite3VdbeList(Vdbe*);
int sqlite3VdbeChangeEncoding(Mem *, int);
int sqlite3VdbeMemCopy(Mem*, const Mem*);
int sqlite3VdbeMemMove(Mem*, Mem*);
int sqlite3VdbeMemNulTerminate(Mem*);
int sqlite3VdbeMemSetStr(Mem*, const char*, int, u8, void(*)(void*));
void sqlite3VdbeMemSetInt64(Mem*, long long int);
void sqlite3VdbeMemSetDouble(Mem*, double);
void sqlite3VdbeMemSetNull(Mem*);
int sqlite3VdbeMemMakeWriteable(Mem*);
int sqlite3VdbeMemDynamicify(Mem*);
Changes to src/vdbeaux.c.
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
** Remove any elements that remain on the sorter for the VDBE given.
*/
void sqlite3VdbeSorterReset(Vdbe *p){
  while( p->pSort ){
    Sorter *pSorter = p->pSort;
    p->pSort = pSorter->pNext;
    sqliteFree(pSorter->zKey);
    sqliteFree(pSorter->pData);
    sqliteFree(pSorter);
  }
}

/*
** Reset an Agg structure.  Delete all its contents.
**







|







689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
** Remove any elements that remain on the sorter for the VDBE given.
*/
void sqlite3VdbeSorterReset(Vdbe *p){
  while( p->pSort ){
    Sorter *pSorter = p->pSort;
    p->pSort = pSorter->pNext;
    sqliteFree(pSorter->zKey);
    sqlite3VdbeMemRelease(&pSorter->data);
    sqliteFree(pSorter);
  }
}

/*
** Reset an Agg structure.  Delete all its contents.
**
Changes to src/vdbemem.c.
306
307
308
309
310
311
312


















313
314
315
316
317
318
319
  if( pTo->flags & (MEM_Str|MEM_Blob) ){
    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
    pTo->flags |= MEM_Ephem;
    sqlite3VdbeMemMakeWriteable(pTo);
  }
  return SQLITE_OK;
}



















/*
** Change the value of a Mem to be a string or a BLOB.
*/
int sqlite3VdbeMemSetStr(
  Mem *pMem,          /* Memory cell to set to string value */
  const char *z,      /* String pointer */







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







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
  if( pTo->flags & (MEM_Str|MEM_Blob) ){
    pTo->flags &= ~(MEM_Dyn|MEM_Static|MEM_Short);
    pTo->flags |= MEM_Ephem;
    sqlite3VdbeMemMakeWriteable(pTo);
  }
  return SQLITE_OK;
}

/*
** Transfer the contents of pFrom to pTo. Any existing value in pTo is
** deleted. pFrom contains an SQL NULL when this routine returns.
*/
int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
  int rc = SQLITE_OK;
  if( !(pFrom->flags&MEM_Dyn && pFrom->xDel) ){
    memcpy(pTo, pFrom, sizeof(Mem));
    if( pFrom->flags & MEM_Short ){
      pTo->z = pTo->zShort;
    }
  }else{
    rc = sqlite3VdbeMemCopy(pTo, pFrom);
    sqlite3VdbeMemRelease(pFrom);
  }
  return SQLITE_OK;
}

/*
** Change the value of a Mem to be a string or a BLOB.
*/
int sqlite3VdbeMemSetStr(
  Mem *pMem,          /* Memory cell to set to string value */
  const char *z,      /* String pointer */
Changes to test/ioerr.test.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# This file implements regression tests for SQLite library.  The
# focus of this file is testing for correct handling of I/O errors
# such as writes failing because the disk is full.
# 
# The tests in this file use special facilities that are only
# available in the SQLite test fixture.
#
# $Id: ioerr.test,v 1.3 2003/04/25 15:37:59 drh Exp $

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

set ::go 1
for {set n 1} {$go} {incr n} {
  do_test ioerr-1.$n.1 {







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# This file implements regression tests for SQLite library.  The
# focus of this file is testing for correct handling of I/O errors
# such as writes failing because the disk is full.
# 
# The tests in this file use special facilities that are only
# available in the SQLite test fixture.
#
# $Id: ioerr.test,v 1.4 2004/06/15 11:40:10 danielk1977 Exp $

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

set ::go 1
for {set n 1} {$go} {incr n} {
  do_test ioerr-1.$n.1 {
53
54
55
56
57
58
59

60


61

62
63
64
65
66
67
68
    set ::go [expr {$::sqlite_io_error_pending<=0}]
    expr {$::sqlite_io_error_pending>0 || $r!=0}
  } {1}
}
set ::sqlite_io_error_pending 0

proc cksum {{db db}} {

  set txt [$db eval {SELECT name, type, sql FROM sqlite_master}]\n


  foreach tbl [$db eval {SELECT name FROM sqlite_master WHERE type='table'}] {

    append txt [$db eval "SELECT * FROM $tbl"]\n
  }
  foreach prag {default_synchronous default_cache_size} {
    append txt $prag-[$db eval "PRAGMA $prag"]\n
  }
  set cksum [string length $txt]-[md5 $txt]
  # puts $cksum-[file size test.db]







>
|
>
>
|
>







53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    set ::go [expr {$::sqlite_io_error_pending<=0}]
    expr {$::sqlite_io_error_pending>0 || $r!=0}
  } {1}
}
set ::sqlite_io_error_pending 0

proc cksum {{db db}} {
  set txt [$db eval {
      SELECT name, type, sql FROM sqlite_master order by name
  }]\n
  foreach tbl [$db eval {
      SELECT name FROM sqlite_master WHERE type='table' order by name
  }] {
    append txt [$db eval "SELECT * FROM $tbl"]\n
  }
  foreach prag {default_synchronous default_cache_size} {
    append txt $prag-[$db eval "PRAGMA $prag"]\n
  }
  set cksum [string length $txt]-[md5 $txt]
  # puts $cksum-[file size test.db]
98
99
100
101
102
103
104




105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
      SELECT name FROM sqlite_master WHERE type='table'
    }
  } {t1 t3}
  do_test ioerr-2.$n.2 [subst {
    set ::sqlite_io_error_pending $n
  }] $n
  do_test ioerr-2.$n.3 {




    set r [catch {db eval {
      VACUUM;
    }} msg]
    # puts "error_pending=$::sqlite_io_error_pending"
    # if {$r} {puts $msg}

    set ::go [expr {$::sqlite_io_error_pending<=0}]
    expr {$::sqlite_io_error_pending>0 || $r!=0}
    set ::sqlite_io_error_pending 0
    db close
    sqlite db test.db
    cksum
  } $cksum
}
set ::sqlite_io_error_pending 0

finish_test







>
>
>
>





>











102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
      SELECT name FROM sqlite_master WHERE type='table'
    }
  } {t1 t3}
  do_test ioerr-2.$n.2 [subst {
    set ::sqlite_io_error_pending $n
  }] $n
  do_test ioerr-2.$n.3 {
if {$n==41} {
  # set sqlite_os_trace 1
  breakpoint
}
    set r [catch {db eval {
      VACUUM;
    }} msg]
    # puts "error_pending=$::sqlite_io_error_pending"
    # if {$r} {puts $msg}
set sqlite_os_trace 0
    set ::go [expr {$::sqlite_io_error_pending<=0}]
    expr {$::sqlite_io_error_pending>0 || $r!=0}
    set ::sqlite_io_error_pending 0
    db close
    sqlite db test.db
    cksum
  } $cksum
}
set ::sqlite_io_error_pending 0

finish_test
Changes to test/memdb.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is in-memory database backend.
#
# $Id: memdb.test,v 1.7 2004/06/09 19:03:55 drh Exp $


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

# In the following sequence of tests, compute the MD5 sum of the content
# of a table, make lots of modifications to that table, then do a rollback.













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is in-memory database backend.
#
# $Id: memdb.test,v 1.8 2004/06/15 11:40:10 danielk1977 Exp $


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

# In the following sequence of tests, compute the MD5 sum of the content
# of a table, make lots of modifications to that table, then do a rollback.
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  1 {}       INSERT                  1 {}  1
  2 {}       {INSERT OR IGNORE}      0 3   1
  3 {}       {INSERT OR REPLACE}     0 4   1
  4 {}       REPLACE                 0 4   1
  5 {}       {INSERT OR FAIL}        1 {}  1
  6 {}       {INSERT OR ABORT}       1 {}  1
  7 {}       {INSERT OR ROLLBACK}    1 {}  {}
  8 IGNORE   INSERT                  0 3   1
  9 IGNORE   {INSERT OR IGNORE}      0 3   1
 10 IGNORE   {INSERT OR REPLACE}     0 4   1
 11 IGNORE   REPLACE                 0 4   1
 12 IGNORE   {INSERT OR FAIL}        1 {}  1
 13 IGNORE   {INSERT OR ABORT}       1 {}  1
 14 IGNORE   {INSERT OR ROLLBACK}    1 {}  {}
 15 REPLACE  INSERT                  0 4   1
 16 FAIL     INSERT                  1 {}  1
 17 ABORT    INSERT                  1 {}  1
 18 ROLLBACK INSERT                  1 {}  {}
} {
  do_test memdb-4.$i {
    if {$conf!=""} {set conf "ON CONFLICT $conf"}
    set r0 [catch {execsql [subst {
      DELETE FROM t1;
      DELETE FROM t2;
      INSERT INTO t1 VALUES(1,2,3);







<
<
<
<
<
<
<
<
<
<
<







166
167
168
169
170
171
172











173
174
175
176
177
178
179
  1 {}       INSERT                  1 {}  1
  2 {}       {INSERT OR IGNORE}      0 3   1
  3 {}       {INSERT OR REPLACE}     0 4   1
  4 {}       REPLACE                 0 4   1
  5 {}       {INSERT OR FAIL}        1 {}  1
  6 {}       {INSERT OR ABORT}       1 {}  1
  7 {}       {INSERT OR ROLLBACK}    1 {}  {}











} {
  do_test memdb-4.$i {
    if {$conf!=""} {set conf "ON CONFLICT $conf"}
    set r0 [catch {execsql [subst {
      DELETE FROM t1;
      DELETE FROM t2;
      INSERT INTO t1 VALUES(1,2,3);
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
 10 ABORT    {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
 11 ROLLBACK {}       {UPDATE OR IGNORE}      0 {6 7 3 9}   1
 12 {}       {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1
 13 {}       {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
 14 {}       {}       {UPDATE OR FAIL}        1 {6 7 3 4}  1
 15 {}       {}       {UPDATE OR ABORT}       1 {1 2 3 4}  1
 16 {}       {}       {UPDATE OR ROLLBACK}    1 {1 2 3 4}  0
 17 {}       IGNORE   UPDATE                  0 {6 7 3 9}  1
 18 {}       REPLACE  UPDATE                  0 {7 6 9}    1
 19 {}       FAIL     UPDATE                  1 {6 7 3 4}  1
 20 {}       ABORT    UPDATE                  1 {1 2 3 4}  1
 21 {}       ROLLBACK UPDATE                  1 {1 2 3 4}  0
 22 REPLACE  IGNORE   UPDATE                  0 {6 7 3 9}  1
 23 IGNORE   REPLACE  UPDATE                  0 {7 6 9}    1
 24 REPLACE  FAIL     UPDATE                  1 {6 7 3 4}  1
 25 IGNORE   ABORT    UPDATE                  1 {1 2 3 4}  1
 26 REPLACE  ROLLBACK UPDATE                  1 {1 2 3 4}  0
} {
  if {$t0} {set t1 {column a is not unique}}
  do_test memdb-5.$i {
    if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
    if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
    set r0 [catch {execsql [subst {
      DROP TABLE t1;







<
<
<
<
<
<
<
<
<
<







226
227
228
229
230
231
232










233
234
235
236
237
238
239
 10 ABORT    {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
 11 ROLLBACK {}       {UPDATE OR IGNORE}      0 {6 7 3 9}   1
 12 {}       {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1
 13 {}       {}       {UPDATE OR REPLACE}     0 {7 6 9}    1
 14 {}       {}       {UPDATE OR FAIL}        1 {6 7 3 4}  1
 15 {}       {}       {UPDATE OR ABORT}       1 {1 2 3 4}  1
 16 {}       {}       {UPDATE OR ROLLBACK}    1 {1 2 3 4}  0










} {
  if {$t0} {set t1 {column a is not unique}}
  do_test memdb-5.$i {
    if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"}
    if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"}
    set r0 [catch {execsql [subst {
      DROP TABLE t1;
Changes to test/quick.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: quick.test,v 1.22 2004/06/15 02:44:20 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {}
set ISQUICK 1

set EXCLUDE {
  all.test
  quick.test
  btree2.test
  malloc.test
  memleak.test
  misuse.test
  format3.test
}

lappend EXCLUDE ioerr.test        ;# seg-faults (?)
lappend EXCLUDE memdb.test        ;# fails - malformed database
lappend EXCLUDE version.test      ;# This is obsolete.

if {[sqlite -has-codec]} {
  lappend EXCLUDE \
    attach.test \
    attach2.test \
    auth.test \
    format3.test \
    version.test












|

















<
<
<
<







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30




31
32
33
34
35
36
37
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file runs all tests.
#
# $Id: quick.test,v 1.23 2004/06/15 11:40:10 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl
rename finish_test really_finish_test
proc finish_test {} {}
set ISQUICK 1

set EXCLUDE {
  all.test
  quick.test
  btree2.test
  malloc.test
  memleak.test
  misuse.test
  format3.test
}





if {[sqlite -has-codec]} {
  lappend EXCLUDE \
    attach.test \
    attach2.test \
    auth.test \
    format3.test \
    version.test
Deleted test/version.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# 2002 July 17
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the ability of the library to detect
# past or future file format version numbers and respond appropriately.
#
# $Id: version.test,v 1.10 2004/05/13 11:34:17 danielk1977 Exp $

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

# Current file format version
set VX 4

# Create a new database
#
do_test version-1.1 {
  execsql {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 SELECT x+1 FROM t1;
    INSERT INTO t1 SELECT x+2 FROM t1;
    INSERT INTO t1 SELECT x+4 FROM t1;
    SELECT * FROM t1;
  }
} {1 2 3 4 5 6 7 8}

# Make sure the version number is set correctly
#
do_test version-1.2 {
  db close
  set ::bt [btree_open test.db 100 0]
  btree_begin_transaction $::bt
  set ::meta [btree_get_meta $::bt]
  btree_rollback $::bt
  lindex $::meta 2
} $VX

# Increase the file_format number by one.  Verify that the
# file will refuse to open.
#
do_test version-1.3 {
  set m2 [lreplace $::meta 2 2 [expr {$::VX+1}]]
  btree_begin_transaction $::bt
  eval btree_update_meta $::bt $m2
  btree_commit $::bt
  set rc [catch {sqlite db test.db} msg]
  lappend rc $msg
} {1 {unsupported file format}}

# Decrease the file_format number by one.  Verify that the
# file will open correctly.
#
do_test version-1.4 {
  set m2 [lreplace $::meta 2 2 [expr {$::VX-1}]]
  btree_begin_transaction $::bt
  eval btree_update_meta $::bt $m2
  btree_commit $::bt
  sqlite db test.db
  execsql {
    SELECT * FROM t1;
  }
} {1 2 3 4 5 6 7 8}

# Set the file_format number to 2.  This should cause the automatic
# upgrade processing to run.
#
do_test version-1.5 {
  set m2 [lreplace $::meta 2 2 2]
  btree_begin_transaction $::bt
  eval btree_update_meta $::bt $m2
  btree_commit $::bt
  sqlite db test.db
  execsql {
    SELECT * FROM t1;
  }
} {1 2 3 4 5 6 7 8}
do_test version-1.6 {
  set ::meta [btree_get_meta $::bt]
  lindex $::meta 2
} $VX

# Add some triggers, views, and indices to the schema and make sure the
# automatic upgrade still works.
#
do_test version-1.7 {
  execsql {
    CREATE INDEX i1 ON t1(x);
    DELETE FROM t1;
    CREATE TABLE t2(a INTEGER PRIMARY KEY, b UNIQUE, c);
    CREATE TABLE cnt(name,ins, del);
    INSERT INTO cnt VALUES('t1',0,0);
    INSERT INTO cnt VALUES('t2',0,0);
    CREATE TRIGGER r1 AFTER INSERT ON t1 FOR EACH ROW BEGIN
      UPDATE cnt SET ins=ins+1 WHERE name='t1';
    END;
    CREATE TRIGGER r2 AFTER DELETE ON t1 FOR EACH ROW BEGIN
      UPDATE cnt SET del=del+1 WHERE name='t1';
    END;
    CREATE TRIGGER r3 AFTER INSERT ON t2 FOR EACH ROW BEGIN
      UPDATE cnt SET ins=ins+1 WHERE name='t2';
    END;
    CREATE TRIGGER r4 AFTER DELETE ON t2 FOR EACH ROW BEGIN
      UPDATE cnt SET del=del+1 WHERE name='t2';
    END;
    CREATE VIEW v1 AS SELECT x+100 FROM t1;
    CREATE VIEW v2 AS SELECT sum(ins), sum(del) FROM cnt;
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 SELECT x+1 FROM t1;
    INSERT INTO t1 SELECT x+2 FROM t1;
    INSERT INTO t1 SELECT x+4 FROM t1;
    SELECT * FROM t1;
  }
} {1 2 3 4 5 6 7 8}
do_test version-1.8 {
  execsql {
    SELECT * FROM v2;
  }
} {8 0}
do_test version-1.9 {
  execsql {
    SELECT * FROM cnt;
  }
} {t1 8 0 t2 0 0}
do_test version-1.10 {
  execsql {
    INSERT INTO t2 SELECT x*3, x*2, x FROM t1;
    SELECT * FROM t2;
  }
} {3 2 1 6 4 2 9 6 3 12 8 4 15 10 5 18 12 6 21 14 7 24 16 8}
do_test version-1.11 {
  execsql {
    SELECT * FROM cnt;
  }
} {t1 8 0 t2 8 0}

# Here we do the upgrade test.
#
do_test version-1.12 {
  db close
  set m2 [lreplace $::meta 2 2 2]
  btree_begin_transaction $::bt
  eval btree_update_meta $::bt $m2
  btree_commit $::bt
  sqlite db test.db
  execsql {
    SELECT * FROM cnt;
  }
} {t1 8 0 t2 8 0}
do_test version-1.13 {
  execsql {
    SELECT * FROM v1;
  }
} {101 102 103 104 105 106 107 108}
do_test version-1.14 {
  execsql {
    SELECT * FROM v2;
  }
} {16 0}

# Try to do an upgrade where the database file is read-only
#
do_test version-2.1 {
  db close
  set m2 [lreplace $::meta 2 2 2]
  btree_begin_transaction $::bt
  eval btree_update_meta $::bt $m2
  btree_commit $::bt
  btree_close $::bt
  catch {file attributes test.db -permissions 0444}
  catch {file attributes test.db -readonly 1}
  if {[file writable test.db]} {
    error "Unable to make the database file test.db readonly - rerun this test as an unprivileged user"
  }
  set rc [catch {sqlite db test.db} msg]
  lappend rc $msg
} {1 {unable to upgrade database to the version 2.6 format: attempt to write a readonly database}}
do_test version-2.2 {
  file delete -force test.db
  set fd [open test.db w]
  set txt "This is not a valid database file\n"
  while {[string length $txt]<4092} {append txt $txt}
  puts $fd $txt
  close $fd
  set rc [catch {sqlite db test.db} msg]
  lappend rc $msg
} {1 {file is encrypted or is not a database}}


finish_test
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<