SQLite

Check-in [db6bab5748]
Login

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

Overview
Comment:Add some tests for user functions that prefer various text encodings. (CVS 1676)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: db6bab574869fde49a147d4e19dd73005f247092
User & Date: danielk1977 2004-06-23 12:15:55.000
Context
2004-06-23
12:35
Fix a bug in the previous checkin. (CVS 1677) (check-in: f31c84a64f user: danielk1977 tags: trunk)
12:15
Add some tests for user functions that prefer various text encodings. (CVS 1676) (check-in: db6bab5748 user: danielk1977 tags: trunk)
10:43
Test cases to verify recovery after a crash. (CVS 1675) (check-in: 41868d79ac user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/expr.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.147 2004/06/21 09:06:42 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.148 2004/06/23 12:15:55 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

char const *sqlite3AffinityString(char affinity){
  switch( affinity ){
    case SQLITE_AFF_INTEGER: return "i";
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
    **    prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
    ** 5: A function with the exact number of arguments requested that
    **    prefers UTF-16LE when UTF-16BE is requested, or vice versa.
    ** 6: An exact match.
    **
    ** A larger value of 'matchqual' indicates a more desirable match.
    */
    if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){
      int match = 1;          /* Quality of this match */
      if( p->nArg==nArg || nArg==-1 ){
        match = 4;
      }
      if( enc==p->iPrefEnc ){
        match += 2;
      }







|







1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
    **    prefers UTF-8 when a UTF-16 encoding is requested, or vice versa.
    ** 5: A function with the exact number of arguments requested that
    **    prefers UTF-16LE when UTF-16BE is requested, or vice versa.
    ** 6: An exact match.
    **
    ** A larger value of 'matchqual' indicates a more desirable match.
    */
    if( (p->xStep||p->xFunc ) && (p->nArg==-1||p->nArg==nArg||nArg==-1) ){
      int match = 1;          /* Quality of this match */
      if( p->nArg==nArg || nArg==-1 ){
        match = 4;
      }
      if( enc==p->iPrefEnc ){
        match += 2;
      }
Changes to src/test1.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.84 2004/06/23 10:43:11 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>








|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the printf() interface to SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test1.c,v 1.85 2004/06/23 12:15:55 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

974
975
976
977
978
979
980



























































































































981
982
983
984
985
986
987
        (void *)SQLITE_UTF16LE, val?test_collate_func:0);
  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
  sqlite3_create_collation(db, "test_collate", SQLITE_UTF16BE, 
        (void *)SQLITE_UTF16BE, val?test_collate_func:0);
  
  return TCL_OK;




























































































































bad_args:
  Tcl_AppendResult(interp, "wrong # args: should be \"",
      Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
  return TCL_ERROR;
}

static int sqlite3_crashparams(







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







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
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
        (void *)SQLITE_UTF16LE, val?test_collate_func:0);
  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
  sqlite3_create_collation(db, "test_collate", SQLITE_UTF16BE, 
        (void *)SQLITE_UTF16BE, val?test_collate_func:0);
  
  return TCL_OK;

bad_args:
  Tcl_AppendResult(interp, "wrong # args: should be \"",
      Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
  return TCL_ERROR;
}

/*
** Usage: add_test_function <db ptr> <utf8> <utf16le> <utf16be>
**
** This function is used to test that SQLite selects the correct user
** function callback when multiple versions (for different text encodings)
** are available.
**
** Calling this routine registers up to three versions of the user function
** "test_function" with database handle <db>.  If the second argument is
** true, then a version of test_function is registered for UTF-8, if the
** third is true, a version is registered for UTF-16le, if the fourth is
** true, a UTF-16be version is available.  Previous versions of
** test_function are deleted.
**
** The user function is implemented by calling the following TCL script:
**
**   "test_function <enc> <arg>"
**
** Where <enc> is one of UTF-8, UTF-16LE or UTF16BE, and <arg> is the
** single argument passed to the SQL function. The value returned by
** the TCL script is used as the return value of the SQL function. It
** is passed to SQLite using UTF-16BE for a UTF-8 test_function(), UTF-8
** for a UTF-16LE test_function(), and UTF-16LE for an implementation that
** prefers UTF-16BE.
*/
static void test_function_utf8(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **argv
){
  Tcl_Interp *interp;
  Tcl_Obj *pX;
  sqlite3_value *pVal;
  interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
  pX = Tcl_NewStringObj("test_function", -1);
  Tcl_IncrRefCount(pX);
  Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-8", -1));
  Tcl_ListObjAppendElement(interp, pX, 
      Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
  Tcl_EvalObjEx(interp, pX, 0);
  Tcl_DecrRefCount(pX);
  sqlite3_result_text(pCtx, Tcl_GetStringResult(interp), -1, SQLITE_TRANSIENT);
  pVal = sqlite3ValueNew();
  sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 
      SQLITE_UTF8, SQLITE_STATIC);
  sqlite3_result_text16be(pCtx, sqlite3_value_text16be(pVal),
      -1, SQLITE_TRANSIENT);
  sqlite3ValueFree(pVal);
}
static void test_function_utf16le(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **argv
){
  Tcl_Interp *interp;
  Tcl_Obj *pX;
  sqlite3_value *pVal;
  interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
  pX = Tcl_NewStringObj("test_function", -1);
  Tcl_IncrRefCount(pX);
  Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16LE", -1));
  Tcl_ListObjAppendElement(interp, pX, 
      Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
  Tcl_EvalObjEx(interp, pX, 0);
  Tcl_DecrRefCount(pX);
  pVal = sqlite3ValueNew();
  sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 
      SQLITE_UTF8, SQLITE_STATIC);
  sqlite3_result_text(pCtx,sqlite3_value_text(pVal),-1,SQLITE_TRANSIENT);
  sqlite3ValueFree(pVal);
}
static void test_function_utf16be(
  sqlite3_context *pCtx, 
  int nArg,
  sqlite3_value **argv
){
  Tcl_Interp *interp;
  Tcl_Obj *pX;
  sqlite3_value *pVal;
  interp = (Tcl_Interp *)sqlite3_user_data(pCtx);
  pX = Tcl_NewStringObj("test_function", -1);
  Tcl_IncrRefCount(pX);
  Tcl_ListObjAppendElement(interp, pX, Tcl_NewStringObj("UTF-16BE", -1));
  Tcl_ListObjAppendElement(interp, pX, 
      Tcl_NewStringObj(sqlite3_value_text(argv[0]), -1));
  Tcl_EvalObjEx(interp, pX, 0);
  Tcl_DecrRefCount(pX);
  pVal = sqlite3ValueNew();
  sqlite3ValueSetStr(pVal, -1, Tcl_GetStringResult(interp), 
      SQLITE_UTF8, SQLITE_STATIC);
  sqlite3_result_text16le(pCtx, sqlite3_value_text16le(pVal),
      -1, SQLITE_TRANSIENT);
  sqlite3ValueFree(pVal);
}
static int test_function(
  void * clientData,
  Tcl_Interp *interp,
  int objc,
  Tcl_Obj *CONST objv[]
){
  sqlite3 *db;
  int val;

  if( objc!=5 ) goto bad_args;
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;

  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR;
  sqlite3_create_function(db, "test_function", 1, SQLITE_UTF8, 
      interp, val?test_function_utf8:0, 0, 0);
  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR;
  sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16LE, 
      interp, val?test_function_utf16le:0, 0, 0);
  if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR;
  sqlite3_create_function(db, "test_function", 1, SQLITE_UTF16BE, 
      interp, val?test_function_utf16be:0, 0, 0);

  return TCL_OK;
bad_args:
  Tcl_AppendResult(interp, "wrong # args: should be \"",
      Tcl_GetStringFromObj(objv[0], 0), " <DB> <utf8> <utf16le> <utf16be>", 0);
  return TCL_ERROR;
}

static int sqlite3_crashparams(
2064
2065
2066
2067
2068
2069
2070

2071
2072
2073
2074
2075
2076
2077

     /* Functions from os.h */
     { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
     { "sqlite3OsClose",        test_sqlite3OsClose, 0 },
     { "sqlite3OsLock",         test_sqlite3OsLock, 0 },
     { "sqlite3OsUnlock",       test_sqlite3OsUnlock, 0 },
     { "add_test_collate",      test_collate, 0         },

     { "sqlite3_crashparams",     sqlite3_crashparams, 0         },

  };
  int i;
  extern int sqlite3_os_trace;

  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){







>







2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201

     /* Functions from os.h */
     { "sqlite3OsOpenReadWrite",test_sqlite3OsOpenReadWrite, 0 },
     { "sqlite3OsClose",        test_sqlite3OsClose, 0 },
     { "sqlite3OsLock",         test_sqlite3OsLock, 0 },
     { "sqlite3OsUnlock",       test_sqlite3OsUnlock, 0 },
     { "add_test_collate",      test_collate, 0         },
     { "add_test_function",     test_function, 0         },
     { "sqlite3_crashparams",     sqlite3_crashparams, 0         },

  };
  int i;
  extern int sqlite3_os_trace;

  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
Changes to test/enc2.test.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The focus of
# this file is testing the SQLite routines used for converting between the
# various suported unicode encodings (UTF-8, UTF-16, UTF-16le and
# UTF-16be).
#
# $Id: enc2.test,v 1.12 2004/06/19 00:16:31 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# The rough organisation of tests in this file is:
#
# enc2.1.*: Simple tests with a UTF-8 db.







|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The focus of
# this file is testing the SQLite routines used for converting between the
# various suported unicode encodings (UTF-8, UTF-16, UTF-16le and
# UTF-16be).
#
# $Id: enc2.test,v 1.13 2004/06/23 12:15:55 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

# The rough organisation of tests in this file is:
#
# enc2.1.*: Simple tests with a UTF-8 db.
258
259
260
261
262
263
264
265

































































































266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
  add_test_collate $DB 1 0 0
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-8}

db close
file delete -force test.db


































































































# The following tests - enc2-6.* - function as follows:
#
# 1: Open an empty database file assuming UTF-16 encoding.
# 2: Open the same database with a different handle assuming UTF-8. Create
#    a table using this handle.
# 3: Read the sqlite_master table from the first handle. 
# 4: Ensure the first handle recognises the database encoding is UTF-8.
#
do_test enc2-6.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA encoding = 'UTF-16';
    SELECT * FROM sqlite_master;
  }
} {}
do_test enc2-6.2 {
  set enc [execsql {
    PRAGMA encoding;
  }]
  string range $enc 0 end-2 ;# Chop off the "le" or "be"
} {UTF-16}
do_test enc2-6.3 {
  sqlite3 db2 test.db
  execsql {
    PRAGMA encoding = 'UTF-8';
    CREATE TABLE abc(a, b, c);
  } db2
} {}
do_test enc2-6.4 {
  execsql {
    SELECT * FROM sqlite_master;
  }
} {table abc abc 2 {CREATE TABLE abc(a, b, c)}}
do_test enc2-6.5 {
  execsql {
    PRAGMA encoding;
  }
} {UTF-8}

db close
db2 close








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








|






|





|






|




|







258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
  add_test_collate $DB 1 0 0
  set res [execsql {SELECT * FROM t5 ORDER BY 1 COLLATE test_collate}]
  lappend res $::test_collate_enc
} {one two three four five UTF-8}

db close
file delete -force test.db

# The following tests - enc2-5.* - test that SQLite selects the correct
# collation sequence when more than one is available.

proc test_function {enc arg} {
  return "$enc $arg"
}

file delete -force test.db
set DB [sqlite3 db test.db]
execsql {pragma encoding = 'UTF-8'}
do_test enc2-6.0 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('one');
  }
} {}
do_test enc2-6.1 {
  add_test_function $DB 1 1 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-8 sqlite}}

do_test enc2-6.2 {
  add_test_function $DB 0 1 0
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16LE sqlite}}
do_test enc2-6.3 {
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

file delete -force test.db
set DB [sqlite3 db test.db]
execsql {pragma encoding = 'UTF-16LE'}
do_test enc2-6.3 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('sqlite');
  }
} {}
do_test enc2-6.4 {
  add_test_function $DB 1 1 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16LE sqlite}}

do_test enc2-6.5 {
  add_test_function $DB 0 1 0
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16LE sqlite}}
do_test enc2-6.6 {
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

file delete -force test.db
set DB [sqlite3 db test.db]
execsql {pragma encoding = 'UTF-16BE'}
do_test enc2-6.7 {
  execsql {
    CREATE TABLE t5(a);
    INSERT INTO t5 VALUES('sqlite');
  }
} {}
do_test enc2-6.8 {
  add_test_function $DB 1 1 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

do_test enc2-6.9 {
  add_test_function $DB 0 1 0
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16LE sqlite}}
do_test enc2-6.10 {
  add_test_function $DB 0 0 1
  execsql {
    SELECT test_function('sqlite')
  }
} {{UTF-16BE sqlite}}

db close
file delete -force test.db

# The following tests - enc2-6.* - function as follows:
#
# 1: Open an empty database file assuming UTF-16 encoding.
# 2: Open the same database with a different handle assuming UTF-8. Create
#    a table using this handle.
# 3: Read the sqlite_master table from the first handle. 
# 4: Ensure the first handle recognises the database encoding is UTF-8.
#
do_test enc2-7.1 {
  sqlite3 db test.db
  execsql {
    PRAGMA encoding = 'UTF-16';
    SELECT * FROM sqlite_master;
  }
} {}
do_test enc2-7.2 {
  set enc [execsql {
    PRAGMA encoding;
  }]
  string range $enc 0 end-2 ;# Chop off the "le" or "be"
} {UTF-16}
do_test enc2-7.3 {
  sqlite3 db2 test.db
  execsql {
    PRAGMA encoding = 'UTF-8';
    CREATE TABLE abc(a, b, c);
  } db2
} {}
do_test enc2-7.4 {
  execsql {
    SELECT * FROM sqlite_master;
  }
} {table abc abc 2 {CREATE TABLE abc(a, b, c)}}
do_test enc2-7.5 {
  execsql {
    PRAGMA encoding;
  }
} {UTF-8}

db close
db2 close