SQLite

Check-in [7a3e97f76b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add the tentative sqlite3_allocate_queryplan() API. (CVS 3228)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 7a3e97f76b1f4f97a04f7c5a9daa400402b2ff25
User & Date: danielk1977 2006-06-13 15:00:55.000
Context
2006-06-13
15:12
Improved comments and documentation of sqlite3_load_extension(). (CVS 3229) (check-in: 0bcec95963 user: drh tags: trunk)
15:00
Add the tentative sqlite3_allocate_queryplan() API. (CVS 3228) (check-in: 7a3e97f76b user: danielk1977 tags: trunk)
14:16
Add simple tests for the xFilter and xBestIndex methods. (CVS 3227) (check-in: 0f4657ea69 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/sqlite.h.in.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the SQLite library
** presents to client programs.
**
** @(#) $Id: sqlite.h.in,v 1.172 2006/06/13 14:16:59 danielk1977 Exp $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** 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 $
*/
#ifndef _SQLITE3_H_
#define _SQLITE3_H_
#include <stdarg.h>     /* Needed for the definition of va_list */

/*
** Make sure we can call this stuff from C++.
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
               int argc, char **argv,
               sqlite3_vtab **ppVTab);
  int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
  int (*xDisconnect)(sqlite3_vtab *pVTab);
  int (*xDestroy)(sqlite3_vtab *pVTab);
  int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
  int (*xClose)(sqlite3_vtab_cursor*);
  int (*xFilter)(sqlite3_vtab_cursor*, int idx,
                int argc, sqlite3_value **argv);
  int (*xNext)(sqlite3_vtab_cursor*);
  int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
  int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid);
  int (*xInsert)(sqlite3_vtab *pVTab, sqlite3_value **apData);
  int (*xDelete)(sqlite3_vtab *pVTab, sqlite_int64 rowid);
  int (*xBegin)(sqlite3_vtab *pVTab);







|







1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
               int argc, char **argv,
               sqlite3_vtab **ppVTab);
  int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
  int (*xDisconnect)(sqlite3_vtab *pVTab);
  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 argc, sqlite3_value **argv);
  int (*xNext)(sqlite3_vtab_cursor*);
  int (*xColumn)(sqlite3_vtab_cursor*, sqlite3_context*, int);
  int (*xRowid)(sqlite3_vtab_cursor*, sqlite_int64 *pRowid);
  int (*xInsert)(sqlite3_vtab *pVTab, sqlite3_value **apData);
  int (*xDelete)(sqlite3_vtab *pVTab, sqlite_int64 rowid);
  int (*xBegin)(sqlite3_vtab *pVTab);
1622
1623
1624
1625
1626
1627
1628
1629



1630
1631
1632
1633
1634
1635
1636
  } *const aOrderBy;         /* The ORDER BY clause */

  /* Outputs */
  struct sqlite3_index_constraint_usage {
    int argvIndex;           /* if >0, constraint is part of argv to xFilter */
    unsigned char omit;      /* Do not code a test for this constraint */
  } *const aConstraintUsage;
  int idxNum;                /* Index number passed to xFilter */



  int orderByConsumed;       /* True if output is already ordered */
  double estimatedCost;      /* Estimated cost of using this index */
};
#define SQLITE_INDEX_CONSTRAINT_EQ    2
#define SQLITE_INDEX_CONSTRAINT_GT    4
#define SQLITE_INDEX_CONSTRAINT_LE    8
#define SQLITE_INDEX_CONSTRAINT_LT    16







|
>
>
>







1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
  } *const aOrderBy;         /* The ORDER BY clause */

  /* Outputs */
  struct sqlite3_index_constraint_usage {
    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 orderByConsumed;       /* True if output is already ordered */
  double estimatedCost;      /* Estimated cost of using this index */
};
#define SQLITE_INDEX_CONSTRAINT_EQ    2
#define SQLITE_INDEX_CONSTRAINT_GT    4
#define SQLITE_INDEX_CONSTRAINT_LE    8
#define SQLITE_INDEX_CONSTRAINT_LT    16
1678
1679
1680
1681
1682
1683
1684







1685
1686
1687
1688
1689
1690
1691
/*
** The xCreate and xConnect methods of a module use the following API
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
*/
int sqlite3_declare_vtab(sqlite3*, const char *zCreateTable);








/*
** The interface to the virtual-table mechanism defined above (back up
** to a comment remarkably similar to this one) is currently considered
** to be experimental.  The interface might change in incompatible ways.
** If this is a problem for you, do not use the interface at this time.
**
** When the virtual-table mechanism stablizes, we will declare the







>
>
>
>
>
>
>







1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
/*
** The xCreate and xConnect methods of a module use the following API
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
*/
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
** to be experimental.  The interface might change in incompatible ways.
** If this is a problem for you, do not use the interface at this time.
**
** When the virtual-table mechanism stablizes, we will declare the
Changes to src/test8.c.
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    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.9 2006/06/13 14:16:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>








|







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
**    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.10 2006/06/13 15:00:55 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
#include "os.h"
#include <stdlib.h>
#include <string.h>

340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
  *pRowid = sqlite3_column_int64(pStmt, 0);
  return SQLITE_OK;
}


static int echoFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  int idx,
  int argc, 
  sqlite3_value **argv
){
  int rc;
  char zBuf[32];
  int ii;

  echo_cursor *pCur = (echo_cursor *)pVtabCursor;
  echo_vtab *pVtab = (echo_vtab *)pVtabCursor->pVtab;
  sqlite3 *db = pVtab->db;

  sprintf(zBuf, "%d", idx);
  appendToEchoModule(pVtab->interp, "xFilter");
  appendToEchoModule(pVtab->interp, zBuf);
  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);







|




<






<

|







340
341
342
343
344
345
346
347
348
349
350
351

352
353
354
355
356
357

358
359
360
361
362
363
364
365
366
  *pRowid = sqlite3_column_int64(pStmt, 0);
  return SQLITE_OK;
}


static int echoFilter(
  sqlite3_vtab_cursor *pVtabCursor, 
  char *zPlan, int nPlan,
  int argc, 
  sqlite3_value **argv
){
  int rc;

  int ii;

  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);
386
387
388
389
390
391
392


393
394
395
396
397
398
399
** to the column "b", but not "a" or "c". If a multi-column index is
** present, only it's left most column is considered. 
*/
static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  int ii;
  char *zWhere = 0;
  char *zOrder = 0;


  int nArg = 0;
  echo_vtab *pVtab = (echo_vtab *)tab;

  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
    const struct sqlite3_index_constraint *pConstraint;
    struct sqlite3_index_constraint_usage *pUsage;








>
>







384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
** to the column "b", but not "a" or "c". If a multi-column index is
** present, only it's left most column is considered. 
*/
static int echoBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
  int ii;
  char *zWhere = 0;
  char *zOrder = 0;
  char *zPlan = 0;
  int nPlan = 0;
  int nArg = 0;
  echo_vtab *pVtab = (echo_vtab *)tab;

  for(ii=0; ii<pIdxInfo->nConstraint; ii++){
    const struct sqlite3_index_constraint *pConstraint;
    struct sqlite3_index_constraint_usage *pUsage;

430
431
432
433
434
435
436













437
438
439
440
441
442
443
444
445
446
447
448
      pUsage->omit = 1;
    }
  }

  appendToEchoModule(pVtab->interp, "xBestIndex");;
  appendToEchoModule(pVtab->interp, zWhere);
  appendToEchoModule(pVtab->interp, zOrder);














  sqliteFree(zWhere);
  sqliteFree(zOrder);

  pIdxInfo->idxNum = 123;
  return SQLITE_OK;
}

/*
** A virtual table module that merely echos method calls into TCL
** variables.
*/







>
>
>
>
>
>
>
>
>
>
>
>
>




<







430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453

454
455
456
457
458
459
460
      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);


  return SQLITE_OK;
}

/*
** A virtual table module that merely echos method calls into TCL
** variables.
*/
Changes to src/vdbe.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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.556 2006/06/13 14:16:59 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** 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 $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
**
** 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.
**
** This opcode invokes the xFilter method on the virtual table specified
** 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 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 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 
** empty.
*/
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;
    int ii;
    Mem **apArg = pOp->p3;
    for(ii = 0; ii<nArg; ii++){
      apArg[ii] = &pTos[ii+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;
    }
  }








|





|






<










|
<






|





|







4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611

4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622

4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
**
** 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.
**
** 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
** 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.
**
** A jump is made to P2 if the result set after filtering would be 
** empty.
*/
case OP_VFilter: {

  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_Blob && 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];
    }

    if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
    res = pModule->xFilter(pCur->pVtabCursor, pTos->z, pTos->n, nArg, apArg);
    if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;

    if( res==0 ){
      pc = pOp->p2 - 1;
    }
  }

Changes to src/vtab.c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 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.6 2006/06/13 10:24:43 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"

/*
** External API function used to create a new virtual-table module.
*/













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 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.7 2006/06/13 15:00:55 danielk1977 Exp $
*/
#ifndef SQLITE_OMIT_VIRTUALTABLE
#include "sqliteInt.h"

/*
** External API function used to create a new virtual-table module.
*/
272
273
274
275
276
277
278











279
280
281
282
283
284
285
    } else {
      rc = sqlite3SafetyOn(db);
    }
  }

  return rc;
}












/*
** This function is used to set the schema of a virtual table.  It is only
** valid to call this function from within the xCreate() or xConnect() of a
** virtual table module.
*/
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){







>
>
>
>
>
>
>
>
>
>
>







272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
    } else {
      rc = sqlite3SafetyOn(db);
    }
  }

  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
** valid to call this function from within the xCreate() or xConnect() of a
** virtual table module.
*/
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
Changes to src/where.c.
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** 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.213 2006/06/13 14:16:59 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)







|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** 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.214 2006/06/13 15:00:55 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
1001
1002
1003
1004
1005
1006
1007
1008

1009
1010
1011
1012
1013
1014
1015
  pUsage = pIdxInfo->aConstraintUsage;
  for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
    j = pIdxCons->iTermOffset;
    pTerm = &pWC->a[j];
    pIdxCons->usable =  (pTerm->prereqRight & notReady)==0;
  }
  memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
  pIdxInfo->idxNum = 0;

  pIdxInfo->orderByConsumed = 0;
  pIdxInfo->estimatedCost = SQLITE_BIG_DBL;
  nOrderBy = pIdxInfo->nOrderBy;
  if( pIdxInfo->nOrderBy && !orderByUsable ){
    *(int*)&pIdxInfo->nOrderBy = 0;
  }
  pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);







|
>







1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
  pUsage = pIdxInfo->aConstraintUsage;
  for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){
    j = pIdxCons->iTermOffset;
    pTerm = &pWC->a[j];
    pIdxCons->usable =  (pTerm->prereqRight & notReady)==0;
  }
  memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint);
  pIdxInfo->zPlan = 0;
  pIdxInfo->nPlan = 0;
  pIdxInfo->orderByConsumed = 0;
  pIdxInfo->estimatedCost = SQLITE_BIG_DBL;
  nOrderBy = pIdxInfo->nOrderBy;
  if( pIdxInfo->nOrderBy && !orderByUsable ){
    *(int*)&pIdxInfo->nOrderBy = 0;
  }
  pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);
1464
1465
1466
1467
1468
1469
1470



1471
1472
1473
1474
1475
1476
1477
/*
** Free a WhereInfo structure
*/
static void whereInfoFree(WhereInfo *pWInfo){
  if( pWInfo ){
    int i;
    for(i=0; i<pWInfo->nLevel; i++){



      sqliteFree(pWInfo->a[i].pIdxInfo);
    }
    sqliteFree(pWInfo);
  }
}









>
>
>







1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
/*
** Free a WhereInfo structure
*/
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);
      }
      sqliteFree(pWInfo->a[i].pIdxInfo);
    }
    sqliteFree(pWInfo);
  }
}


1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
      if( (pIx = pLevel->pIdx)!=0 ){
        zMsg = sqlite3MPrintf("%z WITH INDEX %s", zMsg, pIx->zName);
      }else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
        zMsg = sqlite3MPrintf("%z USING PRIMARY KEY", zMsg);
      }
#ifndef SQLITE_OMIT_VIRTUALTABLE
      else if( pLevel->pIdxInfo ){
        zMsg = sqlite3MPrintf("%z VIRTUAL TABLE INDEX %d",
                    pLevel->pIdxInfo->idxNum);
      }
#endif
      if( pLevel->flags & WHERE_ORDERBY ){
        zMsg = sqlite3MPrintf("%z ORDER BY", zMsg);
      }
      sqlite3VdbeOp3(v, OP_Explain, i, pLevel->iFrom, zMsg, P3_DYNAMIC);
    }







|
|







1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
      if( (pIx = pLevel->pIdx)!=0 ){
        zMsg = sqlite3MPrintf("%z WITH INDEX %s", zMsg, pIx->zName);
      }else if( pLevel->flags & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
        zMsg = sqlite3MPrintf("%z USING PRIMARY KEY", zMsg);
      }
#ifndef SQLITE_OMIT_VIRTUALTABLE
      else if( pLevel->pIdxInfo ){
        zMsg = sqlite3MPrintf("%z VIRTUAL TABLE INDEX %s",
                    pLevel->pIdxInfo->zPlan);
      }
#endif
      if( pLevel->flags & WHERE_ORDERBY ){
        zMsg = sqlite3MPrintf("%z ORDER BY", zMsg);
      }
      sqlite3VdbeOp3(v, OP_Explain, i, pLevel->iFrom, zMsg, P3_DYNAMIC);
    }
1854
1855
1856
1857
1858
1859
1860
1861


1862
1863
1864
1865
1866
1867
1868
            sqlite3ExprCode(pParse, wc.a[j].pExpr->pRight);
            break;
          }
        }
        if( j==pIdxInfo->nConstraint ) break;
      }
      sqlite3VdbeAddOp(v, OP_Integer, i-1, 0);
      sqlite3VdbeAddOp(v, OP_Integer, pIdxInfo->idxNum, 0);


      sqlite3VdbeAddOp(v, OP_VFilter, iCur, brk);
      zSpace = (char *)sqliteMalloc(sizeof(sqlite3_value*)*(i-1));
      sqlite3VdbeChangeP3(v, -1, zSpace, P3_DYNAMIC);
      for(i=0; i<pIdxInfo->nConstraint; i++){
        if( pIdxInfo->aConstraintUsage[i].omit ){
          disableTerm(pLevel, &wc.a[i]);
        }







|
>
>







1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
            sqlite3ExprCode(pParse, wc.a[j].pExpr->pRight);
            break;
          }
        }
        if( j==pIdxInfo->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);
      for(i=0; i<pIdxInfo->nConstraint; i++){
        if( pIdxInfo->aConstraintUsage[i].omit ){
          disableTerm(pLevel, &wc.a[i]);
        }
Changes to test/vtab1.test.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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.9 2006/06/13 14:16:59 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !vtab {
  finish_test
  return













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 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.10 2006/06/13 15:00:55 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !vtab {
  finish_test
  return
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

do_test vtab1-3.6 {
  set echo_module ""
  execsql {
    SELECT * FROM t1;
  }
  set echo_module
} {xBestIndex {} {} xFilter 123}
do_test vtab1-3.7 {
  set echo_module ""
  execsql {
    SELECT * FROM t1 WHERE b = 10;
  }
  set echo_module
} {xBestIndex {WHERE b = ?} {} xFilter 123 10}
do_test vtab1-3.8 {
  set echo_module ""
  execsql {
    SELECT * FROM t1 WHERE b >= 5 AND b <= 10;
  }
  set echo_module
} {xBestIndex {WHERE b >= ? AND b <= ?} {} xFilter 123 5 10}
do_test vtab1-3.9 {
  set echo_module ""
  execsql {
    SELECT * FROM t1 WHERE b BETWEEN 5 AND 10;
  }
  set echo_module
} {xBestIndex {WHERE b >= ? AND b <= ?} {} xFilter 123 5 10}

finish_test








|






|






|






|



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209

do_test vtab1-3.6 {
  set echo_module ""
  execsql {
    SELECT * FROM t1;
  }
  set echo_module
} {xBestIndex {} {} xFilter {}}
do_test vtab1-3.7 {
  set echo_module ""
  execsql {
    SELECT * FROM t1 WHERE b = 10;
  }
  set echo_module
} {xBestIndex {WHERE b = ?} {} xFilter {WHERE b = ?} 10}
do_test vtab1-3.8 {
  set echo_module ""
  execsql {
    SELECT * FROM t1 WHERE b >= 5 AND b <= 10;
  }
  set echo_module
} {xBestIndex {WHERE b >= ? AND b <= ?} {} xFilter {WHERE b >= ? AND b <= ?} 5 10}
do_test vtab1-3.9 {
  set echo_module ""
  execsql {
    SELECT * FROM t1 WHERE b BETWEEN 5 AND 10;
  }
  set echo_module
} {xBestIndex {WHERE b >= ? AND b <= ?} {} xFilter {WHERE b >= ? AND b <= ?} 5 10}

finish_test