1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-07-30 19:03:16 +03:00

Progress toward CREATE VIRTUAL TABLE. Still not even close to working... (CVS 3211)

FossilOrigin-Name: 898ec36b4102aaa03979f8f5c510936e57e2ae48
This commit is contained in:
drh
2006-06-11 23:41:55 +00:00
parent e09daa90ac
commit b9bb7c187e
26 changed files with 637 additions and 150 deletions

View File

@ -130,7 +130,7 @@ LIBOBJ = alter.lo analyze.lo attach.lo auth.lo btree.lo build.lo \
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.
#
@ -184,6 +184,7 @@ SRC = \
$(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.
@ -206,6 +207,7 @@ TESTSRC = \
$(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 \
@ -435,6 +437,9 @@ vdbefifo.lo: $(TOP)/src/vdbefifo.c $(VDBEHDR)
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

View File

@ -63,7 +63,7 @@ LIBOBJ+= alter.o analyze.o attach.o auth.o btree.o build.o \
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.
#
@ -117,6 +117,7 @@ SRC = \
$(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.
@ -139,6 +140,7 @@ TESTSRC = \
$(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 \
@ -360,6 +362,9 @@ vdbefifo.o: $(TOP)/src/vdbefifo.c $(VDBEHDR)
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

View File

@ -1,6 +1,6 @@
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
@ -19,7 +19,7 @@ F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
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
@ -36,20 +36,20 @@ F src/attach.c 27a31d3b89d7ebb5b358847607b1ec795384123c
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
@ -64,43 +64,45 @@ F src/os_win.c c6976ae50b61fb5b7dce399e578aa1865f02b84f
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
@ -175,7 +177,7 @@ F test/in.test 369cb2aa1eab02296b4ec470732fe8c131260b1d
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
@ -231,7 +233,7 @@ F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3
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
@ -284,7 +286,8 @@ F test/utf16align.test 7360e84472095518c56746f76b1f9d4dce99fb4d
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
@ -360,7 +363,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
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

View File

@ -1 +1 @@
66370cb99bd93abb33e1e8433672da45e1795f78
898ec36b4102aaa03979f8f5c510936e57e2ae48

View File

@ -22,7 +22,7 @@
** 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>
@ -533,12 +533,7 @@ void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
#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);
}
@ -810,10 +805,7 @@ void sqlite3StartTable(
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);
@ -1378,7 +1370,7 @@ void sqlite3EndTable(
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.
@ -1974,7 +1966,14 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView, int noErr){
/* Remove the table entry from SQLite's internal schema and modify
** the schema cookie.
*/
#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);

View File

@ -12,7 +12,7 @@
** 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"
@ -190,7 +190,7 @@ void sqlite3DeleteFrom(
*/
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);
}

View File

@ -12,7 +12,7 @@
** 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>
@ -547,12 +547,12 @@ Select *sqlite3SelectDup(Select *p){
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
@ -1316,7 +1316,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
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);
@ -1334,7 +1334,7 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
** 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);

View File

@ -12,7 +12,7 @@
** 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"
@ -371,7 +371,7 @@ void sqlite3Insert(
** 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);

View File

@ -14,7 +14,7 @@
** 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"
@ -159,6 +159,9 @@ int sqlite3_close(sqlite3 *db){
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. */
@ -818,6 +821,9 @@ static int openDatabase(
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

View File

@ -14,7 +14,7 @@
** 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_"
@ -1062,11 +1062,18 @@ kwcolumn_opt ::= COLUMNKW.
//////////////////////// 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

View File

@ -12,7 +12,7 @@
** 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"
@ -72,9 +72,9 @@ Select *sqlite3SelectNew(
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;
@ -522,7 +522,7 @@ static int selectInnerLoop(
/* 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);
@ -705,7 +705,7 @@ static void generateSortTail(
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);
@ -1201,11 +1201,11 @@ static int prepSelectStmt(Parse *pParse, Select *p){
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 */
@ -1538,10 +1538,10 @@ static void createSortingIndex(Parse *pParse, Select *p, ExprList *pOrderBy){
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;
}
}
@ -1647,10 +1647,10 @@ static int multiSelect(
/* 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;
}
@ -1712,14 +1712,14 @@ static int multiSelect(
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 );
@ -1808,10 +1808,10 @@ static int multiSelect(
}
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".
@ -1823,9 +1823,9 @@ static int multiSelect(
/* 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;
@ -1899,7 +1899,7 @@ static int multiSelect(
** 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 */
@ -1925,11 +1925,11 @@ static int multiSelect(
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);
@ -1959,8 +1959,8 @@ static int multiSelect(
*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);
@ -2394,8 +2394,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
/* 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
@ -2404,7 +2404,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
** 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;
@ -2631,7 +2631,7 @@ static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
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);
}
}
@ -2780,7 +2780,7 @@ int sqlite3Select(
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 */
@ -2868,7 +2868,7 @@ int sqlite3Select(
}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;
@ -2908,7 +2908,7 @@ int sqlite3Select(
**
** 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.
*/
@ -2925,8 +2925,8 @@ int sqlite3Select(
}
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;
@ -2934,8 +2934,8 @@ int sqlite3Select(
/* 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.
@ -2949,7 +2949,7 @@ int sqlite3Select(
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;
@ -2963,13 +2963,13 @@ int sqlite3Select(
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
@ -3003,7 +3003,7 @@ int sqlite3Select(
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);
@ -3050,13 +3050,13 @@ int sqlite3Select(
/* 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);
@ -3119,7 +3119,7 @@ int sqlite3Select(
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;

View File

@ -12,7 +12,7 @@
** 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_
@ -1517,6 +1517,7 @@ typedef struct sqlite3_vtab_cursor sqlite3_vtab_cursor;
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,
@ -1568,6 +1569,11 @@ struct sqlite3_index_info {
#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 *
);
/*

View File

@ -11,7 +11,7 @@
*************************************************************************
** 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_
@ -490,8 +490,8 @@ struct sqlite3 {
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 */
@ -672,7 +672,7 @@ struct CollSeq {
** 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
@ -689,7 +689,7 @@ struct Table {
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 */
@ -704,10 +704,12 @@ struct Table {
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 */
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;
};
@ -903,7 +905,7 @@ struct AggInfo {
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[] */
@ -1171,14 +1173,14 @@ struct NameContext {
** 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 {
@ -1187,7 +1189,7 @@ 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 */
@ -1199,7 +1201,7 @@ struct Select {
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 */
};
/*
@ -1216,7 +1218,7 @@ struct 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 */
@ -1277,6 +1279,11 @@ struct Parse {
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
};
/*
@ -1774,6 +1781,16 @@ void sqlite3CloseExtensions(sqlite3*);
#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

View File

@ -11,7 +11,7 @@
*************************************************************************
** 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 */
@ -2151,6 +2151,7 @@ int TCLSH_MAIN(int argc, char **argv){
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*);
@ -2162,6 +2163,7 @@ int TCLSH_MAIN(int argc, char **argv){
Sqlitetest5_Init(interp);
Sqlitetest6_Init(interp);
Sqlitetest7_Init(interp);
Sqlitetest8_Init(interp);
Sqlitetestasync_Init(interp);
Md5_Init(interp);
#ifdef SQLITE_SSE

View File

@ -13,7 +13,7 @@
** 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"
@ -3538,6 +3538,12 @@ static void set_options(Tcl_Interp *interp){
#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
}
/*

136
src/test8.c Normal file
View File

@ -0,0 +1,136 @@
/*
** 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;
}

View File

@ -15,7 +15,7 @@
** 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"
@ -482,6 +482,9 @@ abort_parse:
pParse->aTableLock = 0;
pParse->nTableLock = 0;
}
#endif
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqliteFree(pParse->zArg);
#endif
sqlite3DeleteTable(pParse->db, pParse->pNewTable);
sqlite3DeleteTrigger(pParse->pNewTrigger);

View File

@ -12,7 +12,7 @@
** 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"
@ -268,7 +268,7 @@ void sqlite3Update(
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);
}

View File

@ -43,7 +43,7 @@
** 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"
@ -2640,9 +2640,9 @@ case OP_OpenWrite: { /* no-push */
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.
@ -2651,8 +2651,14 @@ case OP_OpenWrite: { /* no-push */
** 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 );
@ -4525,7 +4531,29 @@ case OP_TableLock: { /* no-push */
}
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...
*/

View File

@ -15,7 +15,7 @@
** 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_

211
src/vtab.c Normal file
View File

@ -0,0 +1,211 @@
/*
** 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 */

View File

@ -16,7 +16,7 @@
** 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"
@ -1601,7 +1601,7 @@ WhereInfo *sqlite3WhereBegin(
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) ){
@ -2087,7 +2087,7 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
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);
}

View File

@ -11,7 +11,7 @@
# 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
@ -247,7 +247,7 @@ ifcapable tempdb {
set x [execsql {
EXPLAIN INSERT INTO t4 SELECT x+2 FROM t4;
}]
expr {[lsearch $x OpenVirtual]>0}
expr {[lsearch $x OpenEphemeral]>0}
} {1}
}

View File

@ -12,7 +12,7 @@
# 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
@ -382,7 +382,7 @@ ifcapable {!explain} {
# 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

View File

@ -11,7 +11,7 @@
# 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
@ -219,7 +219,7 @@ ifcapable {explain} {
do_test view-5.3 {
lsearch [execsql {
EXPLAIN SELECT * FROM v5;
}] OpenVirtual
}] OpenEphemeral
} {-1}
do_test view-5.4 {
execsql {
@ -229,7 +229,7 @@ do_test view-5.4 {
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 {
@ -239,7 +239,7 @@ do_test view-5.6 {
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 {
@ -249,7 +249,7 @@ do_test view-5.8 {
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

53
test/vtab1.test Normal file
View File

@ -0,0 +1,53 @@
# 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