diff options
Diffstat (limited to 'libraries/sqlite/win32/callback.c')
-rwxr-xr-x | libraries/sqlite/win32/callback.c | 378 |
1 files changed, 378 insertions, 0 deletions
diff --git a/libraries/sqlite/win32/callback.c b/libraries/sqlite/win32/callback.c new file mode 100755 index 0000000..009cfd7 --- /dev/null +++ b/libraries/sqlite/win32/callback.c | |||
@@ -0,0 +1,378 @@ | |||
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.23 2007/08/29 12:31:26 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 = sqlite3DbStrNDup(db, zName, nName); | ||
31 | if( !zExternal ) return; | ||
32 | db->xCollNeeded(db->pCollNeededArg, db, (int)ENC(db), zExternal); | ||
33 | sqlite3_free(zExternal); | ||
34 | } | ||
35 | #ifndef SQLITE_OMIT_UTF16 | ||
36 | if( db->xCollNeeded16 ){ | ||
37 | char const *zExternal; | ||
38 | sqlite3_value *pTmp = sqlite3ValueNew(db); | ||
39 | sqlite3ValueSetStr(pTmp, nName, zName, SQLITE_UTF8, SQLITE_STATIC); | ||
40 | zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); | ||
41 | if( zExternal ){ | ||
42 | db->xCollNeeded16(db->pCollNeededArg, db, (int)ENC(db), zExternal); | ||
43 | } | ||
44 | sqlite3ValueFree(pTmp); | ||
45 | } | ||
46 | #endif | ||
47 | } | ||
48 | |||
49 | /* | ||
50 | ** This routine is called if the collation factory fails to deliver a | ||
51 | ** collation function in the best encoding but there may be other versions | ||
52 | ** of this collation function (for other text encodings) available. Use one | ||
53 | ** of these instead if they exist. Avoid a UTF-8 <-> UTF-16 conversion if | ||
54 | ** possible. | ||
55 | */ | ||
56 | static int synthCollSeq(sqlite3 *db, CollSeq *pColl){ | ||
57 | CollSeq *pColl2; | ||
58 | char *z = pColl->zName; | ||
59 | int n = strlen(z); | ||
60 | int i; | ||
61 | static const u8 aEnc[] = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; | ||
62 | for(i=0; i<3; i++){ | ||
63 | pColl2 = sqlite3FindCollSeq(db, aEnc[i], z, n, 0); | ||
64 | if( pColl2->xCmp!=0 ){ | ||
65 | memcpy(pColl, pColl2, sizeof(CollSeq)); | ||
66 | pColl->xDel = 0; /* Do not copy the destructor */ | ||
67 | return SQLITE_OK; | ||
68 | } | ||
69 | } | ||
70 | return SQLITE_ERROR; | ||
71 | } | ||
72 | |||
73 | /* | ||
74 | ** This function is responsible for invoking the collation factory callback | ||
75 | ** or substituting a collation sequence of a different encoding when the | ||
76 | ** requested collation sequence is not available in the database native | ||
77 | ** encoding. | ||
78 | ** | ||
79 | ** If it is not NULL, then pColl must point to the database native encoding | ||
80 | ** collation sequence with name zName, length nName. | ||
81 | ** | ||
82 | ** The return value is either the collation sequence to be used in database | ||
83 | ** db for collation type name zName, length nName, or NULL, if no collation | ||
84 | ** sequence can be found. | ||
85 | */ | ||
86 | CollSeq *sqlite3GetCollSeq( | ||
87 | sqlite3* db, | ||
88 | CollSeq *pColl, | ||
89 | const char *zName, | ||
90 | int nName | ||
91 | ){ | ||
92 | CollSeq *p; | ||
93 | |||
94 | p = pColl; | ||
95 | if( !p ){ | ||
96 | p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); | ||
97 | } | ||
98 | if( !p || !p->xCmp ){ | ||
99 | /* No collation sequence of this type for this encoding is registered. | ||
100 | ** Call the collation factory to see if it can supply us with one. | ||
101 | */ | ||
102 | callCollNeeded(db, zName, nName); | ||
103 | p = sqlite3FindCollSeq(db, ENC(db), zName, nName, 0); | ||
104 | } | ||
105 | if( p && !p->xCmp && synthCollSeq(db, p) ){ | ||
106 | p = 0; | ||
107 | } | ||
108 | assert( !p || p->xCmp ); | ||
109 | return p; | ||
110 | } | ||
111 | |||
112 | /* | ||
113 | ** This routine is called on a collation sequence before it is used to | ||
114 | ** check that it is defined. An undefined collation sequence exists when | ||
115 | ** a database is loaded that contains references to collation sequences | ||
116 | ** that have not been defined by sqlite3_create_collation() etc. | ||
117 | ** | ||
118 | ** If required, this routine calls the 'collation needed' callback to | ||
119 | ** request a definition of the collating sequence. If this doesn't work, | ||
120 | ** an equivalent collating sequence that uses a text encoding different | ||
121 | ** from the main database is substituted, if one is available. | ||
122 | */ | ||
123 | int sqlite3CheckCollSeq(Parse *pParse, CollSeq *pColl){ | ||
124 | if( pColl ){ | ||
125 | const char *zName = pColl->zName; | ||
126 | CollSeq *p = sqlite3GetCollSeq(pParse->db, pColl, zName, -1); | ||
127 | if( !p ){ | ||
128 | if( pParse->nErr==0 ){ | ||
129 | sqlite3ErrorMsg(pParse, "no such collation sequence: %s", zName); | ||
130 | } | ||
131 | pParse->nErr++; | ||
132 | return SQLITE_ERROR; | ||
133 | } | ||
134 | assert( p==pColl ); | ||
135 | } | ||
136 | return SQLITE_OK; | ||
137 | } | ||
138 | |||
139 | |||
140 | |||
141 | /* | ||
142 | ** Locate and return an entry from the db.aCollSeq hash table. If the entry | ||
143 | ** specified by zName and nName is not found and parameter 'create' is | ||
144 | ** true, then create a new entry. Otherwise return NULL. | ||
145 | ** | ||
146 | ** Each pointer stored in the sqlite3.aCollSeq hash table contains an | ||
147 | ** array of three CollSeq structures. The first is the collation sequence | ||
148 | ** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. | ||
149 | ** | ||
150 | ** Stored immediately after the three collation sequences is a copy of | ||
151 | ** the collation sequence name. A pointer to this string is stored in | ||
152 | ** each collation sequence structure. | ||
153 | */ | ||
154 | static CollSeq *findCollSeqEntry( | ||
155 | sqlite3 *db, | ||
156 | const char *zName, | ||
157 | int nName, | ||
158 | int create | ||
159 | ){ | ||
160 | CollSeq *pColl; | ||
161 | if( nName<0 ) nName = strlen(zName); | ||
162 | pColl = sqlite3HashFind(&db->aCollSeq, zName, nName); | ||
163 | |||
164 | if( 0==pColl && create ){ | ||
165 | pColl = sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); | ||
166 | if( pColl ){ | ||
167 | CollSeq *pDel = 0; | ||
168 | pColl[0].zName = (char*)&pColl[3]; | ||
169 | pColl[0].enc = SQLITE_UTF8; | ||
170 | pColl[1].zName = (char*)&pColl[3]; | ||
171 | pColl[1].enc = SQLITE_UTF16LE; | ||
172 | pColl[2].zName = (char*)&pColl[3]; | ||
173 | pColl[2].enc = SQLITE_UTF16BE; | ||
174 | memcpy(pColl[0].zName, zName, nName); | ||
175 | pColl[0].zName[nName] = 0; | ||
176 | pDel = sqlite3HashInsert(&db->aCollSeq, pColl[0].zName, nName, pColl); | ||
177 | |||
178 | /* If a malloc() failure occured in sqlite3HashInsert(), it will | ||
179 | ** return the pColl pointer to be deleted (because it wasn't added | ||
180 | ** to the hash table). | ||
181 | */ | ||
182 | assert( pDel==0 || pDel==pColl ); | ||
183 | if( pDel!=0 ){ | ||
184 | db->mallocFailed = 1; | ||
185 | sqlite3_free(pDel); | ||
186 | pColl = 0; | ||
187 | } | ||
188 | } | ||
189 | } | ||
190 | return pColl; | ||
191 | } | ||
192 | |||
193 | /* | ||
194 | ** Parameter zName points to a UTF-8 encoded string nName bytes long. | ||
195 | ** Return the CollSeq* pointer for the collation sequence named zName | ||
196 | ** for the encoding 'enc' from the database 'db'. | ||
197 | ** | ||
198 | ** If the entry specified is not found and 'create' is true, then create a | ||
199 | ** new entry. Otherwise return NULL. | ||
200 | ** | ||
201 | ** A separate function sqlite3LocateCollSeq() is a wrapper around | ||
202 | ** this routine. sqlite3LocateCollSeq() invokes the collation factory | ||
203 | ** if necessary and generates an error message if the collating sequence | ||
204 | ** cannot be found. | ||
205 | */ | ||
206 | CollSeq *sqlite3FindCollSeq( | ||
207 | sqlite3 *db, | ||
208 | u8 enc, | ||
209 | const char *zName, | ||
210 | int nName, | ||
211 | int create | ||
212 | ){ | ||
213 | CollSeq *pColl; | ||
214 | if( zName ){ | ||
215 | pColl = findCollSeqEntry(db, zName, nName, create); | ||
216 | }else{ | ||
217 | pColl = db->pDfltColl; | ||
218 | } | ||
219 | assert( SQLITE_UTF8==1 && SQLITE_UTF16LE==2 && SQLITE_UTF16BE==3 ); | ||
220 | assert( enc>=SQLITE_UTF8 && enc<=SQLITE_UTF16BE ); | ||
221 | if( pColl ) pColl += enc-1; | ||
222 | return pColl; | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | ** Locate a user function given a name, a number of arguments and a flag | ||
227 | ** indicating whether the function prefers UTF-16 over UTF-8. Return a | ||
228 | ** pointer to the FuncDef structure that defines that function, or return | ||
229 | ** NULL if the function does not exist. | ||
230 | ** | ||
231 | ** If the createFlag argument is true, then a new (blank) FuncDef | ||
232 | ** structure is created and liked into the "db" structure if a | ||
233 | ** no matching function previously existed. When createFlag is true | ||
234 | ** and the nArg parameter is -1, then only a function that accepts | ||
235 | ** any number of arguments will be returned. | ||
236 | ** | ||
237 | ** If createFlag is false and nArg is -1, then the first valid | ||
238 | ** function found is returned. A function is valid if either xFunc | ||
239 | ** or xStep is non-zero. | ||
240 | ** | ||
241 | ** If createFlag is false, then a function with the required name and | ||
242 | ** number of arguments may be returned even if the eTextRep flag does not | ||
243 | ** match that requested. | ||
244 | */ | ||
245 | FuncDef *sqlite3FindFunction( | ||
246 | sqlite3 *db, /* An open database */ | ||
247 | const char *zName, /* Name of the function. Not null-terminated */ | ||
248 | int nName, /* Number of characters in the name */ | ||
249 | int nArg, /* Number of arguments. -1 means any number */ | ||
250 | u8 enc, /* Preferred text encoding */ | ||
251 | int createFlag /* Create new entry if true and does not otherwise exist */ | ||
252 | ){ | ||
253 | FuncDef *p; /* Iterator variable */ | ||
254 | FuncDef *pFirst; /* First function with this name */ | ||
255 | FuncDef *pBest = 0; /* Best match found so far */ | ||
256 | int bestmatch = 0; | ||
257 | |||
258 | |||
259 | assert( enc==SQLITE_UTF8 || enc==SQLITE_UTF16LE || enc==SQLITE_UTF16BE ); | ||
260 | if( nArg<-1 ) nArg = -1; | ||
261 | |||
262 | pFirst = (FuncDef*)sqlite3HashFind(&db->aFunc, zName, nName); | ||
263 | for(p=pFirst; p; p=p->pNext){ | ||
264 | /* During the search for the best function definition, bestmatch is set | ||
265 | ** as follows to indicate the quality of the match with the definition | ||
266 | ** pointed to by pBest: | ||
267 | ** | ||
268 | ** 0: pBest is NULL. No match has been found. | ||
269 | ** 1: A variable arguments function that prefers UTF-8 when a UTF-16 | ||
270 | ** encoding is requested, or vice versa. | ||
271 | ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is | ||
272 | ** requested, or vice versa. | ||
273 | ** 3: A variable arguments function using the same text encoding. | ||
274 | ** 4: A function with the exact number of arguments requested that | ||
275 | ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. | ||
276 | ** 5: A function with the exact number of arguments requested that | ||
277 | ** prefers UTF-16LE when UTF-16BE is requested, or vice versa. | ||
278 | ** 6: An exact match. | ||
279 | ** | ||
280 | ** A larger value of 'matchqual' indicates a more desirable match. | ||
281 | */ | ||
282 | if( p->nArg==-1 || p->nArg==nArg || nArg==-1 ){ | ||
283 | int match = 1; /* Quality of this match */ | ||
284 | if( p->nArg==nArg || nArg==-1 ){ | ||
285 | match = 4; | ||
286 | } | ||
287 | if( enc==p->iPrefEnc ){ | ||
288 | match += 2; | ||
289 | } | ||
290 | else if( (enc==SQLITE_UTF16LE && p->iPrefEnc==SQLITE_UTF16BE) || | ||
291 | (enc==SQLITE_UTF16BE && p->iPrefEnc==SQLITE_UTF16LE) ){ | ||
292 | match += 1; | ||
293 | } | ||
294 | |||
295 | if( match>bestmatch ){ | ||
296 | pBest = p; | ||
297 | bestmatch = match; | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | |||
302 | /* If the createFlag parameter is true, and the seach did not reveal an | ||
303 | ** exact match for the name, number of arguments and encoding, then add a | ||
304 | ** new entry to the hash table and return it. | ||
305 | */ | ||
306 | if( createFlag && bestmatch<6 && | ||
307 | (pBest = sqlite3DbMallocZero(db, sizeof(*pBest)+nName))!=0 ){ | ||
308 | pBest->nArg = nArg; | ||
309 | pBest->pNext = pFirst; | ||
310 | pBest->iPrefEnc = enc; | ||
311 | memcpy(pBest->zName, zName, nName); | ||
312 | pBest->zName[nName] = 0; | ||
313 | if( pBest==sqlite3HashInsert(&db->aFunc,pBest->zName,nName,(void*)pBest) ){ | ||
314 | db->mallocFailed = 1; | ||
315 | sqlite3_free(pBest); | ||
316 | return 0; | ||
317 | } | ||
318 | } | ||
319 | |||
320 | if( pBest && (pBest->xStep || pBest->xFunc || createFlag) ){ | ||
321 | return pBest; | ||
322 | } | ||
323 | return 0; | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | ** Free all resources held by the schema structure. The void* argument points | ||
328 | ** at a Schema struct. This function does not call sqlite3_free() on the | ||
329 | ** pointer itself, it just cleans up subsiduary resources (i.e. the contents | ||
330 | ** of the schema hash tables). | ||
331 | */ | ||
332 | void sqlite3SchemaFree(void *p){ | ||
333 | Hash temp1; | ||
334 | Hash temp2; | ||
335 | HashElem *pElem; | ||
336 | Schema *pSchema = (Schema *)p; | ||
337 | |||
338 | temp1 = pSchema->tblHash; | ||
339 | temp2 = pSchema->trigHash; | ||
340 | sqlite3HashInit(&pSchema->trigHash, SQLITE_HASH_STRING, 0); | ||
341 | sqlite3HashClear(&pSchema->aFKey); | ||
342 | sqlite3HashClear(&pSchema->idxHash); | ||
343 | for(pElem=sqliteHashFirst(&temp2); pElem; pElem=sqliteHashNext(pElem)){ | ||
344 | sqlite3DeleteTrigger((Trigger*)sqliteHashData(pElem)); | ||
345 | } | ||
346 | sqlite3HashClear(&temp2); | ||
347 | sqlite3HashInit(&pSchema->tblHash, SQLITE_HASH_STRING, 0); | ||
348 | for(pElem=sqliteHashFirst(&temp1); pElem; pElem=sqliteHashNext(pElem)){ | ||
349 | Table *pTab = sqliteHashData(pElem); | ||
350 | sqlite3DeleteTable(pTab); | ||
351 | } | ||
352 | sqlite3HashClear(&temp1); | ||
353 | pSchema->pSeqTab = 0; | ||
354 | pSchema->flags &= ~DB_SchemaLoaded; | ||
355 | } | ||
356 | |||
357 | /* | ||
358 | ** Find and return the schema associated with a BTree. Create | ||
359 | ** a new one if necessary. | ||
360 | */ | ||
361 | Schema *sqlite3SchemaGet(sqlite3 *db, Btree *pBt){ | ||
362 | Schema * p; | ||
363 | if( pBt ){ | ||
364 | p = (Schema *)sqlite3BtreeSchema(pBt, sizeof(Schema), sqlite3SchemaFree); | ||
365 | }else{ | ||
366 | p = (Schema *)sqlite3MallocZero(sizeof(Schema)); | ||
367 | } | ||
368 | if( !p ){ | ||
369 | db->mallocFailed = 1; | ||
370 | }else if ( 0==p->file_format ){ | ||
371 | sqlite3HashInit(&p->tblHash, SQLITE_HASH_STRING, 0); | ||
372 | sqlite3HashInit(&p->idxHash, SQLITE_HASH_STRING, 0); | ||
373 | sqlite3HashInit(&p->trigHash, SQLITE_HASH_STRING, 0); | ||
374 | sqlite3HashInit(&p->aFKey, SQLITE_HASH_STRING, 1); | ||
375 | p->enc = SQLITE_UTF8; | ||
376 | } | ||
377 | return p; | ||
378 | } | ||