Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Initial support for LIMIT clause on DELETEs and UPDATEs. Changes likely with more testing. The code can be omitted with the define SQLITE_OMIT_UPDATE_DELETE_LIMIT. (CVS 5774) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
9c8b132e34bc6024bc9898182f8f9312 |
User & Date: | shane 2008-10-07 05:27:11.000 |
Context
2008-10-07
| ||
11:51 | Fix a problem with hot-journal rollback. SQLITE_CANTOPEN was being returned if the hot-journal file contained a pointer to a master journal file that did not exist. (CVS 5775) (check-in: 22d1feb9b2 user: danielk1977 tags: trunk) | |
05:27 | Initial support for LIMIT clause on DELETEs and UPDATEs. Changes likely with more testing. The code can be omitted with the define SQLITE_OMIT_UPDATE_DELETE_LIMIT. (CVS 5774) (check-in: 9c8b132e34 user: shane tags: trunk) | |
01:18 | Removed redundant assert(). (CVS 5773) (check-in: 486b1124f7 user: shane tags: trunk) | |
Changes
Changes to src/delete.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** 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. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** 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. |
︙ | ︙ | |||
112 113 114 115 116 117 118 119 120 121 122 123 124 125 | } sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur); sqlite3Select(pParse, pDup, &dest); sqlite3SelectDelete(db, pDup); } #endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */ /* ** Generate code for a DELETE FROM statement. ** ** DELETE FROM table_wxyz WHERE a<5 AND b NOT NULL; ** \________/ \________________/ ** pTabList pWhere | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 112 113 114 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 149 150 151 152 153 154 155 156 157 158 159 160 161 | } 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) */ Expr *sqlite3LimitWhere( 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 |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** 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. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** 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. |
︙ | ︙ | |||
574 575 576 577 578 579 580 | 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 ///////////////////////////// // | > | > > > > > > | | > > > > > > > > > > > > | > > > > > > | | > > > > > > > > > > > > | 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 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 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 | 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); if( LW ) { 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) { Expr *LW = sqlite3LimitWhere(pParse, X, W, O, L.pLimit,L.pOffset); if( LW ) { 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 %type setlist {ExprList*} %destructor setlist {sqlite3ExprListDelete(pParse->db, $$);} setlist(A) ::= setlist(Z) COMMA nm(X) EQ expr(Y). {A = sqlite3ExprListAppend(pParse,Z,Y,&X);} setlist(A) ::= nm(X) EQ expr(Y). |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** 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. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** 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.776 2008/10/07 05:27:11 shane Exp $ */ #ifndef _SQLITEINT_H_ #define _SQLITEINT_H_ /* ** Include the configuration header output by 'configure' if we're using the ** autoconf-based build |
︙ | ︙ | |||
2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 | 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); 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); void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprCodeCopy(Parse*, int, int, int); | > > > | 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 | 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); void sqlite3ExprCodeMove(Parse*, int, int, int); void sqlite3ExprCodeCopy(Parse*, int, int, int); |
︙ | ︙ |