]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Clarification on the best practices for using the _bytes() APIs.
authordrh <drh@noemail.net>
Tue, 15 May 2007 13:27:07 +0000 (13:27 +0000)
committerdrh <drh@noemail.net>
Tue, 15 May 2007 13:27:07 +0000 (13:27 +0000)
Change sqlite3_value_blob() to force the representation to be purely
a BLOB and not a dual BLOB/String.  Ticket #2360. (CVS 4005)

FossilOrigin-Name: cf2dd45b58380de7f3e167b5357848d12872caa3

manifest
manifest.uuid
src/func.c
src/vdbeapi.c
www/capi3ref.tcl

index 0bc3dd0a077f768b702b097b5441c2914e1dd7af..1779be306931d81ce1619031b74e87ceccd312d7 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C A\snew\sapproach\sfor\sUTF-8\stranslation.\s(CVS\s4004)
-D 2007-05-15T11:55:09
+C Clarification\son\sthe\sbest\spractices\sfor\susing\sthe\s_bytes()\sAPIs.\nChange\ssqlite3_value_blob()\sto\sforce\sthe\srepresentation\sto\sbe\spurely\na\sBLOB\sand\snot\sa\sdual\sBLOB/String.\s\sTicket\s#2360.\s(CVS\s4005)
+D 2007-05-15T13:27:07
 F Makefile.in 87b200ad9970907f76df734d29dff3d294c10935
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -71,7 +71,7 @@ F src/date.c 6049db7d5a8fdf2c677ff7d58fa31d4f6593c988
 F src/delete.c 5c0d89b3ef7d48fe1f5124bfe8341f982747fe29
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
 F src/expr.c 436f1d3e5addf95c195016b518cd2f44a6f5f081
-F src/func.c fc1524fd6097b19c54cc4555e3ea724eec628e2c
+F src/func.c 047c974d530ceca010293f4ae145e4ebc762e9d2
 F src/hash.c 67b23e14f0257b69a3e8aa663e4eeadc1a2b6fd5
 F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564
 F src/insert.c e595ca26805dfb3a9ebaabc28e7947c479f3b14d
@@ -135,7 +135,7 @@ F src/vacuum.c 8bd895d29e7074e78d4e80f948e35ddc9cf2beef
 F src/vdbe.c 5deb4cdccd57065ccf8a2e5c704e8473c90d204b
 F src/vdbe.h 001c5b257567c1d3de7feb2203aac71d0d7b16a3
 F src/vdbeInt.h bddb7931fc1216fda6f6720e18d2a9b1e0f8fc96
-F src/vdbeapi.c 3ca7808c67a10b5c20150108b431d520d141e93e
+F src/vdbeapi.c 805147e4e6cd8218ded3dddf4e83ac6154b74a09
 F src/vdbeaux.c 62011e2ccf5fa9b3dcc7fa6ff5f0e0638d324a70
 F src/vdbeblob.c 96f3572fdc45eda5be06e6372b612bc30742d9f0
 F src/vdbefifo.c 3ca8049c561d5d67cbcb94dc909ae9bb68c0bf8f
@@ -447,7 +447,7 @@ F www/audit.tcl 90e09d580f79c7efec0c7d6f447b7ec5c2dce5c0
 F www/autoinc.tcl b357f5ba954b046ee35392ce0f884a2fcfcdea06
 F www/c_interface.tcl b51b08591554c16a0c3ef718364a508ac25abc7e
 F www/capi3.tcl 88884dd743039d1a95aa57f4a5eb369de7744716
-F www/capi3ref.tcl be09756d8b9aebd2d7b597fb910eed66fb4480e6
+F www/capi3ref.tcl 31da5635eb64ab0f47c71b93b131a6bcb1ddebc9
 F www/changes.tcl 550300b0ff00fc1b872f7802b2d5a1e7587d3e58
 F www/common.tcl 2b793e5c31486c8a01dd27dc0a631ad93704438e
 F www/compile.tcl 276546d7eb445add5a867193bbd80f6919a6b084
@@ -491,7 +491,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 252810424d8c4dcd19b369d62027094df7cf0bcc
-R 8b16cbfea1aee4c8ac49aefcccb7ea15
+P 6c8ad2790eaede90b3f1ef62614e667178b2a8c4
+R 61699b7a12569d4bc746b73ba93dce41
 U drh
-Z 1d3ef6d9d156a8b50e6d1607d4475644
+Z 4386a51ac4f148f41d41e7eee93b8111
index 5da8c0d9aa9e89e6ecad9bbc41991acebb2a8063..95eb9d1f72fb6d2da5aec0ef1787ff931c7abf33 100644 (file)
@@ -1 +1 @@
-6c8ad2790eaede90b3f1ef62614e667178b2a8c4
\ No newline at end of file
+cf2dd45b58380de7f3e167b5357848d12872caa3
\ No newline at end of file
index f33da23ebba903e7111a2a5c97eed3ffec604ca0..8a23cf34b2d7ccec1ed003d7c64b445403df345c 100644 (file)
@@ -16,7 +16,7 @@
 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
 ** All other code has file scope.
 **
-** $Id: func.c,v 1.157 2007/05/15 11:55:09 drh Exp $
+** $Id: func.c,v 1.158 2007/05/15 13:27:07 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -176,6 +176,7 @@ static void substrFunc(
     len = sqlite3_value_bytes(argv[0]);
     z = sqlite3_value_blob(argv[0]);
     if( z==0 ) return;
+    assert( len==sqlite3_value_bytes(argv[0]) );
   }else{
     z = sqlite3_value_text(argv[0]);
     if( z==0 ) return;
@@ -242,8 +243,10 @@ static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   const char *z2;
   int i, n;
   if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
-  n = sqlite3_value_bytes(argv[0]);
   z2 = (char*)sqlite3_value_text(argv[0]);
+  n = sqlite3_value_bytes(argv[0]);
+  /* Verify that the call to _bytes() does not invalidate the _text() pointer */
+  assert( z2==(char*)sqlite3_value_text(argv[0]) );
   if( z2 ){
     z1 = sqlite3_malloc(n+1);
     if( z1 ){
@@ -260,8 +263,10 @@ static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
   const char *z2;
   int i, n;
   if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
-  n = sqlite3_value_bytes(argv[0]);
   z2 = (char*)sqlite3_value_text(argv[0]);
+  n = sqlite3_value_bytes(argv[0]);
+  /* Verify that the call to _bytes() does not invalidate the _text() pointer */
+  assert( z2==(char*)sqlite3_value_text(argv[0]) );
   if( z2 ){
     z1 = sqlite3_malloc(n+1);
     if( z1 ){
@@ -562,6 +567,9 @@ static void likeFunc(
   const unsigned char *zA, *zB;
   int escape = 0;
 
+  zB = sqlite3_value_text(argv[0]);
+  zA = sqlite3_value_text(argv[1]);
+
   /* Limit the length of the LIKE or GLOB pattern to avoid problems
   ** of deep recursion and N*N behavior in patternCompare().
   */
@@ -569,9 +577,8 @@ static void likeFunc(
     sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
     return;
   }
+  assert( zB==sqlite3_value_text(argv[0]) );  /* Encoding did not change */
 
-  zB = sqlite3_value_text(argv[0]);
-  zA = sqlite3_value_text(argv[1]);
   if( argc==3 ){
     /* The escape character string must consist of a single UTF-8 character.
     ** Otherwise, return an error.
@@ -655,8 +662,9 @@ static void quoteFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
     }
     case SQLITE_BLOB: {
       char *zText = 0;
-      int nBlob = sqlite3_value_bytes(argv[0]);
       char const *zBlob = sqlite3_value_blob(argv[0]);
+      int nBlob = sqlite3_value_bytes(argv[0]);
+      assert( zBlob==sqlite3_value_blob(argv[0]) ); /* No encoding change */
 
       if( 2*nBlob+4>SQLITE_MAX_LENGTH ){
         sqlite3_result_error_toobig(context);
@@ -722,12 +730,13 @@ static void hexFunc(
   const unsigned char *pBlob;
   char *zHex, *z;
   assert( argc==1 );
+  pBlob = sqlite3_value_blob(argv[0]);
   n = sqlite3_value_bytes(argv[0]);
   if( n*2+1>SQLITE_MAX_LENGTH ){
     sqlite3_result_error_toobig(context);
     return;
   }
-  pBlob = sqlite3_value_blob(argv[0]);
+  assert( pBlob==sqlite3_value_blob(argv[0]) );  /* No encoding change */
   z = zHex = sqlite3_malloc(n*2 + 1);
   if( zHex==0 ) return;
   for(i=0; i<n; i++, pBlob++){
@@ -776,15 +785,18 @@ static void replaceFunc(
   int i, j;                /* Loop counters */
 
   assert( argc==3 );
-  nStr = sqlite3_value_bytes(argv[0]);
   zStr = sqlite3_value_text(argv[0]);
   if( zStr==0 ) return;
-  nPattern = sqlite3_value_bytes(argv[1]);
+  nStr = sqlite3_value_bytes(argv[0]);
+  assert( zStr==sqlite3_value_text(argv[0]) );  /* No encoding change */
   zPattern = sqlite3_value_text(argv[1]);
   if( zPattern==0 || zPattern[0]==0 ) return;
-  nRep = sqlite3_value_bytes(argv[2]);
+  nPattern = sqlite3_value_bytes(argv[1]);
+  assert( zPattern==sqlite3_value_text(argv[1]) );  /* No encoding change */
   zRep = sqlite3_value_text(argv[2]);
   if( zRep==0 ) return;
+  nRep = sqlite3_value_bytes(argv[2]);
+  assert( zRep==sqlite3_value_text(argv[2]) );
   nOut = nStr + 1;
   assert( nOut<SQLITE_MAX_LENGTH );
   zOut = sqlite3_malloc((int)nOut);
@@ -840,9 +852,10 @@ static void trimFunc(
   if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
     return;
   }
-  nIn = sqlite3_value_bytes(argv[0]);
   zIn = sqlite3_value_text(argv[0]);
   if( zIn==0 ) return;
+  nIn = sqlite3_value_bytes(argv[0]);
+  assert( zIn==sqlite3_value_text(argv[0]) );
   if( argc==1 ){
     static const unsigned char lenOne[] = { 1 };
     static const unsigned char *azOne[] = { (u8*)" " };
index 91fb9a926e5da518df39396613b8c8bd3320d43e..56c0ba0aa92beb959f8fb5e145cf5a0311a6e548 100644 (file)
@@ -38,9 +38,9 @@ const void *sqlite3_value_blob(sqlite3_value *pVal){
   Mem *p = (Mem*)pVal;
   if( p->flags & (MEM_Blob|MEM_Str) ){
     sqlite3VdbeMemExpandBlob(p);
-    if( (p->flags & MEM_Term)==0 ){
-      p->flags &= ~MEM_Str;
-    }
+    p->flags &= ~MEM_Str;
+    p->flags |= MEM_Blob;
+    p->type = SQLITE_BLOB;
     return p->z;
   }else{
     return sqlite3_value_text(pVal);
index 07fca4c06a14f08892b89263827420b54b5f2c17..7c5214e3e5ef56a95cab0acc41281aa5bfa2f0c1 100644 (file)
@@ -1,4 +1,4 @@
-set rcsid {$Id: capi3ref.tcl,v 1.57 2007/05/07 11:24:31 drh Exp $}
+set rcsid {$Id: capi3ref.tcl,v 1.58 2007/05/15 13:27:08 drh Exp $}
 source common.tcl
 header {C/C++ Interface For SQLite Version 3}
 puts {
@@ -391,20 +391,23 @@ int sqlite3_column_type(sqlite3_stmt*, int iCol);
  If the SQL statement is not currently point to a valid row, or if the
  the column index is out of range, the result is undefined.
 
- If the result is a BLOB then the sqlite3_column_bytes() routine returns
- the number of bytes in that BLOB.  No type conversions occur.
- If the result is a string (or a number since a number can be converted
- into a string) then sqlite3_column_bytes() converts
- the value into a UTF-8 string and returns
- the number of bytes in the resulting string.  The value returned does
- not include the \\000 terminator at the end of the string.  The
- sqlite3_column_bytes16() routine converts the value into a UTF-16
- encoding and returns the number of bytes (not characters) in the
- resulting string.  The \\u0000 terminator is not included in this count.
+ If the result is a BLOB or UTF-8 string then the sqlite3_column_bytes() 
+ routine returns the number of bytes in that BLOB or string.
+ If the result is a UTF-16 string, then sqlite3_column_bytes() converts
+ the string to UTF-8 and then returns the number of bytes.
+ If the result is a numeric value then sqlite3_column_bytes() uses
+ sqlite3_snprintf() to convert that value to a UTF-8 string and returns
+ the number of bytes in that string.
+ The value returned does
+ not include the \\000 terminator at the end of the string.  
+
+ The sqlite3_column_bytes16() routine is similar to sqlite3_column_bytes()
+ but leaves the result in UTF-16 instead of UTF-8.  
+ The \\u0000 terminator is not included in this count.
 
  These routines attempt to convert the value where appropriate.  For
  example, if the internal representation is FLOAT and a text result
- is requested, sprintf() is used internally to do the conversion
+ is requested, sqlite3_snprintf() is used internally to do the conversion
  automatically.  The following table details the conversions that
  are applied:
 
@@ -459,24 +462,21 @@ int sqlite3_column_type(sqlite3_stmt*, int iCol);
   of conversion are done in place when it is possible, but sometime it is
   not possible and in those cases prior pointers are invalidated.  
 
-  The safest and easiest to remember policy is this: assume that any
-  result from
-  <ul>
-  <li>sqlite3_column_blob(),</li>
-  <li>sqlite3_column_text(), or</li>
-  <li>sqlite3_column_text16()</li>
-  </ul>
-  is invalided by subsequent calls to 
+  The safest and easiest to remember policy is to invoke these routines
+  in one of the following ways:
+
   <ul>
-  <li>sqlite3_column_bytes(),</li>
-  <li>sqlite3_column_bytes16(),</li>
-  <li>sqlite3_column_text(), or</li>
-  <li>sqlite3_column_text16().</li>
+  <li>sqlite3_column_text() followed by sqlite3_column_bytes()</li>
+  <li>sqlite3_column_blob() followed by sqlite3_column_bytes()</li>
+  <li>sqlite3_column_text16() followed by sqlite3_column_bytes16()</li>
   </ul>
-  This means that you should always call sqlite3_column_bytes() or
-  sqlite3_column_bytes16() <u>before</u> calling sqlite3_column_blob(),
-  sqlite3_column_text(), or sqlite3_column_text16().
 
+  In other words, you should call sqlite3_column_text(), sqlite3_column_blob(),
+  or sqlite3_column_text16() first to force the result into the desired
+  format, then invoke sqlite3_column_bytes() or sqlite3_column_bytes16() to
+  find the size of the result.  Do not mix call to sqlite3_column_text() or
+  sqlite3_column_blob() with calls to sqlite3_column_bytes16().  And do not
+  mix calls to sqlite3_column_text16() with calls to sqlite3_column_bytes().
 }
 
 api {} {