/ Check-in [cc149eb9]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Get rid of OP_Dup, OP_MemStore, OP_MemLoad, and OP_MemMove. Replace with OP_Copy, OP_SCopy, and OP_Move. Add the infrastructure for operation properties in1, in2, in3, out2, and out3 but do not yet use any of these. (CVS 4682)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cc149eb9ca3c672cc6fea3528353234ac2ed5745
User & Date: drh 2008-01-05 04:06:04
Context
2008-01-05
05:20
Register-ify the OP_AddImm and all casting opcodes. Omit the OP_MemIncr opcode. (CVS 4683) check-in: 3e8a07dd user: drh tags: trunk
04:06
Get rid of OP_Dup, OP_MemStore, OP_MemLoad, and OP_MemMove. Replace with OP_Copy, OP_SCopy, and OP_Move. Add the infrastructure for operation properties in1, in2, in3, out2, and out3 but do not yet use any of these. (CVS 4682) check-in: cc149eb9 user: drh tags: trunk
2008-01-04
22:01
Implement the out2-prerelease opcode design pattern. (CVS 4681) check-in: fe057a88 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to mkopcodeh.awk.

49
50
51
52
53
54
55





56
57
58
59
60
61
62
..
65
66
67
68
69
70
71










72
73
74
75
76
77
78
...
114
115
116
117
118
119
120





121
122
123
124
125
126
127
128
129
130





131
132
133
134
135
136
137
  name = $2
  sub(/:/,"",name)
  sub("\r","",name)
  op[name] = -1
  jump[name] = 0
  nopush[name] = 0
  out2_prerelease[name] = 0





  for(i=3; i<NF; i++){
    if($i=="same" && $(i+1)=="as"){
      sym = $(i+2)
      sub(/,/,"",sym)
      op[name] = tk[sym]
      used[op[name]] = 1
      sameas[op[name]] = sym
................................................................................
    sub(",","",x)
    if(x=="no-push"){
      nopush[name] = 1
    }else if(x=="jump"){
      jump[name] = 1
    }else if(x=="out2-prerelease"){
      out2_prerelease[name] = 1










    }
  }
}

# Assign numbers to all opcodes and output the result.
END {
  cnt = 0
................................................................................
  for(i=0; i<=max; i++) bv[i] = 0;
  for(name in op){
    x = op[name]
    a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0
    if( jump[name] ) a0 = 1;
    if( nopush[name]==0 ) a1 = 2;
    if( out2_prerelease[name] ) a2 = 4;





    bv[x] = a0+a1+a2+a3+a4+a5+a6+a7;
  }
  print "\n"
  print "/* Properties such as \"out2\" or \"jump\" that are specified in"
  print "** comments following the "case" for each opcode in the vdbe.c"
  print "** are encoded into bitvectors as follows:"
  print "*/"
  print "#define OPFLG_JUMP            0x01    /* jump:  P2 holds jmp target */"
  print "#define OPFLG_PUSH            0x02    /* ~no-push:  Does not push */"
  print "#define OPFLG_OUT2_PRERELEASE 0x04    /* out2-prerelease: */"





  print "#define OPFLG_INITIALIZER {\\"
  for(i=0; i<=max; i++){
    printf " 0x%02x,", bv[i]
    if( i%8==7 ) printf("\\\n");
  }
  print "}"
}







>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>










>
>
>
>
>







49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
...
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
  name = $2
  sub(/:/,"",name)
  sub("\r","",name)
  op[name] = -1
  jump[name] = 0
  nopush[name] = 0
  out2_prerelease[name] = 0
  in1[name] = 0
  in2[name] = 0
  in3[name] = 0
  out2[name] = 0
  out3[name] = 0
  for(i=3; i<NF; i++){
    if($i=="same" && $(i+1)=="as"){
      sym = $(i+2)
      sub(/,/,"",sym)
      op[name] = tk[sym]
      used[op[name]] = 1
      sameas[op[name]] = sym
................................................................................
    sub(",","",x)
    if(x=="no-push"){
      nopush[name] = 1
    }else if(x=="jump"){
      jump[name] = 1
    }else if(x=="out2-prerelease"){
      out2_prerelease[name] = 1
    }else if(x=="in1"){
      in1[name] = 1
    }else if(x=="in2"){
      in2[name] = 1
    }else if(x=="in3"){
      in3[name] = 1
    }else if(x=="out2"){
      out2[name] = 1
    }else if(x=="out3"){
      out3[name] = 1
    }
  }
}

# Assign numbers to all opcodes and output the result.
END {
  cnt = 0
................................................................................
  for(i=0; i<=max; i++) bv[i] = 0;
  for(name in op){
    x = op[name]
    a0 = a1 = a2 = a3 = a4 = a5 = a6 = a7 = 0
    if( jump[name] ) a0 = 1;
    if( nopush[name]==0 ) a1 = 2;
    if( out2_prerelease[name] ) a2 = 4;
    if( in1[name] ) a3 = 8;
    if( in2[name] ) a4 = 16;
    if( in3[name] ) a5 = 32;
    if( out2[name] ) a6 = 64;
    if( out3[name] ) a7 = 128;
    bv[x] = a0+a1+a2+a3+a4+a5+a6+a7;
  }
  print "\n"
  print "/* Properties such as \"out2\" or \"jump\" that are specified in"
  print "** comments following the "case" for each opcode in the vdbe.c"
  print "** are encoded into bitvectors as follows:"
  print "*/"
  print "#define OPFLG_JUMP            0x01    /* jump:  P2 holds jmp target */"
  print "#define OPFLG_PUSH            0x02    /* ~no-push:  Does not push */"
  print "#define OPFLG_OUT2_PRERELEASE 0x04    /* out2-prerelease: */"
  print "#define OPFLG_IN1             0x08    /* in1:   P1 is an input */"
  print "#define OPFLG_IN2             0x10    /* in2:   P2 is an input */"
  print "#define OPFLG_IN3             0x20    /* in3:   P3 is an input */"
  print "#define OPFLG_OUT2            0x40    /* out2:  P2 is an output */"
  print "#define OPFLG_OUT3            0x80    /* out3:  P3 is an output */"
  print "#define OPFLG_INITIALIZER {\\"
  for(i=0; i<=max; i++){
    printf " 0x%02x,", bv[i]
    if( i%8==7 ) printf("\\\n");
  }
  print "}"
}

Changes to src/analyze.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
** @(#) $Id: analyze.c,v 1.31 2008/01/04 22:01:03 drh Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"

/*
** This routine generates code that opens the sqlite_stat1 table on cursor
** iStatCur.
................................................................................
    */
    endOfLoop = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
    topOfLoop = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeAddOp2(v, OP_MemIncr, 1, iMem);
    for(i=0; i<nCol; i++){
      sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, i);
      sqlite3VdbeAddOp1(v, OP_MemLoad, iMem+nCol+i+1);
      sqlite3VdbeAddOp1(v, OP_Ne, 0x100);
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
    for(i=0; i<nCol; i++){
      addr = sqlite3VdbeAddOp2(v, OP_MemIncr, 1, iMem+i+1);
      sqlite3VdbeChangeP2(v, topOfLoop + 3*i + 3, addr);
      sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, i);
      sqlite3VdbeAddOp2(v, OP_MemStore, iMem+nCol+i+1, 1);
    }
    sqlite3VdbeResolveLabel(v, endOfLoop);
    sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
    sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);

    /* Store the results.  
    **
................................................................................
    **
    **        I = (K+D-1)/D
    **
    ** If K==0 then no entry is made into the sqlite_stat1 table.  
    ** If K>0 then it is always the case the D>0 so division by zero
    ** is never possible.
    */
    sqlite3VdbeAddOp1(v, OP_MemLoad, iMem);
    addr = sqlite3VdbeAddOp0(v, OP_IfNot);
    sqlite3VdbeAddOp1(v, OP_NewRowid, iStatCur);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pIdx->zName, 0);
    sqlite3VdbeAddOp1(v, OP_MemLoad, iMem);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, " ", 0);
    for(i=0; i<nCol; i++){
      sqlite3VdbeAddOp1(v, OP_MemLoad, iMem);
      sqlite3VdbeAddOp1(v, OP_MemLoad, iMem+i+1);
      sqlite3VdbeAddOp0(v, OP_Add);
      sqlite3VdbeAddOp1(v, OP_AddImm, -1);
      sqlite3VdbeAddOp1(v, OP_MemLoad, iMem+i+1);
      sqlite3VdbeAddOp0(v, OP_Divide);
      sqlite3VdbeAddOp0(v, OP_ToInt);
      if( i==nCol-1 ){
        sqlite3VdbeAddOp1(v, OP_Concat, nCol*2-1);
      }else{
        sqlite3VdbeAddOp1(v, OP_Dup, 1);
      }
    }
    sqlite3VdbeAddOp4(v, OP_MakeRecord, 3, 0, 0, "aaa", 0);
    sqlite3CodeInsert(pParse, iStatCur, OPFLAG_APPEND);
    sqlite3VdbeJumpHere(v, addr);
  }
}







|







 







|






|
<







 







|




|


|
|


|





|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168

169
170
171
172
173
174
175
...
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code associated with the ANALYZE command.
**
** @(#) $Id: analyze.c,v 1.32 2008/01/05 04:06:04 drh Exp $
*/
#ifndef SQLITE_OMIT_ANALYZE
#include "sqliteInt.h"

/*
** This routine generates code that opens the sqlite_stat1 table on cursor
** iStatCur.
................................................................................
    */
    endOfLoop = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop);
    topOfLoop = sqlite3VdbeCurrentAddr(v);
    sqlite3VdbeAddOp2(v, OP_MemIncr, 1, iMem);
    for(i=0; i<nCol; i++){
      sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, i);
      sqlite3VdbeAddOp1(v, OP_SCopy, iMem+nCol+i+1);
      sqlite3VdbeAddOp1(v, OP_Ne, 0x100);
    }
    sqlite3VdbeAddOp2(v, OP_Goto, 0, endOfLoop);
    for(i=0; i<nCol; i++){
      addr = sqlite3VdbeAddOp2(v, OP_MemIncr, 1, iMem+i+1);
      sqlite3VdbeChangeP2(v, topOfLoop + 3*i + 3, addr);
      sqlite3VdbeAddOp3(v, OP_Column, iIdxCur, i, iMem+nCol+i+1);

    }
    sqlite3VdbeResolveLabel(v, endOfLoop);
    sqlite3VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop);
    sqlite3VdbeAddOp1(v, OP_Close, iIdxCur);

    /* Store the results.  
    **
................................................................................
    **
    **        I = (K+D-1)/D
    **
    ** If K==0 then no entry is made into the sqlite_stat1 table.  
    ** If K>0 then it is always the case the D>0 so division by zero
    ** is never possible.
    */
    sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
    addr = sqlite3VdbeAddOp0(v, OP_IfNot);
    sqlite3VdbeAddOp1(v, OP_NewRowid, iStatCur);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pIdx->zName, 0);
    sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, " ", 0);
    for(i=0; i<nCol; i++){
      sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
      sqlite3VdbeAddOp1(v, OP_SCopy, iMem+i+1);
      sqlite3VdbeAddOp0(v, OP_Add);
      sqlite3VdbeAddOp1(v, OP_AddImm, -1);
      sqlite3VdbeAddOp1(v, OP_SCopy, iMem+i+1);
      sqlite3VdbeAddOp0(v, OP_Divide);
      sqlite3VdbeAddOp0(v, OP_ToInt);
      if( i==nCol-1 ){
        sqlite3VdbeAddOp1(v, OP_Concat, nCol*2-1);
      }else{
        sqlite3VdbeAddOp1(v, OP_Copy, -1);
      }
    }
    sqlite3VdbeAddOp4(v, OP_MakeRecord, 3, 0, 0, "aaa", 0);
    sqlite3CodeInsert(pParse, iStatCur, OPFLAG_APPEND);
    sqlite3VdbeJumpHere(v, addr);
  }
}

Changes to src/build.c.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
....
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
....
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
....
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.457 2008/01/04 22:01:03 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................
    }else
#endif
    {
      sqlite3VdbeAddOp1(v, OP_CreateTable, iDb);
    }
    sqlite3OpenMasterTable(pParse, iDb);
    sqlite3VdbeAddOp0(v, OP_NewRowid);
    sqlite3VdbeAddOp0(v, OP_Dup);
    sqlite3VdbeAddOp0(v, OP_Null);
    sqlite3CodeInsert(pParse, 0, OPFLAG_APPEND);
    sqlite3VdbeAddOp0(v, OP_Close);
    sqlite3VdbeAddOp1(v, OP_Pull, 1);
  }

  /* Normal (non-error) return. */
................................................................................
    ** as a schema-lock must have already been obtained to create it. Since
    ** a schema-lock excludes all other database users, the write-lock would
    ** be redundant.
    */
    if( pSelect ){
      SelectDest dest = {SRT_Table, 1, 0};
      Table *pSelTab;
      sqlite3VdbeAddOp1(v, OP_Dup, 0);
      sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, 0, iDb);
      pParse->nTab = 2;
      sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
      sqlite3VdbeAddOp1(v, OP_Close, 1);
      if( pParse->nErr==0 ){
        pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
        if( pSelTab==0 ) return;
................................................................................

  /* Require a write-lock on the table to perform this operation */
  sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);

  v = sqlite3GetVdbe(pParse);
  if( v==0 ) return;
  if( memRootPage>=0 ){
    sqlite3VdbeAddOp1(v, OP_MemLoad, memRootPage);
    tnum = 0;
  }else{
    tnum = pIndex->tnum;
    sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
  }
  pKey = sqlite3IndexKeyinfo(pParse, pIndex);
  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
................................................................................
    if( v==0 ) goto exit_create_index;


    /* Create the rootpage for the index
    */
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3VdbeAddOp1(v, OP_CreateIndex, iDb);
    sqlite3VdbeAddOp2(v, OP_MemStore, iMem, 0);

    /* Gather the complete text of the CREATE INDEX statement into
    ** the zStmt variable
    */
    if( pStart && pEnd ){
      /* A named index with an explicit CREATE INDEX statement */
      zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",







|







 







|







 







|







 







|







 







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
....
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
....
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
....
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.458 2008/01/05 04:06:04 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................
    }else
#endif
    {
      sqlite3VdbeAddOp1(v, OP_CreateTable, iDb);
    }
    sqlite3OpenMasterTable(pParse, iDb);
    sqlite3VdbeAddOp0(v, OP_NewRowid);
    sqlite3VdbeAddOp0(v, OP_Copy);
    sqlite3VdbeAddOp0(v, OP_Null);
    sqlite3CodeInsert(pParse, 0, OPFLAG_APPEND);
    sqlite3VdbeAddOp0(v, OP_Close);
    sqlite3VdbeAddOp1(v, OP_Pull, 1);
  }

  /* Normal (non-error) return. */
................................................................................
    ** as a schema-lock must have already been obtained to create it. Since
    ** a schema-lock excludes all other database users, the write-lock would
    ** be redundant.
    */
    if( pSelect ){
      SelectDest dest = {SRT_Table, 1, 0};
      Table *pSelTab;
      sqlite3VdbeAddOp0(v, OP_Copy);
      sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, 0, iDb);
      pParse->nTab = 2;
      sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
      sqlite3VdbeAddOp1(v, OP_Close, 1);
      if( pParse->nErr==0 ){
        pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
        if( pSelTab==0 ) return;
................................................................................

  /* Require a write-lock on the table to perform this operation */
  sqlite3TableLock(pParse, iDb, pTab->tnum, 1, pTab->zName);

  v = sqlite3GetVdbe(pParse);
  if( v==0 ) return;
  if( memRootPage>=0 ){
    sqlite3VdbeAddOp1(v, OP_SCopy, memRootPage);
    tnum = 0;
  }else{
    tnum = pIndex->tnum;
    sqlite3VdbeAddOp2(v, OP_Clear, tnum, iDb);
  }
  pKey = sqlite3IndexKeyinfo(pParse, pIndex);
  sqlite3VdbeAddOp4(v, OP_OpenWrite, iIdx, tnum, iDb, 
................................................................................
    if( v==0 ) goto exit_create_index;


    /* Create the rootpage for the index
    */
    sqlite3BeginWriteOperation(pParse, 1, iDb);
    sqlite3VdbeAddOp1(v, OP_CreateIndex, iDb);
    sqlite3VdbeAddOp2(v, OP_Copy, 0, iMem);

    /* Gather the complete text of the CREATE INDEX statement into
    ** the zStmt variable
    */
    if( pStart && pEnd ){
      /* A named index with an explicit CREATE INDEX statement */
      zStmt = sqlite3MPrintf(db, "CREATE%s INDEX %.*s",

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
...
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.148 2008/01/04 22:01:03 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
** This function is a temporary measure required because OP_Insert now
** reads the key and data to insert from memory cells.
*/
void sqlite3CodeInsert(Parse *p, int iCur, u8 flags){
  int iData = ++p->nMem;
  int iKey = ++p->nMem;
  Vdbe *v = sqlite3GetVdbe(p);
  sqlite3VdbeAddOp2(v, OP_MemStore, iData, 1);
  sqlite3VdbeAddOp2(v, OP_MemStore, iKey, 1);
  sqlite3VdbeAddOp3(v, OP_Insert, iCur, iData, iKey);
  sqlite3VdbeChangeP5(v, sqlite3VdbeCurrentAddr(v)-1, flags);
}

/*
** Allocate nVal contiguous memory cells and return the index of the
** first. Also pop nVal elements from the stack and store them in the 
................................................................................
int sqlite3StackToReg(Parse *p, int nVal){
  int i;
  int iRet = p->nMem+1;
  Vdbe *v = sqlite3GetVdbe(p);
  assert(v);
  p->nMem += nVal;
  for(i=nVal-1; i>=0; i--){
    sqlite3VdbeAddOp2(v, OP_MemStore, iRet+i, 1);
  }
  return iRet;
}
void sqlite3RegToStack(Parse *p, int iReg, int nVal){
  int i;
  Vdbe *v = sqlite3GetVdbe(p);
  assert(v);
  for(i=0; i<nVal; i++){
    sqlite3VdbeAddOp2(v, OP_MemLoad, iReg+i, 0);
  }
}

/*
** Generate code that will open a table for reading.
*/
void sqlite3OpenTable(
................................................................................
  int j;
  Table *pTab = pIdx->pTable;

  sqlite3VdbeAddOp1(v, OP_Rowid, iCur);
  for(j=0; j<pIdx->nColumn; j++){
    int idx = pIdx->aiColumn[j];
    if( idx==pTab->iPKey ){
      sqlite3VdbeAddOp1(v, OP_Dup, j);
    }else{
      sqlite3VdbeAddOp2(v, OP_Column, iCur, idx);
      sqlite3ColumnDefault(v, pTab, idx);
    }
  }
  sqlite3VdbeAddOp1(v, OP_MakeIdxRec, pIdx->nColumn);
  sqlite3IndexAffinityStr(v, pIdx);
}







|







 







|
|







 







|








|







 







|








8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
...
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.149 2008/01/05 04:06:04 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
** This function is a temporary measure required because OP_Insert now
** reads the key and data to insert from memory cells.
*/
void sqlite3CodeInsert(Parse *p, int iCur, u8 flags){
  int iData = ++p->nMem;
  int iKey = ++p->nMem;
  Vdbe *v = sqlite3GetVdbe(p);
  sqlite3VdbeAddOp2(v, OP_Move, 0, iData);
  sqlite3VdbeAddOp2(v, OP_Move, 0, iKey);
  sqlite3VdbeAddOp3(v, OP_Insert, iCur, iData, iKey);
  sqlite3VdbeChangeP5(v, sqlite3VdbeCurrentAddr(v)-1, flags);
}

/*
** Allocate nVal contiguous memory cells and return the index of the
** first. Also pop nVal elements from the stack and store them in the 
................................................................................
int sqlite3StackToReg(Parse *p, int nVal){
  int i;
  int iRet = p->nMem+1;
  Vdbe *v = sqlite3GetVdbe(p);
  assert(v);
  p->nMem += nVal;
  for(i=nVal-1; i>=0; i--){
    sqlite3VdbeAddOp2(v, OP_Move, 0, iRet+i);
  }
  return iRet;
}
void sqlite3RegToStack(Parse *p, int iReg, int nVal){
  int i;
  Vdbe *v = sqlite3GetVdbe(p);
  assert(v);
  for(i=0; i<nVal; i++){
    sqlite3VdbeAddOp2(v, OP_SCopy, iReg+i, 0);
  }
}

/*
** Generate code that will open a table for reading.
*/
void sqlite3OpenTable(
................................................................................
  int j;
  Table *pTab = pIdx->pTable;

  sqlite3VdbeAddOp1(v, OP_Rowid, iCur);
  for(j=0; j<pIdx->nColumn; j++){
    int idx = pIdx->aiColumn[j];
    if( idx==pTab->iPKey ){
      sqlite3VdbeAddOp1(v, OP_Copy, -j);
    }else{
      sqlite3VdbeAddOp2(v, OP_Column, iCur, idx);
      sqlite3ColumnDefault(v, pTab, idx);
    }
  }
  sqlite3VdbeAddOp1(v, OP_MakeIdxRec, pIdx->nColumn);
  sqlite3IndexAffinityStr(v, pIdx);
}

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
....
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
....
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
....
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
....
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
....
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
....
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
....
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
2212
....
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
....
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
2301
....
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
....
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
....
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
....
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.330 2008/01/04 22:01:03 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
  if( v==0 ) return 0;
  p = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, pToken);
  if( p==0 ){
    return 0;  /* Malloc failed */
  }
  depth = atoi((char*)&pToken->z[1]);
  p->iTable = ++pParse->nMem;
  sqlite3VdbeAddOp1(v, OP_Dup, depth);
  sqlite3VdbeAddOp2(v, OP_MemStore, p->iTable, 1);
  return p;
}

/*
** Join two expressions using an AND operator.  If either expression is
** NULL, then just return the other expression.
*/
................................................................................
    if( iCol<0 ){
      int iMem = ++pParse->nMem;
      int iAddr;
      Table *pTab = p->pSrc->a[0].pTab;
      int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
      sqlite3VdbeUsesBtree(v, iDb);

      sqlite3VdbeAddOp1(v, OP_MemLoad, iMem);
      iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);

      sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
      eType = IN_INDEX_ROWID;

      sqlite3VdbeJumpHere(v, iAddr);
................................................................................
          int iAddr;
          char *pKey;
  
          pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
          iDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
          sqlite3VdbeUsesBtree(v, iDb);

          sqlite3VdbeAddOp1(v, OP_MemLoad, iMem);
          iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem);
          sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
  
          sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
                               pKey,P4_KEYINFO_HANDOFF);
          VdbeComment((v, "%s", pIdx->zName));
          eType = IN_INDEX_INDEX;
................................................................................
  **    *  We are inside a trigger
  **
  ** If all of the above are false, then we can run this code just once
  ** save the results, and reuse the same result on subsequent invocations.
  */
  if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
    int mem = ++pParse->nMem;
    sqlite3VdbeAddOp1(v, OP_MemLoad, mem);
    testAddr = sqlite3VdbeAddOp0(v, OP_If);
    assert( testAddr>0 || pParse->db->mallocFailed );
    sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
  }

  switch( pExpr->op ){
    case TK_IN: {
................................................................................
    op = pExpr->op;
  }
  switch( op ){
    case TK_AGG_COLUMN: {
      AggInfo *pAggInfo = pExpr->pAggInfo;
      struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
      if( !pAggInfo->directMode ){
        sqlite3VdbeAddOp1(v, OP_MemLoad, pCol->iMem);
        break;
      }else if( pAggInfo->useSortingIdx ){
        sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx,
                              pCol->iSorterColumn, target);
        inReg = 1;
        break;
      }
      /* Otherwise, fall thru into the TK_COLUMN case */
    }
    case TK_COLUMN: {
      if( pExpr->iTable<0 ){
        /* This only happens when coding check constraints */
        assert( pParse->ckOffset>0 );
        sqlite3VdbeAddOp2(v, OP_Dup, pParse->ckOffset-pExpr->iColumn-1, 1);
      }else{
        sqlite3ExprCodeGetColumn(v, pExpr->pTab,
                                 pExpr->iColumn, pExpr->iTable, target);
        inReg = 1;
      }
      break;
    }
................................................................................
      sqlite3VdbeAddOp1(v, OP_Variable, pExpr->iTable);
      if( pExpr->token.n>1 ){
        sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n);
      }
      break;
    }
    case TK_REGISTER: {
      sqlite3VdbeAddOp1(v, OP_MemLoad, pExpr->iTable);
      break;
    }
#ifndef SQLITE_OMIT_CAST
    case TK_CAST: {
      /* Expressions of the form:   CAST(pLeft AS token) */
      int aff, to_op;
      sqlite3ExprCode(pParse, pExpr->pLeft, 0);
................................................................................
    }
    case TK_AGG_FUNCTION: {
      AggInfo *pInfo = pExpr->pAggInfo;
      if( pInfo==0 ){
        sqlite3ErrorMsg(pParse, "misuse of aggregate: %T",
            &pExpr->span);
      }else{
        sqlite3VdbeAddOp1(v, OP_MemLoad, pInfo->aFunc[pExpr->iAgg].iMem);
      }
      break;
    }
    case TK_CONST_FUNC:
    case TK_FUNCTION: {
      ExprList *pList = pExpr->pList;
      int nExpr = pList ? pList->nExpr : 0;
................................................................................
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_EXISTS:
    case TK_SELECT: {
      if( pExpr->iColumn==0 ){
        sqlite3CodeSubselect(pParse, pExpr);
      }
      sqlite3VdbeAddOp1(v, OP_MemLoad, pExpr->iColumn);
      VdbeComment((v, "load subquery result"));
      break;
    }
    case TK_IN: {
      int addr;
      char affinity;
      int ckOffset = pParse->ckOffset;
................................................................................
    }
#endif
    case TK_BETWEEN: {
      Expr *pLeft = pExpr->pLeft;
      struct ExprList_item *pLItem = pExpr->pList->a;
      Expr *pRight = pLItem->pExpr;
      sqlite3ExprCode(pParse, pLeft, 0);
      sqlite3VdbeAddOp0(v, OP_Dup);
      sqlite3ExprCode(pParse, pRight, 0);
      codeCompare(pParse, pLeft, pRight, OP_Ge, 0, 0);
      sqlite3VdbeAddOp1(v, OP_Pull, 1);
      pLItem++;
      pRight = pLItem->pExpr;
      sqlite3ExprCode(pParse, pRight, 0);
      codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0);
................................................................................
      expr_end_label = sqlite3VdbeMakeLabel(v);
      if( pExpr->pLeft ){
        sqlite3ExprCode(pParse, pExpr->pLeft, 0);
      }
      for(i=0; i<nExpr; i=i+2){
        sqlite3ExprCode(pParse, aListelem[i].pExpr, 0);
        if( pExpr->pLeft ){
          sqlite3VdbeAddOp2(v, OP_Dup, 1, 1);
          jumpInst = codeCompare(pParse, pExpr->pLeft, aListelem[i].pExpr,
                                 OP_Ne, 0, 1);
          sqlite3VdbeAddOp1(v, OP_Pop, 1);
        }else{
          jumpInst = sqlite3VdbeAddOp2(v, OP_IfNot, 1, 0);
        }
        sqlite3ExprCode(pParse, aListelem[i+1].pExpr, 0);
................................................................................
      }
      stackChng = 0;
      break;
    }
#endif
  }
  if( target && !inReg ){
    sqlite3VdbeAddOp2(v, OP_MemStore, target, 1);
    stackChng = 0;
  }
  if( pParse->ckOffset ){
    pParse->ckOffset += stackChng;
    assert( pParse->ckOffset );
  }
  return target;
................................................................................
  if( v==0 ) return;
  addr1 = sqlite3VdbeCurrentAddr(v);
  sqlite3ExprCode(pParse, pExpr, 0);
  addr2 = sqlite3VdbeCurrentAddr(v);
  if( addr2>addr1+1
   || ((pOp = sqlite3VdbeGetOp(v, addr1))!=0 && pOp->opcode==OP_Function) ){
    iMem = pExpr->iTable = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_MemStore, iMem, 0);
    pExpr->op = TK_REGISTER;
  }
}
#endif

/*
** Generate code that pushes the value of every element of the given
................................................................................
      ** 2 IF (x <= z) GOTO <dest>
      ** 3 ...
      */
      int addr;
      Expr *pLeft = pExpr->pLeft;
      Expr *pRight = pExpr->pList->a[0].pExpr;
      sqlite3ExprCode(pParse, pLeft, 0);
      sqlite3VdbeAddOp2(v, OP_Dup, 0, 0);
      sqlite3ExprCode(pParse, pRight, 0);
      addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull);

      pRight = pExpr->pList->a[1].pExpr;
      sqlite3ExprCode(pParse, pRight, 0);
      codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull);

................................................................................
      ** 2 GOTO <dest>
      ** 3 IF (x > z) GOTO <dest>
      */
      int addr;
      Expr *pLeft = pExpr->pLeft;
      Expr *pRight = pExpr->pList->a[0].pExpr;
      sqlite3ExprCode(pParse, pLeft, 0);
      sqlite3VdbeAddOp2(v, OP_Dup, 0, 0);
      sqlite3ExprCode(pParse, pRight, 0);
      addr = sqlite3VdbeCurrentAddr(v);
      codeCompare(pParse, pLeft, pRight, OP_Ge, addr+3, !jumpIfNull);

      sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
      sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
      pRight = pExpr->pList->a[1].pExpr;







|







 







<
|







 







|







 







|







 







|







 







|













|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
304
305
306
307
308
309
310

311
312
313
314
315
316
317
318
....
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
....
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
....
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
....
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
....
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
....
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
....
2197
2198
2199
2200
2201
2202
2203
2204
2205
2206
2207
2208
2209
2210
2211
....
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
....
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
2298
2299
2300
....
2334
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
....
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
....
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
....
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.331 2008/01/05 04:06:04 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
  if( v==0 ) return 0;
  p = sqlite3PExpr(pParse, TK_REGISTER, 0, 0, pToken);
  if( p==0 ){
    return 0;  /* Malloc failed */
  }
  depth = atoi((char*)&pToken->z[1]);
  p->iTable = ++pParse->nMem;

  sqlite3VdbeAddOp2(v, OP_Copy, -depth, p->iTable);
  return p;
}

/*
** Join two expressions using an AND operator.  If either expression is
** NULL, then just return the other expression.
*/
................................................................................
    if( iCol<0 ){
      int iMem = ++pParse->nMem;
      int iAddr;
      Table *pTab = p->pSrc->a[0].pTab;
      int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
      sqlite3VdbeUsesBtree(v, iDb);

      sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
      iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem);
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);

      sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead);
      eType = IN_INDEX_ROWID;

      sqlite3VdbeJumpHere(v, iAddr);
................................................................................
          int iAddr;
          char *pKey;
  
          pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx);
          iDb = sqlite3SchemaToIndex(db, pIdx->pSchema);
          sqlite3VdbeUsesBtree(v, iDb);

          sqlite3VdbeAddOp1(v, OP_SCopy, iMem);
          iAddr = sqlite3VdbeAddOp2(v, OP_If, 0, iMem);
          sqlite3VdbeAddOp2(v, OP_Integer, 1, iMem);
  
          sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb,
                               pKey,P4_KEYINFO_HANDOFF);
          VdbeComment((v, "%s", pIdx->zName));
          eType = IN_INDEX_INDEX;
................................................................................
  **    *  We are inside a trigger
  **
  ** If all of the above are false, then we can run this code just once
  ** save the results, and reuse the same result on subsequent invocations.
  */
  if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->trigStack ){
    int mem = ++pParse->nMem;
    sqlite3VdbeAddOp1(v, OP_SCopy, mem);
    testAddr = sqlite3VdbeAddOp0(v, OP_If);
    assert( testAddr>0 || pParse->db->mallocFailed );
    sqlite3VdbeAddOp2(v, OP_Integer, 1, mem);
  }

  switch( pExpr->op ){
    case TK_IN: {
................................................................................
    op = pExpr->op;
  }
  switch( op ){
    case TK_AGG_COLUMN: {
      AggInfo *pAggInfo = pExpr->pAggInfo;
      struct AggInfo_col *pCol = &pAggInfo->aCol[pExpr->iAgg];
      if( !pAggInfo->directMode ){
        sqlite3VdbeAddOp1(v, OP_SCopy, pCol->iMem);
        break;
      }else if( pAggInfo->useSortingIdx ){
        sqlite3VdbeAddOp3(v, OP_Column, pAggInfo->sortingIdx,
                              pCol->iSorterColumn, target);
        inReg = 1;
        break;
      }
      /* Otherwise, fall thru into the TK_COLUMN case */
    }
    case TK_COLUMN: {
      if( pExpr->iTable<0 ){
        /* This only happens when coding check constraints */
        assert( pParse->ckOffset>0 );
        sqlite3VdbeAddOp1(v, OP_SCopy, -(pParse->ckOffset-pExpr->iColumn-1));
      }else{
        sqlite3ExprCodeGetColumn(v, pExpr->pTab,
                                 pExpr->iColumn, pExpr->iTable, target);
        inReg = 1;
      }
      break;
    }
................................................................................
      sqlite3VdbeAddOp1(v, OP_Variable, pExpr->iTable);
      if( pExpr->token.n>1 ){
        sqlite3VdbeChangeP4(v, -1, (char*)pExpr->token.z, pExpr->token.n);
      }
      break;
    }
    case TK_REGISTER: {
      sqlite3VdbeAddOp1(v, OP_SCopy, pExpr->iTable);
      break;
    }
#ifndef SQLITE_OMIT_CAST
    case TK_CAST: {
      /* Expressions of the form:   CAST(pLeft AS token) */
      int aff, to_op;
      sqlite3ExprCode(pParse, pExpr->pLeft, 0);
................................................................................
    }
    case TK_AGG_FUNCTION: {
      AggInfo *pInfo = pExpr->pAggInfo;
      if( pInfo==0 ){
        sqlite3ErrorMsg(pParse, "misuse of aggregate: %T",
            &pExpr->span);
      }else{
        sqlite3VdbeAddOp1(v, OP_SCopy, pInfo->aFunc[pExpr->iAgg].iMem);
      }
      break;
    }
    case TK_CONST_FUNC:
    case TK_FUNCTION: {
      ExprList *pList = pExpr->pList;
      int nExpr = pList ? pList->nExpr : 0;
................................................................................
    }
#ifndef SQLITE_OMIT_SUBQUERY
    case TK_EXISTS:
    case TK_SELECT: {
      if( pExpr->iColumn==0 ){
        sqlite3CodeSubselect(pParse, pExpr);
      }
      sqlite3VdbeAddOp1(v, OP_SCopy, pExpr->iColumn);
      VdbeComment((v, "load subquery result"));
      break;
    }
    case TK_IN: {
      int addr;
      char affinity;
      int ckOffset = pParse->ckOffset;
................................................................................
    }
#endif
    case TK_BETWEEN: {
      Expr *pLeft = pExpr->pLeft;
      struct ExprList_item *pLItem = pExpr->pList->a;
      Expr *pRight = pLItem->pExpr;
      sqlite3ExprCode(pParse, pLeft, 0);
      sqlite3VdbeAddOp0(v, OP_Copy);
      sqlite3ExprCode(pParse, pRight, 0);
      codeCompare(pParse, pLeft, pRight, OP_Ge, 0, 0);
      sqlite3VdbeAddOp1(v, OP_Pull, 1);
      pLItem++;
      pRight = pLItem->pExpr;
      sqlite3ExprCode(pParse, pRight, 0);
      codeCompare(pParse, pLeft, pRight, OP_Le, 0, 0);
................................................................................
      expr_end_label = sqlite3VdbeMakeLabel(v);
      if( pExpr->pLeft ){
        sqlite3ExprCode(pParse, pExpr->pLeft, 0);
      }
      for(i=0; i<nExpr; i=i+2){
        sqlite3ExprCode(pParse, aListelem[i].pExpr, 0);
        if( pExpr->pLeft ){
          sqlite3VdbeAddOp1(v, OP_SCopy, -1);
          jumpInst = codeCompare(pParse, pExpr->pLeft, aListelem[i].pExpr,
                                 OP_Ne, 0, 1);
          sqlite3VdbeAddOp1(v, OP_Pop, 1);
        }else{
          jumpInst = sqlite3VdbeAddOp2(v, OP_IfNot, 1, 0);
        }
        sqlite3ExprCode(pParse, aListelem[i+1].pExpr, 0);
................................................................................
      }
      stackChng = 0;
      break;
    }
#endif
  }
  if( target && !inReg ){
    sqlite3VdbeAddOp2(v, OP_Move, 0, target);
    stackChng = 0;
  }
  if( pParse->ckOffset ){
    pParse->ckOffset += stackChng;
    assert( pParse->ckOffset );
  }
  return target;
................................................................................
  if( v==0 ) return;
  addr1 = sqlite3VdbeCurrentAddr(v);
  sqlite3ExprCode(pParse, pExpr, 0);
  addr2 = sqlite3VdbeCurrentAddr(v);
  if( addr2>addr1+1
   || ((pOp = sqlite3VdbeGetOp(v, addr1))!=0 && pOp->opcode==OP_Function) ){
    iMem = pExpr->iTable = ++pParse->nMem;
    sqlite3VdbeAddOp2(v, OP_Copy, 0, iMem);
    pExpr->op = TK_REGISTER;
  }
}
#endif

/*
** Generate code that pushes the value of every element of the given
................................................................................
      ** 2 IF (x <= z) GOTO <dest>
      ** 3 ...
      */
      int addr;
      Expr *pLeft = pExpr->pLeft;
      Expr *pRight = pExpr->pList->a[0].pExpr;
      sqlite3ExprCode(pParse, pLeft, 0);
      sqlite3VdbeAddOp0(v, OP_Copy);
      sqlite3ExprCode(pParse, pRight, 0);
      addr = codeCompare(pParse, pLeft, pRight, OP_Lt, 0, !jumpIfNull);

      pRight = pExpr->pList->a[1].pExpr;
      sqlite3ExprCode(pParse, pRight, 0);
      codeCompare(pParse, pLeft, pRight, OP_Le, dest, jumpIfNull);

................................................................................
      ** 2 GOTO <dest>
      ** 3 IF (x > z) GOTO <dest>
      */
      int addr;
      Expr *pLeft = pExpr->pLeft;
      Expr *pRight = pExpr->pList->a[0].pExpr;
      sqlite3ExprCode(pParse, pLeft, 0);
      sqlite3VdbeAddOp0(v, OP_Copy);
      sqlite3ExprCode(pParse, pRight, 0);
      addr = sqlite3VdbeCurrentAddr(v);
      codeCompare(pParse, pLeft, pRight, OP_Ge, addr+3, !jumpIfNull);

      sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
      sqlite3VdbeAddOp2(v, OP_Goto, 0, dest);
      pRight = pExpr->pList->a[1].pExpr;

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
...
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
...
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
....
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
....
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
....
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
....
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
....
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
....
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
....
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
....
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
....
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
....
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.211 2008/01/04 22:01:03 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
    memId = pParse->nMem;
    sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
    sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+12);
    sqlite3VdbeAddOp2(v, OP_Column, iCur, 0);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
    sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+11);
    sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0);
    sqlite3VdbeAddOp2(v, OP_MemStore, memId-1, 1);
    sqlite3VdbeAddOp2(v, OP_Column, iCur, 1);
    sqlite3VdbeAddOp2(v, OP_MemStore, memId, 1);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+12);
    sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+3);
    sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
  }
  return memId;
}

................................................................................
    int iCur = pParse->nTab;
    Vdbe *v = pParse->pVdbe;
    Db *pDb = &pParse->db->aDb[iDb];
    int addr;
    assert( v );
    addr = sqlite3VdbeCurrentAddr(v);
    sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
    sqlite3VdbeAddOp2(v, OP_MemLoad, memId-1, 0);
    sqlite3VdbeAddOp2(v, OP_NotNull, -1, addr+6);
    sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
    sqlite3VdbeAddOp1(v, OP_NewRowid, iCur);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
    sqlite3VdbeAddOp2(v, OP_MemLoad, memId, 0);
    sqlite3VdbeAddOp2(v, OP_MakeRecord, 2, 0);
    sqlite3CodeInsert(pParse, iCur, OPFLAG_APPEND);
    sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
  }
}
#else
/*
................................................................................
      /* The row that the VUpdate opcode will delete: none */
      sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
    }
    if( keyColumn>=0 ){
      if( useTempTable ){
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, iRowid);
      }else if( pSelect ){
        sqlite3VdbeAddOp3(v, OP_Dup, nColumn - keyColumn - 1, 1, iRowid);
        /* TODO: Avoid this use of the stack. */
        sqlite3VdbeAddOp2(v, OP_MemStore, iRowid, 1);
      }else{
        VdbeOp *pOp;
        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
        pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);
        if( pOp && pOp->opcode==OP_Null ){
          appendFlag = 1;
          pOp->opcode = OP_NewRowid;
          pOp->p1 = base;
          pOp->p2 = iRowid;
          pOp->p3 = counterMem;
        }else{
          /* TODO: Avoid this use of the stack. */
          sqlite3VdbeAddOp2(v, OP_MemStore, iRowid, 1);
        }
      }
      /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
      ** to generate a unique primary key value.
      */
      if( !appendFlag ){
        sqlite3VdbeAddOp2(v, OP_IfMemNull, iRowid, sqlite3VdbeCurrentAddr(v)+2);
................................................................................
        sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2);
        sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem);
        sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, iRowid);
      }
    }else if( IsVirtual(pTab) ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, iRowid);
    }else{
      sqlite3VdbeAddOp3(v, OP_NewRowid, base, 0, counterMem);
      sqlite3VdbeAddOp2(v, OP_MemStore, iRowid, 1);
      appendFlag = 1;
    }
    autoIncStep(pParse, counterMem, iRowid);

    /* Push onto the stack, data for all columns of the new entry, beginning
    ** with the first column.
    */
................................................................................
        }
      }
      if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore);
      }else if( useTempTable ){
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); 
      }else if( pSelect ){
        sqlite3VdbeAddOp2(v, OP_Dup, nColumn-j-1, 1);
        /* TODO: Avoid this use of the stack */
        sqlite3VdbeAddOp2(v, OP_MemStore, iRegStore, 1);
      }else{
        sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
      }
    }

    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
................................................................................
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
      onError = OE_Abort;
    }
    sqlite3VdbeAddOp2(v, OP_Dup, nCol-1-i, 1);
    addr = sqlite3VdbeAddOp2(v, OP_NotNull, 1, 0);
    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
        || onError==OE_Ignore || onError==OE_Replace );
    switch( onError ){
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
................................................................................
      case OE_Ignore: {
        sqlite3VdbeAddOp2(v, OP_Pop, nCol+1+hasTwoRowids, 0);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, 0);
        sqlite3VdbeAddOp2(v, OP_Push, nCol-i, 0);
        break;
      }
    }
    sqlite3VdbeJumpHere(v, addr);
  }

  /* Test all CHECK constraints
................................................................................
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    
    if( isUpdate ){
      sqlite3VdbeAddOp2(v, OP_Dup, nCol+1, 1);
      sqlite3VdbeAddOp2(v, OP_Dup, nCol+1, 1);
      jumpInst1 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
    }
    sqlite3VdbeAddOp2(v, OP_Dup, nCol, 1);
    jumpInst2 = sqlite3VdbeAddOp2(v, OP_NotExists, base, 0);
    switch( onError ){
      default: {
        onError = OE_Abort;
        /* Fall thru into the next case */
      }
      case OE_Rollback:
................................................................................
        sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
                         "PRIMARY KEY must be unique", P4_STATIC);
        break;
      }
      case OE_Replace: {
        sqlite3GenerateRowIndexDelete(v, pTab, base, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp2(v, OP_Dup, nCol+hasTwoRowids, 1);
          sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
        }
        seenReplace = 1;
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
................................................................................
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;
      }
    }
    sqlite3VdbeJumpHere(v, jumpInst2);
    if( isUpdate ){
      sqlite3VdbeJumpHere(v, jumpInst1);
      sqlite3VdbeAddOp2(v, OP_Dup, nCol+1, 1);
      sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
    }
  }

  /* Test all UNIQUE constraints by creating entries for each UNIQUE
  ** index and making sure that duplicate entries do not already exist.
  ** Add the new records to the indices as we go.
................................................................................
  */
  extra = -1;
  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
    if( aIdxUsed && aIdxUsed[iCur]==0 ) continue;  /* Skip unused indices */
    extra++;

    /* Create a key for accessing the index entry */
    sqlite3VdbeAddOp2(v, OP_Dup, nCol+extra, 1);
    for(i=0; i<pIdx->nColumn; i++){
      int idx = pIdx->aiColumn[i];
      if( idx==pTab->iPKey ){
        sqlite3VdbeAddOp2(v, OP_Dup, i+extra+nCol+1, 1);
      }else{
        sqlite3VdbeAddOp2(v, OP_Dup, i+extra+nCol-idx, 1);
      }
    }
    jumpInst1 = sqlite3VdbeAddOp2(v, OP_MakeIdxRec, pIdx->nColumn, 0);
    sqlite3IndexAffinityStr(v, pIdx);

    /* Find out what action to take in case there is an indexing conflict */
    onError = pIdx->onError;
................................................................................
    if( seenReplace ){
      if( onError==OE_Ignore ) onError = OE_Replace;
      else if( onError==OE_Fail ) onError = OE_Abort;
    }
    

    /* Check to see if the new index entry will be unique */
    sqlite3VdbeAddOp2(v, OP_Dup, extra+nCol+1+hasTwoRowids, 1);
    jumpInst2 = sqlite3VdbeAddOp2(v, OP_IsUnique, base+iCur+1, 0);

    /* Generate code that executes if the new index entry is not unique */
    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
        || onError==OE_Ignore || onError==OE_Replace );
    switch( onError ){
      case OE_Rollback:
................................................................................
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {
        int iRowid = sqlite3StackToReg(pParse, 1);
        sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp2(v, OP_Dup, nCol+extra+1+hasTwoRowids, 1);
          sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
        }
        seenReplace = 1;
        break;
      }
    }
#if NULL_DISTINCT_FOR_UNIQUE
................................................................................
    if( aIdxUsed && aIdxUsed[i]==0 ) continue;
    sqlite3VdbeAddOp2(v, OP_IdxInsert, base+i+1, 0);
  }
  sqlite3VdbeAddOp2(v, OP_MakeRecord, pTab->nCol, 0);
  sqlite3TableAffinityStr(v, pTab);
#ifndef SQLITE_OMIT_TRIGGER
  if( newIdx>=0 ){
    sqlite3VdbeAddOp2(v, OP_Dup, 1, 0);
    sqlite3VdbeAddOp2(v, OP_Dup, 1, 0);
    sqlite3CodeInsert(pParse, newIdx, 0);
  }
#endif
  if( pParse->nested ){
    pik_flags = 0;
  }else{
    pik_flags = OPFLAG_NCHANGE;
................................................................................
  }else{
    emptyDestTest = 0;
  }
  sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
  emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
  if( pDest->iPKey>=0 ){
    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0);
    sqlite3VdbeAddOp2(v, OP_Dup, 0, 0);
    addr2 = sqlite3VdbeAddOp2(v, OP_NotExists, iDest, 0);
    sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
                      "PRIMARY KEY must be unique", P4_STATIC);
    sqlite3VdbeJumpHere(v, addr2);
    autoIncStep(pParse, counterMem, 0);
  }else if( pDest->pIndex==0 ){
    addr1 = sqlite3VdbeAddOp1(v, OP_NewRowid, iDest);







|







 







|

|







 







|




|







 







<
<
|












|







 







|
<







 







|
<
<







 







|







 







|







 







|
|


|







 







|







 







|







 







|



|

|







 







|







 







|







 







|
|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
...
724
725
726
727
728
729
730


731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
...
752
753
754
755
756
757
758
759

760
761
762
763
764
765
766
...
789
790
791
792
793
794
795
796


797
798
799
800
801
802
803
...
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
....
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
....
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
....
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
....
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
....
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
....
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
....
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
....
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
....
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.212 2008/01/05 04:06:04 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
    memId = pParse->nMem;
    sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenRead);
    sqlite3VdbeAddOp2(v, OP_Rewind, iCur, addr+12);
    sqlite3VdbeAddOp2(v, OP_Column, iCur, 0);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
    sqlite3VdbeAddOp2(v, OP_Ne, 0x100, addr+11);
    sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0);
    sqlite3VdbeAddOp2(v, OP_Move, 0, memId-1);
    sqlite3VdbeAddOp2(v, OP_Column, iCur, 1);
    sqlite3VdbeAddOp2(v, OP_Move, 0, memId);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, addr+12);
    sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+3);
    sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
  }
  return memId;
}

................................................................................
    int iCur = pParse->nTab;
    Vdbe *v = pParse->pVdbe;
    Db *pDb = &pParse->db->aDb[iDb];
    int addr;
    assert( v );
    addr = sqlite3VdbeCurrentAddr(v);
    sqlite3OpenTable(pParse, iCur, iDb, pDb->pSchema->pSeqTab, OP_OpenWrite);
    sqlite3VdbeAddOp2(v, OP_SCopy, memId-1, 0);
    sqlite3VdbeAddOp2(v, OP_NotNull, -1, addr+6);
    sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
    sqlite3VdbeAddOp1(v, OP_NewRowid, iCur);
    sqlite3VdbeAddOp4(v, OP_String8, 0, 0, 0, pTab->zName, 0);
    sqlite3VdbeAddOp2(v, OP_SCopy, memId, 0);
    sqlite3VdbeAddOp2(v, OP_MakeRecord, 2, 0);
    sqlite3CodeInsert(pParse, iCur, OPFLAG_APPEND);
    sqlite3VdbeAddOp2(v, OP_Close, iCur, 0);
  }
}
#else
/*
................................................................................
      /* The row that the VUpdate opcode will delete: none */
      sqlite3VdbeAddOp2(v, OP_Null, 0, iReg);
    }
    if( keyColumn>=0 ){
      if( useTempTable ){
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, keyColumn, iRowid);
      }else if( pSelect ){


        sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn - keyColumn - 1), iRowid);
      }else{
        VdbeOp *pOp;
        sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, 0);
        pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);
        if( pOp && pOp->opcode==OP_Null ){
          appendFlag = 1;
          pOp->opcode = OP_NewRowid;
          pOp->p1 = base;
          pOp->p2 = iRowid;
          pOp->p3 = counterMem;
        }else{
          /* TODO: Avoid this use of the stack. */
          sqlite3VdbeAddOp2(v, OP_Move, 0, iRowid);
        }
      }
      /* If the PRIMARY KEY expression is NULL, then use OP_NewRowid
      ** to generate a unique primary key value.
      */
      if( !appendFlag ){
        sqlite3VdbeAddOp2(v, OP_IfMemNull, iRowid, sqlite3VdbeCurrentAddr(v)+2);
................................................................................
        sqlite3VdbeAddOp2(v, OP_Goto, -1, sqlite3VdbeCurrentAddr(v)+2);
        sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem);
        sqlite3VdbeAddOp3(v, OP_MustBeInt, 0, 0, iRowid);
      }
    }else if( IsVirtual(pTab) ){
      sqlite3VdbeAddOp2(v, OP_Null, 0, iRowid);
    }else{
      sqlite3VdbeAddOp3(v, OP_NewRowid, base, iRowid, counterMem);

      appendFlag = 1;
    }
    autoIncStep(pParse, counterMem, iRowid);

    /* Push onto the stack, data for all columns of the new entry, beginning
    ** with the first column.
    */
................................................................................
        }
      }
      if( j<0 || nColumn==0 || (pColumn && j>=pColumn->nId) ){
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, iRegStore);
      }else if( useTempTable ){
        sqlite3VdbeAddOp3(v, OP_Column, srcTab, j, iRegStore); 
      }else if( pSelect ){
        sqlite3VdbeAddOp2(v, OP_SCopy, -(nColumn-j-1), iRegStore);


      }else{
        sqlite3ExprCode(pParse, pList->a[j].pExpr, iRegStore);
      }
    }

    /* Generate code to check constraints and generate index keys and
    ** do the insertion.
................................................................................
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
      onError = OE_Abort;
    }
    sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i));
    addr = sqlite3VdbeAddOp2(v, OP_NotNull, 1, 0);
    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
        || onError==OE_Ignore || onError==OE_Replace );
    switch( onError ){
      case OE_Rollback:
      case OE_Abort:
      case OE_Fail: {
................................................................................
      case OE_Ignore: {
        sqlite3VdbeAddOp2(v, OP_Pop, nCol+1+hasTwoRowids, 0);
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {
        sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, 0);
        sqlite3VdbeAddOp1(v, OP_Push, nCol-i);
        break;
      }
    }
    sqlite3VdbeJumpHere(v, addr);
  }

  /* Test all CHECK constraints
................................................................................
    if( overrideError!=OE_Default ){
      onError = overrideError;
    }else if( onError==OE_Default ){
      onError = OE_Abort;
    }
    
    if( isUpdate ){
      sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
      sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
      jumpInst1 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
    }
    sqlite3VdbeAddOp1(v, OP_SCopy, -nCol);
    jumpInst2 = sqlite3VdbeAddOp2(v, OP_NotExists, base, 0);
    switch( onError ){
      default: {
        onError = OE_Abort;
        /* Fall thru into the next case */
      }
      case OE_Rollback:
................................................................................
        sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
                         "PRIMARY KEY must be unique", P4_STATIC);
        break;
      }
      case OE_Replace: {
        sqlite3GenerateRowIndexDelete(v, pTab, base, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+hasTwoRowids));
          sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
        }
        seenReplace = 1;
        break;
      }
      case OE_Ignore: {
        assert( seenReplace==0 );
................................................................................
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;
      }
    }
    sqlite3VdbeJumpHere(v, jumpInst2);
    if( isUpdate ){
      sqlite3VdbeJumpHere(v, jumpInst1);
      sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
      sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
    }
  }

  /* Test all UNIQUE constraints by creating entries for each UNIQUE
  ** index and making sure that duplicate entries do not already exist.
  ** Add the new records to the indices as we go.
................................................................................
  */
  extra = -1;
  for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
    if( aIdxUsed && aIdxUsed[iCur]==0 ) continue;  /* Skip unused indices */
    extra++;

    /* Create a key for accessing the index entry */
    sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra));
    for(i=0; i<pIdx->nColumn; i++){
      int idx = pIdx->aiColumn[i];
      if( idx==pTab->iPKey ){
        sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol+1));
      }else{
        sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol-idx));
      }
    }
    jumpInst1 = sqlite3VdbeAddOp2(v, OP_MakeIdxRec, pIdx->nColumn, 0);
    sqlite3IndexAffinityStr(v, pIdx);

    /* Find out what action to take in case there is an indexing conflict */
    onError = pIdx->onError;
................................................................................
    if( seenReplace ){
      if( onError==OE_Ignore ) onError = OE_Replace;
      else if( onError==OE_Fail ) onError = OE_Abort;
    }
    

    /* Check to see if the new index entry will be unique */
    sqlite3VdbeAddOp1(v, OP_SCopy, -(extra+nCol+1+hasTwoRowids));
    jumpInst2 = sqlite3VdbeAddOp2(v, OP_IsUnique, base+iCur+1, 0);

    /* Generate code that executes if the new index entry is not unique */
    assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
        || onError==OE_Ignore || onError==OE_Replace );
    switch( onError ){
      case OE_Rollback:
................................................................................
        sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
        break;
      }
      case OE_Replace: {
        int iRowid = sqlite3StackToReg(pParse, 1);
        sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0);
        if( isUpdate ){
          sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra+1+hasTwoRowids));
          sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
        }
        seenReplace = 1;
        break;
      }
    }
#if NULL_DISTINCT_FOR_UNIQUE
................................................................................
    if( aIdxUsed && aIdxUsed[i]==0 ) continue;
    sqlite3VdbeAddOp2(v, OP_IdxInsert, base+i+1, 0);
  }
  sqlite3VdbeAddOp2(v, OP_MakeRecord, pTab->nCol, 0);
  sqlite3TableAffinityStr(v, pTab);
#ifndef SQLITE_OMIT_TRIGGER
  if( newIdx>=0 ){
    sqlite3VdbeAddOp1(v, OP_Copy, -1);
    sqlite3VdbeAddOp1(v, OP_Copy, -1);
    sqlite3CodeInsert(pParse, newIdx, 0);
  }
#endif
  if( pParse->nested ){
    pik_flags = 0;
  }else{
    pik_flags = OPFLAG_NCHANGE;
................................................................................
  }else{
    emptyDestTest = 0;
  }
  sqlite3OpenTable(pParse, iSrc, iDbSrc, pSrc, OP_OpenRead);
  emptySrcTest = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
  if( pDest->iPKey>=0 ){
    addr1 = sqlite3VdbeAddOp2(v, OP_Rowid, iSrc, 0);
    sqlite3VdbeAddOp0(v, OP_Copy);
    addr2 = sqlite3VdbeAddOp2(v, OP_NotExists, iDest, 0);
    sqlite3VdbeAddOp4(v, OP_Halt, SQLITE_CONSTRAINT, onError, 0,
                      "PRIMARY KEY must be unique", P4_STATIC);
    sqlite3VdbeJumpHere(v, addr2);
    autoIncStep(pParse, counterMem, 0);
  }else if( pDest->pIndex==0 ){
    addr1 = sqlite3VdbeAddOp1(v, OP_NewRowid, iDest);

Changes to src/pragma.c.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
...
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
...
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.158 2008/01/04 22:01:03 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/* Ignore this whole file if pragmas are disabled
*/
#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER)
................................................................................
  ** synchronous setting.  A negative value means synchronous is off
  ** and a positive value means synchronous is on.
  */
  if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
    static const VdbeOpList getCacheSize[] = {
      { OP_ReadCookie,  0, 0,        2},  /* 0 */
      { OP_AbsValue,    0, 0,        0},
      { OP_Dup,         0, 0,        0},
      { OP_Integer,     0, 0,        0},
      { OP_Ne,          0, 6,        0},
      { OP_Integer,     0, 0,        0},  /* 5 */
      { OP_Callback,    1, 0,        0},
    };
    int addr;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
................................................................................
    int i, j, addr, mxErr;

    /* Code that appears at the end of the integrity check.  If no error
    ** messages have been generated, output OK.  Otherwise output the
    ** error message
    */
    static const VdbeOpList endCode[] = {
      { OP_MemLoad,     1, 0,        0},
      { OP_Integer,     0, 0,        0},
      { OP_Ne,          0, 0,        0},    /* 2 */
      { OP_String8,     0, 0,        0},    /* 3 */
      { OP_Callback,    1, 0,        0},
    };

    int isQuick = (zLeft[0]=='q');
................................................................................
        sqlite3VdbeJumpHere(v, loopTop);
        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
          static const VdbeOpList cntIdx[] = {
             { OP_Integer,      0,  3,  0},
             { OP_Rewind,       0,  0,  0},  /* 1 */
             { OP_MemIncr,      1,  3,  0},
             { OP_Next,         0,  0,  0},  /* 3 */
             { OP_MemLoad,      2,  0,  0},
             { OP_MemLoad,      3,  0,  0},
             { OP_Eq,           0,  0,  0},  /* 6 */
             { OP_MemIncr,     -1,  1,  0},
             { OP_String8,      0,  0,  0},  /* 8 */
             { OP_String8,      0,  0,  0},  /* 9 */
             { OP_Concat,       0,  0,  0},
             { OP_Callback,     1,  0,  0},
          };







|







 







|







 







|







 







|
|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
...
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
...
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains code used to implement the PRAGMA command.
**
** $Id: pragma.c,v 1.159 2008/01/05 04:06:04 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/* Ignore this whole file if pragmas are disabled
*/
#if !defined(SQLITE_OMIT_PRAGMA) && !defined(SQLITE_OMIT_PARSER)
................................................................................
  ** synchronous setting.  A negative value means synchronous is off
  ** and a positive value means synchronous is on.
  */
  if( sqlite3StrICmp(zLeft,"default_cache_size")==0 ){
    static const VdbeOpList getCacheSize[] = {
      { OP_ReadCookie,  0, 0,        2},  /* 0 */
      { OP_AbsValue,    0, 0,        0},
      { OP_Copy,        0, 0,        0},
      { OP_Integer,     0, 0,        0},
      { OP_Ne,          0, 6,        0},
      { OP_Integer,     0, 0,        0},  /* 5 */
      { OP_Callback,    1, 0,        0},
    };
    int addr;
    if( sqlite3ReadSchema(pParse) ) goto pragma_out;
................................................................................
    int i, j, addr, mxErr;

    /* Code that appears at the end of the integrity check.  If no error
    ** messages have been generated, output OK.  Otherwise output the
    ** error message
    */
    static const VdbeOpList endCode[] = {
      { OP_SCopy,       1, 0,        0},
      { OP_Integer,     0, 0,        0},
      { OP_Ne,          0, 0,        0},    /* 2 */
      { OP_String8,     0, 0,        0},    /* 3 */
      { OP_Callback,    1, 0,        0},
    };

    int isQuick = (zLeft[0]=='q');
................................................................................
        sqlite3VdbeJumpHere(v, loopTop);
        for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
          static const VdbeOpList cntIdx[] = {
             { OP_Integer,      0,  3,  0},
             { OP_Rewind,       0,  0,  0},  /* 1 */
             { OP_MemIncr,      1,  3,  0},
             { OP_Next,         0,  0,  0},  /* 3 */
             { OP_SCopy,        2,  0,  0},
             { OP_SCopy,        3,  0,  0},
             { OP_Eq,           0,  0,  0},  /* 6 */
             { OP_MemIncr,     -1,  1,  0},
             { OP_String8,      0,  0,  0},  /* 8 */
             { OP_String8,      0,  0,  0},  /* 9 */
             { OP_Concat,       0,  0,  0},
             { OP_Callback,     1,  0,  0},
          };

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
...
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
...
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
....
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
....
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
....
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
....
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.384 2008/01/04 22:01:03 drh Exp $
*/
#include "sqliteInt.h"


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
................................................................................
      addr2 = sqlite3VdbeAddOp2(v, OP_IfMemNull, iMem+1, 0);
      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
      if( pOrderBy ){
        /* At first glance you would think we could optimize out the
        ** ORDER BY in this case since the order of entries in the set
        ** does not matter.  But there might be a LIMIT clause, in which
        ** case the order does matter */
        sqlite3VdbeAddOp2(v, OP_MemLoad, iMem+1, 0);
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 0, 0, &p->affinity, 1);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
      }
      sqlite3VdbeJumpHere(v, addr2);
      break;
................................................................................

    /* If this is a scalar select that is part of an expression, then
    ** store the results in the appropriate memory cell and break out
    ** of the scan loop.
    */
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite3VdbeAddOp2(v, OP_MemLoad, iMem+1, 0);
      if( pOrderBy ){
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp2(v, OP_MemStore, iParm, 1);
        /* The LIMIT clause will jump out of the loop for us */
      }
      break;
    }
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */

    /* Send the data to the callback function or to a subroutine.  In the
................................................................................
    */
    case SRT_Subroutine:
    case SRT_Callback: {
      if( pOrderBy ){
        sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0);
        pushOntoSorter(pParse, pOrderBy, p);
      }else if( eDest==SRT_Subroutine ){
        for(i=0; i<nColumn; i++) sqlite3VdbeAddOp2(v, OP_MemLoad, iMem+i+1, 0);
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }else{
        sqlite3VdbeAddOp2(v, OP_ResultRow, iMem+1, nColumn);
      }
      break;
    }

................................................................................
      sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
      sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &p->affinity, 1);
      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
      break;
    }
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite3VdbeAddOp2(v, OP_MemStore, iParm, 1);
      /* The LIMIT clause will terminate the loop for us */
      break;
    }
#endif
    case SRT_Callback:
    case SRT_Subroutine: {
      int i;
................................................................................
  if( p->pLimit ){
    p->iLimit = iLimit = ++pParse->nMem;
    pParse->nMem++;
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) return;
    sqlite3ExprCode(pParse, p->pLimit, 0);
    sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0);
    sqlite3VdbeAddOp2(v, OP_MemStore, iLimit, 1);
    VdbeComment((v, "LIMIT counter"));
    sqlite3VdbeAddOp2(v, OP_IfMemZero, iLimit, iBreak);
    sqlite3VdbeAddOp2(v, OP_MemLoad, iLimit, 0);
  }
  if( p->pOffset ){
    p->iOffset = iOffset = ++pParse->nMem;
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) return;
    sqlite3ExprCode(pParse, p->pOffset, 0);
    sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0);
    sqlite3VdbeAddOp2(v, OP_MemStore, iOffset, p->pLimit==0);
    VdbeComment((v, "OFFSET counter"));
    addr1 = sqlite3VdbeAddOp2(v, OP_IfMemPos, iOffset, 0);
    sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
    sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
    sqlite3VdbeJumpHere(v, addr1);
    if( p->pLimit ){
      sqlite3VdbeAddOp2(v, OP_Add, 0, 0);
................................................................................
  }
  if( p->pLimit ){
    addr1 = sqlite3VdbeAddOp2(v, OP_IfMemPos, iLimit, 0);
    sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
    sqlite3VdbeAddOp2(v, OP_Integer, -1, iLimit+1);
    addr2 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
    sqlite3VdbeJumpHere(v, addr1);
    sqlite3VdbeAddOp2(v, OP_MemStore, iLimit+1, 1);
    VdbeComment((v, "LIMIT+OFFSET"));
    sqlite3VdbeJumpHere(v, addr2);
  }
}

/*
** Allocate a virtual index to use for sorting.
................................................................................
      for(j=0; j<pGroupBy->nExpr; j++){
        if( groupBySort ){
          sqlite3VdbeAddOp2(v, OP_Column, sAggInfo.sortingIdx, j);
        }else{
          sAggInfo.directMode = 1;
          sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, 0);
        }
        sqlite3VdbeAddOp2(v, OP_MemStore, iBMem+j, j<pGroupBy->nExpr-1);
      }
      for(j=pGroupBy->nExpr-1; j>=0; j--){
        if( j<pGroupBy->nExpr-1 ){
          sqlite3VdbeAddOp2(v, OP_MemLoad, iBMem+j, 0);
        }
        sqlite3VdbeAddOp2(v, OP_MemLoad, iAMem+j, 0);
        if( j==0 ){
          sqlite3VdbeAddOp2(v, OP_Eq, 0x200, addrProcessRow);
        }else{
          sqlite3VdbeAddOp2(v, OP_Ne, 0x200, addrGroupByChange);
        }
        sqlite3VdbeChangeP4(v, -1, (void*)pKeyInfo->aColl[j], P4_COLLSEQ);
      }
................................................................................
      ** This code copies current group by terms in b0,b1,b2,...
      ** over to a0,a1,a2.  It then calls the output subroutine
      ** and resets the aggregate accumulator registers in preparation
      ** for the next GROUP BY batch.
      */
      sqlite3VdbeResolveLabel(v, addrGroupByChange);
      for(j=0; j<pGroupBy->nExpr; j++){
        sqlite3VdbeAddOp2(v, OP_MemMove, iAMem+j, iBMem+j);
      }
      sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow);
      VdbeComment((v, "output one row"));
      sqlite3VdbeAddOp2(v, OP_IfMemPos, iAbortFlag, addrEnd);
      VdbeComment((v, "check abort flag"));
      sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrReset);
      VdbeComment((v, "reset accumulator"));







|







 







|







 







|



|







 







|







 







|







 







|


|







|







 







|







 







|



|

|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
...
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
...
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
...
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
....
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
....
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
....
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
....
3569
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.385 2008/01/05 04:06:04 drh Exp $
*/
#include "sqliteInt.h"


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
................................................................................
      addr2 = sqlite3VdbeAddOp2(v, OP_IfMemNull, iMem+1, 0);
      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
      if( pOrderBy ){
        /* At first glance you would think we could optimize out the
        ** ORDER BY in this case since the order of entries in the set
        ** does not matter.  But there might be a LIMIT clause, in which
        ** case the order does matter */
        sqlite3VdbeAddOp2(v, OP_SCopy, iMem+1, 0);
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 0, 0, &p->affinity, 1);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
      }
      sqlite3VdbeJumpHere(v, addr2);
      break;
................................................................................

    /* If this is a scalar select that is part of an expression, then
    ** store the results in the appropriate memory cell and break out
    ** of the scan loop.
    */
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite3VdbeAddOp2(v, OP_SCopy, iMem+1, 0);
      if( pOrderBy ){
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp2(v, OP_Move, 0, iParm);
        /* The LIMIT clause will jump out of the loop for us */
      }
      break;
    }
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */

    /* Send the data to the callback function or to a subroutine.  In the
................................................................................
    */
    case SRT_Subroutine:
    case SRT_Callback: {
      if( pOrderBy ){
        sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0);
        pushOntoSorter(pParse, pOrderBy, p);
      }else if( eDest==SRT_Subroutine ){
        for(i=0; i<nColumn; i++) sqlite3VdbeAddOp2(v, OP_SCopy, iMem+i+1, 0);
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }else{
        sqlite3VdbeAddOp2(v, OP_ResultRow, iMem+1, nColumn);
      }
      break;
    }

................................................................................
      sqlite3VdbeAddOp2(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
      sqlite3VdbeAddOp4(v, OP_MakeRecord, 1, 0, 0, &p->affinity, 1);
      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
      break;
    }
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite3VdbeAddOp2(v, OP_Move, 0, iParm);
      /* The LIMIT clause will terminate the loop for us */
      break;
    }
#endif
    case SRT_Callback:
    case SRT_Subroutine: {
      int i;
................................................................................
  if( p->pLimit ){
    p->iLimit = iLimit = ++pParse->nMem;
    pParse->nMem++;
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) return;
    sqlite3ExprCode(pParse, p->pLimit, 0);
    sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0);
    sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit);
    VdbeComment((v, "LIMIT counter"));
    sqlite3VdbeAddOp2(v, OP_IfMemZero, iLimit, iBreak);
    sqlite3VdbeAddOp2(v, OP_SCopy, iLimit, 0);
  }
  if( p->pOffset ){
    p->iOffset = iOffset = ++pParse->nMem;
    v = sqlite3GetVdbe(pParse);
    if( v==0 ) return;
    sqlite3ExprCode(pParse, p->pOffset, 0);
    sqlite3VdbeAddOp2(v, OP_MustBeInt, 0, 0);
    sqlite3VdbeAddOp2(v, p->pLimit==0 ? OP_Move : OP_Copy, 0, iOffset);
    VdbeComment((v, "OFFSET counter"));
    addr1 = sqlite3VdbeAddOp2(v, OP_IfMemPos, iOffset, 0);
    sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
    sqlite3VdbeAddOp2(v, OP_Integer, 0, 0);
    sqlite3VdbeJumpHere(v, addr1);
    if( p->pLimit ){
      sqlite3VdbeAddOp2(v, OP_Add, 0, 0);
................................................................................
  }
  if( p->pLimit ){
    addr1 = sqlite3VdbeAddOp2(v, OP_IfMemPos, iLimit, 0);
    sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
    sqlite3VdbeAddOp2(v, OP_Integer, -1, iLimit+1);
    addr2 = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
    sqlite3VdbeJumpHere(v, addr1);
    sqlite3VdbeAddOp2(v, OP_Move, 0, iLimit+1);
    VdbeComment((v, "LIMIT+OFFSET"));
    sqlite3VdbeJumpHere(v, addr2);
  }
}

/*
** Allocate a virtual index to use for sorting.
................................................................................
      for(j=0; j<pGroupBy->nExpr; j++){
        if( groupBySort ){
          sqlite3VdbeAddOp2(v, OP_Column, sAggInfo.sortingIdx, j);
        }else{
          sAggInfo.directMode = 1;
          sqlite3ExprCode(pParse, pGroupBy->a[j].pExpr, 0);
        }
        sqlite3VdbeAddOp2(v, j<pGroupBy->nExpr-1?OP_Move:OP_Copy, 0, iBMem+j);
      }
      for(j=pGroupBy->nExpr-1; j>=0; j--){
        if( j<pGroupBy->nExpr-1 ){
          sqlite3VdbeAddOp2(v, OP_SCopy, iBMem+j, 0);
        }
        sqlite3VdbeAddOp2(v, OP_SCopy, iAMem+j, 0);
        if( j==0 ){
          sqlite3VdbeAddOp2(v, OP_Eq, 0x200, addrProcessRow);
        }else{
          sqlite3VdbeAddOp2(v, OP_Ne, 0x200, addrGroupByChange);
        }
        sqlite3VdbeChangeP4(v, -1, (void*)pKeyInfo->aColl[j], P4_COLLSEQ);
      }
................................................................................
      ** This code copies current group by terms in b0,b1,b2,...
      ** over to a0,a1,a2.  It then calls the output subroutine
      ** and resets the aggregate accumulator registers in preparation
      ** for the next GROUP BY batch.
      */
      sqlite3VdbeResolveLabel(v, addrGroupByChange);
      for(j=0; j<pGroupBy->nExpr; j++){
        sqlite3VdbeAddOp2(v, OP_Move, iBMem+j, iAMem+j);
      }
      sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrOutputRow);
      VdbeComment((v, "output one row"));
      sqlite3VdbeAddOp2(v, OP_IfMemPos, iAbortFlag, addrEnd);
      VdbeComment((v, "check abort flag"));
      sqlite3VdbeAddOp2(v, OP_Gosub, 0, addrReset);
      VdbeComment((v, "reset accumulator"));

Changes to src/trigger.c.

233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
      { OP_String8,    0, 0,  0          },  /* 2: trigger name */
      { OP_String8,    0, 0,  0          },  /* 3: table name */
      { OP_Integer,    0, 0,  0          },
      { OP_String8,    0, 0,  0          },  /* 5: "CREATE TRIGGER " */
      { OP_String8,    0, 0,  0          },  /* 6: SQL */
      { OP_Concat,     0, 0,  0          }, 
      { OP_MakeRecord, 5, 0,  0          },  /* 8: "aaada" */
      { OP_MemStore,   0, 1,  0          },  /* 9: Store data */
      { OP_MemStore,   0, 1,  0          },  /* 10: Store key */
      { OP_Insert,     0, 0,  0          },
    };
    int addr;
    Vdbe *v;
    int iKey = ++pParse->nMem;
    int iData = ++pParse->nMem;

................................................................................
    addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
    sqlite3VdbeChangeP4(v, addr+1, "trigger", P4_STATIC);
    sqlite3VdbeChangeP4(v, addr+2, pTrig->name, 0); 
    sqlite3VdbeChangeP4(v, addr+3, pTrig->table, 0);
    sqlite3VdbeChangeP4(v, addr+5, "CREATE TRIGGER ", P4_STATIC); 
    sqlite3VdbeChangeP4(v, addr+6, (char*)pAll->z, pAll->n);
    sqlite3VdbeChangeP4(v, addr+8, "aaada", P4_STATIC);
    sqlite3VdbeChangeP1(v, addr+9, iData);
    sqlite3VdbeChangeP2(v, addr+11, iData);
    sqlite3VdbeChangeP1(v, addr+10, iKey);
    sqlite3VdbeChangeP3(v, addr+11, iKey);
    sqlite3ChangeCookie(db, v, iDb);
    sqlite3VdbeAddOp2(v, OP_Close, 0, 0);
    sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
        db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC
    );
  }







|
|







 







|
|
|







233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
...
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
      { OP_String8,    0, 0,  0          },  /* 2: trigger name */
      { OP_String8,    0, 0,  0          },  /* 3: table name */
      { OP_Integer,    0, 0,  0          },
      { OP_String8,    0, 0,  0          },  /* 5: "CREATE TRIGGER " */
      { OP_String8,    0, 0,  0          },  /* 6: SQL */
      { OP_Concat,     0, 0,  0          }, 
      { OP_MakeRecord, 5, 0,  0          },  /* 8: "aaada" */
      { OP_Move,       0, 0,  0          },  /* 9: Store data */
      { OP_Move,       0, 0,  0          },  /* 10: Store key */
      { OP_Insert,     0, 0,  0          },
    };
    int addr;
    Vdbe *v;
    int iKey = ++pParse->nMem;
    int iData = ++pParse->nMem;

................................................................................
    addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
    sqlite3VdbeChangeP4(v, addr+1, "trigger", P4_STATIC);
    sqlite3VdbeChangeP4(v, addr+2, pTrig->name, 0); 
    sqlite3VdbeChangeP4(v, addr+3, pTrig->table, 0);
    sqlite3VdbeChangeP4(v, addr+5, "CREATE TRIGGER ", P4_STATIC); 
    sqlite3VdbeChangeP4(v, addr+6, (char*)pAll->z, pAll->n);
    sqlite3VdbeChangeP4(v, addr+8, "aaada", P4_STATIC);
    sqlite3VdbeChangeP2(v, addr+9, iData);
    sqlite3VdbeChangeP2(v, addr+10, iKey);
    sqlite3VdbeChangeP2(v, addr+11, iData);
    sqlite3VdbeChangeP3(v, addr+11, iKey);
    sqlite3ChangeCookie(db, v, iDb);
    sqlite3VdbeAddOp2(v, OP_Close, 0, 0);
    sqlite3VdbeAddOp4(v, OP_ParseSchema, iDb, 0, 0, sqlite3MPrintf(
        db, "type='trigger' AND name='%q'", pTrig->name), P4_DYNAMIC
    );
  }

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.158 2008/01/04 22:01:03 drh Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
    /* Loop over every record that needs updating.  We have to load
    ** the old data for each record to be updated because some columns
    ** might not change and we will need to copy the old value.
    ** Also, the old data is needed to delete the old index entries.
    ** So make the cursor point at the old record.
    */
    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);
    sqlite3VdbeAddOp2(v, OP_MemLoad, iRowid, 0);

    /* If the record number will change, push the record number as it
    ** will be after the update. (The old record number is currently
    ** on top of the stack.)
    */
    if( chngRowid ){
      sqlite3ExprCode(pParse, pRowidExpr, 0);







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.159 2008/01/05 04:06:04 drh Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
    /* Loop over every record that needs updating.  We have to load
    ** the old data for each record to be updated because some columns
    ** might not change and we will need to copy the old value.
    ** Also, the old data is needed to delete the old index entries.
    ** So make the cursor point at the old record.
    */
    sqlite3VdbeAddOp3(v, OP_NotExists, iCur, addr, iRowid);
    sqlite3VdbeAddOp2(v, OP_SCopy, iRowid, 0);

    /* If the record number will change, push the record number as it
    ** will be after the update. (The old record number is currently
    ** on top of the stack.)
    */
    if( chngRowid ){
      sqlite3ExprCode(pParse, pRowidExpr, 0);

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
466
467
468
469
470
471
472

473
474
475
476
477
478
479
...
592
593
594
595
596
597
598
599

600
601
602
603
604
605
606
607
608

































































609
610
611
612
613
614
615
...
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936

937
938
939
940



941
942










943


















944
945




946






947









948
949
950
951

952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
....
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
....
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
4648
4649
4650
4651
4652
4653
4654
4655
4656
4657
4658
4659
4660
4661
4662
4663
4664
....
4764
4765
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
....
5301
5302
5303
5304
5305
5306
5307






5308
5309
5310
5311
5312
5313
5314
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.679 2008/01/04 22:01:03 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
  int rc = SQLITE_OK;        /* Value to return */
  sqlite3 *db = p->db;       /* The database */
  u8 encoding = ENC(db);     /* The database encoding */
  Mem *pTos;                 /* Top entry in the operand stack */
  Mem *pIn1, *pIn2;          /* Input operands */
  Mem *pOut;                 /* Output operand */
  int nPop = 0;              /* Number of times to pop the stack */

#ifdef VDBE_PROFILE
  unsigned long long start;  /* CPU clock count at start of opcode */
  int origPc;                /* Program counter at start of opcode */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
#endif
................................................................................
    /* Do common setup processing for any opcode that is marked
    ** with the "out2-prerelease" tag.  Such opcodes have a single
    ** output which is specified by the P2 parameter.  The output
    ** is normally written into the P2-th register.  But if P2==0
    ** then the output is pushed onto the stack.  The P2 operand
    ** is initialized to a NULL.
    */
    if( (opcodeProperty[pOp->opcode]&OPFLG_OUT2_PRERELEASE)!=0 ){

      assert( pOp->p2>=0 );
      if( pOp->p2==0 ){
        pOut = ++pTos;
      }else{
        assert( pOp->p2<=p->nMem );
        pOut = &p->aMem[pOp->p2];
        sqlite3VdbeMemRelease(pOut);
      }
      pOut->flags = MEM_Null;

































































    }

    switch( pOp->opcode ){

/*****************************************************************************
** What follows is a massive switch statement where each case implements a
** separate instruction in the virtual machine.  If we follow the usual
................................................................................
case OP_Pop: {            /* no-push */
  assert( pOp->p1>=0 );
  popStack(&pTos, pOp->p1);
  assert( pTos>=&p->aStack[-1] );
  break;
}

/* Opcode: Dup P1 P2 *
**
** A copy of the P1-th element of the stack 
** is made and pushed onto the top of the stack.
** The top of the stack is element 0.  So the
** instruction "Dup 0 0 0" will make a copy of the
** top of the stack.
**

** If the content of the P1-th element is a dynamically
** allocated string, then a new copy of that string
** is made if P2==0.  If P2!=0, then just a pointer
** to the string is copied.



**
** Also see the Pull instruction.










*/


















case OP_Dup: {
  Mem *pFrom = &pTos[-pOp->p1];




  assert( pFrom<=pTos && pFrom>=p->aStack );






  pTos++;









  sqlite3VdbeMemShallowCopy(pTos, pFrom, MEM_Ephem);
  if( pOp->p2 ){
    Deephemeralize(pTos);
  }

  break;
}

/* Opcode: Pull P1 * *
**
** The P1-th element is removed from its current location on 
** the stack and pushed back on top of the stack.  The
** top of the stack is element 0, so "Pull 0 0 0" is
** a no-op.  "Pull 1 0 0" swaps the top two elements of
** the stack.
**
** See also the Dup instruction.
*/
case OP_Pull: {            /* no-push */
  Mem *pFrom = &pTos[-pOp->p1];
  int i;
  Mem ts;

  ts = *pFrom;
................................................................................
    if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){
      goto abort_due_to_error;
    }
  }
  break;
}

/* Opcode: ReadCookie P1 P2 P3
**
** Read cookie number P3 from database P1 and write it into register
** P2 or push it onto the stack if P2==0.
** P3==0 is the schema version.  P3==1 is the database format.
** P3==2 is the recommended pager cache size, and so forth.  P1==0 is
** the main database file and P1==1 is the database file used to store
** temporary tables.
................................................................................
  p->nChange = pContext->nChange;
  sqlite3VdbeFifoClear(&p->sFifo);
  p->sFifo = pContext->sFifo;
  break;
}
#endif /* #ifndef SQLITE_OMIT_TRIGGER */

/* Opcode: MemStore P1 P2 *
**
** Write the top of the stack into memory location P1.
** P1 should be a small integer since space is allocated
** for all memory locations between 0 and P1 inclusive.
**
** After the data is stored in the memory location, the
** stack is popped once if P2 is 1.  If P2 is zero, then
** the original data remains on the stack.
*/
case OP_MemStore: {        /* no-push */
  assert( pTos>=p->aStack );
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
  rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], pTos);
  pTos--;

  /* If P2 is 0 then fall thru to the next opcode, OP_MemLoad, that will
  ** restore the top of the stack to its original value.
  */
  if( pOp->p2 ){
    break;
  }
}
/* Opcode: MemLoad P1 * *
**
** Push a copy of the value in memory location P1 onto the stack.
**
** If the value is a string, then the value pushed is a pointer to
** the string that is stored in the memory location.  If the memory
** location is subsequently changed (using OP_MemStore) then the
** value pushed onto the stack will change too.
*/
case OP_MemLoad: {
  int i = pOp->p1;
  assert( i>0 && i<=p->nMem );
  pTos++;
  sqlite3VdbeMemShallowCopy(pTos, &p->aMem[i], MEM_Ephem);
  break;
}

#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Opcode: MemMax P1 P2 *
**
** Set the value of memory cell P1 to the maximum of its current value
** and the value in cell P2, or the value on the top of the stack if P2
** is zero. The stack is unchanged in either case.
**
................................................................................
  assert( i>0 && i<=p->nMem );
  if( p->aMem[i].flags & MEM_Null ){
     pc = pOp->p2 - 1;
  }
  break;
}

/* Opcode: MemMove P1 P2 *
**
** Move the content of memory cell P2 over to memory cell P1.
** Any prior content of P1 is erased.  Memory cell P2 is left
** containing a NULL.
*/
case OP_MemMove: {
  assert( pOp->p1>0 && pOp->p1<=p->nMem );
  assert( pOp->p2>0 && pOp->p2<=p->nMem );
  rc = sqlite3VdbeMemMove(&p->aMem[pOp->p1], &p->aMem[pOp->p2]);
  break;
}

/* Opcode: AggStep P1 P2 P4
**
** Execute the step function for an aggregate.  The
** function has P2 arguments.  P4 is a pointer to the FuncDef
** structure that specifies the function.  Use memory location
** P1 as the accumulator.
**
................................................................................
/*****************************************************************************
** The cases of the switch statement above this line should all be indented
** by 6 spaces.  But the left-most 6 spaces have been removed to improve the
** readability.  From this point on down, the normal indentation rules are
** restored.
*****************************************************************************/
    }







    /* Make sure the stack limit was not exceeded */
    assert( pTos>=&p->aStack[-1] && pTos<=pStackLimit );

#ifdef VDBE_PROFILE
    {
      long long elapse = hwtime() - start;







|







 







>







 







|
>









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|

|
|
|
|
<

>
|
|
|
|
>
>
>

<
>
>
>
>
>
>
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>
>
>
>
|
>
>
>
>
>
>
|
>
>
>
>
>
>
>
>
>
|
|
|
|
>










<
<







 







|







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
<
<
<
<
<
<
<
<







 







>
>
>
>
>
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
...
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
...
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
...
989
990
991
992
993
994
995
996
997
998
999
1000
1001

1002
1003
1004
1005
1006
1007
1008
1009
1010
1011

1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041

1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077


1078
1079
1080
1081
1082
1083
1084
....
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
....
4725
4726
4727
4728
4729
4730
4731








































4732
4733
4734
4735
4736
4737
4738
....
4838
4839
4840
4841
4842
4843
4844













4845
4846
4847
4848
4849
4850
4851
....
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.680 2008/01/05 04:06:04 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
  int rc = SQLITE_OK;        /* Value to return */
  sqlite3 *db = p->db;       /* The database */
  u8 encoding = ENC(db);     /* The database encoding */
  Mem *pTos;                 /* Top entry in the operand stack */
  Mem *pIn1, *pIn2;          /* Input operands */
  Mem *pOut;                 /* Output operand */
  int nPop = 0;              /* Number of times to pop the stack */
  u8 opProperty;
#ifdef VDBE_PROFILE
  unsigned long long start;  /* CPU clock count at start of opcode */
  int origPc;                /* Program counter at start of opcode */
#endif
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
  int nProgressOps = 0;      /* Opcodes executed since progress callback. */
#endif
................................................................................
    /* Do common setup processing for any opcode that is marked
    ** with the "out2-prerelease" tag.  Such opcodes have a single
    ** output which is specified by the P2 parameter.  The output
    ** is normally written into the P2-th register.  But if P2==0
    ** then the output is pushed onto the stack.  The P2 operand
    ** is initialized to a NULL.
    */
    opProperty = opcodeProperty[pOp->opcode];
    if( (opProperty & OPFLG_OUT2_PRERELEASE)!=0 ){
      assert( pOp->p2>=0 );
      if( pOp->p2==0 ){
        pOut = ++pTos;
      }else{
        assert( pOp->p2<=p->nMem );
        pOut = &p->aMem[pOp->p2];
        sqlite3VdbeMemRelease(pOut);
      }
      pOut->flags = MEM_Null;
    }else
 
    /* Do common setup for opcodes marked with one of the following
    ** combinations of properties.
    **
    **           in1
    **           in1 in2
    **           in1 in2 out3
    **           in1 in3
    **           in1 out2
    **
    ** Variables pIn1 and pIn2 are made to point to the first two
    ** inputs and pOut points to the output.  Variable nPop holds the
    ** number of times that the stack should be popped after the
    ** the instruction.
    */
    if( (opProperty & OPFLG_IN1)!=0 ){
      assert( pOp->p1>=0 );
      if( pOp->p1==0 ){
        pIn1 = pTos;
        nPop = 1;
      }else{
        assert( pOp->p1<=p->nMem );
        pIn1 = &p->aMem[pOp->p1];
      }
      if( (opProperty & OPFLG_IN2)!=0 ){
        assert( pOp->p2>=0 );
        if( pOp->p2==0 ){
          pIn2 = &pTos[-nPop];
          nPop++;
        }else{
          assert( pOp->p2<=p->nMem );
          pIn2 = &p->aMem[pOp->p2];
        }
        if( (opProperty & OPFLG_OUT3)!=0 ){
          assert( pOp->p3>=0 );
          if( pOp->p3==0 ){
            pTos++;
            pOut = &pTos[-nPop];
            pOut->flags = MEM_Null;
          }else{
            assert( pOp->p3<=p->nMem );
            pOut = &p->aMem[pOp->p3];
          }
        }
      }else if( (opProperty & OPFLG_IN3)!=0 ){
        assert( pOp->p3>=0 );
        if( pOp->p3==0 ){
          pIn2 = &pTos[-nPop];
          nPop++;
        }else{
          assert( pOp->p3<=p->nMem );
          pIn2 = &p->aMem[pOp->p3];
        }
      }else if( (opProperty & OPFLG_OUT2)!=0 ){
        assert( pOp->p2>=0 );
        if( pOp->p2==0 ){
          pTos++;
          pOut = &pTos[-nPop];
          pOut->flags = MEM_Null;
        }else{
          assert( pOp->p2<=p->nMem );
          pOut = &p->aMem[pOp->p2];
        }
      }
    }

    switch( pOp->opcode ){

/*****************************************************************************
** What follows is a massive switch statement where each case implements a
** separate instruction in the virtual machine.  If we follow the usual
................................................................................
case OP_Pop: {            /* no-push */
  assert( pOp->p1>=0 );
  popStack(&pTos, pOp->p1);
  assert( pTos>=&p->aStack[-1] );
  break;
}

/* Opcode: Move P1 P2 * * *
**
** Move the value in P1 into P2.  If P1 is positive then read from the
** P1-th register.  If P1 is zero or negative read from the stack.
** When P1 is 0 read from the top the stack.  When P1 is -1 read from
** the next entry down on the stack.  And so forth.

**
** If P2 is zero, push the new value onto the top of the stack.  
** If P2 is positive, write into the P2-th register.
**
** If P1 is zero then the stack is popped once.  The stack is
** unchanged for all other values of P1.  The P1 value contains
** a NULL after this operation.
*/
/* Opcode: Copy P1 P2 * * *
**

** Make a copy of P1 into P2.  If P1 is positive then read from the
** P1-th register.  If P1 is zero or negative read from the stack.
** When P1 is 0 read from the top the stack.  When P1 is -1 read from
** the next entry down on the stack.  And so forth.
**
** If P2 is zero, push the new value onto the top of the stack.  
** If P2 is positive, write into the P2-th register.
**
** This instruction makes a deep copy of the value.  A duplicate
** is made of any string or blob constant.  See also OP_SCopy.
*/
/* Opcode: SCopy P1 P2 * * *
**
** Make a shallow copy of P1 into P2.  If P1 is positive then read from the
** P1-th register.  If P1 is zero or negative read from the stack.
** When P1 is 0 read from the top the stack.  When P1 is -1 read from
** the next entry down on the stack.  And so forth.
**
** If P2 is zero, push the new value onto the top of the stack.  
** If P2 is positive, write into the P2-th register.
**
** This instruction makes a shallow copy of the value.  If the value
** is a string or blob, then the copy is only a pointer to the
** original and hence if the original changes so will the copy.
** Worse, if the original is deallocated, the copy becomes invalid.
** Thus the program must guarantee that the original will not change
** during the lifetime of the copy.  Use OP_Copy to make a complete
** copy.
*/
case OP_Move:

case OP_Copy:
case OP_SCopy: {
  if( pOp->p1<=0 ){
    pIn1 = &pTos[pOp->p1];
    assert( pIn1>=p->aStack );
  }else{
    assert( pOp->p1<=p->nMem );
    pIn1 = &p->aMem[pOp->p1];
  }
  assert( pOp->p2>=0 );
  if( pOp->p2==0 ){
    pOut = ++pTos;
    pOut->flags = MEM_Null;
  }else{
    assert( pOp->p2<=p->nMem );
    pOut = &p->aMem[pOp->p2];
  }
  if( pOp->opcode==OP_Move ){
    rc = sqlite3VdbeMemMove(pOut, pIn1);
    if( pOp->p1==0 ) pTos--;
  }else{
    sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
    if( pOp->opcode==OP_Copy ){
      Deephemeralize(pOut);
    }
  }
  break;
}

/* Opcode: Pull P1 * *
**
** The P1-th element is removed from its current location on 
** the stack and pushed back on top of the stack.  The
** top of the stack is element 0, so "Pull 0 0 0" is
** a no-op.  "Pull 1 0 0" swaps the top two elements of
** the stack.


*/
case OP_Pull: {            /* no-push */
  Mem *pFrom = &pTos[-pOp->p1];
  int i;
  Mem ts;

  ts = *pFrom;
................................................................................
    if( rc!=SQLITE_OK && rc!=SQLITE_READONLY /* && rc!=SQLITE_BUSY */ ){
      goto abort_due_to_error;
    }
  }
  break;
}

/* Opcode: ReadCookie P1 P2 P3 * *
**
** Read cookie number P3 from database P1 and write it into register
** P2 or push it onto the stack if P2==0.
** P3==0 is the schema version.  P3==1 is the database format.
** P3==2 is the recommended pager cache size, and so forth.  P1==0 is
** the main database file and P1==1 is the database file used to store
** temporary tables.
................................................................................
  p->nChange = pContext->nChange;
  sqlite3VdbeFifoClear(&p->sFifo);
  p->sFifo = pContext->sFifo;
  break;
}
#endif /* #ifndef SQLITE_OMIT_TRIGGER */









































#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Opcode: MemMax P1 P2 *
**
** Set the value of memory cell P1 to the maximum of its current value
** and the value in cell P2, or the value on the top of the stack if P2
** is zero. The stack is unchanged in either case.
**
................................................................................
  assert( i>0 && i<=p->nMem );
  if( p->aMem[i].flags & MEM_Null ){
     pc = pOp->p2 - 1;
  }
  break;
}














/* Opcode: AggStep P1 P2 P4
**
** Execute the step function for an aggregate.  The
** function has P2 arguments.  P4 is a pointer to the FuncDef
** structure that specifies the function.  Use memory location
** P1 as the accumulator.
**
................................................................................
/*****************************************************************************
** The cases of the switch statement above this line should all be indented
** by 6 spaces.  But the left-most 6 spaces have been removed to improve the
** readability.  From this point on down, the normal indentation rules are
** restored.
*****************************************************************************/
    }

    /* Pop the stack if necessary */
    if( nPop ){
      popStack(&pTos, nPop);
      nPop = 0;
    }

    /* Make sure the stack limit was not exceeded */
    assert( pTos>=&p->aStack[-1] && pTos<=pStackLimit );

#ifdef VDBE_PROFILE
    {
      long long elapse = hwtime() - start;

Changes to src/where.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
....
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
....
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
....
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
....
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
....
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
....
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.273 2008/01/04 22:01:03 drh Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
    if( pTerm==0 ) break;
    assert( (pTerm->flags & TERM_CODED)==0 );
    codeEqualityTerm(pParse, pTerm, pLevel);
    if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
      sqlite3VdbeAddOp2(v, OP_IsNull, termsInMem ? -1 : -(j+1), pLevel->brk);
    }
    if( termsInMem ){
      sqlite3VdbeAddOp2(v, OP_MemStore, pLevel->iMem+j+1, 1);
    }
  }

  /* Make sure all the constraint values are on the top of the stack
  */
  if( termsInMem ){
    for(j=0; j<nEq; j++){
      sqlite3VdbeAddOp2(v, OP_MemLoad, pLevel->iMem+j+1, 0);
    }
  }
}

#if defined(SQLITE_TEST)
/*
** The following variable holds a text description of query plan generated
................................................................................
      if( pEnd ){
        Expr *pX;
        pX = pEnd->pExpr;
        assert( pX!=0 );
        assert( pEnd->leftCursor==iCur );
        sqlite3ExprCode(pParse, pX->pRight, 0);
        pLevel->iMem = ++pParse->nMem;
        sqlite3VdbeAddOp2(v, OP_MemStore, pLevel->iMem, 1);
        if( pX->op==TK_LT || pX->op==TK_GT ){
          testOp = bRev ? OP_Le : OP_Ge;
        }else{
          testOp = bRev ? OP_Lt : OP_Gt;
        }
        disableTerm(pLevel, pEnd);
      }
      start = sqlite3VdbeCurrentAddr(v);
      pLevel->op = bRev ? OP_Prev : OP_Next;
      pLevel->p1 = iCur;
      pLevel->p2 = start;
      if( testOp!=OP_Noop ){
        sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0);
        sqlite3VdbeAddOp2(v, OP_MemLoad, pLevel->iMem, 0);
        sqlite3VdbeAddOp2(v, testOp, SQLITE_AFF_NUMERIC|0x100, brk);
      }
    }else if( pLevel->flags & WHERE_COLUMN_RANGE ){
      /* Case 3: The WHERE clause term that refers to the right-most
      **         column of the index is an inequality.  For example, if
      **         the index is on (x,y,z) and the WHERE clause is of the
      **         form "x=5 AND y<10" then this case is used.  Only the
................................................................................
      codeAllEqualityTerms(pParse, pLevel, &wc, notReady);

      /* Duplicate the equality term values because they will all be
      ** used twice: once to make the termination key and once to make the
      ** start key.
      */
      for(j=0; j<nEq; j++){
        sqlite3VdbeAddOp2(v, OP_Dup, nEq-1, 0);
      }

      /* Figure out what comparison operators to use for top and bottom 
      ** search bounds. For an ascending index, the bottom bound is a > or >=
      ** operator and the top bound is a < or <= operator.  For a descending
      ** index the operators are reversed.
      */
................................................................................
        int nCol = nEq + topLimit;
        pLevel->iMem = ++pParse->nMem;
        buildIndexProbe(v, nCol, pIdx);
        if( bRev ){
          int op = topEq ? OP_MoveLe : OP_MoveLt;
          sqlite3VdbeAddOp2(v, op, iIdxCur, nxt);
        }else{
          sqlite3VdbeAddOp2(v, OP_MemStore, pLevel->iMem, 1);
        }
      }else if( bRev ){
        sqlite3VdbeAddOp2(v, OP_Last, iIdxCur, brk);
      }

      /* Generate the start key.  This is the key that defines the lower
      ** bound on the search.  There is no start key if there are no
................................................................................
        btmEq = 1;
      }
      if( nEq>0 || btmLimit ){
        int nCol = nEq + btmLimit;
        buildIndexProbe(v, nCol, pIdx);
        if( bRev ){
          pLevel->iMem = ++pParse->nMem;
          sqlite3VdbeAddOp2(v, OP_MemStore, pLevel->iMem, 1);
          testOp = OP_IdxLT;
        }else{
          int op = btmEq ? OP_MoveGe : OP_MoveGt;
          sqlite3VdbeAddOp2(v, op, iIdxCur, nxt);
        }
      }else if( bRev ){
        testOp = OP_Noop;
................................................................................

      /* Generate the the top of the loop.  If there is a termination
      ** key we have to test for that key and abort at the top of the
      ** loop.
      */
      start = sqlite3VdbeCurrentAddr(v);
      if( testOp!=OP_Noop ){
        sqlite3VdbeAddOp2(v, OP_MemLoad, pLevel->iMem, 0);
        sqlite3VdbeAddOp2(v, testOp, iIdxCur, nxt);
        if( (topEq && !bRev) || (!btmEq && bRev) ){
          sqlite3VdbeChangeP4(v, -1, "+", P4_STATIC);
        }
      }
      if( topLimit | btmLimit ){
        sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq);
................................................................................
      codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
      nxt = pLevel->nxt;

      /* Generate a single key that will be used to both start and terminate
      ** the search
      */
      buildIndexProbe(v, nEq, pIdx);
      sqlite3VdbeAddOp2(v, OP_MemStore, pLevel->iMem, 0);

      /* Generate code (1) to move to the first matching element of the table.
      ** Then generate code (2) that jumps to "nxt" after the cursor is past
      ** the last matching element of the table.  The code (1) is executed
      ** once to initialize the search, the code (2) is executed before each
      ** iteration of the scan to see if the scan has finished. */
      if( bRev ){
        /* Scan in reverse order */
        sqlite3VdbeAddOp2(v, OP_MoveLe, iIdxCur, nxt);
        start = sqlite3VdbeAddOp2(v, OP_MemLoad, pLevel->iMem, 0);
        sqlite3VdbeAddOp2(v, OP_IdxLT, iIdxCur, nxt);
        pLevel->op = OP_Prev;
      }else{
        /* Scan in the forward order */
        sqlite3VdbeAddOp2(v, OP_MoveGe, iIdxCur, nxt);
        start = sqlite3VdbeAddOp2(v, OP_MemLoad, pLevel->iMem, 0);
        sqlite3VdbeAddOp4(v, OP_IdxGE, iIdxCur, nxt, 0, "+", P4_STATIC);
        pLevel->op = OP_Next;
      }
      if( !omitTable ){
        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0);
        sqlite3VdbeAddOp2(v, OP_MoveGe, iCur, 0);
      }







|







 







|







|







 







|













|







 







|







 







|







 







|







 







|







 







|









|





|







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
....
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
....
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
....
2406
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
....
2455
2456
2457
2458
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
....
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
2499
2500
2501
2502
2503
....
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
....
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.  This module is reponsible for
** generating the code that loops through a table looking for applicable
** rows.  Indices are selected and used to speed the search when doing
** so is applicable.  Because this module is responsible for selecting
** indices, you might also think of this module as the "query optimizer".
**
** $Id: where.c,v 1.274 2008/01/05 04:06:04 drh Exp $
*/
#include "sqliteInt.h"

/*
** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
*/
#define BMS  (sizeof(Bitmask)*8)
................................................................................
    if( pTerm==0 ) break;
    assert( (pTerm->flags & TERM_CODED)==0 );
    codeEqualityTerm(pParse, pTerm, pLevel);
    if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
      sqlite3VdbeAddOp2(v, OP_IsNull, termsInMem ? -1 : -(j+1), pLevel->brk);
    }
    if( termsInMem ){
      sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem+j+1);
    }
  }

  /* Make sure all the constraint values are on the top of the stack
  */
  if( termsInMem ){
    for(j=0; j<nEq; j++){
      sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem+j+1, 0);
    }
  }
}

#if defined(SQLITE_TEST)
/*
** The following variable holds a text description of query plan generated
................................................................................
      if( pEnd ){
        Expr *pX;
        pX = pEnd->pExpr;
        assert( pX!=0 );
        assert( pEnd->leftCursor==iCur );
        sqlite3ExprCode(pParse, pX->pRight, 0);
        pLevel->iMem = ++pParse->nMem;
        sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
        if( pX->op==TK_LT || pX->op==TK_GT ){
          testOp = bRev ? OP_Le : OP_Ge;
        }else{
          testOp = bRev ? OP_Lt : OP_Gt;
        }
        disableTerm(pLevel, pEnd);
      }
      start = sqlite3VdbeCurrentAddr(v);
      pLevel->op = bRev ? OP_Prev : OP_Next;
      pLevel->p1 = iCur;
      pLevel->p2 = start;
      if( testOp!=OP_Noop ){
        sqlite3VdbeAddOp2(v, OP_Rowid, iCur, 0);
        sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
        sqlite3VdbeAddOp2(v, testOp, SQLITE_AFF_NUMERIC|0x100, brk);
      }
    }else if( pLevel->flags & WHERE_COLUMN_RANGE ){
      /* Case 3: The WHERE clause term that refers to the right-most
      **         column of the index is an inequality.  For example, if
      **         the index is on (x,y,z) and the WHERE clause is of the
      **         form "x=5 AND y<10" then this case is used.  Only the
................................................................................
      codeAllEqualityTerms(pParse, pLevel, &wc, notReady);

      /* Duplicate the equality term values because they will all be
      ** used twice: once to make the termination key and once to make the
      ** start key.
      */
      for(j=0; j<nEq; j++){
        sqlite3VdbeAddOp1(v, OP_Copy, 1-nEq);
      }

      /* Figure out what comparison operators to use for top and bottom 
      ** search bounds. For an ascending index, the bottom bound is a > or >=
      ** operator and the top bound is a < or <= operator.  For a descending
      ** index the operators are reversed.
      */
................................................................................
        int nCol = nEq + topLimit;
        pLevel->iMem = ++pParse->nMem;
        buildIndexProbe(v, nCol, pIdx);
        if( bRev ){
          int op = topEq ? OP_MoveLe : OP_MoveLt;
          sqlite3VdbeAddOp2(v, op, iIdxCur, nxt);
        }else{
          sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
        }
      }else if( bRev ){
        sqlite3VdbeAddOp2(v, OP_Last, iIdxCur, brk);
      }

      /* Generate the start key.  This is the key that defines the lower
      ** bound on the search.  There is no start key if there are no
................................................................................
        btmEq = 1;
      }
      if( nEq>0 || btmLimit ){
        int nCol = nEq + btmLimit;
        buildIndexProbe(v, nCol, pIdx);
        if( bRev ){
          pLevel->iMem = ++pParse->nMem;
          sqlite3VdbeAddOp2(v, OP_Move, 0, pLevel->iMem);
          testOp = OP_IdxLT;
        }else{
          int op = btmEq ? OP_MoveGe : OP_MoveGt;
          sqlite3VdbeAddOp2(v, op, iIdxCur, nxt);
        }
      }else if( bRev ){
        testOp = OP_Noop;
................................................................................

      /* Generate the the top of the loop.  If there is a termination
      ** key we have to test for that key and abort at the top of the
      ** loop.
      */
      start = sqlite3VdbeCurrentAddr(v);
      if( testOp!=OP_Noop ){
        sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
        sqlite3VdbeAddOp2(v, testOp, iIdxCur, nxt);
        if( (topEq && !bRev) || (!btmEq && bRev) ){
          sqlite3VdbeChangeP4(v, -1, "+", P4_STATIC);
        }
      }
      if( topLimit | btmLimit ){
        sqlite3VdbeAddOp2(v, OP_Column, iIdxCur, nEq);
................................................................................
      codeAllEqualityTerms(pParse, pLevel, &wc, notReady);
      nxt = pLevel->nxt;

      /* Generate a single key that will be used to both start and terminate
      ** the search
      */
      buildIndexProbe(v, nEq, pIdx);
      sqlite3VdbeAddOp2(v, OP_Copy, 0, pLevel->iMem);

      /* Generate code (1) to move to the first matching element of the table.
      ** Then generate code (2) that jumps to "nxt" after the cursor is past
      ** the last matching element of the table.  The code (1) is executed
      ** once to initialize the search, the code (2) is executed before each
      ** iteration of the scan to see if the scan has finished. */
      if( bRev ){
        /* Scan in reverse order */
        sqlite3VdbeAddOp2(v, OP_MoveLe, iIdxCur, nxt);
        start = sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
        sqlite3VdbeAddOp2(v, OP_IdxLT, iIdxCur, nxt);
        pLevel->op = OP_Prev;
      }else{
        /* Scan in the forward order */
        sqlite3VdbeAddOp2(v, OP_MoveGe, iIdxCur, nxt);
        start = sqlite3VdbeAddOp2(v, OP_SCopy, pLevel->iMem, 0);
        sqlite3VdbeAddOp4(v, OP_IdxGE, iIdxCur, nxt, 0, "+", P4_STATIC);
        pLevel->op = OP_Next;
      }
      if( !omitTable ){
        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, 0);
        sqlite3VdbeAddOp2(v, OP_MoveGe, iCur, 0);
      }

Changes to test/incrblob.test.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
..
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# $Id: incrblob.test,v 1.17 2007/10/09 08:29:32 danielk1977 Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable {!autovacuum || !pragma || !incrblob} {
  finish_test
................................................................................
do_test incrblob-1.3.4 {
  seek $::blob 8496
  read $::blob 10
} {....123456}
do_test incrblob-1.3.10 {
  close $::blob
} {}


#------------------------------------------------------------------------
# incrblob-2.*: 
#
# Test that the following operations use ptrmap pages to reduce
# unnecessary reads:
#







|







 







<







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
..
78
79
80
81
82
83
84

85
86
87
88
89
90
91
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# $Id: incrblob.test,v 1.18 2008/01/05 04:06:04 drh Exp $
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable {!autovacuum || !pragma || !incrblob} {
  finish_test
................................................................................
do_test incrblob-1.3.4 {
  seek $::blob 8496
  read $::blob 10
} {....123456}
do_test incrblob-1.3.10 {
  close $::blob
} {}


#------------------------------------------------------------------------
# incrblob-2.*: 
#
# Test that the following operations use ptrmap pages to reduce
# unnecessary reads:
#