mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Better optimize queries that use parameters in the LIMIT clause.
FossilOrigin-Name: e58cb304d1e0ec6e30260a165aaccc2cf096ce6c999efb06683c4ef600ee12ef
This commit is contained in:
30
src/expr.c
30
src/expr.c
@ -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;
|
||||
|
@ -1505,7 +1505,7 @@ static int resolveOrderByTermToExprList(
|
||||
int rc; /* Return code from subprocedures */
|
||||
u8 savedSuppErr; /* Saved value of db->suppressErr */
|
||||
|
||||
assert( sqlite3ExprIsInteger(pE, &i)==0 );
|
||||
assert( sqlite3ExprIsInteger(pE, &i, 0)==0 );
|
||||
pEList = pSelect->pEList;
|
||||
|
||||
/* Resolve all names in the ORDER BY term expression
|
||||
@ -1604,7 +1604,7 @@ static int resolveCompoundOrderBy(
|
||||
if( pItem->fg.done ) continue;
|
||||
pE = sqlite3ExprSkipCollateAndLikely(pItem->pExpr);
|
||||
if( NEVER(pE==0) ) continue;
|
||||
if( sqlite3ExprIsInteger(pE, &iCol) ){
|
||||
if( sqlite3ExprIsInteger(pE, &iCol, 0) ){
|
||||
if( iCol<=0 || iCol>pEList->nExpr ){
|
||||
resolveOutOfRangeError(pParse, "ORDER", i+1, pEList->nExpr, pE);
|
||||
return 1;
|
||||
@ -1789,7 +1789,7 @@ static int resolveOrderGroupBy(
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if( sqlite3ExprIsInteger(pE2, &iCol) ){
|
||||
if( sqlite3ExprIsInteger(pE2, &iCol, 0) ){
|
||||
/* The ORDER BY term is an integer constant. Again, set the column
|
||||
** number so that sqlite3ResolveOrderGroupBy() will convert the
|
||||
** order-by term to a copy of the result-set expression */
|
||||
|
@ -2492,7 +2492,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
p->iLimit = iLimit = ++pParse->nMem;
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
assert( v!=0 );
|
||||
if( sqlite3ExprIsInteger(pLimit->pLeft, &n) ){
|
||||
if( sqlite3ExprIsInteger(pLimit->pLeft, &n, pParse) ){
|
||||
sqlite3VdbeAddOp2(v, OP_Integer, n, iLimit);
|
||||
VdbeComment((v, "LIMIT counter"));
|
||||
if( n==0 ){
|
||||
@ -2972,7 +2972,7 @@ static int multiSelect(
|
||||
p->pPrior = pPrior;
|
||||
p->nSelectRow = sqlite3LogEstAdd(p->nSelectRow, pPrior->nSelectRow);
|
||||
if( p->pLimit
|
||||
&& sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit)
|
||||
&& sqlite3ExprIsInteger(p->pLimit->pLeft, &nLimit, pParse)
|
||||
&& nLimit>0 && p->nSelectRow > sqlite3LogEst((u64)nLimit)
|
||||
){
|
||||
p->nSelectRow = sqlite3LogEst((u64)nLimit);
|
||||
|
@ -4253,6 +4253,7 @@ static int shell_exec(
|
||||
sqlite3_reset(pExplain);
|
||||
rc = sqlite3_stmt_explain(pExplain, 2);
|
||||
if( rc==SQLITE_OK ){
|
||||
bind_prepared_stmt(pArg, pExplain);
|
||||
while( sqlite3_step(pExplain)==SQLITE_ROW ){
|
||||
const char *zEQPLine = (const char*)sqlite3_column_text(pExplain,3);
|
||||
int iEqpId = sqlite3_column_int(pExplain, 0);
|
||||
@ -4270,6 +4271,7 @@ static int shell_exec(
|
||||
if( rc==SQLITE_OK ){
|
||||
pArg->cMode = MODE_Explain;
|
||||
assert( sqlite3_stmt_isexplain(pExplain)==1 );
|
||||
bind_prepared_stmt(pArg, pExplain);
|
||||
explain_data_prepare(pArg, pExplain);
|
||||
exec_prepared_stmt(pArg, pExplain);
|
||||
explain_data_delete(pArg);
|
||||
|
@ -5088,7 +5088,7 @@ int sqlite3ExprIsSingleTableConstraint(Expr*,const SrcList*,int,int);
|
||||
#ifdef SQLITE_ENABLE_CURSOR_HINTS
|
||||
int sqlite3ExprContainsSubquery(Expr*);
|
||||
#endif
|
||||
int sqlite3ExprIsInteger(const Expr*, int*);
|
||||
int sqlite3ExprIsInteger(const Expr*, int*, Parse*);
|
||||
int sqlite3ExprCanBeNull(const Expr*);
|
||||
int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
|
||||
int sqlite3IsRowid(const char*);
|
||||
|
@ -2942,7 +2942,7 @@ static void whereLoopOutputAdjust(
|
||||
Expr *pRight = pTerm->pExpr->pRight;
|
||||
int k = 0;
|
||||
testcase( pTerm->pExpr->op==TK_IS );
|
||||
if( sqlite3ExprIsInteger(pRight, &k) && k>=(-1) && k<=1 ){
|
||||
if( sqlite3ExprIsInteger(pRight, &k, 0) && k>=(-1) && k<=1 ){
|
||||
k = 10;
|
||||
}else{
|
||||
k = 20;
|
||||
|
@ -1583,7 +1583,7 @@ static void whereAddLimitExpr(
|
||||
Expr *pNew;
|
||||
int iVal = 0;
|
||||
|
||||
if( sqlite3ExprIsInteger(pExpr, &iVal) && iVal>=0 ){
|
||||
if( sqlite3ExprIsInteger(pExpr, &iVal, pParse) && iVal>=0 ){
|
||||
Expr *pVal = sqlite3Expr(db, TK_INTEGER, 0);
|
||||
if( pVal==0 ) return;
|
||||
ExprSetProperty(pVal, EP_IntValue);
|
||||
|
@ -909,7 +909,7 @@ static ExprList *exprListAppendList(
|
||||
int iDummy;
|
||||
Expr *pSub;
|
||||
pSub = sqlite3ExprSkipCollateAndLikely(pDup);
|
||||
if( sqlite3ExprIsInteger(pSub, &iDummy) ){
|
||||
if( sqlite3ExprIsInteger(pSub, &iDummy, 0) ){
|
||||
pSub->op = TK_NULL;
|
||||
pSub->flags &= ~(EP_IntValue|EP_IsTrue|EP_IsFalse);
|
||||
pSub->u.zToken = 0;
|
||||
|
Reference in New Issue
Block a user