From: drh Date: Sat, 27 Jan 2007 02:24:54 +0000 (+0000) Subject: Limit the number of errors returned by PRAGMA integrity_check to 100 by X-Git-Tag: version-3.6.10~2561 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1dcdbc0639eafe17acdacd89741e3580b5179a33;p=thirdparty%2Fsqlite.git 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 --- diff --git a/manifest b/manifest index 49abe62e2a..0246e350b8 100644 --- a/manifest +++ b/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 diff --git a/manifest.uuid b/manifest.uuid index f2b71816b6..3668855f5c 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -93edd3b0565d08383b3034c57f221073fde6de4b \ No newline at end of file +d564a039f27be2bb2c3973e79dc99b25869139da \ No newline at end of file diff --git a/src/btree.c b/src/btree.c index b8f3f378b5..8ac469ded9 100644 --- a/src/btree.c +++ b/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 @@ -5958,10 +5958,12 @@ Pager *sqlite3BtreePager(Btree *p){ typedef struct IntegrityCk IntegrityCk; struct IntegrityCk { BtShared *pBt; /* The tree being checked out */ - 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. */ + 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 */ + 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; inCell; i++){ + for(i=0; inCell && 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; iautoVacuum && 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 */ diff --git a/src/btree.h b/src/btree.h index ae24233859..8a05759ee9 100644 --- a/src/btree.h +++ b/src/btree.h @@ -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*); diff --git a/src/pragma.c b/src/pragma.c index 2474fa7a45..26bdba224c 100644 --- a/src/pragma.c +++ b/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; inDb; 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 */ diff --git a/src/test3.c b/src/test3.c index 4f42b5fbfd..0f0184d0f4 100644 --- a/src/test3.c +++ b/src/test3.c @@ -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 diff --git a/src/vdbe.c b/src/vdbe.c index 8d66b99c73..798228d53d 100644 --- a/src/vdbe.c +++ b/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 && jnMem ); + pnErr = &p->aMem[j]; + assert( (pnErr->flags & MEM_Int)!=0 ); for(j=0; ji; @@ -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); diff --git a/test/pragma.test b/test/pragma.test index be253b086e..ae8b2ec594 100644 --- a/test/pragma.test +++ b/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 { + 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.3 { - execsql { - DROP 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 { diff --git a/www/pragma.tcl b/www/pragma.tcl index 4f92a6bddf..a8dc281096 100644 --- a/www/pragma.tcl +++ b/www/pragma.tcl @@ -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 {
    -
  • PRAGMA integrity_check;

    +
  • PRAGMA integrity_check; +
    PRAGMA integrity_check(
    integer)

    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 integer errors will be reported + before the analysis quits. The default value for integer + is 100. If no errors are found, a single row with the value "ok" is returned.