Use the faster LIKE function from sqlite v2. Add special user functions to
test builds to test the auxdata APIs. (CVS 1610) FossilOrigin-Name: b9493c5facea4d24a6cbc4f6fa2f75dc2399a11d
This commit is contained in:
parent
d09b592f63
commit
3f6b087471
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
||||
C Remove\sthe\ssecond\sdefinition\sof\sSQLITE_N_BTREE_META\sfrom\stest3.c.\s(CVS\s1609)
|
||||
D 2004-06-17T00:01:21
|
||||
C Use\sthe\sfaster\sLIKE\sfunction\sfrom\ssqlite\sv2.\sAdd\sspecial\suser\sfunctions\sto\ntest\sbuilds\sto\stest\sthe\sauxdata\sAPIs.\s(CVS\s1610)
|
||||
D 2004-06-17T05:36:44
|
||||
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
|
||||
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@ -33,7 +33,7 @@ F src/date.c 65b483caeb0e4dd663667d2f927caa058168ebff
|
||||
F src/delete.c 1e94ef693e45b441f5c828ea0a064ac339008f8e
|
||||
F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
|
||||
F src/expr.c 657ca11f63a06aefd78014e6bc51dab6c735cc63
|
||||
F src/func.c be055fc63f1ae59c6a5dc4901240669f2a21f40c
|
||||
F src/func.c 1959a0c2f5328b2b9934620f9492964f080f4a71
|
||||
F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f
|
||||
F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb
|
||||
F src/insert.c 15575e57917ea2e5702a2b5935583c84139699c3
|
||||
@ -57,7 +57,7 @@ F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
|
||||
F src/select.c ee37ea91bea336e9cb3356e0790d3e8787b6ba13
|
||||
F src/shell.c ca519519dcbbc582f6d88f7d0e7583b857fd3469
|
||||
F src/sqlite.h.in 36c253844656186ca53e1999efa6ef7b44f88779
|
||||
F src/sqliteInt.h 924f0bcb493722c90cec7b19a240a37a4f01bbe7
|
||||
F src/sqliteInt.h 59c1e1b637e7cf329f39425469bc4dbeab1fa1d5
|
||||
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
|
||||
F src/tclsqlite.c 6f88be282a3617c6739c043fd13571b5f2fe9922
|
||||
F src/test1.c 49c69d360ce09f8ecf56ec5e55fba625703d8b21
|
||||
@ -68,7 +68,7 @@ F src/test5.c 13ac1db35b03acbc197ceb245fe862da5ebf2369
|
||||
F src/tokenize.c 183c5d7da11affab5d70d903d33409c8c0ce6c5b
|
||||
F src/trigger.c 3325207ea41d2d429e70370ce2ff987fd49b7ada
|
||||
F src/update.c f9a03233577e0c3d57234d1957963875fc941da2
|
||||
F src/utf.c e16737b3fc4201bf7ce9bd8ced5250596aa31b76
|
||||
F src/utf.c 92f0dd69bd1c1e4eff93c6038dd91b37ac1b9a65
|
||||
F src/util.c 6e93dad9a17b34f37fc270ba871b224240168bf0
|
||||
F src/vacuum.c f9561c8095407a970af4e6a304b77c4083433d3e
|
||||
F src/vdbe.c 35ae18345a8c35b17a37226cf868a99623288139
|
||||
@ -76,7 +76,7 @@ F src/vdbe.h 46f74444a213129bc4b5ce40124dd8ed613b0cde
|
||||
F src/vdbeInt.h 4e636b1b6c18d1d85b085fe0e5a19d45ad85f382
|
||||
F src/vdbeapi.c ee350b552fc4c1c695b760f914f69e9c5556e829
|
||||
F src/vdbeaux.c dc0e7d3bdf3b6f322448b4bee29fe5bec656b4d4
|
||||
F src/vdbemem.c 1e7df5ed53bc05433c7d3fb28899cf2c82bd16ac
|
||||
F src/vdbemem.c c00e939cfb19380fc80349e143b541a45ab53424
|
||||
F src/where.c 4955f34f7b46c9ca5c4e50e2db440f5e356f04dd
|
||||
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
|
||||
F test/attach.test aed659e52635662bcd5069599aaca823533edf5a
|
||||
@ -107,9 +107,9 @@ F test/date.test aed5030482ebc02bd8d386c6c86a29f694ab068d
|
||||
F test/delete.test ac14bd6df5f1581d646eebc013d6b844a885dcf6
|
||||
F test/enc.test a55481d45ff493804e8d88357feb4642fc50a6b2
|
||||
F test/enc2.test 8b00df318822731ea545365629bc9f52d73a3c6f
|
||||
F test/expr.test 521588701dae8cf5aa2b8a18c5c897711f754332
|
||||
F test/expr.test 2262ade5e4e98e359b11e40b01cb3498ac7fa42b
|
||||
F test/fkey1.test d65c824459916249bee501532d6154ddab0b5db7
|
||||
F test/func.test a63cf7a16bbd9dd1430214f6a0625099faa530f3
|
||||
F test/func.test 5fb6008f8805f8ff1f41cf269cf675aff8923c04
|
||||
F test/hook.test c4102c672d67f8fb60ea459842805abcba69a747
|
||||
F test/in.test b92a2df9162e1cbd33c6449a29a05e6955b1741a
|
||||
F test/index.test 4d2e73647872b540df4335387cc91faff4365020
|
||||
@ -224,7 +224,7 @@ F www/support.tcl 1801397edd271cc39a2aadd54e701184b5181248
|
||||
F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075
|
||||
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
|
||||
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
|
||||
P b3d5ad6f7832d46e34e99e4a1cb7e47c88f207a4
|
||||
R d93bea5ab3d12a073c52b74c322a8b4e
|
||||
P b1e66ae4640c2cd32d47c043b5c25ea67182098b
|
||||
R 79cf4eb54da41f0b0cf0acbcc361a701
|
||||
U danielk1977
|
||||
Z 8afc068f768f5a3187c752516f58beb6
|
||||
Z ebc17dbd051543173585388ad5a016a2
|
||||
|
@ -1 +1 @@
|
||||
b1e66ae4640c2cd32d47c043b5c25ea67182098b
|
||||
b9493c5facea4d24a6cbc4f6fa2f75dc2399a11d
|
62
src/func.c
62
src/func.c
@ -16,7 +16,7 @@
|
||||
** sqliteRegisterBuildinFunctions() found at the bottom of the file.
|
||||
** All other code has file scope.
|
||||
**
|
||||
** $Id: func.c,v 1.70 2004/06/16 10:39:24 danielk1977 Exp $
|
||||
** $Id: func.c,v 1.71 2004/06/17 05:36:44 danielk1977 Exp $
|
||||
*/
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
@ -317,8 +317,8 @@ void deleteLike(void *pLike){
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* #define TRACE_LIKE */
|
||||
|
||||
#if defined(TRACE_LIKE) && !defined(NDEBUG)
|
||||
char *dumpLike(LikePattern *pLike){
|
||||
int i;
|
||||
@ -543,6 +543,31 @@ skip_read:
|
||||
sqlite3_result_int(context, 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Implementation of the like() SQL function. This function implements
|
||||
** the build-in LIKE operator. The first argument to the function is the
|
||||
** pattern and the second argument is the string. So, the SQL statements:
|
||||
**
|
||||
** A LIKE B
|
||||
**
|
||||
** is implemented as like(B,A).
|
||||
**
|
||||
** If the pointer retrieved by via a call to sqlite3_user_data() is
|
||||
** not NULL, then this function uses UTF-16. Otherwise UTF-8.
|
||||
*/
|
||||
static void likeFunc(
|
||||
sqlite3_context *context,
|
||||
int argc,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
const unsigned char *zA = sqlite3_value_text(argv[0]);
|
||||
const unsigned char *zB = sqlite3_value_text(argv[1]);
|
||||
if( zA && zB ){
|
||||
sqlite3_result_int(context, sqlite3utf8LikeCompare(zA, zB));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of the glob() SQL function. This function implements
|
||||
@ -785,6 +810,36 @@ static void test_destructor_count(
|
||||
){
|
||||
sqlite3_result_int(pCtx, test_destructor_count_var);
|
||||
}
|
||||
|
||||
static void free_test_auxdata(void *p) {sqliteFree(p);}
|
||||
static void test_auxdata(
|
||||
sqlite3_context *pCtx,
|
||||
int nArg,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
int i;
|
||||
char *zRet = sqliteMalloc(nArg*2);
|
||||
if( !zRet ) return;
|
||||
for(i=0; i<nArg; i++){
|
||||
char const *z = sqlite3_value_text(argv[i]);
|
||||
if( z ){
|
||||
char *zAux = sqlite3_get_auxdata(pCtx, i);
|
||||
if( zAux ){
|
||||
zRet[i*2] = '1';
|
||||
if( strcmp(zAux, z) ){
|
||||
sqlite3_result_error(pCtx, "Auxilary data corruption", -1);
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
zRet[i*2] = '0';
|
||||
zAux = sqliteStrDup(z);
|
||||
sqlite3_set_auxdata(pCtx, i, zAux, free_test_auxdata);
|
||||
}
|
||||
zRet[i*2+1] = ' ';
|
||||
}
|
||||
}
|
||||
sqlite3_result_text(pCtx, zRet, 2*nArg-1, free_test_auxdata);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
@ -965,7 +1020,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite *db){
|
||||
{ "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc },
|
||||
{ "random", -1, 0, SQLITE_UTF8, 0, randomFunc },
|
||||
{ "like", 2, 0, SQLITE_UTF8, 0, likeFunc },
|
||||
{ "like", 2, 2, SQLITE_UTF16,0, likeFunc },
|
||||
/* { "like", 2, 2, SQLITE_UTF16,0, likeFunc }, */
|
||||
{ "glob", 2, 0, SQLITE_UTF8, 0, globFunc },
|
||||
{ "nullif", 2, 0, SQLITE_UTF8, 0, nullifFunc },
|
||||
{ "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc},
|
||||
@ -981,6 +1036,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite *db){
|
||||
{ "randstr", 2, 0, SQLITE_UTF8, 0, randStr },
|
||||
{ "test_destructor", 1, 0, SQLITE_UTF8, 0, test_destructor},
|
||||
{ "test_destructor_count", 0, 0, SQLITE_UTF8, 0, test_destructor_count},
|
||||
{ "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata},
|
||||
#endif
|
||||
};
|
||||
static struct {
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.285 2004/06/12 09:25:21 danielk1977 Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.286 2004/06/17 05:36:44 danielk1977 Exp $
|
||||
*/
|
||||
#include "config.h"
|
||||
#include "sqlite3.h"
|
||||
@ -1382,6 +1382,7 @@ void sqlite3utf16to16le(void *pData, int N);
|
||||
void sqlite3utf16to16be(void *pData, int N);
|
||||
int sqlite3utf16ByteLen(const void *pData, int nChar);
|
||||
int sqlite3utf8CharLen(const char *pData, int nByte);
|
||||
int sqlite3utf8LikeCompare(const unsigned char*, const unsigned char*);
|
||||
int sqlite3PutVarint(unsigned char *, u64);
|
||||
int sqlite3GetVarint(const unsigned char *, u64 *);
|
||||
int sqlite3GetVarint32(const unsigned char *, u32 *);
|
||||
@ -1414,4 +1415,3 @@ int sqlite3ValueBytes(sqlite3_value*, u8);
|
||||
void sqlite3ValueSetStr(sqlite3_value*, int, const void *,u8);
|
||||
void sqlite3ValueFree(sqlite3_value*);
|
||||
sqlite3_value *sqlite3ValueNew();
|
||||
|
||||
|
59
src/utf.c
59
src/utf.c
@ -12,7 +12,7 @@
|
||||
** This file contains routines used to translate between UTF-8,
|
||||
** UTF-16, UTF-16BE, and UTF-16LE.
|
||||
**
|
||||
** $Id: utf.c,v 1.19 2004/06/12 00:42:35 danielk1977 Exp $
|
||||
** $Id: utf.c,v 1.20 2004/06/17 05:36:44 danielk1977 Exp $
|
||||
**
|
||||
** Notes on UTF-8:
|
||||
**
|
||||
@ -85,7 +85,7 @@ struct UtfString {
|
||||
** correctly (unless they are encoded as composite characters, which would
|
||||
** doubtless cause much trouble).
|
||||
*/
|
||||
#define LOWERCASE(x) (x<91?(int)(UpperToLower[x]):x);
|
||||
#define LOWERCASE(x) (x<91?(int)(UpperToLower[x]):x)
|
||||
static unsigned char UpperToLower[91] = {
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
|
||||
18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
|
||||
@ -709,3 +709,58 @@ int sqlite3utfTranslate(
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
#define sqliteNextChar(X) while( (0xc0&*++(X))==0x80 ){}
|
||||
|
||||
/*
|
||||
** Compare two UTF-8 strings for equality using the "LIKE" operator of
|
||||
** SQL. The '%' character matches any sequence of 0 or more
|
||||
** characters and '_' matches any single character. Case is
|
||||
** not significant.
|
||||
*/
|
||||
int sqlite3utf8LikeCompare(
|
||||
const unsigned char *zPattern,
|
||||
const unsigned char *zString
|
||||
){
|
||||
register int c;
|
||||
int c2;
|
||||
|
||||
while( (c = LOWERCASE(*zPattern))!=0 ){
|
||||
switch( c ){
|
||||
case '%': {
|
||||
while( (c=zPattern[1]) == '%' || c == '_' ){
|
||||
if( c=='_' ){
|
||||
if( *zString==0 ) return 0;
|
||||
sqliteNextChar(zString);
|
||||
}
|
||||
zPattern++;
|
||||
}
|
||||
if( c==0 ) return 1;
|
||||
c = LOWERCASE(c);
|
||||
while( (c2=LOWERCASE(*zString))!=0 ){
|
||||
while( c2 != 0 && c2 != c ){
|
||||
zString++;
|
||||
c2 = LOWERCASE(*zString);
|
||||
}
|
||||
if( c2==0 ) return 0;
|
||||
if( sqlite3utf8LikeCompare(&zPattern[1],zString) ) return 1;
|
||||
sqliteNextChar(zString);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
case '_': {
|
||||
if( *zString==0 ) return 0;
|
||||
sqliteNextChar(zString);
|
||||
zPattern++;
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
if( c != LOWERCASE(*zString) ) return 0;
|
||||
zPattern++;
|
||||
zString++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return *zString==0;
|
||||
}
|
||||
|
@ -147,9 +147,38 @@ int sqlite3VdbeMemNulTerminate(Mem *pMem){
|
||||
if( (pMem->flags & MEM_Term)!=0 || (pMem->flags & (MEM_Str|MEM_Blob))==0 ){
|
||||
return SQLITE_OK; /* Nothing to do */
|
||||
}
|
||||
/* Only static or ephemeral strings can be unterminated */
|
||||
assert( (pMem->flags & (MEM_Static|MEM_Ephem))!=0 );
|
||||
return sqlite3VdbeMemMakeWriteable(pMem);
|
||||
|
||||
if( pMem->flags & (MEM_Static|MEM_Ephem) ){
|
||||
return sqlite3VdbeMemMakeWriteable(pMem);
|
||||
}else{
|
||||
if( pMem->flags & MEM_Dyn ){
|
||||
if( pMem->xDel ){
|
||||
char *z = sqliteMalloc(pMem->n+2);
|
||||
if( !z ) return SQLITE_NOMEM;
|
||||
memcpy(z, pMem->z, pMem->n);
|
||||
pMem->xDel(pMem->z);
|
||||
pMem->xDel = 0;
|
||||
pMem->z = z;
|
||||
}else{
|
||||
pMem->z = sqliteRealloc(pMem->z, pMem->n+2);
|
||||
if( !pMem->z ) return SQLITE_NOMEM;
|
||||
}
|
||||
}else{
|
||||
assert( pMem->flags & MEM_Short );
|
||||
if( pMem->n+2>NBFS ){
|
||||
char *z = sqliteMalloc(pMem->n+2);
|
||||
if( !z ) return SQLITE_NOMEM;
|
||||
memcpy(z, pMem->z, pMem->n);
|
||||
pMem->flags &= !(MEM_Short);
|
||||
pMem->flags |= MEM_Dyn;
|
||||
pMem->xDel = 0;
|
||||
pMem->z = z;
|
||||
}
|
||||
}
|
||||
pMem->z[pMem->n++] = 0;
|
||||
pMem->z[pMem->n++] = 0;
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing expressions.
|
||||
#
|
||||
# $Id: expr.test,v 1.33 2004/06/02 00:41:10 drh Exp $
|
||||
# $Id: expr.test,v 1.34 2004/06/17 05:36:45 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -232,6 +232,7 @@ test_expr expr-5.2 {t1='abc', t2='ABC'} {t1 LIKE t2} 1
|
||||
test_expr expr-5.3 {t1='abc', t2='A_C'} {t1 LIKE t2} 1
|
||||
test_expr expr-5.4 {t1='abc', t2='abc_'} {t1 LIKE t2} 0
|
||||
test_expr expr-5.5 {t1='abc', t2='A%C'} {t1 LIKE t2} 1
|
||||
test_expr expr-5.5a {t1='abdc', t2='a%c'} {t1 LIKE t2} 1
|
||||
test_expr expr-5.5b {t1='ac', t2='A%C'} {t1 LIKE t2} 1
|
||||
test_expr expr-5.6 {t1='abxyzzyc', t2='A%C'} {t1 LIKE t2} 1
|
||||
test_expr expr-5.7 {t1='abxyzzy', t2='A%C'} {t1 LIKE t2} 0
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing built-in functions.
|
||||
#
|
||||
# $Id: func.test,v 1.21 2004/06/12 09:25:30 danielk1977 Exp $
|
||||
# $Id: func.test,v 1.22 2004/06/17 05:36:45 danielk1977 Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -337,7 +337,14 @@ do_test func-11.1 {
|
||||
} [sqlite -version]
|
||||
|
||||
# Test that destructors passed to sqlite by calls to sqlite3_result_text()
|
||||
# etc. are called.
|
||||
# etc. are called. These tests use two special user-defined functions
|
||||
# (implemented in func.c) only available in test builds.
|
||||
#
|
||||
# Function test_destructor() takes one argument and returns a copy of the
|
||||
# text form of that argument. A destructor is associated with the return
|
||||
# value. Function test_destructor_count() returns the number of outstanding
|
||||
# destructor calls for values returned by test_destructor().
|
||||
#
|
||||
do_test func-12.1 {
|
||||
execsql {
|
||||
SELECT test_destructor('hello world'), test_destructor_count();
|
||||
@ -371,6 +378,61 @@ do_test func-12.6 {
|
||||
SELECT test_destructor_count();
|
||||
}
|
||||
} {0}
|
||||
do_test func-12.7 {
|
||||
execsql {
|
||||
DROP TABLE t4;
|
||||
}
|
||||
} {}
|
||||
|
||||
# Test that the auxdata API for scalar functions works. This test uses
|
||||
# a special user-defined function only available in test builds,
|
||||
# test_auxdata(). Function test_auxdata() takes any number of arguments.
|
||||
do_test func-13.1 {
|
||||
execsql {
|
||||
SELECT test_auxdata('hello world');
|
||||
}
|
||||
} {0}
|
||||
do_test func-13.2 {
|
||||
execsql {
|
||||
CREATE TABLE t4(a, b);
|
||||
INSERT INTO t4 VALUES('abc', 'def');
|
||||
INSERT INTO t4 VALUES('ghi', 'jkl');
|
||||
}
|
||||
} {}
|
||||
do_test func-13.3 {
|
||||
execsql {
|
||||
SELECT test_auxdata('hello world') FROM t4;
|
||||
}
|
||||
} {0 1}
|
||||
do_test func-13.4 {
|
||||
execsql {
|
||||
SELECT test_auxdata('hello world', 123) FROM t4;
|
||||
}
|
||||
} {{0 0} {1 1}}
|
||||
do_test func-13.5 {
|
||||
execsql {
|
||||
SELECT test_auxdata('hello world', a) FROM t4;
|
||||
}
|
||||
} {{0 0} {1 0}}
|
||||
do_test func-13.6 {
|
||||
execsql {
|
||||
SELECT test_auxdata('hello'||'world', a) FROM t4;
|
||||
}
|
||||
} {{0 0} {1 0}}
|
||||
|
||||
# Test that auxilary data is preserved between calls for SQL variables.
|
||||
do_test func-13.7 {
|
||||
db close
|
||||
set DB [sqlite db test.db]
|
||||
set sql "SELECT test_auxdata( ? , a ) FROM t4;"
|
||||
set STMT [sqlite3_prepare $DB $sql -1 TAIL]
|
||||
sqlite3_bind_text $STMT 1 hello -1
|
||||
set res [list]
|
||||
while { "SQLITE_ROW"==[sqlite3_step $STMT] } {
|
||||
lappend res [sqlite3_column_text $STMT 0]
|
||||
}
|
||||
lappend res [sqlite3_finalize $STMT]
|
||||
} {{0 0} {1 0} SQLITE_OK}
|
||||
|
||||
|
||||
finish_test
|
||||
|
Loading…
Reference in New Issue
Block a user