aboutsummaryrefslogtreecommitdiff
path: root/src/vtab.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/vtab.c')
-rw-r--r--src/vtab.c107
1 files changed, 96 insertions, 11 deletions
diff --git a/src/vtab.c b/src/vtab.c
index bd43e567c..ae7b7930f 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to help implement virtual tables.
**
-** $Id: vtab.c,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $
+** $Id: vtab.c,v 1.3 2006/06/12 11:24:37 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"
@@ -128,7 +128,6 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
if( pTab==0 ) return;
db = pParse->db;
if( pTab->nModuleArg<1 ) return;
- pParse->pNewTable = 0;
zModule = pTab->azModuleArg[0];
pTab->pModule = (sqlite3_module*)sqlite3HashFind(&db->aModule,
zModule, strlen(zModule));
@@ -188,14 +187,10 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
**
** TODO: If the module is already registered, should we call xConnect()
** here, or should it wait until the table is first referenced. Maybe
- ** it's better to be lazy here, in case xConnect() is expensive to call.
+ ** it's better to be lazy here, in case xConnect() is expensive to call
+ ** and the schema is reparsed a number of times.
*/
else {
-#if 0
- sqlite3_module *pMod = pTab->pModule;
- assert( pMod->xConnect );
- pMod->xConnect(db, pMod, pTab->nModuleArg, pTab->azModuleArg, &pTab->pVtab);
-#endif
Table *pOld;
Schema *pSchema = pTab->pSchema;
const char *zName = pTab->zName;
@@ -205,6 +200,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
return;
}
+ pParse->pNewTable = 0;
}
}
@@ -239,6 +235,84 @@ void sqlite3VtabArgExtend(Parse *pParse, Token *p){
}
/*
+** This function is invoked by the parser to call the xConnect() method
+** of table pTab. If an error occurs, an error code is returned and an error
+** left in pParse.
+*/
+int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
+ sqlite3_module *pModule;
+ const char *zModule;
+ int rc = SQLITE_OK;
+
+ assert(pTab && pTab->isVirtual);
+ if( pTab->pVtab ){
+ return SQLITE_OK;
+ }
+
+ pModule = pTab->pModule;
+ zModule = pTab->azModuleArg[0];
+ if( !pModule || !pModule->xConnect ){
+ const char *zModule = pTab->azModuleArg[0];
+ sqlite3ErrorMsg(pParse, "unknown module: %s", zModule);
+ rc = SQLITE_ERROR;
+ } else {
+ char **azArg = pTab->azModuleArg;
+ int nArg = pTab->nModuleArg;
+ assert( !pParse->db->pVTab );
+ pParse->db->pVTab = pTab;
+ rc = pModule->xConnect(pParse->db, pModule, nArg, azArg, &pTab->pVtab);
+ pParse->db->pVTab = 0;
+ if( rc ){
+ sqlite3ErrorMsg(pParse, "module connect failed: %s", zModule);
+ }
+ }
+
+ return rc;
+}
+
+int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
+ Parse sParse;
+
+ int rc = SQLITE_OK;
+ Table *pTab = db->pVTab;
+ char *zErr = 0;
+
+ if( !pTab ){
+ sqlite3Error(db, SQLITE_MISUSE, 0);
+ return SQLITE_MISUSE;
+ }
+ assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
+
+ memset(&sParse, 0, sizeof(Parse));
+ sParse.declareVtab = 1;
+ sParse.db = db;
+
+ if(
+ SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) &&
+ sParse.pNewTable &&
+ !sParse.pNewTable->pSelect &&
+ !sParse.pNewTable->isVirtual
+ ){
+ pTab->aCol = sParse.pNewTable->aCol;
+ pTab->nCol = sParse.pNewTable->nCol;
+ sParse.pNewTable->nCol = 0;
+ sParse.pNewTable->aCol = 0;
+ } else {
+ sqlite3Error(db, SQLITE_ERROR, zErr);
+ sqliteFree(zErr);
+ rc = SQLITE_ERROR;
+ }
+ sParse.declareVtab = 0;
+
+ sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
+ sqlite3DeleteTable(0, sParse.pNewTable);
+ sParse.pNewTable = 0;
+ db->pVTab = 0;
+
+ return rc;
+}
+
+/*
** This function is invoked by the vdbe to call the xCreate method
** of the virtual table named zTab in database iDb.
**
@@ -250,11 +324,12 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
int rc = SQLITE_OK;
Table *pTab;
sqlite3_module *pModule;
+ const char *zModule;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
- assert(pTab && pTab->isVirtual);
+ assert(pTab && pTab->isVirtual && !pTab->pVtab);
pModule = pTab->pModule;
- const char *zModule = pTab->azModuleArg[0];
+ zModule = pTab->azModuleArg[0];
/* If the module has been registered and includes a Create method,
** invoke it now. If the module has not been registered, return an
@@ -264,10 +339,20 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
*pzErr = sqlite3MPrintf("unknown module: %s", zModule);
rc = SQLITE_ERROR;
}else if( pModule->xCreate ){
- /* TODO: Maybe the above condition should refer to pTable->needCreate. */
char **azArg = pTab->azModuleArg;
int nArg = pTab->nModuleArg;
+ assert( !db->pVTab );
+ db->pVTab = pTab;
+ rc = sqlite3SafetyOff(db);
+ assert( rc==SQLITE_OK );
rc = pModule->xCreate(db, pModule, nArg, azArg, &pTab->pVtab);
+ db->pVTab = 0;
+ if( rc ){
+ *pzErr = sqlite3MPrintf("module create failed: %s", zModule);
+ sqlite3SafetyOn(db);
+ } else {
+ rc = sqlite3SafetyOn(db);
+ }
}
if( SQLITE_OK==rc ){