aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordanielk1977 <danielk1977@noemail.net>2004-06-17 05:36:44 +0000
committerdanielk1977 <danielk1977@noemail.net>2004-06-17 05:36:44 +0000
commit3f6b08747175508d3078a8cc56e3ee745ba6a044 (patch)
treed41a1d374a359b6755dfd3ff8e3a386438d2ee41 /src
parentd09b592f635572b81150f2ae2639701d7fb7f4f9 (diff)
downloadsqlite-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.c62
-rw-r--r--src/sqliteInt.h4
-rw-r--r--src/utf.c59
-rw-r--r--src/vdbemem.c35
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();
-
diff --git a/src/utf.c b/src/utf.c
index 5ee017c0d..d257f3f48 100644
--- a/src/utf.c
+++ b/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;
+}
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;
}
/*