From: danielk1977 Date: Mon, 12 Jun 2006 06:09:17 +0000 (+0000) Subject: Incremental work on parsing/storing and invoking the xCreate callback for virtual... X-Git-Tag: version-3.6.10~2955 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=78efaba10e4568817e5b75bcdfd4f599677e94c9;p=thirdparty%2Fsqlite.git Incremental work on parsing/storing and invoking the xCreate callback for virtual tables. (CVS 3212) FossilOrigin-Name: 8ffbab79d5a76dea0f87cf551d5b6ad4f0fab337 --- diff --git a/manifest b/manifest index 6a0c4f192a..823fad00db 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Progress\stoward\sCREATE\sVIRTUAL\sTABLE.\s\sStill\snot\seven\sclose\sto\sworking...\s(CVS\s3211) -D 2006-06-11T23:41:55 +C Incremental\swork\son\sparsing/storing\sand\sinvoking\sthe\sxCreate\scallback\sfor\svirtual\stables.\s(CVS\s3212) +D 2006-06-12T06:09:18 F Makefile.in 56fd6261e83f60724e6dcd764e06ab68cbd53909 F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -66,7 +66,7 @@ F src/pager.c ddd05666bb89808a516baef2c186d6a75887ae90 F src/pager.h 43f32f3847421f7502cfbb66f4eb2302b8033818 F src/parse.y 05cd1419b625df99ea9776e2c767d2a792d84345 F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55 -F src/prepare.c bbf12d3147116b284b157232efaef3bbe5df08fc +F src/prepare.c 6dc945dab34cf97364c661d2b7a12be65d338267 F src/printf.c 7029e5f7344a478394a02c52837ff296ee1ab240 F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261 F src/select.c 38eda11d950ed5e631ea9054f84a4a8b9e9b39d8 @@ -74,7 +74,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c b9eb3ed4d3ab41fbf630eabb602f3c9d20fc737a F src/sqlite.h.in ca30260d7815ee68be410e1fa0bd1f131c86cf10 F src/sqlite3ext.h 127bd394c8eea481f2ac9b754bf399dbfc818b75 -F src/sqliteInt.h 90957da628f83fa7d57c35b239573496642393c0 +F src/sqliteInt.h 4ac8c35fec748b1886bed00f1086fa2520faea80 F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e F src/tclsqlite.c 0b2a04cfc1b4298adfbe90a754cfbbe207aca11a F src/test1.c 88291fa6674dcd409b1c9d76d3119151d4b81a50 @@ -84,7 +84,7 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25 F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3 -F src/test8.c 210f2109333e3373a1cb814e22e7b6b33e1e0a20 +F src/test8.c c1a91a3307e4d8d8a46211498111d1c5778b9294 F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3 F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3 F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c @@ -94,14 +94,14 @@ F src/update.c 0186f09414a6578156d40666becc964f85c2a616 F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44 F src/util.c ca6ee72772c0f5dc04d2e0ab1973fd3b6a9bf79d F src/vacuum.c 5b37d0f436f8e1ffacd17934e44720b38d2247f9 -F src/vdbe.c 2547e931baf0f35cc8df77fdb18004a9f987bc6a +F src/vdbe.c 5c77e8b57c07e7776ec34df8088749c639bbfe7c F src/vdbe.h 190d85a37658c2397be75a4c70bbc02ebc4ec0ba F src/vdbeInt.h 85cd5f81d38edb1b8f4786f407c77a7a3ba636fb F src/vdbeapi.c 7dc662e7c905ce666bb506dced932e0307115cbf F src/vdbeaux.c 4002e6b19d7c9719cb81f9797316b9ad118e4370 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3 -F src/vtab.c 4ace1448bdba6a13d93c7642aa66447f8a5cd63c +F src/vtab.c 6872f6a6ca33aac85b62bcd66d883f4deffab00d F src/where.c 3dc5269ba552c0db39247f6bbc98b312ae786863 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -287,7 +287,7 @@ F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102 F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5 -F test/vtab1.test 9029c3ef19f1db3eebb2554b4db12e04b39a30ca +F test/vtab1.test 5bf2bebe96272953928596b256cefb21d9c765b1 F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394 F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa @@ -363,7 +363,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P 66370cb99bd93abb33e1e8433672da45e1795f78 -R 9ff37f743d5a6a690e7a66e29bc79ec5 -U drh -Z 6146abfd990542c70d1912af93fdb676 +P 898ec36b4102aaa03979f8f5c510936e57e2ae48 +R fd0d79bfdfee01e76c00d486659426af +U danielk1977 +Z 21ad209dbac4dc09cf972c3f2b10f101 diff --git a/manifest.uuid b/manifest.uuid index cb8e1fd491..adbc054d49 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -898ec36b4102aaa03979f8f5c510936e57e2ae48 \ No newline at end of file +8ffbab79d5a76dea0f87cf551d5b6ad4f0fab337 \ No newline at end of file diff --git a/src/prepare.c b/src/prepare.c index 582cff0861..d4c752a7c6 100644 --- a/src/prepare.c +++ b/src/prepare.c @@ -13,7 +13,7 @@ ** interface, and routines that contribute to loading the database schema ** from disk. ** -** $Id: prepare.c,v 1.34 2006/05/23 23:22:29 drh Exp $ +** $Id: prepare.c,v 1.35 2006/06/12 06:09:18 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -38,7 +38,7 @@ static void corruptSchema(InitData *pData, const char *zExtra){ ** Each callback contains the following information: ** ** argv[0] = name of thing being created -** argv[1] = root page number for table or index. NULL for trigger or view. +** 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. diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 9a2de48755..de904fb3b9 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.497 2006/06/11 23:41:56 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.498 2006/06/12 06:09:18 danielk1977 Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1790,6 +1790,7 @@ 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" diff --git a/src/test8.c b/src/test8.c index c0d08a4695..97e8483460 100644 --- a/src/test8.c +++ b/src/test8.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test8.c,v 1.1 2006/06/11 23:41:56 drh Exp $ +** $Id: test8.c,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -21,6 +21,15 @@ #include #include +/* +** 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, @@ -32,11 +41,11 @@ static int echoCreate( Tcl_Interp *interp = pModule->pAux; *ppVtab = pModule->pAux; - Tcl_SetVar(interp, "echo_module", "xCreate", TCL_GLOBAL_ONLY); + appendToEchoModule(pModule, "xCreate"); for(i=0; ip1, pOp->p3, &p->zErrMsg); break; } #endif /* SQLITE_OMIT_VIRTUALTABLE */ @@ -4547,7 +4548,7 @@ case OP_VCreate: { #ifndef SQLITE_OMIT_VIRTUALTABLE /* Opcode: VDestroy * * P3 ** -** P3 is the name of a virtual table. Call the xCreate method for +** P3 is the name of a virtual table. Call the xDestroy method for ** that table. */ case OP_VDestroy: { diff --git a/src/vtab.c b/src/vtab.c index d7d7515bd0..bd43e567ce 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.1 2006/06/11 23:41:56 drh Exp $ +** $Id: vtab.c,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" @@ -81,7 +81,14 @@ void sqlite3VtabBeginParse( ){ Table *pTable; /* The new virtual table */ - sqlite3StartTable(pParse, pName1, pName2, 0, 0, 0); + /* 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; @@ -134,6 +141,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ */ if( !db->init.busy ){ char *zStmt; + char *zWhere; int iDb; Vdbe *v; if( pTab->pModule==0 ){ @@ -148,14 +156,18 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ /* 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 rowid for the preallocated - ** slot is the top the stack. + ** 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=NULL, sql=%Q " - "WHERE rowid=#0", + "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, @@ -163,18 +175,36 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ ); sqliteFree(zStmt); v = sqlite3GetVdbe(pParse); - sqlite3VdbeOp3(v, OP_VCreate, 0, 0, pTab->zName, P3_DYNAMIC); 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 and we happen to - ** currently know the module for the new table, create an - ** sqlite3_vtab instance. + /* 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( pTab->pModule ){ + 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; + } } } @@ -208,4 +238,42 @@ void sqlite3VtabArgExtend(Parse *pParse, Token *p){ 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 */ diff --git a/test/vtab1.test b/test/vtab1.test index 18e034f159..84e20048bf 100644 --- a/test/vtab1.test +++ b/test/vtab1.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is creating and dropping virtual tables. # -# $Id: vtab1.test,v 1.1 2006/06/11 23:41:56 drh Exp $ +# $Id: vtab1.test,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -35,7 +35,6 @@ do_test vtab1-1.2 { # do_test vtab1-1.3 { register_echo_module [sqlite3_connection_pointer db] -execsql {pragma vdbe_listing=on; pragma vdbe_trace=on} catchsql { CREATE VIRTUAL TABLE t1 USING echo; } @@ -49,5 +48,4 @@ do_test vtab1-1.5 { } } {t1 {CREATE VIRTUAL TABLE t1 USING echo}} - finish_test