Make VACUUM work even if multiple processes have the database open at once. (CVS 933)
FossilOrigin-Name: caa960289f3d1f5e8f35a94e9e4321996c211ed2
This commit is contained in:
parent
fd9903de51
commit
f7c5753174
26
manifest
26
manifest
@ -1,5 +1,5 @@
|
|||||||
C Explicit\scasts\sto\ssquelch\sbogus\swarnings\sfor\svc++.\s\sTicket\s#194.\s(CVS\s932)
|
C Make\sVACUUM\swork\seven\sif\smultiple\sprocesses\shave\sthe\sdatabase\sopen\sat\sonce.\s(CVS\s933)
|
||||||
D 2003-04-25T03:13:25
|
D 2003-04-25T13:22:52
|
||||||
F Makefile.in 004acec253ecdde985c8ecd5b7c9accdb210378f
|
F Makefile.in 004acec253ecdde985c8ecd5b7c9accdb210378f
|
||||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||||
@ -21,9 +21,9 @@ F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
|
|||||||
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2
|
||||||
F src/attach.c 7ebc7487de43e357a64226f8abef81f2669f2183
|
F src/attach.c 7ebc7487de43e357a64226f8abef81f2669f2183
|
||||||
F src/auth.c a4afd27964fb9f661147115790c8ae2ee230ebcc
|
F src/auth.c a4afd27964fb9f661147115790c8ae2ee230ebcc
|
||||||
F src/btree.c 3de765f186a5d07d8764f970ecd07d83ccfdc51d
|
F src/btree.c a9e8aa96c2af6a81e442719d0cbc1a71bb9b3e08
|
||||||
F src/btree.h dc899dd3a10ec9a0c9b51308610d2f53e36b4820
|
F src/btree.h 6488448db856bb92729b1325b932864c9aa163f5
|
||||||
F src/btree_rb.c b427e6f2df7807cd338636259efadb4e43dba669
|
F src/btree_rb.c 8e00e40be264716e1929987878672e55d9e0e76d
|
||||||
F src/build.c d5a26baeffa5bc49b4b7009a7723c6ab7e1b02d9
|
F src/build.c d5a26baeffa5bc49b4b7009a7723c6ab7e1b02d9
|
||||||
F src/copy.c 44b13fd4d2444fb53bff8a5ecee1c5f6f86a8263
|
F src/copy.c 44b13fd4d2444fb53bff8a5ecee1c5f6f86a8263
|
||||||
F src/delete.c 23d33fd8967c6cc492943bbecea93be6491edc6a
|
F src/delete.c 23d33fd8967c6cc492943bbecea93be6491edc6a
|
||||||
@ -35,10 +35,10 @@ F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
|
|||||||
F src/insert.c 19882be1edc4b1629b8f3097e2615164f2c9cecb
|
F src/insert.c 19882be1edc4b1629b8f3097e2615164f2c9cecb
|
||||||
F src/main.c 5e4d4d081d82840a743c57269ca3c32640cefc06
|
F src/main.c 5e4d4d081d82840a743c57269ca3c32640cefc06
|
||||||
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
|
F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
|
||||||
F src/os.c 7274951ed6894f383cb889342267ded07caf339b
|
F src/os.c e56853eaea5dab258ab1ccb77b4743b453516e3a
|
||||||
F src/os.h 9e5bbddff123187295e3d00d49af06192cd1cd49
|
F src/os.h 9e5bbddff123187295e3d00d49af06192cd1cd49
|
||||||
F src/pager.c df4c81350cbd80c1ab48341ae0768ba78d99ad49
|
F src/pager.c 18066f5057500dccc2948c258ea5ffd4139bbf7d
|
||||||
F src/pager.h e3702f7d384921f6cd5ce0b3ed589185433e9f6c
|
F src/pager.h 5da62c83443f26b1792cfd72c96c422f91aadd31
|
||||||
F src/parse.y 15ae47e7dd84304c1c6ae9205558405127977541
|
F src/parse.y 15ae47e7dd84304c1c6ae9205558405127977541
|
||||||
F src/pragma.c 118fe400d71b7fdcc03580d5eab6bb5aa00772a5
|
F src/pragma.c 118fe400d71b7fdcc03580d5eab6bb5aa00772a5
|
||||||
F src/printf.c fc5fdef6e92ad205005263661fe9716f55a49f3e
|
F src/printf.c fc5fdef6e92ad205005263661fe9716f55a49f3e
|
||||||
@ -58,7 +58,7 @@ F src/tokenize.c 067d1a477a94af7712ca74e09aaa6bd0f7299527
|
|||||||
F src/trigger.c e763f4015c96e06b694184ead5754985c1dfdae0
|
F src/trigger.c e763f4015c96e06b694184ead5754985c1dfdae0
|
||||||
F src/update.c b7fa7c427b74aee6db56ecfa09e5e151e6f9fa6a
|
F src/update.c b7fa7c427b74aee6db56ecfa09e5e151e6f9fa6a
|
||||||
F src/util.c 87635cfdfffa056a8d3147719357aa442374f78c
|
F src/util.c 87635cfdfffa056a8d3147719357aa442374f78c
|
||||||
F src/vacuum.c 67199f3d626aed21940b3b428c25979a98fda03d
|
F src/vacuum.c 44420de0f02cc66a673469fee1f33b6d08bb717e
|
||||||
F src/vdbe.c f0868ac926d98395d28c2a29119364ff11b77852
|
F src/vdbe.c f0868ac926d98395d28c2a29119364ff11b77852
|
||||||
F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21
|
F src/vdbe.h 985c24f312d10f9ef8f9a8b8ea62fcdf68e82f21
|
||||||
F src/where.c f632cd30f013163484a4d60c249d36fe31f5be12
|
F src/where.c f632cd30f013163484a4d60c249d36fe31f5be12
|
||||||
@ -125,7 +125,7 @@ F test/trigger3.test 870afef7997a5b86bf3ea893ce0c2e85d6356c72
|
|||||||
F test/trigger4.test 9a5c1406344d743020c2753ae8d6dfe6eb75f818
|
F test/trigger4.test 9a5c1406344d743020c2753ae8d6dfe6eb75f818
|
||||||
F test/unique.test 22a46df72a3e0a3fd1a2d39e96fb59f18448dd5f
|
F test/unique.test 22a46df72a3e0a3fd1a2d39e96fb59f18448dd5f
|
||||||
F test/update.test 198360dfa14e65354dbcc66d5b98d8070780e42b
|
F test/update.test 198360dfa14e65354dbcc66d5b98d8070780e42b
|
||||||
F test/vacuum.test baf8e0c44587322da5669996ffc55daf8cc60266
|
F test/vacuum.test 9262504c37e9d796e3d8d6c1730e878c8fa8787a
|
||||||
F test/version.test 605fd0d7e7d571370c32b12dbf395b58953de246
|
F test/version.test 605fd0d7e7d571370c32b12dbf395b58953de246
|
||||||
F test/view.test d356f445d481c04ffa6036a4c61cb8ba70289f69
|
F test/view.test d356f445d481c04ffa6036a4c61cb8ba70289f69
|
||||||
F test/where.test d719129a052280fe245a2ddcbd09bcc0b8c17ce4
|
F test/where.test d719129a052280fe245a2ddcbd09bcc0b8c17ce4
|
||||||
@ -165,7 +165,7 @@ F www/speed.tcl cb4c10a722614aea76d2c51f32ee43400d5951be
|
|||||||
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
|
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
|
||||||
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
||||||
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
||||||
P 5afb88008fed253e6d1fc0ed5172370b61d3727b
|
P cb808c14bc14e7bd1cfff134ae5206ace451f2df
|
||||||
R f2421cf3a297d027e70ffbccdb3ba489
|
R 304a2370652d1a06037c5b9e50c2e06c
|
||||||
U drh
|
U drh
|
||||||
Z 38db8e55b84708279a57f38314d421c3
|
Z a3c697bfebd34cfeb9979168f63ba185
|
||||||
|
@ -1 +1 @@
|
|||||||
cb808c14bc14e7bd1cfff134ae5206ace451f2df
|
caa960289f3d1f5e8f35a94e9e4321996c211ed2
|
34
src/btree.c
34
src/btree.c
@ -9,7 +9,7 @@
|
|||||||
** May you share freely, never taking more than you give.
|
** May you share freely, never taking more than you give.
|
||||||
**
|
**
|
||||||
*************************************************************************
|
*************************************************************************
|
||||||
** $Id: btree.c,v 1.90 2003/04/25 03:13:25 drh Exp $
|
** $Id: btree.c,v 1.91 2003/04/25 13:22:52 drh Exp $
|
||||||
**
|
**
|
||||||
** This file implements a external (disk-based) database using BTrees.
|
** This file implements a external (disk-based) database using BTrees.
|
||||||
** For a detailed discussion of BTrees, refer to
|
** For a detailed discussion of BTrees, refer to
|
||||||
@ -3490,10 +3490,34 @@ static const char *fileBtreeGetFilename(Btree *pBt){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Change the name of the underlying database file.
|
** Copy the complete content of pBtFrom into pBtTo. A transaction
|
||||||
|
** must be active for both files.
|
||||||
|
**
|
||||||
|
** The size of file pBtFrom may be reduced by this operation.
|
||||||
|
** If anything goes wrong, the transaction on pBtFrom is rolled back.
|
||||||
*/
|
*/
|
||||||
static int fileBtreeChangeFilename(Btree *pBt, const char *zNew){
|
static int fileBtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){
|
||||||
return sqlitepager_rename(pBt->pPager, zNew);
|
int rc = SQLITE_OK;
|
||||||
|
Pgno i, nPage;
|
||||||
|
|
||||||
|
if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR;
|
||||||
|
if( pBtTo->needSwab!=pBtFrom->needSwab ) return SQLITE_ERROR;
|
||||||
|
if( pBtTo->pCursor ) return SQLITE_BUSY;
|
||||||
|
memcpy(pBtTo->page1, pBtFrom->page1, SQLITE_PAGE_SIZE);
|
||||||
|
sqlitepager_overwrite(pBtTo->pPager, 1, pBtFrom->page1);
|
||||||
|
nPage = sqlitepager_pagecount(pBtFrom->pPager);
|
||||||
|
for(i=2; i<=nPage; i++){
|
||||||
|
void *pPage;
|
||||||
|
rc = sqlitepager_get(pBtFrom->pPager, i, &pPage);
|
||||||
|
if( rc ) break;
|
||||||
|
sqlitepager_overwrite(pBtTo->pPager, i, pPage);
|
||||||
|
sqlitepager_unref(pPage);
|
||||||
|
}
|
||||||
|
if( !rc ) rc = sqlitepager_truncate(pBtTo->pPager, nPage);
|
||||||
|
if( rc ){
|
||||||
|
fileBtreeRollback(pBtTo);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3521,7 +3545,7 @@ static BtOps sqliteBtreeOps = {
|
|||||||
fileBtreeUpdateMeta,
|
fileBtreeUpdateMeta,
|
||||||
fileBtreeIntegrityCheck,
|
fileBtreeIntegrityCheck,
|
||||||
fileBtreeGetFilename,
|
fileBtreeGetFilename,
|
||||||
fileBtreeChangeFilename,
|
fileBtreeCopyFile,
|
||||||
#ifdef SQLITE_TEST
|
#ifdef SQLITE_TEST
|
||||||
fileBtreePageDump,
|
fileBtreePageDump,
|
||||||
fileBtreePager
|
fileBtreePager
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
** subsystem. See comments in the source code for a detailed description
|
** subsystem. See comments in the source code for a detailed description
|
||||||
** of what each interface routine does.
|
** of what each interface routine does.
|
||||||
**
|
**
|
||||||
** @(#) $Id: btree.h,v 1.32 2003/04/25 02:43:08 drh Exp $
|
** @(#) $Id: btree.h,v 1.33 2003/04/25 13:22:53 drh Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _BTREE_H_
|
#ifndef _BTREE_H_
|
||||||
#define _BTREE_H_
|
#define _BTREE_H_
|
||||||
@ -56,7 +56,7 @@ struct BtOps {
|
|||||||
int (*UpdateMeta)(Btree*, int*);
|
int (*UpdateMeta)(Btree*, int*);
|
||||||
char *(*IntegrityCheck)(Btree*, int*, int);
|
char *(*IntegrityCheck)(Btree*, int*, int);
|
||||||
const char *(*GetFilename)(Btree*);
|
const char *(*GetFilename)(Btree*);
|
||||||
int (*ChangeFilename)(Btree*, const char *zNew);
|
int (*CopyFile)(Btree*,Btree*);
|
||||||
#ifdef SQLITE_TEST
|
#ifdef SQLITE_TEST
|
||||||
int (*PageDump)(Btree*, int, int);
|
int (*PageDump)(Btree*, int, int);
|
||||||
struct Pager *(*Pager)(Btree*);
|
struct Pager *(*Pager)(Btree*);
|
||||||
@ -141,8 +141,7 @@ int sqliteRBtreeOpen(const char *zFilename, int mode, int nPg, Btree **ppBtree);
|
|||||||
#define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\
|
#define sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot)\
|
||||||
(btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot))
|
(btOps(pBt)->IntegrityCheck(pBt, aRoot, nRoot))
|
||||||
#define sqliteBtreeGetFilename(pBt) (btOps(pBt)->GetFilename(pBt))
|
#define sqliteBtreeGetFilename(pBt) (btOps(pBt)->GetFilename(pBt))
|
||||||
#define sqliteBtreeChangeFilename(pBt, zNew)\
|
#define sqliteBtreeCopyFile(pBt1, pBt2) (btOps(pBt1)->CopyFile(pBt1, pBt2))
|
||||||
(btOps(pBt)->ChangeFilename(pBt, zNew))
|
|
||||||
|
|
||||||
#ifdef SQLITE_TEST
|
#ifdef SQLITE_TEST
|
||||||
#define sqliteBtreePageDump(pBt, pgno, recursive)\
|
#define sqliteBtreePageDump(pBt, pgno, recursive)\
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
** May you share freely, never taking more than you give.
|
** 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 $
|
** $Id: btree_rb.c,v 1.9 2003/04/25 13:22:53 drh Exp $
|
||||||
**
|
**
|
||||||
** This file implements an in-core database using Red-Black balanced
|
** This file implements an in-core database using Red-Black balanced
|
||||||
** binary trees.
|
** binary trees.
|
||||||
@ -1331,10 +1331,10 @@ static const char *memBtreeGetFilename(Btree *pBt){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Change the name of the underlying database file.
|
** The copy file function is not implemented for the in-memory database
|
||||||
*/
|
*/
|
||||||
static int memBtreeChangeFilename(Btree *pBt, const char *zNew){
|
static int memBtreeCopyFile(Btree *pBt, Btree *pBt2){
|
||||||
return SQLITE_OK;
|
return SQLITE_INTERNAL; /* Not implemented */
|
||||||
}
|
}
|
||||||
|
|
||||||
static BtOps sqliteBtreeOps = {
|
static BtOps sqliteBtreeOps = {
|
||||||
@ -1356,7 +1356,7 @@ static BtOps sqliteBtreeOps = {
|
|||||||
memBtreeUpdateMeta,
|
memBtreeUpdateMeta,
|
||||||
memBtreeIntegrityCheck,
|
memBtreeIntegrityCheck,
|
||||||
memBtreeGetFilename,
|
memBtreeGetFilename,
|
||||||
memBtreeChangeFilename,
|
memBtreeCopyFile,
|
||||||
|
|
||||||
#ifdef SQLITE_TEST
|
#ifdef SQLITE_TEST
|
||||||
memBtreePageDump,
|
memBtreePageDump,
|
||||||
|
3
src/os.c
3
src/os.c
@ -282,6 +282,7 @@ int sqliteOsFileExists(const char *zFilename){
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if 0 /* NOT USED */
|
||||||
/*
|
/*
|
||||||
** Change the name of an existing file.
|
** Change the name of an existing file.
|
||||||
*/
|
*/
|
||||||
@ -304,7 +305,7 @@ int sqliteOsFileRename(const char *zOldName, const char *zNewName){
|
|||||||
return SQLITE_ERROR;
|
return SQLITE_ERROR;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
#endif /* NOT USED */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Attempt to open a file for both reading and writing. If that
|
** Attempt to open a file for both reading and writing. If that
|
||||||
|
61
src/pager.c
61
src/pager.c
@ -18,7 +18,7 @@
|
|||||||
** file simultaneously, or one process from reading the database while
|
** file simultaneously, or one process from reading the database while
|
||||||
** another is writing.
|
** another is writing.
|
||||||
**
|
**
|
||||||
** @(#) $Id: pager.c,v 1.81 2003/04/06 20:52:32 drh Exp $
|
** @(#) $Id: pager.c,v 1.82 2003/04/25 13:22:53 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "os.h" /* Must be first to enable large file support */
|
#include "os.h" /* Must be first to enable large file support */
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@ -927,6 +927,28 @@ int sqlitepager_pagecount(Pager *pPager){
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Forward declaration
|
||||||
|
*/
|
||||||
|
static int syncAllPages(Pager*);
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Truncate the file to the number of pages specified.
|
||||||
|
*/
|
||||||
|
int sqlitepager_truncate(Pager *pPager, Pgno nPage){
|
||||||
|
int rc;
|
||||||
|
if( pPager->dbSize<0 ) sqlitepager_pagecount(pPager);
|
||||||
|
if( nPage>=pPager->dbSize ){
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
syncAllPages(pPager);
|
||||||
|
rc = sqliteOsTruncate(&pPager->fd, SQLITE_PAGE_SIZE*(off_t)nPage);
|
||||||
|
if( rc==SQLITE_OK ){
|
||||||
|
pPager->dbSize = nPage;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Shutdown the page cache. Free all memory and close all files.
|
** Shutdown the page cache. Free all memory and close all files.
|
||||||
**
|
**
|
||||||
@ -2037,43 +2059,6 @@ const char *sqlitepager_filename(Pager *pPager){
|
|||||||
return pPager->zFilename;
|
return pPager->zFilename;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
** Rename the database file
|
|
||||||
*/
|
|
||||||
int sqlitepager_rename(Pager *pPager, const char *zNewName){
|
|
||||||
char *zNew;
|
|
||||||
char *zJournal;
|
|
||||||
int nName;
|
|
||||||
int rc;
|
|
||||||
|
|
||||||
nName = strlen(zNewName);
|
|
||||||
zNew = sqliteMalloc( nName*2 + 30 );
|
|
||||||
if( zNew==0 ){
|
|
||||||
return SQLITE_NOMEM;
|
|
||||||
}
|
|
||||||
memcpy(zNew, zNewName, nName+1);
|
|
||||||
zJournal = &zNew[nName+1];
|
|
||||||
memcpy(zJournal, zNew, nName);
|
|
||||||
strcpy(&zJournal[nName], "-journal");
|
|
||||||
if( pPager->journalOpen ){
|
|
||||||
rc = sqliteOsFileRename(pPager->zJournal, zJournal);
|
|
||||||
if( rc ){
|
|
||||||
sqliteFree(zNew);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rc = sqliteOsFileRename(pPager->zFilename, zNew);
|
|
||||||
if( rc ){
|
|
||||||
sqliteFree(zNew);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
if( pPager->zFilename!=(char*)&pPager[1] ){
|
|
||||||
sqliteFree(pPager->zFilename);
|
|
||||||
}
|
|
||||||
pPager->zFilename = zNew;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef SQLITE_TEST
|
#ifdef SQLITE_TEST
|
||||||
/*
|
/*
|
||||||
** Print a listing of all referenced pages and their ref count.
|
** Print a listing of all referenced pages and their ref count.
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
** subsystem. The page cache subsystem reads and writes a file a page
|
** subsystem. The page cache subsystem reads and writes a file a page
|
||||||
** at a time and provides a journal for rollback.
|
** at a time and provides a journal for rollback.
|
||||||
**
|
**
|
||||||
** @(#) $Id: pager.h,v 1.22 2003/04/06 20:44:45 drh Exp $
|
** @(#) $Id: pager.h,v 1.23 2003/04/25 13:22:53 drh Exp $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -61,6 +61,7 @@ int sqlitepager_write(void*);
|
|||||||
int sqlitepager_iswriteable(void*);
|
int sqlitepager_iswriteable(void*);
|
||||||
int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void*);
|
int sqlitepager_overwrite(Pager *pPager, Pgno pgno, void*);
|
||||||
int sqlitepager_pagecount(Pager*);
|
int sqlitepager_pagecount(Pager*);
|
||||||
|
int sqlitepager_truncate(Pager*,Pgno);
|
||||||
int sqlitepager_begin(void*);
|
int sqlitepager_begin(void*);
|
||||||
int sqlitepager_commit(Pager*);
|
int sqlitepager_commit(Pager*);
|
||||||
int sqlitepager_rollback(Pager*);
|
int sqlitepager_rollback(Pager*);
|
||||||
|
71
src/vacuum.c
71
src/vacuum.c
@ -14,7 +14,7 @@
|
|||||||
** Most of the code in this file may be omitted by defining the
|
** Most of the code in this file may be omitted by defining the
|
||||||
** SQLITE_OMIT_VACUUM macro.
|
** SQLITE_OMIT_VACUUM macro.
|
||||||
**
|
**
|
||||||
** $Id: vacuum.c,v 1.4 2003/04/25 02:43:08 drh Exp $
|
** $Id: vacuum.c,v 1.5 2003/04/25 13:22:53 drh Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@ -209,14 +209,13 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){
|
|||||||
const char *zFilename; /* full pathname of the database file */
|
const char *zFilename; /* full pathname of the database file */
|
||||||
int nFilename; /* number of characters in zFilename[] */
|
int nFilename; /* number of characters in zFilename[] */
|
||||||
char *zTemp = 0; /* a temporary file in same directory as zFilename */
|
char *zTemp = 0; /* a temporary file in same directory as zFilename */
|
||||||
char *zTemp2; /* Another temp file in the same directory */
|
|
||||||
sqlite *dbNew = 0; /* The new vacuumed database */
|
sqlite *dbNew = 0; /* The new vacuumed database */
|
||||||
sqlite *db; /* The original database */
|
sqlite *db; /* The original database */
|
||||||
int rc, i;
|
int rc = SQLITE_OK; /* Return code from service routines */
|
||||||
char *zErrMsg = 0;
|
int i; /* Loop counter */
|
||||||
char *zSql = 0;
|
char *zErrMsg = 0; /* Error messages stored here */
|
||||||
int safety = 0;
|
int safety = 0; /* TRUE if safety is off */
|
||||||
vacuumStruct sVac;
|
vacuumStruct sVac; /* Information passed to callbacks */
|
||||||
|
|
||||||
/* These are all of the pragmas that need to be transferred over
|
/* These are all of the pragmas that need to be transferred over
|
||||||
** to the new database */
|
** to the new database */
|
||||||
@ -248,20 +247,16 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
nFilename = strlen(zFilename);
|
nFilename = strlen(zFilename);
|
||||||
zTemp = sqliteMalloc( 2*(nFilename+40) );
|
zTemp = sqliteMalloc( nFilename+100 );
|
||||||
if( zTemp==0 ) return;
|
if( zTemp==0 ) return;
|
||||||
zTemp2 = &zTemp[nFilename+40];
|
|
||||||
strcpy(zTemp, zFilename);
|
strcpy(zTemp, zFilename);
|
||||||
strcpy(zTemp2, zFilename);
|
|
||||||
for(i=0; i<10; i++){
|
for(i=0; i<10; i++){
|
||||||
zTemp[nFilename] = '-';
|
zTemp[nFilename] = '-';
|
||||||
randomName(&zTemp[nFilename+1]);
|
randomName(&zTemp[nFilename+1]);
|
||||||
zTemp2[nFilename] = '-';
|
if( !sqliteOsFileExists(zTemp) ) break;
|
||||||
randomName(&zTemp2[nFilename+1]);
|
|
||||||
if( !sqliteOsFileExists(zTemp) && !sqliteOsFileExists(zTemp2) ) break;
|
|
||||||
}
|
}
|
||||||
if( i>=10 ){
|
if( i>=10 ){
|
||||||
sqliteErrorMsg(pParse, "unable to create a temporary database files "
|
sqliteErrorMsg(pParse, "unable to create a temporary database file "
|
||||||
"in the same directory as the original database");
|
"in the same directory as the original database");
|
||||||
goto end_of_vacuum;
|
goto end_of_vacuum;
|
||||||
}
|
}
|
||||||
@ -279,7 +274,9 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){
|
|||||||
}
|
}
|
||||||
safety = 1;
|
safety = 1;
|
||||||
if( execsql(pParse, db, "BEGIN") ) goto end_of_vacuum;
|
if( execsql(pParse, db, "BEGIN") ) goto end_of_vacuum;
|
||||||
if( execsql(pParse, dbNew, "BEGIN") ) goto end_of_vacuum;
|
if( execsql(pParse, dbNew, "PRAGMA synchronous=off; BEGIN") ){
|
||||||
|
goto end_of_vacuum;
|
||||||
|
}
|
||||||
sVac.dbOld = db;
|
sVac.dbOld = db;
|
||||||
sVac.dbNew = dbNew;
|
sVac.dbNew = dbNew;
|
||||||
sVac.pParse = pParse;
|
sVac.pParse = pParse;
|
||||||
@ -291,55 +288,33 @@ void sqliteVacuum(Parse *pParse, Token *pTableName){
|
|||||||
rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg);
|
rc = sqlite_exec(db, zBuf, vacuumCallback3, &sVac, &zErrMsg);
|
||||||
if( rc ) goto vacuum_error;
|
if( rc ) goto vacuum_error;
|
||||||
}
|
}
|
||||||
rc = sqlite_exec(db, "SELECT type, name, sql FROM sqlite_master "
|
if( rc==SQLITE_OK ){
|
||||||
"WHERE sql NOT NULL", vacuumCallback1, &sVac, &zErrMsg);
|
rc = sqlite_exec(db, "SELECT type, name, sql FROM sqlite_master "
|
||||||
if( rc ) goto vacuum_error;
|
"WHERE sql NOT NULL", vacuumCallback1, &sVac, &zErrMsg);
|
||||||
|
}
|
||||||
if( sqliteOsFileRename(zFilename, zTemp2) ){
|
if( rc ){
|
||||||
sqliteErrorMsg(pParse, "unable to rename database file");
|
if( pParse->zErrMsg==0 ){
|
||||||
|
sqliteErrorMsg(pParse, "unable to vacuum database - %s", zErrMsg);
|
||||||
|
}
|
||||||
goto end_of_vacuum;
|
goto end_of_vacuum;
|
||||||
}
|
}
|
||||||
if( sqliteOsFileRename(zTemp, zFilename) ){
|
rc = sqliteBtreeCopyFile(db->aDb[0].pBt, dbNew->aDb[0].pBt);
|
||||||
sqliteOsFileRename(zTemp2, zFilename);
|
sqlite_exec(db, "COMMIT", 0, 0, 0);
|
||||||
sqliteErrorMsg(pParse, "unable to rename database file");
|
|
||||||
goto end_of_vacuum;
|
|
||||||
}
|
|
||||||
if( execsql(pParse, dbNew, "COMMIT;") ){
|
|
||||||
sqliteOsDelete(zFilename);
|
|
||||||
sqliteOsFileRename(zTemp2, zFilename);
|
|
||||||
goto end_of_vacuum;
|
|
||||||
}
|
|
||||||
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);
|
sqliteResetInternalSchema(db, 0);
|
||||||
|
|
||||||
end_of_vacuum:
|
end_of_vacuum:
|
||||||
sqlite_exec(db, "COMMIT", 0, 0, 0);
|
sqlite_exec(db, "COMMIT", 0, 0, 0);
|
||||||
if( safety) {
|
if( safety ) {
|
||||||
sqliteSafetyOn(db);
|
sqliteSafetyOn(db);
|
||||||
}
|
}
|
||||||
if( dbNew ) sqlite_close(dbNew);
|
if( dbNew ) sqlite_close(dbNew);
|
||||||
sqliteOsDelete(zTemp);
|
sqliteOsDelete(zTemp);
|
||||||
sqliteFree(zTemp);
|
sqliteFree(zTemp);
|
||||||
sqliteFree(zSql);
|
|
||||||
sqliteFree(sVac.s1.z);
|
sqliteFree(sVac.s1.z);
|
||||||
sqliteFree(sVac.s2.z);
|
sqliteFree(sVac.s2.z);
|
||||||
if( zErrMsg ) sqlite_freemem(zErrMsg);
|
if( zErrMsg ) sqlite_freemem(zErrMsg);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
vacuum_error:
|
vacuum_error:
|
||||||
if( pParse->zErrMsg==0 ){
|
|
||||||
sqliteErrorMsg(pParse, "unable to vacuum database - %s", zErrMsg);
|
|
||||||
}
|
|
||||||
goto end_of_vacuum;
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -11,23 +11,22 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is testing the VACUUM statement.
|
# focus of this file is testing the VACUUM statement.
|
||||||
#
|
#
|
||||||
# $Id: vacuum.test,v 1.8 2003/04/25 02:43:08 drh Exp $
|
# $Id: vacuum.test,v 1.9 2003/04/25 13:22:53 drh Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
|
|
||||||
proc cksum {filename} {
|
proc cksum {{db db}} {
|
||||||
set txt [db eval {SELECT name, type, sql FROM sqlite_master}]\n
|
set txt [$db eval {SELECT name, type, sql FROM sqlite_master}]\n
|
||||||
foreach tbl [db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
|
foreach tbl [$db eval {SELECT name FROM sqlite_master WHERE type='table'}] {
|
||||||
append txt [db eval "SELECT * FROM $tbl"]\n
|
append txt [$db eval "SELECT * FROM $tbl"]\n
|
||||||
}
|
}
|
||||||
foreach prag {default_synchronous default_cache_size} {
|
foreach prag {default_synchronous default_cache_size} {
|
||||||
append txt $prag-[db eval "PRAGMA $prag"]\n
|
append txt $prag-[$db eval "PRAGMA $prag"]\n
|
||||||
}
|
}
|
||||||
# set fd [open $filename w]
|
set cksum [string length $txt]-[md5 $txt]
|
||||||
# puts $fd $txt
|
puts $cksum-[file size test.db]
|
||||||
# close $fd
|
return $cksum
|
||||||
return [string length $txt]-[md5 $txt]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
do_test vacuum-1.1 {
|
do_test vacuum-1.1 {
|
||||||
@ -49,14 +48,14 @@ do_test vacuum-1.1 {
|
|||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
}
|
}
|
||||||
set ::size1 [file size test.db]
|
set ::size1 [file size test.db]
|
||||||
set ::cksum [cksum vacuum1.txt]
|
set ::cksum [cksum]
|
||||||
expr {$::cksum!=""}
|
expr {$::cksum!=""}
|
||||||
} {1}
|
} {1}
|
||||||
do_test vacuum-1.2 {
|
do_test vacuum-1.2 {
|
||||||
execsql {
|
execsql {
|
||||||
VACUUM;
|
VACUUM;
|
||||||
}
|
}
|
||||||
cksum vacuum2.txt
|
cksum
|
||||||
} $cksum
|
} $cksum
|
||||||
do_test vacuum-1.3 {
|
do_test vacuum-1.3 {
|
||||||
expr {[file size test.db]<$::size1}
|
expr {[file size test.db]<$::size1}
|
||||||
@ -74,14 +73,14 @@ do_test vacuum-1.4 {
|
|||||||
DROP TABLE t2;
|
DROP TABLE t2;
|
||||||
}
|
}
|
||||||
set ::size1 [file size test.db]
|
set ::size1 [file size test.db]
|
||||||
set ::cksum [cksum vacuum3.txt]
|
set ::cksum [cksum]
|
||||||
expr {$::cksum!=""}
|
expr {$::cksum!=""}
|
||||||
} {1}
|
} {1}
|
||||||
do_test vacuum-1.5 {
|
do_test vacuum-1.5 {
|
||||||
execsql {
|
execsql {
|
||||||
VACUUM;
|
VACUUM;
|
||||||
}
|
}
|
||||||
cksum vacuum4.txt
|
cksum
|
||||||
} $cksum
|
} $cksum
|
||||||
do_test vacuum-1.6 {
|
do_test vacuum-1.6 {
|
||||||
expr {[file size test.db]<$::size1}
|
expr {[file size test.db]<$::size1}
|
||||||
@ -94,6 +93,34 @@ do_test vacuum-2.1 {
|
|||||||
COMMIT;
|
COMMIT;
|
||||||
}
|
}
|
||||||
} {1 {cannot VACUUM from within a transaction}}
|
} {1 {cannot VACUUM from within a transaction}}
|
||||||
execsql COMMIT
|
catch {db eval COMMIT}
|
||||||
|
do_test vacuum-2.2 {
|
||||||
|
sqlite db2 test.db
|
||||||
|
execsql {
|
||||||
|
BEGIN;
|
||||||
|
CREATE TABLE t4 AS SELECT * FROM t1;
|
||||||
|
CREATE TABLE t5 AS SELECT * FROM t1;
|
||||||
|
COMMIT;
|
||||||
|
DROP TABLE t4;
|
||||||
|
DROP TABLE t5;
|
||||||
|
} db2
|
||||||
|
set ::cksum [cksum db2]
|
||||||
|
catchsql {
|
||||||
|
VACUUM
|
||||||
|
}
|
||||||
|
} {1 {database schema has changed}}
|
||||||
|
do_test vacuum-2.3 {
|
||||||
|
execsql {
|
||||||
|
VACUUM;
|
||||||
|
}
|
||||||
|
cksum
|
||||||
|
} $cksum
|
||||||
|
do_test vacuum-2.4 {
|
||||||
|
catch {db2 eval {SELECT count(*) FROM sqlite_master}}
|
||||||
|
cksum db2
|
||||||
|
} $cksum
|
||||||
|
|
||||||
|
|
||||||
|
catch {db2 close}
|
||||||
|
|
||||||
# finish_test
|
# finish_test
|
||||||
|
Loading…
Reference in New Issue
Block a user