/ Check-in [8b61d1ae]
Login

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

Overview
Comment:More work on the implementation of cursors, but they are still not functioning. (CVS 2142)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8b61d1ae1ca469b80f2b344d550c3b363448b193
User & Date: drh 2004-11-23 01:47:30
Context
2004-11-23
09:06
Fix a bug involving balance_shallow() and the sqlite_master table. (CVS 2143) check-in: 557be3ff user: danielk1977 tags: trunk
01:47
More work on the implementation of cursors, but they are still not functioning. (CVS 2142) check-in: 8b61d1ae user: drh tags: trunk
2004-11-22
19:12
Add initial infrastructure for cursors. In where.c, optimize out clauses of the form "ORDER BY rowid" if a table scan is being performed. Do a reverse table scan if "ORDER BY rowid DESC" is present. (CVS 2141) check-in: fc8c1393 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/cursor.c.

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
82
83
84
85
86
87
88

89
90
91
92
93
94
95


96
97
98
99
100
101
102
...
112
113
114
115
116
117
118




















119
120
121
122
123
124
125
...
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
163
164

165
166
167
168
169
** using the DECLARE...CURSOR command and deleted using CLOSE.  A
** B-tree cursor is an abstraction of the b-tree layer.  See the btree.c
** module for additional information.  There is also a VDBE-cursor that
** is used by the VDBE module.  Even though all these objects are called
** cursors, they are really very different things.  It is worth your while
** to fully understand the difference.
**
** @(#) $Id: cursor.c,v 1.1 2004/11/22 19:12:20 drh Exp $
*/
#ifndef SQLITE_OMIT_CURSOR
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** Delete a cursor object.
................................................................................
  }
  if( i>=db->nSqlCursor ){
    db->apSqlCursor = sqliteRealloc(db->apSqlCursor, (i+1)*sizeof(pNew));
    db->nSqlCursor = i+1;
  }
  db->apSqlCursor[i] = pNew = sqliteMallocRaw( sizeof(*pNew) + pName->n + 1 );
  if( pNew==0 ) goto end_create_cursor;

  pNew->zName = (char*)&pNew[1];
  memcpy(pNew->zName, pName->z, pName->n);
  pNew->zName[pName->n] = 0;
  pNew->pSelect = sqlite3SelectDup(pSelect);
  pNew->nPtr = 0;
  pNew->aPtr = 0;
  pNew->idx = i;



end_create_cursor:
  sqlite3SelectDelete(pSelect);
}

/*
** The parser calls this routine in response to a CLOSE command.  Delete
................................................................................
    return;
  }
  assert( p->idx>=0 && p->idx<db->nSqlCursor );
  assert( db->apSqlCursor[p->idx]==p );
  db->apSqlCursor[p->idx] = 0;
  sqlite3CursorDelete(p);
}





















/*
** The parser calls this routine when it sees a complete FETCH statement.
** This routine generates code to implement the FETCH.
**
** Information about the direction of the FETCH has already been inserted
** into the pParse structure by parser rules.  The arguments specify the
................................................................................
    return;
  }
  sFetch.pCursor = p;
  pCopy = sqlite3SelectDup(p->pSelect);
  pCopy->pFetch = &sFetch;
  switch( pParse->fetchDir ){
    case TK_FIRST: {




      break;
    }
    case TK_LAST: {





      break;
    }
    case TK_NEXT: {




      break;
    }
    case TK_PRIOR: {





      break;
    }
    case TK_ABSOLUTE: {




      break;
    }
    default: {
      assert( pParse->fetchDir==TK_RELATIVE );
























      break;
    }
  }
  sqlite3Select(pParse, pCopy, SRT_Callback, 0, 0, 0, 0, 0);

end_fetch:
  sqlite3IdListDelete(pInto);
}

#endif /* SQLITE_OMIT_CURSOR */







|







 







>




|
|
|
>
>







 







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







 







>
>
>
>



>
>
>
>
>



>
>
>
>



>
>
>
>
>



>
>
>
>




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




>





17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
...
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
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
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
** using the DECLARE...CURSOR command and deleted using CLOSE.  A
** B-tree cursor is an abstraction of the b-tree layer.  See the btree.c
** module for additional information.  There is also a VDBE-cursor that
** is used by the VDBE module.  Even though all these objects are called
** cursors, they are really very different things.  It is worth your while
** to fully understand the difference.
**
** @(#) $Id: cursor.c,v 1.2 2004/11/23 01:47:30 drh Exp $
*/
#ifndef SQLITE_OMIT_CURSOR
#include "sqliteInt.h"
#include "vdbeInt.h"

/*
** Delete a cursor object.
................................................................................
  }
  if( i>=db->nSqlCursor ){
    db->apSqlCursor = sqliteRealloc(db->apSqlCursor, (i+1)*sizeof(pNew));
    db->nSqlCursor = i+1;
  }
  db->apSqlCursor[i] = pNew = sqliteMallocRaw( sizeof(*pNew) + pName->n + 1 );
  if( pNew==0 ) goto end_create_cursor;
  pNew->idx = i;
  pNew->zName = (char*)&pNew[1];
  memcpy(pNew->zName, pName->z, pName->n);
  pNew->zName[pName->n] = 0;
  pNew->pSelect = sqlite3SelectDup(pSelect);
  pNew->nPtr = 2;
  pNew->aPtr = sqliteMalloc( sizeof(Mem)*2 );
  for(i=0; i<2; i++){
    pNew->aPtr[i].flags = MEM_Null;
  }

end_create_cursor:
  sqlite3SelectDelete(pSelect);
}

/*
** The parser calls this routine in response to a CLOSE command.  Delete
................................................................................
    return;
  }
  assert( p->idx>=0 && p->idx<db->nSqlCursor );
  assert( db->apSqlCursor[p->idx]==p );
  db->apSqlCursor[p->idx] = 0;
  sqlite3CursorDelete(p);
}

/*
** Reverse the direction the ORDER BY clause on the SELECT statement.
*/
static void reverseSortOrder(Select *p){
  if( p->pOrderBy==0 ){
    /* If there no ORDER BY clause, add a new one that is "rowid DESC" */
    static const Token rowid = { "ROWID", 0, 5 };
    Expr *pExpr = sqlite3Expr(TK_ID, 0, 0, &rowid);
    ExprList *pList = sqlite3ExprListAppend(0, pExpr, 0);
    if( pList )  pList->a[0].sortOrder = SQLITE_SO_DESC;
    p->pOrderBy = pList;
  }else{
    int i;
    ExprList *pList = p->pOrderBy;
    for(i=0; i<pList->nExpr; i++){
      pList->a[i].sortOrder = !pList->a[i].sortOrder;
    }
  }
}

/*
** The parser calls this routine when it sees a complete FETCH statement.
** This routine generates code to implement the FETCH.
**
** Information about the direction of the FETCH has already been inserted
** into the pParse structure by parser rules.  The arguments specify the
................................................................................
    return;
  }
  sFetch.pCursor = p;
  pCopy = sqlite3SelectDup(p->pSelect);
  pCopy->pFetch = &sFetch;
  switch( pParse->fetchDir ){
    case TK_FIRST: {
      sFetch.isBackwards = 0;
      sFetch.doRewind = 1;
      pCopy->nLimit = pParse->dirArg1;
      pCopy->nOffset = 0;
      break;
    }
    case TK_LAST: {
      reverseSortOrder(pCopy);
      sFetch.isBackwards = 1;
      sFetch.doRewind = 1;
      pCopy->nLimit = pParse->dirArg1;
      pCopy->nOffset = 0;
      break;
    }
    case TK_NEXT: {
      sFetch.isBackwards = 0;
      sFetch.doRewind = 0;
      pCopy->nLimit = pParse->dirArg1;
      pCopy->nOffset = 0;
      break;
    }
    case TK_PRIOR: {
      reverseSortOrder(pCopy);
      sFetch.isBackwards = 1;
      sFetch.doRewind = 0;
      pCopy->nLimit = pParse->dirArg1;
      pCopy->nOffset = 0;
      break;
    }
    case TK_ABSOLUTE: {
      sFetch.isBackwards = 0;
      sFetch.doRewind = 1;
      pCopy->nLimit = pParse->dirArg1;
      pCopy->nOffset = pParse->dirArg2;
      break;
    }
    default: {
      assert( pParse->fetchDir==TK_RELATIVE );
      if( pParse->dirArg2>=0 ){
        /* The index parameter is positive.  Move forward from the current
        ** location */
        sFetch.isBackwards = 0;
        sFetch.doRewind = 0;
        pCopy->nLimit = pParse->dirArg1;
        pCopy->nOffset = pParse->dirArg2;
      }else{
        /* The index is negative.  We have to code two separate SELECTs.
        ** The first one seeks to the no position and the second one does
        ** the query.
        */
        Select *pSeek = sqlite3SelectDup(pCopy);
        reverseSortOrder(pSeek);
        sFetch.isBackwards = 1;
        sFetch.doRewind = 0;
        pSeek->nLimit = pParse->dirArg2;
        pSeek->pFetch = &sFetch;
        sqlite3Select(pParse, pSeek, SRT_Discard, 0, 0, 0, 0, 0);
        sFetch.isBackwards = 0;
        sFetch.doRewind = 0;
        pCopy->nLimit = pParse->dirArg1;
        pCopy->nOffset = 0;
      }
      break;
    }
  }
  sqlite3Select(pParse, pCopy, SRT_Callback, 0, 0, 0, 0, 0);

end_fetch:
  sqlite3IdListDelete(pInto);
}

#endif /* SQLITE_OMIT_CURSOR */

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
**    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 DELETE FROM statements.
**
** $Id: delete.c,v 1.90 2004/11/22 10:02:10 danielk1977 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.
................................................................................
      if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){
        goto delete_from_cleanup;
      }
    }

    /* Begin the database scan
    */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0);
    if( pWInfo==0 ) goto delete_from_cleanup;

    /* Remember the key of every item to be deleted.
    */
    sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
    if( db->flags & SQLITE_CountRows ){
      sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
**    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 DELETE FROM statements.
**
** $Id: delete.c,v 1.91 2004/11/23 01:47:30 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.
................................................................................
      if( sqlite3CheckIndexCollSeq(pParse, pIdx) ){
        goto delete_from_cleanup;
      }
    }

    /* Begin the database scan
    */
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0, 0);
    if( pWInfo==0 ) goto delete_from_cleanup;

    /* Remember the key of every item to be deleted.
    */
    sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);
    if( db->flags & SQLITE_CountRows ){
      sqlite3VdbeAddOp(v, OP_AddImm, 1, 0);

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
**    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.173 2004/11/22 19:12:20 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
}

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
** is responsible for making sure the node eventually gets freed.
*/
Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
  Expr *pNew;
  pNew = sqliteMalloc( sizeof(Expr) );
  if( pNew==0 ){
    /* When malloc fails, we leak memory from pLeft and pRight */
    return 0;
  }
  pNew->op = op;







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
**    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.174 2004/11/23 01:47:30 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................
}

/*
** Construct a new expression node and return a pointer to it.  Memory
** for this node is obtained from sqliteMalloc().  The calling function
** is responsible for making sure the node eventually gets freed.
*/
Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, const Token *pToken){
  Expr *pNew;
  pNew = sqliteMalloc( sizeof(Expr) );
  if( pNew==0 ){
    /* When malloc fails, we leak memory from pLeft and pRight */
    return 0;
  }
  pNew->op = op;

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
**    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.216 2004/11/22 19:12:21 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
    openTempIndex(pParse, p, distinct, 0);
  }else{
    distinct = -1;
  }

  /* Begin the database scan
  */
#if 0 /* ndef SQLITE_OMIT_CURSOR */
  if( p->pFetch ){
    pWInfo = sqlite3WhereBeginFetch(pParse, pTabList, pWhere,
                                    pOrderby, p->pFetch);
  }else
#endif
  {
    pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
                               pGroupBy ? 0 : &pOrderBy);
  }
  if( pWInfo==0 ) goto select_end;

  /* Use the standard inner loop if we are not dealing with
  ** aggregates
  */
  if( !isAgg ){
    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,







|







 







<
<
<
<
<
<
<
|
|
<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
2543
2544
2545
2546
2547
2548
2549







2550
2551

2552
2553
2554
2555
2556
2557
2558
**    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.217 2004/11/23 01:47:30 drh Exp $
*/
#include "sqliteInt.h"


/*
** Allocate a new Select structure and return a pointer to that
** structure.
................................................................................
    openTempIndex(pParse, p, distinct, 0);
  }else{
    distinct = -1;
  }

  /* Begin the database scan
  */







  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0,
                             pGroupBy ? 0 : &pOrderBy, p->pFetch);

  if( pWInfo==0 ) goto select_end;

  /* Use the standard inner loop if we are not dealing with
  ** aggregates
  */
  if( !isAgg ){
    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, eDest,

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
....
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.343 2004/11/22 19:12:21 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it.  If the OS lacks
................................................................................
void *sqlite3TextToPtr(const char*);
void sqlite3SetString(char **, const char *, ...);
void sqlite3ErrorMsg(Parse*, const char*, ...);
void sqlite3Dequote(char*);
int sqlite3KeywordCode(const char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
void sqlite3FinishCoding(Parse*);
Expr *sqlite3Expr(int, Expr*, Expr*, Token*);
Expr *sqlite3RegisterExpr(Parse*,Token*);
Expr *sqlite3ExprAnd(Expr*, Expr*);
void sqlite3ExprSpan(Expr*,Token*,Token*);
Expr *sqlite3ExprFunction(ExprList*, Token*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
void sqlite3ExprDelete(Expr*);
ExprList *sqlite3ExprListAppend(ExprList*,Expr*,Token*);
................................................................................
void sqlite3SelectUnbind(Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*);
void sqlite3OpenTable(Vdbe*, int iCur, Table*, int);
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, int, ExprList**);
void sqlite3WhereEnd(WhereInfo*);
void sqlite3ExprCode(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*);
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
void sqlite3NextedParse(Parse*, const char*, ...);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);







|







 







|







 







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
....
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
**    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.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.344 2004/11/23 01:47:30 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** These #defines should enable >2GB file support on Posix if the
** underlying operating system supports it.  If the OS lacks
................................................................................
void *sqlite3TextToPtr(const char*);
void sqlite3SetString(char **, const char *, ...);
void sqlite3ErrorMsg(Parse*, const char*, ...);
void sqlite3Dequote(char*);
int sqlite3KeywordCode(const char*, int);
int sqlite3RunParser(Parse*, const char*, char **);
void sqlite3FinishCoding(Parse*);
Expr *sqlite3Expr(int, Expr*, Expr*, const Token*);
Expr *sqlite3RegisterExpr(Parse*,Token*);
Expr *sqlite3ExprAnd(Expr*, Expr*);
void sqlite3ExprSpan(Expr*,Token*,Token*);
Expr *sqlite3ExprFunction(ExprList*, Token*);
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
void sqlite3ExprDelete(Expr*);
ExprList *sqlite3ExprListAppend(ExprList*,Expr*,Token*);
................................................................................
void sqlite3SelectUnbind(Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTableForReading(Vdbe*, int iCur, Table*);
void sqlite3OpenTable(Vdbe*, int iCur, Table*, int);
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, int, ExprList**, Fetch*);
void sqlite3WhereEnd(WhereInfo*);
void sqlite3ExprCode(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*);
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
void sqlite3NextedParse(Parse*, const char*, ...);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
**    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.96 2004/11/22 10:02:11 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
    pView = sqlite3SelectDup(pTab->pSelect);
    sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0);
    sqlite3SelectDelete(pView);
  }

  /* Begin the database scan
  */
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0);
  if( pWInfo==0 ) goto update_cleanup;

  /* Remember the index of every item to be updated.
  */
  sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);

  /* End the database scan loop.







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
**    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.97 2004/11/23 01:47:30 drh Exp $
*/
#include "sqliteInt.h"

/*
** Process an UPDATE statement.
**
**   UPDATE OR IGNORE table_wxyz SET a=b, c=d WHERE e<5 AND f NOT NULL;
................................................................................
    pView = sqlite3SelectDup(pTab->pSelect);
    sqlite3Select(pParse, pView, SRT_TempTable, iCur, 0, 0, 0, 0);
    sqlite3SelectDelete(pView);
  }

  /* Begin the database scan
  */
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 1, 0, 0);
  if( pWInfo==0 ) goto update_cleanup;

  /* Remember the index of every item to be updated.
  */
  sqlite3VdbeAddOp(v, OP_ListWrite, 0, 0);

  /* End the database scan loop.

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4428
4429
4430
4431
4432
4433
4434


















































4435
4436
4437
4438
4439
4440
4441
**
** 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.430 2004/11/18 02:10:55 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
*/
case OP_Vacuum: {
  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; 
  rc = sqlite3RunVacuum(&p->zErrMsg, db);
  if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
  break;
}



















































/* An other opcode is illegal...
*/
default: {
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",pOp->opcode);
  sqlite3SetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0);
  rc = SQLITE_INTERNAL;







|







 







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







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
4486
4487
4488
4489
4490
4491
**
** 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.431 2004/11/23 01:47:30 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
*/
case OP_Vacuum: {
  if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; 
  rc = sqlite3RunVacuum(&p->zErrMsg, db);
  if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
  break;
}

#ifndef SQLITE_OMIT_CURSOR
/* Opcode: CursorStore P1 P2 *
**
** The implementation of SQL cursors (not to be confused with VDBE cursors
** or B-tree cursors) stores information in the SQLite database connection
** structure (the sqlite3* pointer) that identifies the row
** in a table that an SQL cursor is pointing to.  This opcode is
** used to store that information.  P1 is an index of an SQL cursor.
** P2 is the index of a memory slot within that SQL cursor.  This opcode
** pops the top of the stack and stores it in the SQL cursor.
*/
case OP_CursorStore: {
  SqlCursor *pCursor;
  assert( pTos>=p->aStack );
  assert( pOp->p1>=0 && pOp->p1<db->nSqlCursor );
  pCursor = db->apSqlCursor[pOp->p1];
  assert( pCursor!=0 );
  assert( pOp->p2>=0 && pOp->p2<2 );  
  rc = sqlite3VdbeMemMove(&pCursor->aPtr[pOp->p1], pTos);
  pTos--;
  break;
}

/* Opcode: CursorLoad P1 P2 *
**
** The implementation of SQL cursors (not to be confused with VDBE cursors
** or B-tree cursors) stores information in the SQLite database connection
** structure (the sqlite3* pointer) that effectively records the current
** location in a table that an SQL cursor is pointing to.  This opcode is
** used to recover that information.  P1 is an index of an SQL cursor.
** P2 is the index of a memory slot within that SQL cursor.  This opcode
** pushes a new value onto the stack which is a copy of the information
** obtained from entry P2 of cursor P1.
*/
case OP_CursorLoad: {
  SqlCursor *pCursor;
  int i = pOp->p1;
  assert( pTos>=p->aStack );
  assert( pOp->p1>=0 && pOp->p1<db->nSqlCursor );
  pCursor = db->apSqlCursor[pOp->p1];
  assert( pCursor!=0 );
  assert( pOp->p2>=0 && pOp->p2<2 );  
  pTos++;
  sqlite3VdbeMemShallowCopy(pTos, &pCursor->aPtr[i], MEM_Ephem);
  break;
}
#endif /* SQLITE_OMIT_CURSOR */



/* An other opcode is illegal...
*/
default: {
  sqlite3_snprintf(sizeof(zBuf),zBuf,"%d",pOp->opcode);
  sqlite3SetString(&p->zErrMsg, "unknown opcode ", zBuf, (char*)0);
  rc = SQLITE_INTERNAL;

Changes to src/where.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511

512
513
514
515
516
517
518
...
524
525
526
527
528
529
530



531
532
533
534
535
536
537
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.119 2004/11/22 19:12:21 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
** scan is correct for the ORDER BY clause, then that index is used and
** *ppOrderBy is set to NULL.  This is an optimization that prevents an
** unnecessary sort of the result set if an index appropriate for the
** ORDER BY clause already exists.
**
** If the where clause loops cannot be arranged to provide the correct
** output order, then the *ppOrderBy is unchanged.
**
** If parameter iTabCur is non-negative, then it is a cursor already open
** on table pTabList->aSrc[0]. Use this cursor instead of opening a new
** one.
*/
WhereInfo *sqlite3WhereBegin(
  Parse *pParse,        /* The parser context */
  SrcList *pTabList,    /* A list of all tables to be scanned */
  Expr *pWhere,         /* The WHERE clause */
  int pushKey,          /* If TRUE, leave the table key on the stack */
  ExprList **ppOrderBy  /* An ORDER BY clause, or NULL */

){
  int i;                     /* Loop counter */
  WhereInfo *pWInfo;         /* Will become the return value of this function */
  Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
  int brk, cont = 0;         /* Addresses used during code generation */
  int nExpr;           /* Number of subexpressions in the WHERE clause */
  int loopMask;        /* One bit set for each outer loop */
................................................................................
  int iDirectGt[32];   /* Term of the form ROWID>X or ROWID>=X */
  ExprInfo aExpr[101]; /* The WHERE clause is divided into these terms */

  /* pushKey is only allowed if there is a single table (as in an INSERT or
  ** UPDATE statement)
  */
  assert( pushKey==0 || pTabList->nSrc==1 );




  /* Split the WHERE clause into separate subexpressions where each
  ** subexpression is separated by an AND operator.  If the aExpr[]
  ** array fills up, the last entry might point to an expression which
  ** contains additional unfactored AND operators.
  */
  initMaskSet(&maskSet);







|







 







<
<
<
<






|
>







 







>
>
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
494
495
496
497
498
499
500




501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
...
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This module contains C code that generates VDBE code used to process
** the WHERE clause of SQL statements.
**
** $Id: where.c,v 1.120 2004/11/23 01:47:31 drh Exp $
*/
#include "sqliteInt.h"

/*
** The query generator uses an array of instances of this structure to
** help it analyze the subexpressions of the WHERE clause.  Each WHERE
** clause subexpression is separated from the others by an AND operator.
................................................................................
** scan is correct for the ORDER BY clause, then that index is used and
** *ppOrderBy is set to NULL.  This is an optimization that prevents an
** unnecessary sort of the result set if an index appropriate for the
** ORDER BY clause already exists.
**
** If the where clause loops cannot be arranged to provide the correct
** output order, then the *ppOrderBy is unchanged.




*/
WhereInfo *sqlite3WhereBegin(
  Parse *pParse,        /* The parser context */
  SrcList *pTabList,    /* A list of all tables to be scanned */
  Expr *pWhere,         /* The WHERE clause */
  int pushKey,          /* If TRUE, leave the table key on the stack */
  ExprList **ppOrderBy, /* An ORDER BY clause, or NULL */
  Fetch *pFetch         /* Initial location of cursors.  NULL otherwise */
){
  int i;                     /* Loop counter */
  WhereInfo *pWInfo;         /* Will become the return value of this function */
  Vdbe *v = pParse->pVdbe;   /* The virtual database engine */
  int brk, cont = 0;         /* Addresses used during code generation */
  int nExpr;           /* Number of subexpressions in the WHERE clause */
  int loopMask;        /* One bit set for each outer loop */
................................................................................
  int iDirectGt[32];   /* Term of the form ROWID>X or ROWID>=X */
  ExprInfo aExpr[101]; /* The WHERE clause is divided into these terms */

  /* pushKey is only allowed if there is a single table (as in an INSERT or
  ** UPDATE statement)
  */
  assert( pushKey==0 || pTabList->nSrc==1 );

  /*
  */

  /* Split the WHERE clause into separate subexpressions where each
  ** subexpression is separated by an AND operator.  If the aExpr[]
  ** array fills up, the last entry might point to an expression which
  ** contains additional unfactored AND operators.
  */
  initMaskSet(&maskSet);

Changes to test/cursor.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is DECLARE...CURSOR functionality
#
# $Id: cursor.test,v 1.1 2004/11/22 19:12:21 drh Exp $
#

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

# If SQLITE_OMIT_CURSOR is defined, omit this file.
ifcapable {!cursor} {







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#*************************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is DECLARE...CURSOR functionality
#
# $Id: cursor.test,v 1.2 2004/11/23 01:47:31 drh Exp $
#

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

# If SQLITE_OMIT_CURSOR is defined, omit this file.
ifcapable {!cursor} {