]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix the TCL interface so that SQL functions implemented in TCL honor the
authordrh <drh@noemail.net>
Wed, 3 Oct 2012 11:02:33 +0000 (11:02 +0000)
committerdrh <drh@noemail.net>
Wed, 3 Oct 2012 11:02:33 +0000 (11:02 +0000)
"nullvalue" setting.  Also remove from the TCL interface some unused
legacy UTF8 translation code left over from SQLite2.

FossilOrigin-Name: c1f10a2643179ec58f3879764e9e89676d4b5f91

manifest
manifest.uuid
src/tclsqlite.c
test/tclsqlite.test

index 178efcf35c38a74378283c5fabf6d80a222078f1..05b97bd3c0922ab607b504d26d627f24f6644592 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Work\saround\san\soptimization\sissue\swith\sthe\sMSVC\scompiler\sfor\sARM.
-D 2012-10-02T22:54:27.390
+C Fix\sthe\sTCL\sinterface\sso\sthat\sSQL\sfunctions\simplemented\sin\sTCL\shonor\sthe\n"nullvalue"\ssetting.\s\sAlso\sremove\sfrom\sthe\sTCL\sinterface\ssome\sunused\s\nlegacy\sUTF8\stranslation\scode\sleft\sover\sfrom\sSQLite2.
+D 2012-10-03T11:02:33.741
 F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
 F Makefile.in 5f4f26109f9d80829122e0e09f9cda008fa065fb
 F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -183,7 +183,7 @@ F src/sqliteInt.h c29395d6e68cfbcb2661787ae4820e5e256c916a
 F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
 F src/status.c 35939e7e03abf1b7577ce311f48f682c40de3208
 F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
-F src/tclsqlite.c 22de426c579d01c7bd2c24fb9229fbd774613b42
+F src/tclsqlite.c fc9027118d5fa1b3d16a7b22c63684a54adeeb42
 F src/test1.c 936afc02766403e5debca49a1817a780e116df7e
 F src/test2.c 4178056dd1e7d70f954ad8a1e3edb71a2a784daf
 F src/test3.c 3c3c2407fa6ec7a19e24ae23f7cb439d0275a60d
@@ -737,7 +737,7 @@ F test/syscall.test bea9bf329bff733c791310244617c2a76974e64a
 F test/sysfault.test c79441d88d23696fbec7b147dba98d42a04f523f
 F test/table.test a59d985ca366e39b17b175f387f9d5db5a18d4e2
 F test/tableapi.test 2674633fa95d80da917571ebdd759a14d9819126
-F test/tclsqlite.test a3d2df21ee98957f5de4f9dc1db0eab68047ab5d
+F test/tclsqlite.test 37a61c2da7e3bfe3b8c1a2867199f6b860df5d43
 F test/tempdb.test 19d0f66e2e3eeffd68661a11c83ba5e6ace9128c
 F test/temptable.test 51edd31c65ed1560dd600b1796e8325df96318e2
 F test/temptrigger.test 26670ed7a39cf2296a7f0a9e0a1d7bdb7abe936d
@@ -1018,7 +1018,7 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
 F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
 F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
 F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9
-P abcf6a5d054559ee5a093ba39180c47b4958d9cd
-R e2af9a84c8984f66075b1b5542126d99
-U mistachkin
-Z 2e5e5eca8b24072e2977c29980c9c33a
+P 7d301fdfeec540e4a58f43bff04d219e9f769dc4
+R 6327212080c41cdbc10c1e2eb094be0d
+U drh
+Z 25d327c4e46a0608f83a0eb5d2f156c2
index 6ff004a2dbed4e07e63c901050f15869738bd7a0..c4e20d4544b3f28052ed883969f1e69b838c729b 100644 (file)
@@ -1 +1 @@
-7d301fdfeec540e4a58f43bff04d219e9f769dc4
\ No newline at end of file
+c1f10a2643179ec58f3879764e9e89676d4b5f91
\ No newline at end of file
index 47110cb8d2836379a656b3de89e2b635a489de9d..5ea67782a0ca5bb41d8fb712fb2007d3b4f05904 100644 (file)
 #define NUM_PREPARED_STMTS 10
 #define MAX_PREPARED_STMTS 100
 
-/*
-** If TCL uses UTF-8 and SQLite is configured to use iso8859, then we
-** have to do a translation when going between the two.  Set the 
-** UTF_TRANSLATION_NEEDED macro to indicate that we need to do
-** this translation.  
-*/
-#if defined(TCL_UTF_MAX) && !defined(SQLITE_UTF8)
-# define UTF_TRANSLATION_NEEDED 1
-#endif
+/* Forward declaration */
+typedef struct SqliteDb SqliteDb;
 
 /*
 ** New SQL functions can be created as TCL scripts.  Each such function
@@ -71,6 +64,7 @@ typedef struct SqlFunc SqlFunc;
 struct SqlFunc {
   Tcl_Interp *interp;   /* The TCL interpret to execute the function */
   Tcl_Obj *pScript;     /* The Tcl_Obj representation of the script */
+  SqliteDb *pDb;        /* Database connection that owns this function */
   int useEvalObjv;      /* True if it is safe to use Tcl_EvalObjv */
   char *zName;          /* Name of this function */
   SqlFunc *pNext;       /* Next function on the list of them all */
@@ -113,7 +107,6 @@ typedef struct IncrblobChannel IncrblobChannel;
 ** sqlite3_prepare_v2() or sqlite3_prepare() to prepare SQL statements.
 ** If SqliteDb.bLegacyPrepare is true, sqlite3_prepare() is used.
 */
-typedef struct SqliteDb SqliteDb;
 struct SqliteDb {
   sqlite3 *db;               /* The "real" database structure. MUST BE FIRST */
   Tcl_Interp *interp;        /* The interpreter used for this database */
@@ -431,6 +424,7 @@ static SqlFunc *findSqlFunc(SqliteDb *pDb, const char *zName){
     }
   }
   pNew->interp = pDb->interp;
+  pNew->pDb = pDb;
   pNew->pScript = 0;
   pNew->pNext = pDb->pFunc;
   pDb->pFunc = pNew;
@@ -478,6 +472,7 @@ static void DbDeleteCmd(void *db){
   while( pDb->pFunc ){
     SqlFunc *pFunc = pDb->pFunc;
     pDb->pFunc = pFunc->pNext;
+    assert( pFunc->pDb==pDb );
     Tcl_DecrRefCount(pFunc->pScript);
     Tcl_Free((char*)pFunc);
   }
@@ -794,7 +789,7 @@ static void tclSqlFunc(sqlite3_context *context, int argc, sqlite3_value**argv){
           break;
         }
         case SQLITE_NULL: {
-          pVal = Tcl_NewStringObj("", 0);
+          pVal = Tcl_NewStringObj(p->pDb->zNull, -1);
           break;
         }
         default: {
@@ -933,26 +928,6 @@ 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;
-}
-
 /*
 ** This routine reads a line of text from FILE in, stores
 ** the text in memory obtained from malloc() and returns a pointer
@@ -1140,13 +1115,13 @@ static int dbPrepareAndBind(
     int nByte;
 
     if( SQLITE_OK!=dbPrepare(pDb, zSql, &pStmt, pzOut) ){
-      Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
+      Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
       return TCL_ERROR;
     }
     if( pStmt==0 ){
       if( SQLITE_OK!=sqlite3_errcode(pDb->db) ){
         /* A compile-time error in the statement. */
-        Tcl_SetObjResult(interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
+        Tcl_SetObjResult(interp, Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
         return TCL_ERROR;
       }else{
         /* The statement was a no-op.  Continue to the next statement
@@ -1365,7 +1340,7 @@ static void dbEvalRowInfo(
     if( nCol>0 && (papColName || p->pArray) ){
       apColName = (Tcl_Obj**)Tcl_Alloc( sizeof(Tcl_Obj*)*nCol );
       for(i=0; i<nCol; i++){
-        apColName[i] = dbTextToObj(sqlite3_column_name(pStmt,i));
+        apColName[i] = Tcl_NewStringObj(sqlite3_column_name(pStmt,i), -1);
         Tcl_IncrRefCount(apColName[i]);
       }
       p->apColName = apColName;
@@ -1452,7 +1427,8 @@ static int dbEvalStep(DbEvalContext *p){
           continue;
         }
 #endif
-        Tcl_SetObjResult(pDb->interp, dbTextToObj(sqlite3_errmsg(pDb->db)));
+        Tcl_SetObjResult(pDb->interp,
+                         Tcl_NewStringObj(sqlite3_errmsg(pDb->db), -1));
         return TCL_ERROR;
       }else{
         dbReleaseStmt(pDb, pPreStmt, 0);
@@ -1509,11 +1485,11 @@ static Tcl_Obj *dbEvalColumnValue(DbEvalContext *p, int iCol){
       return Tcl_NewDoubleObj(sqlite3_column_double(pStmt, iCol));
     }
     case SQLITE_NULL: {
-      return dbTextToObj(p->pDb->zNull);
+      return Tcl_NewStringObj(p->pDb->zNull, -1);
     }
   }
 
-  return dbTextToObj((char *)sqlite3_column_text(pStmt, iCol));
+  return Tcl_NewStringObj(sqlite3_column_text(pStmt, iCol), -1);
 }
 
 /*
@@ -2433,7 +2409,7 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
         pDb->zNull = 0;
       }
     }
-    Tcl_SetObjResult(interp, dbTextToObj(pDb->zNull));
+    Tcl_SetObjResult(interp, Tcl_NewStringObj(pDb->zNull, -1));
     break;
   }
 
index 5761e1604c3287303fe939d51e8e36bb8a5b3140..3d9cd46ac6b949e366e0b352b1f961a654bd555a 100644 (file)
@@ -319,14 +319,23 @@ do_test tcl-8.1 {
   execsql {INSERT INTO t1 VALUES(30,NULL)}
   db eval {SELECT * FROM t1 WHERE b IS NULL}
 } {30 NaN}
+proc concatFunc args {return [join $args {}]}
 do_test tcl-8.2 {
+  db function concat concatFunc
+  db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
+} {aNaNz}
+do_test tcl-8.3 {
   db nullvalue NULL
   db nullvalue
 } {NULL}
-do_test tcl-8.3 {
+do_test tcl-8.4 {
   db nullvalue {}
   db eval {SELECT * FROM t1 WHERE b IS NULL}
 } {30 {}}
+do_test tcl-8.5 {
+  db function concat concatFunc
+  db eval {SELECT concat('a', b, 'z') FROM t1 WHERE b is NULL}
+} {az}
 
 # Test the return type of user-defined functions
 #