diff options
author | danielk1977 <danielk1977@noemail.net> | 2004-06-17 05:36:44 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2004-06-17 05:36:44 +0000 |
commit | 3f6b08747175508d3078a8cc56e3ee745ba6a044 (patch) | |
tree | d41a1d374a359b6755dfd3ff8e3a386438d2ee41 /src | |
parent | d09b592f635572b81150f2ae2639701d7fb7f4f9 (diff) | |
download | sqlite-3f6b08747175508d3078a8cc56e3ee745ba6a044.tar.gz sqlite-3f6b08747175508d3078a8cc56e3ee745ba6a044.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/func.c | 62 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/utf.c | 59 | ||||
-rw-r--r-- | src/vdbemem.c | 35 |
4 files changed, 150 insertions, 10 deletions
diff --git a/src/func.c b/src/func.c index e4660ecab..015b20070 100644 --- a/src/func.c +++ b/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 { diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 554e3c68e..416642534 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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(); - @@ -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; +} diff --git a/src/vdbemem.c b/src/vdbemem.c index 787b2b029..6becf6f87 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -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; } /* |