diff options
Diffstat (limited to 'src/tclsqlite.c')
-rw-r--r-- | src/tclsqlite.c | 290 |
1 files changed, 31 insertions, 259 deletions
diff --git a/src/tclsqlite.c b/src/tclsqlite.c index 29e609303..c446710a7 100644 --- a/src/tclsqlite.c +++ b/src/tclsqlite.c @@ -11,7 +11,7 @@ ************************************************************************* ** A TCL Interface to SQLite ** -** $Id: tclsqlite.c,v 1.75 2004/05/27 13:35:20 danielk1977 Exp $ +** $Id: tclsqlite.c,v 1.76 2004/05/29 02:37:19 danielk1977 Exp $ */ #ifndef NO_TCL /* Omit this whole file if TCL is unavailable */ @@ -75,182 +75,6 @@ struct CallbackData { char **azColName; /* Column names translated to UTF-8 */ }; -#ifdef UTF_TRANSLATION_NEEDED -/* -** Called for each row of the result. -** -** This version is used when TCL expects UTF-8 data but the database -** uses the ISO8859 format. A translation must occur from ISO8859 into -** UTF-8. -*/ -static int DbEvalCallback( - void *clientData, /* An instance of CallbackData */ - int nCol, /* Number of columns in the result */ - char ** azCol, /* Data for each column */ - char ** azN /* Name for each column */ -){ - CallbackData *cbData = (CallbackData*)clientData; - int i, rc; - Tcl_DString dCol; - Tcl_DStringInit(&dCol); - if( cbData->azColName==0 ){ - assert( cbData->once ); - cbData->once = 0; - if( cbData->zArray[0] ){ - Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0); - } - cbData->azColName = malloc( nCol*sizeof(char*) ); - if( cbData->azColName==0 ){ return 1; } - cbData->nColName = nCol; - for(i=0; i<nCol; i++){ - Tcl_ExternalToUtfDString(NULL, azN[i], -1, &dCol); - cbData->azColName[i] = malloc( Tcl_DStringLength(&dCol) + 1 ); - if( cbData->azColName[i] ){ - strcpy(cbData->azColName[i], Tcl_DStringValue(&dCol)); - }else{ - return 1; - } - if( cbData->zArray[0] ){ - Tcl_SetVar2(cbData->interp, cbData->zArray, "*", - Tcl_DStringValue(&dCol), TCL_LIST_ELEMENT|TCL_APPEND_VALUE); - if( azN[nCol]!=0 ){ - Tcl_DString dType; - Tcl_DStringInit(&dType); - Tcl_DStringAppend(&dType, "typeof:", -1); - Tcl_DStringAppend(&dType, Tcl_DStringValue(&dCol), -1); - Tcl_DStringFree(&dCol); - Tcl_ExternalToUtfDString(NULL, azN[i+nCol], -1, &dCol); - Tcl_SetVar2(cbData->interp, cbData->zArray, - Tcl_DStringValue(&dType), Tcl_DStringValue(&dCol), - TCL_LIST_ELEMENT|TCL_APPEND_VALUE); - Tcl_DStringFree(&dType); - } - } - - Tcl_DStringFree(&dCol); - } - } - if( azCol!=0 ){ - if( cbData->zArray[0] ){ - for(i=0; i<nCol; i++){ - char *z = azCol[i]; - if( z==0 ) z = ""; - Tcl_DStringInit(&dCol); - Tcl_ExternalToUtfDString(NULL, z, -1, &dCol); - Tcl_SetVar2(cbData->interp, cbData->zArray, cbData->azColName[i], - Tcl_DStringValue(&dCol), 0); - Tcl_DStringFree(&dCol); - } - }else{ - for(i=0; i<nCol; i++){ - char *z = azCol[i]; - if( z==0 ) z = ""; - Tcl_DStringInit(&dCol); - Tcl_ExternalToUtfDString(NULL, z, -1, &dCol); - Tcl_SetVar(cbData->interp, cbData->azColName[i], - Tcl_DStringValue(&dCol), 0); - Tcl_DStringFree(&dCol); - } - } - } - rc = Tcl_EvalObj(cbData->interp, cbData->pCode); - if( rc==TCL_CONTINUE ) rc = TCL_OK; - cbData->tcl_rc = rc; - return rc!=TCL_OK; -} -#endif /* UTF_TRANSLATION_NEEDED */ - -#ifndef UTF_TRANSLATION_NEEDED -/* -** Called for each row of the result. -** -** This version is used when either of the following is true: -** -** (1) This version of TCL uses UTF-8 and the data in the -** SQLite database is already in the UTF-8 format. -** -** (2) This version of TCL uses ISO8859 and the data in the -** SQLite database is already in the ISO8859 format. -*/ -static int DbEvalCallback( - void *clientData, /* An instance of CallbackData */ - int nCol, /* Number of columns in the result */ - char ** azCol, /* Data for each column */ - char ** azN /* Name for each column */ -){ - CallbackData *cbData = (CallbackData*)clientData; - int i, rc; - if( azCol==0 || (cbData->once && cbData->zArray[0]) ){ - Tcl_SetVar2(cbData->interp, cbData->zArray, "*", "", 0); - for(i=0; i<nCol; i++){ - Tcl_SetVar2(cbData->interp, cbData->zArray, "*", azN[i], - TCL_LIST_ELEMENT|TCL_APPEND_VALUE); - if( azN[nCol] ){ - char *z = sqlite3_mprintf("typeof:%s", azN[i]); - Tcl_SetVar2(cbData->interp, cbData->zArray, z, azN[i+nCol], - TCL_LIST_ELEMENT|TCL_APPEND_VALUE); - sqlite3_freemem(z); - } - } - cbData->once = 0; - } - if( azCol!=0 ){ - if( cbData->zArray[0] ){ - for(i=0; i<nCol; i++){ - char *z = azCol[i]; - if( z==0 ) z = ""; - Tcl_SetVar2(cbData->interp, cbData->zArray, azN[i], z, 0); - } - }else{ - for(i=0; i<nCol; i++){ - char *z = azCol[i]; - if( z==0 ) z = ""; - Tcl_SetVar(cbData->interp, azN[i], z, 0); - } - } - } - rc = Tcl_EvalObj(cbData->interp, cbData->pCode); - if( rc==TCL_CONTINUE ) rc = TCL_OK; - cbData->tcl_rc = rc; - return rc!=TCL_OK; -} -#endif - -/* -** This is an alternative callback for database queries. Instead -** of invoking a TCL script to handle the result, this callback just -** appends each column of the result to a list. After the query -** is complete, the list is returned. -*/ -static int DbEvalCallback2( - void *clientData, /* An instance of CallbackData */ - int nCol, /* Number of columns in the result */ - char ** azCol, /* Data for each column */ - char ** azN /* Name for each column */ -){ - Tcl_Obj *pList = (Tcl_Obj*)clientData; - int i; - if( azCol==0 ) return 0; - for(i=0; i<nCol; i++){ - Tcl_Obj *pElem; - if( azCol[i] && *azCol[i] ){ -#ifdef UTF_TRANSLATION_NEEDED - Tcl_DString dCol; - Tcl_DStringInit(&dCol); - Tcl_ExternalToUtfDString(NULL, azCol[i], -1, &dCol); - pElem = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1); - Tcl_DStringFree(&dCol); -#else - pElem = Tcl_NewStringObj(azCol[i], -1); -#endif - }else{ - pElem = Tcl_NewObj(); - } - Tcl_ListObjAppendElement(0, pList, pElem); - } - return 0; -} - /* ** This is a second alternative callback for database queries. A the ** first column of the first row of the result is made the TCL result. @@ -476,6 +300,26 @@ static int auth_callback( #endif /* SQLITE_OMIT_AUTHORIZATION */ /* +** zText is a pointer to text obtained via an sqlite3_result_text() +** or similar interface. This routine returns a Tcl string object, +** reference count set to 0, containing the text. If a translation +** between iso8859 and UTF-8 is required, it is preformed. +*/ +static Tcl_Obj *dbTextToObj(char const *zText){ + Tcl_Obj *pVal; +#ifdef UTF_TRANSLATION_NEEDED + Tcl_DString dCol; + Tcl_DStringInit(&dCol); + Tcl_ExternalToUtfDString(NULL, zText, -1, &dCol); + pVal = Tcl_NewStringObj(Tcl_DStringValue(&dCol), -1); + Tcl_DStringFree(&dCol); +#else + pVal = Tcl_NewStringObj(zText, -1); +#endif + return pVal; +} + +/* ** The "sqlite" command below creates a new Tcl command for each ** connection it opens to an SQLite database. This routine is invoked ** whenever one of those connection-specific commands is executed @@ -777,7 +621,9 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ char const *zSql; char const *zLeft; sqlite3_stmt *pStmt; - Tcl_Obj *pRet = 0; + + Tcl_Obj *pRet = Tcl_NewObj(); + Tcl_IncrRefCount(pRet); if( objc!=5 && objc!=3 ){ Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?"); @@ -790,7 +636,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ int i; if( SQLITE_OK!=sqlite3_prepare(pDb->db, zSql, -1, &pStmt, &zLeft) ){ - Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_STATIC); + Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); rc = TCL_ERROR; break; } @@ -801,7 +647,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ for(i=0; i<sqlite3_column_count(pStmt); i++){ Tcl_ListObjAppendElement(interp, pColList, - Tcl_NewStringObj(sqlite3_column_name(pStmt, i), -1) + dbTextToObj(sqlite3_column_name(pStmt, i)) ); } Tcl_ObjSetVar2(interp,objv[3],Tcl_NewStringObj("*",-1),pColList,0); @@ -813,14 +659,14 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ /* Set pVal to contain the i'th column of this row. */ if( SQLITE3_BLOB!=sqlite3_column_type(pStmt, i) ){ - pVal = Tcl_NewStringObj(sqlite3_column_text(pStmt, i), -1); + pVal = dbTextToObj(sqlite3_column_text(pStmt, i)); }else{ int bytes = sqlite3_column_bytes(pStmt, i); pVal = Tcl_NewByteArrayObj(sqlite3_column_blob(pStmt, i), bytes); } if( objc==5 ){ - Tcl_Obj *pName = Tcl_NewStringObj(sqlite3_column_name(pStmt, i), -1); + Tcl_Obj *pName = dbTextToObj(sqlite3_column_name(pStmt, i)); Tcl_IncrRefCount(pName); if( !strcmp("", Tcl_GetString(objv[3])) ){ Tcl_ObjSetVar2(interp, pName, 0, pVal, 0); @@ -829,10 +675,6 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ } Tcl_DecrRefCount(pName); }else{ - if( !pRet ){ - pRet = Tcl_NewObj(); - Tcl_IncrRefCount(pRet); - } Tcl_ListObjAppendElement(interp, pRet, pVal); } } @@ -848,7 +690,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ } if( pStmt && SQLITE_OK!=sqlite3_errcode(pDb->db) ){ - Tcl_SetResult(interp, (char *)sqlite3_errmsg(pDb->db), TCL_STATIC); + Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db))); rc = TCL_ERROR; break; } @@ -857,83 +699,13 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ zSql = zLeft; } - if( rc==TCL_OK && pRet ){ + if( rc==TCL_OK ){ Tcl_SetObjResult(interp, pRet); - Tcl_DecrRefCount(pRet); } + Tcl_DecrRefCount(pRet); break; } -#if 0 - case DB_EVAL: { - CallbackData cbData; - char *zErrMsg; - char *zSql; -#ifdef UTF_TRANSLATION_NEEDED - Tcl_DString dSql; - int i; -#endif - - if( objc!=5 && objc!=3 ){ - Tcl_WrongNumArgs(interp, 2, objv, "SQL ?ARRAY-NAME CODE?"); - return TCL_ERROR; - } - pDb->interp = interp; - zSql = Tcl_GetStringFromObj(objv[2], 0); -#ifdef UTF_TRANSLATION_NEEDED - Tcl_DStringInit(&dSql); - Tcl_UtfToExternalDString(NULL, zSql, -1, &dSql); - zSql = Tcl_DStringValue(&dSql); -#endif - Tcl_IncrRefCount(objv[2]); - if( objc==5 ){ - cbData.interp = interp; - cbData.once = 1; - cbData.zArray = Tcl_GetStringFromObj(objv[3], 0); - cbData.pCode = objv[4]; - cbData.tcl_rc = TCL_OK; - cbData.nColName = 0; - cbData.azColName = 0; - zErrMsg = 0; - Tcl_IncrRefCount(objv[3]); - Tcl_IncrRefCount(objv[4]); - rc = sqlite3_exec(pDb->db, zSql, DbEvalCallback, &cbData, &zErrMsg); - Tcl_DecrRefCount(objv[4]); - Tcl_DecrRefCount(objv[3]); - if( cbData.tcl_rc==TCL_BREAK ){ cbData.tcl_rc = TCL_OK; } - }else{ - Tcl_Obj *pList = Tcl_NewObj(); - cbData.tcl_rc = TCL_OK; - rc = sqlite3_exec(pDb->db, zSql, DbEvalCallback2, pList, &zErrMsg); - Tcl_SetObjResult(interp, pList); - } - pDb->rc = rc; - if( rc==SQLITE_ABORT ){ - if( zErrMsg ) free(zErrMsg); - rc = cbData.tcl_rc; - }else if( zErrMsg ){ - Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE); - free(zErrMsg); - rc = TCL_ERROR; - }else if( rc!=SQLITE_OK ){ - Tcl_AppendResult(interp, sqlite3_error_string(rc), 0); - rc = TCL_ERROR; - }else{ - } - Tcl_DecrRefCount(objv[2]); -#ifdef UTF_TRANSLATION_NEEDED - Tcl_DStringFree(&dSql); - if( objc==5 && cbData.azColName ){ - for(i=0; i<cbData.nColName; i++){ - if( cbData.azColName[i] ) free(cbData.azColName[i]); - } - free(cbData.azColName); - cbData.azColName = 0; - } -#endif - return rc; - } -#endif /* ** $db function NAME SCRIPT |