Improvements to PRAGMA integrity_check for better detection of malformed
records. Integrity_check now avoids returning SQLITE_CORRUPT on a corrupt record. Also includes microoptimizations that I stumbled over while working on integrity_check. FossilOrigin-Name: 8525c30c1d6676e51b9d9c642450aae3722c129edafdbc39b8435fcfe09b1817
This commit is contained in:
commit
d33bcb8a3c
21
manifest
21
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\stest\sscript\scomment.\s\sNo\schanges\sto\scode.
|
||||
D 2017-09-13T00:01:26.395
|
||||
C Improvements\sto\sPRAGMA\sintegrity_check\sfor\sbetter\sdetection\sof\smalformed\nrecords.\s\sIntegrity_check\snow\savoids\sreturning\sSQLITE_CORRUPT\son\sa\scorrupt\nrecord.\s\sAlso\sincludes\smicrooptimizations\sthat\sI\sstumbled\sover\swhile\sworking\non\sintegrity_check.
|
||||
D 2017-09-13T00:33:36.268
|
||||
F Makefile.in c644bbe8ebe4aae82ad6783eae6b6beea4c727b99ff97568b847ced5e2ac7afb
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc 6a7a74bf60ad395098c0bd175ab054cd65ef85d7f034198d52bcc4d9e5fb4c6b
|
||||
@ -450,7 +450,7 @@ F src/parse.y 52ef3cecd0934e9da4a45b585883a03243ad615d338ad94f44501a05891dcdfa
|
||||
F src/pcache.c 4bada070456980c3c1f16d58ec2e64e389ad77b935e3d77e0c96e7bbd397289c
|
||||
F src/pcache.h 072f94d29281cffd99e46c1539849f248c4b56ae7684c1f36626797fee375170
|
||||
F src/pcache1.c 716975564c15eb6679e97f734cec1bfd6c16ac3d4010f05f1f8e509fc7d19880
|
||||
F src/pragma.c faf5f9ec553b71035c63e08d31651bbd28bec826d546b32c8e9c295855ca3605
|
||||
F src/pragma.c 88d99aa4752894aaf4102eefd09b5e497f4277661aff69f8fff61f8611f19d14
|
||||
F src/pragma.h bb83728944b42f6d409c77f5838a8edbdb0fe83046c5496ffc9602b40340a324
|
||||
F src/prepare.c 9a141a1b02dca53beaa9771699d390aafcac01f5d1f1c0ae6e23ded8dcdb709a
|
||||
F src/printf.c 40aee47ae9be4bd3dbdc8968bd07fddc027be8edec8daddf24d3391d36698a1c
|
||||
@ -525,11 +525,11 @@ F src/update.c 5404be9e840717323a69209190cdbc9d0d34adaedaaf1d1a1069babf2c4171c0
|
||||
F src/utf.c 810fbfebe12359f10bc2a011520a6e10879ab2a163bcb26c74768eab82ea62a5
|
||||
F src/util.c ece10cb34b4a62cbb3aab8d711b67e93a2765e0b81d0f72458cb801a3ac60703
|
||||
F src/vacuum.c 90839322fd5f00df9617eb21b68beda9b6e2a2937576b0d65985e4aeb1c53739
|
||||
F src/vdbe.c 82fc4553a0986a06bdd0d2b03a424e159bba5c74802fabb2841aa6cd27ccd962
|
||||
F src/vdbe.c 0a0ef7f0759ee4c3ed5ff0c6e9641216d4b31ebb0fea9a7b5a9c4a86ce875ff3
|
||||
F src/vdbe.h d50cadf12bcf9fb99117ef392ce1ea283aa429270481426b6e8b0280c101fd97
|
||||
F src/vdbeInt.h 1fe00770144c12c4913128f35262d11527ef3284561baaab59b947a41c08d0d9
|
||||
F src/vdbeapi.c 9c670ca0dcc1cd86373aa353b747b26fe531ca5cd4331690c611d1f03842e2a1
|
||||
F src/vdbeaux.c 2dff8186d34e0e525838f77b2fac70bd480f0273a77015bf21b6a08f2792da82
|
||||
F src/vdbeaux.c 41d90002d774e234f95d1298fc70d25e3420e8d9ebd65aa270a8b771c5525790
|
||||
F src/vdbeblob.c db3cf91060f6f4b2f1358a4200e844697990752177784c7c95da00b7ac9f1c7b
|
||||
F src/vdbemem.c 2f9d672af5260f0145787e1dc2c6985414987cc0dc575133a0dc17dda767d868
|
||||
F src/vdbesort.c 731a09e5cb9e96b70c394c1b7cf3860fbe84acca7682e178615eb941a3a0ef2f
|
||||
@ -1096,7 +1096,7 @@ F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||
F test/permutations.test d911c9ba49088d22054a05dc73743f677872a92ac89288bcdeafa0ebf3f9c531
|
||||
F test/pragma.test 277488e8098e55eef32cf3188513269035cccf5a1804d505db7ac4c725fa52a5
|
||||
F test/pragma.test c31b5e98998c160a4c85b1e04f590655c67f2daa7f73854640cd120610e3ac15
|
||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
|
||||
F test/pragma4.test 6e85b6eab8e61ffc9c7db59d842276674e8e3264
|
||||
@ -1653,7 +1653,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 3a2793aa65727cbbf8c4678d478cf8fb02350f19ff98201934a984727368d64d
|
||||
R 1b5d97330475c133bb2adcba21536957
|
||||
U mistachkin
|
||||
Z e62aad7ac8dd39a60ddf24398d01019c
|
||||
P a5a1949259a26c3330d7b1dcf38a8dd2e9b2c3af8d52f937e8537df138c9a55a 81f62e99f27dedf3dc10fa1593c4cd9fc158680867206aee853e503a0cc8df71
|
||||
R fccb8367f74d1b5d089bf2ff62c634d9
|
||||
T +closed 81f62e99f27dedf3dc10fa1593c4cd9fc158680867206aee853e503a0cc8df71
|
||||
U drh
|
||||
Z 70196bf0d2abbf2ab0f5b4a6633369ee
|
||||
|
@ -1 +1 @@
|
||||
a5a1949259a26c3330d7b1dcf38a8dd2e9b2c3af8d52f937e8537df138c9a55a
|
||||
8525c30c1d6676e51b9d9c642450aae3722c129edafdbc39b8435fcfe09b1817
|
150
src/pragma.c
150
src/pragma.c
@ -298,16 +298,16 @@ static const PragmaName *pragmaLocate(const char *zName){
|
||||
/*
|
||||
** Helper subroutine for PRAGMA integrity_check:
|
||||
**
|
||||
** Generate code to output a single-column result row with the result
|
||||
** held in register regResult. Decrement the result count and halt if
|
||||
** the maximum number of result rows have been issued.
|
||||
** Generate code to output a single-column result row with a value of the
|
||||
** string held in register 3. Decrement the result count in register 1
|
||||
** and halt if the maximum number of result rows have been issued.
|
||||
*/
|
||||
static int integrityCheckResultRow(Vdbe *v, int regResult){
|
||||
static int integrityCheckResultRow(Vdbe *v){
|
||||
int addr;
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
|
||||
addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
|
||||
VdbeCoverage(v);
|
||||
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
|
||||
sqlite3VdbeAddOp0(v, OP_Halt);
|
||||
return addr;
|
||||
}
|
||||
|
||||
@ -1484,12 +1484,11 @@ void sqlite3Pragma(
|
||||
|
||||
/* Do an integrity check on each database file */
|
||||
for(i=0; i<db->nDb; i++){
|
||||
HashElem *x;
|
||||
Hash *pTbls;
|
||||
int *aRoot;
|
||||
int cnt = 0;
|
||||
int mxIdx = 0;
|
||||
int nIdx;
|
||||
HashElem *x; /* For looping over tables in the schema */
|
||||
Hash *pTbls; /* Set of all tables in the schema */
|
||||
int *aRoot; /* Array of root page numbers of all btrees */
|
||||
int cnt = 0; /* Number of entries in aRoot[] */
|
||||
int mxIdx = 0; /* Maximum number of indexes for any table */
|
||||
|
||||
if( OMIT_TEMPDB && i==1 ) continue;
|
||||
if( iDb>=0 && i!=iDb ) continue;
|
||||
@ -1504,8 +1503,9 @@ void sqlite3Pragma(
|
||||
assert( sqlite3SchemaMutexHeld(db, i, 0) );
|
||||
pTbls = &db->aDb[i].pSchema->tblHash;
|
||||
for(cnt=0, x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
|
||||
Table *pTab = sqliteHashData(x);
|
||||
Index *pIdx;
|
||||
Table *pTab = sqliteHashData(x); /* Current table */
|
||||
Index *pIdx; /* An index on pTab */
|
||||
int nIdx; /* Number of indexes on pTab */
|
||||
if( HasRowid(pTab) ) cnt++;
|
||||
for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){ cnt++; }
|
||||
if( nIdx>mxIdx ) mxIdx = nIdx;
|
||||
@ -1533,9 +1533,8 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0,
|
||||
sqlite3MPrintf(db, "*** in database %s ***\n", db->aDb[i].zDbSName),
|
||||
P4_DYNAMIC);
|
||||
sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
|
||||
integrityCheckResultRow(v, 2);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 2, 3, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
|
||||
/* Make sure all the indices are constructed correctly.
|
||||
@ -1549,16 +1548,13 @@ void sqlite3Pragma(
|
||||
int r1 = -1;
|
||||
|
||||
if( pTab->tnum<1 ) continue; /* Skip VIEWs or VIRTUAL TABLEs */
|
||||
if( pTab->pCheck==0
|
||||
&& (pTab->tabFlags & TF_HasNotNull)==0
|
||||
&& (pTab->pIndex==0 || isQuick)
|
||||
){
|
||||
continue; /* No additional checks needed for this table */
|
||||
}
|
||||
pPk = HasRowid(pTab) ? 0 : sqlite3PrimaryKeyIndex(pTab);
|
||||
sqlite3ExprCacheClear(pParse);
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
|
||||
1, 0, &iDataCur, &iIdxCur);
|
||||
/* reg[7] counts the number of entries in the table.
|
||||
** reg[8+i] counts the number of entries in the i-th index
|
||||
*/
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 7);
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, 0, 8+j); /* index entries counter */
|
||||
@ -1579,11 +1575,10 @@ void sqlite3Pragma(
|
||||
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
|
||||
pTab->aCol[j].zName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
integrityCheckResultRow(v, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
}
|
||||
/* Verify CHECK constraints */
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
|
||||
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
|
||||
ExprList *pCheck = sqlite3ExprListDup(db, pTab->pCheck, 0);
|
||||
if( db->mallocFailed==0 ){
|
||||
@ -1603,57 +1598,62 @@ void sqlite3Pragma(
|
||||
zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
|
||||
pTab->zName);
|
||||
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
|
||||
integrityCheckResultRow(v, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeResolveLabel(v, addrCkOk);
|
||||
sqlite3ExprCachePop(pParse);
|
||||
}
|
||||
sqlite3ExprListDelete(db, pCheck);
|
||||
}
|
||||
/* Validate index entries for the current row */
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx && !isQuick; pIdx=pIdx->pNext, j++){
|
||||
int jmp2, jmp3, jmp4, jmp5;
|
||||
int ckUniq = sqlite3VdbeMakeLabel(v);
|
||||
if( pPk==pIdx ) continue;
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
|
||||
pPrior, r1);
|
||||
pPrior = pIdx;
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1); /* increment entry count */
|
||||
/* Verify that an index entry exists for the current table row */
|
||||
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
|
||||
pIdx->nColumn); VdbeCoverage(v);
|
||||
sqlite3VdbeLoadString(v, 3, "row ");
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
|
||||
sqlite3VdbeLoadString(v, 4, " missing from index ");
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
|
||||
jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
|
||||
jmp4 = integrityCheckResultRow(v, 3);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
/* For UNIQUE indexes, verify that only one entry exists with the
|
||||
** current key. The entry is unique if (1) any column is NULL
|
||||
** or (2) the next entry has a different key */
|
||||
if( IsUniqueIndex(pIdx) ){
|
||||
int uniqOk = sqlite3VdbeMakeLabel(v);
|
||||
int jmp6;
|
||||
int kk;
|
||||
for(kk=0; kk<pIdx->nKeyCol; kk++){
|
||||
int iCol = pIdx->aiColumn[kk];
|
||||
assert( iCol!=XN_ROWID && iCol<pTab->nCol );
|
||||
if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
|
||||
VdbeCoverage(v);
|
||||
if( !isQuick ){ /* Omit the remaining tests for quick_check */
|
||||
/* Sanity check on record header decoding */
|
||||
sqlite3VdbeAddOp3(v, OP_Column, iDataCur, pTab->nCol-1, 3);
|
||||
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
|
||||
/* Validate index entries for the current row */
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int jmp2, jmp3, jmp4, jmp5;
|
||||
int ckUniq = sqlite3VdbeMakeLabel(v);
|
||||
if( pPk==pIdx ) continue;
|
||||
r1 = sqlite3GenerateIndexKey(pParse, pIdx, iDataCur, 0, 0, &jmp3,
|
||||
pPrior, r1);
|
||||
pPrior = pIdx;
|
||||
sqlite3VdbeAddOp2(v, OP_AddImm, 8+j, 1);/* increment entry count */
|
||||
/* Verify that an index entry exists for the current table row */
|
||||
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
|
||||
pIdx->nColumn); VdbeCoverage(v);
|
||||
sqlite3VdbeLoadString(v, 3, "row ");
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 7, 3, 3);
|
||||
sqlite3VdbeLoadString(v, 4, " missing from index ");
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
|
||||
jmp5 = sqlite3VdbeLoadString(v, 4, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 3);
|
||||
jmp4 = integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, jmp2);
|
||||
/* For UNIQUE indexes, verify that only one entry exists with the
|
||||
** current key. The entry is unique if (1) any column is NULL
|
||||
** or (2) the next entry has a different key */
|
||||
if( IsUniqueIndex(pIdx) ){
|
||||
int uniqOk = sqlite3VdbeMakeLabel(v);
|
||||
int jmp6;
|
||||
int kk;
|
||||
for(kk=0; kk<pIdx->nKeyCol; kk++){
|
||||
int iCol = pIdx->aiColumn[kk];
|
||||
assert( iCol!=XN_ROWID && iCol<pTab->nCol );
|
||||
if( iCol>=0 && pTab->aCol[iCol].notNull ) continue;
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, r1+kk, uniqOk);
|
||||
VdbeCoverage(v);
|
||||
}
|
||||
jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
|
||||
sqlite3VdbeGoto(v, uniqOk);
|
||||
sqlite3VdbeJumpHere(v, jmp6);
|
||||
sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
|
||||
pIdx->nKeyCol); VdbeCoverage(v);
|
||||
sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
|
||||
sqlite3VdbeGoto(v, jmp5);
|
||||
sqlite3VdbeResolveLabel(v, uniqOk);
|
||||
}
|
||||
jmp6 = sqlite3VdbeAddOp1(v, OP_Next, iIdxCur+j); VdbeCoverage(v);
|
||||
sqlite3VdbeGoto(v, uniqOk);
|
||||
sqlite3VdbeJumpHere(v, jmp6);
|
||||
sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
|
||||
pIdx->nKeyCol); VdbeCoverage(v);
|
||||
sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
|
||||
sqlite3VdbeGoto(v, jmp5);
|
||||
sqlite3VdbeResolveLabel(v, uniqOk);
|
||||
sqlite3VdbeJumpHere(v, jmp4);
|
||||
sqlite3ResolvePartIdxLabel(pParse, jmp3);
|
||||
}
|
||||
sqlite3VdbeJumpHere(v, jmp4);
|
||||
sqlite3ResolvePartIdxLabel(pParse, jmp3);
|
||||
}
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
|
||||
sqlite3VdbeJumpHere(v, loopTop-1);
|
||||
@ -1665,9 +1665,9 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
|
||||
addr = sqlite3VdbeAddOp3(v, OP_Eq, 8+j, 0, 3); VdbeCoverage(v);
|
||||
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
|
||||
sqlite3VdbeLoadString(v, 3, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
|
||||
integrityCheckResultRow(v, 7);
|
||||
sqlite3VdbeLoadString(v, 4, pIdx->zName);
|
||||
sqlite3VdbeAddOp3(v, OP_Concat, 4, 2, 3);
|
||||
integrityCheckResultRow(v);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
}
|
||||
@ -1681,6 +1681,9 @@ void sqlite3Pragma(
|
||||
{ OP_IfNotZero, 1, 4, 0}, /* 1 */
|
||||
{ OP_String8, 0, 3, 0}, /* 2 */
|
||||
{ OP_ResultRow, 3, 1, 0}, /* 3 */
|
||||
{ OP_Halt, 0, 0, 0}, /* 4 */
|
||||
{ OP_String8, 0, 3, 0}, /* 5 */
|
||||
{ OP_Goto, 0, 3, 0}, /* 6 */
|
||||
};
|
||||
VdbeOp *aOp;
|
||||
|
||||
@ -1689,7 +1692,10 @@ void sqlite3Pragma(
|
||||
aOp[0].p2 = 1-mxErr;
|
||||
aOp[2].p4type = P4_STATIC;
|
||||
aOp[2].p4.z = "ok";
|
||||
aOp[5].p4type = P4_STATIC;
|
||||
aOp[5].p4.z = (char*)sqlite3ErrStr(SQLITE_CORRUPT);
|
||||
}
|
||||
sqlite3VdbeChangeP3(v, 0, sqlite3VdbeCurrentAddr(v)-2);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
20
src/vdbe.c
20
src/vdbe.c
@ -2461,8 +2461,7 @@ case OP_Column: {
|
||||
** extra bytes for the header length itself. 32768*3 + 3 = 98307.
|
||||
*/
|
||||
if( aOffset[0] > 98307 || aOffset[0] > pC->payloadSize ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto abort_due_to_error;
|
||||
goto op_column_corrupt;
|
||||
}
|
||||
}else{
|
||||
/* This is an optimization. By skipping over the first few tests
|
||||
@ -2535,8 +2534,7 @@ case OP_Column: {
|
||||
zHdr = zEndHdr;
|
||||
}else{
|
||||
if( pC->aRow==0 ) sqlite3VdbeMemRelease(&sMem);
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto abort_due_to_error;
|
||||
goto op_column_corrupt;
|
||||
}
|
||||
}
|
||||
|
||||
@ -2631,6 +2629,15 @@ op_column_out:
|
||||
UPDATE_MAX_BLOBSIZE(pDest);
|
||||
REGISTER_TRACE(pOp->p3, pDest);
|
||||
break;
|
||||
|
||||
op_column_corrupt:
|
||||
if( aOp[0].p3>0 ){
|
||||
pOp = &aOp[aOp[0].p3-1];
|
||||
break;
|
||||
}else{
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
goto abort_due_to_error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Opcode: Affinity P1 P2 * P4 *
|
||||
@ -7015,7 +7022,7 @@ case OP_Function: {
|
||||
}
|
||||
|
||||
|
||||
/* Opcode: Init P1 P2 * P4 *
|
||||
/* Opcode: Init P1 P2 P3 P4 *
|
||||
** Synopsis: Start at P2
|
||||
**
|
||||
** Programs contain a single instance of this opcode as the very first
|
||||
@ -7029,6 +7036,9 @@ case OP_Function: {
|
||||
**
|
||||
** Increment the value of P1 so that OP_Once opcodes will jump the
|
||||
** first time they are evaluated for this run.
|
||||
**
|
||||
** If P3 is not zero, then it is an address to jump to if an SQLITE_CORRUPT
|
||||
** error is encountered.
|
||||
*/
|
||||
case OP_Init: { /* jump */
|
||||
char *zTrace;
|
||||
|
@ -2158,27 +2158,6 @@ static void closeAllCursors(Vdbe *p){
|
||||
assert( p->pAuxData==0 );
|
||||
}
|
||||
|
||||
/*
|
||||
** Clean up the VM after a single run.
|
||||
*/
|
||||
static void Cleanup(Vdbe *p){
|
||||
sqlite3 *db = p->db;
|
||||
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Execute assert() statements to ensure that the Vdbe.apCsr[] and
|
||||
** Vdbe.aMem[] arrays have already been cleaned up. */
|
||||
int i;
|
||||
if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
|
||||
if( p->aMem ){
|
||||
for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
|
||||
}
|
||||
#endif
|
||||
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
p->pResultSet = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the number of result columns that will be returned by this SQL
|
||||
** statement. This is now set at compile time, rather than during
|
||||
@ -2904,8 +2883,6 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
if( p->pc>=0 ){
|
||||
vdbeInvokeSqllog(p);
|
||||
sqlite3VdbeTransferError(p);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
if( p->runOnlyOnce ) p->expired = 1;
|
||||
}else if( p->rc && p->expired ){
|
||||
/* The expired flag was set on the VDBE before the first call
|
||||
@ -2913,13 +2890,22 @@ int sqlite3VdbeReset(Vdbe *p){
|
||||
** called), set the database error in this case as well.
|
||||
*/
|
||||
sqlite3ErrorWithMsg(db, p->rc, p->zErrMsg ? "%s" : 0, p->zErrMsg);
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
}
|
||||
|
||||
/* Reclaim all memory used by the VDBE
|
||||
/* Reset register contents and reclaim error message memory.
|
||||
*/
|
||||
Cleanup(p);
|
||||
#ifdef SQLITE_DEBUG
|
||||
/* Execute assert() statements to ensure that the Vdbe.apCsr[] and
|
||||
** Vdbe.aMem[] arrays have already been cleaned up. */
|
||||
int i;
|
||||
if( p->apCsr ) for(i=0; i<p->nCursor; i++) assert( p->apCsr[i]==0 );
|
||||
if( p->aMem ){
|
||||
for(i=0; i<p->nMem; i++) assert( p->aMem[i].flags==MEM_Undefined );
|
||||
}
|
||||
#endif
|
||||
sqlite3DbFree(db, p->zErrMsg);
|
||||
p->zErrMsg = 0;
|
||||
p->pResultSet = 0;
|
||||
|
||||
/* Save profiling information from this VDBE run.
|
||||
*/
|
||||
|
@ -1953,7 +1953,7 @@ do_catchsql_test 24.1 {
|
||||
} {1 {database disk image is malformed}}
|
||||
do_catchsql_test 24.2 {
|
||||
PRAGMA integrity_check;
|
||||
} {1 {database disk image is malformed}}
|
||||
} {0 {{database disk image is malformed}}}
|
||||
|
||||
database_never_corrupt
|
||||
finish_test
|
||||
|
Loading…
x
Reference in New Issue
Block a user