/ Check-in [97657445]
Login

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

Overview
Comment:Merge recent trunk fixes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA1:97657445860363f5bd62c37e6a565e782e7eb908
User & Date: drh 2016-07-28 18:42:21
Context
2016-08-04
09:13
Merge the ORDER BY LIMIT fix, and other enhancements, from trunk. check-in: bf5a9542 user: drh tags: apple-osx
01:47
Add an experimental SQLITE_ENABLE_UNKNOWN_SQL_FUNCTION compile-time option. This changes has been merged into main branches via cherry-pick. Closed-Leaf check-in: 4ada023c user: drh tags: unknown-function
2016-07-28
18:42
Merge recent trunk fixes. check-in: 97657445 user: drh tags: apple-osx
18:38
Disable the authorizer callback when reparsing the schema. This avoids undesirable authorization failures following an ALTER TABLE. check-in: 805d01cd user: drh tags: trunk
2016-07-26
15:17
Merge fixes to sqlite3_scrub_backup() from trunk. check-in: 91e811f5 user: drh tags: apple-osx
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/auth.c.

   107    107     const char *zCol,               /* Column name */
   108    108     int iDb                         /* Index of containing database. */
   109    109   ){
   110    110     sqlite3 *db = pParse->db;       /* Database handle */
   111    111     char *zDb = db->aDb[iDb].zName; /* Name of attached database */
   112    112     int rc;                         /* Auth callback return code */
   113    113   
          114  +  if( db->init.busy ) return SQLITE_OK;
   114    115     rc = db->xAuth(db->pAuthArg, SQLITE_READ, zTab,zCol,zDb,pParse->zAuthContext
   115    116   #ifdef SQLITE_USER_AUTHENTICATION
   116    117                    ,db->auth.zAuthUser
   117    118   #endif
   118    119                   );
   119    120     if( rc==SQLITE_DENY ){
   120    121       if( db->nDb>2 || iDb!=0 ){

Changes to src/ctime.c.

    41     41   #endif
    42     42   #if SQLITE_CASE_SENSITIVE_LIKE
    43     43     "CASE_SENSITIVE_LIKE",
    44     44   #endif
    45     45   #if SQLITE_CHECK_PAGES
    46     46     "CHECK_PAGES",
    47     47   #endif
    48         -#if defined(__clang__) && defined(__clang_version__)
    49         -  "COMPILER=clang-" __clang_version__,
           48  +#if defined(__clang__) && defined(__clang_major__)
           49  +  "COMPILER=clang-" CTIMEOPT_VAL(__clang_major__) "."
           50  +                    CTIMEOPT_VAL(__clang_minor__) "."
           51  +                    CTIMEOPT_VAL(__clang_patchlevel__),
    50     52   #elif defined(_MSC_VER)
    51     53     "COMPILER=msvc-" CTIMEOPT_VAL(_MSC_VER),
    52     54   #elif defined(__GNUC__) && defined(__VERSION__)
    53     55     "COMPILER=gcc-" __VERSION__,
    54     56   #endif
    55     57   #if SQLITE_COVERAGE_TEST
    56     58     "COVERAGE_TEST",

Changes to src/expr.c.

  3960   3960      && sqlite3ExprCompare(pE1->pLeft, pE2->pLeft, iTab)==0
  3961   3961      && (pE1->op!=TK_ISNULL && pE1->op!=TK_IS)
  3962   3962     ){
  3963   3963       return 1;
  3964   3964     }
  3965   3965     return 0;
  3966   3966   }
         3967  +
         3968  +/*
         3969  +** An instance of the following structure is used by the tree walker
         3970  +** to determine if an expression can be evaluated by reference to the
         3971  +** index only, without having to do a search for the corresponding
         3972  +** table entry.  The IdxCover.pIdx field is the index.  IdxCover.iCur
         3973  +** is the cursor for the table.
         3974  +*/
         3975  +struct IdxCover {
         3976  +  Index *pIdx;     /* The index to be tested for coverage */
         3977  +  int iCur;        /* Cursor number for the table corresponding to the index */
         3978  +};
         3979  +
         3980  +/*
         3981  +** Check to see if there are references to columns in table 
         3982  +** pWalker->u.pIdxCover->iCur can be satisfied using the index
         3983  +** pWalker->u.pIdxCover->pIdx.
         3984  +*/
         3985  +static int exprIdxCover(Walker *pWalker, Expr *pExpr){
         3986  +  if( pExpr->op==TK_COLUMN
         3987  +   && pExpr->iTable==pWalker->u.pIdxCover->iCur
         3988  +   && sqlite3ColumnOfIndex(pWalker->u.pIdxCover->pIdx, pExpr->iColumn)<0
         3989  +  ){
         3990  +    pWalker->eCode = 1;
         3991  +    return WRC_Abort;
         3992  +  }
         3993  +  return WRC_Continue;
         3994  +}
         3995  +
         3996  +/*
         3997  +** Determine if an index pIdx on table with cursor iCur contains will
         3998  +** the expression pExpr.  Return true if the index does cover the
         3999  +** expression and false if the pExpr expression references table columns
         4000  +** that are not found in the index pIdx.
         4001  +**
         4002  +** An index covering an expression means that the expression can be
         4003  +** evaluated using only the index and without having to lookup the
         4004  +** corresponding table entry.
         4005  +*/
         4006  +int sqlite3ExprCoveredByIndex(
         4007  +  Expr *pExpr,        /* The index to be tested */
         4008  +  int iCur,           /* The cursor number for the corresponding table */
         4009  +  Index *pIdx         /* The index that might be used for coverage */
         4010  +){
         4011  +  Walker w;
         4012  +  struct IdxCover xcov;
         4013  +  memset(&w, 0, sizeof(w));
         4014  +  xcov.iCur = iCur;
         4015  +  xcov.pIdx = pIdx;
         4016  +  w.xExprCallback = exprIdxCover;
         4017  +  w.u.pIdxCover = &xcov;
         4018  +  sqlite3WalkExpr(&w, pExpr);
         4019  +  return !w.eCode;
         4020  +}
         4021  +
  3967   4022   
  3968   4023   /*
  3969   4024   ** An instance of the following structure is used by the tree walker
  3970   4025   ** to count references to table columns in the arguments of an 
  3971   4026   ** aggregate function, in order to implement the
  3972   4027   ** sqlite3FunctionThisSrc() routine.
  3973   4028   */

Changes to src/sqliteInt.h.

  3253   3253       NameContext *pNC;                          /* Naming context */
  3254   3254       int n;                                     /* A counter */
  3255   3255       int iCur;                                  /* A cursor number */
  3256   3256       SrcList *pSrcList;                         /* FROM clause */
  3257   3257       struct SrcCount *pSrcCount;                /* Counting column references */
  3258   3258       struct CCurHint *pCCurHint;                /* Used by codeCursorHint() */
  3259   3259       int *aiCol;                                /* array of column indexes */
         3260  +    struct IdxCover *pIdxCover;                /* Check for index coverage */
  3260   3261     } u;
  3261   3262   };
  3262   3263   
  3263   3264   /* Forward declarations */
  3264   3265   int sqlite3WalkExpr(Walker*, Expr*);
  3265   3266   int sqlite3WalkExprList(Walker*, ExprList*);
  3266   3267   int sqlite3WalkSelect(Walker*, Select*);
................................................................................
  3696   3697   int sqlite3RunVacuum(char**, sqlite3*);
  3697   3698   char *sqlite3NameFromToken(sqlite3*, Token*);
  3698   3699   int sqlite3ExprCompare(Expr*, Expr*, int);
  3699   3700   int sqlite3ExprListCompare(ExprList*, ExprList*, int);
  3700   3701   int sqlite3ExprImpliesExpr(Expr*, Expr*, int);
  3701   3702   void sqlite3ExprAnalyzeAggregates(NameContext*, Expr*);
  3702   3703   void sqlite3ExprAnalyzeAggList(NameContext*,ExprList*);
         3704  +int sqlite3ExprCoveredByIndex(Expr*, int iCur, Index *pIdx);
  3703   3705   int sqlite3FunctionUsesThisSrc(Expr*, SrcList*);
  3704   3706   Vdbe *sqlite3GetVdbe(Parse*);
  3705   3707   #ifndef SQLITE_OMIT_BUILTIN_TEST
  3706   3708   void sqlite3PrngSaveState(void);
  3707   3709   void sqlite3PrngRestoreState(void);
  3708   3710   #endif
  3709   3711   void sqlite3RollbackAll(sqlite3*,int);

Changes to src/where.c.

  2474   2474      && (rc = whereLoopResize(db, pNew, pNew->nLTerm+1))==SQLITE_OK
  2475   2475     ){
  2476   2476       LogEst nIter;
  2477   2477       pNew->u.btree.nEq++;
  2478   2478       pNew->nSkip++;
  2479   2479       pNew->aLTerm[pNew->nLTerm++] = 0;
  2480   2480       pNew->wsFlags |= WHERE_SKIPSCAN;
  2481         -    nIter = pProbe->aiRowLogEst[saved_nEq] - pProbe->aiRowLogEst[saved_nEq+1];
         2481  +    nIter = pProbe->aiRowLogEst[saved_nEq]+1 - pProbe->aiRowLogEst[saved_nEq+1];
  2482   2482       pNew->nOut -= nIter;
  2483   2483       /* TUNING:  Because uncertainties in the estimates for skip-scan queries,
  2484   2484       ** add a 1.375 fudge factor to make skip-scan slightly less likely. */
  2485         -    nIter += 5;
         2485  +    nIter += 4;
  2486   2486       whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nIter + nInMul);
  2487   2487       pNew->nOut = saved_nOut;
  2488   2488       pNew->u.btree.nEq = saved_nEq;
  2489   2489       pNew->nSkip = saved_nSkip;
  2490   2490       pNew->wsFlags = saved_wsFlags;
  2491   2491     }
  2492   2492   
................................................................................
  2771   2771            && OptimizationEnabled(pWInfo->pParse->db, SQLITE_CoverIdxScan)
  2772   2772             )
  2773   2773         ){
  2774   2774           pNew->iSortIdx = b ? iSortIdx : 0;
  2775   2775   
  2776   2776           /* The cost of visiting the index rows is N*K, where K is
  2777   2777           ** between 1.1 and 3.0, depending on the relative sizes of the
  2778         -        ** index and table rows. If this is a non-covering index scan,
  2779         -        ** also add the cost of visiting table rows (N*3.0).  */
         2778  +        ** index and table rows. */
  2780   2779           pNew->rRun = rSize + 1 + (15*pProbe->szIdxRow)/pTab->szTabRow;
  2781   2780           if( m!=0 ){
  2782         -          pNew->rRun = sqlite3LogEstAdd(pNew->rRun, rSize+16);
         2781  +          /* If this is a non-covering index scan, add in the cost of
         2782  +          ** doing table lookups.  The cost will be 3x the number of
         2783  +          ** lookups.  Take into account WHERE clause terms that can be
         2784  +          ** satisfied using just the index, and that do not require a
         2785  +          ** table lookup. */
         2786  +          LogEst nLookup = rSize + 16;  /* Base cost:  N*3 */
         2787  +          int ii;
         2788  +          int iCur = pSrc->iCursor;
         2789  +          WhereClause *pWC = &pWInfo->sWC;
         2790  +          for(ii=0; ii<pWC->nTerm; ii++){
         2791  +            WhereTerm *pTerm = &pWC->a[ii];
         2792  +            if( !sqlite3ExprCoveredByIndex(pTerm->pExpr, iCur, pProbe) ){
         2793  +              break;
         2794  +            }
         2795  +            /* pTerm can be evaluated using just the index.  So reduce
         2796  +            ** the expected number of table lookups accordingly */
         2797  +            if( pTerm->truthProb<=0 ){
         2798  +              nLookup += pTerm->truthProb;
         2799  +            }else{
         2800  +              nLookup--;
         2801  +              if( pTerm->eOperator & (WO_EQ|WO_IS) ) nLookup -= 19;
         2802  +            }
         2803  +          }
         2804  +          
         2805  +          pNew->rRun = sqlite3LogEstAdd(pNew->rRun, nLookup);
  2783   2806           }
  2784   2807           ApplyCostMultiplier(pNew->rRun, pTab->costMult);
  2785   2808           whereLoopOutputAdjust(pWC, pNew, rSize);
  2786   2809           rc = whereLoopInsert(pBuilder, pNew);
  2787   2810           pNew->nOut = rSize;
  2788   2811           if( rc ) break;
  2789   2812         }
................................................................................
  3945   3968         }
  3946   3969       }else{
  3947   3970         pWInfo->nOBSat = pFrom->isOrdered;
  3948   3971         pWInfo->revMask = pFrom->revLoop;
  3949   3972         if( pWInfo->nOBSat<=0 ){
  3950   3973           pWInfo->nOBSat = 0;
  3951   3974           if( nLoop>0 ){
  3952         -          Bitmask m;
         3975  +          Bitmask m = 0;
  3953   3976             int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom,
  3954   3977                         WHERE_ORDERBY_LIMIT, nLoop-1, pFrom->aLoop[nLoop-1], &m);
  3955   3978             if( rc==pWInfo->pOrderBy->nExpr ){
  3956   3979               pWInfo->bOrderedInnerLoop = 1;
  3957   3980               pWInfo->revMask = m;
  3958   3981             }
  3959   3982           }

Changes to test/auth2.test.

    94     94   SQLITE_CREATE_TABLE t2 {} main {}
    95     95   SQLITE_UPDATE sqlite_master type main {}
    96     96   SQLITE_UPDATE sqlite_master name main {}
    97     97   SQLITE_UPDATE sqlite_master tbl_name main {}
    98     98   SQLITE_UPDATE sqlite_master rootpage main {}
    99     99   SQLITE_UPDATE sqlite_master sql main {}
   100    100   SQLITE_READ sqlite_master ROWID main {}
   101         -SQLITE_READ sqlite_master name main {}
   102         -SQLITE_READ sqlite_master rootpage main {}
   103         -SQLITE_READ sqlite_master sql main {}
   104         -SQLITE_READ sqlite_master tbl_name main {}
   105         -SQLITE_READ sqlite_master type main {}
   106         -SQLITE_READ sqlite_master ROWID main {}
   107    101   }
   108    102   do_test auth2-2.2 {
   109    103     set ::authargs {}
   110    104     db eval {
   111    105       CREATE VIEW v2 AS SELECT x+y AS a, y+z AS b from t2;
   112    106     }
   113    107     set ::authargs
................................................................................
   114    108   } {SQLITE_INSERT sqlite_master {} main {}
   115    109   SQLITE_CREATE_VIEW v2 {} main {}
   116    110   SQLITE_UPDATE sqlite_master type main {}
   117    111   SQLITE_UPDATE sqlite_master name main {}
   118    112   SQLITE_UPDATE sqlite_master tbl_name main {}
   119    113   SQLITE_UPDATE sqlite_master rootpage main {}
   120    114   SQLITE_UPDATE sqlite_master sql main {}
   121         -SQLITE_READ sqlite_master ROWID main {}
   122         -SQLITE_READ sqlite_master name main {}
   123         -SQLITE_READ sqlite_master rootpage main {}
   124         -SQLITE_READ sqlite_master sql main {}
   125         -SQLITE_READ sqlite_master tbl_name main {}
   126         -SQLITE_READ sqlite_master type main {}
   127    115   SQLITE_READ sqlite_master ROWID main {}
   128    116   }
   129    117   do_test auth2-2.3 {
   130    118     set ::authargs {}
   131    119     db eval {
   132    120       SELECT a, b FROM v2;
   133    121     }

Changes to test/auth3.test.

     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   #
    12     12   # Test that the truncate optimization is disabled if the SQLITE_DELETE
    13     13   # authorization callback returns SQLITE_IGNORE.
    14     14   #
    15         -# $Id: auth3.test,v 1.2 2009/05/04 01:58:31 drh Exp $
    16         -#
           15  +# Test that authorizer is disabled during schema parsing.
    17     16   
    18     17   set testdir [file dirname $argv0]
    19     18   source $testdir/tester.tcl
    20     19   
    21     20   # disable this test if the SQLITE_OMIT_AUTHORIZATION macro is
    22     21   # defined during compilation.
    23     22   if {[catch {db auth {}} msg]} {
................................................................................
   103    102     }
   104    103     set sqlite_search_count 0
   105    104     execsql {
   106    105       DELETE FROM t1;
   107    106     }
   108    107     set sqlite_search_count
   109    108   } {1}
          109  +
          110  +# 2016-07-28.  A problem report from a private client complaining about
          111  +# an authorizer failure during an ALTER TABLE.  The solution (I think) is
          112  +# to disable the authorizer during schema parsing.
          113  +#
          114  +proc auth {code args} {
          115  +  if {$code=="SQLITE_READ" && [regexp {DoNotRead} $args]} {
          116  +    return SQLITE_DENY
          117  +  }
          118  +  return SQLITE_OK
          119  +}
          120  +do_execsql_test auth3-3.0 {
          121  +  CREATE TEMPORARY TABLE TempTable (
          122  +      key TEXT NOT NULL ON CONFLICT FAIL UNIQUE ON CONFLICT REPLACE,
          123  +      value TEXT NOT NULL ON CONFLICT FAIL);
          124  +  ALTER TABLE TempTable RENAME TO DoNotRead;
          125  +  SELECT name FROM sqlite_temp_master;
          126  +} {DoNotRead sqlite_autoindex_DoNotRead_1}
   110    127   
   111    128   finish_test

Changes to test/in.test.

   635    635     }
   636    636   } {1 {only a single result allowed for a SELECT that is part of an expression}}
   637    637   
   638    638   
   639    639   do_test in-13.X {
   640    640     db nullvalue ""
   641    641   } {}
          642  +
          643  +# At one point the following was causing valgrind to report a "jump
          644  +# depends on unitialized location" problem.
          645  +#
          646  +do_execsql_test in-14.0 {
          647  +  CREATE TABLE c1(a);
          648  +  INSERT INTO c1 VALUES(1), (2), (4), (3);
          649  +}
          650  +do_execsql_test in-14.1 {
          651  +  SELECT * FROM c1 WHERE a IN (SELECT a FROM c1) ORDER BY 1
          652  +} {1 2 3 4}
   642    653   
   643    654   finish_test

Added test/index8.test.

            1  +# 2016-07-27
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# Test cases for ORDER BY and LIMIT on an index scan.
           13  +#
           14  +
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +
           19  +# Performance regression reported at
           20  +# http://www.mail-archive.com/sqlite-users@mailinglists.sqlite.org/msg98615.html
           21  +#
           22  +# Caused by the ORDER BY LIMIT optionation for check-in
           23  +# https://sqlite.org/src/info/bf46179d44843769
           24  +#
           25  +# Fixed on approximately 2016-07-27 by changes that compute a better score
           26  +# for index scans by taking into account WHERE clause constraints that can
           27  +# be handled by the index and do not require a table lookup.
           28  +#
           29  +do_execsql_test 1.0 {
           30  +  CREATE TABLE t1(a,b,c,d);
           31  +  WITH RECURSIVE c(x) AS (VALUES(0) UNION ALL SELECT x+1 FROM c WHERE x<100)
           32  +  INSERT INTO t1(a,b,c,d)
           33  +     SELECT x/10, x%10, x%19, x FROM c;
           34  +  CREATE INDEX t1abc ON t1(a,b,c);
           35  +  SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
           36  +} {0 4 4 4 2 3 4 23}
           37  +
           38  +# Prior to the fix, the following EQP would show a table scan and a sort
           39  +# rather than an index scan.
           40  +#
           41  +do_execsql_test 1.0eqp {
           42  +  EXPLAIN QUERY PLAN
           43  +  SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
           44  +} {/SCAN TABLE t1 USING INDEX t1abc/}
           45  +
           46  +# If we change the index so that it no longer covers the WHERE clause,
           47  +# then we should (correctly) revert to using a table scan.
           48  +#
           49  +do_execsql_test 1.1 {
           50  +  DROP INDEX t1abc;
           51  +  CREATE INDEX t1abd ON t1(a,b,d);
           52  +  SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
           53  +} {0 4 4 4 2 3 4 23}
           54  +do_execsql_test 1.1eqp {
           55  +  EXPLAIN QUERY PLAN
           56  +  SELECT * FROM t1 WHERE c=4 ORDER BY a, b LIMIT 2;
           57  +} {~/USING INDEX/}
           58  +
           59  +
           60  +finish_test

Changes to test/parser1.test.

    72     72   } {1 {syntax error after column name "x"}}
    73     73   do_catchsql_test parser1-2.2 {
    74     74     WITH RECURSIVE
    75     75       c(x ASC) AS (VALUES(1) UNION SELECT x+1 FROM c WHERE x<5)
    76     76     SELECT x FROM c;
    77     77   } {1 {syntax error after column name "x"}}
    78     78   
           79  +# Verify that the comma between multiple table constraints is
           80  +# optional.
           81  +#
           82  +# The missing comma is technically a syntax error.  But we have to support
           83  +# it because there might be legacy databases that omit the commas in their
           84  +# sqlite_master tables.
           85  +#
           86  +do_execsql_test parser1-3.1 {
           87  +  CREATE TABLE t300(id INTEGER PRIMARY KEY);
           88  +  CREATE TABLE t301(
           89  +    id INTEGER PRIMARY KEY,
           90  +    c1 INTEGER NOT NULL,
           91  +    c2 INTEGER NOT NULL,
           92  +    c3 BOOLEAN NOT NULL DEFAULT 0,
           93  +    FOREIGN KEY(c1) REFERENCES t300(id) ON DELETE CASCADE ON UPDATE RESTRICT
           94  +        /* no comma */
           95  +    FOREIGN KEY(c2) REFERENCES t300(id) ON DELETE CASCADE ON UPDATE RESTRICT
           96  +        /* no comma */
           97  +    UNIQUE(c1, c2)
           98  +  );
           99  +  PRAGMA foreign_key_list(t301);
          100  +} {0 0 t300 c2 id RESTRICT CASCADE NONE 1 0 t300 c1 id RESTRICT CASCADE NONE}
          101  +
    79    102   finish_test

Changes to test/scanstatus.test.

   329    329   do_eqp_test 5.3.1 {
   330    330     SELECT count(*) FROM t2 WHERE y = 'j';
   331    331   } {0 0 0 {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}}
   332    332   do_execsql_test 5.3.2 {
   333    333     SELECT count(*) FROM t2 WHERE y = 'j';
   334    334   } {19}
   335    335   do_scanstatus_test 5.3.3 { 
   336         -  nLoop 1 nVisit 19 nEst 56.0 zName t2xy zExplain
          336  +  nLoop 1 nVisit 19 nEst 52.0 zName t2xy zExplain
   337    337     {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
   338    338   }
   339    339   
   340    340   do_eqp_test 5.4.1 {
   341    341     SELECT count(*) FROM t1, t2 WHERE y = c;
   342    342   } {
   343    343     0 0 0 {SCAN TABLE t1 USING COVERING INDEX t1bc}
................................................................................
   345    345   }
   346    346   do_execsql_test 5.4.2 {
   347    347     SELECT count(*) FROM t1, t2 WHERE y = c;
   348    348   } {200}
   349    349   do_scanstatus_test 5.4.3 { 
   350    350     nLoop 1 nVisit 10 nEst 10.0 zName t1bc 
   351    351     zExplain {SCAN TABLE t1 USING COVERING INDEX t1bc}
   352         -  nLoop 10 nVisit 200 nEst 56.0 zName t2xy 
          352  +  nLoop 10 nVisit 200 nEst 52.0 zName t2xy 
   353    353     zExplain {SEARCH TABLE t2 USING COVERING INDEX t2xy (ANY(x) AND y=?)}
   354    354   }
   355    355   
   356    356   do_eqp_test 5.5.1 {
   357    357     SELECT count(*) FROM t1, t3 WHERE y = c;
   358    358   } {
   359    359     0 0 1 {SCAN TABLE t3}