Annotation of embedaddon/sqlite3/src/test1.c, revision 1.1
1.1 ! misho 1: /*
! 2: ** 2001 September 15
! 3: **
! 4: ** The author disclaims copyright to this source code. In place of
! 5: ** a legal notice, here is a blessing:
! 6: **
! 7: ** May you do good and not evil.
! 8: ** May you find forgiveness for yourself and forgive others.
! 9: ** May you share freely, never taking more than you give.
! 10: **
! 11: *************************************************************************
! 12: ** Code for testing all sorts of SQLite interfaces. This code
! 13: ** is not included in the SQLite library. It is used for automated
! 14: ** testing of the SQLite library.
! 15: */
! 16: #include "sqliteInt.h"
! 17: #include "vdbeInt.h"
! 18: #include "tcl.h"
! 19: #include <stdlib.h>
! 20: #include <string.h>
! 21:
! 22: /*
! 23: ** This is a copy of the first part of the SqliteDb structure in
! 24: ** tclsqlite.c. We need it here so that the get_sqlite_pointer routine
! 25: ** can extract the sqlite3* pointer from an existing Tcl SQLite
! 26: ** connection.
! 27: */
! 28: struct SqliteDb {
! 29: sqlite3 *db;
! 30: };
! 31:
! 32: /*
! 33: ** Convert text generated by the "%p" conversion format back into
! 34: ** a pointer.
! 35: */
! 36: static int testHexToInt(int h){
! 37: if( h>='0' && h<='9' ){
! 38: return h - '0';
! 39: }else if( h>='a' && h<='f' ){
! 40: return h - 'a' + 10;
! 41: }else{
! 42: assert( h>='A' && h<='F' );
! 43: return h - 'A' + 10;
! 44: }
! 45: }
! 46: void *sqlite3TestTextToPtr(const char *z){
! 47: void *p;
! 48: u64 v;
! 49: u32 v2;
! 50: if( z[0]=='0' && z[1]=='x' ){
! 51: z += 2;
! 52: }
! 53: v = 0;
! 54: while( *z ){
! 55: v = (v<<4) + testHexToInt(*z);
! 56: z++;
! 57: }
! 58: if( sizeof(p)==sizeof(v) ){
! 59: memcpy(&p, &v, sizeof(p));
! 60: }else{
! 61: assert( sizeof(p)==sizeof(v2) );
! 62: v2 = (u32)v;
! 63: memcpy(&p, &v2, sizeof(p));
! 64: }
! 65: return p;
! 66: }
! 67:
! 68:
! 69: /*
! 70: ** A TCL command that returns the address of the sqlite* pointer
! 71: ** for an sqlite connection instance. Bad things happen if the
! 72: ** input is not an sqlite connection.
! 73: */
! 74: static int get_sqlite_pointer(
! 75: void * clientData,
! 76: Tcl_Interp *interp,
! 77: int objc,
! 78: Tcl_Obj *CONST objv[]
! 79: ){
! 80: struct SqliteDb *p;
! 81: Tcl_CmdInfo cmdInfo;
! 82: char zBuf[100];
! 83: if( objc!=2 ){
! 84: Tcl_WrongNumArgs(interp, 1, objv, "SQLITE-CONNECTION");
! 85: return TCL_ERROR;
! 86: }
! 87: if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
! 88: Tcl_AppendResult(interp, "command not found: ",
! 89: Tcl_GetString(objv[1]), (char*)0);
! 90: return TCL_ERROR;
! 91: }
! 92: p = (struct SqliteDb*)cmdInfo.objClientData;
! 93: sprintf(zBuf, "%p", p->db);
! 94: if( strncmp(zBuf,"0x",2) ){
! 95: sprintf(zBuf, "0x%p", p->db);
! 96: }
! 97: Tcl_AppendResult(interp, zBuf, 0);
! 98: return TCL_OK;
! 99: }
! 100:
! 101: /*
! 102: ** Decode a pointer to an sqlite3 object.
! 103: */
! 104: int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
! 105: struct SqliteDb *p;
! 106: Tcl_CmdInfo cmdInfo;
! 107: if( Tcl_GetCommandInfo(interp, zA, &cmdInfo) ){
! 108: p = (struct SqliteDb*)cmdInfo.objClientData;
! 109: *ppDb = p->db;
! 110: }else{
! 111: *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
! 112: }
! 113: return TCL_OK;
! 114: }
! 115:
! 116:
! 117: const char *sqlite3TestErrorName(int rc){
! 118: const char *zName = 0;
! 119: switch( rc ){
! 120: case SQLITE_OK: zName = "SQLITE_OK"; break;
! 121: case SQLITE_ERROR: zName = "SQLITE_ERROR"; break;
! 122: case SQLITE_INTERNAL: zName = "SQLITE_INTERNAL"; break;
! 123: case SQLITE_PERM: zName = "SQLITE_PERM"; break;
! 124: case SQLITE_ABORT: zName = "SQLITE_ABORT"; break;
! 125: case SQLITE_BUSY: zName = "SQLITE_BUSY"; break;
! 126: case SQLITE_LOCKED: zName = "SQLITE_LOCKED"; break;
! 127: case SQLITE_LOCKED_SHAREDCACHE: zName = "SQLITE_LOCKED_SHAREDCACHE";break;
! 128: case SQLITE_NOMEM: zName = "SQLITE_NOMEM"; break;
! 129: case SQLITE_READONLY: zName = "SQLITE_READONLY"; break;
! 130: case SQLITE_INTERRUPT: zName = "SQLITE_INTERRUPT"; break;
! 131: case SQLITE_IOERR: zName = "SQLITE_IOERR"; break;
! 132: case SQLITE_CORRUPT: zName = "SQLITE_CORRUPT"; break;
! 133: case SQLITE_NOTFOUND: zName = "SQLITE_NOTFOUND"; break;
! 134: case SQLITE_FULL: zName = "SQLITE_FULL"; break;
! 135: case SQLITE_CANTOPEN: zName = "SQLITE_CANTOPEN"; break;
! 136: case SQLITE_PROTOCOL: zName = "SQLITE_PROTOCOL"; break;
! 137: case SQLITE_EMPTY: zName = "SQLITE_EMPTY"; break;
! 138: case SQLITE_SCHEMA: zName = "SQLITE_SCHEMA"; break;
! 139: case SQLITE_TOOBIG: zName = "SQLITE_TOOBIG"; break;
! 140: case SQLITE_CONSTRAINT: zName = "SQLITE_CONSTRAINT"; break;
! 141: case SQLITE_MISMATCH: zName = "SQLITE_MISMATCH"; break;
! 142: case SQLITE_MISUSE: zName = "SQLITE_MISUSE"; break;
! 143: case SQLITE_NOLFS: zName = "SQLITE_NOLFS"; break;
! 144: case SQLITE_AUTH: zName = "SQLITE_AUTH"; break;
! 145: case SQLITE_FORMAT: zName = "SQLITE_FORMAT"; break;
! 146: case SQLITE_RANGE: zName = "SQLITE_RANGE"; break;
! 147: case SQLITE_NOTADB: zName = "SQLITE_NOTADB"; break;
! 148: case SQLITE_ROW: zName = "SQLITE_ROW"; break;
! 149: case SQLITE_DONE: zName = "SQLITE_DONE"; break;
! 150: case SQLITE_IOERR_READ: zName = "SQLITE_IOERR_READ"; break;
! 151: case SQLITE_IOERR_SHORT_READ: zName = "SQLITE_IOERR_SHORT_READ"; break;
! 152: case SQLITE_IOERR_WRITE: zName = "SQLITE_IOERR_WRITE"; break;
! 153: case SQLITE_IOERR_FSYNC: zName = "SQLITE_IOERR_FSYNC"; break;
! 154: case SQLITE_IOERR_DIR_FSYNC: zName = "SQLITE_IOERR_DIR_FSYNC"; break;
! 155: case SQLITE_IOERR_TRUNCATE: zName = "SQLITE_IOERR_TRUNCATE"; break;
! 156: case SQLITE_IOERR_FSTAT: zName = "SQLITE_IOERR_FSTAT"; break;
! 157: case SQLITE_IOERR_UNLOCK: zName = "SQLITE_IOERR_UNLOCK"; break;
! 158: case SQLITE_IOERR_RDLOCK: zName = "SQLITE_IOERR_RDLOCK"; break;
! 159: case SQLITE_IOERR_DELETE: zName = "SQLITE_IOERR_DELETE"; break;
! 160: case SQLITE_IOERR_BLOCKED: zName = "SQLITE_IOERR_BLOCKED"; break;
! 161: case SQLITE_IOERR_NOMEM: zName = "SQLITE_IOERR_NOMEM"; break;
! 162: case SQLITE_IOERR_ACCESS: zName = "SQLITE_IOERR_ACCESS"; break;
! 163: case SQLITE_IOERR_CHECKRESERVEDLOCK:
! 164: zName = "SQLITE_IOERR_CHECKRESERVEDLOCK"; break;
! 165: case SQLITE_IOERR_LOCK: zName = "SQLITE_IOERR_LOCK"; break;
! 166: case SQLITE_CORRUPT_VTAB: zName = "SQLITE_CORRUPT_VTAB"; break;
! 167: case SQLITE_READONLY_RECOVERY: zName = "SQLITE_READONLY_RECOVERY"; break;
! 168: case SQLITE_READONLY_CANTLOCK: zName = "SQLITE_READONLY_CANTLOCK"; break;
! 169: default: zName = "SQLITE_Unknown"; break;
! 170: }
! 171: return zName;
! 172: }
! 173: #define t1ErrorName sqlite3TestErrorName
! 174:
! 175: /*
! 176: ** Convert an sqlite3_stmt* into an sqlite3*. This depends on the
! 177: ** fact that the sqlite3* is the first field in the Vdbe structure.
! 178: */
! 179: #define StmtToDb(X) sqlite3_db_handle(X)
! 180:
! 181: /*
! 182: ** Check a return value to make sure it agrees with the results
! 183: ** from sqlite3_errcode.
! 184: */
! 185: int sqlite3TestErrCode(Tcl_Interp *interp, sqlite3 *db, int rc){
! 186: if( sqlite3_threadsafe()==0 && rc!=SQLITE_MISUSE && rc!=SQLITE_OK
! 187: && sqlite3_errcode(db)!=rc ){
! 188: char zBuf[200];
! 189: int r2 = sqlite3_errcode(db);
! 190: sprintf(zBuf, "error code %s (%d) does not match sqlite3_errcode %s (%d)",
! 191: t1ErrorName(rc), rc, t1ErrorName(r2), r2);
! 192: Tcl_ResetResult(interp);
! 193: Tcl_AppendResult(interp, zBuf, 0);
! 194: return 1;
! 195: }
! 196: return 0;
! 197: }
! 198:
! 199: /*
! 200: ** Decode a pointer to an sqlite3_stmt object.
! 201: */
! 202: static int getStmtPointer(
! 203: Tcl_Interp *interp,
! 204: const char *zArg,
! 205: sqlite3_stmt **ppStmt
! 206: ){
! 207: *ppStmt = (sqlite3_stmt*)sqlite3TestTextToPtr(zArg);
! 208: return TCL_OK;
! 209: }
! 210:
! 211: /*
! 212: ** Generate a text representation of a pointer that can be understood
! 213: ** by the getDbPointer and getVmPointer routines above.
! 214: **
! 215: ** The problem is, on some machines (Solaris) if you do a printf with
! 216: ** "%p" you cannot turn around and do a scanf with the same "%p" and
! 217: ** get your pointer back. You have to prepend a "0x" before it will
! 218: ** work. Or at least that is what is reported to me (drh). But this
! 219: ** behavior varies from machine to machine. The solution used her is
! 220: ** to test the string right after it is generated to see if it can be
! 221: ** understood by scanf, and if not, try prepending an "0x" to see if
! 222: ** that helps. If nothing works, a fatal error is generated.
! 223: */
! 224: int sqlite3TestMakePointerStr(Tcl_Interp *interp, char *zPtr, void *p){
! 225: sqlite3_snprintf(100, zPtr, "%p", p);
! 226: return TCL_OK;
! 227: }
! 228:
! 229: /*
! 230: ** The callback routine for sqlite3_exec_printf().
! 231: */
! 232: static int exec_printf_cb(void *pArg, int argc, char **argv, char **name){
! 233: Tcl_DString *str = (Tcl_DString*)pArg;
! 234: int i;
! 235:
! 236: if( Tcl_DStringLength(str)==0 ){
! 237: for(i=0; i<argc; i++){
! 238: Tcl_DStringAppendElement(str, name[i] ? name[i] : "NULL");
! 239: }
! 240: }
! 241: for(i=0; i<argc; i++){
! 242: Tcl_DStringAppendElement(str, argv[i] ? argv[i] : "NULL");
! 243: }
! 244: return 0;
! 245: }
! 246:
! 247: /*
! 248: ** The I/O tracing callback.
! 249: */
! 250: #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
! 251: static FILE *iotrace_file = 0;
! 252: static void io_trace_callback(const char *zFormat, ...){
! 253: va_list ap;
! 254: va_start(ap, zFormat);
! 255: vfprintf(iotrace_file, zFormat, ap);
! 256: va_end(ap);
! 257: fflush(iotrace_file);
! 258: }
! 259: #endif
! 260:
! 261: /*
! 262: ** Usage: io_trace FILENAME
! 263: **
! 264: ** Turn I/O tracing on or off. If FILENAME is not an empty string,
! 265: ** I/O tracing begins going into FILENAME. If FILENAME is an empty
! 266: ** string, I/O tracing is turned off.
! 267: */
! 268: static int test_io_trace(
! 269: void *NotUsed,
! 270: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 271: int argc, /* Number of arguments */
! 272: char **argv /* Text of each argument */
! 273: ){
! 274: #if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
! 275: if( argc!=2 ){
! 276: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 277: " FILENAME\"", 0);
! 278: return TCL_ERROR;
! 279: }
! 280: if( iotrace_file ){
! 281: if( iotrace_file!=stdout && iotrace_file!=stderr ){
! 282: fclose(iotrace_file);
! 283: }
! 284: iotrace_file = 0;
! 285: sqlite3IoTrace = 0;
! 286: }
! 287: if( argv[1][0] ){
! 288: if( strcmp(argv[1],"stdout")==0 ){
! 289: iotrace_file = stdout;
! 290: }else if( strcmp(argv[1],"stderr")==0 ){
! 291: iotrace_file = stderr;
! 292: }else{
! 293: iotrace_file = fopen(argv[1], "w");
! 294: }
! 295: sqlite3IoTrace = io_trace_callback;
! 296: }
! 297: #endif
! 298: return TCL_OK;
! 299: }
! 300:
! 301:
! 302: /*
! 303: ** Usage: sqlite3_exec_printf DB FORMAT STRING
! 304: **
! 305: ** Invoke the sqlite3_exec_printf() interface using the open database
! 306: ** DB. The SQL is the string FORMAT. The format string should contain
! 307: ** one %s or %q. STRING is the value inserted into %s or %q.
! 308: */
! 309: static int test_exec_printf(
! 310: void *NotUsed,
! 311: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 312: int argc, /* Number of arguments */
! 313: char **argv /* Text of each argument */
! 314: ){
! 315: sqlite3 *db;
! 316: Tcl_DString str;
! 317: int rc;
! 318: char *zErr = 0;
! 319: char *zSql;
! 320: char zBuf[30];
! 321: if( argc!=4 ){
! 322: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 323: " DB FORMAT STRING", 0);
! 324: return TCL_ERROR;
! 325: }
! 326: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 327: Tcl_DStringInit(&str);
! 328: zSql = sqlite3_mprintf(argv[2], argv[3]);
! 329: rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
! 330: sqlite3_free(zSql);
! 331: sprintf(zBuf, "%d", rc);
! 332: Tcl_AppendElement(interp, zBuf);
! 333: Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
! 334: Tcl_DStringFree(&str);
! 335: if( zErr ) sqlite3_free(zErr);
! 336: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 337: return TCL_OK;
! 338: }
! 339:
! 340: /*
! 341: ** Usage: sqlite3_exec_hex DB HEX
! 342: **
! 343: ** Invoke the sqlite3_exec() on a string that is obtained by translating
! 344: ** HEX into ASCII. Most characters are translated as is. %HH becomes
! 345: ** a hex character.
! 346: */
! 347: static int test_exec_hex(
! 348: void *NotUsed,
! 349: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 350: int argc, /* Number of arguments */
! 351: char **argv /* Text of each argument */
! 352: ){
! 353: sqlite3 *db;
! 354: Tcl_DString str;
! 355: int rc, i, j;
! 356: char *zErr = 0;
! 357: char *zHex;
! 358: char zSql[500];
! 359: char zBuf[30];
! 360: if( argc!=3 ){
! 361: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 362: " DB HEX", 0);
! 363: return TCL_ERROR;
! 364: }
! 365: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 366: zHex = argv[2];
! 367: for(i=j=0; i<sizeof(zSql) && zHex[j]; i++, j++){
! 368: if( zHex[j]=='%' && zHex[j+2] && zHex[j+2] ){
! 369: zSql[i] = (testHexToInt(zHex[j+1])<<4) + testHexToInt(zHex[j+2]);
! 370: j += 2;
! 371: }else{
! 372: zSql[i] = zHex[j];
! 373: }
! 374: }
! 375: zSql[i] = 0;
! 376: Tcl_DStringInit(&str);
! 377: rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
! 378: sprintf(zBuf, "%d", rc);
! 379: Tcl_AppendElement(interp, zBuf);
! 380: Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
! 381: Tcl_DStringFree(&str);
! 382: if( zErr ) sqlite3_free(zErr);
! 383: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 384: return TCL_OK;
! 385: }
! 386:
! 387: /*
! 388: ** Usage: db_enter DB
! 389: ** db_leave DB
! 390: **
! 391: ** Enter or leave the mutex on a database connection.
! 392: */
! 393: static int db_enter(
! 394: void *NotUsed,
! 395: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 396: int argc, /* Number of arguments */
! 397: char **argv /* Text of each argument */
! 398: ){
! 399: sqlite3 *db;
! 400: if( argc!=2 ){
! 401: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 402: " DB", 0);
! 403: return TCL_ERROR;
! 404: }
! 405: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 406: sqlite3_mutex_enter(db->mutex);
! 407: return TCL_OK;
! 408: }
! 409: static int db_leave(
! 410: void *NotUsed,
! 411: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 412: int argc, /* Number of arguments */
! 413: char **argv /* Text of each argument */
! 414: ){
! 415: sqlite3 *db;
! 416: if( argc!=2 ){
! 417: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 418: " DB", 0);
! 419: return TCL_ERROR;
! 420: }
! 421: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 422: sqlite3_mutex_leave(db->mutex);
! 423: return TCL_OK;
! 424: }
! 425:
! 426: /*
! 427: ** Usage: sqlite3_exec DB SQL
! 428: **
! 429: ** Invoke the sqlite3_exec interface using the open database DB
! 430: */
! 431: static int test_exec(
! 432: void *NotUsed,
! 433: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 434: int argc, /* Number of arguments */
! 435: char **argv /* Text of each argument */
! 436: ){
! 437: sqlite3 *db;
! 438: Tcl_DString str;
! 439: int rc;
! 440: char *zErr = 0;
! 441: char *zSql;
! 442: int i, j;
! 443: char zBuf[30];
! 444: if( argc!=3 ){
! 445: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 446: " DB SQL", 0);
! 447: return TCL_ERROR;
! 448: }
! 449: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 450: Tcl_DStringInit(&str);
! 451: zSql = sqlite3_mprintf("%s", argv[2]);
! 452: for(i=j=0; zSql[i];){
! 453: if( zSql[i]=='%' ){
! 454: zSql[j++] = (testHexToInt(zSql[i+1])<<4) + testHexToInt(zSql[i+2]);
! 455: i += 3;
! 456: }else{
! 457: zSql[j++] = zSql[i++];
! 458: }
! 459: }
! 460: zSql[j] = 0;
! 461: rc = sqlite3_exec(db, zSql, exec_printf_cb, &str, &zErr);
! 462: sqlite3_free(zSql);
! 463: sprintf(zBuf, "%d", rc);
! 464: Tcl_AppendElement(interp, zBuf);
! 465: Tcl_AppendElement(interp, rc==SQLITE_OK ? Tcl_DStringValue(&str) : zErr);
! 466: Tcl_DStringFree(&str);
! 467: if( zErr ) sqlite3_free(zErr);
! 468: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 469: return TCL_OK;
! 470: }
! 471:
! 472: /*
! 473: ** Usage: sqlite3_exec_nr DB SQL
! 474: **
! 475: ** Invoke the sqlite3_exec interface using the open database DB. Discard
! 476: ** all results
! 477: */
! 478: static int test_exec_nr(
! 479: void *NotUsed,
! 480: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 481: int argc, /* Number of arguments */
! 482: char **argv /* Text of each argument */
! 483: ){
! 484: sqlite3 *db;
! 485: int rc;
! 486: char *zErr = 0;
! 487: if( argc!=3 ){
! 488: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 489: " DB SQL", 0);
! 490: return TCL_ERROR;
! 491: }
! 492: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 493: rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
! 494: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 495: return TCL_OK;
! 496: }
! 497:
! 498: /*
! 499: ** Usage: sqlite3_mprintf_z_test SEPARATOR ARG0 ARG1 ...
! 500: **
! 501: ** Test the %z format of sqlite_mprintf(). Use multiple mprintf() calls to
! 502: ** concatenate arg0 through argn using separator as the separator.
! 503: ** Return the result.
! 504: */
! 505: static int test_mprintf_z(
! 506: void *NotUsed,
! 507: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 508: int argc, /* Number of arguments */
! 509: char **argv /* Text of each argument */
! 510: ){
! 511: char *zResult = 0;
! 512: int i;
! 513:
! 514: for(i=2; i<argc && (i==2 || zResult); i++){
! 515: zResult = sqlite3_mprintf("%z%s%s", zResult, argv[1], argv[i]);
! 516: }
! 517: Tcl_AppendResult(interp, zResult, 0);
! 518: sqlite3_free(zResult);
! 519: return TCL_OK;
! 520: }
! 521:
! 522: /*
! 523: ** Usage: sqlite3_mprintf_n_test STRING
! 524: **
! 525: ** Test the %n format of sqlite_mprintf(). Return the length of the
! 526: ** input string.
! 527: */
! 528: static int test_mprintf_n(
! 529: void *NotUsed,
! 530: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 531: int argc, /* Number of arguments */
! 532: char **argv /* Text of each argument */
! 533: ){
! 534: char *zStr;
! 535: int n = 0;
! 536: zStr = sqlite3_mprintf("%s%n", argv[1], &n);
! 537: sqlite3_free(zStr);
! 538: Tcl_SetObjResult(interp, Tcl_NewIntObj(n));
! 539: return TCL_OK;
! 540: }
! 541:
! 542: /*
! 543: ** Usage: sqlite3_snprintf_int SIZE FORMAT INT
! 544: **
! 545: ** Test the of sqlite3_snprintf() routine. SIZE is the size of the
! 546: ** output buffer in bytes. The maximum size is 100. FORMAT is the
! 547: ** format string. INT is a single integer argument. The FORMAT
! 548: ** string must require no more than this one integer argument. If
! 549: ** You pass in a format string that requires more than one argument,
! 550: ** bad things will happen.
! 551: */
! 552: static int test_snprintf_int(
! 553: void *NotUsed,
! 554: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 555: int argc, /* Number of arguments */
! 556: char **argv /* Text of each argument */
! 557: ){
! 558: char zStr[100];
! 559: int n = atoi(argv[1]);
! 560: const char *zFormat = argv[2];
! 561: int a1 = atoi(argv[3]);
! 562: if( n>sizeof(zStr) ) n = sizeof(zStr);
! 563: sqlite3_snprintf(sizeof(zStr), zStr, "abcdefghijklmnopqrstuvwxyz");
! 564: sqlite3_snprintf(n, zStr, zFormat, a1);
! 565: Tcl_AppendResult(interp, zStr, 0);
! 566: return TCL_OK;
! 567: }
! 568:
! 569: #ifndef SQLITE_OMIT_GET_TABLE
! 570:
! 571: /*
! 572: ** Usage: sqlite3_get_table_printf DB FORMAT STRING ?--no-counts?
! 573: **
! 574: ** Invoke the sqlite3_get_table_printf() interface using the open database
! 575: ** DB. The SQL is the string FORMAT. The format string should contain
! 576: ** one %s or %q. STRING is the value inserted into %s or %q.
! 577: */
! 578: static int test_get_table_printf(
! 579: void *NotUsed,
! 580: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 581: int argc, /* Number of arguments */
! 582: char **argv /* Text of each argument */
! 583: ){
! 584: sqlite3 *db;
! 585: Tcl_DString str;
! 586: int rc;
! 587: char *zErr = 0;
! 588: int nRow, nCol;
! 589: char **aResult;
! 590: int i;
! 591: char zBuf[30];
! 592: char *zSql;
! 593: int resCount = -1;
! 594: if( argc==5 ){
! 595: if( Tcl_GetInt(interp, argv[4], &resCount) ) return TCL_ERROR;
! 596: }
! 597: if( argc!=4 && argc!=5 ){
! 598: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 599: " DB FORMAT STRING ?COUNT?", 0);
! 600: return TCL_ERROR;
! 601: }
! 602: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 603: Tcl_DStringInit(&str);
! 604: zSql = sqlite3_mprintf(argv[2],argv[3]);
! 605: if( argc==5 ){
! 606: rc = sqlite3_get_table(db, zSql, &aResult, 0, 0, &zErr);
! 607: }else{
! 608: rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr);
! 609: resCount = (nRow+1)*nCol;
! 610: }
! 611: sqlite3_free(zSql);
! 612: sprintf(zBuf, "%d", rc);
! 613: Tcl_AppendElement(interp, zBuf);
! 614: if( rc==SQLITE_OK ){
! 615: if( argc==4 ){
! 616: sprintf(zBuf, "%d", nRow);
! 617: Tcl_AppendElement(interp, zBuf);
! 618: sprintf(zBuf, "%d", nCol);
! 619: Tcl_AppendElement(interp, zBuf);
! 620: }
! 621: for(i=0; i<resCount; i++){
! 622: Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL");
! 623: }
! 624: }else{
! 625: Tcl_AppendElement(interp, zErr);
! 626: }
! 627: sqlite3_free_table(aResult);
! 628: if( zErr ) sqlite3_free(zErr);
! 629: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 630: return TCL_OK;
! 631: }
! 632:
! 633: #endif /* SQLITE_OMIT_GET_TABLE */
! 634:
! 635:
! 636: /*
! 637: ** Usage: sqlite3_last_insert_rowid DB
! 638: **
! 639: ** Returns the integer ROWID of the most recent insert.
! 640: */
! 641: static int test_last_rowid(
! 642: void *NotUsed,
! 643: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 644: int argc, /* Number of arguments */
! 645: char **argv /* Text of each argument */
! 646: ){
! 647: sqlite3 *db;
! 648: char zBuf[30];
! 649:
! 650: if( argc!=2 ){
! 651: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
! 652: return TCL_ERROR;
! 653: }
! 654: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 655: sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db));
! 656: Tcl_AppendResult(interp, zBuf, 0);
! 657: return SQLITE_OK;
! 658: }
! 659:
! 660: /*
! 661: ** Usage: sqlite3_key DB KEY
! 662: **
! 663: ** Set the codec key.
! 664: */
! 665: static int test_key(
! 666: void *NotUsed,
! 667: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 668: int argc, /* Number of arguments */
! 669: char **argv /* Text of each argument */
! 670: ){
! 671: sqlite3 *db;
! 672: const char *zKey;
! 673: int nKey;
! 674: if( argc!=3 ){
! 675: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 676: " FILENAME\"", 0);
! 677: return TCL_ERROR;
! 678: }
! 679: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 680: zKey = argv[2];
! 681: nKey = strlen(zKey);
! 682: #ifdef SQLITE_HAS_CODEC
! 683: sqlite3_key(db, zKey, nKey);
! 684: #endif
! 685: return TCL_OK;
! 686: }
! 687:
! 688: /*
! 689: ** Usage: sqlite3_rekey DB KEY
! 690: **
! 691: ** Change the codec key.
! 692: */
! 693: static int test_rekey(
! 694: void *NotUsed,
! 695: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 696: int argc, /* Number of arguments */
! 697: char **argv /* Text of each argument */
! 698: ){
! 699: sqlite3 *db;
! 700: const char *zKey;
! 701: int nKey;
! 702: if( argc!=3 ){
! 703: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 704: " FILENAME\"", 0);
! 705: return TCL_ERROR;
! 706: }
! 707: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 708: zKey = argv[2];
! 709: nKey = strlen(zKey);
! 710: #ifdef SQLITE_HAS_CODEC
! 711: sqlite3_rekey(db, zKey, nKey);
! 712: #endif
! 713: return TCL_OK;
! 714: }
! 715:
! 716: /*
! 717: ** Usage: sqlite3_close DB
! 718: **
! 719: ** Closes the database opened by sqlite3_open.
! 720: */
! 721: static int sqlite_test_close(
! 722: void *NotUsed,
! 723: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 724: int argc, /* Number of arguments */
! 725: char **argv /* Text of each argument */
! 726: ){
! 727: sqlite3 *db;
! 728: int rc;
! 729: if( argc!=2 ){
! 730: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 731: " FILENAME\"", 0);
! 732: return TCL_ERROR;
! 733: }
! 734: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 735: rc = sqlite3_close(db);
! 736: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
! 737: return TCL_OK;
! 738: }
! 739:
! 740: /*
! 741: ** Implementation of the x_coalesce() function.
! 742: ** Return the first argument non-NULL argument.
! 743: */
! 744: static void t1_ifnullFunc(
! 745: sqlite3_context *context,
! 746: int argc,
! 747: sqlite3_value **argv
! 748: ){
! 749: int i;
! 750: for(i=0; i<argc; i++){
! 751: if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){
! 752: int n = sqlite3_value_bytes(argv[i]);
! 753: sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]),
! 754: n, SQLITE_TRANSIENT);
! 755: break;
! 756: }
! 757: }
! 758: }
! 759:
! 760: /*
! 761: ** These are test functions. hex8() interprets its argument as
! 762: ** UTF8 and returns a hex encoding. hex16le() interprets its argument
! 763: ** as UTF16le and returns a hex encoding.
! 764: */
! 765: static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){
! 766: const unsigned char *z;
! 767: int i;
! 768: char zBuf[200];
! 769: z = sqlite3_value_text(argv[0]);
! 770: for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){
! 771: sprintf(&zBuf[i*2], "%02x", z[i]&0xff);
! 772: }
! 773: zBuf[i*2] = 0;
! 774: sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
! 775: }
! 776: #ifndef SQLITE_OMIT_UTF16
! 777: static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){
! 778: const unsigned short int *z;
! 779: int i;
! 780: char zBuf[400];
! 781: z = sqlite3_value_text16(argv[0]);
! 782: for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){
! 783: sprintf(&zBuf[i*4], "%04x", z[i]&0xff);
! 784: }
! 785: zBuf[i*4] = 0;
! 786: sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);
! 787: }
! 788: #endif
! 789:
! 790: /*
! 791: ** A structure into which to accumulate text.
! 792: */
! 793: struct dstr {
! 794: int nAlloc; /* Space allocated */
! 795: int nUsed; /* Space used */
! 796: char *z; /* The space */
! 797: };
! 798:
! 799: /*
! 800: ** Append text to a dstr
! 801: */
! 802: static void dstrAppend(struct dstr *p, const char *z, int divider){
! 803: int n = strlen(z);
! 804: if( p->nUsed + n + 2 > p->nAlloc ){
! 805: char *zNew;
! 806: p->nAlloc = p->nAlloc*2 + n + 200;
! 807: zNew = sqlite3_realloc(p->z, p->nAlloc);
! 808: if( zNew==0 ){
! 809: sqlite3_free(p->z);
! 810: memset(p, 0, sizeof(*p));
! 811: return;
! 812: }
! 813: p->z = zNew;
! 814: }
! 815: if( divider && p->nUsed>0 ){
! 816: p->z[p->nUsed++] = divider;
! 817: }
! 818: memcpy(&p->z[p->nUsed], z, n+1);
! 819: p->nUsed += n;
! 820: }
! 821:
! 822: /*
! 823: ** Invoked for each callback from sqlite3ExecFunc
! 824: */
! 825: static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){
! 826: struct dstr *p = (struct dstr*)pData;
! 827: int i;
! 828: for(i=0; i<argc; i++){
! 829: if( argv[i]==0 ){
! 830: dstrAppend(p, "NULL", ' ');
! 831: }else{
! 832: dstrAppend(p, argv[i], ' ');
! 833: }
! 834: }
! 835: return 0;
! 836: }
! 837:
! 838: /*
! 839: ** Implementation of the x_sqlite_exec() function. This function takes
! 840: ** a single argument and attempts to execute that argument as SQL code.
! 841: ** This is illegal and should set the SQLITE_MISUSE flag on the database.
! 842: **
! 843: ** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()
! 844: ** from within a function call.
! 845: **
! 846: ** This routine simulates the effect of having two threads attempt to
! 847: ** use the same database at the same time.
! 848: */
! 849: static void sqlite3ExecFunc(
! 850: sqlite3_context *context,
! 851: int argc,
! 852: sqlite3_value **argv
! 853: ){
! 854: struct dstr x;
! 855: memset(&x, 0, sizeof(x));
! 856: (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context),
! 857: (char*)sqlite3_value_text(argv[0]),
! 858: execFuncCallback, &x, 0);
! 859: sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT);
! 860: sqlite3_free(x.z);
! 861: }
! 862:
! 863: /*
! 864: ** Implementation of tkt2213func(), a scalar function that takes exactly
! 865: ** one argument. It has two interesting features:
! 866: **
! 867: ** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.
! 868: ** If the three pointers returned are not the same an SQL error is raised.
! 869: **
! 870: ** * Otherwise it returns a copy of the text representation of its
! 871: ** argument in such a way as the VDBE representation is a Mem* cell
! 872: ** with the MEM_Term flag clear.
! 873: **
! 874: ** Ticket #2213 can therefore be tested by evaluating the following
! 875: ** SQL expression:
! 876: **
! 877: ** tkt2213func(tkt2213func('a string'));
! 878: */
! 879: static void tkt2213Function(
! 880: sqlite3_context *context,
! 881: int argc,
! 882: sqlite3_value **argv
! 883: ){
! 884: int nText;
! 885: unsigned char const *zText1;
! 886: unsigned char const *zText2;
! 887: unsigned char const *zText3;
! 888:
! 889: nText = sqlite3_value_bytes(argv[0]);
! 890: zText1 = sqlite3_value_text(argv[0]);
! 891: zText2 = sqlite3_value_text(argv[0]);
! 892: zText3 = sqlite3_value_text(argv[0]);
! 893:
! 894: if( zText1!=zText2 || zText2!=zText3 ){
! 895: sqlite3_result_error(context, "tkt2213 is not fixed", -1);
! 896: }else{
! 897: char *zCopy = (char *)sqlite3_malloc(nText);
! 898: memcpy(zCopy, zText1, nText);
! 899: sqlite3_result_text(context, zCopy, nText, sqlite3_free);
! 900: }
! 901: }
! 902:
! 903: /*
! 904: ** The following SQL function takes 4 arguments. The 2nd and
! 905: ** 4th argument must be one of these strings: 'text', 'text16',
! 906: ** or 'blob' corresponding to API functions
! 907: **
! 908: ** sqlite3_value_text()
! 909: ** sqlite3_value_text16()
! 910: ** sqlite3_value_blob()
! 911: **
! 912: ** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',
! 913: ** corresponding to APIs:
! 914: **
! 915: ** sqlite3_value_bytes()
! 916: ** sqlite3_value_bytes16()
! 917: ** noop
! 918: **
! 919: ** The APIs designated by the 2nd through 4th arguments are applied
! 920: ** to the first argument in order. If the pointers returned by the
! 921: ** second and fourth are different, this routine returns 1. Otherwise,
! 922: ** this routine returns 0.
! 923: **
! 924: ** This function is used to test to see when returned pointers from
! 925: ** the _text(), _text16() and _blob() APIs become invalidated.
! 926: */
! 927: static void ptrChngFunction(
! 928: sqlite3_context *context,
! 929: int argc,
! 930: sqlite3_value **argv
! 931: ){
! 932: const void *p1, *p2;
! 933: const char *zCmd;
! 934: if( argc!=4 ) return;
! 935: zCmd = (const char*)sqlite3_value_text(argv[1]);
! 936: if( zCmd==0 ) return;
! 937: if( strcmp(zCmd,"text")==0 ){
! 938: p1 = (const void*)sqlite3_value_text(argv[0]);
! 939: #ifndef SQLITE_OMIT_UTF16
! 940: }else if( strcmp(zCmd, "text16")==0 ){
! 941: p1 = (const void*)sqlite3_value_text16(argv[0]);
! 942: #endif
! 943: }else if( strcmp(zCmd, "blob")==0 ){
! 944: p1 = (const void*)sqlite3_value_blob(argv[0]);
! 945: }else{
! 946: return;
! 947: }
! 948: zCmd = (const char*)sqlite3_value_text(argv[2]);
! 949: if( zCmd==0 ) return;
! 950: if( strcmp(zCmd,"bytes")==0 ){
! 951: sqlite3_value_bytes(argv[0]);
! 952: #ifndef SQLITE_OMIT_UTF16
! 953: }else if( strcmp(zCmd, "bytes16")==0 ){
! 954: sqlite3_value_bytes16(argv[0]);
! 955: #endif
! 956: }else if( strcmp(zCmd, "noop")==0 ){
! 957: /* do nothing */
! 958: }else{
! 959: return;
! 960: }
! 961: zCmd = (const char*)sqlite3_value_text(argv[3]);
! 962: if( zCmd==0 ) return;
! 963: if( strcmp(zCmd,"text")==0 ){
! 964: p2 = (const void*)sqlite3_value_text(argv[0]);
! 965: #ifndef SQLITE_OMIT_UTF16
! 966: }else if( strcmp(zCmd, "text16")==0 ){
! 967: p2 = (const void*)sqlite3_value_text16(argv[0]);
! 968: #endif
! 969: }else if( strcmp(zCmd, "blob")==0 ){
! 970: p2 = (const void*)sqlite3_value_blob(argv[0]);
! 971: }else{
! 972: return;
! 973: }
! 974: sqlite3_result_int(context, p1!=p2);
! 975: }
! 976:
! 977:
! 978: /*
! 979: ** Usage: sqlite_test_create_function DB
! 980: **
! 981: ** Call the sqlite3_create_function API on the given database in order
! 982: ** to create a function named "x_coalesce". This function does the same thing
! 983: ** as the "coalesce" function. This function also registers an SQL function
! 984: ** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()
! 985: ** in this way is illegal recursion and should raise an SQLITE_MISUSE error.
! 986: ** The effect is similar to trying to use the same database connection from
! 987: ** two threads at the same time.
! 988: **
! 989: ** The original motivation for this routine was to be able to call the
! 990: ** sqlite3_create_function function while a query is in progress in order
! 991: ** to test the SQLITE_MISUSE detection logic.
! 992: */
! 993: static int test_create_function(
! 994: void *NotUsed,
! 995: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 996: int argc, /* Number of arguments */
! 997: char **argv /* Text of each argument */
! 998: ){
! 999: int rc;
! 1000: sqlite3 *db;
! 1001:
! 1002: if( argc!=2 ){
! 1003: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1004: " DB\"", 0);
! 1005: return TCL_ERROR;
! 1006: }
! 1007: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 1008: rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0,
! 1009: t1_ifnullFunc, 0, 0);
! 1010: if( rc==SQLITE_OK ){
! 1011: rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0,
! 1012: hex8Func, 0, 0);
! 1013: }
! 1014: #ifndef SQLITE_OMIT_UTF16
! 1015: if( rc==SQLITE_OK ){
! 1016: rc = sqlite3_create_function(db, "hex16", 1, SQLITE_ANY, 0,
! 1017: hex16Func, 0, 0);
! 1018: }
! 1019: #endif
! 1020: if( rc==SQLITE_OK ){
! 1021: rc = sqlite3_create_function(db, "tkt2213func", 1, SQLITE_ANY, 0,
! 1022: tkt2213Function, 0, 0);
! 1023: }
! 1024: if( rc==SQLITE_OK ){
! 1025: rc = sqlite3_create_function(db, "pointer_change", 4, SQLITE_ANY, 0,
! 1026: ptrChngFunction, 0, 0);
! 1027: }
! 1028:
! 1029: #ifndef SQLITE_OMIT_UTF16
! 1030: /* Use the sqlite3_create_function16() API here. Mainly for fun, but also
! 1031: ** because it is not tested anywhere else. */
! 1032: if( rc==SQLITE_OK ){
! 1033: const void *zUtf16;
! 1034: sqlite3_value *pVal;
! 1035: sqlite3_mutex_enter(db->mutex);
! 1036: pVal = sqlite3ValueNew(db);
! 1037: sqlite3ValueSetStr(pVal, -1, "x_sqlite_exec", SQLITE_UTF8, SQLITE_STATIC);
! 1038: zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
! 1039: if( db->mallocFailed ){
! 1040: rc = SQLITE_NOMEM;
! 1041: }else{
! 1042: rc = sqlite3_create_function16(db, zUtf16,
! 1043: 1, SQLITE_UTF16, db, sqlite3ExecFunc, 0, 0);
! 1044: }
! 1045: sqlite3ValueFree(pVal);
! 1046: sqlite3_mutex_leave(db->mutex);
! 1047: }
! 1048: #endif
! 1049:
! 1050: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 1051: Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
! 1052: return TCL_OK;
! 1053: }
! 1054:
! 1055: /*
! 1056: ** Routines to implement the x_count() aggregate function.
! 1057: **
! 1058: ** x_count() counts the number of non-null arguments. But there are
! 1059: ** some twists for testing purposes.
! 1060: **
! 1061: ** If the argument to x_count() is 40 then a UTF-8 error is reported
! 1062: ** on the step function. If x_count(41) is seen, then a UTF-16 error
! 1063: ** is reported on the step function. If the total count is 42, then
! 1064: ** a UTF-8 error is reported on the finalize function.
! 1065: */
! 1066: typedef struct t1CountCtx t1CountCtx;
! 1067: struct t1CountCtx {
! 1068: int n;
! 1069: };
! 1070: static void t1CountStep(
! 1071: sqlite3_context *context,
! 1072: int argc,
! 1073: sqlite3_value **argv
! 1074: ){
! 1075: t1CountCtx *p;
! 1076: p = sqlite3_aggregate_context(context, sizeof(*p));
! 1077: if( (argc==0 || SQLITE_NULL!=sqlite3_value_type(argv[0]) ) && p ){
! 1078: p->n++;
! 1079: }
! 1080: if( argc>0 ){
! 1081: int v = sqlite3_value_int(argv[0]);
! 1082: if( v==40 ){
! 1083: sqlite3_result_error(context, "value of 40 handed to x_count", -1);
! 1084: #ifndef SQLITE_OMIT_UTF16
! 1085: }else if( v==41 ){
! 1086: const char zUtf16ErrMsg[] = { 0, 0x61, 0, 0x62, 0, 0x63, 0, 0, 0};
! 1087: sqlite3_result_error16(context, &zUtf16ErrMsg[1-SQLITE_BIGENDIAN], -1);
! 1088: #endif
! 1089: }
! 1090: }
! 1091: }
! 1092: static void t1CountFinalize(sqlite3_context *context){
! 1093: t1CountCtx *p;
! 1094: p = sqlite3_aggregate_context(context, sizeof(*p));
! 1095: if( p ){
! 1096: if( p->n==42 ){
! 1097: sqlite3_result_error(context, "x_count totals to 42", -1);
! 1098: }else{
! 1099: sqlite3_result_int(context, p ? p->n : 0);
! 1100: }
! 1101: }
! 1102: }
! 1103:
! 1104: #ifndef SQLITE_OMIT_DEPRECATED
! 1105: static void legacyCountStep(
! 1106: sqlite3_context *context,
! 1107: int argc,
! 1108: sqlite3_value **argv
! 1109: ){
! 1110: /* no-op */
! 1111: }
! 1112:
! 1113: static void legacyCountFinalize(sqlite3_context *context){
! 1114: sqlite3_result_int(context, sqlite3_aggregate_count(context));
! 1115: }
! 1116: #endif
! 1117:
! 1118: /*
! 1119: ** Usage: sqlite3_create_aggregate DB
! 1120: **
! 1121: ** Call the sqlite3_create_function API on the given database in order
! 1122: ** to create a function named "x_count". This function is similar
! 1123: ** to the built-in count() function, with a few special quirks
! 1124: ** for testing the sqlite3_result_error() APIs.
! 1125: **
! 1126: ** The original motivation for this routine was to be able to call the
! 1127: ** sqlite3_create_aggregate function while a query is in progress in order
! 1128: ** to test the SQLITE_MISUSE detection logic. See misuse.test.
! 1129: **
! 1130: ** This routine was later extended to test the use of sqlite3_result_error()
! 1131: ** within aggregate functions.
! 1132: **
! 1133: ** Later: It is now also extended to register the aggregate function
! 1134: ** "legacy_count()" with the supplied database handle. This is used
! 1135: ** to test the deprecated sqlite3_aggregate_count() API.
! 1136: */
! 1137: static int test_create_aggregate(
! 1138: void *NotUsed,
! 1139: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1140: int argc, /* Number of arguments */
! 1141: char **argv /* Text of each argument */
! 1142: ){
! 1143: sqlite3 *db;
! 1144: int rc;
! 1145: if( argc!=2 ){
! 1146: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1147: " FILENAME\"", 0);
! 1148: return TCL_ERROR;
! 1149: }
! 1150: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 1151: rc = sqlite3_create_function(db, "x_count", 0, SQLITE_UTF8, 0, 0,
! 1152: t1CountStep,t1CountFinalize);
! 1153: if( rc==SQLITE_OK ){
! 1154: rc = sqlite3_create_function(db, "x_count", 1, SQLITE_UTF8, 0, 0,
! 1155: t1CountStep,t1CountFinalize);
! 1156: }
! 1157: #ifndef SQLITE_OMIT_DEPRECATED
! 1158: if( rc==SQLITE_OK ){
! 1159: rc = sqlite3_create_function(db, "legacy_count", 0, SQLITE_ANY, 0, 0,
! 1160: legacyCountStep, legacyCountFinalize
! 1161: );
! 1162: }
! 1163: #endif
! 1164: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 1165: Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
! 1166: return TCL_OK;
! 1167: }
! 1168:
! 1169:
! 1170: /*
! 1171: ** Usage: printf TEXT
! 1172: **
! 1173: ** Send output to printf. Use this rather than puts to merge the output
! 1174: ** in the correct sequence with debugging printfs inserted into C code.
! 1175: ** Puts uses a separate buffer and debugging statements will be out of
! 1176: ** sequence if it is used.
! 1177: */
! 1178: static int test_printf(
! 1179: void *NotUsed,
! 1180: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1181: int argc, /* Number of arguments */
! 1182: char **argv /* Text of each argument */
! 1183: ){
! 1184: if( argc!=2 ){
! 1185: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1186: " TEXT\"", 0);
! 1187: return TCL_ERROR;
! 1188: }
! 1189: printf("%s\n", argv[1]);
! 1190: return TCL_OK;
! 1191: }
! 1192:
! 1193:
! 1194:
! 1195: /*
! 1196: ** Usage: sqlite3_mprintf_int FORMAT INTEGER INTEGER INTEGER
! 1197: **
! 1198: ** Call mprintf with three integer arguments
! 1199: */
! 1200: static int sqlite3_mprintf_int(
! 1201: void *NotUsed,
! 1202: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1203: int argc, /* Number of arguments */
! 1204: char **argv /* Text of each argument */
! 1205: ){
! 1206: int a[3], i;
! 1207: char *z;
! 1208: if( argc!=5 ){
! 1209: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1210: " FORMAT INT INT INT\"", 0);
! 1211: return TCL_ERROR;
! 1212: }
! 1213: for(i=2; i<5; i++){
! 1214: if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
! 1215: }
! 1216: z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
! 1217: Tcl_AppendResult(interp, z, 0);
! 1218: sqlite3_free(z);
! 1219: return TCL_OK;
! 1220: }
! 1221:
! 1222: /*
! 1223: ** Usage: sqlite3_mprintf_int64 FORMAT INTEGER INTEGER INTEGER
! 1224: **
! 1225: ** Call mprintf with three 64-bit integer arguments
! 1226: */
! 1227: static int sqlite3_mprintf_int64(
! 1228: void *NotUsed,
! 1229: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1230: int argc, /* Number of arguments */
! 1231: char **argv /* Text of each argument */
! 1232: ){
! 1233: int i;
! 1234: sqlite_int64 a[3];
! 1235: char *z;
! 1236: if( argc!=5 ){
! 1237: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1238: " FORMAT INT INT INT\"", 0);
! 1239: return TCL_ERROR;
! 1240: }
! 1241: for(i=2; i<5; i++){
! 1242: if( sqlite3Atoi64(argv[i], &a[i-2], 1000000, SQLITE_UTF8) ){
! 1243: Tcl_AppendResult(interp, "argument is not a valid 64-bit integer", 0);
! 1244: return TCL_ERROR;
! 1245: }
! 1246: }
! 1247: z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
! 1248: Tcl_AppendResult(interp, z, 0);
! 1249: sqlite3_free(z);
! 1250: return TCL_OK;
! 1251: }
! 1252:
! 1253: /*
! 1254: ** Usage: sqlite3_mprintf_long FORMAT INTEGER INTEGER INTEGER
! 1255: **
! 1256: ** Call mprintf with three long integer arguments. This might be the
! 1257: ** same as sqlite3_mprintf_int or sqlite3_mprintf_int64, depending on
! 1258: ** platform.
! 1259: */
! 1260: static int sqlite3_mprintf_long(
! 1261: void *NotUsed,
! 1262: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1263: int argc, /* Number of arguments */
! 1264: char **argv /* Text of each argument */
! 1265: ){
! 1266: int i;
! 1267: long int a[3];
! 1268: int b[3];
! 1269: char *z;
! 1270: if( argc!=5 ){
! 1271: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1272: " FORMAT INT INT INT\"", 0);
! 1273: return TCL_ERROR;
! 1274: }
! 1275: for(i=2; i<5; i++){
! 1276: if( Tcl_GetInt(interp, argv[i], &b[i-2]) ) return TCL_ERROR;
! 1277: a[i-2] = (long int)b[i-2];
! 1278: a[i-2] &= (((u64)1)<<(sizeof(int)*8))-1;
! 1279: }
! 1280: z = sqlite3_mprintf(argv[1], a[0], a[1], a[2]);
! 1281: Tcl_AppendResult(interp, z, 0);
! 1282: sqlite3_free(z);
! 1283: return TCL_OK;
! 1284: }
! 1285:
! 1286: /*
! 1287: ** Usage: sqlite3_mprintf_str FORMAT INTEGER INTEGER STRING
! 1288: **
! 1289: ** Call mprintf with two integer arguments and one string argument
! 1290: */
! 1291: static int sqlite3_mprintf_str(
! 1292: void *NotUsed,
! 1293: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1294: int argc, /* Number of arguments */
! 1295: char **argv /* Text of each argument */
! 1296: ){
! 1297: int a[3], i;
! 1298: char *z;
! 1299: if( argc<4 || argc>5 ){
! 1300: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1301: " FORMAT INT INT ?STRING?\"", 0);
! 1302: return TCL_ERROR;
! 1303: }
! 1304: for(i=2; i<4; i++){
! 1305: if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
! 1306: }
! 1307: z = sqlite3_mprintf(argv[1], a[0], a[1], argc>4 ? argv[4] : NULL);
! 1308: Tcl_AppendResult(interp, z, 0);
! 1309: sqlite3_free(z);
! 1310: return TCL_OK;
! 1311: }
! 1312:
! 1313: /*
! 1314: ** Usage: sqlite3_snprintf_str INTEGER FORMAT INTEGER INTEGER STRING
! 1315: **
! 1316: ** Call mprintf with two integer arguments and one string argument
! 1317: */
! 1318: static int sqlite3_snprintf_str(
! 1319: void *NotUsed,
! 1320: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1321: int argc, /* Number of arguments */
! 1322: char **argv /* Text of each argument */
! 1323: ){
! 1324: int a[3], i;
! 1325: int n;
! 1326: char *z;
! 1327: if( argc<5 || argc>6 ){
! 1328: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1329: " INT FORMAT INT INT ?STRING?\"", 0);
! 1330: return TCL_ERROR;
! 1331: }
! 1332: if( Tcl_GetInt(interp, argv[1], &n) ) return TCL_ERROR;
! 1333: if( n<0 ){
! 1334: Tcl_AppendResult(interp, "N must be non-negative", 0);
! 1335: return TCL_ERROR;
! 1336: }
! 1337: for(i=3; i<5; i++){
! 1338: if( Tcl_GetInt(interp, argv[i], &a[i-3]) ) return TCL_ERROR;
! 1339: }
! 1340: z = sqlite3_malloc( n+1 );
! 1341: sqlite3_snprintf(n, z, argv[2], a[0], a[1], argc>4 ? argv[5] : NULL);
! 1342: Tcl_AppendResult(interp, z, 0);
! 1343: sqlite3_free(z);
! 1344: return TCL_OK;
! 1345: }
! 1346:
! 1347: /*
! 1348: ** Usage: sqlite3_mprintf_double FORMAT INTEGER INTEGER DOUBLE
! 1349: **
! 1350: ** Call mprintf with two integer arguments and one double argument
! 1351: */
! 1352: static int sqlite3_mprintf_double(
! 1353: void *NotUsed,
! 1354: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1355: int argc, /* Number of arguments */
! 1356: char **argv /* Text of each argument */
! 1357: ){
! 1358: int a[3], i;
! 1359: double r;
! 1360: char *z;
! 1361: if( argc!=5 ){
! 1362: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1363: " FORMAT INT INT DOUBLE\"", 0);
! 1364: return TCL_ERROR;
! 1365: }
! 1366: for(i=2; i<4; i++){
! 1367: if( Tcl_GetInt(interp, argv[i], &a[i-2]) ) return TCL_ERROR;
! 1368: }
! 1369: if( Tcl_GetDouble(interp, argv[4], &r) ) return TCL_ERROR;
! 1370: z = sqlite3_mprintf(argv[1], a[0], a[1], r);
! 1371: Tcl_AppendResult(interp, z, 0);
! 1372: sqlite3_free(z);
! 1373: return TCL_OK;
! 1374: }
! 1375:
! 1376: /*
! 1377: ** Usage: sqlite3_mprintf_scaled FORMAT DOUBLE DOUBLE
! 1378: **
! 1379: ** Call mprintf with a single double argument which is the product of the
! 1380: ** two arguments given above. This is used to generate overflow and underflow
! 1381: ** doubles to test that they are converted properly.
! 1382: */
! 1383: static int sqlite3_mprintf_scaled(
! 1384: void *NotUsed,
! 1385: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1386: int argc, /* Number of arguments */
! 1387: char **argv /* Text of each argument */
! 1388: ){
! 1389: int i;
! 1390: double r[2];
! 1391: char *z;
! 1392: if( argc!=4 ){
! 1393: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1394: " FORMAT DOUBLE DOUBLE\"", 0);
! 1395: return TCL_ERROR;
! 1396: }
! 1397: for(i=2; i<4; i++){
! 1398: if( Tcl_GetDouble(interp, argv[i], &r[i-2]) ) return TCL_ERROR;
! 1399: }
! 1400: z = sqlite3_mprintf(argv[1], r[0]*r[1]);
! 1401: Tcl_AppendResult(interp, z, 0);
! 1402: sqlite3_free(z);
! 1403: return TCL_OK;
! 1404: }
! 1405:
! 1406: /*
! 1407: ** Usage: sqlite3_mprintf_stronly FORMAT STRING
! 1408: **
! 1409: ** Call mprintf with a single double argument which is the product of the
! 1410: ** two arguments given above. This is used to generate overflow and underflow
! 1411: ** doubles to test that they are converted properly.
! 1412: */
! 1413: static int sqlite3_mprintf_stronly(
! 1414: void *NotUsed,
! 1415: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1416: int argc, /* Number of arguments */
! 1417: char **argv /* Text of each argument */
! 1418: ){
! 1419: char *z;
! 1420: if( argc!=3 ){
! 1421: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1422: " FORMAT STRING\"", 0);
! 1423: return TCL_ERROR;
! 1424: }
! 1425: z = sqlite3_mprintf(argv[1], argv[2]);
! 1426: Tcl_AppendResult(interp, z, 0);
! 1427: sqlite3_free(z);
! 1428: return TCL_OK;
! 1429: }
! 1430:
! 1431: /*
! 1432: ** Usage: sqlite3_mprintf_hexdouble FORMAT HEX
! 1433: **
! 1434: ** Call mprintf with a single double argument which is derived from the
! 1435: ** hexadecimal encoding of an IEEE double.
! 1436: */
! 1437: static int sqlite3_mprintf_hexdouble(
! 1438: void *NotUsed,
! 1439: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1440: int argc, /* Number of arguments */
! 1441: char **argv /* Text of each argument */
! 1442: ){
! 1443: char *z;
! 1444: double r;
! 1445: unsigned int x1, x2;
! 1446: sqlite_uint64 d;
! 1447: if( argc!=3 ){
! 1448: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 1449: " FORMAT STRING\"", 0);
! 1450: return TCL_ERROR;
! 1451: }
! 1452: if( sscanf(argv[2], "%08x%08x", &x2, &x1)!=2 ){
! 1453: Tcl_AppendResult(interp, "2nd argument should be 16-characters of hex", 0);
! 1454: return TCL_ERROR;
! 1455: }
! 1456: d = x2;
! 1457: d = (d<<32) + x1;
! 1458: memcpy(&r, &d, sizeof(r));
! 1459: z = sqlite3_mprintf(argv[1], r);
! 1460: Tcl_AppendResult(interp, z, 0);
! 1461: sqlite3_free(z);
! 1462: return TCL_OK;
! 1463: }
! 1464:
! 1465: /*
! 1466: ** Usage: sqlite3_enable_shared_cache ?BOOLEAN?
! 1467: **
! 1468: */
! 1469: #if !defined(SQLITE_OMIT_SHARED_CACHE)
! 1470: static int test_enable_shared(
! 1471: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 1472: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1473: int objc, /* Number of arguments */
! 1474: Tcl_Obj *CONST objv[] /* Command arguments */
! 1475: ){
! 1476: int rc;
! 1477: int enable;
! 1478: int ret = 0;
! 1479:
! 1480: if( objc!=2 && objc!=1 ){
! 1481: Tcl_WrongNumArgs(interp, 1, objv, "?BOOLEAN?");
! 1482: return TCL_ERROR;
! 1483: }
! 1484: ret = sqlite3GlobalConfig.sharedCacheEnabled;
! 1485:
! 1486: if( objc==2 ){
! 1487: if( Tcl_GetBooleanFromObj(interp, objv[1], &enable) ){
! 1488: return TCL_ERROR;
! 1489: }
! 1490: rc = sqlite3_enable_shared_cache(enable);
! 1491: if( rc!=SQLITE_OK ){
! 1492: Tcl_SetResult(interp, (char *)sqlite3ErrStr(rc), TCL_STATIC);
! 1493: return TCL_ERROR;
! 1494: }
! 1495: }
! 1496: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(ret));
! 1497: return TCL_OK;
! 1498: }
! 1499: #endif
! 1500:
! 1501:
! 1502:
! 1503: /*
! 1504: ** Usage: sqlite3_extended_result_codes DB BOOLEAN
! 1505: **
! 1506: */
! 1507: static int test_extended_result_codes(
! 1508: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 1509: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1510: int objc, /* Number of arguments */
! 1511: Tcl_Obj *CONST objv[] /* Command arguments */
! 1512: ){
! 1513: int enable;
! 1514: sqlite3 *db;
! 1515:
! 1516: if( objc!=3 ){
! 1517: Tcl_WrongNumArgs(interp, 1, objv, "DB BOOLEAN");
! 1518: return TCL_ERROR;
! 1519: }
! 1520: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 1521: if( Tcl_GetBooleanFromObj(interp, objv[2], &enable) ) return TCL_ERROR;
! 1522: sqlite3_extended_result_codes(db, enable);
! 1523: return TCL_OK;
! 1524: }
! 1525:
! 1526: /*
! 1527: ** Usage: sqlite3_libversion_number
! 1528: **
! 1529: */
! 1530: static int test_libversion_number(
! 1531: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 1532: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1533: int objc, /* Number of arguments */
! 1534: Tcl_Obj *CONST objv[] /* Command arguments */
! 1535: ){
! 1536: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_libversion_number()));
! 1537: return TCL_OK;
! 1538: }
! 1539:
! 1540: /*
! 1541: ** Usage: sqlite3_table_column_metadata DB dbname tblname colname
! 1542: **
! 1543: */
! 1544: #ifdef SQLITE_ENABLE_COLUMN_METADATA
! 1545: static int test_table_column_metadata(
! 1546: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 1547: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1548: int objc, /* Number of arguments */
! 1549: Tcl_Obj *CONST objv[] /* Command arguments */
! 1550: ){
! 1551: sqlite3 *db;
! 1552: const char *zDb;
! 1553: const char *zTbl;
! 1554: const char *zCol;
! 1555: int rc;
! 1556: Tcl_Obj *pRet;
! 1557:
! 1558: const char *zDatatype;
! 1559: const char *zCollseq;
! 1560: int notnull;
! 1561: int primarykey;
! 1562: int autoincrement;
! 1563:
! 1564: if( objc!=5 ){
! 1565: Tcl_WrongNumArgs(interp, 1, objv, "DB dbname tblname colname");
! 1566: return TCL_ERROR;
! 1567: }
! 1568: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 1569: zDb = Tcl_GetString(objv[2]);
! 1570: zTbl = Tcl_GetString(objv[3]);
! 1571: zCol = Tcl_GetString(objv[4]);
! 1572:
! 1573: if( strlen(zDb)==0 ) zDb = 0;
! 1574:
! 1575: rc = sqlite3_table_column_metadata(db, zDb, zTbl, zCol,
! 1576: &zDatatype, &zCollseq, ¬null, &primarykey, &autoincrement);
! 1577:
! 1578: if( rc!=SQLITE_OK ){
! 1579: Tcl_AppendResult(interp, sqlite3_errmsg(db), 0);
! 1580: return TCL_ERROR;
! 1581: }
! 1582:
! 1583: pRet = Tcl_NewObj();
! 1584: Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zDatatype, -1));
! 1585: Tcl_ListObjAppendElement(0, pRet, Tcl_NewStringObj(zCollseq, -1));
! 1586: Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(notnull));
! 1587: Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(primarykey));
! 1588: Tcl_ListObjAppendElement(0, pRet, Tcl_NewIntObj(autoincrement));
! 1589: Tcl_SetObjResult(interp, pRet);
! 1590:
! 1591: return TCL_OK;
! 1592: }
! 1593: #endif
! 1594:
! 1595: #ifndef SQLITE_OMIT_INCRBLOB
! 1596:
! 1597: static int blobHandleFromObj(
! 1598: Tcl_Interp *interp,
! 1599: Tcl_Obj *pObj,
! 1600: sqlite3_blob **ppBlob
! 1601: ){
! 1602: char *z;
! 1603: int n;
! 1604:
! 1605: z = Tcl_GetStringFromObj(pObj, &n);
! 1606: if( n==0 ){
! 1607: *ppBlob = 0;
! 1608: }else{
! 1609: int notUsed;
! 1610: Tcl_Channel channel;
! 1611: ClientData instanceData;
! 1612:
! 1613: channel = Tcl_GetChannel(interp, z, ¬Used);
! 1614: if( !channel ) return TCL_ERROR;
! 1615:
! 1616: Tcl_Flush(channel);
! 1617: Tcl_Seek(channel, 0, SEEK_SET);
! 1618:
! 1619: instanceData = Tcl_GetChannelInstanceData(channel);
! 1620: *ppBlob = *((sqlite3_blob **)instanceData);
! 1621: }
! 1622:
! 1623: return TCL_OK;
! 1624: }
! 1625:
! 1626: /*
! 1627: ** sqlite3_blob_bytes CHANNEL
! 1628: */
! 1629: static int test_blob_bytes(
! 1630: ClientData clientData, /* Not used */
! 1631: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1632: int objc, /* Number of arguments */
! 1633: Tcl_Obj *CONST objv[] /* Command arguments */
! 1634: ){
! 1635: sqlite3_blob *pBlob;
! 1636: int nByte;
! 1637:
! 1638: if( objc!=2 ){
! 1639: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL");
! 1640: return TCL_ERROR;
! 1641: }
! 1642:
! 1643: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
! 1644: nByte = sqlite3_blob_bytes(pBlob);
! 1645: Tcl_SetObjResult(interp, Tcl_NewIntObj(nByte));
! 1646:
! 1647: return TCL_OK;
! 1648: }
! 1649:
! 1650: /*
! 1651: ** sqlite3_blob_close CHANNEL
! 1652: */
! 1653: static int test_blob_close(
! 1654: ClientData clientData, /* Not used */
! 1655: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1656: int objc, /* Number of arguments */
! 1657: Tcl_Obj *CONST objv[] /* Command arguments */
! 1658: ){
! 1659: sqlite3_blob *pBlob;
! 1660:
! 1661: if( objc!=2 ){
! 1662: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL");
! 1663: return TCL_ERROR;
! 1664: }
! 1665:
! 1666: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
! 1667: sqlite3_blob_close(pBlob);
! 1668:
! 1669: return TCL_OK;
! 1670: }
! 1671:
! 1672: /*
! 1673: ** sqlite3_blob_read CHANNEL OFFSET N
! 1674: **
! 1675: ** This command is used to test the sqlite3_blob_read() in ways that
! 1676: ** the Tcl channel interface does not. The first argument should
! 1677: ** be the name of a valid channel created by the [incrblob] method
! 1678: ** of a database handle. This function calls sqlite3_blob_read()
! 1679: ** to read N bytes from offset OFFSET from the underlying SQLite
! 1680: ** blob handle.
! 1681: **
! 1682: ** On success, a byte-array object containing the read data is
! 1683: ** returned. On failure, the interpreter result is set to the
! 1684: ** text representation of the returned error code (i.e. "SQLITE_NOMEM")
! 1685: ** and a Tcl exception is thrown.
! 1686: */
! 1687: static int test_blob_read(
! 1688: ClientData clientData, /* Not used */
! 1689: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1690: int objc, /* Number of arguments */
! 1691: Tcl_Obj *CONST objv[] /* Command arguments */
! 1692: ){
! 1693: sqlite3_blob *pBlob;
! 1694: int nByte;
! 1695: int iOffset;
! 1696: unsigned char *zBuf = 0;
! 1697: int rc;
! 1698:
! 1699: if( objc!=4 ){
! 1700: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET N");
! 1701: return TCL_ERROR;
! 1702: }
! 1703:
! 1704: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
! 1705: if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset)
! 1706: || TCL_OK!=Tcl_GetIntFromObj(interp, objv[3], &nByte)
! 1707: ){
! 1708: return TCL_ERROR;
! 1709: }
! 1710:
! 1711: if( nByte>0 ){
! 1712: zBuf = (unsigned char *)Tcl_Alloc(nByte);
! 1713: }
! 1714: rc = sqlite3_blob_read(pBlob, zBuf, nByte, iOffset);
! 1715: if( rc==SQLITE_OK ){
! 1716: Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zBuf, nByte));
! 1717: }else{
! 1718: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
! 1719: }
! 1720: Tcl_Free((char *)zBuf);
! 1721:
! 1722: return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
! 1723: }
! 1724:
! 1725: /*
! 1726: ** sqlite3_blob_write CHANNEL OFFSET DATA ?NDATA?
! 1727: **
! 1728: ** This command is used to test the sqlite3_blob_write() in ways that
! 1729: ** the Tcl channel interface does not. The first argument should
! 1730: ** be the name of a valid channel created by the [incrblob] method
! 1731: ** of a database handle. This function calls sqlite3_blob_write()
! 1732: ** to write the DATA byte-array to the underlying SQLite blob handle.
! 1733: ** at offset OFFSET.
! 1734: **
! 1735: ** On success, an empty string is returned. On failure, the interpreter
! 1736: ** result is set to the text representation of the returned error code
! 1737: ** (i.e. "SQLITE_NOMEM") and a Tcl exception is thrown.
! 1738: */
! 1739: static int test_blob_write(
! 1740: ClientData clientData, /* Not used */
! 1741: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1742: int objc, /* Number of arguments */
! 1743: Tcl_Obj *CONST objv[] /* Command arguments */
! 1744: ){
! 1745: sqlite3_blob *pBlob;
! 1746: int iOffset;
! 1747: int rc;
! 1748:
! 1749: unsigned char *zBuf;
! 1750: int nBuf;
! 1751:
! 1752: if( objc!=4 && objc!=5 ){
! 1753: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL OFFSET DATA ?NDATA?");
! 1754: return TCL_ERROR;
! 1755: }
! 1756:
! 1757: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
! 1758: if( TCL_OK!=Tcl_GetIntFromObj(interp, objv[2], &iOffset) ){
! 1759: return TCL_ERROR;
! 1760: }
! 1761:
! 1762: zBuf = Tcl_GetByteArrayFromObj(objv[3], &nBuf);
! 1763: if( objc==5 && Tcl_GetIntFromObj(interp, objv[4], &nBuf) ){
! 1764: return TCL_ERROR;
! 1765: }
! 1766: rc = sqlite3_blob_write(pBlob, zBuf, nBuf, iOffset);
! 1767: if( rc!=SQLITE_OK ){
! 1768: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
! 1769: }
! 1770:
! 1771: return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
! 1772: }
! 1773:
! 1774: static int test_blob_reopen(
! 1775: ClientData clientData, /* Not used */
! 1776: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1777: int objc, /* Number of arguments */
! 1778: Tcl_Obj *CONST objv[] /* Command arguments */
! 1779: ){
! 1780: Tcl_WideInt iRowid;
! 1781: sqlite3_blob *pBlob;
! 1782: int rc;
! 1783:
! 1784: if( objc!=3 ){
! 1785: Tcl_WrongNumArgs(interp, 1, objv, "CHANNEL ROWID");
! 1786: return TCL_ERROR;
! 1787: }
! 1788:
! 1789: if( blobHandleFromObj(interp, objv[1], &pBlob) ) return TCL_ERROR;
! 1790: if( Tcl_GetWideIntFromObj(interp, objv[2], &iRowid) ) return TCL_ERROR;
! 1791:
! 1792: rc = sqlite3_blob_reopen(pBlob, iRowid);
! 1793: if( rc!=SQLITE_OK ){
! 1794: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_VOLATILE);
! 1795: }
! 1796:
! 1797: return (rc==SQLITE_OK ? TCL_OK : TCL_ERROR);
! 1798: }
! 1799:
! 1800: #endif
! 1801:
! 1802: /*
! 1803: ** Usage: sqlite3_create_collation_v2 DB-HANDLE NAME CMP-PROC DEL-PROC
! 1804: **
! 1805: ** This Tcl proc is used for testing the experimental
! 1806: ** sqlite3_create_collation_v2() interface.
! 1807: */
! 1808: struct TestCollationX {
! 1809: Tcl_Interp *interp;
! 1810: Tcl_Obj *pCmp;
! 1811: Tcl_Obj *pDel;
! 1812: };
! 1813: typedef struct TestCollationX TestCollationX;
! 1814: static void testCreateCollationDel(void *pCtx){
! 1815: TestCollationX *p = (TestCollationX *)pCtx;
! 1816:
! 1817: int rc = Tcl_EvalObjEx(p->interp, p->pDel, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL);
! 1818: if( rc!=TCL_OK ){
! 1819: Tcl_BackgroundError(p->interp);
! 1820: }
! 1821:
! 1822: Tcl_DecrRefCount(p->pCmp);
! 1823: Tcl_DecrRefCount(p->pDel);
! 1824: sqlite3_free((void *)p);
! 1825: }
! 1826: static int testCreateCollationCmp(
! 1827: void *pCtx,
! 1828: int nLeft,
! 1829: const void *zLeft,
! 1830: int nRight,
! 1831: const void *zRight
! 1832: ){
! 1833: TestCollationX *p = (TestCollationX *)pCtx;
! 1834: Tcl_Obj *pScript = Tcl_DuplicateObj(p->pCmp);
! 1835: int iRes = 0;
! 1836:
! 1837: Tcl_IncrRefCount(pScript);
! 1838: Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zLeft, nLeft));
! 1839: Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj((char *)zRight,nRight));
! 1840:
! 1841: if( TCL_OK!=Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL)
! 1842: || TCL_OK!=Tcl_GetIntFromObj(p->interp, Tcl_GetObjResult(p->interp), &iRes)
! 1843: ){
! 1844: Tcl_BackgroundError(p->interp);
! 1845: }
! 1846: Tcl_DecrRefCount(pScript);
! 1847:
! 1848: return iRes;
! 1849: }
! 1850: static int test_create_collation_v2(
! 1851: ClientData clientData, /* Not used */
! 1852: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 1853: int objc, /* Number of arguments */
! 1854: Tcl_Obj *CONST objv[] /* Command arguments */
! 1855: ){
! 1856: TestCollationX *p;
! 1857: sqlite3 *db;
! 1858: int rc;
! 1859:
! 1860: if( objc!=5 ){
! 1861: Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE NAME CMP-PROC DEL-PROC");
! 1862: return TCL_ERROR;
! 1863: }
! 1864: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 1865:
! 1866: p = (TestCollationX *)sqlite3_malloc(sizeof(TestCollationX));
! 1867: p->pCmp = objv[3];
! 1868: p->pDel = objv[4];
! 1869: p->interp = interp;
! 1870: Tcl_IncrRefCount(p->pCmp);
! 1871: Tcl_IncrRefCount(p->pDel);
! 1872:
! 1873: rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), 16,
! 1874: (void *)p, testCreateCollationCmp, testCreateCollationDel
! 1875: );
! 1876: if( rc!=SQLITE_MISUSE ){
! 1877: Tcl_AppendResult(interp, "sqlite3_create_collate_v2() failed to detect "
! 1878: "an invalid encoding", (char*)0);
! 1879: return TCL_ERROR;
! 1880: }
! 1881: rc = sqlite3_create_collation_v2(db, Tcl_GetString(objv[2]), SQLITE_UTF8,
! 1882: (void *)p, testCreateCollationCmp, testCreateCollationDel
! 1883: );
! 1884: return TCL_OK;
! 1885: }
! 1886:
! 1887: /*
! 1888: ** USAGE: sqlite3_create_function_v2 DB NAME NARG ENC ?SWITCHES?
! 1889: **
! 1890: ** Available switches are:
! 1891: **
! 1892: ** -func SCRIPT
! 1893: ** -step SCRIPT
! 1894: ** -final SCRIPT
! 1895: ** -destroy SCRIPT
! 1896: */
! 1897: typedef struct CreateFunctionV2 CreateFunctionV2;
! 1898: struct CreateFunctionV2 {
! 1899: Tcl_Interp *interp;
! 1900: Tcl_Obj *pFunc; /* Script for function invocation */
! 1901: Tcl_Obj *pStep; /* Script for agg. step invocation */
! 1902: Tcl_Obj *pFinal; /* Script for agg. finalization invocation */
! 1903: Tcl_Obj *pDestroy; /* Destructor script */
! 1904: };
! 1905: static void cf2Func(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
! 1906: }
! 1907: static void cf2Step(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
! 1908: }
! 1909: static void cf2Final(sqlite3_context *ctx){
! 1910: }
! 1911: static void cf2Destroy(void *pUser){
! 1912: CreateFunctionV2 *p = (CreateFunctionV2 *)pUser;
! 1913:
! 1914: if( p->interp && p->pDestroy ){
! 1915: int rc = Tcl_EvalObjEx(p->interp, p->pDestroy, 0);
! 1916: if( rc!=TCL_OK ) Tcl_BackgroundError(p->interp);
! 1917: }
! 1918:
! 1919: if( p->pFunc ) Tcl_DecrRefCount(p->pFunc);
! 1920: if( p->pStep ) Tcl_DecrRefCount(p->pStep);
! 1921: if( p->pFinal ) Tcl_DecrRefCount(p->pFinal);
! 1922: if( p->pDestroy ) Tcl_DecrRefCount(p->pDestroy);
! 1923: sqlite3_free(p);
! 1924: }
! 1925: static int test_create_function_v2(
! 1926: ClientData clientData, /* Not used */
! 1927: Tcl_Interp *interp, /* The invoking TCL interpreter */
! 1928: int objc, /* Number of arguments */
! 1929: Tcl_Obj *CONST objv[] /* Command arguments */
! 1930: ){
! 1931: sqlite3 *db;
! 1932: const char *zFunc;
! 1933: int nArg;
! 1934: int enc;
! 1935: CreateFunctionV2 *p;
! 1936: int i;
! 1937: int rc;
! 1938:
! 1939: struct EncTable {
! 1940: const char *zEnc;
! 1941: int enc;
! 1942: } aEnc[] = {
! 1943: {"utf8", SQLITE_UTF8 },
! 1944: {"utf16", SQLITE_UTF16 },
! 1945: {"utf16le", SQLITE_UTF16LE },
! 1946: {"utf16be", SQLITE_UTF16BE },
! 1947: {"any", SQLITE_ANY },
! 1948: {"0", 0 }
! 1949: };
! 1950:
! 1951: if( objc<5 || (objc%2)==0 ){
! 1952: Tcl_WrongNumArgs(interp, 1, objv, "DB NAME NARG ENC SWITCHES...");
! 1953: return TCL_ERROR;
! 1954: }
! 1955:
! 1956: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 1957: zFunc = Tcl_GetString(objv[2]);
! 1958: if( Tcl_GetIntFromObj(interp, objv[3], &nArg) ) return TCL_ERROR;
! 1959: if( Tcl_GetIndexFromObjStruct(interp, objv[4], aEnc, sizeof(aEnc[0]),
! 1960: "encoding", 0, &enc)
! 1961: ){
! 1962: return TCL_ERROR;
! 1963: }
! 1964: enc = aEnc[enc].enc;
! 1965:
! 1966: p = sqlite3_malloc(sizeof(CreateFunctionV2));
! 1967: assert( p );
! 1968: memset(p, 0, sizeof(CreateFunctionV2));
! 1969: p->interp = interp;
! 1970:
! 1971: for(i=5; i<objc; i+=2){
! 1972: int iSwitch;
! 1973: const char *azSwitch[] = {"-func", "-step", "-final", "-destroy", 0};
! 1974: if( Tcl_GetIndexFromObj(interp, objv[i], azSwitch, "switch", 0, &iSwitch) ){
! 1975: sqlite3_free(p);
! 1976: return TCL_ERROR;
! 1977: }
! 1978:
! 1979: switch( iSwitch ){
! 1980: case 0: p->pFunc = objv[i+1]; break;
! 1981: case 1: p->pStep = objv[i+1]; break;
! 1982: case 2: p->pFinal = objv[i+1]; break;
! 1983: case 3: p->pDestroy = objv[i+1]; break;
! 1984: }
! 1985: }
! 1986: if( p->pFunc ) p->pFunc = Tcl_DuplicateObj(p->pFunc);
! 1987: if( p->pStep ) p->pStep = Tcl_DuplicateObj(p->pStep);
! 1988: if( p->pFinal ) p->pFinal = Tcl_DuplicateObj(p->pFinal);
! 1989: if( p->pDestroy ) p->pDestroy = Tcl_DuplicateObj(p->pDestroy);
! 1990:
! 1991: if( p->pFunc ) Tcl_IncrRefCount(p->pFunc);
! 1992: if( p->pStep ) Tcl_IncrRefCount(p->pStep);
! 1993: if( p->pFinal ) Tcl_IncrRefCount(p->pFinal);
! 1994: if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy);
! 1995:
! 1996: rc = sqlite3_create_function_v2(db, zFunc, nArg, enc, (void *)p,
! 1997: (p->pFunc ? cf2Func : 0),
! 1998: (p->pStep ? cf2Step : 0),
! 1999: (p->pFinal ? cf2Final : 0),
! 2000: cf2Destroy
! 2001: );
! 2002: if( rc!=SQLITE_OK ){
! 2003: Tcl_ResetResult(interp);
! 2004: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
! 2005: return TCL_ERROR;
! 2006: }
! 2007: return TCL_OK;
! 2008: }
! 2009:
! 2010: /*
! 2011: ** Usage: sqlite3_load_extension DB-HANDLE FILE ?PROC?
! 2012: */
! 2013: static int test_load_extension(
! 2014: ClientData clientData, /* Not used */
! 2015: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 2016: int objc, /* Number of arguments */
! 2017: Tcl_Obj *CONST objv[] /* Command arguments */
! 2018: ){
! 2019: Tcl_CmdInfo cmdInfo;
! 2020: sqlite3 *db;
! 2021: int rc;
! 2022: char *zDb;
! 2023: char *zFile;
! 2024: char *zProc = 0;
! 2025: char *zErr = 0;
! 2026:
! 2027: if( objc!=4 && objc!=3 ){
! 2028: Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE FILE ?PROC?");
! 2029: return TCL_ERROR;
! 2030: }
! 2031: zDb = Tcl_GetString(objv[1]);
! 2032: zFile = Tcl_GetString(objv[2]);
! 2033: if( objc==4 ){
! 2034: zProc = Tcl_GetString(objv[3]);
! 2035: }
! 2036:
! 2037: /* Extract the C database handle from the Tcl command name */
! 2038: if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
! 2039: Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
! 2040: return TCL_ERROR;
! 2041: }
! 2042: db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
! 2043: assert(db);
! 2044:
! 2045: /* Call the underlying C function. If an error occurs, set rc to
! 2046: ** TCL_ERROR and load any error string into the interpreter. If no
! 2047: ** error occurs, set rc to TCL_OK.
! 2048: */
! 2049: #ifdef SQLITE_OMIT_LOAD_EXTENSION
! 2050: rc = SQLITE_ERROR;
! 2051: zErr = sqlite3_mprintf("this build omits sqlite3_load_extension()");
! 2052: #else
! 2053: rc = sqlite3_load_extension(db, zFile, zProc, &zErr);
! 2054: #endif
! 2055: if( rc!=SQLITE_OK ){
! 2056: Tcl_SetResult(interp, zErr ? zErr : "", TCL_VOLATILE);
! 2057: rc = TCL_ERROR;
! 2058: }else{
! 2059: rc = TCL_OK;
! 2060: }
! 2061: sqlite3_free(zErr);
! 2062:
! 2063: return rc;
! 2064: }
! 2065:
! 2066: /*
! 2067: ** Usage: sqlite3_enable_load_extension DB-HANDLE ONOFF
! 2068: */
! 2069: static int test_enable_load(
! 2070: ClientData clientData, /* Not used */
! 2071: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 2072: int objc, /* Number of arguments */
! 2073: Tcl_Obj *CONST objv[] /* Command arguments */
! 2074: ){
! 2075: Tcl_CmdInfo cmdInfo;
! 2076: sqlite3 *db;
! 2077: char *zDb;
! 2078: int onoff;
! 2079:
! 2080: if( objc!=3 ){
! 2081: Tcl_WrongNumArgs(interp, 1, objv, "DB-HANDLE ONOFF");
! 2082: return TCL_ERROR;
! 2083: }
! 2084: zDb = Tcl_GetString(objv[1]);
! 2085:
! 2086: /* Extract the C database handle from the Tcl command name */
! 2087: if( !Tcl_GetCommandInfo(interp, zDb, &cmdInfo) ){
! 2088: Tcl_AppendResult(interp, "command not found: ", zDb, (char*)0);
! 2089: return TCL_ERROR;
! 2090: }
! 2091: db = ((struct SqliteDb*)cmdInfo.objClientData)->db;
! 2092: assert(db);
! 2093:
! 2094: /* Get the onoff parameter */
! 2095: if( Tcl_GetBooleanFromObj(interp, objv[2], &onoff) ){
! 2096: return TCL_ERROR;
! 2097: }
! 2098:
! 2099: #ifdef SQLITE_OMIT_LOAD_EXTENSION
! 2100: Tcl_AppendResult(interp, "this build omits sqlite3_load_extension()");
! 2101: return TCL_ERROR;
! 2102: #else
! 2103: sqlite3_enable_load_extension(db, onoff);
! 2104: return TCL_OK;
! 2105: #endif
! 2106: }
! 2107:
! 2108: /*
! 2109: ** Usage: sqlite_abort
! 2110: **
! 2111: ** Shutdown the process immediately. This is not a clean shutdown.
! 2112: ** This command is used to test the recoverability of a database in
! 2113: ** the event of a program crash.
! 2114: */
! 2115: static int sqlite_abort(
! 2116: void *NotUsed,
! 2117: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 2118: int argc, /* Number of arguments */
! 2119: char **argv /* Text of each argument */
! 2120: ){
! 2121: #if defined(_MSC_VER)
! 2122: /* We do this, otherwise the test will halt with a popup message
! 2123: * that we have to click away before the test will continue.
! 2124: */
! 2125: _set_abort_behavior( 0, _CALL_REPORTFAULT );
! 2126: #endif
! 2127: exit(255);
! 2128: assert( interp==0 ); /* This will always fail */
! 2129: return TCL_OK;
! 2130: }
! 2131:
! 2132: /*
! 2133: ** The following routine is a user-defined SQL function whose purpose
! 2134: ** is to test the sqlite_set_result() API.
! 2135: */
! 2136: static void testFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
! 2137: while( argc>=2 ){
! 2138: const char *zArg0 = (char*)sqlite3_value_text(argv[0]);
! 2139: if( zArg0 ){
! 2140: if( 0==sqlite3StrICmp(zArg0, "int") ){
! 2141: sqlite3_result_int(context, sqlite3_value_int(argv[1]));
! 2142: }else if( sqlite3StrICmp(zArg0,"int64")==0 ){
! 2143: sqlite3_result_int64(context, sqlite3_value_int64(argv[1]));
! 2144: }else if( sqlite3StrICmp(zArg0,"string")==0 ){
! 2145: sqlite3_result_text(context, (char*)sqlite3_value_text(argv[1]), -1,
! 2146: SQLITE_TRANSIENT);
! 2147: }else if( sqlite3StrICmp(zArg0,"double")==0 ){
! 2148: sqlite3_result_double(context, sqlite3_value_double(argv[1]));
! 2149: }else if( sqlite3StrICmp(zArg0,"null")==0 ){
! 2150: sqlite3_result_null(context);
! 2151: }else if( sqlite3StrICmp(zArg0,"value")==0 ){
! 2152: sqlite3_result_value(context, argv[sqlite3_value_int(argv[1])]);
! 2153: }else{
! 2154: goto error_out;
! 2155: }
! 2156: }else{
! 2157: goto error_out;
! 2158: }
! 2159: argc -= 2;
! 2160: argv += 2;
! 2161: }
! 2162: return;
! 2163:
! 2164: error_out:
! 2165: sqlite3_result_error(context,"first argument should be one of: "
! 2166: "int int64 string double null value", -1);
! 2167: }
! 2168:
! 2169: /*
! 2170: ** Usage: sqlite_register_test_function DB NAME
! 2171: **
! 2172: ** Register the test SQL function on the database DB under the name NAME.
! 2173: */
! 2174: static int test_register_func(
! 2175: void *NotUsed,
! 2176: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 2177: int argc, /* Number of arguments */
! 2178: char **argv /* Text of each argument */
! 2179: ){
! 2180: sqlite3 *db;
! 2181: int rc;
! 2182: if( argc!=3 ){
! 2183: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 2184: " DB FUNCTION-NAME", 0);
! 2185: return TCL_ERROR;
! 2186: }
! 2187: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 2188: rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0,
! 2189: testFunc, 0, 0);
! 2190: if( rc!=0 ){
! 2191: Tcl_AppendResult(interp, sqlite3ErrStr(rc), 0);
! 2192: return TCL_ERROR;
! 2193: }
! 2194: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 2195: return TCL_OK;
! 2196: }
! 2197:
! 2198: /*
! 2199: ** Usage: sqlite3_finalize STMT
! 2200: **
! 2201: ** Finalize a statement handle.
! 2202: */
! 2203: static int test_finalize(
! 2204: void * clientData,
! 2205: Tcl_Interp *interp,
! 2206: int objc,
! 2207: Tcl_Obj *CONST objv[]
! 2208: ){
! 2209: sqlite3_stmt *pStmt;
! 2210: int rc;
! 2211: sqlite3 *db = 0;
! 2212:
! 2213: if( objc!=2 ){
! 2214: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2215: Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
! 2216: return TCL_ERROR;
! 2217: }
! 2218:
! 2219: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 2220:
! 2221: if( pStmt ){
! 2222: db = StmtToDb(pStmt);
! 2223: }
! 2224: rc = sqlite3_finalize(pStmt);
! 2225: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
! 2226: if( db && sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 2227: return TCL_OK;
! 2228: }
! 2229:
! 2230: /*
! 2231: ** Usage: sqlite3_stmt_status STMT CODE RESETFLAG
! 2232: **
! 2233: ** Get the value of a status counter from a statement.
! 2234: */
! 2235: static int test_stmt_status(
! 2236: void * clientData,
! 2237: Tcl_Interp *interp,
! 2238: int objc,
! 2239: Tcl_Obj *CONST objv[]
! 2240: ){
! 2241: int iValue;
! 2242: int i, op, resetFlag;
! 2243: const char *zOpName;
! 2244: sqlite3_stmt *pStmt;
! 2245:
! 2246: static const struct {
! 2247: const char *zName;
! 2248: int op;
! 2249: } aOp[] = {
! 2250: { "SQLITE_STMTSTATUS_FULLSCAN_STEP", SQLITE_STMTSTATUS_FULLSCAN_STEP },
! 2251: { "SQLITE_STMTSTATUS_SORT", SQLITE_STMTSTATUS_SORT },
! 2252: { "SQLITE_STMTSTATUS_AUTOINDEX", SQLITE_STMTSTATUS_AUTOINDEX },
! 2253: };
! 2254: if( objc!=4 ){
! 2255: Tcl_WrongNumArgs(interp, 1, objv, "STMT PARAMETER RESETFLAG");
! 2256: return TCL_ERROR;
! 2257: }
! 2258: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 2259: zOpName = Tcl_GetString(objv[2]);
! 2260: for(i=0; i<ArraySize(aOp); i++){
! 2261: if( strcmp(aOp[i].zName, zOpName)==0 ){
! 2262: op = aOp[i].op;
! 2263: break;
! 2264: }
! 2265: }
! 2266: if( i>=ArraySize(aOp) ){
! 2267: if( Tcl_GetIntFromObj(interp, objv[2], &op) ) return TCL_ERROR;
! 2268: }
! 2269: if( Tcl_GetBooleanFromObj(interp, objv[3], &resetFlag) ) return TCL_ERROR;
! 2270: iValue = sqlite3_stmt_status(pStmt, op, resetFlag);
! 2271: Tcl_SetObjResult(interp, Tcl_NewIntObj(iValue));
! 2272: return TCL_OK;
! 2273: }
! 2274:
! 2275: /*
! 2276: ** Usage: sqlite3_next_stmt DB STMT
! 2277: **
! 2278: ** Return the next statment in sequence after STMT.
! 2279: */
! 2280: static int test_next_stmt(
! 2281: void * clientData,
! 2282: Tcl_Interp *interp,
! 2283: int objc,
! 2284: Tcl_Obj *CONST objv[]
! 2285: ){
! 2286: sqlite3_stmt *pStmt;
! 2287: sqlite3 *db = 0;
! 2288: char zBuf[50];
! 2289:
! 2290: if( objc!=3 ){
! 2291: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2292: Tcl_GetStringFromObj(objv[0], 0), " DB STMT", 0);
! 2293: return TCL_ERROR;
! 2294: }
! 2295:
! 2296: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 2297: if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt) ) return TCL_ERROR;
! 2298: pStmt = sqlite3_next_stmt(db, pStmt);
! 2299: if( pStmt ){
! 2300: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
! 2301: Tcl_AppendResult(interp, zBuf, 0);
! 2302: }
! 2303: return TCL_OK;
! 2304: }
! 2305:
! 2306: /*
! 2307: ** Usage: sqlite3_stmt_readonly STMT
! 2308: **
! 2309: ** Return true if STMT is a NULL pointer or a pointer to a statement
! 2310: ** that is guaranteed to leave the database unmodified.
! 2311: */
! 2312: static int test_stmt_readonly(
! 2313: void * clientData,
! 2314: Tcl_Interp *interp,
! 2315: int objc,
! 2316: Tcl_Obj *CONST objv[]
! 2317: ){
! 2318: sqlite3_stmt *pStmt;
! 2319: int rc;
! 2320:
! 2321: if( objc!=2 ){
! 2322: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2323: Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
! 2324: return TCL_ERROR;
! 2325: }
! 2326:
! 2327: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 2328: rc = sqlite3_stmt_readonly(pStmt);
! 2329: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
! 2330: return TCL_OK;
! 2331: }
! 2332:
! 2333: /*
! 2334: ** Usage: sqlite3_stmt_busy STMT
! 2335: **
! 2336: ** Return true if STMT is a non-NULL pointer to a statement
! 2337: ** that has been stepped but not to completion.
! 2338: */
! 2339: static int test_stmt_busy(
! 2340: void * clientData,
! 2341: Tcl_Interp *interp,
! 2342: int objc,
! 2343: Tcl_Obj *CONST objv[]
! 2344: ){
! 2345: sqlite3_stmt *pStmt;
! 2346: int rc;
! 2347:
! 2348: if( objc!=2 ){
! 2349: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2350: Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
! 2351: return TCL_ERROR;
! 2352: }
! 2353:
! 2354: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 2355: rc = sqlite3_stmt_busy(pStmt);
! 2356: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(rc));
! 2357: return TCL_OK;
! 2358: }
! 2359:
! 2360: /*
! 2361: ** Usage: uses_stmt_journal STMT
! 2362: **
! 2363: ** Return true if STMT uses a statement journal.
! 2364: */
! 2365: static int uses_stmt_journal(
! 2366: void * clientData,
! 2367: Tcl_Interp *interp,
! 2368: int objc,
! 2369: Tcl_Obj *CONST objv[]
! 2370: ){
! 2371: sqlite3_stmt *pStmt;
! 2372: int rc;
! 2373:
! 2374: if( objc!=2 ){
! 2375: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2376: Tcl_GetStringFromObj(objv[0], 0), " STMT", 0);
! 2377: return TCL_ERROR;
! 2378: }
! 2379:
! 2380: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 2381: rc = sqlite3_stmt_readonly(pStmt);
! 2382: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(((Vdbe *)pStmt)->usesStmtJournal));
! 2383: return TCL_OK;
! 2384: }
! 2385:
! 2386:
! 2387: /*
! 2388: ** Usage: sqlite3_reset STMT
! 2389: **
! 2390: ** Reset a statement handle.
! 2391: */
! 2392: static int test_reset(
! 2393: void * clientData,
! 2394: Tcl_Interp *interp,
! 2395: int objc,
! 2396: Tcl_Obj *CONST objv[]
! 2397: ){
! 2398: sqlite3_stmt *pStmt;
! 2399: int rc;
! 2400:
! 2401: if( objc!=2 ){
! 2402: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2403: Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
! 2404: return TCL_ERROR;
! 2405: }
! 2406:
! 2407: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 2408:
! 2409: rc = sqlite3_reset(pStmt);
! 2410: if( pStmt && sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ){
! 2411: return TCL_ERROR;
! 2412: }
! 2413: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
! 2414: /*
! 2415: if( rc ){
! 2416: return TCL_ERROR;
! 2417: }
! 2418: */
! 2419: return TCL_OK;
! 2420: }
! 2421:
! 2422: /*
! 2423: ** Usage: sqlite3_expired STMT
! 2424: **
! 2425: ** Return TRUE if a recompilation of the statement is recommended.
! 2426: */
! 2427: static int test_expired(
! 2428: void * clientData,
! 2429: Tcl_Interp *interp,
! 2430: int objc,
! 2431: Tcl_Obj *CONST objv[]
! 2432: ){
! 2433: #ifndef SQLITE_OMIT_DEPRECATED
! 2434: sqlite3_stmt *pStmt;
! 2435: if( objc!=2 ){
! 2436: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2437: Tcl_GetStringFromObj(objv[0], 0), " <STMT>", 0);
! 2438: return TCL_ERROR;
! 2439: }
! 2440: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 2441: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(sqlite3_expired(pStmt)));
! 2442: #endif
! 2443: return TCL_OK;
! 2444: }
! 2445:
! 2446: /*
! 2447: ** Usage: sqlite3_transfer_bindings FROMSTMT TOSTMT
! 2448: **
! 2449: ** Transfer all bindings from FROMSTMT over to TOSTMT
! 2450: */
! 2451: static int test_transfer_bind(
! 2452: void * clientData,
! 2453: Tcl_Interp *interp,
! 2454: int objc,
! 2455: Tcl_Obj *CONST objv[]
! 2456: ){
! 2457: #ifndef SQLITE_OMIT_DEPRECATED
! 2458: sqlite3_stmt *pStmt1, *pStmt2;
! 2459: if( objc!=3 ){
! 2460: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2461: Tcl_GetStringFromObj(objv[0], 0), " FROM-STMT TO-STMT", 0);
! 2462: return TCL_ERROR;
! 2463: }
! 2464: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt1)) return TCL_ERROR;
! 2465: if( getStmtPointer(interp, Tcl_GetString(objv[2]), &pStmt2)) return TCL_ERROR;
! 2466: Tcl_SetObjResult(interp,
! 2467: Tcl_NewIntObj(sqlite3_transfer_bindings(pStmt1,pStmt2)));
! 2468: #endif
! 2469: return TCL_OK;
! 2470: }
! 2471:
! 2472: /*
! 2473: ** Usage: sqlite3_changes DB
! 2474: **
! 2475: ** Return the number of changes made to the database by the last SQL
! 2476: ** execution.
! 2477: */
! 2478: static int test_changes(
! 2479: void * clientData,
! 2480: Tcl_Interp *interp,
! 2481: int objc,
! 2482: Tcl_Obj *CONST objv[]
! 2483: ){
! 2484: sqlite3 *db;
! 2485: if( objc!=2 ){
! 2486: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2487: Tcl_GetString(objv[0]), " DB", 0);
! 2488: return TCL_ERROR;
! 2489: }
! 2490: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 2491: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_changes(db)));
! 2492: return TCL_OK;
! 2493: }
! 2494:
! 2495: /*
! 2496: ** This is the "static_bind_value" that variables are bound to when
! 2497: ** the FLAG option of sqlite3_bind is "static"
! 2498: */
! 2499: static char *sqlite_static_bind_value = 0;
! 2500: static int sqlite_static_bind_nbyte = 0;
! 2501:
! 2502: /*
! 2503: ** Usage: sqlite3_bind VM IDX VALUE FLAGS
! 2504: **
! 2505: ** Sets the value of the IDX-th occurance of "?" in the original SQL
! 2506: ** string. VALUE is the new value. If FLAGS=="null" then VALUE is
! 2507: ** ignored and the value is set to NULL. If FLAGS=="static" then
! 2508: ** the value is set to the value of a static variable named
! 2509: ** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
! 2510: ** of the VALUE is made. If FLAGS=="blob10" then a VALUE is ignored
! 2511: ** an a 10-byte blob "abc\000xyz\000pq" is inserted.
! 2512: */
! 2513: static int test_bind(
! 2514: void *NotUsed,
! 2515: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 2516: int argc, /* Number of arguments */
! 2517: char **argv /* Text of each argument */
! 2518: ){
! 2519: sqlite3_stmt *pStmt;
! 2520: int rc;
! 2521: int idx;
! 2522: if( argc!=5 ){
! 2523: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 2524: " VM IDX VALUE (null|static|normal)\"", 0);
! 2525: return TCL_ERROR;
! 2526: }
! 2527: if( getStmtPointer(interp, argv[1], &pStmt) ) return TCL_ERROR;
! 2528: if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
! 2529: if( strcmp(argv[4],"null")==0 ){
! 2530: rc = sqlite3_bind_null(pStmt, idx);
! 2531: }else if( strcmp(argv[4],"static")==0 ){
! 2532: rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value, -1, 0);
! 2533: }else if( strcmp(argv[4],"static-nbytes")==0 ){
! 2534: rc = sqlite3_bind_text(pStmt, idx, sqlite_static_bind_value,
! 2535: sqlite_static_bind_nbyte, 0);
! 2536: }else if( strcmp(argv[4],"normal")==0 ){
! 2537: rc = sqlite3_bind_text(pStmt, idx, argv[3], -1, SQLITE_TRANSIENT);
! 2538: }else if( strcmp(argv[4],"blob10")==0 ){
! 2539: rc = sqlite3_bind_text(pStmt, idx, "abc\000xyz\000pq", 10, SQLITE_STATIC);
! 2540: }else{
! 2541: Tcl_AppendResult(interp, "4th argument should be "
! 2542: "\"null\" or \"static\" or \"normal\"", 0);
! 2543: return TCL_ERROR;
! 2544: }
! 2545: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
! 2546: if( rc ){
! 2547: char zBuf[50];
! 2548: sprintf(zBuf, "(%d) ", rc);
! 2549: Tcl_AppendResult(interp, zBuf, sqlite3ErrStr(rc), 0);
! 2550: return TCL_ERROR;
! 2551: }
! 2552: return TCL_OK;
! 2553: }
! 2554:
! 2555: #ifndef SQLITE_OMIT_UTF16
! 2556: /*
! 2557: ** Usage: add_test_collate <db ptr> <utf8> <utf16le> <utf16be>
! 2558: **
! 2559: ** This function is used to test that SQLite selects the correct collation
! 2560: ** sequence callback when multiple versions (for different text encodings)
! 2561: ** are available.
! 2562: **
! 2563: ** Calling this routine registers the collation sequence "test_collate"
! 2564: ** with database handle <db>. The second argument must be a list of three
! 2565: ** boolean values. If the first is true, then a version of test_collate is
! 2566: ** registered for UTF-8, if the second is true, a version is registered for
! 2567: ** UTF-16le, if the third is true, a UTF-16be version is available.
! 2568: ** Previous versions of test_collate are deleted.
! 2569: **
! 2570: ** The collation sequence test_collate is implemented by calling the
! 2571: ** following TCL script:
! 2572: **
! 2573: ** "test_collate <enc> <lhs> <rhs>"
! 2574: **
! 2575: ** The <lhs> and <rhs> are the two values being compared, encoded in UTF-8.
! 2576: ** The <enc> parameter is the encoding of the collation function that
! 2577: ** SQLite selected to call. The TCL test script implements the
! 2578: ** "test_collate" proc.
! 2579: **
! 2580: ** Note that this will only work with one intepreter at a time, as the
! 2581: ** interp pointer to use when evaluating the TCL script is stored in
! 2582: ** pTestCollateInterp.
! 2583: */
! 2584: static Tcl_Interp* pTestCollateInterp;
! 2585: static int test_collate_func(
! 2586: void *pCtx,
! 2587: int nA, const void *zA,
! 2588: int nB, const void *zB
! 2589: ){
! 2590: Tcl_Interp *i = pTestCollateInterp;
! 2591: int encin = SQLITE_PTR_TO_INT(pCtx);
! 2592: int res;
! 2593: int n;
! 2594:
! 2595: sqlite3_value *pVal;
! 2596: Tcl_Obj *pX;
! 2597:
! 2598: pX = Tcl_NewStringObj("test_collate", -1);
! 2599: Tcl_IncrRefCount(pX);
! 2600:
! 2601: switch( encin ){
! 2602: case SQLITE_UTF8:
! 2603: Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-8",-1));
! 2604: break;
! 2605: case SQLITE_UTF16LE:
! 2606: Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16LE",-1));
! 2607: break;
! 2608: case SQLITE_UTF16BE:
! 2609: Tcl_ListObjAppendElement(i,pX,Tcl_NewStringObj("UTF-16BE",-1));
! 2610: break;
! 2611: default:
! 2612: assert(0);
! 2613: }
! 2614:
! 2615: sqlite3BeginBenignMalloc();
! 2616: pVal = sqlite3ValueNew(0);
! 2617: if( pVal ){
! 2618: sqlite3ValueSetStr(pVal, nA, zA, encin, SQLITE_STATIC);
! 2619: n = sqlite3_value_bytes(pVal);
! 2620: Tcl_ListObjAppendElement(i,pX,
! 2621: Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
! 2622: sqlite3ValueSetStr(pVal, nB, zB, encin, SQLITE_STATIC);
! 2623: n = sqlite3_value_bytes(pVal);
! 2624: Tcl_ListObjAppendElement(i,pX,
! 2625: Tcl_NewStringObj((char*)sqlite3_value_text(pVal),n));
! 2626: sqlite3ValueFree(pVal);
! 2627: }
! 2628: sqlite3EndBenignMalloc();
! 2629:
! 2630: Tcl_EvalObjEx(i, pX, 0);
! 2631: Tcl_DecrRefCount(pX);
! 2632: Tcl_GetIntFromObj(i, Tcl_GetObjResult(i), &res);
! 2633: return res;
! 2634: }
! 2635: static int test_collate(
! 2636: void * clientData,
! 2637: Tcl_Interp *interp,
! 2638: int objc,
! 2639: Tcl_Obj *CONST objv[]
! 2640: ){
! 2641: sqlite3 *db;
! 2642: int val;
! 2643: sqlite3_value *pVal;
! 2644: int rc;
! 2645:
! 2646: if( objc!=5 ) goto bad_args;
! 2647: pTestCollateInterp = interp;
! 2648: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 2649:
! 2650: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
! 2651: rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF8,
! 2652: (void *)SQLITE_UTF8, val?test_collate_func:0);
! 2653: if( rc==SQLITE_OK ){
! 2654: const void *zUtf16;
! 2655: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
! 2656: rc = sqlite3_create_collation(db, "test_collate", SQLITE_UTF16LE,
! 2657: (void *)SQLITE_UTF16LE, val?test_collate_func:0);
! 2658: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
! 2659:
! 2660: #if 0
! 2661: if( sqlite3_iMallocFail>0 ){
! 2662: sqlite3_iMallocFail++;
! 2663: }
! 2664: #endif
! 2665: sqlite3_mutex_enter(db->mutex);
! 2666: pVal = sqlite3ValueNew(db);
! 2667: sqlite3ValueSetStr(pVal, -1, "test_collate", SQLITE_UTF8, SQLITE_STATIC);
! 2668: zUtf16 = sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
! 2669: if( db->mallocFailed ){
! 2670: rc = SQLITE_NOMEM;
! 2671: }else{
! 2672: rc = sqlite3_create_collation16(db, zUtf16, SQLITE_UTF16BE,
! 2673: (void *)SQLITE_UTF16BE, val?test_collate_func:0);
! 2674: }
! 2675: sqlite3ValueFree(pVal);
! 2676: sqlite3_mutex_leave(db->mutex);
! 2677: }
! 2678: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 2679:
! 2680: if( rc!=SQLITE_OK ){
! 2681: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
! 2682: return TCL_ERROR;
! 2683: }
! 2684: return TCL_OK;
! 2685:
! 2686: bad_args:
! 2687: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2688: Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
! 2689: return TCL_ERROR;
! 2690: }
! 2691:
! 2692: /*
! 2693: ** When the collation needed callback is invoked, record the name of
! 2694: ** the requested collating function here. The recorded name is linked
! 2695: ** to a TCL variable and used to make sure that the requested collation
! 2696: ** name is correct.
! 2697: */
! 2698: static char zNeededCollation[200];
! 2699: static char *pzNeededCollation = zNeededCollation;
! 2700:
! 2701:
! 2702: /*
! 2703: ** Called when a collating sequence is needed. Registered using
! 2704: ** sqlite3_collation_needed16().
! 2705: */
! 2706: static void test_collate_needed_cb(
! 2707: void *pCtx,
! 2708: sqlite3 *db,
! 2709: int eTextRep,
! 2710: const void *pName
! 2711: ){
! 2712: int enc = ENC(db);
! 2713: int i;
! 2714: char *z;
! 2715: for(z = (char*)pName, i=0; *z || z[1]; z++){
! 2716: if( *z ) zNeededCollation[i++] = *z;
! 2717: }
! 2718: zNeededCollation[i] = 0;
! 2719: sqlite3_create_collation(
! 2720: db, "test_collate", ENC(db), SQLITE_INT_TO_PTR(enc), test_collate_func);
! 2721: }
! 2722:
! 2723: /*
! 2724: ** Usage: add_test_collate_needed DB
! 2725: */
! 2726: static int test_collate_needed(
! 2727: void * clientData,
! 2728: Tcl_Interp *interp,
! 2729: int objc,
! 2730: Tcl_Obj *CONST objv[]
! 2731: ){
! 2732: sqlite3 *db;
! 2733: int rc;
! 2734:
! 2735: if( objc!=2 ) goto bad_args;
! 2736: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 2737: rc = sqlite3_collation_needed16(db, 0, test_collate_needed_cb);
! 2738: zNeededCollation[0] = 0;
! 2739: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 2740: return TCL_OK;
! 2741:
! 2742: bad_args:
! 2743: Tcl_WrongNumArgs(interp, 1, objv, "DB");
! 2744: return TCL_ERROR;
! 2745: }
! 2746:
! 2747: /*
! 2748: ** tclcmd: add_alignment_test_collations DB
! 2749: **
! 2750: ** Add two new collating sequences to the database DB
! 2751: **
! 2752: ** utf16_aligned
! 2753: ** utf16_unaligned
! 2754: **
! 2755: ** Both collating sequences use the same sort order as BINARY.
! 2756: ** The only difference is that the utf16_aligned collating
! 2757: ** sequence is declared with the SQLITE_UTF16_ALIGNED flag.
! 2758: ** Both collating functions increment the unaligned utf16 counter
! 2759: ** whenever they see a string that begins on an odd byte boundary.
! 2760: */
! 2761: static int unaligned_string_counter = 0;
! 2762: static int alignmentCollFunc(
! 2763: void *NotUsed,
! 2764: int nKey1, const void *pKey1,
! 2765: int nKey2, const void *pKey2
! 2766: ){
! 2767: int rc, n;
! 2768: n = nKey1<nKey2 ? nKey1 : nKey2;
! 2769: if( nKey1>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey1))) ) unaligned_string_counter++;
! 2770: if( nKey2>0 && 1==(1&(SQLITE_PTR_TO_INT(pKey2))) ) unaligned_string_counter++;
! 2771: rc = memcmp(pKey1, pKey2, n);
! 2772: if( rc==0 ){
! 2773: rc = nKey1 - nKey2;
! 2774: }
! 2775: return rc;
! 2776: }
! 2777: static int add_alignment_test_collations(
! 2778: void * clientData,
! 2779: Tcl_Interp *interp,
! 2780: int objc,
! 2781: Tcl_Obj *CONST objv[]
! 2782: ){
! 2783: sqlite3 *db;
! 2784: if( objc>=2 ){
! 2785: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 2786: sqlite3_create_collation(db, "utf16_unaligned", SQLITE_UTF16,
! 2787: 0, alignmentCollFunc);
! 2788: sqlite3_create_collation(db, "utf16_aligned", SQLITE_UTF16_ALIGNED,
! 2789: 0, alignmentCollFunc);
! 2790: }
! 2791: return SQLITE_OK;
! 2792: }
! 2793: #endif /* !defined(SQLITE_OMIT_UTF16) */
! 2794:
! 2795: /*
! 2796: ** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
! 2797: **
! 2798: ** This function is used to test that SQLite selects the correct user
! 2799: ** function callback when multiple versions (for different text encodings)
! 2800: ** are available.
! 2801: **
! 2802: ** Calling this routine registers up to three versions of the user function
! 2803: ** "test_function" with database handle <db>. If the second argument is
! 2804: ** true, then a version of test_function is registered for UTF-8, if the
! 2805: ** third is true, a version is registered for UTF-16le, if the fourth is
! 2806: ** true, a UTF-16be version is available. Previous versions of
! 2807: ** test_function are deleted.
! 2808: **
! 2809: ** The user function is implemented by calling the following TCL script:
! 2810: **
! 2811: ** "test_function <enc> <arg>"
! 2812: **
! 2813: ** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
! 2814: ** single argument passed to the SQL function. The value returned by
! 2815: ** the TCL script is used as the return value of the SQL function. It
! 2816: ** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
! 2817: ** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
! 2818: ** prefers UTF-16BE.
! 2819: */
! 2820: #ifndef SQLITE_OMIT_UTF16
! 2821: static void test_function_utf8(
! 2822: sqlite3_context *pCtx,
! 2823: int nArg,
! 2824: sqlite3_value **argv
! 2825: ){
! 2826: Tcl_Interp *interp;
! 2827: Tcl_Obj *pX;
! 2828: sqlite3_value *pVal;
! 2829: interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
! 2830: pX = Tcl_NewStringObj("test_function", -1);
! 2831: Tcl_IncrRefCount(pX);
! 2832: Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
! 2833: Tcl_ListObjAppendElement(interp, pX,
! 2834: Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
! 2835: Tcl_EvalObjEx(interp, pX, 0);
! 2836: Tcl_DecrRefCount(pX);
! 2837: sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
! 2838: pVal = sqlite3ValueNew(0);
! 2839: sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
! 2840: SQLITE_UTF8, SQLITE_STATIC);
! 2841: sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
! 2842: -1, SQLITE_TRANSIENT);
! 2843: sqlite3ValueFree(pVal);
! 2844: }
! 2845: static void test_function_utf16le(
! 2846: sqlite3_context *pCtx,
! 2847: int nArg,
! 2848: sqlite3_value **argv
! 2849: ){
! 2850: Tcl_Interp *interp;
! 2851: Tcl_Obj *pX;
! 2852: sqlite3_value *pVal;
! 2853: interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
! 2854: pX = Tcl_NewStringObj("test_function", -1);
! 2855: Tcl_IncrRefCount(pX);
! 2856: Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
! 2857: Tcl_ListObjAppendElement(interp, pX,
! 2858: Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
! 2859: Tcl_EvalObjEx(interp, pX, 0);
! 2860: Tcl_DecrRefCount(pX);
! 2861: pVal = sqlite3ValueNew(0);
! 2862: sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
! 2863: SQLITE_UTF8, SQLITE_STATIC);
! 2864: sqlite3_result_text(pCtx,(char*)sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
! 2865: sqlite3ValueFree(pVal);
! 2866: }
! 2867: static void test_function_utf16be(
! 2868: sqlite3_context *pCtx,
! 2869: int nArg,
! 2870: sqlite3_value **argv
! 2871: ){
! 2872: Tcl_Interp *interp;
! 2873: Tcl_Obj *pX;
! 2874: sqlite3_value *pVal;
! 2875: interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
! 2876: pX = Tcl_NewStringObj("test_function", -1);
! 2877: Tcl_IncrRefCount(pX);
! 2878: Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
! 2879: Tcl_ListObjAppendElement(interp, pX,
! 2880: Tcl_NewStringObj((char*)sqlite3_value_text(argv[0]), -1));
! 2881: Tcl_EvalObjEx(interp, pX, 0);
! 2882: Tcl_DecrRefCount(pX);
! 2883: pVal = sqlite3ValueNew(0);
! 2884: sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp),
! 2885: SQLITE_UTF8, SQLITE_STATIC);
! 2886: sqlite3_result_text16(pCtx, sqlite3_value_text16le(pVal),
! 2887: -1, SQLITE_TRANSIENT);
! 2888: sqlite3_result_text16be(pCtx, sqlite3_value_text16le(pVal),
! 2889: -1, SQLITE_TRANSIENT);
! 2890: sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
! 2891: -1, SQLITE_TRANSIENT);
! 2892: sqlite3ValueFree(pVal);
! 2893: }
! 2894: #endif /* SQLITE_OMIT_UTF16 */
! 2895: static int test_function(
! 2896: void * clientData,
! 2897: Tcl_Interp *interp,
! 2898: int objc,
! 2899: Tcl_Obj *CONST objv[]
! 2900: ){
! 2901: #ifndef SQLITE_OMIT_UTF16
! 2902: sqlite3 *db;
! 2903: int val;
! 2904:
! 2905: if( objc!=5 ) goto bad_args;
! 2906: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 2907:
! 2908: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
! 2909: if( val ){
! 2910: sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8,
! 2911: interp, test_function_utf8, 0, 0);
! 2912: }
! 2913: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
! 2914: if( val ){
! 2915: sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE,
! 2916: interp, test_function_utf16le, 0, 0);
! 2917: }
! 2918: if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
! 2919: if( val ){
! 2920: sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE,
! 2921: interp, test_function_utf16be, 0, 0);
! 2922: }
! 2923:
! 2924: return TCL_OK;
! 2925: bad_args:
! 2926: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 2927: Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
! 2928: #endif /* SQLITE_OMIT_UTF16 */
! 2929: return TCL_ERROR;
! 2930: }
! 2931:
! 2932: /*
! 2933: ** Usage: sqlite3_test_errstr <err code>
! 2934: **
! 2935: ** Test that the english language string equivalents for sqlite error codes
! 2936: ** are sane. The parameter is an integer representing an sqlite error code.
! 2937: ** The result is a list of two elements, the string representation of the
! 2938: ** error code and the english language explanation.
! 2939: */
! 2940: static int test_errstr(
! 2941: void * clientData,
! 2942: Tcl_Interp *interp,
! 2943: int objc,
! 2944: Tcl_Obj *CONST objv[]
! 2945: ){
! 2946: char *zCode;
! 2947: int i;
! 2948: if( objc!=1 ){
! 2949: Tcl_WrongNumArgs(interp, 1, objv, "<error code>");
! 2950: }
! 2951:
! 2952: zCode = Tcl_GetString(objv[1]);
! 2953: for(i=0; i<200; i++){
! 2954: if( 0==strcmp(t1ErrorName(i), zCode) ) break;
! 2955: }
! 2956: Tcl_SetResult(interp, (char *)sqlite3ErrStr(i), 0);
! 2957: return TCL_OK;
! 2958: }
! 2959:
! 2960: /*
! 2961: ** Usage: breakpoint
! 2962: **
! 2963: ** This routine exists for one purpose - to provide a place to put a
! 2964: ** breakpoint with GDB that can be triggered using TCL code. The use
! 2965: ** for this is when a particular test fails on (say) the 1485th iteration.
! 2966: ** In the TCL test script, we can add code like this:
! 2967: **
! 2968: ** if {$i==1485} breakpoint
! 2969: **
! 2970: ** Then run testfixture in the debugger and wait for the breakpoint to
! 2971: ** fire. Then additional breakpoints can be set to trace down the bug.
! 2972: */
! 2973: static int test_breakpoint(
! 2974: void *NotUsed,
! 2975: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 2976: int argc, /* Number of arguments */
! 2977: char **argv /* Text of each argument */
! 2978: ){
! 2979: return TCL_OK; /* Do nothing */
! 2980: }
! 2981:
! 2982: /*
! 2983: ** Usage: sqlite3_bind_zeroblob STMT IDX N
! 2984: **
! 2985: ** Test the sqlite3_bind_zeroblob interface. STMT is a prepared statement.
! 2986: ** IDX is the index of a wildcard in the prepared statement. This command
! 2987: ** binds a N-byte zero-filled BLOB to the wildcard.
! 2988: */
! 2989: static int test_bind_zeroblob(
! 2990: void * clientData,
! 2991: Tcl_Interp *interp,
! 2992: int objc,
! 2993: Tcl_Obj *CONST objv[]
! 2994: ){
! 2995: sqlite3_stmt *pStmt;
! 2996: int idx;
! 2997: int n;
! 2998: int rc;
! 2999:
! 3000: if( objc!=4 ){
! 3001: Tcl_WrongNumArgs(interp, 1, objv, "STMT IDX N");
! 3002: return TCL_ERROR;
! 3003: }
! 3004:
! 3005: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3006: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
! 3007: if( Tcl_GetIntFromObj(interp, objv[3], &n) ) return TCL_ERROR;
! 3008:
! 3009: rc = sqlite3_bind_zeroblob(pStmt, idx, n);
! 3010: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
! 3011: if( rc!=SQLITE_OK ){
! 3012: return TCL_ERROR;
! 3013: }
! 3014:
! 3015: return TCL_OK;
! 3016: }
! 3017:
! 3018: /*
! 3019: ** Usage: sqlite3_bind_int STMT N VALUE
! 3020: **
! 3021: ** Test the sqlite3_bind_int interface. STMT is a prepared statement.
! 3022: ** N is the index of a wildcard in the prepared statement. This command
! 3023: ** binds a 32-bit integer VALUE to that wildcard.
! 3024: */
! 3025: static int test_bind_int(
! 3026: void * clientData,
! 3027: Tcl_Interp *interp,
! 3028: int objc,
! 3029: Tcl_Obj *CONST objv[]
! 3030: ){
! 3031: sqlite3_stmt *pStmt;
! 3032: int idx;
! 3033: int value;
! 3034: int rc;
! 3035:
! 3036: if( objc!=4 ){
! 3037: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3038: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
! 3039: return TCL_ERROR;
! 3040: }
! 3041:
! 3042: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3043: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
! 3044: if( Tcl_GetIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
! 3045:
! 3046: rc = sqlite3_bind_int(pStmt, idx, value);
! 3047: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
! 3048: if( rc!=SQLITE_OK ){
! 3049: return TCL_ERROR;
! 3050: }
! 3051:
! 3052: return TCL_OK;
! 3053: }
! 3054:
! 3055:
! 3056: /*
! 3057: ** Usage: sqlite3_bind_int64 STMT N VALUE
! 3058: **
! 3059: ** Test the sqlite3_bind_int64 interface. STMT is a prepared statement.
! 3060: ** N is the index of a wildcard in the prepared statement. This command
! 3061: ** binds a 64-bit integer VALUE to that wildcard.
! 3062: */
! 3063: static int test_bind_int64(
! 3064: void * clientData,
! 3065: Tcl_Interp *interp,
! 3066: int objc,
! 3067: Tcl_Obj *CONST objv[]
! 3068: ){
! 3069: sqlite3_stmt *pStmt;
! 3070: int idx;
! 3071: i64 value;
! 3072: int rc;
! 3073:
! 3074: if( objc!=4 ){
! 3075: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3076: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
! 3077: return TCL_ERROR;
! 3078: }
! 3079:
! 3080: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3081: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
! 3082: if( Tcl_GetWideIntFromObj(interp, objv[3], &value) ) return TCL_ERROR;
! 3083:
! 3084: rc = sqlite3_bind_int64(pStmt, idx, value);
! 3085: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
! 3086: if( rc!=SQLITE_OK ){
! 3087: return TCL_ERROR;
! 3088: }
! 3089:
! 3090: return TCL_OK;
! 3091: }
! 3092:
! 3093:
! 3094: /*
! 3095: ** Usage: sqlite3_bind_double STMT N VALUE
! 3096: **
! 3097: ** Test the sqlite3_bind_double interface. STMT is a prepared statement.
! 3098: ** N is the index of a wildcard in the prepared statement. This command
! 3099: ** binds a 64-bit integer VALUE to that wildcard.
! 3100: */
! 3101: static int test_bind_double(
! 3102: void * clientData,
! 3103: Tcl_Interp *interp,
! 3104: int objc,
! 3105: Tcl_Obj *CONST objv[]
! 3106: ){
! 3107: sqlite3_stmt *pStmt;
! 3108: int idx;
! 3109: double value;
! 3110: int rc;
! 3111: const char *zVal;
! 3112: int i;
! 3113: static const struct {
! 3114: const char *zName; /* Name of the special floating point value */
! 3115: unsigned int iUpper; /* Upper 32 bits */
! 3116: unsigned int iLower; /* Lower 32 bits */
! 3117: } aSpecialFp[] = {
! 3118: { "NaN", 0x7fffffff, 0xffffffff },
! 3119: { "SNaN", 0x7ff7ffff, 0xffffffff },
! 3120: { "-NaN", 0xffffffff, 0xffffffff },
! 3121: { "-SNaN", 0xfff7ffff, 0xffffffff },
! 3122: { "+Inf", 0x7ff00000, 0x00000000 },
! 3123: { "-Inf", 0xfff00000, 0x00000000 },
! 3124: { "Epsilon", 0x00000000, 0x00000001 },
! 3125: { "-Epsilon", 0x80000000, 0x00000001 },
! 3126: { "NaN0", 0x7ff80000, 0x00000000 },
! 3127: { "-NaN0", 0xfff80000, 0x00000000 },
! 3128: };
! 3129:
! 3130: if( objc!=4 ){
! 3131: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3132: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE", 0);
! 3133: return TCL_ERROR;
! 3134: }
! 3135:
! 3136: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3137: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
! 3138:
! 3139: /* Intercept the string "NaN" and generate a NaN value for it.
! 3140: ** All other strings are passed through to Tcl_GetDoubleFromObj().
! 3141: ** Tcl_GetDoubleFromObj() should understand "NaN" but some versions
! 3142: ** contain a bug.
! 3143: */
! 3144: zVal = Tcl_GetString(objv[3]);
! 3145: for(i=0; i<sizeof(aSpecialFp)/sizeof(aSpecialFp[0]); i++){
! 3146: if( strcmp(aSpecialFp[i].zName, zVal)==0 ){
! 3147: sqlite3_uint64 x;
! 3148: x = aSpecialFp[i].iUpper;
! 3149: x <<= 32;
! 3150: x |= aSpecialFp[i].iLower;
! 3151: assert( sizeof(value)==8 );
! 3152: assert( sizeof(x)==8 );
! 3153: memcpy(&value, &x, 8);
! 3154: break;
! 3155: }
! 3156: }
! 3157: if( i>=sizeof(aSpecialFp)/sizeof(aSpecialFp[0]) &&
! 3158: Tcl_GetDoubleFromObj(interp, objv[3], &value) ){
! 3159: return TCL_ERROR;
! 3160: }
! 3161: rc = sqlite3_bind_double(pStmt, idx, value);
! 3162: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
! 3163: if( rc!=SQLITE_OK ){
! 3164: return TCL_ERROR;
! 3165: }
! 3166:
! 3167: return TCL_OK;
! 3168: }
! 3169:
! 3170: /*
! 3171: ** Usage: sqlite3_bind_null STMT N
! 3172: **
! 3173: ** Test the sqlite3_bind_null interface. STMT is a prepared statement.
! 3174: ** N is the index of a wildcard in the prepared statement. This command
! 3175: ** binds a NULL to the wildcard.
! 3176: */
! 3177: static int test_bind_null(
! 3178: void * clientData,
! 3179: Tcl_Interp *interp,
! 3180: int objc,
! 3181: Tcl_Obj *CONST objv[]
! 3182: ){
! 3183: sqlite3_stmt *pStmt;
! 3184: int idx;
! 3185: int rc;
! 3186:
! 3187: if( objc!=3 ){
! 3188: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3189: Tcl_GetStringFromObj(objv[0], 0), " STMT N", 0);
! 3190: return TCL_ERROR;
! 3191: }
! 3192:
! 3193: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3194: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
! 3195:
! 3196: rc = sqlite3_bind_null(pStmt, idx);
! 3197: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
! 3198: if( rc!=SQLITE_OK ){
! 3199: return TCL_ERROR;
! 3200: }
! 3201:
! 3202: return TCL_OK;
! 3203: }
! 3204:
! 3205: /*
! 3206: ** Usage: sqlite3_bind_text STMT N STRING BYTES
! 3207: **
! 3208: ** Test the sqlite3_bind_text interface. STMT is a prepared statement.
! 3209: ** N is the index of a wildcard in the prepared statement. This command
! 3210: ** binds a UTF-8 string STRING to the wildcard. The string is BYTES bytes
! 3211: ** long.
! 3212: */
! 3213: static int test_bind_text(
! 3214: void * clientData,
! 3215: Tcl_Interp *interp,
! 3216: int objc,
! 3217: Tcl_Obj *CONST objv[]
! 3218: ){
! 3219: sqlite3_stmt *pStmt;
! 3220: int idx;
! 3221: int bytes;
! 3222: char *value;
! 3223: int rc;
! 3224:
! 3225: if( objc!=5 ){
! 3226: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3227: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
! 3228: return TCL_ERROR;
! 3229: }
! 3230:
! 3231: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3232: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
! 3233: value = (char*)Tcl_GetByteArrayFromObj(objv[3], &bytes);
! 3234: if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
! 3235:
! 3236: rc = sqlite3_bind_text(pStmt, idx, value, bytes, SQLITE_TRANSIENT);
! 3237: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
! 3238: if( rc!=SQLITE_OK ){
! 3239: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
! 3240: return TCL_ERROR;
! 3241: }
! 3242:
! 3243: return TCL_OK;
! 3244: }
! 3245:
! 3246: /*
! 3247: ** Usage: sqlite3_bind_text16 ?-static? STMT N STRING BYTES
! 3248: **
! 3249: ** Test the sqlite3_bind_text16 interface. STMT is a prepared statement.
! 3250: ** N is the index of a wildcard in the prepared statement. This command
! 3251: ** binds a UTF-16 string STRING to the wildcard. The string is BYTES bytes
! 3252: ** long.
! 3253: */
! 3254: static int test_bind_text16(
! 3255: void * clientData,
! 3256: Tcl_Interp *interp,
! 3257: int objc,
! 3258: Tcl_Obj *CONST objv[]
! 3259: ){
! 3260: #ifndef SQLITE_OMIT_UTF16
! 3261: sqlite3_stmt *pStmt;
! 3262: int idx;
! 3263: int bytes;
! 3264: char *value;
! 3265: int rc;
! 3266:
! 3267: void (*xDel)() = (objc==6?SQLITE_STATIC:SQLITE_TRANSIENT);
! 3268: Tcl_Obj *oStmt = objv[objc-4];
! 3269: Tcl_Obj *oN = objv[objc-3];
! 3270: Tcl_Obj *oString = objv[objc-2];
! 3271: Tcl_Obj *oBytes = objv[objc-1];
! 3272:
! 3273: if( objc!=5 && objc!=6){
! 3274: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3275: Tcl_GetStringFromObj(objv[0], 0), " STMT N VALUE BYTES", 0);
! 3276: return TCL_ERROR;
! 3277: }
! 3278:
! 3279: if( getStmtPointer(interp, Tcl_GetString(oStmt), &pStmt) ) return TCL_ERROR;
! 3280: if( Tcl_GetIntFromObj(interp, oN, &idx) ) return TCL_ERROR;
! 3281: value = (char*)Tcl_GetByteArrayFromObj(oString, 0);
! 3282: if( Tcl_GetIntFromObj(interp, oBytes, &bytes) ) return TCL_ERROR;
! 3283:
! 3284: rc = sqlite3_bind_text16(pStmt, idx, (void *)value, bytes, xDel);
! 3285: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
! 3286: if( rc!=SQLITE_OK ){
! 3287: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
! 3288: return TCL_ERROR;
! 3289: }
! 3290:
! 3291: #endif /* SQLITE_OMIT_UTF16 */
! 3292: return TCL_OK;
! 3293: }
! 3294:
! 3295: /*
! 3296: ** Usage: sqlite3_bind_blob ?-static? STMT N DATA BYTES
! 3297: **
! 3298: ** Test the sqlite3_bind_blob interface. STMT is a prepared statement.
! 3299: ** N is the index of a wildcard in the prepared statement. This command
! 3300: ** binds a BLOB to the wildcard. The BLOB is BYTES bytes in size.
! 3301: */
! 3302: static int test_bind_blob(
! 3303: void * clientData,
! 3304: Tcl_Interp *interp,
! 3305: int objc,
! 3306: Tcl_Obj *CONST objv[]
! 3307: ){
! 3308: sqlite3_stmt *pStmt;
! 3309: int idx;
! 3310: int bytes;
! 3311: char *value;
! 3312: int rc;
! 3313: sqlite3_destructor_type xDestructor = SQLITE_TRANSIENT;
! 3314:
! 3315: if( objc!=5 && objc!=6 ){
! 3316: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3317: Tcl_GetStringFromObj(objv[0], 0), " STMT N DATA BYTES", 0);
! 3318: return TCL_ERROR;
! 3319: }
! 3320:
! 3321: if( objc==6 ){
! 3322: xDestructor = SQLITE_STATIC;
! 3323: objv++;
! 3324: }
! 3325:
! 3326: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3327: if( Tcl_GetIntFromObj(interp, objv[2], &idx) ) return TCL_ERROR;
! 3328: value = Tcl_GetString(objv[3]);
! 3329: if( Tcl_GetIntFromObj(interp, objv[4], &bytes) ) return TCL_ERROR;
! 3330:
! 3331: rc = sqlite3_bind_blob(pStmt, idx, value, bytes, xDestructor);
! 3332: if( sqlite3TestErrCode(interp, StmtToDb(pStmt), rc) ) return TCL_ERROR;
! 3333: if( rc!=SQLITE_OK ){
! 3334: return TCL_ERROR;
! 3335: }
! 3336:
! 3337: return TCL_OK;
! 3338: }
! 3339:
! 3340: /*
! 3341: ** Usage: sqlite3_bind_parameter_count STMT
! 3342: **
! 3343: ** Return the number of wildcards in the given statement.
! 3344: */
! 3345: static int test_bind_parameter_count(
! 3346: void * clientData,
! 3347: Tcl_Interp *interp,
! 3348: int objc,
! 3349: Tcl_Obj *CONST objv[]
! 3350: ){
! 3351: sqlite3_stmt *pStmt;
! 3352:
! 3353: if( objc!=2 ){
! 3354: Tcl_WrongNumArgs(interp, 1, objv, "STMT");
! 3355: return TCL_ERROR;
! 3356: }
! 3357: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3358: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_bind_parameter_count(pStmt)));
! 3359: return TCL_OK;
! 3360: }
! 3361:
! 3362: /*
! 3363: ** Usage: sqlite3_bind_parameter_name STMT N
! 3364: **
! 3365: ** Return the name of the Nth wildcard. The first wildcard is 1.
! 3366: ** An empty string is returned if N is out of range or if the wildcard
! 3367: ** is nameless.
! 3368: */
! 3369: static int test_bind_parameter_name(
! 3370: void * clientData,
! 3371: Tcl_Interp *interp,
! 3372: int objc,
! 3373: Tcl_Obj *CONST objv[]
! 3374: ){
! 3375: sqlite3_stmt *pStmt;
! 3376: int i;
! 3377:
! 3378: if( objc!=3 ){
! 3379: Tcl_WrongNumArgs(interp, 1, objv, "STMT N");
! 3380: return TCL_ERROR;
! 3381: }
! 3382: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3383: if( Tcl_GetIntFromObj(interp, objv[2], &i) ) return TCL_ERROR;
! 3384: Tcl_SetObjResult(interp,
! 3385: Tcl_NewStringObj(sqlite3_bind_parameter_name(pStmt,i),-1)
! 3386: );
! 3387: return TCL_OK;
! 3388: }
! 3389:
! 3390: /*
! 3391: ** Usage: sqlite3_bind_parameter_index STMT NAME
! 3392: **
! 3393: ** Return the index of the wildcard called NAME. Return 0 if there is
! 3394: ** no such wildcard.
! 3395: */
! 3396: static int test_bind_parameter_index(
! 3397: void * clientData,
! 3398: Tcl_Interp *interp,
! 3399: int objc,
! 3400: Tcl_Obj *CONST objv[]
! 3401: ){
! 3402: sqlite3_stmt *pStmt;
! 3403:
! 3404: if( objc!=3 ){
! 3405: Tcl_WrongNumArgs(interp, 1, objv, "STMT NAME");
! 3406: return TCL_ERROR;
! 3407: }
! 3408: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3409: Tcl_SetObjResult(interp,
! 3410: Tcl_NewIntObj(
! 3411: sqlite3_bind_parameter_index(pStmt,Tcl_GetString(objv[2]))
! 3412: )
! 3413: );
! 3414: return TCL_OK;
! 3415: }
! 3416:
! 3417: /*
! 3418: ** Usage: sqlite3_clear_bindings STMT
! 3419: **
! 3420: */
! 3421: static int test_clear_bindings(
! 3422: void * clientData,
! 3423: Tcl_Interp *interp,
! 3424: int objc,
! 3425: Tcl_Obj *CONST objv[]
! 3426: ){
! 3427: sqlite3_stmt *pStmt;
! 3428:
! 3429: if( objc!=2 ){
! 3430: Tcl_WrongNumArgs(interp, 1, objv, "STMT");
! 3431: return TCL_ERROR;
! 3432: }
! 3433: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 3434: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_clear_bindings(pStmt)));
! 3435: return TCL_OK;
! 3436: }
! 3437:
! 3438: /*
! 3439: ** Usage: sqlite3_sleep MILLISECONDS
! 3440: */
! 3441: static int test_sleep(
! 3442: void * clientData,
! 3443: Tcl_Interp *interp,
! 3444: int objc,
! 3445: Tcl_Obj *CONST objv[]
! 3446: ){
! 3447: int ms;
! 3448:
! 3449: if( objc!=2 ){
! 3450: Tcl_WrongNumArgs(interp, 1, objv, "MILLISECONDS");
! 3451: return TCL_ERROR;
! 3452: }
! 3453: if( Tcl_GetIntFromObj(interp, objv[1], &ms) ){
! 3454: return TCL_ERROR;
! 3455: }
! 3456: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_sleep(ms)));
! 3457: return TCL_OK;
! 3458: }
! 3459:
! 3460: /*
! 3461: ** Usage: sqlite3_extended_errcode DB
! 3462: **
! 3463: ** Return the string representation of the most recent sqlite3_* API
! 3464: ** error code. e.g. "SQLITE_ERROR".
! 3465: */
! 3466: static int test_ex_errcode(
! 3467: void * clientData,
! 3468: Tcl_Interp *interp,
! 3469: int objc,
! 3470: Tcl_Obj *CONST objv[]
! 3471: ){
! 3472: sqlite3 *db;
! 3473: int rc;
! 3474:
! 3475: if( objc!=2 ){
! 3476: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3477: Tcl_GetString(objv[0]), " DB", 0);
! 3478: return TCL_ERROR;
! 3479: }
! 3480: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 3481: rc = sqlite3_extended_errcode(db);
! 3482: Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
! 3483: return TCL_OK;
! 3484: }
! 3485:
! 3486:
! 3487: /*
! 3488: ** Usage: sqlite3_errcode DB
! 3489: **
! 3490: ** Return the string representation of the most recent sqlite3_* API
! 3491: ** error code. e.g. "SQLITE_ERROR".
! 3492: */
! 3493: static int test_errcode(
! 3494: void * clientData,
! 3495: Tcl_Interp *interp,
! 3496: int objc,
! 3497: Tcl_Obj *CONST objv[]
! 3498: ){
! 3499: sqlite3 *db;
! 3500: int rc;
! 3501:
! 3502: if( objc!=2 ){
! 3503: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3504: Tcl_GetString(objv[0]), " DB", 0);
! 3505: return TCL_ERROR;
! 3506: }
! 3507: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 3508: rc = sqlite3_errcode(db);
! 3509: Tcl_AppendResult(interp, (char *)t1ErrorName(rc), 0);
! 3510: return TCL_OK;
! 3511: }
! 3512:
! 3513: /*
! 3514: ** Usage: sqlite3_errmsg DB
! 3515: **
! 3516: ** Returns the UTF-8 representation of the error message string for the
! 3517: ** most recent sqlite3_* API call.
! 3518: */
! 3519: static int test_errmsg(
! 3520: void * clientData,
! 3521: Tcl_Interp *interp,
! 3522: int objc,
! 3523: Tcl_Obj *CONST objv[]
! 3524: ){
! 3525: sqlite3 *db;
! 3526: const char *zErr;
! 3527:
! 3528: if( objc!=2 ){
! 3529: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3530: Tcl_GetString(objv[0]), " DB", 0);
! 3531: return TCL_ERROR;
! 3532: }
! 3533: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 3534:
! 3535: zErr = sqlite3_errmsg(db);
! 3536: Tcl_SetObjResult(interp, Tcl_NewStringObj(zErr, -1));
! 3537: return TCL_OK;
! 3538: }
! 3539:
! 3540: /*
! 3541: ** Usage: test_errmsg16 DB
! 3542: **
! 3543: ** Returns the UTF-16 representation of the error message string for the
! 3544: ** most recent sqlite3_* API call. This is a byte array object at the TCL
! 3545: ** level, and it includes the 0x00 0x00 terminator bytes at the end of the
! 3546: ** UTF-16 string.
! 3547: */
! 3548: static int test_errmsg16(
! 3549: void * clientData,
! 3550: Tcl_Interp *interp,
! 3551: int objc,
! 3552: Tcl_Obj *CONST objv[]
! 3553: ){
! 3554: #ifndef SQLITE_OMIT_UTF16
! 3555: sqlite3 *db;
! 3556: const void *zErr;
! 3557: const char *z;
! 3558: int bytes = 0;
! 3559:
! 3560: if( objc!=2 ){
! 3561: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3562: Tcl_GetString(objv[0]), " DB", 0);
! 3563: return TCL_ERROR;
! 3564: }
! 3565: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 3566:
! 3567: zErr = sqlite3_errmsg16(db);
! 3568: if( zErr ){
! 3569: z = zErr;
! 3570: for(bytes=0; z[bytes] || z[bytes+1]; bytes+=2){}
! 3571: }
! 3572: Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(zErr, bytes));
! 3573: #endif /* SQLITE_OMIT_UTF16 */
! 3574: return TCL_OK;
! 3575: }
! 3576:
! 3577: /*
! 3578: ** Usage: sqlite3_prepare DB sql bytes ?tailvar?
! 3579: **
! 3580: ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
! 3581: ** database handle <DB>. The parameter <tailval> is the name of a global
! 3582: ** variable that is set to the unused portion of <sql> (if any). A
! 3583: ** STMT handle is returned.
! 3584: */
! 3585: static int test_prepare(
! 3586: void * clientData,
! 3587: Tcl_Interp *interp,
! 3588: int objc,
! 3589: Tcl_Obj *CONST objv[]
! 3590: ){
! 3591: sqlite3 *db;
! 3592: const char *zSql;
! 3593: int bytes;
! 3594: const char *zTail = 0;
! 3595: sqlite3_stmt *pStmt = 0;
! 3596: char zBuf[50];
! 3597: int rc;
! 3598:
! 3599: if( objc!=5 && objc!=4 ){
! 3600: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3601: Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
! 3602: return TCL_ERROR;
! 3603: }
! 3604: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 3605: zSql = Tcl_GetString(objv[2]);
! 3606: if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
! 3607:
! 3608: rc = sqlite3_prepare(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
! 3609: Tcl_ResetResult(interp);
! 3610: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 3611: if( zTail && objc>=5 ){
! 3612: if( bytes>=0 ){
! 3613: bytes = bytes - (zTail-zSql);
! 3614: }
! 3615: if( strlen(zTail)<bytes ){
! 3616: bytes = strlen(zTail);
! 3617: }
! 3618: Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
! 3619: }
! 3620: if( rc!=SQLITE_OK ){
! 3621: assert( pStmt==0 );
! 3622: sprintf(zBuf, "(%d) ", rc);
! 3623: Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
! 3624: return TCL_ERROR;
! 3625: }
! 3626:
! 3627: if( pStmt ){
! 3628: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
! 3629: Tcl_AppendResult(interp, zBuf, 0);
! 3630: }
! 3631: return TCL_OK;
! 3632: }
! 3633:
! 3634: /*
! 3635: ** Usage: sqlite3_prepare_v2 DB sql bytes ?tailvar?
! 3636: **
! 3637: ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
! 3638: ** database handle <DB>. The parameter <tailval> is the name of a global
! 3639: ** variable that is set to the unused portion of <sql> (if any). A
! 3640: ** STMT handle is returned.
! 3641: */
! 3642: static int test_prepare_v2(
! 3643: void * clientData,
! 3644: Tcl_Interp *interp,
! 3645: int objc,
! 3646: Tcl_Obj *CONST objv[]
! 3647: ){
! 3648: sqlite3 *db;
! 3649: const char *zSql;
! 3650: int bytes;
! 3651: const char *zTail = 0;
! 3652: sqlite3_stmt *pStmt = 0;
! 3653: char zBuf[50];
! 3654: int rc;
! 3655:
! 3656: if( objc!=5 && objc!=4 ){
! 3657: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3658: Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
! 3659: return TCL_ERROR;
! 3660: }
! 3661: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 3662: zSql = Tcl_GetString(objv[2]);
! 3663: if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
! 3664:
! 3665: rc = sqlite3_prepare_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
! 3666: assert(rc==SQLITE_OK || pStmt==0);
! 3667: Tcl_ResetResult(interp);
! 3668: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 3669: if( zTail && objc>=5 ){
! 3670: if( bytes>=0 ){
! 3671: bytes = bytes - (zTail-zSql);
! 3672: }
! 3673: Tcl_ObjSetVar2(interp, objv[4], 0, Tcl_NewStringObj(zTail, bytes), 0);
! 3674: }
! 3675: if( rc!=SQLITE_OK ){
! 3676: assert( pStmt==0 );
! 3677: sprintf(zBuf, "(%d) ", rc);
! 3678: Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
! 3679: return TCL_ERROR;
! 3680: }
! 3681:
! 3682: if( pStmt ){
! 3683: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
! 3684: Tcl_AppendResult(interp, zBuf, 0);
! 3685: }
! 3686: return TCL_OK;
! 3687: }
! 3688:
! 3689: /*
! 3690: ** Usage: sqlite3_prepare_tkt3134 DB
! 3691: **
! 3692: ** Generate a prepared statement for a zero-byte string as a test
! 3693: ** for ticket #3134. The string should be preceeded by a zero byte.
! 3694: */
! 3695: static int test_prepare_tkt3134(
! 3696: void * clientData,
! 3697: Tcl_Interp *interp,
! 3698: int objc,
! 3699: Tcl_Obj *CONST objv[]
! 3700: ){
! 3701: sqlite3 *db;
! 3702: static const char zSql[] = "\000SELECT 1";
! 3703: sqlite3_stmt *pStmt = 0;
! 3704: char zBuf[50];
! 3705: int rc;
! 3706:
! 3707: if( objc!=2 ){
! 3708: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3709: Tcl_GetString(objv[0]), " DB sql bytes tailvar", 0);
! 3710: return TCL_ERROR;
! 3711: }
! 3712: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 3713: rc = sqlite3_prepare_v2(db, &zSql[1], 0, &pStmt, 0);
! 3714: assert(rc==SQLITE_OK || pStmt==0);
! 3715: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 3716: if( rc!=SQLITE_OK ){
! 3717: assert( pStmt==0 );
! 3718: sprintf(zBuf, "(%d) ", rc);
! 3719: Tcl_AppendResult(interp, zBuf, sqlite3_errmsg(db), 0);
! 3720: return TCL_ERROR;
! 3721: }
! 3722:
! 3723: if( pStmt ){
! 3724: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
! 3725: Tcl_AppendResult(interp, zBuf, 0);
! 3726: }
! 3727: return TCL_OK;
! 3728: }
! 3729:
! 3730: /*
! 3731: ** Usage: sqlite3_prepare16 DB sql bytes tailvar
! 3732: **
! 3733: ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
! 3734: ** database handle <DB>. The parameter <tailval> is the name of a global
! 3735: ** variable that is set to the unused portion of <sql> (if any). A
! 3736: ** STMT handle is returned.
! 3737: */
! 3738: static int test_prepare16(
! 3739: void * clientData,
! 3740: Tcl_Interp *interp,
! 3741: int objc,
! 3742: Tcl_Obj *CONST objv[]
! 3743: ){
! 3744: #ifndef SQLITE_OMIT_UTF16
! 3745: sqlite3 *db;
! 3746: const void *zSql;
! 3747: const void *zTail = 0;
! 3748: Tcl_Obj *pTail = 0;
! 3749: sqlite3_stmt *pStmt = 0;
! 3750: char zBuf[50];
! 3751: int rc;
! 3752: int bytes; /* The integer specified as arg 3 */
! 3753: int objlen; /* The byte-array length of arg 2 */
! 3754:
! 3755: if( objc!=5 && objc!=4 ){
! 3756: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3757: Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
! 3758: return TCL_ERROR;
! 3759: }
! 3760: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 3761: zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
! 3762: if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
! 3763:
! 3764: rc = sqlite3_prepare16(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
! 3765: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 3766: if( rc ){
! 3767: return TCL_ERROR;
! 3768: }
! 3769:
! 3770: if( objc>=5 ){
! 3771: if( zTail ){
! 3772: objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
! 3773: }else{
! 3774: objlen = 0;
! 3775: }
! 3776: pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
! 3777: Tcl_IncrRefCount(pTail);
! 3778: Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
! 3779: Tcl_DecrRefCount(pTail);
! 3780: }
! 3781:
! 3782: if( pStmt ){
! 3783: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
! 3784: }
! 3785: Tcl_AppendResult(interp, zBuf, 0);
! 3786: #endif /* SQLITE_OMIT_UTF16 */
! 3787: return TCL_OK;
! 3788: }
! 3789:
! 3790: /*
! 3791: ** Usage: sqlite3_prepare16_v2 DB sql bytes ?tailvar?
! 3792: **
! 3793: ** Compile up to <bytes> bytes of the supplied SQL string <sql> using
! 3794: ** database handle <DB>. The parameter <tailval> is the name of a global
! 3795: ** variable that is set to the unused portion of <sql> (if any). A
! 3796: ** STMT handle is returned.
! 3797: */
! 3798: static int test_prepare16_v2(
! 3799: void * clientData,
! 3800: Tcl_Interp *interp,
! 3801: int objc,
! 3802: Tcl_Obj *CONST objv[]
! 3803: ){
! 3804: #ifndef SQLITE_OMIT_UTF16
! 3805: sqlite3 *db;
! 3806: const void *zSql;
! 3807: const void *zTail = 0;
! 3808: Tcl_Obj *pTail = 0;
! 3809: sqlite3_stmt *pStmt = 0;
! 3810: char zBuf[50];
! 3811: int rc;
! 3812: int bytes; /* The integer specified as arg 3 */
! 3813: int objlen; /* The byte-array length of arg 2 */
! 3814:
! 3815: if( objc!=5 && objc!=4 ){
! 3816: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3817: Tcl_GetString(objv[0]), " DB sql bytes ?tailvar?", 0);
! 3818: return TCL_ERROR;
! 3819: }
! 3820: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 3821: zSql = Tcl_GetByteArrayFromObj(objv[2], &objlen);
! 3822: if( Tcl_GetIntFromObj(interp, objv[3], &bytes) ) return TCL_ERROR;
! 3823:
! 3824: rc = sqlite3_prepare16_v2(db, zSql, bytes, &pStmt, objc>=5 ? &zTail : 0);
! 3825: if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR;
! 3826: if( rc ){
! 3827: return TCL_ERROR;
! 3828: }
! 3829:
! 3830: if( objc>=5 ){
! 3831: if( zTail ){
! 3832: objlen = objlen - ((u8 *)zTail-(u8 *)zSql);
! 3833: }else{
! 3834: objlen = 0;
! 3835: }
! 3836: pTail = Tcl_NewByteArrayObj((u8 *)zTail, objlen);
! 3837: Tcl_IncrRefCount(pTail);
! 3838: Tcl_ObjSetVar2(interp, objv[4], 0, pTail, 0);
! 3839: Tcl_DecrRefCount(pTail);
! 3840: }
! 3841:
! 3842: if( pStmt ){
! 3843: if( sqlite3TestMakePointerStr(interp, zBuf, pStmt) ) return TCL_ERROR;
! 3844: }
! 3845: Tcl_AppendResult(interp, zBuf, 0);
! 3846: #endif /* SQLITE_OMIT_UTF16 */
! 3847: return TCL_OK;
! 3848: }
! 3849:
! 3850: /*
! 3851: ** Usage: sqlite3_open filename ?options-list?
! 3852: */
! 3853: static int test_open(
! 3854: void * clientData,
! 3855: Tcl_Interp *interp,
! 3856: int objc,
! 3857: Tcl_Obj *CONST objv[]
! 3858: ){
! 3859: const char *zFilename;
! 3860: sqlite3 *db;
! 3861: int rc;
! 3862: char zBuf[100];
! 3863:
! 3864: if( objc!=3 && objc!=2 && objc!=1 ){
! 3865: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3866: Tcl_GetString(objv[0]), " filename options-list", 0);
! 3867: return TCL_ERROR;
! 3868: }
! 3869:
! 3870: zFilename = objc>1 ? Tcl_GetString(objv[1]) : 0;
! 3871: rc = sqlite3_open(zFilename, &db);
! 3872:
! 3873: if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
! 3874: Tcl_AppendResult(interp, zBuf, 0);
! 3875: return TCL_OK;
! 3876: }
! 3877:
! 3878: /*
! 3879: ** Usage: sqlite3_open_v2 FILENAME FLAGS VFS
! 3880: */
! 3881: static int test_open_v2(
! 3882: void * clientData,
! 3883: Tcl_Interp *interp,
! 3884: int objc,
! 3885: Tcl_Obj *CONST objv[]
! 3886: ){
! 3887: const char *zFilename;
! 3888: const char *zVfs;
! 3889: int flags = 0;
! 3890: sqlite3 *db;
! 3891: int rc;
! 3892: char zBuf[100];
! 3893:
! 3894: int nFlag;
! 3895: Tcl_Obj **apFlag;
! 3896: int i;
! 3897:
! 3898: if( objc!=4 ){
! 3899: Tcl_WrongNumArgs(interp, 1, objv, "FILENAME FLAGS VFS");
! 3900: return TCL_ERROR;
! 3901: }
! 3902: zFilename = Tcl_GetString(objv[1]);
! 3903: zVfs = Tcl_GetString(objv[3]);
! 3904: if( zVfs[0]==0x00 ) zVfs = 0;
! 3905:
! 3906: rc = Tcl_ListObjGetElements(interp, objv[2], &nFlag, &apFlag);
! 3907: if( rc!=TCL_OK ) return rc;
! 3908: for(i=0; i<nFlag; i++){
! 3909: int iFlag;
! 3910: struct OpenFlag {
! 3911: const char *zFlag;
! 3912: int flag;
! 3913: } aFlag[] = {
! 3914: { "SQLITE_OPEN_READONLY", SQLITE_OPEN_READONLY },
! 3915: { "SQLITE_OPEN_READWRITE", SQLITE_OPEN_READWRITE },
! 3916: { "SQLITE_OPEN_CREATE", SQLITE_OPEN_CREATE },
! 3917: { "SQLITE_OPEN_DELETEONCLOSE", SQLITE_OPEN_DELETEONCLOSE },
! 3918: { "SQLITE_OPEN_EXCLUSIVE", SQLITE_OPEN_EXCLUSIVE },
! 3919: { "SQLITE_OPEN_AUTOPROXY", SQLITE_OPEN_AUTOPROXY },
! 3920: { "SQLITE_OPEN_MAIN_DB", SQLITE_OPEN_MAIN_DB },
! 3921: { "SQLITE_OPEN_TEMP_DB", SQLITE_OPEN_TEMP_DB },
! 3922: { "SQLITE_OPEN_TRANSIENT_DB", SQLITE_OPEN_TRANSIENT_DB },
! 3923: { "SQLITE_OPEN_MAIN_JOURNAL", SQLITE_OPEN_MAIN_JOURNAL },
! 3924: { "SQLITE_OPEN_TEMP_JOURNAL", SQLITE_OPEN_TEMP_JOURNAL },
! 3925: { "SQLITE_OPEN_SUBJOURNAL", SQLITE_OPEN_SUBJOURNAL },
! 3926: { "SQLITE_OPEN_MASTER_JOURNAL", SQLITE_OPEN_MASTER_JOURNAL },
! 3927: { "SQLITE_OPEN_NOMUTEX", SQLITE_OPEN_NOMUTEX },
! 3928: { "SQLITE_OPEN_FULLMUTEX", SQLITE_OPEN_FULLMUTEX },
! 3929: { "SQLITE_OPEN_SHAREDCACHE", SQLITE_OPEN_SHAREDCACHE },
! 3930: { "SQLITE_OPEN_PRIVATECACHE", SQLITE_OPEN_PRIVATECACHE },
! 3931: { "SQLITE_OPEN_WAL", SQLITE_OPEN_WAL },
! 3932: { "SQLITE_OPEN_URI", SQLITE_OPEN_URI },
! 3933: { 0, 0 }
! 3934: };
! 3935: rc = Tcl_GetIndexFromObjStruct(interp, apFlag[i], aFlag, sizeof(aFlag[0]),
! 3936: "flag", 0, &iFlag
! 3937: );
! 3938: if( rc!=TCL_OK ) return rc;
! 3939: flags |= aFlag[iFlag].flag;
! 3940: }
! 3941:
! 3942: rc = sqlite3_open_v2(zFilename, &db, flags, zVfs);
! 3943: if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
! 3944: Tcl_AppendResult(interp, zBuf, 0);
! 3945: return TCL_OK;
! 3946: }
! 3947:
! 3948: /*
! 3949: ** Usage: sqlite3_open16 filename options
! 3950: */
! 3951: static int test_open16(
! 3952: void * clientData,
! 3953: Tcl_Interp *interp,
! 3954: int objc,
! 3955: Tcl_Obj *CONST objv[]
! 3956: ){
! 3957: #ifndef SQLITE_OMIT_UTF16
! 3958: const void *zFilename;
! 3959: sqlite3 *db;
! 3960: int rc;
! 3961: char zBuf[100];
! 3962:
! 3963: if( objc!=3 ){
! 3964: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 3965: Tcl_GetString(objv[0]), " filename options-list", 0);
! 3966: return TCL_ERROR;
! 3967: }
! 3968:
! 3969: zFilename = Tcl_GetByteArrayFromObj(objv[1], 0);
! 3970: rc = sqlite3_open16(zFilename, &db);
! 3971:
! 3972: if( sqlite3TestMakePointerStr(interp, zBuf, db) ) return TCL_ERROR;
! 3973: Tcl_AppendResult(interp, zBuf, 0);
! 3974: #endif /* SQLITE_OMIT_UTF16 */
! 3975: return TCL_OK;
! 3976: }
! 3977:
! 3978: /*
! 3979: ** Usage: sqlite3_complete16 <UTF-16 string>
! 3980: **
! 3981: ** Return 1 if the supplied argument is a complete SQL statement, or zero
! 3982: ** otherwise.
! 3983: */
! 3984: static int test_complete16(
! 3985: void * clientData,
! 3986: Tcl_Interp *interp,
! 3987: int objc,
! 3988: Tcl_Obj *CONST objv[]
! 3989: ){
! 3990: #if !defined(SQLITE_OMIT_COMPLETE) && !defined(SQLITE_OMIT_UTF16)
! 3991: char *zBuf;
! 3992:
! 3993: if( objc!=2 ){
! 3994: Tcl_WrongNumArgs(interp, 1, objv, "<utf-16 sql>");
! 3995: return TCL_ERROR;
! 3996: }
! 3997:
! 3998: zBuf = (char*)Tcl_GetByteArrayFromObj(objv[1], 0);
! 3999: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_complete16(zBuf)));
! 4000: #endif /* SQLITE_OMIT_COMPLETE && SQLITE_OMIT_UTF16 */
! 4001: return TCL_OK;
! 4002: }
! 4003:
! 4004: /*
! 4005: ** Usage: sqlite3_step STMT
! 4006: **
! 4007: ** Advance the statement to the next row.
! 4008: */
! 4009: static int test_step(
! 4010: void * clientData,
! 4011: Tcl_Interp *interp,
! 4012: int objc,
! 4013: Tcl_Obj *CONST objv[]
! 4014: ){
! 4015: sqlite3_stmt *pStmt;
! 4016: int rc;
! 4017:
! 4018: if( objc!=2 ){
! 4019: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4020: Tcl_GetString(objv[0]), " STMT", 0);
! 4021: return TCL_ERROR;
! 4022: }
! 4023:
! 4024: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4025: rc = sqlite3_step(pStmt);
! 4026:
! 4027: /* if( rc!=SQLITE_DONE && rc!=SQLITE_ROW ) return TCL_ERROR; */
! 4028: Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
! 4029: return TCL_OK;
! 4030: }
! 4031:
! 4032: static int test_sql(
! 4033: void * clientData,
! 4034: Tcl_Interp *interp,
! 4035: int objc,
! 4036: Tcl_Obj *CONST objv[]
! 4037: ){
! 4038: sqlite3_stmt *pStmt;
! 4039:
! 4040: if( objc!=2 ){
! 4041: Tcl_WrongNumArgs(interp, 1, objv, "STMT");
! 4042: return TCL_ERROR;
! 4043: }
! 4044:
! 4045: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4046: Tcl_SetResult(interp, (char *)sqlite3_sql(pStmt), TCL_VOLATILE);
! 4047: return TCL_OK;
! 4048: }
! 4049:
! 4050: /*
! 4051: ** Usage: sqlite3_column_count STMT
! 4052: **
! 4053: ** Return the number of columns returned by the sql statement STMT.
! 4054: */
! 4055: static int test_column_count(
! 4056: void * clientData,
! 4057: Tcl_Interp *interp,
! 4058: int objc,
! 4059: Tcl_Obj *CONST objv[]
! 4060: ){
! 4061: sqlite3_stmt *pStmt;
! 4062:
! 4063: if( objc!=2 ){
! 4064: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4065: Tcl_GetString(objv[0]), " STMT column", 0);
! 4066: return TCL_ERROR;
! 4067: }
! 4068:
! 4069: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4070:
! 4071: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_column_count(pStmt)));
! 4072: return TCL_OK;
! 4073: }
! 4074:
! 4075: /*
! 4076: ** Usage: sqlite3_column_type STMT column
! 4077: **
! 4078: ** Return the type of the data in column 'column' of the current row.
! 4079: */
! 4080: static int test_column_type(
! 4081: void * clientData,
! 4082: Tcl_Interp *interp,
! 4083: int objc,
! 4084: Tcl_Obj *CONST objv[]
! 4085: ){
! 4086: sqlite3_stmt *pStmt;
! 4087: int col;
! 4088: int tp;
! 4089:
! 4090: if( objc!=3 ){
! 4091: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4092: Tcl_GetString(objv[0]), " STMT column", 0);
! 4093: return TCL_ERROR;
! 4094: }
! 4095:
! 4096: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4097: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
! 4098:
! 4099: tp = sqlite3_column_type(pStmt, col);
! 4100: switch( tp ){
! 4101: case SQLITE_INTEGER:
! 4102: Tcl_SetResult(interp, "INTEGER", TCL_STATIC);
! 4103: break;
! 4104: case SQLITE_NULL:
! 4105: Tcl_SetResult(interp, "NULL", TCL_STATIC);
! 4106: break;
! 4107: case SQLITE_FLOAT:
! 4108: Tcl_SetResult(interp, "FLOAT", TCL_STATIC);
! 4109: break;
! 4110: case SQLITE_TEXT:
! 4111: Tcl_SetResult(interp, "TEXT", TCL_STATIC);
! 4112: break;
! 4113: case SQLITE_BLOB:
! 4114: Tcl_SetResult(interp, "BLOB", TCL_STATIC);
! 4115: break;
! 4116: default:
! 4117: assert(0);
! 4118: }
! 4119:
! 4120: return TCL_OK;
! 4121: }
! 4122:
! 4123: /*
! 4124: ** Usage: sqlite3_column_int64 STMT column
! 4125: **
! 4126: ** Return the data in column 'column' of the current row cast as an
! 4127: ** wide (64-bit) integer.
! 4128: */
! 4129: static int test_column_int64(
! 4130: void * clientData,
! 4131: Tcl_Interp *interp,
! 4132: int objc,
! 4133: Tcl_Obj *CONST objv[]
! 4134: ){
! 4135: sqlite3_stmt *pStmt;
! 4136: int col;
! 4137: i64 iVal;
! 4138:
! 4139: if( objc!=3 ){
! 4140: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4141: Tcl_GetString(objv[0]), " STMT column", 0);
! 4142: return TCL_ERROR;
! 4143: }
! 4144:
! 4145: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4146: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
! 4147:
! 4148: iVal = sqlite3_column_int64(pStmt, col);
! 4149: Tcl_SetObjResult(interp, Tcl_NewWideIntObj(iVal));
! 4150: return TCL_OK;
! 4151: }
! 4152:
! 4153: /*
! 4154: ** Usage: sqlite3_column_blob STMT column
! 4155: */
! 4156: static int test_column_blob(
! 4157: void * clientData,
! 4158: Tcl_Interp *interp,
! 4159: int objc,
! 4160: Tcl_Obj *CONST objv[]
! 4161: ){
! 4162: sqlite3_stmt *pStmt;
! 4163: int col;
! 4164:
! 4165: int len;
! 4166: const void *pBlob;
! 4167:
! 4168: if( objc!=3 ){
! 4169: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4170: Tcl_GetString(objv[0]), " STMT column", 0);
! 4171: return TCL_ERROR;
! 4172: }
! 4173:
! 4174: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4175: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
! 4176:
! 4177: len = sqlite3_column_bytes(pStmt, col);
! 4178: pBlob = sqlite3_column_blob(pStmt, col);
! 4179: Tcl_SetObjResult(interp, Tcl_NewByteArrayObj(pBlob, len));
! 4180: return TCL_OK;
! 4181: }
! 4182:
! 4183: /*
! 4184: ** Usage: sqlite3_column_double STMT column
! 4185: **
! 4186: ** Return the data in column 'column' of the current row cast as a double.
! 4187: */
! 4188: static int test_column_double(
! 4189: void * clientData,
! 4190: Tcl_Interp *interp,
! 4191: int objc,
! 4192: Tcl_Obj *CONST objv[]
! 4193: ){
! 4194: sqlite3_stmt *pStmt;
! 4195: int col;
! 4196: double rVal;
! 4197:
! 4198: if( objc!=3 ){
! 4199: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4200: Tcl_GetString(objv[0]), " STMT column", 0);
! 4201: return TCL_ERROR;
! 4202: }
! 4203:
! 4204: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4205: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
! 4206:
! 4207: rVal = sqlite3_column_double(pStmt, col);
! 4208: Tcl_SetObjResult(interp, Tcl_NewDoubleObj(rVal));
! 4209: return TCL_OK;
! 4210: }
! 4211:
! 4212: /*
! 4213: ** Usage: sqlite3_data_count STMT
! 4214: **
! 4215: ** Return the number of columns returned by the sql statement STMT.
! 4216: */
! 4217: static int test_data_count(
! 4218: void * clientData,
! 4219: Tcl_Interp *interp,
! 4220: int objc,
! 4221: Tcl_Obj *CONST objv[]
! 4222: ){
! 4223: sqlite3_stmt *pStmt;
! 4224:
! 4225: if( objc!=2 ){
! 4226: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4227: Tcl_GetString(objv[0]), " STMT column", 0);
! 4228: return TCL_ERROR;
! 4229: }
! 4230:
! 4231: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4232:
! 4233: Tcl_SetObjResult(interp, Tcl_NewIntObj(sqlite3_data_count(pStmt)));
! 4234: return TCL_OK;
! 4235: }
! 4236:
! 4237: /*
! 4238: ** Usage: sqlite3_column_text STMT column
! 4239: **
! 4240: ** Usage: sqlite3_column_decltype STMT column
! 4241: **
! 4242: ** Usage: sqlite3_column_name STMT column
! 4243: */
! 4244: static int test_stmt_utf8(
! 4245: void * clientData, /* Pointer to SQLite API function to be invoke */
! 4246: Tcl_Interp *interp,
! 4247: int objc,
! 4248: Tcl_Obj *CONST objv[]
! 4249: ){
! 4250: sqlite3_stmt *pStmt;
! 4251: int col;
! 4252: const char *(*xFunc)(sqlite3_stmt*, int);
! 4253: const char *zRet;
! 4254:
! 4255: xFunc = (const char *(*)(sqlite3_stmt*, int))clientData;
! 4256: if( objc!=3 ){
! 4257: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4258: Tcl_GetString(objv[0]), " STMT column", 0);
! 4259: return TCL_ERROR;
! 4260: }
! 4261:
! 4262: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4263: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
! 4264: zRet = xFunc(pStmt, col);
! 4265: if( zRet ){
! 4266: Tcl_SetResult(interp, (char *)zRet, 0);
! 4267: }
! 4268: return TCL_OK;
! 4269: }
! 4270:
! 4271: static int test_global_recover(
! 4272: void * clientData,
! 4273: Tcl_Interp *interp,
! 4274: int objc,
! 4275: Tcl_Obj *CONST objv[]
! 4276: ){
! 4277: #ifndef SQLITE_OMIT_DEPRECATED
! 4278: int rc;
! 4279: if( objc!=1 ){
! 4280: Tcl_WrongNumArgs(interp, 1, objv, "");
! 4281: return TCL_ERROR;
! 4282: }
! 4283: rc = sqlite3_global_recover();
! 4284: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
! 4285: #endif
! 4286: return TCL_OK;
! 4287: }
! 4288:
! 4289: /*
! 4290: ** Usage: sqlite3_column_text STMT column
! 4291: **
! 4292: ** Usage: sqlite3_column_decltype STMT column
! 4293: **
! 4294: ** Usage: sqlite3_column_name STMT column
! 4295: */
! 4296: static int test_stmt_utf16(
! 4297: void * clientData, /* Pointer to SQLite API function to be invoked */
! 4298: Tcl_Interp *interp,
! 4299: int objc,
! 4300: Tcl_Obj *CONST objv[]
! 4301: ){
! 4302: #ifndef SQLITE_OMIT_UTF16
! 4303: sqlite3_stmt *pStmt;
! 4304: int col;
! 4305: Tcl_Obj *pRet;
! 4306: const void *zName16;
! 4307: const void *(*xFunc)(sqlite3_stmt*, int);
! 4308:
! 4309: xFunc = (const void *(*)(sqlite3_stmt*, int))clientData;
! 4310: if( objc!=3 ){
! 4311: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4312: Tcl_GetString(objv[0]), " STMT column", 0);
! 4313: return TCL_ERROR;
! 4314: }
! 4315:
! 4316: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4317: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
! 4318:
! 4319: zName16 = xFunc(pStmt, col);
! 4320: if( zName16 ){
! 4321: int n;
! 4322: const char *z = zName16;
! 4323: for(n=0; z[n] || z[n+1]; n+=2){}
! 4324: pRet = Tcl_NewByteArrayObj(zName16, n+2);
! 4325: Tcl_SetObjResult(interp, pRet);
! 4326: }
! 4327: #endif /* SQLITE_OMIT_UTF16 */
! 4328:
! 4329: return TCL_OK;
! 4330: }
! 4331:
! 4332: /*
! 4333: ** Usage: sqlite3_column_int STMT column
! 4334: **
! 4335: ** Usage: sqlite3_column_bytes STMT column
! 4336: **
! 4337: ** Usage: sqlite3_column_bytes16 STMT column
! 4338: **
! 4339: */
! 4340: static int test_stmt_int(
! 4341: void * clientData, /* Pointer to SQLite API function to be invoked */
! 4342: Tcl_Interp *interp,
! 4343: int objc,
! 4344: Tcl_Obj *CONST objv[]
! 4345: ){
! 4346: sqlite3_stmt *pStmt;
! 4347: int col;
! 4348: int (*xFunc)(sqlite3_stmt*, int);
! 4349:
! 4350: xFunc = (int (*)(sqlite3_stmt*, int))clientData;
! 4351: if( objc!=3 ){
! 4352: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4353: Tcl_GetString(objv[0]), " STMT column", 0);
! 4354: return TCL_ERROR;
! 4355: }
! 4356:
! 4357: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 4358: if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR;
! 4359:
! 4360: Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col)));
! 4361: return TCL_OK;
! 4362: }
! 4363:
! 4364: /*
! 4365: ** Usage: sqlite_set_magic DB MAGIC-NUMBER
! 4366: **
! 4367: ** Set the db->magic value. This is used to test error recovery logic.
! 4368: */
! 4369: static int sqlite_set_magic(
! 4370: void * clientData,
! 4371: Tcl_Interp *interp,
! 4372: int argc,
! 4373: char **argv
! 4374: ){
! 4375: sqlite3 *db;
! 4376: if( argc!=3 ){
! 4377: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 4378: " DB MAGIC", 0);
! 4379: return TCL_ERROR;
! 4380: }
! 4381: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 4382: if( strcmp(argv[2], "SQLITE_MAGIC_OPEN")==0 ){
! 4383: db->magic = SQLITE_MAGIC_OPEN;
! 4384: }else if( strcmp(argv[2], "SQLITE_MAGIC_CLOSED")==0 ){
! 4385: db->magic = SQLITE_MAGIC_CLOSED;
! 4386: }else if( strcmp(argv[2], "SQLITE_MAGIC_BUSY")==0 ){
! 4387: db->magic = SQLITE_MAGIC_BUSY;
! 4388: }else if( strcmp(argv[2], "SQLITE_MAGIC_ERROR")==0 ){
! 4389: db->magic = SQLITE_MAGIC_ERROR;
! 4390: }else if( Tcl_GetInt(interp, argv[2], (int*)&db->magic) ){
! 4391: return TCL_ERROR;
! 4392: }
! 4393: return TCL_OK;
! 4394: }
! 4395:
! 4396: /*
! 4397: ** Usage: sqlite3_interrupt DB
! 4398: **
! 4399: ** Trigger an interrupt on DB
! 4400: */
! 4401: static int test_interrupt(
! 4402: void * clientData,
! 4403: Tcl_Interp *interp,
! 4404: int argc,
! 4405: char **argv
! 4406: ){
! 4407: sqlite3 *db;
! 4408: if( argc!=2 ){
! 4409: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
! 4410: return TCL_ERROR;
! 4411: }
! 4412: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 4413: sqlite3_interrupt(db);
! 4414: return TCL_OK;
! 4415: }
! 4416:
! 4417: static u8 *sqlite3_stack_baseline = 0;
! 4418:
! 4419: /*
! 4420: ** Fill the stack with a known bitpattern.
! 4421: */
! 4422: static void prepStack(void){
! 4423: int i;
! 4424: u32 bigBuf[65536];
! 4425: for(i=0; i<sizeof(bigBuf)/sizeof(bigBuf[0]); i++) bigBuf[i] = 0xdeadbeef;
! 4426: sqlite3_stack_baseline = (u8*)&bigBuf[65536];
! 4427: }
! 4428:
! 4429: /*
! 4430: ** Get the current stack depth. Used for debugging only.
! 4431: */
! 4432: u64 sqlite3StackDepth(void){
! 4433: u8 x;
! 4434: return (u64)(sqlite3_stack_baseline - &x);
! 4435: }
! 4436:
! 4437: /*
! 4438: ** Usage: sqlite3_stack_used DB SQL
! 4439: **
! 4440: ** Try to measure the amount of stack space used by a call to sqlite3_exec
! 4441: */
! 4442: static int test_stack_used(
! 4443: void * clientData,
! 4444: Tcl_Interp *interp,
! 4445: int argc,
! 4446: char **argv
! 4447: ){
! 4448: sqlite3 *db;
! 4449: int i;
! 4450: if( argc!=3 ){
! 4451: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 4452: " DB SQL", 0);
! 4453: return TCL_ERROR;
! 4454: }
! 4455: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 4456: prepStack();
! 4457: (void)sqlite3_exec(db, argv[2], 0, 0, 0);
! 4458: for(i=65535; i>=0 && ((u32*)sqlite3_stack_baseline)[-i]==0xdeadbeef; i--){}
! 4459: Tcl_SetObjResult(interp, Tcl_NewIntObj(i*4));
! 4460: return TCL_OK;
! 4461: }
! 4462:
! 4463: /*
! 4464: ** Usage: sqlite_delete_function DB function-name
! 4465: **
! 4466: ** Delete the user function 'function-name' from database handle DB. It
! 4467: ** is assumed that the user function was created as UTF8, any number of
! 4468: ** arguments (the way the TCL interface does it).
! 4469: */
! 4470: static int delete_function(
! 4471: void * clientData,
! 4472: Tcl_Interp *interp,
! 4473: int argc,
! 4474: char **argv
! 4475: ){
! 4476: int rc;
! 4477: sqlite3 *db;
! 4478: if( argc!=3 ){
! 4479: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 4480: " DB function-name", 0);
! 4481: return TCL_ERROR;
! 4482: }
! 4483: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 4484: rc = sqlite3_create_function(db, argv[2], -1, SQLITE_UTF8, 0, 0, 0, 0);
! 4485: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
! 4486: return TCL_OK;
! 4487: }
! 4488:
! 4489: /*
! 4490: ** Usage: sqlite_delete_collation DB collation-name
! 4491: **
! 4492: ** Delete the collation sequence 'collation-name' from database handle
! 4493: ** DB. It is assumed that the collation sequence was created as UTF8 (the
! 4494: ** way the TCL interface does it).
! 4495: */
! 4496: static int delete_collation(
! 4497: void * clientData,
! 4498: Tcl_Interp *interp,
! 4499: int argc,
! 4500: char **argv
! 4501: ){
! 4502: int rc;
! 4503: sqlite3 *db;
! 4504: if( argc!=3 ){
! 4505: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 4506: " DB function-name", 0);
! 4507: return TCL_ERROR;
! 4508: }
! 4509: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 4510: rc = sqlite3_create_collation(db, argv[2], SQLITE_UTF8, 0, 0);
! 4511: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
! 4512: return TCL_OK;
! 4513: }
! 4514:
! 4515: /*
! 4516: ** Usage: sqlite3_get_autocommit DB
! 4517: **
! 4518: ** Return true if the database DB is currently in auto-commit mode.
! 4519: ** Return false if not.
! 4520: */
! 4521: static int get_autocommit(
! 4522: void * clientData,
! 4523: Tcl_Interp *interp,
! 4524: int argc,
! 4525: char **argv
! 4526: ){
! 4527: char zBuf[30];
! 4528: sqlite3 *db;
! 4529: if( argc!=2 ){
! 4530: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 4531: " DB", 0);
! 4532: return TCL_ERROR;
! 4533: }
! 4534: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 4535: sprintf(zBuf, "%d", sqlite3_get_autocommit(db));
! 4536: Tcl_AppendResult(interp, zBuf, 0);
! 4537: return TCL_OK;
! 4538: }
! 4539:
! 4540: /*
! 4541: ** Usage: sqlite3_busy_timeout DB MS
! 4542: **
! 4543: ** Set the busy timeout. This is more easily done using the timeout
! 4544: ** method of the TCL interface. But we need a way to test the case
! 4545: ** where it returns SQLITE_MISUSE.
! 4546: */
! 4547: static int test_busy_timeout(
! 4548: void * clientData,
! 4549: Tcl_Interp *interp,
! 4550: int argc,
! 4551: char **argv
! 4552: ){
! 4553: int rc, ms;
! 4554: sqlite3 *db;
! 4555: if( argc!=3 ){
! 4556: Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
! 4557: " DB", 0);
! 4558: return TCL_ERROR;
! 4559: }
! 4560: if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
! 4561: if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
! 4562: rc = sqlite3_busy_timeout(db, ms);
! 4563: Tcl_AppendResult(interp, sqlite3TestErrorName(rc), 0);
! 4564: return TCL_OK;
! 4565: }
! 4566:
! 4567: /*
! 4568: ** Usage: tcl_variable_type VARIABLENAME
! 4569: **
! 4570: ** Return the name of the internal representation for the
! 4571: ** value of the given variable.
! 4572: */
! 4573: static int tcl_variable_type(
! 4574: void * clientData,
! 4575: Tcl_Interp *interp,
! 4576: int objc,
! 4577: Tcl_Obj *CONST objv[]
! 4578: ){
! 4579: Tcl_Obj *pVar;
! 4580: if( objc!=2 ){
! 4581: Tcl_WrongNumArgs(interp, 1, objv, "VARIABLE");
! 4582: return TCL_ERROR;
! 4583: }
! 4584: pVar = Tcl_GetVar2Ex(interp, Tcl_GetString(objv[1]), 0, TCL_LEAVE_ERR_MSG);
! 4585: if( pVar==0 ) return TCL_ERROR;
! 4586: if( pVar->typePtr ){
! 4587: Tcl_SetObjResult(interp, Tcl_NewStringObj(pVar->typePtr->name, -1));
! 4588: }
! 4589: return TCL_OK;
! 4590: }
! 4591:
! 4592: /*
! 4593: ** Usage: sqlite3_release_memory ?N?
! 4594: **
! 4595: ** Attempt to release memory currently held but not actually required.
! 4596: ** The integer N is the number of bytes we are trying to release. The
! 4597: ** return value is the amount of memory actually released.
! 4598: */
! 4599: static int test_release_memory(
! 4600: void * clientData,
! 4601: Tcl_Interp *interp,
! 4602: int objc,
! 4603: Tcl_Obj *CONST objv[]
! 4604: ){
! 4605: #if defined(SQLITE_ENABLE_MEMORY_MANAGEMENT) && !defined(SQLITE_OMIT_DISKIO)
! 4606: int N;
! 4607: int amt;
! 4608: if( objc!=1 && objc!=2 ){
! 4609: Tcl_WrongNumArgs(interp, 1, objv, "?N?");
! 4610: return TCL_ERROR;
! 4611: }
! 4612: if( objc==2 ){
! 4613: if( Tcl_GetIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
! 4614: }else{
! 4615: N = -1;
! 4616: }
! 4617: amt = sqlite3_release_memory(N);
! 4618: Tcl_SetObjResult(interp, Tcl_NewIntObj(amt));
! 4619: #endif
! 4620: return TCL_OK;
! 4621: }
! 4622:
! 4623:
! 4624: /*
! 4625: ** Usage: sqlite3_db_release_memory DB
! 4626: **
! 4627: ** Attempt to release memory currently held by database DB. Return the
! 4628: ** result code (which in the current implementation is always zero).
! 4629: */
! 4630: static int test_db_release_memory(
! 4631: void * clientData,
! 4632: Tcl_Interp *interp,
! 4633: int objc,
! 4634: Tcl_Obj *CONST objv[]
! 4635: ){
! 4636: sqlite3 *db;
! 4637: int rc;
! 4638: if( objc!=2 ){
! 4639: Tcl_WrongNumArgs(interp, 1, objv, "DB");
! 4640: return TCL_ERROR;
! 4641: }
! 4642: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 4643: rc = sqlite3_db_release_memory(db);
! 4644: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
! 4645: return TCL_OK;
! 4646: }
! 4647:
! 4648: /*
! 4649: ** Usage: sqlite3_db_filename DB DBNAME
! 4650: **
! 4651: ** Return the name of a file associated with a database.
! 4652: */
! 4653: static int test_db_filename(
! 4654: void * clientData,
! 4655: Tcl_Interp *interp,
! 4656: int objc,
! 4657: Tcl_Obj *CONST objv[]
! 4658: ){
! 4659: sqlite3 *db;
! 4660: const char *zDbName;
! 4661: if( objc!=3 ){
! 4662: Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME");
! 4663: return TCL_ERROR;
! 4664: }
! 4665: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 4666: zDbName = Tcl_GetString(objv[2]);
! 4667: Tcl_AppendResult(interp, sqlite3_db_filename(db, zDbName), (void*)0);
! 4668: return TCL_OK;
! 4669: }
! 4670:
! 4671: /*
! 4672: ** Usage: sqlite3_soft_heap_limit ?N?
! 4673: **
! 4674: ** Query or set the soft heap limit for the current thread. The
! 4675: ** limit is only changed if the N is present. The previous limit
! 4676: ** is returned.
! 4677: */
! 4678: static int test_soft_heap_limit(
! 4679: void * clientData,
! 4680: Tcl_Interp *interp,
! 4681: int objc,
! 4682: Tcl_Obj *CONST objv[]
! 4683: ){
! 4684: sqlite3_int64 amt;
! 4685: sqlite3_int64 N = -1;
! 4686: if( objc!=1 && objc!=2 ){
! 4687: Tcl_WrongNumArgs(interp, 1, objv, "?N?");
! 4688: return TCL_ERROR;
! 4689: }
! 4690: if( objc==2 ){
! 4691: if( Tcl_GetWideIntFromObj(interp, objv[1], &N) ) return TCL_ERROR;
! 4692: }
! 4693: amt = sqlite3_soft_heap_limit64(N);
! 4694: Tcl_SetObjResult(interp, Tcl_NewWideIntObj(amt));
! 4695: return TCL_OK;
! 4696: }
! 4697:
! 4698: /*
! 4699: ** Usage: sqlite3_thread_cleanup
! 4700: **
! 4701: ** Call the sqlite3_thread_cleanup API.
! 4702: */
! 4703: static int test_thread_cleanup(
! 4704: void * clientData,
! 4705: Tcl_Interp *interp,
! 4706: int objc,
! 4707: Tcl_Obj *CONST objv[]
! 4708: ){
! 4709: #ifndef SQLITE_OMIT_DEPRECATED
! 4710: sqlite3_thread_cleanup();
! 4711: #endif
! 4712: return TCL_OK;
! 4713: }
! 4714:
! 4715: /*
! 4716: ** Usage: sqlite3_pager_refcounts DB
! 4717: **
! 4718: ** Return a list of numbers which are the PagerRefcount for all
! 4719: ** pagers on each database connection.
! 4720: */
! 4721: static int test_pager_refcounts(
! 4722: void * clientData,
! 4723: Tcl_Interp *interp,
! 4724: int objc,
! 4725: Tcl_Obj *CONST objv[]
! 4726: ){
! 4727: sqlite3 *db;
! 4728: int i;
! 4729: int v, *a;
! 4730: Tcl_Obj *pResult;
! 4731:
! 4732: if( objc!=2 ){
! 4733: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4734: Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
! 4735: return TCL_ERROR;
! 4736: }
! 4737: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 4738: pResult = Tcl_NewObj();
! 4739: for(i=0; i<db->nDb; i++){
! 4740: if( db->aDb[i].pBt==0 ){
! 4741: v = -1;
! 4742: }else{
! 4743: sqlite3_mutex_enter(db->mutex);
! 4744: a = sqlite3PagerStats(sqlite3BtreePager(db->aDb[i].pBt));
! 4745: v = a[0];
! 4746: sqlite3_mutex_leave(db->mutex);
! 4747: }
! 4748: Tcl_ListObjAppendElement(0, pResult, Tcl_NewIntObj(v));
! 4749: }
! 4750: Tcl_SetObjResult(interp, pResult);
! 4751: return TCL_OK;
! 4752: }
! 4753:
! 4754:
! 4755: /*
! 4756: ** tclcmd: working_64bit_int
! 4757: **
! 4758: ** Some TCL builds (ex: cygwin) do not support 64-bit integers. This
! 4759: ** leads to a number of test failures. The present command checks the
! 4760: ** TCL build to see whether or not it supports 64-bit integers. It
! 4761: ** returns TRUE if it does and FALSE if not.
! 4762: **
! 4763: ** This command is used to warn users that their TCL build is defective
! 4764: ** and that the errors they are seeing in the test scripts might be
! 4765: ** a result of their defective TCL rather than problems in SQLite.
! 4766: */
! 4767: static int working_64bit_int(
! 4768: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 4769: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 4770: int objc, /* Number of arguments */
! 4771: Tcl_Obj *CONST objv[] /* Command arguments */
! 4772: ){
! 4773: Tcl_Obj *pTestObj;
! 4774: int working = 0;
! 4775:
! 4776: pTestObj = Tcl_NewWideIntObj(1000000*(i64)1234567890);
! 4777: working = strcmp(Tcl_GetString(pTestObj), "1234567890000000")==0;
! 4778: Tcl_DecrRefCount(pTestObj);
! 4779: Tcl_SetObjResult(interp, Tcl_NewBooleanObj(working));
! 4780: return TCL_OK;
! 4781: }
! 4782:
! 4783:
! 4784: /*
! 4785: ** tclcmd: vfs_unlink_test
! 4786: **
! 4787: ** This TCL command unregisters the primary VFS and then registers
! 4788: ** it back again. This is used to test the ability to register a
! 4789: ** VFS when none are previously registered, and the ability to
! 4790: ** unregister the only available VFS. Ticket #2738
! 4791: */
! 4792: static int vfs_unlink_test(
! 4793: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 4794: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 4795: int objc, /* Number of arguments */
! 4796: Tcl_Obj *CONST objv[] /* Command arguments */
! 4797: ){
! 4798: int i;
! 4799: sqlite3_vfs *pMain;
! 4800: sqlite3_vfs *apVfs[20];
! 4801: sqlite3_vfs one, two;
! 4802:
! 4803: sqlite3_vfs_unregister(0); /* Unregister of NULL is harmless */
! 4804: one.zName = "__one";
! 4805: two.zName = "__two";
! 4806:
! 4807: /* Calling sqlite3_vfs_register with 2nd argument of 0 does not
! 4808: ** change the default VFS
! 4809: */
! 4810: pMain = sqlite3_vfs_find(0);
! 4811: sqlite3_vfs_register(&one, 0);
! 4812: assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
! 4813: sqlite3_vfs_register(&two, 0);
! 4814: assert( pMain==0 || pMain==sqlite3_vfs_find(0) );
! 4815:
! 4816: /* We can find a VFS by its name */
! 4817: assert( sqlite3_vfs_find("__one")==&one );
! 4818: assert( sqlite3_vfs_find("__two")==&two );
! 4819:
! 4820: /* Calling sqlite_vfs_register with non-zero second parameter changes the
! 4821: ** default VFS, even if the 1st parameter is an existig VFS that is
! 4822: ** previously registered as the non-default.
! 4823: */
! 4824: sqlite3_vfs_register(&one, 1);
! 4825: assert( sqlite3_vfs_find("__one")==&one );
! 4826: assert( sqlite3_vfs_find("__two")==&two );
! 4827: assert( sqlite3_vfs_find(0)==&one );
! 4828: sqlite3_vfs_register(&two, 1);
! 4829: assert( sqlite3_vfs_find("__one")==&one );
! 4830: assert( sqlite3_vfs_find("__two")==&two );
! 4831: assert( sqlite3_vfs_find(0)==&two );
! 4832: if( pMain ){
! 4833: sqlite3_vfs_register(pMain, 1);
! 4834: assert( sqlite3_vfs_find("__one")==&one );
! 4835: assert( sqlite3_vfs_find("__two")==&two );
! 4836: assert( sqlite3_vfs_find(0)==pMain );
! 4837: }
! 4838:
! 4839: /* Unlink the default VFS. Repeat until there are no more VFSes
! 4840: ** registered.
! 4841: */
! 4842: for(i=0; i<sizeof(apVfs)/sizeof(apVfs[0]); i++){
! 4843: apVfs[i] = sqlite3_vfs_find(0);
! 4844: if( apVfs[i] ){
! 4845: assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
! 4846: sqlite3_vfs_unregister(apVfs[i]);
! 4847: assert( 0==sqlite3_vfs_find(apVfs[i]->zName) );
! 4848: }
! 4849: }
! 4850: assert( 0==sqlite3_vfs_find(0) );
! 4851:
! 4852: /* Register the main VFS as non-default (will be made default, since
! 4853: ** it'll be the only one in existence).
! 4854: */
! 4855: sqlite3_vfs_register(pMain, 0);
! 4856: assert( sqlite3_vfs_find(0)==pMain );
! 4857:
! 4858: /* Un-register the main VFS again to restore an empty VFS list */
! 4859: sqlite3_vfs_unregister(pMain);
! 4860: assert( 0==sqlite3_vfs_find(0) );
! 4861:
! 4862: /* Relink all VFSes in reverse order. */
! 4863: for(i=sizeof(apVfs)/sizeof(apVfs[0])-1; i>=0; i--){
! 4864: if( apVfs[i] ){
! 4865: sqlite3_vfs_register(apVfs[i], 1);
! 4866: assert( apVfs[i]==sqlite3_vfs_find(0) );
! 4867: assert( apVfs[i]==sqlite3_vfs_find(apVfs[i]->zName) );
! 4868: }
! 4869: }
! 4870:
! 4871: /* Unregister out sample VFSes. */
! 4872: sqlite3_vfs_unregister(&one);
! 4873: sqlite3_vfs_unregister(&two);
! 4874:
! 4875: /* Unregistering a VFS that is not currently registered is harmless */
! 4876: sqlite3_vfs_unregister(&one);
! 4877: sqlite3_vfs_unregister(&two);
! 4878: assert( sqlite3_vfs_find("__one")==0 );
! 4879: assert( sqlite3_vfs_find("__two")==0 );
! 4880:
! 4881: /* We should be left with the original default VFS back as the
! 4882: ** original */
! 4883: assert( sqlite3_vfs_find(0)==pMain );
! 4884:
! 4885: return TCL_OK;
! 4886: }
! 4887:
! 4888: /*
! 4889: ** tclcmd: vfs_initfail_test
! 4890: **
! 4891: ** This TCL command attempts to vfs_find and vfs_register when the
! 4892: ** sqlite3_initialize() interface is failing. All calls should fail.
! 4893: */
! 4894: static int vfs_initfail_test(
! 4895: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 4896: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 4897: int objc, /* Number of arguments */
! 4898: Tcl_Obj *CONST objv[] /* Command arguments */
! 4899: ){
! 4900: sqlite3_vfs one;
! 4901: one.zName = "__one";
! 4902:
! 4903: if( sqlite3_vfs_find(0) ) return TCL_ERROR;
! 4904: sqlite3_vfs_register(&one, 0);
! 4905: if( sqlite3_vfs_find(0) ) return TCL_ERROR;
! 4906: sqlite3_vfs_register(&one, 1);
! 4907: if( sqlite3_vfs_find(0) ) return TCL_ERROR;
! 4908: return TCL_OK;
! 4909: }
! 4910:
! 4911: /*
! 4912: ** Saved VFSes
! 4913: */
! 4914: static sqlite3_vfs *apVfs[20];
! 4915: static int nVfs = 0;
! 4916:
! 4917: /*
! 4918: ** tclcmd: vfs_unregister_all
! 4919: **
! 4920: ** Unregister all VFSes.
! 4921: */
! 4922: static int vfs_unregister_all(
! 4923: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 4924: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 4925: int objc, /* Number of arguments */
! 4926: Tcl_Obj *CONST objv[] /* Command arguments */
! 4927: ){
! 4928: int i;
! 4929: for(i=0; i<ArraySize(apVfs); i++){
! 4930: apVfs[i] = sqlite3_vfs_find(0);
! 4931: if( apVfs[i]==0 ) break;
! 4932: sqlite3_vfs_unregister(apVfs[i]);
! 4933: }
! 4934: nVfs = i;
! 4935: return TCL_OK;
! 4936: }
! 4937: /*
! 4938: ** tclcmd: vfs_reregister_all
! 4939: **
! 4940: ** Restore all VFSes that were removed using vfs_unregister_all
! 4941: */
! 4942: static int vfs_reregister_all(
! 4943: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 4944: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 4945: int objc, /* Number of arguments */
! 4946: Tcl_Obj *CONST objv[] /* Command arguments */
! 4947: ){
! 4948: int i;
! 4949: for(i=0; i<nVfs; i++){
! 4950: sqlite3_vfs_register(apVfs[i], i==0);
! 4951: }
! 4952: return TCL_OK;
! 4953: }
! 4954:
! 4955:
! 4956: /*
! 4957: ** tclcmd: file_control_test DB
! 4958: **
! 4959: ** This TCL command runs the sqlite3_file_control interface and
! 4960: ** verifies correct operation of the same.
! 4961: */
! 4962: static int file_control_test(
! 4963: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 4964: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 4965: int objc, /* Number of arguments */
! 4966: Tcl_Obj *CONST objv[] /* Command arguments */
! 4967: ){
! 4968: int iArg = 0;
! 4969: sqlite3 *db;
! 4970: int rc;
! 4971:
! 4972: if( objc!=2 ){
! 4973: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 4974: Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
! 4975: return TCL_ERROR;
! 4976: }
! 4977: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 4978: rc = sqlite3_file_control(db, 0, 0, &iArg);
! 4979: assert( rc==SQLITE_NOTFOUND );
! 4980: rc = sqlite3_file_control(db, "notadatabase", SQLITE_FCNTL_LOCKSTATE, &iArg);
! 4981: assert( rc==SQLITE_ERROR );
! 4982: rc = sqlite3_file_control(db, "main", -1, &iArg);
! 4983: assert( rc==SQLITE_NOTFOUND );
! 4984: rc = sqlite3_file_control(db, "temp", -1, &iArg);
! 4985: assert( rc==SQLITE_NOTFOUND || rc==SQLITE_ERROR );
! 4986:
! 4987: return TCL_OK;
! 4988: }
! 4989:
! 4990:
! 4991: /*
! 4992: ** tclcmd: file_control_lasterrno_test DB
! 4993: **
! 4994: ** This TCL command runs the sqlite3_file_control interface and
! 4995: ** verifies correct operation of the SQLITE_LAST_ERRNO verb.
! 4996: */
! 4997: static int file_control_lasterrno_test(
! 4998: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 4999: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5000: int objc, /* Number of arguments */
! 5001: Tcl_Obj *CONST objv[] /* Command arguments */
! 5002: ){
! 5003: int iArg = 0;
! 5004: sqlite3 *db;
! 5005: int rc;
! 5006:
! 5007: if( objc!=2 ){
! 5008: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 5009: Tcl_GetStringFromObj(objv[0], 0), " DB", 0);
! 5010: return TCL_ERROR;
! 5011: }
! 5012: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
! 5013: return TCL_ERROR;
! 5014: }
! 5015: rc = sqlite3_file_control(db, NULL, SQLITE_LAST_ERRNO, &iArg);
! 5016: if( rc ){
! 5017: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
! 5018: return TCL_ERROR;
! 5019: }
! 5020: if( iArg!=0 ) {
! 5021: Tcl_AppendResult(interp, "Unexpected non-zero errno: ",
! 5022: Tcl_GetStringFromObj(Tcl_NewIntObj(iArg), 0), " ", 0);
! 5023: return TCL_ERROR;
! 5024: }
! 5025: return TCL_OK;
! 5026: }
! 5027:
! 5028: /*
! 5029: ** tclcmd: file_control_chunksize_test DB DBNAME SIZE
! 5030: **
! 5031: ** This TCL command runs the sqlite3_file_control interface and
! 5032: ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
! 5033: ** SQLITE_SET_LOCKPROXYFILE verbs.
! 5034: */
! 5035: static int file_control_chunksize_test(
! 5036: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5037: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5038: int objc, /* Number of arguments */
! 5039: Tcl_Obj *CONST objv[] /* Command arguments */
! 5040: ){
! 5041: int nSize; /* New chunk size */
! 5042: char *zDb; /* Db name ("main", "temp" etc.) */
! 5043: sqlite3 *db; /* Database handle */
! 5044: int rc; /* file_control() return code */
! 5045:
! 5046: if( objc!=4 ){
! 5047: Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
! 5048: return TCL_ERROR;
! 5049: }
! 5050: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
! 5051: || Tcl_GetIntFromObj(interp, objv[3], &nSize)
! 5052: ){
! 5053: return TCL_ERROR;
! 5054: }
! 5055: zDb = Tcl_GetString(objv[2]);
! 5056: if( zDb[0]=='\0' ) zDb = NULL;
! 5057:
! 5058: rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_CHUNK_SIZE, (void *)&nSize);
! 5059: if( rc ){
! 5060: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
! 5061: return TCL_ERROR;
! 5062: }
! 5063: return TCL_OK;
! 5064: }
! 5065:
! 5066: /*
! 5067: ** tclcmd: file_control_sizehint_test DB DBNAME SIZE
! 5068: **
! 5069: ** This TCL command runs the sqlite3_file_control interface
! 5070: ** with SQLITE_FCNTL_SIZE_HINT
! 5071: */
! 5072: static int file_control_sizehint_test(
! 5073: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5074: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5075: int objc, /* Number of arguments */
! 5076: Tcl_Obj *CONST objv[] /* Command arguments */
! 5077: ){
! 5078: sqlite3_int64 nSize; /* Hinted size */
! 5079: char *zDb; /* Db name ("main", "temp" etc.) */
! 5080: sqlite3 *db; /* Database handle */
! 5081: int rc; /* file_control() return code */
! 5082:
! 5083: if( objc!=4 ){
! 5084: Tcl_WrongNumArgs(interp, 1, objv, "DB DBNAME SIZE");
! 5085: return TCL_ERROR;
! 5086: }
! 5087: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
! 5088: || Tcl_GetWideIntFromObj(interp, objv[3], &nSize)
! 5089: ){
! 5090: return TCL_ERROR;
! 5091: }
! 5092: zDb = Tcl_GetString(objv[2]);
! 5093: if( zDb[0]=='\0' ) zDb = NULL;
! 5094:
! 5095: rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_SIZE_HINT, (void *)&nSize);
! 5096: if( rc ){
! 5097: Tcl_SetResult(interp, (char *)sqlite3TestErrorName(rc), TCL_STATIC);
! 5098: return TCL_ERROR;
! 5099: }
! 5100: return TCL_OK;
! 5101: }
! 5102:
! 5103: /*
! 5104: ** tclcmd: file_control_lockproxy_test DB PWD
! 5105: **
! 5106: ** This TCL command runs the sqlite3_file_control interface and
! 5107: ** verifies correct operation of the SQLITE_GET_LOCKPROXYFILE and
! 5108: ** SQLITE_SET_LOCKPROXYFILE verbs.
! 5109: */
! 5110: static int file_control_lockproxy_test(
! 5111: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5112: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5113: int objc, /* Number of arguments */
! 5114: Tcl_Obj *CONST objv[] /* Command arguments */
! 5115: ){
! 5116: sqlite3 *db;
! 5117: const char *zPwd;
! 5118: int nPwd;
! 5119:
! 5120: if( objc!=3 ){
! 5121: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 5122: Tcl_GetStringFromObj(objv[0], 0), " DB PWD", 0);
! 5123: return TCL_ERROR;
! 5124: }
! 5125: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
! 5126: return TCL_ERROR;
! 5127: }
! 5128: zPwd = Tcl_GetStringFromObj(objv[2], &nPwd);
! 5129:
! 5130: #if !defined(SQLITE_ENABLE_LOCKING_STYLE)
! 5131: # if defined(__APPLE__)
! 5132: # define SQLITE_ENABLE_LOCKING_STYLE 1
! 5133: # else
! 5134: # define SQLITE_ENABLE_LOCKING_STYLE 0
! 5135: # endif
! 5136: #endif
! 5137: #if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
! 5138: {
! 5139: char *testPath;
! 5140: int rc;
! 5141: char proxyPath[400];
! 5142:
! 5143: if( sizeof(proxyPath)<nPwd+20 ){
! 5144: Tcl_AppendResult(interp, "PWD too big", (void*)0);
! 5145: return TCL_ERROR;
! 5146: }
! 5147: sprintf(proxyPath, "%s/test.proxy", zPwd);
! 5148: rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
! 5149: if( rc ){
! 5150: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
! 5151: return TCL_ERROR;
! 5152: }
! 5153: rc = sqlite3_file_control(db, NULL, SQLITE_GET_LOCKPROXYFILE, &testPath);
! 5154: if( strncmp(proxyPath,testPath,11) ){
! 5155: Tcl_AppendResult(interp, "Lock proxy file did not match the "
! 5156: "previously assigned value", 0);
! 5157: return TCL_ERROR;
! 5158: }
! 5159: if( rc ){
! 5160: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
! 5161: return TCL_ERROR;
! 5162: }
! 5163: rc = sqlite3_file_control(db, NULL, SQLITE_SET_LOCKPROXYFILE, proxyPath);
! 5164: if( rc ){
! 5165: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
! 5166: return TCL_ERROR;
! 5167: }
! 5168: }
! 5169: #endif
! 5170: return TCL_OK;
! 5171: }
! 5172:
! 5173: /*
! 5174: ** tclcmd: file_control_win32_av_retry DB NRETRY DELAY
! 5175: **
! 5176: ** This TCL command runs the sqlite3_file_control interface with
! 5177: ** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
! 5178: */
! 5179: static int file_control_win32_av_retry(
! 5180: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5181: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5182: int objc, /* Number of arguments */
! 5183: Tcl_Obj *CONST objv[] /* Command arguments */
! 5184: ){
! 5185: sqlite3 *db;
! 5186: int rc;
! 5187: int a[2];
! 5188: char z[100];
! 5189:
! 5190: if( objc!=4 ){
! 5191: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 5192: Tcl_GetStringFromObj(objv[0], 0), " DB NRETRY DELAY", 0);
! 5193: return TCL_ERROR;
! 5194: }
! 5195: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
! 5196: return TCL_ERROR;
! 5197: }
! 5198: if( Tcl_GetIntFromObj(interp, objv[2], &a[0]) ) return TCL_ERROR;
! 5199: if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
! 5200: rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
! 5201: sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
! 5202: Tcl_AppendResult(interp, z, (char*)0);
! 5203: return TCL_OK;
! 5204: }
! 5205:
! 5206: /*
! 5207: ** tclcmd: file_control_persist_wal DB PERSIST-FLAG
! 5208: **
! 5209: ** This TCL command runs the sqlite3_file_control interface with
! 5210: ** the SQLITE_FCNTL_PERSIST_WAL opcode.
! 5211: */
! 5212: static int file_control_persist_wal(
! 5213: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5214: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5215: int objc, /* Number of arguments */
! 5216: Tcl_Obj *CONST objv[] /* Command arguments */
! 5217: ){
! 5218: sqlite3 *db;
! 5219: int rc;
! 5220: int bPersist;
! 5221: char z[100];
! 5222:
! 5223: if( objc!=3 ){
! 5224: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 5225: Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
! 5226: return TCL_ERROR;
! 5227: }
! 5228: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
! 5229: return TCL_ERROR;
! 5230: }
! 5231: if( Tcl_GetIntFromObj(interp, objv[2], &bPersist) ) return TCL_ERROR;
! 5232: rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, (void*)&bPersist);
! 5233: sqlite3_snprintf(sizeof(z), z, "%d %d", rc, bPersist);
! 5234: Tcl_AppendResult(interp, z, (char*)0);
! 5235: return TCL_OK;
! 5236: }
! 5237:
! 5238: /*
! 5239: ** tclcmd: file_control_powersafe_overwrite DB PSOW-FLAG
! 5240: **
! 5241: ** This TCL command runs the sqlite3_file_control interface with
! 5242: ** the SQLITE_FCNTL_POWERSAFE_OVERWRITE opcode.
! 5243: */
! 5244: static int file_control_powersafe_overwrite(
! 5245: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5246: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5247: int objc, /* Number of arguments */
! 5248: Tcl_Obj *CONST objv[] /* Command arguments */
! 5249: ){
! 5250: sqlite3 *db;
! 5251: int rc;
! 5252: int b;
! 5253: char z[100];
! 5254:
! 5255: if( objc!=3 ){
! 5256: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 5257: Tcl_GetStringFromObj(objv[0], 0), " DB FLAG", 0);
! 5258: return TCL_ERROR;
! 5259: }
! 5260: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
! 5261: return TCL_ERROR;
! 5262: }
! 5263: if( Tcl_GetIntFromObj(interp, objv[2], &b) ) return TCL_ERROR;
! 5264: rc = sqlite3_file_control(db,NULL,SQLITE_FCNTL_POWERSAFE_OVERWRITE,(void*)&b);
! 5265: sqlite3_snprintf(sizeof(z), z, "%d %d", rc, b);
! 5266: Tcl_AppendResult(interp, z, (char*)0);
! 5267: return TCL_OK;
! 5268: }
! 5269:
! 5270:
! 5271: /*
! 5272: ** tclcmd: file_control_vfsname DB ?AUXDB?
! 5273: **
! 5274: ** Return a string that describes the stack of VFSes.
! 5275: */
! 5276: static int file_control_vfsname(
! 5277: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5278: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5279: int objc, /* Number of arguments */
! 5280: Tcl_Obj *CONST objv[] /* Command arguments */
! 5281: ){
! 5282: sqlite3 *db;
! 5283: const char *zDbName = "main";
! 5284: char *zVfsName = 0;
! 5285:
! 5286: if( objc!=2 && objc!=3 ){
! 5287: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 5288: Tcl_GetStringFromObj(objv[0], 0), " DB ?AUXDB?", 0);
! 5289: return TCL_ERROR;
! 5290: }
! 5291: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
! 5292: return TCL_ERROR;
! 5293: }
! 5294: if( objc==3 ){
! 5295: zDbName = Tcl_GetString(objv[2]);
! 5296: }
! 5297: sqlite3_file_control(db, zDbName, SQLITE_FCNTL_VFSNAME,(void*)&zVfsName);
! 5298: Tcl_AppendResult(interp, zVfsName, (char*)0);
! 5299: sqlite3_free(zVfsName);
! 5300: return TCL_OK;
! 5301: }
! 5302:
! 5303:
! 5304: /*
! 5305: ** tclcmd: sqlite3_vfs_list
! 5306: **
! 5307: ** Return a tcl list containing the names of all registered vfs's.
! 5308: */
! 5309: static int vfs_list(
! 5310: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5311: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5312: int objc, /* Number of arguments */
! 5313: Tcl_Obj *CONST objv[] /* Command arguments */
! 5314: ){
! 5315: sqlite3_vfs *pVfs;
! 5316: Tcl_Obj *pRet = Tcl_NewObj();
! 5317: if( objc!=1 ){
! 5318: Tcl_WrongNumArgs(interp, 1, objv, "");
! 5319: return TCL_ERROR;
! 5320: }
! 5321: for(pVfs=sqlite3_vfs_find(0); pVfs; pVfs=pVfs->pNext){
! 5322: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj(pVfs->zName, -1));
! 5323: }
! 5324: Tcl_SetObjResult(interp, pRet);
! 5325: return TCL_OK;
! 5326: }
! 5327:
! 5328: /*
! 5329: ** tclcmd: sqlite3_limit DB ID VALUE
! 5330: **
! 5331: ** This TCL command runs the sqlite3_limit interface and
! 5332: ** verifies correct operation of the same.
! 5333: */
! 5334: static int test_limit(
! 5335: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5336: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5337: int objc, /* Number of arguments */
! 5338: Tcl_Obj *CONST objv[] /* Command arguments */
! 5339: ){
! 5340: sqlite3 *db;
! 5341: int rc;
! 5342: static const struct {
! 5343: char *zName;
! 5344: int id;
! 5345: } aId[] = {
! 5346: { "SQLITE_LIMIT_LENGTH", SQLITE_LIMIT_LENGTH },
! 5347: { "SQLITE_LIMIT_SQL_LENGTH", SQLITE_LIMIT_SQL_LENGTH },
! 5348: { "SQLITE_LIMIT_COLUMN", SQLITE_LIMIT_COLUMN },
! 5349: { "SQLITE_LIMIT_EXPR_DEPTH", SQLITE_LIMIT_EXPR_DEPTH },
! 5350: { "SQLITE_LIMIT_COMPOUND_SELECT", SQLITE_LIMIT_COMPOUND_SELECT },
! 5351: { "SQLITE_LIMIT_VDBE_OP", SQLITE_LIMIT_VDBE_OP },
! 5352: { "SQLITE_LIMIT_FUNCTION_ARG", SQLITE_LIMIT_FUNCTION_ARG },
! 5353: { "SQLITE_LIMIT_ATTACHED", SQLITE_LIMIT_ATTACHED },
! 5354: { "SQLITE_LIMIT_LIKE_PATTERN_LENGTH", SQLITE_LIMIT_LIKE_PATTERN_LENGTH },
! 5355: { "SQLITE_LIMIT_VARIABLE_NUMBER", SQLITE_LIMIT_VARIABLE_NUMBER },
! 5356: { "SQLITE_LIMIT_TRIGGER_DEPTH", SQLITE_LIMIT_TRIGGER_DEPTH },
! 5357:
! 5358: /* Out of range test cases */
! 5359: { "SQLITE_LIMIT_TOOSMALL", -1, },
! 5360: { "SQLITE_LIMIT_TOOBIG", SQLITE_LIMIT_TRIGGER_DEPTH+1 },
! 5361: };
! 5362: int i, id;
! 5363: int val;
! 5364: const char *zId;
! 5365:
! 5366: if( objc!=4 ){
! 5367: Tcl_AppendResult(interp, "wrong # args: should be \"",
! 5368: Tcl_GetStringFromObj(objv[0], 0), " DB ID VALUE", 0);
! 5369: return TCL_ERROR;
! 5370: }
! 5371: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 5372: zId = Tcl_GetString(objv[2]);
! 5373: for(i=0; i<sizeof(aId)/sizeof(aId[0]); i++){
! 5374: if( strcmp(zId, aId[i].zName)==0 ){
! 5375: id = aId[i].id;
! 5376: break;
! 5377: }
! 5378: }
! 5379: if( i>=sizeof(aId)/sizeof(aId[0]) ){
! 5380: Tcl_AppendResult(interp, "unknown limit type: ", zId, (char*)0);
! 5381: return TCL_ERROR;
! 5382: }
! 5383: if( Tcl_GetIntFromObj(interp, objv[3], &val) ) return TCL_ERROR;
! 5384: rc = sqlite3_limit(db, id, val);
! 5385: Tcl_SetObjResult(interp, Tcl_NewIntObj(rc));
! 5386: return TCL_OK;
! 5387: }
! 5388:
! 5389: /*
! 5390: ** tclcmd: save_prng_state
! 5391: **
! 5392: ** Save the state of the pseudo-random number generator.
! 5393: ** At the same time, verify that sqlite3_test_control works even when
! 5394: ** called with an out-of-range opcode.
! 5395: */
! 5396: static int save_prng_state(
! 5397: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5398: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5399: int objc, /* Number of arguments */
! 5400: Tcl_Obj *CONST objv[] /* Command arguments */
! 5401: ){
! 5402: int rc = sqlite3_test_control(9999);
! 5403: assert( rc==0 );
! 5404: rc = sqlite3_test_control(-1);
! 5405: assert( rc==0 );
! 5406: sqlite3_test_control(SQLITE_TESTCTRL_PRNG_SAVE);
! 5407: return TCL_OK;
! 5408: }
! 5409: /*
! 5410: ** tclcmd: restore_prng_state
! 5411: */
! 5412: static int restore_prng_state(
! 5413: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5414: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5415: int objc, /* Number of arguments */
! 5416: Tcl_Obj *CONST objv[] /* Command arguments */
! 5417: ){
! 5418: sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESTORE);
! 5419: return TCL_OK;
! 5420: }
! 5421: /*
! 5422: ** tclcmd: reset_prng_state
! 5423: */
! 5424: static int reset_prng_state(
! 5425: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5426: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5427: int objc, /* Number of arguments */
! 5428: Tcl_Obj *CONST objv[] /* Command arguments */
! 5429: ){
! 5430: sqlite3_test_control(SQLITE_TESTCTRL_PRNG_RESET);
! 5431: return TCL_OK;
! 5432: }
! 5433:
! 5434: /*
! 5435: ** tclcmd: pcache_stats
! 5436: */
! 5437: static int test_pcache_stats(
! 5438: ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
! 5439: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5440: int objc, /* Number of arguments */
! 5441: Tcl_Obj *CONST objv[] /* Command arguments */
! 5442: ){
! 5443: int nMin;
! 5444: int nMax;
! 5445: int nCurrent;
! 5446: int nRecyclable;
! 5447: Tcl_Obj *pRet;
! 5448:
! 5449: sqlite3PcacheStats(&nCurrent, &nMax, &nMin, &nRecyclable);
! 5450:
! 5451: pRet = Tcl_NewObj();
! 5452: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("current", -1));
! 5453: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCurrent));
! 5454: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("max", -1));
! 5455: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMax));
! 5456: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("min", -1));
! 5457: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nMin));
! 5458: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewStringObj("recyclable", -1));
! 5459: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nRecyclable));
! 5460:
! 5461: Tcl_SetObjResult(interp, pRet);
! 5462:
! 5463: return TCL_OK;
! 5464: }
! 5465:
! 5466: #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
! 5467: static void test_unlock_notify_cb(void **aArg, int nArg){
! 5468: int ii;
! 5469: for(ii=0; ii<nArg; ii++){
! 5470: Tcl_EvalEx((Tcl_Interp *)aArg[ii], "unlock_notify", -1, TCL_EVAL_GLOBAL);
! 5471: }
! 5472: }
! 5473: #endif /* SQLITE_ENABLE_UNLOCK_NOTIFY */
! 5474:
! 5475: /*
! 5476: ** tclcmd: sqlite3_unlock_notify db
! 5477: */
! 5478: #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
! 5479: static int test_unlock_notify(
! 5480: ClientData clientData, /* Unused */
! 5481: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5482: int objc, /* Number of arguments */
! 5483: Tcl_Obj *CONST objv[] /* Command arguments */
! 5484: ){
! 5485: sqlite3 *db;
! 5486: int rc;
! 5487:
! 5488: if( objc!=2 ){
! 5489: Tcl_WrongNumArgs(interp, 1, objv, "DB");
! 5490: return TCL_ERROR;
! 5491: }
! 5492:
! 5493: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
! 5494: return TCL_ERROR;
! 5495: }
! 5496: rc = sqlite3_unlock_notify(db, test_unlock_notify_cb, (void *)interp);
! 5497: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
! 5498: return TCL_OK;
! 5499: }
! 5500: #endif
! 5501:
! 5502: /*
! 5503: ** tclcmd: sqlite3_wal_checkpoint db ?NAME?
! 5504: */
! 5505: static int test_wal_checkpoint(
! 5506: ClientData clientData, /* Unused */
! 5507: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5508: int objc, /* Number of arguments */
! 5509: Tcl_Obj *CONST objv[] /* Command arguments */
! 5510: ){
! 5511: char *zDb = 0;
! 5512: sqlite3 *db;
! 5513: int rc;
! 5514:
! 5515: if( objc!=3 && objc!=2 ){
! 5516: Tcl_WrongNumArgs(interp, 1, objv, "DB ?NAME?");
! 5517: return TCL_ERROR;
! 5518: }
! 5519:
! 5520: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
! 5521: return TCL_ERROR;
! 5522: }
! 5523: if( objc==3 ){
! 5524: zDb = Tcl_GetString(objv[2]);
! 5525: }
! 5526: rc = sqlite3_wal_checkpoint(db, zDb);
! 5527: Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC);
! 5528: return TCL_OK;
! 5529: }
! 5530:
! 5531: /*
! 5532: ** tclcmd: sqlite3_wal_checkpoint_v2 db MODE ?NAME?
! 5533: **
! 5534: ** This command calls the wal_checkpoint_v2() function with the specified
! 5535: ** mode argument (passive, full or restart). If present, the database name
! 5536: ** NAME is passed as the second argument to wal_checkpoint_v2(). If it the
! 5537: ** NAME argument is not present, a NULL pointer is passed instead.
! 5538: **
! 5539: ** If wal_checkpoint_v2() returns any value other than SQLITE_BUSY or
! 5540: ** SQLITE_OK, then this command returns TCL_ERROR. The Tcl result is set
! 5541: ** to the error message obtained from sqlite3_errmsg().
! 5542: **
! 5543: ** Otherwise, this command returns a list of three integers. The first integer
! 5544: ** is 1 if SQLITE_BUSY was returned, or 0 otherwise. The following two integers
! 5545: ** are the values returned via the output paramaters by wal_checkpoint_v2() -
! 5546: ** the number of frames in the log and the number of frames in the log
! 5547: ** that have been checkpointed.
! 5548: */
! 5549: static int test_wal_checkpoint_v2(
! 5550: ClientData clientData, /* Unused */
! 5551: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5552: int objc, /* Number of arguments */
! 5553: Tcl_Obj *CONST objv[] /* Command arguments */
! 5554: ){
! 5555: char *zDb = 0;
! 5556: sqlite3 *db;
! 5557: int rc;
! 5558:
! 5559: int eMode;
! 5560: int nLog = -555;
! 5561: int nCkpt = -555;
! 5562: Tcl_Obj *pRet;
! 5563:
! 5564: const char * aMode[] = { "passive", "full", "restart", 0 };
! 5565: assert( SQLITE_CHECKPOINT_PASSIVE==0 );
! 5566: assert( SQLITE_CHECKPOINT_FULL==1 );
! 5567: assert( SQLITE_CHECKPOINT_RESTART==2 );
! 5568:
! 5569: if( objc!=3 && objc!=4 ){
! 5570: Tcl_WrongNumArgs(interp, 1, objv, "DB MODE ?NAME?");
! 5571: return TCL_ERROR;
! 5572: }
! 5573:
! 5574: if( objc==4 ){
! 5575: zDb = Tcl_GetString(objv[3]);
! 5576: }
! 5577: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db)
! 5578: || Tcl_GetIndexFromObj(interp, objv[2], aMode, "mode", 0, &eMode)
! 5579: ){
! 5580: return TCL_ERROR;
! 5581: }
! 5582:
! 5583: rc = sqlite3_wal_checkpoint_v2(db, zDb, eMode, &nLog, &nCkpt);
! 5584: if( rc!=SQLITE_OK && rc!=SQLITE_BUSY ){
! 5585: Tcl_SetResult(interp, (char *)sqlite3_errmsg(db), TCL_VOLATILE);
! 5586: return TCL_ERROR;
! 5587: }
! 5588:
! 5589: pRet = Tcl_NewObj();
! 5590: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(rc==SQLITE_BUSY?1:0));
! 5591: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nLog));
! 5592: Tcl_ListObjAppendElement(interp, pRet, Tcl_NewIntObj(nCkpt));
! 5593: Tcl_SetObjResult(interp, pRet);
! 5594:
! 5595: return TCL_OK;
! 5596: }
! 5597:
! 5598: /*
! 5599: ** tclcmd: test_sqlite3_log ?SCRIPT?
! 5600: */
! 5601: static struct LogCallback {
! 5602: Tcl_Interp *pInterp;
! 5603: Tcl_Obj *pObj;
! 5604: } logcallback = {0, 0};
! 5605: static void xLogcallback(void *unused, int err, char *zMsg){
! 5606: Tcl_Obj *pNew = Tcl_DuplicateObj(logcallback.pObj);
! 5607: Tcl_IncrRefCount(pNew);
! 5608: Tcl_ListObjAppendElement(
! 5609: 0, pNew, Tcl_NewStringObj(sqlite3TestErrorName(err), -1)
! 5610: );
! 5611: Tcl_ListObjAppendElement(0, pNew, Tcl_NewStringObj(zMsg, -1));
! 5612: Tcl_EvalObjEx(logcallback.pInterp, pNew, TCL_EVAL_GLOBAL|TCL_EVAL_DIRECT);
! 5613: Tcl_DecrRefCount(pNew);
! 5614: }
! 5615: static int test_sqlite3_log(
! 5616: ClientData clientData,
! 5617: Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
! 5618: int objc, /* Number of arguments */
! 5619: Tcl_Obj *CONST objv[] /* Command arguments */
! 5620: ){
! 5621: if( objc>2 ){
! 5622: Tcl_WrongNumArgs(interp, 1, objv, "SCRIPT");
! 5623: return TCL_ERROR;
! 5624: }
! 5625: if( logcallback.pObj ){
! 5626: Tcl_DecrRefCount(logcallback.pObj);
! 5627: logcallback.pObj = 0;
! 5628: logcallback.pInterp = 0;
! 5629: sqlite3_config(SQLITE_CONFIG_LOG, 0, 0);
! 5630: }
! 5631: if( objc>1 ){
! 5632: logcallback.pObj = objv[1];
! 5633: Tcl_IncrRefCount(logcallback.pObj);
! 5634: logcallback.pInterp = interp;
! 5635: sqlite3_config(SQLITE_CONFIG_LOG, xLogcallback, 0);
! 5636: }
! 5637: return TCL_OK;
! 5638: }
! 5639:
! 5640: /*
! 5641: ** tcl_objproc COMMANDNAME ARGS...
! 5642: **
! 5643: ** Run a TCL command using its objProc interface. Throw an error if
! 5644: ** the command has no objProc interface.
! 5645: */
! 5646: static int runAsObjProc(
! 5647: void * clientData,
! 5648: Tcl_Interp *interp,
! 5649: int objc,
! 5650: Tcl_Obj *CONST objv[]
! 5651: ){
! 5652: Tcl_CmdInfo cmdInfo;
! 5653: if( objc<2 ){
! 5654: Tcl_WrongNumArgs(interp, 1, objv, "COMMAND ...");
! 5655: return TCL_ERROR;
! 5656: }
! 5657: if( !Tcl_GetCommandInfo(interp, Tcl_GetString(objv[1]), &cmdInfo) ){
! 5658: Tcl_AppendResult(interp, "command not found: ",
! 5659: Tcl_GetString(objv[1]), (char*)0);
! 5660: return TCL_ERROR;
! 5661: }
! 5662: if( cmdInfo.objProc==0 ){
! 5663: Tcl_AppendResult(interp, "command has no objProc: ",
! 5664: Tcl_GetString(objv[1]), (char*)0);
! 5665: return TCL_ERROR;
! 5666: }
! 5667: return cmdInfo.objProc(cmdInfo.objClientData, interp, objc-1, objv+1);
! 5668: }
! 5669:
! 5670: #ifndef SQLITE_OMIT_EXPLAIN
! 5671: /*
! 5672: ** WARNING: The following function, printExplainQueryPlan() is an exact
! 5673: ** copy of example code from eqp.in (eqp.html). If this code is modified,
! 5674: ** then the documentation copy needs to be modified as well.
! 5675: */
! 5676: /*
! 5677: ** Argument pStmt is a prepared SQL statement. This function compiles
! 5678: ** an EXPLAIN QUERY PLAN command to report on the prepared statement,
! 5679: ** and prints the report to stdout using printf().
! 5680: */
! 5681: int printExplainQueryPlan(sqlite3_stmt *pStmt){
! 5682: const char *zSql; /* Input SQL */
! 5683: char *zExplain; /* SQL with EXPLAIN QUERY PLAN prepended */
! 5684: sqlite3_stmt *pExplain; /* Compiled EXPLAIN QUERY PLAN command */
! 5685: int rc; /* Return code from sqlite3_prepare_v2() */
! 5686:
! 5687: zSql = sqlite3_sql(pStmt);
! 5688: if( zSql==0 ) return SQLITE_ERROR;
! 5689:
! 5690: zExplain = sqlite3_mprintf("EXPLAIN QUERY PLAN %s", zSql);
! 5691: if( zExplain==0 ) return SQLITE_NOMEM;
! 5692:
! 5693: rc = sqlite3_prepare_v2(sqlite3_db_handle(pStmt), zExplain, -1, &pExplain, 0);
! 5694: sqlite3_free(zExplain);
! 5695: if( rc!=SQLITE_OK ) return rc;
! 5696:
! 5697: while( SQLITE_ROW==sqlite3_step(pExplain) ){
! 5698: int iSelectid = sqlite3_column_int(pExplain, 0);
! 5699: int iOrder = sqlite3_column_int(pExplain, 1);
! 5700: int iFrom = sqlite3_column_int(pExplain, 2);
! 5701: const char *zDetail = (const char *)sqlite3_column_text(pExplain, 3);
! 5702:
! 5703: printf("%d %d %d %s\n", iSelectid, iOrder, iFrom, zDetail);
! 5704: }
! 5705:
! 5706: return sqlite3_finalize(pExplain);
! 5707: }
! 5708:
! 5709: static int test_print_eqp(
! 5710: void * clientData,
! 5711: Tcl_Interp *interp,
! 5712: int objc,
! 5713: Tcl_Obj *CONST objv[]
! 5714: ){
! 5715: int rc;
! 5716: sqlite3_stmt *pStmt;
! 5717:
! 5718: if( objc!=2 ){
! 5719: Tcl_WrongNumArgs(interp, 1, objv, "STMT");
! 5720: return TCL_ERROR;
! 5721: }
! 5722: if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
! 5723: rc = printExplainQueryPlan(pStmt);
! 5724: /* This is needed on Windows so that a test case using this
! 5725: ** function can open a read pipe and get the output of
! 5726: ** printExplainQueryPlan() immediately.
! 5727: */
! 5728: fflush(stdout);
! 5729: Tcl_SetResult(interp, (char *)t1ErrorName(rc), 0);
! 5730: return TCL_OK;
! 5731: }
! 5732: #endif /* SQLITE_OMIT_EXPLAIN */
! 5733:
! 5734: /*
! 5735: ** sqlite3_test_control VERB ARGS...
! 5736: */
! 5737: static int test_test_control(
! 5738: void * clientData,
! 5739: Tcl_Interp *interp,
! 5740: int objc,
! 5741: Tcl_Obj *CONST objv[]
! 5742: ){
! 5743: struct Verb {
! 5744: const char *zName;
! 5745: int i;
! 5746: } aVerb[] = {
! 5747: { "SQLITE_TESTCTRL_LOCALTIME_FAULT", SQLITE_TESTCTRL_LOCALTIME_FAULT },
! 5748: };
! 5749: int iVerb;
! 5750: int iFlag;
! 5751: int rc;
! 5752:
! 5753: if( objc<2 ){
! 5754: Tcl_WrongNumArgs(interp, 1, objv, "VERB ARGS...");
! 5755: return TCL_ERROR;
! 5756: }
! 5757:
! 5758: rc = Tcl_GetIndexFromObjStruct(
! 5759: interp, objv[1], aVerb, sizeof(aVerb[0]), "VERB", 0, &iVerb
! 5760: );
! 5761: if( rc!=TCL_OK ) return rc;
! 5762:
! 5763: iFlag = aVerb[iVerb].i;
! 5764: switch( iFlag ){
! 5765: case SQLITE_TESTCTRL_LOCALTIME_FAULT: {
! 5766: int val;
! 5767: if( objc!=3 ){
! 5768: Tcl_WrongNumArgs(interp, 2, objv, "ONOFF");
! 5769: return TCL_ERROR;
! 5770: }
! 5771: if( Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
! 5772: sqlite3_test_control(SQLITE_TESTCTRL_LOCALTIME_FAULT, val);
! 5773: break;
! 5774: }
! 5775: }
! 5776:
! 5777: Tcl_ResetResult(interp);
! 5778: return TCL_OK;
! 5779: }
! 5780:
! 5781: #if SQLITE_OS_WIN
! 5782: /*
! 5783: ** Information passed from the main thread into the windows file locker
! 5784: ** background thread.
! 5785: */
! 5786: struct win32FileLocker {
! 5787: char *evName; /* Name of event to signal thread startup */
! 5788: HANDLE h; /* Handle of the file to be locked */
! 5789: int delay1; /* Delay before locking */
! 5790: int delay2; /* Delay before unlocking */
! 5791: int ok; /* Finished ok */
! 5792: int err; /* True if an error occurs */
! 5793: };
! 5794: #endif
! 5795:
! 5796:
! 5797: #if SQLITE_OS_WIN
! 5798: /*
! 5799: ** The background thread that does file locking.
! 5800: */
! 5801: static void win32_file_locker(void *pAppData){
! 5802: struct win32FileLocker *p = (struct win32FileLocker*)pAppData;
! 5803: if( p->evName ){
! 5804: HANDLE ev = OpenEvent(EVENT_MODIFY_STATE, FALSE, p->evName);
! 5805: if ( ev ){
! 5806: SetEvent(ev);
! 5807: CloseHandle(ev);
! 5808: }
! 5809: }
! 5810: if( p->delay1 ) Sleep(p->delay1);
! 5811: if( LockFile(p->h, 0, 0, 100000000, 0) ){
! 5812: Sleep(p->delay2);
! 5813: UnlockFile(p->h, 0, 0, 100000000, 0);
! 5814: p->ok = 1;
! 5815: }else{
! 5816: p->err = 1;
! 5817: }
! 5818: CloseHandle(p->h);
! 5819: p->h = 0;
! 5820: p->delay1 = 0;
! 5821: p->delay2 = 0;
! 5822: }
! 5823: #endif
! 5824:
! 5825: #if SQLITE_OS_WIN
! 5826: /*
! 5827: ** lock_win32_file FILENAME DELAY1 DELAY2
! 5828: **
! 5829: ** Get an exclusive manditory lock on file for DELAY2 milliseconds.
! 5830: ** Wait DELAY1 milliseconds before acquiring the lock.
! 5831: */
! 5832: static int win32_file_lock(
! 5833: void * clientData,
! 5834: Tcl_Interp *interp,
! 5835: int objc,
! 5836: Tcl_Obj *CONST objv[]
! 5837: ){
! 5838: static struct win32FileLocker x = { "win32_file_lock", 0, 0, 0, 0, 0 };
! 5839: const char *zFilename;
! 5840: char zBuf[200];
! 5841: int retry = 0;
! 5842: HANDLE ev;
! 5843: DWORD wResult;
! 5844:
! 5845: if( objc!=4 && objc!=1 ){
! 5846: Tcl_WrongNumArgs(interp, 1, objv, "FILENAME DELAY1 DELAY2");
! 5847: return TCL_ERROR;
! 5848: }
! 5849: if( objc==1 ){
! 5850: sqlite3_snprintf(sizeof(zBuf), zBuf, "%d %d %d %d %d",
! 5851: x.ok, x.err, x.delay1, x.delay2, x.h);
! 5852: Tcl_AppendResult(interp, zBuf, (char*)0);
! 5853: return TCL_OK;
! 5854: }
! 5855: while( x.h && retry<30 ){
! 5856: retry++;
! 5857: Sleep(100);
! 5858: }
! 5859: if( x.h ){
! 5860: Tcl_AppendResult(interp, "busy", (char*)0);
! 5861: return TCL_ERROR;
! 5862: }
! 5863: if( Tcl_GetIntFromObj(interp, objv[2], &x.delay1) ) return TCL_ERROR;
! 5864: if( Tcl_GetIntFromObj(interp, objv[3], &x.delay2) ) return TCL_ERROR;
! 5865: zFilename = Tcl_GetString(objv[1]);
! 5866: x.h = CreateFile(zFilename, GENERIC_READ|GENERIC_WRITE,
! 5867: FILE_SHARE_READ|FILE_SHARE_WRITE, 0, OPEN_ALWAYS,
! 5868: FILE_ATTRIBUTE_NORMAL, 0);
! 5869: if( !x.h ){
! 5870: Tcl_AppendResult(interp, "cannot open file: ", zFilename, (char*)0);
! 5871: return TCL_ERROR;
! 5872: }
! 5873: ev = CreateEvent(NULL, TRUE, FALSE, x.evName);
! 5874: if ( !ev ){
! 5875: Tcl_AppendResult(interp, "cannot create event: ", x.evName, (char*)0);
! 5876: return TCL_ERROR;
! 5877: }
! 5878: _beginthread(win32_file_locker, 0, (void*)&x);
! 5879: Sleep(0);
! 5880: if ( (wResult = WaitForSingleObject(ev, 10000))!=WAIT_OBJECT_0 ){
! 5881: sqlite3_snprintf(sizeof(zBuf), zBuf, "0x%x", wResult);
! 5882: Tcl_AppendResult(interp, "wait failed: ", zBuf, (char*)0);
! 5883: CloseHandle(ev);
! 5884: return TCL_ERROR;
! 5885: }
! 5886: CloseHandle(ev);
! 5887: return TCL_OK;
! 5888: }
! 5889: #endif
! 5890:
! 5891:
! 5892: /*
! 5893: ** optimization_control DB OPT BOOLEAN
! 5894: **
! 5895: ** Enable or disable query optimizations using the sqlite3_test_control()
! 5896: ** interface. Disable if BOOLEAN is false and enable if BOOLEAN is true.
! 5897: ** OPT is the name of the optimization to be disabled.
! 5898: */
! 5899: static int optimization_control(
! 5900: void * clientData,
! 5901: Tcl_Interp *interp,
! 5902: int objc,
! 5903: Tcl_Obj *CONST objv[]
! 5904: ){
! 5905: int i;
! 5906: sqlite3 *db;
! 5907: const char *zOpt;
! 5908: int onoff;
! 5909: int mask;
! 5910: static const struct {
! 5911: const char *zOptName;
! 5912: int mask;
! 5913: } aOpt[] = {
! 5914: { "all", SQLITE_OptMask },
! 5915: { "query-flattener", SQLITE_QueryFlattener },
! 5916: { "column-cache", SQLITE_ColumnCache },
! 5917: { "index-sort", SQLITE_IndexSort },
! 5918: { "index-search", SQLITE_IndexSearch },
! 5919: { "index-cover", SQLITE_IndexCover },
! 5920: { "groupby-order", SQLITE_GroupByOrder },
! 5921: { "factor-constants", SQLITE_FactorOutConst },
! 5922: { "real-as-int", SQLITE_IdxRealAsInt },
! 5923: };
! 5924:
! 5925: if( objc!=4 ){
! 5926: Tcl_WrongNumArgs(interp, 1, objv, "DB OPT BOOLEAN");
! 5927: return TCL_ERROR;
! 5928: }
! 5929: if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
! 5930: if( Tcl_GetBooleanFromObj(interp, objv[3], &onoff) ) return TCL_ERROR;
! 5931: zOpt = Tcl_GetString(objv[2]);
! 5932: for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
! 5933: if( strcmp(zOpt, aOpt[i].zOptName)==0 ){
! 5934: mask = aOpt[i].mask;
! 5935: break;
! 5936: }
! 5937: }
! 5938: if( onoff ) mask = ~mask;
! 5939: if( i>=sizeof(aOpt)/sizeof(aOpt[0]) ){
! 5940: Tcl_AppendResult(interp, "unknown optimization - should be one of:",
! 5941: (char*)0);
! 5942: for(i=0; i<sizeof(aOpt)/sizeof(aOpt[0]); i++){
! 5943: Tcl_AppendResult(interp, " ", aOpt[i].zOptName);
! 5944: }
! 5945: return TCL_ERROR;
! 5946: }
! 5947: sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS, db, mask);
! 5948: return TCL_OK;
! 5949: }
! 5950:
! 5951: /*
! 5952: ** Register commands with the TCL interpreter.
! 5953: */
! 5954: int Sqlitetest1_Init(Tcl_Interp *interp){
! 5955: extern int sqlite3_search_count;
! 5956: extern int sqlite3_found_count;
! 5957: extern int sqlite3_interrupt_count;
! 5958: extern int sqlite3_open_file_count;
! 5959: extern int sqlite3_sort_count;
! 5960: extern int sqlite3_current_time;
! 5961: #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
! 5962: extern int sqlite3_hostid_num;
! 5963: #endif
! 5964: extern int sqlite3_max_blobsize;
! 5965: extern int sqlite3BtreeSharedCacheReport(void*,
! 5966: Tcl_Interp*,int,Tcl_Obj*CONST*);
! 5967: static struct {
! 5968: char *zName;
! 5969: Tcl_CmdProc *xProc;
! 5970: } aCmd[] = {
! 5971: { "db_enter", (Tcl_CmdProc*)db_enter },
! 5972: { "db_leave", (Tcl_CmdProc*)db_leave },
! 5973: { "sqlite3_mprintf_int", (Tcl_CmdProc*)sqlite3_mprintf_int },
! 5974: { "sqlite3_mprintf_int64", (Tcl_CmdProc*)sqlite3_mprintf_int64 },
! 5975: { "sqlite3_mprintf_long", (Tcl_CmdProc*)sqlite3_mprintf_long },
! 5976: { "sqlite3_mprintf_str", (Tcl_CmdProc*)sqlite3_mprintf_str },
! 5977: { "sqlite3_snprintf_str", (Tcl_CmdProc*)sqlite3_snprintf_str },
! 5978: { "sqlite3_mprintf_stronly", (Tcl_CmdProc*)sqlite3_mprintf_stronly},
! 5979: { "sqlite3_mprintf_double", (Tcl_CmdProc*)sqlite3_mprintf_double },
! 5980: { "sqlite3_mprintf_scaled", (Tcl_CmdProc*)sqlite3_mprintf_scaled },
! 5981: { "sqlite3_mprintf_hexdouble", (Tcl_CmdProc*)sqlite3_mprintf_hexdouble},
! 5982: { "sqlite3_mprintf_z_test", (Tcl_CmdProc*)test_mprintf_z },
! 5983: { "sqlite3_mprintf_n_test", (Tcl_CmdProc*)test_mprintf_n },
! 5984: { "sqlite3_snprintf_int", (Tcl_CmdProc*)test_snprintf_int },
! 5985: { "sqlite3_last_insert_rowid", (Tcl_CmdProc*)test_last_rowid },
! 5986: { "sqlite3_exec_printf", (Tcl_CmdProc*)test_exec_printf },
! 5987: { "sqlite3_exec_hex", (Tcl_CmdProc*)test_exec_hex },
! 5988: { "sqlite3_exec", (Tcl_CmdProc*)test_exec },
! 5989: { "sqlite3_exec_nr", (Tcl_CmdProc*)test_exec_nr },
! 5990: #ifndef SQLITE_OMIT_GET_TABLE
! 5991: { "sqlite3_get_table_printf", (Tcl_CmdProc*)test_get_table_printf },
! 5992: #endif
! 5993: { "sqlite3_close", (Tcl_CmdProc*)sqlite_test_close },
! 5994: { "sqlite3_create_function", (Tcl_CmdProc*)test_create_function },
! 5995: { "sqlite3_create_aggregate", (Tcl_CmdProc*)test_create_aggregate },
! 5996: { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func },
! 5997: { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort },
! 5998: { "sqlite_bind", (Tcl_CmdProc*)test_bind },
! 5999: { "breakpoint", (Tcl_CmdProc*)test_breakpoint },
! 6000: { "sqlite3_key", (Tcl_CmdProc*)test_key },
! 6001: { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
! 6002: { "sqlite_set_magic", (Tcl_CmdProc*)sqlite_set_magic },
! 6003: { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
! 6004: { "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
! 6005: { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
! 6006: { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },
! 6007: { "sqlite3_stack_used", (Tcl_CmdProc*)test_stack_used },
! 6008: { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout },
! 6009: { "printf", (Tcl_CmdProc*)test_printf },
! 6010: { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace },
! 6011: };
! 6012: static struct {
! 6013: char *zName;
! 6014: Tcl_ObjCmdProc *xProc;
! 6015: void *clientData;
! 6016: } aObjCmd[] = {
! 6017: { "sqlite3_connection_pointer", get_sqlite_pointer, 0 },
! 6018: { "sqlite3_bind_int", test_bind_int, 0 },
! 6019: { "sqlite3_bind_zeroblob", test_bind_zeroblob, 0 },
! 6020: { "sqlite3_bind_int64", test_bind_int64, 0 },
! 6021: { "sqlite3_bind_double", test_bind_double, 0 },
! 6022: { "sqlite3_bind_null", test_bind_null ,0 },
! 6023: { "sqlite3_bind_text", test_bind_text ,0 },
! 6024: { "sqlite3_bind_text16", test_bind_text16 ,0 },
! 6025: { "sqlite3_bind_blob", test_bind_blob ,0 },
! 6026: { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0},
! 6027: { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0},
! 6028: { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0},
! 6029: { "sqlite3_clear_bindings", test_clear_bindings, 0},
! 6030: { "sqlite3_sleep", test_sleep, 0},
! 6031: { "sqlite3_errcode", test_errcode ,0 },
! 6032: { "sqlite3_extended_errcode", test_ex_errcode ,0 },
! 6033: { "sqlite3_errmsg", test_errmsg ,0 },
! 6034: { "sqlite3_errmsg16", test_errmsg16 ,0 },
! 6035: { "sqlite3_open", test_open ,0 },
! 6036: { "sqlite3_open16", test_open16 ,0 },
! 6037: { "sqlite3_open_v2", test_open_v2 ,0 },
! 6038: { "sqlite3_complete16", test_complete16 ,0 },
! 6039:
! 6040: { "sqlite3_prepare", test_prepare ,0 },
! 6041: { "sqlite3_prepare16", test_prepare16 ,0 },
! 6042: { "sqlite3_prepare_v2", test_prepare_v2 ,0 },
! 6043: { "sqlite3_prepare_tkt3134", test_prepare_tkt3134, 0},
! 6044: { "sqlite3_prepare16_v2", test_prepare16_v2 ,0 },
! 6045: { "sqlite3_finalize", test_finalize ,0 },
! 6046: { "sqlite3_stmt_status", test_stmt_status ,0 },
! 6047: { "sqlite3_reset", test_reset ,0 },
! 6048: { "sqlite3_expired", test_expired ,0 },
! 6049: { "sqlite3_transfer_bindings", test_transfer_bind ,0 },
! 6050: { "sqlite3_changes", test_changes ,0 },
! 6051: { "sqlite3_step", test_step ,0 },
! 6052: { "sqlite3_sql", test_sql ,0 },
! 6053: { "sqlite3_next_stmt", test_next_stmt ,0 },
! 6054: { "sqlite3_stmt_readonly", test_stmt_readonly ,0 },
! 6055: { "sqlite3_stmt_busy", test_stmt_busy ,0 },
! 6056: { "uses_stmt_journal", uses_stmt_journal ,0 },
! 6057:
! 6058: { "sqlite3_release_memory", test_release_memory, 0},
! 6059: { "sqlite3_db_release_memory", test_db_release_memory, 0},
! 6060: { "sqlite3_db_filename", test_db_filename, 0},
! 6061: { "sqlite3_soft_heap_limit", test_soft_heap_limit, 0},
! 6062: { "sqlite3_thread_cleanup", test_thread_cleanup, 0},
! 6063: { "sqlite3_pager_refcounts", test_pager_refcounts, 0},
! 6064:
! 6065: { "sqlite3_load_extension", test_load_extension, 0},
! 6066: { "sqlite3_enable_load_extension", test_enable_load, 0},
! 6067: { "sqlite3_extended_result_codes", test_extended_result_codes, 0},
! 6068: { "sqlite3_limit", test_limit, 0},
! 6069:
! 6070: { "save_prng_state", save_prng_state, 0 },
! 6071: { "restore_prng_state", restore_prng_state, 0 },
! 6072: { "reset_prng_state", reset_prng_state, 0 },
! 6073: { "optimization_control", optimization_control,0},
! 6074: #if SQLITE_OS_WIN
! 6075: { "lock_win32_file", win32_file_lock, 0 },
! 6076: #endif
! 6077: { "tcl_objproc", runAsObjProc, 0 },
! 6078:
! 6079: /* sqlite3_column_*() API */
! 6080: { "sqlite3_column_count", test_column_count ,0 },
! 6081: { "sqlite3_data_count", test_data_count ,0 },
! 6082: { "sqlite3_column_type", test_column_type ,0 },
! 6083: { "sqlite3_column_blob", test_column_blob ,0 },
! 6084: { "sqlite3_column_double", test_column_double ,0 },
! 6085: { "sqlite3_column_int64", test_column_int64 ,0 },
! 6086: { "sqlite3_column_text", test_stmt_utf8, (void*)sqlite3_column_text },
! 6087: { "sqlite3_column_name", test_stmt_utf8, (void*)sqlite3_column_name },
! 6088: { "sqlite3_column_int", test_stmt_int, (void*)sqlite3_column_int },
! 6089: { "sqlite3_column_bytes", test_stmt_int, (void*)sqlite3_column_bytes},
! 6090: #ifndef SQLITE_OMIT_DECLTYPE
! 6091: { "sqlite3_column_decltype",test_stmt_utf8,(void*)sqlite3_column_decltype},
! 6092: #endif
! 6093: #ifdef SQLITE_ENABLE_COLUMN_METADATA
! 6094: { "sqlite3_column_database_name",test_stmt_utf8,(void*)sqlite3_column_database_name},
! 6095: { "sqlite3_column_table_name",test_stmt_utf8,(void*)sqlite3_column_table_name},
! 6096: { "sqlite3_column_origin_name",test_stmt_utf8,(void*)sqlite3_column_origin_name},
! 6097: #endif
! 6098:
! 6099: #ifndef SQLITE_OMIT_UTF16
! 6100: { "sqlite3_column_bytes16", test_stmt_int, (void*)sqlite3_column_bytes16 },
! 6101: { "sqlite3_column_text16", test_stmt_utf16, (void*)sqlite3_column_text16},
! 6102: { "sqlite3_column_name16", test_stmt_utf16, (void*)sqlite3_column_name16},
! 6103: { "add_alignment_test_collations", add_alignment_test_collations, 0 },
! 6104: #ifndef SQLITE_OMIT_DECLTYPE
! 6105: { "sqlite3_column_decltype16",test_stmt_utf16,(void*)sqlite3_column_decltype16},
! 6106: #endif
! 6107: #ifdef SQLITE_ENABLE_COLUMN_METADATA
! 6108: {"sqlite3_column_database_name16",
! 6109: test_stmt_utf16, sqlite3_column_database_name16},
! 6110: {"sqlite3_column_table_name16", test_stmt_utf16, (void*)sqlite3_column_table_name16},
! 6111: {"sqlite3_column_origin_name16", test_stmt_utf16, (void*)sqlite3_column_origin_name16},
! 6112: #endif
! 6113: #endif
! 6114: { "sqlite3_create_collation_v2", test_create_collation_v2, 0 },
! 6115: { "sqlite3_global_recover", test_global_recover, 0 },
! 6116: { "working_64bit_int", working_64bit_int, 0 },
! 6117: { "vfs_unlink_test", vfs_unlink_test, 0 },
! 6118: { "vfs_initfail_test", vfs_initfail_test, 0 },
! 6119: { "vfs_unregister_all", vfs_unregister_all, 0 },
! 6120: { "vfs_reregister_all", vfs_reregister_all, 0 },
! 6121: { "file_control_test", file_control_test, 0 },
! 6122: { "file_control_lasterrno_test", file_control_lasterrno_test, 0 },
! 6123: { "file_control_lockproxy_test", file_control_lockproxy_test, 0 },
! 6124: { "file_control_chunksize_test", file_control_chunksize_test, 0 },
! 6125: { "file_control_sizehint_test", file_control_sizehint_test, 0 },
! 6126: { "file_control_win32_av_retry", file_control_win32_av_retry, 0 },
! 6127: { "file_control_persist_wal", file_control_persist_wal, 0 },
! 6128: { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
! 6129: { "file_control_vfsname", file_control_vfsname, 0 },
! 6130: { "sqlite3_vfs_list", vfs_list, 0 },
! 6131: { "sqlite3_create_function_v2", test_create_function_v2, 0 },
! 6132:
! 6133: /* Functions from os.h */
! 6134: #ifndef SQLITE_OMIT_UTF16
! 6135: { "add_test_collate", test_collate, 0 },
! 6136: { "add_test_collate_needed", test_collate_needed, 0 },
! 6137: { "add_test_function", test_function, 0 },
! 6138: #endif
! 6139: { "sqlite3_test_errstr", test_errstr, 0 },
! 6140: { "tcl_variable_type", tcl_variable_type, 0 },
! 6141: #ifndef SQLITE_OMIT_SHARED_CACHE
! 6142: { "sqlite3_enable_shared_cache", test_enable_shared, 0 },
! 6143: { "sqlite3_shared_cache_report", sqlite3BtreeSharedCacheReport, 0},
! 6144: #endif
! 6145: { "sqlite3_libversion_number", test_libversion_number, 0 },
! 6146: #ifdef SQLITE_ENABLE_COLUMN_METADATA
! 6147: { "sqlite3_table_column_metadata", test_table_column_metadata, 0 },
! 6148: #endif
! 6149: #ifndef SQLITE_OMIT_INCRBLOB
! 6150: { "sqlite3_blob_read", test_blob_read, 0 },
! 6151: { "sqlite3_blob_write", test_blob_write, 0 },
! 6152: { "sqlite3_blob_reopen", test_blob_reopen, 0 },
! 6153: { "sqlite3_blob_bytes", test_blob_bytes, 0 },
! 6154: { "sqlite3_blob_close", test_blob_close, 0 },
! 6155: #endif
! 6156: { "pcache_stats", test_pcache_stats, 0 },
! 6157: #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
! 6158: { "sqlite3_unlock_notify", test_unlock_notify, 0 },
! 6159: #endif
! 6160: { "sqlite3_wal_checkpoint", test_wal_checkpoint, 0 },
! 6161: { "sqlite3_wal_checkpoint_v2",test_wal_checkpoint_v2, 0 },
! 6162: { "test_sqlite3_log", test_sqlite3_log, 0 },
! 6163: #ifndef SQLITE_OMIT_EXPLAIN
! 6164: { "print_explain_query_plan", test_print_eqp, 0 },
! 6165: #endif
! 6166: { "sqlite3_test_control", test_test_control },
! 6167: };
! 6168: static int bitmask_size = sizeof(Bitmask)*8;
! 6169: int i;
! 6170: extern int sqlite3_sync_count, sqlite3_fullsync_count;
! 6171: extern int sqlite3_opentemp_count;
! 6172: extern int sqlite3_like_count;
! 6173: extern int sqlite3_xferopt_count;
! 6174: extern int sqlite3_pager_readdb_count;
! 6175: extern int sqlite3_pager_writedb_count;
! 6176: extern int sqlite3_pager_writej_count;
! 6177: #if SQLITE_OS_WIN
! 6178: extern int sqlite3_os_type;
! 6179: #endif
! 6180: #ifdef SQLITE_DEBUG
! 6181: extern int sqlite3WhereTrace;
! 6182: extern int sqlite3OSTrace;
! 6183: extern int sqlite3VdbeAddopTrace;
! 6184: extern int sqlite3WalTrace;
! 6185: #endif
! 6186: #ifdef SQLITE_TEST
! 6187: extern char sqlite3_query_plan[];
! 6188: static char *query_plan = sqlite3_query_plan;
! 6189: #ifdef SQLITE_ENABLE_FTS3
! 6190: extern int sqlite3_fts3_enable_parentheses;
! 6191: #endif
! 6192: #endif
! 6193:
! 6194: for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
! 6195: Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
! 6196: }
! 6197: for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
! 6198: Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
! 6199: aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
! 6200: }
! 6201: Tcl_LinkVar(interp, "sqlite_search_count",
! 6202: (char*)&sqlite3_search_count, TCL_LINK_INT);
! 6203: Tcl_LinkVar(interp, "sqlite_found_count",
! 6204: (char*)&sqlite3_found_count, TCL_LINK_INT);
! 6205: Tcl_LinkVar(interp, "sqlite_sort_count",
! 6206: (char*)&sqlite3_sort_count, TCL_LINK_INT);
! 6207: Tcl_LinkVar(interp, "sqlite3_max_blobsize",
! 6208: (char*)&sqlite3_max_blobsize, TCL_LINK_INT);
! 6209: Tcl_LinkVar(interp, "sqlite_like_count",
! 6210: (char*)&sqlite3_like_count, TCL_LINK_INT);
! 6211: Tcl_LinkVar(interp, "sqlite_interrupt_count",
! 6212: (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
! 6213: Tcl_LinkVar(interp, "sqlite_open_file_count",
! 6214: (char*)&sqlite3_open_file_count, TCL_LINK_INT);
! 6215: Tcl_LinkVar(interp, "sqlite_current_time",
! 6216: (char*)&sqlite3_current_time, TCL_LINK_INT);
! 6217: #if SQLITE_OS_UNIX && defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE
! 6218: Tcl_LinkVar(interp, "sqlite_hostid_num",
! 6219: (char*)&sqlite3_hostid_num, TCL_LINK_INT);
! 6220: #endif
! 6221: Tcl_LinkVar(interp, "sqlite3_xferopt_count",
! 6222: (char*)&sqlite3_xferopt_count, TCL_LINK_INT);
! 6223: Tcl_LinkVar(interp, "sqlite3_pager_readdb_count",
! 6224: (char*)&sqlite3_pager_readdb_count, TCL_LINK_INT);
! 6225: Tcl_LinkVar(interp, "sqlite3_pager_writedb_count",
! 6226: (char*)&sqlite3_pager_writedb_count, TCL_LINK_INT);
! 6227: Tcl_LinkVar(interp, "sqlite3_pager_writej_count",
! 6228: (char*)&sqlite3_pager_writej_count, TCL_LINK_INT);
! 6229: #ifndef SQLITE_OMIT_UTF16
! 6230: Tcl_LinkVar(interp, "unaligned_string_counter",
! 6231: (char*)&unaligned_string_counter, TCL_LINK_INT);
! 6232: #endif
! 6233: #ifndef SQLITE_OMIT_UTF16
! 6234: Tcl_LinkVar(interp, "sqlite_last_needed_collation",
! 6235: (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
! 6236: #endif
! 6237: #if SQLITE_OS_WIN
! 6238: Tcl_LinkVar(interp, "sqlite_os_type",
! 6239: (char*)&sqlite3_os_type, TCL_LINK_INT);
! 6240: #endif
! 6241: #ifdef SQLITE_TEST
! 6242: Tcl_LinkVar(interp, "sqlite_query_plan",
! 6243: (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
! 6244: #endif
! 6245: #ifdef SQLITE_DEBUG
! 6246: Tcl_LinkVar(interp, "sqlite_addop_trace",
! 6247: (char*)&sqlite3VdbeAddopTrace, TCL_LINK_INT);
! 6248: Tcl_LinkVar(interp, "sqlite_where_trace",
! 6249: (char*)&sqlite3WhereTrace, TCL_LINK_INT);
! 6250: Tcl_LinkVar(interp, "sqlite_os_trace",
! 6251: (char*)&sqlite3OSTrace, TCL_LINK_INT);
! 6252: #ifndef SQLITE_OMIT_WAL
! 6253: Tcl_LinkVar(interp, "sqlite_wal_trace",
! 6254: (char*)&sqlite3WalTrace, TCL_LINK_INT);
! 6255: #endif
! 6256: #endif
! 6257: #ifndef SQLITE_OMIT_DISKIO
! 6258: Tcl_LinkVar(interp, "sqlite_opentemp_count",
! 6259: (char*)&sqlite3_opentemp_count, TCL_LINK_INT);
! 6260: #endif
! 6261: Tcl_LinkVar(interp, "sqlite_static_bind_value",
! 6262: (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
! 6263: Tcl_LinkVar(interp, "sqlite_static_bind_nbyte",
! 6264: (char*)&sqlite_static_bind_nbyte, TCL_LINK_INT);
! 6265: Tcl_LinkVar(interp, "sqlite_temp_directory",
! 6266: (char*)&sqlite3_temp_directory, TCL_LINK_STRING);
! 6267: Tcl_LinkVar(interp, "bitmask_size",
! 6268: (char*)&bitmask_size, TCL_LINK_INT|TCL_LINK_READ_ONLY);
! 6269: Tcl_LinkVar(interp, "sqlite_sync_count",
! 6270: (char*)&sqlite3_sync_count, TCL_LINK_INT);
! 6271: Tcl_LinkVar(interp, "sqlite_fullsync_count",
! 6272: (char*)&sqlite3_fullsync_count, TCL_LINK_INT);
! 6273: #if defined(SQLITE_ENABLE_FTS3) && defined(SQLITE_TEST)
! 6274: Tcl_LinkVar(interp, "sqlite_fts3_enable_parentheses",
! 6275: (char*)&sqlite3_fts3_enable_parentheses, TCL_LINK_INT);
! 6276: #endif
! 6277: return TCL_OK;
! 6278: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>