📄 test1.c
字号:
** bad things will happen.*/static int test_snprintf_int( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */){ char zStr[100]; int n = atoi(argv[1]); const char *zFormat = argv[2]; int a1 = atoi(argv[3]); if( n>sizeof(zStr) ) n = sizeof(zStr); strcpy(zStr, "abcdefghijklmnopqrstuvwxyz"); sqlite3_snprintf(n, zStr, zFormat, a1); Tcl_AppendResult(interp, zStr, 0); return TCL_OK;}/*** Usage: sqlite3_get_table_printf DB FORMAT STRING**** Invoke the sqlite3_get_table_printf() interface using the open database** DB. The SQL is the string FORMAT. The format string should contain** one %s or %q. STRING is the value inserted into %s or %q.*/static int test_get_table_printf( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */){ sqlite3 *db; Tcl_DString str; int rc; char *zErr = 0; int nRow, nCol; char **aResult; int i; char zBuf[30]; char *zSql; if( argc!=4 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB FORMAT STRING", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; Tcl_DStringInit(&str); zSql = sqlite3_mprintf(argv[2],argv[3]); rc = sqlite3_get_table(db, zSql, &aResult, &nRow, &nCol, &zErr); sqlite3_free(zSql); sprintf(zBuf, "%d", rc); Tcl_AppendElement(interp, zBuf); if( rc==SQLITE_OK ){ sprintf(zBuf, "%d", nRow); Tcl_AppendElement(interp, zBuf); sprintf(zBuf, "%d", nCol); Tcl_AppendElement(interp, zBuf); for(i=0; i<(nRow+1)*nCol; i++){ Tcl_AppendElement(interp, aResult[i] ? aResult[i] : "NULL"); } }else{ Tcl_AppendElement(interp, zErr); } sqlite3_free_table(aResult); if( zErr ) sqlite3_free(zErr); if( sqlite3TestErrCode(interp, db, rc) ) return TCL_ERROR; return TCL_OK;}/*** Usage: sqlite3_last_insert_rowid DB**** Returns the integer ROWID of the most recent insert.*/static int test_last_rowid( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */){ sqlite3 *db; char zBuf[30]; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; sprintf(zBuf, "%lld", sqlite3_last_insert_rowid(db)); Tcl_AppendResult(interp, zBuf, 0); return SQLITE_OK;}/*** Usage: sqlite3_key DB KEY**** Set the codec key.*/static int test_key( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */){ sqlite3 *db; const char *zKey; int nKey; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; zKey = argv[2]; nKey = strlen(zKey);#ifdef SQLITE_HAS_CODEC sqlite3_key(db, zKey, nKey);#endif return TCL_OK;}/*** Usage: sqlite3_rekey DB KEY**** Change the codec key.*/static int test_rekey( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */){ sqlite3 *db; const char *zKey; int nKey; if( argc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; zKey = argv[2]; nKey = strlen(zKey);#ifdef SQLITE_HAS_CODEC sqlite3_rekey(db, zKey, nKey);#endif return TCL_OK;}/*** Usage: sqlite3_close DB**** Closes the database opened by sqlite3_open.*/static int sqlite_test_close( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */){ sqlite3 *db; int rc; if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " FILENAME\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; rc = sqlite3_close(db); Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); return TCL_OK;}/*** Implementation of the x_coalesce() function.** Return the first argument non-NULL argument.*/static void t1_ifnullFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ int i; for(i=0; i<argc; i++){ if( SQLITE_NULL!=sqlite3_value_type(argv[i]) ){ int n = sqlite3_value_bytes(argv[i]); sqlite3_result_text(context, (char*)sqlite3_value_text(argv[i]), n, SQLITE_TRANSIENT); break; } }}/*** These are test functions. hex8() interprets its argument as** UTF8 and returns a hex encoding. hex16le() interprets its argument** as UTF16le and returns a hex encoding.*/static void hex8Func(sqlite3_context *p, int argc, sqlite3_value **argv){ const unsigned char *z; int i; char zBuf[200]; z = sqlite3_value_text(argv[0]); for(i=0; i<sizeof(zBuf)/2 - 2 && z[i]; i++){ sprintf(&zBuf[i*2], "%02x", z[i]&0xff); } zBuf[i*2] = 0; sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);}#ifndef SQLITE_OMIT_UTF16static void hex16Func(sqlite3_context *p, int argc, sqlite3_value **argv){ const unsigned short int *z; int i; char zBuf[400]; z = sqlite3_value_text16(argv[0]); for(i=0; i<sizeof(zBuf)/4 - 4 && z[i]; i++){ sprintf(&zBuf[i*4], "%04x", z[i]&0xff); } zBuf[i*4] = 0; sqlite3_result_text(p, (char*)zBuf, -1, SQLITE_TRANSIENT);}#endif/*** A structure into which to accumulate text.*/struct dstr { int nAlloc; /* Space allocated */ int nUsed; /* Space used */ char *z; /* The space */};/*** Append text to a dstr*/static void dstrAppend(struct dstr *p, const char *z, int divider){ int n = strlen(z); if( p->nUsed + n + 2 > p->nAlloc ){ char *zNew; p->nAlloc = p->nAlloc*2 + n + 200; zNew = sqliteRealloc(p->z, p->nAlloc); if( zNew==0 ){ sqliteFree(p->z); memset(p, 0, sizeof(*p)); return; } p->z = zNew; } if( divider && p->nUsed>0 ){ p->z[p->nUsed++] = divider; } memcpy(&p->z[p->nUsed], z, n+1); p->nUsed += n;}/*** Invoked for each callback from sqlite3ExecFunc*/static int execFuncCallback(void *pData, int argc, char **argv, char **NotUsed){ struct dstr *p = (struct dstr*)pData; int i; for(i=0; i<argc; i++){ if( argv[i]==0 ){ dstrAppend(p, "NULL", ' '); }else{ dstrAppend(p, argv[i], ' '); } } return 0;}/*** Implementation of the x_sqlite_exec() function. This function takes** a single argument and attempts to execute that argument as SQL code.** This is illegal and should set the SQLITE_MISUSE flag on the database.**** 2004-Jan-07: We have changed this to make it legal to call sqlite3_exec()** from within a function call. ** ** This routine simulates the effect of having two threads attempt to** use the same database at the same time.*/static void sqlite3ExecFunc( sqlite3_context *context, int argc, sqlite3_value **argv){ struct dstr x; memset(&x, 0, sizeof(x)); (void)sqlite3_exec((sqlite3*)sqlite3_user_data(context), (char*)sqlite3_value_text(argv[0]), execFuncCallback, &x, 0); sqlite3_result_text(context, x.z, x.nUsed, SQLITE_TRANSIENT); sqliteFree(x.z);}/*** Implementation of tkt2213func(), a scalar function that takes exactly** one argument. It has two interesting features:**** * It calls sqlite3_value_text() 3 times on the argument sqlite3_value*.** If the three pointers returned are not the same an SQL error is raised.**** * Otherwise it returns a copy of the text representation of it's ** argument in such a way as the VDBE representation is a Mem* cell ** with the MEM_Term flag clear. **** Ticket #2213 can therefore be tested by evaluating the following** SQL expression:**** tkt2213func(tkt2213func('a string'));*/static void tkt2213Function( sqlite3_context *context, int argc, sqlite3_value **argv){ int nText; unsigned char const *zText1; unsigned char const *zText2; unsigned char const *zText3; nText = sqlite3_value_bytes(argv[0]); zText1 = sqlite3_value_text(argv[0]); zText2 = sqlite3_value_text(argv[0]); zText3 = sqlite3_value_text(argv[0]); if( zText1!=zText2 || zText2!=zText3 ){ sqlite3_result_error(context, "tkt2213 is not fixed", -1); }else{ char *zCopy = (char *)sqlite3_malloc(nText); memcpy(zCopy, zText1, nText); sqlite3_result_text(context, zCopy, nText, sqlite3_free); }}/*** The following SQL function takes 4 arguments. The 2nd and** 4th argument must be one of these strings: 'text', 'text16',** or 'blob' corresponding to API functions**** sqlite3_value_text()** sqlite3_value_text16()** sqlite3_value_blob()**** The third argument is a string, either 'bytes' or 'bytes16' or 'noop',** corresponding to APIs:**** sqlite3_value_bytes()** sqlite3_value_bytes16()** noop**** The APIs designated by the 2nd through 4th arguments are applied** to the first argument in order. If the pointers returned by the** second and fourth are different, this routine returns 1. Otherwise,** this routine returns 0.**** This function is used to test to see when returned pointers from** the _text(), _text16() and _blob() APIs become invalidated.*/static void ptrChngFunction( sqlite3_context *context, int argc, sqlite3_value **argv){ const void *p1, *p2; const char *zCmd; if( argc!=4 ) return; zCmd = (const char*)sqlite3_value_text(argv[1]); if( zCmd==0 ) return; if( strcmp(zCmd,"text")==0 ){ p1 = (const void*)sqlite3_value_text(argv[0]);#ifndef SQLITE_OMIT_UTF16 }else if( strcmp(zCmd, "text16")==0 ){ p1 = (const void*)sqlite3_value_text16(argv[0]);#endif }else if( strcmp(zCmd, "blob")==0 ){ p1 = (const void*)sqlite3_value_blob(argv[0]); }else{ return; } zCmd = (const char*)sqlite3_value_text(argv[2]); if( zCmd==0 ) return; if( strcmp(zCmd,"bytes")==0 ){ sqlite3_value_bytes(argv[0]);#ifndef SQLITE_OMIT_UTF16 }else if( strcmp(zCmd, "bytes16")==0 ){ sqlite3_value_bytes16(argv[0]);#endif }else if( strcmp(zCmd, "noop")==0 ){ /* do nothing */ }else{ return; } zCmd = (const char*)sqlite3_value_text(argv[3]); if( zCmd==0 ) return; if( strcmp(zCmd,"text")==0 ){ p2 = (const void*)sqlite3_value_text(argv[0]);#ifndef SQLITE_OMIT_UTF16 }else if( strcmp(zCmd, "text16")==0 ){ p2 = (const void*)sqlite3_value_text16(argv[0]);#endif }else if( strcmp(zCmd, "blob")==0 ){ p2 = (const void*)sqlite3_value_blob(argv[0]); }else{ return; } sqlite3_result_int(context, p1!=p2);}/*** Usage: sqlite_test_create_function DB**** Call the sqlite3_create_function API on the given database in order** to create a function named "x_coalesce". This function does the same thing** as the "coalesce" function. This function also registers an SQL function** named "x_sqlite_exec" that invokes sqlite3_exec(). Invoking sqlite3_exec()** in this way is illegal recursion and should raise an SQLITE_MISUSE error.** The effect is similar to trying to use the same database connection from** two threads at the same time.**** The original motivation for this routine was to be able to call the** sqlite3_create_function function while a query is in progress in order** to test the SQLITE_MISUSE detection logic.*/static int test_create_function( void *NotUsed, Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ int argc, /* Number of arguments */ char **argv /* Text of each argument */){ int rc; sqlite3 *db; extern void Md5_Register(sqlite3*); if( argc!=2 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; rc = sqlite3_create_function(db, "x_coalesce", -1, SQLITE_ANY, 0, t1_ifnullFunc, 0, 0); if( rc==SQLITE_OK ){ rc = sqlite3_create_function(db, "hex8", 1, SQLITE_ANY, 0, hex8Func, 0, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -