/ Check-in [cf2dd45b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Clarification on the best practices for using the _bytes() APIs. Change sqlite3_value_blob() to force the representation to be purely a BLOB and not a dual BLOB/String. Ticket #2360. (CVS 4005)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cf2dd45b58380de7f3e167b5357848d12872caa3
User & Date: drh 2007-05-15 13:27:07
Context
2007-05-15
14:10
Fix to check-in (4005). A call to sqlite3_column_blob() should not make subsequent calls to sqlite3_column_type() return SQLITE_BLOB. Sqlite3_column_type() returns the initial type. (CVS 4006) check-in: b5e85deb user: drh tags: trunk
13:27
Clarification on the best practices for using the _bytes() APIs. Change sqlite3_value_blob() to force the representation to be purely a BLOB and not a dual BLOB/String. Ticket #2360. (CVS 4005) check-in: cf2dd45b user: drh tags: trunk
11:55
A new approach for UTF-8 translation. (CVS 4004) check-in: 6c8ad279 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/func.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
172
173
174
175
176
177
178

179
180
181
182
183
184
185
...
238
239
240
241
242
243
244

245

246
247
248
249
250
251
252
253
...
256
257
258
259
260
261
262

263

264
265
266
267
268
269
270
271
...
557
558
559
560
561
562
563



564
565
566
567
568
569
570
571

572
573
574
575
576
577
578
579
580
581
...
651
652
653
654
655
656
657

658
659
660
661
662
663
664
665
666
...
718
719
720
721
722
723
724

725
726
727
728
729
730
731
732
733
734
735
736
737
...
772
773
774
775
776
777
778
779
780
781
782

783
784
785

786
787


788
789
790
791
792
793
794
...
836
837
838
839
840
841
842
843
844
845


846
847
848
849
850
851
852
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** 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 $
*/
#include "sqliteInt.h"
#include <ctype.h>
/* #include <math.h> */
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
................................................................................

  assert( argc==3 );
  p0type = sqlite3_value_type(argv[0]);
  if( p0type==SQLITE_BLOB ){
    len = sqlite3_value_bytes(argv[0]);
    z = sqlite3_value_blob(argv[0]);
    if( z==0 ) return;

  }else{
    z = sqlite3_value_text(argv[0]);
    if( z==0 ) return;
    len = 0;
    for(z2=z; *z2; len++){
      SQLITE_SKIP_UTF8(z2);
    }
................................................................................
** Implementation of the upper() and lower() SQL functions.
*/
static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  char *z1;
  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]);
  if( z2 ){
    z1 = sqlite3_malloc(n+1);
    if( z1 ){
      memcpy(z1, z2, n+1);
      for(i=0; z1[i]; i++){
        z1[i] = toupper(z1[i]);
      }
................................................................................
  }
}
static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  char *z1;
  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]);
  if( z2 ){
    z1 = sqlite3_malloc(n+1);
    if( z1 ){
      memcpy(z1, z2, n+1);
      for(i=0; z1[i]; i++){
        z1[i] = tolower(z1[i]);
      }
................................................................................
static void likeFunc(
  sqlite3_context *context, 
  int argc, 
  sqlite3_value **argv
){
  const unsigned char *zA, *zB;
  int escape = 0;




  /* Limit the length of the LIKE or GLOB pattern to avoid problems
  ** of deep recursion and N*N behavior in patternCompare().
  */
  if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){
    sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
    return;
  }


  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.
    */
    const unsigned char *zEsc = sqlite3_value_text(argv[2]);
    if( zEsc==0 ) return;
    if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){
................................................................................
    case SQLITE_INTEGER:
    case SQLITE_FLOAT: {
      sqlite3_result_value(context, argv[0]);
      break;
    }
    case SQLITE_BLOB: {
      char *zText = 0;

      int nBlob = sqlite3_value_bytes(argv[0]);
      char const *zBlob = sqlite3_value_blob(argv[0]);

      if( 2*nBlob+4>SQLITE_MAX_LENGTH ){
        sqlite3_result_error_toobig(context);
        return;
      }
      zText = (char *)sqliteMalloc((2*nBlob)+4); 
      if( !zText ){
................................................................................
  int argc,
  sqlite3_value **argv
){
  int i, n;
  const unsigned char *pBlob;
  char *zHex, *z;
  assert( argc==1 );

  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]);
  z = zHex = sqlite3_malloc(n*2 + 1);
  if( zHex==0 ) return;
  for(i=0; i<n; i++, pBlob++){
    unsigned char c = *pBlob;
    *(z++) = hexdigits[(c>>4)&0xf];
    *(z++) = hexdigits[c&0xf];
  }
................................................................................
  int nPattern;            /* Size of zPattern */
  int nRep;                /* Size of zRep */
  i64 nOut;                /* Maximum size of zOut */
  int loopLimit;           /* Last zStr[] that might match zPattern[] */
  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]);

  zPattern = sqlite3_value_text(argv[1]);
  if( zPattern==0 || zPattern[0]==0 ) return;
  nRep = sqlite3_value_bytes(argv[2]);

  zRep = sqlite3_value_text(argv[2]);
  if( zRep==0 ) return;


  nOut = nStr + 1;
  assert( nOut<SQLITE_MAX_LENGTH );
  zOut = sqlite3_malloc((int)nOut);
  if( zOut==0 ){
    return;
  }
  loopLimit = nStr - nPattern;  
................................................................................
  unsigned char *aLen;              /* Length of each character in zCharSet */
  const unsigned char **azChar;     /* Individual characters in zCharSet */
  int nChar;                        /* Number of characters in zCharSet */

  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;


  if( argc==1 ){
    static const unsigned char lenOne[] = { 1 };
    static const unsigned char *azOne[] = { (u8*)" " };
    nChar = 1;
    aLen = (u8*)lenOne;
    azChar = azOne;
    zCharSet = 0;







|







 







>







 







>

>
|







 







>

>
|







 







>
>
>








>

<
<







 







>

|







 







>





|







 







<


|
>


|
>


>
>







 







<


>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
...
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
...
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
...
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581


582
583
584
585
586
587
588
...
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
...
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
...
781
782
783
784
785
786
787

788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
...
848
849
850
851
852
853
854

855
856
857
858
859
860
861
862
863
864
865
** This file contains the C functions that implement various SQL
** functions of SQLite.  
**
** There is only one exported symbol in this file - the function
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
** All other code has file scope.
**
** $Id: func.c,v 1.158 2007/05/15 13:27:07 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
/* #include <math.h> */
#include <stdlib.h>
#include <assert.h>
#include "vdbeInt.h"
................................................................................

  assert( argc==3 );
  p0type = sqlite3_value_type(argv[0]);
  if( p0type==SQLITE_BLOB ){
    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;
    len = 0;
    for(z2=z; *z2; len++){
      SQLITE_SKIP_UTF8(z2);
    }
................................................................................
** Implementation of the upper() and lower() SQL functions.
*/
static void upperFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  char *z1;
  const char *z2;
  int i, n;
  if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
  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 ){
      memcpy(z1, z2, n+1);
      for(i=0; z1[i]; i++){
        z1[i] = toupper(z1[i]);
      }
................................................................................
  }
}
static void lowerFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
  char *z1;
  const char *z2;
  int i, n;
  if( argc<1 || SQLITE_NULL==sqlite3_value_type(argv[0]) ) return;
  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 ){
      memcpy(z1, z2, n+1);
      for(i=0; z1[i]; i++){
        z1[i] = tolower(z1[i]);
      }
................................................................................
static void likeFunc(
  sqlite3_context *context, 
  int argc, 
  sqlite3_value **argv
){
  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().
  */
  if( sqlite3_value_bytes(argv[0])>SQLITE_MAX_LIKE_PATTERN_LENGTH ){
    sqlite3_result_error(context, "LIKE or GLOB pattern too complex", -1);
    return;
  }
  assert( zB==sqlite3_value_text(argv[0]) );  /* Encoding did not change */



  if( argc==3 ){
    /* The escape character string must consist of a single UTF-8 character.
    ** Otherwise, return an error.
    */
    const unsigned char *zEsc = sqlite3_value_text(argv[2]);
    if( zEsc==0 ) return;
    if( sqlite3Utf8CharLen((char*)zEsc, -1)!=1 ){
................................................................................
    case SQLITE_INTEGER:
    case SQLITE_FLOAT: {
      sqlite3_result_value(context, argv[0]);
      break;
    }
    case SQLITE_BLOB: {
      char *zText = 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);
        return;
      }
      zText = (char *)sqliteMalloc((2*nBlob)+4); 
      if( !zText ){
................................................................................
  int argc,
  sqlite3_value **argv
){
  int i, n;
  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;
  }
  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++){
    unsigned char c = *pBlob;
    *(z++) = hexdigits[(c>>4)&0xf];
    *(z++) = hexdigits[c&0xf];
  }
................................................................................
  int nPattern;            /* Size of zPattern */
  int nRep;                /* Size of zRep */
  i64 nOut;                /* Maximum size of zOut */
  int loopLimit;           /* Last zStr[] that might match zPattern[] */
  int i, j;                /* Loop counters */

  assert( argc==3 );

  zStr = sqlite3_value_text(argv[0]);
  if( zStr==0 ) return;
  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;
  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);
  if( zOut==0 ){
    return;
  }
  loopLimit = nStr - nPattern;  
................................................................................
  unsigned char *aLen;              /* Length of each character in zCharSet */
  const unsigned char **azChar;     /* Individual characters in zCharSet */
  int nChar;                        /* Number of characters in zCharSet */

  if( sqlite3_value_type(argv[0])==SQLITE_NULL ){
    return;
  }

  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*)" " };
    nChar = 1;
    aLen = (u8*)lenOne;
    azChar = azOne;
    zCharSet = 0;

Changes to src/vdbeapi.c.

34
35
36
37
38
39
40
41
42
43


44
45
46
47
48
49
50
** The following routines extract information from a Mem or sqlite3_value
** structure.
*/
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;
    }


    return p->z;
  }else{
    return sqlite3_value_text(pVal);
  }
}
int sqlite3_value_bytes(sqlite3_value *pVal){
  return sqlite3ValueBytes(pVal, SQLITE_UTF8);







<
|
<
>
>







34
35
36
37
38
39
40

41

42
43
44
45
46
47
48
49
50
** The following routines extract information from a Mem or sqlite3_value
** structure.
*/
const void *sqlite3_value_blob(sqlite3_value *pVal){
  Mem *p = (Mem*)pVal;
  if( p->flags & (MEM_Blob|MEM_Str) ){
    sqlite3VdbeMemExpandBlob(p);

    p->flags &= ~MEM_Str;

    p->flags |= MEM_Blob;
    p->type = SQLITE_BLOB;
    return p->z;
  }else{
    return sqlite3_value_text(pVal);
  }
}
int sqlite3_value_bytes(sqlite3_value *pVal){
  return sqlite3ValueBytes(pVal, SQLITE_UTF8);

Changes to www/capi3ref.tcl.

1
2
3
4
5
6
7
8
...
387
388
389
390
391
392
393
394
395
396

397
398

399
400

401
402

403
404
405
406
407
408
409
410
411
412
413
414
...
455
456
457
458
459
460
461
462
463

464
465
466
467
468
469
470

471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
set rcsid {$Id: capi3ref.tcl,v 1.57 2007/05/07 11:24:31 drh Exp $}
source common.tcl
header {C/C++ Interface For SQLite Version 3}
puts {
<h2 class=pdf_section>C/C++ Interface For SQLite Version 3</h2>
}

proc api {name prototype desc {notused x}} {
................................................................................
 the second argument is the index of the column for which information 
 should be returned.  iCol is zero-indexed.  The left-most column has an
 index of 0.

 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.

 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
 automatically.  The following table details the conversions that
 are applied:

<blockquote>
<table border="1">
<tr><th>Internal Type</th><th>Requested Type</th><th>Conversion</th></tr>
<tr><td> NULL    </td><td> INTEGER</td><td>Result is 0</td></tr>
................................................................................
  Conversions between UTF-16be and UTF-16le 
  are always done in place and do
  not invalidate a prior pointer, though of course the content of the buffer
  that the prior pointer points to will have been modified.  Other kinds
  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 
  <ul>

  <li>sqlite3_column_bytes(),</li>
  <li>sqlite3_column_bytes16(),</li>
  <li>sqlite3_column_text(), or</li>
  <li>sqlite3_column_text16().</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().

}

api {} {
int sqlite3_column_count(sqlite3_stmt *pStmt);
} {
 Return the number of columns in the result set returned by the prepared
 SQL statement. This routine returns 0 if pStmt is an SQL statement
|







 







|
|
|
>
|
|
>
|
|
>
|
<
>
|



|







 







|
|
>

|
|
|

<
<
>
|
|
|
|
|
|
<
<
<







1
2
3
4
5
6
7
8
...
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404

405
406
407
408
409
410
411
412
413
414
415
416
417
...
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472


473
474
475
476
477
478
479



480
481
482
483
484
485
486
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 {
<h2 class=pdf_section>C/C++ Interface For SQLite Version 3</h2>
}

proc api {name prototype desc {notused x}} {
................................................................................
 the second argument is the index of the column for which information 
 should be returned.  iCol is zero-indexed.  The left-most column has an
 index of 0.

 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 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, sqlite3_snprintf() is used internally to do the conversion
 automatically.  The following table details the conversions that
 are applied:

<blockquote>
<table border="1">
<tr><th>Internal Type</th><th>Requested Type</th><th>Conversion</th></tr>
<tr><td> NULL    </td><td> INTEGER</td><td>Result is 0</td></tr>
................................................................................
  Conversions between UTF-16be and UTF-16le 
  are always done in place and do
  not invalidate a prior pointer, though of course the content of the buffer
  that the prior pointer points to will have been modified.  Other kinds
  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 to invoke these routines
  in one of the following ways:

  <ul>
  <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>



  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 {} {
int sqlite3_column_count(sqlite3_stmt *pStmt);
} {
 Return the number of columns in the result set returned by the prepared
 SQL statement. This routine returns 0 if pStmt is an SQL statement