1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Fix for bugs #77 and #80: Rework the LIMIT mechanism to be reentrant and to

clean up the VDBE stack properly. (CVS 636)

FossilOrigin-Name: 9d5523107937e3700c76666fb058694babdd672c
This commit is contained in:
drh
2002-06-21 23:01:49 +00:00
parent 7aa128dbc5
commit d11d382c99
8 changed files with 218 additions and 189 deletions

View File

@@ -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) 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-21T13:09:17 D 2002-06-21T23:01:50
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
@@ -37,11 +37,11 @@ F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e
F src/parse.y 2285d8967d7334d52a2188089e5a881d73ba56f6 F src/parse.y 2285d8967d7334d52a2188089e5a881d73ba56f6
F src/printf.c 236ed7a79386feed4456fa728fff8be793f1547c F src/printf.c 236ed7a79386feed4456fa728fff8be793f1547c
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
F src/select.c 3eadcde4c74341d8ee7db69948cbcb16df9ae9fc F src/select.c 346da88a44aef311e932e95239dc0288fdcb10dd
F src/shell.c 1d22fe870ee852cfb975fd000dbe3973713d0a15 F src/shell.c 1d22fe870ee852cfb975fd000dbe3973713d0a15
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
F src/sqlite.h.in 7c8882e352cb70818cfaf9bdb5b1b3bee81ef144 F src/sqlite.h.in 7c8882e352cb70818cfaf9bdb5b1b3bee81ef144
F src/sqliteInt.h 16ccbf72dd823d5764b475353927410ec272305e F src/sqliteInt.h f283e5628174d7124c39968442e7adb5b95ea82c
F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
F src/tclsqlite.c 9300c9606a38bc0c75d6c0bc8a6197ab979353d1 F src/tclsqlite.c 9300c9606a38bc0c75d6c0bc8a6197ab979353d1
F src/test1.c 5cc4f0bbf38237e04e1b2077e285b41bfb4c4cbf F src/test1.c 5cc4f0bbf38237e04e1b2077e285b41bfb4c4cbf
@@ -52,8 +52,8 @@ F src/tokenize.c ac4c46f190346b87da54ec3e2605d160af80c619
F src/trigger.c 21342af6ac031fece39c8fc6eabd1739ca5327c1 F src/trigger.c 21342af6ac031fece39c8fc6eabd1739ca5327c1
F src/update.c 6f6a4dcd71cd9ff730b7f12c83de5498cde4924f F src/update.c 6f6a4dcd71cd9ff730b7f12c83de5498cde4924f
F src/util.c 876b259f9186e84b944b72e793dd3dad50e63e95 F src/util.c 876b259f9186e84b944b72e793dd3dad50e63e95
F src/vdbe.c c33572f803b853c50c22f84d6dfa6922ec79bf6b F src/vdbe.c 774f79483ce809b27c3bdb02afd7295cc3c7acd4
F src/vdbe.h 9b6e632bfa5d52507130f1ae456ef2c01bc0be7e F src/vdbe.h a9292f2b5fcecef924fa255fb74609e9cbc776c2
F src/where.c 1fdb7aca26c1963eb42615a95e0fc2978eec566a F src/where.c 1fdb7aca26c1963eb42615a95e0fc2978eec566a
F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1 F test/all.test e4d3821eeba751829b419cd47814bd20af4286d1
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578 F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
@@ -72,12 +72,12 @@ F test/insert2.test eb8481878a7f52ccb4e3346f87550f5afdd77f76
F test/intpkey.test 69a6a9b41e541f27a2ffcd20264fb35adc3c2680 F test/intpkey.test 69a6a9b41e541f27a2ffcd20264fb35adc3c2680
F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a
F test/join.test ea6a4097e4fcebbb16eac7ec819569e759336a74 F test/join.test ea6a4097e4fcebbb16eac7ec819569e759336a74
F test/limit.test 96b33e108e134b5cc674a660064229d15fa278b9 F test/limit.test 49b44e027a002c0ba336d723b448f07e05b04466
F test/lock.test 3fcfd46a73119f6a18094673328a32c7b3047a8f F test/lock.test 3fcfd46a73119f6a18094673328a32c7b3047a8f
F test/main.test c66b564554b770ee7fdbf6a66c0cd90329bc2c85 F test/main.test c66b564554b770ee7fdbf6a66c0cd90329bc2c85
F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd F test/malloc.test 7ba32a9ebd3aeed52ae4aaa6d42ca37e444536fd
F test/minmax.test 29bc5727c3e4c792d5c4745833dd4b505905819e F test/minmax.test 29bc5727c3e4c792d5c4745833dd4b505905819e
F test/misc1.test faae0b01cce45a75fe8011b1f462c3ef36fb9bda F test/misc1.test 18c74cdfa6cc920f1c51827ccb23a442c62caefb
F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162 F test/misuse.test a3aa2b18a97e4c409a1fcaff5151a4dd804a0162
F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30 F test/notnull.test b1f3e42fc475b0b5827b27b2e9b562081995ff30
F test/null.test 5c2b57307e4b6178aae825eb65ddbee01e76b0fd F test/null.test 5c2b57307e4b6178aae825eb65ddbee01e76b0fd
@@ -137,7 +137,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
P 2532792a5875f9cc0f7d8eaf90dd49d1f6025ca3 P 7936b0325024c81ed8d4bab192d7350d045ec999
R 3fe0ffaffb77713981828251190bdd81 R d15c924c28dce20794c50e0013aa8eb2
U drh U drh
Z 08d058b9c9d8b8b2fa6e6514672f1243 Z 7d39bfd0dd2f959041e3d2a9c3cd818e

View File

@@ -1 +1 @@
7936b0325024c81ed8d4bab192d7350d045ec999 9d5523107937e3700c76666fb058694babdd672c

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser ** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite. ** 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" #include "sqliteInt.h"
@@ -334,10 +334,12 @@ static int selectInnerLoop(
*/ */
if( pOrderBy==0 ){ if( pOrderBy==0 ){
if( p->nOffset>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 ){ if( p->nLimit>=0 ){
sqliteVdbeAddOp(v, OP_LimitCk, 0, iBreak); sqliteVdbeAddOp(v, OP_MemIncr, p->nLimit, iBreak);
} }
} }
@@ -483,10 +485,12 @@ static void generateSortTail(
sqliteVdbeAddOp(v, OP_Sort, 0, 0); sqliteVdbeAddOp(v, OP_Sort, 0, 0);
addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end); addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end);
if( p->nOffset>0 ){ 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 ){ if( p->nLimit>=0 ){
sqliteVdbeAddOp(v, OP_LimitCk, 0, end); sqliteVdbeAddOp(v, OP_MemIncr, p->nLimit, end);
} }
switch( eDest ){ switch( eDest ){
case SRT_Callback: { 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) ){ if( (pSub->isDistinct || pSub->nLimit>=0) && (pSrc->nSrc>1 || isAgg) ){
return 0; 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 /* If we reach this point, it means flattening is permitted for the
** i-th entry of the FROM clause in the outer query. ** i-th entry of the FROM clause in the outer query.
@@ -1722,10 +1726,21 @@ int sqliteSelect(
/* Set the limiter /* Set the limiter
*/ */
if( p->nLimit<=0 ){ if( p->nLimit<=0 ){
p->nLimit = -1;
p->nOffset = 0; p->nOffset = 0;
}else{ }else{
if( p->nOffset<0 ) p->nOffset = 0; int iMem = pParse->nMem++;
sqliteVdbeAddOp(v, OP_Limit, p->nLimit, p->nOffset); 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 /* Generate code for all sub-queries in the FROM clause

View File

@@ -11,7 +11,7 @@
************************************************************************* *************************************************************************
** Internal interface definitions for SQLite. ** 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 "sqlite.h"
#include "hash.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 ** 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 ** of the expression tree will have something to point to. zSelect is used
** to hold that copy. ** 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 { struct Select {
int isDistinct; /* True if the DISTINCT keyword is present */ int isDistinct; /* True if the DISTINCT keyword is present */

View File

@@ -30,7 +30,7 @@
** But other routines are also provided to help in building up ** But other routines are also provided to help in building up
** a program instruction by instruction. ** 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 "sqliteInt.h"
#include <ctype.h> #include <ctype.h>
@@ -248,8 +248,6 @@ struct Vdbe {
int nSet; /* Number of sets allocated */ int nSet; /* Number of sets allocated */
Set *aSet; /* An array of sets */ Set *aSet; /* An array of sets */
int nCallback; /* Number of callbacks invoked so far */ 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 */ int keylistStackDepth; /* The size of the "keylist" stack */
Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */ Keylist **keylistStack; /* The stack used by opcodes ListPush & ListPop */
}; };
@@ -1060,28 +1058,28 @@ static char *zOpName[] = { 0,
"Last", "Rewind", "Next", "Destroy", "Last", "Rewind", "Next", "Destroy",
"Clear", "CreateIndex", "CreateTable", "IntegrityCk", "Clear", "CreateIndex", "CreateTable", "IntegrityCk",
"IdxPut", "IdxDelete", "IdxRecno", "IdxGT", "IdxPut", "IdxDelete", "IdxRecno", "IdxGT",
"IdxGE", "MemLoad", "MemStore", "ListWrite", "IdxGE", "MemLoad", "MemStore", "MemIncr",
"ListRewind", "ListRead", "ListReset", "ListPush", "ListWrite", "ListRewind", "ListRead", "ListReset",
"ListPop", "SortPut", "SortMakeRec", "SortMakeKey", "ListPush", "ListPop", "SortPut", "SortMakeRec",
"Sort", "SortNext", "SortCallback", "SortReset", "SortMakeKey", "Sort", "SortNext", "SortCallback",
"FileOpen", "FileRead", "FileColumn", "AggReset", "SortReset", "FileOpen", "FileRead", "FileColumn",
"AggFocus", "AggNext", "AggSet", "AggGet", "AggReset", "AggFocus", "AggNext", "AggSet",
"AggFunc", "AggInit", "AggPush", "AggPop", "AggGet", "AggFunc", "AggInit", "AggPush",
"SetInsert", "SetFound", "SetNotFound", "SetFirst", "AggPop", "SetInsert", "SetFound", "SetNotFound",
"SetNext", "MakeRecord", "MakeKey", "MakeIdxKey", "SetFirst", "SetNext", "MakeRecord", "MakeKey",
"IncrKey", "Goto", "If", "IfNot", "MakeIdxKey", "IncrKey", "Goto", "If",
"Halt", "ColumnCount", "ColumnName", "Callback", "IfNot", "Halt", "ColumnCount", "ColumnName",
"NullCallback", "Integer", "String", "Pop", "Callback", "NullCallback", "Integer", "String",
"Dup", "Pull", "Push", "MustBeInt", "Pop", "Dup", "Pull", "Push",
"Add", "AddImm", "Subtract", "Multiply", "MustBeInt", "Add", "AddImm", "Subtract",
"Divide", "Remainder", "BitAnd", "BitOr", "Multiply", "Divide", "Remainder", "BitAnd",
"BitNot", "ShiftLeft", "ShiftRight", "AbsValue", "BitOr", "BitNot", "ShiftLeft", "ShiftRight",
"Eq", "Ne", "Lt", "Le", "AbsValue", "Eq", "Ne", "Lt",
"Gt", "Ge", "StrEq", "StrNe", "Le", "Gt", "Ge", "StrEq",
"StrLt", "StrLe", "StrGt", "StrGe", "StrNe", "StrLt", "StrLe", "StrGt",
"IsNull", "NotNull", "Negative", "And", "StrGe", "IsNull", "NotNull", "Negative",
"Or", "Not", "Concat", "Noop", "And", "Or", "Not", "Concat",
"Function", "Limit", "LimitCk", "Noop", "Function",
}; };
/* /*
@@ -1300,8 +1298,6 @@ int sqliteVdbeExec(
zStack = p->zStack; zStack = p->zStack;
aStack = p->aStack; aStack = p->aStack;
p->tos = -1; p->tos = -1;
p->iLimit = 0;
p->iOffset = 0;
/* Initialize the aggregrate hash table. /* Initialize the aggregrate hash table.
*/ */
@@ -4068,54 +4064,6 @@ case OP_IntegrityCk: {
break; 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 * * * /* Opcode: ListWrite * * *
** **
** Write the integer on the top of the stack ** Write the integer on the top of the stack
@@ -4675,6 +4623,28 @@ case OP_MemLoad: {
break; 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 * /* Opcode: AggReset * P2 *
** **
** Reset the aggregator so that it no longer contains any data. ** Reset the aggregator so that it no longer contains any data.

View File

@@ -15,7 +15,7 @@
** or VDBE. The VDBE implements an abstract machine that runs a ** or VDBE. The VDBE implements an abstract machine that runs a
** simple program to access and modify the underlying database. ** 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_ #ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_ #define _SQLITE_VDBE_H_
@@ -116,108 +116,105 @@ typedef struct VdbeOp VdbeOp;
#define OP_MemLoad 42 #define OP_MemLoad 42
#define OP_MemStore 43 #define OP_MemStore 43
#define OP_MemIncr 44
#define OP_ListWrite 44 #define OP_ListWrite 45
#define OP_ListRewind 45 #define OP_ListRewind 46
#define OP_ListRead 46 #define OP_ListRead 47
#define OP_ListReset 47 #define OP_ListReset 48
#define OP_ListPush 48 #define OP_ListPush 49
#define OP_ListPop 49 #define OP_ListPop 50
#define OP_SortPut 50 #define OP_SortPut 51
#define OP_SortMakeRec 51 #define OP_SortMakeRec 52
#define OP_SortMakeKey 52 #define OP_SortMakeKey 53
#define OP_Sort 53 #define OP_Sort 54
#define OP_SortNext 54 #define OP_SortNext 55
#define OP_SortCallback 55 #define OP_SortCallback 56
#define OP_SortReset 56 #define OP_SortReset 57
#define OP_FileOpen 57 #define OP_FileOpen 58
#define OP_FileRead 58 #define OP_FileRead 59
#define OP_FileColumn 59 #define OP_FileColumn 60
#define OP_AggReset 60 #define OP_AggReset 61
#define OP_AggFocus 61 #define OP_AggFocus 62
#define OP_AggNext 62 #define OP_AggNext 63
#define OP_AggSet 63 #define OP_AggSet 64
#define OP_AggGet 64 #define OP_AggGet 65
#define OP_AggFunc 65 #define OP_AggFunc 66
#define OP_AggInit 66 #define OP_AggInit 67
#define OP_AggPush 67 #define OP_AggPush 68
#define OP_AggPop 68 #define OP_AggPop 69
#define OP_SetInsert 69 #define OP_SetInsert 70
#define OP_SetFound 70 #define OP_SetFound 71
#define OP_SetNotFound 71 #define OP_SetNotFound 72
#define OP_SetFirst 72 #define OP_SetFirst 73
#define OP_SetNext 73 #define OP_SetNext 74
#define OP_MakeRecord 74 #define OP_MakeRecord 75
#define OP_MakeKey 75 #define OP_MakeKey 76
#define OP_MakeIdxKey 76 #define OP_MakeIdxKey 77
#define OP_IncrKey 77 #define OP_IncrKey 78
#define OP_Goto 78 #define OP_Goto 79
#define OP_If 79 #define OP_If 80
#define OP_IfNot 80 #define OP_IfNot 81
#define OP_Halt 81 #define OP_Halt 82
#define OP_ColumnCount 82 #define OP_ColumnCount 83
#define OP_ColumnName 83 #define OP_ColumnName 84
#define OP_Callback 84 #define OP_Callback 85
#define OP_NullCallback 85 #define OP_NullCallback 86
#define OP_Integer 86 #define OP_Integer 87
#define OP_String 87 #define OP_String 88
#define OP_Pop 88 #define OP_Pop 89
#define OP_Dup 89 #define OP_Dup 90
#define OP_Pull 90 #define OP_Pull 91
#define OP_Push 91 #define OP_Push 92
#define OP_MustBeInt 92 #define OP_MustBeInt 93
#define OP_Add 93 #define OP_Add 94
#define OP_AddImm 94 #define OP_AddImm 95
#define OP_Subtract 95 #define OP_Subtract 96
#define OP_Multiply 96 #define OP_Multiply 97
#define OP_Divide 97 #define OP_Divide 98
#define OP_Remainder 98 #define OP_Remainder 99
#define OP_BitAnd 99 #define OP_BitAnd 100
#define OP_BitOr 100 #define OP_BitOr 101
#define OP_BitNot 101 #define OP_BitNot 102
#define OP_ShiftLeft 102 #define OP_ShiftLeft 103
#define OP_ShiftRight 103 #define OP_ShiftRight 104
#define OP_AbsValue 104 #define OP_AbsValue 105
/* Note: The code generator assumes that OP_XX+6==OP_StrXX */ /* Note: The code generator assumes that OP_XX+6==OP_StrXX */
#define OP_Eq 105 #define OP_Eq 106
#define OP_Ne 106 #define OP_Ne 107
#define OP_Lt 107 #define OP_Lt 108
#define OP_Le 108 #define OP_Le 109
#define OP_Gt 109 #define OP_Gt 110
#define OP_Ge 110 #define OP_Ge 111
#define OP_StrEq 111 #define OP_StrEq 112
#define OP_StrNe 112 #define OP_StrNe 113
#define OP_StrLt 113 #define OP_StrLt 114
#define OP_StrLe 114 #define OP_StrLe 115
#define OP_StrGt 115 #define OP_StrGt 116
#define OP_StrGe 116 #define OP_StrGe 117
/* Note: the code generator assumes that OP_XX+6==OP_StrXX */ /* Note: the code generator assumes that OP_XX+6==OP_StrXX */
#define OP_IsNull 117 #define OP_IsNull 118
#define OP_NotNull 118 #define OP_NotNull 119
#define OP_Negative 119 #define OP_Negative 120
#define OP_And 120 #define OP_And 121
#define OP_Or 121 #define OP_Or 122
#define OP_Not 122 #define OP_Not 123
#define OP_Concat 123 #define OP_Concat 124
#define OP_Noop 124 #define OP_Noop 125
#define OP_Function 125 #define OP_Function 126
#define OP_Limit 126 #define OP_MAX 126
#define OP_LimitCk 127
#define OP_MAX 127
/* /*
** Prototypes for the VDBE interface. See comments on the implementation ** Prototypes for the VDBE interface. See comments on the implementation

View File

@@ -12,7 +12,7 @@
# focus of this file is testing the LIMIT ... OFFSET ... clause # focus of this file is testing the LIMIT ... OFFSET ... clause
# of SELECT statements. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@@ -74,5 +74,47 @@ do_test limit-2.3 {
} }
} 2 } 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 finish_test

View File

@@ -13,7 +13,7 @@
# This file implements tests for miscellanous features that were # This file implements tests for miscellanous features that were
# left out of other test files. # 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] set testdir [file dirname $argv0]
source $testdir/tester.tcl source $testdir/tester.tcl
@@ -258,5 +258,4 @@ do_test misc1-9.1 {
} }
} {0 {a 12345678901234567890 b 12345678911234567890 c 12345678921234567890}} } {0 {a 12345678901234567890 b 12345678911234567890 c 12345678921234567890}}
finish_test finish_test