SQLite

Check-in [43507bbefb]
Login

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

Overview
Comment:Re-factored memory allocation failure handling in the sqlite3LimitWhere() function based on failures in the mallocJ.test script. (CVS 5791)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 43507bbefbf79e8db8fe31319ad621d48247983f
User & Date: shane 2008-10-10 13:35:58.000
Context
2008-10-10
14:27
Simplify the parser reduction code for the LIMIT clause on an UPDATE or DELETE. (CVS 5792) (check-in: 3de179630e user: drh tags: trunk)
13:35
Re-factored memory allocation failure handling in the sqlite3LimitWhere() function based on failures in the mallocJ.test script. (CVS 5791) (check-in: 43507bbefb user: shane tags: trunk)
13:34
Added mallocJ.test to test allocation failure handling of the new LIMIT/OFFSET support for UPDATE/DELETE. (CVS 5790) (check-in: 5375b348b1 user: shane tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/delete.c.
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.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.







|







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.180 2008/10/10 13:35:58 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.
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
  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.
**







|


>

|

|
>

|

|
>
>
>
>
|

|
|




>




<

<
<
>
|
<
<







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
  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 ( 
  **     SELECT 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 ) return 0;
  pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid, 0);
  if( pEList == 0 ) return 0;

  /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
  ** and the SELECT subtree. */
  pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc);
  if( pSelectSrc == 0 ) {
    sqlite3ExprListDelete(pParse->db, pEList);
    return 0;
  }

  /* generate the SELECT expression tree. */
  pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,pOrderBy,0,pLimit,pOffset);
  if( pSelect == 0 ) return 0;

  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;


  /* something went wrong. clean up anything allocated. */


limit_where_cleanup:
  sqlite3SelectDelete(pParse->db, pSelect);


  return 0;
}
#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */

/*
** Generate code for a DELETE FROM statement.
**