Factor constant subexpressions out of loops. (CVS 4942)
FossilOrigin-Name: 2126db39854c751aea6c95c67894ed9b9dfc0763
This commit is contained in:
parent
a686bfcfa5
commit
678ccce8b3
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C In\ssetQuotedToken(),\sonly\smake\sa\smalloced\scopy\sif\sthe\sargument\scontains\sone\sor\smore\s"\scharacters.\s(CVS\s4941)
|
||||
D 2008-03-31T17:41:18
|
||||
C Factor\sconstant\ssubexpressions\sout\sof\sloops.\s(CVS\s4942)
|
||||
D 2008-03-31T18:19:54
|
||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||
F Makefile.in cf434ce8ca902e69126ae0f94fc9f7dc7428a5fa
|
||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||
@ -95,7 +95,7 @@ F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
|
||||
F src/date.c e41ce4513fb0e359dc678d6bddb4ace135fe365d
|
||||
F src/delete.c 3dc7d7cc46c8675219a7776b7c67b626bba530df
|
||||
F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
|
||||
F src/expr.c 7e56d2a24af8137f4bebbfa1d7dd1dcf70107c88
|
||||
F src/expr.c d005510999ccc68301167fd3fcff21f133389379
|
||||
F src/fault.c 83057e86815d473e526f7df0b0108dfdd022ff23
|
||||
F src/func.c c9e8c7ff4c45027edee89bde7adbf86a3a3b2afe
|
||||
F src/hash.c 53655c312280211444bfe23af6490a460aec2980
|
||||
@ -140,7 +140,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
|
||||
F src/shell.c 22297fffa6f00a6c6d44020fa13b1184a1bb372d
|
||||
F src/sqlite.h.in b1ac824d9fc163a5d2226ebf5990b09a02a11117
|
||||
F src/sqlite3ext.h faacd0e6a81aabee0861c6d7883c9172e74ef5b3
|
||||
F src/sqliteInt.h db668a07004d53a47c5d570963842489c6c4c3f3
|
||||
F src/sqliteInt.h 4d25edd2adb5f4be4c2b44c25533e0bbe69eb6e0
|
||||
F src/sqliteLimit.h f435e728c6b620ef7312814d660a81f9356eb5c8
|
||||
F src/table.c 2c48c575dd59b3a6c5c306bc55f51a9402cf429a
|
||||
F src/tclsqlite.c 1367762764772a233643524c3585b4711a9adcda
|
||||
@ -174,7 +174,7 @@ F src/update.c 2aefd3c9277792e9fa2414dfe14202119fa49fe7
|
||||
F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
|
||||
F src/util.c dba9e04121eb17ec4643d6ca231ff859452cf0e2
|
||||
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
|
||||
F src/vdbe.c 09dd6f4c5e69f17f7633d22e3f45edbafe83eeaf
|
||||
F src/vdbe.c 07f500db3880a8555f7d76ef5f3cc405725ae9b8
|
||||
F src/vdbe.h f72201a0657d5f3d6cc008d1f8d9cc65768518c9
|
||||
F src/vdbeInt.h 0b96efdeecb0803e504bf1c16b198f87c91d6019
|
||||
F src/vdbeapi.c ab6e99f8a6b7fcb82c2c698da7a36762a7593f0a
|
||||
@ -183,7 +183,7 @@ F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
|
||||
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
|
||||
F src/vdbemem.c b96fea7b98cc662ad7b587f28560b0c5649ac39f
|
||||
F src/vtab.c 00cd16317b29495c185ff40e4b227917d5a371b2
|
||||
F src/where.c dc146152cd0eb3b3568e92e7fed55cd008ebb9b5
|
||||
F src/where.c 902ddf1e7a737d19324d02de755fc816cc9cdba7
|
||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
F test/all.test d12210212bada2bde6d5aeb90969b86c1aa977d2
|
||||
@ -619,7 +619,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||
P 618df68b8b78d376d30cea79a273fd39140f5033
|
||||
R 90b5f03ff5ebb83c1c1b0247d291a8ab
|
||||
U danielk1977
|
||||
Z 3148119d5b8a2206c0e723ccd87c91b1
|
||||
P b266924b8975b69bdb9ab45cf462e41436f89cc2
|
||||
R 2c294fffeaf40038acaaca80e4e177dd
|
||||
U drh
|
||||
Z 39a34de4a0aac903f6ed893e46452e8f
|
||||
|
@ -1 +1 @@
|
||||
b266924b8975b69bdb9ab45cf462e41436f89cc2
|
||||
2126db39854c751aea6c95c67894ed9b9dfc0763
|
53
src/expr.c
53
src/expr.c
@ -12,7 +12,7 @@
|
||||
** This file contains routines used for analyzing expressions and
|
||||
** for generating VDBE code that evaluates expressions in SQLite.
|
||||
**
|
||||
** $Id: expr.c,v 1.357 2008/03/25 09:47:35 danielk1977 Exp $
|
||||
** $Id: expr.c,v 1.358 2008/03/31 18:19:54 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -786,7 +786,8 @@ void sqlite3ExprListDelete(ExprList *pList){
|
||||
}
|
||||
|
||||
/*
|
||||
** Walk an expression tree. Call xFunc for each node visited.
|
||||
** Walk an expression tree. Call xFunc for each node visited. xFunc
|
||||
** is called on the node before xFunc is called on the nodes children.
|
||||
**
|
||||
** The return value from xFunc determines whether the tree walk continues.
|
||||
** 0 means continue walking the tree. 1 means do not walk children
|
||||
@ -1932,13 +1933,13 @@ void sqlite3ExprCodeGetColumn(
|
||||
** must check the return code and move the results to the desired
|
||||
** register.
|
||||
*/
|
||||
static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
Vdbe *v = pParse->pVdbe; /* The VM under construction */
|
||||
int op; /* The opcode being coded */
|
||||
int inReg = target; /* Results stored in register inReg */
|
||||
int regFree1 = 0; /* If non-zero free this temporary register */
|
||||
int regFree2 = 0; /* If non-zero free this temporary register */
|
||||
int r1, r2, r3; /* Various register numbers */
|
||||
int r1, r2, r3, r4; /* Various register numbers */
|
||||
|
||||
assert( v!=0 || pParse->db->mallocFailed );
|
||||
assert( target>0 && target<=pParse->nMem );
|
||||
@ -2227,7 +2228,7 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
j2 = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
sqlite3VdbeJumpHere(v, j1);
|
||||
if( eType==IN_INDEX_ROWID ){
|
||||
j3 = sqlite3VdbeAddOp3(v, OP_MustBeInt, r1, 0, 1);
|
||||
j3 = sqlite3VdbeAddOp1(v, OP_MustBeInt, r1);
|
||||
j4 = sqlite3VdbeAddOp3(v, OP_NotExists, pExpr->iTable, 0, r1);
|
||||
j5 = sqlite3VdbeAddOp0(v, OP_Goto);
|
||||
sqlite3VdbeJumpHere(v, j3);
|
||||
@ -2262,15 +2263,17 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
r1 = sqlite3ExprCodeTemp(pParse, pLeft, ®Free1);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2);
|
||||
r3 = sqlite3GetTempReg(pParse);
|
||||
r4 = sqlite3GetTempReg(pParse);
|
||||
codeCompare(pParse, pLeft, pRight, OP_Ge,
|
||||
r1, r2, r3, SQLITE_STOREP2);
|
||||
pLItem++;
|
||||
pRight = pLItem->pExpr;
|
||||
sqlite3ReleaseTempReg(pParse, regFree2);
|
||||
r2 = sqlite3ExprCodeTemp(pParse, pRight, ®Free2);
|
||||
codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r2, SQLITE_STOREP2);
|
||||
sqlite3VdbeAddOp3(v, OP_And, r3, r2, target);
|
||||
codeCompare(pParse, pLeft, pRight, OP_Le, r1, r2, r4, SQLITE_STOREP2);
|
||||
sqlite3VdbeAddOp3(v, OP_And, r3, r4, target);
|
||||
sqlite3ReleaseTempReg(pParse, r3);
|
||||
sqlite3ReleaseTempReg(pParse, r4);
|
||||
break;
|
||||
}
|
||||
case TK_UPLUS: {
|
||||
@ -2322,6 +2325,7 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
cacheX = *pX;
|
||||
cacheX.iTable = sqlite3ExprCodeTemp(pParse, pX, ®Free1);
|
||||
cacheX.op = TK_REGISTER;
|
||||
cacheX.iColumn = 0;
|
||||
opCompare.op = TK_EQ;
|
||||
opCompare.pLeft = &cacheX;
|
||||
pTest = &opCompare;
|
||||
@ -2381,7 +2385,7 @@ static int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
||||
** are stored.
|
||||
**
|
||||
** If the register is a temporary register that can be deallocated,
|
||||
** then write its number into *pReg. If the result register is no
|
||||
** then write its number into *pReg. If the result register is not
|
||||
** a temporary, then set *pReg to zero.
|
||||
*/
|
||||
int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
|
||||
@ -2435,11 +2439,44 @@ int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
|
||||
iMem = ++pParse->nMem;
|
||||
sqlite3VdbeAddOp2(v, OP_Copy, inReg, iMem);
|
||||
pExpr->iTable = iMem;
|
||||
pExpr->iColumn = pExpr->op;
|
||||
pExpr->op = TK_REGISTER;
|
||||
}
|
||||
return inReg;
|
||||
}
|
||||
|
||||
/*
|
||||
** If pExpr is a constant expression, then evaluate the expression
|
||||
** into a register and convert the expression into a TK_REGISTER
|
||||
** expression.
|
||||
*/
|
||||
static int evalConstExpr(void *pArg, Expr *pExpr){
|
||||
Parse *pParse = (Parse*)pArg;
|
||||
if( pExpr->op==TK_REGISTER ){
|
||||
return 1;
|
||||
}
|
||||
if( sqlite3ExprIsConstantNotJoin(pExpr) ){
|
||||
int r1 = ++pParse->nMem;
|
||||
int r2;
|
||||
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
|
||||
if( r1!=r2 ) pParse->nMem--;
|
||||
pExpr->iColumn = pExpr->op;
|
||||
pExpr->op = TK_REGISTER;
|
||||
pExpr->iTable = r2;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Preevaluate constant subexpressions within pExpr and store the
|
||||
** results in registers. Modify pExpr so that the constant subexpresions
|
||||
** are TK_REGISTER opcodes that refer to the precomputed values.
|
||||
*/
|
||||
void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
|
||||
walkExprTree(pExpr, evalConstExpr, pParse);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Generate code that pushes the value of every element of the given
|
||||
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** Internal interface definitions for SQLite.
|
||||
**
|
||||
** @(#) $Id: sqliteInt.h,v 1.681 2008/03/26 12:46:24 drh Exp $
|
||||
** @(#) $Id: sqliteInt.h,v 1.682 2008/03/31 18:19:54 drh Exp $
|
||||
*/
|
||||
#ifndef _SQLITEINT_H_
|
||||
#define _SQLITEINT_H_
|
||||
@ -1130,15 +1130,16 @@ struct Expr {
|
||||
/*
|
||||
** The following are the meanings of bits in the Expr.flags field.
|
||||
*/
|
||||
#define EP_FromJoin 0x01 /* Originated in ON or USING clause of a join */
|
||||
#define EP_Agg 0x02 /* Contains one or more aggregate functions */
|
||||
#define EP_Resolved 0x04 /* IDs have been resolved to COLUMNs */
|
||||
#define EP_Error 0x08 /* Expression contains one or more errors */
|
||||
#define EP_Distinct 0x10 /* Aggregate function with DISTINCT keyword */
|
||||
#define EP_VarSelect 0x20 /* pSelect is correlated, not constant */
|
||||
#define EP_Dequoted 0x40 /* True if the string has been dequoted */
|
||||
#define EP_InfixFunc 0x80 /* True for an infix function: LIKE, GLOB, etc */
|
||||
#define EP_ExpCollate 0x100 /* Collating sequence specified explicitly */
|
||||
#define EP_FromJoin 0x0001 /* Originated in ON or USING clause of a join */
|
||||
#define EP_Agg 0x0002 /* Contains one or more aggregate functions */
|
||||
#define EP_Resolved 0x0004 /* IDs have been resolved to COLUMNs */
|
||||
#define EP_Error 0x0008 /* Expression contains one or more errors */
|
||||
#define EP_Distinct 0x0010 /* Aggregate function with DISTINCT keyword */
|
||||
#define EP_VarSelect 0x0020 /* pSelect is correlated, not constant */
|
||||
#define EP_Dequoted 0x0040 /* True if the string has been dequoted */
|
||||
#define EP_InfixFunc 0x0080 /* True for an infix function: LIKE, GLOB, etc */
|
||||
#define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */
|
||||
#define EP_Constant 0x0200 /* A constant expression */
|
||||
|
||||
/*
|
||||
** These macros can be used to test, set, or clear bits in the
|
||||
@ -1831,7 +1832,9 @@ void sqlite3WhereEnd(WhereInfo*);
|
||||
void sqlite3ExprCodeGetColumn(Vdbe*, Table*, int, int, int);
|
||||
int sqlite3ExprCode(Parse*, Expr*, int);
|
||||
int sqlite3ExprCodeTemp(Parse*, Expr*, int*);
|
||||
int sqlite3ExprCodeTarget(Parse*, Expr*, int);
|
||||
int sqlite3ExprCodeAndCache(Parse*, Expr*, int);
|
||||
void sqlite3ExprCodeConstants(Parse*, Expr*);
|
||||
int sqlite3ExprCodeExprList(Parse*, ExprList*, int);
|
||||
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
|
||||
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
|
||||
|
@ -43,7 +43,7 @@
|
||||
** in this file for details. If in doubt, do not deviate from existing
|
||||
** commenting and indentation practices when changing or adding code.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.722 2008/03/28 19:16:34 danielk1977 Exp $
|
||||
** $Id: vdbe.c,v 1.723 2008/03/31 18:19:54 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -103,7 +103,7 @@ static void updateMaxBlobsize(Mem *p){
|
||||
** Test a register to see if it exceeds the current maximum blob size.
|
||||
** If it does, record the new maximum blob size.
|
||||
*/
|
||||
#ifdef SQLITE_TEST
|
||||
#if defined(SQLITE_TEST) && !defined(SQLITE_OMIT_BUILTIN_TEST)
|
||||
# define UPDATE_MAX_BLOBSIZE(P) updateMaxBlobsize(P)
|
||||
#else
|
||||
# define UPDATE_MAX_BLOBSIZE(P)
|
||||
|
32
src/where.c
32
src/where.c
@ -16,7 +16,7 @@
|
||||
** so is applicable. Because this module is responsible for selecting
|
||||
** indices, you might also think of this module as the "query optimizer".
|
||||
**
|
||||
** $Id: where.c,v 1.294 2008/03/28 19:16:57 danielk1977 Exp $
|
||||
** $Id: where.c,v 1.295 2008/03/31 18:19:54 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -535,7 +535,8 @@ static int isLikeOrGlob(
|
||||
#endif
|
||||
pList = pExpr->pList;
|
||||
pRight = pList->a[0].pExpr;
|
||||
if( pRight->op!=TK_STRING ){
|
||||
if( pRight->op!=TK_STRING
|
||||
&& (pRight->op!=TK_REGISTER || pRight->iColumn!=TK_STRING) ){
|
||||
return 0;
|
||||
}
|
||||
pLeft = pList->a[1].pExpr;
|
||||
@ -1752,19 +1753,23 @@ static void buildIndexProbe(
|
||||
** result is left on the stack. For constraints of the form X IN (...)
|
||||
** this routine sets up a loop that will iterate over all values of X.
|
||||
*/
|
||||
static void codeEqualityTerm(
|
||||
static int codeEqualityTerm(
|
||||
Parse *pParse, /* The parsing context */
|
||||
WhereTerm *pTerm, /* The term of the WHERE clause to be coded */
|
||||
WhereLevel *pLevel, /* When level of the FROM clause we are working on */
|
||||
int iReg /* Leave results in this register */
|
||||
int iTarget /* Attempt to leave results in this register */
|
||||
){
|
||||
Expr *pX = pTerm->pExpr;
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
int iReg; /* Register holding results */
|
||||
|
||||
assert( iReg>0 && iReg<=pParse->nMem );
|
||||
if( iTarget<=0 ){
|
||||
iReg = iTarget = sqlite3GetTempReg(pParse);
|
||||
}
|
||||
if( pX->op==TK_EQ ){
|
||||
sqlite3ExprCode(pParse, pX->pRight, iReg);
|
||||
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
|
||||
}else if( pX->op==TK_ISNULL ){
|
||||
iReg = iTarget;
|
||||
sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
|
||||
#ifndef SQLITE_OMIT_SUBQUERY
|
||||
}else{
|
||||
@ -1773,6 +1778,7 @@ static void codeEqualityTerm(
|
||||
struct InLoop *pIn;
|
||||
|
||||
assert( pX->op==TK_IN );
|
||||
iReg = iTarget;
|
||||
eType = sqlite3FindInIndex(pParse, pX, 1);
|
||||
iTab = pX->iTable;
|
||||
sqlite3VdbeAddOp2(v, OP_Rewind, iTab, 0);
|
||||
@ -1799,6 +1805,7 @@ static void codeEqualityTerm(
|
||||
#endif
|
||||
}
|
||||
disableTerm(pLevel, pTerm);
|
||||
return iReg;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1852,11 +1859,15 @@ static int codeAllEqualityTerms(
|
||||
*/
|
||||
assert( pIdx->nColumn>=nEq );
|
||||
for(j=0; j<nEq; j++){
|
||||
int r1;
|
||||
int k = pIdx->aiColumn[j];
|
||||
pTerm = findTerm(pWC, iCur, k, notReady, pLevel->flags, pIdx);
|
||||
if( pTerm==0 ) break;
|
||||
assert( (pTerm->flags & TERM_CODED)==0 );
|
||||
codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
|
||||
r1 = codeEqualityTerm(pParse, pTerm, pLevel, regBase+j);
|
||||
if( r1!=regBase+j ){
|
||||
sqlite3VdbeAddOp2(v, OP_SCopy, r1, regBase+j);
|
||||
}
|
||||
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->brk);
|
||||
}
|
||||
@ -2022,6 +2033,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
initMaskSet(&maskSet);
|
||||
whereClauseInit(&wc, pParse, &maskSet);
|
||||
sqlite3ExprCodeConstants(pParse, pWhere);
|
||||
whereSplit(&wc, pWhere, TK_AND);
|
||||
|
||||
/* Allocate and initialize the WhereInfo structure that will become the
|
||||
@ -2367,13 +2379,11 @@ WhereInfo *sqlite3WhereBegin(
|
||||
assert( pTerm->pExpr!=0 );
|
||||
assert( pTerm->leftCursor==iCur );
|
||||
assert( omitTable==0 );
|
||||
r1 = sqlite3GetTempReg(pParse);
|
||||
codeEqualityTerm(pParse, pTerm, pLevel, r1);
|
||||
r1 = codeEqualityTerm(pParse, pTerm, pLevel, 0);
|
||||
nxt = pLevel->nxt;
|
||||
sqlite3VdbeAddOp3(v, OP_MustBeInt, r1, nxt, 1);
|
||||
sqlite3VdbeAddOp2(v, OP_MustBeInt, r1, nxt);
|
||||
sqlite3VdbeAddOp3(v, OP_NotExists, iCur, nxt, r1);
|
||||
VdbeComment((v, "pk"));
|
||||
sqlite3ReleaseTempReg(pParse, r1);
|
||||
pLevel->op = OP_Noop;
|
||||
}else if( pLevel->flags & WHERE_ROWID_RANGE ){
|
||||
/* Case 2: We have an inequality comparison against the ROWID field.
|
||||
|
Loading…
Reference in New Issue
Block a user