]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Optimizations to the code generator. (CVS 1899)
authordrh <drh@noemail.net>
Sat, 21 Aug 2004 17:54:45 +0000 (17:54 +0000)
committerdrh <drh@noemail.net>
Sat, 21 Aug 2004 17:54:45 +0000 (17:54 +0000)
FossilOrigin-Name: bd6649c5aae1bf182610eb267b546c297a34481d

19 files changed:
manifest
manifest.uuid
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/main.c
src/pragma.c
src/select.c
src/sqliteInt.h
src/trigger.c
src/update.c
src/vdbe.c
src/vdbe.h
src/vdbeInt.h
src/vdbeapi.c
src/vdbeaux.c
src/where.c
test/crash.test

index 7dc1a5c59d7bb6bf69d404634fff866402459c93..a8fa5593873a116c4cb680d5bd8af6d3d057d5b3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Tcl\sinterface\stransfers\svalues\sdirectly\sbetween\sSQLite\sand\sTcl_Objs,\swithout\nat\stranslation\sto\sstrings.\s(CVS\s1898)
-D 2004-08-20T18:34:20
+C Optimizations\sto\sthe\scode\sgenerator.\s(CVS\s1899)
+D 2004-08-21T17:54:45
 F Makefile.in 4a5e570a9e2d35b09c31b3cf01b78cea764ade4b
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -29,17 +29,17 @@ F src/attach.c 0bd4f11da6999665da30625665a4096ba7898de6
 F src/auth.c 60db23b98bb94c8b0178180faaf49dc116674217
 F src/btree.c 14c20dfb320473a1fd4e37d43eba5e2afd606757
 F src/btree.h 94dfec0a1722d33359b23e7e310f2b64ffedf029
-F src/build.c bad6652b33a447a06fca79a257f74932412fc110
+F src/build.c 7d93b19d03bffd171f7c7873739688cab7e300c5
 F src/date.c edff4aa851eeca8abbc737dc3933a2f0671156ce
-F src/delete.c e81545e546f6bc87d7508a93a09ca70695265af3
+F src/delete.c 0ccc3424d72e5aaded165a8861b9d958c9d0afe6
 F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37
-F src/expr.c 39ef5c141483f88c82472dbe0b5606b14d0a766d
+F src/expr.c 3694386726ca140dddb839837ba24b58563d10af
 F src/func.c 7e2eeebe219aa612ce7a04c74ae6d57379c6656b
 F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
-F src/insert.c bedcba371401395033a1a1c578d8fdc3fec87bec
+F src/insert.c fc1ce65a0fe68f226143de9b43c3582164a92aff
 F src/legacy.c 2f3617c61bcdcd1d776154a9cfebf99facda8ad8
-F src/main.c a779422c5402df92c390e233ac32ab718fc4436b
+F src/main.c 581ccf00909842d05c42ce02bb19b92859f447db
 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
 F src/os.h d1780e0db95cad01f213d48da22ab490eb4fd345
 F src/os_common.h cd7eb025fdab7dc91e0e97bf6310f1648205857f
@@ -54,13 +54,13 @@ F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44
 F src/pager.c 2698653a3bd895b2156c108a37a32d240a55bb0e
 F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71
 F src/parse.y 8b4cab1901900927f717d10885b7a1bd3375345b
-F src/pragma.c 5cf335adfdac453a2d03ab0c82f93847c43bea81
+F src/pragma.c a7cea75286fcff6666a5412b04478fcf0ecef5c4
 F src/printf.c 17b28a1eedfe8129b05de981719306c18c3f1327
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
-F src/select.c cbed45f4af76ad7fdfc0a0df6878b2b3827ae1d4
+F src/select.c 24b9ab865e34c0d5e7f2447558f93d1fe6f9d588
 F src/shell.c 42f65424a948f197f389e13bc7aaa3cf24dafd0c
 F src/sqlite.h.in de2be4043f0bfa16958d33392a3e7a5e7d4bd50b
-F src/sqliteInt.h 251662c89dd35c4ed745681ff00758d19ffd0906
+F src/sqliteInt.h c7ed161ecc40f9fd0f080fbcc00e34bd7d6735ee
 F src/table.c 4521c278892f60e4d630788c0ea5cf4db1e75c49
 F src/tclsqlite.c 2e044cb0638c03fa38575fe607bdd4ee4885e1f4
 F src/test1.c b87fae63b2994c150a579c4101f302be48ad77bc
@@ -69,18 +69,18 @@ F src/test3.c 94d0a2a90bccd85802488cb42c69ec8afd2e4646
 F src/test4.c c38766914e924091516030b6a8b677d849c08bf0
 F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1
 F src/tokenize.c b96043fdf662d93ccfc758d3e1cdf2513f23eca2
-F src/trigger.c 360cf8f12edd4eb3a8a2895b136aac238c3cf44e
-F src/update.c b66b1896c9da54678ba3eff2bf0b4d291a95986a
+F src/trigger.c 8b147c6b8ae0bab3a13463a4ca9ab6ad61f1361d
+F src/update.c 151f1869ce532ed883f1ce26306f0b0fa7b2589a
 F src/utf.c 3d8f7bffcbefcced69a436c9e0a1c7eb9e0bb4fa
 F src/util.c e2c631849cc9e035f6fd387f507ad8886f77cedd
 F src/vacuum.c 9978a5760c2c430bc5b5e66505a02dad76f25813
-F src/vdbe.c 281af7f601a3220e86be2152eeb2ec6d82a6f71a
-F src/vdbe.h 75b241c02431b9c0f16eaa9cdbb34146c6287f52
-F src/vdbeInt.h 5e57e36a03ebf09f2653caec0d9c18a904e0d060
-F src/vdbeapi.c 4f9b3072589dcad2fcd3abb3538e5e8f00d224a1
-F src/vdbeaux.c cc86e59cb56dad2f9335933f71268227f5f91bce
+F src/vdbe.c ea662188cc489934a567d1eaa3fb6754d5b92b7d
+F src/vdbe.h e081c72cd0f7c19d49b1927460aeefcf0fbc85ac
+F src/vdbeInt.h 16322cbfccf0b05631fcf0df68b115c46584d6c9
+F src/vdbeapi.c e20e646a0ec4e74934bfcb82bd0fbb3c3c4a21f7
+F src/vdbeaux.c 022c484dba235d2dcbb1faca0f1943702f4232ed
 F src/vdbemem.c 68fefaf83adb48fe44135da01502c9327f6172b0
-F src/where.c cf8a54641eea01f1af5d09529ad69166db92f658
+F src/where.c a84eee276cd072158224da6b5f30733df2d56027
 F test/all.test 3b692eb43583b52c99c344b2fa8934512d179016
 F test/attach.test feb2ce54e78688df4c84553416d5aec3b2a0112e
 F test/attach2.test 9be9656bc1e929b224861960299920c76d45b14d
@@ -105,7 +105,7 @@ F test/collate4.test 4a7902b7560686af11d6cace717d876c6937b7ef
 F test/collate5.test 1dd5f0f508c46667f9d4606c7950c414b0bdc0d5
 F test/collate6.test 2a45768914f04c1447a69d1358bbede376552675
 F test/conflict.test c5b849b01cfbe0a4f63a90cba6f68e2fe3a75f87
-F test/crash.test 3ea432ce624369c04ba1a23a5288115e40f5daa2
+F test/crash.test 59a91b7fbb41e9e5cb8ab652f22a7e639a0adc78
 F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
 F test/date.test fd3db29bba089578b1b008e3511ea9e74840377a
 F test/delete.test ec0b455f2dcc0e189d96ee438438ba026c4e51d8
@@ -243,7 +243,7 @@ F www/tclsqlite.tcl 06a86cba4d7fc88e2bcd633b57702d3d16abebb5
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P d3be0b7c5a39c02b9b2d6d85f1595d591984a569
-R 1cbcdf6d3d0885857959264a9f52fa75
+P e97c331362545ce21117776c7b61d3488668f2bf
+R b22d8f216bcbbb8b75e2380cdf547c74
 U drh
-Z e2be1e764ed7eb73ae85dcaeb658f10f
+Z d01e8ee90bb832b679bd3adc8a30a5ef
index a74654c7eeed4be985754acbd48602d89554dcb3..7611e3fcffb714cc2b8deaa421ad6b88b002ba8a 100644 (file)
@@ -1 +1 @@
-e97c331362545ce21117776c7b61d3488668f2bf
\ No newline at end of file
+bd6649c5aae1bf182610eb267b546c297a34481d
\ No newline at end of file
index 7f6ac411db484a1ae5d0a2e246cfbd2ca8fd9394..ca536f76436ea0bf816111b0599b565f3182a60e 100644 (file)
@@ -23,7 +23,7 @@
 **     ROLLBACK
 **     PRAGMA
 **
-** $Id: build.c,v 1.248 2004/08/18 15:58:23 drh Exp $
+** $Id: build.c,v 1.249 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -96,7 +96,8 @@ void sqlite3FinishCoding(Parse *pParse){
   if( v && pParse->nErr==0 ){
     FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
     sqlite3VdbeTrace(v, trace);
-    sqlite3VdbeMakeReady(v, pParse->nVar, pParse->explain);
+    sqlite3VdbeMakeReady(v, pParse->nVar, pParse->nMem+3,
+                         pParse->nTab+3, pParse->explain);
     pParse->rc = pParse->nErr ? SQLITE_ERROR : SQLITE_DONE;
     pParse->colNamesSet = 0;
   }else if( pParse->rc==SQLITE_OK ){
index 7308eb817ee8bd03c32973de5e78291148a0d900..bfe1cbde5b3477288598f6e75110357e8cec49d2 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle DELETE FROM statements.
 **
-** $Id: delete.c,v 1.77 2004/06/21 18:14:47 drh Exp $
+** $Id: delete.c,v 1.78 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -121,13 +121,8 @@ void sqlite3DeleteFrom(
   */
   assert( pTabList->nSrc==1 );
   iCur = pTabList->a[0].iCursor = pParse->nTab++;
-  if( pWhere ){
-    if( sqlite3ExprResolveIds(pParse, pTabList, 0, pWhere) ){
-      goto delete_from_cleanup;
-    }
-    if( sqlite3ExprCheck(pParse, pWhere, 0, 0) ){
-      goto delete_from_cleanup;
-    }
+  if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){
+    goto delete_from_cleanup;
   }
 
   /* Start the view context
@@ -262,8 +257,7 @@ void sqlite3DeleteFrom(
       ** before the trigger fires.  If there are no row triggers, the
       ** cursors are opened only once on the outside the loop.
       */
-      pParse->nTab = iCur + 1;
-      sqlite3OpenTableAndIndices(pParse, pTab, iCur);
+      sqlite3OpenTableAndIndices(pParse, pTab, iCur, OP_OpenWrite);
 
       /* This is the beginning of the delete loop when there are no
       ** row triggers */
@@ -301,7 +295,6 @@ void sqlite3DeleteFrom(
         sqlite3VdbeAddOp(v, OP_Close, iCur + i, pIdx->tnum);
       }
       sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
-      pParse->nTab = iCur;
     }
   }
   sqlite3EndWriteOperation(pParse);
index 6e8a75ee47335b19197be0410587db33cbdf978d..5377a2daa5adaaf7ee09a695d8fdc9690778e151 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.156 2004/08/20 16:02:39 drh Exp $
+** $Id: expr.c,v 1.157 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1079,6 +1079,27 @@ int sqlite3ExprCheck(Parse *pParse, Expr *pExpr, int allowAgg, int *pIsAgg){
   return nErr;
 }
 
+/*
+** Call sqlite3ExprResolveIds() followed by sqlite3ExprCheck().
+**
+** This routine is provided as a convenience since it is very common
+** to call ResolveIds() and Check() back to back.
+*/
+int sqlite3ExprResolveAndCheck(
+  Parse *pParse,     /* The parser context */
+  SrcList *pSrcList, /* List of tables used to resolve column names */
+  ExprList *pEList,  /* List of expressions used to resolve "AS" */
+  Expr *pExpr,       /* The expression to be analyzed. */
+  int allowAgg,      /* True to allow aggregate expressions */
+  int *pIsAgg        /* Set to TRUE if aggregates are found */
+){
+  if( pExpr==0 ) return 0;
+  if( sqlite3ExprResolveIds(pParse,pSrcList,pEList,pExpr) ){
+    return 1;
+  }
+  return sqlite3ExprCheck(pParse, pExpr, allowAgg, pIsAgg);
+}
+
 /*
 ** Generate an instruction that will put the integer describe by
 ** text z[0..n-1] on the stack.
index 7959947d15060e4ed32a7da1ed3c8cf10dbeb7b3..77638b7f2e6ecb64669e1052a6a255cc9b593e39 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.114 2004/07/24 17:38:29 drh Exp $
+** $Id: insert.c,v 1.115 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -333,10 +333,7 @@ void sqlite3Insert(
     nColumn = pList->nExpr;
     dummy.nSrc = 0;
     for(i=0; i<nColumn; i++){
-      if( sqlite3ExprResolveIds(pParse, &dummy, 0, pList->a[i].pExpr) ){
-        goto insert_cleanup;
-      }
-      if( sqlite3ExprCheck(pParse, pList->a[i].pExpr, 0, 0) ){
+      if( sqlite3ExprResolveAndCheck(pParse,&dummy,0,pList->a[i].pExpr,0,0) ){
         goto insert_cleanup;
       }
     }
@@ -420,8 +417,7 @@ void sqlite3Insert(
   /* Open tables and indices if there are no row triggers */
   if( !row_triggers_exist ){
     base = pParse->nTab;
-    idx = sqlite3OpenTableAndIndices(pParse, pTab, base);
-    pParse->nTab += idx;
+    sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
   }
 
   /* If the data source is a temporary table, then we have to create
@@ -507,8 +503,7 @@ void sqlite3Insert(
   */
   if( row_triggers_exist && !isView ){
     base = pParse->nTab;
-    idx = sqlite3OpenTableAndIndices(pParse, pTab, base);
-    pParse->nTab += idx;
+    sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
   }
 
   /* Push the record number for the new entry onto the stack.  The
@@ -993,25 +988,29 @@ void sqlite3CompleteInsertion(
 }
 
 /*
-** Generate code that will open write cursors for a table and for all
+** Generate code that will open cursors for a table and for all
 ** indices of that table.  The "base" parameter is the cursor number used
 ** for the table.  Indices are opened on subsequent cursors.
-**
-** Return the total number of cursors opened.  This is always at least
-** 1 (for the main table) plus more for each cursor.
 */
-int sqlite3OpenTableAndIndices(Parse *pParse, Table *pTab, int base){
+void sqlite3OpenTableAndIndices(
+  Parse *pParse,   /* Parsing context */
+  Table *pTab,     /* Table to be opened */
+  int base,        /* Cursor number assigned to the table */
+  int op           /* OP_OpenRead or OP_OpenWrite */
+){
   int i;
   Index *pIdx;
   Vdbe *v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
   sqlite3VdbeAddOp(v, OP_Integer, pTab->iDb, 0);
-  sqlite3VdbeAddOp(v, OP_OpenWrite, base, pTab->tnum);
+  sqlite3VdbeAddOp(v, op, base, pTab->tnum);
   sqlite3VdbeAddOp(v, OP_SetNumColumns, base, pTab->nCol);
   for(i=1, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
     sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
-    sqlite3VdbeOp3(v, OP_OpenWrite, i+base, pIdx->tnum,
+    sqlite3VdbeOp3(v, op, i+base, pIdx->tnum,
                    (char*)&pIdx->keyInfo, P3_KEYINFO);
   }
-  return i;
+  if( pParse->nTab<=base+i ){
+    pParse->nTab = base+i;
+  }
 }
index 0d34349fa4cbd6dfe85143614b255f30809be2c9..35b9c387d2ae254f934d333c0c66380634d0e5cd 100644 (file)
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.252 2004/08/18 02:10:15 drh Exp $
+** $Id: main.c,v 1.253 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -1253,7 +1253,7 @@ int sqlite3_finalize(sqlite3_stmt *pStmt){
 */
 int sqlite3_reset(sqlite3_stmt *pStmt){
   int rc = sqlite3VdbeReset((Vdbe*)pStmt);
-  sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0);
+  sqlite3VdbeMakeReady((Vdbe*)pStmt, -1, 0, 0, 0);
   return rc;
 }
 
index a7189945a30fda07e21213827cd7ae949412a4fb..172ace35914a7037c0f80aefb9409f777d25fcb0 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to implement the PRAGMA command.
 **
-** $Id: pragma.c,v 1.59 2004/08/08 20:22:18 drh Exp $
+** $Id: pragma.c,v 1.60 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -538,7 +538,7 @@ void sqlite3Pragma(
       { OP_MemLoad,     0, 0,        0},
       { OP_Integer,     0, 0,        0},
       { OP_Ne,          0, 0,        0},    /* 2 */
-      { OP_String8,      0, 0,        "ok"},
+      { OP_String8,     0, 0,        "ok"},
       { OP_Callback,    1, 0,        0},
     };
 
@@ -589,15 +589,7 @@ void sqlite3Pragma(
         int loopTop;
 
         if( pTab->pIndex==0 ) continue;
-        sqlite3VdbeAddOp(v, OP_Integer, i, 0);
-        sqlite3VdbeAddOp(v, OP_OpenRead, 1, pTab->tnum);
-        sqlite3VdbeAddOp(v, OP_SetNumColumns, 1, pTab->nCol);
-        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
-          if( pIdx->tnum==0 ) continue;
-          sqlite3VdbeAddOp(v, OP_Integer, pIdx->iDb, 0);
-          sqlite3VdbeOp3(v, OP_OpenRead, j+2, pIdx->tnum, 
-                         (char*)&pIdx->keyInfo, P3_KEYINFO);
-        }
+        sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
         sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
         sqlite3VdbeAddOp(v, OP_MemStore, 1, 1);
         loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0);
@@ -606,11 +598,11 @@ void sqlite3Pragma(
           int jmp2;
           static VdbeOpList idxErr[] = {
             { OP_MemIncr,     0,  0,  0},
-            { OP_String8,      0,  0,  "rowid "},
+            { OP_String8,     0,  0,  "rowid "},
             { OP_Recno,       1,  0,  0},
-            { OP_String8,      0,  0,  " missing from index "},
-            { OP_String8,      0,  0,  0},    /* 4 */
-            { OP_Concat8,      4,  0,  0},
+            { OP_String8,     0,  0,  " missing from index "},
+            { OP_String8,     0,  0,  0},    /* 4 */
+            { OP_Concat8,     4,  0,  0},
             { OP_Callback,    1,  0,  0},
           };
           sqlite3GenerateIndexKey(v, pIdx, 1);
@@ -632,9 +624,9 @@ void sqlite3Pragma(
              { OP_MemLoad,      2,  0,  0},
              { OP_Eq,           0,  0,  0},  /* 7 */
              { OP_MemIncr,      0,  0,  0},
-             { OP_String8,       0,  0,  "wrong # of entries in index "},
-             { OP_String8,       0,  0,  0},  /* 10 */
-             { OP_Concat8,       2,  0,  0},
+             { OP_String8,      0,  0,  "wrong # of entries in index "},
+             { OP_String8,      0,  0,  0},  /* 10 */
+             { OP_Concat8,      2,  0,  0},
              { OP_Callback,     1,  0,  0},
           };
           if( pIdx->tnum==0 ) continue;
index 820f73ffc5d11025cd5742cf7255a767949a6f0b..191ec4ba1c6285316782b96d9f18908cbdeb8079 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.202 2004/07/26 23:32:27 drh Exp $
+** $Id: select.c,v 1.203 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -83,8 +83,8 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
   Token *p;
   static struct {
     const char *zKeyword;
-    int nChar;
-    int code;
+    u8 nChar;
+    u8 code;
   } keywords[] = {
     { "natural", 7, JT_NATURAL },
     { "left",    4, JT_LEFT|JT_OUTER },
@@ -804,7 +804,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
   Table *pTab;
   int i, j;
   ExprList *pEList;
-  Column *aCol;
+  Column *aCol, *pCol;
 
   if( fillInColumnList(pParse, pSelect) ){
     return 0;
@@ -818,44 +818,45 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){
   pTab->nCol = pEList->nExpr;
   assert( pTab->nCol>0 );
   pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );
-  for(i=0; i<pTab->nCol; i++){
+  for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){
     Expr *pR;
     char *zType;
     Expr *p = pEList->a[i].pExpr;
+    assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );
     if( pEList->a[i].zName ){
-      aCol[i].zName = sqliteStrDup(pEList->a[i].zName);
+      pCol->zName = sqliteStrDup(pEList->a[i].zName);
     }else if( p->op==TK_DOT 
                && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){
       int cnt;
-      sqlite3SetNString(&aCol[i].zName, pR->token.z, pR->token.n, 0);
+      sqlite3SetNString(&pCol->zName, pR->token.z, pR->token.n, 0);
       for(j=cnt=0; j<i; j++){
-        if( sqlite3StrICmp(aCol[j].zName, aCol[i].zName)==0 ){
+        if( sqlite3StrICmp(aCol[j].zName, pCol->zName)==0 ){
           int n;
           char zBuf[30];
           sprintf(zBuf,"_%d",++cnt);
           n = strlen(zBuf);
-          sqlite3SetNString(&aCol[i].zName, pR->token.z, pR->token.n, zBuf,n,0);
+          sqlite3SetNString(&pCol->zName, pR->token.z, pR->token.n, zBuf,n,0);
           j = -1;
         }
       }
     }else if( p->span.z && p->span.z[0] ){
-      sqlite3SetNString(&pTab->aCol[i].zName, p->span.z, p->span.n, 0);
+      sqlite3SetNString(&pCol->zName, p->span.z, p->span.n, 0);
     }else{
       char zBuf[30];
       sprintf(zBuf, "column%d", i+1);
-      pTab->aCol[i].zName = sqliteStrDup(zBuf);
+      pCol->zName = sqliteStrDup(zBuf);
     }
-    sqlite3Dequote(aCol[i].zName);
+    sqlite3Dequote(pCol->zName);
 
     zType = sqliteStrDup(columnType(pParse, pSelect->pSrc ,p));
-    pTab->aCol[i].zType = zType;
-    pTab->aCol[i].affinity = SQLITE_AFF_NUMERIC;
+    pCol->zType = zType;
+    pCol->affinity = SQLITE_AFF_NUMERIC;
     if( zType ){
-      pTab->aCol[i].affinity = sqlite3AffinityType(zType, strlen(zType));
+      pCol->affinity = sqlite3AffinityType(zType, strlen(zType));
     }
-    pTab->aCol[i].pColl = sqlite3ExprCollSeq(pParse, p);
-    if( !pTab->aCol[i].pColl ){
-      pTab->aCol[i].pColl = pParse->db->pDfltColl;
+    pCol->pColl = sqlite3ExprCollSeq(pParse, p);
+    if( !pCol->pColl ){
+      pCol->pColl = pParse->db->pDfltColl;
     }
   }
   pTab->iPKey = -1;
@@ -889,6 +890,7 @@ static int fillInColumnList(Parse *pParse, Select *p){
   SrcList *pTabList;
   ExprList *pEList;
   Table *pTab;
+  struct SrcList_item *pFrom;
 
   if( p==0 || p->pSrc==0 ) return 1;
   pTabList = p->pSrc;
@@ -896,23 +898,21 @@ static int fillInColumnList(Parse *pParse, Select *p){
 
   /* Look up every table in the table list.
   */
-  for(i=0; i<pTabList->nSrc; i++){
-    if( pTabList->a[i].pTab ){
+  for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+    if( pFrom->pTab ){
       /* This routine has run before!  No need to continue */
       return 0;
     }
-    if( pTabList->a[i].zName==0 ){
+    if( pFrom->zName==0 ){
       /* A sub-query in the FROM clause of a SELECT */
-      assert( pTabList->a[i].pSelect!=0 );
-      if( pTabList->a[i].zAlias==0 ){
+      assert( pFrom->pSelect!=0 );
+      if( pFrom->zAlias==0 ){
         char zFakeName[60];
-        sprintf(zFakeName, "sqlite_subquery_%p_",
-           (void*)pTabList->a[i].pSelect);
-        sqlite3SetString(&pTabList->a[i].zAlias, zFakeName, 0);
+        sprintf(zFakeName, "sqlite_subquery_%p_", (void*)pFrom->pSelect);
+        sqlite3SetString(&pFrom->zAlias, zFakeName, 0);
       }
-      pTabList->a[i].pTab = pTab = 
-        sqlite3ResultSetOfSelect(pParse, pTabList->a[i].zAlias,
-                                        pTabList->a[i].pSelect);
+      pFrom->pTab = pTab = 
+        sqlite3ResultSetOfSelect(pParse, pFrom->zAlias, pFrom->pSelect);
       if( pTab==0 ){
         return 1;
       }
@@ -923,8 +923,8 @@ static int fillInColumnList(Parse *pParse, Select *p){
       pTab->isTransient = 1;
     }else{
       /* An ordinary table or view name in the FROM clause */
-      pTabList->a[i].pTab = pTab = 
-        sqlite3LocateTable(pParse,pTabList->a[i].zName,pTabList->a[i].zDatabase);
+      pFrom->pTab = pTab = 
+        sqlite3LocateTable(pParse,pFrom->zName,pFrom->zDatabase);
       if( pTab==0 ){
         return 1;
       }
@@ -933,13 +933,13 @@ static int fillInColumnList(Parse *pParse, Select *p){
         if( sqlite3ViewGetColumnNames(pParse, pTab) ){
           return 1;
         }
-        /* If pTabList->a[i].pSelect!=0 it means we are dealing with a
+        /* If pFrom->pSelect!=0 it means we are dealing with a
         ** view within a view.  The SELECT structure has already been
         ** copied by the outer view so we can skip the copy step here
         ** in the inner view.
         */
-        if( pTabList->a[i].pSelect==0 ){
-          pTabList->a[i].pSelect = sqlite3SelectDup(pTab->pSelect);
+        if( pFrom->pSelect==0 ){
+          pFrom->pSelect = sqlite3SelectDup(pTab->pSelect);
         }
       }
     }
@@ -994,9 +994,9 @@ static int fillInColumnList(Parse *pParse, Select *p){
         }else{
           zTName = 0;
         }
-        for(i=0; i<pTabList->nSrc; i++){
-          Table *pTab = pTabList->a[i].pTab;
-          char *zTabName = pTabList->a[i].zAlias;
+        for(i=0, pFrom=pTabList->a; i<pTabList->nSrc; i++, pFrom++){
+          Table *pTab = pFrom->pTab;
+          char *zTabName = pFrom->zAlias;
           if( zTabName==0 || zTabName[0]==0 ){ 
             zTabName = pTab->zName;
           }
@@ -1188,21 +1188,6 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
   return v;
 }
 
-#if 0  /***** This routine needs deleting *****/
-static void multiSelectAffinity(Select *p, char *zAff){
-  int i;
-
-  if( !p ) return;
-  multiSelectAffinity(p->pPrior, zAff);
-
-  for(i=0; i<p->pEList->nExpr; i++){
-    if( zAff[i]=='\0' ){
-      zAff[i] = sqlite3ExprAffinity(p->pEList->a[i].pExpr);
-    }
-  }
-}
-#endif
-
 /*
 ** Compute the iLimit and iOffset fields of the SELECT based on the
 ** nLimit and nOffset fields.  nLimit and nOffset hold the integers
@@ -2112,6 +2097,50 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
   return 1;
 }
 
+/*
+** Analyze and ORDER BY or GROUP BY clause in a SELECT statement.  Return
+** the number of errors seen.
+**
+** An ORDER BY or GROUP BY is a list of expressions.  If any expression
+** is an integer constant, then that expression is replaced by the
+** corresponding entry in the result set.
+*/
+static int processOrderGroupBy(
+  Parse *pParse,        /* Parsing context */
+  ExprList *pOrderBy,   /* The ORDER BY or GROUP BY clause to be processed */
+  SrcList *pTabList,    /* The FROM clause */
+  ExprList *pEList,     /* The result set */
+  int isAgg,            /* True if aggregate functions are involved */
+  const char *zType     /* Either "ORDER" or "GROUP", as appropriate */
+){
+  int i;
+  if( pOrderBy==0 ) return 0;
+  for(i=0; i<pOrderBy->nExpr; i++){
+    int iCol;
+    Expr *pE = pOrderBy->a[i].pExpr;
+    if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){
+      sqlite3ExprDelete(pE);
+      pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
+    }
+    if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pE, isAgg, 0) ){
+      return 1;
+    }
+    if( sqlite3ExprIsConstant(pE) ){
+      if( sqlite3ExprIsInteger(pE, &iCol)==0 ){
+        sqlite3ErrorMsg(pParse,
+          "%s BY terms must not be non-integer constants", zType);
+        return 1;
+      }else if( iCol<=0 || iCol>pEList->nExpr ){
+        sqlite3ErrorMsg(pParse, 
+           "%s BY column number %d out of range - should be "
+           "between 1 and %d", zType, iCol, pEList->nExpr);
+        return 1;
+      }
+    }
+  }
+  return 0;
+}
+
 /*
 ** Generate code for the given SELECT statement.
 **
@@ -2254,88 +2283,27 @@ int sqlite3Select(
   ** Resolve the column names and do a semantics check on all the expressions.
   */
   for(i=0; i<pEList->nExpr; i++){
-    if( sqlite3ExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){
-      goto select_end;
-    }
-    if( sqlite3ExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){
+    if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pEList->a[i].pExpr,
+                                    1, &isAgg) ){
       goto select_end;
     }
   }
-  if( pWhere ){
-    if( sqlite3ExprResolveIds(pParse, pTabList, pEList, pWhere) ){
-      goto select_end;
-    }
-    if( sqlite3ExprCheck(pParse, pWhere, 0, 0) ){
-      goto select_end;
-    }
+  if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList, pWhere, 0, 0) ){
+    goto select_end;
   }
   if( pHaving ){
     if( pGroupBy==0 ){
       sqlite3ErrorMsg(pParse, "a GROUP BY clause is required before HAVING");
       goto select_end;
     }
-    if( sqlite3ExprResolveIds(pParse, pTabList, pEList, pHaving) ){
-      goto select_end;
-    }
-    if( sqlite3ExprCheck(pParse, pHaving, 1, &isAgg) ){
+    if( sqlite3ExprResolveAndCheck(pParse, pTabList, pEList,pHaving,1,&isAgg) ){
       goto select_end;
     }
   }
-  if( pOrderBy ){
-    for(i=0; i<pOrderBy->nExpr; i++){
-      int iCol;
-      Expr *pE = pOrderBy->a[i].pExpr;
-      if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){
-        sqlite3ExprDelete(pE);
-        pE = pOrderBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
-      }
-      if( sqlite3ExprResolveIds(pParse, pTabList, pEList, pE) ){
-        goto select_end;
-      }
-      if( sqlite3ExprCheck(pParse, pE, isAgg, 0) ){
-        goto select_end;
-      }
-      if( sqlite3ExprIsConstant(pE) ){
-        if( sqlite3ExprIsInteger(pE, &iCol)==0 ){
-          sqlite3ErrorMsg(pParse,
-             "ORDER BY terms must not be non-integer constants");
-          goto select_end;
-        }else if( iCol<=0 || iCol>pEList->nExpr ){
-          sqlite3ErrorMsg(pParse, 
-             "ORDER BY column number %d out of range - should be "
-             "between 1 and %d", iCol, pEList->nExpr);
-          goto select_end;
-        }
-      }
-    }
-  }
-  if( pGroupBy ){
-    for(i=0; i<pGroupBy->nExpr; i++){
-      int iCol;
-      Expr *pE = pGroupBy->a[i].pExpr;
-      if( sqlite3ExprIsInteger(pE, &iCol) && iCol>0 && iCol<=pEList->nExpr ){
-        sqlite3ExprDelete(pE);
-        pE = pGroupBy->a[i].pExpr = sqlite3ExprDup(pEList->a[iCol-1].pExpr);
-      }
-      if( sqlite3ExprResolveIds(pParse, pTabList, pEList, pE) ){
-        goto select_end;
-      }
-      if( sqlite3ExprCheck(pParse, pE, isAgg, 0) ){
-        goto select_end;
-      }
-      if( sqlite3ExprIsConstant(pE) ){
-        if( sqlite3ExprIsInteger(pE, &iCol)==0 ){
-          sqlite3ErrorMsg(pParse,
-            "GROUP BY terms must not be non-integer constants");
-          goto select_end;
-        }else if( iCol<=0 || iCol>pEList->nExpr ){
-          sqlite3ErrorMsg(pParse,
-             "GROUP BY column number %d out of range - should be "
-             "between 1 and %d", iCol, pEList->nExpr);
-          goto select_end;
-        }
-      }
-    }
+  if( processOrderGroupBy(pParse, pOrderBy, pTabList, pEList, isAgg, "ORDER")
+   || processOrderGroupBy(pParse, pGroupBy, pTabList, pEList, isAgg, "GROUP")
+  ){
+    goto select_end;
   }
 
   /* Begin generating code.
index 5ae24c4b139802bc1f6733875ebad53cade92fb1..3881dfa4358670c47f265235f33feaf794d51452 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.315 2004/08/08 20:22:18 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.316 2004/08/21 17:54:45 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -888,8 +888,6 @@ struct WhereInfo {
   int iContinue;       /* Jump here to continue with next record */
   int iBreak;          /* Jump here to break out of the loop */
   int nLevel;          /* Number of nested loop */
-  int savedNTab;       /* Value of pParse->nTab before WhereBegin() */
-  int peakNTab;        /* Value of pParse->nTab after WhereBegin() */
   WhereLevel a[1];     /* Information about each nest loop in the WHERE */
 };
 
@@ -1278,6 +1276,7 @@ int sqlite3ExprCheck(Parse*, Expr*, int, int*);
 int sqlite3ExprCompare(Expr*, Expr*);
 int sqliteFuncId(Token*);
 int sqlite3ExprResolveIds(Parse*, SrcList*, ExprList*, Expr*);
+int sqlite3ExprResolveAndCheck(Parse*,SrcList*,ExprList*,Expr*,int,int*);
 int sqlite3ExprAnalyzeAggregates(Parse*, Expr*);
 Vdbe *sqlite3GetVdbe(Parse*);
 void sqlite3Randomness(int, void*);
@@ -1294,7 +1293,7 @@ void sqlite3GenerateRowIndexDelete(sqlite*, Vdbe*, Table*, int, char*);
 void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
 void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
 void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int);
-int sqlite3OpenTableAndIndices(Parse*, Table*, int);
+void sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
 void sqlite3BeginWriteOperation(Parse*, int, int);
 void sqlite3EndWriteOperation(Parse*);
 Expr *sqlite3ExprDup(Expr*);
index 49bd0768cd21afe1b9c3c9a7a452367c55ded10c..df8e5fb4d7087496bcc3624b2982945f70dfd48a 100644 (file)
@@ -647,8 +647,6 @@ static int codeTriggerProgram(
   int orconf;
 
   while( pTriggerStep ){
-    int saveNTab = pParse->nTab;
     orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
     pParse->trigStack->orconf = orconf;
     switch( pTriggerStep->op ){
@@ -696,7 +694,6 @@ static int codeTriggerProgram(
       default:
         assert(0);
     } 
-    pParse->nTab = saveNTab;
     pTriggerStep = pTriggerStep->pNext;
   }
 
index 59a373aab604e347903ced7989baaf9dc5ac1f6e..e57537d5b2bbefe94d73bd1461785ce5a2b17485 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.85 2004/06/21 06:50:29 danielk1977 Exp $
+** $Id: update.c,v 1.86 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -111,10 +111,8 @@ void sqlite3Update(
   */
   chngRecno = 0;
   for(i=0; i<pChanges->nExpr; i++){
-    if( sqlite3ExprResolveIds(pParse, pTabList, 0, pChanges->a[i].pExpr) ){
-      goto update_cleanup;
-    }
-    if( sqlite3ExprCheck(pParse, pChanges->a[i].pExpr, 0, 0) ){
+    if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0,
+             pChanges->a[i].pExpr, 0, 0) ){
       goto update_cleanup;
     }
     for(j=0; j<pTab->nCol; j++){
@@ -190,13 +188,8 @@ void sqlite3Update(
   /* Resolve the column names in all the expressions in the
   ** WHERE clause.
   */
-  if( pWhere ){
-    if( sqlite3ExprResolveIds(pParse, pTabList, 0, pWhere) ){
-      goto update_cleanup;
-    }
-    if( sqlite3ExprCheck(pParse, pWhere, 0, 0) ){
-      goto update_cleanup;
-    }
+  if( sqlite3ExprResolveAndCheck(pParse, pTabList, 0, pWhere, 0, 0) ){
+    goto update_cleanup;
   }
 
   /* Start the view context
@@ -412,7 +405,6 @@ void sqlite3Update(
           sqlite3VdbeAddOp(v, OP_Close, iCur+i+1, 0);
       }
       sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
-      pParse->nTab = iCur;
     }
     if( sqlite3CodeRowTrigger(pParse, TK_UPDATE, pChanges, TK_AFTER, pTab, 
           newIdx, oldIdx, onError, addr) ){
@@ -435,7 +427,6 @@ void sqlite3Update(
       }
     }
     sqlite3VdbeAddOp(v, OP_Close, iCur, 0);
-    pParse->nTab = iCur;
   }else{
     sqlite3VdbeAddOp(v, OP_Close, newIdx, 0);
     sqlite3VdbeAddOp(v, OP_Close, oldIdx, 0);
index 12c8eadfcefe9b99a61bf9bcb5e5ef8a2ab4aab7..5a92c9b07854e4c5419efdd1dbdbf14de617ccda 100644 (file)
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.408 2004/08/08 23:39:19 drh Exp $
+** $Id: vdbe.c,v 1.409 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -261,18 +261,8 @@ static Sorter *Merge(Sorter *pLeft, Sorter *pRight, KeyInfo *pKeyInfo){
 */
 static Cursor *allocateCursor(Vdbe *p, int iCur){
   Cursor *pCx;
-  if( iCur>=p->nCursor ){
-    int i;
-    p->apCsr = sqliteRealloc( p->apCsr, (iCur+1)*sizeof(Cursor*) );
-    if( p->apCsr==0 ){
-      p->nCursor = 0;
-      return 0;
-    }
-    for(i=p->nCursor; i<iCur; i++){
-      p->apCsr[i] = 0;
-    }
-    p->nCursor = iCur+1;
-  }else if( p->apCsr[iCur] ){
+  assert( iCur<p->nCursor );
+  if( p->apCsr[iCur] ){
     sqlite3VdbeFreeCursor(p->apCsr[iCur]);
   }
   p->apCsr[iCur] = pCx = sqliteMalloc( sizeof(Cursor) );
@@ -802,8 +792,7 @@ case OP_Variable: {
   assert( j>=0 && j<p->nVar );
 
   pTos++;
-  /* sqlite3VdbeMemCopyStatic(pTos, &p->apVar[j]); */
-  memcpy(pTos, &p->apVar[j], sizeof(*pTos)-NBFS);
+  memcpy(pTos, &p->aVar[j], sizeof(*pTos)-NBFS);
   pTos->xDel = 0;
   if( pTos->flags&(MEM_Str|MEM_Blob) ){
     pTos->flags &= ~(MEM_Dyn|MEM_Ephem|MEM_Short);
@@ -4056,7 +4045,7 @@ case OP_Sort: {
     p->pSort = pElem->pNext;
     pElem->pNext = 0;
     for(i=0; i<NSORT-1; i++){
-    if( apSorter[i]==0 ){
+      if( apSorter[i]==0 ){
         apSorter[i] = pElem;
         break;
       }else{
@@ -4123,49 +4112,24 @@ case OP_MemStore: {
   int i = pOp->p1;
   Mem *pMem;
   assert( pTos>=p->aStack );
-  if( i>=p->nMem ){
-    int nOld = p->nMem;
-    Mem *aMem;
-    p->nMem = i + 5;
-    aMem = sqliteRealloc(p->aMem, p->nMem*sizeof(p->aMem[0]));
-    if( aMem==0 ) goto no_mem;
-    if( aMem!=p->aMem ){
-      int j;
-      for(j=0; j<nOld; j++){
-        if( aMem[j].flags & MEM_Short ){
-          aMem[j].z = aMem[j].zShort;
-        }
-      }
-    }
-    p->aMem = aMem;
-    if( nOld<p->nMem ){
-      memset(&p->aMem[nOld], 0, sizeof(p->aMem[0])*(p->nMem-nOld));
-    }
-  }
+  assert( i<p->nMem );
   Deephemeralize(pTos);
   pMem = &p->aMem[i];
   Release(pMem);
   *pMem = *pTos;
-  if( pMem->flags & MEM_Dyn ){
-    if( pOp->p2 ){
-      pTos->flags = MEM_Null;
-    }else{
-      pMem->z = sqliteMallocRaw( pMem->n+2 );
-      if( pMem->z==0 ) goto no_mem;
-      memcpy(pMem->z, pTos->z, pMem->n);
-      memcpy(&pMem->z[pMem->n], "\000", 2);
-      pMem->flags |= MEM_Term;
-    }
-  }else if( pMem->flags & MEM_Short ){
+  pTos->flags = MEM_Null;
+  if( pMem->flags & MEM_Short ){
     pMem->z = pMem->zShort;
   }
+  pTos--;
+
+  /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will
+  ** restore the top of the stack to its original value.
+  */
   if( pOp->p2 ){
-    Release(pTos);
-    pTos--;
+    break;
   }
-  break;
 }
-
 /* Opcode: MemLoad P1 * *
 **
 ** Push a copy of the value in memory location P1 onto the stack.
@@ -4338,15 +4302,12 @@ case OP_AggFocus: {
   if( res==0 ){
     rc = sqlite3BtreeData(p->agg.pCsr, 0, sizeof(AggElem*),
         (char *)&p->agg.pCurrent);
-    if( rc!=SQLITE_OK ){
-      goto abort_due_to_error;
-    }
     pc = pOp->p2 - 1;
   }else{
     rc = AggInsert(&p->agg, zKey, nKey);
-    if( rc!=SQLITE_OK ){
-      goto abort_due_to_error;
-    }
+  }
+  if( rc!=SQLITE_OK ){
+    goto abort_due_to_error;
   }
   Release(pTos);
   pTos--;
@@ -4371,9 +4332,8 @@ case OP_AggSet: {
   pMem = &pFocus->aMem[i];
   Release(pMem);
   *pMem = *pTos;
-  if( pMem->flags & MEM_Dyn ){
-    pTos->flags = MEM_Null;
-  }else if( pMem->flags & MEM_Short ){
+  pTos->flags = MEM_Null;
+  if( pMem->flags & MEM_Short ){
     pMem->z = pMem->zShort;
   }
   pTos--;
@@ -4422,23 +4382,23 @@ case OP_AggGet: {
 */
 case OP_AggNext: {
   int res;
+  assert( rc==SQLITE_OK );
   CHECK_FOR_INTERRUPT;
   if( p->agg.searching==0 ){
     p->agg.searching = 1;
     if( p->agg.pCsr ){
       rc = sqlite3BtreeFirst(p->agg.pCsr, &res);
-      if( rc!=SQLITE_OK ) goto abort_due_to_error;
     }else{
       res = 0;
     }
   }else{
     if( p->agg.pCsr ){
       rc = sqlite3BtreeNext(p->agg.pCsr, &res);
-      if( rc!=SQLITE_OK ) goto abort_due_to_error;
     }else{
       res = 1;
     }
   }
+  if( rc!=SQLITE_OK ) goto abort_due_to_error;
   if( res!=0 ){
     pc = pOp->p2 - 1;
   }else{
@@ -4453,24 +4413,23 @@ case OP_AggNext: {
     }
     aMem = p->agg.pCurrent->aMem;
     for(i=0; i<p->agg.nMem; i++){
-      int freeCtx;
-      if( p->agg.apFunc[i]==0 ) continue;
-      if( p->agg.apFunc[i]->xFinalize==0 ) continue;
+      FuncDef *pFunc = p->agg.apFunc[i];
+      Mem *pMem = &aMem[i];
+      if( pFunc==0 || pFunc->xFinalize==0 ) continue;
       ctx.s.flags = MEM_Null;
-      ctx.s.z = aMem[i].zShort;
-      ctx.pAgg = (void*)aMem[i].z;
-      ctx.cnt = aMem[i].i;
+      ctx.s.z = pMem->zShort;
+      ctx.pAgg = (void*)pMem->z;
+      ctx.cnt = pMem->i;
       ctx.isStep = 0;
-      ctx.pFunc = p->agg.apFunc[i];
-      (*p->agg.apFunc[i]->xFinalize)(&ctx);
-      aMem[i].z = ctx.pAgg;
-      freeCtx = aMem[i].z && aMem[i].z!=aMem[i].zShort;
-      if( freeCtx ){
-        sqliteFree( aMem[i].z );
+      ctx.pFunc = pFunc;
+      pFunc->xFinalize(&ctx);
+      pMem->z = ctx.pAgg;
+      if( pMem->z && pMem->z!=pMem->zShort ){
+        sqliteFree( pMem->z );
       }
-      aMem[i] = ctx.s;
-      if( aMem[i].flags & MEM_Short ){
-        aMem[i].z = aMem[i].zShort;
+      *pMem = ctx.s;
+      if( pMem->flags & MEM_Short ){
+        pMem->z = pMem->zShort;
       }
     }
   }
index 6c11f22873f7522619c18506f884b07612cddedb..6e7d11c3ddb21c44185b42073520b4474f9c06db 100644 (file)
@@ -15,7 +15,7 @@
 ** or VDBE.  The VDBE implements an abstract machine that runs a
 ** simple program to access and modify the underlying database.
 **
-** $Id: vdbe.h,v 1.89 2004/06/27 21:31:40 drh Exp $
+** $Id: vdbe.h,v 1.90 2004/08/21 17:54:45 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -110,7 +110,7 @@ int sqlite3VdbeFindOp(Vdbe*, int, int, int);
 VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
 int sqlite3VdbeMakeLabel(Vdbe*);
 void sqlite3VdbeDelete(Vdbe*);
-void sqlite3VdbeMakeReady(Vdbe*,int,int);
+void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int);
 int sqlite3VdbeFinalize(Vdbe*);
 void sqlite3VdbeResolveLabel(Vdbe*, int);
 int sqlite3VdbeCurrentAddr(Vdbe*);
index c010b572c42d01f74e961a6e322883b79204a00a..af6667a9f1290d1631bc687f8e244966f2c094a0 100644 (file)
@@ -311,15 +311,10 @@ struct Vdbe {
   int nCursor;        /* Number of slots in apCsr[] */
   Cursor **apCsr;     /* One element of this array for each open cursor */
   Sorter *pSort;      /* A linked list of objects to be sorted */
-  FILE *pFile;        /* At most one open file handler */
-  int nField;         /* Number of file fields */
-  char **azField;     /* Data for each file field */
-  int nVar;           /* Number of entries in apVar[] */
-  Mem *apVar;         /* Values for the OP_Variable opcode. */
+  int nVar;           /* Number of entries in aVar[] */
+  Mem *aVar;          /* Values for the OP_Variable opcode. */
   char **azVar;       /* Name of variables */
   int okVar;          /* True if azVar[] has been initialized */
-  char *zLine;            /* A single line from the input file */
-  int nLineAlloc;         /* Number of spaces allocated for zLine */
   int magic;              /* Magic number for sanity checking */
   int nMem;               /* Number of memory locations currently allocated */
   Mem *aMem;              /* The memory locations */
index 2bc31bd23bb30413c0aedb534a7bf8ba1f1f4e98..b955190aec958330b34e1b4481af8064dcca9884 100644 (file)
@@ -414,7 +414,7 @@ static int vdbeUnbind(Vdbe *p, int i){
     return SQLITE_RANGE;
   }
   i--;
-  pVar = &p->apVar[i];
+  pVar = &p->aVar[i];
   sqlite3VdbeMemRelease(pVar);
   pVar->flags = MEM_Null;
   sqlite3Error(p->db, SQLITE_OK, 0);
@@ -439,7 +439,7 @@ int sqlite3_bind_blob(
   if( rc || zData==0 ){
     return rc;
   }
-  pVar = &p->apVar[i-1];
+  pVar = &p->aVar[i-1];
   rc = sqlite3VdbeMemSetStr(pVar, zData, nData, 0, xDel);
   return rc;
 }
@@ -448,7 +448,7 @@ int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
   Vdbe *p = (Vdbe *)pStmt;
   rc = vdbeUnbind(p, i);
   if( rc==SQLITE_OK ){
-    sqlite3VdbeMemSetDouble(&p->apVar[i-1], rValue);
+    sqlite3VdbeMemSetDouble(&p->aVar[i-1], rValue);
   }
   return rc;
 }
@@ -460,7 +460,7 @@ int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
   Vdbe *p = (Vdbe *)pStmt;
   rc = vdbeUnbind(p, i);
   if( rc==SQLITE_OK ){
-    sqlite3VdbeMemSetInt64(&p->apVar[i-1], iValue);
+    sqlite3VdbeMemSetInt64(&p->aVar[i-1], iValue);
   }
   return rc;
 }
@@ -482,7 +482,7 @@ int sqlite3_bind_text(
   if( rc || zData==0 ){
     return rc;
   }
-  pVar = &p->apVar[i-1];
+  pVar = &p->aVar[i-1];
   rc = sqlite3VdbeMemSetStr(pVar, zData, nData, SQLITE_UTF8, xDel);
   if( rc ){
     return rc;
@@ -505,7 +505,7 @@ int sqlite3_bind_text16(
   if( rc || zData==0 ){
     return rc;
   }
-  pVar = &p->apVar[i-1];
+  pVar = &p->aVar[i-1];
 
   rc = sqlite3VdbeMemSetStr(pVar, zData, nData, SQLITE_UTF16NATIVE, xDel);
   if( rc ){
index 9e72062053803a23e1a0b1ea7f777149658b5ca6..1734677c31a3149c251be218f8547b4a596d9f5d 100644 (file)
@@ -547,6 +547,8 @@ void sqlite3VdbePrintSql(Vdbe *p){
 void sqlite3VdbeMakeReady(
   Vdbe *p,                       /* The VDBE */
   int nVar,                      /* Number of '?' see in the SQL statement */
+  int nMem,                      /* Number of memory cells to allocate */
+  int nCursor,                   /* Number of cursors to allocate */
   int isExplain                  /* True if the EXPLAIN keywords is present */
 ){
   int n;
@@ -568,20 +570,31 @@ void sqlite3VdbeMakeReady(
   ** Allocation all the stack space we will ever need.
   */
   if( p->aStack==0 ){
-    p->nVar = nVar;
     assert( nVar>=0 );
     n = isExplain ? 10 : p->nOp;
     p->aStack = sqliteMalloc(
       n*(sizeof(p->aStack[0])+sizeof(Mem*))          /* aStack, apArg */
-      + p->nVar*sizeof(Mem)                          /* apVar */
-      + p->nVar*sizeof(char*)                        /* apVarName */
+      + nVar*sizeof(Mem)                             /* aVar */
+      + nVar*sizeof(char*)                           /* azVar */
+      + nMem*sizeof(Mem)                             /* aMem */
+      + nCursor*sizeof(Cursor*)                      /* apCsr */
     );
-    p->apArg = (Mem **)&p->aStack[n];
-    p->apVar = (Mem *)&p->apArg[n];
-    p->azVar = (char**)&p->apVar[p->nVar];
-    p->okVar = 0;
-    for(n=0; n<p->nVar; n++){
-      p->apVar[n].flags = MEM_Null;
+    if( !sqlite3_malloc_failed ){
+      p->apArg = (Mem **)&p->aStack[n];
+      p->aVar = (Mem *)&p->apArg[n];
+      p->azVar = (char**)&p->aVar[nVar];
+      p->okVar = 0;
+      p->nVar = nVar;
+      p->aMem = (Mem*)&p->azVar[nVar];
+      p->nMem = nMem;
+      p->apCsr = (Cursor**)&p->aMem[nMem];
+      p->nCursor = nCursor;
+      for(n=0; n<nVar; n++){
+        p->aVar[n].flags = MEM_Null;
+      }
+      for(n=0; n<nMem; n++){
+        p->aMem[n].flags = MEM_Null;
+      }
     }
   }
 
@@ -800,12 +813,11 @@ void sqlite3VdbeFreeCursor(Cursor *pCx){
 */
 static void closeAllCursors(Vdbe *p){
   int i;
+  if( p->apCsr==0 ) return;
   for(i=0; i<p->nCursor; i++){
     sqlite3VdbeFreeCursor(p->apCsr[i]);
+    p->apCsr[i] = 0;
   }
-  sqliteFree(p->apCsr);
-  p->apCsr = 0;
-  p->nCursor = 0;
 }
 
 /*
@@ -826,33 +838,14 @@ static void Cleanup(Vdbe *p){
     p->pTos = pTos;
   }
   closeAllCursors(p);
-  if( p->aMem ){
-    for(i=0; i<p->nMem; i++){
-      sqlite3VdbeMemRelease(&p->aMem[i]);
-    }
+  for(i=0; i<p->nMem; i++){
+    sqlite3VdbeMemRelease(&p->aMem[i]);
   }
-  sqliteFree(p->aMem);
-  p->aMem = 0;
-  p->nMem = 0;
   if( p->pList ){
     sqlite3VdbeKeylistFree(p->pList);
     p->pList = 0;
   }
   sqlite3VdbeSorterReset(p);
-  if( p->pFile ){
-    if( p->pFile!=stdin ) fclose(p->pFile);
-    p->pFile = 0;
-  }
-  if( p->azField ){
-    sqliteFree(p->azField);
-    p->azField = 0;
-  }
-  p->nField = 0;
-  if( p->zLine ){
-    sqliteFree(p->zLine);
-    p->zLine = 0;
-  }
-  p->nLineAlloc = 0;
   sqlite3VdbeAggReset(0, &p->agg, 0);
   if( p->keylistStack ){
     int ii;
@@ -1360,7 +1353,7 @@ void sqlite3VdbeDelete(Vdbe *p){
     }
   }
   for(i=0; i<p->nVar; i++){
-    sqlite3VdbeMemRelease(&p->apVar[i]);
+    sqlite3VdbeMemRelease(&p->aVar[i]);
   }
   sqliteFree(p->aOp);
   sqliteFree(p->aLabel);
index 0145873bc2f64c12658a8864f11a4c938594a2cb..49091d4760dfd2460681a60f2cadcd978deea653 100644 (file)
@@ -12,7 +12,7 @@
 ** This module contains C code that generates VDBE code used to process
 ** the WHERE clause of SQL statements.
 **
-** $Id: where.c,v 1.111 2004/07/20 18:23:15 drh Exp $
+** $Id: where.c,v 1.112 2004/08/21 17:54:45 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -484,7 +484,6 @@ WhereInfo *sqlite3WhereBegin(
   }
   pWInfo->pParse = pParse;
   pWInfo->pTabList = pTabList;
-  pWInfo->peakNTab = pWInfo->savedNTab = pParse->nTab;
   pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
 
   /* Special case: a WHERE clause that is constant.  Evaluate the
@@ -686,7 +685,6 @@ WhereInfo *sqlite3WhereBegin(
     loopMask |= mask;
     if( pBestIdx ){
       pWInfo->a[i].iCur = pParse->nTab++;
-      pWInfo->peakNTab = pParse->nTab;
     }
   }
 
@@ -721,7 +719,6 @@ WhereInfo *sqlite3WhereBegin(
        if( pIdx==0 ){
          pWInfo->a[0].pIdx = pSortIdx;
          pWInfo->a[0].iCur = pParse->nTab++;
-         pWInfo->peakNTab = pParse->nTab;
        }
        pWInfo->a[0].bRev = bRev;
        *ppOrderBy = 0;
@@ -1210,11 +1207,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
       sqlite3VdbeAddOp(v, OP_Close, pLevel->iCur, 0);
     }
   }
-#if 0  /* Never reuse a cursor */
-  if( pWInfo->pParse->nTab==pWInfo->peakNTab ){
-    pWInfo->pParse->nTab = pWInfo->savedNTab;
-  }
-#endif
   sqliteFree(pWInfo);
   return;
 }
index 963d628d97a2c186da4ea28449556f8a964d1518..1522a1a8206b100a9dd56f43a09b965b7f8631c1 100644 (file)
@@ -20,7 +20,7 @@
 # The special crash-test module with its os_test.c backend only works
 # on Unix.
 #
-# $Id: crash.test,v 1.7 2004/06/28 04:52:31 danielk1977 Exp $
+# $Id: crash.test,v 1.8 2004/08/21 17:54:46 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -167,7 +167,7 @@ do_test crash-2.1 {
   execsql { COMMIT }
   set ::sig [signature]
   execsql { SELECT sum(a), sum(b), sum(c) from abc }
-} {499500 999000 1498500}
+} {499500.0 999000.0 1498500.0}
 do_test crash-2.2 {
   expr [file size test.db] / 1024
 } {19}
@@ -273,6 +273,7 @@ for {set i 1} {$i<$repeats} {incr i} {
   } $sig2
 } 
 set i 0
+set i 55
 while {[incr i]} {
   set sig [signature]
   set sig2 [signature2]