SQLite

Check-in [be24939052]
Login

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

Overview
Comment:Add new SQL functions unicode() and char().
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: be2493905281e12c7f4c146ab17c8872e52da350
User & Date: drh 2013-02-25 14:39:47.361
Context
2013-02-26
05:42
Remove extra use of the sqlite3_value_int64() function. (check-in: 6d7973524a user: mistachkin tags: trunk)
2013-02-25
14:39
Add new SQL functions unicode() and char(). (check-in: be24939052 user: drh tags: trunk)
13:55
Strengthen the final test case in index5.test. Also provide additional diagnostic information out the output. (check-in: 47b6418242 user: drh tags: trunk)
2013-02-22
19:34
Two new SQL functions: unicode() and char(). (Closed-Leaf check-in: 209b21085b user: drh tags: unicode-function)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/func.c.
957
958
959
960
961
962
963


















































964
965
966
967
968
969
970
    default: {
      assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
      sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
      break;
    }
  }
}



















































/*
** The hex() function.  Interpret the argument as a blob.  Return
** a hexadecimal rendering as text.
*/
static void hexFunc(
  sqlite3_context *context,







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
    default: {
      assert( sqlite3_value_type(argv[0])==SQLITE_NULL );
      sqlite3_result_text(context, "NULL", 4, SQLITE_STATIC);
      break;
    }
  }
}

/*
** The unicode() function.  Return the integer unicode code-point value
** for the first character of the input string. 
*/
static void unicodeFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  const unsigned char *z = sqlite3_value_text(argv[0]);
  if( z && z[0] ) sqlite3_result_int(context, sqlite3Utf8Read(&z));
}

/*
** The char() function takes zero or more arguments, each of which is
** an integer.  It constructs a string where each character of the string
** is the unicode character for the corresponding integer argument.
*/
static void charFunc(
  sqlite3_context *context,
  int argc,
  sqlite3_value **argv
){
  unsigned char *z, *zOut;
  int i;
  zOut = z = sqlite3_malloc( argc*4 );
  if( z==0 ){
    sqlite3_result_error_nomem(context);
    return;
  }
  for(i=0; i<argc; i++){
    sqlite3_int64 x = sqlite3_value_int64(argv[i]);
    unsigned c;
    x = sqlite3_value_int64(argv[i]);
    if( x<0 || x>0x10ffff ) x = 0xfffd;
    c = (unsigned)(x & 0x1fffff);
    if( c<=0xFFFF ){
      *zOut++ = (u8)(c&0x00FF);
      *zOut++ = (u8)((c>>8)&0x00FF);
    }else{
      if( c>=0xd800 && c<=0xdbff ) c = 0xfffd;
      *zOut++ = (u8)(((c>>10)&0x003F) + (((c-0x10000)>>10)&0x00C0));
      *zOut++ = (u8)(0x00D8 + (((c-0x10000)>>18)&0x03));
      *zOut++ = (u8)(c&0x00FF);
      *zOut++ = (u8)(0x00DC + ((c>>8)&0x03));
    }
  }
  sqlite3_result_text16le(context, (char*)z, (int)(zOut-z), sqlite3_free);
}

/*
** The hex() function.  Interpret the argument as a blob.  Return
** a hexadecimal rendering as text.
*/
static void hexFunc(
  sqlite3_context *context,
1585
1586
1587
1588
1589
1590
1591


1592
1593
1594
1595
1596
1597
1598
    FUNCTION(max,                0, 1, 1, 0                ),
    AGGREGATE(max,               1, 1, 1, minmaxStep,      minMaxFinalize ),
    FUNCTION2(typeof,            1, 0, 0, typeofFunc,  SQLITE_FUNC_TYPEOF),
    FUNCTION2(length,            1, 0, 0, lengthFunc,  SQLITE_FUNC_LENGTH),
    FUNCTION(instr,              2, 0, 0, instrFunc        ),
    FUNCTION(substr,             2, 0, 0, substrFunc       ),
    FUNCTION(substr,             3, 0, 0, substrFunc       ),


    FUNCTION(abs,                1, 0, 0, absFunc          ),
#ifndef SQLITE_OMIT_FLOATING_POINT
    FUNCTION(round,              1, 0, 0, roundFunc        ),
    FUNCTION(round,              2, 0, 0, roundFunc        ),
#endif
    FUNCTION(upper,              1, 0, 0, upperFunc        ),
    FUNCTION(lower,              1, 0, 0, lowerFunc        ),







>
>







1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
    FUNCTION(max,                0, 1, 1, 0                ),
    AGGREGATE(max,               1, 1, 1, minmaxStep,      minMaxFinalize ),
    FUNCTION2(typeof,            1, 0, 0, typeofFunc,  SQLITE_FUNC_TYPEOF),
    FUNCTION2(length,            1, 0, 0, lengthFunc,  SQLITE_FUNC_LENGTH),
    FUNCTION(instr,              2, 0, 0, instrFunc        ),
    FUNCTION(substr,             2, 0, 0, substrFunc       ),
    FUNCTION(substr,             3, 0, 0, substrFunc       ),
    FUNCTION(unicode,            1, 0, 0, unicodeFunc      ),
    FUNCTION(char,              -1, 0, 0, charFunc         ),
    FUNCTION(abs,                1, 0, 0, absFunc          ),
#ifndef SQLITE_OMIT_FLOATING_POINT
    FUNCTION(round,              1, 0, 0, roundFunc        ),
    FUNCTION(round,              2, 0, 0, roundFunc        ),
#endif
    FUNCTION(upper,              1, 0, 0, upperFunc        ),
    FUNCTION(lower,              1, 0, 0, lowerFunc        ),
Changes to test/func.test.
1285
1286
1287
1288
1289
1290
1291
1292















1293
1294
  db eval {SELECT sum(length(x)) FROM t29}
} {1000009}
do_test func-29.6 {
  set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
  if {$x<5} {set x 1}
  set x
} {1}
  
















finish_test







|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
  db eval {SELECT sum(length(x)) FROM t29}
} {1000009}
do_test func-29.6 {
  set x [lindex [sqlite3_db_status db CACHE_MISS 1] 1]
  if {$x<5} {set x 1}
  set x
} {1}

do_execsql_test func-30.1 {SELECT unicode('$');} 36
do_execsql_test func-30.2 {SELECT unicode('¢');} 162
do_execsql_test func-30.3 {SELECT unicode('€');} 8364
do_execsql_test func-30.4 {SELECT char(36,162,8364);} {$¢€}

for {set i 1} {$i<0xd800} {incr i 13} {
  do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
}
for {set i 57344} {$i<=0xfffd} {incr i 17} {
  if {$i==0xfeff} continue
  do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
}
for {set i 65536} {$i<=0x10ffff} {incr i 139} {
  do_execsql_test func-30.5.$i {SELECT unicode(char($i))} $i
}

finish_test