/ Check-in [6609c25f]
Login

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

Overview
Comment:Cleanup and refactor parts of the optimizer. (CVS 3301)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:6609c25fbfa5ad7f55c356936abb1721686c47ca
User & Date: drh 2006-06-27 02:33:40
Context
2006-06-27
02:36
Make sure that MATCH terms that a virtual table says should be omitted really are omitted. (CVS 3302) check-in: 3e1f5567 user: drh tags: trunk
02:33
Cleanup and refactor parts of the optimizer. (CVS 3301) check-in: 6609c25f user: drh tags: trunk
01:54
Cache and reuse virtual table index information in the optimizer. Improved diagnostics for virtual table index selection. (CVS 3300) check-in: 28413cf2 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/where.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
....
1871
1872
1873
1874
1875
1876
1877

1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
....
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
....
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064

2065
2066
2067
2068
2069
2070
2071
2072
** 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.224 2006/06/27 01:54:26 drh Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
      m = getMask(&maskSet, pTabItem->iCursor);
      if( (m & notReady)==0 ){
        if( j==iFrom ) iFrom++;
        continue;
      }
      assert( pTabItem->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE
      pIndex = 0;
      if( IsVirtual(pTabItem->pTab) ){
        sqlite3_index_info **ppIdxInfo = &pWInfo->a[j].pIdxInfo;
        cost = bestVirtualIndex(pParse, &wc, pTabItem, notReady,
                                ppOrderBy ? *ppOrderBy : 0, i==0,
                                ppIdxInfo);
        flags = WHERE_VIRTUALTABLE;
        pIndex = *ppIdxInfo;
................................................................................
        nEq = 0;
      }else 
#endif
      {
        cost = bestIndex(pParse, &wc, pTabItem, notReady,
                         (i==0 && ppOrderBy) ? *ppOrderBy : 0,
                         &pIdx, &flags, &nEq);

      }
      if( cost<lowestCost ){
        once = 1;
        lowestCost = cost;
        pBest = pIdx;
        bestFlags = flags;
        bestNEq = nEq;
        bestJ = j;
#ifndef SQLITE_OMIT_VIRTUALTABLE
        pLevel->pBestIdx = pIndex;
#endif
      }
      if( doNotReorder ) break;
    }
    TRACE(("*** Optimizer choose table %d for loop %d\n", bestJ,
           pLevel-pWInfo->a));
    if( (bestFlags & WHERE_ORDERBY)!=0 ){
      *ppOrderBy = 0;
................................................................................
    *ppOrderBy = 0;
  }

  /* Open all tables in the pTabList and any indices selected for
  ** searching those tables.
  */
  sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */
  pLevel = pWInfo->a;
  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
    Table *pTab;     /* Table to open */
    Index *pIx;      /* Index used to access pTab (if any) */
    int iDb;         /* Index of database containing table/index */
    int iIdxCur = pLevel->iIdxCur;

#ifndef SQLITE_OMIT_EXPLAIN
................................................................................
    }

#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( pLevel->pBestIdx ){
      /* Case 0:  The table is a virtual-table.  Use the VFilter and VNext
      **          to access the data.
      */
      int ii;
      sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
      int nConstraint = pBestIdx->nConstraint;
      struct sqlite3_index_constraint_usage *aUsage =
                                                  pBestIdx->aConstraintUsage;
      const struct sqlite3_index_constraint *aConstraint =
                                                  pBestIdx->aConstraint;

      for(ii=1; ii<=nConstraint; ii++){
        int j;
        for(j=0; j<nConstraint; j++){
          if( aUsage[j].argvIndex==ii ){
            int k = aConstraint[j].iTermOffset;
            sqlite3ExprCode(pParse, wc.a[k].pExpr->pRight);
            break;
          }
        }
        if( j==nConstraint ) break;
      }
      sqlite3VdbeAddOp(v, OP_Integer, ii-1, 0);
      sqlite3VdbeAddOp(v, OP_Integer, pBestIdx->idxNum, 0);
      sqlite3VdbeOp3(v, OP_VFilter, iCur, brk, pBestIdx->idxStr,
                      pBestIdx->needToFreeIdxStr ? P3_MPRINTF : P3_STATIC);
      pBestIdx->needToFreeIdxStr = 0;
      for(ii=0; ii<pBestIdx->nConstraint; ii++){
        if( pBestIdx->aConstraintUsage[ii].omit ){

          disableTerm(pLevel, &wc.a[ii]);
        }
      }
      pLevel->op = OP_VNext;
      pLevel->p1 = iCur;
      pLevel->p2 = sqlite3VdbeCurrentAddr(v);
    }else
#endif /* SQLITE_OMIT_VIRTUALTABLE */







|







 







<







 







>








<

<







 







<







 







|







|
|
|
|
|
|



|

|




|
|
>
|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1852
1853
1854
1855
1856
1857
1858

1859
1860
1861
1862
1863
1864
1865
....
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885

1886

1887
1888
1889
1890
1891
1892
1893
....
1915
1916
1917
1918
1919
1920
1921

1922
1923
1924
1925
1926
1927
1928
....
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
** 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.225 2006/06/27 02:33:40 drh Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
      m = getMask(&maskSet, pTabItem->iCursor);
      if( (m & notReady)==0 ){
        if( j==iFrom ) iFrom++;
        continue;
      }
      assert( pTabItem->pTab );
#ifndef SQLITE_OMIT_VIRTUALTABLE

      if( IsVirtual(pTabItem->pTab) ){
        sqlite3_index_info **ppIdxInfo = &pWInfo->a[j].pIdxInfo;
        cost = bestVirtualIndex(pParse, &wc, pTabItem, notReady,
                                ppOrderBy ? *ppOrderBy : 0, i==0,
                                ppIdxInfo);
        flags = WHERE_VIRTUALTABLE;
        pIndex = *ppIdxInfo;
................................................................................
        nEq = 0;
      }else 
#endif
      {
        cost = bestIndex(pParse, &wc, pTabItem, notReady,
                         (i==0 && ppOrderBy) ? *ppOrderBy : 0,
                         &pIdx, &flags, &nEq);
        pIndex = 0;
      }
      if( cost<lowestCost ){
        once = 1;
        lowestCost = cost;
        pBest = pIdx;
        bestFlags = flags;
        bestNEq = nEq;
        bestJ = j;

        pLevel->pBestIdx = pIndex;

      }
      if( doNotReorder ) break;
    }
    TRACE(("*** Optimizer choose table %d for loop %d\n", bestJ,
           pLevel-pWInfo->a));
    if( (bestFlags & WHERE_ORDERBY)!=0 ){
      *ppOrderBy = 0;
................................................................................
    *ppOrderBy = 0;
  }

  /* Open all tables in the pTabList and any indices selected for
  ** searching those tables.
  */
  sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */

  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){
    Table *pTab;     /* Table to open */
    Index *pIx;      /* Index used to access pTab (if any) */
    int iDb;         /* Index of database containing table/index */
    int iIdxCur = pLevel->iIdxCur;

#ifndef SQLITE_OMIT_EXPLAIN
................................................................................
    }

#ifndef SQLITE_OMIT_VIRTUALTABLE
    if( pLevel->pBestIdx ){
      /* Case 0:  The table is a virtual-table.  Use the VFilter and VNext
      **          to access the data.
      */
      int j;
      sqlite3_index_info *pBestIdx = pLevel->pBestIdx;
      int nConstraint = pBestIdx->nConstraint;
      struct sqlite3_index_constraint_usage *aUsage =
                                                  pBestIdx->aConstraintUsage;
      const struct sqlite3_index_constraint *aConstraint =
                                                  pBestIdx->aConstraint;

      for(j=1; j<=nConstraint; j++){
        int k;
        for(k=0; k<nConstraint; k++){
          if( aUsage[k].argvIndex==j ){
            int iTerm = aConstraint[j-1].iTermOffset;
            sqlite3ExprCode(pParse, wc.a[iTerm].pExpr->pRight);
            break;
          }
        }
        if( k==nConstraint ) break;
      }
      sqlite3VdbeAddOp(v, OP_Integer, j-1, 0);
      sqlite3VdbeAddOp(v, OP_Integer, pBestIdx->idxNum, 0);
      sqlite3VdbeOp3(v, OP_VFilter, iCur, brk, pBestIdx->idxStr,
                      pBestIdx->needToFreeIdxStr ? P3_MPRINTF : P3_STATIC);
      pBestIdx->needToFreeIdxStr = 0;
      for(j=0; j<pBestIdx->nConstraint; j++){
        if( aUsage[j].omit ){
          int iTerm = aConstraint[j].iTermOffset;
          disableTerm(pLevel, &wc.a[iTerm]);
        }
      }
      pLevel->op = OP_VNext;
      pLevel->p1 = iCur;
      pLevel->p2 = sqlite3VdbeCurrentAddr(v);
    }else
#endif /* SQLITE_OMIT_VIRTUALTABLE */