/ Check-in [ae985db4]
Login

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

Overview
Comment:Futher simplifications to the NGQP. Fix some test cases to use EXPLAIN QUERY PLAN rather than the (now obsolete) sqlite_query_plan global variable.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | nextgen-query-plan-exp
Files: files | file ages | folders
SHA1:ae985db4fa08b5efbef5a834e852f0b05101264b
User & Date: drh 2013-05-30 19:29:19
Context
2013-05-30
22:27
Incremental check-in with various NGQP fixes. Many tests still fail. check-in: a51d8c92 user: drh tags: nextgen-query-plan-exp
19:29
Futher simplifications to the NGQP. Fix some test cases to use EXPLAIN QUERY PLAN rather than the (now obsolete) sqlite_query_plan global variable. check-in: ae985db4 user: drh tags: nextgen-query-plan-exp
19:28
The expected result in a test case can be of the form "*glob*" or "~*glob*" to match or not match the GLOB pattern. This is useful for matching EXPLAIN QUERY PLAN output that contains regular expression syntax characters like "?", "(", and ")". check-in: a3b4e261 user: drh tags: nextgen-query-plan-exp
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/test1.c.

6298
6299
6300
6301
6302
6303
6304
6305
6306
6307
6308
6309
6310
6311
6312
6313
....
6353
6354
6355
6356
6357
6358
6359


6360
6361

6362
6363
6364
6365
6366
6367
6368
#endif
#ifdef SQLITE_DEBUG
  extern int sqlite3WhereTrace;
  extern int sqlite3OSTrace;
  extern int sqlite3WalTrace;
#endif
#ifdef SQLITE_TEST
  extern char sqlite3_query_plan[];
  static char *query_plan = sqlite3_query_plan;
#ifdef SQLITE_ENABLE_FTS3
  extern int sqlite3_fts3_enable_parentheses;
#endif
#endif

  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
................................................................................
      (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
#endif
#if SQLITE_OS_WIN
  Tcl_LinkVar(interp, "sqlite_os_type",
      (char*)&sqlite3_os_type, TCL_LINK_INT);
#endif
#ifdef SQLITE_TEST


  Tcl_LinkVar(interp, "sqlite_query_plan",
      (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);

#endif
#ifdef SQLITE_DEBUG
  Tcl_LinkVar(interp, "sqlite_where_trace",
      (char*)&sqlite3WhereTrace, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_os_trace",
      (char*)&sqlite3OSTrace, TCL_LINK_INT);
#ifndef SQLITE_OMIT_WAL







<
<







 







>
>
|
|
>







6298
6299
6300
6301
6302
6303
6304


6305
6306
6307
6308
6309
6310
6311
....
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
6363
6364
6365
6366
6367
6368
6369
#endif
#ifdef SQLITE_DEBUG
  extern int sqlite3WhereTrace;
  extern int sqlite3OSTrace;
  extern int sqlite3WalTrace;
#endif
#ifdef SQLITE_TEST


#ifdef SQLITE_ENABLE_FTS3
  extern int sqlite3_fts3_enable_parentheses;
#endif
#endif

  for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){
    Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0);
................................................................................
      (char*)&pzNeededCollation, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
#endif
#if SQLITE_OS_WIN
  Tcl_LinkVar(interp, "sqlite_os_type",
      (char*)&sqlite3_os_type, TCL_LINK_INT);
#endif
#ifdef SQLITE_TEST
  {
    static const char *query_plan = "*** OBSOLETE VARIABLE ***";
    Tcl_LinkVar(interp, "sqlite_query_plan",
       (char*)&query_plan, TCL_LINK_STRING|TCL_LINK_READ_ONLY);
  }
#endif
#ifdef SQLITE_DEBUG
  Tcl_LinkVar(interp, "sqlite_where_trace",
      (char*)&sqlite3WhereTrace, TCL_LINK_INT);
  Tcl_LinkVar(interp, "sqlite_os_trace",
      (char*)&sqlite3OSTrace, TCL_LINK_INT);
#ifndef SQLITE_OMIT_WAL

Changes to src/where.c.

322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349


350


351
352
353
354
355
356
357
358
359
360
361
362
....
2667
2668
2669
2670
2671
2672
2673
2674

2675
2676
2677
2678
2679
2680
2681
....
3189
3190
3191
3192
3193
3194
3195
3196

3197
3198
3199
3200
3201
3202
3203
....
3742
3743
3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
....
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
3803
....
3806
3807
3808
3809
3810
3811
3812




3813
3814
3815
3816
3817
3818
3819
....
3822
3823
3824
3825
3826
3827
3828
3829
3830
3831
3832
3833
3834
3835
3836
3837
3838
3839
3840
3841
3842
3843
3844
3845
....
4022
4023
4024
4025
4026
4027
4028
4029
4030




4031
4032
4033
4034
4035
4036
4037
....
4193
4194
4195
4196
4197
4198
4199
4200
4201
4202
4203
4204
4205
4206
4207
....
5242
5243
5244
5245
5246
5247
5248
5249
5250
5251
5252
5253
5254
5255
5256
5257
5258
5259
5260
5261
5262
5263
5264
5265
5266
5267
5268
5269
5270
5271
5272
5273
5274
5275
5276
5277
5278
5279
5280
5281
5282
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
#define WO_SINGLE 0x0ff       /* Mask of all non-compound WO_* values */

/*
** Value for wsFlags returned by bestIndex() and stored in
** WhereLevel.wsFlags.  These flags determine which search
** strategies are appropriate.
*/
#define WHERE_ROWID_EQ     0x00000001  /* rowid=EXPR or rowid IN (...) */
#define WHERE_ROWID_RANGE  0x00000002  /* rowid<EXPR and/or rowid>EXPR */
#define WHERE_NULL_OK      0x00000004  /* Ok to use WO_ISNULL */
#define WHERE_IPK          0x00000008  /* x is the INTEGER PRIMARY KEY */
#define WHERE_COLUMN_EQ    0x00000010  /* x=EXPR or x IN (...) or x IS NULL */
#define WHERE_COLUMN_RANGE 0x00000020  /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN    0x00000040  /* x IN (...) */
#define WHERE_COLUMN_NULL  0x00000080  /* x IS NULL */
#define WHERE_INDEXED      0x000000f0  /* Anything that uses an index */
#define WHERE_NOT_FULLSCAN 0x000200f3  /* Does not do a full table scan */
#define WHERE_IN_ABLE      0x000100f1  /* Able to support an IN operator */
#define WHERE_TOP_LIMIT    0x00000100  /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT    0x00000200  /* x>EXPR or x>=EXPR constraint */
#define WHERE_BOTH_LIMIT   0x00000300  /* Both x>EXPR and x<EXPR */
#define WHERE_IDX_ONLY     0x00000400  /* Use index only - omit table */
#define WHERE_ORDERED      0x00000800  /* Output will appear in correct order */
#define WHERE_REVERSE      0x00001000  /* Scan in reverse order */
#define WHERE_UNIQUE       0x00002000  /* Selects no more than one row */
#define WHERE_ALL_UNIQUE   0x00004000  /* This and all prior have one row */
#define WHERE_OB_UNIQUE    0x00008000  /* Values in ORDER BY columns are 
                                       ** different for every output row */


#define WHERE_VIRTUALTABLE 0x00010000  /* Use virtual-table processing */


#define WHERE_MULTI_OR     0x00020000  /* OR using multiple indices */
#define WHERE_TEMP_INDEX   0x00040000  /* Uses an ephemeral index */
#define WHERE_DISTINCT     0x00080000  /* Correct order for DISTINCT */
#define WHERE_COVER_SCAN   0x00100000  /* Full scan of a covering index */
#define WHERE_SINGLE_ROW   0x00200000  /* No more than one row guaranteed */

/*
** This module contains many separate subroutines that work together to
** find the best indices to use for accessing a particular table in a query.
** An instance of the following structure holds context information about the
** index search so that it can be more easily passed between the various
** routines.
................................................................................
    eType = sqlite3FindInIndex(pParse, pX, 0);
    if( eType==IN_INDEX_INDEX_DESC ){
      testcase( bRev );
      bRev = !bRev;
    }
    iTab = pX->iTable;
    sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
    assert( pLoop->wsFlags & WHERE_IN_ABLE );

    if( pLevel->u.in.nIn==0 ){
      pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
    }
    pLevel->u.in.nIn++;
    pLevel->u.in.aInLoop =
       sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop,
                              sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
................................................................................
    if( testOp!=OP_Noop ){
      iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
      sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
      sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
      sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
    }
  }else if( pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ|WHERE_IDX_ONLY) ){

    /* Case 4: A scan using an index.
    **
    **         The WHERE clause may contain zero or more equality 
    **         terms ("==" or "IN" operators) that refer to the N
    **         left-most columns of the index. It may also contain
    **         inequality constraints (>, <, >= or <=) on the indexed
    **         column that immediately follows the N equalities. Only 
................................................................................
    }
  }
  sqlite3ReleaseTempReg(pParse, iReleaseReg);

  return newNotReady;
}

#if defined(SQLITE_TEST)
/*
** The following variable holds a text description of query plan generated
** by the most recent call to sqlite3WhereBegin().  Each call to WhereBegin
** overwrites the previous.  This information is used for testing and
** analysis only.
*/
char sqlite3_query_plan[BMS*2*40];  /* Text of the join */
static int nQPlan = 0;              /* Next free slow in _query_plan[] */

#endif /* SQLITE_TEST */

#ifdef WHERETRACE_ENABLED
/*
** Print a WhereLoop object for debugging purposes
*/
static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){
  int nb = 2*((pTabList->nSrc+15)/16);
  struct SrcList_item *pItem = pTabList->a + p->iTab;
................................................................................
                p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
    }else{
      z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
    }
    sqlite3DebugPrintf(" %-15s", z);
    sqlite3_free(z);
  }
  sqlite3DebugPrintf(" fg %08x N %d", p->wsFlags, p->nTerm);
  sqlite3DebugPrintf(" cost %.2g,%.2g,%.2g\n",
                     p->prereq, p->rSetup, p->rRun, p->nOut);
}
#endif

/*
** Deallocate internal memory used by a WhereLoop object
................................................................................
  sqlite3DbFree(db, p->aTerm);
  p->aTerm = 0;
  p->nTerm = 0;
  if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
    if( p->u.vtab.needFree ) sqlite3_free(p->u.vtab.idxStr);
    p->u.vtab.needFree = 0;
    p->u.vtab.idxStr = 0;




  }
}

/*
** Delete a WhereLoop object
*/
static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
................................................................................
}

/*
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
  if( ALWAYS(pWInfo) ){
    int i;
    for(i=0; i<pWInfo->nLevel; i++){
      if( pWInfo->a[i].pWLoop->wsFlags & WHERE_TEMP_INDEX ){
        Index *pIdx = pWInfo->a[i].pWLoop->u.btree.pIndex;
        if( pIdx ){
          sqlite3DbFree(db, pIdx->zColAff);
          sqlite3DbFree(db, pIdx);
        }
      }
    }
    whereClauseClear(pWInfo->pWC);
    while( pWInfo->pLoops ){
      WhereLoop *p = pWInfo->pLoops;
      pWInfo->pLoops = p->pNextLoop;
      whereLoopDelete(db, p);
    }
    sqlite3DbFree(db, pWInfo);
................................................................................
        nIn = 25;
      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
        /* "x IN (value, value, ...)" */
        nIn = pExpr->x.pList->nExpr;
      }
      pNew->u.btree.nEq++;
      pNew->nOut = (double)iRowEst * nInMul * nIn;
    }else if( pTerm->eOperator & (WO_EQ|WO_ISNULL) ){
      pNew->wsFlags |= WHERE_COLUMN_EQ;




      pNew->u.btree.nEq++;
      pNew->nOut = (double)iRowEst * nInMul;
    }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
      pNew->nOut = savedLoop.nOut/3;
    }else if( pTerm->eOperator & (WO_LT|WO_LE) ){
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
................................................................................
      int j;
      for(j=pProbe->nColumn-1; j>=0; j--){
        int x = pProbe->aiColumn[j];
        if( x<BMS-1 ){
          m &= ~(((Bitmask)1)<<x);
        }
      }
      pNew->wsFlags = (m==0) ? WHERE_IDX_ONLY : 0;

      /* Full scan via index */
      if( (m==0 || b) && pProbe->bUnordered==0 ){
        pNew->iSortIdx = b ? iSortIdx : 0;
        pNew->nOut = rSize;
        pNew->rRun = (m==0) ? (rSize + rLogSize)*(1+b) : (rSize*rLogSize);
        rc = whereLoopInsert(pBuilder, pNew);
................................................................................
  for(ii=0; ii<nTabList; ii++){
    pLevel = &pWInfo->a[ii];
    explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
    notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
    pWInfo->iContinue = pLevel->addrCont;
  }

#if defined(SQLITE_TEST) && 0  /* For testing and debugging use only */
  /* Record in the query plan information about the current table
  ** and the index used to access it (if any).  If the table itself
  ** is not used, its name is just '{}'.  If no index is used
  ** the index is listed as "{}".  If the primary key is used the
  ** index name is '*'.
  */
  for(ii=0; ii<nTabList; ii++){
    char *z;
    int n;
    int w;
    struct SrcList_item *pTabItem;

    pLevel = &pWInfo->a[ii];
    w = pLevel->plan.wsFlags;
    pTabItem = &pTabList->a[pLevel->iFrom];
    z = pTabItem->zAlias;
    if( z==0 ) z = pTabItem->pTab->zName;
    n = sqlite3Strlen30(z);
    if( n+nQPlan < sizeof(sqlite3_query_plan)-10 ){
      if( (w & WHERE_IDX_ONLY)!=0 && (w & WHERE_COVER_SCAN)==0 ){
        memcpy(&sqlite3_query_plan[nQPlan], "{}", 2);
        nQPlan += 2;
      }else{
        memcpy(&sqlite3_query_plan[nQPlan], z, n);
        nQPlan += n;
      }
      sqlite3_query_plan[nQPlan++] = ' ';
    }
    testcase( w & WHERE_ROWID_EQ );
    testcase( w & WHERE_ROWID_RANGE );
    if( w & (WHERE_ROWID_EQ|WHERE_ROWID_RANGE) ){
      memcpy(&sqlite3_query_plan[nQPlan], "* ", 2);
      nQPlan += 2;
    }else if( (w & WHERE_INDEXED)!=0 && (w & WHERE_COVER_SCAN)==0 ){
      n = sqlite3Strlen30(pLevel->plan.u.pIdx->zName);
      if( n+nQPlan < sizeof(sqlite3_query_plan)-2 ){
        memcpy(&sqlite3_query_plan[nQPlan], pLevel->plan.u.pIdx->zName, n);
        nQPlan += n;
        sqlite3_query_plan[nQPlan++] = ' ';
      }
    }else{
      memcpy(&sqlite3_query_plan[nQPlan], "{} ", 3);
      nQPlan += 3;
    }
  }
  while( nQPlan>0 && sqlite3_query_plan[nQPlan-1]==' ' ){
    sqlite3_query_plan[--nQPlan] = 0;
  }
  sqlite3_query_plan[nQPlan] = 0;
  nQPlan = 0;
#endif /* SQLITE_TEST // Testing and debugging use only */

  /* Record the continuation address in the WhereInfo structure.  Then
  ** clean up and return.
  */
  return pWInfo;

  /* Jump here if malloc fails */
whereBeginError:
  if( pWInfo ){
    pParse->nQueryLoop = pWInfo->savedNQueryLoop;
    whereInfoFree(db, pWInfo);







<
<
<
<
|
|
|
|
<
<
<
|
|
|
|
<
<
<
<
<
<
>
>
|
>
>
|
|
<
|
<







 







|
>







 







|
>







 







<
<
<
<
<
<
<
<
<
<
<
<







 







|







 







>
>
>
>







 







<
<
<
<
<
<
<
<
<
<







 







|

>
>
>
>







 







|







 







|
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







322
323
324
325
326
327
328




329
330
331
332



333
334
335
336






337
338
339
340
341
342
343

344

345
346
347
348
349
350
351
....
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
....
3179
3180
3181
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
....
3733
3734
3735
3736
3737
3738
3739












3740
3741
3742
3743
3744
3745
3746
....
3768
3769
3770
3771
3772
3773
3774
3775
3776
3777
3778
3779
3780
3781
3782
....
3785
3786
3787
3788
3789
3790
3791
3792
3793
3794
3795
3796
3797
3798
3799
3800
3801
3802
....
3805
3806
3807
3808
3809
3810
3811










3812
3813
3814
3815
3816
3817
3818
....
3995
3996
3997
3998
3999
4000
4001
4002
4003
4004
4005
4006
4007
4008
4009
4010
4011
4012
4013
4014
....
4170
4171
4172
4173
4174
4175
4176
4177
4178
4179
4180
4181
4182
4183
4184
....
5219
5220
5221
5222
5223
5224
5225
5226























































5227
5228
5229
5230
5231
5232
5233
#define WO_SINGLE 0x0ff       /* Mask of all non-compound WO_* values */

/*
** Value for wsFlags returned by bestIndex() and stored in
** WhereLevel.wsFlags.  These flags determine which search
** strategies are appropriate.
*/




#define WHERE_COLUMN_EQ    0x00000001  /* x=EXPR or x IN (...) or x IS NULL */
#define WHERE_COLUMN_RANGE 0x00000002  /* x<EXPR and/or x>EXPR */
#define WHERE_COLUMN_IN    0x00000004  /* x IN (...) */
#define WHERE_COLUMN_NULL  0x00000008  /* x IS NULL */



#define WHERE_TOP_LIMIT    0x00000010  /* x<EXPR or x<=EXPR constraint */
#define WHERE_BTM_LIMIT    0x00000020  /* x>EXPR or x>=EXPR constraint */
#define WHERE_BOTH_LIMIT   0x00000030  /* Both x>EXPR and x<EXPR */
#define WHERE_IDX_ONLY     0x00000040  /* Use index only - omit table */






#define WHERE_IPK          0x00000100  /* x is the INTEGER PRIMARY KEY */
#define WHERE_INDEXED      0x00000200  /* WhereLoop.u.btree.pIndex is valid */
#define WHERE_VIRTUALTABLE 0x00000400  /* WhereLoop.u.vtab is valid */
#define WHERE_IN_ABLE      0x00000800  /* Able to support an IN operator */
#define WHERE_UNIQUE       0x00001000  /* Selects no more than one row */
#define WHERE_MULTI_OR     0x00002000  /* OR using multiple indices */
#define WHERE_TEMP_INDEX   0x00004000  /* Uses an ephemeral index */

#define WHERE_COVER_SCAN   0x00008000  /* Full scan of a covering index */


/*
** This module contains many separate subroutines that work together to
** find the best indices to use for accessing a particular table in a query.
** An instance of the following structure holds context information about the
** index search so that it can be more easily passed between the various
** routines.
................................................................................
    eType = sqlite3FindInIndex(pParse, pX, 0);
    if( eType==IN_INDEX_INDEX_DESC ){
      testcase( bRev );
      bRev = !bRev;
    }
    iTab = pX->iTable;
    sqlite3VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0);
    assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 );
    pLoop->wsFlags |= WHERE_IN_ABLE;
    if( pLevel->u.in.nIn==0 ){
      pLevel->addrNxt = sqlite3VdbeMakeLabel(v);
    }
    pLevel->u.in.nIn++;
    pLevel->u.in.aInLoop =
       sqlite3DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop,
                              sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn);
................................................................................
    if( testOp!=OP_Noop ){
      iRowidReg = iReleaseReg = sqlite3GetTempReg(pParse);
      sqlite3VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg);
      sqlite3ExprCacheStore(pParse, iCur, -1, iRowidReg);
      sqlite3VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg);
      sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
    }
  }else if( pLoop->wsFlags & (WHERE_COLUMN_RANGE | WHERE_COLUMN_NULL |
                              WHERE_COLUMN_EQ | WHERE_IDX_ONLY) ){
    /* Case 4: A scan using an index.
    **
    **         The WHERE clause may contain zero or more equality 
    **         terms ("==" or "IN" operators) that refer to the N
    **         left-most columns of the index. It may also contain
    **         inequality constraints (>, <, >= or <=) on the indexed
    **         column that immediately follows the N equalities. Only 
................................................................................
    }
  }
  sqlite3ReleaseTempReg(pParse, iReleaseReg);

  return newNotReady;
}













#ifdef WHERETRACE_ENABLED
/*
** Print a WhereLoop object for debugging purposes
*/
static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){
  int nb = 2*((pTabList->nSrc+15)/16);
  struct SrcList_item *pItem = pTabList->a + p->iTab;
................................................................................
                p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask);
    }else{
      z = sqlite3_mprintf("(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask);
    }
    sqlite3DebugPrintf(" %-15s", z);
    sqlite3_free(z);
  }
  sqlite3DebugPrintf(" fg %05x N %d", p->wsFlags, p->nTerm);
  sqlite3DebugPrintf(" cost %.2g,%.2g,%.2g\n",
                     p->prereq, p->rSetup, p->rRun, p->nOut);
}
#endif

/*
** Deallocate internal memory used by a WhereLoop object
................................................................................
  sqlite3DbFree(db, p->aTerm);
  p->aTerm = 0;
  p->nTerm = 0;
  if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 ){
    if( p->u.vtab.needFree ) sqlite3_free(p->u.vtab.idxStr);
    p->u.vtab.needFree = 0;
    p->u.vtab.idxStr = 0;
  }else if( (p->wsFlags & WHERE_TEMP_INDEX)!=0 && p->u.btree.pIndex!=0 ){
    sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
    sqlite3DbFree(db, p->u.btree.pIndex);
    p->u.btree.pIndex = 0;
  }
}

/*
** Delete a WhereLoop object
*/
static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
................................................................................
}

/*
** Free a WhereInfo structure
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
  if( ALWAYS(pWInfo) ){










    whereClauseClear(pWInfo->pWC);
    while( pWInfo->pLoops ){
      WhereLoop *p = pWInfo->pLoops;
      pWInfo->pLoops = p->pNextLoop;
      whereLoopDelete(db, p);
    }
    sqlite3DbFree(db, pWInfo);
................................................................................
        nIn = 25;
      }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){
        /* "x IN (value, value, ...)" */
        nIn = pExpr->x.pList->nExpr;
      }
      pNew->u.btree.nEq++;
      pNew->nOut = (double)iRowEst * nInMul * nIn;
    }else if( pTerm->eOperator & (WO_EQ) ){
      pNew->wsFlags |= WHERE_COLUMN_EQ;
      pNew->u.btree.nEq++;
      pNew->nOut = (double)iRowEst * nInMul;
    }else if( pTerm->eOperator & (WO_ISNULL) ){
      pNew->wsFlags |= WHERE_COLUMN_NULL;
      pNew->u.btree.nEq++;
      pNew->nOut = (double)iRowEst * nInMul;
    }else if( pTerm->eOperator & (WO_GT|WO_GE) ){
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
      pNew->nOut = savedLoop.nOut/3;
    }else if( pTerm->eOperator & (WO_LT|WO_LE) ){
      pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT;
................................................................................
      int j;
      for(j=pProbe->nColumn-1; j>=0; j--){
        int x = pProbe->aiColumn[j];
        if( x<BMS-1 ){
          m &= ~(((Bitmask)1)<<x);
        }
      }
      pNew->wsFlags = (m==0) ? (WHERE_IDX_ONLY|WHERE_INDEXED) : WHERE_INDEXED;

      /* Full scan via index */
      if( (m==0 || b) && pProbe->bUnordered==0 ){
        pNew->iSortIdx = b ? iSortIdx : 0;
        pNew->nOut = rSize;
        pNew->rRun = (m==0) ? (rSize + rLogSize)*(1+b) : (rSize*rLogSize);
        rc = whereLoopInsert(pBuilder, pNew);
................................................................................
  for(ii=0; ii<nTabList; ii++){
    pLevel = &pWInfo->a[ii];
    explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags);
    notReady = codeOneLoopStart(pWInfo, ii, wctrlFlags, notReady);
    pWInfo->iContinue = pLevel->addrCont;
  }

  /* Done. */























































  return pWInfo;

  /* Jump here if malloc fails */
whereBeginError:
  if( pWInfo ){
    pParse->nQueryLoop = pWInfo->savedNQueryLoop;
    whereInfoFree(db, pWInfo);

Changes to test/where.test.

61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# "sqlite_search_count" which tallys the number of executions of MoveTo
# and Next operators in the VDBE.  By verifing that the search count is
# small we can be assured that indices are being used properly.
#
do_test where-1.1.1 {
  count {SELECT x, y, w FROM t1 WHERE w=10}
} {3 121 10 3}
do_test where-1.1.2 {
  set sqlite_query_plan
} {t1 i1w}
do_test where-1.1.3 {
  db status step
} {0}
do_test where-1.1.4 {
  db eval {SELECT x, y, w FROM t1 WHERE +w=10}
} {3 121 10}
do_test where-1.1.5 {
  db status step
} {99}
do_test where-1.1.6 {
  set sqlite_query_plan
} {t1 {}}
do_test where-1.1.7 {
  count {SELECT x, y, w AS abc FROM t1 WHERE abc=10}
} {3 121 10 3}
do_test where-1.1.8 {
  set sqlite_query_plan
} {t1 i1w}
do_test where-1.1.9 {
  db status step
} {0}
do_test where-1.2.1 {
  count {SELECT x, y, w FROM t1 WHERE w=11}
} {3 144 11 3}
do_test where-1.2.2 {
................................................................................
} {3 144 11 3}
do_test where-1.3.2 {
  count {SELECT x, y, w AS abc FROM t1 WHERE 11=abc}
} {3 144 11 3}
do_test where-1.4.1 {
  count {SELECT w, x, y FROM t1 WHERE 11=w AND x>2}
} {11 3 144 3}
do_test where-1.4.2 {
  set sqlite_query_plan
} {t1 i1w}
do_test where-1.4.3 {
  count {SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2}
} {11 3 144 3}
do_test where-1.4.4 {
  set sqlite_query_plan
} {t1 i1w}
do_test where-1.5 {
  count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2}
} {3 144 3}
do_test where-1.5.2 {
  set sqlite_query_plan
} {t1 i1w}
do_test where-1.6 {
  count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11}
} {3 144 3}
do_test where-1.7 {
  count {SELECT x, y FROM t1 WHERE w=11 AND y<200 AND x>2}
} {3 144 3}
do_test where-1.8 {
  count {SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3}
} {3 144 3}
do_test where-1.8.2 {
  set sqlite_query_plan
} {t1 i1xy}
do_test where-1.8.3 {
  count {SELECT x, y FROM t1 WHERE y=144 AND x=3}
  set sqlite_query_plan
} {{} i1xy}
do_test where-1.9 {
  count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3}
} {3 144 3}
do_test where-1.10 {
  count {SELECT x, y FROM t1 WHERE x=3 AND w>=10 AND y=121}
} {3 121 3}
do_test where-1.11 {







|
|
|









|
|
|



|
|
|







 







|
|
|



|
|
|



|
|
|









|
|
|
|
|
|
<







61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
...
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
# "sqlite_search_count" which tallys the number of executions of MoveTo
# and Next operators in the VDBE.  By verifing that the search count is
# small we can be assured that indices are being used properly.
#
do_test where-1.1.1 {
  count {SELECT x, y, w FROM t1 WHERE w=10}
} {3 121 10 3}
do_eqp_test where-1.1.2 {
  SELECT x, y, w FROM t1 WHERE w=10
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.1.3 {
  db status step
} {0}
do_test where-1.1.4 {
  db eval {SELECT x, y, w FROM t1 WHERE +w=10}
} {3 121 10}
do_test where-1.1.5 {
  db status step
} {99}
do_eqp_test where-1.1.6 {
  SELECT x, y, w FROM t1 WHERE +w=10
} {*SCAN TABLE t1 *}
do_test where-1.1.7 {
  count {SELECT x, y, w AS abc FROM t1 WHERE abc=10}
} {3 121 10 3}
do_eqp_test where-1.1.8 {
  SELECT x, y, w AS abc FROM t1 WHERE abc=10
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.1.9 {
  db status step
} {0}
do_test where-1.2.1 {
  count {SELECT x, y, w FROM t1 WHERE w=11}
} {3 144 11 3}
do_test where-1.2.2 {
................................................................................
} {3 144 11 3}
do_test where-1.3.2 {
  count {SELECT x, y, w AS abc FROM t1 WHERE 11=abc}
} {3 144 11 3}
do_test where-1.4.1 {
  count {SELECT w, x, y FROM t1 WHERE 11=w AND x>2}
} {11 3 144 3}
do_eqp_test where-1.4.2 {
  SELECT w, x, y FROM t1 WHERE 11=w AND x>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.4.3 {
  count {SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2}
} {11 3 144 3}
do_eqp_test where-1.4.4 {
  SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.5 {
  count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2}
} {3 144 3}
do_eqp_test where-1.5.2 {
  SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2
} {*SEARCH TABLE t1 USING INDEX i1w (w=?) *}
do_test where-1.6 {
  count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11}
} {3 144 3}
do_test where-1.7 {
  count {SELECT x, y FROM t1 WHERE w=11 AND y<200 AND x>2}
} {3 144 3}
do_test where-1.8 {
  count {SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3}
} {3 144 3}
do_eqp_test where-1.8.2 {
  SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3
} {*SEARCH TABLE t1 USING INDEX i1xy (x=? AND y=?) *}
do_eqp_test where-1.8.3 {
  SELECT x, y FROM t1 WHERE y=144 AND x=3
} {*SEARCH TABLE t1 USING COVERING INDEX i1xy (x=? AND y=?) *}

do_test where-1.9 {
  count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3}
} {3 144 3}
do_test where-1.10 {
  count {SELECT x, y FROM t1 WHERE x=3 AND w>=10 AND y=121}
} {3 121 3}
do_test where-1.11 {