diff options
author | dan miller | 2007-10-20 02:49:29 +0000 |
---|---|---|
committer | dan miller | 2007-10-20 02:49:29 +0000 |
commit | e36d23a85ebff914d74bb541558c2b6082b78edb (patch) | |
tree | 54b58fdf162e78af64055282a6035c8d2443389d /libraries/sqlite/unix/sqlite-3.5.1/src/vtab.c | |
parent | * Fixed an issue whereby avatar chat distances were being calculated against ... (diff) | |
download | opensim-SC_OLD-e36d23a85ebff914d74bb541558c2b6082b78edb.zip opensim-SC_OLD-e36d23a85ebff914d74bb541558c2b6082b78edb.tar.gz opensim-SC_OLD-e36d23a85ebff914d74bb541558c2b6082b78edb.tar.bz2 opensim-SC_OLD-e36d23a85ebff914d74bb541558c2b6082b78edb.tar.xz |
sqlite source (unix build) added to libraries
Diffstat (limited to 'libraries/sqlite/unix/sqlite-3.5.1/src/vtab.c')
-rw-r--r-- | libraries/sqlite/unix/sqlite-3.5.1/src/vtab.c | 797 |
1 files changed, 797 insertions, 0 deletions
diff --git a/libraries/sqlite/unix/sqlite-3.5.1/src/vtab.c b/libraries/sqlite/unix/sqlite-3.5.1/src/vtab.c new file mode 100644 index 0000000..9ca317b --- /dev/null +++ b/libraries/sqlite/unix/sqlite-3.5.1/src/vtab.c | |||
@@ -0,0 +1,797 @@ | |||
1 | /* | ||
2 | ** 2006 June 10 | ||
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 | ** This file contains code used to help implement virtual tables. | ||
13 | ** | ||
14 | ** $Id: vtab.c,v 1.59 2007/09/20 11:32:18 rse Exp $ | ||
15 | */ | ||
16 | #ifndef SQLITE_OMIT_VIRTUALTABLE | ||
17 | #include "sqliteInt.h" | ||
18 | |||
19 | static int createModule( | ||
20 | sqlite3 *db, /* Database in which module is registered */ | ||
21 | const char *zName, /* Name assigned to this module */ | ||
22 | const sqlite3_module *pModule, /* The definition of the module */ | ||
23 | void *pAux, /* Context pointer for xCreate/xConnect */ | ||
24 | void (*xDestroy)(void *) /* Module destructor function */ | ||
25 | ) { | ||
26 | int rc, nName; | ||
27 | Module *pMod; | ||
28 | |||
29 | sqlite3_mutex_enter(db->mutex); | ||
30 | nName = strlen(zName); | ||
31 | pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); | ||
32 | if( pMod ){ | ||
33 | char *zCopy = (char *)(&pMod[1]); | ||
34 | memcpy(zCopy, zName, nName+1); | ||
35 | pMod->zName = zCopy; | ||
36 | pMod->pModule = pModule; | ||
37 | pMod->pAux = pAux; | ||
38 | pMod->xDestroy = xDestroy; | ||
39 | pMod = (Module *)sqlite3HashInsert(&db->aModule, zCopy, nName, (void*)pMod); | ||
40 | if( pMod && pMod->xDestroy ){ | ||
41 | pMod->xDestroy(pMod->pAux); | ||
42 | } | ||
43 | sqlite3_free(pMod); | ||
44 | sqlite3ResetInternalSchema(db, 0); | ||
45 | } | ||
46 | rc = sqlite3ApiExit(db, SQLITE_OK); | ||
47 | sqlite3_mutex_leave(db->mutex); | ||
48 | return rc; | ||
49 | } | ||
50 | |||
51 | |||
52 | /* | ||
53 | ** External API function used to create a new virtual-table module. | ||
54 | */ | ||
55 | int sqlite3_create_module( | ||
56 | sqlite3 *db, /* Database in which module is registered */ | ||
57 | const char *zName, /* Name assigned to this module */ | ||
58 | const sqlite3_module *pModule, /* The definition of the module */ | ||
59 | void *pAux /* Context pointer for xCreate/xConnect */ | ||
60 | ){ | ||
61 | return createModule(db, zName, pModule, pAux, 0); | ||
62 | } | ||
63 | |||
64 | /* | ||
65 | ** External API function used to create a new virtual-table module. | ||
66 | */ | ||
67 | int sqlite3_create_module_v2( | ||
68 | sqlite3 *db, /* Database in which module is registered */ | ||
69 | const char *zName, /* Name assigned to this module */ | ||
70 | const sqlite3_module *pModule, /* The definition of the module */ | ||
71 | void *pAux, /* Context pointer for xCreate/xConnect */ | ||
72 | void (*xDestroy)(void *) /* Module destructor function */ | ||
73 | ){ | ||
74 | return createModule(db, zName, pModule, pAux, xDestroy); | ||
75 | } | ||
76 | |||
77 | /* | ||
78 | ** Lock the virtual table so that it cannot be disconnected. | ||
79 | ** Locks nest. Every lock should have a corresponding unlock. | ||
80 | ** If an unlock is omitted, resources leaks will occur. | ||
81 | ** | ||
82 | ** If a disconnect is attempted while a virtual table is locked, | ||
83 | ** the disconnect is deferred until all locks have been removed. | ||
84 | */ | ||
85 | void sqlite3VtabLock(sqlite3_vtab *pVtab){ | ||
86 | pVtab->nRef++; | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | ** Unlock a virtual table. When the last lock is removed, | ||
91 | ** disconnect the virtual table. | ||
92 | */ | ||
93 | void sqlite3VtabUnlock(sqlite3 *db, sqlite3_vtab *pVtab){ | ||
94 | pVtab->nRef--; | ||
95 | assert(db); | ||
96 | assert(!sqlite3SafetyCheck(db)); | ||
97 | if( pVtab->nRef==0 ){ | ||
98 | if( db->magic==SQLITE_MAGIC_BUSY ){ | ||
99 | sqlite3SafetyOff(db); | ||
100 | pVtab->pModule->xDisconnect(pVtab); | ||
101 | sqlite3SafetyOn(db); | ||
102 | } else { | ||
103 | pVtab->pModule->xDisconnect(pVtab); | ||
104 | } | ||
105 | } | ||
106 | } | ||
107 | |||
108 | /* | ||
109 | ** Clear any and all virtual-table information from the Table record. | ||
110 | ** This routine is called, for example, just before deleting the Table | ||
111 | ** record. | ||
112 | */ | ||
113 | void sqlite3VtabClear(Table *p){ | ||
114 | sqlite3_vtab *pVtab = p->pVtab; | ||
115 | if( pVtab ){ | ||
116 | assert( p->pMod && p->pMod->pModule ); | ||
117 | sqlite3VtabUnlock(p->pSchema->db, pVtab); | ||
118 | p->pVtab = 0; | ||
119 | } | ||
120 | if( p->azModuleArg ){ | ||
121 | int i; | ||
122 | for(i=0; i<p->nModuleArg; i++){ | ||
123 | sqlite3_free(p->azModuleArg[i]); | ||
124 | } | ||
125 | sqlite3_free(p->azModuleArg); | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /* | ||
130 | ** Add a new module argument to pTable->azModuleArg[]. | ||
131 | ** The string is not copied - the pointer is stored. The | ||
132 | ** string will be freed automatically when the table is | ||
133 | ** deleted. | ||
134 | */ | ||
135 | static void addModuleArgument(sqlite3 *db, Table *pTable, char *zArg){ | ||
136 | int i = pTable->nModuleArg++; | ||
137 | int nBytes = sizeof(char *)*(1+pTable->nModuleArg); | ||
138 | char **azModuleArg; | ||
139 | azModuleArg = sqlite3DbRealloc(db, pTable->azModuleArg, nBytes); | ||
140 | if( azModuleArg==0 ){ | ||
141 | int j; | ||
142 | for(j=0; j<i; j++){ | ||
143 | sqlite3_free(pTable->azModuleArg[j]); | ||
144 | } | ||
145 | sqlite3_free(zArg); | ||
146 | sqlite3_free(pTable->azModuleArg); | ||
147 | pTable->nModuleArg = 0; | ||
148 | }else{ | ||
149 | azModuleArg[i] = zArg; | ||
150 | azModuleArg[i+1] = 0; | ||
151 | } | ||
152 | pTable->azModuleArg = azModuleArg; | ||
153 | } | ||
154 | |||
155 | /* | ||
156 | ** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE | ||
157 | ** statement. The module name has been parsed, but the optional list | ||
158 | ** of parameters that follow the module name are still pending. | ||
159 | */ | ||
160 | void sqlite3VtabBeginParse( | ||
161 | Parse *pParse, /* Parsing context */ | ||
162 | Token *pName1, /* Name of new table, or database name */ | ||
163 | Token *pName2, /* Name of new table or NULL */ | ||
164 | Token *pModuleName /* Name of the module for the virtual table */ | ||
165 | ){ | ||
166 | int iDb; /* The database the table is being created in */ | ||
167 | Table *pTable; /* The new virtual table */ | ||
168 | sqlite3 *db; /* Database connection */ | ||
169 | |||
170 | if( pParse->db->flags & SQLITE_SharedCache ){ | ||
171 | sqlite3ErrorMsg(pParse, "Cannot use virtual tables in shared-cache mode"); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | sqlite3StartTable(pParse, pName1, pName2, 0, 0, 1, 0); | ||
176 | pTable = pParse->pNewTable; | ||
177 | if( pTable==0 || pParse->nErr ) return; | ||
178 | assert( 0==pTable->pIndex ); | ||
179 | |||
180 | db = pParse->db; | ||
181 | iDb = sqlite3SchemaToIndex(db, pTable->pSchema); | ||
182 | assert( iDb>=0 ); | ||
183 | |||
184 | pTable->isVirtual = 1; | ||
185 | pTable->nModuleArg = 0; | ||
186 | addModuleArgument(db, pTable, sqlite3NameFromToken(db, pModuleName)); | ||
187 | addModuleArgument(db, pTable, sqlite3DbStrDup(db, db->aDb[iDb].zName)); | ||
188 | addModuleArgument(db, pTable, sqlite3DbStrDup(db, pTable->zName)); | ||
189 | pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z; | ||
190 | |||
191 | #ifndef SQLITE_OMIT_AUTHORIZATION | ||
192 | /* Creating a virtual table invokes the authorization callback twice. | ||
193 | ** The first invocation, to obtain permission to INSERT a row into the | ||
194 | ** sqlite_master table, has already been made by sqlite3StartTable(). | ||
195 | ** The second call, to obtain permission to create the table, is made now. | ||
196 | */ | ||
197 | if( pTable->azModuleArg ){ | ||
198 | sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, | ||
199 | pTable->azModuleArg[0], pParse->db->aDb[iDb].zName); | ||
200 | } | ||
201 | #endif | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | ** This routine takes the module argument that has been accumulating | ||
206 | ** in pParse->zArg[] and appends it to the list of arguments on the | ||
207 | ** virtual table currently under construction in pParse->pTable. | ||
208 | */ | ||
209 | static void addArgumentToVtab(Parse *pParse){ | ||
210 | if( pParse->sArg.z && pParse->pNewTable ){ | ||
211 | const char *z = (const char*)pParse->sArg.z; | ||
212 | int n = pParse->sArg.n; | ||
213 | sqlite3 *db = pParse->db; | ||
214 | addModuleArgument(db, pParse->pNewTable, sqlite3DbStrNDup(db, z, n)); | ||
215 | } | ||
216 | } | ||
217 | |||
218 | /* | ||
219 | ** The parser calls this routine after the CREATE VIRTUAL TABLE statement | ||
220 | ** has been completely parsed. | ||
221 | */ | ||
222 | void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ | ||
223 | Table *pTab; /* The table being constructed */ | ||
224 | sqlite3 *db; /* The database connection */ | ||
225 | char *zModule; /* The module name of the table: USING modulename */ | ||
226 | Module *pMod = 0; | ||
227 | |||
228 | addArgumentToVtab(pParse); | ||
229 | pParse->sArg.z = 0; | ||
230 | |||
231 | /* Lookup the module name. */ | ||
232 | pTab = pParse->pNewTable; | ||
233 | if( pTab==0 ) return; | ||
234 | db = pParse->db; | ||
235 | if( pTab->nModuleArg<1 ) return; | ||
236 | zModule = pTab->azModuleArg[0]; | ||
237 | pMod = (Module *)sqlite3HashFind(&db->aModule, zModule, strlen(zModule)); | ||
238 | pTab->pMod = pMod; | ||
239 | |||
240 | /* If the CREATE VIRTUAL TABLE statement is being entered for the | ||
241 | ** first time (in other words if the virtual table is actually being | ||
242 | ** created now instead of just being read out of sqlite_master) then | ||
243 | ** do additional initialization work and store the statement text | ||
244 | ** in the sqlite_master table. | ||
245 | */ | ||
246 | if( !db->init.busy ){ | ||
247 | char *zStmt; | ||
248 | char *zWhere; | ||
249 | int iDb; | ||
250 | Vdbe *v; | ||
251 | |||
252 | /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ | ||
253 | if( pEnd ){ | ||
254 | pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n; | ||
255 | } | ||
256 | zStmt = sqlite3MPrintf(db, "CREATE VIRTUAL TABLE %T", &pParse->sNameToken); | ||
257 | |||
258 | /* A slot for the record has already been allocated in the | ||
259 | ** SQLITE_MASTER table. We just need to update that slot with all | ||
260 | ** the information we've collected. | ||
261 | ** | ||
262 | ** The top of the stack is the rootpage allocated by sqlite3StartTable(). | ||
263 | ** This value is always 0 and is ignored, a virtual table does not have a | ||
264 | ** rootpage. The next entry on the stack is the rowid of the record | ||
265 | ** in the sqlite_master table. | ||
266 | */ | ||
267 | iDb = sqlite3SchemaToIndex(db, pTab->pSchema); | ||
268 | sqlite3NestedParse(pParse, | ||
269 | "UPDATE %Q.%s " | ||
270 | "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " | ||
271 | "WHERE rowid=#1", | ||
272 | db->aDb[iDb].zName, SCHEMA_TABLE(iDb), | ||
273 | pTab->zName, | ||
274 | pTab->zName, | ||
275 | zStmt | ||
276 | ); | ||
277 | sqlite3_free(zStmt); | ||
278 | v = sqlite3GetVdbe(pParse); | ||
279 | sqlite3ChangeCookie(db, v, iDb); | ||
280 | |||
281 | sqlite3VdbeAddOp(v, OP_Expire, 0, 0); | ||
282 | zWhere = sqlite3MPrintf(db, "name='%q'", pTab->zName); | ||
283 | sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 1, zWhere, P3_DYNAMIC); | ||
284 | sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1); | ||
285 | } | ||
286 | |||
287 | /* If we are rereading the sqlite_master table create the in-memory | ||
288 | ** record of the table. If the module has already been registered, | ||
289 | ** also call the xConnect method here. | ||
290 | */ | ||
291 | else { | ||
292 | Table *pOld; | ||
293 | Schema *pSchema = pTab->pSchema; | ||
294 | const char *zName = pTab->zName; | ||
295 | int nName = strlen(zName) + 1; | ||
296 | pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); | ||
297 | if( pOld ){ | ||
298 | db->mallocFailed = 1; | ||
299 | assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ | ||
300 | return; | ||
301 | } | ||
302 | pSchema->db = pParse->db; | ||
303 | pParse->pNewTable = 0; | ||
304 | } | ||
305 | } | ||
306 | |||
307 | /* | ||
308 | ** The parser calls this routine when it sees the first token | ||
309 | ** of an argument to the module name in a CREATE VIRTUAL TABLE statement. | ||
310 | */ | ||
311 | void sqlite3VtabArgInit(Parse *pParse){ | ||
312 | addArgumentToVtab(pParse); | ||
313 | pParse->sArg.z = 0; | ||
314 | pParse->sArg.n = 0; | ||
315 | } | ||
316 | |||
317 | /* | ||
318 | ** The parser calls this routine for each token after the first token | ||
319 | ** in an argument to the module name in a CREATE VIRTUAL TABLE statement. | ||
320 | */ | ||
321 | void sqlite3VtabArgExtend(Parse *pParse, Token *p){ | ||
322 | Token *pArg = &pParse->sArg; | ||
323 | if( pArg->z==0 ){ | ||
324 | pArg->z = p->z; | ||
325 | pArg->n = p->n; | ||
326 | }else{ | ||
327 | assert(pArg->z < p->z); | ||
328 | pArg->n = (p->z + p->n - pArg->z); | ||
329 | } | ||
330 | } | ||
331 | |||
332 | /* | ||
333 | ** Invoke a virtual table constructor (either xCreate or xConnect). The | ||
334 | ** pointer to the function to invoke is passed as the fourth parameter | ||
335 | ** to this procedure. | ||
336 | */ | ||
337 | static int vtabCallConstructor( | ||
338 | sqlite3 *db, | ||
339 | Table *pTab, | ||
340 | Module *pMod, | ||
341 | int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**), | ||
342 | char **pzErr | ||
343 | ){ | ||
344 | int rc; | ||
345 | int rc2; | ||
346 | sqlite3_vtab *pVtab = 0; | ||
347 | const char *const*azArg = (const char *const*)pTab->azModuleArg; | ||
348 | int nArg = pTab->nModuleArg; | ||
349 | char *zErr = 0; | ||
350 | char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); | ||
351 | |||
352 | if( !zModuleName ){ | ||
353 | return SQLITE_NOMEM; | ||
354 | } | ||
355 | |||
356 | assert( !db->pVTab ); | ||
357 | assert( xConstruct ); | ||
358 | |||
359 | db->pVTab = pTab; | ||
360 | rc = sqlite3SafetyOff(db); | ||
361 | assert( rc==SQLITE_OK ); | ||
362 | rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVtab, &zErr); | ||
363 | rc2 = sqlite3SafetyOn(db); | ||
364 | if( rc==SQLITE_OK && pVtab ){ | ||
365 | pVtab->pModule = pMod->pModule; | ||
366 | pVtab->nRef = 1; | ||
367 | pTab->pVtab = pVtab; | ||
368 | } | ||
369 | |||
370 | if( SQLITE_OK!=rc ){ | ||
371 | if( zErr==0 ){ | ||
372 | *pzErr = sqlite3MPrintf(db, "vtable constructor failed: %s", zModuleName); | ||
373 | }else { | ||
374 | *pzErr = sqlite3MPrintf(db, "%s", zErr); | ||
375 | sqlite3_free(zErr); | ||
376 | } | ||
377 | }else if( db->pVTab ){ | ||
378 | const char *zFormat = "vtable constructor did not declare schema: %s"; | ||
379 | *pzErr = sqlite3MPrintf(db, zFormat, pTab->zName); | ||
380 | rc = SQLITE_ERROR; | ||
381 | } | ||
382 | if( rc==SQLITE_OK ){ | ||
383 | rc = rc2; | ||
384 | } | ||
385 | db->pVTab = 0; | ||
386 | sqlite3_free(zModuleName); | ||
387 | |||
388 | /* If everything went according to plan, loop through the columns | ||
389 | ** of the table to see if any of them contain the token "hidden". | ||
390 | ** If so, set the Column.isHidden flag and remove the token from | ||
391 | ** the type string. | ||
392 | */ | ||
393 | if( rc==SQLITE_OK ){ | ||
394 | int iCol; | ||
395 | for(iCol=0; iCol<pTab->nCol; iCol++){ | ||
396 | char *zType = pTab->aCol[iCol].zType; | ||
397 | int nType; | ||
398 | int i = 0; | ||
399 | if( !zType ) continue; | ||
400 | nType = strlen(zType); | ||
401 | if( sqlite3StrNICmp("hidden", zType, 6) || (zType[6] && zType[6]!=' ') ){ | ||
402 | for(i=0; i<nType; i++){ | ||
403 | if( (0==sqlite3StrNICmp(" hidden", &zType[i], 7)) | ||
404 | && (zType[i+7]=='\0' || zType[i+7]==' ') | ||
405 | ){ | ||
406 | i++; | ||
407 | break; | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | if( i<nType ){ | ||
412 | int j; | ||
413 | int nDel = 6 + (zType[i+6] ? 1 : 0); | ||
414 | for(j=i; (j+nDel)<=nType; j++){ | ||
415 | zType[j] = zType[j+nDel]; | ||
416 | } | ||
417 | if( zType[i]=='\0' && i>0 ){ | ||
418 | assert(zType[i-1]==' '); | ||
419 | zType[i-1] = '\0'; | ||
420 | } | ||
421 | pTab->aCol[iCol].isHidden = 1; | ||
422 | } | ||
423 | } | ||
424 | } | ||
425 | return rc; | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | ** This function is invoked by the parser to call the xConnect() method | ||
430 | ** of the virtual table pTab. If an error occurs, an error code is returned | ||
431 | ** and an error left in pParse. | ||
432 | ** | ||
433 | ** This call is a no-op if table pTab is not a virtual table. | ||
434 | */ | ||
435 | int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){ | ||
436 | Module *pMod; | ||
437 | int rc = SQLITE_OK; | ||
438 | |||
439 | if( !pTab || !pTab->isVirtual || pTab->pVtab ){ | ||
440 | return SQLITE_OK; | ||
441 | } | ||
442 | |||
443 | pMod = pTab->pMod; | ||
444 | if( !pMod ){ | ||
445 | const char *zModule = pTab->azModuleArg[0]; | ||
446 | sqlite3ErrorMsg(pParse, "no such module: %s", zModule); | ||
447 | rc = SQLITE_ERROR; | ||
448 | } else { | ||
449 | char *zErr = 0; | ||
450 | sqlite3 *db = pParse->db; | ||
451 | rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xConnect, &zErr); | ||
452 | if( rc!=SQLITE_OK ){ | ||
453 | sqlite3ErrorMsg(pParse, "%s", zErr); | ||
454 | } | ||
455 | sqlite3_free(zErr); | ||
456 | } | ||
457 | |||
458 | return rc; | ||
459 | } | ||
460 | |||
461 | /* | ||
462 | ** Add the virtual table pVtab to the array sqlite3.aVTrans[]. | ||
463 | */ | ||
464 | static int addToVTrans(sqlite3 *db, sqlite3_vtab *pVtab){ | ||
465 | const int ARRAY_INCR = 5; | ||
466 | |||
467 | /* Grow the sqlite3.aVTrans array if required */ | ||
468 | if( (db->nVTrans%ARRAY_INCR)==0 ){ | ||
469 | sqlite3_vtab **aVTrans; | ||
470 | int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); | ||
471 | aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); | ||
472 | if( !aVTrans ){ | ||
473 | return SQLITE_NOMEM; | ||
474 | } | ||
475 | memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); | ||
476 | db->aVTrans = aVTrans; | ||
477 | } | ||
478 | |||
479 | /* Add pVtab to the end of sqlite3.aVTrans */ | ||
480 | db->aVTrans[db->nVTrans++] = pVtab; | ||
481 | sqlite3VtabLock(pVtab); | ||
482 | return SQLITE_OK; | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | ** This function is invoked by the vdbe to call the xCreate method | ||
487 | ** of the virtual table named zTab in database iDb. | ||
488 | ** | ||
489 | ** If an error occurs, *pzErr is set to point an an English language | ||
490 | ** description of the error and an SQLITE_XXX error code is returned. | ||
491 | ** In this case the caller must call sqlite3_free() on *pzErr. | ||
492 | */ | ||
493 | int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ | ||
494 | int rc = SQLITE_OK; | ||
495 | Table *pTab; | ||
496 | Module *pMod; | ||
497 | const char *zModule; | ||
498 | |||
499 | pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); | ||
500 | assert(pTab && pTab->isVirtual && !pTab->pVtab); | ||
501 | pMod = pTab->pMod; | ||
502 | zModule = pTab->azModuleArg[0]; | ||
503 | |||
504 | /* If the module has been registered and includes a Create method, | ||
505 | ** invoke it now. If the module has not been registered, return an | ||
506 | ** error. Otherwise, do nothing. | ||
507 | */ | ||
508 | if( !pMod ){ | ||
509 | *pzErr = sqlite3MPrintf(db, "no such module: %s", zModule); | ||
510 | rc = SQLITE_ERROR; | ||
511 | }else{ | ||
512 | rc = vtabCallConstructor(db, pTab, pMod, pMod->pModule->xCreate, pzErr); | ||
513 | } | ||
514 | |||
515 | if( rc==SQLITE_OK && pTab->pVtab ){ | ||
516 | rc = addToVTrans(db, pTab->pVtab); | ||
517 | } | ||
518 | |||
519 | return rc; | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | ** This function is used to set the schema of a virtual table. It is only | ||
524 | ** valid to call this function from within the xCreate() or xConnect() of a | ||
525 | ** virtual table module. | ||
526 | */ | ||
527 | int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ | ||
528 | Parse sParse; | ||
529 | |||
530 | int rc = SQLITE_OK; | ||
531 | Table *pTab; | ||
532 | char *zErr = 0; | ||
533 | |||
534 | sqlite3_mutex_enter(db->mutex); | ||
535 | pTab = db->pVTab; | ||
536 | if( !pTab ){ | ||
537 | sqlite3Error(db, SQLITE_MISUSE, 0); | ||
538 | sqlite3_mutex_leave(db->mutex); | ||
539 | return SQLITE_MISUSE; | ||
540 | } | ||
541 | assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0); | ||
542 | |||
543 | memset(&sParse, 0, sizeof(Parse)); | ||
544 | sParse.declareVtab = 1; | ||
545 | sParse.db = db; | ||
546 | |||
547 | if( | ||
548 | SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) && | ||
549 | sParse.pNewTable && | ||
550 | !sParse.pNewTable->pSelect && | ||
551 | !sParse.pNewTable->isVirtual | ||
552 | ){ | ||
553 | pTab->aCol = sParse.pNewTable->aCol; | ||
554 | pTab->nCol = sParse.pNewTable->nCol; | ||
555 | sParse.pNewTable->nCol = 0; | ||
556 | sParse.pNewTable->aCol = 0; | ||
557 | db->pVTab = 0; | ||
558 | } else { | ||
559 | sqlite3Error(db, SQLITE_ERROR, zErr); | ||
560 | sqlite3_free(zErr); | ||
561 | rc = SQLITE_ERROR; | ||
562 | } | ||
563 | sParse.declareVtab = 0; | ||
564 | |||
565 | sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe); | ||
566 | sqlite3DeleteTable(sParse.pNewTable); | ||
567 | sParse.pNewTable = 0; | ||
568 | |||
569 | assert( (rc&0xff)==rc ); | ||
570 | rc = sqlite3ApiExit(db, rc); | ||
571 | sqlite3_mutex_leave(db->mutex); | ||
572 | return rc; | ||
573 | } | ||
574 | |||
575 | /* | ||
576 | ** This function is invoked by the vdbe to call the xDestroy method | ||
577 | ** of the virtual table named zTab in database iDb. This occurs | ||
578 | ** when a DROP TABLE is mentioned. | ||
579 | ** | ||
580 | ** This call is a no-op if zTab is not a virtual table. | ||
581 | */ | ||
582 | int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab) | ||
583 | { | ||
584 | int rc = SQLITE_OK; | ||
585 | Table *pTab; | ||
586 | |||
587 | pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); | ||
588 | assert(pTab); | ||
589 | if( pTab->pVtab ){ | ||
590 | int (*xDestroy)(sqlite3_vtab *pVTab) = pTab->pMod->pModule->xDestroy; | ||
591 | rc = sqlite3SafetyOff(db); | ||
592 | assert( rc==SQLITE_OK ); | ||
593 | if( xDestroy ){ | ||
594 | rc = xDestroy(pTab->pVtab); | ||
595 | } | ||
596 | sqlite3SafetyOn(db); | ||
597 | if( rc==SQLITE_OK ){ | ||
598 | pTab->pVtab = 0; | ||
599 | } | ||
600 | } | ||
601 | |||
602 | return rc; | ||
603 | } | ||
604 | |||
605 | /* | ||
606 | ** This function invokes either the xRollback or xCommit method | ||
607 | ** of each of the virtual tables in the sqlite3.aVTrans array. The method | ||
608 | ** called is identified by the second argument, "offset", which is | ||
609 | ** the offset of the method to call in the sqlite3_module structure. | ||
610 | ** | ||
611 | ** The array is cleared after invoking the callbacks. | ||
612 | */ | ||
613 | static void callFinaliser(sqlite3 *db, int offset){ | ||
614 | int i; | ||
615 | if( db->aVTrans ){ | ||
616 | for(i=0; i<db->nVTrans && db->aVTrans[i]; i++){ | ||
617 | sqlite3_vtab *pVtab = db->aVTrans[i]; | ||
618 | int (*x)(sqlite3_vtab *); | ||
619 | x = *(int (**)(sqlite3_vtab *))((char *)pVtab->pModule + offset); | ||
620 | if( x ) x(pVtab); | ||
621 | sqlite3VtabUnlock(db, pVtab); | ||
622 | } | ||
623 | sqlite3_free(db->aVTrans); | ||
624 | db->nVTrans = 0; | ||
625 | db->aVTrans = 0; | ||
626 | } | ||
627 | } | ||
628 | |||
629 | /* | ||
630 | ** If argument rc2 is not SQLITE_OK, then return it and do nothing. | ||
631 | ** Otherwise, invoke the xSync method of all virtual tables in the | ||
632 | ** sqlite3.aVTrans array. Return the error code for the first error | ||
633 | ** that occurs, or SQLITE_OK if all xSync operations are successful. | ||
634 | */ | ||
635 | int sqlite3VtabSync(sqlite3 *db, int rc2){ | ||
636 | int i; | ||
637 | int rc = SQLITE_OK; | ||
638 | int rcsafety; | ||
639 | sqlite3_vtab **aVTrans = db->aVTrans; | ||
640 | if( rc2!=SQLITE_OK ) return rc2; | ||
641 | |||
642 | rc = sqlite3SafetyOff(db); | ||
643 | db->aVTrans = 0; | ||
644 | for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){ | ||
645 | sqlite3_vtab *pVtab = aVTrans[i]; | ||
646 | int (*x)(sqlite3_vtab *); | ||
647 | x = pVtab->pModule->xSync; | ||
648 | if( x ){ | ||
649 | rc = x(pVtab); | ||
650 | } | ||
651 | } | ||
652 | db->aVTrans = aVTrans; | ||
653 | rcsafety = sqlite3SafetyOn(db); | ||
654 | |||
655 | if( rc==SQLITE_OK ){ | ||
656 | rc = rcsafety; | ||
657 | } | ||
658 | return rc; | ||
659 | } | ||
660 | |||
661 | /* | ||
662 | ** Invoke the xRollback method of all virtual tables in the | ||
663 | ** sqlite3.aVTrans array. Then clear the array itself. | ||
664 | */ | ||
665 | int sqlite3VtabRollback(sqlite3 *db){ | ||
666 | callFinaliser(db, (int)(&((sqlite3_module *)0)->xRollback)); | ||
667 | return SQLITE_OK; | ||
668 | } | ||
669 | |||
670 | /* | ||
671 | ** Invoke the xCommit method of all virtual tables in the | ||
672 | ** sqlite3.aVTrans array. Then clear the array itself. | ||
673 | */ | ||
674 | int sqlite3VtabCommit(sqlite3 *db){ | ||
675 | callFinaliser(db, (int)(&((sqlite3_module *)0)->xCommit)); | ||
676 | return SQLITE_OK; | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | ** If the virtual table pVtab supports the transaction interface | ||
681 | ** (xBegin/xRollback/xCommit and optionally xSync) and a transaction is | ||
682 | ** not currently open, invoke the xBegin method now. | ||
683 | ** | ||
684 | ** If the xBegin call is successful, place the sqlite3_vtab pointer | ||
685 | ** in the sqlite3.aVTrans array. | ||
686 | */ | ||
687 | int sqlite3VtabBegin(sqlite3 *db, sqlite3_vtab *pVtab){ | ||
688 | int rc = SQLITE_OK; | ||
689 | const sqlite3_module *pModule; | ||
690 | |||
691 | /* Special case: If db->aVTrans is NULL and db->nVTrans is greater | ||
692 | ** than zero, then this function is being called from within a | ||
693 | ** virtual module xSync() callback. It is illegal to write to | ||
694 | ** virtual module tables in this case, so return SQLITE_LOCKED. | ||
695 | */ | ||
696 | if( 0==db->aVTrans && db->nVTrans>0 ){ | ||
697 | return SQLITE_LOCKED; | ||
698 | } | ||
699 | if( !pVtab ){ | ||
700 | return SQLITE_OK; | ||
701 | } | ||
702 | pModule = pVtab->pModule; | ||
703 | |||
704 | if( pModule->xBegin ){ | ||
705 | int i; | ||
706 | |||
707 | |||
708 | /* If pVtab is already in the aVTrans array, return early */ | ||
709 | for(i=0; (i<db->nVTrans) && 0!=db->aVTrans[i]; i++){ | ||
710 | if( db->aVTrans[i]==pVtab ){ | ||
711 | return SQLITE_OK; | ||
712 | } | ||
713 | } | ||
714 | |||
715 | /* Invoke the xBegin method */ | ||
716 | rc = pModule->xBegin(pVtab); | ||
717 | if( rc!=SQLITE_OK ){ | ||
718 | return rc; | ||
719 | } | ||
720 | |||
721 | rc = addToVTrans(db, pVtab); | ||
722 | } | ||
723 | return rc; | ||
724 | } | ||
725 | |||
726 | /* | ||
727 | ** The first parameter (pDef) is a function implementation. The | ||
728 | ** second parameter (pExpr) is the first argument to this function. | ||
729 | ** If pExpr is a column in a virtual table, then let the virtual | ||
730 | ** table implementation have an opportunity to overload the function. | ||
731 | ** | ||
732 | ** This routine is used to allow virtual table implementations to | ||
733 | ** overload MATCH, LIKE, GLOB, and REGEXP operators. | ||
734 | ** | ||
735 | ** Return either the pDef argument (indicating no change) or a | ||
736 | ** new FuncDef structure that is marked as ephemeral using the | ||
737 | ** SQLITE_FUNC_EPHEM flag. | ||
738 | */ | ||
739 | FuncDef *sqlite3VtabOverloadFunction( | ||
740 | sqlite3 *db, /* Database connection for reporting malloc problems */ | ||
741 | FuncDef *pDef, /* Function to possibly overload */ | ||
742 | int nArg, /* Number of arguments to the function */ | ||
743 | Expr *pExpr /* First argument to the function */ | ||
744 | ){ | ||
745 | Table *pTab; | ||
746 | sqlite3_vtab *pVtab; | ||
747 | sqlite3_module *pMod; | ||
748 | void (*xFunc)(sqlite3_context*,int,sqlite3_value**); | ||
749 | void *pArg; | ||
750 | FuncDef *pNew; | ||
751 | int rc = 0; | ||
752 | char *zLowerName; | ||
753 | unsigned char *z; | ||
754 | |||
755 | |||
756 | /* Check to see the left operand is a column in a virtual table */ | ||
757 | if( pExpr==0 ) return pDef; | ||
758 | if( pExpr->op!=TK_COLUMN ) return pDef; | ||
759 | pTab = pExpr->pTab; | ||
760 | if( pTab==0 ) return pDef; | ||
761 | if( !pTab->isVirtual ) return pDef; | ||
762 | pVtab = pTab->pVtab; | ||
763 | assert( pVtab!=0 ); | ||
764 | assert( pVtab->pModule!=0 ); | ||
765 | pMod = (sqlite3_module *)pVtab->pModule; | ||
766 | if( pMod->xFindFunction==0 ) return pDef; | ||
767 | |||
768 | /* Call the xFindFunction method on the virtual table implementation | ||
769 | ** to see if the implementation wants to overload this function | ||
770 | */ | ||
771 | zLowerName = sqlite3DbStrDup(db, pDef->zName); | ||
772 | if( zLowerName ){ | ||
773 | for(z=(unsigned char*)zLowerName; *z; z++){ | ||
774 | *z = sqlite3UpperToLower[*z]; | ||
775 | } | ||
776 | rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg); | ||
777 | sqlite3_free(zLowerName); | ||
778 | } | ||
779 | if( rc==0 ){ | ||
780 | return pDef; | ||
781 | } | ||
782 | |||
783 | /* Create a new ephemeral function definition for the overloaded | ||
784 | ** function */ | ||
785 | pNew = sqlite3DbMallocZero(db, sizeof(*pNew) + strlen(pDef->zName) ); | ||
786 | if( pNew==0 ){ | ||
787 | return pDef; | ||
788 | } | ||
789 | *pNew = *pDef; | ||
790 | memcpy(pNew->zName, pDef->zName, strlen(pDef->zName)+1); | ||
791 | pNew->xFunc = xFunc; | ||
792 | pNew->pUserData = pArg; | ||
793 | pNew->flags |= SQLITE_FUNC_EPHEM; | ||
794 | return pNew; | ||
795 | } | ||
796 | |||
797 | #endif /* SQLITE_OMIT_VIRTUALTABLE */ | ||