aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <Dan Kennedy>2024-02-26 12:16:02 +0000
committerdan <Dan Kennedy>2024-02-26 12:16:02 +0000
commit09e1900cdcd40548a8d1dfb15076f77c80e492c7 (patch)
treec929fca2c2a2f61458bb189d01dfa3c08a88fbbd /src
parentf286ad9211dceab80dc81e9207afdeac80bc777e (diff)
parent1103eb423e7c975ba77f8a9a10b0667636191be8 (diff)
downloadsqlite-09e1900cdcd40548a8d1dfb15076f77c80e492c7.tar.gz
sqlite-09e1900cdcd40548a8d1dfb15076f77c80e492c7.zip
Add the intck extension. For performing incremental integrity-check on a database.
FossilOrigin-Name: 141d8bb059f8987d05d18327b97c4d36e98258f657b41a3d4d8877fe8b4e72e3
Diffstat (limited to 'src')
-rw-r--r--src/shell.c.in53
-rw-r--r--src/test_tclsh.c2
-rw-r--r--src/where.c4
3 files changed, 58 insertions, 1 deletions
diff --git a/src/shell.c.in b/src/shell.c.in
index da377982e..07e4b201c 100644
--- a/src/shell.c.in
+++ b/src/shell.c.in
@@ -1222,6 +1222,9 @@ INCLUDE ../ext/misc/sqlar.c
INCLUDE ../ext/expert/sqlite3expert.h
INCLUDE ../ext/expert/sqlite3expert.c
+INCLUDE ../ext/intck/sqlite3intck.h
+INCLUDE ../ext/intck/sqlite3intck.c
+
#if !defined(SQLITE_OMIT_VIRTUALTABLE) && defined(SQLITE_ENABLE_DBPAGE_VTAB)
#define SQLITE_SHELL_HAVE_RECOVER 1
#else
@@ -4741,6 +4744,7 @@ static const char *(azHelp[]) = {
".indexes ?TABLE? Show names of indexes",
" If TABLE is specified, only show indexes for",
" tables matching TABLE using the LIKE operator.",
+ ".intck ?STEPS_PER_UNLOCK? Run an incremental integrity check on the db",
#ifdef SQLITE_ENABLE_IOTRACE
",iotrace FILE Enable I/O diagnostic logging to FILE",
#endif
@@ -7650,6 +7654,40 @@ static int recoverDatabaseCmd(ShellState *pState, int nArg, char **azArg){
}
#endif /* SQLITE_SHELL_HAVE_RECOVER */
+/*
+** Implementation of ".intck STEPS_PER_UNLOCK" command.
+*/
+static int intckDatabaseCmd(ShellState *pState, i64 nStepPerUnlock){
+ sqlite3_intck *p = 0;
+ int rc = SQLITE_OK;
+
+ rc = sqlite3_intck_open(pState->db, "main", &p);
+ if( rc==SQLITE_OK ){
+ i64 nStep = 0;
+ i64 nError = 0;
+ const char *zErr = 0;
+ while( SQLITE_OK==sqlite3_intck_step(p) ){
+ const char *zMsg = sqlite3_intck_message(p);
+ if( zMsg ){
+ oputf("%s\n", zMsg);
+ nError++;
+ }
+ nStep++;
+ if( nStepPerUnlock && (nStep % nStepPerUnlock)==0 ){
+ sqlite3_intck_unlock(p);
+ }
+ }
+ rc = sqlite3_intck_error(p, &zErr);
+ if( zErr ){
+ eputf("%s\n", zErr);
+ }
+ sqlite3_intck_close(p);
+
+ oputf("%lld steps, %lld errors\n", nStep, nError);
+ }
+
+ return rc;
+}
/*
* zAutoColumn(zCol, &db, ?) => Maybe init db, add column zCol to it.
@@ -9140,6 +9178,21 @@ static int do_meta_command(char *zLine, ShellState *p){
}else
#endif /* !defined(SQLITE_OMIT_TEST_CONTROL) */
+ if( c=='i' && cli_strncmp(azArg[0], "intck", n)==0 ){
+ i64 iArg = 0;
+ if( nArg==2 ){
+ iArg = integerValue(azArg[1]);
+ if( iArg==0 ) iArg = -1;
+ }
+ if( (nArg!=1 && nArg!=2) || iArg<0 ){
+ eputf("Usage: .intck STEPS_PER_UNLOCK\n");
+ rc = 1;
+ goto meta_command_exit;
+ }
+ open_db(p, 0);
+ rc = intckDatabaseCmd(p, iArg);
+ }else
+
#ifdef SQLITE_ENABLE_IOTRACE
if( c=='i' && cli_strncmp(azArg[0], "iotrace", n)==0 ){
SQLITE_API extern void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...);
diff --git a/src/test_tclsh.c b/src/test_tclsh.c
index 32aee4267..4697c3b85 100644
--- a/src/test_tclsh.c
+++ b/src/test_tclsh.c
@@ -108,6 +108,7 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
extern int Sqlitetest_window_Init(Tcl_Interp *);
extern int Sqlitetestvdbecov_Init(Tcl_Interp *);
extern int TestRecover_Init(Tcl_Interp*);
+ extern int Sqlitetestintck_Init(Tcl_Interp*);
Tcl_CmdInfo cmdInfo;
@@ -175,6 +176,7 @@ const char *sqlite3TestInit(Tcl_Interp *interp){
Sqlitetest_window_Init(interp);
Sqlitetestvdbecov_Init(interp);
TestRecover_Init(interp);
+ Sqlitetestintck_Init(interp);
Tcl_CreateObjCommand(
interp, "load_testfixture_extensions", load_testfixture_extensions,0,0
diff --git a/src/where.c b/src/where.c
index 0e526b337..9850d22cc 100644
--- a/src/where.c
+++ b/src/where.c
@@ -2975,7 +2975,9 @@ static int whereLoopAddBtreeIndex(
}
if( pProbe->bUnordered || pProbe->bLowQual ){
if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE);
- if( pProbe->bLowQual ) opMask &= ~(WO_EQ|WO_IN|WO_IS);
+ if( pProbe->bLowQual && pSrc->fg.isIndexedBy==0 ){
+ opMask &= ~(WO_EQ|WO_IN|WO_IS);
+ }
}
assert( pNew->u.btree.nEq<pProbe->nColumn );