Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Incremental work on parsing/storing and invoking the xCreate callback for virtual tables. (CVS 3212) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
8ffbab79d5a76dea0f87cf551d5b6ad4 |
User & Date: | danielk1977 2006-06-12 06:09:18.000 |
Context
2006-06-12
| ||
11:24 | Add first cut of sqlite3_declare_vtab(). Not at all well tested yet. (CVS 3213) (check-in: bbeb93b5bb user: danielk1977 tags: trunk) | |
06:09 | Incremental work on parsing/storing and invoking the xCreate callback for virtual tables. (CVS 3212) (check-in: 8ffbab79d5 user: danielk1977 tags: trunk) | |
2006-06-11
| ||
23:41 | Progress toward CREATE VIRTUAL TABLE. Still not even close to working... (CVS 3211) (check-in: 898ec36b41 user: drh tags: trunk) | |
Changes
Changes to src/prepare.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** ** $Id: prepare.c,v 1.35 2006/06/12 06:09:18 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** Fill the InitData structure with an error message that indicates |
︙ | ︙ | |||
34 35 36 37 38 39 40 | ** This is the callback routine for the code that initializes the ** database. See sqlite3Init() below for additional information. ** This routine is also called from the OP_ParseSchema opcode of the VDBE. ** ** Each callback contains the following information: ** ** argv[0] = name of thing being created | | | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | ** This is the callback routine for the code that initializes the ** database. See sqlite3Init() below for additional information. ** This routine is also called from the OP_ParseSchema opcode of the VDBE. ** ** Each callback contains the following information: ** ** argv[0] = name of thing being created ** argv[1] = root page number for table or index. 0 for trigger or view. ** argv[2] = SQL text for the CREATE statement. ** argv[3] = "1" for temporary files, "0" for main database, "2" or more ** for auxiliary database files. ** */ int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){ InitData *pData = (InitData*)pInit; |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.498 2006/06/12 06:09:18 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Extra interface definitions for those who need them */ |
︙ | ︙ | |||
1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 | #else void sqlite3VtabClear(Table*); #endif void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*); void sqlite3VtabFinishParse(Parse*, Token*); void sqlite3VtabArgInit(Parse*); void sqlite3VtabArgExtend(Parse*, Token*); #ifdef SQLITE_SSE #include "sseInt.h" #endif #endif | > | 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 | #else void sqlite3VtabClear(Table*); #endif void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*); void sqlite3VtabFinishParse(Parse*, Token*); void sqlite3VtabArgInit(Parse*); void sqlite3VtabArgExtend(Parse*, Token*); int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **); #ifdef SQLITE_SSE #include "sseInt.h" #endif #endif |
Changes to src/test8.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the virtual table interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | > > > > > > > > > | | < > | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the virtual table interfaces. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test8.c,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include "os.h" #include <stdlib.h> #include <string.h> /* ** Global Tcl variable $echo_module is a list. This routine appends ** the string element zArg to that list in interpreter interp. */ static void appendToEchoModule(const sqlite3_module *pModule, const char *zArg){ int flags = (TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY); Tcl_SetVar((Tcl_Interp *)(pModule->pAux), "echo_module", zArg, flags); } /* Methods for the echo module */ static int echoCreate( sqlite3 *db, const sqlite3_module *pModule, int argc, char **argv, sqlite3_vtab **ppVtab ){ int i; Tcl_Interp *interp = pModule->pAux; *ppVtab = pModule->pAux; appendToEchoModule(pModule, "xCreate"); for(i=0; i<argc; i++){ appendToEchoModule(pModule, argv[i]); } return 0; } static int echoConnect( sqlite3 *db, const sqlite3_module *pModule, int argc, char **argv, sqlite3_vtab **ppVtab |
︙ | ︙ | |||
70 71 72 73 74 75 76 | } /* ** A virtual table module that merely echos method calls into TCL ** variables. */ static sqlite3_module echoModule = { | | | | | | 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | } /* ** A virtual table module that merely echos method calls into TCL ** variables. */ static sqlite3_module echoModule = { 0, /* iVersion */ "echo", /* zName */ 0, /* pAux */ echoCreate, echoConnect, 0, /* xBestIndex */ echoDisconnect, echoDestroy, }; /* ** Decode a pointer to an sqlite3 object. */ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
39 40 41 42 43 44 45 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** | | | 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 | ** ** Various scripts scan this source file in order to generate HTML ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** ** $Id: vdbe.c,v 1.552 2006/06/12 06:09:19 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include "vdbeInt.h" /* |
︙ | ︙ | |||
4530 4531 4532 4533 4534 4535 4536 | sqlite3SetString(&p->zErrMsg, "database table is locked: ", z, (char*)0); } break; } #endif /* SQLITE_OMIT_SHARED_CACHE */ #ifndef SQLITE_OMIT_VIRTUALTABLE | | | | > | | 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 | sqlite3SetString(&p->zErrMsg, "database table is locked: ", z, (char*)0); } break; } #endif /* SQLITE_OMIT_SHARED_CACHE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VCreate P1 * P3 ** ** P3 is the name of a virtual table in database P1. Call the xCreate method ** for that table. */ case OP_VCreate: { rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p3, &p->zErrMsg); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VDestroy * * P3 ** ** P3 is the name of a virtual table. Call the xDestroy method for ** that table. */ case OP_VDestroy: { break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
︙ | ︙ |
Changes to src/vtab.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2006 June 10 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to help implement virtual tables. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2006 June 10 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains code used to help implement virtual tables. ** ** $Id: vtab.c,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" /* ** External API function used to create a new virtual-table module. */ |
︙ | ︙ | |||
77 78 79 80 81 82 83 | Parse *pParse, /* Parsing context */ Token *pName1, /* Name of new table, or database name */ Token *pName2, /* Name of new table or NULL */ Token *pModuleName /* Name of the module for the virtual table */ ){ Table *pTable; /* The new virtual table */ | > > > > > > | > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 | Parse *pParse, /* Parsing context */ Token *pName1, /* Name of new table, or database name */ Token *pName2, /* Name of new table or NULL */ Token *pModuleName /* Name of the module for the virtual table */ ){ Table *pTable; /* The new virtual table */ /* TODO: The 5th argument to sqlite3StartTable() - isView - is being ** passed a true value at present. This prevents sqlite3StartTable() ** from coding OP_CreateTable, which is correct, but causes it ** to invoke the authorization function as if a CREATE VIEW statement ** were attempted, which is incorrect. */ sqlite3StartTable(pParse, pName1, pName2, 0, 1, 0); pTable = pParse->pNewTable; if( pTable==0 ) return; pTable->isVirtual = 1; pTable->nModuleArg = 0; addModuleArgument(pTable, sqlite3NameFromToken(pModuleName)); pParse->sNameToken.n = pModuleName->z + pModuleName->n - pName1->z; } |
︙ | ︙ | |||
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | ** first time (in other words if the virtual table is actually being ** created now instead of just being read out of sqlite_master) then ** do additional initialization work and store the statement text ** in the sqlite_master table. */ if( !db->init.busy ){ char *zStmt; int iDb; Vdbe *v; if( pTab->pModule==0 ){ sqlite3ErrorMsg(pParse, "unknown module: %s", zModule); } /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ if( pEnd ){ pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n; } zStmt = sqlite3MPrintf("CREATE VIRTUAL TABLE %T", &pParse->sNameToken); /* A slot for the record has already been allocated in the ** SQLITE_MASTER table. We just need to update that slot with all | > | > > > > | | | < | > > > > | > | | | > > > | > > > > > > > > > > > | 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 | ** first time (in other words if the virtual table is actually being ** created now instead of just being read out of sqlite_master) then ** do additional initialization work and store the statement text ** in the sqlite_master table. */ if( !db->init.busy ){ char *zStmt; char *zWhere; int iDb; Vdbe *v; if( pTab->pModule==0 ){ sqlite3ErrorMsg(pParse, "unknown module: %s", zModule); } /* Compute the complete text of the CREATE VIRTUAL TABLE statement */ if( pEnd ){ pParse->sNameToken.n = pEnd->z - pParse->sNameToken.z + pEnd->n; } zStmt = sqlite3MPrintf("CREATE VIRTUAL TABLE %T", &pParse->sNameToken); /* A slot for the record has already been allocated in the ** SQLITE_MASTER table. We just need to update that slot with all ** the information we've collected. ** ** The top of the stack is the rootpage allocated by sqlite3StartTable(). ** This value is always 0 and is ignored, a virtual table does not have a ** rootpage. The next entry on the stack is the rowid of the record ** in the sqlite_master table. */ iDb = sqlite3SchemaToIndex(db, pTab->pSchema); sqlite3NestedParse(pParse, "UPDATE %Q.%s " "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " "WHERE rowid=#1", db->aDb[iDb].zName, SCHEMA_TABLE(iDb), pTab->zName, pTab->zName, zStmt ); sqliteFree(zStmt); v = sqlite3GetVdbe(pParse); sqlite3ChangeCookie(db, v, iDb); sqlite3VdbeAddOp(v, OP_Expire, 0, 0); zWhere = sqlite3MPrintf("name='%q'", pTab->zName); sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC); sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1); } /* If we are rereading the sqlite_master table create the in-memory ** record of the table. ** ** 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. */ 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; int nName = strlen(zName) + 1; pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab); if( pOld ){ assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ return; } } } /* ** The parser calls this routine when it sees the first token ** of an argument to the module name in a CREATE VIRTUAL TABLE statement. */ |
︙ | ︙ | |||
203 204 205 206 207 208 209 210 211 | if( pParse->nArgUsed ){ pParse->zArg[pParse->nArgUsed++] = ' '; } memcpy(&pParse->zArg[pParse->nArgUsed], p->z, p->n); pParse->nArgUsed += p->n; pParse->zArg[pParse->nArgUsed] = 0; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | if( pParse->nArgUsed ){ pParse->zArg[pParse->nArgUsed++] = ' '; } memcpy(&pParse->zArg[pParse->nArgUsed], p->z, p->n); pParse->nArgUsed += p->n; pParse->zArg[pParse->nArgUsed] = 0; } /* ** This function is invoked by the vdbe to call the xCreate method ** of the virtual table named zTab in database iDb. ** ** If an error occurs, *pzErr is set to point an an English language ** description of the error and an SQLITE_XXX error code is returned. ** In this case the caller must call sqliteFree() on *pzErr. */ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ int rc = SQLITE_OK; Table *pTab; sqlite3_module *pModule; pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); assert(pTab && pTab->isVirtual); pModule = pTab->pModule; const char *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 ** error. Otherwise, do nothing. */ if( !pModule ){ *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; rc = pModule->xCreate(db, pModule, nArg, azArg, &pTab->pVtab); } if( SQLITE_OK==rc ){ pTab->needCreate = 0; } return rc; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ |
Changes to test/vtab1.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2006 June 10 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is creating and dropping virtual tables. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2006 June 10 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is creating and dropping virtual tables. # # $Id: vtab1.test,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # We cannot create a virtual table if the module has not # been registered. # |
︙ | ︙ | |||
31 32 33 34 35 36 37 | } {} # After we register the echo module, we are allowed to create # virtual tables using that module. # do_test vtab1-1.3 { register_echo_module [sqlite3_connection_pointer db] | < < | 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | } {} # After we register the echo module, we are allowed to create # virtual tables using that module. # do_test vtab1-1.3 { register_echo_module [sqlite3_connection_pointer db] catchsql { CREATE VIRTUAL TABLE t1 USING echo; } } {0 {}} do_test vtab1-1.4 { set echo_module } {xCreate echo} do_test vtab1-1.5 { execsql { SELECT name, sql FROM sqlite_master ORDER BY 1 } } {t1 {CREATE VIRTUAL TABLE t1 USING echo}} finish_test |