mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Support root-page allocation/deallocation in auto-vacuum databases. Still a few problems. (CVS 2054)
FossilOrigin-Name: 1da361fae82d420be63c53f8e3efaccac24f348a
This commit is contained in:
28
manifest
28
manifest
@@ -1,5 +1,5 @@
|
|||||||
C All\stests\spass\seven\sif\sOMIT_TRIGGER\sis\sdefined.\s(CVS\s2053)
|
C Support\sroot-page\sallocation/deallocation\sin\sauto-vacuum\sdatabases.\sStill\sa\sfew\sproblems.\s(CVS\s2054)
|
||||||
D 2004-11-04T04:42:28
|
D 2004-11-04T14:30:05
|
||||||
F Makefile.in c4d2416860f472a1e3393714d0372074197565df
|
F Makefile.in c4d2416860f472a1e3393714d0372074197565df
|
||||||
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
||||||
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
|
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
|
||||||
@@ -29,9 +29,9 @@ F sqlite3.def dbaeb20c153e1d366e8f421b55a573f5dfc00863
|
|||||||
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
||||||
F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689
|
F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689
|
||||||
F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea
|
F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea
|
||||||
F src/btree.c 93163198e6fb666b92c893fba5edb3ef6f335c0f
|
F src/btree.c a3e45d54eb1a81698f609693c22df382dfbf9151
|
||||||
F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029
|
F src/btree.h 3166388fa58c5594d8064d38b43440d79da38fb6
|
||||||
F src/build.c bb896c5f85ab749d17ae5d730235134c12c08033
|
F src/build.c 89d1ace10837e61d11cf9818750d8782369ac3f5
|
||||||
F src/date.c 34bdb0082db7ec2a83ef00063f7b44e61ee19dad
|
F src/date.c 34bdb0082db7ec2a83ef00063f7b44e61ee19dad
|
||||||
F src/delete.c 52980e594e69e80374fb928fe611d5f75ca4e390
|
F src/delete.c 52980e594e69e80374fb928fe611d5f75ca4e390
|
||||||
F src/expr.c 3a43e508a3dc213703808bbcbb17633b88b57d17
|
F src/expr.c 3a43e508a3dc213703808bbcbb17633b88b57d17
|
||||||
@@ -52,7 +52,7 @@ F src/os_unix.c 5824b22ba41fe9d514ef9169aac1b5fde73af229
|
|||||||
F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
|
F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
|
||||||
F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb
|
F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb
|
||||||
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||||
F src/pager.c 9ce238f9540eb56b21fef085dc038dffca75835b
|
F src/pager.c a43e2a392be51966129e9afb18b81551c9f222b8
|
||||||
F src/pager.h cbe4ba356d9dd3f30260f322b3dc77408164df14
|
F src/pager.h cbe4ba356d9dd3f30260f322b3dc77408164df14
|
||||||
F src/parse.y 4a27450611ed2b8c359078e04daf93c50b1d22dd
|
F src/parse.y 4a27450611ed2b8c359078e04daf93c50b1d22dd
|
||||||
F src/pragma.c 44e192eb5928157bdb015926f858a7c6e3ef6c98
|
F src/pragma.c 44e192eb5928157bdb015926f858a7c6e3ef6c98
|
||||||
@@ -61,12 +61,12 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
|||||||
F src/select.c 156990c636102bb6b8de85e7ff3396a62568476b
|
F src/select.c 156990c636102bb6b8de85e7ff3396a62568476b
|
||||||
F src/shell.c 55adda3cf3c1cc2f6c1919aac17b2318f9c2a96f
|
F src/shell.c 55adda3cf3c1cc2f6c1919aac17b2318f9c2a96f
|
||||||
F src/sqlite.h.in 4f97b5907acfd2a5068cb0cec9d5178816734db7
|
F src/sqlite.h.in 4f97b5907acfd2a5068cb0cec9d5178816734db7
|
||||||
F src/sqliteInt.h 84d5ca7b02793697641a74fb125fcee3995ea2ff
|
F src/sqliteInt.h 8b93c9d7b7343b9013ffb73cbd2cb6ea4f546c62
|
||||||
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
|
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
|
||||||
F src/tclsqlite.c 0302e3f42f015d132d1291f3388c06e86c24a008
|
F src/tclsqlite.c 0302e3f42f015d132d1291f3388c06e86c24a008
|
||||||
F src/test1.c df1d1ca2c40cafefb9a29860f072c4d0fee1a7b5
|
F src/test1.c df1d1ca2c40cafefb9a29860f072c4d0fee1a7b5
|
||||||
F src/test2.c b11fa244fff02190707dd0879987c37c75e61fc8
|
F src/test2.c b11fa244fff02190707dd0879987c37c75e61fc8
|
||||||
F src/test3.c f423597e220b3d446a65c9cc0c49cb4eb00c0215
|
F src/test3.c b6aece10ee51579d0f75d09137b3c94c80b3c278
|
||||||
F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
|
F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
|
||||||
F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1
|
F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1
|
||||||
F src/tokenize.c bf9de9689b3bb813d65784bf54472804bf9595e6
|
F src/tokenize.c bf9de9689b3bb813d65784bf54472804bf9595e6
|
||||||
@@ -75,7 +75,7 @@ F src/update.c 7b17b281d600bf3e220b3c5718e0883442dee722
|
|||||||
F src/utf.c f4f83acd73389090e32d6589d307fc55d794c7ed
|
F src/utf.c f4f83acd73389090e32d6589d307fc55d794c7ed
|
||||||
F src/util.c 005fdf2d008f3429d081766ad6098fdd86d8d8e6
|
F src/util.c 005fdf2d008f3429d081766ad6098fdd86d8d8e6
|
||||||
F src/vacuum.c ecb4a2c6f1ac5cc9b394dc64d3bb14ca650c4f60
|
F src/vacuum.c ecb4a2c6f1ac5cc9b394dc64d3bb14ca650c4f60
|
||||||
F src/vdbe.c a156e1a2f324e5e11d82af3fbbf41df7a174c860
|
F src/vdbe.c cf7eb35b5a649c11345c5f85ad7b1511253431cc
|
||||||
F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181
|
F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181
|
||||||
F src/vdbeInt.h 6017100adff362b8dfa37a69e3f1431f084bfa5b
|
F src/vdbeInt.h 6017100adff362b8dfa37a69e3f1431f084bfa5b
|
||||||
F src/vdbeapi.c 3965bf4678ae32c05f73550c1b5be3268f9f3006
|
F src/vdbeapi.c 3965bf4678ae32c05f73550c1b5be3268f9f3006
|
||||||
@@ -87,7 +87,7 @@ F test/attach.test ff7fc16b4518a448fed47dfb3694bf57f522d552
|
|||||||
F test/attach2.test f7795123d3051ace1672b6d23973da6435de3745
|
F test/attach2.test f7795123d3051ace1672b6d23973da6435de3745
|
||||||
F test/attach3.test 742c932d7130e0e699a5d9f265cb831e0a824633
|
F test/attach3.test 742c932d7130e0e699a5d9f265cb831e0a824633
|
||||||
F test/auth.test 1cc252d9e7b3bdc1314199cbf3a0d3c5ed026c21
|
F test/auth.test 1cc252d9e7b3bdc1314199cbf3a0d3c5ed026c21
|
||||||
F test/autovacuum.test 9211914801ad35ad8f0fc15711b12461850ef2ac
|
F test/autovacuum.test a5b11269daac313bea6694b04473fdd0e16e439a
|
||||||
F test/bigfile.test d3744a8821ce9abb8697f2826a3e3d22b719e89f
|
F test/bigfile.test d3744a8821ce9abb8697f2826a3e3d22b719e89f
|
||||||
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
F test/bigrow.test f0aeb7573dcb8caaafea76454be3ade29b7fc747
|
||||||
F test/bind.test fa74f98417cd313f28272acff832a8a7d04a0916
|
F test/bind.test fa74f98417cd313f28272acff832a8a7d04a0916
|
||||||
@@ -252,7 +252,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
|
|||||||
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
||||||
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
|
||||||
F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
|
F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
|
||||||
P da045bd183335a112f9a6c805c12efe12d0a25ca
|
P c33b3a613751057e8a46fdcd428b8448329d414d
|
||||||
R 3020d6f48bce04fcef7f5133e21d3db2
|
R 904dc0805c4ad385b004eaf63c77188e
|
||||||
U drh
|
U danielk1977
|
||||||
Z 625b1d515abab0cebf7c5f6337f4ff8c
|
Z d7dc31bf4e5f4e3f4969266ba871dca0
|
||||||
|
@@ -1 +1 @@
|
|||||||
c33b3a613751057e8a46fdcd428b8448329d414d
|
1da361fae82d420be63c53f8e3efaccac24f348a
|
86
src/btree.c
86
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.203 2004/11/04 02:57:34 danielk1977 Exp $
|
** $Id: btree.c,v 1.204 2004/11/04 14:30:05 danielk1977 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
|
||||||
@@ -1624,8 +1624,8 @@ static int relocatePage(
|
|||||||
Pager *pPager = pBt->pPager;
|
Pager *pPager = pBt->pPager;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
assert( eType==PTRMAP_OVERFLOW2
|
assert( eType==PTRMAP_OVERFLOW2 || eType==PTRMAP_OVERFLOW1 ||
|
||||||
|| eType==PTRMAP_OVERFLOW1 || eType==PTRMAP_BTREE );
|
eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE );
|
||||||
|
|
||||||
/* Move page iDbPage from it's current location to page number iFreePage */
|
/* Move page iDbPage from it's current location to page number iFreePage */
|
||||||
TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
|
TRACE(("AUTOVACUUM: Moving %d to free page %d (ptr page %d type %d)\n",
|
||||||
@@ -1644,7 +1644,7 @@ static int relocatePage(
|
|||||||
** pointer to a subsequent overflow page. If this is the case, then
|
** pointer to a subsequent overflow page. If this is the case, then
|
||||||
** the pointer map needs to be updated for the subsequent overflow page.
|
** the pointer map needs to be updated for the subsequent overflow page.
|
||||||
*/
|
*/
|
||||||
if( eType==PTRMAP_BTREE ){
|
if( eType==PTRMAP_BTREE || eType==PTRMAP_ROOTPAGE ){
|
||||||
rc = setChildPtrmaps(pDbPage);
|
rc = setChildPtrmaps(pDbPage);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1664,6 +1664,7 @@ static int relocatePage(
|
|||||||
** that it points at iFreePage. Also fix the pointer map entry for
|
** that it points at iFreePage. Also fix the pointer map entry for
|
||||||
** iPtrPage.
|
** iPtrPage.
|
||||||
*/
|
*/
|
||||||
|
if( eType!=PTRMAP_ROOTPAGE ){
|
||||||
rc = getPage(pBt, iPtrPage, &pPtrPage);
|
rc = getPage(pBt, iPtrPage, &pPtrPage);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
return rc;
|
return rc;
|
||||||
@@ -1676,6 +1677,7 @@ static int relocatePage(
|
|||||||
modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
|
modifyPagePointer(pPtrPage, iDbPage, iFreePage, eType);
|
||||||
rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);
|
rc = ptrmapPut(pBt, iFreePage, eType, iPtrPage);
|
||||||
releasePage(pPtrPage);
|
releasePage(pPtrPage);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1723,6 +1725,7 @@ static int autoVacuumCommit(Btree *pBt){
|
|||||||
|
|
||||||
TRACE(("AUTOVACUUM: Begin (db size %d->%d)\n", origSize, finSize));
|
TRACE(("AUTOVACUUM: Begin (db size %d->%d)\n", origSize, finSize));
|
||||||
|
|
||||||
|
#if 0
|
||||||
/* Note: This is temporary code for use during development of auto-vacuum.
|
/* Note: This is temporary code for use during development of auto-vacuum.
|
||||||
**
|
**
|
||||||
** Inspect the pointer map to make sure there are no root pages with a
|
** Inspect the pointer map to make sure there are no root pages with a
|
||||||
@@ -1738,6 +1741,7 @@ static int autoVacuumCommit(Btree *pBt){
|
|||||||
return SQLITE_OK;
|
return SQLITE_OK;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Variable 'finSize' will be the size of the file in pages after
|
/* Variable 'finSize' will be the size of the file in pages after
|
||||||
** the auto-vacuum has completed (the current file size minus the number
|
** the auto-vacuum has completed (the current file size minus the number
|
||||||
@@ -4287,6 +4291,7 @@ int sqlite3BtreeCreateTable(Btree *pBt, int *piTable, int flags){
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
|
rc = ptrmapGet(pBt, pgnoRoot, &eType, &iPtrPage);
|
||||||
|
assert( eType!=PTRMAP_ROOTPAGE );
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
releasePage(pRoot);
|
releasePage(pRoot);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -4408,29 +4413,90 @@ int sqlite3BtreeClearTable(Btree *pBt, int iTable){
|
|||||||
** This routine will fail with SQLITE_LOCKED if there are any open
|
** This routine will fail with SQLITE_LOCKED if there are any open
|
||||||
** cursors on the table.
|
** cursors on the table.
|
||||||
*/
|
*/
|
||||||
int sqlite3BtreeDropTable(Btree *pBt, int iTable){
|
int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){
|
||||||
int rc;
|
int rc;
|
||||||
MemPage *pPage;
|
MemPage *pPage = 0;
|
||||||
BtCursor *pCur;
|
BtCursor *pCur;
|
||||||
/* TODO: Disallow schema modifications if there are open cursors */
|
|
||||||
if( pBt->inTrans!=TRANS_WRITE ){
|
if( pBt->inTrans!=TRANS_WRITE ){
|
||||||
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
return pBt->readOnly ? SQLITE_READONLY : SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* TODO: Disallow schema modifications if there are open cursors */
|
||||||
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
|
for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
|
||||||
if( pCur->pgnoRoot==(Pgno)iTable ){
|
if( pCur->pgnoRoot==(Pgno)iTable ){
|
||||||
return SQLITE_LOCKED; /* Cannot drop a table that has a cursor */
|
return SQLITE_LOCKED; /* Cannot drop a table that has a cursor */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = getPage(pBt, (Pgno)iTable, &pPage);
|
rc = getPage(pBt, (Pgno)iTable, &pPage);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
rc = sqlite3BtreeClearTable(pBt, iTable);
|
rc = sqlite3BtreeClearTable(pBt, iTable);
|
||||||
if( rc ) return rc;
|
if( rc ) return rc;
|
||||||
|
|
||||||
|
if( piMoved ) *piMoved = 0;
|
||||||
|
|
||||||
if( iTable>1 ){
|
if( iTable>1 ){
|
||||||
|
#ifdef SQLITE_OMIT_AUTOVACUUM
|
||||||
rc = freePage(pPage);
|
rc = freePage(pPage);
|
||||||
}else{
|
|
||||||
zeroPage(pPage, PTF_INTKEY|PTF_LEAF );
|
|
||||||
}
|
|
||||||
releasePage(pPage);
|
releasePage(pPage);
|
||||||
|
#else
|
||||||
|
if( pBt->autoVacuum ){
|
||||||
|
Pgno maxRootPgno;
|
||||||
|
rc = sqlite3BtreeGetMeta(pBt, 4, &maxRootPgno);
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
releasePage(pPage);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( iTable==maxRootPgno ){
|
||||||
|
/* If the table being dropped is the table with the largest root-page
|
||||||
|
** number in the database, put the root page on the free list.
|
||||||
|
*/
|
||||||
|
rc = freePage(pPage);
|
||||||
|
releasePage(pPage);
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
/* The table being dropped does not have the largest root-page
|
||||||
|
** number in the database. So move the page that does into the
|
||||||
|
** gap left by the deleted root-page.
|
||||||
|
*/
|
||||||
|
MemPage *pMove;
|
||||||
|
releasePage(pPage);
|
||||||
|
rc = getPage(pBt, maxRootPgno, &pMove);
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = relocatePage(pBt, pMove, PTRMAP_ROOTPAGE, 0, iTable);
|
||||||
|
releasePage(pMove);
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = getPage(pBt, maxRootPgno, &pMove);
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
rc = freePage(pMove);
|
||||||
|
releasePage(pMove);
|
||||||
|
if( rc!=SQLITE_OK ){
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
*piMoved = maxRootPgno;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = sqlite3BtreeUpdateMeta(pBt, 4, maxRootPgno-1);
|
||||||
|
}else{
|
||||||
|
rc = freePage(pPage);
|
||||||
|
releasePage(pPage);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}else{
|
||||||
|
/* If sqlite3BtreeDropTable was called on page 1. */
|
||||||
|
zeroPage(pPage, PTF_INTKEY|PTF_LEAF );
|
||||||
|
releasePage(pPage);
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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.58 2004/07/23 00:01:39 drh Exp $
|
** @(#) $Id: btree.h,v 1.59 2004/11/04 14:30:05 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _BTREE_H_
|
#ifndef _BTREE_H_
|
||||||
#define _BTREE_H_
|
#define _BTREE_H_
|
||||||
@@ -72,7 +72,7 @@ int sqlite3BtreeCopyFile(Btree *, Btree *);
|
|||||||
#define BTREE_ZERODATA 2 /* Table has keys only - no data */
|
#define BTREE_ZERODATA 2 /* Table has keys only - no data */
|
||||||
#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */
|
#define BTREE_LEAFDATA 4 /* Data stored in leaves only. Implies INTKEY */
|
||||||
|
|
||||||
int sqlite3BtreeDropTable(Btree*, int);
|
int sqlite3BtreeDropTable(Btree*, int, int*);
|
||||||
int sqlite3BtreeClearTable(Btree*, int);
|
int sqlite3BtreeClearTable(Btree*, int);
|
||||||
int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
|
int sqlite3BtreeGetMeta(Btree*, int idx, u32 *pValue);
|
||||||
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
int sqlite3BtreeUpdateMeta(Btree*, int idx, u32 value);
|
||||||
|
147
src/build.c
147
src/build.c
@@ -23,7 +23,7 @@
|
|||||||
** ROLLBACK
|
** ROLLBACK
|
||||||
** PRAGMA
|
** PRAGMA
|
||||||
**
|
**
|
||||||
** $Id: build.c,v 1.258 2004/10/31 02:22:49 drh Exp $
|
** $Id: build.c,v 1.259 2004/11/04 14:30:05 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -1554,6 +1554,141 @@ static void sqliteViewResetAll(sqlite3 *db, int idx){
|
|||||||
# define sqliteViewResetAll(A,B)
|
# define sqliteViewResetAll(A,B)
|
||||||
#endif /* SQLITE_OMIT_VIEW */
|
#endif /* SQLITE_OMIT_VIEW */
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This function is called by the VDBE to adjust the internal schema
|
||||||
|
** used by SQLite when the btree layer moves a table root page. The
|
||||||
|
** root-page of a table or index in database iDb has changed from iFrom
|
||||||
|
** to iTo.
|
||||||
|
*/
|
||||||
|
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||||
|
void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
|
||||||
|
HashElem *pElem;
|
||||||
|
|
||||||
|
for(pElem=sqliteHashFirst(&pDb->tblHash); pElem; pElem=sqliteHashNext(pElem)){
|
||||||
|
Table *pTab = sqliteHashData(pElem);
|
||||||
|
if( pTab->tnum==iFrom ){
|
||||||
|
pTab->tnum = iTo;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(pElem=sqliteHashFirst(&pDb->idxHash); pElem; pElem=sqliteHashNext(pElem)){
|
||||||
|
Index *pIdx = sqliteHashData(pElem);
|
||||||
|
if( pIdx->tnum==iFrom ){
|
||||||
|
pIdx->tnum = iTo;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Write code to erase the table with root-page iTable from database iDb.
|
||||||
|
** Also write code to modify the sqlite_master table and internal schema
|
||||||
|
** if a root-page of another table is moved by the btree-layer whilst
|
||||||
|
** erasing iTable (this can happen with an auto-vacuum database).
|
||||||
|
*/
|
||||||
|
static void destroyRootPage(Vdbe *v, int iTable, int iDb){
|
||||||
|
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||||
|
int base;
|
||||||
|
#endif
|
||||||
|
sqlite3VdbeAddOp(v, OP_Destroy, iTable, iDb);
|
||||||
|
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||||
|
/* If SQLITE_OMIT_AUTOVACUUM is not defined, then OP_Destroy pushes
|
||||||
|
** an integer onto the stack. If this integer is non-zero, then it is
|
||||||
|
** the root page number of a table moved to location iTable. The
|
||||||
|
** following writes VDBE code to modify the sqlite_master table to
|
||||||
|
** reflect this. It is assumed that cursor number 0 is a write-cursor
|
||||||
|
** opened on the sqlite_master table.
|
||||||
|
*/
|
||||||
|
static const VdbeOpList updateMaster[] = {
|
||||||
|
/* If the Op_Destroy pushed a 0 onto the stack, then skip the following
|
||||||
|
** code. sqlite_master does not need updating in this case.
|
||||||
|
*/
|
||||||
|
{ OP_Dup, 0, 0, 0},
|
||||||
|
{ OP_Integer, 0, 0, 0},
|
||||||
|
{ OP_Eq, 0, ADDR(17), 0},
|
||||||
|
|
||||||
|
/* Search for the sqlite_master row containing root-page iTable. */
|
||||||
|
{ OP_Rewind, 0, ADDR(8), 0},
|
||||||
|
{ OP_Dup, 0, 0, 0}, /* 4 */
|
||||||
|
{ OP_Column, 0, 3, 0}, /* 5 */
|
||||||
|
{ OP_Eq, 0, ADDR(9), 0},
|
||||||
|
{ OP_Next, 0, ADDR(4), 0},
|
||||||
|
{ OP_Halt, SQLITE_CORRUPT, OE_Fail, 0}, /* 8 */
|
||||||
|
{ OP_Recno, 0, 0, 0}, /* 9 */
|
||||||
|
|
||||||
|
/* Cursor 0 now points at the row that will be updated. The top of
|
||||||
|
** the stack is the rowid of that row. The next value on the stack is
|
||||||
|
** the new value for the root-page field.
|
||||||
|
*/
|
||||||
|
{ OP_Column, 0, 0, 0}, /* 10 */
|
||||||
|
{ OP_Column, 0, 1, 0},
|
||||||
|
{ OP_Column, 0, 2, 0},
|
||||||
|
{ OP_Integer, 4, 0, 0}, /* 13 */
|
||||||
|
{ OP_Column, 0, 4, 0},
|
||||||
|
{ OP_MakeRecord, 5, 0, 0},
|
||||||
|
{ OP_PutIntKey, 0, 0, 0} /* 16 */
|
||||||
|
};
|
||||||
|
|
||||||
|
base = sqlite3VdbeAddOpList(v, ArraySize(updateMaster), updateMaster);
|
||||||
|
sqlite3VdbeChangeP1(v, base+13, iTable);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Write VDBE code to erase table pTab and all associated indices on disk.
|
||||||
|
** Code to update the sqlite_master tables and internal schema definitions
|
||||||
|
** in case a root-page belonging to another table is moved by the btree layer
|
||||||
|
** is also added (this can happen with an auto-vacuum database).
|
||||||
|
*/
|
||||||
|
static void destroyTable(Vdbe *v, Table *pTab){
|
||||||
|
#ifdef SQLITE_OMIT_AUTOVACUUM
|
||||||
|
destroyRootPage(v, pTab->tnum, pTab->iDb);
|
||||||
|
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||||
|
destroyRootPage(v, pIdx->tnum, pIdx->iDb);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* If the database may be auto-vacuum capable (if SQLITE_OMIT_AUTOVACUUM
|
||||||
|
** is not defined), then it is important to call OP_Destroy on the
|
||||||
|
** table and index root-pages in order, starting with the numerically
|
||||||
|
** largest root-page number. This guarantees that none of the root-pages
|
||||||
|
** to be destroyed is relocated by an earlier OP_Destroy. i.e. if the
|
||||||
|
** following were coded:
|
||||||
|
**
|
||||||
|
** OP_Destroy 4 0
|
||||||
|
** ...
|
||||||
|
** OP_Destroy 5 0
|
||||||
|
**
|
||||||
|
** and root page 5 happened to be the largest root-page number in the
|
||||||
|
** database, then root page 5 would be moved to page 4 by the
|
||||||
|
** "OP_Destroy 4 0" opcode. The subsequent "OP_Destroy 5 0" would hit
|
||||||
|
** a free-list page.
|
||||||
|
*/
|
||||||
|
int iTab = pTab->tnum;
|
||||||
|
int iDestroyed = 0;
|
||||||
|
|
||||||
|
while( 1 ){
|
||||||
|
Index *pIdx;
|
||||||
|
int iLargest = 0;
|
||||||
|
|
||||||
|
if( iDestroyed==0 || iTab<iDestroyed ){
|
||||||
|
iLargest = iTab;
|
||||||
|
}
|
||||||
|
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||||
|
int iIdx = pIdx->tnum;
|
||||||
|
assert( pIdx->iDb==pTab->iDb );
|
||||||
|
if( (iDestroyed==0 || (iIdx<iDestroyed)) && iIdx>iLargest ){
|
||||||
|
iLargest = iIdx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( iLargest==0 ) return;
|
||||||
|
destroyRootPage(v, iLargest, pTab->iDb);
|
||||||
|
iDestroyed = iLargest;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This routine is called to do the work of a DROP TABLE statement.
|
** This routine is called to do the work of a DROP TABLE statement.
|
||||||
** pName is the name of the table to be dropped.
|
** pName is the name of the table to be dropped.
|
||||||
@@ -1635,7 +1770,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
|
|||||||
{ OP_Goto, 0, ADDR(3), 0},
|
{ OP_Goto, 0, ADDR(3), 0},
|
||||||
{ OP_Next, 0, ADDR(3), 0}, /* 12 */
|
{ OP_Next, 0, ADDR(3), 0}, /* 12 */
|
||||||
};
|
};
|
||||||
Index *pIdx;
|
/* Index *pIdx; */
|
||||||
Trigger *pTrigger;
|
Trigger *pTrigger;
|
||||||
sqlite3BeginWriteOperation(pParse, 0, pTab->iDb);
|
sqlite3BeginWriteOperation(pParse, 0, pTab->iDb);
|
||||||
|
|
||||||
@@ -1661,13 +1796,16 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
|
|||||||
base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable);
|
base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable);
|
||||||
sqlite3VdbeChangeP3(v, base+1, pTab->zName, 0);
|
sqlite3VdbeChangeP3(v, base+1, pTab->zName, 0);
|
||||||
sqlite3ChangeCookie(db, v, pTab->iDb);
|
sqlite3ChangeCookie(db, v, pTab->iDb);
|
||||||
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
|
|
||||||
if( !isView ){
|
if( !isView ){
|
||||||
|
/*
|
||||||
sqlite3VdbeAddOp(v, OP_Destroy, pTab->tnum, pTab->iDb);
|
sqlite3VdbeAddOp(v, OP_Destroy, pTab->tnum, pTab->iDb);
|
||||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||||
sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
|
sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
destroyTable(v, pTab);
|
||||||
}
|
}
|
||||||
|
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
|
||||||
sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0);
|
sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0);
|
||||||
}
|
}
|
||||||
sqliteViewResetAll(db, iDb);
|
sqliteViewResetAll(db, iDb);
|
||||||
@@ -2237,8 +2375,9 @@ void sqlite3DropIndex(Parse *pParse, SrcList *pName){
|
|||||||
base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
|
base = sqlite3VdbeAddOpList(v, ArraySize(dropIndex), dropIndex);
|
||||||
sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0);
|
sqlite3VdbeChangeP3(v, base+1, pIndex->zName, 0);
|
||||||
sqlite3ChangeCookie(db, v, pIndex->iDb);
|
sqlite3ChangeCookie(db, v, pIndex->iDb);
|
||||||
|
/* sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb); */
|
||||||
|
destroyRootPage(v, pIndex->tnum, pIndex->iDb);
|
||||||
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
|
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
|
||||||
sqlite3VdbeAddOp(v, OP_Destroy, pIndex->tnum, pIndex->iDb);
|
|
||||||
sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0);
|
sqlite3VdbeOp3(v, OP_DropIndex, pIndex->iDb, 0, pIndex->zName, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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.171 2004/11/03 08:44:06 danielk1977 Exp $
|
** @(#) $Id: pager.c,v 1.172 2004/11/04 14:30:05 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@@ -2588,8 +2588,7 @@ int sqlite3pager_write(void *pData){
|
|||||||
pPg->dirty = 1;
|
pPg->dirty = 1;
|
||||||
if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){
|
if( pPg->inJournal && (pPg->inStmt || pPager->stmtInUse==0) ){
|
||||||
pPager->dirtyCache = 1;
|
pPager->dirtyCache = 1;
|
||||||
return SQLITE_OK;
|
}else{
|
||||||
}
|
|
||||||
|
|
||||||
/* If we get this far, it means that the page needs to be
|
/* If we get this far, it means that the page needs to be
|
||||||
** written to the transaction journal or the ckeckpoint journal
|
** written to the transaction journal or the ckeckpoint journal
|
||||||
@@ -2698,6 +2697,7 @@ int sqlite3pager_write(void *pData){
|
|||||||
}
|
}
|
||||||
page_add_to_stmt_list(pPg);
|
page_add_to_stmt_list(pPg);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Update the database size and return.
|
/* Update the database size and return.
|
||||||
*/
|
*/
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.329 2004/10/31 02:22:49 drh Exp $
|
** @(#) $Id: sqliteInt.h,v 1.330 2004/11/04 14:30:05 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@@ -1432,5 +1432,6 @@ void sqlite3ValueFree(sqlite3_value*);
|
|||||||
sqlite3_value *sqlite3ValueNew();
|
sqlite3_value *sqlite3ValueNew();
|
||||||
sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
|
sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
|
||||||
extern const unsigned char sqlite3UpperToLower[];
|
extern const unsigned char sqlite3UpperToLower[];
|
||||||
|
void sqlite3RootPageMoved(Db*, int, int);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -13,7 +13,7 @@
|
|||||||
** is not included in the SQLite library. It is used for automated
|
** is not included in the SQLite library. It is used for automated
|
||||||
** testing of the SQLite library.
|
** testing of the SQLite library.
|
||||||
**
|
**
|
||||||
** $Id: test3.c,v 1.53 2004/10/31 02:22:49 drh Exp $
|
** $Id: test3.c,v 1.54 2004/11/04 14:30:06 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "pager.h"
|
#include "pager.h"
|
||||||
@@ -322,7 +322,7 @@ static int btree_drop_table(
|
|||||||
}
|
}
|
||||||
pBt = sqlite3TextToPtr(argv[1]);
|
pBt = sqlite3TextToPtr(argv[1]);
|
||||||
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
|
||||||
rc = sqlite3BtreeDropTable(pBt, iTable);
|
rc = sqlite3BtreeDropTable(pBt, iTable, 0);
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
Tcl_AppendResult(interp, errorName(rc), 0);
|
Tcl_AppendResult(interp, errorName(rc), 0);
|
||||||
return TCL_ERROR;
|
return TCL_ERROR;
|
||||||
|
13
src/vdbe.c
13
src/vdbe.c
@@ -43,7 +43,7 @@
|
|||||||
** in this file for details. If in doubt, do not deviate from existing
|
** in this file for details. If in doubt, do not deviate from existing
|
||||||
** commenting and indentation practices when changing or adding code.
|
** commenting and indentation practices when changing or adding code.
|
||||||
**
|
**
|
||||||
** $Id: vdbe.c,v 1.422 2004/11/03 16:27:01 drh Exp $
|
** $Id: vdbe.c,v 1.423 2004/11/04 14:30:06 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@@ -3610,7 +3610,16 @@ case OP_IdxIsNull: {
|
|||||||
** See also: Clear
|
** See also: Clear
|
||||||
*/
|
*/
|
||||||
case OP_Destroy: {
|
case OP_Destroy: {
|
||||||
rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1);
|
int iMoved;
|
||||||
|
rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
|
||||||
|
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||||
|
pTos++;
|
||||||
|
pTos->flags = MEM_Int;
|
||||||
|
pTos->i = iMoved;
|
||||||
|
if( iMoved!=0 ){
|
||||||
|
sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,7 +11,7 @@
|
|||||||
# 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 SELECT statement.
|
# focus of this file is testing the SELECT statement.
|
||||||
#
|
#
|
||||||
# $Id: autovacuum.test,v 1.5 2004/11/04 02:57:35 danielk1977 Exp $
|
# $Id: autovacuum.test,v 1.6 2004/11/04 14:30:06 danielk1977 Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@@ -144,6 +144,5 @@ for {set i 5} {$i < 15} {incr i} {
|
|||||||
} {ok}
|
} {ok}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user