1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-10-27 08:52:26 +03:00

The echo module test is now running. Added the tclvar module test but have

not yet done anything with it. (CVS 3234)

FossilOrigin-Name: 29199eeea4c46168ccaa7535d4941bd740479dee
This commit is contained in:
drh
2006-06-13 23:51:34 +00:00
parent 88897a72e9
commit 4be8b51ee1
15 changed files with 357 additions and 159 deletions

View File

@@ -12,7 +12,7 @@
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.173 2006/06/13 15:00:55 danielk1977 Exp $
** @(#) $Id: sqlite.h.in,v 1.174 2006/06/13 23:51:34 drh Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
@@ -926,6 +926,7 @@ const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
int sqlite3_column_type(sqlite3_stmt*, int iCol);
int sqlite3_column_numeric_type(sqlite3_stmt*, int iCol);
sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
/*
** The sqlite3_finalize() function is called to delete a compiled
@@ -1547,7 +1548,7 @@ struct sqlite3_module {
int (*xDestroy)(sqlite3_vtab *pVTab);
int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
int (*xClose)(sqlite3_vtab_cursor*);
int (*xFilter)(sqlite3_vtab_cursor*, char *zPlan, int nPlan,
int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
int argc, sqlite3_value **argv);
int (*xNext)(sqlite3_vtab_cursor*);
int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
@@ -1595,7 +1596,8 @@ struct sqlite3_module {
** is true, then the constraint is assumed to be fully handled by the
** virtual table and is not checked again by SQLite.
**
** The idxNum value is recorded and passed into xFilter.
** The idxNum and idxPtr values are recorded and passed into xFilter.
** sqlite3_free() is used to free idxPtr if needToFreeIdxPtr is true.
**
** The orderByConsumed means that output from xFilter will occur in
** the correct order to satisfy the ORDER BY clause so that no separate
@@ -1626,10 +1628,9 @@ struct sqlite3_index_info {
int argvIndex; /* if >0, constraint is part of argv to xFilter */
unsigned char omit; /* Do not code a test for this constraint */
} *const aConstraintUsage;
char *zPlan; /* xBestIndex blob passed to xFilter */
int nPlan; /* Size of nPlan */
int idxNum; /* Number used to identify the index */
char *idxStr; /* String, possibly obtained from sqlite3_malloc */
int needToFreeIdxStr; /* Free idxStr using sqlite3_free() if true */
int orderByConsumed; /* True if output is already ordered */
double estimatedCost; /* Estimated cost of using this index */
};
@@ -1685,13 +1686,6 @@ struct sqlite3_vtab_cursor {
*/
int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);
/*
** This function is called by the xBestIndex method of a module to
** allocate space to store the query-plan passed to the corresponding
** xFilter invocation(s).
*/
char *sqlite3_allocate_queryplan(sqlite3_index_info *, int);
/*
** The interface to the virtual-table mechanism defined above (back up
** to a comment remarkably similar to this one) is currently considered

View File

@@ -11,7 +11,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
** $Id: tclsqlite.c,v 1.157 2006/06/11 23:41:56 drh Exp $
** $Id: tclsqlite.c,v 1.158 2006/06/13 23:51:35 drh Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@@ -2155,6 +2155,7 @@ int TCLSH_MAIN(int argc, char **argv){
extern int Md5_Init(Tcl_Interp*);
extern int Sqlitetestsse_Init(Tcl_Interp*);
extern int Sqlitetestasync_Init(Tcl_Interp*);
extern int Sqlitetesttclvar_Init(Tcl_Interp*);
Sqlitetest1_Init(interp);
Sqlitetest2_Init(interp);
@@ -2165,6 +2166,7 @@ int TCLSH_MAIN(int argc, char **argv){
Sqlitetest7_Init(interp);
Sqlitetest8_Init(interp);
Sqlitetestasync_Init(interp);
Sqlitetesttclvar_Init(interp);
Md5_Init(interp);
#ifdef SQLITE_SSE
Sqlitetestsse_Init(interp);

View File

@@ -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.10 2006/06/13 15:00:55 danielk1977 Exp $
** $Id: test8.c,v 1.11 2006/06/13 23:51:35 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -35,6 +35,7 @@ struct echo_vtab {
sqlite3_vtab base;
Tcl_Interp *interp;
sqlite3 *db;
char *zTableName; /* Name of the real table */
char *zStmt; /* "SELECT rowid, * FROM <real-table-name> " */
int *aIndex;
@@ -224,6 +225,7 @@ static int echoConstructor(
pVtab->base.pModule = pModule;
pVtab->interp = pModule->pAux;
pVtab->db = db;
pVtab->zTableName = sqlite3MPrintf("%s", argv[1]);
for(i=0; i<argc; i++){
appendToEchoModule(pVtab->interp, argv[i]);
}
@@ -261,6 +263,7 @@ static int echoDestructor(sqlite3_vtab *pVtab){
sqliteFree(p->aCol[ii]);
}
sqliteFree(p->aCol);
sqliteFree(p->zTableName);
sqliteFree(p);
return 0;
}
@@ -310,28 +313,7 @@ static int echoColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
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;
}
sqlite3_result_value(ctx, sqlite3_column_value(pStmt, iCol));
return SQLITE_OK;
}
@@ -344,31 +326,55 @@ static int echoRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
static int echoFilter(
sqlite3_vtab_cursor *pVtabCursor,
char *zPlan, int nPlan,
int argc,
sqlite3_value **argv
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
int rc;
int ii;
int i;
echo_cursor *pCur = (echo_cursor *)pVtabCursor;
echo_vtab *pVtab = (echo_vtab *)pVtabCursor->pVtab;
sqlite3 *db = pVtab->db;
appendToEchoModule(pVtab->interp, "xFilter");
appendToEchoModule(pVtab->interp, zPlan);
for(ii=0; ii<argc; ii++){
appendToEchoModule(pVtab->interp, sqlite3_value_text(argv[ii]));
}
sqlite3_finalize(pCur->pStmt);
pCur->pStmt = 0;
rc = sqlite3_prepare(db, pVtab->zStmt, -1, &pCur->pStmt, 0);
rc = sqlite3_prepare(db, idxStr, -1, &pCur->pStmt, 0);
for(i=0; i<argc; i++){
switch( sqlite3_value_type(argv[i]) ){
case SQLITE_INTEGER: {
sqlite3_bind_int64(pCur->pStmt, i+1, sqlite3_value_int64(argv[i]));
break;
}
case SQLITE_FLOAT: {
sqlite3_bind_double(pCur->pStmt, i+1, sqlite3_value_double(argv[i]));
break;
}
case SQLITE_NULL: {
sqlite3_bind_null(pCur->pStmt, i+1);
break;
}
case SQLITE_TEXT: {
sqlite3_bind_text(pCur->pStmt, i+1, sqlite3_value_text(argv[i]),
sqlite3_value_bytes(argv[i]), SQLITE_TRANSIENT);
break;
}
case SQLITE_BLOB: {
sqlite3_bind_blob(pCur->pStmt, i+1, sqlite3_value_blob(argv[i]),
sqlite3_value_bytes(argv[i]), SQLITE_TRANSIENT);
break;
}
}
}
if( rc==SQLITE_OK ){
rc = echoNext(pVtabCursor);
}
appendToEchoModule(pVtab->interp, "xFilter");
appendToEchoModule(pVtab->interp, idxStr);
for(i=0; i<argc; i++){
appendToEchoModule(pVtab->interp, sqlite3_value_text(argv[i]));
}
return rc;
}
@@ -386,13 +392,13 @@ static int echoFilter(
*/
static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
int ii;
char *zWhere = 0;
char *zOrder = 0;
char *zPlan = 0;
int nPlan = 0;
char *zQuery = 0;
char *zNew;
int nArg = 0;
const char *zSep = "WHERE";
echo_vtab *pVtab = (echo_vtab *)tab;
zQuery = sqlite3_mprintf("SELECT rowid, * FROM %Q", pVtab->zTableName);
for(ii=0; ii<pIdxInfo->nConstraint; ii++){
const struct sqlite3_index_constraint *pConstraint;
struct sqlite3_index_constraint_usage *pUsage;
@@ -418,39 +424,20 @@ static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
case SQLITE_INDEX_CONSTRAINT_MATCH:
zOp = "MATCH"; break;
}
if( zWhere ){
char *zTmp = zWhere;
zWhere = sqlite3MPrintf("%s AND %s %s ?", zWhere, zCol, zOp);
sqliteFree(zTmp);
} else {
zWhere = sqlite3MPrintf("WHERE %s %s ?", zCol, zOp);
}
zNew = sqlite3_mprintf("%s %s %s %s ?", zQuery, zSep, zCol, zOp);
sqlite3_free(zQuery);
zQuery = zNew;
zSep = "AND";
pUsage->argvIndex = ++nArg;
pUsage->omit = 1;
}
}
appendToEchoModule(pVtab->interp, "xBestIndex");;
appendToEchoModule(pVtab->interp, zWhere);
appendToEchoModule(pVtab->interp, zOrder);
nPlan = 2;
if( zWhere ){
nPlan += strlen(zWhere);
}
if( zOrder ){
nPlan += strlen(zWhere);
}
zPlan = sqlite3_allocate_queryplan(pIdxInfo, nPlan);
if( zPlan ){
sprintf(zPlan, "%s%s%s",
zWhere?zWhere:"", (zOrder&&zWhere)?" ":"", zOrder?zOrder:"");
}
sqliteFree(zWhere);
sqliteFree(zOrder);
appendToEchoModule(pVtab->interp, zQuery);
pIdxInfo->idxStr = zQuery;
pIdxInfo->needToFreeIdxStr = 1;
pIdxInfo->estimatedCost = 1.0;
return SQLITE_OK;
}

193
src/test_tclvar.c Normal file
View File

@@ -0,0 +1,193 @@
/*
** 2006 June 13
**
** 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.
**
** The emphasis of this file is a virtual table that provides
** access to TCL variables.
**
** $Id: test_tclvar.c,v 1.1 2006/06/13 23:51:35 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>
typedef struct tclvar_vtab tclvar_vtab;
typedef struct tclvar_cursor tclvar_cursor;
/*
** A tclvar virtual-table object
*/
struct tclvar_vtab {
sqlite3_vtab base;
Tcl_Interp *interp;
};
/* A tclvar cursor object */
struct tclvar_cursor {
sqlite3_vtab_cursor base;
Tcl_Obj *pList1, *pList2;
int i, j;
};
/* Methods for the tclvar module */
static int tclvarConnect(
sqlite3 *db,
const sqlite3_module *pModule,
int argc, char **argv,
sqlite3_vtab **ppVtab
){
tclvar_vtab *pVtab;
static const char zSchema[] =
"CREATE TABLE whatever(name TEXT, arrayname TEXT, value TEXT)";
pVtab = sqliteMalloc( sizeof(*pVtab) );
if( pVtab==0 ) return SQLITE_NOMEM;
*ppVtab = &pVtab->base;
pVtab->base.pModule = pModule;
pVtab->interp = pModule->pAux;
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_declare_vtab(db, zSchema);
#endif
return SQLITE_OK;
}
/* Note that for this virtual table, the xCreate and xConnect
** methods are identical. */
static int tclvarDisconnect(sqlite3_vtab *pVtab){
free(pVtab);
}
/* The xDisconnect and xDestroy methods are also the same */
static int tclvarOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
tclvar_cursor *pCur;
pCur = sqliteMalloc(sizeof(tclvar_cursor));
*ppCursor = &pCur->base;
return SQLITE_OK;
}
static int tclvarClose(sqlite3_vtab_cursor *cur){
tclvar_cursor *pCur = (tclvar_cursor *)cur;
if( pCur->pList1 ){
Tcl_DecrRefCount(pCur->pList1);
}
if( pCur->pList2 ){
Tcl_DecrRefCount(pCur->pList2);
}
sqliteFree(pCur);
return SQLITE_OK;
}
static int tclvarNext(sqlite3_vtab_cursor *cur){
tclvar_cursor *pCur = (tclvar_cursor *)cur;
return 0;
}
static int tclvarColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
tclvar_cursor *pCur = (tclvar_cursor*)cur;
return SQLITE_OK;
}
static int tclvarRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
tclvar_cursor *pCur = (tclvar_cursor*)cur;
return SQLITE_OK;
}
static int tclvarFilter(
sqlite3_vtab_cursor *pVtabCursor,
int idxNum, const char *idxStr,
int argc, sqlite3_value **argv
){
tclvar_cursor *pCur = (tclvar_cursor *)pVtabCursor;
tclvar_vtab *pVtab = (tclvar_vtab *)pCur->base.pVtab;
return 0;
}
/*
*/
static int tclvarBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
tclvar_vtab *pVtab = (tclvar_vtab *)tab;
return SQLITE_OK;
}
/*
** A virtual table module that merely echos method calls into TCL
** variables.
*/
static sqlite3_module tclvarModule = {
0, /* iVersion */
"tclvar", /* zName */
0, /* pAux */
tclvarConnect,
tclvarConnect,
tclvarBestIndex,
tclvarDisconnect,
tclvarDisconnect,
tclvarOpen, /* xOpen - open a cursor */
tclvarClose, /* xClose - close a cursor */
tclvarFilter, /* xFilter - configure scan constraints */
tclvarNext, /* xNext - advance a cursor */
tclvarColumn, /* xColumn - read data */
tclvarRowid /* xRowid - read data */
};
/*
** 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_tclvar_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;
tclvarModule.pAux = interp;
#ifndef SQLITE_OMIT_VIRTUALTABLE
sqlite3_create_module(db, "tclvar", &tclvarModule);
#endif
return TCL_OK;
}
/*
** Register commands with the TCL interpreter.
*/
int Sqlitetesttclvar_Init(Tcl_Interp *interp){
static struct {
char *zName;
Tcl_ObjCmdProc *xProc;
void *clientData;
} aObjCmd[] = {
{ "register_tclvar_module", register_tclvar_module, 0 },
};
int i;
for(i=0; i<sizeof(aObjCmd)/sizeof(aObjCmd[0]); i++){
Tcl_CreateObjCommand(interp, aObjCmd[i].zName,
aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
}
return TCL_OK;
}

View File

@@ -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.557 2006/06/13 15:00:55 danielk1977 Exp $
** $Id: vdbe.c,v 1.558 2006/06/13 23:51:35 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -4593,17 +4593,19 @@ case OP_VOpen: {
** P1 is a cursor opened using VOpen. P2 is an address to jump to if
** the filtered result set is empty.
**
** P3 points to enough free space to use to marshall the arguments.
** P3 is either NULL or a string that was generated by the xBestIndex
** method of the module. The interpretation of the P3 string is left
** to the module implementation.
**
** This opcode invokes the xFilter method on the virtual table specified
** by P1. The query plan parameter to xFilter is the top of the stack.
** Next down on the stack is the argc parameter. Beneath the
** by P1. The integer query plan parameter to xFilter is the top of the
** stack. Next down on the stack is the argc parameter. Beneath the
** next of stack are argc additional parameters which are passed to
** xFilter as argv. The topmost parameter (i.e. 3rd element popped from
** the stack) becomes argv[argc-1] when passed to xFilter.
**
** The query plan, argc, and all argv stack values are popped from the
** stack before this instruction completes.
** The integer query plan parameter, 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
** empty.
@@ -4619,20 +4621,21 @@ case OP_VFilter: {
/* Grab the index number and argc parameters off the top of the stack. */
assert( (&pTos[-1])>=p->aStack );
assert( pTos[0].flags&MEM_Blob && pTos[-1].flags==MEM_Int );
assert( (pTos[0].flags&MEM_Int)!=0 && pTos[-1].flags==MEM_Int );
nArg = pTos[-1].i;
/* Invoke the xFilter method if one is defined. */
if( pModule->xFilter ){
int res;
int ii;
Mem **apArg = (Mem **)pOp->p3;
for(ii = 0; ii<nArg; ii++){
apArg[ii] = &pTos[ii+1-2-nArg];
int i;
Mem **apArg = p->apArg;
for(i = 0; i<nArg; i++){
apArg[i] = &pTos[i+1-2-nArg];
storeTypeInfo(apArg[i], 0);
}
if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
res = pModule->xFilter(pCur->pVtabCursor, pTos->z, pTos->n, nArg, apArg);
res = pModule->xFilter(pCur->pVtabCursor, pTos->i, pOp->p3, nArg, apArg);
if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
if( res==0 ){

View File

@@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database.
**
** $Id: vdbe.h,v 1.104 2006/06/13 01:04:53 drh Exp $
** $Id: vdbe.h,v 1.105 2006/06/13 23:51:35 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@@ -71,6 +71,7 @@ typedef struct VdbeOpList VdbeOpList;
#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_VTAB (-10) /* P3 is a pointer to an sqlite3_vtab structure */
#define P3_MPRINTF (-11) /* P3 is a string obtained from sqlite3_mprintf() */
/* 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

View File

@@ -454,11 +454,9 @@ const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
columnMallocFailure(pStmt);
return val;
}
#if 0
sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
return columnMem(pStmt, i);
}
#endif
#ifndef SQLITE_OMIT_UTF16
const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
const void *val = sqlite3_value_text16( columnMem(pStmt,i) );

View File

@@ -263,8 +263,13 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
}
}else if( opcode==OP_Statement ){
hasStatementBegin = 1;
}else if( opcode==OP_VFilter ){
int n;
assert( p->nOp - i >= 3 );
assert( pOp[-2].opcode==OP_Integer );
n = pOp[-2].p1;
if( n>nMaxArgs ) nMaxArgs = n;
}
if( opcodeNoPush(opcode) ){
nMaxStack--;
}
@@ -380,6 +385,10 @@ static void freeP3(int p3type, void *p3){
sqliteFree(p3);
break;
}
case P3_MPRINTF: {
sqlite3_free(p3);
break;
}
case P3_VDBEFUNC: {
VdbeFunc *pVdbeFunc = (VdbeFunc *)p3;
sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);

View File

@@ -11,7 +11,7 @@
*************************************************************************
** This file contains code used to help implement virtual tables.
**
** $Id: vtab.c,v 1.7 2006/06/13 15:00:55 danielk1977 Exp $
** $Id: vtab.c,v 1.8 2006/06/13 23:51:35 drh Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"
@@ -277,16 +277,6 @@ int sqlite3VtabCallConnect(Parse *pParse, Table *pTab){
return rc;
}
/*
** Resize pInfo->zPlan to nBytes bytes using realloc(). Set pInfo->nPlan
** to nBytes and return a pointer to the allocated memory.
*/
char *sqlite3_allocate_queryplan(sqlite3_index_info *pInfo, int nBytes){
pInfo->nPlan = nBytes;
sqlite3ReallocOrFree(&pInfo->zPlan, nBytes);
return pInfo->zPlan;
}
/*
** This function is used to set the schema of a virtual table. It is only

View File

@@ -16,7 +16,7 @@
** so is applicable. Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.215 2006/06/13 17:39:01 drh Exp $
** $Id: where.c,v 1.216 2006/06/13 23:51:35 drh Exp $
*/
#include "sqliteInt.h"
@@ -1108,8 +1108,12 @@ static double bestVirtualIndex(
pIdxCons->usable = (pTerm->prereqRight & notReady)==0;
}
memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
pIdxInfo->zPlan = 0;
pIdxInfo->nPlan = 0;
if( pIdxInfo->needToFreeIdxStr ){
sqlite3_free(pIdxInfo->idxStr);
}
pIdxInfo->idxStr = 0;
pIdxInfo->idxNum = 0;
pIdxInfo->needToFreeIdxStr = 0;
pIdxInfo->orderByConsumed = 0;
pIdxInfo->estimatedCost = SQLITE_BIG_DBL;
nOrderBy = pIdxInfo->nOrderBy;
@@ -1572,10 +1576,13 @@ static void whereInfoFree(WhereInfo *pWInfo){
if( pWInfo ){
int i;
for(i=0; i<pWInfo->nLevel; i++){
if( pWInfo->a[i].pIdxInfo ){
sqliteFree(pWInfo->a[i].pIdxInfo->zPlan);
sqlite3_index_info *pInfo = pWInfo->a[i].pIdxInfo;
if( pInfo ){
if( pInfo->needToFreeIdxStr ){
sqlite3_free(pInfo->idxStr);
}
sqliteFree(pInfo);
}
sqliteFree(pWInfo->a[i].pIdxInfo);
}
sqliteFree(pWInfo);
}
@@ -1861,8 +1868,9 @@ WhereInfo *sqlite3WhereBegin(
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
else if( pLevel->pIdxInfo ){
zMsg = sqlite3MPrintf("%z VIRTUAL TABLE INDEX %s",
pLevel->pIdxInfo->zPlan);
sqlite3_index_info *pIdxInfo = pLevel->pIdxInfo;
zMsg = sqlite3MPrintf("%z VIRTUAL TABLE INDEX %d:%s",
pIdxInfo->idxNum, pIdxInfo->idxStr);
}
#endif
if( pLevel->flags & WHERE_ORDERBY ){
@@ -1952,26 +1960,29 @@ WhereInfo *sqlite3WhereBegin(
/* Case 0: The table is a virtual-table. Use the VFilter and VNext
** to access the data.
*/
char *zSpace; /* Space for OP_VFilter to marshall it's arguments */
sqlite3_index_info *pIdxInfo = pLevel->pIdxInfo;
for(i=1; i<=pIdxInfo->nConstraint; i++){
int nConstraint = pIdxInfo->nConstraint;
struct sqlite3_index_constraint_usage *aUsage =
pIdxInfo->aConstraintUsage;
const struct sqlite3_index_constraint *aConstraint =
pIdxInfo->aConstraint;
for(i=1; i<=nConstraint; i++){
int j;
for(j=0; j<pIdxInfo->nConstraint; j++){
if( pIdxInfo->aConstraintUsage[j].argvIndex==i ){
sqlite3ExprCode(pParse, wc.a[j].pExpr->pRight);
for(j=0; j<nConstraint; j++){
if( aUsage[j].argvIndex==i ){
int k = aConstraint[j].iTermOffset;
sqlite3ExprCode(pParse, wc.a[k].pExpr->pRight);
break;
}
}
if( j==pIdxInfo->nConstraint ) break;
if( j==nConstraint ) break;
}
sqlite3VdbeAddOp(v, OP_Integer, i-1, 0);
sqlite3VdbeAddOp(v, OP_Blob, pIdxInfo->nPlan, 0);
sqlite3VdbeChangeP3(v, -1, pIdxInfo->zPlan, P3_DYNAMIC);
pIdxInfo->zPlan = 0;
sqlite3VdbeAddOp(v, OP_VFilter, iCur, brk);
zSpace = (char *)sqliteMalloc(sizeof(sqlite3_value*)*(i-1));
sqlite3VdbeChangeP3(v, -1, zSpace, P3_DYNAMIC);
sqlite3VdbeAddOp(v, OP_Integer, pIdxInfo->idxNum, 0);
sqlite3VdbeOp3(v, OP_VFilter, iCur, brk, pIdxInfo->idxStr,
pIdxInfo->needToFreeIdxStr ? P3_MPRINTF : P3_STATIC);
pIdxInfo->needToFreeIdxStr = 0;
for(i=0; i<pIdxInfo->nConstraint; i++){
if( pIdxInfo->aConstraintUsage[i].omit ){
disableTerm(pLevel, &wc.a[i]);