diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/func.c | 84 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/utf.c | 82 | ||||
-rw-r--r-- | src/vdbe.c | 10 | ||||
-rw-r--r-- | src/vdbeapi.c | 6 | ||||
-rw-r--r-- | src/vdbemem.c | 8 |
6 files changed, 146 insertions, 47 deletions
diff --git a/src/func.c b/src/func.c index e8cea2bbd..023a42f92 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.76 2004/06/24 00:20:05 danielk1977 Exp $ +** $Id: func.c,v 1.77 2004/06/28 13:09:11 danielk1977 Exp $ */ #include <ctype.h> #include <math.h> @@ -794,14 +794,26 @@ static void test_destructor( sqlite3_value **argv ){ char *zVal; + int len; + sqlite *db = sqlite3_user_data(pCtx); + test_destructor_count_var++; assert( nArg==1 ); if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return; - zVal = sqliteMalloc(sqlite3_value_bytes(argv[0]) + 2); + len = sqlite3ValueBytes(argv[0], db->enc); + zVal = sqliteMalloc(len+3); + zVal[len] = 0; + zVal[len-1] = 0; assert( zVal ); zVal++; - strcpy(zVal, sqlite3_value_text(argv[0])); - sqlite3_result_text(pCtx, zVal, -1, destructor); + memcpy(zVal, sqlite3ValueText(argv[0], db->enc), len); + if( db->enc==SQLITE_UTF8 ){ + sqlite3_result_text(pCtx, zVal, -1, destructor); + }else if( db->enc==SQLITE_UTF16LE ){ + sqlite3_result_text16le(pCtx, zVal, -1, destructor); + }else{ + sqlite3_result_text16be(pCtx, zVal, -1, destructor); + } } static void test_destructor_count( sqlite3_context *pCtx, @@ -1010,45 +1022,45 @@ void sqlite3RegisterBuiltinFunctions(sqlite *db){ static struct { char *zName; signed char nArg; - u8 argType; /* 0: none. 1: db 2: (-1) */ - u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ + u8 argType; /* 0: none. 1: db 2: (-1) */ + u8 eTextRep; /* 1: UTF-16. 0: UTF-8 */ u8 needCollSeq; void (*xFunc)(sqlite3_context*,int,sqlite3_value **); } aFuncs[] = { - { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc }, - { "min", 0, 0, SQLITE_UTF8, 1, 0 }, - { "max", -1, 2, SQLITE_UTF8, 1, minmaxFunc }, - { "max", 0, 2, SQLITE_UTF8, 1, 0 }, - { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc }, - { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc }, - { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc }, - { "abs", 1, 0, SQLITE_UTF8, 0, absFunc }, - { "round", 1, 0, SQLITE_UTF8, 0, roundFunc }, - { "round", 2, 0, SQLITE_UTF8, 0, roundFunc }, - { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc }, - { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc }, - { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc }, - { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 }, - { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 }, - { "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 }, */ - { "glob", 2, 0, SQLITE_UTF8, 0, globFunc }, - { "nullif", 2, 0, SQLITE_UTF8, 0, nullifFunc }, - { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, - { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, - { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, - { "changes", 0, 1, SQLITE_UTF8, 0, changes }, - { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, + { "min", -1, 0, SQLITE_UTF8, 1, minmaxFunc }, + { "min", 0, 0, SQLITE_UTF8, 1, 0 }, + { "max", -1, 2, SQLITE_UTF8, 1, minmaxFunc }, + { "max", 0, 2, SQLITE_UTF8, 1, 0 }, + { "typeof", 1, 0, SQLITE_UTF8, 0, typeofFunc }, + { "length", 1, 0, SQLITE_UTF8, 0, lengthFunc }, + { "substr", 3, 0, SQLITE_UTF8, 0, substrFunc }, + { "substr", 3, 0, SQLITE_UTF16LE, 0, sqlite3utf16Substr }, + { "abs", 1, 0, SQLITE_UTF8, 0, absFunc }, + { "round", 1, 0, SQLITE_UTF8, 0, roundFunc }, + { "round", 2, 0, SQLITE_UTF8, 0, roundFunc }, + { "upper", 1, 0, SQLITE_UTF8, 0, upperFunc }, + { "lower", 1, 0, SQLITE_UTF8, 0, lowerFunc }, + { "coalesce", -1, 0, SQLITE_UTF8, 0, ifnullFunc }, + { "coalesce", 0, 0, SQLITE_UTF8, 0, 0 }, + { "coalesce", 1, 0, SQLITE_UTF8, 0, 0 }, + { "ifnull", 2, 0, SQLITE_UTF8, 1, ifnullFunc }, + { "random", -1, 0, SQLITE_UTF8, 0, randomFunc }, + { "like", 2, 0, SQLITE_UTF8, 0, likeFunc }, + { "glob", 2, 0, SQLITE_UTF8, 0, globFunc }, + { "nullif", 2, 0, SQLITE_UTF8, 0, nullifFunc }, + { "sqlite_version", 0, 0, SQLITE_UTF8, 0, versionFunc}, + { "quote", 1, 0, SQLITE_UTF8, 0, quoteFunc }, + { "last_insert_rowid", 0, 1, SQLITE_UTF8, 0, last_insert_rowid }, + { "changes", 0, 1, SQLITE_UTF8, 0, changes }, + { "total_changes", 0, 1, SQLITE_UTF8, 0, total_changes }, #ifdef SQLITE_SOUNDEX - { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, + { "soundex", 1, 0, SQLITE_UTF8, 0, soundexFunc}, #endif #ifdef SQLITE_TEST - { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, - { "test_destructor", 1, 0, SQLITE_UTF8, 0, test_destructor}, + { "randstr", 2, 0, SQLITE_UTF8, 0, randStr }, + { "test_destructor", 1, 1, 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}, + { "test_auxdata", -1, 0, SQLITE_UTF8, 0, test_auxdata}, #endif }; static struct { diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 60fccc787..fde5bac5b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.301 2004/06/26 08:38:25 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.302 2004/06/28 13:09:11 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1368,6 +1368,7 @@ int sqlite3CheckCollSeq(Parse *, CollSeq *); int sqlite3CheckIndexCollSeq(Parse *, Index *); int sqlite3CheckObjectName(Parse *, const char *); void sqlite3VdbeSetChanges(sqlite3 *, int); +void sqlite3utf16Substr(sqlite3_context *,int,sqlite3_value **); const void *sqlite3ValueText(sqlite3_value*, u8); int sqlite3ValueBytes(sqlite3_value*, u8); @@ -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.25 2004/06/23 13:46:32 danielk1977 Exp $ +** $Id: utf.c,v 1.26 2004/06/28 13:09:11 danielk1977 Exp $ ** ** Notes on UTF-8: ** @@ -210,6 +210,38 @@ static const int xtra_utf8_bits[4] = { } \ } +#define SKIP_UTF16BE(zIn){ \ + if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn+1)==0x00)) ){ \ + zIn += 4; \ + }else{ \ + zIn += 2; \ + } \ +} +#define SKIP_UTF16LE(zIn){ \ + zIn++; \ + if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn-1)==0x00)) ){ \ + zIn += 3; \ + }else{ \ + zIn += 1; \ + } \ +} + +#define RSKIP_UTF16LE(zIn){ \ + if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn-1)==0x00)) ){ \ + zIn -= 4; \ + }else{ \ + zIn -= 2; \ + } \ +} +#define RSKIP_UTF16BE(zIn){ \ + zIn--; \ + if( *zIn>=0xD8 && (*zIn<0xE0 || (*zIn==0xE0 && *(zIn+1)==0x00)) ){ \ + zIn -= 3; \ + }else{ \ + zIn -= 1; \ + } \ +} + /* ** If the TRANSLATE_TRACE macro is defined, the value of each Mem is ** printed on stderr on the way into and out of sqlite3VdbeMemTranslate(). @@ -507,6 +539,54 @@ int sqlite3utf8LikeCompare( return *zString==0; } +/* +** UTF-16 implementation of the substr() +*/ +void sqlite3utf16Substr( + sqlite3_context *context, + int argc, + sqlite3_value **argv +){ + int y, z; + unsigned char const *zStr; + unsigned char const *zStrEnd; + unsigned char const *zStart; + unsigned char const *zEnd; + int i; + + zStr = (unsigned char const *)sqlite3_value_text16(argv[0]); + zStrEnd = &zStr[sqlite3_value_bytes16(argv[0])]; + y = sqlite3_value_int(argv[1]); + z = sqlite3_value_int(argv[2]); + + if( y>0 ){ + y = y-1; + zStart = zStr; + if( SQLITE_UTF16BE==SQLITE_UTF16NATIVE ){ + for(i=0; i<y && zStart<zStrEnd; i++) SKIP_UTF16BE(zStart); + }else{ + for(i=0; i<y && zStart<zStrEnd; i++) SKIP_UTF16LE(zStart); + } + }else{ + zStart = zStrEnd; + if( SQLITE_UTF16BE==SQLITE_UTF16NATIVE ){ + for(i=y; i<0 && zStart>zStr; i++) RSKIP_UTF16BE(zStart); + }else{ + for(i=y; i<0 && zStart>zStr; i++) RSKIP_UTF16LE(zStart); + } + for(; i<0; i++) z -= 1; + } + + zEnd = zStart; + if( SQLITE_UTF16BE==SQLITE_UTF16NATIVE ){ + for(i=0; i<z && zEnd<zStrEnd; i++) SKIP_UTF16BE(zEnd); + }else{ + for(i=0; i<z && zEnd<zStrEnd; i++) SKIP_UTF16LE(zEnd); + } + + sqlite3_result_text16(context, zStart, zEnd-zStart, SQLITE_TRANSIENT); +} + #if defined(SQLITE_TEST) /* ** This routine is called from the TCL test function "translate_selftest". diff --git a/src/vdbe.c b/src/vdbe.c index 6f2b71b33..5b49d1d9b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.392 2004/06/28 01:11:47 danielk1977 Exp $ +** $Id: vdbe.c,v 1.393 2004/06/28 13:09:11 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -1288,8 +1288,12 @@ case OP_Function: { } /* If the function returned an error, throw an exception */ if( ctx.isError ){ - sqlite3SetString(&p->zErrMsg, - (pTos->flags & MEM_Str)!=0 ? pTos->z : "user function error", (char*)0); + if( !(pTos->flags&MEM_Str) ){ + sqlite3SetString(&p->zErrMsg, "user function error", (char*)0); + }else{ + sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pTos), (char*)0); + sqlite3VdbeChangeEncoding(pTos, db->enc); + } rc = SQLITE_ERROR; } break; diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 57b1b8776..6935ca7d1 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -341,7 +341,6 @@ const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){ Mem *pColName; if( N>=sqlite3_column_count(pStmt) || N<0 ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); return 0; } @@ -358,7 +357,6 @@ const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){ Mem *pColName; if( N>=sqlite3_column_count(pStmt) || N<0 ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); return 0; } @@ -375,7 +373,6 @@ const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){ Mem *pColName; if( N>=sqlite3_column_count(pStmt) || N<0 ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); return 0; } @@ -392,7 +389,6 @@ const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ Mem *pColName; if( N>=sqlite3_column_count(pStmt) || N<0 ){ - sqlite3Error(p->db, SQLITE_RANGE, 0); return 0; } @@ -459,7 +455,7 @@ int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){ if( rc==SQLITE_OK ){ sqlite3VdbeMemSetDouble(&p->apVar[i-1], rValue); } - return SQLITE_OK; + return rc; } int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){ return sqlite3_bind_int64(p, i, (i64)iValue); diff --git a/src/vdbemem.c b/src/vdbemem.c index 55b0fbb9f..7f26c7dd6 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -497,13 +497,19 @@ int sqlite3MemCompare(const Mem *pMem1, const Mem *pMem2, const CollSeq *pColl){ if( pMem1->enc==pColl->enc ){ return pColl->xCmp(pColl->pUser,pMem1->n,pMem1->z,pMem2->n,pMem2->z); }else{ - return pColl->xCmp( + u8 origEnc = pMem1->enc; + rc = pColl->xCmp( pColl->pUser, sqlite3ValueBytes((sqlite3_value*)pMem1, pColl->enc), sqlite3ValueText((sqlite3_value*)pMem1, pColl->enc), sqlite3ValueBytes((sqlite3_value*)pMem2, pColl->enc), sqlite3ValueText((sqlite3_value*)pMem2, pColl->enc) ); + sqlite3ValueBytes((sqlite3_value*)pMem1, origEnc); + sqlite3ValueText((sqlite3_value*)pMem1, origEnc); + sqlite3ValueBytes((sqlite3_value*)pMem2, origEnc); + sqlite3ValueText((sqlite3_value*)pMem2, origEnc); + return rc; } } /* If a NULL pointer was passed as the collate function, fall through |