]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Continuing work toward converting the VM into a register machine. (CVS 4707)
authordrh <drh@noemail.net>
Sat, 12 Jan 2008 12:48:07 +0000 (12:48 +0000)
committerdrh <drh@noemail.net>
Sat, 12 Jan 2008 12:48:07 +0000 (12:48 +0000)
FossilOrigin-Name: a6dddebcc5ccbbf3009c9d06163a8b59036331de

13 files changed:
manifest
manifest.uuid
src/analyze.c
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/select.c
src/sqliteInt.h
src/vdbe.c
src/vtab.c
test/select4.test
test/select8.test [new file with mode: 0644]

index a36016af58d8e501fc9896d919e89af21a98c22c..91864257a6b535aefba417230c07bfd7c824ea65 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Do\sexplicit\srange\stests\sbefore\sattempting\sto\sconvert\sa\s64-bit\sfloat\ninto\sa\s64-bit\sinteger.\s\sSome\ssystems\s(windows)\sseem\sto\sthrow\sexceptions\nif\sthe\sconversion\sis\sout\sof\srange.\s\sTicket\s#2880.\s(CVS\s4706)
-D 2008-01-11T15:27:03
+C Continuing\swork\stoward\sconverting\sthe\sVM\sinto\sa\sregister\smachine.\s(CVS\s4707)
+D 2008-01-12T12:48:08
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -79,24 +79,24 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
 F sqlite3.def a96c1d0d39362b763d2ddba220a32da41a15c4b4
 F sqlite3.pc.in abed4664817e1cd500f2276142c71958087c16bc
 F src/alter.c 5a54f58d9481ac14c4e58b702f3f8758dee84d04
-F src/analyze.c 52cbc3577c962975445d3e1341cba046f228d21e
+F src/analyze.c 5aa93f191b365ea308795f62ca6f2e8caa9de3e1
 F src/attach.c 61f0cae7b1a0e7c3b5f5286be5dc1a7c4d7112d2
 F src/auth.c c8b2ab5c8bad4bd90ed7c294694f48269162c627
 F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
 F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef
 F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb
 F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76
-F src/build.c e5bb1ddf630d4fbd042bf6a09168fe2feb4f7549
+F src/build.c 353cce0f4e773b0889d94663dca6dc99598d6b3d
 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
-F src/delete.c 44eac0a8a1bad1e62ee64e59e07a5a97a838bd0f
+F src/delete.c 00e536847b8eedc5d35f89f7f38a8a7c1d2a22f9
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c 560fbd4aff7c65e716e0310f85f044141abd9523
+F src/expr.c 68bcc07517c763cc7601be45d60084bc11ee0212
 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
 F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 405cf0550252cdd3ba5b14ce1545571c82e35250
+F src/insert.c a19d9f51b611943386fcff714e3a0ffb137e463b
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
@@ -131,12 +131,12 @@ F src/pragma.c 1d3d9deefcf325e14a99b94f9f506f1a90a9232b
 F src/prepare.c c31a879d6795f4765fd0b113675c6debbc96b7fd
 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
-F src/select.c ff00897172bad962c7f775f0a1daa19e2a3ed80a
+F src/select.c 9e3c65ca3d2508b585b6786dbcbe6cd65560b013
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
 F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h ba917f5ed26ab1b47d3814d624e36a73dfe4c5bd
+F src/sqliteInt.h b143c53760aeb4feeb4eaf8cb10eb26ad5b6c89e
 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
@@ -168,7 +168,7 @@ F src/update.c aad823f97a930e6982264299863837d4c6107d3b
 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
-F src/vdbe.c 2a62b69e8344f28438ba0a007582be93b33b53ca
+F src/vdbe.c 20bd088657280d75b630d299c59cdb3c6a5c9b9e
 F src/vdbe.h a9166e1601f5b74c20516a74182773a20baee43e
 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
 F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
@@ -176,7 +176,7 @@ F src/vdbeaux.c db33a4c2477546da05e772352be43896d24d51d5
 F src/vdbeblob.c e386d49d8354aa5a58f0a7f2794303442c149120
 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
 F src/vdbemem.c a86119b5ccc41ab8653e4746f83d591ff0ae892e
-F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
+F src/vtab.c 7f206d148f6e76f427f008f589610c72a4b9336c
 F src/where.c 9705df3c2b78ea8e02a768be8ac5d3f7a2902f1e
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
@@ -417,10 +417,11 @@ F test/schema2.test 35e1c9696443d6694c8980c411497c2b5190d32e
 F test/select1.test 871df931cbbc0e78170605628e8b5fc60765e265
 F test/select2.test f3c2678c3a9f3cf08ec4988a3845bda64be6d9e3
 F test/select3.test 7f99c0d4067064e0865479a56faa7aaa29b9041a
-F test/select4.test 69015a6c02c3d8efed01f15e5d025fb4e5256183
+F test/select4.test 491193f50799e7fdb375ef04a1a8f40393dd7cfe
 F test/select5.test 0b47058d3e916c1fc9fe81f44b438e02bade21ce
 F test/select6.test 399f14b9ba37b768afe5d2cd8c12e4f340a69db8
 F test/select7.test 7906735805cfbee4dddc0bed4c14e68d7f5f9c5f
+F test/select8.test 391de11bdd52339c30580dabbbbe97e3e9a3c79d
 F test/server1.test f5b790d4c0498179151ca8a7715a65a7802c859c
 F test/shared.test 9a1e81629efaebaad2247e9e81aa33570fba8f13
 F test/shared2.test 0ee9de8964d70e451936a48c41cb161d9134ccf4
@@ -605,7 +606,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 6de0ee49073c7a47d5e10495b569b33df76d1448
-R 72b005345d91bd390788cc14572cdea6
+P 4744257d3cd2dd96485fde6d9f60542714383421
+R 9fded3f0e818ece501c0ececcbd26a94
 U drh
-Z f60ae65829aa8eb88bba7196814bec78
+Z fe475f28d0df336b5a859493e9293538
index da894ad9cbcff0423b664bf2b462e551aa6d163d..992dde0d9b04b13fdda207923ddc2fca1a732fac 100644 (file)
@@ -1 +1 @@
-4744257d3cd2dd96485fde6d9f60542714383421
\ No newline at end of file
+a6dddebcc5ccbbf3009c9d06163a8b59036331de
\ No newline at end of file
index d1873f0f50161f44c3d7ef6c599990b69e3ba846..a1bc2ee3c0d5726696751d922836cb2ee25d3782 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code associated with the ANALYZE command.
 **
-** @(#) $Id: analyze.c,v 1.37 2008/01/10 23:50:11 drh Exp $
+** @(#) $Id: analyze.c,v 1.38 2008/01/12 12:48:08 drh Exp $
 */
 #ifndef SQLITE_OMIT_ANALYZE
 #include "sqliteInt.h"
@@ -33,6 +33,7 @@ static void openStatTable(
   sqlite3 *db = pParse->db;
   Db *pDb;
   int iRootPage;
+  int createStat1 = 0;
   Table *pStat;
   Vdbe *v = sqlite3GetVdbe(pParse);
 
@@ -43,13 +44,14 @@ static void openStatTable(
   if( (pStat = sqlite3FindTable(db, "sqlite_stat1", pDb->zName))==0 ){
     /* The sqlite_stat1 tables does not exist.  Create it.  
     ** Note that a side-effect of the CREATE TABLE statement is to leave
-    ** the rootpage of the new table on the top of the stack.  This is
+    ** the rootpage of the new table in register pParse->regRoot.  This is
     ** important because the OpenWrite opcode below will be needing it. */
     sqlite3NestedParse(pParse,
       "CREATE TABLE %Q.sqlite_stat1(tbl,idx,stat)",
       pDb->zName
     );
-    iRootPage = 0;  /* Cause rootpage to be taken from top of stack */
+    iRootPage = pParse->regRoot;
+    createStat1 = 1;  /* Cause rootpage to be taken from top of stack */
   }else if( zWhere ){
     /* The sqlite_stat1 table exists.  Delete all entries associated with
     ** the table zWhere. */
@@ -69,13 +71,11 @@ static void openStatTable(
   ** If this vdbe did create the sqlite_stat1 table, then it must have 
   ** already obtained a schema-lock, making the write-lock redundant.
   */
-  if( iRootPage>0 ){
+  if( !createStat1 ){
     sqlite3TableLock(pParse, iDb, iRootPage, 1, "sqlite_stat1");
   }
   sqlite3VdbeAddOp3(v, OP_OpenWrite, iStatCur, iRootPage, iDb);
-  if( iRootPage==0 ){
-    sqlite3VdbeChangeP5(v, 1);
-  }
+  sqlite3VdbeChangeP5(v, createStat1);
   sqlite3VdbeAddOp2(v, OP_SetNumColumns, iStatCur, 3);
 }
 
index b11e203756758374ac7dd6ab64487284dfcb85ca..12a330df6a80eca983f74472c59c539b223a771f 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.463 2008/01/10 23:50:11 drh Exp $
+** $Id: build.c,v 1.464 2008/01/12 12:48:08 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -838,8 +838,9 @@ void sqlite3StartTable(
   ** now.
   */
   if( !db->init.busy && (v = sqlite3GetVdbe(pParse))!=0 ){
-    int lbl;
+    int j1;
     int fileFormat;
+    int reg1, reg2, reg3;
     sqlite3BeginWriteOperation(pParse, 0, iDb);
 
 #ifndef SQLITE_OMIT_VIRTUALTABLE
@@ -851,17 +852,19 @@ void sqlite3StartTable(
     /* If the file format and encoding in the database have not been set, 
     ** set them now.
     */
-    sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, 0, 1);   /* file_format */
+    reg1 = pParse->regRowid = ++pParse->nMem;
+    reg2 = pParse->regRoot = ++pParse->nMem;
+    reg3 = ++pParse->nMem;
+    sqlite3VdbeAddOp3(v, OP_ReadCookie, iDb, reg3, 1);   /* file_format */
     sqlite3VdbeUsesBtree(v, iDb);
-    lbl = sqlite3VdbeMakeLabel(v);
-    sqlite3VdbeAddOp2(v, OP_If, 0, lbl);
+    j1 = sqlite3VdbeAddOp1(v, OP_If, reg3);
     fileFormat = (db->flags & SQLITE_LegacyFileFmt)!=0 ?
                   1 : SQLITE_MAX_FILE_FORMAT;
-    sqlite3VdbeAddOp1(v, OP_Integer, fileFormat);
-    sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 1);
-    sqlite3VdbeAddOp1(v, OP_Integer, ENC(db));
-    sqlite3VdbeAddOp2(v, OP_SetCookie, iDb, 4);
-    sqlite3VdbeResolveLabel(v, lbl);
+    sqlite3VdbeAddOp2(v, OP_Integer, fileFormat, reg3);
+    sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 1, reg3);
+    sqlite3VdbeAddOp2(v, OP_Integer, ENC(db), reg3);
+    sqlite3VdbeAddOp3(v, OP_SetCookie, iDb, 4, reg3);
+    sqlite3VdbeJumpHere(v, j1);
 
     /* This just creates a place-holder record in the sqlite_master table.
     ** The record created does not contain anything yet.  It will be replaced
@@ -873,19 +876,18 @@ void sqlite3StartTable(
     */
 #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
     if( isView || isVirtual ){
-      sqlite3VdbeAddOp0(v, OP_Integer);
+      sqlite3VdbeAddOp2(v, OP_Integer, 0, reg2);
     }else
 #endif
     {
-      sqlite3VdbeAddOp1(v, OP_CreateTable, iDb);
+      sqlite3VdbeAddOp2(v, OP_CreateTable, iDb, reg2);
     }
     sqlite3OpenMasterTable(pParse, iDb);
-    sqlite3VdbeAddOp0(v, OP_NewRowid);
-    sqlite3VdbeAddOp0(v, OP_Copy);
-    sqlite3VdbeAddOp0(v, OP_Null);
-    sqlite3CodeInsert(pParse, 0, OPFLAG_APPEND);
+    sqlite3VdbeAddOp2(v, OP_NewRowid, 0, reg1);
+    sqlite3VdbeAddOp2(v, OP_Null, 0, reg3);
+    sqlite3VdbeAddOp3(v, OP_Insert, 0, reg3, reg1);
+    sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
     sqlite3VdbeAddOp0(v, OP_Close);
-    sqlite3VdbeAddOp1(v, OP_Pull, 1);
   }
 
   /* Normal (non-error) return. */
@@ -1494,8 +1496,7 @@ void sqlite3EndTable(
       SelectDest dest;
       Table *pSelTab;
 
-      sqlite3VdbeAddOp0(v, OP_Copy);
-      sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, 0, iDb);
+      sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, pParse->regRoot, iDb);
       sqlite3VdbeChangeP5(v, 1);
       pParse->nTab = 2;
       sqlite3SelectDestInit(&dest, SRT_Table, 1);
@@ -1531,13 +1532,15 @@ void sqlite3EndTable(
     */
     sqlite3NestedParse(pParse,
       "UPDATE %Q.%s "
-         "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#0, sql=%Q "
-       "WHERE rowid=#1",
+         "SET type='%s', name=%Q, tbl_name=%Q, rootpage=#%d, sql=%Q "
+       "WHERE rowid=#%d",
       db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
       zType,
       p->zName,
       p->zName,
-      zStmt
+      pParse->regRoot,
+      zStmt,
+      pParse->regRowid
     );
     sqlite3_free(zStmt);
     sqlite3ChangeCookie(db, v, iDb);
@@ -1835,20 +1838,22 @@ void sqlite3RootPageMoved(Db *pDb, int iFrom, int iTo){
 */ 
 static void destroyRootPage(Parse *pParse, int iTable, int iDb){
   Vdbe *v = sqlite3GetVdbe(pParse);
-  sqlite3VdbeAddOp3(v, OP_Destroy, iTable, 0, iDb);
+  int r1 = sqlite3GetTempReg(pParse);
+  sqlite3VdbeAddOp3(v, OP_Destroy, iTable, r1, iDb);
 #ifndef SQLITE_OMIT_AUTOVACUUM
-  /* OP_Destroy pushes an integer onto the stack. If this integer
+  /* OP_Destroy stores an in integer r1. If this integer
   ** is non-zero, then it is the root page number of a table moved to
   ** location iTable. The following code modifies the sqlite_master table to
   ** reflect this.
   **
-  ** The "#0" in the SQL is a special constant that means whatever value
+  ** The "#%d" in the SQL is a special constant that means whatever value
   ** is on the top of the stack.  See sqlite3RegisterExpr().
   */
   sqlite3NestedParse(pParse, 
-     "UPDATE %Q.%s SET rootpage=%d WHERE #0 AND rootpage=#0",
-     pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable);
+     "UPDATE %Q.%s SET rootpage=%d WHERE #%d AND rootpage=#%d",
+     pParse->db->aDb[iDb].zName, SCHEMA_TABLE(iDb), iTable, r1, r1);
 #endif
+  sqlite3ReleaseTempReg(pParse, r1);
 }
 
 /*
@@ -2649,8 +2654,7 @@ void sqlite3CreateIndex(
     /* Create the rootpage for the index
     */
     sqlite3BeginWriteOperation(pParse, 1, iDb);
-    sqlite3VdbeAddOp1(v, OP_CreateIndex, iDb);
-    sqlite3VdbeAddOp2(v, OP_Copy, 0, iMem);
+    sqlite3VdbeAddOp2(v, OP_CreateIndex, iDb, iMem);
 
     /* Gather the complete text of the CREATE INDEX statement into
     ** the zStmt variable
@@ -2670,13 +2674,13 @@ void sqlite3CreateIndex(
     /* Add an entry in sqlite_master for this index
     */
     sqlite3NestedParse(pParse, 
-        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#0,%Q);",
+        "INSERT INTO %Q.%s VALUES('index',%Q,%Q,#%d,%Q);",
         db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
         pIndex->zName,
         pTab->zName,
+        iMem,
         zStmt
     );
-    sqlite3VdbeAddOp1(v, OP_Pop, 1);
     sqlite3_free(zStmt);
 
     /* Fill the index with data and reparse the schema. Code an OP_Expire
index 18a16ed557e4302dae89310f3e9bb848e1a7e022..87436ae935119c18dc9014fd6d124ca5a0ae1fec 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.156 2008/01/10 23:50:11 drh Exp $
+** $Id: delete.c,v 1.157 2008/01/12 12:48:08 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -60,20 +60,6 @@ int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
   return 0;
 }
 
-/*
-** This function is a temporary measure required because OP_Insert now
-** reads the key and data to insert from memory cells.
-*/
-void sqlite3CodeInsert(Parse *p, int iCur, u8 flags){
-  int iData = ++p->nMem;
-  int iKey = ++p->nMem;
-  Vdbe *v = sqlite3GetVdbe(p);
-  sqlite3VdbeAddOp2(v, OP_Move, 0, iData);
-  sqlite3VdbeAddOp2(v, OP_Move, 0, iKey);
-  sqlite3VdbeAddOp3(v, OP_Insert, iCur, iData, iKey);
-  sqlite3VdbeChangeP5(v, flags);
-}
-
 /*
 ** Allocate nVal contiguous memory cells and return the index of the
 ** first. Also pop nVal elements from the stack and store them in the 
@@ -91,14 +77,6 @@ int sqlite3StackToReg(Parse *p, int nVal){
   }
   return iRet;
 }
-void sqlite3RegToStack(Parse *p, int iReg, int nVal){
-  int i;
-  Vdbe *v = sqlite3GetVdbe(p);
-  assert(v);
-  for(i=0; i<nVal; i++){
-    sqlite3VdbeAddOp2(v, OP_SCopy, iReg+i, 0);
-  }
-}
 
 /*
 ** Generate code that will open a table for reading.
index 88636411e6476fa924b271759cb4e7a07725ec45..2d333f74a3b4a90c31f69491539b01096127214a 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.342 2008/01/10 23:50:11 drh Exp $
+** $Id: expr.c,v 1.343 2008/01/12 12:48:08 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -289,9 +289,8 @@ Expr *sqlite3PExpr(
 
 /*
 ** When doing a nested parse, you can include terms in an expression
-** that look like this:   #0 #1 #2 ...  These terms refer to elements
-** on the stack.  "#0" means the top of the stack.
-** "#1" means the next down on the stack.  And so forth.
+** that look like this:   #1 #2 ...  These terms refer to registers
+** in the virtual machine.  #N is the N-th register.
 **
 ** This routine is called by the parser to deal with on of those terms.
 ** It immediately generates code to store the value in a memory location.
@@ -301,7 +300,6 @@ Expr *sqlite3PExpr(
 Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
   Vdbe *v = pParse->pVdbe;
   Expr *p;
-  int depth;
   if( pParse->nested==0 ){
     sqlite3ErrorMsg(pParse, "near \"%T\": syntax error", pToken);
     return sqlite3PExpr(pParse, TK_NULL, 0, 0, 0);
@@ -311,9 +309,7 @@ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
   if( p==0 ){
     return 0;  /* Malloc failed */
   }
-  depth = atoi((char*)&pToken->z[1]);
-  p->iTable = ++pParse->nMem;
-  sqlite3VdbeAddOp2(v, OP_Copy, -depth, p->iTable);
+  p->iTable = atoi((char*)&pToken->z[1]);
   return p;
 }
 
index 7577f46774e237cc5ea4a397fe1b53313b6a792c..024a3403f46e0e6f7a01348936415f95679ab912 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.222 2008/01/10 23:50:11 drh Exp $
+** $Id: insert.c,v 1.223 2008/01/12 12:48:08 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -519,13 +519,18 @@ void sqlite3Insert(
       /* Generate the subroutine that SELECT calls to process each row of
       ** the result.  Store the result in a temporary table
       */
+      int regRec, regRowid;
+
       srcTab = pParse->nTab++;
+      regRec = sqlite3GetTempReg(pParse);
+      regRowid = sqlite3GetTempReg(pParse);
       sqlite3VdbeResolveLabel(v, iInsertBlock);
-      sqlite3VdbeAddOp2(v, OP_RegMakeRec, regFromSelect, nColumn);
-      sqlite3VdbeAddOp1(v, OP_NewRowid, srcTab);
-      sqlite3VdbeAddOp2(v, OP_Pull, 1, 0);
-      sqlite3CodeInsert(pParse, srcTab, OPFLAG_APPEND);
+      sqlite3VdbeAddOp3(v, OP_RegMakeRec, regFromSelect, nColumn, regRec);
+      sqlite3VdbeAddOp2(v, OP_NewRowid, srcTab, regRowid);
+      sqlite3VdbeAddOp3(v, OP_Insert, srcTab, regRec, regRowid);
       sqlite3VdbeAddOp2(v, OP_Return, 0, 0);
+      sqlite3ReleaseTempReg(pParse, regRec);
+      sqlite3ReleaseTempReg(pParse, regRowid);
 
       /* The following code runs first because the GOTO at the very top
       ** of the program jumps to it.  Create the temporary table, then jump
@@ -663,7 +668,6 @@ void sqlite3Insert(
   }else if( pSelect ){
     sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop);
     sqlite3VdbeResolveLabel(v, iInsertBlock);
-    sqlite3RegToStack(pParse, regFromSelect, nColumn);
     sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
   }
 
@@ -770,7 +774,7 @@ void sqlite3Insert(
       if( useTempTable ){
         sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, regRowid);
       }else if( pSelect ){
-        sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), regRowid);
+        sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+keyColumn, regRowid);
       }else{
         VdbeOp *pOp;
         sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
@@ -835,7 +839,7 @@ void sqlite3Insert(
       }else if( useTempTable ){
         sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); 
       }else if( pSelect ){
-        sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn-j-1), iRegStore);
+        sqlite3VdbeAddOp2(v, OP_SCopy, regFromSelect+j, iRegStore);
       }else{
         sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
       }
@@ -899,7 +903,6 @@ void sqlite3Insert(
     sqlite3VdbeResolveLabel(v, iBreak);
     sqlite3VdbeAddOp2(v, OP_Close, srcTab, 0);
   }else if( pSelect ){
-    sqlite3VdbeAddOp2(v, OP_Pop, nColumn, 0);
     sqlite3VdbeAddOp2(v, OP_Return, 0, 0);
     sqlite3VdbeResolveLabel(v, iCleanup);
   }
@@ -1279,6 +1282,7 @@ void sqlite3CompleteInsertion(
   Index *pIdx;
   int pik_flags;
   int regData;
+  int regRec;
 
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
@@ -1289,14 +1293,12 @@ void sqlite3CompleteInsertion(
     sqlite3VdbeAddOp2(v, OP_IdxInsert, baseCur+i+1, aRegIdx[i]);
   }
   regData = regRowid + 1;
-  sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
-  sqlite3VdbeAddOp2(v, OP_RegMakeRec, regData, pTab->nCol);
+  regRec = sqlite3GetTempReg(pParse);
+  sqlite3VdbeAddOp3(v, OP_RegMakeRec, regData, pTab->nCol, regRec);
   sqlite3TableAffinityStr(v, pTab);
 #ifndef SQLITE_OMIT_TRIGGER
   if( newIdx>=0 ){
-    sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
-    sqlite3VdbeAddOp1(v, OP_SCopy, -1);
-    sqlite3CodeInsert(pParse, newIdx, 0);
+    sqlite3VdbeAddOp3(v, OP_Insert, newIdx, regRec, regRowid);
   }
 #endif
   if( pParse->nested ){
@@ -1308,10 +1310,11 @@ void sqlite3CompleteInsertion(
   if( appendBias ){
     pik_flags |= OPFLAG_APPEND;
   }
-  sqlite3CodeInsert(pParse, baseCur, pik_flags);
+  sqlite3VdbeAddOp3(v, OP_Insert, baseCur, regRec, regRowid);
   if( !pParse->nested ){
     sqlite3VdbeChangeP4(v, -1, pTab->zName, P4_STATIC);
   }
+  sqlite3VdbeChangeP5(v, pik_flags);
 }
 
 /*
@@ -1465,6 +1468,7 @@ static int xferOptimization(
   KeyInfo *pKey;                   /* Key information for an index */
   int regAutoinc;                  /* Memory register used by AUTOINC */
   int destHasUniqueIdx = 0;        /* True if pDest has a UNIQUE index */
+  int regData, regRowid;           /* Registers holding data and rowid */
 
   if( pSelect==0 ){
     return 0;   /* Must be of the form  INSERT INTO ... SELECT ... */
@@ -1612,22 +1616,24 @@ static int xferOptimization(
   }
   sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
   emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
+  regData = sqlite3GetTempReg(pParse);
+  regRowid = sqlite3GetTempReg(pParse);
   if( pDest->iPKey>=0 ){
-    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0);
-    sqlite3VdbeAddOp0(v, OP_Copy);
-    addr2 = sqlite3VdbeAddOp2(v, OP_NotExists, iDest, 0);
+    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
+    addr2 = sqlite3VdbeAddOp3(v, OP_NotExists, iDest, 0, regRowid);
     sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
                       "PRIMARY KEY must be unique", P4_STATIC);
     sqlite3VdbeJumpHere(v, addr2);
-    autoIncStep(pParse, regAutoinc, 0);
+    autoIncStep(pParse, regAutoinc, regRowid);
   }else if( pDest->pIndex==0 ){
-    addr1 = sqlite3VdbeAddOp1(v, OP_NewRowid, iDest);
+    addr1 = sqlite3VdbeAddOp2(v, OP_NewRowid, iDest, regRowid);
   }else{
-    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0);
+    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, regRowid);
     assert( pDest->autoInc==0 );
   }
-  sqlite3VdbeAddOp1(v, OP_RowData, iSrc);
-  sqlite3CodeInsert(pParse,iDest,OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
+  sqlite3VdbeAddOp2(v, OP_RowData, iSrc, regData);
+  sqlite3VdbeAddOp3(v, OP_Insert, iDest, regData, regRowid);
+  sqlite3VdbeChangeP5(v, OPFLAG_NCHANGE|OPFLAG_LASTROWID|OPFLAG_APPEND);
   sqlite3VdbeChangeP4(v, -1, pDest->zName, 0);
   sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1);
   autoIncEnd(pParse, iDbDest, pDest, regAutoinc);
@@ -1647,12 +1653,14 @@ static int xferOptimization(
                       (char*)pKey, P4_KEYINFO_HANDOFF);
     VdbeComment((v, "%s", pDestIdx->zName));
     addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
-    sqlite3VdbeAddOp1(v, OP_RowKey, iSrc);
-    sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, 0, 1);
+    sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
+    sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
     sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
     sqlite3VdbeJumpHere(v, addr1);
   }
   sqlite3VdbeJumpHere(v, emptySrcTest);
+  sqlite3ReleaseTempReg(pParse, regRowid);
+  sqlite3ReleaseTempReg(pParse, regData);
   sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
   sqlite3VdbeAddOp2(v, OP_Close, iDest, 0);
   if( emptyDestTest ){
index 65aa3622698dbe475d48bb16202e1357b35a35f3..6d28f406365213ce13f346cc1d128c8c73708357 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.397 2008/01/10 23:50:11 drh Exp $
+** $Id: select.c,v 1.398 2008/01/12 12:48:08 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -394,7 +394,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
 static void pushOntoSorter(
   Parse *pParse,         /* Parser context */
   ExprList *pOrderBy,    /* The ORDER BY clause */
-  Select *pSelect        /* The whole SELECT statement */
+  Select *pSelect,       /* The whole SELECT statement */
+  int regData            /* Register holding data to be sorted */
 ){
   Vdbe *v = pParse->pVdbe;
   int nExpr = pOrderBy->nExpr;
@@ -402,15 +403,21 @@ static void pushOntoSorter(
   int regRecord = sqlite3GetTempReg(pParse);
   sqlite3ExprCodeExprList(pParse, pOrderBy, regBase);
   sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);
-  sqlite3VdbeAddOp2(v, OP_Move, 0, regBase+nExpr+1);
+  sqlite3VdbeAddOp2(v, OP_Move, regData, regBase+nExpr+1);
   sqlite3VdbeAddOp3(v, OP_RegMakeRec, regBase, nExpr + 2, regRecord);
   sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
   sqlite3ReleaseTempReg(pParse, regRecord);
   sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
   if( pSelect->iLimit>=0 ){
     int addr1, addr2;
-    addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, pSelect->iLimit+1);
-    sqlite3VdbeAddOp2(v, OP_AddImm, pSelect->iLimit+1, -1);
+    int iLimit;
+    if( pSelect->pOffset ){
+      iLimit = pSelect->iOffset+1;
+    }else{
+      iLimit = pSelect->iLimit;
+    }
+    addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit);
+    sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
     addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
     sqlite3VdbeJumpHere(v, addr1);
     sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);
@@ -426,16 +433,12 @@ static void pushOntoSorter(
 static void codeOffset(
   Vdbe *v,          /* Generate code into this VM */
   Select *p,        /* The SELECT statement being coded */
-  int iContinue,    /* Jump here to skip the current record */
-  int nPop          /* Number of times to pop stack when jumping */
+  int iContinue     /* Jump here to skip the current record */
 ){
   if( p->iOffset>=0 && iContinue!=0 ){
     int addr;
     sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1);
     addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset);
-    if( nPop>0 ){
-      sqlite3VdbeAddOp1(v, OP_Pop, nPop);
-    }
     sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);
     VdbeComment((v, "skip OFFSET records"));
     sqlite3VdbeJumpHere(v, addr);
@@ -524,7 +527,7 @@ static int selectInnerLoop(
   */
   hasDistinct = distinct>=0 && pEList->nExpr>0;
   if( pOrderBy==0 && !hasDistinct ){
-    codeOffset(v, p, iContinue, 0);
+    codeOffset(v, p, iContinue);
   }
 
   /* Pull the requested columns.
@@ -563,7 +566,7 @@ static int selectInnerLoop(
     assert( pEList->nExpr==nColumn );
     codeDistinct(v, distinct, iContinue, nColumn, iMem);
     if( pOrderBy==0 ){
-      codeOffset(v, p, iContinue, nColumn);
+      codeOffset(v, p, iContinue);
     }
   }
 
@@ -603,14 +606,18 @@ static int selectInnerLoop(
     */
     case SRT_Table:
     case SRT_EphemTab: {
-      sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
+      int r1 = sqlite3GetTempReg(pParse);
+      sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, nColumn, r1);
       if( pOrderBy ){
-        pushOntoSorter(pParse, pOrderBy, p);
+        pushOntoSorter(pParse, pOrderBy, p, r1);
       }else{
-        sqlite3VdbeAddOp1(v, OP_NewRowid, iParm);
-        sqlite3VdbeAddOp2(v, OP_Pull, 1, 0);
-        sqlite3CodeInsert(pParse, iParm, OPFLAG_APPEND);
+        int r2 = sqlite3GetTempReg(pParse);
+        sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);
+        sqlite3VdbeAddOp3(v, OP_Insert, iParm, r1, r2);
+        sqlite3VdbeChangeP5(v, OPFLAG_APPEND);
+        sqlite3ReleaseTempReg(pParse, r2);
       }
+      sqlite3ReleaseTempReg(pParse, r1);
       break;
     }
 
@@ -630,11 +637,12 @@ static int selectInnerLoop(
         ** ORDER BY in this case since the order of entries in the set
         ** does not matter.  But there might be a LIMIT clause, in which
         ** case the order does matter */
-        sqlite3VdbeAddOp2(v, OP_SCopy, iMem, 0);
-        pushOntoSorter(pParse, pOrderBy, p);
+        pushOntoSorter(pParse, pOrderBy, p, iMem);
       }else{
-        sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 1, 0, &p->affinity, 1);
-        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
+        int r1 = sqlite3GetTempReg(pParse);
+        sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 1, r1, &p->affinity, 1);
+        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);
+        sqlite3ReleaseTempReg(pParse, r1);
       }
       sqlite3VdbeJumpHere(v, addr2);
       break;
@@ -654,11 +662,10 @@ static int selectInnerLoop(
     */
     case SRT_Mem: {
       assert( nColumn==1 );
-      sqlite3VdbeAddOp2(v, OP_SCopy, iMem, 0);
       if( pOrderBy ){
-        pushOntoSorter(pParse, pOrderBy, p);
+        pushOntoSorter(pParse, pOrderBy, p, iMem);
       }else{
-        sqlite3VdbeAddOp2(v, OP_Move, 0, iParm);
+        sqlite3VdbeAddOp2(v, OP_Move, iMem, iParm);
         /* The LIMIT clause will jump out of the loop for us */
       }
       break;
@@ -672,8 +679,10 @@ static int selectInnerLoop(
     case SRT_Subroutine:
     case SRT_Callback: {
       if( pOrderBy ){
-        sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
-        pushOntoSorter(pParse, pOrderBy, p);
+        int r1 = sqlite3GetTempReg(pParse);
+        sqlite3VdbeAddOp3(v, OP_RegMakeRec, iMem, nColumn, r1);
+        pushOntoSorter(pParse, pOrderBy, p, r1);
+        sqlite3ReleaseTempReg(pParse, r1);
       }else if( eDest==SRT_Subroutine ){
         sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
       }else{
@@ -779,7 +788,7 @@ static void generateSortTail(
     sqlite3VdbeAddOp2(v, OP_SetNumColumns, pseudoTab, nColumn);
   }
   addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk);
-  codeOffset(v, p, cont, 0);
+  codeOffset(v, p, cont);
   regRow = sqlite3GetTempReg(pParse);
   regRowid = sqlite3GetTempReg(pParse);
   sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow);
@@ -1737,7 +1746,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
   Vdbe *v = 0;
   int iLimit = 0;
   int iOffset;
-  int addr1, addr2;
+  int addr1;
 
   /* 
   ** "LIMIT -1" always shows all rows.  There is some
@@ -1747,42 +1756,34 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
   */
   if( p->pLimit ){
     p->iLimit = iLimit = ++pParse->nMem;
-    pParse->nMem++;
     v = sqlite3GetVdbe(pParse);
     if( v==0 ) return;
-    sqlite3ExprCode(pParse, p->pLimit, 0);
-    sqlite3VdbeAddOp0(v, OP_MustBeInt);
-    sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit);
+    sqlite3ExprCode(pParse, p->pLimit, iLimit);
+    sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit);
     VdbeComment((v, "LIMIT counter"));
     sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak);
-    sqlite3VdbeAddOp2(v, OP_SCopy, iLimit, 0);
   }
   if( p->pOffset ){
     p->iOffset = iOffset = ++pParse->nMem;
+    if( p->pLimit ){
+      pParse->nMem++;   /* Allocate an extra register for limit+offset */
+    }
     v = sqlite3GetVdbe(pParse);
     if( v==0 ) return;
-    sqlite3ExprCode(pParse, p->pOffset, 0);
-    sqlite3VdbeAddOp0(v, OP_MustBeInt);
-    sqlite3VdbeAddOp2(v, p->pLimit==0 ? OP_Move : OP_Copy, 0, iOffset);
+    sqlite3ExprCode(pParse, p->pOffset, iOffset);
+    sqlite3VdbeAddOp1(v, OP_MustBeInt, iOffset);
     VdbeComment((v, "OFFSET counter"));
     addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iOffset);
-    sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
-    sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
+    sqlite3VdbeAddOp2(v, OP_Integer, 0, iOffset);
     sqlite3VdbeJumpHere(v, addr1);
     if( p->pLimit ){
-      sqlite3VdbeAddOp2(v, OP_Add, 0, 0);
+      sqlite3VdbeAddOp3(v, OP_Add, iLimit, iOffset, iOffset+1);
+      VdbeComment((v, "LIMIT+OFFSET"));
+      addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit);
+      sqlite3VdbeAddOp2(v, OP_Integer, -1, iOffset+1);
+      sqlite3VdbeJumpHere(v, addr1);
     }
   }
-  if( p->pLimit ){
-    addr1 = sqlite3VdbeAddOp1(v, OP_IfPos, iLimit);
-    sqlite3VdbeAddOp1(v, OP_Pop, 1);
-    sqlite3VdbeAddOp2(v, OP_Integer, -1, iLimit+1);
-    addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
-    sqlite3VdbeJumpHere(v, addr1);
-    sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit+1);
-    VdbeComment((v, "LIMIT+OFFSET"));
-    sqlite3VdbeJumpHere(v, addr2);
-  }
 }
 
 /*
index 52ee5db32fb820f2379041db2909c18c12e97629..d9c9dd40a62f5728b430b86e54c9a246912180d3 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.647 2008/01/10 23:50:11 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.648 2008/01/12 12:48:08 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1420,6 +1420,8 @@ struct Parse {
   /* Above is constant between recursions.  Below is reset before and after
   ** each recursion */
 
+  int regRowid;        /* Register holding rowid of CREATE TABLE entry */
+  int regRoot;         /* Register holding root page number for new objects */
   int nVar;            /* Number of '?' variables seen in the SQL so far */
   int nVarExpr;        /* Number of used slots in apVarExpr[] */
   int nVarExprAlloc;   /* Number of allocated slots in apVarExpr[] */
@@ -1945,9 +1947,7 @@ int sqlite3OpenTempDatabase(Parse *);
 void sqlite3StrAccumAppend(StrAccum*,const char*,int);
 char *sqlite3StrAccumFinish(StrAccum*);
 void sqlite3StrAccumReset(StrAccum*);
-void sqlite3CodeInsert(Parse *, int, u8);
 int sqlite3StackToReg(Parse *, int);
-void sqlite3RegToStack(Parse *, int, int);
 void sqlite3SelectDestInit(SelectDest*,int,int);
 
 /*
index 66c49af6000355e611bcf057b9ed0530b4b60fc0..b56babc3ac37cc4fd2f274587734037509eed673 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.692 2008/01/10 23:50:11 drh Exp $
+** $Id: vdbe.c,v 1.693 2008/01/12 12:48:08 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -94,6 +94,18 @@ int sqlite3_sort_count = 0;
 int sqlite3_max_blobsize = 0;
 #endif
 
+/*
+** Test a register to see if it exceeds the current maximum blob size.
+** If it does, record the new maximum blob size.
+*/
+#ifdef SQLITE_TEST
+# define UPDATE_MAX_BLOBSIZE(P)  if( ((P)->flags&(MEM_Str|MEM_Blob))!=0 \
+                                      && (P)->n>sqlite3_max_blobsize ) \
+                                          {sqlite3_max_blobsize = (P)->n;}
+#else
+# define UPDATE_MAX_BLOBSIZE(P)
+#endif
+
 /*
 ** Release the memory associated with the given stack level.  This
 ** leaves the Mem.flags field in an inconsistent state.
@@ -939,6 +951,7 @@ case OP_String8: {         /* same as TK_STRING, out2-prerelease */
     if( pOp->p1>SQLITE_MAX_LENGTH ){
       goto too_big;
     }
+    UPDATE_MAX_BLOBSIZE(pOut);
     break;
   }
 #endif
@@ -959,6 +972,7 @@ case OP_String: {          /* out2-prerelease */
   pOut->z = pOp->p4.z;
   pOut->n = pOp->p1;
   pOut->enc = encoding;
+  UPDATE_MAX_BLOBSIZE(pOut);
   break;
 }
 
@@ -1019,6 +1033,7 @@ case OP_Blob: {                /* out2-prerelease */
   assert( pOp->p1 <= SQLITE_MAX_LENGTH );
   sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
   pOut->enc = encoding;
+  UPDATE_MAX_BLOBSIZE(pOut);
   break;
 }
 #endif /* SQLITE_OMIT_BLOB_LITERAL */
@@ -1043,6 +1058,7 @@ case OP_Variable: {           /* out2-prerelease */
     goto too_big;
   }
   sqlite3VdbeMemShallowCopy(pOut, &p->aVar[j], MEM_Static);
+  UPDATE_MAX_BLOBSIZE(pOut);
   break;
 }
 
@@ -1136,40 +1152,6 @@ case OP_SCopy: {
   break;
 }
 
-/* Opcode: Pull P1 * *
-**
-** The P1-th element is removed from its current location on 
-** the stack and pushed back on top of the stack.  The
-** top of the stack is element 0, so "Pull 0 0 0" is
-** a no-op.  "Pull 1 0 0" swaps the top two elements of
-** the stack.
-*/
-case OP_Pull: {            /* no-push */
-  Mem *pFrom = &pTos[-pOp->p1];
-  int i;
-  Mem ts;
-
-  ts = *pFrom;
-  Deephemeralize(pTos);
-  for(i=0; i<pOp->p1; i++, pFrom++){
-    Deephemeralize(&pFrom[1]);
-    assert( (pFrom[1].flags & MEM_Ephem)==0 );
-    *pFrom = pFrom[1];
-    if( pFrom->flags & MEM_Short ){
-      assert( pFrom->flags & (MEM_Str|MEM_Blob) );
-      assert( pFrom->z==pFrom[1].zShort );
-      pFrom->z = pFrom->zShort;
-    }
-  }
-  *pTos = ts;
-  if( pTos->flags & MEM_Short ){
-    assert( pTos->flags & (MEM_Str|MEM_Blob) );
-    assert( pTos->z==pTos[-pOp->p1].zShort );
-    pTos->z = pTos->zShort;
-  }
-  break;
-}
-
 /* Opcode: ResultRow P1 P2 *
 **
 ** The registers P1 throught P1+P2-1 contain a single row of
@@ -1257,6 +1239,7 @@ case OP_Concat: {           /* same as TK_CONCAT, in1, in2, out3 */
   pOut->xDel = 0;
   pOut->enc = encoding;
   pOut->z = zNew;
+  UPDATE_MAX_BLOBSIZE(pOut);
   break;
 }
 
@@ -1489,6 +1472,7 @@ case OP_Function: {
   if( sqlite3VdbeMemTooBig(pOut) ){
     goto too_big;
   }
+  UPDATE_MAX_BLOBSIZE(pOut);
   break;
 }
 
@@ -1658,6 +1642,7 @@ case OP_ToText: {                  /* same as TK_TO_TEXT, no-push, in1 */
   rc = ExpandBlob(pIn1);
   assert( pIn1->flags & MEM_Str );
   pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Blob);
+  UPDATE_MAX_BLOBSIZE(pIn1);
   break;
 }
 
@@ -1679,6 +1664,7 @@ case OP_ToBlob: {                  /* same as TK_TO_BLOB, no-push, in1 */
     pIn1->flags |= MEM_Blob;
   }
   pIn1->flags &= ~(MEM_Int|MEM_Real|MEM_Str);
+  UPDATE_MAX_BLOBSIZE(pIn1);
   break;
 }
 
@@ -2337,6 +2323,7 @@ case OP_Column: {
   rc = sqlite3VdbeMemMakeWriteable(pDest);
 
 op_column_out:
+  UPDATE_MAX_BLOBSIZE(pDest);
   REGISTER_TRACE(pOp->p3, pDest);
   break;
 }
@@ -2525,6 +2512,7 @@ case OP_MakeRecord: {        /* jump */
   }
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever converted to text */
   REGISTER_TRACE(pOp->p3, pOut);
+  UPDATE_MAX_BLOBSIZE(pOut);
 
   /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */
   if( jumpIfNull && containsNull ){
@@ -2683,7 +2671,7 @@ case OP_ReadCookie: {               /* out2-prerelease */
   int iDb = pOp->p1;
   int iCookie = pOp->p3;
 
-  assert( pOp->p2<SQLITE_N_BTREE_META );
+  assert( pOp->p3<SQLITE_N_BTREE_META );
   if( iDb<0 ){
     iDb = (-1*(iDb+1));
     iCookie *= -1;
@@ -3819,6 +3807,7 @@ case OP_RowData: {          /* out2-prerelease */
     pOut->flags = MEM_Null;
   }
   pOut->enc = SQLITE_UTF8;  /* In case the blob is ever cast to text */
+  UPDATE_MAX_BLOBSIZE(pOut);
   break;
 }
 
@@ -4440,6 +4429,7 @@ case OP_IntegrityCk: {
     pIn1->xDel = 0;
   }
   pIn1->enc = SQLITE_UTF8;
+  UPDATE_MAX_BLOBSIZE(pIn1);
   sqlite3VdbeChangeEncoding(pIn1, encoding);
   sqlite3_free(aRoot);
   break;
@@ -4656,6 +4646,7 @@ case OP_AggFinal: {        /* no-push */
   if( rc==SQLITE_ERROR ){
     sqlite3SetString(&p->zErrMsg, sqlite3_value_text(pMem), (char*)0);
   }
+  UPDATE_MAX_BLOBSIZE(pMem);
   if( sqlite3VdbeMemTooBig(pMem) ){
     goto too_big;
   }
@@ -4961,6 +4952,7 @@ case OP_VColumn: {
       pDest->flags = 0;
     }
     sqlite3VdbeMemMove(pDest, &sContext.s);
+    UPDATE_MAX_BLOBSIZE(pDest);
 
     if( sqlite3SafetyOn(db) ){
       goto abort_due_to_misuse;
@@ -5134,16 +5126,6 @@ default: {
     }
 #endif
 
-#ifdef SQLITE_TEST
-    /* Keep track of the size of the largest BLOB or STR that has appeared
-    ** on the top of the VDBE stack.
-    */
-    if( pTos>=p->aStack && (pTos->flags & (MEM_Blob|MEM_Str))!=0
-         && pTos->n>sqlite3_max_blobsize ){
-      sqlite3_max_blobsize = pTos->n;
-    }
-#endif
-
     /* The following code adds nothing to the actual functionality
     ** of the program.  It is only here for testing and debugging.
     ** On the other hand, it does burn CPU cycles every time through
index 9746f40e767cc10a034802af0832f20e675c2341..398fd649fef4e21c80d10d2a3e4f9f901a32e0a5 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to help implement virtual tables.
 **
-** $Id: vtab.c,v 1.60 2008/01/03 00:01:25 drh Exp $
+** $Id: vtab.c,v 1.61 2008/01/12 12:48:08 drh Exp $
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 #include "sqliteInt.h"
@@ -259,20 +259,20 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
     ** SQLITE_MASTER table.  We just need to update that slot with all
     ** the information we've collected.  
     **
-    ** The top of the stack is the rootpage allocated by sqlite3StartTable().
-    ** This value is always 0 and is ignored, a virtual table does not have a
-    ** rootpage. The next entry on the stack is the rowid of the record
-    ** in the sqlite_master table.
+    ** The VM register number pParse->regRowid holds the rowid of an
+    ** entry in the sqlite_master table tht was created for this vtab
+    ** by sqlite3StartTable().
     */
     iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
     sqlite3NestedParse(pParse,
       "UPDATE %Q.%s "
          "SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q "
-       "WHERE rowid=#1",
+       "WHERE rowid=#%d",
       db->aDb[iDb].zName, SCHEMA_TABLE(iDb),
       pTab->zName,
       pTab->zName,
-      zStmt
+      zStmt,
+      pParse->regRowid
     );
     sqlite3_free(zStmt);
     v = sqlite3GetVdbe(pParse);
index 62b041adccaa5496262e365eae869c659ddbb251..adbc57104dda8f7b2d30f06d58423717054ef0bf 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this file is testing UNION, INTERSECT and EXCEPT operators
 # in SELECT statements.
 #
-# $Id: select4.test,v 1.24 2007/12/13 07:58:51 danielk1977 Exp $
+# $Id: select4.test,v 1.25 2008/01/12 12:48:09 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -618,4 +618,55 @@ do_test select4-9.12 {
 
 } ;# ifcapable compound
 
+# Try combining DISTINCT, LIMIT, and OFFSET.  Make sure they all work
+# together.
+#
+do_test select4-10.1 {
+  execsql {
+    SELECT DISTINCT log FROM t1 ORDER BY log
+  }
+} {0 1 2 3 4 5}
+do_test select4-10.2 {
+  execsql {
+    SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 4
+  }
+} {0 1 2 3}
+do_test select4-10.3 {
+  execsql {
+    SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 0
+  }
+} {}
+do_test select4-10.4 {
+  execsql {
+    SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1
+  }
+} {0 1 2 3 4 5}
+do_test select4-10.5 {
+  execsql {
+    SELECT DISTINCT log FROM t1 ORDER BY log LIMIT -1 OFFSET 2
+  }
+} {2 3 4 5}
+do_test select4-10.6 {
+  execsql {
+    SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 3 OFFSET 2
+  }
+} {2 3 4}
+do_test select4-10.7 {
+  execsql {
+    SELECT DISTINCT log FROM t1 ORDER BY +log LIMIT 3 OFFSET 20
+  }
+} {}
+do_test select4-10.8 {
+  execsql {
+    SELECT DISTINCT log FROM t1 ORDER BY log LIMIT 0 OFFSET 3
+  }
+} {}
+do_test select4-10.9 {
+breakpoint
+  execsql {
+    SELECT DISTINCT max(n), log FROM t1 ORDER BY +log; -- LIMIT 2 OFFSET 1
+  }
+} {31 5}
+
+
 finish_test
diff --git a/test/select8.test b/test/select8.test
new file mode 100644 (file)
index 0000000..9862664
--- /dev/null
@@ -0,0 +1,62 @@
+# 2001 September 15
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library. 
+#
+# The focus of this file is testing that LIMIT and OFFSET work for
+# unusual combinations SELECT statements.
+#
+# $Id: select8.test,v 1.1 2008/01/12 12:48:09 drh Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+execsql {
+  CREATE TABLE songs(songid, artist, timesplayed);
+  INSERT INTO songs VALUES(1,'one',1);
+  INSERT INTO songs VALUES(2,'one',2);
+  INSERT INTO songs VALUES(3,'two',3);
+  INSERT INTO songs VALUES(4,'three',5);
+  INSERT INTO songs VALUES(5,'one',7);
+  INSERT INTO songs VALUES(6,'two',11);
+}
+set result [execsql {
+  SELECT DISTINCT artist,sum(timesplayed) AS total      
+  FROM songs      
+  GROUP BY LOWER(artist)      
+}]
+puts result=$result
+do_test select8-1.1 {
+  execsql {
+    SELECT DISTINCT artist,sum(timesplayed) AS total      
+    FROM songs      
+    GROUP BY LOWER(artist)      
+    LIMIT 1 OFFSET 1
+  }
+} [lrange $result 2 3]
+do_test select8-1.2 {
+  execsql {
+    SELECT DISTINCT artist,sum(timesplayed) AS total      
+    FROM songs      
+    GROUP BY LOWER(artist)      
+    LIMIT 2 OFFSET 1
+  }
+} [lrange $result 2 5]
+do_test select8-1.3 {
+  execsql {
+    SELECT DISTINCT artist,sum(timesplayed) AS total      
+    FROM songs      
+    GROUP BY LOWER(artist)      
+    LIMIT -1 OFFSET 2
+  }
+} [lrange $result 4 end]
+
+
+finish_test