select.lo table.lo tokenize.lo trigger.lo update.lo \
util.lo vacuum.lo \
vdbe.lo vdbeapi.lo vdbeaux.lo vdbefifo.lo vdbemem.lo \
- where.lo utf.lo legacy.lo
+ where.lo utf.lo legacy.lo vtab.lo
# All of the source code files.
#
$(TOP)/src/vdbefifo.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/vdbeInt.h \
+ $(TOP)/src/vtab.c \
$(TOP)/src/where.c
# Source code to the test files.
$(TOP)/src/test5.c \
$(TOP)/src/test6.c \
$(TOP)/src/test7.c \
+ $(TOP)/src/test8.c \
$(TOP)/src/test_async.c \
$(TOP)/src/test_md5.c \
$(TOP)/src/test_server.c \
vdbemem.lo: $(TOP)/src/vdbemem.c $(VDBEHDR)
$(LTCOMPILE) -c $(TOP)/src/vdbemem.c
+vtab.lo: $(TOP)/src/vtab.c $(VDBEHDR)
+ $(LTCOMPILE) -c $(TOP)/src/vtab.c
+
where.lo: $(TOP)/src/where.c $(HDR)
$(LTCOMPILE) -c $(TOP)/src/where.c
select.o table.o tclsqlite.o tokenize.o trigger.o \
update.o util.o vacuum.o \
vdbe.o vdbeapi.o vdbeaux.o vdbefifo.o vdbemem.o \
- where.o utf.o legacy.o
+ where.o utf.o legacy.o vtab.o
# All of the source code files.
#
$(TOP)/src/vdbefifo.c \
$(TOP)/src/vdbemem.c \
$(TOP)/src/vdbeInt.h \
+ $(TOP)/src/vtab.c \
$(TOP)/src/where.c
# Source code to the test files.
$(TOP)/src/test5.c \
$(TOP)/src/test6.c \
$(TOP)/src/test7.c \
+ $(TOP)/src/test8.c \
$(TOP)/src/test_async.c \
$(TOP)/src/test_md5.c \
$(TOP)/src/test_server.c \
vdbemem.o: $(TOP)/src/vdbemem.c $(VDBEHDR)
$(TCCX) -c $(TOP)/src/vdbemem.c
+vtab.o: $(TOP)/src/vtab.c $(VDBEHDR)
+ $(TCCX) -c $(TOP)/src/vtab.c
+
where.o: $(TOP)/src/where.c $(HDR)
$(TCCX) -c $(TOP)/src/where.c
-C Basic\sparsing\sof\sCREATE\sVIRTUAL\sTABLE\sstatements.\s(CVS\s3210)
-D 2006-06-10T13:29:32
-F Makefile.in 50d948a8c4eda30ebb5799b661bd4c2de11824d0
+C Progress\stoward\sCREATE\sVIRTUAL\sTABLE.\s\sStill\snot\seven\sclose\sto\sworking...\s(CVS\s3211)
+D 2006-06-11T23:41:55
+F Makefile.in 56fd6261e83f60724e6dcd764e06ab68cbd53909
F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F VERSION 301ed2b2c08f5cca242ea56e50a9ed0264a3eb76
F doc/report1.txt a031aaf37b185e4fa540223cb516d3bccec7eeac
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895
F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
-F main.mk 9a328281e0d992dcbbf502ec868793dca0a1d7b9
+F main.mk a7796b31f0d7e16ea57ff00ac88b97befe519977
F mkdll.sh 919df5efde876194e3102c6ebc60657d38949909
F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
F mkopcodeh.awk cde995d269aa06c94adbf6455bea0acedb913fa5
F src/auth.c 9ae84d2d94eb96195e04515715e08e85963e96c2
F src/btree.c ed343b3dbcbc7da9ac481ef2b98c4239fe6d9629
F src/btree.h 40055cfc09defd1146bc5b922399c035f969e56d
-F src/build.c a64e4765ca1148e191742af306db5b70d821d0c9
+F src/build.c f541d3e9afed5eb8a397353b2b54c23d8d531e97
F src/callback.c fd9bb39f7ff6b52bad8365617abc61c720640429
F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675
F src/date.c cd2bd5d1ebc6fa12d6312f69789ae5b0a2766f2e
-F src/delete.c 2dea1a83e6ef534346e74fd03114d3a7b16f08fc
+F src/delete.c f9a8c7837adb4bb4810a698a041a88d5ec7bfa9a
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c f1ad18d0b7bb3abbf09cb30871ae6e7618447bc5
+F src/expr.c 3ea9b26c6cdb7bcf0715c1b6aa0f7f5e813f61eb
F src/func.c acbbf533b55221f26760798d99b37de3ac5678fe
F src/hash.c 449f3d6620193aa557f5d86cbc5cc6b87702b185
F src/hash.h 1b3f7e2609141fd571f62199fc38687d262e9564
-F src/insert.c 1ae4b8ff5549497808e1b57b9243abcb599fd02f
+F src/insert.c 2c3eeb4bcde13c1006824ef14953c2fdad31cf36
F src/legacy.c fa15d505dd4e45044177ee4d1c6aeaf8c836d390
F src/loadext.c 528a3c130ca32b83609593605ebeec235de4e55b
-F src/main.c 0147dbf7ba04563749aef77ef709b78dd86d6771
+F src/main.c f4397bf95216496e49db2153789788f4b1207b91
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
F src/os.c 59f05de8c5777c34876607114a2fbe55ae578235
F src/os.h 46fad85c707ad8643622bab9d894a642940850aa
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c ddd05666bb89808a516baef2c186d6a75887ae90
F src/pager.h 43f32f3847421f7502cfbb66f4eb2302b8033818
-F src/parse.y 79c324627c8145d307a80a13fb18be1d1d63dff8
+F src/parse.y 05cd1419b625df99ea9776e2c767d2a792d84345
F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55
F src/prepare.c bbf12d3147116b284b157232efaef3bbe5df08fc
F src/printf.c 7029e5f7344a478394a02c52837ff296ee1ab240
F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
-F src/select.c 8daba07a04a6d41f5267ea8353324cbe5a210e14
+F src/select.c 38eda11d950ed5e631ea9054f84a4a8b9e9b39d8
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c b9eb3ed4d3ab41fbf630eabb602f3c9d20fc737a
-F src/sqlite.h.in fadc690a16e8da1215d3f4bdf6a2501e41516c25
+F src/sqlite.h.in ca30260d7815ee68be410e1fa0bd1f131c86cf10
F src/sqlite3ext.h 127bd394c8eea481f2ac9b754bf399dbfc818b75
-F src/sqliteInt.h c1c752970e90570750be529d9d22111211614381
+F src/sqliteInt.h 90957da628f83fa7d57c35b239573496642393c0
F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e
-F src/tclsqlite.c 5ae9f08f7af7fe80d38fbccc4f5359f272643af1
-F src/test1.c becd9202b733debc607b5aec43002769730e1f71
+F src/tclsqlite.c 0b2a04cfc1b4298adfbe90a754cfbbe207aca11a
+F src/test1.c 88291fa6674dcd409b1c9d76d3119151d4b81a50
F src/test2.c ca74a1d8aeb7d9606e8f6b762c5daf85c1a3f92b
F src/test3.c 86e99724ee898b119ed575ef9f98618afe7e5e5d
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/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c
-F src/tokenize.c 91dc520980c0e2fb9265046adf8b7a86eff881dd
+F src/tokenize.c 279c62792222e0ae6efc4f7609bc47301dde1ef3
F src/trigger.c 48bbb94c11954c8e132efcc04478efe8304c4196
-F src/update.c 34add66fcd3301b33b6e4c4c813f4e408f7ee4a0
+F src/update.c 0186f09414a6578156d40666becc964f85c2a616
F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44
F src/util.c ca6ee72772c0f5dc04d2e0ab1973fd3b6a9bf79d
F src/vacuum.c 5b37d0f436f8e1ffacd17934e44720b38d2247f9
-F src/vdbe.c a4c970bd74a5af20bf4627f704a634ceff8ff68d
-F src/vdbe.h 44ff995a8b4e87016794095273e9e7300f0001bb
+F src/vdbe.c 2547e931baf0f35cc8df77fdb18004a9f987bc6a
+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/where.c 06ec443109d8aec7be6d491ef31f72bc08af2c75
+F src/vtab.c 4ace1448bdba6a13d93c7642aa66447f8a5cd63c
+F src/where.c 3dc5269ba552c0db39247f6bbc98b312ae786863
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/all.test 5df90d015ca63fcef2a4b62c24f7316b66c4bfd4
F test/index.test e65df12bed94b2903ee89987115e1578687e9266
F test/index2.test ee83c6b5e3173a3d7137140d945d9a5d4fdfb9d6
F test/index3.test f66718cd92ce1216819d47e6a156755e4b2c4ca1
-F test/insert.test b4d43f8e75e203fe51bc06cacf3636081903dcd1
+F test/insert.test 42e26d9192f36859938765e6817fb957cf19532b
F test/insert2.test 5a20e1ace5fa0800b58d28284212290189b49aed
F test/insert3.test 0096bd9766f94f4fa06ef712658e590b782cb44f
F test/interrupt.test cd24dc5bedd02325be4bfa5d6209fae01c465157
F test/select3.test 33c78663e6b1b41220dcec4eb6affb1a05001ffe
F test/select4.test d0280e3b6d760d1cff0fcc2a65ecb0611aec3df2
F test/select5.test 0b47058d3e916c1fc9fe81f44b438e02bade21ce
-F test/select6.test d8ea108b65607399580f2765df0aee5e464b0fd8
+F test/select6.test a4e97b713b096f17414f50d078ec4efe7dc43253
F test/select7.test 1bf795b948c133a15a2a5e99d3270e652ec58ce6
F test/server1.test e328b8e641ba8fe9273132cfef497383185dc1f5
F test/shared.test 0ed247941236788c255b3b29b5a82d5ca71b6432
F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f
F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
-F test/view.test b0aeb933cc9dc5bb44d87f3859f3763d770f0153
+F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
+F test/vtab1.test 9029c3ef19f1db3eebb2554b4db12e04b39a30ca
F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P 39e3427813135601a7417c96e55b410fa89ac1f5
-R ca50c82454da9812f6118b6e9d547ee0
+P 66370cb99bd93abb33e1e8433672da45e1795f78
+R 9ff37f743d5a6a690e7a66e29bc79ec5
U drh
-Z 20f490cb0723888395733c25c97f6fa4
+Z 6146abfd990542c70d1912af93fdb676
-66370cb99bd93abb33e1e8433672da45e1795f78
\ No newline at end of file
+898ec36b4102aaa03979f8f5c510936e57e2ae48
\ No newline at end of file
** COMMIT
** ROLLBACK
**
-** $Id: build.c,v 1.395 2006/06/10 13:29:32 drh Exp $
+** $Id: build.c,v 1.396 2006/06/11 23:41:55 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#ifndef SQLITE_OMIT_CHECK
sqlite3ExprDelete(pTable->pCheck);
#endif
-#ifndef SQLITE_OMIT_MODULE
- sqliteFree(pTable->zModuleName);
- if( pTable->pMod && pTable->pVTab ){
- pTable->pMod->xDisconnect(pTable->pVTab);
- }
-#endif SQLITE_OMIT_MODULE
+ sqlite3VtabClear(pTable);
sqliteFree(pTable);
}
goto begin_table_error;
}
pTable->zName = zName;
- pTable->nCol = 0;
- pTable->aCol = 0;
pTable->iPKey = -1;
- pTable->pIndex = 0;
pTable->pSchema = db->aDb[iDb].pSchema;
pTable->nRef = 1;
if( pParse->pNewTable ) sqlite3DeleteTable(db, pParse->pNewTable);
assert( !db->init.busy || !pSelect );
- iDb = sqlite3SchemaToIndex(pParse->db, p->pSchema);
+ iDb = sqlite3SchemaToIndex(db, p->pSchema);
#ifndef SQLITE_OMIT_CHECK
/* Resolve names in all CHECK constraint expressions.
/* Remove the table entry from SQLite's internal schema and modify
** the schema cookie.
*/
- sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ if( pTab->isEphem ){
+ sqlite3VdbeOp3(v, OP_VDestroy, iDb, 0, pTab->zName, 0);
+ }else
+#endif
+ {
+ sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
+ }
sqlite3ChangeCookie(db, v, iDb);
}
sqliteViewResetAll(db, iDb);
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
-** $Id: delete.c,v 1.122 2006/02/24 02:53:50 drh Exp $
+** $Id: delete.c,v 1.123 2006/06/11 23:41:55 drh Exp $
*/
#include "sqliteInt.h"
*/
if( isView ){
Select *pView = sqlite3SelectDup(pTab->pSelect);
- sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
+ sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
-** $Id: expr.c,v 1.258 2006/05/23 23:22:29 drh Exp $
+** $Id: expr.c,v 1.259 2006/06/11 23:41:55 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
pNew->iOffset = -1;
pNew->isResolved = p->isResolved;
pNew->isAgg = p->isAgg;
- pNew->usesVirt = 0;
+ pNew->usesEphm = 0;
pNew->disallowOrderBy = 0;
pNew->pRightmost = 0;
- pNew->addrOpenVirt[0] = -1;
- pNew->addrOpenVirt[1] = -1;
- pNew->addrOpenVirt[2] = -1;
+ pNew->addrOpenEphm[0] = -1;
+ pNew->addrOpenEphm[1] = -1;
+ pNew->addrOpenEphm[2] = -1;
return pNew;
}
#else
case TK_IN: {
char affinity;
KeyInfo keyInfo;
- int addr; /* Address of OP_OpenVirtual instruction */
+ int addr; /* Address of OP_OpenEphemeral instruction */
affinity = sqlite3ExprAffinity(pExpr->pLeft);
** is used.
*/
pExpr->iTable = pParse->nTab++;
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, pExpr->iTable, 0);
+ addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, pExpr->iTable, 0);
memset(&keyInfo, 0, sizeof(keyInfo));
keyInfo.nField = 1;
sqlite3VdbeAddOp(v, OP_SetNumColumns, pExpr->iTable, 1);
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
-** $Id: insert.c,v 1.164 2006/03/15 16:26:10 drh Exp $
+** $Id: insert.c,v 1.165 2006/06/11 23:41:55 drh Exp $
*/
#include "sqliteInt.h"
** back up and execute the SELECT code above.
*/
sqlite3VdbeJumpHere(v, iInitCode);
- sqlite3VdbeAddOp(v, OP_OpenVirtual, srcTab, 0);
+ sqlite3VdbeAddOp(v, OP_OpenEphemeral, srcTab, 0);
sqlite3VdbeAddOp(v, OP_SetNumColumns, srcTab, nColumn);
sqlite3VdbeAddOp(v, OP_Goto, 0, iSelectLoop);
sqlite3VdbeResolveLabel(v, iCleanup);
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.341 2006/06/08 15:48:01 drh Exp $
+** $Id: main.c,v 1.342 2006/06/11 23:41:55 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
sqliteFree(pColl);
}
sqlite3HashClear(&db->aCollSeq);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlite3HashClear(&db->aModule);
+#endif
sqlite3HashClear(&db->aFunc);
sqlite3Error(db, SQLITE_OK, 0); /* Deallocates any cached error strings. */
db->flags |= SQLITE_ShortColNames;
sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0);
sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0);
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlite3HashInit(&db->aModule, SQLITE_HASH_STRING, 0);
+#endif
/* Add the default collation sequence BINARY. BINARY works for both UTF-8
** and UTF-16, so add a version for each to avoid any unnecessary
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.201 2006/06/10 13:29:33 drh Exp $
+** @(#) $Id: parse.y,v 1.202 2006/06/11 23:41:55 drh Exp $
*/
// All token codes are small integers with #defines that begin with "TK_"
//////////////////////// CREATE VIRTUAL TABLE ... /////////////////////////////
%ifndef SQLITE_OMIT_VIRTUALTABLE
-cmd ::= CREATE VIRTUAL TABLE nm(X) dbnm(Y) USING nm(Z) vtabargsopt.
-vtabargsopt ::= .
-vtabargsopt ::= LP vtabarglist RP.
+cmd ::= create_vtab. {sqlite3VtabFinishParse(pParse,0);}
+cmd ::= create_vtab LP vtabarglist RP(X). {sqlite3VtabFinishParse(pParse,&X);}
+create_vtab ::= CREATE VIRTUAL TABLE nm(X) dbnm(Y) USING nm(Z). {
+ sqlite3VtabBeginParse(pParse, &X, &Y, &Z);
+}
vtabarglist ::= vtabarg.
vtabarglist ::= vtabarglist COMMA vtabarg.
-vtabarg ::= ANY.
-vtabarg ::= vtabarg ANY.
+vtabarg ::= . {sqlite3VtabArgInit(pParse);}
+vtabarg ::= vtabarg vtabargtoken.
+vtabargtoken ::= ANY(X). {sqlite3VtabArgExtend(pParse,&X);}
+vtabargtoken ::= lp anylist RP(X). {sqlite3VtabArgExtend(pParse,&X);}
+lp ::= LP(X). {sqlite3VtabArgExtend(pParse,&X);}
+anylist ::= .
+anylist ::= anylist ANY(X). {sqlite3VtabArgExtend(pParse,&X);}
%endif
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.313 2006/04/26 17:39:34 drh Exp $
+** $Id: select.c,v 1.314 2006/06/11 23:41:56 drh Exp $
*/
#include "sqliteInt.h"
pNew->pOffset = pOffset;
pNew->iLimit = -1;
pNew->iOffset = -1;
- pNew->addrOpenVirt[0] = -1;
- pNew->addrOpenVirt[1] = -1;
- pNew->addrOpenVirt[2] = -1;
+ pNew->addrOpenEphm[0] = -1;
+ pNew->addrOpenEphm[1] = -1;
+ pNew->addrOpenEphm[2] = -1;
if( pNew==&standin) {
clearSelect(pNew);
pNew = 0;
/* Store the result as data using a unique key.
*/
case SRT_Table:
- case SRT_VirtualTab: {
+ case SRT_EphemTab: {
sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);
if( pOrderBy ){
pushOntoSorter(pParse, pOrderBy, p);
sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1);
switch( eDest ){
case SRT_Table:
- case SRT_VirtualTab: {
+ case SRT_EphemTab: {
sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);
if( pTab==0 ){
return 1;
}
- /* The isTransient flag indicates that the Table structure has been
+ /* The isEphem flag indicates that the Table structure has been
** dynamically allocated and may be freed at any time. In other words,
** pTab is not pointing to a persistent table structure that defines
** part of the schema. */
- pTab->isTransient = 1;
+ pTab->isEphem = 1;
#endif
}else{
/* An ordinary table or view name in the FROM clause */
int addr;
assert( pOrderBy->iECursor==0 );
pOrderBy->iECursor = pParse->nTab++;
- addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenVirtual,
+ addr = sqlite3VdbeAddOp(pParse->pVdbe, OP_OpenEphemeral,
pOrderBy->iECursor, pOrderBy->nExpr+1);
- assert( p->addrOpenVirt[2] == -1 );
- p->addrOpenVirt[2] = addr;
+ assert( p->addrOpenEphm[2] == -1 );
+ p->addrOpenEphm[2] = addr;
}
}
/* Create the destination temporary table if necessary
*/
- if( eDest==SRT_VirtualTab ){
+ if( eDest==SRT_EphemTab ){
assert( p->pEList );
assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) );
- aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 0);
+ aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 0);
eDest = SRT_Table;
}
rc = 1;
goto multi_select_end;
}
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, unionTab, 0);
+ addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, unionTab, 0);
if( priorOp==SRT_Table ){
assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) );
aSetP2[nSetP2++] = addr;
}else{
- assert( p->addrOpenVirt[0] == -1 );
- p->addrOpenVirt[0] = addr;
- p->pRightmost->usesVirt = 1;
+ assert( p->addrOpenEphm[0] == -1 );
+ p->addrOpenEphm[0] = addr;
+ p->pRightmost->usesEphm = 1;
}
createSortingIndex(pParse, p, pOrderBy);
assert( p->pEList );
}
createSortingIndex(pParse, p, pOrderBy);
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab1, 0);
- assert( p->addrOpenVirt[0] == -1 );
- p->addrOpenVirt[0] = addr;
- p->pRightmost->usesVirt = 1;
+ addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab1, 0);
+ assert( p->addrOpenEphm[0] == -1 );
+ p->addrOpenEphm[0] = addr;
+ p->pRightmost->usesEphm = 1;
assert( p->pEList );
/* Code the SELECTs to our left into temporary table "tab1".
/* Code the current SELECT into temporary table "tab2"
*/
- addr = sqlite3VdbeAddOp(v, OP_OpenVirtual, tab2, 0);
- assert( p->addrOpenVirt[1] == -1 );
- p->addrOpenVirt[1] = addr;
+ addr = sqlite3VdbeAddOp(v, OP_OpenEphemeral, tab2, 0);
+ assert( p->addrOpenEphm[1] == -1 );
+ p->addrOpenEphm[1] = addr;
p->pPrior = 0;
pLimit = p->pLimit;
p->pLimit = 0;
** SELECT might also skip this part if it has no ORDER BY clause and
** no temp tables are required.
*/
- if( pOrderBy || p->usesVirt ){
+ if( pOrderBy || p->usesEphm ){
int i; /* Loop counter */
KeyInfo *pKeyInfo; /* Collating sequence for the result set */
Select *pLoop; /* For looping through SELECT statements */
for(pLoop=p; pLoop; pLoop=pLoop->pPrior){
for(i=0; i<2; i++){
- int addr = pLoop->addrOpenVirt[i];
+ int addr = pLoop->addrOpenEphm[i];
if( addr<0 ){
/* If [0] is unused then [1] is also unused. So we can
** always safely abort as soon as the first unused slot is found */
- assert( pLoop->addrOpenVirt[1]<0 );
+ assert( pLoop->addrOpenEphm[1]<0 );
break;
}
sqlite3VdbeChangeP2(v, addr, nCol);
*pSortOrder = pOTerm->sortOrder;
}
assert( p->pRightmost==p );
- assert( p->addrOpenVirt[2]>=0 );
- addr = p->addrOpenVirt[2];
+ assert( p->addrOpenEphm[2]>=0 );
+ addr = p->addrOpenEphm[2];
sqlite3VdbeChangeP2(v, addr, p->pEList->nExpr+2);
pKeyInfo->nField = nOrderByExpr;
sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
/* If the output is destined for a temporary table, open that table.
*/
- if( eDest==SRT_VirtualTab ){
- sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, 1);
+ if( eDest==SRT_EphemTab ){
+ sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 1);
}
/* Generating code to find the min or the max. Basically all we have
** or last entry in the main table.
*/
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- assert( iDb>=0 || pTab->isTransient );
+ assert( iDb>=0 || pTab->isEphem );
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName);
base = pSrc->a[0].iCursor;
pFunc->iDistinct = -1;
}else{
KeyInfo *pKeyInfo = keyInfoFromExprList(pParse, pE->pList);
- sqlite3VdbeOp3(v, OP_OpenVirtual, pFunc->iDistinct, 0,
+ sqlite3VdbeOp3(v, OP_OpenEphemeral, pFunc->iDistinct, 0,
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
}
}
int isDistinct; /* True if the DISTINCT keyword is present */
int distinct; /* Table to use for the distinct set */
int rc = 1; /* Value to return from this function */
- int addrSortIndex; /* Address of an OP_OpenVirtual instruction */
+ int addrSortIndex; /* Address of an OP_OpenEphemeral instruction */
AggInfo sAggInfo; /* Information used by aggregate queries */
int iEnd; /* Address of the end of the query */
}else{
needRestoreContext = 0;
}
- sqlite3Select(pParse, pItem->pSelect, SRT_VirtualTab,
+ sqlite3Select(pParse, pItem->pSelect, SRT_EphemTab,
pItem->iCursor, p, i, &isAgg, 0);
if( needRestoreContext ){
pParse->zAuthContext = zSavedAuthContext;
**
** This sorting index might end up being unused if the data can be
** extracted in pre-sorted order. If that is the case, then the
- ** OP_OpenVirtual instruction will be changed to an OP_Noop once
+ ** OP_OpenEphemeral instruction will be changed to an OP_Noop once
** we figure out that the sorting index is not needed. The addrSortIndex
** variable is used to facilitate that change.
*/
}
pKeyInfo = keyInfoFromExprList(pParse, pOrderBy);
pOrderBy->iECursor = pParse->nTab++;
- p->addrOpenVirt[2] = addrSortIndex =
- sqlite3VdbeOp3(v, OP_OpenVirtual, pOrderBy->iECursor, pOrderBy->nExpr+2,
+ p->addrOpenEphm[2] = addrSortIndex =
+ sqlite3VdbeOp3(v, OP_OpenEphemeral, pOrderBy->iECursor, pOrderBy->nExpr+2,
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
}else{
addrSortIndex = -1;
/* If the output is destined for a temporary table, open that table.
*/
- if( eDest==SRT_VirtualTab ){
- sqlite3VdbeAddOp(v, OP_OpenVirtual, iParm, pEList->nExpr);
+ if( eDest==SRT_EphemTab ){
+ sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, pEList->nExpr);
}
/* Set the limiter.
KeyInfo *pKeyInfo;
distinct = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
- sqlite3VdbeOp3(v, OP_OpenVirtual, distinct, 0,
+ sqlite3VdbeOp3(v, OP_OpenEphemeral, distinct, 0,
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
}else{
distinct = -1;
pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pOrderBy);
if( pWInfo==0 ) goto select_end;
- /* If sorting index that was created by a prior OP_OpenVirtual
- ** instruction ended up not being needed, then change the OP_OpenVirtual
+ /* If sorting index that was created by a prior OP_OpenEphemeral
+ ** instruction ended up not being needed, then change the OP_OpenEphemeral
** into an OP_Noop.
*/
if( addrSortIndex>=0 && pOrderBy==0 ){
sqlite3VdbeChangeToNoop(v, addrSortIndex, 1);
- p->addrOpenVirt[2] = -1;
+ p->addrOpenEphm[2] = -1;
}
/* Use the standard inner loop
int addrGroupByChange; /* Code that runs when any GROUP BY term changes */
int addrProcessRow; /* Code to process a single input row */
int addrEnd; /* End of all processing */
- int addrSortingIdx; /* The OP_OpenVirtual for the sorting index */
+ int addrSortingIdx; /* The OP_OpenEphemeral for the sorting index */
int addrReset; /* Subroutine for resetting the accumulator */
addrEnd = sqlite3VdbeMakeLabel(v);
/* If there is a GROUP BY clause we might need a sorting index to
** implement it. Allocate that sorting index now. If it turns out
- ** that we do not need it after all, the OpenVirtual instruction
+ ** that we do not need it after all, the OpenEphemeral instruction
** will be converted into a Noop.
*/
sAggInfo.sortingIdx = pParse->nTab++;
pKeyInfo = keyInfoFromExprList(pParse, pGroupBy);
addrSortingIdx =
- sqlite3VdbeOp3(v, OP_OpenVirtual, sAggInfo.sortingIdx,
+ sqlite3VdbeOp3(v, OP_OpenEphemeral, sAggInfo.sortingIdx,
sAggInfo.nSortingColumn,
(char*)pKeyInfo, P3_KEYINFO_HANDOFF);
if( pWInfo==0 ) goto select_end;
if( pGroupBy==0 ){
/* The optimizer is able to deliver rows in group by order so
- ** we do not have to sort. The OP_OpenVirtual table will be
+ ** we do not have to sort. The OP_OpenEphemeral table will be
** cancelled later because we still need to use the pKeyInfo
*/
pGroupBy = p->pGroupBy;
** This header file defines the interface that the SQLite library
** presents to client programs.
**
-** @(#) $Id: sqlite.h.in,v 1.167 2006/06/10 13:29:33 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.168 2006/06/11 23:41:56 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
typedef struct sqlite3_module sqlite3_module;
struct sqlite3_module {
int iVersion;
+ const char *zName;
void *pAux;
int (*xCreate)(sqlite3*, const sqlite3_module *pModule,
int argc, char **argv,
#define SQLITE_INDEX_CONSTRAINT_LT 5
#define SQLITE_INDEX_CONSTRAINT_GE 6
#define SQLITE_INDEX_CONSTRAINT_MATCH 7
+int sqlite3_create_module(
+ sqlite3 *db,
+ const char *zName,
+ const sqlite3_module *
+);
/*
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.496 2006/06/10 13:29:33 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.497 2006/06/11 23:41:56 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
void *pProgressArg; /* Argument to the progress callback */
int nProgressOps; /* Number of opcodes for progress callback */
#endif
-#ifndef SQLITE_OMIT_GLOBALRECOVER
- sqlite3 *pNext; /* Linked list of open db handles. */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ Hash aModule; /* populated by sqlite3_create_module() */
#endif
Hash aFunc; /* All functions that can be in SQL exprs */
Hash aCollSeq; /* All collating sequences */
BusyHandler busyHandler; /* Busy callback */
- int busyTimeout; /* Busy handler timeout, in msec */
+ int busyTimeout; /* Busy handler timeout, in msec */
Db aDbStatic[2]; /* Static space for the 2 default backends */
#ifdef SQLITE_SSE
sqlite3_stmt *pFetch; /* Used by SSE to fetch stored statements */
** Table.tnum is the page number for the root BTree page of the table in the
** database file. If Table.iDb is the index of the database table backend
** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
-** holds temporary tables and indices. If Table.isTransient
+** holds temporary tables and indices. If Table.isEphem
** is true, then the table is stored in a file that is automatically deleted
** when the VDBE cursor to the table is closed. In this case Table.tnum
** refers VDBE cursor number that holds the table open, not to the root
int tnum; /* Root BTree node for this table (see note above) */
Select *pSelect; /* NULL for tables. Points to definition if a view. */
u8 readOnly; /* True if this table should not be written by the user */
- u8 isTransient; /* True if automatically deleted when VDBE finishes */
+ u8 isEphem; /* True if created using OP_OpenEphermeral */
u8 hasPrimKey; /* True if there exists a primary key */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
u8 autoInc; /* True if the integer primary key is autoincrement */
int addColOffset; /* Offset in CREATE TABLE statement to add a new column */
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
- char *zModuleName; /* Name of module implementing this virtual table */
- sqlite3_module *pMod; /* Pointer to the implementation of the module */
- sqlite3_vtab *pVTab; /* Pointer to the module instance */
- u8 needCreate; /* Need to call pMod->xCreate() */
+ sqlite3_module *pModule; /* Pointer to the implementation of the module */
+ sqlite3_vtab *pVtab; /* Pointer to the module instance */
+ int nModuleArg; /* Number of arguments to the module */
+ char **azModuleArg; /* Text of all module args. [0] is module name */
+ u8 needCreate; /* Need to call pMod->xCreate() */
+ u8 isVirtual; /* True if this is a virtual table */
#endif
Schema *pSchema;
};
Expr *pExpr; /* Expression encoding the function */
FuncDef *pFunc; /* The aggregate function implementation */
int iMem; /* Memory location that acts as accumulator */
- int iDistinct; /* Virtual table used to enforce DISTINCT */
+ int iDistinct; /* Ephermeral table used to enforce DISTINCT */
} *aFunc;
int nFunc; /* Number of entries in aFunc[] */
int nFuncAlloc; /* Number of slots allocated for aFunc[] */
** offset). But later on, nLimit and nOffset become the memory locations
** in the VDBE that record the limit and offset counters.
**
-** addrOpenVirt[] entries contain the address of OP_OpenVirtual opcodes.
+** addrOpenEphm[] entries contain the address of OP_OpenEphemeral opcodes.
** These addresses must be stored so that we can go back and fill in
** the P3_KEYINFO and P2 parameters later. Neither the KeyInfo nor
** the number of columns in P2 can be computed at the same time
-** as the OP_OpenVirtual instruction is coded because not
+** as the OP_OpenEphm instruction is coded because not
** enough information about the compound query is known at that point.
-** The KeyInfo for addrOpenVirt[0] and [1] contains collating sequences
-** for the result set. The KeyInfo for addrOpenVirt[2] contains collating
+** The KeyInfo for addrOpenTran[0] and [1] contains collating sequences
+** for the result set. The KeyInfo for addrOpenTran[2] contains collating
** sequences for the ORDER BY clause.
*/
struct Select {
u8 isDistinct; /* True if the DISTINCT keyword is present */
u8 isResolved; /* True once sqlite3SelectResolve() has run. */
u8 isAgg; /* True if this is an aggregate query */
- u8 usesVirt; /* True if uses an OpenVirtual opcode */
+ u8 usesEphm; /* True if uses an OpenEphemeral opcode */
u8 disallowOrderBy; /* Do not allow an ORDER BY to be attached if TRUE */
SrcList *pSrc; /* The FROM clause */
Expr *pWhere; /* The WHERE clause */
Expr *pLimit; /* LIMIT expression. NULL means not used. */
Expr *pOffset; /* OFFSET expression. NULL means not used. */
int iLimit, iOffset; /* Memory registers holding LIMIT & OFFSET counters */
- int addrOpenVirt[3]; /* OP_OpenVirtual opcodes related to this select */
+ int addrOpenEphm[3]; /* OP_OpenEphem opcodes related to this select */
};
/*
#define SRT_Mem 5 /* Store result in a memory cell */
#define SRT_Set 6 /* Store non-null results as keys in an index */
#define SRT_Table 7 /* Store result as data with an automatic rowid */
-#define SRT_VirtualTab 8 /* Create virtual table and store like SRT_Table */
+#define SRT_EphemTab 8 /* Create transient tab and store like SRT_Table */
#define SRT_Subroutine 9 /* Call a subroutine to handle results */
#define SRT_Exists 10 /* Store 1 if the result is not empty */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
TriggerStack *trigStack; /* Trigger actions being coded */
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ int nArgAlloc; /* Number of bytes allocated for zArg[] */
+ int nArgUsed; /* Number of bytes of zArg[] used so far */
+ char *zArg; /* Complete text of a module argument */
+#endif
};
/*
#define sqlite3ThreadSafeFree sqlite3FreeX
#endif
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+# define sqlite3VtabClear(X)
+#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
*************************************************************************
** A TCL Interface to SQLite
**
-** $Id: tclsqlite.c,v 1.156 2006/05/10 14:39:14 drh Exp $
+** $Id: tclsqlite.c,v 1.157 2006/06/11 23:41:56 drh Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
extern int Sqlitetest5_Init(Tcl_Interp*);
extern int Sqlitetest6_Init(Tcl_Interp*);
extern int Sqlitetest7_Init(Tcl_Interp*);
+ extern int Sqlitetest8_Init(Tcl_Interp*);
extern int Md5_Init(Tcl_Interp*);
extern int Sqlitetestsse_Init(Tcl_Interp*);
extern int Sqlitetestasync_Init(Tcl_Interp*);
Sqlitetest5_Init(interp);
Sqlitetest6_Init(interp);
Sqlitetest7_Init(interp);
+ Sqlitetest8_Init(interp);
Sqlitetestasync_Init(interp);
Md5_Init(interp);
#ifdef SQLITE_SSE
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test1.c,v 1.209 2006/03/19 13:00:25 drh Exp $
+** $Id: test1.c,v 1.210 2006/06/11 23:41:56 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#else
Tcl_SetVar2(interp, "sqlite_options", "view", "1", TCL_GLOBAL_ONLY);
#endif
+
+#ifdef SQLITE_OMIT_VIRTUALTABLE
+ Tcl_SetVar2(interp, "sqlite_options", "vtab", "0", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "vtab", "1", TCL_GLOBAL_ONLY);
+#endif
}
/*
--- /dev/null
+/*
+** 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.
+**
+*************************************************************************
+** 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.1 2006/06/11 23:41:56 drh Exp $
+*/
+#include "sqliteInt.h"
+#include "tcl.h"
+#include "os.h"
+#include <stdlib.h>
+#include <string.h>
+
+/* 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;
+
+ Tcl_SetVar(interp, "echo_module", "xCreate", TCL_GLOBAL_ONLY);
+ for(i=0; i<argc; i++){
+ Tcl_SetVar(interp, "echo_module", argv[i],
+ TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
+ }
+ return 0;
+}
+static int echoConnect(
+ sqlite3 *db,
+ const sqlite3_module *pModule,
+ int argc, char **argv,
+ sqlite3_vtab **ppVtab
+){
+ int i;
+ Tcl_Interp *interp = pModule->pAux;
+ *ppVtab = pModule->pAux;
+
+ Tcl_SetVar(interp, "echo_module", "xConnect", TCL_GLOBAL_ONLY);
+ for(i=0; i<argc; i++){
+ Tcl_SetVar(interp, "echo_module", argv[i],
+ TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
+ }
+ return 0;
+}
+static int echoDisconnect(sqlite3_vtab *pVtab){
+ Tcl_Interp *interp = (Tcl_Interp*)pVtab;
+ Tcl_SetVar(interp, "echo_module", "xDisconnect",
+ TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
+ return 0;
+}
+static int echoDestroy(sqlite3_vtab *pVtab){
+ Tcl_Interp *interp = (Tcl_Interp*)pVtab;
+ Tcl_SetVar(interp, "echo_module", "xDestroy",
+ TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
+ return 0;
+}
+
+/*
+** A virtual table module that merely echos method calls into TCL
+** variables.
+*/
+static sqlite3_module echoModule = {
+ 0,
+ "echo",
+ 0,
+ echoCreate,
+ echoConnect,
+ 0,
+ echoDisconnect,
+ echoDestroy,
+};
+
+/*
+** Decode a pointer to an sqlite3 object.
+*/
+static int getDbPointer(Tcl_Interp *interp, const char *zA, sqlite3 **ppDb){
+ *ppDb = (sqlite3*)sqlite3TextToPtr(zA);
+ return TCL_OK;
+}
+
+
+/*
+** Register the echo virtual table module.
+*/
+static int register_echo_module(
+ ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int objc, /* Number of arguments */
+ Tcl_Obj *CONST objv[] /* Command arguments */
+){
+ sqlite3 *db;
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 1, objv, "DB");
+ return TCL_ERROR;
+ }
+ if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;
+ echoModule.pAux = interp;
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqlite3_create_module(db, "echo", &echoModule);
+#endif
+ return TCL_OK;
+}
+
+
+/*
+** Register commands with the TCL interpreter.
+*/
+int Sqlitetest8_Init(Tcl_Interp *interp){
+ static struct {
+ char *zName;
+ Tcl_ObjCmdProc *xProc;
+ void *clientData;
+ } aObjCmd[] = {
+ { "register_echo_module", register_echo_module, 0 },
+ };
+ int i;
+ for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
+ Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
+ aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
+ }
+ return TCL_OK;
+}
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
-** $Id: tokenize.c,v 1.118 2006/04/04 01:54:55 drh Exp $
+** $Id: tokenize.c,v 1.119 2006/06/11 23:41:56 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
pParse->aTableLock = 0;
pParse->nTableLock = 0;
}
+#endif
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+ sqliteFree(pParse->zArg);
#endif
sqlite3DeleteTable(pParse->db, pParse->pNewTable);
sqlite3DeleteTrigger(pParse->pNewTrigger);
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.123 2006/02/24 02:53:50 drh Exp $
+** $Id: update.c,v 1.124 2006/06/11 23:41:56 drh Exp $
*/
#include "sqliteInt.h"
if( isView ){
Select *pView;
pView = sqlite3SelectDup(pTab->pSelect);
- sqlite3Select(pParse, pView, SRT_VirtualTab, iCur, 0, 0, 0, 0);
+ sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
sqlite3SelectDelete(pView);
}
** 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.550 2006/06/03 18:04:17 drh Exp $
+** $Id: vdbe.c,v 1.551 2006/06/11 23:41:56 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
break;
}
-/* Opcode: OpenVirtual P1 P2 P3
+/* Opcode: OpenEphemeral P1 P2 P3
**
-** Open a new cursor P1 to a transient or virtual table.
+** Open a new cursor P1 to a transient table.
** The cursor is always opened read/write even if
** the main database is read-only. The transient or virtual
** table is deleted automatically when the cursor is closed.
** The cursor points to a BTree table if P3==0 and to a BTree index
** if P3 is not 0. If P3 is not NULL, it points to a KeyInfo structure
** that defines the format of keys in the index.
+**
+** This opcode was once called OpenTemp. But that created
+** confusion because the term "temp table", might refer either
+** to a TEMP table at the SQL level, or to a table opened by
+** this opcode. Then this opcode was call OpenVirtual. But
+** that created confusion with the whole virtual-table idea.
*/
-case OP_OpenVirtual: { /* no-push */
+case OP_OpenEphemeral: { /* no-push */
int i = pOp->p1;
Cursor *pCx;
assert( i>=0 );
}
break;
}
-#endif /* SHARED_OMIT_SHARED_CACHE */
+#endif /* SQLITE_OMIT_SHARED_CACHE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VCreate * * P3
+**
+** P3 is the name of a virtual table. Call the xCreate method for
+** that table.
+*/
+case OP_VCreate: {
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
+
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+/* Opcode: VDestroy * * P3
+**
+** P3 is the name of a virtual table. Call the xCreate method for
+** that table.
+*/
+case OP_VDestroy: {
+ break;
+}
+#endif /* SQLITE_OMIT_VIRTUALTABLE */
/* An other opcode is illegal...
*/
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
-** $Id: vdbe.h,v 1.102 2006/03/17 13:56:34 drh Exp $
+** $Id: vdbe.h,v 1.103 2006/06/11 23:41:56 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
#define P3_KEYINFO (-6) /* P3 is a pointer to a KeyInfo structure */
#define P3_VDBEFUNC (-7) /* P3 is a pointer to a VdbeFunc structure */
#define P3_MEM (-8) /* P3 is a pointer to a Mem* structure */
-#define P3_TRANSIENT (-9) /* P3 is a pointer to a transient string */
+#define P3_TRANSIENT (-9) /* P3 is a pointer to a transient string */
/* When adding a P3 argument using P3_KEYINFO, a copy of the KeyInfo structure
** is made. That copy is freed when the Vdbe is finalized. But if the
--- /dev/null
+/*
+** 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.1 2006/06/11 23:41:56 drh Exp $
+*/
+#ifndef SQLITE_OMIT_VIRTUALTABLE
+#include "sqliteInt.h"
+
+/*
+** External API function used to create a new virtual-table module.
+*/
+int sqlite3_create_module(
+ sqlite3 *db, /* Database in which module is registered */
+ const char *zName, /* Name assigned to this module */
+ const sqlite3_module *pModule /* The definition of the module */
+){
+ sqlite3HashInsert(&db->aModule, zName, strlen(zName), (void*)pModule);
+ sqlite3ResetInternalSchema(db, 0);
+ return SQLITE_OK;
+}
+
+
+/*
+** Clear any and all virtual-table information from the Table record.
+** This routine is called, for example, just before deleting the Table
+** record.
+*/
+void sqlite3VtabClear(Table *p){
+ if( p->pVtab ){
+ assert( p->pModule!=0 );
+ p->pModule->xDisconnect(p->pVtab);
+ }
+ if( p->azModuleArg ){
+ int i;
+ for(i=0; i<p->nModuleArg; i++){
+ sqliteFree(p->azModuleArg[i]);
+ }
+ sqliteFree(p->azModuleArg);
+ }
+}
+
+/*
+** Add a new module argument to pTable->azModuleArg[].
+** The string is not copied - the pointer is stored. The
+** string will be freed automatically when the table is
+** deleted.
+*/
+static void addModuleArgument(Table *pTable, char *zArg){
+ int i = pTable->nModuleArg++;
+ pTable->azModuleArg = sqliteRealloc(pTable->azModuleArg,
+ sizeof(char*)*(pTable->nModuleArg+1));
+ if( pTable->azModuleArg==0 ){
+ pTable->nModuleArg = 0;
+ sqliteFree(zArg);
+ }else{
+ pTable->azModuleArg[i] = zArg;
+ pTable->azModuleArg[i+1] = 0;
+ }
+}
+
+/*
+** The parser calls this routine when it first sees a CREATE VIRTUAL TABLE
+** statement. The module name has been parsed, but the optional list
+** of parameters that follow the module name are still pending.
+*/
+void sqlite3VtabBeginParse(
+ 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 */
+
+ sqlite3StartTable(pParse, pName1, pName2, 0, 0, 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;
+}
+
+/*
+** This routine takes the module argument that has been accumulating
+** in pParse->zArg[] and appends it to the list of arguments on the
+** virtual table currently under construction in pParse->pTable.
+*/
+static void addArgumentToVtab(Parse *pParse){
+ if( pParse->nArgUsed && pParse->pNewTable ){
+ addModuleArgument(pParse->pNewTable, sqliteStrDup(pParse->zArg));
+ }
+ pParse->nArgUsed = 0;
+}
+
+/*
+** The parser calls this routine after the CREATE VIRTUAL TABLE statement
+** has been completely parsed.
+*/
+void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
+ Table *pTab; /* The table being constructed */
+ sqlite3 *db; /* The database connection */
+ char *zModule; /* The module name of the table: USING modulename */
+
+ addArgumentToVtab(pParse);
+ sqliteFree(pParse->zArg);
+ pParse->zArg = 0;
+ pParse->nArgAlloc = 0;
+
+ /* Lookup the module name. */
+ pTab = pParse->pNewTable;
+ 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));
+
+ /* If the CREATE VIRTUAL TABLE statement is being entered for the
+ ** 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
+ ** the information we've collected. The rowid for the preallocated
+ ** slot is the top the stack.
+ */
+ 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",
+ db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
+ pTab->zName,
+ pTab->zName,
+ zStmt
+ );
+ sqliteFree(zStmt);
+ v = sqlite3GetVdbe(pParse);
+ sqlite3VdbeOp3(v, OP_VCreate, 0, 0, pTab->zName, P3_DYNAMIC);
+ sqlite3ChangeCookie(db, v, iDb);
+ }
+
+ /* 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.
+ */
+ else if( pTab->pModule ){
+ sqlite3_module *pMod = pTab->pModule;
+ assert( pMod->xConnect );
+ pMod->xConnect(db, pMod, pTab->nModuleArg, pTab->azModuleArg, &pTab->pVtab);
+ }
+}
+
+/*
+** The parser calls this routine when it sees the first token
+** of an argument to the module name in a CREATE VIRTUAL TABLE statement.
+*/
+void sqlite3VtabArgInit(Parse *pParse){
+ addArgumentToVtab(pParse);
+ pParse->nArgUsed = 0;
+}
+
+/*
+** The parser calls this routine for each token after the first token
+** in an argument to the module name in a CREATE VIRTUAL TABLE statement.
+*/
+void sqlite3VtabArgExtend(Parse *pParse, Token *p){
+ if( pParse->nArgUsed + p->n + 2 >= pParse->nArgAlloc ){
+ pParse->nArgAlloc = pParse->nArgAlloc*2 + p->n + 200;
+ pParse->zArg = sqliteRealloc(pParse->zArg, pParse->nArgAlloc);
+ if( pParse->zArg==0 ){
+ pParse->nArgAlloc = 0;
+ return;
+ }
+ }
+ 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 */
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
-** $Id: where.c,v 1.209 2006/06/06 11:45:55 drh Exp $
+** $Id: where.c,v 1.210 2006/06/11 23:41:56 drh Exp $
*/
#include "sqliteInt.h"
pTabItem = &pTabList->a[pLevel->iFrom];
pTab = pTabItem->pTab;
iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
- if( pTab->isTransient || pTab->pSelect ) continue;
+ if( pTab->isEphem || pTab->pSelect ) continue;
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, OP_OpenRead);
if( pTab->nCol<(sizeof(Bitmask)*8) ){
struct SrcList_item *pTabItem = &pTabList->a[pLevel->iFrom];
Table *pTab = pTabItem->pTab;
assert( pTab!=0 );
- if( pTab->isTransient || pTab->pSelect ) continue;
+ if( pTab->isEphem || pTab->pSelect ) continue;
if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){
sqlite3VdbeAddOp(v, OP_Close, pTabItem->iCursor, 0);
}
# This file implements regression tests for SQLite library. The
# focus of this file is testing the INSERT statement.
#
-# $Id: insert.test,v 1.29 2006/01/17 09:35:02 danielk1977 Exp $
+# $Id: insert.test,v 1.30 2006/06/11 23:41:56 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set x [execsql {
EXPLAIN INSERT INTO t4 SELECT x+2 FROM t4;
}]
- expr {[lsearch $x OpenVirtual]>0}
+ expr {[lsearch $x OpenEphemeral]>0}
} {1}
}
# focus of this file is testing SELECT statements that contain
# subqueries in their FROM clause.
#
-# $Id: select6.test,v 1.23 2006/01/23 07:52:41 danielk1977 Exp $
+# $Id: select6.test,v 1.24 2006/06/11 23:41:56 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
# sqliteFlattenSubquery() routine in select.c is doing its job.
#
proc is_flat {sql} {
- return [expr 0>[lsearch [execsql "EXPLAIN $sql"] OpenVirtual]]
+ return [expr 0>[lsearch [execsql "EXPLAIN $sql"] OpenEphemeral]]
}
# Check that the flattener works correctly for deeply nested subqueries
# This file implements regression tests for SQLite library. The
# focus of this file is testing VIEW statements.
#
-# $Id: view.test,v 1.31 2006/03/26 01:21:23 drh Exp $
+# $Id: view.test,v 1.32 2006/06/11 23:41:56 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test view-5.3 {
lsearch [execsql {
EXPLAIN SELECT * FROM v5;
- }] OpenVirtual
+ }] OpenEphemeral
} {-1}
do_test view-5.4 {
execsql {
do_test view-5.5 {
lsearch [execsql {
EXPLAIN SELECT * FROM v5 AS a, t2 AS b WHERE a.w=b.y;
- }] OpenVirtual
+ }] OpenEphemeral
} {-1}
do_test view-5.6 {
execsql {
do_test view-5.7 {
lsearch [execsql {
EXPLAIN SELECT * FROM t2 AS b, v5 AS a WHERE a.w=b.y;
- }] OpenVirtual
+ }] OpenEphemeral
} {-1}
do_test view-5.8 {
execsql {
do_test view-5.9 {
lsearch [execsql {
EXPLAIN SELECT * FROM t1 AS a, v5 AS b, t2 AS c WHERE a.x=b.v AND b.w=c.y;
- }] OpenVirtual
+ }] OpenEphemeral
} {-1}
} ;# endif explain
--- /dev/null
+# 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.1 2006/06/11 23:41:56 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+# We cannot create a virtual table if the module has not
+# been registered.
+#
+do_test vtab1-1.1 {
+ catchsql {
+ CREATE VIRTUAL TABLE t1 USING echo;
+ }
+} {1 {unknown module: echo}}
+do_test vtab1-1.2 {
+ execsql {
+ SELECT name FROM sqlite_master ORDER BY 1
+ }
+} {}
+
+# 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]
+execsql {pragma vdbe_listing=on; pragma vdbe_trace=on}
+ 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