Get LIMIT and OFFSET working again for negative limits and offsets.
Ticket #1586. (CVS 2889) FossilOrigin-Name: b2ac0be07ec76ab23b7e5b800c0bc62d0bc97f4b
This commit is contained in:
parent
6f58f7069b
commit
15007a99e4
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
||||
C Remove\ssome\scruft\sfrom\sthe\sVDBE.\s\sBring\scomments\sup\sto\sdate.\s(CVS\s2888)
|
||||
D 2006-01-08T05:26:41
|
||||
C Get\sLIMIT\sand\sOFFSET\sworking\sagain\sfor\snegative\slimits\sand\soffsets.\nTicket\s#1586.\s(CVS\s2889)
|
||||
D 2006-01-08T18:10:18
|
||||
F Makefile.in c79fbdaa264c6afcd435f2fb492551de5a8cf80d
|
||||
F Makefile.linux-gcc aee18d8a05546dcf1888bd4547e442008a49a092
|
||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
|
||||
@ -31,7 +31,7 @@ F sqlite3.1 6be1ad09113570e1fc8dcaff84c9b0b337db5ffc
|
||||
F sqlite3.def c413e514217736884254739a105c8c942fdf0c2f
|
||||
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
|
||||
F src/alter.c e9deb3f4fd7c663a0d1f235d541bc5ea1f2cfa8b
|
||||
F src/analyze.c 82e334a1be4bb6961387a4c1441aed90fe9a2d8a
|
||||
F src/analyze.c fd2fe03b10dd5058747083362e56dec5bd9c4e5c
|
||||
F src/attach.c 4a04ffcd17357a7848aa17c12c955d109f533bd0
|
||||
F src/auth.c cdec356a5cd8b217c346f816c5912221537fe87f
|
||||
F src/btree.c 902d0d3f5c32b665a2184be5997ae0597bd47d56
|
||||
@ -46,7 +46,7 @@ F src/expr.c ed2a272c7afd63232ca04881159ce2366266e35d
|
||||
F src/func.c 5e4204b2ebe89de5228d78eef9352a0ed253f4c0
|
||||
F src/hash.c 8747cf51d12de46512880dfcf1b68b4e24072863
|
||||
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
|
||||
F src/insert.c 66f2e745bd3db551bed9756c7d7df191f7b72ba9
|
||||
F src/insert.c 59f8c1f95c3d27e07f4b4a962bef54a34655786c
|
||||
F src/legacy.c 59757d857ab95fcbb0ac27692d3201e35f093dd7
|
||||
F src/main.c 8c2d64f1460200d79d7de4605a9489c0506be5fe
|
||||
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
|
||||
@ -62,11 +62,11 @@ F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
|
||||
F src/pager.c f06b85eb1e43bb2e6a7a5108ac8346576b4b78fa
|
||||
F src/pager.h e0acb095b3ad0bca48f2ab00c87346665643f64f
|
||||
F src/parse.y 83df51fea35f68f7e07384d75dce83d1ed30434c
|
||||
F src/pragma.c ae8b135531e7a4d692c60bd909c819d0b3fc588a
|
||||
F src/pragma.c 7358baf8e2be14a0f3d71e7afae41e430d76b054
|
||||
F src/prepare.c fef89dc92703d345251142af966b60e44a66cfc5
|
||||
F src/printf.c f47a2f4b5387cd2ebb12e9117a1a5d6bd9a2b812
|
||||
F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
|
||||
F src/select.c ad632ffd92ac280d9f8565fe27256e0c4e94c2c9
|
||||
F src/select.c 48d3ecfb1bf271f0540d3534bdfd8487d6a4b9ee
|
||||
F src/shell.c 66b073375efbdee19045e7e0cd38b85f9aff71da
|
||||
F src/sqlite.h.in ba3a29daa6a16e054191ccb384a981964e882a1d
|
||||
F src/sqliteInt.h 40c3511c05df83c7c1c244d0432baa9497feee4d
|
||||
@ -84,7 +84,7 @@ F src/update.c 29ba0385c8639803cd8e6e616e99096a0bc10443
|
||||
F src/utf.c b7bffac4260177ae7f83c01d025fe0f5ed70ce71
|
||||
F src/util.c 8a3ef3c1b345cdadcee33ce4537c63bb0fda0ed8
|
||||
F src/vacuum.c a7301804d4f849da0ce9d869219c71c6d621c34e
|
||||
F src/vdbe.c 21a1cb8500e5482aa4b670ce4788b7474d3b8bb7
|
||||
F src/vdbe.c 1aee0e9d410e1f633e8c1fb247731af3566fc98c
|
||||
F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13
|
||||
F src/vdbeInt.h 5451cf71f229e366ac543607c0a17f36e5737ea9
|
||||
F src/vdbeapi.c 7335569b1bad946ba53892384b4b1534e877b1ee
|
||||
@ -177,7 +177,7 @@ F test/journal1.test 36f2d1bb9bf03f790f43fbdb439e44c0657fab19
|
||||
F test/lastinsert.test 9d7241f562d7adcf61730de83176417d7e30d76b
|
||||
F test/laststmtchanges.test 19a6d0c11f7a31dc45465b495f7b845a62cbec17
|
||||
F test/like.test 145382e6a1f3d2edf266ca7d0236ab1b7c0ba66f
|
||||
F test/limit.test 39f084f4e5f11e0b984cb517b56867cbf88df156
|
||||
F test/limit.test 4b538057d5b5c7ca10ec8d40d6c567e886c90bdd
|
||||
F test/lock.test 9b7afcb24f53d24da502abb33daaad2cd6d44107
|
||||
F test/lock2.test d83ba79d3c4fffdb5b926c7d8ca7a36c34288a55
|
||||
F test/lock3.test 615111293cf32aa2ed16d01c6611737651c96fb9
|
||||
@ -335,7 +335,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
|
||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
|
||||
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
|
||||
P 55e703ecac6e03d7364c2d919ba18d7293d6b7f6
|
||||
R b966bf179439ff438aedbc30041f68e4
|
||||
P 41aef6496a10c81e1095408dc8f69740d6ea7627
|
||||
R f8372c9e0611d6543d33717d70ffa331
|
||||
U drh
|
||||
Z 3ef314255d1b0a31cdba3fda0e06ec3c
|
||||
Z 94880a5caf5e837e862337f4a0188bc2
|
||||
|
@ -1 +1 @@
|
||||
41aef6496a10c81e1095408dc8f69740d6ea7627
|
||||
b2ac0be07ec76ab23b7e5b800c0bc62d0bc97f4b
|
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code associated with the ANALYZE command.
|
||||
**
|
||||
** @(#) $Id: analyze.c,v 1.13 2006/01/07 13:21:04 danielk1977 Exp $
|
||||
** @(#) $Id: analyze.c,v 1.14 2006/01/08 18:10:18 drh Exp $
|
||||
*/
|
||||
#ifndef SQLITE_OMIT_ANALYZE
|
||||
#include "sqliteInt.h"
|
||||
@ -152,7 +152,7 @@ static void analyzeOneTable(
|
||||
endOfLoop = sqlite3VdbeMakeLabel(v);
|
||||
sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, endOfLoop);
|
||||
topOfLoop = sqlite3VdbeCurrentAddr(v);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, iMem, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem);
|
||||
for(i=0; i<nCol; i++){
|
||||
sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
|
||||
sqlite3VdbeAddOp(v, OP_MemLoad, iMem+nCol+i+1, 0);
|
||||
@ -160,7 +160,7 @@ static void analyzeOneTable(
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, endOfLoop);
|
||||
for(i=0; i<nCol; i++){
|
||||
addr = sqlite3VdbeAddOp(v, OP_MemIncr, iMem+i+1, 0);
|
||||
addr = sqlite3VdbeAddOp(v, OP_MemIncr, 1, iMem+i+1);
|
||||
sqlite3VdbeChangeP2(v, topOfLoop + 3*i + 3, addr);
|
||||
sqlite3VdbeAddOp(v, OP_Column, iIdxCur, i);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, iMem+nCol+i+1, 1);
|
||||
|
@ -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.153 2006/01/07 13:21:04 danielk1977 Exp $
|
||||
** $Id: insert.c,v 1.154 2006/01/08 18:10:18 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -636,7 +636,7 @@ void sqlite3Insert(
|
||||
/* Update the count of rows that are inserted
|
||||
*/
|
||||
if( (db->flags & SQLITE_CountRows)!=0 ){
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, iCntMem, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, 1, iCntMem);
|
||||
}
|
||||
|
||||
if( triggers_exist ){
|
||||
|
12
src/pragma.c
12
src/pragma.c
@ -11,7 +11,7 @@
|
||||
*************************************************************************
|
||||
** This file contains code used to implement the PRAGMA command.
|
||||
**
|
||||
** $Id: pragma.c,v 1.109 2006/01/06 14:32:20 drh Exp $
|
||||
** $Id: pragma.c,v 1.110 2006/01/08 18:10:18 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -686,7 +686,7 @@ void sqlite3Pragma(
|
||||
sqlite3VdbeAddOp(v, OP_Pull, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Concat, 0, 1);
|
||||
sqlite3VdbeAddOp(v, OP_Callback, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0);
|
||||
|
||||
/* Make sure all the indices are constructed correctly.
|
||||
*/
|
||||
@ -700,11 +700,11 @@ void sqlite3Pragma(
|
||||
sqlite3OpenTableAndIndices(pParse, pTab, 1, OP_OpenRead);
|
||||
sqlite3VdbeAddOp(v, OP_MemInt, 0, 1);
|
||||
loopTop = sqlite3VdbeAddOp(v, OP_Rewind, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, 1, 1);
|
||||
for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
|
||||
int jmp2;
|
||||
static const VdbeOpList idxErr[] = {
|
||||
{ OP_MemIncr, 0, 0, 0},
|
||||
{ OP_MemIncr, 1, 0, 0},
|
||||
{ OP_String8, 0, 0, "rowid "},
|
||||
{ OP_Rowid, 1, 0, 0},
|
||||
{ OP_String8, 0, 0, " missing from index "},
|
||||
@ -724,12 +724,12 @@ void sqlite3Pragma(
|
||||
static const VdbeOpList cntIdx[] = {
|
||||
{ OP_MemInt, 0, 2, 0},
|
||||
{ OP_Rewind, 0, 0, 0}, /* 1 */
|
||||
{ OP_MemIncr, 2, 0, 0},
|
||||
{ OP_MemIncr, 1, 2, 0},
|
||||
{ OP_Next, 0, 0, 0}, /* 3 */
|
||||
{ OP_MemLoad, 1, 0, 0},
|
||||
{ OP_MemLoad, 2, 0, 0},
|
||||
{ OP_Eq, 0, 0, 0}, /* 6 */
|
||||
{ OP_MemIncr, 0, 0, 0},
|
||||
{ OP_MemIncr, 1, 0, 0},
|
||||
{ OP_String8, 0, 0, "wrong # of entries in index "},
|
||||
{ OP_String8, 0, 0, 0}, /* 9 */
|
||||
{ OP_Concat, 0, 0, 0},
|
||||
|
61
src/select.c
61
src/select.c
@ -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.287 2006/01/08 05:02:55 drh Exp $
|
||||
** $Id: select.c,v 1.288 2006/01/08 18:10:18 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
|
||||
@ -363,14 +363,14 @@ static void pushOntoSorter(
|
||||
sqlite3VdbeAddOp(v, OP_MakeRecord, pOrderBy->nExpr + 2, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IdxInsert, pOrderBy->iECursor, 0);
|
||||
if( pSelect->iLimit>=0 ){
|
||||
int addr1;
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, pSelect->iLimit+1, 0);
|
||||
addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, pSelect->iLimit+1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
|
||||
int addr1, addr2;
|
||||
addr1 = sqlite3VdbeAddOp(v, OP_IfMemZero, pSelect->iLimit+1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, -1, pSelect->iLimit+1);
|
||||
addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp(v, OP_Last, pOrderBy->iECursor, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Delete, pOrderBy->iECursor, 0);
|
||||
sqlite3VdbeJumpHere(v, addr1+1);
|
||||
sqlite3VdbeJumpHere(v, addr2);
|
||||
pSelect->iLimit = -1;
|
||||
}
|
||||
}
|
||||
@ -385,15 +385,15 @@ static void codeOffset(
|
||||
int nPop /* Number of times to pop stack when jumping */
|
||||
){
|
||||
if( p->iOffset>=0 && iContinue!=0 ){
|
||||
int addr = sqlite3VdbeCurrentAddr(v) + 3;
|
||||
if( nPop>0 ) addr++;
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, p->iOffset, 0);
|
||||
sqlite3VdbeAddOp(v, OP_IfMemPos, p->iOffset, addr);
|
||||
int addr;
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iOffset);
|
||||
addr = sqlite3VdbeAddOp(v, OP_IfMemNeg, p->iOffset, addr);
|
||||
if( nPop>0 ){
|
||||
sqlite3VdbeAddOp(v, OP_Pop, nPop, 0);
|
||||
}
|
||||
sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);
|
||||
VdbeComment((v, "# skip OFFSET records"));
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -617,7 +617,7 @@ static int selectInnerLoop(
|
||||
/* Jump to the end of the loop if the LIMIT is reached.
|
||||
*/
|
||||
if( p->iLimit>=0 && pOrderBy==0 ){
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit);
|
||||
sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, iBreak);
|
||||
}
|
||||
return 0;
|
||||
@ -739,7 +739,7 @@ static void generateSortTail(
|
||||
/* Jump to the end of the loop when the LIMIT is reached
|
||||
*/
|
||||
if( p->iLimit>=0 ){
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, p->iLimit, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit);
|
||||
sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, brk);
|
||||
}
|
||||
|
||||
@ -1365,6 +1365,7 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Compute the iLimit and iOffset fields of the SELECT based on the
|
||||
** pLimit and pOffset expressions. pLimit and pOffset hold the expressions
|
||||
@ -1384,6 +1385,11 @@ Vdbe *sqlite3GetVdbe(Parse *pParse){
|
||||
** SELECT statements.
|
||||
*/
|
||||
static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
Vdbe *v;
|
||||
int iLimit;
|
||||
int iOffset;
|
||||
int addr1, addr2;
|
||||
|
||||
/*
|
||||
** "LIMIT -1" always shows all rows. There is some
|
||||
** contraversy about what the correct behavior should be.
|
||||
@ -1391,36 +1397,41 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
|
||||
** no rows.
|
||||
*/
|
||||
if( p->pLimit ){
|
||||
int iMem = pParse->nMem;
|
||||
p->iLimit = iLimit = pParse->nMem;
|
||||
pParse->nMem += 2;
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v==0 ) return;
|
||||
sqlite3ExprCode(pParse, p->pLimit);
|
||||
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, iMem, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, iLimit, 0);
|
||||
VdbeComment((v, "# LIMIT counter"));
|
||||
sqlite3VdbeAddOp(v, OP_IfMemZero, iMem, iBreak);
|
||||
p->iLimit = iMem;
|
||||
sqlite3VdbeAddOp(v, OP_IfMemZero, iLimit, iBreak);
|
||||
}
|
||||
if( p->pOffset ){
|
||||
int iMem = pParse->nMem++;
|
||||
Vdbe *v = sqlite3GetVdbe(pParse);
|
||||
p->iOffset = iOffset = pParse->nMem++;
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v==0 ) return;
|
||||
sqlite3ExprCode(pParse, p->pOffset);
|
||||
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Negative, 0, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, iMem, p->pLimit==0);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, iOffset, p->pLimit==0);
|
||||
VdbeComment((v, "# OFFSET counter"));
|
||||
addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iOffset, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
if( p->pLimit ){
|
||||
sqlite3VdbeAddOp(v, OP_Add, 0, 0);
|
||||
}
|
||||
p->iOffset = iMem;
|
||||
}
|
||||
if( p->pLimit ){
|
||||
Vdbe *v = pParse->pVdbe;
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, p->iLimit+1, 1);
|
||||
addr1 = sqlite3VdbeAddOp(v, OP_IfMemPos, iLimit, 0);
|
||||
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
|
||||
sqlite3VdbeAddOp(v, OP_MemInt, -1, iLimit+1);
|
||||
addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
|
||||
sqlite3VdbeJumpHere(v, addr1);
|
||||
sqlite3VdbeAddOp(v, OP_MemStore, iLimit+1, 1);
|
||||
VdbeComment((v, "# LIMIT+OFFSET"));
|
||||
sqlite3VdbeJumpHere(v, addr2);
|
||||
}
|
||||
}
|
||||
|
||||
|
33
src/vdbe.c
33
src/vdbe.c
@ -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.517 2006/01/08 05:26:41 drh Exp $
|
||||
** $Id: vdbe.c,v 1.518 2006/01/08 18:10:18 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@ -4277,28 +4277,26 @@ case OP_MemMax: { /* no-push */
|
||||
}
|
||||
#endif /* SQLITE_OMIT_AUTOINCREMENT */
|
||||
|
||||
/* Opcode: MemIncr P1 * *
|
||||
/* Opcode: MemIncr P1 P2 *
|
||||
**
|
||||
** Increment the integer valued memory cell P1 by 1.
|
||||
** Increment the integer valued memory cell P2 by the value in P1.
|
||||
**
|
||||
** It is illegal to use this instruction on a memory cell that does
|
||||
** not contain an integer. An assertion fault will result if you try.
|
||||
*/
|
||||
case OP_MemIncr: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
int i = pOp->p2;
|
||||
Mem *pMem;
|
||||
assert( i>=0 && i<p->nMem );
|
||||
pMem = &p->aMem[i];
|
||||
assert( pMem->flags==MEM_Int );
|
||||
pMem->i++;
|
||||
assert( pOp->p2==0 );
|
||||
pMem->i += pOp->p1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IfMemPos P1 P2 *
|
||||
**
|
||||
** If the value of memory cell P1 is 1 or greater, jump to P2. If
|
||||
** the memory cell holds an integer of 0 or less.
|
||||
** If the value of memory cell P1 is 1 or greater, jump to P2.
|
||||
**
|
||||
** It is illegal to use this instruction on a memory cell that does
|
||||
** not contain an integer. An assertion fault will result if you try.
|
||||
@ -4315,6 +4313,25 @@ case OP_IfMemPos: { /* no-push */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IfMemNeg P1 P2 *
|
||||
**
|
||||
** If the value of memory cell P1 is less than zero, jump to P2.
|
||||
**
|
||||
** It is illegal to use this instruction on a memory cell that does
|
||||
** not contain an integer. An assertion fault will result if you try.
|
||||
*/
|
||||
case OP_IfMemNeg: { /* no-push */
|
||||
int i = pOp->p1;
|
||||
Mem *pMem;
|
||||
assert( i>=0 && i<p->nMem );
|
||||
pMem = &p->aMem[i];
|
||||
assert( pMem->flags==MEM_Int );
|
||||
if( pMem->i<0 ){
|
||||
pc = pOp->p2 - 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* Opcode: IfMemZero P1 P2 *
|
||||
**
|
||||
** If the value of memory cell P1 is exactly 0, jump to P2.
|
||||
|
@ -12,7 +12,7 @@
|
||||
# focus of this file is testing the LIMIT ... OFFSET ... clause
|
||||
# of SELECT statements.
|
||||
#
|
||||
# $Id: limit.test,v 1.25 2005/09/08 10:37:01 drh Exp $
|
||||
# $Id: limit.test,v 1.26 2006/01/08 18:10:18 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -44,6 +44,18 @@ do_test limit-1.2.2 {
|
||||
execsql {SELECT x FROM t1 ORDER BY x LIMIT 5 OFFSET 2}
|
||||
} {2 3 4 5 6}
|
||||
do_test limit-1.2.3 {
|
||||
execsql {SELECT x FROM t1 ORDER BY x+1 LIMIT 5 OFFSET -2}
|
||||
} {0 1 2 3 4}
|
||||
do_test limit-1.2.4 {
|
||||
execsql {SELECT x FROM t1 ORDER BY x+1 LIMIT 2, -5}
|
||||
} {2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}
|
||||
do_test limit-1.2.5 {
|
||||
execsql {SELECT x FROM t1 ORDER BY x+1 LIMIT -2, 5}
|
||||
} {0 1 2 3 4}
|
||||
do_test limit-1.2.6 {
|
||||
execsql {SELECT x FROM t1 ORDER BY x+1 LIMIT -2, -5}
|
||||
} {0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31}
|
||||
do_test limit-1.2.7 {
|
||||
execsql {SELECT x FROM t1 ORDER BY x LIMIT 2, 5}
|
||||
} {2 3 4 5 6}
|
||||
do_test limit-1.3 {
|
||||
|
Loading…
x
Reference in New Issue
Block a user