]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Remove the experimental and incomplete ext/repair extension, to prevent AIs
authordrh <>
Mon, 2 Mar 2026 13:44:04 +0000 (13:44 +0000)
committerdrh <>
Mon, 2 Mar 2026 13:44:04 +0000 (13:44 +0000)
from scanning the (incomplete) code and reporting bugs against it.

FossilOrigin-Name: 213b1c6608af4b3e9d6e0d8de6432cc6857931427baf4beac1e0a4294e4dc6ce

13 files changed:
Makefile.msc
ext/repair/README.md [deleted file]
ext/repair/checkfreelist.c [deleted file]
ext/repair/checkindex.c [deleted file]
ext/repair/sqlite3_checker.c.in [deleted file]
ext/repair/sqlite3_checker.tcl [deleted file]
ext/repair/test/README.md [deleted file]
ext/repair/test/checkfreelist01.test [deleted file]
ext/repair/test/checkindex01.test [deleted file]
ext/repair/test/test.tcl [deleted file]
main.mk
manifest
manifest.uuid

index 561d5f58e0f675f400a1203030e0dc1e3d4a6d1e..763616ce9379e33cd936aa759c49d68a7114e5bb 100644 (file)
@@ -2660,23 +2660,6 @@ sqltclsh.exe: sqltclsh.c  $(SHELL_CORE_DEP) $(LIBRESOBJS)
 sqlite3_expert.exe: $(SQLITE3C) $(TOP)\ext\expert\sqlite3expert.h $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c
        $(LTLINK) $(NO_WARN)    $(TOP)\ext\expert\sqlite3expert.c $(TOP)\ext\expert\expert.c $(SQLITE3C) $(TLIBS)
 
-CHECKER_DEPS =\
-  $(TOP)\tool\mkccode.tcl \
-  sqlite3.c \
-  tclsqlite-ex.c \
-  $(TOP)\ext\repair\sqlite3_checker.tcl \
-  $(TOP)\ext\repair\checkindex.c \
-  $(TOP)\ext\repair\checkfreelist.c \
-  $(TOP)\ext\misc\btreeinfo.c \
-  $(TOP)\ext\repair\sqlite3_checker.c.in
-
-sqlite3_checker.c:     $(CHECKER_DEPS)
-       $(TCLSH_CMD) $(TOP)\tool\mkccode.tcl $(TOP)\ext\repair\sqlite3_checker.c.in > $@
-
-sqlite3_checker.exe:   sqlite3_checker.c $(LIBRESOBJS)
-       $(LTLINK) $(NO_WARN) -DBUILD_sqlite -I$(TCLINCDIR) sqlite3_checker.c \
-               /link $(LDFLAGS) $(LTLINKOPTS) $(TCLLIBPATHS) $(LTLIBPATHS) $(LIBRESOBJS) $(TCLLIBS) $(LTLIBS) $(TLIBS)
-
 dbdump.exe:    $(TOP)\ext\misc\dbdump.c $(SQLITE3C) $(SQLITE3H) $(LIBRESOBJS)
        $(LTLINK) $(NO_WARN) -DDBDUMP_STANDALONE $(TOP)\ext\misc\dbdump.c $(SQLITE3C) \
                /link $(LDFLAGS) $(LTLINKOPTS) $(LTLIBPATHS) $(LIBRESOBJS) $(LTLIBS)
diff --git a/ext/repair/README.md b/ext/repair/README.md
deleted file mode 100644 (file)
index 927ceb7..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-This folder contains extensions and utility programs intended to analyze
-live database files, detect problems, and possibly fix them.
-
-As SQLite is being used on larger and larger databases, database sizes
-are growing into the terabyte range.  At that size, hardware malfunctions
-and/or cosmic rays will occasionally corrupt a database file.  Detecting 
-problems and fixing errors a terabyte-sized databases can take hours or days,
-and it is undesirable to take applications that depend on the databases 
-off-line for such a long time.
-The utilities in the folder are intended to provide mechanisms for
-detecting and fixing problems in large databases while those databases
-are in active use.
-
-The utilities and extensions in this folder are experimental and under
-active development at the time of this writing (2017-10-12).  If and when
-they stabilize, this README will be updated to reflect that fact.
diff --git a/ext/repair/checkfreelist.c b/ext/repair/checkfreelist.c
deleted file mode 100644 (file)
index d1d3d54..0000000
+++ /dev/null
@@ -1,310 +0,0 @@
-/*
-** 2017 October 11
-**
-** 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 module exports a single C function:
-**
-**   int sqlite3_check_freelist(sqlite3 *db, const char *zDb);
-**
-** This function checks the free-list in database zDb (one of "main", 
-** "temp", etc.) and reports any errors by invoking the sqlite3_log()
-** function. It returns SQLITE_OK if successful, or an SQLite error
-** code otherwise. It is not an error if the free-list is corrupted but
-** no IO or OOM errors occur.
-**
-** If this file is compiled and loaded as an SQLite loadable extension,
-** it adds an SQL function "checkfreelist" to the database handle, to
-** be invoked as follows:
-**
-**   SELECT checkfreelist(<database-name>);
-**
-** This function performs the same checks as sqlite3_check_freelist(),
-** except that it returns all error messages as a single text value,
-** separated by newline characters. If the freelist is not corrupted
-** in any way, an empty string is returned.
-**
-** To compile this module for use as an SQLite loadable extension:
-**
-**   gcc -Os -fPIC -shared checkfreelist.c -o checkfreelist.so
-*/
-
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-#ifndef SQLITE_AMALGAMATION
-# include <string.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <assert.h>
-# if defined(SQLITE_COVERAGE_TEST) || defined(SQLITE_MUTATION_TEST)
-#   define SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS 1
-# endif
-# if defined(SQLITE_OMIT_AUXILIARY_SAFETY_CHECKS)
-#   define ALWAYS(X)      (1)
-#   define NEVER(X)       (0)
-# elif !defined(NDEBUG)
-#   define ALWAYS(X)      ((X)?1:(assert(0),0))
-#   define NEVER(X)       ((X)?(assert(0),1):0)
-# else
-#   define ALWAYS(X)      (X)
-#   define NEVER(X)       (X)
-# endif
-  typedef unsigned char u8;
-  typedef unsigned short u16;
-  typedef unsigned int u32;
-#define get4byte(x) (        \
-    ((u32)((x)[0])<<24) +    \
-    ((u32)((x)[1])<<16) +    \
-    ((u32)((x)[2])<<8) +     \
-    ((u32)((x)[3]))          \
-)
-#endif
-
-/*
-** Execute a single PRAGMA statement and return the integer value returned
-** via output parameter (*pnOut).
-**
-** The SQL statement passed as the third argument should be a printf-style
-** format string containing a single "%s" which will be replace by the
-** value passed as the second argument. e.g.
-**
-**   sqlGetInteger(db, "main", "PRAGMA %s.page_count", pnOut)
-**
-** executes "PRAGMA main.page_count" and stores the results in (*pnOut).
-*/
-static int sqlGetInteger(
-  sqlite3 *db,                    /* Database handle */
-  const char *zDb,                /* Database name ("main", "temp" etc.) */
-  const char *zFmt,               /* SQL statement format */
-  u32 *pnOut                      /* OUT: Integer value */
-){
-  int rc, rc2;
-  char *zSql;
-  sqlite3_stmt *pStmt = 0;
-  int bOk = 0;
-
-  zSql = sqlite3_mprintf(zFmt, zDb);
-  if( zSql==0 ){
-    rc = SQLITE_NOMEM;
-  }else{
-    rc = sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0);
-    sqlite3_free(zSql);
-  }
-
-  if( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
-    *pnOut = (u32)sqlite3_column_int(pStmt, 0);
-    bOk = 1;
-  }
-
-  rc2 = sqlite3_finalize(pStmt);
-  if( rc==SQLITE_OK ) rc = rc2;
-  if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_ERROR;
-  return rc;
-}
-
-/*
-** Argument zFmt must be a printf-style format string and must be 
-** followed by its required arguments. If argument pzOut is NULL, 
-** then the results of printf()ing the format string are passed to
-** sqlite3_log(). Otherwise, they are appended to the string
-** at (*pzOut).
-*/
-static int checkFreelistError(char **pzOut, const char *zFmt, ...){
-  int rc = SQLITE_OK;
-  char *zErr = 0;
-  va_list ap;
-
-  va_start(ap, zFmt);
-  zErr = sqlite3_vmprintf(zFmt, ap);
-  if( zErr==0 ){
-    rc = SQLITE_NOMEM;
-  }else{
-    if( pzOut ){
-      *pzOut = sqlite3_mprintf("%s%z%s", *pzOut?"\n":"", *pzOut, zErr);
-      if( *pzOut==0 ) rc = SQLITE_NOMEM;
-    }else{
-      sqlite3_log(SQLITE_ERROR, "checkfreelist: %s", zErr);
-    }
-    sqlite3_free(zErr);
-  }
-  va_end(ap);
-  return rc;
-}
-
-static int checkFreelist(
-  sqlite3 *db, 
-  const char *zDb,
-  char **pzOut
-){
-  /* This query returns one row for each page on the free list. Each row has
-  ** two columns - the page number and page content.  */
-  const char *zTrunk = 
-    "WITH freelist_trunk(i, d, n) AS ("
-      "SELECT 1, NULL, sqlite_readint32(data, 32) "
-      "FROM sqlite_dbpage(:1) WHERE pgno=1 "
-        "UNION ALL "
-      "SELECT n, data, sqlite_readint32(data) "
-      "FROM freelist_trunk, sqlite_dbpage(:1) WHERE pgno=n "
-    ")"
-    "SELECT i, d FROM freelist_trunk WHERE i!=1;";
-
-  int rc, rc2;                    /* Return code */
-  sqlite3_stmt *pTrunk = 0;       /* Compilation of zTrunk */
-  u32 nPage = 0;                  /* Number of pages in db */
-  u32 nExpected = 0;              /* Expected number of free pages */
-  u32 nFree = 0;                  /* Number of pages on free list */
-
-  if( zDb==0 ) zDb = "main";
-
-  if( (rc = sqlGetInteger(db, zDb, "PRAGMA %s.page_count", &nPage))
-   || (rc = sqlGetInteger(db, zDb, "PRAGMA %s.freelist_count", &nExpected))
-  ){
-    return rc;
-  }
-
-  rc = sqlite3_prepare_v2(db, zTrunk, -1, &pTrunk, 0);
-  if( rc!=SQLITE_OK ) return rc;
-  sqlite3_bind_text(pTrunk, 1, zDb, -1, SQLITE_STATIC);
-  while( rc==SQLITE_OK && sqlite3_step(pTrunk)==SQLITE_ROW ){
-    u32 i;
-    u32 iTrunk = (u32)sqlite3_column_int(pTrunk, 0);
-    const u8 *aData = (const u8*)sqlite3_column_blob(pTrunk, 1);
-    u32 nData = (u32)sqlite3_column_bytes(pTrunk, 1);
-    u32 iNext = get4byte(&aData[0]);
-    u32 nLeaf = get4byte(&aData[4]);
-
-    if( nLeaf>((nData/4)-2-6) ){
-      rc = checkFreelistError(pzOut, 
-          "leaf count out of range (%d) on trunk page %d", 
-          (int)nLeaf, (int)iTrunk
-      );
-      nLeaf = (nData/4) - 2 - 6;
-    }
-
-    nFree += 1+nLeaf;
-    if( iNext>nPage ){
-      rc = checkFreelistError(pzOut, 
-          "trunk page %d is out of range", (int)iNext
-      );
-    }
-
-    for(i=0; rc==SQLITE_OK && i<nLeaf; i++){
-      u32 iLeaf = get4byte(&aData[8 + 4*i]);
-      if( iLeaf==0 || iLeaf>nPage ){
-        rc = checkFreelistError(pzOut,
-            "leaf page %d is out of range (child %d of trunk page %d)", 
-            (int)iLeaf, (int)i, (int)iTrunk
-        );
-      }
-    }
-  }
-
-  if( rc==SQLITE_OK && nFree!=nExpected ){
-    rc = checkFreelistError(pzOut,
-        "free-list count mismatch: actual=%d header=%d", 
-        (int)nFree, (int)nExpected
-    );
-  }
-
-  rc2 = sqlite3_finalize(pTrunk);
-  if( rc==SQLITE_OK ) rc = rc2;
-  return rc;
-}
-
-int sqlite3_check_freelist(sqlite3 *db, const char *zDb){
-  return checkFreelist(db, zDb, 0);
-}
-
-static void checkfreelist_function(
-  sqlite3_context *pCtx,
-  int nArg,
-  sqlite3_value **apArg
-){
-  const char *zDb;
-  int rc;
-  char *zOut = 0;
-  sqlite3 *db = sqlite3_context_db_handle(pCtx);
-
-  assert( nArg==1 );
-  zDb = (const char*)sqlite3_value_text(apArg[0]);
-  rc = checkFreelist(db, zDb, &zOut);
-  if( rc==SQLITE_OK ){
-    sqlite3_result_text(pCtx, zOut?zOut:"ok", -1, SQLITE_TRANSIENT);
-  }else{
-    sqlite3_result_error_code(pCtx, rc);
-  }
-
-  sqlite3_free(zOut);
-}
-
-/*
-** An SQL function invoked as follows:
-**
-**   sqlite_readint32(BLOB)           -- Decode 32-bit integer from start of blob
-*/
-static void readint_function(
-  sqlite3_context *pCtx,
-  int nArg,
-  sqlite3_value **apArg
-){
-  const u8 *zBlob;
-  int nBlob;
-  int iOff = 0;
-  u32 iRet = 0;
-
-  if( nArg!=1 && nArg!=2 ){
-    sqlite3_result_error(
-        pCtx, "wrong number of arguments to function sqlite_readint32()", -1
-    );
-    return;
-  }
-  if( nArg==2 ){
-    iOff = sqlite3_value_int(apArg[1]);
-  }
-
-  zBlob = sqlite3_value_blob(apArg[0]);
-  nBlob = sqlite3_value_bytes(apArg[0]);
-
-  if( nBlob>=(iOff+4) ){
-    iRet = get4byte(&zBlob[iOff]);
-  }
-
-  sqlite3_result_int64(pCtx, (sqlite3_int64)iRet);
-}
-
-/*
-** Register the SQL functions.
-*/
-static int cflRegister(sqlite3 *db){
-  int rc = sqlite3_create_function(
-      db, "sqlite_readint32", -1, SQLITE_UTF8, 0, readint_function, 0, 0
-  );
-  if( rc!=SQLITE_OK ) return rc;
-  rc = sqlite3_create_function(
-      db, "checkfreelist", 1, SQLITE_UTF8, 0, checkfreelist_function, 0, 0
-  );
-  return rc;
-}
-
-/*
-** Extension load function.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_checkfreelist_init(
-  sqlite3 *db, 
-  char **pzErrMsg, 
-  const sqlite3_api_routines *pApi
-){
-  SQLITE_EXTENSION_INIT2(pApi);
-  return cflRegister(db);
-}
diff --git a/ext/repair/checkindex.c b/ext/repair/checkindex.c
deleted file mode 100644 (file)
index ed30357..0000000
+++ /dev/null
@@ -1,929 +0,0 @@
-/*
-** 2017 October 27
-**
-** 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.
-**
-*************************************************************************
-*/
-
-#include "sqlite3ext.h"
-SQLITE_EXTENSION_INIT1
-
-/*
-** Stuff that is available inside the amalgamation, but which we need to
-** declare ourselves if this module is compiled separately.
-*/
-#ifndef SQLITE_AMALGAMATION
-# include <string.h>
-# include <stdio.h>
-# include <stdlib.h>
-# include <assert.h>
-typedef unsigned char u8;
-typedef unsigned short u16;
-typedef unsigned int u32;
-#define get4byte(x) (        \
-    ((u32)((x)[0])<<24) +    \
-    ((u32)((x)[1])<<16) +    \
-    ((u32)((x)[2])<<8) +     \
-    ((u32)((x)[3]))          \
-)
-#endif
-
-typedef struct CidxTable CidxTable;
-typedef struct CidxCursor CidxCursor;
-
-struct CidxTable {
-  sqlite3_vtab base;              /* Base class.  Must be first */
-  sqlite3 *db;
-};
-
-struct CidxCursor {
-  sqlite3_vtab_cursor base;       /* Base class.  Must be first */
-  sqlite3_int64 iRowid;           /* Row number of the output */
-  char *zIdxName;                 /* Copy of the index_name parameter */
-  char *zAfterKey;                /* Copy of the after_key parameter */
-  sqlite3_stmt *pStmt;            /* SQL statement that generates the output */
-};
-
-typedef struct CidxColumn CidxColumn;
-struct CidxColumn {
-  char *zExpr;                    /* Text for indexed expression */
-  int bDesc;                      /* True for DESC columns, otherwise false */
-  int bKey;                       /* Part of index, not PK */
-};
-
-typedef struct CidxIndex CidxIndex;
-struct CidxIndex {
-  char *zWhere;                   /* WHERE clause, if any */
-  int nCol;                       /* Elements in aCol[] array */
-  CidxColumn aCol[1];             /* Array of indexed columns */
-};
-
-static void *cidxMalloc(int *pRc, int n){
-  void *pRet = 0;
-  assert( n!=0 );
-  if( *pRc==SQLITE_OK ){
-    pRet = sqlite3_malloc(n);
-    if( pRet ){
-      memset(pRet, 0, n);
-    }else{
-      *pRc = SQLITE_NOMEM;
-    }
-  }
-  return pRet;
-}
-
-static void cidxCursorError(CidxCursor *pCsr, const char *zFmt, ...){
-  va_list ap;
-  va_start(ap, zFmt);
-  assert( pCsr->base.pVtab->zErrMsg==0 );
-  pCsr->base.pVtab->zErrMsg = sqlite3_vmprintf(zFmt, ap);
-  va_end(ap);
-}
-
-/*
-** Connect to the incremental_index_check virtual table.
-*/
-static int cidxConnect(
-  sqlite3 *db,
-  void *pAux,
-  int argc, const char *const*argv,
-  sqlite3_vtab **ppVtab,
-  char **pzErr
-){
-  int rc = SQLITE_OK;
-  CidxTable *pRet;
-
-#define IIC_ERRMSG        0
-#define IIC_CURRENT_KEY   1
-#define IIC_INDEX_NAME    2
-#define IIC_AFTER_KEY     3
-#define IIC_SCANNER_SQL   4
-  rc = sqlite3_declare_vtab(db,
-      "CREATE TABLE xyz("
-      " errmsg TEXT,"            /* Error message or NULL if everything is ok */
-      " current_key TEXT,"       /* SQLite quote() text of key values */
-      " index_name HIDDEN,"      /* IN: name of the index being scanned */
-      " after_key HIDDEN,"       /* IN: Start scanning after this key */
-      " scanner_sql HIDDEN"      /* debugging info: SQL used for scanner */
-      ")"
-  );
-  pRet = cidxMalloc(&rc, sizeof(CidxTable));
-  if( pRet ){
-    pRet->db = db;
-  }
-
-  *ppVtab = (sqlite3_vtab*)pRet;
-  return rc;
-}
-
-/*
-** Disconnect from or destroy an incremental_index_check virtual table.
-*/
-static int cidxDisconnect(sqlite3_vtab *pVtab){
-  CidxTable *pTab = (CidxTable*)pVtab;
-  sqlite3_free(pTab);
-  return SQLITE_OK;
-}
-
-/*
-** idxNum and idxStr are not used.  There are only three possible plans,
-** which are all distinguished by the number of parameters.
-**
-**   No parameters:         A degenerate plan.  The result is zero rows.
-**   1 Parameter:           Scan all of the index starting with first entry
-**   2 parameters:          Scan the index starting after the "after_key".    
-**
-** Provide successively smaller costs for each of these plans to encourage
-** the query planner to select the one with the most parameters.
-*/
-static int cidxBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pInfo){
-  int iIdxName = -1;
-  int iAfterKey = -1;
-  int i;
-
-  for(i=0; i<pInfo->nConstraint; i++){
-    struct sqlite3_index_constraint *p = &pInfo->aConstraint[i];
-    if( p->usable==0 ) continue;
-    if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
-
-    if( p->iColumn==IIC_INDEX_NAME ){
-      iIdxName = i;
-    }
-    if( p->iColumn==IIC_AFTER_KEY ){
-      iAfterKey = i;
-    }
-  }
-
-  if( iIdxName<0 ){
-    pInfo->estimatedCost = 1000000000.0;
-  }else{
-    pInfo->aConstraintUsage[iIdxName].argvIndex = 1;
-    pInfo->aConstraintUsage[iIdxName].omit = 1;
-    if( iAfterKey<0 ){
-      pInfo->estimatedCost = 1000000.0;
-    }else{
-      pInfo->aConstraintUsage[iAfterKey].argvIndex = 2;
-      pInfo->aConstraintUsage[iAfterKey].omit = 1;
-      pInfo->estimatedCost = 1000.0;
-    }
-  }
-
-  return SQLITE_OK;
-}
-
-/*
-** Open a new btreeinfo cursor.
-*/
-static int cidxOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
-  CidxCursor *pRet;
-  int rc = SQLITE_OK;
-
-  pRet = cidxMalloc(&rc, sizeof(CidxCursor));
-
-  *ppCursor = (sqlite3_vtab_cursor*)pRet;
-  return rc;
-}
-
-/*
-** Close a btreeinfo cursor.
-*/
-static int cidxClose(sqlite3_vtab_cursor *pCursor){
-  CidxCursor *pCsr = (CidxCursor*)pCursor;
-  sqlite3_finalize(pCsr->pStmt);
-  sqlite3_free(pCsr->zIdxName);
-  sqlite3_free(pCsr->zAfterKey);
-  sqlite3_free(pCsr);
-  return SQLITE_OK;
-}
-
-/*
-** Move a btreeinfo cursor to the next entry in the file.
-*/
-static int cidxNext(sqlite3_vtab_cursor *pCursor){
-  CidxCursor *pCsr = (CidxCursor*)pCursor;
-  int rc = sqlite3_step(pCsr->pStmt);
-  if( rc!=SQLITE_ROW ){
-    rc = sqlite3_finalize(pCsr->pStmt);
-    pCsr->pStmt = 0;
-    if( rc!=SQLITE_OK ){
-      sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
-      cidxCursorError(pCsr, "Cursor error: %s", sqlite3_errmsg(db));
-    }
-  }else{
-    pCsr->iRowid++;
-    rc = SQLITE_OK;
-  }
-  return rc;
-}
-
-/* We have reached EOF if previous sqlite3_step() returned
-** anything other than SQLITE_ROW;
-*/
-static int cidxEof(sqlite3_vtab_cursor *pCursor){
-  CidxCursor *pCsr = (CidxCursor*)pCursor;
-  return pCsr->pStmt==0;
-}
-
-static char *cidxMprintf(int *pRc, const char *zFmt, ...){
-  char *zRet = 0;
-  va_list ap;
-  va_start(ap, zFmt);
-  zRet = sqlite3_vmprintf(zFmt, ap);
-  if( *pRc==SQLITE_OK ){
-    if( zRet==0 ){
-      *pRc = SQLITE_NOMEM;
-    }
-  }else{
-    sqlite3_free(zRet);
-    zRet = 0;
-  }
-  va_end(ap);
-  return zRet;
-}
-
-static sqlite3_stmt *cidxPrepare(
-  int *pRc, CidxCursor *pCsr, const char *zFmt, ...
-){
-  sqlite3_stmt *pRet = 0;
-  char *zSql;
-  va_list ap;                     /* ... printf arguments */
-  va_start(ap, zFmt);
-
-  zSql = sqlite3_vmprintf(zFmt, ap);
-  if( *pRc==SQLITE_OK ){
-    if( zSql==0 ){
-      *pRc = SQLITE_NOMEM;
-    }else{
-      sqlite3 *db = ((CidxTable*)pCsr->base.pVtab)->db;
-      *pRc = sqlite3_prepare_v2(db, zSql, -1, &pRet, 0);
-      if( *pRc!=SQLITE_OK ){
-        cidxCursorError(pCsr, "SQL error: %s", sqlite3_errmsg(db));
-      }
-    }
-  }
-  sqlite3_free(zSql);
-  va_end(ap);
-
-  return pRet;
-}
-
-static void cidxFinalize(int *pRc, sqlite3_stmt *pStmt){
-  int rc = sqlite3_finalize(pStmt);
-  if( *pRc==SQLITE_OK ) *pRc = rc;
-}
-
-char *cidxStrdup(int *pRc, const char *zStr){
-  char *zRet = 0;
-  if( *pRc==SQLITE_OK ){
-    int n = (int)strlen(zStr);
-    zRet = cidxMalloc(pRc, n+1);
-    if( zRet ) memcpy(zRet, zStr, n+1);
-  }
-  return zRet;
-}
-
-static void cidxFreeIndex(CidxIndex *pIdx){
-  if( pIdx ){
-    int i;
-    for(i=0; i<pIdx->nCol; i++){
-      sqlite3_free(pIdx->aCol[i].zExpr);
-    }
-    sqlite3_free(pIdx->zWhere);
-    sqlite3_free(pIdx);
-  }
-}
-
-static int cidx_isspace(char c){
-  return c==' ' || c=='\t' || c=='\r' || c=='\n';
-}
-
-static int cidx_isident(char c){
-  return c<0 
-    || (c>='0' && c<='9') || (c>='a' && c<='z') 
-    || (c>='A' && c<='Z') || c=='_';
-}
-
-#define CIDX_PARSE_EOF   0
-#define CIDX_PARSE_COMMA 1      /*  "," */
-#define CIDX_PARSE_OPEN  2      /*  "(" */
-#define CIDX_PARSE_CLOSE 3      /*  ")" */
-
-/*
-** Argument zIn points into the start, middle or end of a CREATE INDEX
-** statement. If argument pbDoNotTrim is non-NULL, then this function
-** scans the input until it finds EOF, a comma (",") or an open or
-** close parenthesis character. It then sets (*pzOut) to point to said
-** character and returns a CIDX_PARSE_XXX constant as appropriate. The
-** parser is smart enough that special characters inside SQL strings
-** or comments are not returned for.
-**
-** Or, if argument pbDoNotTrim is NULL, then this function sets *pzOut
-** to point to the first character of the string that is not whitespace
-** or part of an SQL comment and returns CIDX_PARSE_EOF.
-**
-** Additionally, if pbDoNotTrim is not NULL and the element immediately
-** before (*pzOut) is an SQL comment of the form "-- comment", then
-** (*pbDoNotTrim) is set before returning. In all other cases it is
-** cleared.
-*/
-static int cidxFindNext(
-  const char *zIn, 
-  const char **pzOut,
-  int *pbDoNotTrim                /* OUT: True if prev is -- comment */
-){
-  const char *z = zIn;
-
-  while( 1 ){
-    while( cidx_isspace(*z) ) z++;
-    if( z[0]=='-' && z[1]=='-' ){
-      z += 2;
-      while( z[0]!='\n' ){
-        if( z[0]=='\0' ) return CIDX_PARSE_EOF;
-        z++;
-      }
-      while( cidx_isspace(*z) ) z++;
-      if( pbDoNotTrim ) *pbDoNotTrim = 1;
-    }else
-    if( z[0]=='/' && z[1]=='*' ){
-      z += 2;
-      while( z[0]!='*' || z[1]!='/' ){
-        if( z[1]=='\0' ) return CIDX_PARSE_EOF;
-        z++;
-      }
-      z += 2;
-    }else{
-      *pzOut = z;
-      if( pbDoNotTrim==0 ) return CIDX_PARSE_EOF;
-      switch( *z ){
-        case '\0':
-          return CIDX_PARSE_EOF;
-        case '(':
-          return CIDX_PARSE_OPEN;
-        case ')':
-          return CIDX_PARSE_CLOSE;
-        case ',':
-          return CIDX_PARSE_COMMA;
-  
-        case '"': 
-        case '\'': 
-        case '`': {
-          char q = *z;
-          z++;
-          while( *z ){
-            if( *z==q ){
-              z++;
-              if( *z!=q ) break;
-            }
-            z++;
-          }
-          break;
-        }
-  
-        case '[':
-          while( *z++!=']' );
-          break;
-  
-        default:
-          z++;
-          break;
-      }
-      *pbDoNotTrim = 0;
-    }
-  }
-
-  assert( 0 );
-  return -1;
-}
-
-static int cidxParseSQL(CidxCursor *pCsr, CidxIndex *pIdx, const char *zSql){
-  const char *z = zSql;
-  const char *z1;
-  int e;
-  int rc = SQLITE_OK;
-  int nParen = 1;
-  int bDoNotTrim = 0;
-  CidxColumn *pCol = pIdx->aCol;
-
-  e = cidxFindNext(z, &z, &bDoNotTrim);
-  if( e!=CIDX_PARSE_OPEN ) goto parse_error;
-  z1 = z+1;
-  z++;
-  while( nParen>0 ){
-    e = cidxFindNext(z, &z, &bDoNotTrim);
-    if( e==CIDX_PARSE_EOF ) goto parse_error;
-    if( (e==CIDX_PARSE_COMMA || e==CIDX_PARSE_CLOSE) && nParen==1 ){
-      const char *z2 = z;
-      if( pCol->zExpr ) goto parse_error;
-
-      if( bDoNotTrim==0 ){
-        while( cidx_isspace(z[-1]) ) z--;
-        if( !sqlite3_strnicmp(&z[-3], "asc", 3) && 0==cidx_isident(z[-4]) ){
-          z -= 3;
-          while( cidx_isspace(z[-1]) ) z--;
-        }else
-          if( !sqlite3_strnicmp(&z[-4], "desc", 4) && 0==cidx_isident(z[-5]) ){
-            z -= 4;
-            while( cidx_isspace(z[-1]) ) z--;
-          }
-        while( cidx_isspace(z1[0]) ) z1++;
-      }
-
-      pCol->zExpr = cidxMprintf(&rc, "%.*s", z-z1, z1);
-      pCol++;
-      z = z1 = z2+1;
-    }
-    if( e==CIDX_PARSE_OPEN ) nParen++;
-    if( e==CIDX_PARSE_CLOSE ) nParen--;
-    z++;
-  }
-
-  /* Search for a WHERE clause */
-  cidxFindNext(z, &z, 0);
-  if( 0==sqlite3_strnicmp(z, "where", 5) ){
-    pIdx->zWhere = cidxMprintf(&rc, "%s\n", &z[5]);
-  }else if( z[0]!='\0' ){
-    goto parse_error;
-  }
-
-  return rc;
-
- parse_error:
-  cidxCursorError(pCsr, "Parse error in: %s", zSql);
-  return SQLITE_ERROR;
-}
-
-static int cidxLookupIndex(
-  CidxCursor *pCsr,               /* Cursor object */
-  const char *zIdx,               /* Name of index to look up */
-  CidxIndex **ppIdx,              /* OUT: Description of columns */
-  char **pzTab                    /* OUT: Table name */
-){
-  int rc = SQLITE_OK;
-  char *zTab = 0;
-  CidxIndex *pIdx = 0;
-
-  sqlite3_stmt *pFindTab = 0;
-  sqlite3_stmt *pInfo = 0;
-    
-  /* Find the table for this index. */
-  pFindTab = cidxPrepare(&rc, pCsr, 
-      "SELECT tbl_name, sql FROM sqlite_schema WHERE name=%Q AND type='index'",
-      zIdx
-  );
-  if( rc==SQLITE_OK && sqlite3_step(pFindTab)==SQLITE_ROW ){
-    const char *zSql = (const char*)sqlite3_column_text(pFindTab, 1);
-    zTab = cidxStrdup(&rc, (const char*)sqlite3_column_text(pFindTab, 0));
-
-    pInfo = cidxPrepare(&rc, pCsr, "PRAGMA index_xinfo(%Q)", zIdx);
-    if( rc==SQLITE_OK ){
-      int nAlloc = 0;
-      int iCol = 0;
-
-      while( sqlite3_step(pInfo)==SQLITE_ROW ){
-        const char *zName = (const char*)sqlite3_column_text(pInfo, 2);
-        const char *zColl = (const char*)sqlite3_column_text(pInfo, 4);
-        CidxColumn *p;
-        if( zName==0 ) zName = "rowid";
-        if( iCol==nAlloc ){
-          int nByte = sizeof(CidxIndex) + sizeof(CidxColumn)*(nAlloc+8);
-          pIdx = (CidxIndex*)sqlite3_realloc(pIdx, nByte);
-          nAlloc += 8;
-        }
-        p = &pIdx->aCol[iCol++];
-        p->bDesc = sqlite3_column_int(pInfo, 3);
-        p->bKey = sqlite3_column_int(pInfo, 5);
-        if( zSql==0 || p->bKey==0 ){
-          p->zExpr = cidxMprintf(&rc, "\"%w\" COLLATE %s",zName,zColl);
-        }else{
-          p->zExpr = 0;
-        }
-        pIdx->nCol = iCol;
-        pIdx->zWhere = 0;
-      }
-      cidxFinalize(&rc, pInfo);
-    }
-
-    if( rc==SQLITE_OK && zSql ){
-      rc = cidxParseSQL(pCsr, pIdx, zSql);
-    }
-  }
-
-  cidxFinalize(&rc, pFindTab);
-  if( rc==SQLITE_OK && zTab==0 ){
-    rc = SQLITE_ERROR;
-  }
-  
-  if( rc!=SQLITE_OK ){
-    sqlite3_free(zTab);
-    cidxFreeIndex(pIdx);
-  }else{
-    *pzTab = zTab;
-    *ppIdx = pIdx;
-  }
-
-  return rc;
-}
-
-static int cidxDecodeAfter(
-  CidxCursor *pCsr, 
-  int nCol, 
-  const char *zAfterKey, 
-  char ***pazAfter
-){
-  char **azAfter;
-  int rc = SQLITE_OK;
-  int nAfterKey = (int)strlen(zAfterKey);
-
-  azAfter = cidxMalloc(&rc, sizeof(char*)*nCol + nAfterKey+1);
-  if( rc==SQLITE_OK ){
-    int i;
-    char *zCopy = (char*)&azAfter[nCol];
-    char *p = zCopy;
-    memcpy(zCopy, zAfterKey, nAfterKey+1);
-    for(i=0; i<nCol; i++){
-      while( *p==' ' ) p++;
-
-      /* Check NULL values */
-      if( *p=='N' ){
-        if( memcmp(p, "NULL", 4) ) goto parse_error;
-        p += 4;
-      }
-
-      /* Check strings and blob literals */
-      else if( *p=='X' || *p=='\'' ){
-        azAfter[i] = p;
-        if( *p=='X' ) p++;
-        if( *p!='\'' ) goto parse_error;
-        p++;
-        while( 1 ){
-          if( *p=='\0' ) goto parse_error;
-          if( *p=='\'' ){
-            p++;
-            if( *p!='\'' ) break;
-          }
-          p++;
-        }
-      }
-
-      /* Check numbers */
-      else{
-        azAfter[i] = p;
-        while( (*p>='0' && *p<='9') 
-            || *p=='.' || *p=='+' || *p=='-' || *p=='e' || *p=='E'
-        ){
-          p++;
-        }
-      }
-
-      while( *p==' ' ) p++;
-      if( *p!=(i==(nCol-1) ? '\0' : ',') ){
-        goto parse_error;
-      }
-      *p++ = '\0';
-    }
-  }
-
-  *pazAfter = azAfter;
-  return rc;
-
- parse_error:
-  sqlite3_free(azAfter);
-  *pazAfter = 0;
-  cidxCursorError(pCsr, "%s", "error parsing after value");
-  return SQLITE_ERROR;
-}
-
-static char *cidxWhere(
-  int *pRc, CidxColumn *aCol, char **azAfter, int iGt, int bLastIsNull
-){
-  char *zRet = 0;
-  const char *zSep = "";
-  int i;
-
-  for(i=0; i<iGt; i++){
-    zRet = cidxMprintf(pRc, "%z%s(%s) IS %s", zRet, 
-        zSep, aCol[i].zExpr, (azAfter[i] ? azAfter[i] : "NULL")
-    );
-    zSep = " AND ";
-  }
-
-  if( bLastIsNull ){
-    zRet = cidxMprintf(pRc, "%z%s(%s) IS NULL", zRet, zSep, aCol[iGt].zExpr);
-  }
-  else if( azAfter[iGt] ){
-    zRet = cidxMprintf(pRc, "%z%s(%s) %s %s", zRet, 
-        zSep, aCol[iGt].zExpr, (aCol[iGt].bDesc ? "<" : ">"), 
-        azAfter[iGt]
-    );
-  }else{
-    zRet = cidxMprintf(pRc, "%z%s(%s) IS NOT NULL", zRet, zSep,aCol[iGt].zExpr);
-  }
-
-  return zRet;
-}
-
-#define CIDX_CLIST_ALL         0
-#define CIDX_CLIST_ORDERBY     1
-#define CIDX_CLIST_CURRENT_KEY 2
-#define CIDX_CLIST_SUBWHERE    3
-#define CIDX_CLIST_SUBEXPR     4
-
-/*
-** This function returns various strings based on the contents of the
-** CidxIndex structure and the eType parameter.
-*/
-static char *cidxColumnList(
-  int *pRc,                       /* IN/OUT: Error code */
-  const char *zIdx,
-  CidxIndex *pIdx,                /* Indexed columns */
-  int eType                       /* True to include ASC/DESC */
-){
-  char *zRet = 0;
-  if( *pRc==SQLITE_OK ){
-    const char *aDir[2] = {"", " DESC"};
-    int i;
-    const char *zSep = "";
-
-    for(i=0; i<pIdx->nCol; i++){
-      CidxColumn *p = &pIdx->aCol[i];
-      assert( pIdx->aCol[i].bDesc==0 || pIdx->aCol[i].bDesc==1 );
-      switch( eType ){
-
-        case CIDX_CLIST_ORDERBY:
-          zRet = cidxMprintf(pRc, "%z%s%d%s", zRet, zSep, i+1, aDir[p->bDesc]);
-          zSep = ",";
-          break;
-
-        case CIDX_CLIST_CURRENT_KEY:
-          zRet = cidxMprintf(pRc, "%z%squote(i%d)", zRet, zSep, i);
-          zSep = "||','||";
-          break;
-
-        case CIDX_CLIST_SUBWHERE:
-          if( p->bKey==0 ){
-            zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet, 
-                zSep, p->zExpr, i
-            );
-            zSep = " AND ";
-          }
-          break;
-
-        case CIDX_CLIST_SUBEXPR:
-          if( p->bKey==1 ){
-            zRet = cidxMprintf(pRc, "%z%s%s IS i.i%d", zRet, 
-                zSep, p->zExpr, i
-            );
-            zSep = " AND ";
-          }
-          break;
-
-        default:
-          assert( eType==CIDX_CLIST_ALL );
-          zRet = cidxMprintf(pRc, "%z%s(%s) AS i%d", zRet, zSep, p->zExpr, i);
-          zSep = ", ";
-          break;
-      }
-    }
-  }
-
-  return zRet;
-}
-
-/*
-** Generate SQL (in memory obtained from sqlite3_malloc()) that will
-** continue the index scan for zIdxName starting after zAfterKey.
-*/
-int cidxGenerateScanSql(
-  CidxCursor *pCsr,           /* The cursor which needs the new statement */
-  const char *zIdxName,       /* index to be scanned */
-  const char *zAfterKey,      /* start after this key, if not NULL */
-  char **pzSqlOut             /* OUT: Write the generated SQL here */
-){
-  int rc;
-  char *zTab = 0;
-  char *zCurrentKey = 0;
-  char *zOrderBy = 0;
-  char *zSubWhere = 0;
-  char *zSubExpr = 0;
-  char *zSrcList = 0;
-  char **azAfter = 0;
-  CidxIndex *pIdx = 0;
-
-  *pzSqlOut = 0;
-  rc = cidxLookupIndex(pCsr, zIdxName, &pIdx, &zTab);
-
-  zOrderBy = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ORDERBY);
-  zCurrentKey = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_CURRENT_KEY);
-  zSubWhere = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBWHERE);
-  zSubExpr = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_SUBEXPR);
-  zSrcList = cidxColumnList(&rc, zIdxName, pIdx, CIDX_CLIST_ALL);
-
-  if( rc==SQLITE_OK && zAfterKey ){
-    rc = cidxDecodeAfter(pCsr, pIdx->nCol, zAfterKey, &azAfter);
-  }
-
-  if( rc==SQLITE_OK ){
-    if( zAfterKey==0 ){
-      *pzSqlOut = cidxMprintf(&rc,
-          "SELECT (SELECT %s FROM %Q AS t WHERE %s), %s "
-          "FROM (SELECT %s FROM %Q INDEXED BY %Q %s%sORDER BY %s) AS i",
-          zSubExpr, zTab, zSubWhere, zCurrentKey, 
-          zSrcList, zTab, zIdxName, 
-          (pIdx->zWhere ? "WHERE " : ""), (pIdx->zWhere ? pIdx->zWhere : ""),
-          zOrderBy
-      );
-    }else{
-      const char *zSep = "";
-      char *zSql;
-      int i;
-  
-      zSql = cidxMprintf(&rc, 
-          "SELECT (SELECT %s FROM %Q WHERE %s), %s FROM (",
-          zSubExpr, zTab, zSubWhere, zCurrentKey
-      );
-      for(i=pIdx->nCol-1; i>=0; i--){
-        int j;
-        if( pIdx->aCol[i].bDesc && azAfter[i]==0 ) continue;
-        for(j=0; j<2; j++){
-          char *zWhere = cidxWhere(&rc, pIdx->aCol, azAfter, i, j);
-          zSql = cidxMprintf(&rc, "%z"
-              "%sSELECT * FROM ("
-                "SELECT %s FROM %Q INDEXED BY %Q WHERE %s%s%z ORDER BY %s"
-              ")",
-              zSql, zSep, zSrcList, zTab, zIdxName, 
-              pIdx->zWhere ? pIdx->zWhere : "",
-              pIdx->zWhere ? " AND " : "",
-              zWhere, zOrderBy
-          );
-          zSep = " UNION ALL ";
-          if( pIdx->aCol[i].bDesc==0 ) break;
-        }
-      }
-      *pzSqlOut = cidxMprintf(&rc, "%z) AS i", zSql);
-    }
-  }
-
-  sqlite3_free(zTab);
-  sqlite3_free(zCurrentKey);
-  sqlite3_free(zOrderBy);
-  sqlite3_free(zSubWhere);
-  sqlite3_free(zSubExpr);
-  sqlite3_free(zSrcList);
-  cidxFreeIndex(pIdx);
-  sqlite3_free(azAfter);
-  return rc;
-}
-
-
-/* 
-** Position a cursor back to the beginning.
-*/
-static int cidxFilter(
-  sqlite3_vtab_cursor *pCursor, 
-  int idxNum, const char *idxStr,
-  int argc, sqlite3_value **argv
-){
-  int rc = SQLITE_OK;
-  CidxCursor *pCsr = (CidxCursor*)pCursor;
-  const char *zIdxName = 0;
-  const char *zAfterKey = 0;
-
-  sqlite3_free(pCsr->zIdxName);
-  pCsr->zIdxName = 0;
-  sqlite3_free(pCsr->zAfterKey);
-  pCsr->zAfterKey = 0;
-  sqlite3_finalize(pCsr->pStmt);
-  pCsr->pStmt = 0;
-
-  if( argc>0 ){
-    zIdxName = (const char*)sqlite3_value_text(argv[0]);
-    if( argc>1 ){
-      zAfterKey = (const char*)sqlite3_value_text(argv[1]);
-    }
-  }
-
-  if( zIdxName ){
-    char *zSql = 0;
-    pCsr->zIdxName = sqlite3_mprintf("%s", zIdxName);
-    pCsr->zAfterKey = zAfterKey ? sqlite3_mprintf("%s", zAfterKey) : 0;
-    rc = cidxGenerateScanSql(pCsr, zIdxName, zAfterKey, &zSql);
-    if( zSql ){
-      pCsr->pStmt = cidxPrepare(&rc, pCsr, "%z", zSql);
-    }
-  }
-
-  if( pCsr->pStmt ){
-    assert( rc==SQLITE_OK );
-    rc = cidxNext(pCursor);
-  }
-  pCsr->iRowid = 1;
-  return rc;
-}
-
-/* 
-** Return a column value.
-*/
-static int cidxColumn(
-  sqlite3_vtab_cursor *pCursor, 
-  sqlite3_context *ctx, 
-  int iCol
-){
-  CidxCursor *pCsr = (CidxCursor*)pCursor;
-  assert( iCol>=IIC_ERRMSG && iCol<=IIC_SCANNER_SQL );
-  switch( iCol ){
-    case IIC_ERRMSG: {
-      const char *zVal = 0;
-      if( sqlite3_column_type(pCsr->pStmt, 0)==SQLITE_INTEGER ){
-        if( sqlite3_column_int(pCsr->pStmt, 0)==0 ){
-          zVal = "row data mismatch";
-        }
-      }else{
-        zVal = "row missing";
-      }
-      sqlite3_result_text(ctx, zVal, -1, SQLITE_STATIC);
-      break;
-    }
-    case IIC_CURRENT_KEY: {
-      sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pStmt, 1));
-      break;
-    }
-    case IIC_INDEX_NAME: {
-      sqlite3_result_text(ctx, pCsr->zIdxName, -1, SQLITE_TRANSIENT);
-      break;
-    }
-    case IIC_AFTER_KEY: {
-      sqlite3_result_text(ctx, pCsr->zAfterKey, -1, SQLITE_TRANSIENT);
-      break;
-    }
-    case IIC_SCANNER_SQL: {
-      char *zSql = 0;
-      cidxGenerateScanSql(pCsr, pCsr->zIdxName, pCsr->zAfterKey, &zSql);
-      sqlite3_result_text(ctx, zSql, -1, sqlite3_free);
-      break;
-    }
-  }
-  return SQLITE_OK;
-}
-
-/* Return the ROWID for the sqlite_btreeinfo table */
-static int cidxRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
-  CidxCursor *pCsr = (CidxCursor*)pCursor;
-  *pRowid = pCsr->iRowid;
-  return SQLITE_OK;
-}
-
-/*
-** Register the virtual table modules with the database handle passed
-** as the only argument.
-*/
-static int ciInit(sqlite3 *db){
-  static sqlite3_module cidx_module = {
-    0,                            /* iVersion */
-    0,                            /* xCreate */
-    cidxConnect,                  /* xConnect */
-    cidxBestIndex,                /* xBestIndex */
-    cidxDisconnect,               /* xDisconnect */
-    0,                            /* xDestroy */
-    cidxOpen,                     /* xOpen - open a cursor */
-    cidxClose,                    /* xClose - close a cursor */
-    cidxFilter,                   /* xFilter - configure scan constraints */
-    cidxNext,                     /* xNext - advance a cursor */
-    cidxEof,                      /* xEof - check for end of scan */
-    cidxColumn,                   /* xColumn - read data */
-    cidxRowid,                    /* xRowid - read data */
-    0,                            /* xUpdate */
-    0,                            /* xBegin */
-    0,                            /* xSync */
-    0,                            /* xCommit */
-    0,                            /* xRollback */
-    0,                            /* xFindMethod */
-    0,                            /* xRename */
-    0,                            /* xSavepoint */
-    0,                            /* xRelease */
-    0,                            /* xRollbackTo */
-    0,                            /* xShadowName */
-    0                             /* xIntegrity */
-  };
-  return sqlite3_create_module(db, "incremental_index_check", &cidx_module, 0);
-}
-
-/*
-** Extension load function.
-*/
-#ifdef _WIN32
-__declspec(dllexport)
-#endif
-int sqlite3_checkindex_init(
-  sqlite3 *db, 
-  char **pzErrMsg, 
-  const sqlite3_api_routines *pApi
-){
-  SQLITE_EXTENSION_INIT2(pApi);
-  return ciInit(db);
-}
diff --git a/ext/repair/sqlite3_checker.c.in b/ext/repair/sqlite3_checker.c.in
deleted file mode 100644 (file)
index 96b15f2..0000000
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
-** Read an SQLite database file and analyze its space utilization.  Generate
-** text on standard output.
-*/
-#define TCLSH_INIT_PROC sqlite3_checker_init_proc
-#define SQLITE_ENABLE_DBPAGE_VTAB 1
-#undef SQLITE_THREADSAFE
-#define SQLITE_THREADSAFE 0
-#undef SQLITE_ENABLE_COLUMN_METADATA
-#define SQLITE_OMIT_DECLTYPE 1
-#define SQLITE_OMIT_DEPRECATED 1
-#define SQLITE_OMIT_PROGRESS_CALLBACK 1
-#define SQLITE_OMIT_SHARED_CACHE 1
-#define SQLITE_DEFAULT_MEMSTATUS 0
-#define SQLITE_MAX_EXPR_DEPTH 0
-INCLUDE sqlite3.c
-INCLUDE $ROOT/src/tclsqlite.c
-INCLUDE $ROOT/ext/misc/btreeinfo.c
-INCLUDE $ROOT/ext/repair/checkindex.c
-INCLUDE $ROOT/ext/repair/checkfreelist.c
-
-/*
-** Decode a pointer to an sqlite3 object.
-*/
-int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
-  struct SqliteDb *p;
-  Tcl_CmdInfo cmdInfo;
-  if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
-    p = (struct SqliteDb*)cmdInfo.objClientData;
-    *ppDb = p->db;
-    return TCL_OK;
-  }else{
-    *ppDb = 0;
-    return TCL_ERROR;
-  }
-  return TCL_OK;
-}
-
-/*
-**   sqlite3_imposter db main rootpage {CREATE TABLE...}  ;# setup an imposter
-**   sqlite3_imposter db main                             ;# rm all imposters
-*/
-static int sqlite3_imposter(
-  void *clientData,
-  Tcl_Interp *interp,
-  int objc,
-  Tcl_Obj *CONST objv[]
-){
-  sqlite3 *db;
-  const char *zSchema;
-  int iRoot;
-  const char *zSql;
-
-  if( objc!=3 && objc!=5 ){
-    Tcl_WrongNumArgs(interp, 1, objv, "DB SCHEMA [ROOTPAGE SQL]");
-    return TCL_ERROR;
-  }
-  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
-  zSchema = Tcl_GetString(objv[2]);
-  if( objc==3 ){
-    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 1);
-  }else{
-    if( Tcl_GetIntFromObj(interp, objv[3], &iRoot) ) return TCL_ERROR;
-    zSql = Tcl_GetString(objv[4]);
-    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 1, iRoot);
-    sqlite3_exec(db, zSql, 0, 0, 0);
-    sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zSchema, 0, 0);
-  }
-  return TCL_OK;
-}
-
-#include <stdio.h>
-
-const char *sqlite3_checker_init_proc(Tcl_Interp *interp){
-  Tcl_CreateObjCommand(interp, "sqlite3_imposter", 
-                       (Tcl_ObjCmdProc*)sqlite3_imposter, 0, 0);
-  sqlite3_auto_extension((void(*)(void))sqlite3_btreeinfo_init);
-  sqlite3_auto_extension((void(*)(void))sqlite3_checkindex_init);
-  sqlite3_auto_extension((void(*)(void))sqlite3_checkfreelist_init);
-  return
-BEGIN_STRING
-INCLUDE $ROOT/ext/repair/sqlite3_checker.tcl
-END_STRING
-;
-}
diff --git a/ext/repair/sqlite3_checker.tcl b/ext/repair/sqlite3_checker.tcl
deleted file mode 100644 (file)
index 2ae6e15..0000000
+++ /dev/null
@@ -1,264 +0,0 @@
-# This TCL script is the main driver script for the sqlite3_checker utility
-# program.
-#
-
-# Special case:
-#
-#      sqlite3_checker --test FILENAME ARGS
-#
-# uses FILENAME in place of this script.
-#
-if {[lindex $argv 0]=="--test" && [llength $argv]>1} {
-  set ::argv0 [lindex $argv 1]
-  set argv [lrange $argv 2 end]
-  source $argv0
-  exit 0
-}
-
-# Emulate a TCL shell
-#
-proc tclsh {} {
-  set line {}
-  while {![eof stdin]} {
-    if {$line!=""} {
-      puts -nonewline "> "
-    } else {
-      puts -nonewline "% "
-    }
-    flush stdout
-    append line [gets stdin]
-    if {[info complete $line]} {
-      if {[catch {uplevel #0 $line} result]} {
-        puts stderr "Error: $result"
-      } elseif {$result!=""} {
-        puts $result
-      }
-      set line {}
-    } else {
-      append line \n
-    }
-  }
-}
-
-# Do an incremental integrity check of a single index
-#
-proc check_index {idxname batchsize bTrace} {
-  set i 0
-  set more 1
-  set nerr 0
-  set pct 00.0
-  set max [db one {SELECT nEntry FROM sqlite_btreeinfo('main')
-                    WHERE name=$idxname}]
-  puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
-  flush stdout
-  if {$bTrace} {
-    set sql {SELECT errmsg, current_key AS key,
-                    CASE WHEN rowid=1 THEN scanner_sql END AS traceOut
-               FROM incremental_index_check($idxname)
-              WHERE after_key=$key
-              LIMIT $batchsize}
-  } else {
-    set sql {SELECT errmsg, current_key AS key, NULL AS traceOut
-               FROM incremental_index_check($idxname)
-              WHERE after_key=$key
-              LIMIT $batchsize}
-  }
-  while {$more} {
-    set more 0
-    db eval $sql {
-      set more 1
-      if {$errmsg!=""} {
-        incr nerr
-        puts "$idxname: key($key): $errmsg"
-      } elseif {$traceOut!=""} {
-        puts "$idxname: $traceOut"
-      }
-      incr i
-      
-    }
-    set x [format {%.1f} [expr {($i*100.0)/$max}]]
-    if {$x!=$pct} {
-      puts -nonewline "$idxname: $i of $max rows ($pct%)\r"
-      flush stdout
-      set pct $x
-    }
-  }
-  puts "$idxname: $nerr errors out of $i entries"
-}
-
-# Print a usage message on standard error, then quit.
-#
-proc usage {} {
-  set argv0 [file rootname [file tail [info nameofexecutable]]]
-  puts stderr "Usage: $argv0 OPTIONS database-filename"
-  puts stderr {
-Do sanity checking on a live SQLite3 database file specified by the
-"database-filename" argument.
-
-Options:
-
-   --batchsize N     Number of rows to check per transaction
-
-   --freelist        Perform a freelist check
-
-   --index NAME      Run a check of the index NAME
-
-   --summary         Print summary information about the database
-
-   --table NAME      Run a check of all indexes for table NAME
-
-   --tclsh           Run the built-in TCL interpreter (for debugging)
-
-   --trace           (Debugging only:) Output trace information on the scan
-
-   --version         Show the version number of SQLite
-}
-  exit 1
-}
-
-set file_to_analyze {}
-append argv {}
-set bFreelistCheck 0
-set bSummary 0
-set zIndex {}
-set zTable {}
-set batchsize 1000
-set bAll 1
-set bTrace 0
-set argc [llength $argv]
-for {set i 0} {$i<$argc} {incr i} {
-  set arg [lindex $argv $i]
-  if {[regexp {^-+tclsh$} $arg]} {
-    tclsh
-    exit 0
-  }
-  if {[regexp {^-+version$} $arg]} {
-    sqlite3 mem :memory:
-    puts [mem one {SELECT sqlite_version()||' '||sqlite_source_id()}]
-    mem close
-    exit 0
-  }
-  if {[regexp {^-+freelist$} $arg]} {
-    set bFreelistCheck 1
-    set bAll 0
-    continue
-  }
-  if {[regexp {^-+summary$} $arg]} {
-    set bSummary 1
-    set bAll 0
-    continue
-  }
-  if {[regexp {^-+trace$} $arg]} {
-    set bTrace 1
-    continue
-  }
-  if {[regexp {^-+batchsize$} $arg]} {
-    incr i
-    if {$i>=$argc} {
-      puts stderr "missing argument on $arg"
-      exit 1
-    }
-    set batchsize [lindex $argv $i]
-    continue
-  }
-  if {[regexp {^-+index$} $arg]} {
-    incr i
-    if {$i>=$argc} {
-      puts stderr "missing argument on $arg"
-      exit 1
-    }
-    set zIndex [lindex $argv $i]
-    set bAll 0
-    continue
-  }
-  if {[regexp {^-+table$} $arg]} {
-    incr i
-    if {$i>=$argc} {
-      puts stderr "missing argument on $arg"
-      exit 1
-    }
-    set zTable [lindex $argv $i]
-    set bAll 0
-    continue
-  }
-  if {[regexp {^-} $arg]} {
-    puts stderr "Unknown option: $arg"
-    usage
-  }
-  if {$file_to_analyze!=""} {
-    usage
-  } else {
-    set file_to_analyze $arg
-  }
-}
-if {$file_to_analyze==""} usage
-
-# If a TCL script is specified on the command-line, then run that
-# script.
-#
-if {[file extension $file_to_analyze]==".tcl"} {
-  source $file_to_analyze
-  exit 0
-}
-
-set root_filename $file_to_analyze
-regexp {^file:(//)?([^?]*)} $file_to_analyze all x1 root_filename
-if {![file exists $root_filename]} {
-  puts stderr "No such file: $root_filename"
-  exit 1
-}
-if {![file readable $root_filename]} {
-  puts stderr "File is not readable: $root_filename"
-  exit 1
-}
-
-if {[catch {sqlite3 db $file_to_analyze} res]} {
-  puts stderr "Cannot open datababase $root_filename: $res"
-  exit 1
-}
-
-if {$bFreelistCheck || $bAll} {
-  puts -nonewline "freelist-check: "
-  flush stdout
-  db eval BEGIN
-  puts [db one {SELECT checkfreelist('main')}]
-  db eval END
-}
-if {$bSummary} {
-  set scale 0
-  set pgsz [db one {PRAGMA page_size}]
-  db eval {SELECT nPage*$pgsz AS sz, name, tbl_name
-             FROM sqlite_btreeinfo
-            WHERE type='index'
-            ORDER BY 1 DESC, name} {
-    if {$scale==0} {
-      if {$sz>10000000} {
-        set scale 1000000.0
-        set unit MB
-      } else {
-        set scale 1000.0
-        set unit KB
-      }
-    }
-    puts [format {%7.1f %s index %s of table %s} \
-            [expr {$sz/$scale}] $unit $name $tbl_name]
-  }
-}
-if {$zIndex!=""} {
-  check_index $zIndex $batchsize $bTrace
-}
-if {$zTable!=""} {
-  foreach idx [db eval {SELECT name FROM sqlite_master
-                         WHERE type='index' AND rootpage>0
-                           AND tbl_name=$zTable}] {
-    check_index $idx $batchsize $bTrace
-  }
-}
-if {$bAll} {
-  set allidx [db eval {SELECT name FROM sqlite_btreeinfo('main')
-                        WHERE type='index' AND rootpage>0
-                        ORDER BY nEntry}]
-  foreach idx $allidx {
-    check_index $idx $batchsize $bTrace
-  }
-}
diff --git a/ext/repair/test/README.md b/ext/repair/test/README.md
deleted file mode 100644 (file)
index 8cc954a..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-To run these tests, first build sqlite3_checker:
-
-
->     make sqlite3_checker
-
-
-Then run the "test.tcl" script using:
-
-
->     ./sqlite3_checker --test $path/test.tcl
-
-
-Optionally add the full pathnames of individual *.test modules
diff --git a/ext/repair/test/checkfreelist01.test b/ext/repair/test/checkfreelist01.test
deleted file mode 100644 (file)
index 7e2dd51..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-# 2017-10-11
-
-set testprefix checkfreelist
-
-do_execsql_test 1.0 {
-  PRAGMA page_size=1024;
-  CREATE TABLE t1(a, b);
-}
-
-do_execsql_test 1.2 { SELECT checkfreelist('main') } {ok}
-do_execsql_test 1.3 {
-  WITH s(i) AS (
-    SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<10000
-  )
-  INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s;
-  DELETE FROM t1 WHERE rowid%3;
-  PRAGMA freelist_count;
-} {6726}
-
-do_execsql_test 1.4 { SELECT checkfreelist('main') } {ok}
-do_execsql_test 1.5 {
-  WITH freelist_trunk(i, d, n) AS (
-    SELECT 1, NULL, sqlite_readint32(data, 32) FROM sqlite_dbpage WHERE pgno=1
-      UNION ALL
-    SELECT n, data, sqlite_readint32(data) 
-    FROM freelist_trunk, sqlite_dbpage WHERE pgno=n
-  )
-  SELECT i FROM freelist_trunk WHERE i!=1;
-} {
-  10009 9715 9343 8969 8595 8222 7847 7474 7102 6727 6354 5982 5608 5234
-  4860 4487 4112 3740 3367 2992 2619 2247 1872 1499 1125 752 377 5
-}
-
-do_execsql_test 1.6 { SELECT checkfreelist('main') } {ok}
-
-proc set_int {blob idx newval} {
-  binary scan $blob I* ints
-  lset ints $idx $newval
-  binary format I* $ints
-}
-db func set_int set_int
-
-proc get_int {blob idx} {
-  binary scan $blob I* ints
-  lindex $ints $idx
-}
-db func get_int get_int
-
-do_execsql_test 1.7 {
-  BEGIN;
-    UPDATE sqlite_dbpage 
-      SET data = set_int(data, 1, get_int(data, 1)-1) 
-      WHERE pgno=4860;
-    SELECT checkfreelist('main');
-  ROLLBACK;
-} {{free-list count mismatch: actual=6725 header=6726}}
-
-do_execsql_test 1.8 {
-  BEGIN;
-    UPDATE sqlite_dbpage 
-      SET data = set_int(data, 5, (SELECT * FROM pragma_page_count)+1)
-      WHERE pgno=4860;
-    SELECT checkfreelist('main');
-  ROLLBACK;
-} {{leaf page 10092 is out of range (child 3 of trunk page 4860)}}
-
-do_execsql_test 1.9 {
-  BEGIN;
-    UPDATE sqlite_dbpage 
-      SET data = set_int(data, 5, 0)
-      WHERE pgno=4860;
-    SELECT checkfreelist('main');
-  ROLLBACK;
-} {{leaf page 0 is out of range (child 3 of trunk page 4860)}}
-
-do_execsql_test 1.10 {
-  BEGIN;
-    UPDATE sqlite_dbpage 
-      SET data = set_int(data, get_int(data, 1)+1, 0)
-      WHERE pgno=5;
-    SELECT checkfreelist('main');
-  ROLLBACK;
-} {{leaf page 0 is out of range (child 247 of trunk page 5)}}
-
-do_execsql_test 1.11 {
-  BEGIN;
-    UPDATE sqlite_dbpage 
-      SET data = set_int(data, 1, 249)
-      WHERE pgno=5;
-    SELECT checkfreelist('main');
-  ROLLBACK;
-} {{leaf count out of range (249) on trunk page 5}}
diff --git a/ext/repair/test/checkindex01.test b/ext/repair/test/checkindex01.test
deleted file mode 100644 (file)
index 97973ae..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-# 2017-10-11
-#
-set testprefix checkindex
-
-do_execsql_test 1.0 {
-  CREATE TABLE t1(a, b);
-  CREATE INDEX i1 ON t1(a);
-  INSERT INTO t1 VALUES('one', 2);
-  INSERT INTO t1 VALUES('two', 4);
-  INSERT INTO t1 VALUES('three', 6);
-  INSERT INTO t1 VALUES('four', 8);
-  INSERT INTO t1 VALUES('five', 10);
-
-  CREATE INDEX i2 ON t1(a DESC);
-} {}
-
-proc incr_index_check {idx nStep} {
-  set Q {
-    SELECT errmsg, current_key FROM incremental_index_check($idx, $after)
-    LIMIT $nStep
-  }
-
-  set res [list]
-  while {1} {
-    unset -nocomplain current_key
-    set res1 [db eval $Q]
-    if {[llength $res1]==0} break
-    set res [concat $res $res1]
-    set after [lindex $res end]
-  }
-
-  return $res
-}
-
-proc do_index_check_test {tn idx res} {
-  uplevel [list do_execsql_test $tn.1 "
-    SELECT errmsg, current_key FROM incremental_index_check('$idx');
-  " $res]
-
-  uplevel [list do_test $tn.2 "incr_index_check $idx 1" [list {*}$res]]
-  uplevel [list do_test $tn.3 "incr_index_check $idx 2" [list {*}$res]]
-  uplevel [list do_test $tn.4 "incr_index_check $idx 5" [list {*}$res]]
-}
-
-
-do_execsql_test 1.2.1 {
-  SELECT rowid, errmsg IS NULL, current_key FROM incremental_index_check('i1');
-} {
-  1 1 'five',5
-  2 1 'four',4
-  3 1 'one',1
-  4 1 'three',3
-  5 1 'two',2
-}
-do_execsql_test 1.2.2 {
-  SELECT errmsg IS NULL, current_key, index_name, after_key, scanner_sql
-    FROM incremental_index_check('i1') LIMIT 1;
-} {
-  1
-  'five',5
-  i1
-  {}
-  {SELECT (SELECT a IS i.i0 FROM 't1' AS t WHERE "rowid" COLLATE BINARY IS i.i1), quote(i0)||','||quote(i1) FROM (SELECT (a) AS i0, ("rowid" COLLATE BINARY) AS i1 FROM 't1' INDEXED BY 'i1' ORDER BY 1,2) AS i}
-}
-
-do_index_check_test 1.3 i1 {
-  {} 'five',5
-  {} 'four',4
-  {} 'one',1
-  {} 'three',3
-  {} 'two',2
-}
-
-do_index_check_test 1.4 i2 {
-  {} 'two',2
-  {} 'three',3
-  {} 'one',1
-  {} 'four',4
-  {} 'five',5
-}
-
-do_test 1.5 {
-  set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t1' }]
-  sqlite3_imposter db main $tblroot {CREATE TABLE xt1(a,b)}
-  db eval {
-    UPDATE xt1 SET a='six' WHERE rowid=3;
-    DELETE FROM xt1 WHERE rowid = 5;
-  }
-  sqlite3_imposter db main
-} {}
-
-do_index_check_test 1.6 i1 {
-  {row missing} 'five',5
-  {} 'four',4
-  {} 'one',1
-  {row data mismatch} 'three',3
-  {} 'two',2
-}
-
-do_index_check_test 1.7 i2 {
-  {} 'two',2
-  {row data mismatch} 'three',3
-  {} 'one',1
-  {} 'four',4
-  {row missing} 'five',5
-}
-
-#--------------------------------------------------------------------------
-do_execsql_test 2.0 {
-
-  CREATE TABLE t2(a INTEGER PRIMARY KEY, b, c, d);
-
-  INSERT INTO t2 VALUES(1, NULL, 1, 1);
-  INSERT INTO t2 VALUES(2, 1, NULL, 1);
-  INSERT INTO t2 VALUES(3, 1, 1, NULL);
-
-  INSERT INTO t2 VALUES(4, 2, 2, 1);
-  INSERT INTO t2 VALUES(5, 2, 2, 2);
-  INSERT INTO t2 VALUES(6, 2, 2, 3);
-
-  INSERT INTO t2 VALUES(7, 2, 2, 1);
-  INSERT INTO t2 VALUES(8, 2, 2, 2);
-  INSERT INTO t2 VALUES(9, 2, 2, 3);
-
-  CREATE INDEX i3 ON t2(b, c, d);
-  CREATE INDEX i4 ON t2(b DESC, c DESC, d DESC);
-  CREATE INDEX i5 ON t2(d, c DESC, b);
-} {}
-
-do_index_check_test 2.1 i3 {
-  {} NULL,1,1,1 
-  {} 1,NULL,1,2 
-  {} 1,1,NULL,3 
-  {} 2,2,1,4 
-  {} 2,2,1,7 
-  {} 2,2,2,5
-  {} 2,2,2,8 
-  {} 2,2,3,6 
-  {} 2,2,3,9
-}
-
-do_index_check_test 2.2 i4 {
-  {} 2,2,3,6 
-  {} 2,2,3,9
-  {} 2,2,2,5
-  {} 2,2,2,8 
-  {} 2,2,1,4 
-  {} 2,2,1,7 
-  {} 1,1,NULL,3 
-  {} 1,NULL,1,2 
-  {} NULL,1,1,1 
-}
-
-do_index_check_test 2.3 i5 {
-  {} NULL,1,1,3 
-  {} 1,2,2,4 
-  {} 1,2,2,7 
-  {} 1,1,NULL,1 
-  {} 1,NULL,1,2 
-  {} 2,2,2,5 
-  {} 2,2,2,8 
-  {} 3,2,2,6 
-  {} 3,2,2,9
-}
-
-#--------------------------------------------------------------------------
-do_execsql_test 3.0 {
-
-  CREATE TABLE t3(w, x, y, z PRIMARY KEY) WITHOUT ROWID;
-  CREATE INDEX t3wxy ON t3(w, x, y);
-  CREATE INDEX t3wxy2 ON t3(w DESC, x DESC, y DESC);
-
-  INSERT INTO t3 VALUES(NULL, NULL, NULL, 1);
-  INSERT INTO t3 VALUES(NULL, NULL, NULL, 2);
-  INSERT INTO t3 VALUES(NULL, NULL, NULL, 3);
-
-  INSERT INTO t3 VALUES('a', NULL, NULL, 4);
-  INSERT INTO t3 VALUES('a', NULL, NULL, 5);
-  INSERT INTO t3 VALUES('a', NULL, NULL, 6);
-
-  INSERT INTO t3 VALUES('a', 'b', NULL, 7);
-  INSERT INTO t3 VALUES('a', 'b', NULL, 8);
-  INSERT INTO t3 VALUES('a', 'b', NULL, 9);
-
-} {}
-
-do_index_check_test 3.1 t3wxy {
-  {} NULL,NULL,NULL,1 {} NULL,NULL,NULL,2 {} NULL,NULL,NULL,3 
-  {} 'a',NULL,NULL,4  {} 'a',NULL,NULL,5  {} 'a',NULL,NULL,6 
-  {} 'a','b',NULL,7   {} 'a','b',NULL,8   {} 'a','b',NULL,9 
-}
-do_index_check_test 3.2 t3wxy2 {
-  {} 'a','b',NULL,7   {} 'a','b',NULL,8   {} 'a','b',NULL,9 
-  {} 'a',NULL,NULL,4  {} 'a',NULL,NULL,5  {} 'a',NULL,NULL,6 
-  {} NULL,NULL,NULL,1 {} NULL,NULL,NULL,2 {} NULL,NULL,NULL,3 
-}
-
-#--------------------------------------------------------------------------
-# Test with an index that uses non-default collation sequences.
-#
-do_execsql_test 4.0 {
-  CREATE TABLE t4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT);
-  INSERT INTO t4 VALUES(1, 'aaa', 'bbb');
-  INSERT INTO t4 VALUES(2, 'AAA', 'CCC');
-  INSERT INTO t4 VALUES(3, 'aab', 'ddd');
-  INSERT INTO t4 VALUES(4, 'AAB', 'EEE');
-
-  CREATE INDEX t4cc ON t4(c1 COLLATE nocase, c2 COLLATE nocase);
-}
-
-do_index_check_test 4.1 t4cc {
-  {} 'aaa','bbb',1 
-  {} 'AAA','CCC',2 
-  {} 'aab','ddd',3 
-  {} 'AAB','EEE',4
-}
-
-do_test 4.2 {
-  set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t4' }]
-  sqlite3_imposter db main $tblroot \
-     {CREATE TABLE xt4(a INTEGER PRIMARY KEY, c1 TEXT, c2 TEXT)}
-
-  db eval {
-    UPDATE xt4 SET c1='hello' WHERE rowid=2;
-    DELETE FROM xt4 WHERE rowid = 3;
-  }
-  sqlite3_imposter db main
-} {}
-
-do_index_check_test 4.3 t4cc {
-  {} 'aaa','bbb',1 
-  {row data mismatch} 'AAA','CCC',2 
-  {row missing} 'aab','ddd',3 
-  {} 'AAB','EEE',4
-}
-
-#--------------------------------------------------------------------------
-# Test an index on an expression.
-#
-do_execsql_test 5.0 {
-  CREATE TABLE t5(x INTEGER PRIMARY KEY, y TEXT, UNIQUE(y));
-  INSERT INTO t5 VALUES(1, '{"x":1, "y":1}');
-  INSERT INTO t5 VALUES(2, '{"x":2, "y":2}');
-  INSERT INTO t5 VALUES(3, '{"x":3, "y":3}');
-  INSERT INTO t5 VALUES(4, '{"w":4, "z":4}');
-  INSERT INTO t5 VALUES(5, '{"x":5, "y":5}');
-
-  CREATE INDEX t5x ON t5( json_extract(y, '$.x') );
-  CREATE INDEX t5y ON t5( json_extract(y, '$.y') DESC );
-}
-
-do_index_check_test 5.1.1 t5x {
-  {} NULL,4 {} 1,1 {} 2,2 {} 3,3 {} 5,5
-}
-
-do_index_check_test 5.1.2 t5y {
-  {} 5,5 {} 3,3 {} 2,2 {} 1,1 {} NULL,4
-}
-
-do_index_check_test 5.1.3 sqlite_autoindex_t5_1 {
-  {} {'{"w":4, "z":4}',4} 
-  {} {'{"x":1, "y":1}',1} 
-  {} {'{"x":2, "y":2}',2} 
-  {} {'{"x":3, "y":3}',3} 
-  {} {'{"x":5, "y":5}',5}
-}
-
-do_test 5.2 {
-  set tblroot [db one { SELECT rootpage FROM sqlite_master WHERE name='t5' }]
-  sqlite3_imposter db main $tblroot \
-      {CREATE TABLE xt5(a INTEGER PRIMARY KEY, c1 TEXT);}
-  db eval {
-    UPDATE xt5 SET c1='{"x":22, "y":11}' WHERE rowid=1;
-    DELETE FROM xt5 WHERE rowid = 4;
-  }
-  sqlite3_imposter db main
-} {}
-
-do_index_check_test 5.3.1 t5x {
-  {row missing} NULL,4 
-  {row data mismatch} 1,1 
-  {} 2,2 
-  {} 3,3 
-  {} 5,5
-}
-
-do_index_check_test 5.3.2 sqlite_autoindex_t5_1 {
-  {row missing} {'{"w":4, "z":4}',4} 
-  {row data mismatch} {'{"x":1, "y":1}',1} 
-  {} {'{"x":2, "y":2}',2} 
-  {} {'{"x":3, "y":3}',3} 
-  {} {'{"x":5, "y":5}',5}
-}
-
-#-------------------------------------------------------------------------
-#
-do_execsql_test 6.0 {
-  CREATE TABLE t6(x INTEGER PRIMARY KEY, y, z);
-  CREATE INDEX t6x1 ON t6(y, /* one,two,three */ z);
-  CREATE INDEX t6x2 ON t6(z, -- hello,world,
-  y);
-
-  CREATE INDEX t6x3 ON t6(z -- hello,world
-  , y);
-
-  INSERT INTO t6 VALUES(1, 2, 3);
-  INSERT INTO t6 VALUES(4, 5, 6);
-}
-
-do_index_check_test 6.1 t6x1 {
-  {} 2,3,1 
-  {} 5,6,4
-}
-do_index_check_test 6.2 t6x2 {
-  {} 3,2,1 
-  {} 6,5,4
-}
-do_index_check_test 6.2 t6x3 {
-  {} 3,2,1 
-  {} 6,5,4
-}
-
-#-------------------------------------------------------------------------
-#
-do_execsql_test 7.0 {
-  CREATE TABLE t7(x INTEGER PRIMARY KEY, y, z);
-  INSERT INTO t7 VALUES(1, 1, 1);
-  INSERT INTO t7 VALUES(2, 2, 0);
-  INSERT INTO t7 VALUES(3, 3, 1);
-  INSERT INTO t7 VALUES(4, 4, 0);
-
-  CREATE INDEX t7i1 ON t7(y) WHERE z=1;
-  CREATE INDEX t7i2 ON t7(y) /* hello,world */ WHERE z=1;
-  CREATE INDEX t7i3 ON t7(y) WHERE -- yep 
-  z=1;
-  CREATE INDEX t7i4 ON t7(y) WHERE z=1 -- yep;
-}
-do_index_check_test 7.1 t7i1 {
-  {} 1,1 {} 3,3
-}
-do_index_check_test 7.2 t7i2 {
-  {} 1,1 {} 3,3
-}
-do_index_check_test 7.3 t7i3 {
-  {} 1,1 {} 3,3
-}
-do_index_check_test 7.4 t7i4 {
-  {} 1,1 {} 3,3
-}
diff --git a/ext/repair/test/test.tcl b/ext/repair/test/test.tcl
deleted file mode 100644 (file)
index c073bb7..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-# Run this script using
-#
-#       sqlite3_checker --test $thisscript $testscripts
-#
-# The $testscripts argument is optional.  If omitted, all *.test files
-# in the same directory as $thisscript are run.
-#
-set NTEST 0
-set NERR  0
-
-
-# Invoke the do_test procedure to run a single test
-#
-# The $expected parameter is the expected result.  The result is the return
-# value from the last TCL command in $cmd.
-#
-# Normally, $expected must match exactly.  But if $expected is of the form
-# "/regexp/" then regular expression matching is used.  If $expected is
-# "~/regexp/" then the regular expression must NOT match.  If $expected is
-# of the form "#/value-list/" then each term in value-list must be numeric
-# and must approximately match the corresponding numeric term in $result.
-# Values must match within 10%.  Or if the $expected term is A..B then the
-# $result term must be in between A and B.
-#
-proc do_test {name cmd expected} {
-  if {[info exists ::testprefix]} {
-    set name "$::testprefix$name"
-  }
-
-  incr ::NTEST
-  puts -nonewline $name...
-  flush stdout
-
-  if {[catch {uplevel #0 "$cmd;\n"} result]} {
-    puts -nonewline $name...
-    puts "\nError: $result"
-    incr ::NERR
-  } else {
-    set ok [expr {[string compare $result $expected]==0}]
-    if {!$ok} {
-      puts "\n!  $name expected: \[$expected\]\n! $name got:      \[$result\]"
-      incr ::NERR
-    } else {
-      puts " Ok"
-    }
-  }
-  flush stdout
-}
-
-#
-#   do_execsql_test TESTNAME SQL RES
-#
-proc do_execsql_test {testname sql {result {}}} {
-  uplevel [list do_test $testname [list db eval $sql] [list {*}$result]]
-}
-
-if {[llength $argv]==0} {
-  set dir [file dirname $argv0]
-  set argv [glob -nocomplain $dir/*.test]
-}
-foreach testfile $argv {
-  file delete -force test.db
-  sqlite3 db test.db
-  source $testfile
-  catch {db close}
-}
-puts "$NERR errors out of $NTEST tests"
diff --git a/main.mk b/main.mk
index 8b5d2821cf77a9a43b3f8b3d7e3a8861497c7413..46d646d03a9db71fbb0f8a4b7f575fbd8a78aeda 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -1971,24 +1971,6 @@ sqlite3_expert$(T.exe): $(TOP)/ext/expert/sqlite3expert.h $(TOP)/ext/expert/sqli
                $(TOP)/ext/expert/expert.c sqlite3.c -o sqlite3_expert $(LDFLAGS.libsqlite3)
 xbin: sqlite3_expert$(T.exe)
 
-CHECKER_DEPS =\
-  $(TOP)/tool/mkccode.tcl \
-  sqlite3.c \
-  tclsqlite-ex.c \
-  $(TOP)/ext/repair/sqlite3_checker.tcl \
-  $(TOP)/ext/repair/checkindex.c \
-  $(TOP)/ext/repair/checkfreelist.c \
-  $(TOP)/ext/misc/btreeinfo.c \
-  $(TOP)/ext/repair/sqlite3_checker.c.in
-
-sqlite3_checker.c:     $(CHECKER_DEPS)
-       $(B.tclsh) $(TOP)/tool/mkccode.tcl $(TOP)/ext/repair/sqlite3_checker.c.in >$@
-
-sqlite3_checker$(T.exe):       $(T.tcl.env.sh) sqlite3_checker.c
-       $(T.link.tcl) sqlite3_checker.c -o $@ $$TCL_INCLUDE_SPEC \
-               $$TCL_LIB_SPEC $(LDFLAGS.libsqlite3)
-xbin: sqlite3_checker$(T.exe)
-
 dbdump$(T.exe): $(TOP)/ext/misc/dbdump.c sqlite3.o
        $(T.link) -DDBDUMP_STANDALONE -o $@ \
                $(TOP)/ext/misc/dbdump.c sqlite3.o $(LDFLAGS.libsqlite3)
index 1e2d8e52dba119d27f7e41802a5fdcb0057f2a06..559c825e7b1895be5bf194a5a9c9edf534bf5a63 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,12 +1,12 @@
-C Disable\stest\sshell1-5.0\sas\sit\sis\scausing\sa\suse\sof\sinitialized\sdeep\sinside\nof\sTCL.
-D 2026-03-02T13:43:08.964
+C Remove\sthe\sexperimental\sand\sincomplete\sext/repair\sextension,\s\sto\sprevent\sAIs\nfrom\sscanning\sthe\s(incomplete)\scode\sand\sreporting\sbugs\sagainst\sit.
+D 2026-03-02T13:44:04.938
 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md 6bc480fc673fb4acbc4094e77edb326267dd460162d7723c7f30bee2d3d9e97d
 F Makefile.in 3ce07126d7e87c7464301482e161fdae6a51d0a2aa06b200b8f0000ef4d6163b
 F Makefile.linux-generic bd3e3cacd369821a6241d4ea1967395c962dfe3057e38cb0a435cee0e8b789d0
-F Makefile.msc 1fa179beafd6d438b8479146cae77fb1724dd35b330b09dbfebd8a2f0823c62a
+F Makefile.msc 174764cb7e80c80f9003c46b3e388d74c68c8c40230208904b3af8fcabee5f4e
 F README.md 3fa51fc7ababc32edd175ae8b2986c86d5ea120c1cb1e57c7f7849492d1405ec
 F VERSION 74672bfd4c7826c0fc6f84762488a707c52e7d2d94af42ccb0edcc6c74311c41
 F art/icon-243x273.gif 9750b734f82fdb3dc43127753d5e6fbf3b62c9f4e136c2fbf573b2f57ea87af5
@@ -488,15 +488,6 @@ F ext/recover/recoversql.test e66d01f95302a223bcd3fd42b5ee58dc2b53d70afa90b0d00e
 F ext/recover/sqlite3recover.c 56c216332ea91233d6d820d429f3384adbec9ecedda67aa98186b691d427cc57
 F ext/recover/sqlite3recover.h 011c799f02deb70ab685916f6f538e6bb32c4e0025e79bfd0e24ff9c74820959
 F ext/recover/test_recover.c 3d0fb1df7823f5bc22a0b93955034d16a2dfa2eb1e443e9a0123a77f120599a3
-F ext/repair/README.md 92f5e8aae749a4dae14f02eea8e1bb42d4db2b6ce5e83dbcdd6b1446997e0c15
-F ext/repair/checkfreelist.c e21f06995ff4efdc1622dcceaea4dcba2caa83ca2f31a1607b98a8509168a996
-F ext/repair/checkindex.c 7639b4f8928f82c10b950169e60cc45a7f6798df0b299771d17bef025736f657
-F ext/repair/sqlite3_checker.c.in 445118c5f7fea958b36fba1b2c464283e60ed4842039ddee3265f1698115ebf7
-F ext/repair/sqlite3_checker.tcl a9a2caa9660567257c177a91124d8c0dccdfa341e25c51e6da7f1fd9e601eafa
-F ext/repair/test/README.md 34b2f542cf5be7bffe479242b33ee3492cea30711e447cc4a1a86cb5915f419e
-F ext/repair/test/checkfreelist01.test 3e8aa6aeb4007680c94a8d07b41c339aa635cc78249442da72ff3f8297398a69
-F ext/repair/test/checkindex01.test b530f141413b587c9eb78ff734de6bb79bc3515c335096108c12c01bddbadcec
-F ext/repair/test/test.tcl 686d76d888dffd021f64260abf29a55c57b2cedfa7fc69150b42b1d6119aac3c
 F ext/rtree/README 734aa36238bcd2dee91db5dba107d5fcbdb02396612811377a8ad50f1272b1c1
 F ext/rtree/geopoly.c bd1971479184d559499ff3087c37f2823977d7b0ec80916141ae66f70345c88d
 F ext/rtree/rtree.c 9331997a76b88a9bc04e156bdfd6e2fe35c0aa93bc338ebc6aa0ae470fe4a852
@@ -660,7 +651,7 @@ F ext/wasm/tests/opfs/sahpool/index.html be736567fd92d3ecb9754c145755037cbbd2bca
 F ext/wasm/tests/opfs/sahpool/sahpool-pausing.js f264925cfc82155de38cecb3d204c36e0f6991460fff0cb7c15079454679a4e2
 F ext/wasm/tests/opfs/sahpool/sahpool-worker.js bd25a43fc2ab2d1bafd8f2854ad3943ef673f7c3be03e95ecf1612ff6e8e2a61
 F magic.txt 5ade0bc977aa135e79e3faaea894d5671b26107cc91e70783aa7dc83f22f3ba0
-F main.mk 9393d5982db60f26e72c5af24a8c11cf39374ff5e695fadb5a4e7376f28150c6
+F main.mk e1a03e9206f6a042a9147035915cb944e9242d570779bc3ccd7ed6a39df10cae
 F make.bat a136fd0b1c93e89854a86d5f4edcf0386d211e5d5ec2434480f6eea436c7420c
 F mptest/config01.test 3c6adcbc50b991866855f1977ff172eb6d901271
 F mptest/config02.test 4415dfe36c48785f751e16e32c20b077c28ae504
@@ -2197,8 +2188,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
 F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
 F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P e8976d5041c929675772039b7a8fc4ff0b609537d86f9aa6e445ecd512a10673
-R 196e96eb644b7fb48b6564a67ba146cd
+P 440bd6091e3767f0a2f42ffdc92ca5e4736c0a73324fdd15397c3b5dbbc31fb8
+R c2e39b4a7bc89f40ea6792af5222cc7a
 U drh
-Z db4a137667e1314416d854cef3854055
+Z 26aaa04451a5b488441824f4e50b1bf2
 # Remove this line to create a well-formed Fossil manifest.
index b3fac4eaf8ee34aeb4ef43ace6587a246056c72e..a60931df6c3e03ade020204c38db6de05b005be8 100644 (file)
@@ -1 +1 @@
-440bd6091e3767f0a2f42ffdc92ca5e4736c0a73324fdd15397c3b5dbbc31fb8
+213b1c6608af4b3e9d6e0d8de6432cc6857931427baf4beac1e0a4294e4dc6ce