diff options
-rw-r--r-- | manifest | 52 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/alter.c | 2 | ||||
-rw-r--r-- | src/attach.c | 6 | ||||
-rw-r--r-- | src/build.c | 14 | ||||
-rw-r--r-- | src/delete.c | 2 | ||||
-rw-r--r-- | src/expr.c | 238 | ||||
-rw-r--r-- | src/func.c | 5 | ||||
-rw-r--r-- | src/parse.y | 2 | ||||
-rw-r--r-- | src/pragma.c | 2 | ||||
-rw-r--r-- | src/resolve.c | 34 | ||||
-rw-r--r-- | src/select.c | 26 | ||||
-rw-r--r-- | src/sqliteInt.h | 29 | ||||
-rw-r--r-- | src/tokenize.c | 2 | ||||
-rw-r--r-- | src/trigger.c | 36 | ||||
-rw-r--r-- | src/update.c | 2 | ||||
-rw-r--r-- | src/util.c | 2 | ||||
-rw-r--r-- | src/vdbemem.c | 19 | ||||
-rw-r--r-- | src/walker.c | 2 | ||||
-rw-r--r-- | src/where.c | 12 | ||||
-rw-r--r-- | test/attach.test | 2 | ||||
-rw-r--r-- | test/select1.test | 2 | ||||
-rw-r--r-- | test/tkt3508.test | 2 |
23 files changed, 297 insertions, 198 deletions
@@ -1,5 +1,5 @@ -C Simplifications\sto\sthe\sExpr\sobject:\s\sRemove\sExpr.span\scompletely\sand\sconvert\nExpr.token\sinto\sa\schar*\sExpr.zToken.\s\sAlso\ssimplify\sthe\sToken\sobject\sby\nremoving\sthe\sToken.dyn\sand\sToken.quoted\sfields.\s(CVS\s6681) -D 2009-05-27T10:31:29 +C Additional\srefinements\sto\sExpr\shandling.\s\sRestore\scompression\sof\strigger\nexpressions.\s\sChange\sExpr.zToken\sto\sExpr.u.zToken\sand\sadded\sExpr.u.iValue.\nRemove\san\sunnecessary\sExprDup\sfrom\sCHECK\sconstraint\sprocessing.\s\sAnd\sso\sforth.\s(CVS\s6682) +D 2009-05-28T01:00:55 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654 @@ -99,9 +99,9 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc F sqlite3.pc.in ae6f59a76e862f5c561eb32a380228a02afc3cad -F src/alter.c accb3c77ef20903e16ec44a04f5ee5ff1bfcf7e4 +F src/alter.c 88b8cc66c09853b5723f66cfd0103dbebb62c562 F src/analyze.c e239496cfb5394ac8867f1c112905ddab8d01cd9 -F src/attach.c 92517f52fb53037c0584c0ecac922ec83e5d9d42 +F src/attach.c ad7eeae19c0844d3b329781c5a35ccda0a2010d2 F src/auth.c 98db07c2088455797678eb1031f42d4d94d18a71 F src/backup.c 437efc2c3371b52bbb943b8c9dfabba774adcf86 F src/bitvec.c ef370407e03440b0852d05024fb016b14a471d3d @@ -109,14 +109,14 @@ F src/btmutex.c 9b899c0d8df3bd68f527b0afe03088321b696d3c F src/btree.c 7c4b02afea7efb561361f20408414fec68df898c F src/btree.h 58d876d3ed944a8f4f1fd0e67024b385243fc9dd F src/btreeInt.h df64030d632f8c8ac217ed52e8b6b3eacacb33a5 -F src/build.c 028255aa488ee3941ee77e16ae078ad5e03fe6d8 +F src/build.c 567574f5756e9e462cf50c5da1895dc43672bafe F src/callback.c 57359fa93de47c341b6b8ee504a88ff276397686 F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0 F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3 -F src/delete.c 59da0e52380d7626e98d84082b72f431fafe2799 -F src/expr.c cdddb81c68a0d222e03a4b92a7821d370c298a8e +F src/delete.c cb791855c7948cecc96def9d97989879ca26f257 +F src/expr.c 2f8b6e5c3c867fa421189ad5692b1ff60ecc59c4 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff -F src/func.c be5067593d9c8971e1af803bb503b91ef1541e8d +F src/func.c 9d7b47729c337c5e4b78d795922ed34eec4aef67 F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7 F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1 @@ -148,21 +148,21 @@ F src/os_unix.c e55d977c516ed880a2f83f0610b019efd9f8bc06 F src/os_win.c 725c38a524d168ce280446ad8761d731bc516405 F src/pager.c 8bf62fefc7afefc065d37611ebfd1fe0e1c2eb39 F src/pager.h 73f481a308a873ccd626d97331c081db3b53e2e5 -F src/parse.y 6b55e52fb3362ad84130013f861c21f4b3ba5005 +F src/parse.y 07690df997d50b3fdb5e5121e5a27f1a080db13d F src/pcache.c 395f752a13574120bd7513a400ba02a265aaa76d F src/pcache.h 9b927ccc5a538e31b4c3bc7eec4f976db42a1324 F src/pcache1.c bed75f157283e7c666f323df0c874c6a2515f76e -F src/pragma.c cf9adc601f5d0e6de6f3a3ffb8fa5dfef8217d13 +F src/pragma.c d4a6fd74fd1dba0f22c8930791f7fbbe80d2ef26 F src/prepare.c f46d1a029760edee5447e27164fb3ae10e2a6839 F src/printf.c 3f4dca207a88258d37af5a7a03e800a825fe6456 F src/random.c 676b9d7ac820fe81e6fb2394ac8c10cff7f38628 -F src/resolve.c 0c9faa469e4e71ff84efd7fa60613036e88498d6 +F src/resolve.c 64e7ac825a887eb5e33262f0b355514734b24ccd F src/rowset.c c64dafba1f9fd876836c8db8682966b9d197eb1f -F src/select.c 18c296d45cc8cad8dc4b862d2df000a4681d7883 +F src/select.c fd1737a667bab296f50049a841b3aba5ec89418e F src/shell.c 7eacd0bdaa887931f5ff205c9defc3e8df95a2dd F src/sqlite.h.in 79210c4d8905cfb4b038486dde5f36fabb796a86 F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17 -F src/sqliteInt.h 28a5b5c0bfb0efbb735dc0dedc3f076f7de95c57 +F src/sqliteInt.h 97f9125229c14cd3afa6c4fed4b419a1899be476 F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76 F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d @@ -197,11 +197,11 @@ F src/test_server.c f0a403b5f699c09bd2b1236b6f69830fd6221f6b F src/test_tclvar.c 9e42fa59d3d2f064b7ab8628e7ab2dc8a9fe93d4 F src/test_thread.c b8a1ab7ca1a632f18e8a361880d5d65eeea08eac F src/test_wsd.c 3ae5101de6cbfda2720152ab659ea84079719241 -F src/tokenize.c ef5e56bae212d08ff3a334ff059bc5292322251d -F src/trigger.c 6d233d6d737a229e31f810012f38ecac7dd89021 -F src/update.c 3aec63a3a85754d16f7571ec80eb928e2fcf6c2e +F src/tokenize.c 75367c7e4d2aee39a3b0496911284b73de5b4363 +F src/trigger.c c07c5157c58fcdb704f65d5f5e4775276e45bb8b +F src/update.c 6ae6c26adff8dc34532d578f66e6cfde04b5d177 F src/utf.c 9541d28f40441812c0b40f00334372a0542c00ff -F src/util.c f3ee188f05921d450ee2a2ff236e455d3131f9ce +F src/util.c bb2bdd6dd0b51d13301dfb5bfba7abf070aef1dd F src/vacuum.c e8d178004377e97500c7ea87c8a3542976e3ea45 F src/vdbe.c b859cb274024e5755aa03625251ff859e3e95158 F src/vdbe.h 35a648bc3279a120da24f34d9a25213ec15daf8a @@ -209,10 +209,10 @@ F src/vdbeInt.h 43183a2a18654fa570219ab65e53a608057c48ae F src/vdbeapi.c 86aa27a5f3493aaffb8ac051782aa3b22670d7ed F src/vdbeaux.c 1a07329bdf51cc3687f88d9f5b2bd3f1d47cc5a8 F src/vdbeblob.c 5c5abe9af28316772e7829359f6f9cda2c737ebd -F src/vdbemem.c 4d1a9b01ad47a8699b767bfc364168c61510b3d1 +F src/vdbemem.c 9f4224911176f27b80d6e8f70f0e909aead5091b F src/vtab.c b0216337ae7d27708dedd56d220e6f4fecda92f1 -F src/walker.c b28cc618f5dc739bc5fb77389b6a42bc1be679ab -F src/where.c 145bb0d0590b36603a38f0fe17887fde06c3ed53 +F src/walker.c ec4b9742a4077ef80346e2f9aaf0f44c2d95087a +F src/where.c 1a21128db4905a29c287086acd7962cbba1c6f7b F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45 @@ -226,7 +226,7 @@ F test/async.test c042ff6d2a29f65e05d498a52448229d25bb5d9d F test/async2.test bf5e2ca2c96763b4cba3d016249ad7259a5603b6 F test/async3.test 93edaa9122f498e56ea98c36c72abc407f4fb11e F test/async4.test bdb997924394a2034ff3df1d839ff95b2e602ed4 -F test/attach.test 27635c34453504c2df8630730a5eab6e98c59eb9 +F test/attach.test e710d543769305942e9354cee5aba8cfcbe89577 F test/attach2.test a295d2d7061adcee5884ef4a93c7c96a82765437 F test/attach3.test 7b92dc8e40c1ebca9732ca6f2d3fefbd46f196df F test/attachmalloc.test cf8cf17d183de357b1147a9baacbdfc85b940b61 @@ -521,7 +521,7 @@ F test/savepoint5.test 0735db177e0ebbaedc39812c8d065075d563c4fd F test/savepoint6.test e28f7d8ab8a389d4e5bd1dc08bf2c3312754cc67 F test/schema.test deafe5472099ab5bc65748059dc5182fc8ebad74 F test/schema2.test 906408621ea881fdb496d878b1822572a34e32c5 -F test/select1.test 313078d5fca7a6fe1fb83e5f2e5b3e317beb8fac +F test/select1.test f67ca2dfc05df41c7b86eb32ca409b427a5f43b0 F test/select2.test 9735da20ccd41e42bf2b4c19fd939141b591adae F test/select3.test 2ce595f8fb8e2ac10071d3b4e424cadd4634a054 F test/select4.test 44aa6e7110592e18110b0b9cf5c024d37d23be17 @@ -629,7 +629,7 @@ F test/tkt3457.test e9ca2b90f0eb1fb8be73a30d29aacb2e3abedeb9 F test/tkt3461.test f79d027198b7e2bcf3d2d1a5501b6efef52096ee F test/tkt3472.test 98c7e54b8fef2b1266a552a66c8e5d88a6908d1d F test/tkt3493.test 8472b3464e49a27ff7271308eec46154209e667b -F test/tkt3508.test 26dbc10515145627fde6ad8905c842cec18e6f87 +F test/tkt3508.test d75704db9501625c7f7deec119fcaf1696aefb7d F test/tkt3522.test 22ce2ebbcb04a6be56c0977d405c207967318fd6 F test/tkt3527.test ee4af96183579565987e58873a7490bc04934ffb F test/tkt3541.test 5dc257bde9bc833ab9cc6844bf170b998dbb950a @@ -731,7 +731,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e -P 086206e1f51e22ce7b9f45865b370088db126cd2 -R 7a6811accc43c94a2230cdb121b78704 +P 7cb1c3ba0759539cb035978fdaff6316775986f3 +R fbcf886b0709cb6861bc0baa12580b58 U drh -Z 55c79ac1dc5e1ab2bd7febb8a2417351 +Z 0ccb491a6522821e67071949c3a88c54 diff --git a/manifest.uuid b/manifest.uuid index 8182fe564..c70ec0db5 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7cb1c3ba0759539cb035978fdaff6316775986f3
\ No newline at end of file +4ac2bdfbb4230b6ceaae87e738fa61036bbe03cb
\ No newline at end of file diff --git a/src/alter.c b/src/alter.c index 0c3e00e51..ac185f2da 100644 --- a/src/alter.c +++ b/src/alter.c @@ -12,7 +12,7 @@ ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** -** $Id: alter.c,v 1.59 2009/05/27 10:31:29 drh Exp $ +** $Id: alter.c,v 1.60 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" diff --git a/src/attach.c b/src/attach.c index 2b5ddb589..9af765973 100644 --- a/src/attach.c +++ b/src/attach.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the ATTACH and DETACH commands. ** -** $Id: attach.c,v 1.91 2009/05/27 10:31:29 drh Exp $ +** $Id: attach.c,v 1.92 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -41,7 +41,7 @@ static int resolveAttachExpr(NameContext *pName, Expr *pExpr) if( pExpr->op!=TK_ID ){ rc = sqlite3ResolveExprNames(pName, pExpr); if( rc==SQLITE_OK && !sqlite3ExprIsConstant(pExpr) ){ - sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->zToken); + sqlite3ErrorMsg(pName->pParse, "invalid name: \"%s\"", pExpr->u.zToken); return SQLITE_ERROR; } }else{ @@ -312,7 +312,7 @@ static void codeAttach( #ifndef SQLITE_OMIT_AUTHORIZATION if( pAuthArg ){ - char *zAuthArg = pAuthArg->zToken; + char *zAuthArg = pAuthArg->u.zToken; if( zAuthArg==0 ){ goto attach_end; } diff --git a/src/build.c b/src/build.c index 66f932e6e..ce8385992 100644 --- a/src/build.c +++ b/src/build.c @@ -22,7 +22,7 @@ ** COMMIT ** ROLLBACK ** -** $Id: build.c,v 1.545 2009/05/27 10:31:29 drh Exp $ +** $Id: build.c,v 1.546 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -1181,14 +1181,12 @@ void sqlite3AddCheckConstraint( #ifndef SQLITE_OMIT_CHECK Table *pTab = pParse->pNewTable; if( pTab && !IN_DECLARE_VTAB ){ - /* The CHECK expression must be duplicated so that tokens refer - ** to malloced space and not the (ephemeral) text of the CREATE TABLE - ** statement */ - pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, - sqlite3ExprDup(db, pCheckExpr, 0)); - } + pTab->pCheck = sqlite3ExprAnd(db, pTab->pCheck, pCheckExpr); + }else #endif - sqlite3ExprDelete(db, pCheckExpr); + { + sqlite3ExprDelete(db, pCheckExpr); + } } /* diff --git a/src/delete.c b/src/delete.c index e5177819c..95ef3cef7 100644 --- a/src/delete.c +++ b/src/delete.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** in order to generate code for DELETE FROM statements. ** -** $Id: delete.c,v 1.202 2009/05/27 10:31:29 drh Exp $ +** $Id: delete.c,v 1.203 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" diff --git a/src/expr.c b/src/expr.c index 6fe400d1e..a94b825eb 100644 --- a/src/expr.c +++ b/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.437 2009/05/27 10:31:29 drh Exp $ +** $Id: expr.c,v 1.438 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -40,7 +40,8 @@ char sqlite3ExprAffinity(Expr *pExpr){ } #ifndef SQLITE_OMIT_CAST if( op==TK_CAST ){ - return sqlite3AffinityType(pExpr->zToken); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + return sqlite3AffinityType(pExpr->u.zToken); } #endif if( (op==TK_AGG_COLUMN || op==TK_COLUMN || op==TK_REGISTER) @@ -388,6 +389,12 @@ int sqlite3SelectExprHeight(Select *p){ ** parameter is ignored if pToken is NULL or if the token does not ** appear to be quoted. If the quotes were of the form "..." (double-quotes) ** then the EP_DblQuoted flag is set on the expression node. +** +** Special case: If op==TK_INTEGER and pToken points to a string that +** can be translated into a 32-bit integer, then the token is not +** stored in u.zToken. Instead, the integer values is written +** into u.iValue and the EP_IntValue flag is set. No extra storage +** is allocated to hold the integer text and the dequote flag is ignored. */ Expr *sqlite3ExprAlloc( sqlite3 *db, /* Handle for sqlite3DbMallocZero() (may be null) */ @@ -396,26 +403,33 @@ Expr *sqlite3ExprAlloc( int dequote /* True to dequote */ ){ Expr *pNew; - int nExtra; + int nExtra = 0; + int iValue; if( pToken ){ - nExtra = pToken->n+1; - }else{ - nExtra = 0; + if( op!=TK_INTEGER || pToken->z==0 + || sqlite3GetInt32(pToken->z, &iValue)==0 ){ + nExtra = pToken->n+1; + } } pNew = sqlite3DbMallocZero(db, sizeof(Expr)+nExtra); if( pNew ){ pNew->op = (u8)op; pNew->iAgg = -1; if( pToken ){ - int c; - pNew->zToken = (char*)&pNew[1]; - memcpy(pNew->zToken, pToken->z, pToken->n); - pNew->zToken[pToken->n] = 0; - if( dequote && nExtra>=3 - && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ - sqlite3Dequote(pNew->zToken); - if( c=='"' ) pNew->flags |= EP_DblQuoted; + if( nExtra==0 ){ + pNew->flags |= EP_IntValue; + pNew->u.iValue = iValue; + }else{ + int c; + pNew->u.zToken = (char*)&pNew[1]; + memcpy(pNew->u.zToken, pToken->z, pToken->n); + pNew->u.zToken[pToken->n] = 0; + if( dequote && nExtra>=3 + && ((c = pToken->z[0])=='\'' || c=='"' || c=='[' || c=='`') ){ + sqlite3Dequote(pNew->u.zToken); + if( c=='"' ) pNew->flags |= EP_DblQuoted; + } } } #if SQLITE_MAX_EXPR_DEPTH>0 @@ -550,7 +564,8 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ const char *z; if( pExpr==0 ) return; - z = pExpr->zToken; + assert( !ExprHasAnyProperty(pExpr, EP_IntValue|EP_Reduced|EP_TokenOnly) ); + z = pExpr->u.zToken; assert( z!=0 ); assert( z[0]!=0 ); if( z[1]==0 ){ @@ -584,7 +599,7 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ for(i=0; i<pParse->nVarExpr; i++){ Expr *pE = pParse->apVarExpr[i]; assert( pE!=0 ); - if( memcmp(pE->zToken, z, n)==0 && pE->zToken[n]==0 ){ + if( memcmp(pE->u.zToken, z, n)==0 && pE->u.zToken[n]==0 ){ pExpr->iTable = pE->iTable; break; } @@ -616,19 +631,13 @@ void sqlite3ExprAssignVarNumber(Parse *pParse, Expr *pExpr){ ** Substructure is deleted. */ void sqlite3ExprClear(sqlite3 *db, Expr *p){ + assert( p!=0 ); if( !ExprHasAnyProperty(p, EP_TokenOnly) ){ - if( ExprHasProperty(p, EP_Reduced) ){ - /* Subtrees are part of the same memory allocation when EP_Reduced set */ - if( p->pLeft ) sqlite3ExprClear(db, p->pLeft); - if( p->pRight ) sqlite3ExprClear(db, p->pRight); - }else{ - /* Subtrees are separate allocations when EP_Reduced is clear */ - sqlite3ExprDelete(db, p->pLeft); - sqlite3ExprDelete(db, p->pRight); - /* Sometimes the zToken is allocated separately */ - if( p->flags2 & EP2_FreeToken ) sqlite3DbFree(db, p->zToken); + sqlite3ExprDelete(db, p->pLeft); + sqlite3ExprDelete(db, p->pRight); + if( !ExprHasProperty(p, EP_Reduced) && (p->flags2 & EP2_MallocedToken)!=0 ){ + sqlite3DbFree(db, p->u.zToken); } - /* x.pSelect and x.pList are always separately allocated */ if( ExprHasProperty(p, EP_xIsSelect) ){ sqlite3SelectDelete(db, p->x.pSelect); }else{ @@ -643,7 +652,9 @@ void sqlite3ExprClear(sqlite3 *db, Expr *p){ void sqlite3ExprDelete(sqlite3 *db, Expr *p){ if( p==0 ) return; sqlite3ExprClear(db, p); - sqlite3DbFree(db, p); + if( !ExprHasProperty(p, EP_Static) ){ + sqlite3DbFree(db, p); + } } /* @@ -658,34 +669,67 @@ static int exprStructSize(Expr *p){ } /* -** sqlite3ExprDup() has been called to create a copy of expression p with -** the EXPRDUP_XXX flags passed as the second argument. This function -** returns the space required for the copy of the Expr structure only. -** This is always one of EXPR_FULLSIZE, EXPR_REDUCEDSIZE or EXPR_TOKENONLYSIZE. +** The dupedExpr*Size() routines each return the number of bytes required +** to store a copy of an expression or expression tree. They differ in +** how much of the tree is measured. +** +** dupedExprStructSize() Size of only the Expr structure +** dupedExprNodeSize() Size of Expr + space for token +** dupedExprSize() Expr + token + subtree components +** +*************************************************************************** +** +** The dupedExprStructSize() function returns two values OR-ed together: +** (1) the space required for a copy of the Expr structure only and +** (2) the EP_xxx flags that indicate what the structure size should be. +** The return values is always one of: +** +** EXPR_FULLSIZE +** EXPR_REDUCEDSIZE | EP_Reduced +** EXPR_TOKENONLYSIZE | EP_TokenOnly +** +** The size of the structure can be found by masking the return value +** of this routine with 0xfff. The flags can be found by masking the +** return value with EP_Reduced|EP_TokenOnly. +** +** Note that with flags==EXPRDUP_REDUCE, this routines works on full-size +** (unreduced) Expr objects as they or originally constructed by the parser. +** During expression analysis, extra information is computed and moved into +** later parts of teh Expr object and that extra information might get chopped +** off if the expression is reduced. Note also that it does not work to +** make a EXPRDUP_REDUCE copy of a reduced expression. It is only legal +** to reduce a pristine expression tree from the parser. The implementation +** of dupedExprStructSize() contain multiple assert() statements that attempt +** to enforce this constraint. */ static int dupedExprStructSize(Expr *p, int flags){ int nSize; + assert( flags==EXPRDUP_REDUCE || flags==0 ); /* Only one flag value allowed */ if( 0==(flags&EXPRDUP_REDUCE) ){ nSize = EXPR_FULLSIZE; - }else if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ - nSize = EXPR_REDUCEDSIZE; }else{ - nSize = EXPR_TOKENONLYSIZE; + assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasProperty(p, EP_FromJoin) ); + assert( (p->flags2 & EP2_MallocedToken)==0 ); + assert( (p->flags2 & EP2_Irreducible)==0 ); + if( p->pLeft || p->pRight || p->pColl || p->x.pList ){ + nSize = EXPR_REDUCEDSIZE | EP_Reduced; + }else{ + nSize = EXPR_TOKENONLYSIZE | EP_TokenOnly; + } } return nSize; } /* -** sqlite3ExprDup() has been called to create a copy of expression p with -** the EXPRDUP_XXX passed as the second argument. This function returns -** the space in bytes required to store the copy of the Expr structure -** and the copies of the Expr.zToken (if applicable) -** string buffers. +** This function returns the space in bytes required to store the copy +** of the Expr structure and a copy of the Expr.u.zToken string (if that +** string is defined.) */ static int dupedExprNodeSize(Expr *p, int flags){ - int nByte = dupedExprStructSize(p, flags); - if( p->zToken ){ - nByte += sqlite3Strlen30(p->zToken)+1; + int nByte = dupedExprStructSize(p, flags) & 0xfff; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nByte += sqlite3Strlen30(p->u.zToken)+1; } return ROUND8(nByte); } @@ -696,7 +740,7 @@ static int dupedExprNodeSize(Expr *p, int flags){ ** mask containing EXPRDUP_XXX flags. ** ** The value returned includes space to create a copy of the Expr struct -** itself and the buffer referred to by Expr.zToken, if any. +** itself and the buffer referred to by Expr.u.zToken, if any. ** ** If the EXPRDUP_REDUCE flag is set, then the return value includes ** space to duplicate all Expr nodes in the tree formed by Expr.pLeft @@ -717,7 +761,7 @@ static int dupedExprSize(Expr *p, int flags){ /* ** This function is similar to sqlite3ExprDup(), except that if pzBuffer ** is not NULL then *pzBuffer is assumed to point to a buffer large enough -** to store the copy of expression p, the copies of p->zToken +** to store the copy of expression p, the copies of p->u.zToken ** (if applicable), and the copies of the p->pLeft and p->pRight expressions, ** if any. Before returning, *pzBuffer is set to the first byte passed the ** portion of the buffer copied into by this function. @@ -727,12 +771,14 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ if( p ){ const int isReduced = (flags&EXPRDUP_REDUCE); u8 *zAlloc; + u32 staticFlag = 0; assert( pzBuffer==0 || isReduced ); /* Figure out where to write the new Expr structure. */ if( pzBuffer ){ zAlloc = *pzBuffer; + staticFlag = EP_Static; }else{ zAlloc = sqlite3DbMallocRaw(db, dupedExprSize(p, flags)); } @@ -742,10 +788,16 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ /* Set nNewSize to the size allocated for the structure pointed to ** by pNew. This is either EXPR_FULLSIZE, EXPR_REDUCEDSIZE or ** EXPR_TOKENONLYSIZE. nToken is set to the number of bytes consumed - ** by the copy of the p->zToken string (if any). + ** by the copy of the p->u.zToken string (if any). */ - const int nNewSize = dupedExprStructSize(p, flags); - const int nToken = (p->zToken ? sqlite3Strlen30(p->zToken) + 1 : 0); + const unsigned nStructSize = dupedExprStructSize(p, flags); + const int nNewSize = nStructSize & 0xfff; + int nToken; + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + nToken = sqlite3Strlen30(p->u.zToken) + 1; + }else{ + nToken = 0; + } if( isReduced ){ assert( ExprHasProperty(p, EP_Reduced)==0 ); memcpy(zAlloc, p, nNewSize); @@ -755,17 +807,15 @@ static Expr *exprDup(sqlite3 *db, Expr *p, int flags, u8 **pzBuffer){ memset(&zAlloc[nSize], 0, EXPR_FULLSIZE-nSize); } - /* Set the EP_Reduced and EP_TokenOnly flags appropriately. */ - pNew->flags &= ~(EP_Reduced|EP_TokenOnly); - switch( nNewSize ){ - case EXPR_REDUCEDSIZE: pNew->flags |= EP_Reduced; break; - case EXPR_TOKENONLYSIZE: pNew->flags |= EP_TokenOnly; break; - } + /* Set the EP_Reduced, EP_TokenOnly, and EP_Static flags appropriately. */ + pNew->flags &= ~(EP_Reduced|EP_TokenOnly|EP_Static); + pNew->flags |= nStructSize & (EP_Reduced|EP_TokenOnly); + pNew->flags |= staticFlag; - /* Copy the p->zToken string, if any. */ + /* Copy the p->u.zToken string, if any. */ if( nToken ){ - char *zToken = pNew->zToken = (char*)&zAlloc[nNewSize]; - memcpy(zToken, p->zToken, nToken); + char *zToken = pNew->u.zToken = (char*)&zAlloc[nNewSize]; + memcpy(zToken, p->u.zToken, nToken); } if( 0==((p->flags|pNew->flags) & EP_TokenOnly) ){ @@ -1180,12 +1230,13 @@ int sqlite3ExprIsConstantOrFunction(Expr *p){ int sqlite3ExprIsInteger(Expr *p, int *pValue){ int rc = 0; if( p->flags & EP_IntValue ){ - *pValue = p->iTable; + *pValue = p->u.iValue; return 1; } switch( p->op ){ case TK_INTEGER: { - rc = sqlite3GetInt32(p->zToken, pValue); + rc = sqlite3GetInt32(p->u.zToken, pValue); + assert( rc==0 ); break; } case TK_UPLUS: { @@ -1203,9 +1254,11 @@ int sqlite3ExprIsInteger(Expr *p, int *pValue){ default: break; } if( rc ){ + assert( ExprHasAnyProperty(p, EP_Reduced|EP_TokenOnly) + || (p->flags2 & EP2_MallocedToken)==0 ); p->op = TK_INTEGER; p->flags |= EP_IntValue; - p->iTable = *pValue; + p->u.iValue = *pValue; } return rc; } @@ -1602,6 +1655,7 @@ void sqlite3CodeSubselect( return; } pExpr->iColumn = dest.iParm; + ExprSetIrreducible(pExpr); break; } } @@ -1662,12 +1716,12 @@ static void codeReal(Vdbe *v, const char *z, int negateFlag, int iMem){ static void codeInteger(Vdbe *v, Expr *pExpr, int negFlag, int iMem){ const char *z; if( pExpr->flags & EP_IntValue ){ - int i = pExpr->iTable; + int i = pExpr->u.iValue; if( negFlag ) i = -i; sqlite3VdbeAddOp2(v, OP_Integer, i, iMem); - }else if( (z = pExpr->zToken)!=0 ){ + }else if( (z = pExpr->u.zToken)!=0 ){ int i; - int n = sqlite3Strlen30(pExpr->zToken); + int n = sqlite3Strlen30(pExpr->u.zToken); assert( !sqlite3Isdigit(z[n]) ); if( sqlite3GetInt32(z, &i) ){ if( negFlag ) i = -i; @@ -2078,11 +2132,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ break; } case TK_FLOAT: { - codeReal(v, pExpr->zToken, 0, target); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + codeReal(v, pExpr->u.zToken, 0, target); break; } case TK_STRING: { - sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->zToken, 0); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3VdbeAddOp4(v, OP_String8, 0, target, 0, pExpr->u.zToken, 0); break; } case TK_NULL: { @@ -2094,9 +2150,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ int n; const char *z; char *zBlob; - assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' ); - assert( pExpr->zToken[1]=='\'' ); - z = &pExpr->zToken[2]; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); + assert( pExpr->u.zToken[1]=='\'' ); + z = &pExpr->u.zToken[2]; n = sqlite3Strlen30(z) - 1; assert( z[n]=='\'' ); zBlob = sqlite3HexToBlob(sqlite3VdbeDb(v), z, n); @@ -2107,9 +2164,10 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_VARIABLE: { int iPrior; VdbeOp *pOp; - assert( pExpr->zToken!=0 ); - assert( pExpr->zToken[0]!=0 ); - if( pExpr->zToken[1]==0 + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + assert( pExpr->u.zToken!=0 ); + assert( pExpr->u.zToken[0]!=0 ); + if( pExpr->u.zToken[1]==0 && (iPrior = sqlite3VdbeCurrentAddr(v)-1)>=0 && (pOp = sqlite3VdbeGetOp(v, iPrior))->opcode==OP_Variable && pOp->p1+pOp->p3==pExpr->iTable @@ -2124,8 +2182,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ pOp->p3++; }else{ sqlite3VdbeAddOp3(v, OP_Variable, pExpr->iTable, target, 1); - if( pExpr->zToken[1]!=0 ){ - sqlite3VdbeChangeP4(v, -1, pExpr->zToken, 0); + if( pExpr->u.zToken[1]!=0 ){ + sqlite3VdbeChangeP4(v, -1, pExpr->u.zToken, 0); } } break; @@ -2143,7 +2201,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ /* Expressions of the form: CAST(pLeft AS token) */ int aff, to_op; inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target); - aff = sqlite3AffinityType(pExpr->zToken); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + aff = sqlite3AffinityType(pExpr->u.zToken); to_op = aff - SQLITE_AFF_TEXT + OP_ToText; assert( to_op==OP_ToText || aff!=SQLITE_AFF_TEXT ); assert( to_op==OP_ToBlob || aff!=SQLITE_AFF_NONE ); @@ -2236,7 +2295,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ Expr *pLeft = pExpr->pLeft; assert( pLeft ); if( pLeft->op==TK_FLOAT ){ - codeReal(v, pLeft->zToken, 1, target); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + codeReal(v, pLeft->u.zToken, 1, target); }else if( pLeft->op==TK_INTEGER ){ codeInteger(v, pLeft, 1, target); }else{ @@ -2279,7 +2339,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ case TK_AGG_FUNCTION: { AggInfo *pInfo = pExpr->pAggInfo; if( pInfo==0 ){ - sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->zToken); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + sqlite3ErrorMsg(pParse, "misuse of aggregate: %s()", pExpr->u.zToken); }else{ inReg = pInfo->aFunc[pExpr->iAgg].iMem; } @@ -2306,7 +2367,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ pFarg = pExpr->x.pList; } nFarg = pFarg ? pFarg->nExpr : 0; - zId = pExpr->zToken; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(db, zId, nId, nFarg, enc, 0); assert( pDef!=0 ); @@ -2589,8 +2651,9 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ assert( pExpr->affinity==OE_Rollback || pExpr->affinity == OE_Abort || pExpr->affinity == OE_Fail ); + assert( !ExprHasProperty(pExpr, EP_IntValue) ); sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, pExpr->affinity, 0, - pExpr->zToken, 0); + pExpr->u.zToken, 0); } else { assert( pExpr->affinity == OE_Ignore ); sqlite3VdbeAddOp2(v, OP_ContextPop, 0, 0); @@ -3115,6 +3178,8 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ if( pA==0||pB==0 ){ return pB==pA; } + assert( !ExprHasAnyProperty(pA, EP_TokenOnly|EP_Reduced) ); + assert( !ExprHasAnyProperty(pB, EP_TokenOnly|EP_Reduced) ); if( ExprHasProperty(pA, EP_xIsSelect) || ExprHasProperty(pB, EP_xIsSelect) ){ return 0; } @@ -3135,9 +3200,13 @@ int sqlite3ExprCompare(Expr *pA, Expr *pB){ } if( pA->iTable!=pB->iTable || pA->iColumn!=pB->iColumn ) return 0; - if( pA->op!=TK_COLUMN && pA->zToken ){ - if( pB->zToken==0 ) return 0; - if( sqlite3StrICmp(pA->zToken,pB->zToken)!=0 ){ + if( ExprHasProperty(pA, EP_IntValue) ){ + if( !ExprHasProperty(pB, EP_IntValue) || pA->u.iValue!=pB->u.iValue ){ + return 0; + } + }else if( pA->op!=TK_COLUMN && pA->u.zToken ){ + if( ExprHasProperty(pB, EP_IntValue) || pB->u.zToken==0 ) return 0; + if( sqlite3StrICmp(pA->u.zToken,pB->u.zToken)!=0 ){ return 0; } } @@ -3204,6 +3273,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ struct SrcList_item *pItem = pSrcList->a; for(i=0; i<pSrcList->nSrc; i++, pItem++){ struct AggInfo_col *pCol; + assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); if( pExpr->iTable==pItem->iCursor ){ /* If we reach this point, it means that pExpr refers to a table ** that is in the FROM clause of the aggregate query. @@ -3252,6 +3322,7 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ ** Convert the pExpr to be a TK_AGG_COLUMN referring to that ** pAggInfo->aCol[] entry. */ + ExprSetIrreducible(pExpr); pExpr->pAggInfo = pAggInfo; pExpr->op = TK_AGG_COLUMN; pExpr->iAgg = k; @@ -3284,8 +3355,9 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ pItem = &pAggInfo->aFunc[i]; pItem->pExpr = pExpr; pItem->iMem = ++pParse->nMem; + assert( !ExprHasProperty(pExpr, EP_IntValue) ); pItem->pFunc = sqlite3FindFunction(pParse->db, - pExpr->zToken, sqlite3Strlen30(pExpr->zToken), + pExpr->u.zToken, sqlite3Strlen30(pExpr->u.zToken), pExpr->x.pList ? pExpr->x.pList->nExpr : 0, enc, 0); if( pExpr->flags & EP_Distinct ){ pItem->iDistinct = pParse->nTab++; @@ -3296,6 +3368,8 @@ static int analyzeAggregate(Walker *pWalker, Expr *pExpr){ } /* Make pExpr point to the appropriate pAggInfo->aFunc[] entry */ + assert( !ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); + ExprSetIrreducible(pExpr); pExpr->iAgg = i; pExpr->pAggInfo = pAggInfo; return WRC_Prune; diff --git a/src/func.c b/src/func.c index 3792d9efb..893406ceb 100644 --- a/src/func.c +++ b/src/func.c @@ -16,7 +16,7 @@ ** sqliteRegisterBuildinFunctions() found at the bottom of the file. ** All other code has file scope. ** -** $Id: func.c,v 1.235 2009/05/27 10:31:29 drh Exp $ +** $Id: func.c,v 1.236 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> @@ -1368,7 +1368,8 @@ int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){ return 0; } assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - pDef = sqlite3FindFunction(db, pExpr->zToken, sqlite3Strlen30(pExpr->zToken), + pDef = sqlite3FindFunction(db, pExpr->u.zToken, + sqlite3Strlen30(pExpr->u.zToken), 2, SQLITE_UTF8, 0); if( NEVER(pDef==0) || (pDef->flags & SQLITE_FUNC_LIKE)==0 ){ return 0; diff --git a/src/parse.y b/src/parse.y index 848ebaebc..d30f89f26 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.277 2009/05/27 10:31:29 drh Exp $ +** @(#) $Id: parse.y,v 1.278 2009/05/28 01:00:55 drh Exp $ */ // All token codes are small integers with #defines that begin with "TK_" diff --git a/src/pragma.c b/src/pragma.c index 6fca256d0..ae5ca7508 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.210 2009/05/27 10:31:29 drh Exp $ +** $Id: pragma.c,v 1.211 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" diff --git a/src/resolve.c b/src/resolve.c index b9c7face3..015fe4bf7 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -14,7 +14,7 @@ ** resolve all identifiers by associating them with a particular ** table and column. ** -** $Id: resolve.c,v 1.23 2009/05/27 10:31:29 drh Exp $ +** $Id: resolve.c,v 1.24 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> @@ -72,15 +72,15 @@ static void resolveAlias( } pDup->iTable = pEList->a[iCol].iAlias; }else{ - char *zToken = pOrig->zToken; - pOrig->zToken = 0; + char *zToken = pOrig->u.zToken; + pOrig->u.zToken = 0; pDup = sqlite3ExprDup(db, pOrig, 0); - pOrig->zToken = zToken; + pOrig->u.zToken = zToken; if( pDup==0 ) return; if( zToken ){ assert( (pDup->flags & (EP_Reduced|EP_TokenOnly))==0 ); - pDup->flags2 |= EP2_FreeToken; - pDup->zToken = sqlite3DbStrDup(db, zToken); + pDup->flags2 |= EP2_MallocedToken; + pDup->u.zToken = sqlite3DbStrDup(db, zToken); } } if( pExpr->flags & EP_ExpCollate ){ @@ -138,10 +138,12 @@ static int lookupName( assert( pNC ); /* the name context cannot be NULL. */ assert( zCol ); /* The Z in X.Y.Z cannot be NULL */ + assert( ~ExprHasAnyProperty(pExpr, EP_TokenOnly|EP_Reduced) ); /* Initialize the node to no-match */ pExpr->iTable = -1; pExpr->pTab = 0; + ExprSetIrreducible(pExpr); /* Start at the inner-most context and move outward until a match is found */ while( pNC && cnt==0 ){ @@ -439,7 +441,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ /* A lone identifier is the name of a column. */ case TK_ID: { - lookupName(pParse, 0, 0, pExpr->zToken, pNC, pExpr); + lookupName(pParse, 0, 0, pExpr->u.zToken, pNC, pExpr); return WRC_Prune; } @@ -456,13 +458,13 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ pRight = pExpr->pRight; if( pRight->op==TK_ID ){ zDb = 0; - zTable = pExpr->pLeft->zToken; - zColumn = pRight->zToken; + zTable = pExpr->pLeft->u.zToken; + zColumn = pRight->u.zToken; }else{ assert( pRight->op==TK_DOT ); - zDb = pExpr->pLeft->zToken; - zTable = pRight->pLeft->zToken; - zColumn = pRight->pRight->zToken; + zDb = pExpr->pLeft->u.zToken; + zTable = pRight->pLeft->u.zToken; + zColumn = pRight->pRight->u.zToken; } lookupName(pParse, zDb, zTable, zColumn, pNC, pExpr); return WRC_Prune; @@ -484,7 +486,7 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ u8 enc = ENC(pParse->db); /* The database encoding */ assert( !ExprHasProperty(pExpr, EP_xIsSelect) ); - zId = pExpr->zToken; + zId = pExpr->u.zToken; nId = sqlite3Strlen30(zId); pDef = sqlite3FindFunction(pParse->db, zId, nId, n, enc, 0); if( pDef==0 ){ @@ -586,8 +588,8 @@ static int resolveAsName( ){ int i; /* Loop counter */ - if( pE->op==TK_ID || (pE->op==TK_STRING && pE->zToken[0]!='\'') ){ - char *zCol = pE->zToken; + if( pE->op==TK_ID || (pE->op==TK_STRING && pE->u.zToken[0]!='\'') ){ + char *zCol = pE->u.zToken; for(i=0; i<pEList->nExpr; i++){ char *zAs = pEList->a[i].zName; if( zAs!=0 && sqlite3StrICmp(zAs, zCol)==0 ){ @@ -748,7 +750,7 @@ static int resolveCompoundOrderBy( if( pE==0 ) return 1; pE->pColl = pColl; pE->flags |= EP_IntValue | flags; - pE->iTable = iCol; + pE->u.iValue = iCol; pItem->iCol = (u16)iCol; pItem->done = 1; }else{ diff --git a/src/select.c b/src/select.c index 2f91ba9c5..54a42ab29 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.519 2009/05/27 10:31:29 drh Exp $ +** $Id: select.c,v 1.520 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -232,6 +232,8 @@ static void addWhereTerm( pE = sqlite3PExpr(pParse, TK_EQ, pE1c, pE2c, 0); if( pE && isOuterJoin ){ ExprSetProperty(pE, EP_FromJoin); + assert( !ExprHasAnyProperty(pE, EP_TokenOnly|EP_Reduced) ); + ExprSetIrreducible(pE); pE->iRightJoinTable = iRightJoinTable; } *ppExpr = sqlite3ExprAnd(pParse->db,*ppExpr, pE); @@ -266,6 +268,8 @@ static void addWhereTerm( static void setJoinExpr(Expr *p, int iTable){ while( p ){ ExprSetProperty(p, EP_FromJoin); + assert( !ExprHasAnyProperty(p, EP_TokenOnly|EP_Reduced) ); + ExprSetIrreducible(p); p->iRightJoinTable = iTable; setJoinExpr(p->pLeft, iTable); p = p->pRight; @@ -1127,7 +1131,8 @@ static int selectColumnsFromExprList( /* Get an appropriate name for the column */ p = pEList->a[i].pExpr; - assert( p->pRight==0 || p->pRight->zToken==0 || p->pRight->zToken[0]!=0 ); + assert( p->pRight==0 || ExprHasProperty(p->pRight, EP_IntValue) + || p->pRight->u.zToken==0 || p->pRight->u.zToken[0]!=0 ); if( (zName = pEList->a[i].zName)!=0 ){ /* If the column contains an "AS <name>" phrase, use <name> as the name */ zName = sqlite3DbStrDup(db, zName); @@ -1143,7 +1148,8 @@ static int selectColumnsFromExprList( zName = sqlite3MPrintf(db, "%s", iCol>=0 ? pTab->aCol[iCol].zName : "rowid"); }else if( pColExpr->op==TK_ID ){ - zName = sqlite3MPrintf(db, "%s", pColExpr->zToken); + assert( !ExprHasProperty(pColExpr, EP_IntValue) ); + zName = sqlite3MPrintf(db, "%s", pColExpr->u.zToken); }else{ /* Use the original text of the column expression as its name */ zName = sqlite3MPrintf(db, "%s", pEList->a[i].zSpan); @@ -2048,7 +2054,7 @@ static int multiSelectOrderBy( Expr *pNew = sqlite3Expr(db, TK_INTEGER, 0); if( pNew==0 ) return SQLITE_NOMEM; pNew->flags |= EP_IntValue; - pNew->iTable = i; + pNew->u.iValue = i; pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew); pOrderBy->a[nOrderBy++].iCol = (u16)i; } @@ -2896,9 +2902,10 @@ static u8 minMaxQuery(Select *p){ pEList = pExpr->x.pList; if( pEList==0 || pEList->nExpr!=1 ) return 0; if( pEList->a[0].pExpr->op!=TK_AGG_COLUMN ) return WHERE_ORDERBY_NORMAL; - if( sqlite3StrICmp(pExpr->zToken,"min")==0 ){ + assert( !ExprHasProperty(pExpr, EP_IntValue) ); + if( sqlite3StrICmp(pExpr->u.zToken,"min")==0 ){ return WHERE_ORDERBY_MIN; - }else if( sqlite3StrICmp(pExpr->zToken,"max")==0 ){ + }else if( sqlite3StrICmp(pExpr->u.zToken,"max")==0 ){ return WHERE_ORDERBY_MAX; } return WHERE_ORDERBY_NORMAL; @@ -3119,7 +3126,8 @@ static int selectExpander(Walker *pWalker, Select *p){ char *zTName; /* text of name of TABLE */ if( pE->op==TK_DOT ){ assert( pE->pLeft!=0 ); - zTName = pE->pLeft->zToken; + assert( !ExprHasProperty(pE->pLeft, EP_IntValue) ); + zTName = pE->pLeft->u.zToken; }else{ zTName = 0; } @@ -4143,8 +4151,8 @@ select_end: ** or from temporary "printf" statements inserted for debugging. */ void sqlite3PrintExpr(Expr *p){ - if( p->zToken ){ - sqlite3DebugPrintf("(%s", p->zToken); + if( !ExprHasProperty(p, EP_IntValue) && p->u.zToken ){ + sqlite3DebugPrintf("(%s", p->u.zToken); }else{ sqlite3DebugPrintf("(%d", p->op); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3c0a525dd..97de27667 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.876 2009/05/27 10:31:29 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.877 2009/05/28 01:00:55 drh Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ @@ -1464,7 +1464,7 @@ struct AggInfo { ** help reduce memory requirements, sometimes an Expr object will be ** truncated. And to reduce the number of memory allocations, sometimes ** two or more Expr objects will be stored in a single memory allocation, -** together with Expr.token strings. +** together with Expr.zToken strings. ** ** If the EP_Reduced and EP_TokenOnly flags are set when ** an Expr object is truncated. When EP_Reduced is set, then all @@ -1477,7 +1477,10 @@ struct Expr { u8 op; /* Operation performed by this node */ char affinity; /* The affinity of the column or 0 if not a column */ u16 flags; /* Various flags. EP_* See below */ - char *zToken; /* Token value. Zero terminated and dequoted */ + union { + char *zToken; /* Token value. Zero terminated and dequoted */ + int iValue; /* Integer value if EP_IntValue */ + } u; /* If the EP_TokenOnly flag is set in the Expr.flags mask, then no ** space is allocated for the fields below this point. An attempt to @@ -1498,8 +1501,7 @@ struct Expr { *********************************************************************/ int iTable; /* TK_COLUMN: cursor number of table holding column - ** TK_REGISTER: register number - ** EP_IntValue: integer value */ + ** TK_REGISTER: register number */ i16 iColumn; /* TK_COLUMN: column index. -1 for rowid */ i16 iAgg; /* Which entry in pAggInfo->aCol[] or ->aFunc[] */ i16 iRightJoinTable; /* If EP_FromJoin, the right table of the join */ @@ -1525,7 +1527,7 @@ struct Expr { #define EP_ExpCollate 0x0100 /* Collating sequence specified explicitly */ #define EP_AnyAff 0x0200 /* Can take a cached column of any affinity */ #define EP_FixedDest 0x0400 /* Result needed in a specific register */ -#define EP_IntValue 0x0800 /* Integer value contained in iTable */ +#define EP_IntValue 0x0800 /* Integer value contained in u.iValue */ #define EP_xIsSelect 0x1000 /* x.pSelect is valid (otherwise x.pList is) */ #define EP_Reduced 0x2000 /* Expr struct is EXPR_REDUCEDSIZE bytes only */ @@ -1535,7 +1537,20 @@ struct Expr { /* ** The following are the meanings of bits in the Expr.flags2 field. */ -#define EP2_FreeToken 0x0001 /* Need to call sqlite3DbFree() on Expr.zToken */ +#define EP2_MallocedToken 0x0001 /* Need to sqlite3DbFree() Expr.zToken */ +#define EP2_Irreducible 0x0002 /* Cannot EXPRDUP_REDUCE this Expr */ + +/* +** The pseudo-routine sqlite3ExprSetIrreducible sets the EP2_Irreducible +** flag on an expression structure. This flag is used for VV&A only. The +** routine is implemented as a macro that only works when in debugging mode, +** so as not to burden production code. +*/ +#ifdef SQLITE_DEBUG +# define ExprSetIrreducible(X) (X)->flags2 |= EP2_Irreducible +#else +# define ExprSetIrreducible(X) +#endif /* ** These macros can be used to test, set, or clear bits in the diff --git a/src/tokenize.c b/src/tokenize.c index 3e6c98c97..8bfda9bfd 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.157 2009/05/27 10:31:29 drh Exp $ +** $Id: tokenize.c,v 1.158 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> diff --git a/src/trigger.c b/src/trigger.c index 718e46e11..ab94f246a 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -10,7 +10,7 @@ ************************************************************************* ** ** -** $Id: trigger.c,v 1.140 2009/05/27 10:31:29 drh Exp $ +** $Id: trigger.c,v 1.141 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -375,15 +375,15 @@ TriggerStep *sqlite3TriggerInsertStep( pTriggerStep = triggerStepAllocate(db, TK_INSERT, pTableName); if( pTriggerStep ){ - pTriggerStep->pSelect = pSelect; + pTriggerStep->pSelect = sqlite3SelectDup(db, pSelect, EXPRDUP_REDUCE); pTriggerStep->pIdList = pColumn; - pTriggerStep->pExprList = pEList; + pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); pTriggerStep->orconf = orconf; }else{ sqlite3IdListDelete(db, pColumn); - sqlite3ExprListDelete(db, pEList); - sqlite3SelectDelete(db, pSelect); } + sqlite3ExprListDelete(db, pEList); + sqlite3SelectDelete(db, pSelect); return pTriggerStep; } @@ -403,14 +403,13 @@ TriggerStep *sqlite3TriggerUpdateStep( TriggerStep *pTriggerStep; pTriggerStep = triggerStepAllocate(db, TK_UPDATE, pTableName); - if( pTriggerStep==0 ){ - sqlite3ExprListDelete(db, pEList); - sqlite3ExprDelete(db, pWhere); - return 0; - } - pTriggerStep->pExprList = pEList; - pTriggerStep->pWhere = pWhere; - pTriggerStep->orconf = orconf; + if( pTriggerStep ){ + pTriggerStep->pExprList = sqlite3ExprListDup(db, pEList, EXPRDUP_REDUCE); + pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); + pTriggerStep->orconf = orconf; + } + sqlite3ExprListDelete(db, pEList); + sqlite3ExprDelete(db, pWhere); return pTriggerStep; } @@ -427,13 +426,11 @@ TriggerStep *sqlite3TriggerDeleteStep( TriggerStep *pTriggerStep; pTriggerStep = triggerStepAllocate(db, TK_DELETE, pTableName); - if( pTriggerStep==0 ){ - sqlite3ExprDelete(db, pWhere); - return 0; + if( pTriggerStep ){ + pTriggerStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE); + pTriggerStep->orconf = OE_Default; } - pTriggerStep->pWhere = pWhere; - pTriggerStep->orconf = OE_Default; - + sqlite3ExprDelete(db, pWhere); return pTriggerStep; } @@ -640,7 +637,6 @@ static SrcList *targetSrcList( Parse *pParse, /* The parsing context */ TriggerStep *pStep /* The trigger containing the target token */ ){ - Token sDb; /* Dummy database name token */ int iDb; /* Index of the database to use */ SrcList *pSrc; /* SrcList to be returned */ diff --git a/src/update.c b/src/update.c index e72a6354a..6eb92fb61 100644 --- a/src/update.c +++ b/src/update.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle UPDATE statements. ** -** $Id: update.c,v 1.201 2009/05/27 10:31:29 drh Exp $ +** $Id: update.c,v 1.202 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" diff --git a/src/util.c b/src/util.c index 76a8848db..00d13dd0c 100644 --- a/src/util.c +++ b/src/util.c @@ -14,7 +14,7 @@ ** This file contains functions for allocating memory, comparing ** strings, and stuff like that. ** -** $Id: util.c,v 1.255 2009/05/27 10:31:29 drh Exp $ +** $Id: util.c,v 1.256 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdarg.h> diff --git a/src/vdbemem.c b/src/vdbemem.c index 004ea367f..f5120c86b 100644 --- a/src/vdbemem.c +++ b/src/vdbemem.c @@ -15,7 +15,7 @@ ** only within the VDBE. Interface routines refer to a Mem using the ** name sqlite_value ** -** $Id: vdbemem.c,v 1.145 2009/05/27 10:31:29 drh Exp $ +** $Id: vdbemem.c,v 1.146 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include "vdbeInt.h" @@ -974,10 +974,15 @@ int sqlite3ValueFromExpr( op = pExpr->op; if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){ - zVal = sqlite3DbStrDup(db, pExpr->zToken); pVal = sqlite3ValueNew(db); - if( !zVal || !pVal ) goto no_mem; - sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + if( pVal==0 ) goto no_mem; + if( ExprHasProperty(pExpr, EP_IntValue) ){ + sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue); + }else{ + zVal = sqlite3DbStrDup(db, pExpr->u.zToken); + if( zVal==0 ) goto no_mem; + sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC); + } if( (op==TK_INTEGER || op==TK_FLOAT ) && affinity==SQLITE_AFF_NONE ){ sqlite3ValueApplyAffinity(pVal, SQLITE_AFF_NUMERIC, SQLITE_UTF8); }else{ @@ -996,11 +1001,11 @@ int sqlite3ValueFromExpr( #ifndef SQLITE_OMIT_BLOB_LITERAL else if( op==TK_BLOB ){ int nVal; - assert( pExpr->zToken[0]=='x' || pExpr->zToken[0]=='X' ); - assert( pExpr->zToken[1]=='\'' ); + assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' ); + assert( pExpr->u.zToken[1]=='\'' ); pVal = sqlite3ValueNew(db); if( !pVal ) goto no_mem; - zVal = &pExpr->zToken[2]; + zVal = &pExpr->u.zToken[2]; nVal = sqlite3Strlen30(zVal)-1; assert( zVal[nVal]=='\'' ); sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2, diff --git a/src/walker.c b/src/walker.c index 7be9e252f..f565bc55f 100644 --- a/src/walker.c +++ b/src/walker.c @@ -12,7 +12,7 @@ ** This file contains routines used for walking the parser tree for ** an SQL statement. ** -** $Id: walker.c,v 1.5 2009/05/27 10:31:29 drh Exp $ +** $Id: walker.c,v 1.6 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" #include <stdlib.h> diff --git a/src/where.c b/src/where.c index 7396bf198..48651ceb9 100644 --- a/src/where.c +++ b/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.398 2009/05/27 10:31:29 drh Exp $ +** $Id: where.c,v 1.399 2009/05/28 01:00:55 drh Exp $ */ #include "sqliteInt.h" @@ -658,7 +658,7 @@ static int isLikeOrGlob( (pColl->type!=SQLITE_COLL_NOCASE || !*pnoCase) ){ return 0; } - z = pRight->zToken; + z = pRight->u.zToken; cnt = 0; if( z ){ while( (c=z[cnt])!=0 && c!=wc[0] && c!=wc[1] && c!=wc[2] ){ @@ -691,7 +691,7 @@ static int isMatchOfColumn( if( pExpr->op!=TK_FUNCTION ){ return 0; } - if( sqlite3StrICmp(pExpr->zToken,"match")!=0 ){ + if( sqlite3StrICmp(pExpr->u.zToken,"match")!=0 ){ return 0; } pList = pExpr->x.pList; @@ -1161,12 +1161,12 @@ static void exprAnalyze( pLeft = pExpr->x.pList->a[1].pExpr; pRight = pExpr->x.pList->a[0].pExpr; - pStr1 = sqlite3Expr(db, TK_STRING, pRight->zToken); - if( pStr1 ) pStr1->zToken[nPattern] = 0; + pStr1 = sqlite3Expr(db, TK_STRING, pRight->u.zToken); + if( pStr1 ) pStr1->u.zToken[nPattern] = 0; pStr2 = sqlite3ExprDup(db, pStr1, 0); if( !db->mallocFailed ){ u8 c, *pC; - pC = (u8*)&pStr2->zToken[nPattern-1]; + pC = (u8*)&pStr2->u.zToken[nPattern-1]; c = *pC; if( noCase ){ if( c=='@' ) isComplete = 0; diff --git a/test/attach.test b/test/attach.test index 8c4552687..8dda7f2a8 100644 --- a/test/attach.test +++ b/test/attach.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach.test,v 1.50 2009/05/27 10:31:30 drh Exp $ +# $Id: attach.test,v 1.51 2009/05/28 01:00:56 drh Exp $ # set testdir [file dirname $argv0] diff --git a/test/select1.test b/test/select1.test index face8e4cf..73b0e40fe 100644 --- a/test/select1.test +++ b/test/select1.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the SELECT statement. # -# $Id: select1.test,v 1.69 2009/05/27 10:31:30 drh Exp $ +# $Id: select1.test,v 1.70 2009/05/28 01:00:56 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl diff --git a/test/tkt3508.test b/test/tkt3508.test index d4efdc3f6..8275d6998 100644 --- a/test/tkt3508.test +++ b/test/tkt3508.test @@ -10,7 +10,7 @@ #*********************************************************************** # This file implements regression tests for SQLite library. # -# $Id: tkt3508.test,v 1.4 2009/05/27 10:31:30 drh Exp $ +# $Id: tkt3508.test,v 1.5 2009/05/28 01:00:56 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl |