Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Use the faster LIKE function from sqlite v2. Add special user functions to test builds to test the auxdata APIs. (CVS 1610) |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
b9493c5facea4d24a6cbc4f6fa2f75dc |
User & Date: | danielk1977 2004-06-17 05:36:44 |
Context
2004-06-17
| ||
06:13 | Handle conflicting ON CONFLICT clauses in table definitions. (CVS 1611) check-in: 12e77e75 user: danielk1977 tags: trunk | |
05:36 | Use the faster LIKE function from sqlite v2. Add special user functions to test builds to test the auxdata APIs. (CVS 1610) check-in: b9493c5f user: danielk1977 tags: trunk | |
00:01 | Remove the second definition of SQLITE_N_BTREE_META from test3.c. (CVS 1609) check-in: b1e66ae4 user: danielk1977 tags: trunk | |
Changes
Changes to src/func.c.
12 12 ** This file contains the C functions that implement various SQL 13 13 ** functions of SQLite. 14 14 ** 15 15 ** There is only one exported symbol in this file - the function 16 16 ** sqliteRegisterBuildinFunctions() found at the bottom of the file. 17 17 ** All other code has file scope. 18 18 ** 19 -** $Id: func.c,v 1.70 2004/06/16 10:39:24 danielk1977 Exp $ 19 +** $Id: func.c,v 1.71 2004/06/17 05:36:44 danielk1977 Exp $ 20 20 */ 21 21 #include <ctype.h> 22 22 #include <math.h> 23 23 #include <stdlib.h> 24 24 #include <assert.h> 25 25 #include "sqliteInt.h" 26 26 #include "vdbeInt.h" ................................................................................ 313 313 typedef struct LikePattern LikePattern; 314 314 315 315 void deleteLike(void *pLike){ 316 316 sqliteFree(pLike); 317 317 } 318 318 319 319 320 +#if 0 320 321 /* #define TRACE_LIKE */ 321 - 322 322 #if defined(TRACE_LIKE) && !defined(NDEBUG) 323 323 char *dumpLike(LikePattern *pLike){ 324 324 int i; 325 325 int k = 0; 326 326 char *zBuf = (char *)sqliteMalloc(pLike->nState*40); 327 327 328 328 k += sprintf(&zBuf[k], "%d states - ", pLike->nState); ................................................................................ 538 538 }while( c && pState>=aState ); 539 539 540 540 if( (pState-aState)==pLike->nState || (pState-aState)<-1 ){ 541 541 sqlite3_result_int(context, 1); 542 542 }else{ 543 543 sqlite3_result_int(context, 0); 544 544 } 545 +} 546 +#endif 547 + 548 +/* 549 +** Implementation of the like() SQL function. This function implements 550 +** the build-in LIKE operator. The first argument to the function is the 551 +** pattern and the second argument is the string. So, the SQL statements: 552 +** 553 +** A LIKE B 554 +** 555 +** is implemented as like(B,A). 556 +** 557 +** If the pointer retrieved by via a call to sqlite3_user_data() is 558 +** not NULL, then this function uses UTF-16. Otherwise UTF-8. 559 +*/ 560 +static void likeFunc( 561 + sqlite3_context *context, 562 + int argc, 563 + sqlite3_value **argv 564 +){ 565 + const unsigned char *zA = sqlite3_value_text(argv[0]); 566 + const unsigned char *zB = sqlite3_value_text(argv[1]); 567 + if( zA && zB ){ 568 + sqlite3_result_int(context, sqlite3utf8LikeCompare(zA, zB)); 569 + } 545 570 } 546 571 547 572 /* 548 573 ** Implementation of the glob() SQL function. This function implements 549 574 ** the build-in GLOB operator. The first argument to the function is the 550 575 ** string and the second argument is the pattern. So, the SQL statements: 551 576 ** ................................................................................ 781 806 static void test_destructor_count( 782 807 sqlite3_context *pCtx, 783 808 int nArg, 784 809 sqlite3_value **argv 785 810 ){ 786 811 sqlite3_result_int(pCtx, test_destructor_count_var); 787 812 } 813 + 814 +static void free_test_auxdata(void *p) {sqliteFree(p);} 815 +static void test_auxdata( 816 + sqlite3_context *pCtx, 817 + int nArg, 818 + sqlite3_value **argv 819 +){ 820 + int i; 821 + char *zRet = sqliteMalloc(nArg*2); 822 + if( !zRet ) return; 823 + for(i=0; i<nArg; i++){ 824 + char const *z = sqlite3_value_text(argv[i]); 825 + if( z ){ 826 + char *zAux = sqlite3_get_auxdata(pCtx, i); 827 + if( zAux ){ 828 + zRet[i*2] = '1'; 829 + if( strcmp(zAux, z) ){ 830 + sqlite3_result_error(pCtx, "Auxilary data corruption", -1); 831 + return; 832 + } 833 + }else{ 834 + zRet[i*2] = '0'; 835 + zAux = sqliteStrDup(z); 836 + sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata); 837 + } 838 + zRet[i*2+1] = ' '; 839 + } 840 + } 841 + sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata); 842 +} 788 843 #endif 789 844 790 845 /* 791 846 ** An instance of the following structure holds the context of a 792 847 ** sum() or avg() aggregate computation. 793 848 */ 794 849 typedef struct SumCtx SumCtx; ................................................................................ 961 1016 { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc }, 962 1017 { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc }, 963 1018 { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 }, 964 1019 { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 }, 965 1020 { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc }, 966 1021 { "random", -1, 0, SQLITE_UTF8, 0, randomFunc }, 967 1022 { "like", 2, 0, SQLITE_UTF8, 0, likeFunc }, 968 - { "like", 2, 2, SQLITE_UTF16,0, likeFunc }, 1023 +/* { "like", 2, 2, SQLITE_UTF16,0, likeFunc }, */ 969 1024 { "glob", 2, 0, SQLITE_UTF8, 0, globFunc }, 970 1025 { "nullif", 2, 0, SQLITE_UTF8, 0, nullifFunc }, 971 1026 { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, 972 1027 { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, 973 1028 { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, 974 1029 { "change_count", 0, 1, SQLITE_UTF8, 0, change_count }, 975 1030 { "last_statement_change_count", 0, 1, SQLITE_UTF8, 0, ................................................................................ 977 1032 #ifdef SQLITE_SOUNDEX 978 1033 { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, 979 1034 #endif 980 1035 #ifdef SQLITE_TEST 981 1036 { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, 982 1037 { "test_destructor", 1, 0, SQLITE_UTF8, 0, test_destructor}, 983 1038 { "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count}, 1039 + { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata}, 984 1040 #endif 985 1041 }; 986 1042 static struct { 987 1043 char *zName; 988 1044 signed char nArg; 989 1045 u8 argType; 990 1046 u8 needCollSeq;
Changes to src/sqliteInt.h.
7 7 ** May you do good and not evil. 8 8 ** May you find forgiveness for yourself and forgive others. 9 9 ** May you share freely, never taking more than you give. 10 10 ** 11 11 ************************************************************************* 12 12 ** Internal interface definitions for SQLite. 13 13 ** 14 -** @(#) $Id: sqliteInt.h,v 1.285 2004/06/12 09:25:21 danielk1977 Exp $ 14 +** @(#) $Id: sqliteInt.h,v 1.286 2004/06/17 05:36:44 danielk1977 Exp $ 15 15 */ 16 16 #include "config.h" 17 17 #include "sqlite3.h" 18 18 #include "hash.h" 19 19 #include "parse.h" 20 20 #include <stdio.h> 21 21 #include <stdlib.h> ................................................................................ 1378 1378 unsigned char *sqlite3utf16to8(const void *pData, int N, int big_endian); 1379 1379 void *sqlite3utf8to16be(const unsigned char *pIn, int N); 1380 1380 void *sqlite3utf8to16le(const unsigned char *pIn, int N); 1381 1381 void sqlite3utf16to16le(void *pData, int N); 1382 1382 void sqlite3utf16to16be(void *pData, int N); 1383 1383 int sqlite3utf16ByteLen(const void *pData, int nChar); 1384 1384 int sqlite3utf8CharLen(const char *pData, int nByte); 1385 +int sqlite3utf8LikeCompare(const unsigned char*, const unsigned char*); 1385 1386 int sqlite3PutVarint(unsigned char *, u64); 1386 1387 int sqlite3GetVarint(const unsigned char *, u64 *); 1387 1388 int sqlite3GetVarint32(const unsigned char *, u32 *); 1388 1389 int sqlite3VarintLen(u64 v); 1389 1390 char sqlite3AffinityType(const char *, int); 1390 1391 void sqlite3IndexAffinityStr(Vdbe *, Index *); 1391 1392 void sqlite3TableAffinityStr(Vdbe *, Table *); ................................................................................ 1410 1411 int sqlite3CheckObjectName(Parse *, const char *); 1411 1412 1412 1413 const void *sqlite3ValueText(sqlite3_value*, u8); 1413 1414 int sqlite3ValueBytes(sqlite3_value*, u8); 1414 1415 void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8); 1415 1416 void sqlite3ValueFree(sqlite3_value*); 1416 1417 sqlite3_value *sqlite3ValueNew(); 1417 -
Changes to src/utf.c.
8 8 ** May you find forgiveness for yourself and forgive others. 9 9 ** May you share freely, never taking more than you give. 10 10 ** 11 11 ************************************************************************* 12 12 ** This file contains routines used to translate between UTF-8, 13 13 ** UTF-16, UTF-16BE, and UTF-16LE. 14 14 ** 15 -** $Id: utf.c,v 1.19 2004/06/12 00:42:35 danielk1977 Exp $ 15 +** $Id: utf.c,v 1.20 2004/06/17 05:36:44 danielk1977 Exp $ 16 16 ** 17 17 ** Notes on UTF-8: 18 18 ** 19 19 ** Byte-0 Byte-1 Byte-2 Byte-3 Value 20 20 ** 0xxxxxxx 00000000 00000000 0xxxxxxx 21 21 ** 110yyyyy 10xxxxxx 00000000 00000yyy yyxxxxxx 22 22 ** 1110zzzz 10yyyyyy 10xxxxxx 00000000 zzzzyyyy yyxxxxxx ................................................................................ 81 81 ** case relationship between the 26 characters used in the English 82 82 ** language only. 83 83 ** 84 84 ** This means that characters with umlauts etc. will not be folded 85 85 ** correctly (unless they are encoded as composite characters, which would 86 86 ** doubtless cause much trouble). 87 87 */ 88 -#define LOWERCASE(x) (x<91?(int)(UpperToLower[x]):x); 88 +#define LOWERCASE(x) (x<91?(int)(UpperToLower[x]):x) 89 89 static unsigned char UpperToLower[91] = { 90 90 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 91 91 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 92 92 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 93 93 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 97, 98, 99,100,101,102,103, 94 94 104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121, 95 95 122, ................................................................................ 705 705 }else{ 706 706 *zOut = sqlite3utf16to8(zData, nData, enc1==SQLITE_UTF16BE); 707 707 if( !(*zOut) ) return SQLITE_NOMEM; 708 708 *nOut = strlen(*zOut); 709 709 } 710 710 return SQLITE_OK; 711 711 } 712 + 713 +#define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){} 714 + 715 +/* 716 +** Compare two UTF-8 strings for equality using the "LIKE" operator of 717 +** SQL. The '%' character matches any sequence of 0 or more 718 +** characters and '_' matches any single character. Case is 719 +** not significant. 720 +*/ 721 +int sqlite3utf8LikeCompare( 722 + const unsigned char *zPattern, 723 + const unsigned char *zString 724 +){ 725 + register int c; 726 + int c2; 727 + 728 + while( (c = LOWERCASE(*zPattern))!=0 ){ 729 + switch( c ){ 730 + case '%': { 731 + while( (c=zPattern[1]) == '%' || c == '_' ){ 732 + if( c=='_' ){ 733 + if( *zString==0 ) return 0; 734 + sqliteNextChar(zString); 735 + } 736 + zPattern++; 737 + } 738 + if( c==0 ) return 1; 739 + c = LOWERCASE(c); 740 + while( (c2=LOWERCASE(*zString))!=0 ){ 741 + while( c2 != 0 && c2 != c ){ 742 + zString++; 743 + c2 = LOWERCASE(*zString); 744 + } 745 + if( c2==0 ) return 0; 746 + if( sqlite3utf8LikeCompare(&zPattern[1],zString) ) return 1; 747 + sqliteNextChar(zString); 748 + } 749 + return 0; 750 + } 751 + case '_': { 752 + if( *zString==0 ) return 0; 753 + sqliteNextChar(zString); 754 + zPattern++; 755 + break; 756 + } 757 + default: { 758 + if( c != LOWERCASE(*zString) ) return 0; 759 + zPattern++; 760 + zString++; 761 + break; 762 + } 763 + } 764 + } 765 + return *zString==0; 766 +}
Changes to src/vdbemem.c.
143 143 /* 144 144 ** Make sure the given Mem is \u0000 terminated. 145 145 */ 146 146 int sqlite3VdbeMemNulTerminate(Mem *pMem){ 147 147 if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & (MEM_Str|MEM_Blob))==0 ){ 148 148 return SQLITE_OK; /* Nothing to do */ 149 149 } 150 - /* Only static or ephemeral strings can be unterminated */ 151 - assert( (pMem->flags & (MEM_Static|MEM_Ephem))!=0 ); 152 - return sqlite3VdbeMemMakeWriteable(pMem); 150 + 151 + if( pMem->flags & (MEM_Static|MEM_Ephem) ){ 152 + return sqlite3VdbeMemMakeWriteable(pMem); 153 + }else{ 154 + if( pMem->flags & MEM_Dyn ){ 155 + if( pMem->xDel ){ 156 + char *z = sqliteMalloc(pMem->n+2); 157 + if( !z ) return SQLITE_NOMEM; 158 + memcpy(z, pMem->z, pMem->n); 159 + pMem->xDel(pMem->z); 160 + pMem->xDel = 0; 161 + pMem->z = z; 162 + }else{ 163 + pMem->z = sqliteRealloc(pMem->z, pMem->n+2); 164 + if( !pMem->z ) return SQLITE_NOMEM; 165 + } 166 + }else{ 167 + assert( pMem->flags & MEM_Short ); 168 + if( pMem->n+2>NBFS ){ 169 + char *z = sqliteMalloc(pMem->n+2); 170 + if( !z ) return SQLITE_NOMEM; 171 + memcpy(z, pMem->z, pMem->n); 172 + pMem->flags &= !(MEM_Short); 173 + pMem->flags |= MEM_Dyn; 174 + pMem->xDel = 0; 175 + pMem->z = z; 176 + } 177 + } 178 + pMem->z[pMem->n++] = 0; 179 + pMem->z[pMem->n++] = 0; 180 + } 181 + return SQLITE_OK; 153 182 } 154 183 155 184 /* 156 185 ** Add MEM_Str to the set of representations for the given Mem. 157 186 ** A NULL is converted into an empty string. Numbers are converted 158 187 ** using sqlite3_snprintf(). Converting a BLOB to a string is a 159 188 ** no-op.
Changes to test/expr.test.
7 7 # May you find forgiveness for yourself and forgive others. 8 8 # May you share freely, never taking more than you give. 9 9 # 10 10 #*********************************************************************** 11 11 # This file implements regression tests for SQLite library. The 12 12 # focus of this file is testing expressions. 13 13 # 14 -# $Id: expr.test,v 1.33 2004/06/02 00:41:10 drh Exp $ 14 +# $Id: expr.test,v 1.34 2004/06/17 05:36:45 danielk1977 Exp $ 15 15 16 16 set testdir [file dirname $argv0] 17 17 source $testdir/tester.tcl 18 18 19 19 # Create a table to work with. 20 20 # 21 21 execsql {CREATE TABLE test1(i1 int, i2 int, r1 real, r2 real, t1 text, t2 text)} ................................................................................ 228 228 test_expr expr-4.20 {r1='0.0', r2='abc'} {r1>r2} 0 229 229 230 230 test_expr expr-5.1 {t1='abc', t2='xyz'} {t1 LIKE t2} 0 231 231 test_expr expr-5.2 {t1='abc', t2='ABC'} {t1 LIKE t2} 1 232 232 test_expr expr-5.3 {t1='abc', t2='A_C'} {t1 LIKE t2} 1 233 233 test_expr expr-5.4 {t1='abc', t2='abc_'} {t1 LIKE t2} 0 234 234 test_expr expr-5.5 {t1='abc', t2='A%C'} {t1 LIKE t2} 1 235 +test_expr expr-5.5a {t1='abdc', t2='a%c'} {t1 LIKE t2} 1 235 236 test_expr expr-5.5b {t1='ac', t2='A%C'} {t1 LIKE t2} 1 236 237 test_expr expr-5.6 {t1='abxyzzyc', t2='A%C'} {t1 LIKE t2} 1 237 238 test_expr expr-5.7 {t1='abxyzzy', t2='A%C'} {t1 LIKE t2} 0 238 239 test_expr expr-5.8 {t1='abxyzzycx', t2='A%C'} {t1 LIKE t2} 0 239 240 test_expr expr-5.8b {t1='abxyzzycy', t2='A%CX'} {t1 LIKE t2} 0 240 241 test_expr expr-5.9 {t1='abc', t2='A%_C'} {t1 LIKE t2} 1 241 242 test_expr expr-5.9b {t1='ac', t2='A%_C'} {t1 LIKE t2} 0
Changes to test/func.test.
7 7 # May you find forgiveness for yourself and forgive others. 8 8 # May you share freely, never taking more than you give. 9 9 # 10 10 #*********************************************************************** 11 11 # This file implements regression tests for SQLite library. The 12 12 # focus of this file is testing built-in functions. 13 13 # 14 -# $Id: func.test,v 1.21 2004/06/12 09:25:30 danielk1977 Exp $ 14 +# $Id: func.test,v 1.22 2004/06/17 05:36:45 danielk1977 Exp $ 15 15 16 16 set testdir [file dirname $argv0] 17 17 source $testdir/tester.tcl 18 18 19 19 # Create a table to work with. 20 20 # 21 21 do_test func-0.0 { ................................................................................ 333 333 do_test func-11.1 { 334 334 execsql { 335 335 SELECT sqlite_version(*); 336 336 } 337 337 } [sqlite -version] 338 338 339 339 # Test that destructors passed to sqlite by calls to sqlite3_result_text() 340 -# etc. are called. 340 +# etc. are called. These tests use two special user-defined functions 341 +# (implemented in func.c) only available in test builds. 342 +# 343 +# Function test_destructor() takes one argument and returns a copy of the 344 +# text form of that argument. A destructor is associated with the return 345 +# value. Function test_destructor_count() returns the number of outstanding 346 +# destructor calls for values returned by test_destructor(). 347 +# 341 348 do_test func-12.1 { 342 349 execsql { 343 350 SELECT test_destructor('hello world'), test_destructor_count(); 344 351 } 345 352 } {{hello world} 1} 346 353 do_test func-12.2 { 347 354 execsql { ................................................................................ 367 374 } 368 375 } {hello world} 369 376 do_test func-12.6 { 370 377 execsql { 371 378 SELECT test_destructor_count(); 372 379 } 373 380 } {0} 381 +do_test func-12.7 { 382 + execsql { 383 + DROP TABLE t4; 384 + } 385 +} {} 386 + 387 +# Test that the auxdata API for scalar functions works. This test uses 388 +# a special user-defined function only available in test builds, 389 +# test_auxdata(). Function test_auxdata() takes any number of arguments. 390 +do_test func-13.1 { 391 + execsql { 392 + SELECT test_auxdata('hello world'); 393 + } 394 +} {0} 395 +do_test func-13.2 { 396 + execsql { 397 + CREATE TABLE t4(a, b); 398 + INSERT INTO t4 VALUES('abc', 'def'); 399 + INSERT INTO t4 VALUES('ghi', 'jkl'); 400 + } 401 +} {} 402 +do_test func-13.3 { 403 + execsql { 404 + SELECT test_auxdata('hello world') FROM t4; 405 + } 406 +} {0 1} 407 +do_test func-13.4 { 408 + execsql { 409 + SELECT test_auxdata('hello world', 123) FROM t4; 410 + } 411 +} {{0 0} {1 1}} 412 +do_test func-13.5 { 413 + execsql { 414 + SELECT test_auxdata('hello world', a) FROM t4; 415 + } 416 +} {{0 0} {1 0}} 417 +do_test func-13.6 { 418 + execsql { 419 + SELECT test_auxdata('hello'||'world', a) FROM t4; 420 + } 421 +} {{0 0} {1 0}} 422 + 423 +# Test that auxilary data is preserved between calls for SQL variables. 424 +do_test func-13.7 { 425 + db close 426 + set DB [sqlite db test.db] 427 + set sql "SELECT test_auxdata( ? , a ) FROM t4;" 428 + set STMT [sqlite3_prepare $DB $sql -1 TAIL] 429 + sqlite3_bind_text $STMT 1 hello -1 430 + set res [list] 431 + while { "SQLITE_ROW"==[sqlite3_step $STMT] } { 432 + lappend res [sqlite3_column_text $STMT 0] 433 + } 434 + lappend res [sqlite3_finalize $STMT] 435 +} {{0 0} {1 0} SQLITE_OK} 374 436 375 437 376 438 finish_test 377 439 378 440 379 441