]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Additional refinements to Expr handling. Restore compression of trigger
authordrh <drh@noemail.net>
Thu, 28 May 2009 01:00:55 +0000 (01:00 +0000)
committerdrh <drh@noemail.net>
Thu, 28 May 2009 01:00:55 +0000 (01:00 +0000)
expressions.  Change Expr.zToken to Expr.u.zToken and added Expr.u.iValue.
Remove an unnecessary ExprDup from CHECK constraint processing.  And so forth. (CVS 6682)

FossilOrigin-Name: 4ac2bdfbb4230b6ceaae87e738fa61036bbe03cb

23 files changed:
manifest
manifest.uuid
src/alter.c
src/attach.c
src/build.c
src/delete.c
src/expr.c
src/func.c
src/parse.y
src/pragma.c
src/resolve.c
src/select.c
src/sqliteInt.h
src/tokenize.c
src/trigger.c
src/update.c
src/util.c
src/vdbemem.c
src/walker.c
src/where.c
test/attach.test
test/select1.test
test/tkt3508.test

index c2c460feb13f112582649cd10c8d7a58aca4a31f..b2ca6dc2d6656b73061f4bfa12288f950cd857a6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -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
index 8182fe564268e25abfbce0611a361dc98db86676..c70ec0db5372c7bfabb5555fa042da4d0eb2d694 100644 (file)
@@ -1 +1 @@
-7cb1c3ba0759539cb035978fdaff6316775986f3
\ No newline at end of file
+4ac2bdfbb4230b6ceaae87e738fa61036bbe03cb
\ No newline at end of file
index 0c3e00e518be977a17b9bf2889ca49d060ea69b8..ac185f2da0057e18967c9a95f475cbfee477f8a4 100644 (file)
@@ -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"
 
index 2b5ddb589582ba20db34412458ceaa57c610e684..9af765973e4d0642a21b2c26af2ee02687e925d0 100644 (file)
@@ -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;
     }
index 66f932e6eb947c67d02f23afea4797753ad9fee3..ce838599287e95f5e06959f8a493239c07dcf972 100644 (file)
@@ -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);
+  }
 }
 
 /*
index e5177819ca1b55cb0cbcebfff39267421fc1f71e..95ef3cef7439794d7d6314277f4f80f4f5162071 100644 (file)
@@ -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"
 
index 6fe400d1e23e0f178dc9fcc83e0a5bb1aca5143e..a94b825eb35272809f880d72dffea73ad05d921e 100644 (file)
@@ -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;
index 3792d9efbdc3c840b13562bcb879b7ea20210e90..893406cebf7e0e7225eddb46e8875f64c90d99d3 100644 (file)
@@ -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;
index 848ebaebc245e97ea8c91958c1d6ca0565344cf8..d30f89f2692b065015f015377c4f8dfd617e13f3 100644 (file)
@@ -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_"
index 6fca256d041214651be8fd6e6f70ffe31ae30bfa..ae5ca7508c668675244d6970c7c20b593e08eaf5 100644 (file)
@@ -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"
 
index b9c7face322a2f99fe214dd285e1de7cd9a961c2..015fe4bf7984b8c527e121e50233705c9e503804 100644 (file)
@@ -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{
index 2f91ba9c5b97518e01426536981aa001c59a7467..54a42ab29e64ab4aa2880d364bb42c567934f8e5 100644 (file)
@@ -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);
   }
index 3c0a525dd51b75cb7bcd6c955e47a2d6a09bc7ad..97de27667b6227905d12448cd67b86df244c3ec9 100644 (file)
@@ -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 
index 3e6c98c9704afc23f1f9349bb2b73a9c8564064e..8bfda9bfdfcf7eaf880db655edec41cbc49a7c24 100644 (file)
@@ -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>
index 718e46e11017170688669e3fe527a516503ae74d..ab94f246acb6f0d88821c9b794eecd6036fbc349 100644 (file)
@@ -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 */
 
index e72a6354a363696eedd670ea89739cbb59984829..6eb92fb615c01a2ae3187f353e93ebf4107bb50c 100644 (file)
@@ -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"
 
index 76a8848dbcf56182962539209b017249307513d4..00d13dd0c64bc078ecea1a092cb6670d52a1b47f 100644 (file)
@@ -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>
index 004ea367f52248388d0394c2bb79ac99efce0560..f5120c86bca6d66eec3804db7df9650ca134f115 100644 (file)
@@ -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,
index 7be9e252ff46ce0cbed752f295e703cbd474ed00..f565bc55f9d372ea3f82cca581a2540c5d5d433d 100644 (file)
@@ -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>
index 7396bf1989d59a1a2e56ad3d97d09e8959badc6a..48651ceb93cc6bb0c9a3429a57f50aedec6ca1ac 100644 (file)
@@ -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;
index 8c45526873c94b06e491068a12288ee4d63114ae..8dda7f2a829b3e5ee629d689ed93253c93d576e7 100644 (file)
@@ -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]
index face8e4cf606ed41fee5748a66738e78785c162d..73b0e40fe4e73b3422421b933c39600b7f3b01b3 100644 (file)
@@ -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
index d4efdc3f611af237f816b9b25e188df5286e89fd..8275d69987378ebee258e7402a9389b0dcafd650 100644 (file)
@@ -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