Simplification and performance improvement to the logic that factors

constant expressions ouf of inner loops.

FossilOrigin-Name: ee9353fdf3c8f19cd3c344ea8fb7c6d13cadd632
This commit is contained in:
drh 2013-11-16 13:55:34 +00:00
commit e6d058cd97
14 changed files with 191 additions and 246 deletions

View File

@ -1,5 +1,5 @@
C Fix\stestcase\smisc7-16\sso\sthat\sit\sworks\swith\sthe\snew\sUNIQUE\sconstraint\serror\nmessage\sformat.
D 2013-11-16T12:56:46.327
C Simplification\sand\sperformance\simprovement\sto\sthe\slogic\sthat\sfactors\s\nconstant\sexpressions\souf\sof\sinner\sloops.
D 2013-11-16T13:55:34.349
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 8a07bebafbfda0eb67728f4bd15a36201662d1a1
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@ -163,19 +163,19 @@ F src/alter.c 2af0330bb1b601af7a7789bf7229675fd772a083
F src/analyze.c 581d5c18ce89c6f45d4dca65914d0de5b4dad41f
F src/attach.c 0a17c9364895316ca4f52d06a97a72c0af1ae8b3
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
F src/backup.c 2f1987981139bd2f6d8c728d64bf09fb387443c3
F src/backup.c 1809a7caa2504233bdddd12f5018422421789537
F src/bitvec.c 19a4ba637bd85f8f63fc8c9bae5ade9fb05ec1cb
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
F src/btree.c 260dedc13119e6fb7930380bd3d294b98362bf5a
F src/btree.h bfe0e8c5759b4ec77b0d18390064a6ef3cdffaaf
F src/btreeInt.h f038e818bfadf75afbd09819ed93c26a333d39e0
F src/build.c 2baeed38bdaa9f1199f101c63db41fdcc4b39ba5
F src/build.c 07054d45319953e54a89d726e589a423e9c1c590
F src/callback.c f99a8957ba2adf369645fac0db09ad8adcf1caa2
F src/complete.c dc1d136c0feee03c2f7550bafc0d29075e36deac
F src/ctime.c ea4b7f3623a0fcb1146e7f245d7410033e86859c
F src/date.c 593c744b2623971e45affd0bde347631bdfa4625
F src/delete.c ddb92f44595366c4817e576b5f11cad5a915c3ef
F src/expr.c e7bbe3c6916e141f27a28655d3cf325b817695e4
F src/expr.c 1a295d8b0a2ba08919ad9300ebf7b67988ff4030
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
F src/fkey.c 78364daed38e26269c53ddb94c515bceac1063c6
F src/func.c 96caa9dfd1febf9a4b720de4c43ccfb392a52b73
@ -214,17 +214,17 @@ F src/pcache.c f8043b433a57aba85384a531e3937a804432a346
F src/pcache.h a5e4f5d9f5d592051d91212c5949517971ae6222
F src/pcache1.c a467393909a4ed7ca9de066d85ba5c5b04a5be63
F src/pragma.c c8d70c47ec8d8ba93575d92e34d30ddff8e9b517
F src/prepare.c fa6988589f39af8504a61731614cd4f6ae71554f
F src/prepare.c 359d1a1e9c9bd4488e4dd3a1aaaf2d2ebb9bb768
F src/printf.c da9119eb31a187a4b99f60aa4a225141c0ebb74b
F src/random.c 0b2dbc37fdfbfa6bd455b091dfcef5bdb32dba68
F src/resolve.c fc4673cc49b116e51e7f12de074c0acf8f2388f9
F src/resolve.c 6fcceeb653a0020b14491975d567c989e794d408
F src/rowset.c 64655f1a627c9c212d9ab497899e7424a34222e0
F src/select.c 7317406831ecced390edba972818f3c5f82238c0
F src/select.c 253cb683e4a05b0b56b0f9c816f3c4a4e5575ebb
F src/shell.c b98e74123d6c2e20369607c1da2d23c71db633d9
F src/sqlite.h.in 4dedcab5b32358bf7a596badffe7363be1f1a82d
F src/sqlite3.rc 11094cc6a157a028b301a9f06b3d03089ea37c3e
F src/sqlite3ext.h 886f5a34de171002ad46fae8c36a7d8051c190fc
F src/sqliteInt.h 2ec1d71220307fa5ee85a918a6240cf0b4635b0e
F src/sqliteInt.h e16eb6e62146234c05f34a4403a75cf242777ad7
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 7ac05a5c7017d0b9f0b4bcd701228b784f987158
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
@ -275,7 +275,7 @@ F src/test_vfs.c e72f555ef7a59080f898fcf1a233deb9eb704ea9
F src/test_vfstrace.c 34b544e80ba7fb77be15395a609c669df2e660a2
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
F src/tokenize.c ec4c1a62b890bf1dbcdb966399e140b904c700a4
F src/trigger.c 53d6b5d50b3b23d4fcd0a36504feb5cff9aed716
F src/trigger.c d84e1f3669e9a217731a14a9d472b1c7b87c87ba
F src/update.c 3de7e657b98ac67338d775c114a4068faf732402
F src/utf.c 6fc6c88d50448c469c5c196acf21617a24f90269
F src/util.c 2fa6c821d28bbdbeec1b2a7b091a281c9ef8f918
@ -285,15 +285,15 @@ F src/vdbe.h c06f0813f853566457ce9cfb1a4a4bc39a5da644
F src/vdbeInt.h 62eb680327011f3a4b0336642b0ca9d6ecc6eb91
F src/vdbeapi.c 93a22a9ba2abe292d5c2cf304d7eb2e894dde0ed
F src/vdbeaux.c dd0f6ab9dc159911facfc0a7a2164af44779bdda
F src/vdbeblob.c ff60adf2953e0ffc1d59541b3101c9886b03a3de
F src/vdbeblob.c d883398f7260725147dbf5b40c2b61332aee47f9
F src/vdbemem.c cc529bbf4f13e4e181bdb446bf6e6962ab030b4b
F src/vdbesort.c 9d83601f9d6243fe70dd0169a2820c5ddfd48147
F src/vdbetrace.c e7ec40e1999ff3c6414424365d5941178966dcbc
F src/vtab.c 5a423b042eb1402ef77697d03d6a67378d97bc8d
F src/vtab.c 21b932841e51ebd7d075e2d0ad1415dce8d2d5fd
F src/wal.c 7dc3966ef98b74422267e7e6e46e07ff6c6eb1b4
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c e9e593d5bb798c3e67fc3893dfe7055c9e7d8d74
F src/where.c 9d0b21b65b3d1c9f923b5c6bd0ba250dcd16b645
F src/where.c c7d50e26bad54218d8fa109d3127b9769b9474ab
F src/whereInt.h 96a75c61f1d2b9d4a8e4bb17d89deb0cf7cba358
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@ -423,7 +423,7 @@ F test/ctime.test 7bd009071e242aac4f18521581536b652b789a47
F test/date.test 42973251b9429f2c41b77eb98a7b0b0ba2d3b2c0
F test/dbstatus.test 8de104bb5606f19537d23cd553b41349b5ab1204
F test/dbstatus2.test 10418e62b3db5dca070f0c3eef3ea13946f339c2
F test/default.test 6faf23ccb300114924353007795aa9a8ec0aa9dc
F test/default.test 792c3c70836f1901e2a8cb34fa0880ed71e2c1a9
F test/delete.test a065b05d2ebf60fd16639c579a4adfb7c381c701
F test/delete2.test 3a03f2cca1f9a67ec469915cb8babd6485db43fa
F test/delete3.test 555e84a00a99230b7d049d477a324a631126a6ab
@ -1139,7 +1139,8 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh d1a6de74685f360ab718efda6265994b99bbea01
F tool/win/sqlite.vsix 030f3eeaf2cb811a3692ab9c14d021a75ce41fff
P cc17f1f05f15e9c62659a49c0656ff2b667bf701
R b62a58b0c81de204f01fd6d52945fa47
P c7f2ed9f44be3b66a542ee42c0db63bab8ffd2db cee835fe902e46f283257fb8ec9d9744c7d6dd77
R 9a08d5cf387c0a6debd995e2224a08b5
T +closed cee835fe902e46f283257fb8ec9d9744c7d6dd77
U drh
Z 7ba076cecbcdde244db85dd719f20d67
Z c4756f7866a605223b6628b959e50ab9

View File

@ -1 +1 @@
c7f2ed9f44be3b66a542ee42c0db63bab8ffd2db
ee9353fdf3c8f19cd3c344ea8fb7c6d13cadd632

View File

@ -96,6 +96,7 @@ static Btree *findBtree(sqlite3 *pErrorDb, sqlite3 *pDb, const char *zDb){
rc = SQLITE_ERROR;
}
sqlite3DbFree(pErrorDb, pParse->zErrMsg);
sqlite3ParserReset(pParse);
sqlite3StackFree(pErrorDb, pParse);
}
if( rc ){

View File

@ -150,7 +150,7 @@ void sqlite3FinishCoding(Parse *pParse){
*/
if( pParse->cookieGoto>0 ){
yDbMask mask;
int iDb;
int iDb, i, addr;
sqlite3VdbeJumpHere(v, pParse->cookieGoto-1);
for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){
if( (mask & pParse->cookieMask)==0 ) continue;
@ -164,14 +164,11 @@ void sqlite3FinishCoding(Parse *pParse){
}
}
#ifndef SQLITE_OMIT_VIRTUALTABLE
{
int i;
for(i=0; i<pParse->nVtabLock; i++){
char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
}
pParse->nVtabLock = 0;
for(i=0; i<pParse->nVtabLock; i++){
char *vtab = (char *)sqlite3GetVTable(db, pParse->apVtabLock[i]);
sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB);
}
pParse->nVtabLock = 0;
#endif
/* Once all the cookies have been verified and transactions opened,
@ -184,8 +181,18 @@ void sqlite3FinishCoding(Parse *pParse){
*/
sqlite3AutoincrementBegin(pParse);
/* Code constant expressions that where factored out of inner loops */
addr = pParse->cookieGoto;
if( pParse->pConstExpr ){
ExprList *pEL = pParse->pConstExpr;
pParse->cookieGoto = 0;
for(i=0; i<pEL->nExpr; i++){
sqlite3ExprCode(pParse, pEL->a[i].pExpr, pEL->a[i].u.iConstExprReg);
}
}
/* Finally, jump back to the beginning of the executable code. */
sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->cookieGoto);
sqlite3VdbeAddOp2(v, OP_Goto, 0, addr);
}
}

View File

@ -930,8 +930,7 @@ ExprList *sqlite3ExprListDup(sqlite3 *db, ExprList *p, int flags){
pItem->sortOrder = pOldItem->sortOrder;
pItem->done = 0;
pItem->bSpanIsTab = pOldItem->bSpanIsTab;
pItem->iOrderByCol = pOldItem->iOrderByCol;
pItem->iAlias = pOldItem->iAlias;
pItem->u = pOldItem->u;
}
return pNew;
}
@ -2356,6 +2355,7 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
int regFree2 = 0; /* If non-zero free this temporary register */
int r1, r2, r3, r4; /* Various register numbers */
sqlite3 *db = pParse->db; /* The database connection */
Expr tempX; /* Temporary expression node */
assert( target>0 && target<=pParse->nMem );
if( v==0 ){
@ -2575,8 +2575,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
codeReal(v, pLeft->u.zToken, 1, target);
#endif
}else{
regFree1 = r1 = sqlite3GetTempReg(pParse);
sqlite3VdbeAddOp2(v, OP_Integer, 0, r1);
tempX.op = TK_INTEGER;
tempX.flags = EP_IntValue|EP_TokenOnly;
tempX.u.iValue = 0;
r1 = sqlite3ExprCodeTemp(pParse, &tempX, &regFree1);
r2 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, &regFree2);
sqlite3VdbeAddOp3(v, OP_Subtract, r2, r1, target);
testcase( regFree2==0 );
@ -2892,7 +2894,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
ExprList *pEList; /* List of WHEN terms */
struct ExprList_item *aListelem; /* Array of WHEN terms */
Expr opCompare; /* The X==Ei expression */
Expr cacheX; /* Cached expression X */
Expr *pX; /* The X expression */
Expr *pTest = 0; /* X==Ei (form A) or just Ei (form B) */
VVA_ONLY( int iCacheLevel = pParse->iCacheLevel; )
@ -2904,13 +2905,12 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
nExpr = pEList->nExpr;
endLabel = sqlite3VdbeMakeLabel(v);
if( (pX = pExpr->pLeft)!=0 ){
cacheX = *pX;
tempX = *pX;
testcase( pX->op==TK_COLUMN );
testcase( pX->op==TK_REGISTER );
exprToRegister(&cacheX, sqlite3ExprCodeTemp(pParse, pX, &regFree1));
exprToRegister(&tempX, sqlite3ExprCodeTemp(pParse, pX, &regFree1));
testcase( regFree1==0 );
opCompare.op = TK_EQ;
opCompare.pLeft = &cacheX;
opCompare.pLeft = &tempX;
pTest = &opCompare;
/* Ticket b351d95f9cd5ef17e9d9dbae18f5ca8611190001:
** The value in regFree1 might get SCopy-ed into the file result.
@ -2930,7 +2930,6 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
testcase( pTest->op==TK_COLUMN );
sqlite3ExprIfFalse(pParse, pTest, nextCase, SQLITE_JUMPIFNULL);
testcase( aListelem[i+1].pExpr->op==TK_COLUMN );
testcase( aListelem[i+1].pExpr->op==TK_REGISTER );
sqlite3ExprCode(pParse, aListelem[i+1].pExpr, target);
sqlite3VdbeAddOp2(v, OP_Goto, 0, endLabel);
sqlite3ExprCachePop(pParse, 1);
@ -2989,15 +2988,41 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
** If the register is a temporary register that can be deallocated,
** then write its number into *pReg. If the result register is not
** a temporary, then set *pReg to zero.
**
** If pExpr is a constant, then this routine might generate this
** code to fill the register in the initialization section of the
** VDBE program, in order to factor it out of the evaluation loop.
*/
int sqlite3ExprCodeTemp(Parse *pParse, Expr *pExpr, int *pReg){
int r1 = sqlite3GetTempReg(pParse);
int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
if( r2==r1 ){
*pReg = r1;
int r2;
pExpr = sqlite3ExprSkipCollate(pExpr);
if( pParse->cookieGoto>0
&& pExpr->op!=TK_REGISTER
&& sqlite3ExprIsConstantNotJoin(pExpr)
){
ExprList *p = pParse->pConstExpr;
int i;
*pReg = 0;
if( p ){
for(i=0; i<p->nExpr; i++){
if( sqlite3ExprCompare(p->a[i].pExpr, pExpr, -1)==0 ){
return p->a[i].u.iConstExprReg;
}
}
}
p = sqlite3ExprListAppend(pParse, p, sqlite3ExprDup(pParse->db, pExpr, 0));
pParse->pConstExpr = p;
r2 = ++pParse->nMem;
if( p ) p->a[p->nExpr-1].u.iConstExprReg = r2;
}else{
sqlite3ReleaseTempReg(pParse, r1);
*pReg = 0;
int r1 = sqlite3GetTempReg(pParse);
r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
if( r2==r1 ){
*pReg = r1;
}else{
sqlite3ReleaseTempReg(pParse, r1);
*pReg = 0;
}
}
return r2;
}
@ -3040,12 +3065,13 @@ int sqlite3ExprCodeAndCache(Parse *pParse, Expr *pExpr, int target){
int inReg;
inReg = sqlite3ExprCode(pParse, pExpr, target);
assert( target>0 );
/* This routine is called for terms to INSERT or UPDATE. And the only
** other place where expressions can be converted into TK_REGISTER is
** in WHERE clause processing. So as currently implemented, there is
** no way for a TK_REGISTER to exist here. But it seems prudent to
** keep the ALWAYS() in case the conditions above change with future
** modifications or enhancements. */
/* The only place, other than this routine, where expressions can be
** converted to TK_REGISTER is internal subexpressions in BETWEEN and
** CASE operators. Neither ever calls this routine. And this routine
** is never called twice on the same expression. Hence it is impossible
** for the input to this routine to already be a register. Nevertheless,
** it seems prudent to keep the ALWAYS() in case the conditions above
** change with future modifications or enhancements. */
if( ALWAYS(pExpr->op!=TK_REGISTER) ){
int iMem;
iMem = ++pParse->nMem;
@ -3328,140 +3354,6 @@ void sqlite3ExplainExprList(Vdbe *pOut, ExprList *pList){
}
#endif /* SQLITE_DEBUG */
/*
** Return TRUE if pExpr is an constant expression that is appropriate
** for factoring out of a loop. Appropriate expressions are:
**
** * Any expression that evaluates to two or more opcodes.
**
** * Any OP_Integer, OP_Real, OP_String, OP_Blob, OP_Null,
** or OP_Variable that does not need to be placed in a
** specific register.
**
** There is no point in factoring out single-instruction constant
** expressions that need to be placed in a particular register.
** We could factor them out, but then we would end up adding an
** OP_SCopy instruction to move the value into the correct register
** later. We might as well just use the original instruction and
** avoid the OP_SCopy.
*/
static int isAppropriateForFactoring(Expr *p){
if( !sqlite3ExprIsConstantNotJoin(p) ){
return 0; /* Only constant expressions are appropriate for factoring */
}
if( (p->flags & EP_FixedDest)==0 ){
return 1; /* Any constant without a fixed destination is appropriate */
}
while( p->op==TK_UPLUS ) p = p->pLeft;
switch( p->op ){
#ifndef SQLITE_OMIT_BLOB_LITERAL
case TK_BLOB:
#endif
case TK_VARIABLE:
case TK_INTEGER:
case TK_FLOAT:
case TK_NULL:
case TK_STRING: {
testcase( p->op==TK_BLOB );
testcase( p->op==TK_VARIABLE );
testcase( p->op==TK_INTEGER );
testcase( p->op==TK_FLOAT );
testcase( p->op==TK_NULL );
testcase( p->op==TK_STRING );
/* Single-instruction constants with a fixed destination are
** better done in-line. If we factor them, they will just end
** up generating an OP_SCopy to move the value to the destination
** register. */
return 0;
}
case TK_UMINUS: {
if( p->pLeft->op==TK_FLOAT || p->pLeft->op==TK_INTEGER ){
return 0;
}
break;
}
default: {
break;
}
}
return 1;
}
/*
** If pExpr is a constant expression that is appropriate for
** factoring out of a loop, then evaluate the expression
** into a register and convert the expression into a TK_REGISTER
** expression.
*/
static int evalConstExpr(Walker *pWalker, Expr *pExpr){
Parse *pParse = pWalker->pParse;
switch( pExpr->op ){
case TK_IN:
case TK_REGISTER: {
return WRC_Prune;
}
case TK_COLLATE: {
return WRC_Continue;
}
case TK_FUNCTION:
case TK_AGG_FUNCTION:
case TK_CONST_FUNC: {
/* The arguments to a function have a fixed destination.
** Mark them this way to avoid generated unneeded OP_SCopy
** instructions.
*/
ExprList *pList = pExpr->x.pList;
assert( !ExprHasProperty(pExpr, EP_xIsSelect) );
if( pList ){
int i = pList->nExpr;
struct ExprList_item *pItem = pList->a;
for(; i>0; i--, pItem++){
if( ALWAYS(pItem->pExpr) ) pItem->pExpr->flags |= EP_FixedDest;
}
}
break;
}
}
if( isAppropriateForFactoring(pExpr) ){
int r1 = ++pParse->nMem;
int r2 = sqlite3ExprCodeTarget(pParse, pExpr, r1);
/* If r2!=r1, it means that register r1 is never used. That is harmless
** but suboptimal, so we want to know about the situation to fix it.
** Hence the following assert: */
assert( r2==r1 );
exprToRegister(pExpr, r2);
return WRC_Prune;
}
return WRC_Continue;
}
/*
** 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.
**
** This routine is a no-op if the jump to the cookie-check code has
** already occur. Since the cookie-check jump is generated prior to
** any other serious processing, this check ensures that there is no
** way to accidently bypass the constant initializations.
**
** This routine is also a no-op if the SQLITE_FactorOutConst optimization
** is disabled via the sqlite3_test_control(SQLITE_TESTCTRL_OPTIMIZATIONS)
** interface. This allows test logic to verify that the same answer is
** obtained for queries regardless of whether or not constants are
** precomputed into registers or if they are inserted in-line.
*/
void sqlite3ExprCodeConstants(Parse *pParse, Expr *pExpr){
Walker w;
if( pParse->cookieGoto ) return;
if( OptimizationDisabled(pParse->db, SQLITE_FactorOutConst) ) return;
memset(&w, 0, sizeof(w));
w.xExprCallback = evalConstExpr;
w.pParse = pParse;
sqlite3WalkExpr(&w, pExpr);
}
/*
** Generate code that pushes the value of every element of the given
** expression list into a sequence of registers beginning at target.
@ -3839,16 +3731,18 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
** an incorrect 0 or 1 could lead to a malfunction.
*/
int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
if( pA==0||pB==0 ){
u32 combinedFlags;
if( pA==0 || pB==0 ){
return pB==pA ? 0 : 2;
}
assert( !ExprHasProperty(pA, EP_TokenOnly|EP_Reduced) );
assert( !ExprHasProperty(pB, EP_TokenOnly|EP_Reduced) );
if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){
combinedFlags = pA->flags | pB->flags;
if( combinedFlags & EP_IntValue ){
if( (pA->flags&pB->flags&EP_IntValue)!=0 && pA->u.iValue==pB->u.iValue ){
return 0;
}
return 2;
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( pA->op!=pB->op && (pA->op!=TK_REGISTER || pA->op2!=pB->op) ){
if( pA->op!=pB->op ){
if( pA->op==TK_COLLATE && sqlite3ExprCompare(pA->pLeft, pB, iTab)<2 ){
return 1;
}
@ -3857,23 +3751,23 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
}
return 2;
}
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->iTable!=pB->iTable
&& pA->op!=TK_REGISTER
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
if( ExprHasProperty(pA, EP_IntValue) ){
if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){
return 2;
}
}else if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken){
if( ExprHasProperty(pB, EP_IntValue) || NEVER(pB->u.zToken==0) ) return 2;
if( pA->op!=TK_COLUMN && ALWAYS(pA->op!=TK_AGG_COLUMN) && pA->u.zToken ){
if( strcmp(pA->u.zToken,pB->u.zToken)!=0 ){
return pA->op==TK_COLLATE ? 1 : 2;
}
}
if( (pA->flags & EP_Distinct)!=(pB->flags & EP_Distinct) ) return 2;
if( ALWAYS((combinedFlags & EP_TokenOnly)==0) ){
if( combinedFlags & EP_xIsSelect ) return 2;
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
if( ALWAYS((combinedFlags & EP_Reduced)==0) ){
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->iTable!=pB->iTable
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
}
}
return 0;
}

View File

@ -524,6 +524,13 @@ int sqlite3SchemaToIndex(sqlite3 *db, Schema *pSchema){
return i;
}
/*
** Free all memory allocations in the pParse object
*/
void sqlite3ParserReset(Parse *pParse){
if( pParse ) sqlite3ExprListDelete(pParse->db, pParse->pConstExpr);
}
/*
** Compile the UTF-8 encoded SQL statement zSql into a statement handle.
*/
@ -681,6 +688,7 @@ static int sqlite3Prepare(
end_prepare:
sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
rc = sqlite3ApiExit(db, rc);
assert( (rc&db->errMask)==rc );

View File

@ -108,10 +108,10 @@ static void resolveAlias(
pDup = sqlite3PExpr(pParse, TK_AS, pDup, 0, 0);
if( pDup==0 ) return;
ExprSetProperty(pDup, EP_Skip);
if( pEList->a[iCol].iAlias==0 ){
pEList->a[iCol].iAlias = (u16)(++pParse->nAlias);
if( pEList->a[iCol].u.x.iAlias==0 ){
pEList->a[iCol].u.x.iAlias = (u16)(++pParse->nAlias);
}
pDup->iTable = pEList->a[iCol].iAlias;
pDup->iTable = pEList->a[iCol].u.x.iAlias;
}
if( pExpr->op==TK_COLLATE ){
pDup = sqlite3ExprAddCollateString(pParse, pDup, pExpr->u.zToken);
@ -976,7 +976,7 @@ static int resolveCompoundOrderBy(
pItem->pExpr->pLeft = pNew;
}
sqlite3ExprDelete(db, pE);
pItem->iOrderByCol = (u16)iCol;
pItem->u.x.iOrderByCol = (u16)iCol;
pItem->done = 1;
}else{
moreToDo = 1;
@ -997,8 +997,8 @@ static int resolveCompoundOrderBy(
/*
** Check every term in the ORDER BY or GROUP BY clause pOrderBy of
** the SELECT statement pSelect. If any term is reference to a
** result set expression (as determined by the ExprList.a.iOrderByCol field)
** then convert that term into a copy of the corresponding result set
** result set expression (as determined by the ExprList.a.u.x.iOrderByCol
** field) then convert that term into a copy of the corresponding result set
** column.
**
** If any errors are detected, add an error message to pParse and
@ -1025,12 +1025,12 @@ int sqlite3ResolveOrderGroupBy(
pEList = pSelect->pEList;
assert( pEList!=0 ); /* sqlite3SelectNew() guarantees this */
for(i=0, pItem=pOrderBy->a; i<pOrderBy->nExpr; i++, pItem++){
if( pItem->iOrderByCol ){
if( pItem->iOrderByCol>pEList->nExpr ){
if( pItem->u.x.iOrderByCol ){
if( pItem->u.x.iOrderByCol>pEList->nExpr ){
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
return 1;
}
resolveAlias(pParse, pEList, pItem->iOrderByCol-1, pItem->pExpr, zType,0);
resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0);
}
}
return 0;
@ -1079,7 +1079,7 @@ static int resolveOrderGroupBy(
** a copy of the iCol-th result-set column. The subsequent call to
** sqlite3ResolveOrderGroupBy() will convert the expression to a
** copy of the iCol-th result-set expression. */
pItem->iOrderByCol = (u16)iCol;
pItem->u.x.iOrderByCol = (u16)iCol;
continue;
}
}
@ -1091,18 +1091,18 @@ static int resolveOrderGroupBy(
resolveOutOfRangeError(pParse, zType, i+1, nResult);
return 1;
}
pItem->iOrderByCol = (u16)iCol;
pItem->u.x.iOrderByCol = (u16)iCol;
continue;
}
/* Otherwise, treat the ORDER BY term as an ordinary expression */
pItem->iOrderByCol = 0;
pItem->u.x.iOrderByCol = 0;
if( sqlite3ResolveExprNames(pNC, pE) ){
return 1;
}
for(j=0; j<pSelect->pEList->nExpr; j++){
if( sqlite3ExprCompare(pE, pSelect->pEList->a[j].pExpr, -1)==0 ){
pItem->iOrderByCol = j+1;
pItem->u.x.iOrderByCol = j+1;
}
}
}

View File

@ -2372,8 +2372,8 @@ static int multiSelectOrderBy(
for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
struct ExprList_item *pItem;
for(j=0, pItem=pOrderBy->a; j<nOrderBy; j++, pItem++){
assert( pItem->iOrderByCol>0 );
if( pItem->iOrderByCol==i ) break;
assert( pItem->u.x.iOrderByCol>0 );
if( pItem->u.x.iOrderByCol==i ) break;
}
if( j==nOrderBy ){
Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0);
@ -2381,7 +2381,7 @@ static int multiSelectOrderBy(
pNew->flags |= EP_IntValue;
pNew->u.iValue = i;
pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew);
if( pOrderBy ) pOrderBy->a[nOrderBy++].iOrderByCol = (u16)i;
if( pOrderBy ) pOrderBy->a[nOrderBy++].u.x.iOrderByCol = (u16)i;
}
}
}
@ -2397,8 +2397,9 @@ static int multiSelectOrderBy(
if( aPermute ){
struct ExprList_item *pItem;
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
assert( pItem->iOrderByCol>0 && pItem->iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->iOrderByCol - 1;
assert( pItem->u.x.iOrderByCol>0
&& pItem->u.x.iOrderByCol<=p->pEList->nExpr );
aPermute[i] = pItem->u.x.iOrderByCol - 1;
}
pKeyMerge = sqlite3KeyInfoAlloc(db, nOrderBy, 1);
if( pKeyMerge ){
@ -2978,7 +2979,7 @@ static int flattenSubquery(
if( p->pOrderBy ){
int ii;
for(ii=0; ii<p->pOrderBy->nExpr; ii++){
if( p->pOrderBy->a[ii].iOrderByCol==0 ) return 0;
if( p->pOrderBy->a[ii].u.x.iOrderByCol==0 ) return 0;
}
}
}
@ -4385,10 +4386,10 @@ int sqlite3Select(
struct ExprList_item *pItem; /* For looping over expression in a list */
for(k=p->pEList->nExpr, pItem=p->pEList->a; k>0; k--, pItem++){
pItem->iAlias = 0;
pItem->u.x.iAlias = 0;
}
for(k=pGroupBy->nExpr, pItem=pGroupBy->a; k>0; k--, pItem++){
pItem->iAlias = 0;
pItem->u.x.iAlias = 0;
}
if( p->nSelectRow>100 ) p->nSelectRow = 100;
}else{

View File

@ -1829,7 +1829,7 @@ struct Expr {
#define EP_DblQuoted 0x000040 /* token.z was originally in "..." */
#define EP_InfixFunc 0x000080 /* True for an infix function: LIKE, GLOB, etc */
#define EP_Collate 0x000100 /* Tree contains a TK_COLLATE opeartor */
#define EP_FixedDest 0x000200 /* Result needed in a specific register */
/* unused 0x000200 */
#define EP_IntValue 0x000400 /* Integer value contained in u.iValue */
#define EP_xIsSelect 0x000800 /* x.pSelect is valid (otherwise x.pList is) */
#define EP_Skip 0x001000 /* COLLATE, AS, or UNLIKELY */
@ -1900,8 +1900,13 @@ struct ExprList {
u8 sortOrder; /* 1 for DESC or 0 for ASC */
unsigned done :1; /* A flag to indicate when processing is finished */
unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
u16 iOrderByCol; /* For ORDER BY, column number in result set */
u16 iAlias; /* Index into Parse.aAlias[] for zName */
union {
struct {
u16 iOrderByCol; /* For ORDER BY, column number in result set */
u16 iAlias; /* Index into Parse.aAlias[] for zName */
} x;
int iConstExprReg; /* Register in which Expr value is cached */
} u;
} *a; /* Alloc a power of two greater or equal to nExpr */
};
@ -2278,6 +2283,7 @@ struct Parse {
int iReg; /* Reg with value of this column. 0 means none. */
int lru; /* Least recently used entry has the smallest value */
} aColCache[SQLITE_N_COLCACHE]; /* One for each column cache entry */
ExprList *pConstExpr;/* Constant expressions */
yDbMask writeMask; /* Start a write transaction on these databases */
yDbMask cookieMask; /* Bitmask of schema verified databases */
int cookieGoto; /* Address of OP_Goto to cookie verifier subroutine */
@ -2891,7 +2897,6 @@ 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, int);
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
@ -3259,6 +3264,7 @@ void sqlite3InvalidFunction(sqlite3_context*,int,sqlite3_value**);
sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context*);
int sqlite3VdbeParameterIndex(Vdbe*, const char*, int);
int sqlite3TransferBindings(sqlite3_stmt *, sqlite3_stmt *);
void sqlite3ParserReset(Parse*);
int sqlite3Reprepare(Vdbe*);
void sqlite3ExprListCheckLength(Parse*, ExprList*, const char*);
CollSeq *sqlite3BinaryCompareCollSeq(Parse *, Expr *, Expr *);

View File

@ -924,6 +924,7 @@ static TriggerPrg *codeRowTrigger(
assert( !pSubParse->pAinc && !pSubParse->pZombieTab );
assert( !pSubParse->pTriggerPrg && !pSubParse->nMaxArg );
sqlite3ParserReset(pSubParse);
sqlite3StackFree(db, pSubParse);
return pPrg;

View File

@ -328,6 +328,7 @@ blob_open_out:
}
sqlite3Error(db, rc, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
rc = sqlite3ApiExit(db, rc);
sqlite3_mutex_leave(db->mutex);

View File

@ -738,6 +738,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
sqlite3VdbeFinalize(pParse->pVdbe);
}
sqlite3DeleteTable(db, pParse->pNewTable);
sqlite3ParserReset(pParse);
sqlite3StackFree(db, pParse);
}

View File

@ -669,9 +669,6 @@ static int isLikeOrGlob(
pRight = pList->a[0].pExpr;
op = pRight->op;
if( op==TK_REGISTER ){
op = pRight->op2;
}
if( op==TK_VARIABLE ){
Vdbe *pReprepare = pParse->pReprepare;
int iCol = pRight->iColumn;
@ -3001,7 +2998,7 @@ static Bitmask codeOneLoopStart(
int nExtraReg = 0; /* Number of extra registers needed */
int op; /* Instruction opcode */
char *zStartAff; /* Affinity for start of range constraint */
char *zEndAff; /* Affinity for end of range constraint */
char cEndAff = 0; /* Affinity for end of range constraint */
pIdx = pLoop->u.btree.pIndex;
iIdxCur = pLevel->iIdxCur;
@ -3042,7 +3039,8 @@ static Bitmask codeOneLoopStart(
** starting at regBase.
*/
regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff);
zEndAff = sqlite3DbStrDup(db, zStartAff);
assert( zStartAff==0 || sqlite3Strlen30(zStartAff)>=nEq );
if( zStartAff ) cEndAff = zStartAff[nEq];
addrNxt = pLevel->addrNxt;
/* If we are doing a reverse order scan on an ascending index, or
@ -3112,23 +3110,15 @@ static Bitmask codeOneLoopStart(
if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){
sqlite3ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt);
}
if( zEndAff ){
if( sqlite3CompareAffinity(pRight, zEndAff[nEq])==SQLITE_AFF_NONE){
/* Since the comparison is to be performed with no conversions
** applied to the operands, set the affinity to apply to pRight to
** SQLITE_AFF_NONE. */
zEndAff[nEq] = SQLITE_AFF_NONE;
}
if( sqlite3ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){
zEndAff[nEq] = SQLITE_AFF_NONE;
}
}
codeApplyAffinity(pParse, regBase, nEq+1, zEndAff);
if( sqlite3CompareAffinity(pRight, cEndAff)!=SQLITE_AFF_NONE
&& !sqlite3ExprNeedsNoAffinityChange(pRight, cEndAff)
){
codeApplyAffinity(pParse, regBase+nEq, 1, &cEndAff);
}
nConstraint++;
testcase( pRangeEnd->wtFlags & TERM_VIRTUAL );
}
sqlite3DbFree(db, zStartAff);
sqlite3DbFree(db, zEndAff);
/* Top of the loop body */
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
@ -5426,7 +5416,6 @@ WhereInfo *sqlite3WhereBegin(
*/
initMaskSet(pMaskSet);
whereClauseInit(&pWInfo->sWC, pWInfo);
sqlite3ExprCodeConstants(pParse, pWhere);
whereSplit(&pWInfo->sWC, pWhere, TK_AND);
sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */

View File

@ -64,4 +64,39 @@ ifcapable pragma {
} {0 c {} 0 'abc' 0}
}
do_execsql_test default-3.1 {
CREATE TABLE t3(
a INTEGER PRIMARY KEY AUTOINCREMENT,
b INT DEFAULT 12345 UNIQUE NOT NULL CHECK( b>=0 AND b<99999 ),
c VARCHAR(123,456) DEFAULT 'hello' NOT NULL ON CONFLICT REPLACE,
d REAL,
e FLOATING POINT(5,10) DEFAULT 4.36,
f NATIONAL CHARACTER(15) COLLATE RTRIM,
g LONG INTEGER DEFAULT( 3600*12 )
);
INSERT INTO t3 VALUES(null, 5, 'row1', '5.25', 'xyz', 321, '432');
SELECT a, typeof(a), b, typeof(b), c, typeof(c),
d, typeof(d), e, typeof(e), f, typeof(f),
g, typeof(g) FROM t3;
} {1 integer 5 integer row1 text 5.25 real xyz text 321 text 432 integer}
do_execsql_test default-3.2 {
DELETE FROM t3;
INSERT INTO t3 DEFAULT VALUES;
SELECT * FROM t3;
} {2 12345 hello {} 4.36 {} 43200}
do_execsql_test default-3.3 {
CREATE TABLE t300(
a INT DEFAULT 2147483647,
b INT DEFAULT 2147483648,
c INT DEFAULT +9223372036854775807,
d INT DEFAULT -2147483647,
e INT DEFAULT -2147483648,
f INT DEFAULT -9223372036854775808,
g INT DEFAULT (-(-9223372036854775808)),
h INT DEFAULT (-(-9223372036854775807))
);
INSERT INTO t300 DEFAULT VALUES;
SELECT * FROM t300;
} {2147483647 2147483648 9223372036854775807 -2147483647 -2147483648 -9223372036854775808 9.22337203685478e+18 9223372036854775807}
finish_test