diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/test1.c | 190 |
1 files changed, 189 insertions, 1 deletions
diff --git a/src/test1.c b/src/test1.c index 04b9f7a01..a7fb07cb4 100644 --- a/src/test1.c +++ b/src/test1.c @@ -3940,7 +3940,7 @@ static int SQLITE_TCLAPI test_bind_blob( char zBuf[200]; sqlite3_snprintf(sizeof(zBuf), zBuf, "cannot use %d blob bytes, have %d", bytes, len); - Tcl_AppendResult(interp, zBuf, -1); + Tcl_AppendResult(interp, zBuf, (char*)0); return TCL_ERROR; } @@ -3953,6 +3953,193 @@ static int SQLITE_TCLAPI test_bind_blob( return TCL_OK; } + +/* +** sqlite3_carray_bind [options...] STMT NAME VALUE ... +** +** Options: +** -transient +** -static +** -int32 +** -int64 +** -double +** -text +** +** Each call clears static data. Called with no options does nothing +** but clear static data. +*/ +static int SQLITE_TCLAPI test_carray_bind( + void * clientData, + Tcl_Interp *interp, + int objc, + Tcl_Obj *CONST objv[] +){ + sqlite3_stmt *pStmt; + int eType = 0; /* CARRAY_INT32 */ + int nData = 0; + void *aData = 0; + int isTransient = 0; + int isStatic = 0; + int idx; + int i, j; + int rc; + void (*xDel)(void*) = sqlite3_free; + static void *aStaticData = 0; + static int nStaticData = 0; + static int eStaticType = 0; + extern int sqlite3_carray_bind( + sqlite3_stmt *pStmt, + int i, + void *aData, + int nData, + int mFlags, + void (*xDestroy)(void*) + ); + + if( aStaticData ){ + /* Always clear preexisting static data on every call */ + if( eStaticType==3 ){ + for(i=0; i<nStaticData; i++){ + sqlite3_free(((char**)aStaticData)[i]); + } + } + sqlite3_free(aStaticData); + aStaticData = 0; + nStaticData = 0; + eStaticType = 0; + } + if( objc==1 ) return TCL_OK; + + for(i=1; i<objc && Tcl_GetString(objv[i])[0]=='-'; i++){ + const char *z = Tcl_GetString(objv[i]); + if( strcmp(z, "-transient")==0 ){ + isTransient = 1; + xDel = SQLITE_TRANSIENT; + }else + if( strcmp(z, "-static")==0 ){ + isStatic = 1; + xDel = SQLITE_STATIC; + }else + if( strcmp(z, "-int32")==0 ){ + eType = 0; /* CARRAY_INT32 */ + }else + if( strcmp(z, "-int64")==0 ){ + eType = 1; /* CARRAY_INT64 */ + }else + if( strcmp(z, "-double")==0 ){ + eType = 2; /* CARRAY_DOUBLE */ + }else + if( strcmp(z, "-text")==0 ){ + eType = 3; /* CARRAY_TEXT */ + }else + if( strcmp(z, "--")==0 ){ + break; + }else + { + Tcl_AppendResult(interp, "unknown option: ", z, (char*)0); + return TCL_ERROR; + } + } + if( eType==3 && !isStatic && !isTransient ){ + Tcl_AppendResult(interp, "text data must be either -static or -transient", + (char*)0); + return TCL_ERROR; + } + if( isStatic && isTransient ){ + Tcl_AppendResult(interp, "cannot be both -static and -transient", + (char*)0); + return TCL_ERROR; + } + if( objc-i < 2 ){ + Tcl_WrongNumArgs(interp, 1, objv, "[OPTIONS] STMT IDX VALUE ..."); + return TCL_ERROR; + } + if( getStmtPointer(interp, Tcl_GetString(objv[i]), &pStmt) ) return TCL_ERROR; + i++; + if( Tcl_GetIntFromObj(interp, objv[i], &idx) ) return TCL_ERROR; + i++; + nData = objc - i; + switch( eType + 4*(nData<=0) ){ + case 0: { /* INT32 */ + int *a = sqlite3_malloc( sizeof(int)*nData ); + if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; } + for(j=0; j<nData; j++){ + int v; + if( Tcl_GetIntFromObj(interp, objv[i+j], &v) ){ + sqlite3_free(a); + return TCL_ERROR; + } + a[j] = v; + } + aData = a; + break; + } + case 1: { /* INT64 */ + sqlite3_int64 *a = sqlite3_malloc( sizeof(sqlite3_int64)*nData ); + if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; } + for(j=0; j<nData; j++){ + Tcl_WideInt v; + if( Tcl_GetWideIntFromObj(interp, objv[i+j], &v) ){ + sqlite3_free(a); + return TCL_ERROR; + } + a[j] = v; + } + aData = a; + break; + } + case 2: { /* DOUBLE */ + double *a = sqlite3_malloc( sizeof(double)*nData ); + if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; } + for(j=0; j<nData; j++){ + double v; + if( Tcl_GetDoubleFromObj(interp, objv[i+j], &v) ){ + sqlite3_free(a); + return TCL_ERROR; + } + a[j] = v; + } + aData = a; + break; + } + case 3: { /* TEXT */ + char **a = sqlite3_malloc( sizeof(char*)*nData ); + if( a==0 ){ rc = SQLITE_NOMEM; goto carray_bind_done; } + for(j=0; j<nData; j++){ + const char *v = Tcl_GetString(objv[i+j]); + a[j] = sqlite3_mprintf("%s", v); + } + aData = a; + break; + } + case 4: { /* nData==0 */ + aData = ""; + xDel = SQLITE_STATIC; + isTransient = 0; + isStatic = 0; + break; + } + } + if( isStatic ){ + aStaticData = aData; + nStaticData = nData; + eStaticType = eType; + } + rc = sqlite3_carray_bind(pStmt, idx, aData, nData, eType, xDel); + if( isTransient ){ + if( eType==3 ){ + for(i=0; i<nData; i++) sqlite3_free(((char**)aData)[i]); + } + sqlite3_free(aData); + } +carray_bind_done: + if( rc ){ + Tcl_AppendResult(interp, sqlite3_errstr(rc), (char*)0); + return TCL_ERROR; + } + return TCL_OK; +} + /* ** Usage: sqlite3_bind_parameter_count STMT ** @@ -8029,6 +8216,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ { "sqlite3_bind_text", test_bind_text ,0 }, { "sqlite3_bind_text16", test_bind_text16 ,0 }, { "sqlite3_bind_blob", test_bind_blob ,0 }, + { "sqlite3_carray_bind", test_carray_bind ,0 }, { "sqlite3_bind_parameter_count", test_bind_parameter_count, 0}, { "sqlite3_bind_parameter_name", test_bind_parameter_name, 0}, { "sqlite3_bind_parameter_index", test_bind_parameter_index, 0}, |