/ Check-in [bfefc575]
Login

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

Overview
Comment:Do not allow cursor hints to use expressions containing subqueries. This change fixes the problem seen in the previous check-in.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | cursor-hints
Files: files | file ages | folders
SHA1: bfefc57554853e467ee6aeaba8d08331406fa216
User & Date: drh 2013-12-07 23:35:21
Context
2014-07-14
19:04
In the expression passed to sqlite3BtreeCursorHint() for the inner loops of joins, replace any TK_COLUMN references to columns in the outer loops with TK_REGISTER expressions (Expr.iTable indicates the specific register containing the value). There are no automated tests for this yet. check-in: f9dddd00 user: dan tags: cursor-hints
2013-12-07
23:35
Do not allow cursor hints to use expressions containing subqueries. This change fixes the problem seen in the previous check-in. check-in: bfefc575 user: drh tags: cursor-hints
20:39
If the SQLITE_ENABLE_CURSOR_HINTS macro is defined, then invoke the sqlite3BtreeCursorHint() interface to provide hints to the storage engine about rows that need not be returned. Hints can be disabled using SQLITE_TESTCTRL_OPTIMIZATIONS with SQLITE_CursorHints (0x2000). Cursor hints are not used by the built-in storage engine of SQLite but might be useful to applications that provide their own storage engine. The current code is work-in-progrss and contains bugs. check-in: 3a9bec52 user: drh tags: cursor-hints
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

  1259   1259   ** For the purposes of this function, a double-quoted string (ex: "abc")
  1260   1260   ** is considered a variable but a single-quoted string (ex: 'abc') is
  1261   1261   ** a constant.
  1262   1262   */
  1263   1263   int sqlite3ExprIsConstantOrFunction(Expr *p){
  1264   1264     return exprIsConst(p, 2);
  1265   1265   }
         1266  +
         1267  +#ifdef SQLITE_ENABLE_CURSOR_HINTS
         1268  +/*
         1269  +** Walk an expression tree.  Return 1 if the expression contains a
         1270  +** subquery of some kind.  Return 0 if there are no subqueries.
         1271  +*/
         1272  +int sqlite3ExprContainsSubquery(Expr *p){
         1273  +  Walker w;
         1274  +  memset(&w, 0, sizeof(w));
         1275  +  w.u.i = 1;
         1276  +  w.xExprCallback = sqlite3ExprWalkNoop;
         1277  +  w.xSelectCallback = selectNodeIsConstant;
         1278  +  sqlite3WalkExpr(&w, p);
         1279  +  return w.u.i==0;
         1280  +}
         1281  +#endif
  1266   1282   
  1267   1283   /*
  1268   1284   ** If the expression p codes a constant integer that is small enough
  1269   1285   ** to fit in a 32-bit integer, return 1 and put the value of the integer
  1270   1286   ** in *pValue.  If the expression is not an integer or if it is too big
  1271   1287   ** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
  1272   1288   */

Changes to src/select.c.

  3685   3685   **
  3686   3686   ** When this routine is the Walker.xExprCallback then expression trees
  3687   3687   ** are walked without any actions being taken at each node.  Presumably,
  3688   3688   ** when this routine is used for Walker.xExprCallback then 
  3689   3689   ** Walker.xSelectCallback is set to do something useful for every 
  3690   3690   ** subquery in the parser tree.
  3691   3691   */
  3692         -static int exprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
         3692  +int sqlite3ExprWalkNoop(Walker *NotUsed, Expr *NotUsed2){
  3693   3693     UNUSED_PARAMETER2(NotUsed, NotUsed2);
  3694   3694     return WRC_Continue;
  3695   3695   }
  3696   3696   
  3697   3697   /*
  3698   3698   ** This routine "expands" a SELECT statement and all of its subqueries.
  3699   3699   ** For additional information on what it means to "expand" a SELECT
................................................................................
  3706   3706   ** If anything goes wrong, an error message is written into pParse.
  3707   3707   ** The calling function can detect the problem by looking at pParse->nErr
  3708   3708   ** and/or pParse->db->mallocFailed.
  3709   3709   */
  3710   3710   static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
  3711   3711     Walker w;
  3712   3712     memset(&w, 0, sizeof(w));
  3713         -  w.xExprCallback = exprWalkNoop;
         3713  +  w.xExprCallback = sqlite3ExprWalkNoop;
  3714   3714     w.pParse = pParse;
  3715   3715     if( pParse->hasCompound ){
  3716   3716       w.xSelectCallback = convertCompoundSelectToSubquery;
  3717   3717       sqlite3WalkSelect(&w, pSelect);
  3718   3718     }
  3719   3719     w.xSelectCallback = selectExpander;
  3720   3720     sqlite3WalkSelect(&w, pSelect);
................................................................................
  3770   3770   ** Use this routine after name resolution.
  3771   3771   */
  3772   3772   static void sqlite3SelectAddTypeInfo(Parse *pParse, Select *pSelect){
  3773   3773   #ifndef SQLITE_OMIT_SUBQUERY
  3774   3774     Walker w;
  3775   3775     memset(&w, 0, sizeof(w));
  3776   3776     w.xSelectCallback = selectAddSubqueryTypeInfo;
  3777         -  w.xExprCallback = exprWalkNoop;
         3777  +  w.xExprCallback = sqlite3ExprWalkNoop;
  3778   3778     w.pParse = pParse;
  3779   3779     w.bSelectDepthFirst = 1;
  3780   3780     sqlite3WalkSelect(&w, pSelect);
  3781   3781   #endif
  3782   3782   }
  3783   3783   
  3784   3784   

Changes to src/sqliteInt.h.

  2613   2613   
  2614   2614   /* Forward declarations */
  2615   2615   int sqlite3WalkExpr(Walker*, Expr*);
  2616   2616   int sqlite3WalkExprList(Walker*, ExprList*);
  2617   2617   int sqlite3WalkSelect(Walker*, Select*);
  2618   2618   int sqlite3WalkSelectExpr(Walker*, Select*);
  2619   2619   int sqlite3WalkSelectFrom(Walker*, Select*);
         2620  +int sqlite3ExprWalkNoop(Walker*, Expr*);
  2620   2621   
  2621   2622   /*
  2622   2623   ** Return code from the parse-tree walking primitives and their
  2623   2624   ** callbacks.
  2624   2625   */
  2625   2626   #define WRC_Continue    0   /* Continue down into children */
  2626   2627   #define WRC_Prune       1   /* Omit children but continue walking siblings */
................................................................................
  2967   2968   void sqlite3RollbackTransaction(Parse*);
  2968   2969   void sqlite3Savepoint(Parse*, int, Token*);
  2969   2970   void sqlite3CloseSavepoints(sqlite3 *);
  2970   2971   void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
  2971   2972   int sqlite3ExprIsConstant(Expr*);
  2972   2973   int sqlite3ExprIsConstantNotJoin(Expr*);
  2973   2974   int sqlite3ExprIsConstantOrFunction(Expr*);
         2975  +int sqlite3ExprContainsSubquery(Expr*);
  2974   2976   int sqlite3ExprIsInteger(Expr*, int*);
  2975   2977   int sqlite3ExprCanBeNull(const Expr*);
  2976   2978   void sqlite3ExprCodeIsNullJump(Vdbe*, const Expr*, int, int);
  2977   2979   int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
  2978   2980   int sqlite3IsRowid(const char*);
  2979   2981   void sqlite3GenerateRowDelete(Parse*,Table*,Trigger*,int,int,int,i16,u8,u8,u8);
  2980   2982   void sqlite3GenerateRowIndexDelete(Parse*, Table*, int, int, int*);

Changes to src/where.c.

  2741   2741     iCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor;
  2742   2742     msk = ~getMask(&pWInfo->sMaskSet, iCur);
  2743   2743     pWC = &pWInfo->sWC;
  2744   2744     for(i=0; i<pWC->nTerm; i++){
  2745   2745       pTerm = &pWC->a[i];
  2746   2746       if( pTerm->prereqAll & msk ) continue;
  2747   2747       if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue;
         2748  +    if( sqlite3ExprContainsSubquery(pTerm->pExpr) ) continue;
  2748   2749       for(j=0; j<pWLoop->nLTerm && pWLoop->aLTerm[j]!=pTerm; j++){}
  2749   2750       if( j<pWLoop->nLTerm ) continue;
  2750   2751       pExpr = sqlite3ExprAnd(db, pExpr, sqlite3ExprDup(db, pTerm->pExpr, 0));
  2751   2752     } 
  2752   2753     if( pExpr!=0 ){
  2753   2754       sqlite3VdbeAddOp4(v, OP_CursorHint, pLevel->iTabCur, iCur, 0,
  2754   2755                         (const char*)pExpr, P4_EXPR);