| Index: third_party/sqlite/sqlite-src-3100200/src/test1.c
|
| diff --git a/third_party/sqlite/src/src/test1.c b/third_party/sqlite/sqlite-src-3100200/src/test1.c
|
| similarity index 93%
|
| copy from third_party/sqlite/src/src/test1.c
|
| copy to third_party/sqlite/sqlite-src-3100200/src/test1.c
|
| index 85a16488ba850f82143dfd67f54a2eb673ac8db2..c5e71582bcd5a5a21f9f0982e83c465b04f21692 100644
|
| --- a/third_party/sqlite/src/src/test1.c
|
| +++ b/third_party/sqlite/sqlite-src-3100200/src/test1.c
|
| @@ -94,10 +94,7 @@ static int get_sqlite_pointer(
|
| return TCL_ERROR;
|
| }
|
| p = (struct SqliteDb*)cmdInfo.objClientData;
|
| - sprintf(zBuf, "%p", p->db);
|
| - if( strncmp(zBuf,"0x",2) ){
|
| - sprintf(zBuf, "0x%p", p->db);
|
| - }
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%p", p->db);
|
| Tcl_AppendResult(interp, zBuf, 0);
|
| return TCL_OK;
|
| }
|
| @@ -145,7 +142,8 @@ int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
|
| && sqlite3_errcode(db)!=rc ){
|
| char zBuf[200];
|
| int r2 = sqlite3_errcode(db);
|
| - sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf,
|
| + "error code %s (%d) does not match sqlite3_errcode %s (%d)",
|
| t1ErrorName(rc), rc, t1ErrorName(r2), r2);
|
| Tcl_ResetResult(interp);
|
| Tcl_AppendResult(interp, zBuf, 0);
|
| @@ -261,6 +259,8 @@ static int test_io_trace(
|
| **
|
| ** Returns true if the program was compiled using clang with the
|
| ** -fsanitize=address switch on the command line. False otherwise.
|
| +**
|
| +** Also return true if the OMIT_MISUSE environment variable exists.
|
| */
|
| static int clang_sanitize_address(
|
| void *NotUsed,
|
| @@ -274,6 +274,10 @@ static int clang_sanitize_address(
|
| res = 1;
|
| # endif
|
| #endif
|
| +#ifdef __SANITIZE_ADDRESS__
|
| + res = 1;
|
| +#endif
|
| + if( res==0 && getenv("OMIT_MISUSE")!=0 ) res = 1;
|
| Tcl_SetObjResult(interp, Tcl_NewIntObj(res));
|
| return TCL_OK;
|
| }
|
| @@ -307,7 +311,7 @@ static int test_exec_printf(
|
| zSql = sqlite3_mprintf(argv[2], argv[3]);
|
| rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
|
| sqlite3_free(zSql);
|
| - sprintf(zBuf, "%d", rc);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
|
| Tcl_AppendElement(interp, zBuf);
|
| Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
|
| Tcl_DStringFree(&str);
|
| @@ -334,7 +338,7 @@ static int test_exec_hex(
|
| int rc, i, j;
|
| char *zErr = 0;
|
| char *zHex;
|
| - char zSql[500];
|
| + char zSql[501];
|
| char zBuf[30];
|
| if( argc!=3 ){
|
| Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
|
| @@ -343,7 +347,7 @@ static int test_exec_hex(
|
| }
|
| if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
| zHex = argv[2];
|
| - for(i=j=0; i<sizeof(zSql) && zHex[j]; i++, j++){
|
| + for(i=j=0; i<(sizeof(zSql)-1) && zHex[j]; i++, j++){
|
| if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
|
| zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
|
| j += 2;
|
| @@ -354,7 +358,7 @@ static int test_exec_hex(
|
| zSql[i] = 0;
|
| Tcl_DStringInit(&str);
|
| rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
|
| - sprintf(zBuf, "%d", rc);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
|
| Tcl_AppendElement(interp, zBuf);
|
| Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
|
| Tcl_DStringFree(&str);
|
| @@ -439,7 +443,7 @@ static int test_exec(
|
| zSql[j] = 0;
|
| rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
|
| sqlite3_free(zSql);
|
| - sprintf(zBuf, "%d", rc);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
|
| Tcl_AppendElement(interp, zBuf);
|
| Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
|
| Tcl_DStringFree(&str);
|
| @@ -564,7 +568,7 @@ static int test_get_table_printf(
|
| Tcl_DString str;
|
| int rc;
|
| char *zErr = 0;
|
| - int nRow, nCol;
|
| + int nRow = 0, nCol = 0;
|
| char **aResult;
|
| int i;
|
| char zBuf[30];
|
| @@ -588,13 +592,13 @@ static int test_get_table_printf(
|
| resCount = (nRow+1)*nCol;
|
| }
|
| sqlite3_free(zSql);
|
| - sprintf(zBuf, "%d", rc);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", rc);
|
| Tcl_AppendElement(interp, zBuf);
|
| if( rc==SQLITE_OK ){
|
| if( argc==4 ){
|
| - sprintf(zBuf, "%d", nRow);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nRow);
|
| Tcl_AppendElement(interp, zBuf);
|
| - sprintf(zBuf, "%d", nCol);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", nCol);
|
| Tcl_AppendElement(interp, zBuf);
|
| }
|
| for(i=0; i<resCount; i++){
|
| @@ -631,7 +635,7 @@ static int test_last_rowid(
|
| return TCL_ERROR;
|
| }
|
| if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
| - sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%lld", sqlite3_last_insert_rowid(db));
|
| Tcl_AppendResult(interp, zBuf, 0);
|
| return SQLITE_OK;
|
| }
|
| @@ -771,7 +775,7 @@ static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
|
| char zBuf[200];
|
| z = sqlite3_value_text(argv[0]);
|
| for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
|
| - sprintf(&zBuf[i*2], "%02x", z[i]&0xff);
|
| + sqlite3_snprintf(sizeof(zBuf)-i*2, &zBuf[i*2], "%02x", z[i]);
|
| }
|
| zBuf[i*2] = 0;
|
| sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
|
| @@ -783,7 +787,7 @@ static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
|
| char zBuf[400];
|
| z = sqlite3_value_text16(argv[0]);
|
| for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
|
| - sprintf(&zBuf[i*4], "%04x", z[i]&0xff);
|
| + sqlite3_snprintf(sizeof(zBuf)-i*4, &zBuf[i*4],"%04x", z[i]&0xff);
|
| }
|
| zBuf[i*4] = 0;
|
| sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
|
| @@ -1569,7 +1573,6 @@ static int test_libversion_number(
|
| ** Usage: sqlite3_table_column_metadata DB dbname tblname colname
|
| **
|
| */
|
| -#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
| static int test_table_column_metadata(
|
| ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
|
| Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| @@ -1589,14 +1592,14 @@ static int test_table_column_metadata(
|
| int primarykey;
|
| int autoincrement;
|
|
|
| - if( objc!=5 ){
|
| + if( objc!=5 && objc!=4 ){
|
| Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
|
| return TCL_ERROR;
|
| }
|
| if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| zDb = Tcl_GetString(objv[2]);
|
| zTbl = Tcl_GetString(objv[3]);
|
| - zCol = Tcl_GetString(objv[4]);
|
| + zCol = objc==5 ? Tcl_GetString(objv[4]) : 0;
|
|
|
| if( strlen(zDb)==0 ) zDb = 0;
|
|
|
| @@ -1618,7 +1621,6 @@ static int test_table_column_metadata(
|
|
|
| return TCL_OK;
|
| }
|
| -#endif
|
|
|
| #ifndef SQLITE_OMIT_INCRBLOB
|
|
|
| @@ -1651,154 +1653,6 @@ static int blobHandleFromObj(
|
| 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
|
| -**
|
| -** This command is used to test the sqlite3_blob_read() in ways that
|
| -** the Tcl channel interface does not. The first argument should
|
| -** be the name of a valid channel created by the [incrblob] method
|
| -** of a database handle. This function calls sqlite3_blob_read()
|
| -** to read N bytes from offset OFFSET from the underlying SQLite
|
| -** blob handle.
|
| -**
|
| -** On success, a byte-array object containing the read data is
|
| -** returned. On failure, the interpreter result is set to the
|
| -** text representation of the returned error code (i.e. "SQLITE_NOMEM")
|
| -** and a Tcl exception is thrown.
|
| -*/
|
| -static int test_blob_read(
|
| - 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;
|
| - int iOffset;
|
| - unsigned char *zBuf = 0;
|
| - int rc;
|
| -
|
| - if( objc!=4 ){
|
| - Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N");
|
| - return TCL_ERROR;
|
| - }
|
| -
|
| - 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)
|
| - ){
|
| - return TCL_ERROR;
|
| - }
|
| -
|
| - 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));
|
| - }else{
|
| - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
| - }
|
| - Tcl_Free((char *)zBuf);
|
| -
|
| - return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
|
| -}
|
| -
|
| -/*
|
| -** sqlite3_blob_write CHANNEL OFFSET DATA ?NDATA?
|
| -**
|
| -** This command is used to test the sqlite3_blob_write() in ways that
|
| -** the Tcl channel interface does not. The first argument should
|
| -** be the name of a valid channel created by the [incrblob] method
|
| -** of a database handle. This function calls sqlite3_blob_write()
|
| -** to write the DATA byte-array to the underlying SQLite blob handle.
|
| -** at offset OFFSET.
|
| -**
|
| -** On success, an empty string is returned. On failure, the interpreter
|
| -** result is set to the text representation of the returned error code
|
| -** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown.
|
| -*/
|
| -static int test_blob_write(
|
| - 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 iOffset;
|
| - int rc;
|
| -
|
| - unsigned char *zBuf;
|
| - int nBuf;
|
| -
|
| - if( objc!=4 && objc!=5 ){
|
| - Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA ?NDATA?");
|
| - return TCL_ERROR;
|
| - }
|
| -
|
| - if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
|
| - if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){
|
| - return TCL_ERROR;
|
| - }
|
| -
|
| - zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf);
|
| - if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){
|
| - return TCL_ERROR;
|
| - }
|
| - rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
|
| - if( rc!=SQLITE_OK ){
|
| - Tcl_SetResult(interp, (char *)sqlite3ErrName(rc), TCL_VOLATILE);
|
| - }
|
| -
|
| - 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 */
|
| @@ -2267,7 +2121,7 @@ static int test_stmt_status(
|
| Tcl_Obj *CONST objv[]
|
| ){
|
| int iValue;
|
| - int i, op, resetFlag;
|
| + int i, op = 0, resetFlag;
|
| const char *zOpName;
|
| sqlite3_stmt *pStmt;
|
|
|
| @@ -2301,6 +2155,208 @@ static int test_stmt_status(
|
| return TCL_OK;
|
| }
|
|
|
| +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| +/*
|
| +** Usage: sqlite3_stmt_scanstatus STMT IDX
|
| +*/
|
| +static int test_stmt_scanstatus(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3_stmt *pStmt; /* First argument */
|
| + int idx; /* Second argument */
|
| +
|
| + const char *zName;
|
| + const char *zExplain;
|
| + sqlite3_int64 nLoop;
|
| + sqlite3_int64 nVisit;
|
| + double rEst;
|
| + int res;
|
| +
|
| + if( objc!=3 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
| + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
|
| +
|
| + res = sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NLOOP, (void*)&nLoop);
|
| + if( res==0 ){
|
| + Tcl_Obj *pRet = Tcl_NewObj();
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nLoop", -1));
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nLoop));
|
| + sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NVISIT, (void*)&nVisit);
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nVisit", -1));
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewWideIntObj(nVisit));
|
| + sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EST, (void*)&rEst);
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("nEst", -1));
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewDoubleObj(rEst));
|
| + sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_NAME, (void*)&zName);
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zName", -1));
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zName, -1));
|
| + sqlite3_stmt_scanstatus(pStmt, idx, SQLITE_SCANSTAT_EXPLAIN, (void*)&zExplain);
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj("zExplain", -1));
|
| + Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zExplain, -1));
|
| + Tcl_SetObjResult(interp, pRet);
|
| + }else{
|
| + Tcl_ResetResult(interp);
|
| + }
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** Usage: sqlite3_stmt_scanstatus_reset STMT
|
| +*/
|
| +static int test_stmt_scanstatus_reset(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3_stmt *pStmt; /* First argument */
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "STMT");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
| + sqlite3_stmt_scanstatus_reset(pStmt);
|
| + return TCL_OK;
|
| +}
|
| +#endif
|
| +
|
| +#ifdef SQLITE_ENABLE_SQLLOG
|
| +/*
|
| +** Usage: sqlite3_config_sqllog
|
| +**
|
| +** Zero the SQLITE_CONFIG_SQLLOG configuration
|
| +*/
|
| +static int test_config_sqllog(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + if( objc!=1 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "");
|
| + return TCL_ERROR;
|
| + }
|
| + sqlite3_config(SQLITE_CONFIG_SQLLOG, 0, 0);
|
| + return TCL_OK;
|
| +}
|
| +#endif
|
| +
|
| +/*
|
| +** Usage: vfs_current_time_int64
|
| +**
|
| +** Return the value returned by the default VFS's xCurrentTimeInt64 method.
|
| +*/
|
| +static int vfsCurrentTimeInt64(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + i64 t;
|
| + sqlite3_vfs *pVfs = sqlite3_vfs_find(0);
|
| + if( objc!=1 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "");
|
| + return TCL_ERROR;
|
| + }
|
| + pVfs->xCurrentTimeInt64(pVfs, &t);
|
| + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(t));
|
| + return TCL_OK;
|
| +}
|
| +
|
| +#ifdef SQLITE_ENABLE_SNAPSHOT
|
| +/*
|
| +** Usage: sqlite3_snapshot_get DB DBNAME
|
| +*/
|
| +static int test_snapshot_get(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + int rc;
|
| + sqlite3 *db;
|
| + char *zName;
|
| + sqlite3_snapshot *pSnapshot = 0;
|
| +
|
| + if( objc!=3 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| + zName = Tcl_GetString(objv[2]);
|
| +
|
| + rc = sqlite3_snapshot_get(db, zName, &pSnapshot);
|
| + if( rc!=SQLITE_OK ){
|
| + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
| + return TCL_ERROR;
|
| + }else{
|
| + char zBuf[100];
|
| + if( sqlite3TestMakePointerStr(interp, zBuf, pSnapshot) ) return TCL_ERROR;
|
| + Tcl_SetObjResult(interp, Tcl_NewStringObj(zBuf, -1));
|
| + }
|
| + return TCL_OK;
|
| +}
|
| +#endif /* SQLITE_ENABLE_SNAPSHOT */
|
| +
|
| +#ifdef SQLITE_ENABLE_SNAPSHOT
|
| +/*
|
| +** Usage: sqlite3_snapshot_open DB DBNAME SNAPSHOT
|
| +*/
|
| +static int test_snapshot_open(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + int rc;
|
| + sqlite3 *db;
|
| + char *zName;
|
| + sqlite3_snapshot *pSnapshot;
|
| +
|
| + if( objc!=4 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SNAPSHOT");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| + zName = Tcl_GetString(objv[2]);
|
| + pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[3]));
|
| +
|
| + rc = sqlite3_snapshot_open(db, zName, pSnapshot);
|
| + if( rc!=SQLITE_OK ){
|
| + Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3ErrName(rc), -1));
|
| + return TCL_ERROR;
|
| + }
|
| + return TCL_OK;
|
| +}
|
| +#endif /* SQLITE_ENABLE_SNAPSHOT */
|
| +
|
| +#ifdef SQLITE_ENABLE_SNAPSHOT
|
| +/*
|
| +** Usage: sqlite3_snapshot_free SNAPSHOT
|
| +*/
|
| +static int test_snapshot_free(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3_snapshot *pSnapshot;
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "SNAPSHOT");
|
| + return TCL_ERROR;
|
| + }
|
| + pSnapshot = (sqlite3_snapshot*)sqlite3TestTextToPtr(Tcl_GetString(objv[1]));
|
| + sqlite3_snapshot_free(pSnapshot);
|
| + return TCL_OK;
|
| +}
|
| +#endif /* SQLITE_ENABLE_SNAPSHOT */
|
| +
|
| /*
|
| ** Usage: sqlite3_next_stmt DB STMT
|
| **
|
| @@ -2573,7 +2629,7 @@ static int test_bind(
|
| if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
|
| if( rc ){
|
| char zBuf[50];
|
| - sprintf(zBuf, "(%d) ", rc);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
|
| Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
|
| return TCL_ERROR;
|
| }
|
| @@ -3084,6 +3140,43 @@ static int test_bind_zeroblob(
|
| }
|
|
|
| /*
|
| +** Usage: sqlite3_bind_zeroblob64 STMT IDX N
|
| +**
|
| +** Test the sqlite3_bind_zeroblob64 interface. STMT is a prepared statement.
|
| +** IDX is the index of a wildcard in the prepared statement. This command
|
| +** binds a N-byte zero-filled BLOB to the wildcard.
|
| +*/
|
| +static int test_bind_zeroblob64(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3_stmt *pStmt;
|
| + int idx;
|
| + i64 n;
|
| + int rc;
|
| +
|
| + if( objc!=4 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
|
| + if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
|
| + if( Tcl_GetWideIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
|
| +
|
| + rc = sqlite3_bind_zeroblob64(pStmt, idx, n);
|
| + if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
|
| + if( rc!=SQLITE_OK ){
|
| + Tcl_AppendResult(interp, sqlite3ErrName(rc), 0);
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| ** Usage: sqlite3_bind_int STMT N VALUE
|
| **
|
| ** Test the sqlite3_bind_int interface. STMT is a prepared statement.
|
| @@ -3174,7 +3267,7 @@ static int test_bind_double(
|
| ){
|
| sqlite3_stmt *pStmt;
|
| int idx;
|
| - double value;
|
| + double value = 0;
|
| int rc;
|
| const char *zVal;
|
| int i;
|
| @@ -3687,7 +3780,7 @@ static int test_prepare(
|
| }
|
| if( rc!=SQLITE_OK ){
|
| assert( pStmt==0 );
|
| - sprintf(zBuf, "(%d) ", rc);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
|
| Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
|
| return TCL_ERROR;
|
| }
|
| @@ -3715,6 +3808,7 @@ static int test_prepare_v2(
|
| ){
|
| sqlite3 *db;
|
| const char *zSql;
|
| + char *zCopy = 0; /* malloc() copy of zSql */
|
| int bytes;
|
| const char *zTail = 0;
|
| sqlite3_stmt *pStmt = 0;
|
| @@ -3730,11 +3824,25 @@ static int test_prepare_v2(
|
| zSql = Tcl_GetString(objv[2]);
|
| if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
|
|
|
| - rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
|
| + /* Instead of using zSql directly, make a copy into a buffer obtained
|
| + ** directly from malloc(). The idea is to make it easier for valgrind
|
| + ** to spot buffer overreads. */
|
| + if( bytes>=0 ){
|
| + zCopy = malloc(bytes);
|
| + memcpy(zCopy, zSql, bytes);
|
| + }else{
|
| + int n = (int)strlen(zSql) + 1;
|
| + zCopy = malloc(n);
|
| + memcpy(zCopy, zSql, n);
|
| + }
|
| + rc = sqlite3_prepare_v2(db, zCopy, bytes, &pStmt, objc>=5 ? &zTail : 0);
|
| + free(zCopy);
|
| + zTail = &zSql[(zTail - zCopy)];
|
| +
|
| assert(rc==SQLITE_OK || pStmt==0);
|
| Tcl_ResetResult(interp);
|
| if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
| - if( zTail && objc>=5 ){
|
| + if( rc==SQLITE_OK && zTail && objc>=5 ){
|
| if( bytes>=0 ){
|
| bytes = bytes - (int)(zTail-zSql);
|
| }
|
| @@ -3742,7 +3850,7 @@ static int test_prepare_v2(
|
| }
|
| if( rc!=SQLITE_OK ){
|
| assert( pStmt==0 );
|
| - sprintf(zBuf, "(%d) ", rc);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
|
| Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
|
| return TCL_ERROR;
|
| }
|
| @@ -3783,7 +3891,7 @@ static int test_prepare_tkt3134(
|
| if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
|
| if( rc!=SQLITE_OK ){
|
| assert( pStmt==0 );
|
| - sprintf(zBuf, "(%d) ", rc);
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "(%d) ", rc);
|
| Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
|
| return TCL_ERROR;
|
| }
|
| @@ -4598,7 +4706,7 @@ static int get_autocommit(
|
| return TCL_ERROR;
|
| }
|
| if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
|
| - sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
|
| + sqlite3_snprintf(sizeof(zBuf), zBuf, "%d", sqlite3_get_autocommit(db));
|
| Tcl_AppendResult(interp, zBuf, 0);
|
| return TCL_OK;
|
| }
|
| @@ -4712,6 +4820,34 @@ static int test_db_release_memory(
|
| }
|
|
|
| /*
|
| +** Usage: sqlite3_db_cacheflush DB
|
| +**
|
| +** Attempt to flush any dirty pages to disk.
|
| +*/
|
| +static int test_db_cacheflush(
|
| + void * clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| + sqlite3 *db;
|
| + int rc;
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
|
| + rc = sqlite3_db_cacheflush(db);
|
| + if( rc ){
|
| + Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + Tcl_ResetResult(interp);
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| ** Usage: sqlite3_db_filename DB DBNAME
|
| **
|
| ** Return the name of a file associated with a database.
|
| @@ -5234,7 +5370,7 @@ static int file_control_lockproxy_test(
|
| Tcl_AppendResult(interp, "PWD too big", (void*)0);
|
| return TCL_ERROR;
|
| }
|
| - sprintf(proxyPath, "%s/test.proxy", zPwd);
|
| + sqlite3_snprintf(sizeof(proxyPath), proxyPath, "%s/test.proxy", zPwd);
|
| rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
|
| if( rc ){
|
| Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
|
| @@ -5519,7 +5655,7 @@ static int test_limit(
|
| { "SQLITE_LIMIT_TOOSMALL", -1, },
|
| { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_WORKER_THREADS+1 },
|
| };
|
| - int i, id;
|
| + int i, id = 0;
|
| int val;
|
| const char *zId;
|
|
|
| @@ -5752,10 +5888,11 @@ static int test_wal_checkpoint_v2(
|
| int nCkpt = -555;
|
| Tcl_Obj *pRet;
|
|
|
| - const char * aMode[] = { "passive", "full", "restart", 0 };
|
| + const char * aMode[] = { "passive", "full", "restart", "truncate", 0 };
|
| assert( SQLITE_CHECKPOINT_PASSIVE==0 );
|
| assert( SQLITE_CHECKPOINT_FULL==1 );
|
| assert( SQLITE_CHECKPOINT_RESTART==2 );
|
| + assert( SQLITE_CHECKPOINT_TRUNCATE==3 );
|
|
|
| if( objc!=3 && objc!=4 ){
|
| Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
|
| @@ -5765,15 +5902,18 @@ static int test_wal_checkpoint_v2(
|
| 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)
|
| - ){
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) || (
|
| + TCL_OK!=Tcl_GetIntFromObj(0, objv[2], &eMode)
|
| + && TCL_OK!=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);
|
| + const char *zErrCode = sqlite3ErrName(rc);
|
| + Tcl_ResetResult(interp);
|
| + Tcl_AppendResult(interp, zErrCode, " - ", (char *)sqlite3_errmsg(db), 0);
|
| return TCL_ERROR;
|
| }
|
|
|
| @@ -5787,6 +5927,43 @@ static int test_wal_checkpoint_v2(
|
| }
|
|
|
| /*
|
| +** tclcmd: sqlite3_wal_autocheckpoint db VALUE
|
| +*/
|
| +static int test_wal_autocheckpoint(
|
| + ClientData clientData, /* Unused */
|
| + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| + int objc, /* Number of arguments */
|
| + Tcl_Obj *CONST objv[] /* Command arguments */
|
| +){
|
| + sqlite3 *db;
|
| + int rc;
|
| + int iVal;
|
| +
|
| +
|
| + if( objc!=3 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB VALUE");
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
|
| + || Tcl_GetIntFromObj(0, objv[2], &iVal)
|
| + ){
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + rc = sqlite3_wal_autocheckpoint(db, iVal);
|
| + Tcl_ResetResult(interp);
|
| + if( rc!=SQLITE_OK ){
|
| + const char *zErrCode = sqlite3ErrName(rc);
|
| + Tcl_SetObjResult(interp, Tcl_NewStringObj(zErrCode, -1));
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + return TCL_OK;
|
| +}
|
| +
|
| +
|
| +/*
|
| ** tclcmd: test_sqlite3_log ?SCRIPT?
|
| */
|
| static struct LogCallback {
|
| @@ -5817,13 +5994,13 @@ static int test_sqlite3_log(
|
| Tcl_DecrRefCount(logcallback.pObj);
|
| logcallback.pObj = 0;
|
| logcallback.pInterp = 0;
|
| - sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
|
| + sqlite3_config(SQLITE_CONFIG_LOG, (void*)0, (void*)0);
|
| }
|
| if( objc>1 ){
|
| logcallback.pObj = objv[1];
|
| Tcl_IncrRefCount(logcallback.pObj);
|
| logcallback.pInterp = interp;
|
| - sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
|
| + sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, (void*)0);
|
| }
|
| return TCL_OK;
|
| }
|
| @@ -5936,7 +6113,8 @@ static int test_test_control(
|
| int i;
|
| } aVerb[] = {
|
| { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
|
| - { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
|
| + { "SQLITE_TESTCTRL_SORTER_MMAP", SQLITE_TESTCTRL_SORTER_MMAP },
|
| + { "SQLITE_TESTCTRL_IMPOSTER", SQLITE_TESTCTRL_IMPOSTER },
|
| };
|
| int iVerb;
|
| int iFlag;
|
| @@ -5977,6 +6155,22 @@ static int test_test_control(
|
| sqlite3_test_control(SQLITE_TESTCTRL_SORTER_MMAP, db, val);
|
| break;
|
| }
|
| +
|
| + case SQLITE_TESTCTRL_IMPOSTER: {
|
| + int onOff, tnum;
|
| + const char *zDbName;
|
| + sqlite3 *db;
|
| + if( objc!=6 ){
|
| + Tcl_WrongNumArgs(interp, 2, objv, "DB dbName onOff tnum");
|
| + return TCL_ERROR;
|
| + }
|
| + if( getDbPointer(interp, Tcl_GetString(objv[2]), &db) ) return TCL_ERROR;
|
| + zDbName = Tcl_GetString(objv[3]);
|
| + if( Tcl_GetIntFromObj(interp, objv[4], &onOff) ) return TCL_ERROR;
|
| + if( Tcl_GetIntFromObj(interp, objv[5], &tnum) ) return TCL_ERROR;
|
| + sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, zDbName, onOff, tnum);
|
| + break;
|
| + }
|
| }
|
|
|
| Tcl_ResetResult(interp);
|
| @@ -5998,7 +6192,8 @@ static int test_getrusage(
|
| memset(&r, 0, sizeof(r));
|
| getrusage(RUSAGE_SELF, &r);
|
|
|
| - sprintf(buf, "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
|
| + sqlite3_snprintf(sizeof(buf), buf,
|
| + "ru_utime=%d.%06d ru_stime=%d.%06d ru_minflt=%d ru_majflt=%d",
|
| (int)r.ru_utime.tv_sec, (int)r.ru_utime.tv_usec,
|
| (int)r.ru_stime.tv_sec, (int)r.ru_stime.tv_usec,
|
| (int)r.ru_minflt, (int)r.ru_majflt
|
| @@ -6293,7 +6488,8 @@ static int optimization_control(
|
| { "transitive", SQLITE_Transitive },
|
| { "subquery-coroutine", SQLITE_SubqCoroutine },
|
| { "omit-noop-join", SQLITE_OmitNoopJoin },
|
| - { "stat3", SQLITE_Stat3 },
|
| + { "stat3", SQLITE_Stat34 },
|
| + { "stat4", SQLITE_Stat34 },
|
| };
|
|
|
| if( objc!=4 ){
|
| @@ -6336,12 +6532,14 @@ static int tclLoadStaticExtensionCmd(
|
| ){
|
| extern int sqlite3_amatch_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_closure_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_eval_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_fileio_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_fuzzer_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_ieee_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_nextchar_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_percentile_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_regexp_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| + extern int sqlite3_series_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_spellfix_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_totype_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| extern int sqlite3_wholenumber_init(sqlite3*,char**,const sqlite3_api_routines*);
|
| @@ -6351,12 +6549,14 @@ static int tclLoadStaticExtensionCmd(
|
| } aExtension[] = {
|
| { "amatch", sqlite3_amatch_init },
|
| { "closure", sqlite3_closure_init },
|
| + { "eval", sqlite3_eval_init },
|
| { "fileio", sqlite3_fileio_init },
|
| { "fuzzer", sqlite3_fuzzer_init },
|
| { "ieee754", sqlite3_ieee_init },
|
| { "nextchar", sqlite3_nextchar_init },
|
| { "percentile", sqlite3_percentile_init },
|
| { "regexp", sqlite3_regexp_init },
|
| + { "series", sqlite3_series_init },
|
| { "spellfix", sqlite3_spellfix_init },
|
| { "totype", sqlite3_totype_init },
|
| { "wholenumber", sqlite3_wholenumber_init },
|
| @@ -6379,7 +6579,11 @@ static int tclLoadStaticExtensionCmd(
|
| Tcl_AppendResult(interp, "no such extension: ", zName, (char*)0);
|
| return TCL_ERROR;
|
| }
|
| - rc = aExtension[i].pInit(db, &zErrMsg, 0);
|
| + if( aExtension[i].pInit ){
|
| + rc = aExtension[i].pInit(db, &zErrMsg, 0);
|
| + }else{
|
| + rc = SQLITE_OK;
|
| + }
|
| if( rc!=SQLITE_OK || zErrMsg ){
|
| Tcl_AppendResult(interp, "initialization of ", zName, " failed: ", zErrMsg,
|
| (char*)0);
|
| @@ -6625,6 +6829,98 @@ static int test_user_delete(
|
| #endif /* SQLITE_USER_AUTHENTICATION */
|
|
|
| /*
|
| +** tclcmd: bad_behavior TYPE
|
| +**
|
| +** Do some things that should trigger a valgrind or -fsanitize=undefined
|
| +** warning. This is used to verify that errors and warnings output by those
|
| +** tools are detected by the test scripts.
|
| +**
|
| +** TYPE BEHAVIOR
|
| +** 1 Overflow a signed integer
|
| +** 2 Jump based on an uninitialized variable
|
| +** 3 Read after free
|
| +** 4 Panic
|
| +*/
|
| +static int test_bad_behavior(
|
| + ClientData clientData, /* Pointer to an integer containing zero */
|
| + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
|
| + int objc, /* Number of arguments */
|
| + Tcl_Obj *CONST objv[] /* Command arguments */
|
| +){
|
| + int iType;
|
| + int xyz;
|
| + int i = *(int*)clientData;
|
| + int j;
|
| + int w[10];
|
| + int *a;
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "TYPE");
|
| + return TCL_ERROR;
|
| + }
|
| + if( Tcl_GetIntFromObj(interp, objv[1], &iType) ) return TCL_ERROR;
|
| + switch( iType ){
|
| + case 1: {
|
| + xyz = 0x7fffff00 - i;
|
| + xyz += 0x100;
|
| + Tcl_SetObjResult(interp, Tcl_NewIntObj(xyz));
|
| + break;
|
| + }
|
| + case 2: {
|
| + w[1] = 5;
|
| + if( w[i]>0 ) w[1]++;
|
| + Tcl_SetObjResult(interp, Tcl_NewIntObj(w[1]));
|
| + break;
|
| + }
|
| + case 3: {
|
| + a = malloc( sizeof(int)*10 );
|
| + for(j=0; j<10; j++) a[j] = j;
|
| + free(a);
|
| + Tcl_SetObjResult(interp, Tcl_NewIntObj(a[i]));
|
| + break;
|
| + }
|
| + case 4: {
|
| + Tcl_Panic("Deliberate panic");
|
| + break;
|
| + }
|
| + }
|
| + return TCL_OK;
|
| +}
|
| +
|
| +/*
|
| +** tclcmd: register_dbstat_vtab DB
|
| +**
|
| +** Cause the dbstat virtual table to be available on the connection DB
|
| +*/
|
| +static int test_register_dbstat_vtab(
|
| + void *clientData,
|
| + Tcl_Interp *interp,
|
| + int objc,
|
| + Tcl_Obj *CONST objv[]
|
| +){
|
| +#ifdef SQLITE_OMIT_VIRTUALTABLE
|
| + Tcl_AppendResult(interp, "dbstat not available because of "
|
| + "SQLITE_OMIT_VIRTUALTABLE", (void*)0);
|
| + return TCL_ERROR;
|
| +#else
|
| + struct SqliteDb { sqlite3 *db; };
|
| + char *zDb;
|
| + Tcl_CmdInfo cmdInfo;
|
| +
|
| + if( objc!=2 ){
|
| + Tcl_WrongNumArgs(interp, 1, objv, "DB");
|
| + return TCL_ERROR;
|
| + }
|
| +
|
| + zDb = Tcl_GetString(objv[1]);
|
| + if( Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
|
| + sqlite3* db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
|
| + sqlite3DbstatRegister(db);
|
| + }
|
| + return TCL_OK;
|
| +#endif /* SQLITE_OMIT_VIRTUALTABLE */
|
| +}
|
| +
|
| +/*
|
| ** Register commands with the TCL interpreter.
|
| */
|
| int Sqlitetest1_Init(Tcl_Interp *interp){
|
| @@ -6640,6 +6936,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| extern int sqlite3_max_blobsize;
|
| extern int sqlite3BtreeSharedCacheReport(void*,
|
| Tcl_Interp*,int,Tcl_Obj*CONST*);
|
| + static int iZero = 0;
|
| static struct {
|
| char *zName;
|
| Tcl_CmdProc *xProc;
|
| @@ -6692,9 +6989,12 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| Tcl_ObjCmdProc *xProc;
|
| void *clientData;
|
| } aObjCmd[] = {
|
| + { "bad_behavior", test_bad_behavior, (void*)&iZero },
|
| + { "register_dbstat_vtab", test_register_dbstat_vtab },
|
| { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
|
| { "sqlite3_bind_int", test_bind_int, 0 },
|
| { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },
|
| + { "sqlite3_bind_zeroblob64", test_bind_zeroblob64, 0 },
|
| { "sqlite3_bind_int64", test_bind_int64, 0 },
|
| { "sqlite3_bind_double", test_bind_double, 0 },
|
| { "sqlite3_bind_null", test_bind_null ,0 },
|
| @@ -6735,6 +7035,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
|
|
| { "sqlite3_release_memory", test_release_memory, 0},
|
| { "sqlite3_db_release_memory", test_db_release_memory, 0},
|
| + { "sqlite3_db_cacheflush", test_db_cacheflush, 0},
|
| { "sqlite3_db_filename", test_db_filename, 0},
|
| { "sqlite3_db_readonly", test_db_readonly, 0},
|
| { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
|
| @@ -6834,15 +7135,9 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
|
| #endif
|
| { "sqlite3_libversion_number", test_libversion_number, 0 },
|
| -#ifdef SQLITE_ENABLE_COLUMN_METADATA
|
| { "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_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
|
| @@ -6850,6 +7145,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| #endif
|
| { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
|
| { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
|
| + { "sqlite3_wal_autocheckpoint",test_wal_autocheckpoint, 0 },
|
| { "test_sqlite3_log", test_sqlite3_log, 0 },
|
| #ifndef SQLITE_OMIT_EXPLAIN
|
| { "print_explain_query_plan", test_print_eqp, 0 },
|
| @@ -6867,9 +7163,22 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| { "sqlite3_user_change", test_user_change, 0 },
|
| { "sqlite3_user_delete", test_user_delete, 0 },
|
| #endif
|
| -
|
| +#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
|
| + { "sqlite3_stmt_scanstatus", test_stmt_scanstatus, 0 },
|
| + { "sqlite3_stmt_scanstatus_reset", test_stmt_scanstatus_reset, 0 },
|
| +#endif
|
| +#ifdef SQLITE_ENABLE_SQLLOG
|
| + { "sqlite3_config_sqllog", test_config_sqllog, 0 },
|
| +#endif
|
| + { "vfs_current_time_int64", vfsCurrentTimeInt64, 0 },
|
| +#ifdef SQLITE_ENABLE_SNAPSHOT
|
| + { "sqlite3_snapshot_get", test_snapshot_get, 0 },
|
| + { "sqlite3_snapshot_open", test_snapshot_open, 0 },
|
| + { "sqlite3_snapshot_free", test_snapshot_free, 0 },
|
| +#endif
|
| };
|
| static int bitmask_size = sizeof(Bitmask)*8;
|
| + static int longdouble_size = sizeof(LONGDOUBLE_TYPE);
|
| int i;
|
| extern int sqlite3_sync_count, sqlite3_fullsync_count;
|
| extern int sqlite3_opentemp_count;
|
| @@ -6970,6 +7279,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
|
| (char*)&sqlite3_data_directory, TCL_LINK_STRING);
|
| Tcl_LinkVar(interp, "bitmask_size",
|
| (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
|
| + Tcl_LinkVar(interp, "longdouble_size",
|
| + (char*)&longdouble_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
|
| Tcl_LinkVar(interp, "sqlite_sync_count",
|
| (char*)&sqlite3_sync_count, TCL_LINK_INT);
|
| Tcl_LinkVar(interp, "sqlite_fullsync_count",
|
|
|