2
|
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.cpp 1282 2008-11-13 09:31:33Z LarsPson $
|
|
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 |
EXPORT_C 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 |
EXPORT_C 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 = (char**)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 = (Table*)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 = (sqlite3_vtab**)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 |
EXPORT_C 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 = (FuncDef*)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 */
|