mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
clean up the VDBE stack properly. (CVS 636) FossilOrigin-Name: 9d5523107937e3700c76666fb058694babdd672c
This commit is contained in:
35
src/select.c
35
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.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
|
||||
|
@ -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 */
|
||||
|
120
src/vdbe.c
120
src/vdbe.c
@ -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.
|
||||
|
173
src/vdbe.h
173
src/vdbe.h
@ -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_MemIncr 44
|
||||
|
||||
#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_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 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_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 57
|
||||
#define OP_FileRead 58
|
||||
#define OP_FileColumn 59
|
||||
#define OP_FileOpen 58
|
||||
#define OP_FileRead 59
|
||||
#define OP_FileColumn 60
|
||||
|
||||
#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_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 69
|
||||
#define OP_SetFound 70
|
||||
#define OP_SetNotFound 71
|
||||
#define OP_SetFirst 72
|
||||
#define OP_SetNext 73
|
||||
#define OP_SetInsert 70
|
||||
#define OP_SetFound 71
|
||||
#define OP_SetNotFound 72
|
||||
#define OP_SetFirst 73
|
||||
#define OP_SetNext 74
|
||||
|
||||
#define OP_MakeRecord 74
|
||||
#define OP_MakeKey 75
|
||||
#define OP_MakeIdxKey 76
|
||||
#define OP_IncrKey 77
|
||||
#define OP_MakeRecord 75
|
||||
#define OP_MakeKey 76
|
||||
#define OP_MakeIdxKey 77
|
||||
#define OP_IncrKey 78
|
||||
|
||||
#define OP_Goto 78
|
||||
#define OP_If 79
|
||||
#define OP_IfNot 80
|
||||
#define OP_Halt 81
|
||||
#define OP_Goto 79
|
||||
#define OP_If 80
|
||||
#define OP_IfNot 81
|
||||
#define OP_Halt 82
|
||||
|
||||
#define OP_ColumnCount 82
|
||||
#define OP_ColumnName 83
|
||||
#define OP_Callback 84
|
||||
#define OP_NullCallback 85
|
||||
#define OP_ColumnCount 83
|
||||
#define OP_ColumnName 84
|
||||
#define OP_Callback 85
|
||||
#define OP_NullCallback 86
|
||||
|
||||
#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_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 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_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_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_Limit 126
|
||||
#define OP_LimitCk 127
|
||||
|
||||
|
||||
#define OP_MAX 127
|
||||
#define OP_MAX 126
|
||||
|
||||
/*
|
||||
** Prototypes for the VDBE interface. See comments on the implementation
|
||||
|
Reference in New Issue
Block a user