| Index: third_party/sqlite/src/src/test1.c | 
| diff --git a/third_party/sqlite/src/src/test1.c b/third_party/sqlite/src/src/test1.c | 
| index e46ddfdd3e0d5ed712e755f921d81d6686578541..8a0d09a7164752018c497f0e957345118593260a 100644 | 
| --- a/third_party/sqlite/src/src/test1.c | 
| +++ b/third_party/sqlite/src/src/test1.c | 
| @@ -12,8 +12,6 @@ | 
| ** Code for testing all sorts of SQLite interfaces.  This code | 
| ** is not included in the SQLite library.  It is used for automated | 
| ** testing of the SQLite library. | 
| -** | 
| -** $Id: test1.c,v 1.354 2009/08/10 04:37:50 danielk1977 Exp $ | 
| */ | 
| #include "sqliteInt.h" | 
| #include "tcl.h" | 
| @@ -1237,7 +1235,7 @@ static int sqlite3_mprintf_int64( | 
| return TCL_ERROR; | 
| } | 
| for(i=2; i<5; i++){ | 
| -    if( !sqlite3Atoi64(argv[i], &a[i-2]) ){ | 
| +    if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){ | 
| Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0); | 
| return TCL_ERROR; | 
| } | 
| @@ -1592,6 +1590,81 @@ static int test_table_column_metadata( | 
|  | 
| #ifndef SQLITE_OMIT_INCRBLOB | 
|  | 
| +static int blobHandleFromObj( | 
| +  Tcl_Interp *interp, | 
| +  Tcl_Obj *pObj, | 
| +  sqlite3_blob **ppBlob | 
| +){ | 
| +  char *z; | 
| +  int n; | 
| + | 
| +  z = Tcl_GetStringFromObj(pObj, &n); | 
| +  if( n==0 ){ | 
| +    *ppBlob = 0; | 
| +  }else{ | 
| +    int notUsed; | 
| +    Tcl_Channel channel; | 
| +    ClientData instanceData; | 
| + | 
| +    channel = Tcl_GetChannel(interp, z, ¬Used); | 
| +    if( !channel ) return TCL_ERROR; | 
| + | 
| +    Tcl_Flush(channel); | 
| +    Tcl_Seek(channel, 0, SEEK_SET); | 
| + | 
| +    instanceData = Tcl_GetChannelInstanceData(channel); | 
| +    *ppBlob = *((sqlite3_blob **)instanceData); | 
| +  } | 
| + | 
| +  return TCL_OK; | 
| +} | 
| + | 
| +/* | 
| +** sqlite3_blob_bytes  CHANNEL | 
| +*/ | 
| +static int test_blob_bytes( | 
| +  ClientData clientData, /* Not used */ | 
| +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ | 
| +  int objc,              /* Number of arguments */ | 
| +  Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| +){ | 
| +  sqlite3_blob *pBlob; | 
| +  int nByte; | 
| + | 
| +  if( objc!=2 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL"); | 
| +    return TCL_ERROR; | 
| +  } | 
| + | 
| +  if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; | 
| +  nByte = sqlite3_blob_bytes(pBlob); | 
| +  Tcl_SetObjResult(interp, Tcl_NewIntObj(nByte)); | 
| + | 
| +  return TCL_OK; | 
| +} | 
| + | 
| +/* | 
| +** sqlite3_blob_close  CHANNEL | 
| +*/ | 
| +static int test_blob_close( | 
| +  ClientData clientData, /* Not used */ | 
| +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ | 
| +  int objc,              /* Number of arguments */ | 
| +  Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| +){ | 
| +  sqlite3_blob *pBlob; | 
| + | 
| +  if( objc!=2 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL"); | 
| +    return TCL_ERROR; | 
| +  } | 
| + | 
| +  if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; | 
| +  sqlite3_blob_close(pBlob); | 
| + | 
| +  return TCL_OK; | 
| +} | 
| + | 
| /* | 
| ** sqlite3_blob_read  CHANNEL OFFSET N | 
| ** | 
| @@ -1613,13 +1686,10 @@ static int test_blob_read( | 
| int objc,              /* Number of arguments */ | 
| Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| ){ | 
| -  Tcl_Channel channel; | 
| -  ClientData instanceData; | 
| sqlite3_blob *pBlob; | 
| -  int notUsed; | 
| int nByte; | 
| int iOffset; | 
| -  unsigned char *zBuf; | 
| +  unsigned char *zBuf = 0; | 
| int rc; | 
|  | 
| if( objc!=4 ){ | 
| @@ -1627,19 +1697,16 @@ static int test_blob_read( | 
| return TCL_ERROR; | 
| } | 
|  | 
| -  channel = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), ¬Used); | 
| -  if( !channel | 
| -   || TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) | 
| +  if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; | 
| +  if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) | 
| || TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte) | 
| -   || nByte<0 || iOffset<0 | 
| ){ | 
| return TCL_ERROR; | 
| } | 
|  | 
| -  instanceData = Tcl_GetChannelInstanceData(channel); | 
| -  pBlob = *((sqlite3_blob **)instanceData); | 
| - | 
| -  zBuf = (unsigned char *)Tcl_Alloc(nByte); | 
| +  if( nByte>0 ){ | 
| +    zBuf = (unsigned char *)Tcl_Alloc(nByte); | 
| +  } | 
| rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset); | 
| if( rc==SQLITE_OK ){ | 
| Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte)); | 
| @@ -1671,10 +1738,7 @@ static int test_blob_write( | 
| int objc,              /* Number of arguments */ | 
| Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| ){ | 
| -  Tcl_Channel channel; | 
| -  ClientData instanceData; | 
| sqlite3_blob *pBlob; | 
| -  int notUsed; | 
| int iOffset; | 
| int rc; | 
|  | 
| @@ -1686,14 +1750,11 @@ static int test_blob_write( | 
| return TCL_ERROR; | 
| } | 
|  | 
| -  channel = Tcl_GetChannel(interp, Tcl_GetString(objv[1]), ¬Used); | 
| -  if( !channel || TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){ | 
| +  if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; | 
| +  if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){ | 
| return TCL_ERROR; | 
| } | 
|  | 
| -  instanceData = Tcl_GetChannelInstanceData(channel); | 
| -  pBlob = *((sqlite3_blob **)instanceData); | 
| - | 
| zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf); | 
| if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){ | 
| return TCL_ERROR; | 
| @@ -1705,6 +1766,33 @@ static int test_blob_write( | 
|  | 
| return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); | 
| } | 
| + | 
| +static int test_blob_reopen( | 
| +  ClientData clientData, /* Not used */ | 
| +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ | 
| +  int objc,              /* Number of arguments */ | 
| +  Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| +){ | 
| +  Tcl_WideInt iRowid; | 
| +  sqlite3_blob *pBlob; | 
| +  int rc; | 
| + | 
| +  if( objc!=3 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID"); | 
| +    return TCL_ERROR; | 
| +  } | 
| + | 
| +  if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR; | 
| +  if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR; | 
| + | 
| +  rc = sqlite3_blob_reopen(pBlob, iRowid); | 
| +  if( rc!=SQLITE_OK ){ | 
| +    Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE); | 
| +  } | 
| + | 
| +  return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR); | 
| +} | 
| + | 
| #endif | 
|  | 
| /* | 
| @@ -1793,6 +1881,129 @@ static int test_create_collation_v2( | 
| } | 
|  | 
| /* | 
| +** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES? | 
| +** | 
| +** Available switches are: | 
| +** | 
| +**   -func    SCRIPT | 
| +**   -step    SCRIPT | 
| +**   -final   SCRIPT | 
| +**   -destroy SCRIPT | 
| +*/ | 
| +typedef struct CreateFunctionV2 CreateFunctionV2; | 
| +struct CreateFunctionV2 { | 
| +  Tcl_Interp *interp; | 
| +  Tcl_Obj *pFunc;                 /* Script for function invocation */ | 
| +  Tcl_Obj *pStep;                 /* Script for agg. step invocation */ | 
| +  Tcl_Obj *pFinal;                /* Script for agg. finalization invocation */ | 
| +  Tcl_Obj *pDestroy;              /* Destructor script */ | 
| +}; | 
| +static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ | 
| +} | 
| +static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){ | 
| +} | 
| +static void cf2Final(sqlite3_context *ctx){ | 
| +} | 
| +static void cf2Destroy(void *pUser){ | 
| +  CreateFunctionV2 *p = (CreateFunctionV2 *)pUser; | 
| + | 
| +  if( p->interp && p->pDestroy ){ | 
| +    int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0); | 
| +    if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp); | 
| +  } | 
| + | 
| +  if( p->pFunc ) Tcl_DecrRefCount(p->pFunc); | 
| +  if( p->pStep ) Tcl_DecrRefCount(p->pStep); | 
| +  if( p->pFinal ) Tcl_DecrRefCount(p->pFinal); | 
| +  if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy); | 
| +  sqlite3_free(p); | 
| +} | 
| +static int test_create_function_v2( | 
| +  ClientData clientData,          /* Not used */ | 
| +  Tcl_Interp *interp,             /* The invoking TCL interpreter */ | 
| +  int objc,                       /* Number of arguments */ | 
| +  Tcl_Obj *CONST objv[]           /* Command arguments */ | 
| +){ | 
| +  sqlite3 *db; | 
| +  const char *zFunc; | 
| +  int nArg; | 
| +  int enc; | 
| +  CreateFunctionV2 *p; | 
| +  int i; | 
| +  int rc; | 
| + | 
| +  struct EncTable { | 
| +    const char *zEnc; | 
| +    int enc; | 
| +  } aEnc[] = { | 
| +    {"utf8",    SQLITE_UTF8 }, | 
| +    {"utf16",   SQLITE_UTF16 }, | 
| +    {"utf16le", SQLITE_UTF16LE }, | 
| +    {"utf16be", SQLITE_UTF16BE }, | 
| +    {"any",     SQLITE_ANY }, | 
| +    {"0", 0 } | 
| +  }; | 
| + | 
| +  if( objc<5 || (objc%2)==0 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES..."); | 
| +    return TCL_ERROR; | 
| +  } | 
| + | 
| +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; | 
| +  zFunc = Tcl_GetString(objv[2]); | 
| +  if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR; | 
| +  if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]), | 
| +          "encoding", 0, &enc) | 
| +  ){ | 
| +    return TCL_ERROR; | 
| +  } | 
| +  enc = aEnc[enc].enc; | 
| + | 
| +  p = sqlite3_malloc(sizeof(CreateFunctionV2)); | 
| +  assert( p ); | 
| +  memset(p, 0, sizeof(CreateFunctionV2)); | 
| +  p->interp = interp; | 
| + | 
| +  for(i=5; i<objc; i+=2){ | 
| +    int iSwitch; | 
| +    const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0}; | 
| +    if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){ | 
| +      sqlite3_free(p); | 
| +      return TCL_ERROR; | 
| +    } | 
| + | 
| +    switch( iSwitch ){ | 
| +      case 0: p->pFunc = objv[i+1];      break; | 
| +      case 1: p->pStep = objv[i+1];      break; | 
| +      case 2: p->pFinal = objv[i+1];     break; | 
| +      case 3: p->pDestroy = objv[i+1];   break; | 
| +    } | 
| +  } | 
| +  if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc); | 
| +  if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep); | 
| +  if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal); | 
| +  if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy); | 
| + | 
| +  if( p->pFunc ) Tcl_IncrRefCount(p->pFunc); | 
| +  if( p->pStep ) Tcl_IncrRefCount(p->pStep); | 
| +  if( p->pFinal ) Tcl_IncrRefCount(p->pFinal); | 
| +  if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy); | 
| + | 
| +  rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p, | 
| +      (p->pFunc ? cf2Func : 0), | 
| +      (p->pStep ? cf2Step : 0), | 
| +      (p->pFinal ? cf2Final : 0), | 
| +      cf2Destroy | 
| +  ); | 
| +  if( rc!=SQLITE_OK ){ | 
| +    Tcl_ResetResult(interp); | 
| +    Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  return TCL_OK; | 
| +} | 
| + | 
| +/* | 
| ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC? | 
| */ | 
| static int test_load_extension( | 
| @@ -1903,6 +2114,13 @@ static int sqlite_abort( | 
| int argc,              /* Number of arguments */ | 
| char **argv            /* Text of each argument */ | 
| ){ | 
| +#if defined(_MSC_VER) | 
| +  /* We do this, otherwise the test will halt with a popup message | 
| +   * that we have to click away before the test will continue. | 
| +   */ | 
| +  _set_abort_behavior( 0, _CALL_REPORTFAULT ); | 
| +#endif | 
| +  exit(255); | 
| assert( interp==0 );   /* This will always fail */ | 
| return TCL_OK; | 
| } | 
| @@ -2027,6 +2245,7 @@ static int test_stmt_status( | 
| } aOp[] = { | 
| { "SQLITE_STMTSTATUS_FULLSCAN_STEP",   SQLITE_STMTSTATUS_FULLSCAN_STEP   }, | 
| { "SQLITE_STMTSTATUS_SORT",            SQLITE_STMTSTATUS_SORT            }, | 
| +    { "SQLITE_STMTSTATUS_AUTOINDEX",       SQLITE_STMTSTATUS_AUTOINDEX       }, | 
| }; | 
| if( objc!=4 ){ | 
| Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG"); | 
| @@ -2080,6 +2299,33 @@ static int test_next_stmt( | 
| return TCL_OK; | 
| } | 
|  | 
| +/* | 
| +** Usage:  sqlite3_stmt_readonly  STMT | 
| +** | 
| +** Return true if STMT is a NULL pointer or a pointer to a statement | 
| +** that is guaranteed to leave the database unmodified. | 
| +*/ | 
| +static int test_stmt_readonly( | 
| +  void * clientData, | 
| +  Tcl_Interp *interp, | 
| +  int objc, | 
| +  Tcl_Obj *CONST objv[] | 
| +){ | 
| +  sqlite3_stmt *pStmt; | 
| +  int rc; | 
| + | 
| +  if( objc!=2 ){ | 
| +    Tcl_AppendResult(interp, "wrong # args: should be \"", | 
| +        Tcl_GetStringFromObj(objv[0], 0), " STMT", 0); | 
| +    return TCL_ERROR; | 
| +  } | 
| + | 
| +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; | 
| +  rc = sqlite3_stmt_readonly(pStmt); | 
| +  Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc)); | 
| +  return TCL_OK; | 
| +} | 
| + | 
|  | 
| /* | 
| ** Usage:  sqlite3_reset  STMT | 
| @@ -2285,7 +2531,7 @@ static int test_collate_func( | 
| int nB, const void *zB | 
| ){ | 
| Tcl_Interp *i = pTestCollateInterp; | 
| -  int encin = (int)pCtx; | 
| +  int encin = SQLITE_PTR_TO_INT(pCtx); | 
| int res; | 
| int n; | 
|  | 
| @@ -2414,7 +2660,7 @@ static void test_collate_needed_cb( | 
| } | 
| zNeededCollation[i] = 0; | 
| sqlite3_create_collation( | 
| -      db, "test_collate", ENC(db), (void *)enc, test_collate_func); | 
| +      db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func); | 
| } | 
|  | 
| /* | 
| @@ -2463,8 +2709,8 @@ static int alignmentCollFunc( | 
| ){ | 
| int rc, n; | 
| n = nKey1<nKey2 ? nKey1 : nKey2; | 
| -  if( nKey1>0 && 1==(1&(int)pKey1) ) unaligned_string_counter++; | 
| -  if( nKey2>0 && 1==(1&(int)pKey2) ) unaligned_string_counter++; | 
| +  if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++; | 
| +  if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++; | 
| rc = memcmp(pKey1, pKey2, n); | 
| if( rc==0 ){ | 
| rc = nKey1 - nKey2; | 
| @@ -2627,7 +2873,7 @@ bad_args: | 
| } | 
|  | 
| /* | 
| -** Usage:         test_errstr <err code> | 
| +** Usage:         sqlite3_test_errstr <err code> | 
| ** | 
| ** Test that the english language string equivalents for sqlite error codes | 
| ** are sane. The parameter is an integer representing an sqlite error code. | 
| @@ -3303,6 +3549,7 @@ static int test_prepare( | 
| if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR; | 
|  | 
| rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); | 
| +  Tcl_ResetResult(interp); | 
| if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; | 
| if( zTail && objc>=5 ){ | 
| if( bytes>=0 ){ | 
| @@ -3360,6 +3607,7 @@ static int test_prepare_v2( | 
|  | 
| rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0); | 
| assert(rc==SQLITE_OK || pStmt==0); | 
| +  Tcl_ResetResult(interp); | 
| if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; | 
| if( zTail && objc>=5 ){ | 
| if( bytes>=0 ){ | 
| @@ -3899,7 +4147,6 @@ static int test_global_recover( | 
| int objc, | 
| Tcl_Obj *CONST objv[] | 
| ){ | 
| -#ifndef SQLITE_OMIT_GLOBALRECOVER | 
| #ifndef SQLITE_OMIT_DEPRECATED | 
| int rc; | 
| if( objc!=1 ){ | 
| @@ -3909,7 +4156,6 @@ static int test_global_recover( | 
| rc = sqlite3_global_recover(); | 
| Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); | 
| #endif | 
| -#endif | 
| return TCL_OK; | 
| } | 
|  | 
| @@ -4260,20 +4506,17 @@ static int test_soft_heap_limit( | 
| int objc, | 
| Tcl_Obj *CONST objv[] | 
| ){ | 
| -  static int softHeapLimit = 0; | 
| -  int amt; | 
| +  sqlite3_int64 amt; | 
| +  sqlite3_int64 N = -1; | 
| if( objc!=1 && objc!=2 ){ | 
| Tcl_WrongNumArgs(interp, 1, objv, "?N?"); | 
| return TCL_ERROR; | 
| } | 
| -  amt = softHeapLimit; | 
| if( objc==2 ){ | 
| -    int N; | 
| -    if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; | 
| -    sqlite3_soft_heap_limit(N); | 
| -    softHeapLimit = N; | 
| +    if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR; | 
| } | 
| -  Tcl_SetObjResult(interp, Tcl_NewIntObj(amt)); | 
| +  amt = sqlite3_soft_heap_limit64(N); | 
| +  Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt)); | 
| return TCL_OK; | 
| } | 
|  | 
| @@ -4558,13 +4801,13 @@ static int file_control_test( | 
| } | 
| if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; | 
| rc = sqlite3_file_control(db, 0, 0, &iArg); | 
| -  assert( rc==SQLITE_ERROR ); | 
| +  assert( rc==SQLITE_NOTFOUND ); | 
| rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg); | 
| assert( rc==SQLITE_ERROR ); | 
| rc = sqlite3_file_control(db, "main", -1, &iArg); | 
| -  assert( rc==SQLITE_ERROR ); | 
| +  assert( rc==SQLITE_NOTFOUND ); | 
| rc = sqlite3_file_control(db, "temp", -1, &iArg); | 
| -  assert( rc==SQLITE_ERROR ); | 
| +  assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR ); | 
|  | 
| return TCL_OK; | 
| } | 
| @@ -4608,7 +4851,83 @@ static int file_control_lasterrno_test( | 
| } | 
|  | 
| /* | 
| -** tclcmd:   file_control_lockproxy_test DB | 
| +** tclcmd:   file_control_chunksize_test DB DBNAME SIZE | 
| +** | 
| +** This TCL command runs the sqlite3_file_control interface and | 
| +** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and | 
| +** SQLITE_SET_LOCKPROXYFILE verbs. | 
| +*/ | 
| +static int file_control_chunksize_test( | 
| +  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ | 
| +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ | 
| +  int objc,              /* Number of arguments */ | 
| +  Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| +){ | 
| +  int nSize;                      /* New chunk size */ | 
| +  char *zDb;                      /* Db name ("main", "temp" etc.) */ | 
| +  sqlite3 *db;                    /* Database handle */ | 
| +  int rc;                         /* file_control() return code */ | 
| + | 
| +  if( objc!=4 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE"); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) | 
| +   || Tcl_GetIntFromObj(interp, objv[3], &nSize) | 
| +  ){ | 
| +   return TCL_ERROR; | 
| +  } | 
| +  zDb = Tcl_GetString(objv[2]); | 
| +  if( zDb[0]=='\0' ) zDb = NULL; | 
| + | 
| +  rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize); | 
| +  if( rc ){ | 
| +    Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  return TCL_OK; | 
| +} | 
| + | 
| +/* | 
| +** tclcmd:   file_control_sizehint_test DB DBNAME SIZE | 
| +** | 
| +** This TCL command runs the sqlite3_file_control interface and | 
| +** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and | 
| +** SQLITE_SET_LOCKPROXYFILE verbs. | 
| +*/ | 
| +static int file_control_sizehint_test( | 
| +  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */ | 
| +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ | 
| +  int objc,              /* Number of arguments */ | 
| +  Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| +){ | 
| +  sqlite3_int64 nSize;            /* Hinted size */ | 
| +  char *zDb;                      /* Db name ("main", "temp" etc.) */ | 
| +  sqlite3 *db;                    /* Database handle */ | 
| +  int rc;                         /* file_control() return code */ | 
| + | 
| +  if( objc!=4 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE"); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) | 
| +   || Tcl_GetWideIntFromObj(interp, objv[3], &nSize) | 
| +  ){ | 
| +   return TCL_ERROR; | 
| +  } | 
| +  zDb = Tcl_GetString(objv[2]); | 
| +  if( zDb[0]=='\0' ) zDb = NULL; | 
| + | 
| +  rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize); | 
| +  if( rc ){ | 
| +    Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  return TCL_OK; | 
| +} | 
| + | 
| +/* | 
| +** tclcmd:   file_control_lockproxy_test DB PWD | 
| ** | 
| ** This TCL command runs the sqlite3_file_control interface and | 
| ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and | 
| @@ -4621,15 +4940,18 @@ static int file_control_lockproxy_test( | 
| Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| ){ | 
| sqlite3 *db; | 
| +  const char *zPwd; | 
| +  int nPwd; | 
|  | 
| -  if( objc!=2 ){ | 
| +  if( objc!=3 ){ | 
| Tcl_AppendResult(interp, "wrong # args: should be \"", | 
| -                     Tcl_GetStringFromObj(objv[0], 0), " DB", 0); | 
| +                     Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0); | 
| return TCL_ERROR; | 
| } | 
| if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ | 
| return TCL_ERROR; | 
| } | 
| +  zPwd = Tcl_GetStringFromObj(objv[2], &nPwd); | 
|  | 
| #if !defined(SQLITE_ENABLE_LOCKING_STYLE) | 
| #  if defined(__APPLE__) | 
| @@ -4640,9 +4962,15 @@ static int file_control_lockproxy_test( | 
| #endif | 
| #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) | 
| { | 
| -    char *proxyPath = "test.proxy"; | 
| char *testPath; | 
| int rc; | 
| +    char proxyPath[400]; | 
| + | 
| +    if( sizeof(proxyPath)<nPwd+20 ){ | 
| +      Tcl_AppendResult(interp, "PWD too big", (void*)0); | 
| +      return TCL_ERROR; | 
| +    } | 
| +    sprintf(proxyPath, "%s/test.proxy", zPwd); | 
| rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath); | 
| if( rc ){ | 
| Tcl_SetObjResult(interp, Tcl_NewIntObj(rc)); | 
| @@ -4867,17 +5195,302 @@ static int test_unlock_notify( | 
| } | 
| #endif | 
|  | 
| +/* | 
| +** tclcmd:  sqlite3_wal_checkpoint db ?NAME? | 
| +*/ | 
| +static int test_wal_checkpoint( | 
| +  ClientData clientData, /* Unused */ | 
| +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ | 
| +  int objc,              /* Number of arguments */ | 
| +  Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| +){ | 
| +  char *zDb = 0; | 
| +  sqlite3 *db; | 
| +  int rc; | 
| + | 
| +  if( objc!=3 && objc!=2 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?"); | 
| +    return TCL_ERROR; | 
| +  } | 
| + | 
| +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){ | 
| +    return TCL_ERROR; | 
| +  } | 
| +  if( objc==3 ){ | 
| +    zDb = Tcl_GetString(objv[2]); | 
| +  } | 
| +  rc = sqlite3_wal_checkpoint(db, zDb); | 
| +  Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); | 
| +  return TCL_OK; | 
| +} | 
| + | 
| +/* | 
| +** tclcmd:  sqlite3_wal_checkpoint_v2 db MODE ?NAME? | 
| +** | 
| +** This command calls the wal_checkpoint_v2() function with the specified | 
| +** mode argument (passive, full or restart). If present, the database name | 
| +** NAME is passed as the second argument to wal_checkpoint_v2(). If it the | 
| +** NAME argument is not present, a NULL pointer is passed instead. | 
| +** | 
| +** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or | 
| +** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set | 
| +** to the error message obtained from sqlite3_errmsg(). | 
| +** | 
| +** Otherwise, this command returns a list of three integers. The first integer | 
| +** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers | 
| +** are the values returned via the output paramaters by wal_checkpoint_v2() - | 
| +** the number of frames in the log and the number of frames in the log | 
| +** that have been checkpointed. | 
| +*/ | 
| +static int test_wal_checkpoint_v2( | 
| +  ClientData clientData, /* Unused */ | 
| +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ | 
| +  int objc,              /* Number of arguments */ | 
| +  Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| +){ | 
| +  char *zDb = 0; | 
| +  sqlite3 *db; | 
| +  int rc; | 
| + | 
| +  int eMode; | 
| +  int nLog = -555; | 
| +  int nCkpt = -555; | 
| +  Tcl_Obj *pRet; | 
| + | 
| +  const char * aMode[] = { "passive", "full", "restart", 0 }; | 
| +  assert( SQLITE_CHECKPOINT_PASSIVE==0 ); | 
| +  assert( SQLITE_CHECKPOINT_FULL==1 ); | 
| +  assert( SQLITE_CHECKPOINT_RESTART==2 ); | 
| + | 
| +  if( objc!=3 && objc!=4 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?"); | 
| +    return TCL_ERROR; | 
| +  } | 
| + | 
| +  if( objc==4 ){ | 
| +    zDb = Tcl_GetString(objv[3]); | 
| +  } | 
| +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) | 
| +   || Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode) | 
| +  ){ | 
| +    return TCL_ERROR; | 
| +  } | 
| + | 
| +  rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt); | 
| +  if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){ | 
| +    Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE); | 
| +    return TCL_ERROR; | 
| +  } | 
| + | 
| +  pRet = Tcl_NewObj(); | 
| +  Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0)); | 
| +  Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog)); | 
| +  Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt)); | 
| +  Tcl_SetObjResult(interp, pRet); | 
| + | 
| +  return TCL_OK; | 
| +} | 
| + | 
| +/* | 
| +** tclcmd:  test_sqlite3_log ?SCRIPT? | 
| +*/ | 
| +static struct LogCallback { | 
| +  Tcl_Interp *pInterp; | 
| +  Tcl_Obj *pObj; | 
| +} logcallback = {0, 0}; | 
| +static void xLogcallback(void *unused, int err, char *zMsg){ | 
| +  Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj); | 
| +  Tcl_IncrRefCount(pNew); | 
| +  Tcl_ListObjAppendElement( | 
| +      0, pNew, Tcl_NewStringObj(sqlite3TestErrorName(err), -1) | 
| +  ); | 
| +  Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1)); | 
| +  Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT); | 
| +  Tcl_DecrRefCount(pNew); | 
| +} | 
| +static int test_sqlite3_log( | 
| +  ClientData clientData, | 
| +  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */ | 
| +  int objc,              /* Number of arguments */ | 
| +  Tcl_Obj *CONST objv[]  /* Command arguments */ | 
| +){ | 
| +  if( objc>2 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT"); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  if( logcallback.pObj ){ | 
| +    Tcl_DecrRefCount(logcallback.pObj); | 
| +    logcallback.pObj = 0; | 
| +    logcallback.pInterp = 0; | 
| +    sqlite3_config(SQLITE_CONFIG_LOG, 0, 0); | 
| +  } | 
| +  if( objc>1 ){ | 
| +    logcallback.pObj = objv[1]; | 
| +    Tcl_IncrRefCount(logcallback.pObj); | 
| +    logcallback.pInterp = interp; | 
| +    sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0); | 
| +  } | 
| +  return TCL_OK; | 
| +} | 
| + | 
| +/* | 
| +**     tcl_objproc COMMANDNAME ARGS... | 
| +** | 
| +** Run a TCL command using its objProc interface.  Throw an error if | 
| +** the command has no objProc interface. | 
| +*/ | 
| +static int runAsObjProc( | 
| +  void * clientData, | 
| +  Tcl_Interp *interp, | 
| +  int objc, | 
| +  Tcl_Obj *CONST objv[] | 
| +){ | 
| +  Tcl_CmdInfo cmdInfo; | 
| +  if( objc<2 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ..."); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){ | 
| +    Tcl_AppendResult(interp, "command not found: ", | 
| +           Tcl_GetString(objv[1]), (char*)0); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  if( cmdInfo.objProc==0 ){ | 
| +    Tcl_AppendResult(interp, "command has no objProc: ", | 
| +           Tcl_GetString(objv[1]), (char*)0); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1); | 
| +} | 
| + | 
| +#ifndef SQLITE_OMIT_EXPLAIN | 
| +/* | 
| +** WARNING: The following function, printExplainQueryPlan() is an exact | 
| +** copy of example code from eqp.in (eqp.html). If this code is modified, | 
| +** then the documentation copy needs to be modified as well. | 
| +*/ | 
| +/* | 
| +** Argument pStmt is a prepared SQL statement. This function compiles | 
| +** an EXPLAIN QUERY PLAN command to report on the prepared statement, | 
| +** and prints the report to stdout using printf(). | 
| +*/ | 
| +int printExplainQueryPlan(sqlite3_stmt *pStmt){ | 
| +  const char *zSql;               /* Input SQL */ | 
| +  char *zExplain;                 /* SQL with EXPLAIN QUERY PLAN prepended */ | 
| +  sqlite3_stmt *pExplain;         /* Compiled EXPLAIN QUERY PLAN command */ | 
| +  int rc;                         /* Return code from sqlite3_prepare_v2() */ | 
| + | 
| +  zSql = sqlite3_sql(pStmt); | 
| +  if( zSql==0 ) return SQLITE_ERROR; | 
| + | 
| +  zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql); | 
| +  if( zExplain==0 ) return SQLITE_NOMEM; | 
| + | 
| +  rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0); | 
| +  sqlite3_free(zExplain); | 
| +  if( rc!=SQLITE_OK ) return rc; | 
| + | 
| +  while( SQLITE_ROW==sqlite3_step(pExplain) ){ | 
| +    int iSelectid = sqlite3_column_int(pExplain, 0); | 
| +    int iOrder = sqlite3_column_int(pExplain, 1); | 
| +    int iFrom = sqlite3_column_int(pExplain, 2); | 
| +    const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3); | 
| + | 
| +    printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail); | 
| +  } | 
| + | 
| +  return sqlite3_finalize(pExplain); | 
| +} | 
| + | 
| +static int test_print_eqp( | 
| +  void * clientData, | 
| +  Tcl_Interp *interp, | 
| +  int objc, | 
| +  Tcl_Obj *CONST objv[] | 
| +){ | 
| +  int rc; | 
| +  sqlite3_stmt *pStmt; | 
| + | 
| +  if( objc!=2 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "STMT"); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; | 
| +  rc = printExplainQueryPlan(pStmt); | 
| +  Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0); | 
| +  return TCL_OK; | 
| +} | 
| +#endif /* SQLITE_OMIT_EXPLAIN */ | 
| + | 
| +/* | 
| +**      optimization_control DB OPT BOOLEAN | 
| +** | 
| +** Enable or disable query optimizations using the sqlite3_test_control() | 
| +** interface.  Disable if BOOLEAN is false and enable if BOOLEAN is true. | 
| +** OPT is the name of the optimization to be disabled. | 
| +*/ | 
| +static int optimization_control( | 
| +  void * clientData, | 
| +  Tcl_Interp *interp, | 
| +  int objc, | 
| +  Tcl_Obj *CONST objv[] | 
| +){ | 
| +  int i; | 
| +  sqlite3 *db; | 
| +  const char *zOpt; | 
| +  int onoff; | 
| +  int mask; | 
| +  static const struct { | 
| +    const char *zOptName; | 
| +    int mask; | 
| +  } aOpt[] = { | 
| +    { "all",              SQLITE_OptMask        }, | 
| +    { "query-flattener",  SQLITE_QueryFlattener }, | 
| +    { "column-cache",     SQLITE_ColumnCache    }, | 
| +    { "index-sort",       SQLITE_IndexSort      }, | 
| +    { "index-search",     SQLITE_IndexSearch    }, | 
| +    { "index-cover",      SQLITE_IndexCover     }, | 
| +    { "groupby-order",    SQLITE_GroupByOrder   }, | 
| +    { "factor-constants", SQLITE_FactorOutConst }, | 
| +  }; | 
| + | 
| +  if( objc!=4 ){ | 
| +    Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN"); | 
| +    return TCL_ERROR; | 
| +  } | 
| +  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; | 
| +  if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR; | 
| +  zOpt = Tcl_GetString(objv[2]); | 
| +  for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){ | 
| +    if( strcmp(zOpt, aOpt[i].zOptName)==0 ){ | 
| +      mask = aOpt[i].mask; | 
| +      break; | 
| +    } | 
| +  } | 
| +  if( onoff ) mask = ~mask; | 
| +  if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){ | 
| +    Tcl_AppendResult(interp, "unknown optimization - should be one of:", | 
| +                     (char*)0); | 
| +    for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){ | 
| +      Tcl_AppendResult(interp, " ", aOpt[i].zOptName); | 
| +    } | 
| +    return TCL_ERROR; | 
| +  } | 
| +  sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask); | 
| +  return TCL_OK; | 
| +} | 
|  | 
| /* | 
| ** Register commands with the TCL interpreter. | 
| */ | 
| int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| extern int sqlite3_search_count; | 
| +  extern int sqlite3_found_count; | 
| extern int sqlite3_interrupt_count; | 
| extern int sqlite3_open_file_count; | 
| extern int sqlite3_sort_count; | 
| extern int sqlite3_current_time; | 
| -#if SQLITE_OS_UNIX && defined(__APPLE__) | 
| +#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE | 
| extern int sqlite3_hostid_num; | 
| #endif | 
| extern int sqlite3_max_blobsize; | 
| @@ -4969,6 +5582,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| { "sqlite3_step",                  test_step          ,0 }, | 
| { "sqlite3_sql",                   test_sql           ,0 }, | 
| { "sqlite3_next_stmt",             test_next_stmt     ,0 }, | 
| +     { "sqlite3_stmt_readonly",         test_stmt_readonly ,0 }, | 
|  | 
| { "sqlite3_release_memory",        test_release_memory,     0}, | 
| { "sqlite3_soft_heap_limit",       test_soft_heap_limit,    0}, | 
| @@ -4983,6 +5597,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| { "save_prng_state",               save_prng_state,    0 }, | 
| { "restore_prng_state",            restore_prng_state, 0 }, | 
| { "reset_prng_state",              reset_prng_state,   0 }, | 
| +     { "optimization_control",          optimization_control,0}, | 
| +     { "tcl_objproc",                   runAsObjProc,       0 }, | 
|  | 
| /* sqlite3_column_*() API */ | 
| { "sqlite3_column_count",          test_column_count  ,0 }, | 
| @@ -5029,7 +5645,10 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| { "file_control_test",          file_control_test,   0   }, | 
| { "file_control_lasterrno_test", file_control_lasterrno_test,  0   }, | 
| { "file_control_lockproxy_test", file_control_lockproxy_test,  0   }, | 
| +     { "file_control_chunksize_test", file_control_chunksize_test,  0   }, | 
| +     { "file_control_sizehint_test", file_control_sizehint_test,  0   }, | 
| { "sqlite3_vfs_list",           vfs_list,     0   }, | 
| +     { "sqlite3_create_function_v2", test_create_function_v2, 0 }, | 
|  | 
| /* Functions from os.h */ | 
| #ifndef SQLITE_OMIT_UTF16 | 
| @@ -5048,13 +5667,22 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| { "sqlite3_table_column_metadata", test_table_column_metadata, 0  }, | 
| #endif | 
| #ifndef SQLITE_OMIT_INCRBLOB | 
| -     { "sqlite3_blob_read",  test_blob_read, 0  }, | 
| -     { "sqlite3_blob_write", test_blob_write, 0  }, | 
| +     { "sqlite3_blob_read",   test_blob_read, 0  }, | 
| +     { "sqlite3_blob_write",  test_blob_write, 0  }, | 
| +     { "sqlite3_blob_reopen", test_blob_reopen, 0  }, | 
| +     { "sqlite3_blob_bytes",  test_blob_bytes, 0  }, | 
| +     { "sqlite3_blob_close",  test_blob_close, 0  }, | 
| #endif | 
| { "pcache_stats",       test_pcache_stats, 0  }, | 
| #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY | 
| { "sqlite3_unlock_notify", test_unlock_notify, 0  }, | 
| #endif | 
| +     { "sqlite3_wal_checkpoint",   test_wal_checkpoint, 0  }, | 
| +     { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0  }, | 
| +     { "test_sqlite3_log",         test_sqlite3_log, 0  }, | 
| +#ifndef SQLITE_OMIT_EXPLAIN | 
| +     { "print_explain_query_plan", test_print_eqp, 0  }, | 
| +#endif | 
| }; | 
| static int bitmask_size = sizeof(Bitmask)*8; | 
| int i; | 
| @@ -5065,9 +5693,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| extern int sqlite3_pager_readdb_count; | 
| extern int sqlite3_pager_writedb_count; | 
| extern int sqlite3_pager_writej_count; | 
| -#if defined(__linux__) && defined(SQLITE_TEST) && SQLITE_THREADSAFE | 
| -  extern int threadsOverrideEachOthersLocks; | 
| -#endif | 
| #if SQLITE_OS_WIN | 
| extern int sqlite3_os_type; | 
| #endif | 
| @@ -5075,6 +5700,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| extern int sqlite3WhereTrace; | 
| extern int sqlite3OSTrace; | 
| extern int sqlite3VdbeAddopTrace; | 
| +  extern int sqlite3WalTrace; | 
| #endif | 
| #ifdef SQLITE_TEST | 
| extern char sqlite3_query_plan[]; | 
| @@ -5093,6 +5719,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| } | 
| Tcl_LinkVar(interp, "sqlite_search_count", | 
| (char*)&sqlite3_search_count, TCL_LINK_INT); | 
| +  Tcl_LinkVar(interp, "sqlite_found_count", | 
| +      (char*)&sqlite3_found_count, TCL_LINK_INT); | 
| Tcl_LinkVar(interp, "sqlite_sort_count", | 
| (char*)&sqlite3_sort_count, TCL_LINK_INT); | 
| Tcl_LinkVar(interp, "sqlite3_max_blobsize", | 
| @@ -5105,7 +5733,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| (char*)&sqlite3_open_file_count, TCL_LINK_INT); | 
| Tcl_LinkVar(interp, "sqlite_current_time", | 
| (char*)&sqlite3_current_time, TCL_LINK_INT); | 
| -#if SQLITE_OS_UNIX && defined(__APPLE__) | 
| +#if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE | 
| Tcl_LinkVar(interp, "sqlite_hostid_num", | 
| (char*)&sqlite3_hostid_num, TCL_LINK_INT); | 
| #endif | 
| @@ -5121,10 +5749,6 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| Tcl_LinkVar(interp, "unaligned_string_counter", | 
| (char*)&unaligned_string_counter, TCL_LINK_INT); | 
| #endif | 
| -#if defined(__linux__) && defined(SQLITE_TEST) && SQLITE_THREADSAFE | 
| -  Tcl_LinkVar(interp, "threadsOverrideEachOthersLocks", | 
| -      (char*)&threadsOverrideEachOthersLocks, TCL_LINK_INT); | 
| -#endif | 
| #ifndef SQLITE_OMIT_UTF16 | 
| Tcl_LinkVar(interp, "sqlite_last_needed_collation", | 
| (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY); | 
| @@ -5144,6 +5768,10 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ | 
| (char*)&sqlite3WhereTrace, TCL_LINK_INT); | 
| Tcl_LinkVar(interp, "sqlite_os_trace", | 
| (char*)&sqlite3OSTrace, TCL_LINK_INT); | 
| +#ifndef SQLITE_OMIT_WAL | 
| +  Tcl_LinkVar(interp, "sqlite_wal_trace", | 
| +      (char*)&sqlite3WalTrace, TCL_LINK_INT); | 
| +#endif | 
| #endif | 
| #ifndef SQLITE_OMIT_DISKIO | 
| Tcl_LinkVar(interp, "sqlite_opentemp_count", | 
|  |