Incremental work on parsing/storing and invoking the xCreate callback for virtual tables. (CVS 3212)

FossilOrigin-Name: 8ffbab79d5a76dea0f87cf551d5b6ad4f0fab337
This commit is contained in:
danielk1977 2006-06-12 06:09:17 +00:00
parent b9bb7c187e
commit 78efaba10e
8 changed files with 120 additions and 43 deletions

@ -1,5 +1,5 @@
C Progress\stoward\sCREATE\sVIRTUAL\sTABLE.\s\sStill\snot\seven\sclose\sto\sworking...\s(CVS\s3211)
D 2006-06-11T23:41:55
C Incremental\swork\son\sparsing/storing\sand\sinvoking\sthe\sxCreate\scallback\sfor\svirtual\stables.\s(CVS\s3212)
D 2006-06-12T06:09:18
F Makefile.in 56fd6261e83f60724e6dcd764e06ab68cbd53909
F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@ -66,7 +66,7 @@ F src/pager.c ddd05666bb89808a516baef2c186d6a75887ae90
F src/pager.h 43f32f3847421f7502cfbb66f4eb2302b8033818
F src/parse.y 05cd1419b625df99ea9776e2c767d2a792d84345
F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55
F src/prepare.c bbf12d3147116b284b157232efaef3bbe5df08fc
F src/prepare.c 6dc945dab34cf97364c661d2b7a12be65d338267
F src/printf.c 7029e5f7344a478394a02c52837ff296ee1ab240
F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
F src/select.c 38eda11d950ed5e631ea9054f84a4a8b9e9b39d8
@ -74,7 +74,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c b9eb3ed4d3ab41fbf630eabb602f3c9d20fc737a
F src/sqlite.h.in ca30260d7815ee68be410e1fa0bd1f131c86cf10
F src/sqlite3ext.h 127bd394c8eea481f2ac9b754bf399dbfc818b75
F src/sqliteInt.h 90957da628f83fa7d57c35b239573496642393c0
F src/sqliteInt.h 4ac8c35fec748b1886bed00f1086fa2520faea80
F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e
F src/tclsqlite.c 0b2a04cfc1b4298adfbe90a754cfbbe207aca11a
F src/test1.c 88291fa6674dcd409b1c9d76d3119151d4b81a50
@ -84,7 +84,7 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
F src/test8.c 210f2109333e3373a1cb814e22e7b6b33e1e0a20
F src/test8.c c1a91a3307e4d8d8a46211498111d1c5778b9294
F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c
@ -94,14 +94,14 @@ F src/update.c 0186f09414a6578156d40666becc964f85c2a616
F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44
F src/util.c ca6ee72772c0f5dc04d2e0ab1973fd3b6a9bf79d
F src/vacuum.c 5b37d0f436f8e1ffacd17934e44720b38d2247f9
F src/vdbe.c 2547e931baf0f35cc8df77fdb18004a9f987bc6a
F src/vdbe.c 5c77e8b57c07e7776ec34df8088749c639bbfe7c
F src/vdbe.h 190d85a37658c2397be75a4c70bbc02ebc4ec0ba
F src/vdbeInt.h 85cd5f81d38edb1b8f4786f407c77a7a3ba636fb
F src/vdbeapi.c 7dc662e7c905ce666bb506dced932e0307115cbf
F src/vdbeaux.c 4002e6b19d7c9719cb81f9797316b9ad118e4370
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3
F src/vtab.c 4ace1448bdba6a13d93c7642aa66447f8a5cd63c
F src/vtab.c 6872f6a6ca33aac85b62bcd66d883f4deffab00d
F src/where.c 3dc5269ba552c0db39247f6bbc98b312ae786863
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@ -287,7 +287,7 @@ F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f
F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
F test/vtab1.test 9029c3ef19f1db3eebb2554b4db12e04b39a30ca
F test/vtab1.test 5bf2bebe96272953928596b256cefb21d9c765b1
F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
@ -363,7 +363,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
P 66370cb99bd93abb33e1e8433672da45e1795f78
R 9ff37f743d5a6a690e7a66e29bc79ec5
U drh
Z 6146abfd990542c70d1912af93fdb676
P 898ec36b4102aaa03979f8f5c510936e57e2ae48
R fd0d79bfdfee01e76c00d486659426af
U danielk1977
Z 21ad209dbac4dc09cf972c3f2b10f101

@ -1 +1 @@
898ec36b4102aaa03979f8f5c510936e57e2ae48
8ffbab79d5a76dea0f87cf551d5b6ad4f0fab337

@ -13,7 +13,7 @@
** interface, and routines that contribute to loading the database schema
** from disk.
**
** $Id: prepare.c,v 1.34 2006/05/23 23:22:29 drh Exp $
** $Id: prepare.c,v 1.35 2006/06/12 06:09:18 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -38,7 +38,7 @@ static void corruptSchema(InitData *pData, const char *zExtra){
** Each callback contains the following information:
**
** argv[0] = name of thing being created
** argv[1] = root page number for table or index. NULL for trigger or view.
** argv[1] = root page number for table or index. 0 for trigger or view.
** argv[2] = SQL text for the CREATE statement.
** argv[3] = "1" for temporary files, "0" for main database, "2" or more
** for auxiliary database files.

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.497 2006/06/11 23:41:56 drh Exp $
** @(#) $Id: sqliteInt.h,v 1.498 2006/06/12 06:09:18 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -1790,6 +1790,7 @@ void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*);
void sqlite3VtabFinishParse(Parse*, Token*);
void sqlite3VtabArgInit(Parse*);
void sqlite3VtabArgExtend(Parse*, Token*);
int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
#ifdef SQLITE_SSE
#include "sseInt.h"

@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
** $Id: test8.c,v 1.1 2006/06/11 23:41:56 drh Exp $
** $Id: test8.c,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@ -21,6 +21,15 @@
#include <stdlib.h>
#include <string.h>
/*
** Global Tcl variable $echo_module is a list. This routine appends
** the string element zArg to that list in interpreter interp.
*/
static void appendToEchoModule(const sqlite3_module *pModule, const char *zArg){
int flags = (TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
Tcl_SetVar((Tcl_Interp *)(pModule->pAux), "echo_module", zArg, flags);
}
/* Methods for the echo module */
static int echoCreate(
sqlite3 *db,
@ -32,11 +41,11 @@ static int echoCreate(
Tcl_Interp *interp = pModule->pAux;
*ppVtab = pModule->pAux;
Tcl_SetVar(interp, "echo_module", "xCreate", TCL_GLOBAL_ONLY);
appendToEchoModule(pModule, "xCreate");
for(i=0; i<argc; i++){
Tcl_SetVar(interp, "echo_module", argv[i],
TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
appendToEchoModule(pModule, argv[i]);
}
return 0;
}
static int echoConnect(
@ -74,12 +83,12 @@ static int echoDestroy(sqlite3_vtab *pVtab){
** variables.
*/
static sqlite3_module echoModule = {
0,
"echo",
0,
0, /* iVersion */
"echo", /* zName */
0, /* pAux */
echoCreate,
echoConnect,
0,
0, /* xBestIndex */
echoDisconnect,
echoDestroy,
};

@ -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.551 2006/06/11 23:41:56 drh Exp $
** $Id: vdbe.c,v 1.552 2006/06/12 06:09:19 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -4534,12 +4534,13 @@ case OP_TableLock: { /* no-push */
#endif /* SQLITE_OMIT_SHARED_CACHE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VCreate * * P3
/* Opcode: VCreate P1 * P3
**
** P3 is the name of a virtual table. Call the xCreate method for
** that table.
** P3 is the name of a virtual table in database P1. Call the xCreate method
** for that table.
*/
case OP_VCreate: {
rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p3, &p->zErrMsg);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@ -4547,7 +4548,7 @@ case OP_VCreate: {
#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Opcode: VDestroy * * P3
**
** P3 is the name of a virtual table. Call the xCreate method for
** P3 is the name of a virtual table. Call the xDestroy method for
** that table.
*/
case OP_VDestroy: {

@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.1 2006/06/11 23:41:56 drh Exp $
** $Id: vtab.c,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"
@ -81,7 +81,14 @@ void sqlite3VtabBeginParse(
){
Table *pTable; /* The new virtual table */
sqlite3StartTable(pParse, pName1, pName2, 0, 0, 0);
/* TODO: The 5th argument to sqlite3StartTable() - isView - is being
** passed a true value at present. This prevents sqlite3StartTable()
** from coding OP_CreateTable, which is correct, but causes it
** to invoke the authorization function as if a CREATE VIEW statement
** were attempted, which is incorrect.
*/
sqlite3StartTable(pParse, pName1, pName2, 0, 1, 0);
pTable = pParse->pNewTable;
if( pTable==0 ) return;
pTable->isVirtual = 1;
@ -134,6 +141,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
*/
if( !db->init.busy ){
char *zStmt;
char *zWhere;
int iDb;
Vdbe *v;
if( pTab->pModule==0 ){
@ -148,14 +156,18 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
/* A slot for the record has already been allocated in the
** SQLITE_MASTER table. We just need to update that slot with all
** the information we've collected. The rowid for the preallocated
** slot is the top the stack.
** the information we've collected.
**
** The top of the stack is the rootpage allocated by sqlite3StartTable().
** This value is always 0 and is ignored, a virtual table does not have a
** rootpage. The next entry on the stack is the rowid of the record
** in the sqlite_master table.
*/
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
sqlite3NestedParse(pParse,
"UPDATE %Q.%s "
"SET type='table', name=%Q, tbl_name=%Q, rootpage=NULL, sql=%Q "
"WHERE rowid=#0",
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
"WHERE rowid=#1",
db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
pTab->zName,
pTab->zName,
@ -163,18 +175,36 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
);
sqliteFree(zStmt);
v = sqlite3GetVdbe(pParse);
sqlite3VdbeOp3(v, OP_VCreate, 0, 0, pTab->zName, P3_DYNAMIC);
sqlite3ChangeCookie(db, v, iDb);
sqlite3VdbeAddOp(v, OP_Expire, 0, 0);
zWhere = sqlite3MPrintf("name='%q'", pTab->zName);
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0, zWhere, P3_DYNAMIC);
sqlite3VdbeOp3(v, OP_VCreate, iDb, 0, pTab->zName, strlen(pTab->zName) + 1);
}
/* If we are rereading the sqlite_master table and we happen to
** currently know the module for the new table, create an
** sqlite3_vtab instance.
/* If we are rereading the sqlite_master table create the in-memory
** record of the table.
**
** TODO: If the module is already registered, should we call xConnect()
** here, or should it wait until the table is first referenced. Maybe
** it's better to be lazy here, in case xConnect() is expensive to call.
*/
else if( pTab->pModule ){
else {
#if 0
sqlite3_module *pMod = pTab->pModule;
assert( pMod->xConnect );
pMod->xConnect(db, pMod, pTab->nModuleArg, pTab->azModuleArg, &pTab->pVtab);
#endif
Table *pOld;
Schema *pSchema = pTab->pSchema;
const char *zName = pTab->zName;
int nName = strlen(zName) + 1;
pOld = sqlite3HashInsert(&pSchema->tblHash, zName, nName, pTab);
if( pOld ){
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
return;
}
}
}
@ -208,4 +238,42 @@ void sqlite3VtabArgExtend(Parse *pParse, Token *p){
pParse->zArg[pParse->nArgUsed] = 0;
}
/*
** This function is invoked by the vdbe to call the xCreate method
** of the virtual table named zTab in database iDb.
**
** If an error occurs, *pzErr is set to point an an English language
** description of the error and an SQLITE_XXX error code is returned.
** In this case the caller must call sqliteFree() on *pzErr.
*/
int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
int rc = SQLITE_OK;
Table *pTab;
sqlite3_module *pModule;
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
assert(pTab && pTab->isVirtual);
pModule = pTab->pModule;
const char *zModule = pTab->azModuleArg[0];
/* If the module has been registered and includes a Create method,
** invoke it now. If the module has not been registered, return an
** error. Otherwise, do nothing.
*/
if( !pModule ){
*pzErr = sqlite3MPrintf("unknown module: %s", zModule);
rc = SQLITE_ERROR;
}else if( pModule->xCreate ){
/* TODO: Maybe the above condition should refer to pTable->needCreate. */
char **azArg = pTab->azModuleArg;
int nArg = pTab->nModuleArg;
rc = pModule->xCreate(db, pModule, nArg, azArg, &pTab->pVtab);
}
if( SQLITE_OK==rc ){
pTab->needCreate = 0;
}
return rc;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */

@ -11,7 +11,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is creating and dropping virtual tables.
#
# $Id: vtab1.test,v 1.1 2006/06/11 23:41:56 drh Exp $
# $Id: vtab1.test,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@ -35,7 +35,6 @@ do_test vtab1-1.2 {
#
do_test vtab1-1.3 {
register_echo_module [sqlite3_connection_pointer db]
execsql {pragma vdbe_listing=on; pragma vdbe_trace=on}
catchsql {
CREATE VIRTUAL TABLE t1 USING echo;
}
@ -49,5 +48,4 @@ do_test vtab1-1.5 {
}
} {t1 {CREATE VIRTUAL TABLE t1 USING echo}}
finish_test