SQLite

Check-in [95d1f8389d]
Login

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

Overview
Comment:The VACUUM command now does a database sanity check. (CVS 364)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 95d1f8389dd5e168bdf0290169662296b6a0f6d9
User & Date: drh 2002-02-03 03:34:08.000
Context
2002-02-03
17:37
Put in PRAGMA SANITY_CHECK in place of VACUUM. (CVS 365) (check-in: 7c65029e5b user: drh tags: trunk)
03:34
The VACUUM command now does a database sanity check. (CVS 364) (check-in: 95d1f8389d user: drh tags: trunk)
00:56
Five-algorithm conflict resolution appears to be working. (CVS 363) (check-in: 0115518f8e user: drh 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
/*
** 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.
**
*************************************************************************
** $Id: btree.c,v 1.48 2002/02/03 00:56:10 drh 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
/*
** 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.
**
*************************************************************************
** $Id: btree.c,v 1.49 2002/02/03 03:34:08 drh 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.
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
    }

    /* Check that keys are in the right order
    */
    cur.idx = i;
    zKey2 = sqliteMalloc( NKEY(pCell->h)+1 );
    getPayload(&cur, 0, NKEY(pCell->h), zKey2);
    if( zKey1 && strcmp(zKey1,zKey2)>=0 ){
      checkAppendMsg(pCheck, zContext, "Key is out of order");
    }

    /* Check sanity of left child page.
    */
    pgno = (int)pCell->h.leftChild;
    d2 = checkTreePage(pCheck, pgno, pPage, zContext, zKey1, zKey2);







|







2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
    }

    /* Check that keys are in the right order
    */
    cur.idx = i;
    zKey2 = sqliteMalloc( NKEY(pCell->h)+1 );
    getPayload(&cur, 0, NKEY(pCell->h), zKey2);
    if( zKey1 && strcmp(zKey1,zKey2)>0 ){
      checkAppendMsg(pCheck, zContext, "Key is out of order");
    }

    /* Check sanity of left child page.
    */
    pgno = (int)pCell->h.leftChild;
    d2 = checkTreePage(pCheck, pgno, pPage, zContext, zKey1, zKey2);
Changes to src/build.c.
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.72 2002/02/03 00:56:10 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 







|







21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
**     COPY
**     VACUUM
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**     PRAGMA
**
** $Id: build.c,v 1.73 2002/02/03 03:34:08 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called after a single SQL statement has been
** parsed and we want to execute the VDBE code to implement 
1393
1394
1395
1396
1397
1398
1399




1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416

1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442

1443
1444
1445
1446
1447
1448
1449
  return;
}

/*
** The non-standard VACUUM command is used to clean up the database,
** collapse free space, etc.  It is modelled after the VACUUM command
** in PostgreSQL.




*/
void sqliteVacuum(Parse *pParse, Token *pTableName){
  char *zName;
  Vdbe *v;
  sqlite *db = pParse->db;

  if( pParse->nErr || sqlite_malloc_failed ) return;
  if( pTableName ){
    zName = sqliteTableNameFromToken(pTableName);
  }else{
    zName = 0;
  }
  if( zName && sqliteFindIndex(db, zName)==0
    && sqliteFindTable(db, zName)==0 ){
    sqliteSetString(&pParse->zErrMsg, "no such table or index: ", zName, 0);
    pParse->nErr++;
    goto vacuum_cleanup;

  }
  v = sqliteGetVdbe(pParse);
  if( v==0 ) goto vacuum_cleanup;
  sqliteBeginWriteOperation(pParse);
  if( zName ){
    sqliteVdbeAddOp(v, OP_Reorganize, 0, 0);
    sqliteVdbeChangeP3(v, -1, zName, strlen(zName));
  }else{
    Table *pTab;
    Index *pIdx;
    HashElem *pE;
    for(pE=sqliteHashFirst(&db->tblHash); pE; pE=sqliteHashNext(pE)){
      pTab = sqliteHashData(pE);
      sqliteVdbeAddOp(v, OP_Reorganize, 0, 0);
      sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC);
      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
        sqliteVdbeAddOp(v, OP_Reorganize, 0, 0);
        sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);
      }
    }
  }
  sqliteEndWriteOperation(pParse);

vacuum_cleanup:
  sqliteFree(zName);
  return;

}

/*
** Begin a transaction
*/
void sqliteBeginTransaction(Parse *pParse, int onError){
  sqlite *db;







>
>
>
>


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

>







1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407

1408



1409
1410
1411
1412
1413
1414
1415
1416
1417
1418






1419
1420









1421
1422

1423
1424

1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
  return;
}

/*
** The non-standard VACUUM command is used to clean up the database,
** collapse free space, etc.  It is modelled after the VACUUM command
** in PostgreSQL.
**
** In this implementation, no cleanup occurs.  Instead, the B-tree that
** forms the database is checked for integrity.  This is a no-op unless
** SQLite is compiled with the SQLITE_TEST macro.
*/
void sqliteVacuum(Parse *pParse, Token *pTableName){
#if 1
  static VdbeOp checkDb[] = {

    { OP_SetInsert,   0, 0,        "2"},



    { OP_Open,        0, 2,        0},
    { OP_Rewind,      0, 6,        0},
    { OP_Column,      0, 3,        0},
    { OP_SetInsert,   0, 0,        0},
    { OP_Next,        0, 3,        0},
    { OP_SanityCheck, 0, 0,        0},
    { OP_ColumnCount, 1, 0,        0},
    { OP_ColumnName,  0, 0,        "sanity_check"},
    { OP_Callback,    1, 0,        0},
  };






  static 
  Vdbe *v;









 


  v = sqliteGetVdbe(pParse);
  if( v==0 ) return;

  sqliteVdbeAddOpList(v, ArraySize(checkDb), checkDb);
  return;
#endif
}

/*
** Begin a transaction
*/
void sqliteBeginTransaction(Parse *pParse, int onError){
  sqlite *db;
Changes to src/hash.h.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This is the header file for the generic hash-table implemenation
** used in SQLite.
**
** $Id: hash.h,v 1.2 2001/10/09 04:19:47 drh Exp $
*/
#ifndef _SQLITE_HASH_H_
#define _SQLITE_HASH_H_

/* Forward declarations of structures. */
typedef struct Hash Hash;
typedef struct HashElem HashElem;







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This is the header file for the generic hash-table implemenation
** used in SQLite.
**
** $Id: hash.h,v 1.3 2002/02/03 03:34:09 drh Exp $
*/
#ifndef _SQLITE_HASH_H_
#define _SQLITE_HASH_H_

/* Forward declarations of structures. */
typedef struct Hash Hash;
typedef struct HashElem HashElem;
94
95
96
97
98
99
100

101





102
**     SomeStructure *pData = sqliteHashData(p);
**     // do something with pData
**   }
*/
#define sqliteHashFirst(H)  ((H)->first)
#define sqliteHashNext(E)   ((E)->next)
#define sqliteHashData(E)   ((E)->data)







#endif /* _SQLITE_HASH_H_ */







>

>
>
>
>
>

94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
**     SomeStructure *pData = sqliteHashData(p);
**     // do something with pData
**   }
*/
#define sqliteHashFirst(H)  ((H)->first)
#define sqliteHashNext(E)   ((E)->next)
#define sqliteHashData(E)   ((E)->data)
#define sqliteHashKey(E)    ((E)->pKey)

/*
** Number of entries in a hash table
*/
#define sqliteHashCount(H)  ((H)->count)

#endif /* _SQLITE_HASH_H_ */
Changes to src/vdbe.c.
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.115 2002/02/03 00:56:10 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test







|







26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
** type to the other occurs as necessary.
** 
** Most of the code in this file is taken up by the sqliteVdbeExec()
** function which does the work of interpreting a VDBE program.
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
** $Id: vdbe.c,v 1.116 2002/02/03 03:34:09 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** The following global variable is incremented every time a cursor
** moves, either by the OP_MoveTo or the OP_Next opcode.  The test
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
  "ReadCookie",        "SetCookie",         "VerifyCookie",      "Open",
  "OpenTemp",          "OpenWrite",         "OpenAux",           "OpenWrAux",
  "Close",             "MoveTo",            "NewRecno",          "PutIntKey",
  "PutStrKey",         "Distinct",          "Found",             "NotFound",
  "IsUnique",          "NotExists",         "Delete",            "Column",
  "KeyAsData",         "Recno",             "FullKey",           "Rewind",
  "Next",              "Destroy",           "Clear",             "CreateIndex",
  "CreateTable",       "Reorganize",        "IdxPut",            "IdxDelete",
  "IdxRecno",          "IdxGT",             "IdxGE",             "MemLoad",
  "MemStore",          "ListWrite",         "ListRewind",        "ListRead",
  "ListReset",         "SortPut",           "SortMakeRec",       "SortMakeKey",
  "Sort",              "SortNext",          "SortCallback",      "SortReset",
  "FileOpen",          "FileRead",          "FileColumn",        "AggReset",
  "AggFocus",          "AggIncr",           "AggNext",           "AggSet",
  "AggGet",            "SetInsert",         "SetFound",          "SetNotFound",







|







864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
  "ReadCookie",        "SetCookie",         "VerifyCookie",      "Open",
  "OpenTemp",          "OpenWrite",         "OpenAux",           "OpenWrAux",
  "Close",             "MoveTo",            "NewRecno",          "PutIntKey",
  "PutStrKey",         "Distinct",          "Found",             "NotFound",
  "IsUnique",          "NotExists",         "Delete",            "Column",
  "KeyAsData",         "Recno",             "FullKey",           "Rewind",
  "Next",              "Destroy",           "Clear",             "CreateIndex",
  "CreateTable",       "SanityCheck",       "IdxPut",            "IdxDelete",
  "IdxRecno",          "IdxGT",             "IdxGE",             "MemLoad",
  "MemStore",          "ListWrite",         "ListRewind",        "ListRead",
  "ListReset",         "SortPut",           "SortMakeRec",       "SortMakeKey",
  "Sort",              "SortNext",          "SortCallback",      "SortReset",
  "FileOpen",          "FileRead",          "FileColumn",        "AggReset",
  "AggFocus",          "AggIncr",           "AggNext",           "AggSet",
  "AggGet",            "SetInsert",         "SetFound",          "SetNotFound",
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486


3487


3488
3489

3490
3491









3492























3493
3494
3495
3496
3497
3498
3499
    aStack[i].flags = STK_Int;
    *(u32*)pOp->p3 = pgno;
    pOp->p3 = 0;
  }
  break;
}

/* Opcode: Reorganize P1 * *
**
** Compress, optimize, and tidy up table or index whose root page in the


** database file is P1.


**
** In the current implementation, this is a no-op.

*/
case OP_Reorganize: {









  /* This is currently a no-op */























  break;
}

/* Opcode:  Limit P1 P2 *
**
** Set a limit and offset on callbacks.  P1 is the limit and P2 is
** the offset.  If the offset counter is positive, no callbacks are







|

|
>
>
|
>
>

<
>

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







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
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
    aStack[i].flags = STK_Int;
    *(u32*)pOp->p3 = pgno;
    pOp->p3 = 0;
  }
  break;
}

/* Opcode: SanityCheck P1 * *
**
** Do an analysis of the currently open database.  Push onto the
** stack the text of an error message describing any problems.
** If there are no errors, push a "ok" onto the stack.
**
** P1 is the index of a set that contains the root page numbers
** for all tables and indices in this database.
**

** This opcode is used for testing purposes only.
*/
case OP_SanityCheck: {
#if 1  /* This opcode used for testing only */
  int nRoot;
  int *aRoot;
  int tos = ++p->tos;
  int iSet = pOp->p1;
  Set *pSet;
  int j;
  HashElem *i;
  char *z;

  if( iSet<0 || iSet>=p->nSet ){
    goto bad_instruction;
  }
  VERIFY( if( NeedStack(p, p->tos) ) goto no_mem; )
  pSet = &p->aSet[iSet];
  nRoot = sqliteHashCount(&pSet->hash);
  aRoot = sqliteMalloc( sizeof(int)*(nRoot+1) );
  for(j=0, i=sqliteHashFirst(&pSet->hash); i; i=sqliteHashNext(i), j++){
    aRoot[j] = atoi((char*)sqliteHashKey(i));
  }
  aRoot[j] = 0;
  z = sqliteBtreeSanityCheck(pBt, aRoot, nRoot);
  if( z==0 || z[0]==0 ){
    zStack[tos] = "ok";
    aStack[tos].n = 3;
    aStack[tos].flags = STK_Str | STK_Static;
    if( z ) sqliteFree(z);
  }else{
    zStack[tos] = z;
    aStack[tos].n = strlen(z) + 1;
    aStack[tos].flags = STK_Str | STK_Dyn;
  }
#endif /* SQLITE_TEST */
  break;
}

/* Opcode:  Limit P1 P2 *
**
** Set a limit and offset on callbacks.  P1 is the limit and P2 is
** the offset.  If the offset counter is positive, no callbacks are
Changes to src/vdbe.h.
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.40 2002/02/02 18:49:21 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines







|







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
*************************************************************************
** Header file for the Virtual DataBase Engine (VDBE)
**
** This header defines the interface to the virtual database engine
** or VDBE.  The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.41 2002/02/03 03:34:09 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#include <stdio.h>

/*
** A single VDBE is an opaque structure named "Vdbe".  Only routines
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#define OP_Rewind             28
#define OP_Next               29

#define OP_Destroy            30
#define OP_Clear              31
#define OP_CreateIndex        32
#define OP_CreateTable        33
#define OP_Reorganize         34

#define OP_IdxPut             35
#define OP_IdxDelete          36
#define OP_IdxRecno           37
#define OP_IdxGT              38
#define OP_IdxGE              39








|







100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#define OP_Rewind             28
#define OP_Next               29

#define OP_Destroy            30
#define OP_Clear              31
#define OP_CreateIndex        32
#define OP_CreateTable        33
#define OP_SanityCheck        34

#define OP_IdxPut             35
#define OP_IdxDelete          36
#define OP_IdxRecno           37
#define OP_IdxGT              38
#define OP_IdxGE              39

Changes to test/conflict.test.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.5 2002/02/03 00:56:11 drh Exp $

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

# Create tables for the first group of tests.
#
do_test conflict-1.0 {







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
# This file implements tests for the conflict resolution extension
# to SQLite.
#
# $Id: conflict.test,v 1.6 2002/02/03 03:34:09 drh Exp $

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

# Create tables for the first group of tests.
#
do_test conflict-1.0 {
363
364
365
366
367
368
369

370
371
372
373
374
375
376
377
378
379
380
    set r0 [catch {execsql [subst {
      DROP TABLE t1;
      CREATE TABLE t1(a,b,c, UNIQUE(a) $conf1);
      INSERT INTO t1 SELECT * FROM t2;
      UPDATE t3 SET x=0;
      BEGIN $conf2;
      $cmd t3 SET x=1;

      $cmd t1 SET a=c+5;
    }]} r1]
    execsql {COMMIT}
    if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]}
    set r2 [execsql {SELECT x FROM t3}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]
}


finish_test







>











363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
    set r0 [catch {execsql [subst {
      DROP TABLE t1;
      CREATE TABLE t1(a,b,c, UNIQUE(a) $conf1);
      INSERT INTO t1 SELECT * FROM t2;
      UPDATE t3 SET x=0;
      BEGIN $conf2;
      $cmd t3 SET x=1;
      $cmd t1 SET b=b*2;
      $cmd t1 SET a=c+5;
    }]} r1]
    execsql {COMMIT}
    if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]}
    set r2 [execsql {SELECT x FROM t3}]
    list $r0 $r1 $r2
  } [list $t0 $t1 $t2]
}


finish_test