Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Get VACUUM working again - with test cases. Some other minor cleanups. (CVS 931) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
5afb88008fed253e6d1fc0ed5172370b |
User & Date: | drh 2003-04-25 02:43:08.000 |
Context
2003-04-25
| ||
03:13 | Explicit casts to squelch bogus warnings for vc++. Ticket #194. (CVS 932) (check-in: cb808c14bc user: drh tags: trunk) | |
02:43 | Get VACUUM working again - with test cases. Some other minor cleanups. (CVS 931) (check-in: 5afb88008f user: drh tags: trunk) | |
2003-04-24
| ||
01:45 | Fix some issues with INSTEAD OF triggers. (CVS 930) (check-in: 206b17397b user: drh tags: trunk) | |
Changes
Changes to src/btree.h.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** | | | 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. ** ************************************************************************* ** This header file defines the interface that the sqlite B-Tree file ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** ** @(#) $Id: btree.h,v 1.32 2003/04/25 02:43:08 drh Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ /* ** Forward declarations of structure */ |
︙ | ︙ | |||
91 92 93 94 95 96 97 98 99 100 101 102 103 104 | /* ** The number of 4-byte "meta" values contained on the first page of each ** database file. */ #define SQLITE_N_BTREE_META 10 int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree); #define btOps(pBt) (*((BtOps **)(pBt))) #define btCOps(pCur) (*((BtCursorOps **)(pCur))) #define sqliteBtreeClose(pBt) (btOps(pBt)->Close(pBt)) #define sqliteBtreeSetCacheSize(pBt, sz) (btOps(pBt)->SetCacheSize(pBt, sz)) #define sqliteBtreeSetSafetyLevel(pBt, sl) (btOps(pBt)->SetSafetyLevel(pBt, sl)) | > | 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | /* ** The number of 4-byte "meta" values contained on the first page of each ** database file. */ #define SQLITE_N_BTREE_META 10 int sqliteBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree); int sqliteRBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree); #define btOps(pBt) (*((BtOps **)(pBt))) #define btCOps(pCur) (*((BtCursorOps **)(pCur))) #define sqliteBtreeClose(pBt) (btOps(pBt)->Close(pBt)) #define sqliteBtreeSetCacheSize(pBt, sz) (btOps(pBt)->SetCacheSize(pBt, sz)) #define sqliteBtreeSetSafetyLevel(pBt, sl) (btOps(pBt)->SetSafetyLevel(pBt, sl)) |
︙ | ︙ |
Changes to src/btree_rb.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2003 Feb 4 ** ** 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. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2003 Feb 4 ** ** 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_rb.c,v 1.8 2003/04/25 02:43:08 drh Exp $ ** ** This file implements an in-core database using Red-Black balanced ** binary trees. ** ** It was contributed to SQLite by anonymous on 2003-Feb-04 23:24:49 UTC. */ #include "btree.h" |
︙ | ︙ | |||
1323 1324 1325 1326 1327 1328 1329 | } #endif /* ** Return the full pathname of the underlying database file. */ static const char *memBtreeGetFilename(Btree *pBt){ | | | 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 | } #endif /* ** Return the full pathname of the underlying database file. */ static const char *memBtreeGetFilename(Btree *pBt){ return 0; /* A NULL return indicates there is no underlying file */ } /* ** Change the name of the underlying database file. */ static int memBtreeChangeFilename(Btree *pBt, const char *zNew){ return SQLITE_OK; |
︙ | ︙ |
Changes to src/pragma.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2003 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. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2003 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. ** ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** ** $Id: pragma.c,v 1.5 2003/04/25 02:43:08 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Interpret the given string as a boolean value. */ |
︙ | ︙ | |||
67 68 69 70 71 72 73 | /* ** Interpret the given string as a temp db location. Return 1 for file ** backed temporary databases, 2 for the Red-Black tree in memory database ** and 0 to use the compile-time default. */ static int getTempStore(char *z){ | > > | | | 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | /* ** Interpret the given string as a temp db location. Return 1 for file ** backed temporary databases, 2 for the Red-Black tree in memory database ** and 0 to use the compile-time default. */ static int getTempStore(char *z){ if( z[0]>='0' || z[0]<='2' ){ return z[0] - '0'; }else if( sqliteStrICmp(z, "file")==0 ){ return 1; }else if( sqliteStrICmp(z, "memory")==0 ){ return 2; }else{ return 0; } } /* |
︙ | ︙ |
Changes to src/vacuum.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** 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. ** | | | 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.4 2003/04/25 02:43:08 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #define SQLITE_OMIT_VACUUM 1 /* |
︙ | ︙ | |||
37 38 39 40 41 42 43 44 45 46 47 48 49 50 | */ typedef struct vacuumStruct vacuumStruct; struct vacuumStruct { sqlite *dbOld; /* Original database */ sqlite *dbNew; /* New database */ Parse *pParse; /* The parser context */ const char *zTable; /* Name of a table being copied */ dynStr s1, s2; /* Two dynamic strings */ }; #ifdef SQLITE_OMIT_VACUUM /* ** Append text to a dynamic string */ | > | 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | */ typedef struct vacuumStruct vacuumStruct; struct vacuumStruct { sqlite *dbOld; /* Original database */ sqlite *dbNew; /* New database */ Parse *pParse; /* The parser context */ const char *zTable; /* Name of a table being copied */ const char *zPragma; /* Pragma to execute with results */ dynStr s1, s2; /* Two dynamic strings */ }; #ifdef SQLITE_OMIT_VACUUM /* ** Append text to a dynamic string */ |
︙ | ︙ | |||
155 156 157 158 159 160 161 162 163 164 165 166 167 168 | rc = sqlite_exec(p->dbOld, p->s1.z, vacuumCallback2, p, &zErrMsg); if( rc && p->pParse->zErrMsg==0 ){ sqliteErrorMsg(p->pParse, "%s", zErrMsg); } } return rc; } /* ** Generate a random name of 20 character in length. */ static void randomName(char *zBuf){ static const char zChars[] = "abcdefghijklmnopqrstuvwxyz" | > > > > > > > > > > > > > > > > > > | 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 | rc = sqlite_exec(p->dbOld, p->s1.z, vacuumCallback2, p, &zErrMsg); if( rc && p->pParse->zErrMsg==0 ){ sqliteErrorMsg(p->pParse, "%s", zErrMsg); } } return rc; } /* ** This callback is used to transfer PRAGMA settings from one database ** to the other. The value in argv[0] should be passed to a pragma ** identified by ((vacuumStruct*)pArg)->zPragma. */ static int vacuumCallback3(void *pArg, int argc, char **argv, char **NotUsed){ vacuumStruct *p = (vacuumStruct*)pArg; int rc = 0; char zBuf[200]; assert( argc==1 ); assert( argv[0]!=0 ); assert( strlen(p->zPragma)<100 ); assert( strlen(argv[0])<30 ); sprintf(zBuf,"PRAGMA %s=%s;", p->zPragma, argv[0]); rc = execsql(p->pParse, p->dbNew, zBuf); return rc; } /* ** Generate a random name of 20 character in length. */ static void randomName(char *zBuf){ static const char zChars[] = "abcdefghijklmnopqrstuvwxyz" |
︙ | ︙ | |||
194 195 196 197 198 199 200 201 202 203 204 205 206 207 | sqlite *dbNew = 0; /* The new vacuumed database */ sqlite *db; /* The original database */ int rc, i; char *zErrMsg = 0; char *zSql = 0; int safety = 0; vacuumStruct sVac; /* Initial error checks */ if( pParse->explain ){ return; } db = pParse->db; | > > > > > > > > | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 | sqlite *dbNew = 0; /* The new vacuumed database */ sqlite *db; /* The original database */ int rc, i; char *zErrMsg = 0; char *zSql = 0; int safety = 0; vacuumStruct sVac; /* These are all of the pragmas that need to be transferred over ** to the new database */ static const char *zPragma[] = { "default_synchronous", "default_cache_size", /* "default_temp_store", */ }; /* Initial error checks */ if( pParse->explain ){ return; } db = pParse->db; |
︙ | ︙ | |||
252 253 254 255 256 257 258 259 260 | } safety = 1; if( execsql(pParse, db, "BEGIN") ) goto end_of_vacuum; if( execsql(pParse, dbNew, "BEGIN") ) goto end_of_vacuum; sVac.dbOld = db; sVac.dbNew = dbNew; sVac.pParse = pParse; rc = sqlite_exec(db, "SELECT type, name, sql FROM sqlite_master " "WHERE sql NOT NULL", vacuumCallback1, &sVac, &zErrMsg); | > > > > > > > > | < < < < < | 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 | } safety = 1; if( execsql(pParse, db, "BEGIN") ) goto end_of_vacuum; if( execsql(pParse, dbNew, "BEGIN") ) goto end_of_vacuum; sVac.dbOld = db; sVac.dbNew = dbNew; sVac.pParse = pParse; for(i=0; i<sizeof(zPragma)/sizeof(zPragma[0]); i++){ char zBuf[200]; assert( strlen(zPragma[i])<100 ); sprintf(zBuf, "PRAGMA %s;", zPragma[i]); sVac.zPragma = zPragma[i]; rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg); if( rc ) goto vacuum_error; } rc = sqlite_exec(db, "SELECT type, name, sql FROM sqlite_master " "WHERE sql NOT NULL", vacuumCallback1, &sVac, &zErrMsg); if( rc ) goto vacuum_error; if( sqliteOsFileRename(zFilename, zTemp2) ){ sqliteErrorMsg(pParse, "unable to rename database file"); goto end_of_vacuum; } if( sqliteOsFileRename(zTemp, zFilename) ){ sqliteOsFileRename(zTemp2, zFilename); |
︙ | ︙ | |||
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 | } execsql(pParse, db, "COMMIT;"); /* Nothing was written so its gotta work */ sqlite_close(dbNew); dbNew = 0; if( sqliteOsDelete(zTemp2) ){ sqliteErrorMsg(pParse, "unable to delete old database: %s", zTemp2); } end_of_vacuum: sqlite_exec(db, "COMMIT", 0, 0, 0); if( safety) { sqliteSafetyOn(db); } if( dbNew ) sqlite_close(dbNew); sqliteOsDelete(zTemp); sqliteFree(zTemp); sqliteFree(zSql); sqliteFree(sVac.s1.z); sqliteFree(sVac.s2.z); if( zErrMsg ) sqlite_freemem(zErrMsg); #endif } | > > > > > > > > > > > > > | 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 | } execsql(pParse, db, "COMMIT;"); /* Nothing was written so its gotta work */ sqlite_close(dbNew); dbNew = 0; if( sqliteOsDelete(zTemp2) ){ sqliteErrorMsg(pParse, "unable to delete old database: %s", zTemp2); } sqliteBtreeClose(db->aDb[0].pBt); zTemp2[nFilename] = 0; if( sqliteBtreeOpen(zTemp2, 0, MAX_PAGES, &db->aDb[0].pBt) ){ sqliteErrorMsg(pParse, "unable to reopen database after vacuuming"); } sqliteResetInternalSchema(db, 0); end_of_vacuum: sqlite_exec(db, "COMMIT", 0, 0, 0); if( safety) { sqliteSafetyOn(db); } if( dbNew ) sqlite_close(dbNew); sqliteOsDelete(zTemp); sqliteFree(zTemp); sqliteFree(zSql); sqliteFree(sVac.s1.z); sqliteFree(sVac.s2.z); if( zErrMsg ) sqlite_freemem(zErrMsg); return; vacuum_error: if( pParse->zErrMsg==0 ){ sqliteErrorMsg(pParse, "unable to vacuum database - %s", zErrMsg); } goto end_of_vacuum; #endif } |
Changes to test/vacuum.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 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 file is testing the VACUUM statement. # | | > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > | 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 | # 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 file is testing the VACUUM statement. # # $Id: vacuum.test,v 1.8 2003/04/25 02:43:08 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl proc cksum {filename} { 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 fd [open $filename w] # puts $fd $txt # close $fd return [string length $txt]-[md5 $txt] } do_test vacuum-1.1 { execsql { BEGIN; CREATE TABLE t1(a INTEGER PRIMARY KEY, b, c); INSERT INTO t1 VALUES(NULL,randstr(10,100),randstr(5,50)); INSERT INTO t1 VALUES(123456,randstr(10,100),randstr(5,50)); INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; INSERT INTO t1 SELECT NULL, b||'-'||rowid, c||'-'||rowid FROM t1; CREATE INDEX i1 ON t1(b,c); CREATE TABLE t2 AS SELECT * FROM t1; COMMIT; DROP TABLE t2; } set ::size1 [file size test.db] set ::cksum [cksum vacuum1.txt] expr {$::cksum!=""} } {1} do_test vacuum-1.2 { execsql { VACUUM; } cksum vacuum2.txt } $cksum do_test vacuum-1.3 { expr {[file size test.db]<$::size1} } {1} do_test vacuum-1.4 { execsql { BEGIN; CREATE TABLE t2 AS SELECT * FROM t1; CREATE TABLE t3 AS SELECT * FROM t1; CREATE VIEW v1 AS SELECT b, c FROM t3; CREATE TRIGGER r1 AFTER DELETE ON t2 BEGIN SELECT 1; END; COMMIT; DROP TABLE t2; } set ::size1 [file size test.db] set ::cksum [cksum vacuum3.txt] expr {$::cksum!=""} } {1} do_test vacuum-1.5 { execsql { VACUUM; } cksum vacuum4.txt } $cksum do_test vacuum-1.6 { expr {[file size test.db]<$::size1} } {1} do_test vacuum-2.1 { catchsql { BEGIN; VACUUM; COMMIT; } } {1 {cannot VACUUM from within a transaction}} execsql COMMIT # finish_test |