mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Add first cut of sqlite3_declare_vtab(). Not at all well tested yet. (CVS 3213)
FossilOrigin-Name: bbeb93b5bb26ba83ee7b7ae439ca5ceebebac9a0
This commit is contained in:
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
|||||||
C Incremental\swork\son\sparsing/storing\sand\sinvoking\sthe\sxCreate\scallback\sfor\svirtual\stables.\s(CVS\s3212)
|
C Add\sfirst\scut\sof\ssqlite3_declare_vtab().\sNot\sat\sall\swell\stested\syet.\s(CVS\s3213)
|
||||||
D 2006-06-12T06:09:18
|
D 2006-06-12T11:24:37
|
||||||
F Makefile.in 56fd6261e83f60724e6dcd764e06ab68cbd53909
|
F Makefile.in 56fd6261e83f60724e6dcd764e06ab68cbd53909
|
||||||
F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
|
F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
|
||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||||
@ -36,7 +36,7 @@ F src/attach.c 27a31d3b89d7ebb5b358847607b1ec795384123c
|
|||||||
F src/auth.c 9ae84d2d94eb96195e04515715e08e85963e96c2
|
F src/auth.c 9ae84d2d94eb96195e04515715e08e85963e96c2
|
||||||
F src/btree.c ed343b3dbcbc7da9ac481ef2b98c4239fe6d9629
|
F src/btree.c ed343b3dbcbc7da9ac481ef2b98c4239fe6d9629
|
||||||
F src/btree.h 40055cfc09defd1146bc5b922399c035f969e56d
|
F src/btree.h 40055cfc09defd1146bc5b922399c035f969e56d
|
||||||
F src/build.c f541d3e9afed5eb8a397353b2b54c23d8d531e97
|
F src/build.c a72a709541c62402665e053e2e173dfdc62ce049
|
||||||
F src/callback.c fd9bb39f7ff6b52bad8365617abc61c720640429
|
F src/callback.c fd9bb39f7ff6b52bad8365617abc61c720640429
|
||||||
F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675
|
F src/complete.c 7d1a44be8f37de125fcafd3d3a018690b3799675
|
||||||
F src/date.c cd2bd5d1ebc6fa12d6312f69789ae5b0a2766f2e
|
F src/date.c cd2bd5d1ebc6fa12d6312f69789ae5b0a2766f2e
|
||||||
@ -72,9 +72,9 @@ F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
|
|||||||
F src/select.c 38eda11d950ed5e631ea9054f84a4a8b9e9b39d8
|
F src/select.c 38eda11d950ed5e631ea9054f84a4a8b9e9b39d8
|
||||||
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||||
F src/shell.c b9eb3ed4d3ab41fbf630eabb602f3c9d20fc737a
|
F src/shell.c b9eb3ed4d3ab41fbf630eabb602f3c9d20fc737a
|
||||||
F src/sqlite.h.in ca30260d7815ee68be410e1fa0bd1f131c86cf10
|
F src/sqlite.h.in cad97e59cfad8337f9f43ea9662714a256ca80b2
|
||||||
F src/sqlite3ext.h 127bd394c8eea481f2ac9b754bf399dbfc818b75
|
F src/sqlite3ext.h 127bd394c8eea481f2ac9b754bf399dbfc818b75
|
||||||
F src/sqliteInt.h 4ac8c35fec748b1886bed00f1086fa2520faea80
|
F src/sqliteInt.h ef7b936e38858c98c35ab3cad55eea0859c64a94
|
||||||
F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e
|
F src/table.c f64ec4fbfe333f8df925bc6ba494f55e05b0e75e
|
||||||
F src/tclsqlite.c 0b2a04cfc1b4298adfbe90a754cfbbe207aca11a
|
F src/tclsqlite.c 0b2a04cfc1b4298adfbe90a754cfbbe207aca11a
|
||||||
F src/test1.c 88291fa6674dcd409b1c9d76d3119151d4b81a50
|
F src/test1.c 88291fa6674dcd409b1c9d76d3119151d4b81a50
|
||||||
@ -84,11 +84,11 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
|
|||||||
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
|
F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
|
||||||
F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
|
F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
|
||||||
F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
|
F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
|
||||||
F src/test8.c c1a91a3307e4d8d8a46211498111d1c5778b9294
|
F src/test8.c 9eb1d2e41b81df15952ee8ee54f95fa214f8813e
|
||||||
F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
|
F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
|
||||||
F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
|
F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
|
||||||
F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c
|
F src/test_server.c a6460daed0b92ecbc2531b6dc73717470e7a648c
|
||||||
F src/tokenize.c 279c62792222e0ae6efc4f7609bc47301dde1ef3
|
F src/tokenize.c 6ebcafa6622839968dda4418a7b6945f277a128f
|
||||||
F src/trigger.c 48bbb94c11954c8e132efcc04478efe8304c4196
|
F src/trigger.c 48bbb94c11954c8e132efcc04478efe8304c4196
|
||||||
F src/update.c 0186f09414a6578156d40666becc964f85c2a616
|
F src/update.c 0186f09414a6578156d40666becc964f85c2a616
|
||||||
F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44
|
F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44
|
||||||
@ -101,7 +101,7 @@ F src/vdbeapi.c 7dc662e7c905ce666bb506dced932e0307115cbf
|
|||||||
F src/vdbeaux.c 4002e6b19d7c9719cb81f9797316b9ad118e4370
|
F src/vdbeaux.c 4002e6b19d7c9719cb81f9797316b9ad118e4370
|
||||||
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
|
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
|
||||||
F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3
|
F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3
|
||||||
F src/vtab.c 6872f6a6ca33aac85b62bcd66d883f4deffab00d
|
F src/vtab.c 36778506d9af9b750e01eeea1e116f3c80b7fa01
|
||||||
F src/where.c 3dc5269ba552c0db39247f6bbc98b312ae786863
|
F src/where.c 3dc5269ba552c0db39247f6bbc98b312ae786863
|
||||||
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
|
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
@ -287,7 +287,7 @@ F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f
|
|||||||
F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
|
F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
|
||||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||||
F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
|
F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
|
||||||
F test/vtab1.test 5bf2bebe96272953928596b256cefb21d9c765b1
|
F test/vtab1.test 5c7f4a2a53f3894d571239099c0253e27263cc84
|
||||||
F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
|
F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
|
||||||
F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
|
F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
|
||||||
F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
|
F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
|
||||||
@ -363,7 +363,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||||
P 898ec36b4102aaa03979f8f5c510936e57e2ae48
|
P 8ffbab79d5a76dea0f87cf551d5b6ad4f0fab337
|
||||||
R fd0d79bfdfee01e76c00d486659426af
|
R 26c5c53e0c5dda8d367ac8454cb93c3e
|
||||||
U danielk1977
|
U danielk1977
|
||||||
Z 21ad209dbac4dc09cf972c3f2b10f101
|
Z dfbf7809fd6098db180fe009efbe7300
|
||||||
|
@ -1 +1 @@
|
|||||||
8ffbab79d5a76dea0f87cf551d5b6ad4f0fab337
|
bbeb93b5bb26ba83ee7b7ae439ca5ceebebac9a0
|
37
src/build.c
37
src/build.c
@ -22,7 +22,7 @@
|
|||||||
** COMMIT
|
** COMMIT
|
||||||
** ROLLBACK
|
** ROLLBACK
|
||||||
**
|
**
|
||||||
** $Id: build.c,v 1.396 2006/06/11 23:41:55 drh Exp $
|
** $Id: build.c,v 1.397 2006/06/12 11:24:37 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@ -782,22 +782,28 @@ void sqlite3StartTable(
|
|||||||
|
|
||||||
/* Make sure the new table name does not collide with an existing
|
/* Make sure the new table name does not collide with an existing
|
||||||
** index or table name in the same database. Issue an error message if
|
** index or table name in the same database. Issue an error message if
|
||||||
** it does.
|
** it does. The exception is if the statement being parsed was passed
|
||||||
|
** to an sqlite3_declare_vtab() call. In that case only the column names
|
||||||
|
** and types will be used, so there is no need to test for namespace
|
||||||
|
** collisions.
|
||||||
*/
|
*/
|
||||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
if( !IN_DECLARE_VTAB ){
|
||||||
goto begin_table_error;
|
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||||
}
|
goto begin_table_error;
|
||||||
pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName);
|
}
|
||||||
if( pTable ){
|
pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName);
|
||||||
if( !noErr ){
|
if( pTable ){
|
||||||
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
|
if( !noErr ){
|
||||||
|
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
|
||||||
|
}
|
||||||
|
goto begin_table_error;
|
||||||
|
}
|
||||||
|
if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){
|
||||||
|
sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
|
||||||
|
goto begin_table_error;
|
||||||
}
|
}
|
||||||
goto begin_table_error;
|
|
||||||
}
|
|
||||||
if( sqlite3FindIndex(db, zName, 0)!=0 && (iDb==0 || !db->init.busy) ){
|
|
||||||
sqlite3ErrorMsg(pParse, "there is already an index named %s", zName);
|
|
||||||
goto begin_table_error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pTable = sqliteMalloc( sizeof(Table) );
|
pTable = sqliteMalloc( sizeof(Table) );
|
||||||
if( pTable==0 ){
|
if( pTable==0 ){
|
||||||
pParse->rc = SQLITE_NOMEM;
|
pParse->rc = SQLITE_NOMEM;
|
||||||
@ -1649,6 +1655,9 @@ int sqlite3ViewGetColumnNames(Parse *pParse, Table *pTable){
|
|||||||
** already known.
|
** already known.
|
||||||
*/
|
*/
|
||||||
if( pTable->nCol>0 ) return 0;
|
if( pTable->nCol>0 ) return 0;
|
||||||
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
|
if( pTable->isVirtual ) return 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* A negative nCol is a special marker meaning that we are currently
|
/* A negative nCol is a special marker meaning that we are currently
|
||||||
** trying to compute the column names. If we enter this routine with
|
** trying to compute the column names. If we enter this routine with
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
** This header file defines the interface that the SQLite library
|
** This header file defines the interface that the SQLite library
|
||||||
** presents to client programs.
|
** presents to client programs.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqlite.h.in,v 1.168 2006/06/11 23:41:56 drh Exp $
|
** @(#) $Id: sqlite.h.in,v 1.169 2006/06/12 11:24:37 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITE3_H_
|
#ifndef _SQLITE3_H_
|
||||||
#define _SQLITE3_H_
|
#define _SQLITE3_H_
|
||||||
@ -1575,6 +1575,7 @@ int sqlite3_create_module(
|
|||||||
const sqlite3_module *
|
const sqlite3_module *
|
||||||
);
|
);
|
||||||
|
|
||||||
|
int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Undo the hack that converts floating point types to integer for
|
** Undo the hack that converts floating point types to integer for
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** Internal interface definitions for SQLite.
|
** Internal interface definitions for SQLite.
|
||||||
**
|
**
|
||||||
** @(#) $Id: sqliteInt.h,v 1.498 2006/06/12 06:09:18 danielk1977 Exp $
|
** @(#) $Id: sqliteInt.h,v 1.499 2006/06/12 11:24:37 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef _SQLITEINT_H_
|
#ifndef _SQLITEINT_H_
|
||||||
#define _SQLITEINT_H_
|
#define _SQLITEINT_H_
|
||||||
@ -492,6 +492,7 @@ struct sqlite3 {
|
|||||||
#endif
|
#endif
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
Hash aModule; /* populated by sqlite3_create_module() */
|
Hash aModule; /* populated by sqlite3_create_module() */
|
||||||
|
Table *pVTab; /* vtab with active Connect/Create method */
|
||||||
#endif
|
#endif
|
||||||
Hash aFunc; /* All functions that can be in SQL exprs */
|
Hash aFunc; /* All functions that can be in SQL exprs */
|
||||||
Hash aCollSeq; /* All collating sequences */
|
Hash aCollSeq; /* All collating sequences */
|
||||||
@ -1283,9 +1284,16 @@ struct Parse {
|
|||||||
int nArgAlloc; /* Number of bytes allocated for zArg[] */
|
int nArgAlloc; /* Number of bytes allocated for zArg[] */
|
||||||
int nArgUsed; /* Number of bytes of zArg[] used so far */
|
int nArgUsed; /* Number of bytes of zArg[] used so far */
|
||||||
char *zArg; /* Complete text of a module argument */
|
char *zArg; /* Complete text of a module argument */
|
||||||
|
u8 declareVtab; /* True if inside sqlite3_declare_vtab() */
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef SQLITE_OMIT_VIRTUALTABLE
|
||||||
|
#define IN_DECLARE_VTAB 0
|
||||||
|
#else
|
||||||
|
#define IN_DECLARE_VTAB (pParse->declareVtab)
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** An instance of the following structure can be declared on a stack and used
|
** An instance of the following structure can be declared on a stack and used
|
||||||
** to save the Parse.zAuthContext value so that it can be restored later.
|
** to save the Parse.zAuthContext value so that it can be restored later.
|
||||||
@ -1791,6 +1799,7 @@ void sqlite3VtabFinishParse(Parse*, Token*);
|
|||||||
void sqlite3VtabArgInit(Parse*);
|
void sqlite3VtabArgInit(Parse*);
|
||||||
void sqlite3VtabArgExtend(Parse*, Token*);
|
void sqlite3VtabArgExtend(Parse*, Token*);
|
||||||
int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
|
int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
|
||||||
|
int sqlite3VtabCallConnect(Parse*, Table*);
|
||||||
|
|
||||||
#ifdef SQLITE_SSE
|
#ifdef SQLITE_SSE
|
||||||
#include "sseInt.h"
|
#include "sseInt.h"
|
||||||
|
44
src/test8.c
44
src/test8.c
@ -13,7 +13,7 @@
|
|||||||
** is not included in the SQLite library. It is used for automated
|
** is not included in the SQLite library. It is used for automated
|
||||||
** testing of the SQLite library.
|
** testing of the SQLite library.
|
||||||
**
|
**
|
||||||
** $Id: test8.c,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $
|
** $Id: test8.c,v 1.3 2006/06/12 11:24:37 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "tcl.h"
|
#include "tcl.h"
|
||||||
@ -30,6 +30,44 @@ static void appendToEchoModule(const sqlite3_module *pModule, const char *zArg){
|
|||||||
Tcl_SetVar((Tcl_Interp *)(pModule->pAux), "echo_module", zArg, flags);
|
Tcl_SetVar((Tcl_Interp *)(pModule->pAux), "echo_module", zArg, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This function is called from within the echo-modules xCreate and
|
||||||
|
** xConnect methods. The argc and argv arguments are copies of those
|
||||||
|
** passed to the calling method. This function is responsible for
|
||||||
|
** calling sqlite3_declare_vtab() to declare the schema of the virtual
|
||||||
|
** table being created or connected.
|
||||||
|
**
|
||||||
|
** If the constructor was passed just one argument, i.e.:
|
||||||
|
**
|
||||||
|
** CREATE TABLE t1 AS echo(t2);
|
||||||
|
**
|
||||||
|
** Then t2 is assumed to be the name of a *real* database table. The
|
||||||
|
** schema of the virtual table is declared by passing a copy of the
|
||||||
|
** CREATE TABLE statement for the real table to sqlite3_declare_vtab().
|
||||||
|
** Hence, the virtual table should have exactly the same column names and
|
||||||
|
** types as the real table.
|
||||||
|
*/
|
||||||
|
static int echoDeclareVtab(sqlite3 *db, int argc, char **argv){
|
||||||
|
int rc = SQLITE_OK;
|
||||||
|
|
||||||
|
if( argc==2 ){
|
||||||
|
sqlite3_stmt *pStmt = 0;
|
||||||
|
sqlite3_prepare(db,
|
||||||
|
"SELECT sql FROM sqlite_master WHERE type = 'table' AND name = ?",
|
||||||
|
-1, &pStmt, 0);
|
||||||
|
sqlite3_bind_text(pStmt, 1, argv[1], -1, 0);
|
||||||
|
if( sqlite3_step(pStmt)==SQLITE_ROW ){
|
||||||
|
const char *zCreateTable = sqlite3_column_text(pStmt, 0);
|
||||||
|
sqlite3_declare_vtab(db, zCreateTable);
|
||||||
|
} else {
|
||||||
|
rc = SQLITE_ERROR;
|
||||||
|
}
|
||||||
|
sqlite3_finalize(pStmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* Methods for the echo module */
|
/* Methods for the echo module */
|
||||||
static int echoCreate(
|
static int echoCreate(
|
||||||
sqlite3 *db,
|
sqlite3 *db,
|
||||||
@ -38,7 +76,6 @@ static int echoCreate(
|
|||||||
sqlite3_vtab **ppVtab
|
sqlite3_vtab **ppVtab
|
||||||
){
|
){
|
||||||
int i;
|
int i;
|
||||||
Tcl_Interp *interp = pModule->pAux;
|
|
||||||
*ppVtab = pModule->pAux;
|
*ppVtab = pModule->pAux;
|
||||||
|
|
||||||
appendToEchoModule(pModule, "xCreate");
|
appendToEchoModule(pModule, "xCreate");
|
||||||
@ -46,6 +83,7 @@ static int echoCreate(
|
|||||||
appendToEchoModule(pModule, argv[i]);
|
appendToEchoModule(pModule, argv[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echoDeclareVtab(db, argc, argv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int echoConnect(
|
static int echoConnect(
|
||||||
@ -63,6 +101,8 @@ static int echoConnect(
|
|||||||
Tcl_SetVar(interp, "echo_module", argv[i],
|
Tcl_SetVar(interp, "echo_module", argv[i],
|
||||||
TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
|
TCL_APPEND_VALUE | TCL_LIST_ELEMENT | TCL_GLOBAL_ONLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
echoDeclareVtab(db, argc, argv);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static int echoDisconnect(sqlite3_vtab *pVtab){
|
static int echoDisconnect(sqlite3_vtab *pVtab){
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
** individual tokens and sends those tokens one-by-one over to the
|
** individual tokens and sends those tokens one-by-one over to the
|
||||||
** parser for analysis.
|
** parser for analysis.
|
||||||
**
|
**
|
||||||
** $Id: tokenize.c,v 1.119 2006/06/11 23:41:56 drh Exp $
|
** $Id: tokenize.c,v 1.120 2006/06/12 11:24:37 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
@ -483,10 +483,19 @@ abort_parse:
|
|||||||
pParse->nTableLock = 0;
|
pParse->nTableLock = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
sqliteFree(pParse->zArg);
|
sqliteFree(pParse->zArg);
|
||||||
#endif
|
#endif
|
||||||
sqlite3DeleteTable(pParse->db, pParse->pNewTable);
|
|
||||||
|
if( !IN_DECLARE_VTAB ){
|
||||||
|
/* If the pParse->declareVtab flag is set, do not delete any table
|
||||||
|
** structure built up in pParse->pNewTable. The calling code (see vtab.c)
|
||||||
|
** will take responsibility for freeing the Table structure.
|
||||||
|
*/
|
||||||
|
sqlite3DeleteTable(pParse->db, pParse->pNewTable);
|
||||||
|
}
|
||||||
|
|
||||||
sqlite3DeleteTrigger(pParse->pNewTrigger);
|
sqlite3DeleteTrigger(pParse->pNewTrigger);
|
||||||
sqliteFree(pParse->apVarExpr);
|
sqliteFree(pParse->apVarExpr);
|
||||||
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
|
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){
|
||||||
|
107
src/vtab.c
107
src/vtab.c
@ -11,7 +11,7 @@
|
|||||||
*************************************************************************
|
*************************************************************************
|
||||||
** This file contains code used to help implement virtual tables.
|
** This file contains code used to help implement virtual tables.
|
||||||
**
|
**
|
||||||
** $Id: vtab.c,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $
|
** $Id: vtab.c,v 1.3 2006/06/12 11:24:37 danielk1977 Exp $
|
||||||
*/
|
*/
|
||||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||||
#include "sqliteInt.h"
|
#include "sqliteInt.h"
|
||||||
@ -128,7 +128,6 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
|
|||||||
if( pTab==0 ) return;
|
if( pTab==0 ) return;
|
||||||
db = pParse->db;
|
db = pParse->db;
|
||||||
if( pTab->nModuleArg<1 ) return;
|
if( pTab->nModuleArg<1 ) return;
|
||||||
pParse->pNewTable = 0;
|
|
||||||
zModule = pTab->azModuleArg[0];
|
zModule = pTab->azModuleArg[0];
|
||||||
pTab->pModule = (sqlite3_module*)sqlite3HashFind(&db->aModule,
|
pTab->pModule = (sqlite3_module*)sqlite3HashFind(&db->aModule,
|
||||||
zModule, strlen(zModule));
|
zModule, strlen(zModule));
|
||||||
@ -188,14 +187,10 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
|
|||||||
**
|
**
|
||||||
** TODO: If the module is already registered, should we call xConnect()
|
** TODO: If the module is already registered, should we call xConnect()
|
||||||
** here, or should it wait until the table is first referenced. Maybe
|
** 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.
|
** it's better to be lazy here, in case xConnect() is expensive to call
|
||||||
|
** and the schema is reparsed a number of times.
|
||||||
*/
|
*/
|
||||||
else {
|
else {
|
||||||
#if 0
|
|
||||||
sqlite3_module *pMod = pTab->pModule;
|
|
||||||
assert( pMod->xConnect );
|
|
||||||
pMod->xConnect(db, pMod, pTab->nModuleArg, pTab->azModuleArg, &pTab->pVtab);
|
|
||||||
#endif
|
|
||||||
Table *pOld;
|
Table *pOld;
|
||||||
Schema *pSchema = pTab->pSchema;
|
Schema *pSchema = pTab->pSchema;
|
||||||
const char *zName = pTab->zName;
|
const char *zName = pTab->zName;
|
||||||
@ -205,6 +200,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
|
|||||||
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
|
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
pParse->pNewTable = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,6 +234,84 @@ void sqlite3VtabArgExtend(Parse *pParse, Token *p){
|
|||||||
pParse->zArg[pParse->nArgUsed] = 0;
|
pParse->zArg[pParse->nArgUsed] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** This function is invoked by the parser to call the xConnect() method
|
||||||
|
** of table pTab. If an error occurs, an error code is returned and an error
|
||||||
|
** left in pParse.
|
||||||
|
*/
|
||||||
|
int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
|
||||||
|
sqlite3_module *pModule;
|
||||||
|
const char *zModule;
|
||||||
|
int rc = SQLITE_OK;
|
||||||
|
|
||||||
|
assert(pTab && pTab->isVirtual);
|
||||||
|
if( pTab->pVtab ){
|
||||||
|
return SQLITE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
pModule = pTab->pModule;
|
||||||
|
zModule = pTab->azModuleArg[0];
|
||||||
|
if( !pModule || !pModule->xConnect ){
|
||||||
|
const char *zModule = pTab->azModuleArg[0];
|
||||||
|
sqlite3ErrorMsg(pParse, "unknown module: %s", zModule);
|
||||||
|
rc = SQLITE_ERROR;
|
||||||
|
} else {
|
||||||
|
char **azArg = pTab->azModuleArg;
|
||||||
|
int nArg = pTab->nModuleArg;
|
||||||
|
assert( !pParse->db->pVTab );
|
||||||
|
pParse->db->pVTab = pTab;
|
||||||
|
rc = pModule->xConnect(pParse->db, pModule, nArg, azArg, &pTab->pVtab);
|
||||||
|
pParse->db->pVTab = 0;
|
||||||
|
if( rc ){
|
||||||
|
sqlite3ErrorMsg(pParse, "module connect failed: %s", zModule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
|
||||||
|
Parse sParse;
|
||||||
|
|
||||||
|
int rc = SQLITE_OK;
|
||||||
|
Table *pTab = db->pVTab;
|
||||||
|
char *zErr = 0;
|
||||||
|
|
||||||
|
if( !pTab ){
|
||||||
|
sqlite3Error(db, SQLITE_MISUSE, 0);
|
||||||
|
return SQLITE_MISUSE;
|
||||||
|
}
|
||||||
|
assert(pTab->isVirtual && pTab->nCol==0 && pTab->aCol==0);
|
||||||
|
|
||||||
|
memset(&sParse, 0, sizeof(Parse));
|
||||||
|
sParse.declareVtab = 1;
|
||||||
|
sParse.db = db;
|
||||||
|
|
||||||
|
if(
|
||||||
|
SQLITE_OK == sqlite3RunParser(&sParse, zCreateTable, &zErr) &&
|
||||||
|
sParse.pNewTable &&
|
||||||
|
!sParse.pNewTable->pSelect &&
|
||||||
|
!sParse.pNewTable->isVirtual
|
||||||
|
){
|
||||||
|
pTab->aCol = sParse.pNewTable->aCol;
|
||||||
|
pTab->nCol = sParse.pNewTable->nCol;
|
||||||
|
sParse.pNewTable->nCol = 0;
|
||||||
|
sParse.pNewTable->aCol = 0;
|
||||||
|
} else {
|
||||||
|
sqlite3Error(db, SQLITE_ERROR, zErr);
|
||||||
|
sqliteFree(zErr);
|
||||||
|
rc = SQLITE_ERROR;
|
||||||
|
}
|
||||||
|
sParse.declareVtab = 0;
|
||||||
|
|
||||||
|
sqlite3_finalize((sqlite3_stmt*)sParse.pVdbe);
|
||||||
|
sqlite3DeleteTable(0, sParse.pNewTable);
|
||||||
|
sParse.pNewTable = 0;
|
||||||
|
db->pVTab = 0;
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This function is invoked by the vdbe to call the xCreate method
|
** This function is invoked by the vdbe to call the xCreate method
|
||||||
** of the virtual table named zTab in database iDb.
|
** of the virtual table named zTab in database iDb.
|
||||||
@ -250,11 +324,12 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
|
|||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
Table *pTab;
|
Table *pTab;
|
||||||
sqlite3_module *pModule;
|
sqlite3_module *pModule;
|
||||||
|
const char *zModule;
|
||||||
|
|
||||||
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
|
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
|
||||||
assert(pTab && pTab->isVirtual);
|
assert(pTab && pTab->isVirtual && !pTab->pVtab);
|
||||||
pModule = pTab->pModule;
|
pModule = pTab->pModule;
|
||||||
const char *zModule = pTab->azModuleArg[0];
|
zModule = pTab->azModuleArg[0];
|
||||||
|
|
||||||
/* If the module has been registered and includes a Create method,
|
/* If the module has been registered and includes a Create method,
|
||||||
** invoke it now. If the module has not been registered, return an
|
** invoke it now. If the module has not been registered, return an
|
||||||
@ -264,10 +339,20 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
|
|||||||
*pzErr = sqlite3MPrintf("unknown module: %s", zModule);
|
*pzErr = sqlite3MPrintf("unknown module: %s", zModule);
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}else if( pModule->xCreate ){
|
}else if( pModule->xCreate ){
|
||||||
/* TODO: Maybe the above condition should refer to pTable->needCreate. */
|
|
||||||
char **azArg = pTab->azModuleArg;
|
char **azArg = pTab->azModuleArg;
|
||||||
int nArg = pTab->nModuleArg;
|
int nArg = pTab->nModuleArg;
|
||||||
|
assert( !db->pVTab );
|
||||||
|
db->pVTab = pTab;
|
||||||
|
rc = sqlite3SafetyOff(db);
|
||||||
|
assert( rc==SQLITE_OK );
|
||||||
rc = pModule->xCreate(db, pModule, nArg, azArg, &pTab->pVtab);
|
rc = pModule->xCreate(db, pModule, nArg, azArg, &pTab->pVtab);
|
||||||
|
db->pVTab = 0;
|
||||||
|
if( rc ){
|
||||||
|
*pzErr = sqlite3MPrintf("module create failed: %s", zModule);
|
||||||
|
sqlite3SafetyOn(db);
|
||||||
|
} else {
|
||||||
|
rc = sqlite3SafetyOn(db);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( SQLITE_OK==rc ){
|
if( SQLITE_OK==rc ){
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
# This file implements regression tests for SQLite library. The
|
# This file implements regression tests for SQLite library. The
|
||||||
# focus of this file is creating and dropping virtual tables.
|
# focus of this file is creating and dropping virtual tables.
|
||||||
#
|
#
|
||||||
# $Id: vtab1.test,v 1.2 2006/06/12 06:09:19 danielk1977 Exp $
|
# $Id: vtab1.test,v 1.3 2006/06/12 11:24:38 danielk1977 Exp $
|
||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
@ -48,4 +48,31 @@ do_test vtab1-1.5 {
|
|||||||
}
|
}
|
||||||
} {t1 {CREATE VIRTUAL TABLE t1 USING echo}}
|
} {t1 {CREATE VIRTUAL TABLE t1 USING echo}}
|
||||||
|
|
||||||
|
# If a single argument is passed to the echo module during table
|
||||||
|
# creation, it is assumed to be the name of a table in the same
|
||||||
|
# database. The echo module attempts to set the schema of the
|
||||||
|
# new virtual table to be the same as the existing database table.
|
||||||
|
#
|
||||||
|
do_test vtab1-2.1 {
|
||||||
|
execsql {
|
||||||
|
CREATE TABLE template(a, b, c);
|
||||||
|
}
|
||||||
|
execsql { PRAGMA table_info(template); }
|
||||||
|
} [list \
|
||||||
|
0 a {} 0 {} 0 \
|
||||||
|
1 b {} 0 {} 0 \
|
||||||
|
2 c {} 0 {} 0 \
|
||||||
|
]
|
||||||
|
do_test vtab1-2.2 {
|
||||||
|
execsql {
|
||||||
|
CREATE VIRTUAL TABLE t2 USING echo(template);
|
||||||
|
}
|
||||||
|
execsql { PRAGMA table_info(t2); }
|
||||||
|
} [list \
|
||||||
|
0 a {} 0 {} 0 \
|
||||||
|
1 b {} 0 {} 0 \
|
||||||
|
2 c {} 0 {} 0 \
|
||||||
|
]
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user