mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Limit the number of errors returned by PRAGMA integrity_check to 100 by
default. Specify an alternative limit using an argument to the pragma. Ticket #2176. (CVS 3609) FossilOrigin-Name: d564a039f27be2bb2c3973e79dc99b25869139da
This commit is contained in:
24
manifest
24
manifest
@@ -1,5 +1,5 @@
|
||||
C Make\ssure\sthe\svdbeInt.h\sfile\sis\snot\s#included\smultiple\stimes.\s\sTicket\s#2194.\s(CVS\s3608)
|
||||
D 2007-01-26T21:08:05
|
||||
C Limit\sthe\snumber\sof\serrors\sreturned\sby\sPRAGMA\sintegrity_check\sto\s100\sby\ndefault.\s\sSpecify\san\salternative\slimit\susing\san\sargument\sto\sthe\spragma.\nTicket\s#2176.\s(CVS\s3609)
|
||||
D 2007-01-27T02:24:55
|
||||
F Makefile.in 7fa74bf4359aa899da5586e394d17735f221315f
|
||||
F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@@ -57,8 +57,8 @@ F src/alter.c 2c79ec40f65e33deaf90ca493422c74586e481a3
|
||||
F src/analyze.c 7d2b7ab9a9c2fd6e55700f69064dfdd3e36d7a8a
|
||||
F src/attach.c b11eb4d5d3fb99a10a626956bccc7215f6b68b16
|
||||
F src/auth.c 902f4722661c796b97f007d9606bd7529c02597f
|
||||
F src/btree.c 6837dcc4da8677e695a49fcc4505418ff1e0fc54
|
||||
F src/btree.h 061c50e37de7f50b58528e352d400cf33ead7418
|
||||
F src/btree.c 51aef6a4b18df165b83b332befd1447c011b4389
|
||||
F src/btree.h 066444ee25bd6e6accb997bfd2cf5ace14dbcd00
|
||||
F src/build.c 02aedde724dc73295d6e9b8dc29afb5dd38de507
|
||||
F src/callback.c fd9bb39f7ff6b52bad8365617abc61c720640429
|
||||
F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675
|
||||
@@ -88,7 +88,7 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c d6ad66eb119602cb2e6a097f8f635372ba677d23
|
||||
F src/pager.h 2e6d42f4ae004ae748a037b8468112b851c447a7
|
||||
F src/parse.y 2f571c5f6219428d7fb08737db3d113742b1cceb
|
||||
F src/pragma.c fd4df6cf0857dd78a7cb5be5f9805419b53ae7a0
|
||||
F src/pragma.c 5091300911670ddaa552bfa12c45cbca1bb7e7d6
|
||||
F src/prepare.c 484389c6811415b8f23d259ac9c029613e1c72c3
|
||||
F src/printf.c aade23a789d7cc88b397ec0d33a0a01a33a7a9c1
|
||||
F src/random.c 6119474a6f6917f708c1dee25b9a8e519a620e88
|
||||
@@ -102,7 +102,7 @@ F src/table.c 6d0da66dde26ee75614ed8f584a1996467088d06
|
||||
F src/tclsqlite.c d344c7f394d6f055ce3abfe0049b0480c5e34e56
|
||||
F src/test1.c 053f5224697efaefff1f4c647fd90fdea9346cc5
|
||||
F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b
|
||||
F src/test3.c fa0e85ddd1784f2dda5861a2cb4e7d27d1c932c1
|
||||
F src/test3.c 875126eab6749f9d9e2b60b6ee6a65825b3d1fed
|
||||
F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
|
||||
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
|
||||
F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
|
||||
@@ -121,7 +121,7 @@ F src/update.c 951f95ef044cf6d28557c48dc35cb0711a0b9129
|
||||
F src/utf.c 67ecb1032bc0b42c105e88d65ef9d9f626eb0e1f
|
||||
F src/util.c 91d4cb189476906639ae611927d939691d1365f6
|
||||
F src/vacuum.c b4569b08aaa5afb141af3f76d0315745db4e9e4b
|
||||
F src/vdbe.c 4d54659b7dbb7a61570d7136a34fbde12b61c509
|
||||
F src/vdbe.c 31fe3e1e3cc00f5324a5fbde89d0ab603ad246b5
|
||||
F src/vdbe.h 0025259af1939fb264a545816c69e4b5b8d52691
|
||||
F src/vdbeInt.h 13ba07121cf534d5b80130d2f5eb0a4937a36bba
|
||||
F src/vdbeapi.c 2d1e6843af8705a1172e54a418d2a3d5febd1dd7
|
||||
@@ -269,7 +269,7 @@ F test/pager.test 6ee95e90ee8295e376e39a6c6566ef6df993601a
|
||||
F test/pager2.test 49c0f57c7da0b060f0486b85fdd074025caa694e
|
||||
F test/pager3.test 2323bf27fd5bd887b580247e5bce500ceee994b4
|
||||
F test/pagesize.test 05c74ea49f790734ec1e9ab765d9bf1cce79b8f2
|
||||
F test/pragma.test d20fe81e31c6be9cb3182f1792cf5e5a6d4e97f6
|
||||
F test/pragma.test b523286a32bfab309dd42d21ccdc9f5e51e3b2e9
|
||||
F test/printf.test cdd8e20dd901382a385afcbaa777b9377815c2ad
|
||||
F test/progress.test 8b22b4974b0a95272566385f8cb8c341c7130df8 x
|
||||
F test/quick.test 6bc0f7c7b905f7de5fe4d3f13239ced3e4e66fe7
|
||||
@@ -416,7 +416,7 @@ F www/opcode.tcl 5bd68059416b223515a680d410a9f7cb6736485f
|
||||
F www/optimizer.tcl d6812a10269bd0d7c488987aac0ad5036cace9dc
|
||||
F www/optimizing.tcl f0b2538988d1bbad16cbfe63ec6e8f48c9eb04e5
|
||||
F www/optoverview.tcl 815df406a38c9f69b27d37e8f7ede004c6d9f19e
|
||||
F www/pragma.tcl c3d103838ae1c66729f8286e276735618af2a88a
|
||||
F www/pragma.tcl 74544f5564bbb6d9809cf35b4c05ebdfee469165
|
||||
F www/quickstart.tcl 8708a4ca83fbf55c66af1782992626f20c3df095
|
||||
F www/shared.gif 265bae80c5b311c5a86e47662821076ffaf5c6ea
|
||||
F www/sharedcache.tcl 3ebec81110e606af6fd65a3c4c19562cb173b29c
|
||||
@@ -428,7 +428,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||
P 02990fabd1c68fb51afc91a1b720802ef86bfec6
|
||||
R f3d4c318f331af035a24f47aae427d9a
|
||||
P 93edd3b0565d08383b3034c57f221073fde6de4b
|
||||
R 557df95c56e9de3c85559166fb533aa4
|
||||
U drh
|
||||
Z b826f35654120ae9d4f4a22ffb14f63f
|
||||
Z 0cf02b2f60ab84b0a3c77c11c5fcb2c4
|
||||
|
@@ -1 +1 @@
|
||||
93edd3b0565d08383b3034c57f221073fde6de4b
|
||||
d564a039f27be2bb2c3973e79dc99b25869139da
|
30
src/btree.c
30
src/btree.c
@@ -9,7 +9,7 @@
|
||||
** May you share freely, never taking more than you give.
|
||||
**
|
||||
*************************************************************************
|
||||
** $Id: btree.c,v 1.333 2007/01/05 02:00:47 drh Exp $
|
||||
** $Id: btree.c,v 1.334 2007/01/27 02:24:55 drh Exp $
|
||||
**
|
||||
** This file implements a external (disk-based) database using BTrees.
|
||||
** For a detailed discussion of BTrees, refer to
|
||||
@@ -5961,7 +5961,9 @@ struct IntegrityCk {
|
||||
Pager *pPager; /* The associated pager. Also accessible by pBt->pPager */
|
||||
int nPage; /* Number of pages in the database */
|
||||
int *anRef; /* Number of times each page is referenced */
|
||||
char *zErrMsg; /* An error message. NULL of no errors seen. */
|
||||
int mxErr; /* Stop accumulating errors when this reaches zero */
|
||||
char *zErrMsg; /* An error message. NULL if no errors seen. */
|
||||
int nErr; /* Number of messages written to zErrMsg so far */
|
||||
};
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
@@ -5976,6 +5978,9 @@ static void checkAppendMsg(
|
||||
){
|
||||
va_list ap;
|
||||
char *zMsg2;
|
||||
if( !pCheck->mxErr ) return;
|
||||
pCheck->mxErr--;
|
||||
pCheck->nErr++;
|
||||
va_start(ap, zFormat);
|
||||
zMsg2 = sqlite3VMPrintf(zFormat, ap);
|
||||
va_end(ap);
|
||||
@@ -6059,7 +6064,7 @@ static void checkList(
|
||||
int i;
|
||||
int expected = N;
|
||||
int iFirst = iPage;
|
||||
while( N-- > 0 ){
|
||||
while( N-- > 0 && pCheck->mxErr ){
|
||||
unsigned char *pOvfl;
|
||||
if( iPage<1 ){
|
||||
checkAppendMsg(pCheck, zContext,
|
||||
@@ -6171,7 +6176,7 @@ static int checkTreePage(
|
||||
/* Check out all the cells.
|
||||
*/
|
||||
depth = 0;
|
||||
for(i=0; i<pPage->nCell; i++){
|
||||
for(i=0; i<pPage->nCell && pCheck->mxErr; i++){
|
||||
u8 *pCell;
|
||||
int sz;
|
||||
CellInfo info;
|
||||
@@ -6286,7 +6291,13 @@ static int checkTreePage(
|
||||
** and a pointer to that error message is returned. The calling function
|
||||
** is responsible for freeing the error message when it is done.
|
||||
*/
|
||||
char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
char *sqlite3BtreeIntegrityCheck(
|
||||
Btree *p, /* The btree to be checked */
|
||||
int *aRoot, /* An array of root pages numbers for individual trees */
|
||||
int nRoot, /* Number of entries in aRoot[] */
|
||||
int mxErr, /* Stop reporting errors after this many */
|
||||
int *pnErr /* Write number of errors seen to this variable */
|
||||
){
|
||||
int i;
|
||||
int nRef;
|
||||
IntegrityCk sCheck;
|
||||
@@ -6299,6 +6310,9 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
sCheck.pBt = pBt;
|
||||
sCheck.pPager = pBt->pPager;
|
||||
sCheck.nPage = sqlite3pager_pagecount(sCheck.pPager);
|
||||
sCheck.mxErr = mxErr;
|
||||
sCheck.nErr = 0;
|
||||
*pnErr = 0;
|
||||
if( sCheck.nPage==0 ){
|
||||
unlockBtreeIfUnused(pBt);
|
||||
return 0;
|
||||
@@ -6306,6 +6320,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
sCheck.anRef = sqliteMallocRaw( (sCheck.nPage+1)*sizeof(sCheck.anRef[0]) );
|
||||
if( !sCheck.anRef ){
|
||||
unlockBtreeIfUnused(pBt);
|
||||
*pnErr = 1;
|
||||
return sqlite3MPrintf("Unable to malloc %d bytes",
|
||||
(sCheck.nPage+1)*sizeof(sCheck.anRef[0]));
|
||||
}
|
||||
@@ -6323,7 +6338,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
|
||||
/* Check all the tables.
|
||||
*/
|
||||
for(i=0; i<nRoot; i++){
|
||||
for(i=0; i<nRoot && sCheck.mxErr; i++){
|
||||
if( aRoot[i]==0 ) continue;
|
||||
#ifndef SQLITE_OMIT_AUTOVACUUM
|
||||
if( pBt->autoVacuum && aRoot[i]>1 ){
|
||||
@@ -6335,7 +6350,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
|
||||
/* Make sure every page in the file is referenced
|
||||
*/
|
||||
for(i=1; i<=sCheck.nPage; i++){
|
||||
for(i=1; i<=sCheck.nPage && sCheck.mxErr; i++){
|
||||
#ifdef SQLITE_OMIT_AUTOVACUUM
|
||||
if( sCheck.anRef[i]==0 ){
|
||||
checkAppendMsg(&sCheck, 0, "Page %d is never used", i);
|
||||
@@ -6368,6 +6383,7 @@ char *sqlite3BtreeIntegrityCheck(Btree *p, int *aRoot, int nRoot){
|
||||
/* Clean up and report errors.
|
||||
*/
|
||||
sqliteFree(sCheck.anRef);
|
||||
*pnErr = sCheck.nErr;
|
||||
return sCheck.zErrMsg;
|
||||
}
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
|
@@ -13,7 +13,7 @@
|
||||
** subsystem. See comments in the source code for a detailed description
|
||||
** of what each interface routine does.
|
||||
**
|
||||
** @(#) $Id: btree.h,v 1.71 2006/06/27 16:34:57 danielk1977 Exp $
|
||||
** @(#) $Id: btree.h,v 1.72 2007/01/27 02:24:55 drh Exp $
|
||||
*/
|
||||
#ifndef _BTREE_H_
|
||||
#define _BTREE_H_
|
||||
@@ -131,7 +131,7 @@ const void *sqlite3BtreeDataFetch(BtCursor*, int *pAmt);
|
||||
int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
|
||||
int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);
|
||||
|
||||
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot);
|
||||
char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot, int, int*);
|
||||
struct Pager *sqlite3BtreePager(Btree*);
|
||||
|
||||
|
||||
|
46
src/pragma.c
46
src/pragma.c
@@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.126 2007/01/04 22:13:42 drh Exp $
|
||||
** $Id: pragma.c,v 1.127 2007/01/27 02:24:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -640,9 +640,13 @@ void sqlite3Pragma(
|
||||
}
|
||||
}else
|
||||
|
||||
#ifndef SQLITE_INTEGRITY_CHECK_ERROR_MAX
|
||||
# define SQLITE_INTEGRITY_CHECK_ERROR_MAX 100
|
||||
#endif
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
if( sqlite3StrICmp(zLeft, "integrity_check")==0 ){
|
||||
int i, j, addr;
|
||||
int i, j, addr, mxErr;
|
||||
|
||||
/* Code that appears at the end of the integrity check. If no error
|
||||
** messages have been generated, output OK. Otherwise output the
|
||||
@@ -660,7 +664,16 @@ void sqlite3Pragma(
|
||||
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
|
||||
sqlite3VdbeSetNumCols(v, 1);
|
||||
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "integrity_check", P3_STATIC);
|
||||
sqlite3VdbeAddOp(v, OP_MemInt, 0, 0); /* Initialize error count to 0 */
|
||||
|
||||
/* Set the maximum error count */
|
||||
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
|
||||
if( zRight ){
|
||||
mxErr = atoi(zRight);
|
||||
if( mxErr<=0 ){
|
||||
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
|
||||
}
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_MemInt, mxErr, 0);
|
||||
|
||||
/* Do an integrity check on each database file */
|
||||
for(i=0; i<db->nDb; i++){
|
||||
@@ -671,6 +684,9 @@ void sqlite3Pragma(
|
||||
if( OMIT_TEMPDB && i==1 ) continue;
|
||||
|
||||
sqlite3CodeVerifySchema(pParse, i);
|
||||
addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
|
||||
/* Do an integrity check of the B-Tree
|
||||
*/
|
||||
@@ -685,28 +701,28 @@ void sqlite3Pragma(
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
assert( cnt>0 );
|
||||
sqlite3VdbeAddOp(v, OP_IntegrityCk, cnt, i);
|
||||
sqlite3VdbeAddOp(v, OP_Dup, 0, 1);
|
||||
addr = sqlite3VdbeOp3(v, OP_String8, 0, 0, "ok", P3_STATIC);
|
||||
sqlite3VdbeAddOp(v, OP_Eq, 0, addr+7);
|
||||
if( cnt==0 ) continue;
|
||||
sqlite3VdbeAddOp(v, OP_IntegrityCk, 0, i);
|
||||
addr = sqlite3VdbeAddOp(v, OP_IsNull, -1, 0);
|
||||
sqlite3VdbeOp3(v, OP_String8, 0, 0,
|
||||
sqlite3MPrintf("*** in database %s ***\n", db->aDb[i].zName),
|
||||
P3_DYNAMIC);
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Concat, 0, 1);
|
||||
sqlite3VdbeAddOp(v, OP_Concat, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
|
||||
/* Make sure all the indices are constructed correctly.
|
||||
*/
|
||||
sqlite3CodeVerifySchema(pParse, i);
|
||||
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
Index *pIdx;
|
||||
int loopTop;
|
||||
|
||||
if( pTab->pIndex==0 ) continue;
|
||||
addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
|
||||
sqlite3VdbeAddOp(v, OP_MemInt, 0, 1);
|
||||
loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0);
|
||||
@@ -714,7 +730,7 @@ void sqlite3Pragma(
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int jmp2;
|
||||
static const VdbeOpList idxErr[] = {
|
||||
{ OP_MemIncr, 1, 0, 0},
|
||||
{ OP_MemIncr, -1, 0, 0},
|
||||
{ OP_String8, 0, 0, "rowid "},
|
||||
{ OP_Rowid, 1, 0, 0},
|
||||
{ OP_String8, 0, 0, " missing from index "},
|
||||
@@ -739,13 +755,16 @@ void sqlite3Pragma(
|
||||
{ OP_MemLoad, 1, 0, 0},
|
||||
{ OP_MemLoad, 2, 0, 0},
|
||||
{ OP_Eq, 0, 0, 0}, /* 6 */
|
||||
{ OP_MemIncr, 1, 0, 0},
|
||||
{ OP_MemIncr, -1, 0, 0},
|
||||
{ OP_String8, 0, 0, "wrong # of entries in index "},
|
||||
{ OP_String8, 0, 0, 0}, /* 9 */
|
||||
{ OP_Concat, 0, 0, 0},
|
||||
{ OP_Callback, 1, 0, 0},
|
||||
};
|
||||
if( pIdx->tnum==0 ) continue;
|
||||
addr = sqlite3VdbeAddOp(v, OP_IfMemPos, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(cntIdx), cntIdx);
|
||||
sqlite3VdbeChangeP1(v, addr+1, j+2);
|
||||
sqlite3VdbeChangeP2(v, addr+1, addr+4);
|
||||
@@ -757,6 +776,7 @@ void sqlite3Pragma(
|
||||
}
|
||||
}
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode);
|
||||
sqlite3VdbeChangeP1(v, addr+1, mxErr);
|
||||
sqlite3VdbeJumpHere(v, addr+2);
|
||||
}else
|
||||
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
|
||||
|
@@ -13,7 +13,7 @@
|
||||
** is not included in the SQLite library. It is used for automated
|
||||
** testing of the SQLite library.
|
||||
**
|
||||
** $Id: test3.c,v 1.68 2007/01/03 23:37:28 drh Exp $
|
||||
** $Id: test3.c,v 1.69 2007/01/27 02:24:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "pager.h"
|
||||
@@ -567,6 +567,7 @@ static int btree_integrity_check(
|
||||
int nRoot;
|
||||
int *aRoot;
|
||||
int i;
|
||||
int nErr;
|
||||
char *zResult;
|
||||
|
||||
if( argc<3 ){
|
||||
@@ -581,7 +582,7 @@ static int btree_integrity_check(
|
||||
if( Tcl_GetInt(interp, argv[i+2], &aRoot[i]) ) return TCL_ERROR;
|
||||
}
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot);
|
||||
zResult = sqlite3BtreeIntegrityCheck(pBt, aRoot, nRoot, 10000, &nErr);
|
||||
#else
|
||||
zResult = 0;
|
||||
#endif
|
||||
|
31
src/vdbe.c
31
src/vdbe.c
@@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.586 2007/01/12 23:43:43 drh Exp $
|
||||
** $Id: vdbe.c,v 1.587 2007/01/27 02:24:56 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -4120,11 +4120,16 @@ case OP_DropTrigger: { /* no-push */
|
||||
|
||||
|
||||
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
|
||||
/* Opcode: IntegrityCk * P2 *
|
||||
/* Opcode: IntegrityCk P1 P2 *
|
||||
**
|
||||
** 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.
|
||||
** If no problems are found, push a NULL onto the stack.
|
||||
**
|
||||
** P1 is the address of a memory cell that contains the maximum
|
||||
** number of allowed errors. At most mem[P1] errors will be reported.
|
||||
** In other words, the analysis stops as soon as mem[P1] errors are
|
||||
** seen. Mem[P1] is updated with the number of errors remaining.
|
||||
**
|
||||
** The root page numbers of all tables in the database are integer
|
||||
** values on the stack. This opcode pulls as many integers as it
|
||||
@@ -4133,13 +4138,15 @@ case OP_DropTrigger: { /* no-push */
|
||||
** If P2 is not zero, the check is done on the auxiliary database
|
||||
** file, not the main database file.
|
||||
**
|
||||
** This opcode is used for testing purposes only.
|
||||
** This opcode is used to implement the integrity_check pragma.
|
||||
*/
|
||||
case OP_IntegrityCk: {
|
||||
int nRoot;
|
||||
int *aRoot;
|
||||
int j;
|
||||
int nErr;
|
||||
char *z;
|
||||
Mem *pnErr;
|
||||
|
||||
for(nRoot=0; &pTos[-nRoot]>=p->aStack; nRoot++){
|
||||
if( (pTos[-nRoot].flags & MEM_Int)==0 ) break;
|
||||
@@ -4147,6 +4154,10 @@ case OP_IntegrityCk: {
|
||||
assert( nRoot>0 );
|
||||
aRoot = sqliteMallocRaw( sizeof(int*)*(nRoot+1) );
|
||||
if( aRoot==0 ) goto no_mem;
|
||||
j = pOp->p1;
|
||||
assert( j>=0 && j<p->nMem );
|
||||
pnErr = &p->aMem[j];
|
||||
assert( (pnErr->flags & MEM_Int)!=0 );
|
||||
for(j=0; j<nRoot; j++){
|
||||
Mem *pMem = &pTos[-j];
|
||||
aRoot[j] = pMem->i;
|
||||
@@ -4154,12 +4165,12 @@ case OP_IntegrityCk: {
|
||||
aRoot[j] = 0;
|
||||
popStack(&pTos, nRoot);
|
||||
pTos++;
|
||||
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot);
|
||||
if( z==0 || z[0]==0 ){
|
||||
if( z ) sqliteFree(z);
|
||||
pTos->z = "ok";
|
||||
pTos->n = 2;
|
||||
pTos->flags = MEM_Str | MEM_Static | MEM_Term;
|
||||
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p2].pBt, aRoot, nRoot,
|
||||
pnErr->i, &nErr);
|
||||
pnErr->i -= nErr;
|
||||
if( nErr==0 ){
|
||||
assert( z==0 );
|
||||
pTos->flags = MEM_Null;
|
||||
}else{
|
||||
pTos->z = z;
|
||||
pTos->n = strlen(z);
|
||||
|
137
test/pragma.test
137
test/pragma.test
@@ -12,7 +12,7 @@
|
||||
#
|
||||
# This file implements tests for the PRAGMA command.
|
||||
#
|
||||
# $Id: pragma.test,v 1.47 2007/01/22 13:02:24 drh Exp $
|
||||
# $Id: pragma.test,v 1.48 2007/01/27 02:24:56 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@@ -259,12 +259,141 @@ if {![sqlite3 -has-codec] && $sqlite_options(integrityck)} {
|
||||
btree_close $db
|
||||
execsql {PRAGMA integrity_check}
|
||||
} {{rowid 1 missing from index i2} {wrong # of entries in index i2}}
|
||||
}
|
||||
do_test pragma-3.3 {
|
||||
execsql {PRAGMA integrity_check=1}
|
||||
} {{rowid 1 missing from index i2}}
|
||||
do_test pragma-3.4 {
|
||||
execsql {
|
||||
DROP INDEX i2;
|
||||
ATTACH DATABASE 'test.db' AS t2;
|
||||
PRAGMA integrity_check
|
||||
}
|
||||
} {}
|
||||
} {{rowid 1 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {wrong # of entries in index i2}}
|
||||
do_test pragma-3.5 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=3
|
||||
}
|
||||
} {{rowid 1 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2}}
|
||||
do_test pragma-3.6 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=xyz
|
||||
}
|
||||
} {{rowid 1 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {wrong # of entries in index i2}}
|
||||
do_test pragma-3.7 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=0
|
||||
}
|
||||
} {{rowid 1 missing from index i2} {wrong # of entries in index i2} {rowid 1 missing from index i2} {wrong # of entries in index i2}}
|
||||
|
||||
# Add additional corruption by appending unused pages to the end of
|
||||
# the database file testerr.db
|
||||
#
|
||||
do_test pragma-3.8 {
|
||||
execsql {DETACH t2}
|
||||
file delete -force testerr.db testerr.db-journal
|
||||
set out [open testerr.db wb]
|
||||
set in [open test.db rb]
|
||||
puts -nonewline $out [read $in]
|
||||
seek $in 0
|
||||
puts -nonewline $out [read $in]
|
||||
close $in
|
||||
close $out
|
||||
execsql {REINDEX t2}
|
||||
execsql {PRAGMA integrity_check}
|
||||
} {ok}
|
||||
do_test pragma-3.9 {
|
||||
execsql {
|
||||
ATTACH 'testerr.db' AS t2;
|
||||
PRAGMA integrity_check
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used} {rowid 1 missing from index i2} {wrong # of entries in index i2}}
|
||||
do_test pragma-3.10 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=1
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used}}
|
||||
do_test pragma-3.11 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=5
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used} {rowid 1 missing from index i2} {wrong # of entries in index i2}}
|
||||
do_test pragma-3.12 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=4
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used} {rowid 1 missing from index i2}}
|
||||
do_test pragma-3.13 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=3
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used}}
|
||||
do_test pragma-3.14 {
|
||||
execsql {
|
||||
PRAGMA integrity_check(2)
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used}}
|
||||
do_test pragma-3.15 {
|
||||
execsql {
|
||||
ATTACH 'testerr.db' AS t3;
|
||||
PRAGMA integrity_check
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used} {rowid 1 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used} {rowid 1 missing from index i2} {wrong # of entries in index i2}}
|
||||
do_test pragma-3.16 {
|
||||
execsql {
|
||||
PRAGMA integrity_check(9)
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used} {rowid 1 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used} {rowid 1 missing from index i2}}
|
||||
do_test pragma-3.17 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=7
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used} {rowid 1 missing from index i2} {wrong # of entries in index i2} {*** in database t3 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used}}
|
||||
do_test pragma-3.18 {
|
||||
execsql {
|
||||
PRAGMA integrity_check=4
|
||||
}
|
||||
} {{*** in database t2 ***
|
||||
Page 4 is never used
|
||||
Page 5 is never used
|
||||
Page 6 is never used} {rowid 1 missing from index i2}}
|
||||
}
|
||||
do_test pragma-3.99 {
|
||||
file delete -force testerr.db testerr.db-journal
|
||||
catchsql {DETACH t3}
|
||||
catchsql {DETACH t2}
|
||||
catchsql {DROP INDEX i2}
|
||||
} {0 {}}
|
||||
|
||||
# Test modifying the cache_size of an attached database.
|
||||
ifcapable pager_pragmas {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#
|
||||
# Run this Tcl script to generate the pragma.html file.
|
||||
#
|
||||
set rcsid {$Id: pragma.tcl,v 1.18 2006/06/20 00:22:38 drh Exp $}
|
||||
set rcsid {$Id: pragma.tcl,v 1.19 2007/01/27 02:24:57 drh Exp $}
|
||||
source common.tcl
|
||||
header {Pragma statements supported by SQLite}
|
||||
|
||||
@@ -487,12 +487,16 @@ Section {Pragmas to debug the library} debug
|
||||
puts {
|
||||
<ul>
|
||||
<a name="pragma_integrity_check"></a>
|
||||
<li><p><b>PRAGMA integrity_check;</b></p>
|
||||
<li><p><b>PRAGMA integrity_check;
|
||||
<br>PRAGMA integrity_check(</b><i>integer</i><b>)</b></p>
|
||||
<p>The command does an integrity check of the entire database. It
|
||||
looks for out-of-order records, missing pages, malformed records, and
|
||||
corrupt indices.
|
||||
If any problems are found, then a single string is returned which is
|
||||
a description of all problems. If everything is in order, "ok" is
|
||||
If any problems are found, then strings are returned (as multiple
|
||||
rows with a single column per row) which describe
|
||||
the problems. At most <i>integer</i> errors will be reported
|
||||
before the analysis quits. The default value for <i>integer</i>
|
||||
is 100. If no errors are found, a single row with the value "ok" is
|
||||
returned.</p></li>
|
||||
|
||||
<a name="pragma_parser_trace"></a>
|
||||
|
Reference in New Issue
Block a user