wasCSharpSQLite – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Diagnostics; |
||
3 | using System.Text; |
||
4 | |||
5 | using i16 = System.Int16; |
||
6 | using u8 = System.Byte; |
||
7 | using u16 = System.UInt16; |
||
8 | |||
9 | namespace Community.CsharpSqlite |
||
10 | { |
||
11 | using sqlite3_value = Sqlite3.Mem; |
||
12 | |||
13 | public partial class Sqlite3 |
||
14 | { |
||
15 | /* |
||
16 | ** 2005 May 23 |
||
17 | ** |
||
18 | ** The author disclaims copyright to this source code. In place of |
||
19 | ** a legal notice, here is a blessing: |
||
20 | ** |
||
21 | ** May you do good and not evil. |
||
22 | ** May you find forgiveness for yourself and forgive others. |
||
23 | ** May you share freely, never taking more than you give. |
||
24 | ** |
||
25 | ************************************************************************* |
||
26 | ** |
||
27 | ** This file contains functions used to access the internal hash tables |
||
28 | ** of user defined functions and collation sequences. |
||
29 | ************************************************************************* |
||
30 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
31 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
32 | ** |
||
33 | ** SQLITE_SOURCE_ID: 2011-05-19 13:26:54 ed1da510a239ea767a01dc332b667119fa3c908e |
||
34 | ** |
||
35 | ************************************************************************* |
||
36 | */ |
||
37 | |||
38 | //#include "sqliteInt.h" |
||
39 | |||
40 | /* |
||
41 | ** Invoke the 'collation needed' callback to request a collation sequence |
||
42 | ** in the encoding enc of name zName, length nName. |
||
43 | */ |
||
44 | static void callCollNeeded( sqlite3 db, int enc, string zName ) |
||
45 | { |
||
46 | Debug.Assert( db.xCollNeeded == null || db.xCollNeeded16 == null ); |
||
47 | if ( db.xCollNeeded != null ) |
||
48 | { |
||
49 | string zExternal = zName;// sqlite3DbStrDup(db, zName); |
||
50 | if ( zExternal == null ) |
||
51 | return; |
||
52 | db.xCollNeeded( db.pCollNeededArg, db, enc, zExternal ); |
||
53 | sqlite3DbFree( db, ref zExternal ); |
||
54 | } |
||
55 | #if !SQLITE_OMIT_UTF16 |
||
56 | if( db.xCollNeeded16!=null ){ |
||
57 | string zExternal; |
||
58 | sqlite3_value pTmp = sqlite3ValueNew(db); |
||
59 | sqlite3ValueSetStr(pTmp, -1, zName, SQLITE_UTF8, SQLITE_STATIC); |
||
60 | zExternal = sqlite3ValueText(pTmp, SQLITE_UTF16NATIVE); |
||
61 | if( zExternal != string.Empty ){ |
||
62 | db.xCollNeeded16( db.pCollNeededArg, db, db.aDbStatic[0].pSchema.enc, zExternal );//(int)ENC(db), zExternal); |
||
63 | } |
||
64 | sqlite3ValueFree(ref pTmp); |
||
65 | } |
||
66 | #endif |
||
67 | } |
||
68 | |||
69 | /* |
||
70 | ** This routine is called if the collation factory fails to deliver a |
||
71 | ** collation function in the best encoding but there may be other versions |
||
72 | ** of this collation function (for other text encodings) available. Use one |
||
73 | ** of these instead if they exist. Avoid a UTF-8 <. UTF-16 conversion if |
||
74 | ** possible. |
||
75 | */ |
||
76 | static int synthCollSeq( sqlite3 db, CollSeq pColl ) |
||
77 | { |
||
78 | CollSeq pColl2; |
||
79 | string z = pColl.zName; |
||
80 | int i; |
||
81 | byte[] aEnc = { SQLITE_UTF16BE, SQLITE_UTF16LE, SQLITE_UTF8 }; |
||
82 | for ( i = 0; i < 3; i++ ) |
||
83 | { |
||
84 | pColl2 = sqlite3FindCollSeq( db, aEnc[i], z, 0 ); |
||
85 | if ( pColl2.xCmp != null ) |
||
86 | { |
||
87 | pColl = pColl2.Copy(); //memcpy(pColl, pColl2, sizeof(CollSeq)); |
||
88 | pColl.xDel = null; /* Do not copy the destructor */ |
||
89 | return SQLITE_OK; |
||
90 | } |
||
91 | } |
||
92 | return SQLITE_ERROR; |
||
93 | } |
||
94 | |||
95 | /* |
||
96 | ** This function is responsible for invoking the collation factory callback |
||
97 | ** or substituting a collation sequence of a different encoding when the |
||
98 | ** requested collation sequence is not available in the desired encoding. |
||
99 | ** |
||
100 | ** If it is not NULL, then pColl must point to the database native encoding |
||
101 | ** collation sequence with name zName, length nName. |
||
102 | ** |
||
103 | ** The return value is either the collation sequence to be used in database |
||
104 | ** db for collation type name zName, length nName, or NULL, if no collation |
||
105 | ** sequence can be found. |
||
106 | ** |
||
107 | ** See also: sqlite3LocateCollSeq(), sqlite3FindCollSeq() |
||
108 | */ |
||
109 | static CollSeq sqlite3GetCollSeq( |
||
110 | sqlite3 db, /* The database connection */ |
||
111 | u8 enc, /* The desired encoding for the collating sequence */ |
||
112 | CollSeq pColl, /* Collating sequence with native encoding, or NULL */ |
||
113 | string zName /* Collating sequence name */ |
||
114 | ) |
||
115 | { |
||
116 | CollSeq p; |
||
117 | |||
118 | p = pColl; |
||
119 | if ( p == null ) |
||
120 | { |
||
121 | p = sqlite3FindCollSeq( db, enc, zName, 0 ); |
||
122 | } |
||
123 | if ( p == null || p.xCmp == null ) |
||
124 | { |
||
125 | /* No collation sequence of this type for this encoding is registered. |
||
126 | ** Call the collation factory to see if it can supply us with one. |
||
127 | */ |
||
128 | callCollNeeded( db, enc, zName ); |
||
129 | p = sqlite3FindCollSeq( db, enc, zName, 0 ); |
||
130 | } |
||
131 | if ( p != null && p.xCmp == null && synthCollSeq( db, p ) != 0 ) |
||
132 | { |
||
133 | p = null; |
||
134 | } |
||
135 | Debug.Assert( p == null || p.xCmp != null ); |
||
136 | return p; |
||
137 | } |
||
138 | |||
139 | /* |
||
140 | ** This routine is called on a collation sequence before it is used to |
||
141 | ** check that it is defined. An undefined collation sequence exists when |
||
142 | ** a database is loaded that contains references to collation sequences |
||
143 | ** that have not been defined by sqlite3_create_collation() etc. |
||
144 | ** |
||
145 | ** If required, this routine calls the 'collation needed' callback to |
||
146 | ** request a definition of the collating sequence. If this doesn't work, |
||
147 | ** an equivalent collating sequence that uses a text encoding different |
||
148 | ** from the main database is substituted, if one is available. |
||
149 | */ |
||
150 | static int sqlite3CheckCollSeq( Parse pParse, CollSeq pColl ) |
||
151 | { |
||
152 | if ( pColl != null ) |
||
153 | { |
||
154 | string zName = pColl.zName; |
||
155 | sqlite3 db = pParse.db; |
||
156 | CollSeq p = sqlite3GetCollSeq( db, ENC( db ), pColl, zName ); |
||
157 | if ( null == p ) |
||
158 | { |
||
159 | sqlite3ErrorMsg( pParse, "no such collation sequence: %s", zName ); |
||
160 | pParse.nErr++; |
||
161 | return SQLITE_ERROR; |
||
162 | } |
||
163 | // |
||
164 | //Debug.Assert(p == pColl); |
||
165 | if ( p != pColl ) // Had to lookup appropriate sequence |
||
166 | { |
||
167 | pColl.enc = p.enc; |
||
168 | pColl.pUser = p.pUser; |
||
169 | pColl.type = p.type; |
||
170 | pColl.xCmp = p.xCmp; |
||
171 | pColl.xDel = p.xDel; |
||
172 | } |
||
173 | |||
174 | } |
||
175 | return SQLITE_OK; |
||
176 | } |
||
177 | |||
178 | |||
179 | |||
180 | /* |
||
181 | ** Locate and return an entry from the db.aCollSeq hash table. If the entry |
||
182 | ** specified by zName and nName is not found and parameter 'create' is |
||
183 | ** true, then create a new entry. Otherwise return NULL. |
||
184 | ** |
||
185 | ** Each pointer stored in the sqlite3.aCollSeq hash table contains an |
||
186 | ** array of three CollSeq structures. The first is the collation sequence |
||
187 | ** prefferred for UTF-8, the second UTF-16le, and the third UTF-16be. |
||
188 | ** |
||
189 | ** Stored immediately after the three collation sequences is a copy of |
||
190 | ** the collation sequence name. A pointer to this string is stored in |
||
191 | ** each collation sequence structure. |
||
192 | */ |
||
193 | static CollSeq[] findCollSeqEntry( |
||
194 | sqlite3 db, /* Database connection */ |
||
195 | string zName, /* Name of the collating sequence */ |
||
196 | int create /* Create a new entry if true */ |
||
197 | ) |
||
198 | { |
||
199 | CollSeq[] pColl; |
||
200 | int nName = sqlite3Strlen30( zName ); |
||
201 | pColl = sqlite3HashFind( db.aCollSeq, zName, nName, (CollSeq[])null ); |
||
202 | |||
203 | if ( ( null == pColl ) && create != 0 ) |
||
204 | { |
||
205 | pColl = new CollSeq[3]; //sqlite3DbMallocZero(db, 3*sizeof(*pColl) + nName + 1 ); |
||
206 | if ( pColl != null ) |
||
207 | { |
||
208 | CollSeq pDel = null; |
||
209 | pColl[0] = new CollSeq(); |
||
210 | pColl[0].zName = zName; |
||
211 | pColl[0].enc = SQLITE_UTF8; |
||
212 | pColl[1] = new CollSeq(); |
||
213 | pColl[1].zName = zName; |
||
214 | pColl[1].enc = SQLITE_UTF16LE; |
||
215 | pColl[2] = new CollSeq(); |
||
216 | pColl[2].zName = zName; |
||
217 | pColl[2].enc = SQLITE_UTF16BE; |
||
218 | //memcpy(pColl[0].zName, zName, nName); |
||
219 | //pColl[0].zName[nName] = 0; |
||
220 | CollSeq[] pDelArray = sqlite3HashInsert( ref db.aCollSeq, pColl[0].zName, nName, pColl ); |
||
221 | if ( pDelArray != null ) |
||
222 | pDel = pDelArray[0]; |
||
223 | /* If a malloc() failure occurred in sqlite3HashInsert(), it will |
||
224 | ** return the pColl pointer to be deleted (because it wasn't added |
||
225 | ** to the hash table). |
||
226 | */ |
||
227 | Debug.Assert( pDel == null || pDel == pColl[0] ); |
||
228 | if ( pDel != null ) |
||
229 | { |
||
230 | //// db.mallocFailed = 1; |
||
231 | pDel = null; //was sqlite3DbFree(db,ref pDel); |
||
232 | pColl = null; |
||
233 | } |
||
234 | } |
||
235 | } |
||
236 | return pColl; |
||
237 | } |
||
238 | |||
239 | /* |
||
240 | ** Parameter zName points to a UTF-8 encoded string nName bytes long. |
||
241 | ** Return the CollSeq* pointer for the collation sequence named zName |
||
242 | ** for the encoding 'enc' from the database 'db'. |
||
243 | ** |
||
244 | ** If the entry specified is not found and 'create' is true, then create a |
||
245 | ** new entry. Otherwise return NULL. |
||
246 | ** |
||
247 | ** A separate function sqlite3LocateCollSeq() is a wrapper around |
||
248 | ** this routine. sqlite3LocateCollSeq() invokes the collation factory |
||
249 | ** if necessary and generates an error message if the collating sequence |
||
250 | ** cannot be found. |
||
251 | ** |
||
252 | ** See also: sqlite3LocateCollSeq(), sqlite3GetCollSeq() |
||
253 | */ |
||
254 | static CollSeq sqlite3FindCollSeq( |
||
255 | sqlite3 db, |
||
256 | u8 enc, |
||
257 | string zName, |
||
258 | u8 create |
||
259 | ) |
||
260 | { |
||
261 | CollSeq[] pColl; |
||
262 | if ( zName != null ) |
||
263 | { |
||
264 | pColl = findCollSeqEntry( db, zName, create ); |
||
265 | } |
||
266 | else |
||
267 | { |
||
268 | pColl = new CollSeq[enc]; |
||
269 | pColl[enc - 1] = db.pDfltColl; |
||
270 | } |
||
271 | Debug.Assert( SQLITE_UTF8 == 1 && SQLITE_UTF16LE == 2 && SQLITE_UTF16BE == 3 ); |
||
272 | Debug.Assert( enc >= SQLITE_UTF8 && enc <= SQLITE_UTF16BE ); |
||
273 | if ( pColl != null ) |
||
274 | { |
||
275 | enc -= 1; // if (pColl != null) pColl += enc - 1; |
||
276 | return pColl[enc]; |
||
277 | } |
||
278 | else |
||
279 | return null; |
||
280 | } |
||
281 | |||
282 | /* During the search for the best function definition, this procedure |
||
283 | ** is called to test how well the function passed as the first argument |
||
284 | ** matches the request for a function with nArg arguments in a system |
||
285 | ** that uses encoding enc. The value returned indicates how well the |
||
286 | ** request is matched. A higher value indicates a better match. |
||
287 | ** |
||
288 | ** The returned value is always between 0 and 6, as follows: |
||
289 | ** |
||
290 | ** 0: Not a match, or if nArg<0 and the function is has no implementation. |
||
291 | ** 1: A variable arguments function that prefers UTF-8 when a UTF-16 |
||
292 | ** encoding is requested, or vice versa. |
||
293 | ** 2: A variable arguments function that uses UTF-16BE when UTF-16LE is |
||
294 | ** requested, or vice versa. |
||
295 | ** 3: A variable arguments function using the same text encoding. |
||
296 | ** 4: A function with the exact number of arguments requested that |
||
297 | ** prefers UTF-8 when a UTF-16 encoding is requested, or vice versa. |
||
298 | ** 5: A function with the exact number of arguments requested that |
||
299 | ** prefers UTF-16LE when UTF-16BE is requested, or vice versa. |
||
300 | ** 6: An exact match. |
||
301 | ** |
||
302 | */ |
||
303 | static int matchQuality( FuncDef p, int nArg, int enc ) |
||
304 | { |
||
305 | int match = 0; |
||
306 | if ( p.nArg == -1 || p.nArg == nArg |
||
307 | || ( nArg == -1 && ( p.xFunc != null || p.xStep != null ) ) |
||
308 | ) |
||
309 | { |
||
310 | match = 1; |
||
311 | if ( p.nArg == nArg || nArg == -1 ) |
||
312 | { |
||
313 | match = 4; |
||
314 | } |
||
315 | if ( enc == p.iPrefEnc ) |
||
316 | { |
||
317 | match += 2; |
||
318 | } |
||
319 | else if ( ( enc == SQLITE_UTF16LE && p.iPrefEnc == SQLITE_UTF16BE ) || |
||
320 | ( enc == SQLITE_UTF16BE && p.iPrefEnc == SQLITE_UTF16LE ) ) |
||
321 | { |
||
322 | match += 1; |
||
323 | } |
||
324 | } |
||
325 | return match; |
||
326 | } |
||
327 | |||
328 | /* |
||
329 | ** Search a FuncDefHash for a function with the given name. Return |
||
330 | ** a pointer to the matching FuncDef if found, or 0 if there is no match. |
||
331 | */ |
||
332 | static FuncDef functionSearch( |
||
333 | FuncDefHash pHash, /* Hash table to search */ |
||
334 | int h, /* Hash of the name */ |
||
335 | string zFunc, /* Name of function */ |
||
336 | int nFunc /* Number of bytes in zFunc */ |
||
337 | ) |
||
338 | { |
||
339 | FuncDef p; |
||
340 | for ( p = pHash.a[h]; p != null; p = p.pHash ) |
||
341 | { |
||
342 | if ( p.zName.Length == nFunc && p.zName.StartsWith( zFunc, StringComparison.OrdinalIgnoreCase ) ) |
||
343 | { |
||
344 | return p; |
||
345 | } |
||
346 | } |
||
347 | return null; |
||
348 | } |
||
349 | |||
350 | /* |
||
351 | ** Insert a new FuncDef into a FuncDefHash hash table. |
||
352 | */ |
||
353 | static void sqlite3FuncDefInsert( |
||
354 | FuncDefHash pHash, /* The hash table into which to insert */ |
||
355 | FuncDef pDef /* The function definition to insert */ |
||
356 | ) |
||
357 | { |
||
358 | FuncDef pOther; |
||
359 | int nName = sqlite3Strlen30( pDef.zName ); |
||
360 | u8 c1 = (u8)pDef.zName[0]; |
||
361 | int h = ( sqlite3UpperToLower[c1] + nName ) % ArraySize( pHash.a ); |
||
362 | pOther = functionSearch( pHash, h, pDef.zName, nName ); |
||
363 | if ( pOther != null ) |
||
364 | { |
||
365 | Debug.Assert( pOther != pDef && pOther.pNext != pDef ); |
||
366 | pDef.pNext = pOther.pNext; |
||
367 | pOther.pNext = pDef; |
||
368 | } |
||
369 | else |
||
370 | { |
||
371 | pDef.pNext = null; |
||
372 | pDef.pHash = pHash.a[h]; |
||
373 | pHash.a[h] = pDef; |
||
374 | } |
||
375 | } |
||
376 | |||
377 | /* |
||
378 | ** Locate a user function given a name, a number of arguments and a flag |
||
379 | ** indicating whether the function prefers UTF-16 over UTF-8. Return a |
||
380 | ** pointer to the FuncDef structure that defines that function, or return |
||
381 | ** NULL if the function does not exist. |
||
382 | ** |
||
383 | ** If the createFlag argument is true, then a new (blank) FuncDef |
||
384 | ** structure is created and liked into the "db" structure if a |
||
385 | ** no matching function previously existed. When createFlag is true |
||
386 | ** and the nArg parameter is -1, then only a function that accepts |
||
387 | ** any number of arguments will be returned. |
||
388 | ** |
||
389 | ** If createFlag is false and nArg is -1, then the first valid |
||
390 | ** function found is returned. A function is valid if either xFunc |
||
391 | ** or xStep is non-zero. |
||
392 | ** |
||
393 | ** If createFlag is false, then a function with the required name and |
||
394 | ** number of arguments may be returned even if the eTextRep flag does not |
||
395 | ** match that requested. |
||
396 | */ |
||
397 | |||
398 | static FuncDef sqlite3FindFunction( |
||
399 | sqlite3 db, /* An open database */ |
||
400 | string zName, /* Name of the function. Not null-terminated */ |
||
401 | int nName, /* Number of characters in the name */ |
||
402 | int nArg, /* Number of arguments. -1 means any number */ |
||
403 | u8 enc, /* Preferred text encoding */ |
||
404 | u8 createFlag /* Create new entry if true and does not otherwise exist */ |
||
405 | ) |
||
406 | { |
||
407 | FuncDef p; /* Iterator variable */ |
||
408 | FuncDef pBest = null; /* Best match found so far */ |
||
409 | int bestScore = 0; |
||
410 | int h; /* Hash value */ |
||
411 | |||
412 | Debug.Assert( enc == SQLITE_UTF8 || enc == SQLITE_UTF16LE || enc == SQLITE_UTF16BE ); |
||
413 | h = ( sqlite3UpperToLower[(u8)zName[0]] + nName ) % ArraySize( db.aFunc.a ); |
||
414 | |||
415 | |||
416 | /* First search for a match amongst the application-defined functions. |
||
417 | */ |
||
418 | p = functionSearch( db.aFunc, h, zName, nName ); |
||
419 | while ( p != null ) |
||
420 | { |
||
421 | int score = matchQuality( p, nArg, enc ); |
||
422 | if ( score > bestScore ) |
||
423 | { |
||
424 | pBest = p; |
||
425 | bestScore = score; |
||
426 | |||
427 | } |
||
428 | p = p.pNext; |
||
429 | } |
||
430 | |||
431 | |||
432 | /* If no match is found, search the built-in functions. |
||
433 | ** |
||
434 | ** If the SQLITE_PreferBuiltin flag is set, then search the built-in |
||
435 | ** functions even if a prior app-defined function was found. And give |
||
436 | ** priority to built-in functions. |
||
437 | ** |
||
438 | ** Except, if createFlag is true, that means that we are trying to |
||
439 | ** install a new function. Whatever FuncDef structure is returned it will |
||
440 | ** have fields overwritten with new information appropriate for the |
||
441 | ** new function. But the FuncDefs for built-in functions are read-only. |
||
442 | ** So we must not search for built-ins when creating a new function. |
||
443 | */ |
||
444 | if ( 0 == createFlag && ( pBest == null || ( db.flags & SQLITE_PreferBuiltin ) != 0 ) ) |
||
445 | { |
||
446 | #if SQLITE_OMIT_WSD |
||
447 | FuncDefHash pHash = GLOBAL( FuncDefHash, sqlite3GlobalFunctions ); |
||
448 | #else |
||
449 | FuncDefHash pHash = sqlite3GlobalFunctions; |
||
450 | #endif |
||
451 | bestScore = 0; |
||
452 | p = functionSearch( pHash, h, zName, nName ); |
||
453 | while ( p != null ) |
||
454 | { |
||
455 | int score = matchQuality( p, nArg, enc ); |
||
456 | if ( score > bestScore ) |
||
457 | { |
||
458 | pBest = p; |
||
459 | bestScore = score; |
||
460 | } |
||
461 | p = p.pNext; |
||
462 | } |
||
463 | } |
||
464 | |||
465 | /* If the createFlag parameter is true and the search did not reveal an |
||
466 | ** exact match for the name, number of arguments and encoding, then add a |
||
467 | ** new entry to the hash table and return it. |
||
468 | */ |
||
469 | if ( createFlag != 0 && ( bestScore < 6 || pBest.nArg != nArg ) && |
||
470 | ( pBest = new FuncDef() ) != null ) |
||
471 | { //sqlite3DbMallocZero(db, sizeof(*pBest)+nName+1))!=0 ){ |
||
472 | //pBest.zName = (char *)&pBest[1]; |
||
473 | pBest.nArg = (i16)nArg; |
||
474 | pBest.iPrefEnc = enc; |
||
475 | pBest.zName = zName; //memcpy(pBest.zName, zName, nName); |
||
476 | //pBest.zName[nName] = 0; |
||
477 | sqlite3FuncDefInsert( db.aFunc, pBest ); |
||
478 | } |
||
479 | |||
480 | if ( pBest != null && ( pBest.xStep != null || pBest.xFunc != null || createFlag != 0 ) ) |
||
481 | { |
||
482 | return pBest; |
||
483 | } |
||
484 | return null; |
||
485 | } |
||
486 | |||
487 | /* |
||
488 | ** Free all resources held by the schema structure. The void* argument points |
||
489 | ** at a Schema struct. This function does not call sqlite3DbFree(db, ) on the |
||
490 | ** pointer itself, it just cleans up subsidiary resources (i.e. the contents |
||
491 | ** of the schema hash tables). |
||
492 | ** |
||
493 | ** The Schema.cache_size variable is not cleared. |
||
494 | */ |
||
495 | static void sqlite3SchemaClear( Schema p ) |
||
496 | { |
||
497 | Hash temp1; |
||
498 | Hash temp2; |
||
499 | HashElem pElem; |
||
500 | Schema pSchema = p; |
||
501 | |||
502 | temp1 = pSchema.tblHash; |
||
503 | temp2 = pSchema.trigHash; |
||
504 | sqlite3HashInit( pSchema.trigHash ); |
||
505 | sqlite3HashClear( pSchema.idxHash ); |
||
506 | for ( pElem = sqliteHashFirst( temp2 ); pElem != null; pElem = sqliteHashNext( pElem ) ) |
||
507 | { |
||
508 | Trigger pTrigger = (Trigger)sqliteHashData( pElem ); |
||
509 | sqlite3DeleteTrigger( null, ref pTrigger ); |
||
510 | } |
||
511 | sqlite3HashClear( temp2 ); |
||
512 | sqlite3HashInit( pSchema.trigHash ); |
||
513 | for ( pElem = temp1.first; pElem != null; pElem = pElem.next )//sqliteHashFirst(&temp1); pElem; pElem = sqliteHashNext(pElem)) |
||
514 | { |
||
515 | Table pTab = (Table)pElem.data; //sqliteHashData(pElem); |
||
516 | sqlite3DeleteTable( null, ref pTab ); |
||
517 | } |
||
518 | sqlite3HashClear( temp1 ); |
||
519 | sqlite3HashClear( pSchema.fkeyHash ); |
||
520 | pSchema.pSeqTab = null; |
||
521 | if ( ( pSchema.flags & DB_SchemaLoaded ) != 0 ) |
||
522 | { |
||
523 | pSchema.iGeneration++; |
||
524 | pSchema.flags = (u16)( pSchema.flags & ( ~DB_SchemaLoaded ) ); |
||
525 | } |
||
526 | p.Clear(); |
||
527 | } |
||
528 | |||
529 | /* |
||
530 | ** Find and return the schema associated with a BTree. Create |
||
531 | ** a new one if necessary. |
||
532 | */ |
||
533 | static Schema sqlite3SchemaGet( sqlite3 db, Btree pBt ) |
||
534 | { |
||
535 | Schema p; |
||
536 | if ( pBt != null ) |
||
537 | { |
||
538 | p = sqlite3BtreeSchema( pBt, -1, (dxFreeSchema)sqlite3SchemaClear );//Schema.Length, sqlite3SchemaFree); |
||
539 | } |
||
540 | else |
||
541 | { |
||
542 | p = new Schema(); // (Schema *)sqlite3DbMallocZero(0, sizeof(Schema)); |
||
543 | } |
||
544 | if ( p == null ) |
||
545 | { |
||
546 | //// db.mallocFailed = 1; |
||
547 | } |
||
548 | else if ( 0 == p.file_format ) |
||
549 | { |
||
550 | sqlite3HashInit( p.tblHash ); |
||
551 | sqlite3HashInit( p.idxHash ); |
||
552 | sqlite3HashInit( p.trigHash ); |
||
553 | sqlite3HashInit( p.fkeyHash ); |
||
554 | p.enc = SQLITE_UTF8; |
||
555 | } |
||
556 | return p; |
||
557 | } |
||
558 | } |
||
559 | } |