| Index: third_party/sqlite/src/src/func.c
|
| diff --git a/third_party/sqlite/src/src/func.c b/third_party/sqlite/src/src/func.c
|
| index 3fbd2b736bb9ca6a706d4862132a4952227f0237..885725bc6b4757021092ad122a515998ca43accd 100644
|
| --- a/third_party/sqlite/src/src/func.c
|
| +++ b/third_party/sqlite/src/src/func.c
|
| @@ -200,23 +200,28 @@ static void instrFunc(
|
| if( typeHaystack==SQLITE_NULL || typeNeedle==SQLITE_NULL ) return;
|
| nHaystack = sqlite3_value_bytes(argv[0]);
|
| nNeedle = sqlite3_value_bytes(argv[1]);
|
| - if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
|
| - zHaystack = sqlite3_value_blob(argv[0]);
|
| - zNeedle = sqlite3_value_blob(argv[1]);
|
| - isText = 0;
|
| - }else{
|
| - zHaystack = sqlite3_value_text(argv[0]);
|
| - zNeedle = sqlite3_value_text(argv[1]);
|
| - isText = 1;
|
| - }
|
| - while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
|
| - N++;
|
| - do{
|
| - nHaystack--;
|
| - zHaystack++;
|
| - }while( isText && (zHaystack[0]&0xc0)==0x80 );
|
| + if( nNeedle>0 ){
|
| + if( typeHaystack==SQLITE_BLOB && typeNeedle==SQLITE_BLOB ){
|
| + zHaystack = sqlite3_value_blob(argv[0]);
|
| + zNeedle = sqlite3_value_blob(argv[1]);
|
| + assert( zNeedle!=0 );
|
| + assert( zHaystack!=0 || nHaystack==0 );
|
| + isText = 0;
|
| + }else{
|
| + zHaystack = sqlite3_value_text(argv[0]);
|
| + zNeedle = sqlite3_value_text(argv[1]);
|
| + isText = 1;
|
| + if( zHaystack==0 || zNeedle==0 ) return;
|
| + }
|
| + while( nNeedle<=nHaystack && memcmp(zHaystack, zNeedle, nNeedle)!=0 ){
|
| + N++;
|
| + do{
|
| + nHaystack--;
|
| + zHaystack++;
|
| + }while( isText && (zHaystack[0]&0xc0)==0x80 );
|
| + }
|
| + if( nNeedle>nHaystack ) N = 0;
|
| }
|
| - if( nNeedle>nHaystack ) N = 0;
|
| sqlite3_result_int(context, N);
|
| }
|
|
|
| @@ -239,7 +244,8 @@ static void printfFunc(
|
| x.nUsed = 0;
|
| x.apArg = argv+1;
|
| sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
|
| - sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x);
|
| + str.printfFlags = SQLITE_PRINTF_SQLFUNC;
|
| + sqlite3XPrintf(&str, zFormat, &x);
|
| n = str.nChar;
|
| sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
|
| SQLITE_DYNAMIC);
|
| @@ -567,10 +573,10 @@ static void total_changes(
|
| ** A structure defining how to do GLOB-style comparisons.
|
| */
|
| struct compareInfo {
|
| - u8 matchAll;
|
| - u8 matchOne;
|
| - u8 matchSet;
|
| - u8 noCase;
|
| + u8 matchAll; /* "*" or "%" */
|
| + u8 matchOne; /* "?" or "_" */
|
| + u8 matchSet; /* "[" or 0 */
|
| + u8 noCase; /* true to ignore case differences */
|
| };
|
|
|
| /*
|
| @@ -595,9 +601,19 @@ static const struct compareInfo likeInfoNorm = { '%', '_', 0, 1 };
|
| static const struct compareInfo likeInfoAlt = { '%', '_', 0, 0 };
|
|
|
| /*
|
| -** Compare two UTF-8 strings for equality where the first string can
|
| -** potentially be a "glob" or "like" expression. Return true (1) if they
|
| -** are the same and false (0) if they are different.
|
| +** Possible error returns from patternMatch()
|
| +*/
|
| +#define SQLITE_MATCH 0
|
| +#define SQLITE_NOMATCH 1
|
| +#define SQLITE_NOWILDCARDMATCH 2
|
| +
|
| +/*
|
| +** Compare two UTF-8 strings for equality where the first string is
|
| +** a GLOB or LIKE expression. Return values:
|
| +**
|
| +** SQLITE_MATCH: Match
|
| +** SQLITE_NOMATCH: No match
|
| +** SQLITE_NOWILDCARDMATCH: No match in spite of having * or % wildcards.
|
| **
|
| ** Globbing rules:
|
| **
|
| @@ -633,22 +649,14 @@ static int patternCompare(
|
| const u8 *zPattern, /* The glob pattern */
|
| const u8 *zString, /* The string to compare against the glob */
|
| const struct compareInfo *pInfo, /* Information about how to do the compare */
|
| - u32 esc /* The escape character */
|
| + u32 matchOther /* The escape char (LIKE) or '[' (GLOB) */
|
| ){
|
| u32 c, c2; /* Next pattern and input string chars */
|
| u32 matchOne = pInfo->matchOne; /* "?" or "_" */
|
| u32 matchAll = pInfo->matchAll; /* "*" or "%" */
|
| - u32 matchOther; /* "[" or the escape character */
|
| u8 noCase = pInfo->noCase; /* True if uppercase==lowercase */
|
| const u8 *zEscaped = 0; /* One past the last escaped input char */
|
|
|
| - /* The GLOB operator does not have an ESCAPE clause. And LIKE does not
|
| - ** have the matchSet operator. So we either have to look for one or
|
| - ** the other, never both. Hence the single variable matchOther is used
|
| - ** to store the one we have to look for.
|
| - */
|
| - matchOther = esc ? esc : pInfo->matchSet;
|
| -
|
| while( (c = Utf8Read(zPattern))!=0 ){
|
| if( c==matchAll ){ /* Match "*" */
|
| /* Skip over multiple "*" characters in the pattern. If there
|
| @@ -656,30 +664,31 @@ static int patternCompare(
|
| ** single character of the input string for each "?" skipped */
|
| while( (c=Utf8Read(zPattern)) == matchAll || c == matchOne ){
|
| if( c==matchOne && sqlite3Utf8Read(&zString)==0 ){
|
| - return 0;
|
| + return SQLITE_NOWILDCARDMATCH;
|
| }
|
| }
|
| if( c==0 ){
|
| - return 1; /* "*" at the end of the pattern matches */
|
| + return SQLITE_MATCH; /* "*" at the end of the pattern matches */
|
| }else if( c==matchOther ){
|
| - if( esc ){
|
| + if( pInfo->matchSet==0 ){
|
| c = sqlite3Utf8Read(&zPattern);
|
| - if( c==0 ) return 0;
|
| + if( c==0 ) return SQLITE_NOWILDCARDMATCH;
|
| }else{
|
| /* "[...]" immediately follows the "*". We have to do a slow
|
| ** recursive search in this case, but it is an unusual case. */
|
| assert( matchOther<0x80 ); /* '[' is a single-byte character */
|
| - while( *zString
|
| - && patternCompare(&zPattern[-1],zString,pInfo,esc)==0 ){
|
| + while( *zString ){
|
| + int bMatch = patternCompare(&zPattern[-1],zString,pInfo,matchOther);
|
| + if( bMatch!=SQLITE_NOMATCH ) return bMatch;
|
| SQLITE_SKIP_UTF8(zString);
|
| }
|
| - return *zString!=0;
|
| + return SQLITE_NOWILDCARDMATCH;
|
| }
|
| }
|
|
|
| /* At this point variable c contains the first character of the
|
| ** pattern string past the "*". Search in the input string for the
|
| - ** first matching character and recursively contine the match from
|
| + ** first matching character and recursively continue the match from
|
| ** that point.
|
| **
|
| ** For a case-insensitive search, set variable cx to be the same as
|
| @@ -688,6 +697,7 @@ static int patternCompare(
|
| */
|
| if( c<=0x80 ){
|
| u32 cx;
|
| + int bMatch;
|
| if( noCase ){
|
| cx = sqlite3Toupper(c);
|
| c = sqlite3Tolower(c);
|
| @@ -696,27 +706,30 @@ static int patternCompare(
|
| }
|
| while( (c2 = *(zString++))!=0 ){
|
| if( c2!=c && c2!=cx ) continue;
|
| - if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
| + bMatch = patternCompare(zPattern,zString,pInfo,matchOther);
|
| + if( bMatch!=SQLITE_NOMATCH ) return bMatch;
|
| }
|
| }else{
|
| + int bMatch;
|
| while( (c2 = Utf8Read(zString))!=0 ){
|
| if( c2!=c ) continue;
|
| - if( patternCompare(zPattern,zString,pInfo,esc) ) return 1;
|
| + bMatch = patternCompare(zPattern,zString,pInfo,matchOther);
|
| + if( bMatch!=SQLITE_NOMATCH ) return bMatch;
|
| }
|
| }
|
| - return 0;
|
| + return SQLITE_NOWILDCARDMATCH;
|
| }
|
| if( c==matchOther ){
|
| - if( esc ){
|
| + if( pInfo->matchSet==0 ){
|
| c = sqlite3Utf8Read(&zPattern);
|
| - if( c==0 ) return 0;
|
| + if( c==0 ) return SQLITE_NOMATCH;
|
| zEscaped = zPattern;
|
| }else{
|
| u32 prior_c = 0;
|
| int seen = 0;
|
| int invert = 0;
|
| c = sqlite3Utf8Read(&zString);
|
| - if( c==0 ) return 0;
|
| + if( c==0 ) return SQLITE_NOMATCH;
|
| c2 = sqlite3Utf8Read(&zPattern);
|
| if( c2=='^' ){
|
| invert = 1;
|
| @@ -740,34 +753,36 @@ static int patternCompare(
|
| c2 = sqlite3Utf8Read(&zPattern);
|
| }
|
| if( c2==0 || (seen ^ invert)==0 ){
|
| - return 0;
|
| + return SQLITE_NOMATCH;
|
| }
|
| continue;
|
| }
|
| }
|
| c2 = Utf8Read(zString);
|
| if( c==c2 ) continue;
|
| - if( noCase && c<0x80 && c2<0x80 && sqlite3Tolower(c)==sqlite3Tolower(c2) ){
|
| + if( noCase && sqlite3Tolower(c)==sqlite3Tolower(c2) && c<0x80 && c2<0x80 ){
|
| continue;
|
| }
|
| if( c==matchOne && zPattern!=zEscaped && c2!=0 ) continue;
|
| - return 0;
|
| + return SQLITE_NOMATCH;
|
| }
|
| - return *zString==0;
|
| + return *zString==0 ? SQLITE_MATCH : SQLITE_NOMATCH;
|
| }
|
|
|
| /*
|
| -** The sqlite3_strglob() interface.
|
| +** The sqlite3_strglob() interface. Return 0 on a match (like strcmp()) and
|
| +** non-zero if there is no match.
|
| */
|
| int sqlite3_strglob(const char *zGlobPattern, const char *zString){
|
| - return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0;
|
| + return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, '[');
|
| }
|
|
|
| /*
|
| -** The sqlite3_strlike() interface.
|
| +** The sqlite3_strlike() interface. Return 0 on a match and non-zero for
|
| +** a miss - like strcmp().
|
| */
|
| int sqlite3_strlike(const char *zPattern, const char *zStr, unsigned int esc){
|
| - return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc)==0;
|
| + return patternCompare((u8*)zPattern, (u8*)zStr, &likeInfoNorm, esc);
|
| }
|
|
|
| /*
|
| @@ -798,9 +813,10 @@ static void likeFunc(
|
| sqlite3_value **argv
|
| ){
|
| const unsigned char *zA, *zB;
|
| - u32 escape = 0;
|
| + u32 escape;
|
| int nPat;
|
| sqlite3 *db = sqlite3_context_db_handle(context);
|
| + struct compareInfo *pInfo = sqlite3_user_data(context);
|
|
|
| #ifdef SQLITE_LIKE_DOESNT_MATCH_BLOBS
|
| if( sqlite3_value_type(argv[0])==SQLITE_BLOB
|
| @@ -840,14 +856,14 @@ static void likeFunc(
|
| return;
|
| }
|
| escape = sqlite3Utf8Read(&zEsc);
|
| + }else{
|
| + escape = pInfo->matchSet;
|
| }
|
| if( zA && zB ){
|
| - struct compareInfo *pInfo = sqlite3_user_data(context);
|
| #ifdef SQLITE_TEST
|
| sqlite3_like_count++;
|
| #endif
|
| -
|
| - sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape));
|
| + sqlite3_result_int(context, patternCompare(zB, zA, pInfo, escape)==SQLITE_MATCH);
|
| }
|
| }
|
|
|
| @@ -1322,6 +1338,26 @@ static void trimFunc(
|
| }
|
|
|
|
|
| +#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
| +/*
|
| +** The "unknown" function is automatically substituted in place of
|
| +** any unrecognized function name when doing an EXPLAIN or EXPLAIN QUERY PLAN
|
| +** when the SQLITE_ENABLE_UNKNOWN_FUNCTION compile-time option is used.
|
| +** When the "sqlite3" command-line shell is built using this functionality,
|
| +** that allows an EXPLAIN or EXPLAIN QUERY PLAN for complex queries
|
| +** involving application-defined functions to be examined in a generic
|
| +** sqlite3 shell.
|
| +*/
|
| +static void unknownFunc(
|
| + sqlite3_context *context,
|
| + int argc,
|
| + sqlite3_value **argv
|
| +){
|
| + /* no-op */
|
| +}
|
| +#endif /*SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION*/
|
| +
|
| +
|
| /* IMP: R-25361-16150 This function is omitted from SQLite by default. It
|
| ** is only available if the SQLITE_SOUNDEX compile-time option is used
|
| ** when SQLite is built.
|
| @@ -1392,6 +1428,14 @@ static void loadExt(sqlite3_context *context, int argc, sqlite3_value **argv){
|
| sqlite3 *db = sqlite3_context_db_handle(context);
|
| char *zErrMsg = 0;
|
|
|
| + /* Disallow the load_extension() SQL function unless the SQLITE_LoadExtFunc
|
| + ** flag is set. See the sqlite3_enable_load_extension() API.
|
| + */
|
| + if( (db->flags & SQLITE_LoadExtFunc)==0 ){
|
| + sqlite3_result_error(context, "not authorized", -1);
|
| + return;
|
| + }
|
| +
|
| if( argc==2 ){
|
| zProc = (const char *)sqlite3_value_text(argv[1]);
|
| }else{
|
| @@ -1590,7 +1634,7 @@ static void groupConcatStep(
|
| zSep = ",";
|
| nSep = 1;
|
| }
|
| - if( nSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
|
| + if( zSep ) sqlite3StrAccumAppend(pAccum, zSep, nSep);
|
| }
|
| zVal = (char*)sqlite3_value_text(argv[0]);
|
| nVal = sqlite3_value_bytes(argv[0]);
|
| @@ -1617,11 +1661,11 @@ static void groupConcatFinalize(sqlite3_context *context){
|
| ** of the built-in functions above are part of the global function set.
|
| ** This routine only deals with those that are not global.
|
| */
|
| -void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
|
| +void sqlite3RegisterPerConnectionBuiltinFunctions(sqlite3 *db){
|
| int rc = sqlite3_overload_function(db, "MATCH", 2);
|
| assert( rc==SQLITE_NOMEM || rc==SQLITE_OK );
|
| if( rc==SQLITE_NOMEM ){
|
| - db->mallocFailed = 1;
|
| + sqlite3OomFault(db);
|
| }
|
| }
|
|
|
| @@ -1630,8 +1674,7 @@ void sqlite3RegisterBuiltinFunctions(sqlite3 *db){
|
| */
|
| static void setLikeOptFlag(sqlite3 *db, const char *zName, u8 flagVal){
|
| FuncDef *pDef;
|
| - pDef = sqlite3FindFunction(db, zName, sqlite3Strlen30(zName),
|
| - 2, SQLITE_UTF8, 0);
|
| + pDef = sqlite3FindFunction(db, zName, 2, SQLITE_UTF8, 0);
|
| if( ALWAYS(pDef) ){
|
| pDef->funcFlags |= flagVal;
|
| }
|
| @@ -1679,9 +1722,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
| return 0;
|
| }
|
| assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
|
| - pDef = sqlite3FindFunction(db, pExpr->u.zToken,
|
| - sqlite3Strlen30(pExpr->u.zToken),
|
| - 2, SQLITE_UTF8, 0);
|
| + pDef = sqlite3FindFunction(db, pExpr->u.zToken, 2, SQLITE_UTF8, 0);
|
| if( NEVER(pDef==0) || (pDef->funcFlags & SQLITE_FUNC_LIKE)==0 ){
|
| return 0;
|
| }
|
| @@ -1705,7 +1746,7 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
|
| **
|
| ** After this routine runs
|
| */
|
| -void sqlite3RegisterGlobalFunctions(void){
|
| +void sqlite3RegisterBuiltinFunctions(void){
|
| /*
|
| ** The following array holds FuncDef structures for all of the functions
|
| ** defined in this file.
|
| @@ -1713,8 +1754,30 @@ void sqlite3RegisterGlobalFunctions(void){
|
| ** The array cannot be constant since changes are made to the
|
| ** FuncDef.pHash elements at start-time. The elements of this array
|
| ** are read-only after initialization is complete.
|
| + **
|
| + ** For peak efficiency, put the most frequently used function last.
|
| */
|
| - static SQLITE_WSD FuncDef aBuiltinFunc[] = {
|
| + static FuncDef aBuiltinFunc[] = {
|
| +#ifdef SQLITE_SOUNDEX
|
| + FUNCTION(soundex, 1, 0, 0, soundexFunc ),
|
| +#endif
|
| +#ifndef SQLITE_OMIT_LOAD_EXTENSION
|
| + VFUNCTION(load_extension, 1, 0, 0, loadExt ),
|
| + VFUNCTION(load_extension, 2, 0, 0, loadExt ),
|
| +#endif
|
| +#if SQLITE_USER_AUTHENTICATION
|
| + FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
|
| +#endif
|
| +#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
| + DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
|
| + DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
|
| +#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
| + FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
| + FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
| + FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
| +#ifdef SQLITE_DEBUG
|
| + FUNCTION2(affinity, 1, 0, 0, noopFunc, SQLITE_FUNC_AFFINITY),
|
| +#endif
|
| FUNCTION(ltrim, 1, 1, 0, trimFunc ),
|
| FUNCTION(ltrim, 2, 1, 0, trimFunc ),
|
| FUNCTION(rtrim, 1, 2, 0, trimFunc ),
|
| @@ -1732,8 +1795,6 @@ void sqlite3RegisterGlobalFunctions(void){
|
| FUNCTION2(typeof, 1, 0, 0, typeofFunc, SQLITE_FUNC_TYPEOF),
|
| FUNCTION2(length, 1, 0, 0, lengthFunc, SQLITE_FUNC_LENGTH),
|
| FUNCTION(instr, 2, 0, 0, instrFunc ),
|
| - FUNCTION(substr, 2, 0, 0, substrFunc ),
|
| - FUNCTION(substr, 3, 0, 0, substrFunc ),
|
| FUNCTION(printf, -1, 0, 0, printfFunc ),
|
| FUNCTION(unicode, 1, 0, 0, unicodeFunc ),
|
| FUNCTION(char, -1, 0, 0, charFunc ),
|
| @@ -1744,40 +1805,22 @@ void sqlite3RegisterGlobalFunctions(void){
|
| #endif
|
| FUNCTION(upper, 1, 0, 0, upperFunc ),
|
| FUNCTION(lower, 1, 0, 0, lowerFunc ),
|
| - FUNCTION(coalesce, 1, 0, 0, 0 ),
|
| - FUNCTION(coalesce, 0, 0, 0, 0 ),
|
| - FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
|
| FUNCTION(hex, 1, 0, 0, hexFunc ),
|
| FUNCTION2(ifnull, 2, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
|
| - FUNCTION2(unlikely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
| - FUNCTION2(likelihood, 2, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
| - FUNCTION2(likely, 1, 0, 0, noopFunc, SQLITE_FUNC_UNLIKELY),
|
| VFUNCTION(random, 0, 0, 0, randomFunc ),
|
| VFUNCTION(randomblob, 1, 0, 0, randomBlob ),
|
| FUNCTION(nullif, 2, 0, 1, nullifFunc ),
|
| DFUNCTION(sqlite_version, 0, 0, 0, versionFunc ),
|
| DFUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ),
|
| FUNCTION(sqlite_log, 2, 0, 0, errlogFunc ),
|
| -#if SQLITE_USER_AUTHENTICATION
|
| - FUNCTION(sqlite_crypt, 2, 0, 0, sqlite3CryptFunc ),
|
| -#endif
|
| -#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
|
| - DFUNCTION(sqlite_compileoption_used,1, 0, 0, compileoptionusedFunc ),
|
| - DFUNCTION(sqlite_compileoption_get, 1, 0, 0, compileoptiongetFunc ),
|
| -#endif /* SQLITE_OMIT_COMPILEOPTION_DIAGS */
|
| FUNCTION(quote, 1, 0, 0, quoteFunc ),
|
| VFUNCTION(last_insert_rowid, 0, 0, 0, last_insert_rowid),
|
| VFUNCTION(changes, 0, 0, 0, changes ),
|
| VFUNCTION(total_changes, 0, 0, 0, total_changes ),
|
| FUNCTION(replace, 3, 0, 0, replaceFunc ),
|
| FUNCTION(zeroblob, 1, 0, 0, zeroblobFunc ),
|
| - #ifdef SQLITE_SOUNDEX
|
| - FUNCTION(soundex, 1, 0, 0, soundexFunc ),
|
| - #endif
|
| - #ifndef SQLITE_OMIT_LOAD_EXTENSION
|
| - VFUNCTION(load_extension, 1, 0, 0, loadExt ),
|
| - VFUNCTION(load_extension, 2, 0, 0, loadExt ),
|
| - #endif
|
| + FUNCTION(substr, 2, 0, 0, substrFunc ),
|
| + FUNCTION(substr, 3, 0, 0, substrFunc ),
|
| AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ),
|
| AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ),
|
| AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ),
|
| @@ -1788,27 +1831,42 @@ void sqlite3RegisterGlobalFunctions(void){
|
| AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize),
|
|
|
| LIKEFUNC(glob, 2, &globInfo, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
|
| - #ifdef SQLITE_CASE_SENSITIVE_LIKE
|
| +#ifdef SQLITE_CASE_SENSITIVE_LIKE
|
| LIKEFUNC(like, 2, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
|
| LIKEFUNC(like, 3, &likeInfoAlt, SQLITE_FUNC_LIKE|SQLITE_FUNC_CASE),
|
| - #else
|
| +#else
|
| LIKEFUNC(like, 2, &likeInfoNorm, SQLITE_FUNC_LIKE),
|
| LIKEFUNC(like, 3, &likeInfoNorm, SQLITE_FUNC_LIKE),
|
| - #endif
|
| +#endif
|
| +#ifdef SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION
|
| + FUNCTION(unknown, -1, 0, 0, unknownFunc ),
|
| +#endif
|
| + FUNCTION(coalesce, 1, 0, 0, 0 ),
|
| + FUNCTION(coalesce, 0, 0, 0, 0 ),
|
| + FUNCTION2(coalesce, -1, 0, 0, noopFunc, SQLITE_FUNC_COALESCE),
|
| };
|
| -
|
| - int i;
|
| - FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
|
| - FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aBuiltinFunc);
|
| -
|
| - for(i=0; i<ArraySize(aBuiltinFunc); i++){
|
| - sqlite3FuncDefInsert(pHash, &aFunc[i]);
|
| - }
|
| - sqlite3RegisterDateTimeFunctions();
|
| #ifndef SQLITE_OMIT_ALTERTABLE
|
| sqlite3AlterFunctions();
|
| #endif
|
| #if defined(SQLITE_ENABLE_STAT3) || defined(SQLITE_ENABLE_STAT4)
|
| sqlite3AnalyzeFunctions();
|
| #endif
|
| + sqlite3RegisterDateTimeFunctions();
|
| + sqlite3InsertBuiltinFuncs(aBuiltinFunc, ArraySize(aBuiltinFunc));
|
| +
|
| +#if 0 /* Enable to print out how the built-in functions are hashed */
|
| + {
|
| + int i;
|
| + FuncDef *p;
|
| + for(i=0; i<SQLITE_FUNC_HASH_SZ; i++){
|
| + printf("FUNC-HASH %02d:", i);
|
| + for(p=sqlite3BuiltinFunctions.a[i]; p; p=p->u.pHash){
|
| + int n = sqlite3Strlen30(p->zName);
|
| + int h = p->zName[0] + n;
|
| + printf(" %s(%d)", p->zName, h);
|
| + }
|
| + printf("\n");
|
| + }
|
| + }
|
| +#endif
|
| }
|
|
|