1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Add implementations for opcodes required for linear scans of virtual tables. (CVS 3223)

FossilOrigin-Name: 1f20e1832b38c76d2b0dde5fd720670c2ad0438b
This commit is contained in:
danielk1977
2006-06-13 10:24:42 +00:00
parent 48d4580650
commit b7a7b9a3b9
8 changed files with 343 additions and 64 deletions

View File

@@ -1,5 +1,5 @@
C Bugfixes:\sFix\sa\ssegfault\sintroduced\sas\spart\sof\sthe\snew\svtab\scode,\sdeallocate\smemory\sin\sthe\sDestroy()\smethod\sof\sthe\secho\smodule.\s(CVS\s3222) C Add\simplementations\sfor\sopcodes\srequired\sfor\slinear\sscans\sof\svirtual\stables.\s(CVS\s3223)
D 2006-06-13T04:11:44 D 2006-06-13T10:24:43
F Makefile.in 56fd6261e83f60724e6dcd764e06ab68cbd53909 F Makefile.in 56fd6261e83f60724e6dcd764e06ab68cbd53909
F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -74,7 +74,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 55bf6335dae7146f7a300039f5d6bb35010f1996 F src/shell.c 55bf6335dae7146f7a300039f5d6bb35010f1996
F src/sqlite.h.in 6fb7062da7e9c446623fa26b042bcf4b4050d702 F src/sqlite.h.in 6fb7062da7e9c446623fa26b042bcf4b4050d702
F src/sqlite3ext.h 127bd394c8eea481f2ac9b754bf399dbfc818b75 F src/sqlite3ext.h 127bd394c8eea481f2ac9b754bf399dbfc818b75
F src/sqliteInt.h 9562411b336b77123d1f569d4144fe3ba1ecb3bf F src/sqliteInt.h 91cc3603fe2e1be18d52490a2fa65ed9640fb338
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,7 +84,7 @@ 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 c85eba7e98405e6c3d22ece241ee4e9ea4d154f8 F src/test8.c d29427a0254f7609b0dd2561e62cf78e21c9d689
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
@@ -94,14 +94,14 @@ F src/update.c 0186f09414a6578156d40666becc964f85c2a616
F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44 F src/utf.c ab81ac59084ff1c07d421eb1a0a84ec809603b44
F src/util.c ca6ee72772c0f5dc04d2e0ab1973fd3b6a9bf79d F src/util.c ca6ee72772c0f5dc04d2e0ab1973fd3b6a9bf79d
F src/vacuum.c 5b37d0f436f8e1ffacd17934e44720b38d2247f9 F src/vacuum.c 5b37d0f436f8e1ffacd17934e44720b38d2247f9
F src/vdbe.c 59cb0d8cd19f090061f41715c44b3ed2af6bf264 F src/vdbe.c 1f68000f8690e13535106f1b1bbaedc2da045457
F src/vdbe.h f72e5c00af759b7ed6fd606d508036d732098cc3 F src/vdbe.h f72e5c00af759b7ed6fd606d508036d732098cc3
F src/vdbeInt.h 6ccb7eaae76ebd761470f6a035501ff33aa92c20 F src/vdbeInt.h 6ccb7eaae76ebd761470f6a035501ff33aa92c20
F src/vdbeapi.c 7dc662e7c905ce666bb506dced932e0307115cbf F src/vdbeapi.c 7dc662e7c905ce666bb506dced932e0307115cbf
F src/vdbeaux.c bcad5264196266118eb4ed0b2db3829fe335a67d F src/vdbeaux.c 0168d770d03f9815511780a49cd8360d9a5f1ec5
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3 F src/vdbemem.c 5f0afe3b92bb2c037f8d5d697f7c151fa50783a3
F src/vtab.c 4ec6ac7e5e4fccb38401285d0e329d018622859f F src/vtab.c 0e39af5822bb17b0007b0df7fad527aa0e3ebd38
F src/where.c c0f3cd3831cd9defb7c7788038d439a5922e7bd6 F src/where.c c0f3cd3831cd9defb7c7788038d439a5922e7bd6
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 b3a93d0b4667bf27adfbb555154086c7e25ee597 F test/vtab1.test 67fed6f9b91b75d3e1988b47a972b30dd5ed2d97
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 f9ea9704755eee3fd29af7a47be1d41620be8835 P 00f3c249bc79556d0cb3999f543887bd4f160347
R b50ded4b4061c3fa2b3bc042599da575 R 0931417f268857ba4bba3e3f6b5bc6db
U danielk1977 U danielk1977
Z 42d9f8623c9300c98d0eb90f55c29716 Z 7ec75a36e0232c7c8167de06e4e6d3ac

View File

@@ -1 +1 @@
00f3c249bc79556d0cb3999f543887bd4f160347 1f20e1832b38c76d2b0dde5fd720670c2ad0438b

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** Internal interface definitions for SQLite.
** **
** @(#) $Id: sqliteInt.h,v 1.502 2006/06/12 21:59:14 drh Exp $ ** @(#) $Id: sqliteInt.h,v 1.503 2006/06/13 10:24:43 danielk1977 Exp $
*/ */
#ifndef _SQLITEINT_H_ #ifndef _SQLITEINT_H_
#define _SQLITEINT_H_ #define _SQLITEINT_H_
@@ -709,7 +709,6 @@ struct Table {
sqlite3_vtab *pVtab; /* Pointer to the module instance */ sqlite3_vtab *pVtab; /* Pointer to the module instance */
int nModuleArg; /* Number of arguments to the module */ int nModuleArg; /* Number of arguments to the module */
char **azModuleArg; /* Text of all module args. [0] is module name */ 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 */ u8 isVirtual; /* True if this is a virtual table */
#endif #endif
Schema *pSchema; Schema *pSchema;

View File

@@ -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.7 2006/06/13 04:11:44 danielk1977 Exp $ ** $Id: test8.c,v 1.8 2006/06/13 10:24:43 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "tcl.h" #include "tcl.h"
@@ -21,6 +21,24 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
typedef struct echo_vtab echo_vtab;
typedef struct echo_cursor echo_cursor;
/* An echo vtab object */
struct echo_vtab {
sqlite3_vtab base;
Tcl_Interp *interp;
sqlite3 *db;
char *zStmt;
};
/* An echo cursor object */
struct echo_cursor {
sqlite3_vtab_cursor base;
sqlite3_stmt *pStmt;
int errcode; /* Error code */
};
/* /*
** Global Tcl variable $echo_module is a list. This routine appends ** Global Tcl variable $echo_module is a list. This routine appends
** the string element zArg to that list in interpreter interp. ** the string element zArg to that list in interpreter interp.
@@ -47,7 +65,12 @@ static void appendToEchoModule(Tcl_Interp *interp, const char *zArg){
** Hence, the virtual table should have exactly the same column names and ** Hence, the virtual table should have exactly the same column names and
** types as the real table. ** types as the real table.
*/ */
static int echoDeclareVtab(sqlite3 *db, int argc, char **argv){ static int echoDeclareVtab(
echo_vtab *pVtab,
sqlite3 *db,
int argc,
char **argv
){
int rc = SQLITE_OK; int rc = SQLITE_OK;
if( argc==2 ){ if( argc==2 ){
@@ -65,17 +88,34 @@ static int echoDeclareVtab(sqlite3 *db, int argc, char **argv){
rc = SQLITE_ERROR; rc = SQLITE_ERROR;
} }
sqlite3_finalize(pStmt); sqlite3_finalize(pStmt);
pVtab->zStmt = sqlite3MPrintf("SELECT rowid, * FROM %s ", argv[1]);
} }
return rc; return rc;
} }
/* An echo vtab object */ static int echoConstructor(
typedef struct echo_vtab echo_vtab; sqlite3 *db,
struct echo_vtab { const sqlite3_module *pModule,
sqlite3_vtab base; int argc, char **argv,
Tcl_Interp *interp; sqlite3_vtab **ppVtab
}; ){
int i;
echo_vtab *pVtab;
pVtab = sqliteMalloc( sizeof(*pVtab) );
*ppVtab = &pVtab->base;
pVtab->base.pModule = pModule;
pVtab->interp = pModule->pAux;
pVtab->db = db;
for(i=0; i<argc; i++){
appendToEchoModule(pVtab->interp, argv[i]);
}
echoDeclareVtab(pVtab, db, argc, argv);
return 0;
}
/* Methods for the echo module */ /* Methods for the echo module */
static int echoCreate( static int echoCreate(
@@ -84,20 +124,8 @@ static int echoCreate(
int argc, char **argv, int argc, char **argv,
sqlite3_vtab **ppVtab sqlite3_vtab **ppVtab
){ ){
int i; appendToEchoModule((Tcl_Interp *)(pModule->pAux), "xCreate");
echo_vtab *pVtab; return echoConstructor(db, pModule, argc, argv, ppVtab);
pVtab = sqliteMalloc( sizeof(*pVtab) );
*ppVtab = &pVtab->base;
pVtab->base.pModule = pModule;
pVtab->interp = pModule->pAux;
appendToEchoModule(pVtab->interp, "xCreate");
for(i=0; i<argc; i++){
appendToEchoModule(pVtab->interp, argv[i]);
}
echoDeclareVtab(db, argc, argv);
return 0;
} }
static int echoConnect( static int echoConnect(
sqlite3 *db, sqlite3 *db,
@@ -105,35 +133,122 @@ static int echoConnect(
int argc, char **argv, int argc, char **argv,
sqlite3_vtab **ppVtab sqlite3_vtab **ppVtab
){ ){
int i; appendToEchoModule((Tcl_Interp *)(pModule->pAux), "xConnect");
Tcl_Interp *interp = pModule->pAux; return echoConstructor(db, pModule, argc, argv, ppVtab);
echo_vtab *pVtab;
pVtab = sqliteMalloc( sizeof(*pVtab) );
*ppVtab = &pVtab->base;
pVtab->base.pModule = pModule;
pVtab->interp = pModule->pAux;
appendToEchoModule(pVtab->interp, "xConnect");
for(i=0; i<argc; i++){
appendToEchoModule(pVtab->interp, argv[i]);
}
echoDeclareVtab(db, argc, argv);
return 0;
} }
static int echoDisconnect(sqlite3_vtab *pVtab){ static int echoDisconnect(sqlite3_vtab *pVtab){
echo_vtab *p = (echo_vtab*)pVtab; echo_vtab *p = (echo_vtab*)pVtab;
appendToEchoModule(p->interp, "xDisconnect"); appendToEchoModule(p->interp, "xDisconnect");
sqliteFree(pVtab); sqliteFree(p->zStmt);
sqliteFree(p);
return 0; return 0;
} }
static int echoDestroy(sqlite3_vtab *pVtab){ static int echoDestroy(sqlite3_vtab *pVtab){
echo_vtab *p = (echo_vtab*)pVtab; echo_vtab *p = (echo_vtab*)pVtab;
appendToEchoModule(p->interp, "xDestroy"); appendToEchoModule(p->interp, "xDestroy");
sqliteFree(pVtab); sqliteFree(p->zStmt);
sqliteFree(p);
return 0; return 0;
} }
static int echoOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor)
{
echo_cursor *pCur;
pCur = sqliteMalloc(sizeof(echo_cursor));
*ppCursor = (sqlite3_vtab_cursor *)pCur;
return SQLITE_OK;
}
static int echoClose(sqlite3_vtab_cursor *cur)
{
echo_cursor *pCur = (echo_cursor *)cur;
sqlite3_finalize(pCur->pStmt);
sqliteFree(pCur);
return SQLITE_OK;
}
static int echoNext(sqlite3_vtab_cursor *cur)
{
int rc;
echo_cursor *pCur = (echo_cursor *)cur;
rc = sqlite3_step(pCur->pStmt);
if( rc==SQLITE_ROW ){
rc = 1;
} else {
pCur->errcode = sqlite3_finalize(pCur->pStmt);
pCur->pStmt = 0;
rc = 0;
}
return rc;
}
static int echoFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idx,
int argc,
sqlite3_value **argv
){
int rc;
echo_cursor *pCur = (echo_cursor *)pVtabCursor;
echo_vtab *pVtab = (echo_vtab *)pVtabCursor->pVtab;
sqlite3 *db = pVtab->db;
sqlite3_finalize(pCur->pStmt);
pCur->pStmt = 0;
rc = sqlite3_prepare(db, pVtab->zStmt, -1, &pCur->pStmt, 0);
if( rc==SQLITE_OK ){
rc = echoNext(pVtabCursor);
}
return rc;
}
static int echoColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i)
{
int iCol = i + 1;
sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt;
assert( sqlite3_data_count(pStmt)>iCol );
switch( sqlite3_column_type(pStmt, iCol) ){
case SQLITE_INTEGER:
sqlite3_result_int64(ctx, sqlite3_column_int64(pStmt, iCol));
break;
case SQLITE_FLOAT:
sqlite3_result_double(ctx, sqlite3_column_double(pStmt, iCol));
break;
case SQLITE_TEXT:
sqlite3_result_text(ctx,
sqlite3_column_text(pStmt, iCol),
sqlite3_column_bytes(pStmt, iCol),
SQLITE_TRANSIENT
);
break;
case SQLITE_BLOB:
sqlite3_result_blob(ctx,
sqlite3_column_blob(pStmt, iCol),
sqlite3_column_bytes(pStmt, iCol),
SQLITE_TRANSIENT
);
break;
}
return SQLITE_OK;
}
static int echoRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid)
{
sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt;
*pRowid = sqlite3_column_int64(pStmt, 0);
return SQLITE_OK;
}
/* /*
** The xBestIndex method for the echo module always returns ** The xBestIndex method for the echo module always returns
** an index of 123. ** an index of 123.
@@ -156,6 +271,12 @@ static sqlite3_module echoModule = {
echoBestIndex, echoBestIndex,
echoDisconnect, echoDisconnect,
echoDestroy, echoDestroy,
echoOpen, /* xOpen - open a cursor */
echoClose, /* xClose - close a cursor */
echoFilter, /* xFilter - configure scan constraints */
echoNext, /* xNext - advance a cursor */
echoColumn, /* xColumn - read data */
echoRowid /* xRowid - read data */
}; };
/* /*

View File

@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing ** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code. ** commenting and indentation practices when changing or adding code.
** **
** $Id: vdbe.c,v 1.554 2006/06/12 21:59:14 drh Exp $ ** $Id: vdbe.c,v 1.555 2006/06/13 10:24:43 danielk1977 Exp $
*/ */
#include "sqliteInt.h" #include "sqliteInt.h"
#include "os.h" #include "os.h"
@@ -4565,6 +4565,24 @@ case OP_VDestroy: {
** table and stores that cursor in P1. ** table and stores that cursor in P1.
*/ */
case OP_VOpen: { case OP_VOpen: {
Cursor *pCur = 0;
sqlite3_vtab_cursor *pVtabCursor = 0;
sqlite3_vtab *pVtab = (sqlite3_vtab *)(pOp->p3);
sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule;
assert(pVtab && pModule);
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xOpen(pVtab, &pVtabCursor);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( SQLITE_OK==rc ){
/* Initialise sqlite3_vtab_cursor base class */
pVtabCursor->pVtab = pVtab;
/* Initialise vdbe cursor object */
pCur = allocateCursor(p, pOp->p1, -1);
pCur->pVtabCursor = pVtabCursor;
}
break; break;
} }
#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -4579,13 +4597,48 @@ case OP_VOpen: {
** by P1. The index number parameter to xFilter is the top of the stack. ** by P1. The index number parameter to xFilter is the top of the stack.
** Next down on the stack is the argc parameter. Beneath the ** Next down on the stack is the argc parameter. Beneath the
** next of stack are argc additional parameters which are passed to ** next of stack are argc additional parameters which are passed to
** xFilter as argv. The index number, argc, and all argv stack values ** xFilter as argv. The topmost parameter (i.e. 3rd element popped from
** are popped from the stack before this instruction completes. ** the stack) becomes argv[argc-1] when passed to xFilter.
**
** The index number, argc, and all argv stack values are popped from the
** stack before this instruction completes.
** **
** A jump is made to P2 if the result set after filtering would be ** A jump is made to P2 if the result set after filtering would be
** empty. ** empty.
*/ */
case OP_VFilter: { case OP_VFilter: {
int iIndex;
int nArg;
const sqlite3_module *pModule;
Cursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
pModule = pCur->pVtabCursor->pVtab->pModule;
/* Grab the index number and argc parameters off the top of the stack. */
assert( (&pTos[-1])>=p->aStack );
assert( pTos[0].flags==MEM_Int && pTos[-1].flags==MEM_Int );
iIndex = pTos[0].i;
nArg = pTos[-1].i;
/* Invoke the xFilter method if one is defined. */
if( pModule->xFilter ){
int res;
Mem *apArg;
apArg = &pTos[1-2-nArg];
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
res = pModule->xFilter(pCur->pVtabCursor, iIndex, nArg, &apArg);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( res==0 ){
pc = pOp->p2 - 1;
}
}
/* Pop the index number, argc value and parameters off the stack */
popStack(&pTos, 2+nArg);
break; break;
} }
#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -4597,6 +4650,26 @@ case OP_VFilter: {
** the virtual-table that the P1 cursor is pointing to. ** the virtual-table that the P1 cursor is pointing to.
*/ */
case OP_VRowid: { case OP_VRowid: {
const sqlite3_module *pModule;
Cursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
pModule = pCur->pVtabCursor->pVtab->pModule;
if( pModule->xRowid==0 ){
sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xRowid", 0);
rc = SQLITE_ERROR;
} else {
sqlite_int64 iRow;
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
pTos++;
pTos->flags = MEM_Int;
pTos->i = iRow;
}
break; break;
} }
#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -4608,6 +4681,33 @@ case OP_VRowid: {
** the row of the virtual-table that the P1 cursor is pointing to. ** the row of the virtual-table that the P1 cursor is pointing to.
*/ */
case OP_VColumn: { case OP_VColumn: {
const sqlite3_module *pModule;
Cursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
pModule = pCur->pVtabCursor->pVtab->pModule;
if( pModule->xColumn==0 ){
sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xColumn", 0);
rc = SQLITE_ERROR;
} else {
sqlite3_context sContext;
memset(&sContext, 0, sizeof(sContext));
sContext.s.flags = MEM_Null;
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
/* Copy the result of the function to the top of the stack. We
** do this regardless of whether or not an error occured to ensure any
** dynamic allocation in sContext.s (a Mem struct) is released.
*/
sqlite3VdbeChangeEncoding(&sContext.s, encoding);
pTos++;
pTos->flags = 0;
sqlite3VdbeMemMove(pTos, &sContext.s);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
}
break; break;
} }
#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -4620,6 +4720,32 @@ case OP_VColumn: {
** the end of its result set, then fall through to the next instruction. ** the end of its result set, then fall through to the next instruction.
*/ */
case OP_VNext: { case OP_VNext: {
const sqlite3_module *pModule;
int res = 0;
Cursor *pCur = p->apCsr[pOp->p1];
assert( pCur->pVtabCursor );
pModule = pCur->pVtabCursor->pVtab->pModule;
if( pModule->xNext==0 ){
sqlite3SetString(&p->zErrMsg, "Unsupported module operation: xNext", 0);
rc = SQLITE_ERROR;
} else {
/* Invoke the xNext() method of the module. There is no way for the
** underlying implementation to return an error if one occurs during
** xNext(). Instead, if an error occurs, true is returned (indicating that
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
res = pModule->xNext(pCur->pVtabCursor);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( res ){
/* If there is data (or an error), jump to P2 */
pc = pOp->p2 - 1;
}
}
break; break;
} }
#endif /* SQLITE_OMIT_VIRTUALTABLE */ #endif /* SQLITE_OMIT_VIRTUALTABLE */

View File

@@ -839,7 +839,7 @@ void sqlite3VdbeFreeCursor(Cursor *pCx){
if( pCx->pVtabCursor ){ if( pCx->pVtabCursor ){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor; sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
sqlite3_vtab *pVtab = pVtabCursor->pVtab; sqlite3_vtab *pVtab = pVtabCursor->pVtab;
sqlite3_module *pModule = pVtab->pModule; const sqlite3_module *pModule = pVtab->pModule;
pModule->xClose(pVtabCursor); pModule->xClose(pVtabCursor);
} }
#endif #endif

View File

@@ -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.5 2006/06/12 16:01:22 danielk1977 Exp $ ** $Id: vtab.c,v 1.6 2006/06/13 10:24:43 danielk1977 Exp $
*/ */
#ifndef SQLITE_OMIT_VIRTUALTABLE #ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h" #include "sqliteInt.h"
@@ -367,9 +367,6 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){
} }
} }
if( SQLITE_OK==rc ){
pTab->needCreate = 0;
}
return rc; return rc;
} }

View File

@@ -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.7 2006/06/13 04:11:44 danielk1977 Exp $ # $Id: vtab1.test,v 1.8 2006/06/13 10:24:44 danielk1977 Exp $
set testdir [file dirname $argv0] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@@ -110,8 +110,6 @@ do_test vtab1-2.5 {
set echo_module set echo_module
} [list xDestroy] } [list xDestroy]
finish_test
do_test vtab1-2.6 { do_test vtab1-2.6 {
execsql { execsql {
PRAGMA table_info(t2); PRAGMA table_info(t2);
@@ -138,4 +136,42 @@ do_test vtab1-2.9 {
} }
} [list] } [list]
#----------------------------------------------------------------------
# Test case vtab1-3 tests simple linear scans (no filter conditions) of
# virtual table modules.
do_test vtab1-3.1 {
set echo_module ""
execsql {
CREATE TABLE treal(a INTEGER, b VARCHAR(32), c);
CREATE VIRTUAL TABLE t1 USING echo(treal);
}
set echo_module
} [list xCreate echo treal]
do_test vtab1-3.2 {
# Test that a SELECT on t2 doesn't crash. No rows are returned
# because the underlying real table, is currently empty.
execsql {
SELECT a, b, c FROM t1;
}
} {}
do_test vtab1-3.3 {
# Put some data into the table treal. Then try a select on t1.
execsql {
INSERT INTO treal VALUES(1, 2, 3);
INSERT INTO treal VALUES(4, 5, 6);
SELECT * FROM t1;
}
} {1 2 3 4 5 6}
do_test vtab1-3.4 {
execsql {
SELECT a FROM t1;
}
} {1 4}
do_test vtab1-3.5 {
execsql {
SELECT rowid FROM t1;
}
} {1 2}
finish_test finish_test