]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Progress toward CREATE VIRTUAL TABLE. Still not even close to working... (CVS 3211)
authordrh <drh@noemail.net>
Sun, 11 Jun 2006 23:41:55 +0000 (23:41 +0000)
committerdrh <drh@noemail.net>
Sun, 11 Jun 2006 23:41:55 +0000 (23:41 +0000)
FossilOrigin-Name: 898ec36b4102aaa03979f8f5c510936e57e2ae48

26 files changed:
Makefile.in
main.mk
manifest
manifest.uuid
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/main.c
src/parse.y
src/select.c
src/sqlite.h.in
src/sqliteInt.h
src/tclsqlite.c
src/test1.c
src/test8.c [new file with mode: 0644]
src/tokenize.c
src/update.c
src/vdbe.c
src/vdbe.h
src/vtab.c [new file with mode: 0644]
src/where.c
test/insert.test
test/select6.test
test/view.test
test/vtab1.test [new file with mode: 0644]

index 5c600c6c1e4b476329b8cded2aa1f38ced1c9d43..26ada6818d71f73d8b7221267108aea40e4499a5 100644 (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
 
diff --git a/main.mk b/main.mk
index c51b7aa1db0c146081c342fe997ffb66e1d2dba7..5a0233d6b5db063f4da86cf69598fc38910d2a82 100644 (file)
--- a/main.mk
+++ b/main.mk
@@ -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
 
index d87618f2c194f679a510e4f241eac99dea6b07c6..6a0c4f192a4407d395b19d60d67736d1efea2c2d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index cd1dbfe70c20211277757b949bf6ce4c909c1825..cb8e1fd491d98c0726a1895ef5cf01267c769fb1 100644 (file)
@@ -1 +1 @@
-66370cb99bd93abb33e1e8433672da45e1795f78
\ No newline at end of file
+898ec36b4102aaa03979f8f5c510936e57e2ae48
\ No newline at end of file
index 74cf00accc242961714c65c1ac1d2facf7a1a6c3..0be7c92f94269ad8682ff088cb263b92a3e61778 100644 (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.
     */
-    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);
index 237c0f19d256209bf84e1adf14a343d3be07f863..e16597d8afd58be9387c5e8eff9a3eb5877265c6 100644 (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);
   }
 
index 0577737a38b4ea7a4a71033d5addfb28d314e032..5a721ab8541ef752f831bceed5ecaa09a0fc1c27 100644 (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);
index c8c5090e9e6029409a6d20c8aad2f22b7e837c38..295d753d3416ef07c5b27db175f895d677cb8213 100644 (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);
index 9d6cbd9713e923c5b1e0c7b0e929f63e24920d76..6eb047df63257dfbcd9ffb6fe720a8e64d7df2f9 100644 (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
index 922d4730b8159118d2accd86d3f2be0e5ee81f23..ce3a69dba33ced4d6caa46983b3e7507330a2ba5 100644 (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
index 2fda1340079d281f3eafc8a5e8fe6e9261c239aa..5dd23d46fb3cefa347a80b35c8221f393b4fa519 100644 (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;
index 6a25f67cc5e96c52a181e9096a41f32effc85676..3f8a6d7be99fddacdadb5f9f3464ef2283e30372 100644 (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 *
+);
 
 
 /*
index 6e78e07826868fac5cf0a4666ed6dd2901678cc1..9a2de48755875f3ed2593f2b13c066b205874edd 100644 (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,13 +490,13 @@ 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 */
   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 */
@@ -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 */
-  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;
 };
@@ -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
index 875890d81809c35eb3c1554aad3bf1c152333460..07783c1e48a254af06d2f19c57c33291514982eb 100644 (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
index 01dc6d7821225ef49e2132e50098b1e2d9915915..0c18ea129287809ea443887415521b70ce62e5ee 100644 (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
 }
 
 /*
diff --git a/src/test8.c b/src/test8.c
new file mode 100644 (file)
index 0000000..c0d08a4
--- /dev/null
@@ -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;
+}
index 6076e7c656e3a2032c9a089ce1a3eca049c3f2d6..2d49fe8cdf670fa2a07e66f7a175422714b9b18f 100644 (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);
index b3cd7aed090ae7375f87bf7cf897765fd943b933..f1662eb1a8fff97ed11dd6980845edfa34a9f074 100644 (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);
   }
 
index fc6fd97ef570ace48083f7b522d2d6ae12f11862..a85d303153a2b88e82cd8f40749e87b339eed733 100644 (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...
 */
index 46045423d6f795355ad4428282ba19ec484fdd71..3097022f62c708f8980b0a7982e1964965037649 100644 (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_
@@ -69,7 +69,7 @@ typedef struct VdbeOpList VdbeOpList;
 #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
diff --git a/src/vtab.c b/src/vtab.c
new file mode 100644 (file)
index 0000000..d7d7515
--- /dev/null
@@ -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 */
index 4ba6338edd75bd2476240d8fe6dba7fb95f9c65f..515ed4421f8d1ccde460cc6a55cced9e0b1f9db8 100644 (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);
     }
index b7d815c32b85e73701ea167e9ad4895799cb8d3c..723a47d15dd6e9a744aec03aa17c2e943611d6df 100644 (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}
   }
   
index a8682eab8689b51e9ee49e3bd58e0b7e993ec467..5b1ee8980213eecc6e54205373ae94bea2c08987 100644 (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
index 6502c1dbc2d0b0aecfa6385bbbc44644d6ceb05a..19c33f9d4fb9ccc21dc410b71fc477c2a6a19c0e 100644 (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
 
diff --git a/test/vtab1.test b/test/vtab1.test
new file mode 100644 (file)
index 0000000..18e034f
--- /dev/null
@@ -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