]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix for bugs #77 and #80: Rework the LIMIT mechanism to be reentrant and to
authordrh <drh@noemail.net>
Fri, 21 Jun 2002 23:01:49 +0000 (23:01 +0000)
committerdrh <drh@noemail.net>
Fri, 21 Jun 2002 23:01:49 +0000 (23:01 +0000)
clean up the VDBE stack properly. (CVS 636)

FossilOrigin-Name: 9d5523107937e3700c76666fb058694babdd672c

manifest
manifest.uuid
src/select.c
src/sqliteInt.h
src/vdbe.c
src/vdbe.h
test/limit.test
test/misc1.test

index e1f7bd2dfd01c81bcbd92c52109c5324704c69d8..c920d64faa7bfe9576d7e801b7173fb2a713c620 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\sfor\sticket\s#76:\sFix\sa\sdatabase\scorruption\sthat\smight\soccur\swhen\ndropping\stables\sor\sindices.\s(CVS\s635)
-D 2002-06-21T13:09:17
+C Fix\sfor\sbugs\s#77\sand\s#80:\sRework\sthe\sLIMIT\smechanism\sto\sbe\sreentrant\sand\sto\nclean\sup\sthe\sVDBE\sstack\sproperly.\s(CVS\s636)
+D 2002-06-21T23:01:50
 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
 F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495
 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
@@ -37,11 +37,11 @@ F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e
 F src/parse.y 2285d8967d7334d52a2188089e5a881d73ba56f6
 F src/printf.c 236ed7a79386feed4456fa728fff8be793f1547c
 F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
-F src/select.c 3eadcde4c74341d8ee7db69948cbcb16df9ae9fc
+F src/select.c 346da88a44aef311e932e95239dc0288fdcb10dd
 F src/shell.c 1d22fe870ee852cfb975fd000dbe3973713d0a15
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
 F src/sqlite.h.in 7c8882e352cb70818cfaf9bdb5b1b3bee81ef144
-F src/sqliteInt.h 16ccbf72dd823d5764b475353927410ec272305e
+F src/sqliteInt.h f283e5628174d7124c39968442e7adb5b95ea82c
 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
 F src/tclsqlite.c 9300c9606a38bc0c75d6c0bc8a6197ab979353d1
 F src/test1.c 5cc4f0bbf38237e04e1b2077e285b41bfb4c4cbf
@@ -52,8 +52,8 @@ F src/tokenize.c ac4c46f190346b87da54ec3e2605d160af80c619
 F src/trigger.c 21342af6ac031fece39c8fc6eabd1739ca5327c1
 F src/update.c 6f6a4dcd71cd9ff730b7f12c83de5498cde4924f
 F src/util.c 876b259f9186e84b944b72e793dd3dad50e63e95
-F src/vdbe.c c33572f803b853c50c22f84d6dfa6922ec79bf6b
-F src/vdbe.h 9b6e632bfa5d52507130f1ae456ef2c01bc0be7e
+F src/vdbe.c 774f79483ce809b27c3bdb02afd7295cc3c7acd4
+F src/vdbe.h a9292f2b5fcecef924fa255fb74609e9cbc776c2
 F src/where.c 1fdb7aca26c1963eb42615a95e0fc2978eec566a
 F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1
 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
@@ -72,12 +72,12 @@ F test/insert2.test eb8481878a7f52ccb4e3346f87550f5afdd77f76
 F test/intpkey.test 69a6a9b41e541f27a2ffcd20264fb35adc3c2680
 F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a
 F test/join.test ea6a4097e4fcebbb16eac7ec819569e759336a74
-F test/limit.test 96b33e108e134b5cc674a660064229d15fa278b9
+F test/limit.test 49b44e027a002c0ba336d723b448f07e05b04466
 F test/lock.test 3fcfd46a73119f6a18094673328a32c7b3047a8f
 F test/main.test c66b564554b770ee7fdbf6a66c0cd90329bc2c85
 F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd
 F test/minmax.test 29bc5727c3e4c792d5c4745833dd4b505905819e
-F test/misc1.test faae0b01cce45a75fe8011b1f462c3ef36fb9bda
+F test/misc1.test 18c74cdfa6cc920f1c51827ccb23a442c62caefb
 F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162
 F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30
 F test/null.test 5c2b57307e4b6178aae825eb65ddbee01e76b0fd
@@ -137,7 +137,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f
 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 2532792a5875f9cc0f7d8eaf90dd49d1f6025ca3
-R 3fe0ffaffb77713981828251190bdd81
+P 7936b0325024c81ed8d4bab192d7350d045ec999
+R d15c924c28dce20794c50e0013aa8eb2
 U drh
-Z 08d058b9c9d8b8b2fa6e6514672f1243
+Z 7d39bfd0dd2f959041e3d2a9c3cd818e
index 80ff91e26178efd7b68155ebadf3f5f7aed830d8..da81f1e59d7f6286f79ed76ad3443080649e2487 100644 (file)
@@ -1 +1 @@
-7936b0325024c81ed8d4bab192d7350d045ec999
\ No newline at end of file
+9d5523107937e3700c76666fb058694babdd672c
\ No newline at end of file
index 98ede32fc3cf9c18331dfd0b1826fae939f14c24..4cd71a2a1182b34e65854aed301b0d0907693853 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.95 2002/06/20 03:38:26 drh Exp $
+** $Id: select.c,v 1.96 2002/06/21 23:01:50 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -334,10 +334,12 @@ static int selectInnerLoop(
   */
   if( pOrderBy==0 ){
     if( p->nOffset>0 ){
-      sqliteVdbeAddOp(v, OP_LimitCk, 1, iContinue);
+      int addr = sqliteVdbeCurrentAddr(v);
+      sqliteVdbeAddOp(v, OP_MemIncr, p->nOffset, addr+2);
+      sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);
     }
-    if( p->nLimit>0 ){
-      sqliteVdbeAddOp(v, OP_LimitCk, 0, iBreak);
+    if( p->nLimit>=0 ){
+      sqliteVdbeAddOp(v, OP_MemIncr, p->nLimit, iBreak);
     }
   }
 
@@ -483,10 +485,12 @@ static void generateSortTail(
   sqliteVdbeAddOp(v, OP_Sort, 0, 0);
   addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end);
   if( p->nOffset>0 ){
-    sqliteVdbeAddOp(v, OP_LimitCk, 1, addr);
+    sqliteVdbeAddOp(v, OP_MemIncr, p->nOffset, addr+4);
+    sqliteVdbeAddOp(v, OP_Pop, 1, 0);
+    sqliteVdbeAddOp(v, OP_Goto, 0, addr);
   }
-  if( p->nLimit>0 ){
-    sqliteVdbeAddOp(v, OP_LimitCk, 0, end);
+  if( p->nLimit>=0 ){
+    sqliteVdbeAddOp(v, OP_MemIncr, p->nLimit, end);
   }
   switch( eDest ){
     case SRT_Callback: {
@@ -1305,7 +1309,7 @@ int flattenSubquery(Select *p, int iFrom, int isAgg, int subqueryIsAgg){
   if( (pSub->isDistinct || pSub->nLimit>=0) &&  (pSrc->nSrc>1 || isAgg) ){
      return 0;
   }
-  if( (p->isDistinct || p->nLimit) && subqueryIsAgg ) return 0;
+  if( (p->isDistinct || p->nLimit>=0) && subqueryIsAgg ) return 0;
 
   /* If we reach this point, it means flattening is permitted for the
   ** i-th entry of the FROM clause in the outer query.
@@ -1722,10 +1726,21 @@ int sqliteSelect(
   /* Set the limiter
   */
   if( p->nLimit<=0 ){
+    p->nLimit = -1;
     p->nOffset = 0;
   }else{
-    if( p->nOffset<0 ) p->nOffset = 0;
-    sqliteVdbeAddOp(v, OP_Limit, p->nLimit, p->nOffset);
+    int iMem = pParse->nMem++;
+    sqliteVdbeAddOp(v, OP_Integer, -p->nLimit, 0);
+    sqliteVdbeAddOp(v, OP_MemStore, iMem, 0);
+    p->nLimit = iMem;
+    if( p->nOffset<=0 ){
+      p->nOffset = 0;
+    }else{
+      iMem = pParse->nMem++;
+      sqliteVdbeAddOp(v, OP_Integer, -p->nOffset, 0);
+      sqliteVdbeAddOp(v, OP_MemStore, iMem, 0);
+      p->nOffset = iMem;
+    }
   }
 
   /* Generate code for all sub-queries in the FROM clause
index 79a44f97ac8fae845bbe604e2f3a98b93ca06b69..ef2d5ed44a4f2a46f049e1feba09687fca55d8d1 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.127 2002/06/20 11:36:50 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.128 2002/06/21 23:01:50 drh Exp $
 */
 #include "sqlite.h"
 #include "hash.h"
@@ -570,6 +570,12 @@ struct WhereInfo {
 ** a VIEW) we have to make a copy of the input string so that the nodes
 ** of the expression tree will have something to point to.  zSelect is used
 ** to hold that copy.
+**
+** nLimit is set to -1 if there is no LIMIT clause.  nOffset is set to 0.
+** If there is a LIMIT clause, the parser sets nLimit to the value of the
+** limit and nOffset to the value of the offset (or 0 if there is not
+** offset).  But later on, nLimit and nOffset become the memory locations
+** in the VDBE that record the limit and offset counters.
 */
 struct Select {
   int isDistinct;        /* True if the DISTINCT keyword is present */
index d5ad988510871a5e29cc74f9c117e35f8a230b07..74978b2414e0d4a44587d9e58ab54b64c3e8b2a4 100644 (file)
@@ -30,7 +30,7 @@
 ** But other routines are also provided to help in building up
 ** a program instruction by instruction.
 **
-** $Id: vdbe.c,v 1.157 2002/06/20 11:36:50 drh Exp $
+** $Id: vdbe.c,v 1.158 2002/06/21 23:01:50 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -248,8 +248,6 @@ struct Vdbe {
   int nSet;           /* Number of sets allocated */
   Set *aSet;          /* An array of sets */
   int nCallback;      /* Number of callbacks invoked so far */
-  int iLimit;         /* Limit on the number of callbacks remaining */
-  int iOffset;        /* Offset before beginning to do callbacks */
   int keylistStackDepth;  /* The size of the "keylist" stack */
   Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */
 };
@@ -1060,28 +1058,28 @@ static char *zOpName[] = { 0,
   "Last",              "Rewind",            "Next",              "Destroy",
   "Clear",             "CreateIndex",       "CreateTable",       "IntegrityCk",
   "IdxPut",            "IdxDelete",         "IdxRecno",          "IdxGT",
-  "IdxGE",             "MemLoad",           "MemStore",          "ListWrite",
-  "ListRewind",        "ListRead",          "ListReset",         "ListPush",
-  "ListPop",           "SortPut",           "SortMakeRec",       "SortMakeKey",
-  "Sort",              "SortNext",          "SortCallback",      "SortReset",
-  "FileOpen",          "FileRead",          "FileColumn",        "AggReset",
-  "AggFocus",          "AggNext",           "AggSet",            "AggGet",
-  "AggFunc",           "AggInit",           "AggPush",           "AggPop",
-  "SetInsert",         "SetFound",          "SetNotFound",       "SetFirst",
-  "SetNext",           "MakeRecord",        "MakeKey",           "MakeIdxKey",
-  "IncrKey",           "Goto",              "If",                "IfNot",
-  "Halt",              "ColumnCount",       "ColumnName",        "Callback",
-  "NullCallback",      "Integer",           "String",            "Pop",
-  "Dup",               "Pull",              "Push",              "MustBeInt",
-  "Add",               "AddImm",            "Subtract",          "Multiply",
-  "Divide",            "Remainder",         "BitAnd",            "BitOr",
-  "BitNot",            "ShiftLeft",         "ShiftRight",        "AbsValue",
-  "Eq",                "Ne",                "Lt",                "Le",
-  "Gt",                "Ge",                "StrEq",             "StrNe",
-  "StrLt",             "StrLe",             "StrGt",             "StrGe",
-  "IsNull",            "NotNull",           "Negative",          "And",
-  "Or",                "Not",               "Concat",            "Noop",
-  "Function",          "Limit",             "LimitCk",         
+  "IdxGE",             "MemLoad",           "MemStore",          "MemIncr",
+  "ListWrite",         "ListRewind",        "ListRead",          "ListReset",
+  "ListPush",          "ListPop",           "SortPut",           "SortMakeRec",
+  "SortMakeKey",       "Sort",              "SortNext",          "SortCallback",
+  "SortReset",         "FileOpen",          "FileRead",          "FileColumn",
+  "AggReset",          "AggFocus",          "AggNext",           "AggSet",
+  "AggGet",            "AggFunc",           "AggInit",           "AggPush",
+  "AggPop",            "SetInsert",         "SetFound",          "SetNotFound",
+  "SetFirst",          "SetNext",           "MakeRecord",        "MakeKey",
+  "MakeIdxKey",        "IncrKey",           "Goto",              "If",
+  "IfNot",             "Halt",              "ColumnCount",       "ColumnName",
+  "Callback",          "NullCallback",      "Integer",           "String",
+  "Pop",               "Dup",               "Pull",              "Push",
+  "MustBeInt",         "Add",               "AddImm",            "Subtract",
+  "Multiply",          "Divide",            "Remainder",         "BitAnd",
+  "BitOr",             "BitNot",            "ShiftLeft",         "ShiftRight",
+  "AbsValue",          "Eq",                "Ne",                "Lt",
+  "Le",                "Gt",                "Ge",                "StrEq",
+  "StrNe",             "StrLt",             "StrLe",             "StrGt",
+  "StrGe",             "IsNull",            "NotNull",           "Negative",
+  "And",               "Or",                "Not",               "Concat",
+  "Noop",              "Function",        
 };
 
 /*
@@ -1300,8 +1298,6 @@ int sqliteVdbeExec(
   zStack = p->zStack;
   aStack = p->aStack;
   p->tos = -1;
-  p->iLimit = 0;
-  p->iOffset = 0;
 
   /* Initialize the aggregrate hash table.
   */
@@ -4068,54 +4064,6 @@ case OP_IntegrityCk: {
   break;
 }
 
-/* Opcode:  Limit P1 P2 *
-**
-** Set a limit and offset on callbacks.  P1 is the limit and P2 is
-** the offset.  If the offset counter is positive, no callbacks are
-** invoked but instead the counter is decremented.  Once the offset
-** counter reaches zero, callbacks are invoked and the limit
-** counter is decremented.  When the limit counter reaches zero,
-** the OP_Callback or OP_SortCallback instruction executes a jump
-** that should end the query.
-**
-** This opcode is used to implement the "LIMIT x OFFSET y" clause
-** of a SELECT statement.
-*/
-case OP_Limit: {
-  p->iLimit = pOp->p1;
-  p->iOffset = pOp->p2;
-  break;
-}
-
-/* Opcode: LimitCk P1 P2 *
-**
-** If P1 is 1, then check to see if the offset counter (set by the
-** P2 argument of OP_Limit) is positive.  If the offset counter is
-** positive then decrement the counter and jump immediately to P2.
-** Otherwise fall straight through.
-**
-** If P1 is 0, then check the value of the limit counter (set by the
-** P1 argument of OP_Limit).  If the limit counter is negative or
-** zero then jump immedately to P2.  Otherwise decrement the limit
-** counter and fall through.
-*/
-case OP_LimitCk: {
-  if( pOp->p1 ){
-    if( p->iOffset ){
-      p->iOffset--;
-      pc = pOp->p2 - 1;
-    }
-  }else{
-    if( p->iLimit>0 ){
-      p->iLimit--;
-    }else{
-      pc = pOp->p2 - 1;
-    }
-  }
-  break;
-}
-
-
 /* Opcode: ListWrite * * *
 **
 ** Write the integer on the top of the stack
@@ -4675,6 +4623,28 @@ case OP_MemLoad: {
   break;
 }
 
+/* Opcode: MemIncr P1 P2 *
+**
+** Increment the integer valued memory cell P1 by 1.  If P2 is not zero
+** and the result after the increment is greater than zero, then jump
+** to P2.
+**
+** This instruction throws an error if the memory cell is not initially
+** an integer.
+*/
+case OP_MemIncr: {
+  int i = pOp->p1;
+  Mem *pMem;
+  VERIFY( if( i<0 || i>=p->nMem ) goto bad_instruction; )
+  pMem = &p->aMem[i];
+  VERIFY( if( pMem->s.flags != STK_Int ) goto bad_instruction; )
+  pMem->s.i++;
+  if( pOp->p2>0 && pMem->s.i>0 ){
+     pc = pOp->p2 - 1;
+  }
+  break;
+}
+
 /* Opcode: AggReset * P2 *
 **
 ** Reset the aggregator so that it no longer contains any data.
index 91b34f24dcb5e11aad2f3443ac0f07979ef27cac..833f71dd122aa11ff49bd93915def4db90929a2f 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.56 2002/06/20 11:36:50 drh Exp $
+** $Id: vdbe.h,v 1.57 2002/06/21 23:01:50 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -116,108 +116,105 @@ typedef struct VdbeOp VdbeOp;
 
 #define OP_MemLoad            42
 #define OP_MemStore           43
-
-#define OP_ListWrite          44
-#define OP_ListRewind         45
-#define OP_ListRead           46
-#define OP_ListReset          47
-#define OP_ListPush           48
-#define OP_ListPop            49
-
-#define OP_SortPut            50
-#define OP_SortMakeRec        51
-#define OP_SortMakeKey        52
-#define OP_Sort               53
-#define OP_SortNext           54
-#define OP_SortCallback       55
-#define OP_SortReset          56
-
-#define OP_FileOpen           57
-#define OP_FileRead           58
-#define OP_FileColumn         59
-
-#define OP_AggReset           60
-#define OP_AggFocus           61
-#define OP_AggNext            62
-#define OP_AggSet             63
-#define OP_AggGet             64
-#define OP_AggFunc            65
-#define OP_AggInit            66
-#define OP_AggPush            67
-#define OP_AggPop             68
-
-#define OP_SetInsert          69
-#define OP_SetFound           70
-#define OP_SetNotFound        71
-#define OP_SetFirst           72
-#define OP_SetNext            73
-
-#define OP_MakeRecord         74
-#define OP_MakeKey            75
-#define OP_MakeIdxKey         76
-#define OP_IncrKey            77
-
-#define OP_Goto               78
-#define OP_If                 79
-#define OP_IfNot              80
-#define OP_Halt               81
-
-#define OP_ColumnCount        82
-#define OP_ColumnName         83
-#define OP_Callback           84
-#define OP_NullCallback       85
-
-#define OP_Integer            86
-#define OP_String             87
-#define OP_Pop                88
-#define OP_Dup                89
-#define OP_Pull               90
-#define OP_Push               91
-#define OP_MustBeInt          92
-
-#define OP_Add                93
-#define OP_AddImm             94
-#define OP_Subtract           95
-#define OP_Multiply           96
-#define OP_Divide             97
-#define OP_Remainder          98
-#define OP_BitAnd             99
-#define OP_BitOr             100
-#define OP_BitNot            101
-#define OP_ShiftLeft         102
-#define OP_ShiftRight        103
-#define OP_AbsValue          104
+#define OP_MemIncr            44
+
+#define OP_ListWrite          45
+#define OP_ListRewind         46
+#define OP_ListRead           47
+#define OP_ListReset          48
+#define OP_ListPush           49
+#define OP_ListPop            50
+
+#define OP_SortPut            51
+#define OP_SortMakeRec        52
+#define OP_SortMakeKey        53
+#define OP_Sort               54
+#define OP_SortNext           55
+#define OP_SortCallback       56
+#define OP_SortReset          57
+
+#define OP_FileOpen           58
+#define OP_FileRead           59
+#define OP_FileColumn         60
+
+#define OP_AggReset           61
+#define OP_AggFocus           62
+#define OP_AggNext            63
+#define OP_AggSet             64
+#define OP_AggGet             65
+#define OP_AggFunc            66
+#define OP_AggInit            67
+#define OP_AggPush            68
+#define OP_AggPop             69
+
+#define OP_SetInsert          70
+#define OP_SetFound           71
+#define OP_SetNotFound        72
+#define OP_SetFirst           73
+#define OP_SetNext            74
+
+#define OP_MakeRecord         75
+#define OP_MakeKey            76
+#define OP_MakeIdxKey         77
+#define OP_IncrKey            78
+
+#define OP_Goto               79
+#define OP_If                 80
+#define OP_IfNot              81
+#define OP_Halt               82
+
+#define OP_ColumnCount        83
+#define OP_ColumnName         84
+#define OP_Callback           85
+#define OP_NullCallback       86
+
+#define OP_Integer            87
+#define OP_String             88
+#define OP_Pop                89
+#define OP_Dup                90
+#define OP_Pull               91
+#define OP_Push               92
+#define OP_MustBeInt          93
+
+#define OP_Add                94
+#define OP_AddImm             95
+#define OP_Subtract           96
+#define OP_Multiply           97
+#define OP_Divide             98
+#define OP_Remainder          99
+#define OP_BitAnd            100
+#define OP_BitOr             101
+#define OP_BitNot            102
+#define OP_ShiftLeft         103
+#define OP_ShiftRight        104
+#define OP_AbsValue          105
 
 /* Note: The code generator assumes that OP_XX+6==OP_StrXX */
-#define OP_Eq                105
-#define OP_Ne                106
-#define OP_Lt                107
-#define OP_Le                108
-#define OP_Gt                109
-#define OP_Ge                110
-#define OP_StrEq             111
-#define OP_StrNe             112
-#define OP_StrLt             113
-#define OP_StrLe             114
-#define OP_StrGt             115
-#define OP_StrGe             116
+#define OP_Eq                106
+#define OP_Ne                107
+#define OP_Lt                108
+#define OP_Le                109
+#define OP_Gt                110
+#define OP_Ge                111
+#define OP_StrEq             112
+#define OP_StrNe             113
+#define OP_StrLt             114
+#define OP_StrLe             115
+#define OP_StrGt             116
+#define OP_StrGe             117
 /* Note: the code generator assumes that OP_XX+6==OP_StrXX */
 
-#define OP_IsNull            117
-#define OP_NotNull           118
-#define OP_Negative          119
-#define OP_And               120
-#define OP_Or                121
-#define OP_Not               122
-#define OP_Concat            123
-#define OP_Noop              124
-#define OP_Function          125
-
-#define OP_Limit             126
-#define OP_LimitCk           127
-
-
-#define OP_MAX               127
+#define OP_IsNull            118
+#define OP_NotNull           119
+#define OP_Negative          120
+#define OP_And               121
+#define OP_Or                122
+#define OP_Not               123
+#define OP_Concat            124
+#define OP_Noop              125
+#define OP_Function          126
+
+#define OP_MAX               126
 
 /*
 ** Prototypes for the VDBE interface.  See comments on the implementation
index 60221c497d0578be31e23e245dd6c35413b187ff..bc157fdf66e28e63f5f3fb71eb910d4a3da16a4e 100644 (file)
@@ -12,7 +12,7 @@
 # focus of this file is testing the LIMIT ... OFFSET ... clause
 #  of SELECT statements.
 #
-# $Id: limit.test,v 1.3 2002/06/14 22:38:43 drh Exp $
+# $Id: limit.test,v 1.4 2002/06/21 23:01:51 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -74,5 +74,47 @@ do_test limit-2.3 {
   }
 } 2
 
+do_test limit-3.1 {
+  execsql {
+    SELECT z FROM (SELECT y*10+x AS z FROM t1 ORDER BY x LIMIT 10)
+    ORDER BY z LIMIT 5;
+  }
+} {50 51 52 53 54}
+
+do_test limit-4.1 {
+  execsql {
+    BEGIN;
+    CREATE TABLE t3 AS SELECT x FROM t1 ORDER BY x LIMIT 10 OFFSET 1;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
+    END;
+    SELECT count(*) FROM t3;
+  }
+} {10240}
+do_test limit-4.2 {
+  execsql {
+    SELECT x FROM t3 LIMIT 2 OFFSET 10000
+  }
+} {10001 10002}
+do_test limit-4.3 {
+  execsql {
+    CREATE TABLE t4 AS SELECT x,
+       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
+       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
+       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
+       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x ||
+       'abcdefghijklmnopqrstuvwyxz ABCDEFGHIJKLMNOPQRSTUVWYXZ' || x AS y
+    FROM t3 LIMIT 1000;
+    SELECT x FROM t4 ORDER BY y DESC LIMIT 1 OFFSET 999;
+  }
+} {1}
 
 finish_test
index 2ded00d6d4c8a6c642f5c0b65a6f62bf221a1848..051b7b3025633b7940c72802f74532ea64365640 100644 (file)
@@ -13,7 +13,7 @@
 # This file implements tests for miscellanous features that were
 # left out of other test files.
 #
-# $Id: misc1.test,v 1.8 2002/06/09 01:16:01 drh Exp $
+# $Id: misc1.test,v 1.9 2002/06/21 23:01:51 drh Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -258,5 +258,4 @@ do_test misc1-9.1 {
   }
 } {0 {a 12345678901234567890 b 12345678911234567890 c 12345678921234567890}}
 
-
 finish_test