1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-08 14:02:16 +03:00

Better optimize queries that use parameters in the LIMIT clause.

FossilOrigin-Name: e58cb304d1e0ec6e30260a165aaccc2cf096ce6c999efb06683c4ef600ee12ef
This commit is contained in:
drh
2024-06-06 15:03:16 +00:00
parent 404ddadbd4
commit 4703b7d092
12 changed files with 156 additions and 29 deletions

View File

@@ -2789,8 +2789,12 @@ int sqlite3ExprContainsSubquery(Expr *p){
** to fit in a 32-bit integer, return 1 and put the value of the integer
** in *pValue. If the expression is not an integer or if it is too big
** to fit in a signed 32-bit integer, return 0 and leave *pValue unchanged.
**
** If the pParse pointer is provided, then allow the expression p to be
** a parameter (TK_VARIABLE) that is bound to an integer.
** But if pParse is NULL, then p must be a pure integer literal.
*/
int sqlite3ExprIsInteger(const Expr *p, int *pValue){
int sqlite3ExprIsInteger(const Expr *p, int *pValue, Parse *pParse){
int rc = 0;
if( NEVER(p==0) ) return 0; /* Used to only happen following on OOM */
@@ -2805,18 +2809,38 @@ int sqlite3ExprIsInteger(const Expr *p, int *pValue){
}
switch( p->op ){
case TK_UPLUS: {
rc = sqlite3ExprIsInteger(p->pLeft, pValue);
rc = sqlite3ExprIsInteger(p->pLeft, pValue, 0);
break;
}
case TK_UMINUS: {
int v = 0;
if( sqlite3ExprIsInteger(p->pLeft, &v) ){
if( sqlite3ExprIsInteger(p->pLeft, &v, 0) ){
assert( ((unsigned int)v)!=0x80000000 );
*pValue = -v;
rc = 1;
}
break;
}
case TK_VARIABLE: {
sqlite3_value *pVal;
if( pParse==0 ) break;
if( NEVER(pParse->pVdbe==0) ) break;
if( (pParse->db->flags & SQLITE_EnableQPSG)!=0 ) break;
sqlite3VdbeSetVarmask(pParse->pVdbe, p->iColumn);
pVal = sqlite3VdbeGetBoundValue(pParse->pReprepare, p->iColumn,
SQLITE_AFF_BLOB);
if( pVal ){
if( sqlite3_value_type(pVal)==SQLITE_INTEGER ){
sqlite3_int64 vv = sqlite3_value_int64(pVal);
if( vv == (vv & 0x7fffffff) ){ /* non-negative numbers only */
*pValue = (int)vv;
rc = 1;
}
}
sqlite3ValueFree(pVal);
}
break;
}
default: break;
}
return rc;