SQLite

Check-in [4c5a3c5f]
Login

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

Overview
Comment:New assert() statements to validate the parameters to sqlite3BtreeCursorHint(). Fix a problem with the construction of those parameters discovered by forum post 0b53708c95.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 4c5a3c5fb351cc1c2ce16c33314ce19c53531f09263f87456283d9d756002f9d
User & Date: drh 2023-04-10 18:44:00
Context
2023-04-10
23:21
For sha3 extension, mention NIST standard implemented. (check-in: 529ab138 user: larrybr tags: trunk)
18:44
New assert() statements to validate the parameters to sqlite3BtreeCursorHint(). Fix a problem with the construction of those parameters discovered by forum post 0b53708c95. (check-in: 4c5a3c5f user: drh tags: trunk)
13:20
Sync the vt02.c test virtual table with TH3, in order to pull in the fix for long delays when there are huge OFFSET values. (check-in: 49ba0300 user: drh tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

942
943
944
945
946
947
948














949
950



951
952
953
954
955
956
957
/*
** Provide hints to the cursor.  The particular hint given (and the type
** and number of the varargs parameters) is determined by the eHintType
** parameter.  See the definitions of the BTREE_HINT_* macros for details.
*/
void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
  /* Used only by system that substitute their own storage engine */














}
#endif




/*
** Provide flag hints to the cursor.
*/
void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
  assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 );
  pCur->hints = x;







>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
|
>
>
>







942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
/*
** Provide hints to the cursor.  The particular hint given (and the type
** and number of the varargs parameters) is determined by the eHintType
** parameter.  See the definitions of the BTREE_HINT_* macros for details.
*/
void sqlite3BtreeCursorHint(BtCursor *pCur, int eHintType, ...){
  /* Used only by system that substitute their own storage engine */
#ifdef SQLITE_DEBUG
  if( ALWAYS(eHintType==BTREE_HINT_RANGE) ){
    va_list ap;
    Expr *pExpr;
    Walker w;
    memset(&w, 0, sizeof(w));
    w.xExprCallback = sqlite3CursorRangeHintExprCheck;
    va_start(ap, eHintType);
    pExpr = va_arg(ap, Expr*);
    w.u.aMem = va_arg(ap, Mem*);
    va_end(ap);
    assert( pExpr!=0 );
    assert( w.u.aMem!=0 );
    sqlite3WalkExpr(&w, pExpr);
  }
#endif /* SQLITE_DEBUG */
}
#endif /* SQLITE_ENABLE_CURSOR_HINTS */


/*
** Provide flag hints to the cursor.
*/
void sqlite3BtreeCursorHintFlags(BtCursor *pCur, unsigned x){
  assert( x==BTREE_SEEK_EQ || x==BTREE_BULKLOAD || x==0 );
  pCur->hints = x;

Changes to src/sqliteInt.h.

4182
4183
4184
4185
4186
4187
4188

4189
4190
4191
4192
4193
4194
4195
    struct WindowRewrite *pRewrite;           /* Window rewrite context */
    struct WhereConst *pConst;                /* WHERE clause constants */
    struct RenameCtx *pRename;                /* RENAME COLUMN context */
    struct Table *pTab;                       /* Table of generated column */
    struct CoveringIndexCheck *pCovIdxCk;     /* Check for covering index */
    SrcItem *pSrcItem;                        /* A single FROM clause item */
    DbFixer *pFix;                            /* See sqlite3FixSelect() */

  } u;
};

/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.







>







4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
    struct WindowRewrite *pRewrite;           /* Window rewrite context */
    struct WhereConst *pConst;                /* WHERE clause constants */
    struct RenameCtx *pRename;                /* RENAME COLUMN context */
    struct Table *pTab;                       /* Table of generated column */
    struct CoveringIndexCheck *pCovIdxCk;     /* Check for covering index */
    SrcItem *pSrcItem;                        /* A single FROM clause item */
    DbFixer *pFix;                            /* See sqlite3FixSelect() */
    Mem *aMem;                                /* See sqlite3BtreeCursorHint() */
  } u;
};

/*
** The following structure contains information used by the sqliteFix...
** routines as they walk the parse tree to make database references
** explicit.

Changes to src/vdbe.h.

398
399
400
401
402
403
404




405
406
# define sqlite3VdbeScanStatusRange(a,b,c,d)
# define sqlite3VdbeScanStatusCounters(a,b,c,d)
#endif

#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, VdbeOp*);
#endif





#endif /* SQLITE_VDBE_H */







>
>
>
>


398
399
400
401
402
403
404
405
406
407
408
409
410
# define sqlite3VdbeScanStatusRange(a,b,c,d)
# define sqlite3VdbeScanStatusCounters(a,b,c,d)
#endif

#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
void sqlite3VdbePrintOp(FILE*, int, VdbeOp*);
#endif

#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG)
int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr);
#endif

#endif /* SQLITE_VDBE_H */

Changes to src/vdbeaux.c.

5270
5271
5272
5273
5274
5275
5276














5277
5278
5279
5280
5281
5282
5283
                           pCtx->pFunc->zName, zContext);
    sqlite3_result_error(pCtx, zMsg, -1);
    sqlite3_free(zMsg);
    return 0;
  }
  return 1;
}















#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/







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







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
                           pCtx->pFunc->zName, zContext);
    sqlite3_result_error(pCtx, zMsg, -1);
    sqlite3_free(zMsg);
    return 0;
  }
  return 1;
}

#if defined(SQLITE_ENABLE_CURSOR_HINTS) && defined(SQLITE_DEBUG)
/*
** This Walker callback is used to help verify that calls to
** sqlite3BtreeCursorHint() with opcode BTREE_HINT_RANGE have 
** byte-code register values correctly initialized.
*/
int sqlite3CursorRangeHintExprCheck(Walker *pWalker, Expr *pExpr){
  if( pExpr->op==TK_REGISTER ){
    assert( (pWalker->u.aMem[pExpr->iTable].flags & MEM_Undefined)==0 );
  }
  return WRC_Continue;
}
#endif /* SQLITE_ENABLE_CURSOR_HINTS && SQLITE_DEBUG */

#ifndef SQLITE_OMIT_VIRTUALTABLE
/*
** Transfer error message text from an sqlite3_vtab.zErrMsg (text stored
** in memory obtained from sqlite3_malloc) into a Vdbe.zErrMsg (text stored
** in memory obtained from sqlite3DbMalloc).
*/

Changes to src/wherecode.c.

1007
1008
1009
1010
1011
1012
1013

1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034




1035
1036
1037
1038
1039
1040
1041
** Also, if the node is a TK_COLUMN that does access the table idenified
** by pCCurHint.iTabCur, and an index is being used (which we will
** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into
** an access of the index rather than the original table.
*/
static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
  int rc = WRC_Continue;

  struct CCurHint *pHint = pWalker->u.pCCurHint;
  if( pExpr->op==TK_COLUMN ){
    if( pExpr->iTable!=pHint->iTabCur ){
      int reg = ++pWalker->pParse->nMem;   /* Register for column value */
      sqlite3ExprCode(pWalker->pParse, pExpr, reg);
      pExpr->op = TK_REGISTER;
      pExpr->iTable = reg;
    }else if( pHint->pIdx!=0 ){
      pExpr->iTable = pHint->iIdxCur;
      pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn);
      assert( pExpr->iColumn>=0 );
    }
  }else if( pExpr->op==TK_AGG_FUNCTION ){
    /* An aggregate function in the WHERE clause of a query means this must
    ** be a correlated sub-query, and expression pExpr is an aggregate from
    ** the parent context. Do not walk the function arguments in this case.
    **
    ** todo: It should be possible to replace this node with a TK_REGISTER
    ** expression, as the result of the expression must be stored in a 
    ** register at this point. The same holds for TK_AGG_COLUMN nodes. */
    rc = WRC_Prune;




  }
  return rc;
}

/*
** Insert an OP_CursorHint instruction if it is appropriate to do so.
*/







>



|
|







|
<
<
<
<
<
<
<

>
>
>
>







1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027







1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
** Also, if the node is a TK_COLUMN that does access the table idenified
** by pCCurHint.iTabCur, and an index is being used (which we will
** know because CCurHint.pIdx!=0) then transform the TK_COLUMN into
** an access of the index rather than the original table.
*/
static int codeCursorHintFixExpr(Walker *pWalker, Expr *pExpr){
  int rc = WRC_Continue;
  int reg;
  struct CCurHint *pHint = pWalker->u.pCCurHint;
  if( pExpr->op==TK_COLUMN ){
    if( pExpr->iTable!=pHint->iTabCur ){
      reg = ++pWalker->pParse->nMem;   /* Register for column value */
      reg = sqlite3ExprCodeTarget(pWalker->pParse, pExpr, reg);
      pExpr->op = TK_REGISTER;
      pExpr->iTable = reg;
    }else if( pHint->pIdx!=0 ){
      pExpr->iTable = pHint->iIdxCur;
      pExpr->iColumn = sqlite3TableColumnToIndex(pHint->pIdx, pExpr->iColumn);
      assert( pExpr->iColumn>=0 );
    }
  }else if( pExpr->pAggInfo ){







    rc = WRC_Prune;
    reg = ++pWalker->pParse->nMem;   /* Register for column value */
    reg = sqlite3ExprCodeTarget(pWalker->pParse, pExpr, reg);
    pExpr->op = TK_REGISTER;
    pExpr->iTable = reg;
  }
  return rc;
}

/*
** Insert an OP_CursorHint instruction if it is appropriate to do so.
*/

Changes to test/cursorhint.test.

175
176
177
178
179
180
181











182
183
  CREATE VIEW   v2 AS SELECT 0 FROM v1 WHERE c1 IS '' OR c1 > '';
  CREATE VIEW   v3 AS SELECT 0 FROM v2 JOIN (v2 RIGHT JOIN v1);
  CREATE VIEW   v4 AS SELECT 0 FROM v3, v3;
  SELECT * FROM v3 JOIN v3 AS a0, v4 AS a1, v4 AS a2, v3 AS a3,
                v3 AS a4, v4 AS a5
    ORDER BY 1;
}












finish_test







>
>
>
>
>
>
>
>
>
>
>


175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
  CREATE VIEW   v2 AS SELECT 0 FROM v1 WHERE c1 IS '' OR c1 > '';
  CREATE VIEW   v3 AS SELECT 0 FROM v2 JOIN (v2 RIGHT JOIN v1);
  CREATE VIEW   v4 AS SELECT 0 FROM v3, v3;
  SELECT * FROM v3 JOIN v3 AS a0, v4 AS a1, v4 AS a2, v3 AS a3,
                v3 AS a4, v4 AS a5
    ORDER BY 1;
}

# 2023-04-10 https://sqlite.org/forum/forumpost/0b53708c95
#
do_execsql_test 6.0 {
  CREATE TABLE t6(a TEXT UNIQUE, b TEXT);
  INSERT INTO t6(a,b) VALUES('uvw','xyz'),('abc','def');
  WITH v1(a) AS (SELECT a COLLATE NOCASE FROM t6)
  SELECT v1.a, count(*) FROM t6 LEFT JOIN v1 ON true
   GROUP BY 1
  HAVING (SELECT true FROM t6 AS aa LEFT JOIN t6 AS bb ON length(v1.a)>5);
} {abc 2 uvw 2}

finish_test