Index: src/attach.c ================================================================== --- src/attach.c +++ src/attach.c @@ -332,11 +332,10 @@ ** DETACH pDbname */ void sqlite4Detach(Parse *pParse, Expr *pDbname){ static const FuncDef detach_func = { 1, /* nArg */ - SQLITE4_UTF8, /* iPrefEnc */ 0, /* flags */ 0, /* pUserData */ 0, /* pNext */ detachFunc, /* xFunc */ 0, /* xStep */ @@ -354,11 +353,10 @@ ** ATTACH p AS pDbname KEY pKey */ void sqlite4Attach(Parse *pParse, Expr *p, Expr *pDbname, Expr *pKey){ static const FuncDef attach_func = { 3, /* nArg */ - SQLITE4_UTF8, /* iPrefEnc */ 0, /* flags */ 0, /* pUserData */ 0, /* pNext */ attachFunc, /* xFunc */ 0, /* xStep */ Index: src/callback.c ================================================================== --- src/callback.c +++ src/callback.c @@ -221,43 +221,21 @@ ** is called to test how well the function passed as the first argument ** matches the request for a function with nArg arguments in a system ** that uses encoding enc. The value returned indicates how well the ** request is matched. A higher value indicates a better match. ** -** The returned value is always between 0 and 6, as follows: -** -** 0: Not a match, or if nArg<0 and the function is has no implementation. -** 1: A variable arguments function that prefers UTF-8 when a UTF-16 -** encoding is requested, or vice versa. -** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is -** requested, or vice versa. -** 3: A variable arguments function using the same text encoding. -** 4: A function with the exact number of arguments requested that -** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. -** 5: A function with the exact number of arguments requested that -** prefers UTF-16LE when UTF-16BE is requested, or vice versa. -** 6: An exact match. -** +** The returned value is as follows: +** +** 0: Not a match, or nArg<0 and the function has no implementation. +** 1: A variable arguments function. +** 2: An exact match. */ -static int matchQuality(FuncDef *p, int nArg, u8 enc){ - int match = 0; - if( p->nArg==-1 || p->nArg==nArg - || (nArg==-1 && (p->xFunc!=0 || p->xStep!=0)) - ){ - match = 1; - if( p->nArg==nArg || nArg==-1 ){ - match = 4; - } - if( enc==p->iPrefEnc ){ - match += 2; - } - else if( (enc==SQLITE4_UTF16LE && p->iPrefEnc==SQLITE4_UTF16BE) || - (enc==SQLITE4_UTF16BE && p->iPrefEnc==SQLITE4_UTF16LE) ){ - match += 1; - } - } - return match; +static int matchQuality(FuncDef *p, int nArg){ + if( nArg<0 && (p->xFunc || p->xStep) ) return 2; + if( p->nArg==nArg ) return 2; + if( p->nArg<0 ) return 1; + return 0; } /* ** Search a FuncDefTable for a function with the given name. Return ** a pointer to the matching FuncDef if found, or 0 if there is no match. @@ -320,12 +298,12 @@ ** Locate a user function given a name, a number of arguments and a flag ** indicating whether the function prefers UTF-16 over UTF-8. Return a ** pointer to the FuncDef structure that defines that function, or return ** NULL if the function does not exist. ** -** If the createFlag argument is true, then a new (blank) FuncDef -** structure is created and liked into the "db" structure if a +** If the createFlag argument is true, then a new (zeroed) FuncDef +** structure is created and linked into the "db" structure if a ** no matching function previously existed. When createFlag is true ** and the nArg parameter is -1, then only a function that accepts ** any number of arguments will be returned. ** ** If createFlag is false and nArg is -1, then the first valid @@ -339,25 +317,21 @@ FuncDef *sqlite4FindFunction( sqlite4 *db, /* An open database */ const char *zName, /* Name of the function. Not null-terminated */ int nName, /* Number of characters in the name */ int nArg, /* Number of arguments. -1 means any number */ - u8 enc, /* Preferred text encoding */ int createFlag /* Create new entry if true and does not otherwise exist */ ){ FuncDef *p; /* Iterator variable */ FuncDef *pBest = 0; /* Best match found so far */ int bestScore = 0; /* Score of best match */ - - assert( enc==SQLITE4_UTF8 || enc==SQLITE4_UTF16LE || enc==SQLITE4_UTF16BE ); - /* First search for a match amongst the application-defined functions. */ p = functionSearch(&db->aFunc, zName, nName); while( p ){ - int score = matchQuality(p, nArg, enc); + int score = matchQuality(p, nArg); if( score>bestScore ){ pBest = p; bestScore = score; } p = p->pSameName; @@ -378,11 +352,11 @@ if( !createFlag && (pBest==0 || (db->flags & SQLITE4_PreferBuiltin)!=0) ){ FuncDefTable *pFuncTab = &db->pEnv->aGlobalFuncs; bestScore = 0; p = functionSearch(pFuncTab, zName, nName); while( p ){ - int score = matchQuality(p, nArg, enc); + int score = matchQuality(p, nArg); if( score>bestScore ){ pBest = p; bestScore = score; } p = p->pSameName; @@ -391,15 +365,14 @@ /* If the createFlag parameter is true and the search did not reveal an ** exact match for the name, number of arguments and encoding, then add a ** new entry to the hash table and return it. */ - if( createFlag && (bestScore<6 || pBest->nArg!=nArg) && + if( createFlag && (bestScore<2 || pBest->nArg!=nArg) && (pBest = sqlite4DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ pBest->zName = (char *)&pBest[1]; pBest->nArg = (u16)nArg; - pBest->iPrefEnc = enc; memcpy(pBest->zName, zName, nName); pBest->zName[nName] = 0; sqlite4FuncDefInsert(&db->aFunc, pBest, 0); } Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -2489,11 +2489,10 @@ FuncDef *pDef; /* The function definition object */ int nId; /* Length of the function name in bytes */ const char *zId; /* The function name */ int constMask = 0; /* Mask of function arguments that are constant */ int i; /* Loop counter */ - u8 enc = ENC(db); /* The text encoding used by this database */ CollSeq *pColl = 0; /* A collating sequence */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); testcase( op==TK_CONST_FUNC ); testcase( op==TK_FUNCTION ); @@ -2504,11 +2503,11 @@ } nFarg = pFarg ? pFarg->nExpr : 0; assert( !ExprHasProperty(pExpr, EP_IntValue) ); zId = pExpr->u.zToken; nId = sqlite4Strlen30(zId); - pDef = sqlite4FindFunction(db, zId, nId, nFarg, enc, 0); + pDef = sqlite4FindFunction(db, zId, nId, nFarg, 0); if( pDef==0 ){ sqlite4ErrorMsg(pParse, "unknown function: %.*s()", nId, zId); break; } @@ -3845,21 +3844,20 @@ } } if( i>=pAggInfo->nFunc ){ /* pExpr is original. Make a new entry in pAggInfo->aFunc[] */ - u8 enc = ENC(pParse->db); i = addAggInfoFunc(pParse->db, pAggInfo); if( i>=0 ){ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); pItem = &pAggInfo->aFunc[i]; pItem->pExpr = pExpr; pItem->iMem = ++pParse->nMem; assert( !ExprHasProperty(pExpr, EP_IntValue) ); pItem->pFunc = sqlite4FindFunction(pParse->db, pExpr->u.zToken, sqlite4Strlen30(pExpr->u.zToken), - pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); + pExpr->x.pList ? pExpr->x.pList->nExpr : 0, 0); if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; }else{ pItem->iDistinct = -1; } Index: src/fts5.c ================================================================== --- src/fts5.c +++ src/fts5.c @@ -3409,11 +3409,11 @@ ** Register the default FTS5 tokenizer and functions with handle db. */ int sqlite4InitFts5(sqlite4 *db){ #ifdef SQLITE4_TEST int rc = sqlite4_create_function( - db, "fts5_parse_expr", 3, SQLITE4_UTF8, 0, fts5_parse_expr, 0, 0, 0 + db, "fts5_parse_expr", 3, 0, fts5_parse_expr, 0, 0, 0 ); if( rc!=SQLITE4_OK ) return rc; #endif return sqlite4InitFts5Func(db); } Index: src/func.c ================================================================== --- src/func.c +++ src/func.c @@ -1362,12 +1362,11 @@ /* ** Set the LIKEOPT flag on the 2-argument function with the given name. */ static void setLikeOptFlag(sqlite4 *db, const char *zName, u8 flagVal){ FuncDef *pDef; - pDef = sqlite4FindFunction(db, zName, sqlite4Strlen30(zName), - 2, SQLITE4_UTF8, 0); + pDef = sqlite4FindFunction(db, zName, sqlite4Strlen30(zName), 2, 0); if( ALWAYS(pDef) ){ pDef->flags = flagVal; } } @@ -1381,13 +1380,13 @@ if( caseSensitive ){ pInfo = (struct compareInfo*)&likeInfoAlt; }else{ pInfo = (struct compareInfo*)&likeInfoNorm; } - sqlite4CreateFunc(db, "like", 2, SQLITE4_UTF8, pInfo, likeFunc, 0, 0, 0); - sqlite4CreateFunc(db, "like", 3, SQLITE4_UTF8, pInfo, likeFunc, 0, 0, 0); - sqlite4CreateFunc(db, "glob", 2, SQLITE4_UTF8, + sqlite4CreateFunc(db, "like", 2, pInfo, likeFunc, 0, 0, 0); + sqlite4CreateFunc(db, "like", 3, pInfo, likeFunc, 0, 0, 0); + sqlite4CreateFunc(db, "glob", 2, (struct compareInfo*)&globInfo, likeFunc, 0, 0, 0); setLikeOptFlag(db, "glob", SQLITE4_FUNC_LIKE | SQLITE4_FUNC_CASE); setLikeOptFlag(db, "like", caseSensitive ? (SQLITE4_FUNC_LIKE | SQLITE4_FUNC_CASE) : SQLITE4_FUNC_LIKE); } @@ -1407,12 +1406,11 @@ ){ return 0; } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); pDef = sqlite4FindFunction(db, pExpr->u.zToken, - sqlite4Strlen30(pExpr->u.zToken), - 2, SQLITE4_UTF8, 0); + sqlite4Strlen30(pExpr->u.zToken), 2, 0); if( NEVER(pDef==0) || (pDef->flags & SQLITE4_FUNC_LIKE)==0 ){ return 0; } /* The memcpy() statement assumes that the wildcard characters are @@ -1465,14 +1463,14 @@ FUNCTION(upper, 1, 0, 0, upperFunc ), FUNCTION(lower, 1, 0, 0, lowerFunc ), FUNCTION(coalesce, 1, 0, 0, 0 ), FUNCTION(coalesce, 0, 0, 0, 0 ), /* FUNCTION(coalesce, -1, 0, 0, ifnullFunc ), */ - {-1,SQLITE4_UTF8,SQLITE4_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0,0}, + {-1,SQLITE4_FUNC_COALESCE,0,0,ifnullFunc,0,0,"coalesce",0,0}, FUNCTION(hex, 1, 0, 0, hexFunc ), /* FUNCTION(ifnull, 2, 0, 0, ifnullFunc ), */ - {2,SQLITE4_UTF8,SQLITE4_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0,0}, + {2,SQLITE4_FUNC_COALESCE,0,0,ifnullFunc,0,0,"ifnull",0,0}, FUNCTION(random, 0, 0, 0, randomFunc ), FUNCTION(randomblob, 1, 0, 0, randomBlob ), FUNCTION(nullif, 2, 0, 1, nullifFunc ), FUNCTION(sqlite_version, 0, 0, 0, versionFunc ), FUNCTION(sqlite_source_id, 0, 0, 0, sourceidFunc ), @@ -1494,11 +1492,11 @@ #endif AGGREGATE(sum, 1, 0, 0, sumStep, sumFinalize ), AGGREGATE(total, 1, 0, 0, sumStep, totalFinalize ), AGGREGATE(avg, 1, 0, 0, sumStep, avgFinalize ), /* AGGREGATE(count, 0, 0, 0, countStep, countFinalize ), */ - {0,SQLITE4_UTF8,SQLITE4_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0}, + {0,SQLITE4_FUNC_COUNT,0,0,0,countStep,countFinalize,"count",0,0}, AGGREGATE(count, 1, 0, 0, countStep, countFinalize ), AGGREGATE(group_concat, 1, 0, 0, groupConcatStep, groupConcatFinalize), AGGREGATE(group_concat, 2, 0, 0, groupConcatStep, groupConcatFinalize), LIKEFUNC(glob, 2, &globInfo, SQLITE4_FUNC_LIKE|SQLITE4_FUNC_CASE), Index: src/main.c ================================================================== --- src/main.c +++ src/main.c @@ -540,11 +540,10 @@ */ int sqlite4CreateFunc( sqlite4 *db, const char *zFunctionName, int nArg, - int enc, void *pUserData, void (*xFunc)(sqlite4_context*,int,sqlite4_value **), void (*xStep)(sqlite4_context*,int,sqlite4_value **), void (*xFinal)(sqlite4_context*), FuncDestructor *pDestructor @@ -560,44 +559,17 @@ (nArg<-1 || nArg>SQLITE4_MAX_FUNCTION_ARG) || (255<(nName = sqlite4Strlen30( zFunctionName))) ){ return SQLITE4_MISUSE_BKPT; } -#ifndef SQLITE4_OMIT_UTF16 - /* If SQLITE4_UTF16 is specified as the encoding type, transform this - ** to one of SQLITE4_UTF16LE or SQLITE4_UTF16BE using the - ** SQLITE4_UTF16NATIVE macro. SQLITE4_UTF16 is not used internally. - ** - ** If SQLITE4_ANY is specified, add three versions of the function - ** to the hash table. - */ - if( enc==SQLITE4_UTF16 ){ - enc = SQLITE4_UTF16NATIVE; - }else if( enc==SQLITE4_ANY ){ - int rc; - rc = sqlite4CreateFunc(db, zFunctionName, nArg, SQLITE4_UTF8, - pUserData, xFunc, xStep, xFinal, pDestructor); - if( rc==SQLITE4_OK ){ - rc = sqlite4CreateFunc(db, zFunctionName, nArg, SQLITE4_UTF16LE, - pUserData, xFunc, xStep, xFinal, pDestructor); - } - if( rc!=SQLITE4_OK ){ - return rc; - } - enc = SQLITE4_UTF16BE; - } -#else - enc = SQLITE4_UTF8; -#endif - /* Check if an existing function is being overridden or deleted. If so, ** and there are active VMs, then return SQLITE4_BUSY. If a function ** is being overridden/deleted but there are no active VMs, allow the ** operation to continue but invalidate all precompiled statements. */ - p = sqlite4FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 0); - if( p && p->iPrefEnc==enc && p->nArg==nArg ){ + p = sqlite4FindFunction(db, zFunctionName, nName, nArg, 0); + if( p && p->nArg==nArg ){ if( db->activeVdbeCnt ){ sqlite4Error(db, SQLITE4_BUSY, "unable to delete/modify user-function due to active statements"); assert( !db->mallocFailed ); return SQLITE4_BUSY; @@ -604,11 +576,11 @@ }else{ sqlite4ExpirePreparedStatements(db); } } - p = sqlite4FindFunction(db, zFunctionName, nName, nArg, (u8)enc, 1); + p = sqlite4FindFunction(db, zFunctionName, nName, nArg, 1); assert(p || db->mallocFailed); if( !p ){ return SQLITE4_NOMEM; } @@ -635,11 +607,10 @@ */ static int createFunctionDestructor( sqlite4 *db, const char *zFunc, int nArg, - int enc, void *p, void (*xFunc)(sqlite4_context*,int,sqlite4_value **), void (*xStep)(sqlite4_context*,int,sqlite4_value **), void (*xFinal)(sqlite4_context*), void (*xDestroy)(void *) @@ -654,11 +625,11 @@ return SQLITE4_NOMEM; } pArg->xDestroy = xDestroy; pArg->pUserData = p; } - rc = sqlite4CreateFunc(db, zFunc, nArg, enc, p, xFunc, xStep, xFinal, pArg); + rc = sqlite4CreateFunc(db, zFunc, nArg, p, xFunc, xStep, xFinal, pArg); if( pArg && pArg->nRef==0 ){ assert( rc!=SQLITE4_OK ); xDestroy(p); sqlite4DbFree(db, pArg); } @@ -671,21 +642,20 @@ */ int sqlite4_create_function( sqlite4 *db, const char *zFunc, int nArg, - int enc, void *p, void (*xFunc)(sqlite4_context*,int,sqlite4_value **), void (*xStep)(sqlite4_context*,int,sqlite4_value **), void (*xFinal)(sqlite4_context*), void (*xDestroy)(void *) ){ int rc; sqlite4_mutex_enter(db->mutex); rc = createFunctionDestructor( - db, zFunc, nArg, enc, p, xFunc, xStep, xFinal, xDestroy + db, zFunc, nArg, p, xFunc, xStep, xFinal, xDestroy ); rc = sqlite4ApiExit(db, rc); sqlite4_mutex_leave(db->mutex); return rc; } @@ -702,13 +672,13 @@ int rc; int n; n = nArg + (nArg>=0); sqlite4_mutex_enter(db->mutex); - rc = sqlite4_create_function(db, zFunc, n, enc, p, xFunc, 0,0, xDestroy); + rc = sqlite4_create_function(db, zFunc, n, p, xFunc, 0, 0, xDestroy); if( rc==SQLITE4_OK ){ - FuncDef *p = sqlite4FindFunction(db, zFunc, -1, n, enc, 0); + FuncDef *p = sqlite4FindFunction(db, zFunc, -1, n, 0); p->bMatchinfo = 1; } rc = sqlite4ApiExit(db, rc); sqlite4_mutex_leave(db->mutex); return rc; @@ -732,12 +702,12 @@ int nArg ){ int nName = sqlite4Strlen30(zName); int rc = SQLITE4_OK; sqlite4_mutex_enter(db->mutex); - if( sqlite4FindFunction(db, zName, nName, nArg, SQLITE4_UTF8, 0)==0 ){ - rc = sqlite4CreateFunc(db, zName, nArg, SQLITE4_UTF8, + if( sqlite4FindFunction(db, zName, nName, nArg, 0)==0 ){ + rc = sqlite4CreateFunc(db, zName, nArg, 0, sqlite4InvalidFunction, 0, 0, 0); } rc = sqlite4ApiExit(db, rc); sqlite4_mutex_leave(db->mutex); return rc; Index: src/pragma.c ================================================================== --- src/pragma.c +++ src/pragma.c @@ -748,11 +748,11 @@ ); sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, zErr, 0); sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr); sqlite4VdbeAddOp3(v, OP_Function, 0, regKey, regTmp); sqlite4VdbeChangeP4(v, -1, - (char *)sqlite4FindFunction(db, "hex", 3, 1, SQLITE4_UTF8, 0), + (char *)sqlite4FindFunction(db, "hex", 3, 1, 0), P4_FUNCDEF ); sqlite4VdbeChangeP5(v, 1); sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr); sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, "\n", 0); @@ -1380,11 +1380,11 @@ ); sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, zErr, 0); sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr); sqlite4VdbeAddOp3(v, OP_Function, 0, regKey, regTmp); sqlite4VdbeChangeP4(v, -1, - (char *)sqlite4FindFunction(db, "hex", 3, 1, SQLITE4_UTF8, 0), + (char *)sqlite4FindFunction(db, "hex", 3, 1, 0), P4_FUNCDEF ); sqlite4VdbeChangeP5(v, 1); sqlite4VdbeAddOp3(v, OP_Concat, regTmp, regErrstr, regErrstr); sqlite4VdbeAddOp4(v, OP_String8, 0, regTmp, 0, "\n", 0); Index: src/resolve.c ================================================================== --- src/resolve.c +++ src/resolve.c @@ -584,13 +584,13 @@ testcase( pExpr->op==TK_CONST_FUNC ); assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); zId = pExpr->u.zToken; nId = sqlite4Strlen30(zId); - pDef = sqlite4FindFunction(pParse->db, zId, nId, n, enc, 0); + pDef = sqlite4FindFunction(pParse->db, zId, nId, n, 0); if( pDef==0 ){ - pDef = sqlite4FindFunction(pParse->db, zId, nId, -1, enc, 0); + pDef = sqlite4FindFunction(pParse->db, zId, nId, -1, 0); if( pDef==0 ){ no_such_func = 1; }else{ wrong_num_args = 1; } Index: src/shell.c ================================================================== --- src/shell.c +++ src/shell.c @@ -1334,11 +1334,11 @@ static void open_db(struct callback_data *p){ if( p->db==0 ){ sqlite4_open(0, p->zDbFilename, &p->db, 0); db = p->db; if( db && sqlite4_errcode(db)==SQLITE4_OK ){ - sqlite4_create_function(db, "shellstatic", 0, SQLITE4_UTF8, 0, + sqlite4_create_function(db, "shellstatic", 0, 0, shellstaticFunc, 0, 0, 0); } if( db==0 || SQLITE4_OK!=sqlite4_errcode(db) ){ fprintf(stderr,"Error: unable to open database \"%s\": %s\n", p->zDbFilename, sqlite4_errmsg(db)); Index: src/sqlite.h.in ================================================================== --- src/sqlite.h.in +++ src/sqlite.h.in @@ -2285,55 +2285,37 @@ ** function or aggregate may take any number of arguments between 0 and ** the limit set by [sqlite4_limit]([SQLITE4_LIMIT_FUNCTION_ARG]). If ** the third parameter is less than -1 or greater than 127 then the ** behavior is undefined. ** -** ^The fourth parameter, eTextRep, specifies the -** [SQLITE4_UTF8 | text encoding] this SQL function prefers for -** its parameters. Every SQL function implementation must be able to work -** with UTF-8, UTF-16le, or UTF-16be. But some implementations may be -** more efficient with one encoding than another. ^An application may -** invoke sqlite4_create_function() multiple times with the same function -** but with different values of eTextRep. ^When multiple implementations -** of the same function are available, SQLite will pick the one that -** involves the least amount of data conversion. If there is only a single -** implementation which does not care what text encoding is used, then the -** fourth argument should be [SQLITE4_ANY]. -** -** ^(The fifth parameter is an arbitrary pointer. The implementation of the +** ^(The fourth parameter is a context pointer. The implementation of the ** function can gain access to this pointer using [sqlite4_context_appdata()].)^ ** -** ^The sixth, seventh and eighth parameters, xFunc, xStep and xFinal, are +** ^The fifth, sixth and seventh parameters, xFunc, xStep and xFinal, are ** pointers to C-language functions that implement the SQL function or ** aggregate. ^A scalar SQL function requires an implementation of the xFunc ** callback only; NULL pointers must be passed as the xStep and xFinal ** parameters. ^An aggregate SQL function requires an implementation of xStep ** and xFinal and NULL pointer must be passed for xFunc. ^To delete an existing ** SQL function or aggregate, pass NULL pointers for all three function ** callbacks. ** -** ^(If the ninth parameter is not NULL, then it is destructor for the +** ^(If the eighth parameter is not NULL, then it is destructor for the ** application data pointer. The destructor is invoked when the function ** is deleted, either by being overloaded or when the database connection ** closes.)^ ^The destructor is also invoked if the call to ** sqlite4_create_function() fails. ^When the destructor callback ** is invoked, it is passed a single argument which is a copy of the ** application data pointer which was the fifth parameter to ** sqlite4_create_function(). ** ** ^It is permitted to register multiple implementations of the same -** functions with the same name but with either differing numbers of -** arguments or differing preferred text encodings. ^SQLite will use -** the implementation that most closely matches the way in which the +** functions with the same name but differing numbers of arguments. ^SQLite +** will use the implementation that most closely matches the way in which the ** SQL function is used. ^A function implementation with a non-negative ** nArg parameter is a better match than a function implementation with -** a negative nArg. ^A function where the preferred text encoding -** matches the database encoding is a better -** match than a function where the encoding is different. -** ^A function where the encoding difference is between UTF16le and UTF16be -** is a closer match than a function where the encoding difference is -** between UTF8 and UTF16. +** a negative nArg. ** ** ^Built-in functions may be overloaded by new application-defined functions. ** ** ^An application-defined function is permitted to call other ** SQLite interfaces. However, such calls must not @@ -2342,11 +2324,10 @@ */ int sqlite4_create_function( sqlite4 *db, const char *zFunctionName, int nArg, - int eTextRep, void *pApp, void (*xFunc)(sqlite4_context*,int,sqlite4_value**), void (*xStep)(sqlite4_context*,int,sqlite4_value**), void (*xFinal)(sqlite4_context*), void(*xDestroy)(void*) Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -638,11 +638,10 @@ ** hash table. When multiple functions have the same name, the hash table ** points to a linked list of these structures. */ struct FuncDef { i16 nArg; /* Number of arguments. -1 means unlimited */ - u8 iPrefEnc; /* Preferred text encoding (SQLITE4_UTF8, 16LE, 16BE) */ u8 flags; /* Some combination of SQLITE4_FUNC_* */ void *pUserData; /* User data parameter */ FuncDef *pSameName; /* Next with a different name but the same hash */ void (*xFunc)(sqlite4_context*,int,sqlite4_value**); /* Regular function */ void (*xStep)(sqlite4_context*,int,sqlite4_value**); /* Aggregate step */ @@ -990,19 +989,19 @@ ** available as the function user-data (sqlite4_context_appdata()). The ** FuncDef.flags variable is set to the value passed as the flags ** parameter. */ #define FUNCTION(zName, nArg, iArg, bNC, xFunc) \ - {nArg, SQLITE4_UTF8, bNC*SQLITE4_FUNC_NEEDCOLL, \ + {nArg, bNC*SQLITE4_FUNC_NEEDCOLL, \ SQLITE4_INT_TO_PTR(iArg), 0, xFunc, 0, 0, #zName, 0, 0} #define STR_FUNCTION(zName, nArg, pArg, bNC, xFunc) \ - {nArg, SQLITE4_UTF8, bNC*SQLITE4_FUNC_NEEDCOLL, \ + {nArg, bNC*SQLITE4_FUNC_NEEDCOLL, \ pArg, 0, xFunc, 0, 0, #zName, 0, 0} #define LIKEFUNC(zName, nArg, arg, flags) \ - {nArg, SQLITE4_UTF8, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} + {nArg, flags, (void *)arg, 0, likeFunc, 0, 0, #zName, 0, 0} #define AGGREGATE(zName, nArg, arg, nc, xStep, xFinal) \ - {nArg, SQLITE4_UTF8, nc*SQLITE4_FUNC_NEEDCOLL, \ + {nArg, nc*SQLITE4_FUNC_NEEDCOLL, \ SQLITE4_INT_TO_PTR(arg), 0, 0, xStep,xFinal,#zName,0,0} /* ** All current savepoints are stored in a linked list starting at ** sqlite4.pSavepoint. The first element in the list is the most recently @@ -2816,11 +2815,11 @@ ExprList *sqlite4ExprListDup(sqlite4*,ExprList*,int); SrcList *sqlite4SrcListDup(sqlite4*,SrcList*,int); IdList *sqlite4IdListDup(sqlite4*,IdList*); Select *sqlite4SelectDup(sqlite4*,Select*,int); void sqlite4FuncDefInsert(FuncDefTable*, FuncDef*, int); -FuncDef *sqlite4FindFunction(sqlite4*,const char*,int,int,u8,int); +FuncDef *sqlite4FindFunction(sqlite4*,const char*,int,int,int); void sqlite4RegisterBuiltinFunctions(sqlite4*); void sqlite4RegisterDateTimeFunctions(sqlite4_env*); void sqlite4RegisterGlobalFunctions(sqlite4_env*); int sqlite4SafetyCheckOk(sqlite4*); int sqlite4SafetyCheckSickOrOk(sqlite4*); @@ -3017,11 +3016,11 @@ int sqlite4IsLikeFunction(sqlite4*,Expr*,int*,char*); void sqlite4SchemaClear(sqlite4_env*,Schema*); Schema *sqlite4SchemaGet(sqlite4*); int sqlite4SchemaToIndex(sqlite4 *db, Schema *); KeyInfo *sqlite4IndexKeyinfo(Parse *, Index *); -int sqlite4CreateFunc(sqlite4 *, const char *, int, int, void *, +int sqlite4CreateFunc(sqlite4 *, const char *, int, void *, void (*)(sqlite4_context*,int,sqlite4_value **), void (*)(sqlite4_context*,int,sqlite4_value **), void (*)(sqlite4_context*), FuncDestructor *pDestructor ); int sqlite4ApiExit(sqlite4 *db, int); Index: src/tclsqlite.c ================================================================== --- src/tclsqlite.c +++ src/tclsqlite.c @@ -1814,11 +1814,11 @@ Tcl_DecrRefCount(pFunc->pScript); } pFunc->pScript = pScript; Tcl_IncrRefCount(pScript); pFunc->useEvalObjv = safeToUseEvalObjv(interp, pScript); - rc = sqlite4_create_function(pDb->db, zName, nArg, SQLITE4_UTF8, + rc = sqlite4_create_function(pDb->db, zName, nArg, pFunc, tclSqlFunc, 0, 0, 0); if( rc!=SQLITE4_OK ){ rc = TCL_ERROR; Tcl_SetResult(interp, (char *)sqlite4_errmsg(pDb->db), TCL_VOLATILE); } @@ -2714,11 +2714,11 @@ MD5Final(digest,p); MD5DigestToBase16(digest, zBuf); sqlite4_result_text(context, zBuf, -1, SQLITE4_TRANSIENT, 0); } int Md5_Register(sqlite4 *db){ - int rc = sqlite4_create_function(db, "md5sum", -1, SQLITE4_UTF8, 0, 0, + int rc = sqlite4_create_function(db, "md5sum", -1, 0, 0, md5step, md5finalize, 0); sqlite4_overload_function(db, "md5sum", -1); /* To exercise this API */ return rc; } #endif /* defined(SQLITE4_TEST) */ Index: test/func3.test ================================================================== --- test/func3.test +++ test/func3.test @@ -15,31 +15,10 @@ # set testdir [file dirname $argv0] source $testdir/tester.tcl -ifcapable utf16 { - do_test func3-1.1 { - set destroyed 0 - proc destroy {} { set ::destroyed 1 } - sqlite4_create_function_v2 db f2 -1 any -func f2 -destroy destroy - set destroyed - } 0 - do_test func3-1.2 { - sqlite4_create_function_v2 db f2 -1 utf8 -func f2 - set destroyed - } 0 - do_test func3-1.3 { - sqlite4_create_function_v2 db f2 -1 utf16le -func f2 - set destroyed - } 0 - do_test func3-1.4 { - sqlite4_create_function_v2 db f2 -1 utf16be -func f2 - set destroyed - } 1 -} - do_test func3-2.1 { set destroyed 0 proc destroy {} { set ::destroyed 1 } sqlite4_create_function_v2 db f3 -1 utf8 -func f3 -destroy destroy set destroyed Index: test/permutations.test ================================================================== --- test/permutations.test +++ test/permutations.test @@ -189,11 +189,11 @@ savepoint.test savepoint5.test select1.test select2.test select3.test select4.test select5.test select6.test select7.test select8.test select9.test selectA.test - selectB.test selectC.test + selectB.test selectC.test selectF.test sort.test storage1.test subquery.test subquery2.test Index: test/selectF.test ================================================================== --- test/selectF.test +++ test/selectF.test @@ -94,12 +94,14 @@ 6 1 "SELECT a+b FROM t1 GROUP BY (a+b) ORDER BY 1" {3 6 9 12 15 18} 7 0 "SELECT a*b FROM t1 WHERE (c%2)" {18 2 50} 8 0 "SELECT count(*) FROM t1, t1 AS t2 WHERE t1.a=t2.a" {6} 9 0 "SELECT * FROM t1 WHERE a=1 AND b=2" {{1 2 3}} 10 0 "SELECT * FROM t1 WHERE a>3 AND b<12" {{4 8 12} {5 10 15}} + +11 1 "SELECT a FROM t1 ORDER BY a" {1 2 3 4 5 6} +12 1 "SELECT a FROM t1 ORDER BY +a" {1 2 3 4 5 6} +13 1 "SELECT a FROM t1 ORDER BY b DESC" {6 5 4 3 2 1} + } finish_test - - - Index: test/test_func.c ================================================================== --- test/test_func.c +++ test/test_func.c @@ -450,11 +450,11 @@ }; int i; for(i=0; ipFunc ) Tcl_IncrRefCount(p->pFunc); if( p->pStep ) Tcl_IncrRefCount(p->pStep); if( p->pFinal ) Tcl_IncrRefCount(p->pFinal); if( p->pDestroy ) Tcl_IncrRefCount(p->pDestroy); - rc = sqlite4_create_function(db, zFunc, nArg, enc, (void *)p, + rc = sqlite4_create_function(db, zFunc, nArg, (void *)p, (p->pFunc ? cf2Func : 0), (p->pStep ? cf2Step : 0), (p->pFinal ? cf2Final : 0), cf2Destroy ); @@ -1632,12 +1629,11 @@ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB FUNCTION-NAME", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - rc = sqlite4_create_function(db, argv[2], -1, SQLITE4_UTF8, 0, - testFunc, 0, 0, 0); + rc = sqlite4_create_function(db, argv[2], -1, 0, testFunc, 0, 0, 0); if( rc!=0 ){ Tcl_AppendResult(interp, sqlite4ErrStr(rc), 0); return TCL_ERROR; } if( sqlite4TestErrCode(interp, db, rc) ) return TCL_ERROR; @@ -2292,21 +2288,21 @@ if( objc!=5 ) goto bad_args; if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR; if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[2], &val) ) return TCL_ERROR; if( val ){ - sqlite4_create_function(db, "test_function", 1, SQLITE4_UTF8, + sqlite4_create_function(db, "test_function", 1, interp, test_function_utf8, 0, 0, 0); } if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[3], &val) ) return TCL_ERROR; if( val ){ - sqlite4_create_function(db, "test_function", 1, SQLITE4_UTF16LE, + sqlite4_create_function(db, "test_function", 1, interp, test_function_utf16le, 0, 0, 0); } if( TCL_OK!=Tcl_GetBooleanFromObj(interp, objv[4], &val) ) return TCL_ERROR; if( val ){ - sqlite4_create_function(db, "test_function", 1, SQLITE4_UTF16BE, + sqlite4_create_function(db, "test_function", 1, interp, test_function_utf16be, 0, 0, 0); } return TCL_OK; bad_args: @@ -3456,11 +3452,11 @@ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB function-name", 0); return TCL_ERROR; } if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR; - rc = sqlite4_create_function(db, argv[2], -1, SQLITE4_UTF8, 0, 0, 0, 0, 0); + rc = sqlite4_create_function(db, argv[2], -1, 0, 0, 0, 0, 0); Tcl_SetResult(interp, (char *)t1ErrorName(rc), TCL_STATIC); return TCL_OK; } /*