mirror of
				https://github.com/sqlite/sqlite.git
				synced 2025-11-03 16:53:36 +03:00 
			
		
		
		
	Reduce the space allocated for the runtime virtual machine stack. (CVS 2428)
FossilOrigin-Name: 7d6818da33a87076d1faf35ffc15a3aada0533b3
This commit is contained in:
		
							
								
								
									
										22
									
								
								manifest
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								manifest
									
									
									
									
									
								
							@@ -1,5 +1,5 @@
 | 
				
			|||||||
C Add\sthe\sSQLITE_OMIT_TEMPDB\scompile\stime\smacro.\s(CVS\s2427)
 | 
					C Reduce\sthe\sspace\sallocated\sfor\sthe\sruntime\svirtual\smachine\sstack.\s(CVS\s2428)
 | 
				
			||||||
D 2005-03-29T03:10:59
 | 
					D 2005-03-29T08:26:13
 | 
				
			||||||
F Makefile.in 5c00d0037104de2a50ac7647a5f12769795957a3
 | 
					F Makefile.in 5c00d0037104de2a50ac7647a5f12769795957a3
 | 
				
			||||||
F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
 | 
					F Makefile.linux-gcc 06be33b2a9ad4f005a5f42b22c4a19dab3cbb5c7
 | 
				
			||||||
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
 | 
					F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
 | 
				
			||||||
@@ -19,7 +19,7 @@ F ltmain.sh f6b283068efa69f06eb8aa1fe4bddfdbdeb35826
 | 
				
			|||||||
F main.mk 3acc5ae52addd43fd1858fe99fca54a49bca6a56
 | 
					F main.mk 3acc5ae52addd43fd1858fe99fca54a49bca6a56
 | 
				
			||||||
F mkdll.sh 5ec23622515d5bf8969404e80cfb5e220ddf0512
 | 
					F mkdll.sh 5ec23622515d5bf8969404e80cfb5e220ddf0512
 | 
				
			||||||
F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
 | 
					F mkopcodec.awk bd46ad001c98dfbab07b1713cb8e692fa0e5415d
 | 
				
			||||||
F mkopcodeh.awk e4d010870a3e98fd4323635c31565a3ca8584741
 | 
					F mkopcodeh.awk d3d6dfcef5a7b69398627aec581d1ec52561517d
 | 
				
			||||||
F mkso.sh 125868def279650a07d3f0f5e8476fecf99613fd
 | 
					F mkso.sh 125868def279650a07d3f0f5e8476fecf99613fd
 | 
				
			||||||
F publish.sh ed0aba4ffdfadb36597d03ce8efdae96efc038cb
 | 
					F publish.sh ed0aba4ffdfadb36597d03ce8efdae96efc038cb
 | 
				
			||||||
F spec.template b2f6c4e488cbc3b993a57deba22cbc36203c4da3
 | 
					F spec.template b2f6c4e488cbc3b993a57deba22cbc36203c4da3
 | 
				
			||||||
@@ -75,11 +75,11 @@ F src/update.c 42823d00865c9fe4f01b3c62647858726345a28e
 | 
				
			|||||||
F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
 | 
					F src/utf.c bda5eb85039ef16f2d17004c1e18c96e1ab0a80c
 | 
				
			||||||
F src/util.c 02bc2750336b021b3f10e61538f665c4b0033b5d
 | 
					F src/util.c 02bc2750336b021b3f10e61538f665c4b0033b5d
 | 
				
			||||||
F src/vacuum.c 5cf598003191bd91c17a64742bad8e46241698a8
 | 
					F src/vacuum.c 5cf598003191bd91c17a64742bad8e46241698a8
 | 
				
			||||||
F src/vdbe.c e93a28aaa2a59c398ae243c2dc3b2da10cf1c5d2
 | 
					F src/vdbe.c 68c8f34cbf7c05418c93e900d46f81b09500353a
 | 
				
			||||||
F src/vdbe.h 7f586cb6d6b57764e5aac1f87107d6a95ddce24c
 | 
					F src/vdbe.h 7f586cb6d6b57764e5aac1f87107d6a95ddce24c
 | 
				
			||||||
F src/vdbeInt.h e80721cd8ff611789e20743eec43363a9fb5a48e
 | 
					F src/vdbeInt.h 39beecdfb017d3e042fe60974691abd573a5c5a2
 | 
				
			||||||
F src/vdbeapi.c 467caa6e6fb9247528b1c7ab9132ae1b4748e8ac
 | 
					F src/vdbeapi.c 467caa6e6fb9247528b1c7ab9132ae1b4748e8ac
 | 
				
			||||||
F src/vdbeaux.c 0932f570d276992c7b3ee989589b6ff9056f97e7
 | 
					F src/vdbeaux.c b28883d9efc9d4c1ec26c0d2473d5d8febc8178e
 | 
				
			||||||
F src/vdbemem.c 4e853ce3151eaf7906150da85a1b3ce1fe5e8da8
 | 
					F src/vdbemem.c 4e853ce3151eaf7906150da85a1b3ce1fe5e8da8
 | 
				
			||||||
F src/where.c c4b227458e8993decb515ed9a2fe2d4f5f8e3125
 | 
					F src/where.c c4b227458e8993decb515ed9a2fe2d4f5f8e3125
 | 
				
			||||||
F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
 | 
					F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42
 | 
				
			||||||
@@ -173,7 +173,7 @@ F test/pagesize.test 1b826d1608fd86d2303aa895b5586052ad07eba1
 | 
				
			|||||||
F test/pragma.test effcf2f0dea35223cbaa6bf40c47d0796ba39e40
 | 
					F test/pragma.test effcf2f0dea35223cbaa6bf40c47d0796ba39e40
 | 
				
			||||||
F test/printf.test 92ba4c510b4fc61120ffa4a01820446ed917ae57
 | 
					F test/printf.test 92ba4c510b4fc61120ffa4a01820446ed917ae57
 | 
				
			||||||
F test/progress.test 16496001da445e6534afb94562c286708316d82f x
 | 
					F test/progress.test 16496001da445e6534afb94562c286708316d82f x
 | 
				
			||||||
F test/quick.test e9fdedf06bd06ff22fcbf6895c4f62fcbeb9e6b4
 | 
					F test/quick.test a94d12658a2b590c1a5be580bef09bbb04c1266b
 | 
				
			||||||
F test/quote.test 6d75cf635d93ba2484dc9cb378d88cbae9dc2c62
 | 
					F test/quote.test 6d75cf635d93ba2484dc9cb378d88cbae9dc2c62
 | 
				
			||||||
F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b
 | 
					F test/reindex.test 38b138abe36bf9a08c791ed44d9f76cd6b97b78b
 | 
				
			||||||
F test/rollback.test 94cd981ee3a627d9f6466f69dcf1f7dbfe695d7a
 | 
					F test/rollback.test 94cd981ee3a627d9f6466f69dcf1f7dbfe695d7a
 | 
				
			||||||
@@ -221,7 +221,7 @@ F tool/lemon.c c88936c67f6411608db8fa4254d254f509fa40f6
 | 
				
			|||||||
F tool/lempar.c e8b0eb00a6b905ce2ebd55965ed243574482cd5f
 | 
					F tool/lempar.c e8b0eb00a6b905ce2ebd55965ed243574482cd5f
 | 
				
			||||||
F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133
 | 
					F tool/memleak.awk 4e7690a51bf3ed757e611273d43fe3f65b510133
 | 
				
			||||||
F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
 | 
					F tool/memleak2.awk 9cc20c8e8f3c675efac71ea0721ee6874a1566e8
 | 
				
			||||||
F tool/memleak3.tcl 2b1ab290badf3b26f9ba433baf7fad8def14aea8
 | 
					F tool/memleak3.tcl 009da0ea82dc5893edca76cf1a21fb7260e9412e
 | 
				
			||||||
F tool/mkkeywordhash.c 02ac5c523fd6d55364cd70aded5c36ba6651a6bf
 | 
					F tool/mkkeywordhash.c 02ac5c523fd6d55364cd70aded5c36ba6651a6bf
 | 
				
			||||||
F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
 | 
					F tool/mkopts.tcl 66ac10d240cc6e86abd37dc908d50382f84ff46e x
 | 
				
			||||||
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
 | 
					F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
 | 
				
			||||||
@@ -278,7 +278,7 @@ F www/tclsqlite.tcl e73f8f8e5f20e8277619433f7970060ab01088fc
 | 
				
			|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 | 
					F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 | 
				
			||||||
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 | 
					F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 | 
				
			||||||
F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
 | 
					F www/whentouse.tcl 528299b8316726dbcc5548e9aa0648c8b1bd055b
 | 
				
			||||||
P 78df3d040443414ae5b440eeabc0c8c205ab311d
 | 
					P c41d55443c2dd532147962b87f542fb7d37075fd
 | 
				
			||||||
R ab70e88fa1e907bd768a36809abb74cd
 | 
					R d1e86050613dbac2624d4c64006d314d
 | 
				
			||||||
U danielk1977
 | 
					U danielk1977
 | 
				
			||||||
Z a20882d0dd8ba8be64666597fc85c766
 | 
					Z d987ab454820e190643b62f4a4339773
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1 +1 @@
 | 
				
			|||||||
c41d55443c2dd532147962b87f542fb7d37075fd
 | 
					7d6818da33a87076d1faf35ffc15a3aada0533b3
 | 
				
			||||||
@@ -24,6 +24,7 @@
 | 
				
			|||||||
# the total library smaller.
 | 
					# the total library smaller.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Remember the TK_ values from the parse.h file
 | 
					# Remember the TK_ values from the parse.h file
 | 
				
			||||||
/^#define TK_/ {
 | 
					/^#define TK_/ {
 | 
				
			||||||
  tk[$2] = $3
 | 
					  tk[$2] = $3
 | 
				
			||||||
@@ -35,11 +36,16 @@
 | 
				
			|||||||
  gsub(/:/,"",name)
 | 
					  gsub(/:/,"",name)
 | 
				
			||||||
  gsub("\r","",name)
 | 
					  gsub("\r","",name)
 | 
				
			||||||
  op[name] = -1
 | 
					  op[name] = -1
 | 
				
			||||||
  for(i=3; i<NF-2; i++){
 | 
					  for(i=3; i<NF; i++){
 | 
				
			||||||
    if($i=="same" && $(i+1)=="as"){
 | 
					    if($i=="same" && $(i+1)=="as"){
 | 
				
			||||||
      op[name] = tk[$(i+2)]
 | 
					      sym = $(i+2)
 | 
				
			||||||
 | 
					      sub(/,/,"",sym)
 | 
				
			||||||
 | 
					      op[name] = tk[sym]
 | 
				
			||||||
      used[op[name]] = 1
 | 
					      used[op[name]] = 1
 | 
				
			||||||
      sameas[op[name]] = $(i+2)
 | 
					      sameas[op[name]] = sym
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    if($i=="stack"){
 | 
				
			||||||
 | 
					      stack[name] = 1
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -75,4 +81,31 @@ END {
 | 
				
			|||||||
      printf "#define %-25s %15d\n", sprintf( "OP_NotUsed_%-3d", i ), i
 | 
					      printf "#define %-25s %15d\n", sprintf( "OP_NotUsed_%-3d", i ), i
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Generate the 10 16-bit bitmasks used by function opcodeUsesStack()
 | 
				
			||||||
 | 
					  # in vdbeaux.c. See comments in that function for details.
 | 
				
			||||||
 | 
					  # 
 | 
				
			||||||
 | 
					  stack[0] = 0              # 0..15
 | 
				
			||||||
 | 
					  stack[1] = 0              # 16..31
 | 
				
			||||||
 | 
					  stack[2] = 0              # 32..47
 | 
				
			||||||
 | 
					  stack[3] = 0              # 48..63
 | 
				
			||||||
 | 
					  stack[4] = 0              # 64..79
 | 
				
			||||||
 | 
					  stack[5] = 0              # 80..95
 | 
				
			||||||
 | 
					  stack[6] = 0              # 96..111
 | 
				
			||||||
 | 
					  stack[7] = 0              # 112..127
 | 
				
			||||||
 | 
					  stack[8] = 0              # 128..143
 | 
				
			||||||
 | 
					  stack[9] = 0              # 144..159
 | 
				
			||||||
 | 
					  for(name in op){
 | 
				
			||||||
 | 
					    if( stack[name] ){
 | 
				
			||||||
 | 
					      n = op[name]
 | 
				
			||||||
 | 
					      j = n%16
 | 
				
			||||||
 | 
					      i = ((n - j)/16)
 | 
				
			||||||
 | 
					      stack[i] = stack[i] + (2^j)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  printf "\n"
 | 
				
			||||||
 | 
					  for(i=0; i<10; i++){
 | 
				
			||||||
 | 
					    printf "#define STACK_MASK_%d %d\n", i, stack[i]
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										232
									
								
								src/vdbe.c
									
									
									
									
									
								
							
							
						
						
									
										232
									
								
								src/vdbe.c
									
									
									
									
									
								
							@@ -43,7 +43,7 @@
 | 
				
			|||||||
** in this file for details.  If in doubt, do not deviate from existing
 | 
					** in this file for details.  If in doubt, do not deviate from existing
 | 
				
			||||||
** commenting and indentation practices when changing or adding code.
 | 
					** commenting and indentation practices when changing or adding code.
 | 
				
			||||||
**
 | 
					**
 | 
				
			||||||
** $Id: vdbe.c,v 1.461 2005/03/29 03:11:00 danielk1977 Exp $
 | 
					** $Id: vdbe.c,v 1.462 2005/03/29 08:26:13 danielk1977 Exp $
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
#include "sqliteInt.h"
 | 
					#include "sqliteInt.h"
 | 
				
			||||||
#include "os.h"
 | 
					#include "os.h"
 | 
				
			||||||
@@ -462,6 +462,9 @@ int sqlite3VdbeExec(
 | 
				
			|||||||
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
 | 
					#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
 | 
				
			||||||
  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
 | 
					  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					#ifndef NDEBUG
 | 
				
			||||||
 | 
					  Mem *pStackLimit;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
 | 
					  if( p->magic!=VDBE_MAGIC_RUN ) return SQLITE_MISUSE;
 | 
				
			||||||
  assert( db->magic==SQLITE_MAGIC_BUSY );
 | 
					  assert( db->magic==SQLITE_MAGIC_BUSY );
 | 
				
			||||||
@@ -533,6 +536,23 @@ int sqlite3VdbeExec(
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NDEBUG
 | 
				
			||||||
 | 
					    /* This is to check that the return value of static function
 | 
				
			||||||
 | 
					    ** opcodeUsesStack() (see vdbeaux.c) returns values that match the
 | 
				
			||||||
 | 
					    ** implementation of the virtual machine in this file. If
 | 
				
			||||||
 | 
					    ** opcodeUsesStack() returns non-zero, then the stack is guarenteed
 | 
				
			||||||
 | 
					    ** not to grow when the opcode is executed. If it returns zero, then
 | 
				
			||||||
 | 
					    ** the stack may grow by at most 1.
 | 
				
			||||||
 | 
					    **
 | 
				
			||||||
 | 
					    ** The global wrapper function sqlite3VdbeOpcodeUsesStack() is not 
 | 
				
			||||||
 | 
					    ** available if NDEBUG is defined at build time.
 | 
				
			||||||
 | 
					    */ 
 | 
				
			||||||
 | 
					    pStackLimit = pTos;
 | 
				
			||||||
 | 
					    if( !sqlite3VdbeOpcodeUsesStack(pOp->opcode) ){
 | 
				
			||||||
 | 
					      pStackLimit++;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    switch( pOp->opcode ){
 | 
					    switch( pOp->opcode ){
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*****************************************************************************
 | 
					/*****************************************************************************
 | 
				
			||||||
@@ -553,6 +573,11 @@ int sqlite3VdbeExec(
 | 
				
			|||||||
** case statement is followed by a comment of the form "/# same as ... #/"
 | 
					** case statement is followed by a comment of the form "/# same as ... #/"
 | 
				
			||||||
** that comment is used to determine the particular value of the opcode.
 | 
					** that comment is used to determine the particular value of the opcode.
 | 
				
			||||||
**
 | 
					**
 | 
				
			||||||
 | 
					** If a comment on the same line as the "case OP_" construction contains
 | 
				
			||||||
 | 
					** the word "stack", then the opcode is guarenteed not to grow the 
 | 
				
			||||||
 | 
					** vdbe stack when it is executed. See function opcodeUsesStack() in
 | 
				
			||||||
 | 
					** vdbeaux.c for details.
 | 
				
			||||||
 | 
					**
 | 
				
			||||||
** Documentation about VDBE opcodes is generated by scanning this file
 | 
					** Documentation about VDBE opcodes is generated by scanning this file
 | 
				
			||||||
** for lines of that contain "Opcode:".  That line and all subsequent
 | 
					** for lines of that contain "Opcode:".  That line and all subsequent
 | 
				
			||||||
** comment lines are used in the generation of the opcode.html documentation
 | 
					** comment lines are used in the generation of the opcode.html documentation
 | 
				
			||||||
@@ -572,7 +597,7 @@ int sqlite3VdbeExec(
 | 
				
			|||||||
** the one at index P2 from the beginning of
 | 
					** the one at index P2 from the beginning of
 | 
				
			||||||
** the program.
 | 
					** the program.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Goto: {
 | 
					case OP_Goto: {             /* no stack growth */
 | 
				
			||||||
  CHECK_FOR_INTERRUPT;
 | 
					  CHECK_FOR_INTERRUPT;
 | 
				
			||||||
  pc = pOp->p2 - 1;
 | 
					  pc = pOp->p2 - 1;
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
@@ -588,7 +613,7 @@ case OP_Goto: {
 | 
				
			|||||||
** the return address stack will fill up and processing will abort
 | 
					** the return address stack will fill up and processing will abort
 | 
				
			||||||
** with a fatal error.
 | 
					** with a fatal error.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Gosub: {
 | 
					case OP_Gosub: {            /* no stack growth */
 | 
				
			||||||
  assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) );
 | 
					  assert( p->returnDepth<sizeof(p->returnStack)/sizeof(p->returnStack[0]) );
 | 
				
			||||||
  p->returnStack[p->returnDepth++] = pc+1;
 | 
					  p->returnStack[p->returnDepth++] = pc+1;
 | 
				
			||||||
  pc = pOp->p2 - 1;
 | 
					  pc = pOp->p2 - 1;
 | 
				
			||||||
@@ -601,7 +626,7 @@ case OP_Gosub: {
 | 
				
			|||||||
** OP_Gosub.  If an OP_Return has occurred for all OP_Gosubs, then
 | 
					** OP_Gosub.  If an OP_Return has occurred for all OP_Gosubs, then
 | 
				
			||||||
** processing aborts with a fatal error.
 | 
					** processing aborts with a fatal error.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Return: {
 | 
					case OP_Return: {           /* no stack growth */
 | 
				
			||||||
  assert( p->returnDepth>0 );
 | 
					  assert( p->returnDepth>0 );
 | 
				
			||||||
  p->returnDepth--;
 | 
					  p->returnDepth--;
 | 
				
			||||||
  pc = p->returnStack[p->returnDepth] - 1;
 | 
					  pc = p->returnStack[p->returnDepth] - 1;
 | 
				
			||||||
@@ -625,7 +650,7 @@ case OP_Return: {
 | 
				
			|||||||
** every program.  So a jump past the last instruction of the program
 | 
					** every program.  So a jump past the last instruction of the program
 | 
				
			||||||
** is the same as executing Halt.
 | 
					** is the same as executing Halt.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Halt: {
 | 
					case OP_Halt: {            /* no stack growth */
 | 
				
			||||||
  p->pTos = pTos;
 | 
					  p->pTos = pTos;
 | 
				
			||||||
  p->rc = pOp->p1;
 | 
					  p->rc = pOp->p1;
 | 
				
			||||||
  p->pc = pc;
 | 
					  p->pc = pc;
 | 
				
			||||||
@@ -671,7 +696,7 @@ case OP_Integer: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** The string value P3 is converted to a real and pushed on to the stack.
 | 
					** The string value P3 is converted to a real and pushed on to the stack.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Real: {            /* same as TK_FLOAT */
 | 
					case OP_Real: {            /* same as TK_FLOAT, */
 | 
				
			||||||
  pTos++;
 | 
					  pTos++;
 | 
				
			||||||
  pTos->flags = MEM_Str|MEM_Static|MEM_Term;
 | 
					  pTos->flags = MEM_Str|MEM_Static|MEM_Term;
 | 
				
			||||||
  pTos->z = pOp->p3;
 | 
					  pTos->z = pOp->p3;
 | 
				
			||||||
@@ -807,7 +832,7 @@ case OP_Variable: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** P1 elements are popped off of the top of stack and discarded.
 | 
					** P1 elements are popped off of the top of stack and discarded.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Pop: {
 | 
					case OP_Pop: {            /* no stack growth */
 | 
				
			||||||
  assert( pOp->p1>=0 );
 | 
					  assert( pOp->p1>=0 );
 | 
				
			||||||
  popStack(&pTos, pOp->p1);
 | 
					  popStack(&pTos, pOp->p1);
 | 
				
			||||||
  assert( pTos>=&p->aStack[-1] );
 | 
					  assert( pTos>=&p->aStack[-1] );
 | 
				
			||||||
@@ -850,7 +875,7 @@ case OP_Dup: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** See also the Dup instruction.
 | 
					** See also the Dup instruction.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Pull: {
 | 
					case OP_Pull: {            /* no stack growth */
 | 
				
			||||||
  Mem *pFrom = &pTos[-pOp->p1];
 | 
					  Mem *pFrom = &pTos[-pOp->p1];
 | 
				
			||||||
  int i;
 | 
					  int i;
 | 
				
			||||||
  Mem ts;
 | 
					  Mem ts;
 | 
				
			||||||
@@ -882,7 +907,7 @@ case OP_Pull: {
 | 
				
			|||||||
** stack (P1==0 is the top of the stack) with the value
 | 
					** stack (P1==0 is the top of the stack) with the value
 | 
				
			||||||
** of the top of the stack.  Then pop the top of the stack.
 | 
					** of the top of the stack.  Then pop the top of the stack.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Push: {
 | 
					case OP_Push: {            /* no stack growth */
 | 
				
			||||||
  Mem *pTo = &pTos[-pOp->p1];
 | 
					  Mem *pTo = &pTos[-pOp->p1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  assert( pTo>=p->aStack );
 | 
					  assert( pTo>=p->aStack );
 | 
				
			||||||
@@ -897,7 +922,7 @@ case OP_Push: {
 | 
				
			|||||||
** invoke the callback function using the newly formed array as the
 | 
					** invoke the callback function using the newly formed array as the
 | 
				
			||||||
** 3rd parameter.
 | 
					** 3rd parameter.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Callback: {
 | 
					case OP_Callback: {            /* no stack growth */
 | 
				
			||||||
  int i;
 | 
					  int i;
 | 
				
			||||||
  assert( p->nResColumn==pOp->p1 );
 | 
					  assert( p->nResColumn==pOp->p1 );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1033,11 +1058,11 @@ case OP_Concat: {           /* same as TK_CONCAT */
 | 
				
			|||||||
** function before the division.  Division by zero returns NULL.
 | 
					** function before the division.  Division by zero returns NULL.
 | 
				
			||||||
** If either operand is NULL, the result is NULL.
 | 
					** If either operand is NULL, the result is NULL.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Add:                   /* same as TK_PLUS */
 | 
					case OP_Add:                   /* same as TK_PLUS, no stack growth */
 | 
				
			||||||
case OP_Subtract:              /* same as TK_MINUS */
 | 
					case OP_Subtract:              /* same as TK_MINUS, no stack growth */
 | 
				
			||||||
case OP_Multiply:              /* same as TK_STAR */
 | 
					case OP_Multiply:              /* same as TK_STAR, no stack growth */
 | 
				
			||||||
case OP_Divide:                /* same as TK_SLASH */
 | 
					case OP_Divide:                /* same as TK_SLASH, no stack growth */
 | 
				
			||||||
case OP_Remainder: {           /* same as TK_REM */
 | 
					case OP_Remainder: {           /* same as TK_REM, no stack growth */
 | 
				
			||||||
  Mem *pNos = &pTos[-1];
 | 
					  Mem *pNos = &pTos[-1];
 | 
				
			||||||
  assert( pNos>=p->aStack );
 | 
					  assert( pNos>=p->aStack );
 | 
				
			||||||
  if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){
 | 
					  if( ((pTos->flags | pNos->flags) & MEM_Null)!=0 ){
 | 
				
			||||||
@@ -1117,7 +1142,7 @@ divide_by_zero:
 | 
				
			|||||||
** to retrieve the collation sequence set by this opcode is not available
 | 
					** to retrieve the collation sequence set by this opcode is not available
 | 
				
			||||||
** publicly, only to user functions defined in func.c.
 | 
					** publicly, only to user functions defined in func.c.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_CollSeq: {
 | 
					case OP_CollSeq: {             /* no stack growth */
 | 
				
			||||||
  assert( pOp->p3type==P3_COLLSEQ );
 | 
					  assert( pOp->p3type==P3_COLLSEQ );
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -1235,10 +1260,10 @@ case OP_Function: {
 | 
				
			|||||||
** right by N bits where N is the top element on the stack.
 | 
					** right by N bits where N is the top element on the stack.
 | 
				
			||||||
** If either operand is NULL, the result is NULL.
 | 
					** If either operand is NULL, the result is NULL.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_BitAnd:                 /* same as TK_BITAND */
 | 
					case OP_BitAnd:                 /* same as TK_BITAND, no stack growth */
 | 
				
			||||||
case OP_BitOr:                  /* same as TK_BITOR */
 | 
					case OP_BitOr:                  /* same as TK_BITOR, no stack growth */
 | 
				
			||||||
case OP_ShiftLeft:              /* same as TK_LSHIFT */
 | 
					case OP_ShiftLeft:              /* same as TK_LSHIFT, no stack growth */
 | 
				
			||||||
case OP_ShiftRight: {           /* same as TK_RSHIFT */
 | 
					case OP_ShiftRight: {           /* same as TK_RSHIFT, no stack growth */
 | 
				
			||||||
  Mem *pNos = &pTos[-1];
 | 
					  Mem *pNos = &pTos[-1];
 | 
				
			||||||
  int a, b;
 | 
					  int a, b;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1273,7 +1298,7 @@ case OP_ShiftRight: {           /* same as TK_RSHIFT */
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** To force the top of the stack to be an integer, just add 0.
 | 
					** To force the top of the stack to be an integer, just add 0.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AddImm: {
 | 
					case OP_AddImm: {            /* no stack growth */
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
  Integerify(pTos);
 | 
					  Integerify(pTos);
 | 
				
			||||||
  pTos->i += pOp->p1;
 | 
					  pTos->i += pOp->p1;
 | 
				
			||||||
@@ -1290,7 +1315,7 @@ case OP_AddImm: {
 | 
				
			|||||||
** current value if P1==0, or to the least integer that is strictly
 | 
					** current value if P1==0, or to the least integer that is strictly
 | 
				
			||||||
** greater than its current value if P1==1.
 | 
					** greater than its current value if P1==1.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_ForceInt: {
 | 
					case OP_ForceInt: {            /* no stack growth */
 | 
				
			||||||
  int v;
 | 
					  int v;
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
  applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
 | 
					  applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
 | 
				
			||||||
@@ -1325,7 +1350,7 @@ case OP_ForceInt: {
 | 
				
			|||||||
** P1 is 1, then the stack is popped.  In all other cases, the depth
 | 
					** P1 is 1, then the stack is popped.  In all other cases, the depth
 | 
				
			||||||
** of the stack is unchanged.
 | 
					** of the stack is unchanged.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_MustBeInt: {
 | 
					case OP_MustBeInt: {            /* no stack growth */
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
  applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
 | 
					  applyAffinity(pTos, SQLITE_AFF_INTEGER, db->enc);
 | 
				
			||||||
  if( (pTos->flags & MEM_Int)==0 ){
 | 
					  if( (pTos->flags & MEM_Int)==0 ){
 | 
				
			||||||
@@ -1400,12 +1425,12 @@ case OP_MustBeInt: {
 | 
				
			|||||||
** the 2nd element down on the stack is greater than or equal to the
 | 
					** the 2nd element down on the stack is greater than or equal to the
 | 
				
			||||||
** top of the stack.  See the Eq opcode for additional information.
 | 
					** top of the stack.  See the Eq opcode for additional information.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Eq:               /* same as TK_EQ */
 | 
					case OP_Eq:               /* same as TK_EQ, no stack growth */
 | 
				
			||||||
case OP_Ne:               /* same as TK_NE */
 | 
					case OP_Ne:               /* same as TK_NE, no stack growth */
 | 
				
			||||||
case OP_Lt:               /* same as TK_LT */
 | 
					case OP_Lt:               /* same as TK_LT, no stack growth */
 | 
				
			||||||
case OP_Le:               /* same as TK_LE */
 | 
					case OP_Le:               /* same as TK_LE, no stack growth */
 | 
				
			||||||
case OP_Gt:               /* same as TK_GT */
 | 
					case OP_Gt:               /* same as TK_GT, no stack growth */
 | 
				
			||||||
case OP_Ge: {             /* same as TK_GE */
 | 
					case OP_Ge: {             /* same as TK_GE, no stack growth */
 | 
				
			||||||
  Mem *pNos;
 | 
					  Mem *pNos;
 | 
				
			||||||
  int flags;
 | 
					  int flags;
 | 
				
			||||||
  int res;
 | 
					  int res;
 | 
				
			||||||
@@ -1471,8 +1496,8 @@ case OP_Ge: {             /* same as TK_GE */
 | 
				
			|||||||
** two values and push the resulting boolean value back onto the
 | 
					** two values and push the resulting boolean value back onto the
 | 
				
			||||||
** stack. 
 | 
					** stack. 
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_And:              /* same as TK_AND */
 | 
					case OP_And:              /* same as TK_AND, no stack growth */
 | 
				
			||||||
case OP_Or: {             /* same as TK_OR */
 | 
					case OP_Or: {             /* same as TK_OR, no stack growth */
 | 
				
			||||||
  Mem *pNos = &pTos[-1];
 | 
					  Mem *pNos = &pTos[-1];
 | 
				
			||||||
  int v1, v2;    /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */
 | 
					  int v1, v2;    /* 0==TRUE, 1==FALSE, 2==UNKNOWN or NULL */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1519,7 +1544,7 @@ case OP_Or: {             /* same as TK_OR */
 | 
				
			|||||||
** with its absolute value. If the top of the stack is NULL
 | 
					** with its absolute value. If the top of the stack is NULL
 | 
				
			||||||
** its value is unchanged.
 | 
					** its value is unchanged.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Negative:              /* same as TK_UMINUS */
 | 
					case OP_Negative:              /* same as TK_UMINUS, no stack growth */
 | 
				
			||||||
case OP_AbsValue: {
 | 
					case OP_AbsValue: {
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
  if( pTos->flags & MEM_Real ){
 | 
					  if( pTos->flags & MEM_Real ){
 | 
				
			||||||
@@ -1552,7 +1577,7 @@ case OP_AbsValue: {
 | 
				
			|||||||
** with its complement.  If the top of the stack is NULL its value
 | 
					** with its complement.  If the top of the stack is NULL its value
 | 
				
			||||||
** is unchanged.
 | 
					** is unchanged.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Not: {                /* same as TK_NOT */
 | 
					case OP_Not: {                /* same as TK_NOT, no stack growth */
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
  if( pTos->flags & MEM_Null ) break;  /* Do nothing to NULLs */
 | 
					  if( pTos->flags & MEM_Null ) break;  /* Do nothing to NULLs */
 | 
				
			||||||
  Integerify(pTos);
 | 
					  Integerify(pTos);
 | 
				
			||||||
@@ -1568,7 +1593,7 @@ case OP_Not: {                /* same as TK_NOT */
 | 
				
			|||||||
** with its ones-complement.  If the top of the stack is NULL its
 | 
					** with its ones-complement.  If the top of the stack is NULL its
 | 
				
			||||||
** value is unchanged.
 | 
					** value is unchanged.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_BitNot: {             /* same as TK_BITNOT */
 | 
					case OP_BitNot: {             /* same as TK_BITNOT, no stack growth */
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
  if( pTos->flags & MEM_Null ) break;  /* Do nothing to NULLs */
 | 
					  if( pTos->flags & MEM_Null ) break;  /* Do nothing to NULLs */
 | 
				
			||||||
  Integerify(pTos);
 | 
					  Integerify(pTos);
 | 
				
			||||||
@@ -1583,7 +1608,7 @@ case OP_BitNot: {             /* same as TK_BITNOT */
 | 
				
			|||||||
** Do nothing.  This instruction is often useful as a jump
 | 
					** Do nothing.  This instruction is often useful as a jump
 | 
				
			||||||
** destination.
 | 
					** destination.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Noop: {
 | 
					case OP_Noop: {            /* no stack growth */
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -1607,8 +1632,8 @@ case OP_Noop: {
 | 
				
			|||||||
** If the value popped of the stack is NULL, then take the jump if P1
 | 
					** If the value popped of the stack is NULL, then take the jump if P1
 | 
				
			||||||
** is true and fall through if P1 is false.
 | 
					** is true and fall through if P1 is false.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_If:
 | 
					case OP_If:                 /* no stack growth */
 | 
				
			||||||
case OP_IfNot: {
 | 
					case OP_IfNot: {            /* no stack growth */
 | 
				
			||||||
  int c;
 | 
					  int c;
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
  if( pTos->flags & MEM_Null ){
 | 
					  if( pTos->flags & MEM_Null ){
 | 
				
			||||||
@@ -1629,7 +1654,7 @@ case OP_IfNot: {
 | 
				
			|||||||
** to P2.  Pop the stack P1 times if P1>0.   If P1<0 leave the stack
 | 
					** to P2.  Pop the stack P1 times if P1>0.   If P1<0 leave the stack
 | 
				
			||||||
** unchanged.
 | 
					** unchanged.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_IsNull: {            /* same as TK_ISNULL */
 | 
					case OP_IsNull: {            /* same as TK_ISNULL, no stack growth */
 | 
				
			||||||
  int i, cnt;
 | 
					  int i, cnt;
 | 
				
			||||||
  Mem *pTerm;
 | 
					  Mem *pTerm;
 | 
				
			||||||
  cnt = pOp->p1;
 | 
					  cnt = pOp->p1;
 | 
				
			||||||
@@ -1652,7 +1677,7 @@ case OP_IsNull: {            /* same as TK_ISNULL */
 | 
				
			|||||||
** stack if P1 times if P1 is greater than zero.  If P1 is less than
 | 
					** stack if P1 times if P1 is greater than zero.  If P1 is less than
 | 
				
			||||||
** zero then leave the stack unchanged.
 | 
					** zero then leave the stack unchanged.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_NotNull: {            /* same as TK_NOTNULL */
 | 
					case OP_NotNull: {            /* same as TK_NOTNULL, no stack growth */
 | 
				
			||||||
  int i, cnt;
 | 
					  int i, cnt;
 | 
				
			||||||
  cnt = pOp->p1;
 | 
					  cnt = pOp->p1;
 | 
				
			||||||
  if( cnt<0 ) cnt = -cnt;
 | 
					  if( cnt<0 ) cnt = -cnt;
 | 
				
			||||||
@@ -1673,7 +1698,7 @@ case OP_NotNull: {            /* same as TK_NOTNULL */
 | 
				
			|||||||
** If OP_KeyAsData is to be applied to cursor P1, it must be executed
 | 
					** If OP_KeyAsData is to be applied to cursor P1, it must be executed
 | 
				
			||||||
** before this op-code.
 | 
					** before this op-code.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_SetNumColumns: {
 | 
					case OP_SetNumColumns: {       /* no stack growth */
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
  assert( (pOp->p1)<p->nCursor );
 | 
					  assert( (pOp->p1)<p->nCursor );
 | 
				
			||||||
  assert( p->apCsr[pOp->p1]!=0 );
 | 
					  assert( p->apCsr[pOp->p1]!=0 );
 | 
				
			||||||
@@ -2131,7 +2156,7 @@ case OP_MakeRecord: {
 | 
				
			|||||||
** database file has an index of 0 and the file used for temporary tables
 | 
					** database file has an index of 0 and the file used for temporary tables
 | 
				
			||||||
** has an index of 1.
 | 
					** has an index of 1.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Statement: {
 | 
					case OP_Statement: {       /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Btree *pBt;
 | 
					  Btree *pBt;
 | 
				
			||||||
  if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt) && !(db->autoCommit) ){
 | 
					  if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt) && !(db->autoCommit) ){
 | 
				
			||||||
@@ -2151,7 +2176,7 @@ case OP_Statement: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** This instruction causes the VM to halt.
 | 
					** This instruction causes the VM to halt.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AutoCommit: {
 | 
					case OP_AutoCommit: {       /* no stack growth */
 | 
				
			||||||
  u8 i = pOp->p1;
 | 
					  u8 i = pOp->p1;
 | 
				
			||||||
  u8 rollback = pOp->p2;
 | 
					  u8 rollback = pOp->p2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2212,7 +2237,7 @@ case OP_AutoCommit: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** If P2 is zero, then a read-lock is obtained on the database file.
 | 
					** If P2 is zero, then a read-lock is obtained on the database file.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Transaction: {
 | 
					case OP_Transaction: {       /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Btree *pBt;
 | 
					  Btree *pBt;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2275,7 +2300,7 @@ case OP_ReadCookie: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** A transaction must be started before executing this opcode.
 | 
					** A transaction must be started before executing this opcode.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_SetCookie: {
 | 
					case OP_SetCookie: {       /* no stack growth */
 | 
				
			||||||
  Db *pDb;
 | 
					  Db *pDb;
 | 
				
			||||||
  assert( pOp->p2<SQLITE_N_BTREE_META );
 | 
					  assert( pOp->p2<SQLITE_N_BTREE_META );
 | 
				
			||||||
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
 | 
					  assert( pOp->p1>=0 && pOp->p1<db->nDb );
 | 
				
			||||||
@@ -2311,7 +2336,7 @@ case OP_SetCookie: {
 | 
				
			|||||||
** to be executed (to establish a read lock) before this opcode is
 | 
					** to be executed (to establish a read lock) before this opcode is
 | 
				
			||||||
** invoked.
 | 
					** invoked.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_VerifyCookie: {
 | 
					case OP_VerifyCookie: {       /* no stack growth */
 | 
				
			||||||
  int iMeta;
 | 
					  int iMeta;
 | 
				
			||||||
  Btree *pBt;
 | 
					  Btree *pBt;
 | 
				
			||||||
  assert( pOp->p1>=0 && pOp->p1<db->nDb );
 | 
					  assert( pOp->p1>=0 && pOp->p1<db->nDb );
 | 
				
			||||||
@@ -2371,8 +2396,8 @@ case OP_VerifyCookie: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** See also OpenRead.
 | 
					** See also OpenRead.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_OpenRead:
 | 
					case OP_OpenRead:          /* no stack growth */
 | 
				
			||||||
case OP_OpenWrite: {
 | 
					case OP_OpenWrite: {       /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  int p2 = pOp->p2;
 | 
					  int p2 = pOp->p2;
 | 
				
			||||||
  int wrFlag;
 | 
					  int wrFlag;
 | 
				
			||||||
@@ -2460,7 +2485,7 @@ case OP_OpenWrite: {
 | 
				
			|||||||
** whereas "Temporary" in the context of CREATE TABLE means for the duration
 | 
					** whereas "Temporary" in the context of CREATE TABLE means for the duration
 | 
				
			||||||
** of the connection to the database.  Same word; different meanings.
 | 
					** of the connection to the database.  Same word; different meanings.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_OpenTemp: {
 | 
					case OP_OpenTemp: {       /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pCx;
 | 
					  Cursor *pCx;
 | 
				
			||||||
  assert( i>=0 );
 | 
					  assert( i>=0 );
 | 
				
			||||||
@@ -2509,7 +2534,7 @@ case OP_OpenTemp: {
 | 
				
			|||||||
** A pseudo-table created by this opcode is useful for holding the
 | 
					** A pseudo-table created by this opcode is useful for holding the
 | 
				
			||||||
** NEW or OLD tables in a trigger.
 | 
					** NEW or OLD tables in a trigger.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_OpenPseudo: {
 | 
					case OP_OpenPseudo: {       /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pCx;
 | 
					  Cursor *pCx;
 | 
				
			||||||
  assert( i>=0 );
 | 
					  assert( i>=0 );
 | 
				
			||||||
@@ -2527,7 +2552,7 @@ case OP_OpenPseudo: {
 | 
				
			|||||||
** Close a cursor previously opened as P1.  If P1 is not
 | 
					** Close a cursor previously opened as P1.  If P1 is not
 | 
				
			||||||
** currently open, this instruction is a no-op.
 | 
					** currently open, this instruction is a no-op.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Close: {
 | 
					case OP_Close: {       /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  if( i>=0 && i<p->nCursor ){
 | 
					  if( i>=0 && i<p->nCursor ){
 | 
				
			||||||
    sqlite3VdbeFreeCursor(p->apCsr[i]);
 | 
					    sqlite3VdbeFreeCursor(p->apCsr[i]);
 | 
				
			||||||
@@ -2576,10 +2601,10 @@ case OP_Close: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
 | 
					** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_MoveLt:
 | 
					case OP_MoveLt:         /* no stack growth */
 | 
				
			||||||
case OP_MoveLe:
 | 
					case OP_MoveLe:         /* no stack growth */
 | 
				
			||||||
case OP_MoveGe:
 | 
					case OP_MoveGe:         /* no stack growth */
 | 
				
			||||||
case OP_MoveGt: {
 | 
					case OP_MoveGt: {       /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2688,9 +2713,9 @@ case OP_MoveGt: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** See also: Distinct, Found, MoveTo, NotExists, IsUnique
 | 
					** See also: Distinct, Found, MoveTo, NotExists, IsUnique
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Distinct:
 | 
					case OP_Distinct:       /* no stack growth */
 | 
				
			||||||
case OP_NotFound:
 | 
					case OP_NotFound:       /* no stack growth */
 | 
				
			||||||
case OP_Found: {
 | 
					case OP_Found: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  int alreadyExists = 0;
 | 
					  int alreadyExists = 0;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
@@ -2739,7 +2764,7 @@ case OP_Found: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** See also: Distinct, NotFound, NotExists, Found
 | 
					** See also: Distinct, NotFound, NotExists, Found
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_IsUnique: {
 | 
					case OP_IsUnique: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Mem *pNos = &pTos[-1];
 | 
					  Mem *pNos = &pTos[-1];
 | 
				
			||||||
  Cursor *pCx;
 | 
					  Cursor *pCx;
 | 
				
			||||||
@@ -2833,7 +2858,7 @@ case OP_IsUnique: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
 | 
					** See also: Distinct, Found, MoveTo, NotFound, IsUnique
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_NotExists: {
 | 
					case OP_NotExists: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
  BtCursor *pCrsr;
 | 
					  BtCursor *pCrsr;
 | 
				
			||||||
@@ -3036,8 +3061,8 @@ case OP_NewRecno: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** P1 may not be a pseudo-table opened using the OpenPseudo opcode.
 | 
					** P1 may not be a pseudo-table opened using the OpenPseudo opcode.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_PutIntKey:
 | 
					case OP_PutIntKey:          /* no stack growth */
 | 
				
			||||||
case OP_PutStrKey: {
 | 
					case OP_PutStrKey: {        /* no stack growth */
 | 
				
			||||||
  Mem *pNos = &pTos[-1];
 | 
					  Mem *pNos = &pTos[-1];
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
@@ -3131,7 +3156,7 @@ case OP_PutStrKey: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** If P1 is a pseudo-table, then this instruction is a no-op.
 | 
					** If P1 is a pseudo-table, then this instruction is a no-op.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Delete: {
 | 
					case OP_Delete: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
  assert( i>=0 && i<p->nCursor );
 | 
					  assert( i>=0 && i<p->nCursor );
 | 
				
			||||||
@@ -3155,7 +3180,7 @@ case OP_Delete: {
 | 
				
			|||||||
** change counter (returned by subsequent calls to sqlite3_changes())
 | 
					** change counter (returned by subsequent calls to sqlite3_changes())
 | 
				
			||||||
** before it is reset. This is used by trigger programs.
 | 
					** before it is reset. This is used by trigger programs.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_ResetCount: {
 | 
					case OP_ResetCount: {        /* no stack growth */
 | 
				
			||||||
  if( pOp->p1 ){
 | 
					  if( pOp->p1 ){
 | 
				
			||||||
    sqlite3VdbeSetChanges(db, p->nChange);
 | 
					    sqlite3VdbeSetChanges(db, p->nChange);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@@ -3170,7 +3195,7 @@ case OP_ResetCount: {
 | 
				
			|||||||
** data off of the key rather than the data.  This is used for
 | 
					** data off of the key rather than the data.  This is used for
 | 
				
			||||||
** processing compound selects.
 | 
					** processing compound selects.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_KeyAsData: {
 | 
					case OP_KeyAsData: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
  assert( i>=0 && i<p->nCursor );
 | 
					  assert( i>=0 && i<p->nCursor );
 | 
				
			||||||
@@ -3346,7 +3371,7 @@ case OP_FullKey: {
 | 
				
			|||||||
** that occur while the cursor is on the null row will always push 
 | 
					** that occur while the cursor is on the null row will always push 
 | 
				
			||||||
** a NULL onto the stack.
 | 
					** a NULL onto the stack.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_NullRow: {
 | 
					case OP_NullRow: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -3366,7 +3391,7 @@ case OP_NullRow: {
 | 
				
			|||||||
** If P2 is 0 or if the table or index is not empty, fall through
 | 
					** If P2 is 0 or if the table or index is not empty, fall through
 | 
				
			||||||
** to the following instruction.
 | 
					** to the following instruction.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Last: {
 | 
					case OP_Last: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
  BtCursor *pCrsr;
 | 
					  BtCursor *pCrsr;
 | 
				
			||||||
@@ -3397,7 +3422,7 @@ case OP_Last: {
 | 
				
			|||||||
** If P2 is 0 or if the table or index is not empty, fall through
 | 
					** If P2 is 0 or if the table or index is not empty, fall through
 | 
				
			||||||
** to the following instruction.
 | 
					** to the following instruction.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Rewind: {
 | 
					case OP_Rewind: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
  BtCursor *pCrsr;
 | 
					  BtCursor *pCrsr;
 | 
				
			||||||
@@ -3437,8 +3462,8 @@ case OP_Rewind: {
 | 
				
			|||||||
** to the following instruction.  But if the cursor backup was successful,
 | 
					** to the following instruction.  But if the cursor backup was successful,
 | 
				
			||||||
** jump immediately to P2.
 | 
					** jump immediately to P2.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Prev:
 | 
					case OP_Prev:          /* no stack growth */
 | 
				
			||||||
case OP_Next: {
 | 
					case OP_Next: {        /* no stack growth */
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
  BtCursor *pCrsr;
 | 
					  BtCursor *pCrsr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -3479,7 +3504,7 @@ case OP_Next: {
 | 
				
			|||||||
** is rolled back.  If P3 is not null, then it becomes part of the
 | 
					** is rolled back.  If P3 is not null, then it becomes part of the
 | 
				
			||||||
** error message returned with the SQLITE_CONSTRAINT.
 | 
					** error message returned with the SQLITE_CONSTRAINT.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_IdxPut: {
 | 
					case OP_IdxPut: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
  BtCursor *pCrsr;
 | 
					  BtCursor *pCrsr;
 | 
				
			||||||
@@ -3531,7 +3556,7 @@ case OP_IdxPut: {
 | 
				
			|||||||
** The top of the stack is an index key built using the MakeIdxKey opcode.
 | 
					** The top of the stack is an index key built using the MakeIdxKey opcode.
 | 
				
			||||||
** This opcode removes that entry from the index.
 | 
					** This opcode removes that entry from the index.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_IdxDelete: {
 | 
					case OP_IdxDelete: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
  BtCursor *pCrsr;
 | 
					  BtCursor *pCrsr;
 | 
				
			||||||
@@ -3633,9 +3658,9 @@ case OP_IdxRecno: {
 | 
				
			|||||||
** an epsilon prior to the comparison.  This makes the opcode work
 | 
					** an epsilon prior to the comparison.  This makes the opcode work
 | 
				
			||||||
** like IdxLE.
 | 
					** like IdxLE.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_IdxLT:
 | 
					case OP_IdxLT:          /* no stack growth */
 | 
				
			||||||
case OP_IdxGT:
 | 
					case OP_IdxGT:          /* no stack growth */
 | 
				
			||||||
case OP_IdxGE: {
 | 
					case OP_IdxGE: {        /* no stack growth */
 | 
				
			||||||
  int i= pOp->p1;
 | 
					  int i= pOp->p1;
 | 
				
			||||||
  BtCursor *pCrsr;
 | 
					  BtCursor *pCrsr;
 | 
				
			||||||
  Cursor *pC;
 | 
					  Cursor *pC;
 | 
				
			||||||
@@ -3679,7 +3704,7 @@ case OP_IdxGE: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** The index entry is always popped from the stack.
 | 
					** The index entry is always popped from the stack.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_IdxIsNull: {
 | 
					case OP_IdxIsNull: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  int k, n;
 | 
					  int k, n;
 | 
				
			||||||
  const char *z;
 | 
					  const char *z;
 | 
				
			||||||
@@ -3753,7 +3778,7 @@ case OP_Destroy: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** See also: Destroy
 | 
					** See also: Destroy
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Clear: {
 | 
					case OP_Clear: {        /* no stack growth */
 | 
				
			||||||
  rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
 | 
					  rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, pOp->p1);
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -3811,7 +3836,7 @@ case OP_CreateTable: {
 | 
				
			|||||||
** This opcode invokes the parser to create a new virtual machine,
 | 
					** This opcode invokes the parser to create a new virtual machine,
 | 
				
			||||||
** then runs the new virtual machine.  It is thus a reentrant opcode.
 | 
					** then runs the new virtual machine.  It is thus a reentrant opcode.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_ParseSchema: {
 | 
					case OP_ParseSchema: {        /* no stack growth */
 | 
				
			||||||
  char *zSql;
 | 
					  char *zSql;
 | 
				
			||||||
  int iDb = pOp->p1;
 | 
					  int iDb = pOp->p1;
 | 
				
			||||||
  const char *zMaster;
 | 
					  const char *zMaster;
 | 
				
			||||||
@@ -3843,7 +3868,7 @@ case OP_ParseSchema: {
 | 
				
			|||||||
** is dropped in order to keep the internal representation of the
 | 
					** is dropped in order to keep the internal representation of the
 | 
				
			||||||
** schema consistent with what is on disk.
 | 
					** schema consistent with what is on disk.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_DropTable: {
 | 
					case OP_DropTable: {        /* no stack growth */
 | 
				
			||||||
  sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3);
 | 
					  sqlite3UnlinkAndDeleteTable(db, pOp->p1, pOp->p3);
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -3855,7 +3880,7 @@ case OP_DropTable: {
 | 
				
			|||||||
** is dropped in order to keep the internal representation of the
 | 
					** is dropped in order to keep the internal representation of the
 | 
				
			||||||
** schema consistent with what is on disk.
 | 
					** schema consistent with what is on disk.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_DropIndex: {
 | 
					case OP_DropIndex: {        /* no stack growth */
 | 
				
			||||||
  sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3);
 | 
					  sqlite3UnlinkAndDeleteIndex(db, pOp->p1, pOp->p3);
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -3867,7 +3892,7 @@ case OP_DropIndex: {
 | 
				
			|||||||
** is dropped in order to keep the internal representation of the
 | 
					** is dropped in order to keep the internal representation of the
 | 
				
			||||||
** schema consistent with what is on disk.
 | 
					** schema consistent with what is on disk.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_DropTrigger: {
 | 
					case OP_DropTrigger: {        /* no stack growth */
 | 
				
			||||||
  sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3);
 | 
					  sqlite3UnlinkAndDeleteTrigger(db, pOp->p1, pOp->p3);
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -3932,7 +3957,7 @@ case OP_IntegrityCk: {
 | 
				
			|||||||
** Write the integer on the top of the stack
 | 
					** Write the integer on the top of the stack
 | 
				
			||||||
** into the temporary storage list.
 | 
					** into the temporary storage list.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_ListWrite: {
 | 
					case OP_ListWrite: {        /* no stack growth */
 | 
				
			||||||
  Keylist *pKeylist;
 | 
					  Keylist *pKeylist;
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
  pKeylist = p->pList;
 | 
					  pKeylist = p->pList;
 | 
				
			||||||
@@ -3956,7 +3981,7 @@ case OP_ListWrite: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** Rewind the temporary buffer back to the beginning.
 | 
					** Rewind the temporary buffer back to the beginning.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_ListRewind: {
 | 
					case OP_ListRewind: {        /* no stack growth */
 | 
				
			||||||
  /* What this opcode codes, really, is reverse the order of the
 | 
					  /* What this opcode codes, really, is reverse the order of the
 | 
				
			||||||
  ** linked list of Keylist structures so that they are read out
 | 
					  ** linked list of Keylist structures so that they are read out
 | 
				
			||||||
  ** in the same order that they were read in. */
 | 
					  ** in the same order that they were read in. */
 | 
				
			||||||
@@ -4003,7 +4028,7 @@ case OP_ListRead: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** Reset the temporary storage buffer so that it holds nothing.
 | 
					** Reset the temporary storage buffer so that it holds nothing.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_ListReset: {
 | 
					case OP_ListReset: {        /* no stack growth */
 | 
				
			||||||
  if( p->pList ){
 | 
					  if( p->pList ){
 | 
				
			||||||
    sqlite3VdbeKeylistFree(p->pList);
 | 
					    sqlite3VdbeKeylistFree(p->pList);
 | 
				
			||||||
    p->pList = 0;
 | 
					    p->pList = 0;
 | 
				
			||||||
@@ -4018,7 +4043,7 @@ case OP_ListReset: {
 | 
				
			|||||||
** AggContextPop opcode.
 | 
					** AggContextPop opcode.
 | 
				
			||||||
** 
 | 
					** 
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AggContextPush: {
 | 
					case OP_AggContextPush: {        /* no stack growth */
 | 
				
			||||||
  p->pAgg++;
 | 
					  p->pAgg++;
 | 
				
			||||||
  assert( p->pAgg<&p->apAgg[p->nAgg] );
 | 
					  assert( p->pAgg<&p->apAgg[p->nAgg] );
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
@@ -4029,7 +4054,7 @@ case OP_AggContextPush: {
 | 
				
			|||||||
** Restore the aggregator to the state it was in when AggContextPush
 | 
					** Restore the aggregator to the state it was in when AggContextPush
 | 
				
			||||||
** was last called. Any data in the current aggregator is deleted.
 | 
					** was last called. Any data in the current aggregator is deleted.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AggContextPop: {
 | 
					case OP_AggContextPop: {        /* no stack growth */
 | 
				
			||||||
  p->pAgg--;
 | 
					  p->pAgg--;
 | 
				
			||||||
  assert( p->pAgg>=p->apAgg );
 | 
					  assert( p->pAgg>=p->apAgg );
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
@@ -4043,7 +4068,7 @@ case OP_AggContextPop: {
 | 
				
			|||||||
** opcode. The context stores the last insert row id, the last statement change
 | 
					** opcode. The context stores the last insert row id, the last statement change
 | 
				
			||||||
** count, and the current statement change count.
 | 
					** count, and the current statement change count.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_ContextPush: {
 | 
					case OP_ContextPush: {        /* no stack growth */
 | 
				
			||||||
  int i = p->contextStackTop++;
 | 
					  int i = p->contextStackTop++;
 | 
				
			||||||
  Context *pContext;
 | 
					  Context *pContext;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -4068,7 +4093,7 @@ case OP_ContextPush: {
 | 
				
			|||||||
** executed. The context stores the last insert row id, the last statement
 | 
					** executed. The context stores the last insert row id, the last statement
 | 
				
			||||||
** change count, and the current statement change count.
 | 
					** change count, and the current statement change count.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_ContextPop: {
 | 
					case OP_ContextPop: {        /* no stack growth */
 | 
				
			||||||
  Context *pContext = &p->contextStack[--p->contextStackTop];
 | 
					  Context *pContext = &p->contextStack[--p->contextStackTop];
 | 
				
			||||||
  assert( p->contextStackTop>=0 );
 | 
					  assert( p->contextStackTop>=0 );
 | 
				
			||||||
  db->lastRowid = pContext->lastRowid;
 | 
					  db->lastRowid = pContext->lastRowid;
 | 
				
			||||||
@@ -4085,7 +4110,7 @@ case OP_ContextPop: {
 | 
				
			|||||||
** and put them on the sorter.  The key and data should have been
 | 
					** and put them on the sorter.  The key and data should have been
 | 
				
			||||||
** made using the MakeRecord opcode.
 | 
					** made using the MakeRecord opcode.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_SortPut: {
 | 
					case OP_SortPut: {        /* no stack growth */
 | 
				
			||||||
  Mem *pNos = &pTos[-1];
 | 
					  Mem *pNos = &pTos[-1];
 | 
				
			||||||
  Sorter *pSorter;
 | 
					  Sorter *pSorter;
 | 
				
			||||||
  assert( pNos>=p->aStack );
 | 
					  assert( pNos>=p->aStack );
 | 
				
			||||||
@@ -4109,7 +4134,7 @@ case OP_SortPut: {
 | 
				
			|||||||
** mergesort.  The P3 argument is a pointer to a KeyInfo structure
 | 
					** mergesort.  The P3 argument is a pointer to a KeyInfo structure
 | 
				
			||||||
** that describes the keys to be sorted.
 | 
					** that describes the keys to be sorted.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Sort: {
 | 
					case OP_Sort: {        /* no stack growth */
 | 
				
			||||||
  int i;
 | 
					  int i;
 | 
				
			||||||
  KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3;
 | 
					  KeyInfo *pKeyInfo = (KeyInfo*)pOp->p3;
 | 
				
			||||||
  Sorter *pElem;
 | 
					  Sorter *pElem;
 | 
				
			||||||
@@ -4171,7 +4196,7 @@ case OP_SortNext: {
 | 
				
			|||||||
**
 | 
					**
 | 
				
			||||||
** Remove any elements that remain on the sorter.
 | 
					** Remove any elements that remain on the sorter.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_SortReset: {
 | 
					case OP_SortReset: {        /* no stack growth */
 | 
				
			||||||
  sqlite3VdbeSorterReset(p);
 | 
					  sqlite3VdbeSorterReset(p);
 | 
				
			||||||
  break;
 | 
					  break;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -4186,7 +4211,7 @@ case OP_SortReset: {
 | 
				
			|||||||
** stack is popped once if P2 is 1.  If P2 is zero, then
 | 
					** stack is popped once if P2 is 1.  If P2 is zero, then
 | 
				
			||||||
** the original data remains on the stack.
 | 
					** the original data remains on the stack.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_MemStore: {
 | 
					case OP_MemStore: {        /* no stack growth */
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
  assert( pOp->p1>=0 && pOp->p1<p->nMem );
 | 
					  assert( pOp->p1>=0 && pOp->p1<p->nMem );
 | 
				
			||||||
  rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos);
 | 
					  rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos);
 | 
				
			||||||
@@ -4225,7 +4250,7 @@ case OP_MemLoad: {
 | 
				
			|||||||
** This instruction throws an error if the memory cell is not initially
 | 
					** This instruction throws an error if the memory cell is not initially
 | 
				
			||||||
** an integer.
 | 
					** an integer.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_MemMax: {
 | 
					case OP_MemMax: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Mem *pMem;
 | 
					  Mem *pMem;
 | 
				
			||||||
  assert( pTos>=p->aStack );
 | 
					  assert( pTos>=p->aStack );
 | 
				
			||||||
@@ -4249,7 +4274,7 @@ case OP_MemMax: {
 | 
				
			|||||||
** This instruction throws an error if the memory cell is not initially
 | 
					** This instruction throws an error if the memory cell is not initially
 | 
				
			||||||
** an integer.
 | 
					** an integer.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_MemIncr: {
 | 
					case OP_MemIncr: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Mem *pMem;
 | 
					  Mem *pMem;
 | 
				
			||||||
  assert( i>=0 && i<p->nMem );
 | 
					  assert( i>=0 && i<p->nMem );
 | 
				
			||||||
@@ -4267,7 +4292,7 @@ case OP_MemIncr: {
 | 
				
			|||||||
** If the value of memory cell P1 is 1 or greater, jump to P2. This
 | 
					** If the value of memory cell P1 is 1 or greater, jump to P2. This
 | 
				
			||||||
** opcode assumes that memory cell P1 holds an integer value.
 | 
					** opcode assumes that memory cell P1 holds an integer value.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_IfMemPos: {
 | 
					case OP_IfMemPos: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p1;
 | 
					  int i = pOp->p1;
 | 
				
			||||||
  Mem *pMem;
 | 
					  Mem *pMem;
 | 
				
			||||||
  assert( i>=0 && i<p->nMem );
 | 
					  assert( i>=0 && i<p->nMem );
 | 
				
			||||||
@@ -4289,7 +4314,7 @@ case OP_IfMemPos: {
 | 
				
			|||||||
** there is no GROUP BY expression). In this case it is illegal to invoke
 | 
					** there is no GROUP BY expression). In this case it is illegal to invoke
 | 
				
			||||||
** OP_AggFocus.
 | 
					** OP_AggFocus.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AggReset: {
 | 
					case OP_AggReset: {        /* no stack growth */
 | 
				
			||||||
  assert( !pOp->p3 || pOp->p3type==P3_KEYINFO );
 | 
					  assert( !pOp->p3 || pOp->p3type==P3_KEYINFO );
 | 
				
			||||||
  if( pOp->p1 ){
 | 
					  if( pOp->p1 ){
 | 
				
			||||||
    rc = sqlite3VdbeAggReset(0, p->pAgg, (KeyInfo *)pOp->p3);
 | 
					    rc = sqlite3VdbeAggReset(0, p->pAgg, (KeyInfo *)pOp->p3);
 | 
				
			||||||
@@ -4313,7 +4338,7 @@ case OP_AggReset: {
 | 
				
			|||||||
** The aggregate will operate out of aggregate column P2.
 | 
					** The aggregate will operate out of aggregate column P2.
 | 
				
			||||||
** P3 is a pointer to the FuncDef structure for the function.
 | 
					** P3 is a pointer to the FuncDef structure for the function.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AggInit: {
 | 
					case OP_AggInit: {        /* no stack growth */
 | 
				
			||||||
  int i = pOp->p2;
 | 
					  int i = pOp->p2;
 | 
				
			||||||
  assert( i>=0 && i<p->pAgg->nMem );
 | 
					  assert( i>=0 && i<p->pAgg->nMem );
 | 
				
			||||||
  p->pAgg->apFunc[i] = (FuncDef*)pOp->p3;
 | 
					  p->pAgg->apFunc[i] = (FuncDef*)pOp->p3;
 | 
				
			||||||
@@ -4331,7 +4356,7 @@ case OP_AggInit: {
 | 
				
			|||||||
** Ideally, this index would be another parameter, but there are
 | 
					** Ideally, this index would be another parameter, but there are
 | 
				
			||||||
** no free parameters left.  The integer is popped from the stack.
 | 
					** no free parameters left.  The integer is popped from the stack.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AggFunc: {
 | 
					case OP_AggFunc: {        /* no stack growth */
 | 
				
			||||||
  int n = pOp->p2;
 | 
					  int n = pOp->p2;
 | 
				
			||||||
  int i;
 | 
					  int i;
 | 
				
			||||||
  Mem *pMem, *pRec;
 | 
					  Mem *pMem, *pRec;
 | 
				
			||||||
@@ -4389,7 +4414,7 @@ case OP_AggFunc: {
 | 
				
			|||||||
** zero or more AggNext operations.  You must not execute an AggFocus
 | 
					** zero or more AggNext operations.  You must not execute an AggFocus
 | 
				
			||||||
** in between an AggNext and an AggReset.
 | 
					** in between an AggNext and an AggReset.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AggFocus: {
 | 
					case OP_AggFocus: {        /* no stack growth */
 | 
				
			||||||
  char *zKey;
 | 
					  char *zKey;
 | 
				
			||||||
  int nKey;
 | 
					  int nKey;
 | 
				
			||||||
  int res;
 | 
					  int res;
 | 
				
			||||||
@@ -4423,7 +4448,7 @@ case OP_AggFocus: {
 | 
				
			|||||||
** Move the top of the stack into the P2-th field of the current
 | 
					** Move the top of the stack into the P2-th field of the current
 | 
				
			||||||
** aggregate.  String values are duplicated into new memory.
 | 
					** aggregate.  String values are duplicated into new memory.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AggSet: {
 | 
					case OP_AggSet: {        /* no stack growth */
 | 
				
			||||||
  AggElem *pFocus;
 | 
					  AggElem *pFocus;
 | 
				
			||||||
  int i = pOp->p2;
 | 
					  int i = pOp->p2;
 | 
				
			||||||
  pFocus = p->pAgg->pCurrent;
 | 
					  pFocus = p->pAgg->pCurrent;
 | 
				
			||||||
@@ -4488,7 +4513,7 @@ case OP_AggGet: {
 | 
				
			|||||||
** zero or more AggNext operations.  You must not execute an AggFocus
 | 
					** zero or more AggNext operations.  You must not execute an AggFocus
 | 
				
			||||||
** in between an AggNext and an AggReset.
 | 
					** in between an AggNext and an AggReset.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_AggNext: {
 | 
					case OP_AggNext: {        /* no stack growth */
 | 
				
			||||||
  int res;
 | 
					  int res;
 | 
				
			||||||
  assert( rc==SQLITE_OK );
 | 
					  assert( rc==SQLITE_OK );
 | 
				
			||||||
  CHECK_FOR_INTERRUPT;
 | 
					  CHECK_FOR_INTERRUPT;
 | 
				
			||||||
@@ -4549,7 +4574,7 @@ case OP_AggNext: {
 | 
				
			|||||||
** machines to be created and run.  It may not be called from within
 | 
					** machines to be created and run.  It may not be called from within
 | 
				
			||||||
** a transaction.
 | 
					** a transaction.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Vacuum: {
 | 
					case OP_Vacuum: {        /* no stack growth */
 | 
				
			||||||
  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; 
 | 
					  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; 
 | 
				
			||||||
  rc = sqlite3RunVacuum(&p->zErrMsg, db);
 | 
					  rc = sqlite3RunVacuum(&p->zErrMsg, db);
 | 
				
			||||||
  if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
 | 
					  if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
 | 
				
			||||||
@@ -4565,7 +4590,7 @@ case OP_Vacuum: {
 | 
				
			|||||||
** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
 | 
					** If P1 is 0, then all SQL statements become expired. If P1 is non-zero,
 | 
				
			||||||
** then only the currently executing statement is affected. 
 | 
					** then only the currently executing statement is affected. 
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
case OP_Expire: {
 | 
					case OP_Expire: {        /* no stack growth */
 | 
				
			||||||
  if( !pOp->p1 ){
 | 
					  if( !pOp->p1 ){
 | 
				
			||||||
    sqlite3ExpirePreparedStatements(db);
 | 
					    sqlite3ExpirePreparedStatements(db);
 | 
				
			||||||
  }else{
 | 
					  }else{
 | 
				
			||||||
@@ -4592,6 +4617,9 @@ default: {
 | 
				
			|||||||
*****************************************************************************/
 | 
					*****************************************************************************/
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /* Make sure the stack limit was not exceeded */
 | 
				
			||||||
 | 
					    assert( pTos<=pStackLimit );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef VDBE_PROFILE
 | 
					#ifdef VDBE_PROFILE
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      long long elapse = hwtime() - start;
 | 
					      long long elapse = hwtime() - start;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -406,6 +406,7 @@ int sqlite3VdbeMemFromBtree(BtCursor*,int,int,int,Mem*);
 | 
				
			|||||||
void sqlite3VdbeMemRelease(Mem *p);
 | 
					void sqlite3VdbeMemRelease(Mem *p);
 | 
				
			||||||
#ifndef NDEBUG
 | 
					#ifndef NDEBUG
 | 
				
			||||||
void sqlite3VdbeMemSanity(Mem*, u8);
 | 
					void sqlite3VdbeMemSanity(Mem*, u8);
 | 
				
			||||||
 | 
					int sqlite3VdbeOpcodeUsesStack(u8);
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
int sqlite3VdbeMemTranslate(Mem*, u8);
 | 
					int sqlite3VdbeMemTranslate(Mem*, u8);
 | 
				
			||||||
void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf);
 | 
					void sqlite3VdbeMemPrettyPrint(Mem *pMem, char *zBuf, int nBuf);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -166,6 +166,47 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					** Return non-zero if opcode 'op' is guarenteed not to push more values
 | 
				
			||||||
 | 
					** onto the VDBE stack than it pops off.
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					static int opcodeUsesStack(u8 op){
 | 
				
			||||||
 | 
					  /* The 10 STACK_MASK_n constants are defined in the automatically
 | 
				
			||||||
 | 
					  ** generated header file opcodes.h. Each is a 16-bit bitmask, one
 | 
				
			||||||
 | 
					  ** bit corresponding to each opcode implemented by the virtual
 | 
				
			||||||
 | 
					  ** machine in vdbe.c. The bit is true if the word "stack" appears
 | 
				
			||||||
 | 
					  ** in a comment on the same line as the "case OP_XXX:" in 
 | 
				
			||||||
 | 
					  ** sqlite3VdbeExec() in vdbe.c.
 | 
				
			||||||
 | 
					  **
 | 
				
			||||||
 | 
					  ** If the bit is true, then the corresponding opcode is guarenteed not
 | 
				
			||||||
 | 
					  ** to grow the stack when it is executed. Otherwise, it may grow the
 | 
				
			||||||
 | 
					  ** stack by at most one entry.
 | 
				
			||||||
 | 
					  **
 | 
				
			||||||
 | 
					  ** STACK_MASK_0 corresponds to opcodes 0 to 15. STACK_MASK_1 contains
 | 
				
			||||||
 | 
					  ** one bit for opcodes 16 to 31, and so on.
 | 
				
			||||||
 | 
					  **
 | 
				
			||||||
 | 
					  ** 16-bit bitmasks (rather than 32-bit) are specified in opcodes.h 
 | 
				
			||||||
 | 
					  ** because the file is generated by an awk program. Awk manipulates
 | 
				
			||||||
 | 
					  ** all numbers as floating-point and we don't want to risk a rounding
 | 
				
			||||||
 | 
					  ** error if someone builds with an awk that uses (for example) 32-bit 
 | 
				
			||||||
 | 
					  ** IEEE floats.
 | 
				
			||||||
 | 
					  */ 
 | 
				
			||||||
 | 
					  static u32 masks[5] = {
 | 
				
			||||||
 | 
					    STACK_MASK_0 + (STACK_MASK_1<<16),
 | 
				
			||||||
 | 
					    STACK_MASK_2 + (STACK_MASK_3<<16),
 | 
				
			||||||
 | 
					    STACK_MASK_4 + (STACK_MASK_5<<16),
 | 
				
			||||||
 | 
					    STACK_MASK_6 + (STACK_MASK_7<<16),
 | 
				
			||||||
 | 
					    STACK_MASK_8 + (STACK_MASK_9<<16)
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					  return (masks[op>>5] & (1<<(op&0x1F)));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef NDEBUG
 | 
				
			||||||
 | 
					int sqlite3VdbeOpcodeUsesStack(u8 op){
 | 
				
			||||||
 | 
					  return opcodeUsesStack(op);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
** Loop through the program looking for P2 values that are negative.
 | 
					** Loop through the program looking for P2 values that are negative.
 | 
				
			||||||
** Each such value is a label.  Resolve the label by setting the P2
 | 
					** Each such value is a label.  Resolve the label by setting the P2
 | 
				
			||||||
@@ -176,22 +217,30 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
 | 
				
			|||||||
** Variable *pMaxFuncArgs is set to the maximum value of any P1 argument 
 | 
					** Variable *pMaxFuncArgs is set to the maximum value of any P1 argument 
 | 
				
			||||||
** to an OP_Function or P2 to an OP_AggFunc opcode. This is used by 
 | 
					** to an OP_Function or P2 to an OP_AggFunc opcode. This is used by 
 | 
				
			||||||
** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
 | 
					** sqlite3VdbeMakeReady() to size the Vdbe.apArg[] array.
 | 
				
			||||||
 | 
					**
 | 
				
			||||||
 | 
					** The integer *pMaxStack is set to the maximum number of vdbe stack
 | 
				
			||||||
 | 
					** entries that static analysis reveals this program might need.
 | 
				
			||||||
*/
 | 
					*/
 | 
				
			||||||
static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
 | 
					static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs, int *pMaxStack){
 | 
				
			||||||
  int i;
 | 
					  int i;
 | 
				
			||||||
  int nMax = 0;
 | 
					  int nMaxArgs = 0;
 | 
				
			||||||
 | 
					  int nMaxStack = p->nOp;
 | 
				
			||||||
  Op *pOp;
 | 
					  Op *pOp;
 | 
				
			||||||
  int *aLabel = p->aLabel;
 | 
					  int *aLabel = p->aLabel;
 | 
				
			||||||
  if( aLabel==0 ) return;
 | 
					 | 
				
			||||||
  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
 | 
					  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
 | 
				
			||||||
    u8 opcode = pOp->opcode;
 | 
					    u8 opcode = pOp->opcode;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /* Todo: Maybe OP_AggFunc should change to use P1 in the same
 | 
					    /* Todo: Maybe OP_AggFunc should change to use P1 in the same
 | 
				
			||||||
     * way as OP_Function. */
 | 
					     * way as OP_Function. 
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
    if( opcode==OP_Function ){
 | 
					    if( opcode==OP_Function ){
 | 
				
			||||||
      if( pOp->p1>nMax ) nMax = pOp->p1;
 | 
					      if( pOp->p1>nMaxArgs ) nMaxArgs = pOp->p1;
 | 
				
			||||||
    }else if( opcode==OP_AggFunc ){
 | 
					    }else if( opcode==OP_AggFunc ){
 | 
				
			||||||
      if( pOp->p2>nMax ) nMax = pOp->p2;
 | 
					      if( pOp->p2>nMaxArgs ) nMaxArgs = pOp->p2;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if( opcodeUsesStack(opcode) ){
 | 
				
			||||||
 | 
					      nMaxStack--;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if( pOp->p2>=0 ) continue;
 | 
					    if( pOp->p2>=0 ) continue;
 | 
				
			||||||
@@ -200,7 +249,9 @@ static void resolveP2Values(Vdbe *p, int *pMaxFuncArgs){
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  sqliteFree(p->aLabel);
 | 
					  sqliteFree(p->aLabel);
 | 
				
			||||||
  p->aLabel = 0;
 | 
					  p->aLabel = 0;
 | 
				
			||||||
  *pMaxFuncArgs = nMax;
 | 
					
 | 
				
			||||||
 | 
					  *pMaxFuncArgs = nMaxArgs;
 | 
				
			||||||
 | 
					  *pMaxStack = nMaxStack;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -641,12 +692,14 @@ void sqlite3VdbeMakeReady(
 | 
				
			|||||||
  */
 | 
					  */
 | 
				
			||||||
  if( p->aStack==0 ){
 | 
					  if( p->aStack==0 ){
 | 
				
			||||||
    int nArg;       /* Maximum number of args passed to a user function. */
 | 
					    int nArg;       /* Maximum number of args passed to a user function. */
 | 
				
			||||||
    resolveP2Values(p, &nArg);
 | 
					    int nStack;     /* Maximum number of stack entries required */
 | 
				
			||||||
 | 
					    resolveP2Values(p, &nArg, &nStack);
 | 
				
			||||||
    resizeOpArray(p, p->nOp);
 | 
					    resizeOpArray(p, p->nOp);
 | 
				
			||||||
    assert( nVar>=0 );
 | 
					    assert( nVar>=0 );
 | 
				
			||||||
    n = isExplain ? 10 : p->nOp;
 | 
					    assert( nStack<p->nOp );
 | 
				
			||||||
 | 
					    nStack = isExplain ? 10 : nStack;
 | 
				
			||||||
    p->aStack = sqliteMalloc(
 | 
					    p->aStack = sqliteMalloc(
 | 
				
			||||||
        n*sizeof(p->aStack[0])         /* aStack */
 | 
					        nStack*sizeof(p->aStack[0])    /* aStack */
 | 
				
			||||||
      + nArg*sizeof(Mem*)              /* apArg */
 | 
					      + nArg*sizeof(Mem*)              /* apArg */
 | 
				
			||||||
      + nVar*sizeof(Mem)               /* aVar */
 | 
					      + nVar*sizeof(Mem)               /* aVar */
 | 
				
			||||||
      + nVar*sizeof(char*)             /* azVar */
 | 
					      + nVar*sizeof(char*)             /* azVar */
 | 
				
			||||||
@@ -655,7 +708,7 @@ void sqlite3VdbeMakeReady(
 | 
				
			|||||||
      + nAgg*sizeof(Agg)               /* Aggregate contexts */
 | 
					      + nAgg*sizeof(Agg)               /* Aggregate contexts */
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    if( !sqlite3_malloc_failed ){
 | 
					    if( !sqlite3_malloc_failed ){
 | 
				
			||||||
      p->aMem = &p->aStack[n];
 | 
					      p->aMem = &p->aStack[nStack];
 | 
				
			||||||
      p->nMem = nMem;
 | 
					      p->nMem = nMem;
 | 
				
			||||||
      p->aVar = &p->aMem[nMem];
 | 
					      p->aVar = &p->aMem[nMem];
 | 
				
			||||||
      p->nVar = nVar;
 | 
					      p->nVar = nVar;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@
 | 
				
			|||||||
#***********************************************************************
 | 
					#***********************************************************************
 | 
				
			||||||
# This file runs all tests.
 | 
					# This file runs all tests.
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# $Id: quick.test,v 1.35 2005/03/29 03:11:00 danielk1977 Exp $
 | 
					# $Id: quick.test,v 1.36 2005/03/29 08:26:13 danielk1977 Exp $
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set testdir [file dirname $argv0]
 | 
					set testdir [file dirname $argv0]
 | 
				
			||||||
source $testdir/tester.tcl
 | 
					source $testdir/tester.tcl
 | 
				
			||||||
@@ -19,7 +19,6 @@ proc finish_test {} {}
 | 
				
			|||||||
set ISQUICK 1
 | 
					set ISQUICK 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set EXCLUDE {
 | 
					set EXCLUDE {
 | 
				
			||||||
  alter.test
 | 
					 | 
				
			||||||
  all.test
 | 
					  all.test
 | 
				
			||||||
  btree2.test
 | 
					  btree2.test
 | 
				
			||||||
  btree3.test
 | 
					  btree3.test
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -34,14 +34,46 @@ Example:
 | 
				
			|||||||
$ ./testfixture ../sqlite/test/select1.test 2> memtrace.out
 | 
					$ ./testfixture ../sqlite/test/select1.test 2> memtrace.out
 | 
				
			||||||
$ tclsh $argv0 ?-r <malloc-number>? ./testfixture memtrace.out
 | 
					$ tclsh $argv0 ?-r <malloc-number>? ./testfixture memtrace.out
 | 
				
			||||||
"
 | 
					"
 | 
				
			||||||
if { [llength $argv]!=2 && [llength $argv]!=4 } {
 | 
					
 | 
				
			||||||
  set prg [file tail $argv0]
 | 
					
 | 
				
			||||||
 | 
					proc usage {} {
 | 
				
			||||||
 | 
					  set prg [file tail $::argv0]
 | 
				
			||||||
  puts "Usage: $prg ?-r <malloc-number>? <binary file> <mem trace file>"
 | 
					  puts "Usage: $prg ?-r <malloc-number>? <binary file> <mem trace file>"
 | 
				
			||||||
  puts ""
 | 
					  puts ""
 | 
				
			||||||
  puts [string trim $doco]
 | 
					  puts [string trim $::doco]
 | 
				
			||||||
  exit -1
 | 
					  exit -1
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					proc shift {listvar} {
 | 
				
			||||||
 | 
					  upvar $listvar l
 | 
				
			||||||
 | 
					  set ret [lindex $l 0]
 | 
				
			||||||
 | 
					  set l [lrange $l 1 end]
 | 
				
			||||||
 | 
					  return $ret
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Argument handling. The following vars are set:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# $exe       - the name of the executable (i.e. "testfixture" or "./sqlite3")
 | 
				
			||||||
 | 
					# $memfile   - the name of the file containing the trace output.
 | 
				
			||||||
 | 
					# $report_at - The malloc number to stop and report at. Or -1 to read 
 | 
				
			||||||
 | 
					#              all of $memfile.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					set report_at -1
 | 
				
			||||||
 | 
					while {[llength $argv]>2} {
 | 
				
			||||||
 | 
					  set arg [shift argv]
 | 
				
			||||||
 | 
					  switch -- $arg {
 | 
				
			||||||
 | 
					    "-r" {
 | 
				
			||||||
 | 
					      set report_at [shift argv]
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    default {
 | 
				
			||||||
 | 
					      usage
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					if {[llength $argv]!=2} usage
 | 
				
			||||||
 | 
					set exe [lindex $argv 0]
 | 
				
			||||||
 | 
					set memfile [lindex $argv 1]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# If stack traces are enabled, the 'addr2line' program is called to
 | 
					# If stack traces are enabled, the 'addr2line' program is called to
 | 
				
			||||||
# translate a binary stack address into a human-readable form.
 | 
					# translate a binary stack address into a human-readable form.
 | 
				
			||||||
set addr2line addr2line
 | 
					set addr2line addr2line
 | 
				
			||||||
@@ -69,17 +101,6 @@ set iPeak 0                ;# nMalloc when nPeak was set.
 | 
				
			|||||||
#
 | 
					#
 | 
				
			||||||
array unset memmap
 | 
					array unset memmap
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# The executable program being analyzed.
 | 
					 | 
				
			||||||
if {[llength $argv]==2} {
 | 
					 | 
				
			||||||
  set exe [lindex $argv 0]
 | 
					 | 
				
			||||||
  set memfile [lindex $argv 1]
 | 
					 | 
				
			||||||
  set report_at -1
 | 
					 | 
				
			||||||
} else {
 | 
					 | 
				
			||||||
  set exe [lindex $argv 2]
 | 
					 | 
				
			||||||
  set memfile [lindex $argv 3]
 | 
					 | 
				
			||||||
  set report_at [lindex $argv 1]
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
proc process_input {input_file array_name} {
 | 
					proc process_input {input_file array_name} {
 | 
				
			||||||
  upvar $array_name mem 
 | 
					  upvar $array_name mem 
 | 
				
			||||||
  set input [open $input_file]
 | 
					  set input [open $input_file]
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user