Merge integrity_check and other improvements from trunk.

FossilOrigin-Name: fe073905081b421405ca425ca03c5b8b0ff5f2c8
This commit is contained in:
drh 2017-02-22 19:49:54 +00:00
commit 114ce7a4b1
13 changed files with 280 additions and 85 deletions

View File

@ -1110,7 +1110,10 @@ static int fts5ExprNodeNext_OR(
|| (bFromValid && fts5RowidCmp(pExpr, p1->iRowid, iFrom)<0)
){
int rc = fts5ExprNodeNext(pExpr, p1, bFromValid, iFrom);
if( rc!=SQLITE_OK ) return rc;
if( rc!=SQLITE_OK ){
pNode->bNomatch = 0;
return rc;
}
}
}
}
@ -1141,7 +1144,10 @@ static int fts5ExprNodeTest_AND(
if( cmp>0 ){
/* Advance pChild until it points to iLast or laster */
rc = fts5ExprNodeNext(pExpr, pChild, 1, iLast);
if( rc!=SQLITE_OK ) return rc;
if( rc!=SQLITE_OK ){
pAnd->bNomatch = 0;
return rc;
}
}
/* If the child node is now at EOF, so is the parent AND node. Otherwise,
@ -1180,6 +1186,8 @@ static int fts5ExprNodeNext_AND(
int rc = fts5ExprNodeNext(pExpr, pNode->apChild[0], bFromValid, iFrom);
if( rc==SQLITE_OK ){
rc = fts5ExprNodeTest_AND(pExpr, pNode);
}else{
pNode->bNomatch = 0;
}
return rc;
}
@ -1222,6 +1230,9 @@ static int fts5ExprNodeNext_NOT(
if( rc==SQLITE_OK ){
rc = fts5ExprNodeTest_NOT(pExpr, pNode);
}
if( rc!=SQLITE_OK ){
pNode->bNomatch = 0;
}
return rc;
}

View File

@ -0,0 +1,87 @@
# 2016 February 2
#
# The author disclaims copyright to this source code. In place of
# a legal notice, here is a blessing:
#
# May you do good and not evil.
# May you find forgiveness for yourself and forgive others.
# May you share freely, never taking more than you give.
#
#*************************************************************************
#
# This file is focused on OOM errors.
#
source [file join [file dirname [info script]] fts5_common.tcl]
source $testdir/malloc_common.tcl
set testprefix fts5faultA
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
ifcapable !fts5 {
finish_test
return
}
foreach_detail_mode $testprefix {
if {"%DETAIL%"=="none"} continue
do_execsql_test 1.0 {
CREATE VIRTUAL TABLE o1 USING fts5(a, b, c, detail=%DETAIL%);
INSERT INTO o1(o1, rank) VALUES('pgsz', 32);
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
INSERT INTO o1 SELECT 'A', 'B', 'C' FROM s;
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
INSERT INTO o1 SELECT 'C', 'A', 'B' FROM s;
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<60 )
INSERT INTO o1 SELECT 'B', 'C', 'A' FROM s;
}
do_faultsim_test 1 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT count(*) FROM o1('a') }
} -test {
faultsim_test_result {0 180} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 2 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT * FROM o1('a:a AND {b c}:b') ORDER BY rank }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 3 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT * FROM o1('{b c}:b NOT a:a') ORDER BY rank }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 4 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT * FROM o1('b:b OR a:a') }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
do_faultsim_test 5 -faults int* -prep {
sqlite3 db test.db
} -body {
execsql { SELECT count(*) FROM o1('c:b') }
expr 1
} -test {
faultsim_test_result {0 1} {1 {vtable constructor failed: o1}}
}
}
finish_test

View File

@ -1,5 +1,5 @@
C Merge\sfixes\sfrom\strunk.
D 2017-02-20T13:11:07.110
C Merge\sintegrity_check\sand\sother\simprovements\sfrom\strunk.
D 2017-02-22T19:49:54.795
F Makefile.in edb6bcdd37748d2b1c3422ff727c748df7ffe918
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc a89ea37ab5928026001569f056973b9059492fe2
@ -102,7 +102,7 @@ F ext/fts5/fts5Int.h c629b24d2b92b99596f3b8e82289fddca06df6e1
F ext/fts5/fts5_aux.c 67acf8d51723cf28ffc3828210ba662df4b8d267
F ext/fts5/fts5_buffer.c 4c1502d4c956cd092c89ce4480867f9d8bf325cd
F ext/fts5/fts5_config.c 5af9c360e99669d29f06492c370892394aba0857
F ext/fts5/fts5_expr.c 33f0e8063ac7360bcd71c0ff0dcbacdc05fffe50
F ext/fts5/fts5_expr.c c6ecc2280162a3714d15dce2a8f2299f748b627c
F ext/fts5/fts5_hash.c 880998e596b60f078348d48732ca4ad9a90caad2
F ext/fts5/fts5_index.c f67032a9a529ba52a545e6e3ab970764199c05d4
F ext/fts5/fts5_main.c f85281445dcf8be32d18841c93a6f90fe27dbfe2
@ -160,6 +160,7 @@ F ext/fts5/test/fts5fault8.test 6785af34bd1760de74e2824ea9c161965af78f85
F ext/fts5/test/fts5fault9.test e10e395428a9ea0596ebe752ff7123d16ab78e08
F ext/fts5/test/fts5faultA.test fa5d59c0ff62b7125cd14eee38ded1c46e15a7ea
F ext/fts5/test/fts5faultB.test 7f3bba790fa172073ac314f9b8ed197390b61eca
F ext/fts5/test/fts5faultD.test cc5d1225556e356615e719c612e845d41bff7d5a
F ext/fts5/test/fts5full.test 6f6143af0c6700501d9fd597189dfab1555bb741
F ext/fts5/test/fts5fuzz1.test bece4695fc169b61ab236ada7931c6e4942cbef9
F ext/fts5/test/fts5hash.test 06f9309ccb4d5050a131594e9e47d0b21456837d
@ -331,7 +332,7 @@ F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
F src/alter.c 3b23977620ce9662ac54443f65b87ba996e36121
F src/analyze.c 1b7197d619788353437d390de42a9bccbb4aa2ac
F src/analyze.c b4857ec5b46b66049e5a3cec53c071c4902a8e8b
F src/attach.c 8c476f8bd5d2afe11d925f890d30e527e5b0ce43
F src/auth.c 930b376a9c56998557367e6f7f8aaeac82a2a792
F src/backup.c faf17e60b43233c214aae6a8179d24503a61e83b
@ -340,7 +341,7 @@ F src/btmutex.c 0e9ce2d56159b89b9bc8e197e023ee11e39ff8ca
F src/btree.c a4ab1fb5cdeea88c4f76216e41cfecfa505c8c43
F src/btree.h bf64dfeeddeebdb775a5eba0098bbc00d073290d
F src/btreeInt.h cd55d39d9916270837a88c12e701047cba0729b0
F src/build.c 2e05d0360568f40dc583461f2211f020ff282ee4
F src/build.c 43f903c9082040ced2b421543cb0300c2973647d
F src/callback.c 2e76147783386374bf01b227f752c81ec872d730
F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
F src/ctime.c a9984df73898c042a5cfc8f9d8e7723d02bc35c9
@ -379,15 +380,15 @@ F src/os.h 8e976e59eb4ca1c0fca6d35ee803e38951cb0343
F src/os_common.h b2f4707a603e36811d9b1a13278bffd757857b85
F src/os_setup.h 0dbaea40a7d36bf311613d31342e0b99e2536586
F src/os_unix.c 30e2c43e4955db990e5b5a81e901f8aa74cc8820
F src/os_win.c cf90abd4e50d9f56d2c20ce8e005aff55d7bd8e9
F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
F src/parse.y 591704fce84f814d9a3642774c1f011d38f4149c
F src/parse.y af8830094f4aecb91cb69721f3601ad10c36abc4
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
F src/pcache1.c e3967219b2a92b9edcb9324a4ba75009090d3953
F src/pragma.c 8a35509e8f60746fbdcde5312ddfd177c46c7e9c
F src/pragma.c 97742aae32e645926f6f8fc426169fb5ef97c268
F src/pragma.h 065e184494f12e94111da1ab6984faa7b6142e68
F src/prepare.c b1140c3d0cf59bc85ace00ce363153041b424b7a
F src/printf.c 67427bbee66d891fc6f6f5aada857e9cdb368c1c
@ -399,7 +400,7 @@ F src/shell.c bf976d5301be9d8a4c52852c97909cc9a41ee20d
F src/sqlite.h.in 751ff125eb159c8f92c182b8df980a5e4f50e966
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
F src/sqliteInt.h 87857c2b8d8825e22970ce3f466b8618ee55b44e
F src/sqliteInt.h bdc181e371ea618c85f30b4c5ee4d80f4ada6ad7
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
F src/table.c b46ad567748f24a326d9de40e5b9659f96ffff34
@ -461,11 +462,11 @@ F src/update.c 456d4a4656f8a03c2abc88a51b19172197400e58
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
F src/vdbe.c 02f9db522c73ba4e1743585e9fd6f8ac6c71515b
F src/vdbe.c 37e95d52675bd839cc6c209f6b8d907582a27d44
F src/vdbe.h 59998ffd71d7caa8886bc78dafaf8caeccd4c13c
F src/vdbeInt.h 4e4b15b2e1330e1636e4e01974eab2b0b985092f
F src/vdbeapi.c 3e4a8893feeb78620f4aac4ac5b85d92255b97e1
F src/vdbeaux.c 4122458d33318ab039c4b5da1ca4e7c9221c38e4
F src/vdbeaux.c 2f48204a0f2875b098ee046bba9265907297b0b5
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
F src/vdbemem.c 3b5a9a5b375458d3e12a50ae1aaa41eeec2175fd
F src/vdbesort.c eda25cb2d1727efca6f7862fea32b8aa33c0face
@ -576,7 +577,7 @@ F test/capi3d.test 485048dc5cd07bc68011e4917ad035ad6047ab82
F test/capi3e.test 3d49c01ef2a1a55f41d73cba2b23b5059ec460fe
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/cffault.test 9d6b20606afe712374952eec4f8fd74b1a8097ef
F test/check.test 85a84bfc4be0e83f668747211c7cd45a6721d485
F test/check.test 92b23a91fb7be12fba7ee9ce518217e2919a21da
F test/close.test 83947daf3b700631f90f4850ddaab455be4af73d
F test/closure01.test b1703ba40639cfc9b295cf478d70739415eec6a4
F test/coalesce.test cee0dccb9fbd2d494b77234bccf9dc6c6786eb91
@ -1557,7 +1558,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P e842ad391e62df273a5b1ed569d42ea46d03a99b 491814272dce7e937b4734fcbc2ad69e12377b56
R 9def7926ef27f77a7e1d535aaff2eb82
P ff213f2ef5bf96754a2264685d25546d8b5ccf0a d6afd98de3ee8b714dfd6477ead955096f623972
R c12096fa1c0a2878a437d029e47aff9d
U drh
Z ee1e0d41251dc153fd55728fd5740a3d
Z 3c7beae38049bf1fe67e75122f4d0189

View File

@ -1 +1 @@
ff213f2ef5bf96754a2264685d25546d8b5ccf0a
fe073905081b421405ca425ca03c5b8b0ff5f2c8

View File

@ -290,6 +290,7 @@ struct Stat4Accum {
Stat4Sample *aBest; /* Array of nCol best samples */
int iMin; /* Index in a[] of entry with minimum score */
int nSample; /* Current number of samples */
int nMaxEqZero; /* Max leading 0 in anEq[] for any a[] entry */
int iGet; /* Index of current sample accessed by stat_get() */
Stat4Sample *a; /* Array of mxSample Stat4Sample objects */
sqlite3 *db; /* Database connection, for malloc() */
@ -554,6 +555,13 @@ static void sampleInsert(Stat4Accum *p, Stat4Sample *pNew, int nEqZero){
assert( IsStat4 || nEqZero==0 );
#ifdef SQLITE_ENABLE_STAT4
/* Stat4Accum.nMaxEqZero is set to the maximum number of leading 0
** values in the anEq[] array of any sample in Stat4Accum.a[]. In
** other words, if nMaxEqZero is n, then it is guaranteed that there
** are no samples with Stat4Sample.anEq[m]==0 for (m>=n). */
if( nEqZero>p->nMaxEqZero ){
p->nMaxEqZero = nEqZero;
}
if( pNew->isPSample==0 ){
Stat4Sample *pUpgrade = 0;
assert( pNew->anEq[pNew->iCol]>0 );
@ -651,12 +659,22 @@ static void samplePushPrevious(Stat4Accum *p, int iChng){
}
}
/* Update the anEq[] fields of any samples already collected. */
/* Check that no sample contains an anEq[] entry with an index of
** p->nMaxEqZero or greater set to zero. */
for(i=p->nSample-1; i>=0; i--){
int j;
for(j=iChng; j<p->nCol; j++){
if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
for(j=p->nMaxEqZero; j<p->nCol; j++) assert( p->a[i].anEq[j]>0 );
}
/* Update the anEq[] fields of any samples already collected. */
if( iChng<p->nMaxEqZero ){
for(i=p->nSample-1; i>=0; i--){
int j;
for(j=iChng; j<p->nCol; j++){
if( p->a[i].anEq[j]==0 ) p->a[i].anEq[j] = p->current.anEq[j];
}
}
p->nMaxEqZero = iChng;
}
#endif

View File

@ -1115,6 +1115,7 @@ void sqlite3AddNotNull(Parse *pParse, int onError){
p = pParse->pNewTable;
if( p==0 || NEVER(p->nCol<1) ) return;
p->aCol[p->nCol-1].notNull = (u8)onError;
p->tabFlags |= TF_HasNotNull;
}
/*

View File

@ -352,7 +352,34 @@ struct winVfsAppData {
******************************************************************************
*/
#ifndef SQLITE_WIN32_HEAP_CREATE
# define SQLITE_WIN32_HEAP_CREATE (TRUE)
# define SQLITE_WIN32_HEAP_CREATE (TRUE)
#endif
/*
* This is the maximum possible initial size of the Win32-specific heap, in
* bytes.
*/
#ifndef SQLITE_WIN32_HEAP_MAX_INIT_SIZE
# define SQLITE_WIN32_HEAP_MAX_INIT_SIZE (4294967295U)
#endif
/*
* This is the extra space for the initial size of the Win32-specific heap,
* in bytes. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_INIT_EXTRA
# define SQLITE_WIN32_HEAP_INIT_EXTRA (4194304)
#endif
/*
* Calculate the maximum legal cache size, in pages, based on the maximum
* possible initial heap size and the default page size, setting aside the
* needed extra space.
*/
#ifndef SQLITE_WIN32_MAX_CACHE_SIZE
# define SQLITE_WIN32_MAX_CACHE_SIZE (((SQLITE_WIN32_HEAP_MAX_INIT_SIZE) - \
(SQLITE_WIN32_HEAP_INIT_EXTRA)) / \
(SQLITE_DEFAULT_PAGE_SIZE))
#endif
/*
@ -361,25 +388,36 @@ struct winVfsAppData {
*/
#ifndef SQLITE_WIN32_CACHE_SIZE
# if SQLITE_DEFAULT_CACHE_SIZE>=0
# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
# define SQLITE_WIN32_CACHE_SIZE (SQLITE_DEFAULT_CACHE_SIZE)
# else
# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
# define SQLITE_WIN32_CACHE_SIZE (-(SQLITE_DEFAULT_CACHE_SIZE))
# endif
#endif
/*
* Make sure that the calculated cache size, in pages, cannot cause the
* initial size of the Win32-specific heap to exceed the maximum amount
* of memory that can be specified in the call to HeapCreate.
*/
#if SQLITE_WIN32_CACHE_SIZE>SQLITE_WIN32_MAX_CACHE_SIZE
# undef SQLITE_WIN32_CACHE_SIZE
# define SQLITE_WIN32_CACHE_SIZE (2000)
#endif
/*
* The initial size of the Win32-specific heap. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_INIT_SIZE
# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
(SQLITE_DEFAULT_PAGE_SIZE) + 4194304)
# define SQLITE_WIN32_HEAP_INIT_SIZE ((SQLITE_WIN32_CACHE_SIZE) * \
(SQLITE_DEFAULT_PAGE_SIZE) + \
(SQLITE_WIN32_HEAP_INIT_EXTRA))
#endif
/*
* The maximum size of the Win32-specific heap. This value may be zero.
*/
#ifndef SQLITE_WIN32_HEAP_MAX_SIZE
# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
# define SQLITE_WIN32_HEAP_MAX_SIZE (0)
#endif
/*
@ -387,7 +425,7 @@ struct winVfsAppData {
* zero for the default behavior.
*/
#ifndef SQLITE_WIN32_HEAP_FLAGS
# define SQLITE_WIN32_HEAP_FLAGS (0)
# define SQLITE_WIN32_HEAP_FLAGS (0)
#endif

View File

@ -1000,7 +1000,7 @@ expr(A) ::= expr(A) STAR|SLASH|REM(OP) expr(Y).
{spanBinaryExpr(pParse,@OP,&A,&Y);}
expr(A) ::= expr(A) CONCAT(OP) expr(Y). {spanBinaryExpr(pParse,@OP,&A,&Y);}
%type likeop {Token}
likeop(A) ::= LIKE_KW|MATCH(X). {A=X;/*A-overwrites-X*/}
likeop(A) ::= LIKE_KW|MATCH(A).
likeop(A) ::= NOT LIKE_KW|MATCH(X). {A=X; A.n|=0x80000000; /*A-overwrite-X*/}
expr(A) ::= expr(A) likeop(OP) expr(Y). [LIKE_KW] {
ExprList *pList;

View File

@ -295,6 +295,22 @@ static const PragmaName *pragmaLocate(const char *zName){
return lwr>upr ? 0 : &aPragmaName[mid];
}
/*
** 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.
*/
static int integrityCheckResultRow(Vdbe *v, int regResult){
int addr;
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 1);
addr = sqlite3VdbeAddOp3(v, OP_IfPos, 1, sqlite3VdbeCurrentAddr(v)+2, 1);
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
return addr;
}
/*
** Process a pragma statement.
**
@ -1381,9 +1397,17 @@ void sqlite3Pragma(
#endif
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/* Pragma "quick_check" is reduced version of
/* PRAGMA integrity_check
** PRAGMA integrity_check(N)
** PRAGMA quick_check
** PRAGMA quick_check(N)
**
** Verify the integrity of the database.
**
** The "quick_check" is reduced version of
** integrity_check designed to detect most database corruption
** without most of the overhead of a full integrity-check.
** without the overhead of cross-checking indexes. Quick_check
** is linear time wherease integrity_check is O(NlogN).
*/
case PragTyp_INTEGRITY_CHECK: {
int i, j, addr, mxErr;
@ -1414,7 +1438,7 @@ void sqlite3Pragma(
mxErr = SQLITE_INTEGRITY_CHECK_ERROR_MAX;
}
}
sqlite3VdbeAddOp2(v, OP_Integer, mxErr, 1); /* reg[1] holds errors left */
sqlite3VdbeAddOp2(v, OP_Integer, mxErr-1, 1); /* reg[1] holds errors left */
/* Do an integrity check on each database file */
for(i=0; i<db->nDb; i++){
@ -1429,10 +1453,6 @@ void sqlite3Pragma(
if( iDb>=0 && i!=iDb ) continue;
sqlite3CodeVerifySchema(pParse, i);
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Halt if out of errors */
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr);
/* Do an integrity check of the B-Tree
**
@ -1472,12 +1492,12 @@ void sqlite3Pragma(
P4_DYNAMIC);
sqlite3VdbeAddOp3(v, OP_Move, 2, 4, 1);
sqlite3VdbeAddOp3(v, OP_Concat, 4, 3, 2);
sqlite3VdbeAddOp2(v, OP_ResultRow, 2, 1);
integrityCheckResultRow(v, 2);
sqlite3VdbeJumpHere(v, addr);
/* Make sure all the indices are constructed correctly.
*/
for(x=sqliteHashFirst(pTbls); x && !isQuick; x=sqliteHashNext(x)){
for(x=sqliteHashFirst(pTbls); x; x=sqliteHashNext(x)){
Table *pTab = sqliteHashData(x);
Index *pIdx, *pPk;
Index *pPrior = 0;
@ -1485,12 +1505,13 @@ void sqlite3Pragma(
int iDataCur, iIdxCur;
int r1 = -1;
if( pTab->pIndex==0 ) continue;
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);
addr = sqlite3VdbeAddOp1(v, OP_IfPos, 1); /* Stop if out of errors */
VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeJumpHere(v, addr);
sqlite3ExprCacheClear(pParse);
sqlite3OpenTableAndIndices(pParse, pTab, OP_OpenRead, 0,
1, 0, &iDataCur, &iIdxCur);
@ -1505,24 +1526,42 @@ void sqlite3Pragma(
/* Verify that all NOT NULL columns really are NOT NULL */
for(j=0; j<pTab->nCol; j++){
char *zErr;
int jmp2, jmp3;
int jmp2;
if( j==pTab->iPKey ) continue;
if( pTab->aCol[j].notNull==0 ) continue;
sqlite3ExprCodeGetColumnOfTable(v, pTab, iDataCur, j, 3);
sqlite3VdbeChangeP5(v, OPFLAG_TYPEOFARG);
jmp2 = sqlite3VdbeAddOp1(v, OP_NotNull, 3); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
zErr = sqlite3MPrintf(db, "NULL value in %s.%s", pTab->zName,
pTab->aCol[j].zName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
jmp3 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
sqlite3VdbeAddOp0(v, OP_Halt);
integrityCheckResultRow(v, 3);
sqlite3VdbeJumpHere(v, jmp2);
sqlite3VdbeJumpHere(v, jmp3);
}
/* Verify CHECK constraints */
if( pTab->pCheck && (db->flags & SQLITE_IgnoreChecks)==0 ){
int addrCkFault = sqlite3VdbeMakeLabel(v);
int addrCkOk = sqlite3VdbeMakeLabel(v);
ExprList *pCheck = pTab->pCheck;
char *zErr;
int k;
pParse->iSelfTab = iDataCur;
sqlite3ExprCachePush(pParse);
for(k=pCheck->nExpr-1; k>0; k--){
sqlite3ExprIfFalse(pParse, pCheck->a[k].pExpr, addrCkFault, 0);
}
sqlite3ExprIfTrue(pParse, pCheck->a[0].pExpr, addrCkOk,
SQLITE_JUMPIFNULL);
sqlite3VdbeResolveLabel(v, addrCkFault);
zErr = sqlite3MPrintf(db, "CHECK constraint failed in %s",
pTab->zName);
sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, zErr, P4_DYNAMIC);
integrityCheckResultRow(v, 3);
sqlite3VdbeResolveLabel(v, addrCkOk);
sqlite3ExprCachePop(pParse);
}
/* Validate index entries for the current row */
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
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;
@ -1533,16 +1572,13 @@ void sqlite3Pragma(
/* Verify that an index entry exists for the current table row */
jmp2 = sqlite3VdbeAddOp4Int(v, OP_Found, iIdxCur+j, ckUniq, r1,
pIdx->nColumn); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
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);
sqlite3VdbeAddOp2(v, OP_ResultRow, 3, 1);
jmp4 = sqlite3VdbeAddOp1(v, OP_IfPos, 1); VdbeCoverage(v);
sqlite3VdbeAddOp0(v, OP_Halt);
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
@ -1563,7 +1599,6 @@ void sqlite3Pragma(
sqlite3VdbeJumpHere(v, jmp6);
sqlite3VdbeAddOp4Int(v, OP_IdxGT, iIdxCur+j, uniqOk, r1,
pIdx->nKeyCol); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1); /* Decrement error limit */
sqlite3VdbeLoadString(v, 3, "non-unique entry in index ");
sqlite3VdbeGoto(v, jmp5);
sqlite3VdbeResolveLabel(v, uniqOk);
@ -1574,19 +1609,18 @@ void sqlite3Pragma(
sqlite3VdbeAddOp2(v, OP_Next, iDataCur, loopTop); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, loopTop-1);
#ifndef SQLITE_OMIT_BTREECOUNT
sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( pPk==pIdx ) continue;
addr = sqlite3VdbeCurrentAddr(v);
sqlite3VdbeAddOp2(v, OP_IfPos, 1, addr+2); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_Halt, 0, 0);
sqlite3VdbeAddOp2(v, OP_Count, iIdxCur+j, 3);
sqlite3VdbeAddOp3(v, OP_Eq, 8+j, addr+8, 3); VdbeCoverage(v);
sqlite3VdbeChangeP5(v, SQLITE_NOTNULL);
sqlite3VdbeAddOp2(v, OP_AddImm, 1, -1);
sqlite3VdbeLoadString(v, 3, pIdx->zName);
sqlite3VdbeAddOp3(v, OP_Concat, 3, 2, 7);
sqlite3VdbeAddOp2(v, OP_ResultRow, 7, 1);
if( !isQuick ){
sqlite3VdbeLoadString(v, 2, "wrong # of entries in index ");
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
if( pPk==pIdx ) continue;
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);
sqlite3VdbeJumpHere(v, addr);
}
}
#endif /* SQLITE_OMIT_BTREECOUNT */
}
@ -1595,7 +1629,7 @@ void sqlite3Pragma(
static const int iLn = VDBE_OFFSET_LINENO(2);
static const VdbeOpList endCode[] = {
{ OP_AddImm, 1, 0, 0}, /* 0 */
{ OP_If, 1, 4, 0}, /* 1 */
{ OP_IfNotZero, 1, 4, 0}, /* 1 */
{ OP_String8, 0, 3, 0}, /* 2 */
{ OP_ResultRow, 3, 1, 0}, /* 3 */
};
@ -1603,7 +1637,7 @@ void sqlite3Pragma(
aOp = sqlite3VdbeAddOpList(v, ArraySize(endCode), endCode, iLn);
if( aOp ){
aOp[0].p2 = -mxErr;
aOp[0].p2 = 1-mxErr;
aOp[2].p4type = P4_STATIC;
aOp[2].p4.z = "ok";
}

View File

@ -1889,6 +1889,7 @@ struct Table {
#define TF_OOOHidden 0x0080 /* Out-of-Order hidden columns */
#define TF_StatsUsed 0x0100 /* Query planner decisions affected by
** Index.aiRowLogEst[] values */
#define TF_HasNotNull 0x0200 /* Contains NOT NULL constraints */
/*
** Test to see whether or not a table is a virtual table. This is

View File

@ -1669,21 +1669,21 @@ case OP_Function: {
for(i=pCtx->argc-1; i>=0; i--) pCtx->argv[i] = &aMem[pOp->p2+i];
}
memAboutToChange(p, pCtx->pOut);
memAboutToChange(p, pOut);
#ifdef SQLITE_DEBUG
for(i=0; i<pCtx->argc; i++){
assert( memIsValid(pCtx->argv[i]) );
REGISTER_TRACE(pOp->p2+i, pCtx->argv[i]);
}
#endif
MemSetTypeFlag(pCtx->pOut, MEM_Null);
MemSetTypeFlag(pOut, MEM_Null);
pCtx->fErrorOrAux = 0;
(*pCtx->pFunc->xSFunc)(pCtx, pCtx->argc, pCtx->argv);/* IMP: R-24505-23230 */
/* If the function returned an error, throw an exception */
if( pCtx->fErrorOrAux ){
if( pCtx->isError ){
sqlite3VdbeError(p, "%s", sqlite3_value_text(pCtx->pOut));
sqlite3VdbeError(p, "%s", sqlite3_value_text(pOut));
rc = pCtx->isError;
}
sqlite3VdbeDeleteAuxData(db, &p->pAuxData, pCtx->iOp, pOp->p1);
@ -1692,12 +1692,12 @@ case OP_Function: {
/* Copy the result of the function into register P3 */
if( pOut->flags & (MEM_Str|MEM_Blob) ){
sqlite3VdbeChangeEncoding(pCtx->pOut, encoding);
if( sqlite3VdbeMemTooBig(pCtx->pOut) ) goto too_big;
sqlite3VdbeChangeEncoding(pOut, encoding);
if( sqlite3VdbeMemTooBig(pOut) ) goto too_big;
}
REGISTER_TRACE(pOp->p3, pCtx->pOut);
UPDATE_MAX_BLOBSIZE(pCtx->pOut);
REGISTER_TRACE(pOp->p3, pOut);
UPDATE_MAX_BLOBSIZE(pOut);
break;
}
@ -5648,7 +5648,7 @@ case OP_DropTrigger: {
** register P1 the text of an error message describing any problems.
** If no problems are found, store a NULL in register P1.
**
** The register P3 contains the maximum number of allowed errors.
** The register P3 contains one less than the maximum number of allowed errors.
** At most reg(P3) errors will be reported.
** In other words, the analysis stops as soon as reg(P1) errors are
** seen. Reg(P1) is updated with the number of errors remaining.
@ -5681,14 +5681,14 @@ case OP_IntegrityCk: {
assert( pOp->p5<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p5) );
z = sqlite3BtreeIntegrityCheck(db->aDb[pOp->p5].pBt, aRoot, nRoot,
(int)pnErr->u.i, &nErr);
pnErr->u.i -= nErr;
(int)pnErr->u.i+1, &nErr);
sqlite3VdbeMemSetNull(pIn1);
if( nErr==0 ){
assert( z==0 );
}else if( z==0 ){
goto no_mem;
}else{
pnErr->u.i -= nErr-1;
sqlite3VdbeMemSetStr(pIn1, z, -1, SQLITE_UTF8, sqlite3_free);
}
UPDATE_MAX_BLOBSIZE(pIn1);

View File

@ -2609,13 +2609,13 @@ int sqlite3VdbeHalt(Vdbe *p){
** one, or the complete transaction if there is no statement transaction.
*/
if( p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_OK;
}
if( db->mallocFailed ){
p->rc = SQLITE_NOMEM_BKPT;
}
closeAllCursors(p);
if( p->magic!=VDBE_MAGIC_RUN ){
return SQLITE_OK;
}
checkActiveVdbeCnt(db);
/* No commit or rollback needed if the program never started or if the

View File

@ -309,11 +309,15 @@ do_test check-4.8 {
PRAGMA ignore_check_constraints=ON;
UPDATE t4 SET x=0, y=1;
SELECT * FROM t4;
PRAGMA integrity_check;
}
} {0 1}
} {0 1 ok}
do_execsql_test check-4.8.1 {
PRAGMA ignore_check_constraints=OFF;
PRAGMA integrity_check;
} {{CHECK constraint failed in t4}}
do_test check-4.9 {
catchsql {
PRAGMA ignore_check_constraints=OFF;
UPDATE t4 SET x=0, y=2;
}
} {1 {CHECK constraint failed: t4}}