/ Check-in [c10e8a3c]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Updated LIMIT support for DELETE/UPDATE. Omit option changed to SQLITE_ENABLE_UPDATE_DELETE_LIMIT. (CVS 5788)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: c10e8a3c7ab7f21c95f24d0aba590f5b18a4b028
User & Date: shane 2008-10-10 04:34:16
Context
2008-10-10
06:02
Initial test cases for the new LIMIT/OFFSET support for DELETE/UPDATE. (CVS 5789) check-in: d9f5e15c user: shane tags: trunk
04:34
Updated LIMIT support for DELETE/UPDATE. Omit option changed to SQLITE_ENABLE_UPDATE_DELETE_LIMIT. (CVS 5788) check-in: c10e8a3c user: shane tags: trunk
2008-10-09
18:48
Fix an assert() failure that can occur if the user attempts to set an into an integer primary key column to a text value in a table that has a BEFORE UPDATE trigger. (CVS 5787) check-in: c2cf9d60 user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
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
**    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.178 2008/10/07 05:27:11 shane 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.
................................................................................
  }
  sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
  sqlite3Select(pParse, pDup, &dest);
  sqlite3SelectDelete(db, pDup);
}
#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */

#ifndef SQLITE_OMIT_UPDATE_DELETE_LIMIT
/*
** Generate an expression tree to implement the WHERE, ORDER BY,
** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
**
**     DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
**                            \__________________________/
**                               pLimitWhere (pInClause)
................................................................................
  Parse *pParse,          /* The parser context */
  SrcList *pSrc,          /* the FROM clause -- which tables to scan */
  Expr *pWhere,           /* The WHERE clause.  May be null */
  ExprList *pOrderBy,     /* The ORDER BY clause.  May be null */
  Expr *pLimit,           /* The LIMIT clause.  May be null */
  Expr *pOffset           /* The OFFSET clause.  May be null */
){
  Expr *pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
  Expr *pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);


















  Expr *pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);

  ExprList *pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0);



  SrcList *pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc);


  Select *pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,pOrderBy,0,pLimit,pOffset);
  if( pSelect ) {





    pInClause->pSelect = pSelect;
    sqlite3ExprSetHeight(pParse, pInClause);
    return pInClause;
  }


  sqlite3SrcListDelete(pParse->db, pSelectSrc);
  sqlite3ExprListDelete(pParse->db, pEList);
  sqlite3ExprDelete(pParse->db, pSelectRowid);
  sqlite3ExprDelete(pParse->db, pInClause);
  sqlite3ExprDelete(pParse->db, pWhereRowid);
  return 0;
}
#endif /* !defined(SQLITE_OMIT_UPDATE_DELETE_LIMIT) */

/*
** Generate code for a DELETE FROM statement.
**
**     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
**                 \________/       \________________/
**                  pTabList              pWhere







|







 







|







 







|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
|
>
>
>
|
>
>
|
|
>
>
>
>
>
|
|
|
|
>
>







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
...
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
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
**    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.179 2008/10/10 04:34:16 shane 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.
................................................................................
  }
  sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
  sqlite3Select(pParse, pDup, &dest);
  sqlite3SelectDelete(db, pDup);
}
#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */

#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
/*
** Generate an expression tree to implement the WHERE, ORDER BY,
** and LIMIT/OFFSET portion of DELETE and UPDATE statements.
**
**     DELETE FROM table_wxyz WHERE a<5 ORDER BY a LIMIT 1;
**                            \__________________________/
**                               pLimitWhere (pInClause)
................................................................................
  Parse *pParse,          /* The parser context */
  SrcList *pSrc,          /* the FROM clause -- which tables to scan */
  Expr *pWhere,           /* The WHERE clause.  May be null */
  ExprList *pOrderBy,     /* The ORDER BY clause.  May be null */
  Expr *pLimit,           /* The LIMIT clause.  May be null */
  Expr *pOffset           /* The OFFSET clause.  May be null */
){
  Expr *pWhereRowid = NULL;
  Expr *pInClause = NULL;
  Expr *pSelectRowid = NULL;
  ExprList *pEList = NULL;
  SrcList *pSelectSrc = NULL;
  Select *pSelect = NULL;

  /* We only need to generate a select expression if there
  ** is a limit/offset term to enforce.
  */
  if (!pLimit && !pOffset) return pWhere;

  /* Generate a select expression tree to enforce the limit/offset 
  ** term for the DELETE or UPDATE statement.  For example:
  **   DELETE FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
  ** becomes:
  **   DELETE FROM table_a WHERE rowid IN ( 
  **     DELETE rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
  **   );
  */
  pSelectRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
  if( pSelectRowid == 0 ) goto limit_where_cleanup;
  pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0);
  if( pEList == 0 ) goto limit_where_cleanup;
  /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
  ** and the DELETE tree. */
  pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc);
  if( pSelectSrc == 0 ) goto limit_where_cleanup;
  /* generate the DELETE expression tree. */
  pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,pOrderBy,0,pLimit,pOffset);
  if( pSelect == 0 ) goto limit_where_cleanup;
  /* generate the WHERE rowid IN ( select ) expression */
  pWhereRowid = sqlite3Expr(pParse->db, TK_ROW, 0, 0, 0);
  if( pWhereRowid == 0 ) goto limit_where_cleanup;
  pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
  if( pInClause == 0 ) goto limit_where_cleanup;
  pInClause->pSelect = pSelect;
  sqlite3ExprSetHeight(pParse, pInClause);
  return pInClause;

limit_where_cleanup:
  /* something went wrong. clean up anything allocated. */
  sqlite3SrcListDelete(pParse->db, pSelectSrc);
  sqlite3ExprListDelete(pParse->db, pEList);
  sqlite3ExprDelete(pParse->db, pSelectRowid);
  sqlite3ExprDelete(pParse->db, pInClause);
  sqlite3ExprDelete(pParse->db, pWhereRowid);
  return 0;
}
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */

/*
** Generate code for a DELETE FROM statement.
**
**     DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL;
**                 \________/       \________________/
**                  pTabList              pWhere

Changes to src/parse.y.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
...
590
591
592
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
...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.255 2008/10/07 05:27:11 shane Exp $
*/

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
................................................................................
limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). 
                                       {A.pLimit = X; A.pOffset = Y;}
limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). 
                                       {A.pOffset = X; A.pLimit = Y;}

/////////////////////////// The DELETE statement /////////////////////////////
//
%ifndef SQLITE_OMIT_UPDATE_DELETE_LIMIT
cmd ::= DELETE FROM fullname(X) indexed_opt(I) where_opt(W) orderby_opt(O) limit_opt(L). {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  if( O && !L.pLimit ){
    sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on DELETE");
    pParse->parseError = 1;
  } else if (L.pLimit) {
    Expr *LW = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset);
................................................................................
      sqlite3DeleteFrom(pParse,X,LW);
    }
  } else {
    sqlite3DeleteFrom(pParse,X,W);
  }
}
%endif
%ifdef SQLITE_OMIT_UPDATE_DELETE_LIMIT
cmd ::= DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3DeleteFrom(pParse,X,W);
}
%endif

%type where_opt {Expr*}
................................................................................
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}

where_opt(A) ::= .                    {A = 0;}
where_opt(A) ::= WHERE expr(X).       {A = X;}

////////////////////////// The UPDATE command ////////////////////////////////
//
%ifndef SQLITE_OMIT_UPDATE_DELETE_LIMIT
cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W) orderby_opt(O) limit_opt(L).  {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3ExprListCheckLength(pParse,Y,"set list"); 
  if( O && !L.pLimit ){
    sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on UPDATE");
    pParse->parseError = 1;
  } else if (L.pLimit) {
................................................................................
      sqlite3Update(pParse,X,Y,LW,R);
    }
  } else {
    sqlite3Update(pParse,X,Y,W,R);
  }
}
%endif
%ifdef SQLITE_OMIT_UPDATE_DELETE_LIMIT
cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W).  {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3ExprListCheckLength(pParse,Y,"set list"); 
  sqlite3Update(pParse,X,Y,W,R);
}
%endif








|







 







|







 







|







 







|







 







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
...
590
591
592
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
...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
**
*************************************************************************
** This file contains SQLite's grammar for SQL.  Process this file
** using the lemon parser generator to generate C code that runs
** the parser.  Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
** @(#) $Id: parse.y,v 1.256 2008/10/10 04:34:16 shane Exp $
*/

// All token codes are small integers with #defines that begin with "TK_"
%token_prefix TK_

// The type of the data attached to each token is Token.  This is also the
// default type for non-terminals.
................................................................................
limit_opt(A) ::= LIMIT expr(X) OFFSET expr(Y). 
                                       {A.pLimit = X; A.pOffset = Y;}
limit_opt(A) ::= LIMIT expr(X) COMMA expr(Y). 
                                       {A.pOffset = X; A.pLimit = Y;}

/////////////////////////// The DELETE statement /////////////////////////////
//
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= DELETE FROM fullname(X) indexed_opt(I) where_opt(W) orderby_opt(O) limit_opt(L). {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  if( O && !L.pLimit ){
    sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on DELETE");
    pParse->parseError = 1;
  } else if (L.pLimit) {
    Expr *LW = sqlite3LimitWhere(pParse, X, W, O, L.pLimit, L.pOffset);
................................................................................
      sqlite3DeleteFrom(pParse,X,LW);
    }
  } else {
    sqlite3DeleteFrom(pParse,X,W);
  }
}
%endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= DELETE FROM fullname(X) indexed_opt(I) where_opt(W). {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3DeleteFrom(pParse,X,W);
}
%endif

%type where_opt {Expr*}
................................................................................
%destructor where_opt {sqlite3ExprDelete(pParse->db, $$);}

where_opt(A) ::= .                    {A = 0;}
where_opt(A) ::= WHERE expr(X).       {A = X;}

////////////////////////// The UPDATE command ////////////////////////////////
//
%ifdef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W) orderby_opt(O) limit_opt(L).  {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3ExprListCheckLength(pParse,Y,"set list"); 
  if( O && !L.pLimit ){
    sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on UPDATE");
    pParse->parseError = 1;
  } else if (L.pLimit) {
................................................................................
      sqlite3Update(pParse,X,Y,LW,R);
    }
  } else {
    sqlite3Update(pParse,X,Y,W,R);
  }
}
%endif
%ifndef SQLITE_ENABLE_UPDATE_DELETE_LIMIT
cmd ::= UPDATE orconf(R) fullname(X) indexed_opt(I) SET setlist(Y) where_opt(W).  {
  sqlite3SrcListIndexedBy(pParse, X, &I);
  sqlite3ExprListCheckLength(pParse,Y,"set list"); 
  sqlite3Update(pParse,X,Y,W,R);
}
%endif

Changes to src/resolve.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
...
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
**
*************************************************************************
**
** This file contains routines used for walking the parser tree and
** resolve all identifiers by associating them with a particular
** table and column.
**
** $Id: resolve.c,v 1.7 2008/10/06 15:18:02 drh Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>

/*
** Turn the pExpr expression into an alias for the iCol-th column of the
................................................................................
    for(i=0; i<pNC->pSrcList->nSrc; i++){
      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
    }
  }
#endif
  switch( pExpr->op ){

#ifndef SQLITE_OMIT_UPDATE_DELETE_LIMIT
    /* The special operator TK_ROW means use the rowid for the first
    ** column in the FROM clause.  This is used by the LIMIT and ORDER BY
    ** clause processing on UPDATE and DELETE statements.
    */
    case TK_ROW: {
      SrcList *pSrcList = pNC->pSrcList;
      struct SrcList_item *pItem;
................................................................................
      pExpr->op = TK_COLUMN;
      pExpr->pTab = pItem->pTab;
      pExpr->iTable = pItem->iCursor;
      pExpr->iColumn = -1;
      pExpr->affinity = SQLITE_AFF_INTEGER;
      break;
    }
#endif /* SQLITE_OMIT_UPDATE_DELETE_LIMIT */

    /* A lone identifier is the name of a column.
    */
    case TK_ID: {
      lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
      return WRC_Prune;
    }







|







 







|







 







|







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
...
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
...
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
**
*************************************************************************
**
** This file contains routines used for walking the parser tree and
** resolve all identifiers by associating them with a particular
** table and column.
**
** $Id: resolve.c,v 1.8 2008/10/10 04:34:16 shane Exp $
*/
#include "sqliteInt.h"
#include <stdlib.h>
#include <string.h>

/*
** Turn the pExpr expression into an alias for the iCol-th column of the
................................................................................
    for(i=0; i<pNC->pSrcList->nSrc; i++){
      assert( pSrcList->a[i].iCursor>=0 && pSrcList->a[i].iCursor<pParse->nTab);
    }
  }
#endif
  switch( pExpr->op ){

#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
    /* The special operator TK_ROW means use the rowid for the first
    ** column in the FROM clause.  This is used by the LIMIT and ORDER BY
    ** clause processing on UPDATE and DELETE statements.
    */
    case TK_ROW: {
      SrcList *pSrcList = pNC->pSrcList;
      struct SrcList_item *pItem;
................................................................................
      pExpr->op = TK_COLUMN;
      pExpr->pTab = pItem->pTab;
      pExpr->iTable = pItem->iCursor;
      pExpr->iColumn = -1;
      pExpr->affinity = SQLITE_AFF_INTEGER;
      break;
    }
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */

    /* A lone identifier is the name of a column.
    */
    case TK_ID: {
      lookupName(pParse, 0, 0, &pExpr->token, pNC, pExpr);
      return WRC_Prune;
    }

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
**    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.779 2008/10/07 23:46:38 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                         Expr*,ExprList*,int,Expr*,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#ifndef SQLITE_OMIT_UPDATE_DELETE_LIMIT
Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *);
#endif
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8);
void sqlite3WhereEnd(WhereInfo*);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);







|







 







|







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166
2167
2168
2169
2170
2171
**    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.780 2008/10/10 04:34:16 shane Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** Include the configuration header output by 'configure' if we're using the
** autoconf-based build
................................................................................
int sqlite3Select(Parse*, Select*, SelectDest*);
Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                         Expr*,ExprList*,int,Expr*,Expr*);
void sqlite3SelectDelete(sqlite3*, Select*);
Table *sqlite3SrcListLookup(Parse*, SrcList*);
int sqlite3IsReadOnly(Parse*, Table*, int);
void sqlite3OpenTable(Parse*, int iCur, int iDb, Table*, int);
#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
Expr *sqlite3LimitWhere(Parse *, SrcList *, Expr *, ExprList *, Expr *, Expr *);
#endif
void sqlite3DeleteFrom(Parse*, SrcList*, Expr*);
void sqlite3Update(Parse*, SrcList*, ExprList*, Expr*, int);
WhereInfo *sqlite3WhereBegin(Parse*, SrcList*, Expr*, ExprList**, u8);
void sqlite3WhereEnd(WhereInfo*);
int sqlite3ExprCodeGetColumn(Parse*, Table*, int, int, int, int);

Changes to src/test_config.c.

12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
445
446
447
448
449
450
451






452
453
454
455
456
457
458
** 
** This file contains code used for testing the SQLite system.
** None of the code in this file goes into a deliverable build.
** 
** The focus of this file is providing the TCL testing layer
** access to compile-time constants.
**
** $Id: test_config.c,v 1.38 2008/10/07 15:25:49 drh Exp $
*/

#include "sqliteLimit.h"

#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
................................................................................
#endif

#ifdef SQLITE_OMIT_WSD
  Tcl_SetVar2(interp, "sqlite_options", "wsd", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "wsd", "1", TCL_GLOBAL_ONLY);
#endif







#ifdef SQLITE_SECURE_DELETE
  Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "0", TCL_GLOBAL_ONLY);
#endif








|







 







>
>
>
>
>
>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
** 
** This file contains code used for testing the SQLite system.
** None of the code in this file goes into a deliverable build.
** 
** The focus of this file is providing the TCL testing layer
** access to compile-time constants.
**
** $Id: test_config.c,v 1.39 2008/10/10 04:34:16 shane Exp $
*/

#include "sqliteLimit.h"

#include "sqliteInt.h"
#include "tcl.h"
#include <stdlib.h>
................................................................................
#endif

#ifdef SQLITE_OMIT_WSD
  Tcl_SetVar2(interp, "sqlite_options", "wsd", "0", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "wsd", "1", TCL_GLOBAL_ONLY);
#endif

#if defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY)
  Tcl_SetVar2(interp, "sqlite_options", "update_delete_limit", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "update_delete_limit", "0", TCL_GLOBAL_ONLY);
#endif

#ifdef SQLITE_SECURE_DELETE
  Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "1", TCL_GLOBAL_ONLY);
#else
  Tcl_SetVar2(interp, "sqlite_options", "secure_delete", "0", TCL_GLOBAL_ONLY);
#endif