1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-09-11 08:30:57 +03:00

Enhance the automatic index logic so that it creates a partial index when

doing so gives the same answer for less work.

FossilOrigin-Name: d95d0313c447f5baeabdb17284d8606331ab7d49
This commit is contained in:
drh
2014-10-24 19:28:09 +00:00
parent 4dd96a8315
commit 059b2d50e1
7 changed files with 143 additions and 47 deletions

View File

@@ -1210,20 +1210,24 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
}
/*
** These routines are Walker callbacks. Walker.u.pi is a pointer
** to an integer. These routines are checking an expression to see
** if it is a constant. Set *Walker.u.i to 0 if the expression is
** not constant.
** These routines are Walker callbacks used to check expressions to
** see if they are "constant" for some definition of constant. The
** Walker.eCode value determines the type of "constant" we are looking
** for.
**
** These callback routines are used to implement the following:
**
** sqlite3ExprIsConstant() pWalker->u.i==1
** sqlite3ExprIsConstantNotJoin() pWalker->u.i==2
** sqlite3ExprIsConstantOrFunction() pWalker->u.i==3 or 4
** sqlite3ExprIsConstant() pWalker->eCode==1
** sqlite3ExprIsConstantNotJoin() pWalker->eCode==2
** sqlite3ExprRefOneTableOnly() pWalker->eCode==3
** sqlite3ExprIsConstantOrFunction() pWalker->eCode==4 or 5
**
** In all cases, the callbacks set Walker.eCode=0 and abort if the expression
** is found to not be a constant.
**
** The sqlite3ExprIsConstantOrFunction() is used for evaluating expressions
** in a CREATE TABLE statement. The Walker.u.i value is 4 when parsing
** an existing schema and 3 when processing a new statement. A bound
** in a CREATE TABLE statement. The Walker.eCode value is 5 when parsing
** an existing schema and 4 when processing a new statement. A bound
** parameter raises an error for new statements, but is silently converted
** to NULL for existing schemas. This allows sqlite_master tables that
** contain a bound parameter because they were generated by older versions
@@ -1232,23 +1236,25 @@ void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
*/
static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
/* If pWalker->u.i is 2 then any term of the expression that comes from
** the ON or USING clauses of a join disqualifies the expression
/* If pWalker->eCode is 2 then any term of the expression that comes from
** the ON or USING clauses of a left join disqualifies the expression
** from being considered constant. */
if( pWalker->u.i==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
pWalker->u.i = 0;
if( pWalker->eCode==2 && ExprHasProperty(pExpr, EP_FromJoin) ){
pWalker->eCode = 0;
return WRC_Abort;
}
switch( pExpr->op ){
/* Consider functions to be constant if all their arguments are constant
** and either pWalker->u.i==3 or 4 or the function as the SQLITE_FUNC_CONST
** flag. */
** and either pWalker->eCode==4 or 5 or the function has the
** SQLITE_FUNC_CONST flag. */
case TK_FUNCTION:
if( pWalker->u.i>=3 || ExprHasProperty(pExpr,EP_Constant) ){
if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_Constant) ){
return WRC_Continue;
}else{
pWalker->eCode = 0;
return WRC_Abort;
}
/* Fall through */
case TK_ID:
case TK_COLUMN:
case TK_AGG_FUNCTION:
@@ -1257,18 +1263,22 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
testcase( pExpr->op==TK_COLUMN );
testcase( pExpr->op==TK_AGG_FUNCTION );
testcase( pExpr->op==TK_AGG_COLUMN );
pWalker->u.i = 0;
return WRC_Abort;
if( pWalker->eCode==3 && pExpr->iTable==pWalker->u.iCur ){
return WRC_Continue;
}else{
pWalker->eCode = 0;
return WRC_Abort;
}
case TK_VARIABLE:
if( pWalker->u.i==4 ){
if( pWalker->eCode==5 ){
/* Silently convert bound parameters that appear inside of CREATE
** statements into a NULL when parsing the CREATE statement text out
** of the sqlite_master table */
pExpr->op = TK_NULL;
}else if( pWalker->u.i==3 ){
}else if( pWalker->eCode==4 ){
/* A bound parameter in a CREATE statement that originates from
** sqlite3_prepare() causes an error */
pWalker->u.i = 0;
pWalker->eCode = 0;
return WRC_Abort;
}
/* Fall through */
@@ -1280,21 +1290,22 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
}
static int selectNodeIsConstant(Walker *pWalker, Select *NotUsed){
UNUSED_PARAMETER(NotUsed);
pWalker->u.i = 0;
pWalker->eCode = 0;
return WRC_Abort;
}
static int exprIsConst(Expr *p, int initFlag){
static int exprIsConst(Expr *p, int initFlag, int iCur){
Walker w;
memset(&w, 0, sizeof(w));
w.u.i = initFlag;
w.eCode = initFlag;
w.xExprCallback = exprNodeIsConstant;
w.xSelectCallback = selectNodeIsConstant;
w.u.iCur = iCur;
sqlite3WalkExpr(&w, p);
return w.u.i;
return w.eCode;
}
/*
** Walk an expression tree. Return 1 if the expression is constant
** Walk an expression tree. Return non-zero if the expression is constant
** and 0 if it involves variables or function calls.
**
** For the purposes of this function, a double-quoted string (ex: "abc")
@@ -1302,21 +1313,31 @@ static int exprIsConst(Expr *p, int initFlag){
** a constant.
*/
int sqlite3ExprIsConstant(Expr *p){
return exprIsConst(p, 1);
return exprIsConst(p, 1, 0);
}
/*
** Walk an expression tree. Return 1 if the expression is constant
** Walk an expression tree. Return non-zero if the expression is constant
** that does no originate from the ON or USING clauses of a join.
** Return 0 if it involves variables or function calls or terms from
** an ON or USING clause.
*/
int sqlite3ExprIsConstantNotJoin(Expr *p){
return exprIsConst(p, 2);
return exprIsConst(p, 2, 0);
}
/*
** Walk an expression tree. Return 1 if the expression is constant
** Walk an expression tree. Return non-zero if the expression constant
** for any single row of the table with cursor iCur. In other words, the
** expression must not refer to any non-deterministic function nor any
** table other than iCur.
*/
int sqlite3ExprIsTableConstant(Expr *p, int iCur){
return exprIsConst(p, 3, iCur);
}
/*
** Walk an expression tree. Return non-zero if the expression is constant
** or a function call with constant arguments. Return and 0 if there
** are any variables.
**
@@ -1326,7 +1347,7 @@ int sqlite3ExprIsConstantNotJoin(Expr *p){
*/
int sqlite3ExprIsConstantOrFunction(Expr *p, u8 isInit){
assert( isInit==0 || isInit==1 );
return exprIsConst(p, 3+isInit);
return exprIsConst(p, 4+isInit, 0);
}
/*