1 /* 2 ** 2005 May 23 3 ** 4 ** The author disclaims copyright to this source code. In place of 5 ** a legal notice, here is a blessing: 6 ** 7 ** May you do good and not evil. 8 ** May you find forgiveness for yourself and forgive others. 9 ** May you share freely, never taking more than you give. 10 ** 11 ************************************************************************* 12 ** 13 ** This file contains functions used to access the internal hash tables 14 ** of user defined functions and collation sequences. 15 ** 16 ** $Id: callback.c,v 1.2 2005/05/25 10:45:10 danielk1977 Exp $ 17 */ 18 19 #include "sqliteInt.h" 20 21 /* 22 ** Invoke the 'collation needed' callback to request a collation sequence 23 ** in the database text encoding of name zName, length nName. 24 ** If the collation sequence 25 */ 26 static void callCollNeeded(sqlite3 *db, const char *zName, int nName){ 27 assert( !db->xCollNeeded || !db->xCollNeeded16 ); 28 if( nName<0 ) nName = strlen(zName); 29 if( db->xCollNeeded ){ 30 char *zExternal = sqliteStrNDup(zName, nName); 31 if( !zExternal ) return; 32 db->xCollNeeded(db->pCollNeededArg, db, (int)db->enc, zExternal); 33 sqliteFree(zExternal); 34 } 35 #ifndef SQLITE_OMIT_UTF16 36 if( db->xCollNeeded16 ){ 37 char const *zExternal; 38 sqlite3_value *pTmp = sqlite3GetTransientValue(db); 39 sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); 40 zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); 41 if( !zExternal ) return; 42 db->xCollNeeded16(db->pCollNeededArg, db, (int)db->enc, zExternal); 43 } 44 #endif 45 } 46 47 /* 48 ** This routine is called if the collation factory fails to deliver a 49 ** collation function in the best encoding but there may be other versions 50 ** of this collation function (for other text encodings) available. Use one 51 ** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if 52 ** possible. 53 */ 54 static int synthCollSeq(sqlite3 *db, CollSeq *pColl){ 55 CollSeq *pColl2; 56 char *z = pColl->zName; 57 int n = strlen(z); 58 int i; 59 static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; 60 for(i=0; i<3; i++){ 61 pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0); 62 if( pColl2->xCmp!=0 ){ 63 memcpy(pColl, pColl2, sizeof(CollSeq)); 64 return SQLITE_OK; 65 } 66 } 67 return SQLITE_ERROR; 68 } 69 70 /* 71 ** This function is responsible for invoking the collation factory callback 72 ** or substituting a collation sequence of a different encoding when the 73 ** requested collation sequence is not available in the database native 74 ** encoding. 75 ** 76 ** If it is not NULL, then pColl must point to the database native encoding 77 ** collation sequence with name zName, length nName. 78 ** 79 ** The return value is either the collation sequence to be used in database 80 ** db for collation type name zName, length nName, or NULL, if no collation 81 ** sequence can be found. 82 */ 83 CollSeq *sqlite3GetCollSeq( 84 sqlite3* db, 85 CollSeq *pColl, 86 const char *zName, 87 int nName 88 ){ 89 CollSeq *p; 90 91 p = pColl; 92 if( !p ){ 93 p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0); 94 } 95 if( !p || !p->xCmp ){ 96 /* No collation sequence of this type for this encoding is registered. 97 ** Call the collation factory to see if it can supply us with one. 98 */ 99 callCollNeeded(db, zName, nName); 100 p = sqlite3FindCollSeq(db, db->enc, zName, nName, 0); 101 } 102 if( p && !p->xCmp && synthCollSeq(db, p) ){ 103 p = 0; 104 } 105 assert( !p || p->xCmp ); 106 return p; 107 } 108 109 /* 110 ** This routine is called on a collation sequence before it is used to 111 ** check that it is defined. An undefined collation sequence exists when 112 ** a database is loaded that contains references to collation sequences 113 ** that have not been defined by sqlite3_create_collation() etc. 114 ** 115 ** If required, this routine calls the 'collation needed' callback to 116 ** request a definition of the collating sequence. If this doesn't work, 117 ** an equivalent collating sequence that uses a text encoding different 118 ** from the main database is substituted, if one is available. 119 */ 120 int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ 121 if( pColl ){ 122 const char *zName = pColl->zName; 123 CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1); 124 if( !p ){ 125 if( pParse->nErr==0 ){ 126 sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); 127 } 128 pParse->nErr++; 129 return SQLITE_ERROR; 130 } 131 } 132 return SQLITE_OK; 133 } 134 135 136 137 /* 138 ** Locate and return an entry from the db.aCollSeq hash table. If the entry 139 ** specified by zName and nName is not found and parameter 'create' is 140 ** true, then create a new entry. Otherwise return NULL. 141 ** 142 ** Each pointer stored in the sqlite3.aCollSeq hash table contains an 143 ** array of three CollSeq structures. The first is the collation sequence 144 ** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. 145 ** 146 ** Stored immediately after the three collation sequences is a copy of 147 ** the collation sequence name. A pointer to this string is stored in 148 ** each collation sequence structure. 149 */ 150 static CollSeq * findCollSeqEntry( 151 sqlite3 *db, 152 const char *zName, 153 int nName, 154 int create 155 ){ 156 CollSeq *pColl; 157 if( nName<0 ) nName = strlen(zName); 158 pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); 159 160 if( 0==pColl && create ){ 161 pColl = sqliteMalloc( 3*sizeof(*pColl) + nName + 1 ); 162 if( pColl ){ 163 CollSeq *pDel = 0; 164 pColl[0].zName = (char*)&pColl[3]; 165 pColl[0].enc = SQLITE_UTF8; 166 pColl[1].zName = (char*)&pColl[3]; 167 pColl[1].enc = SQLITE_UTF16LE; 168 pColl[2].zName = (char*)&pColl[3]; 169 pColl[2].enc = SQLITE_UTF16BE; 170 memcpy(pColl[0].zName, zName, nName); 171 pColl[0].zName[nName] = 0; 172 pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); 173 174 /* If a malloc() failure occured in sqlite3HashInsert(), it will 175 ** return the pColl pointer to be deleted (because it wasn't added 176 ** to the hash table). 177 */ 178 assert( !pDel || (sqlite3_malloc_failed && pDel==pColl) ); 179 sqliteFree(pDel); 180 } 181 } 182 return pColl; 183 } 184 185 /* 186 ** Parameter zName points to a UTF-8 encoded string nName bytes long. 187 ** Return the CollSeq* pointer for the collation sequence named zName 188 ** for the encoding 'enc' from the database 'db'. 189 ** 190 ** If the entry specified is not found and 'create' is true, then create a 191 ** new entry. Otherwise return NULL. 192 */ 193 CollSeq *sqlite3FindCollSeq( 194 sqlite3 *db, 195 u8 enc, 196 const char *zName, 197 int nName, 198 int create 199 ){ 200 CollSeq *pColl = findCollSeqEntry(db, zName, nName, create); 201 assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); 202 assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); 203 if( pColl ) pColl += enc-1; 204 return pColl; 205 } 206 207 /* 208 ** Locate a user function given a name, a number of arguments and a flag 209 ** indicating whether the function prefers UTF-16 over UTF-8. Return a 210 ** pointer to the FuncDef structure that defines that function, or return 211 ** NULL if the function does not exist. 212 ** 213 ** If the createFlag argument is true, then a new (blank) FuncDef 214 ** structure is created and liked into the "db" structure if a 215 ** no matching function previously existed. When createFlag is true 216 ** and the nArg parameter is -1, then only a function that accepts 217 ** any number of arguments will be returned. 218 ** 219 ** If createFlag is false and nArg is -1, then the first valid 220 ** function found is returned. A function is valid if either xFunc 221 ** or xStep is non-zero. 222 ** 223 ** If createFlag is false, then a function with the required name and 224 ** number of arguments may be returned even if the eTextRep flag does not 225 ** match that requested. 226 */ 227 FuncDef *sqlite3FindFunction( 228 sqlite3 *db, /* An open database */ 229 const char *zName, /* Name of the function. Not null-terminated */ 230 int nName, /* Number of characters in the name */ 231 int nArg, /* Number of arguments. -1 means any number */ 232 u8 enc, /* Preferred text encoding */ 233 int createFlag /* Create new entry if true and does not otherwise exist */ 234 ){ 235 FuncDef *p; /* Iterator variable */ 236 FuncDef *pFirst; /* First function with this name */ 237 FuncDef *pBest = 0; /* Best match found so far */ 238 int bestmatch = 0; 239 240 241 assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); 242 if( nArg<-1 ) nArg = -1; 243 244 pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName); 245 for(p=pFirst; p; p=p->pNext){ 246 /* During the search for the best function definition, bestmatch is set 247 ** as follows to indicate the quality of the match with the definition 248 ** pointed to by pBest: 249 ** 250 ** 0: pBest is NULL. No match has been found. 251 ** 1: A variable arguments function that prefers UTF-8 when a UTF-16 252 ** encoding is requested, or vice versa. 253 ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is 254 ** requested, or vice versa. 255 ** 3: A variable arguments function using the same text encoding. 256 ** 4: A function with the exact number of arguments requested that 257 ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. 258 ** 5: A function with the exact number of arguments requested that 259 ** prefers UTF-16LE when UTF-16BE is requested, or vice versa. 260 ** 6: An exact match. 261 ** 262 ** A larger value of 'matchqual' indicates a more desirable match. 263 */ 264 if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){ 265 int match = 1; /* Quality of this match */ 266 if( p->nArg==nArg || nArg==-1 ){ 267 match = 4; 268 } 269 if( enc==p->iPrefEnc ){ 270 match += 2; 271 } 272 else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || 273 (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ 274 match += 1; 275 } 276 277 if( match>bestmatch ){ 278 pBest = p; 279 bestmatch = match; 280 } 281 } 282 } 283 284 /* If the createFlag parameter is true, and the seach did not reveal an 285 ** exact match for the name, number of arguments and encoding, then add a 286 ** new entry to the hash table and return it. 287 */ 288 if( createFlag && bestmatch<6 && 289 (pBest = sqliteMalloc(sizeof(*pBest)+nName+1)) ){ 290 pBest->nArg = nArg; 291 pBest->pNext = pFirst; 292 pBest->zName = (char*)&pBest[1]; 293 pBest->iPrefEnc = enc; 294 memcpy(pBest->zName, zName, nName); 295 pBest->zName[nName] = 0; 296 if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){ 297 sqliteFree(pBest); 298 return 0; 299 } 300 } 301 302 if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ 303 return pBest; 304 } 305 return 0; 306 } 307