When materializing a view for an UPDATE or DELETE make use of the WHERE
clause to limit the number of rows materialized. Ticket #2938. (CVS 4782)
FossilOrigin-Name: 5ab71c3a79cac04cb2c576f83a62218d05571006
diff --git a/src/delete.c b/src/delete.c
index 5fffc8e..94839c9 100644
--- a/src/delete.c
+++ b/src/delete.c
@@ -12,7 +12,7 @@
** 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.160 2008/01/25 15:04:50 drh Exp $
+** $Id: delete.c,v 1.161 2008/02/12 16:52:14 drh Exp $
*/
#include "sqliteInt.h"
@@ -81,6 +81,39 @@
}
+#if !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER)
+/*
+** Evaluate a view and store its result in an ephemeral table. The
+** pWhere argument is an optional WHERE clause that restricts the
+** set of rows in the view that are to be added to the ephemeral table.
+*/
+void sqlite3MaterializeView(
+ Parse *pParse, /* Parsing context */
+ Select *pView, /* View definition */
+ Expr *pWhere, /* Optional WHERE clause to be added */
+ u32 col_mask, /* Render only the columns in this mask. */
+ int iCur /* Cursor number for ephemerial table */
+){
+ SelectDest dest;
+ Select *pDup;
+ sqlite3 *db = pParse->db;
+
+ pDup = sqlite3SelectDup(db, pView);
+ if( pWhere ){
+ SrcList *pFrom;
+
+ pWhere = sqlite3ExprDup(db, pWhere);
+ pFrom = sqlite3SrcListAppendFromTerm(pParse, 0, 0, 0, 0, pDup, 0, 0);
+ pDup = sqlite3SelectNew(pParse, 0, pFrom, pWhere, 0, 0, 0, 0, 0, 0);
+ }
+ sqlite3SelectMask(pParse, pDup, col_mask);
+ sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
+ sqlite3Select(pParse, pDup, &dest, 0, 0, 0, 0);
+ sqlite3SelectDelete(pDup);
+}
+#endif /* !defined(SQLITE_OMIT_VIEW) && !defined(SQLITE_OMIT_TRIGGER) */
+
+
/*
** Generate code for a DELETE FROM statement.
**
@@ -170,19 +203,13 @@
oldIdx = pParse->nTab++;
}
- /* Resolve the column names in the WHERE clause.
+ /* Assign cursor number to the table and all its indices.
*/
assert( pTabList->nSrc==1 );
iCur = pTabList->a[0].iCursor = pParse->nTab++;
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
pParse->nTab++;
}
- memset(&sNC, 0, sizeof(sNC));
- sNC.pParse = pParse;
- sNC.pSrcList = pTabList;
- if( sqlite3ExprResolveNames(&sNC, pWhere) ){
- goto delete_from_cleanup;
- }
/* Start the view context
*/
@@ -221,14 +248,16 @@
** a ephemeral table.
*/
if( isView ){
- SelectDest dest;
- Select *pView;
+ sqlite3MaterializeView(pParse, pTab->pSelect, pWhere, old_col_mask, iCur);
+ }
- pView = sqlite3SelectDup(db, pTab->pSelect);
- sqlite3SelectMask(pParse, pView, old_col_mask);
- sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
- sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
- sqlite3SelectDelete(pView);
+ /* Resolve the column names in the WHERE clause.
+ */
+ memset(&sNC, 0, sizeof(sNC));
+ sNC.pParse = pParse;
+ sNC.pSrcList = pTabList;
+ if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+ goto delete_from_cleanup;
}
/* Initialize the counter of the number of rows deleted, if
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 2f26f58..f9087f7 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.659 2008/02/02 04:47:09 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.660 2008/02/12 16:52:14 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -1826,6 +1826,7 @@
int sqlite3SafetyCheckOk(sqlite3*);
int sqlite3SafetyCheckSickOrOk(sqlite3*);
void sqlite3ChangeCookie(Parse*, int);
+void sqlite3MaterializeView(Parse*, Select*, Expr*, u32, int);
#ifndef SQLITE_OMIT_TRIGGER
void sqlite3BeginTrigger(Parse*, Token*,Token*,int,int,IdList*,SrcList*,
diff --git a/src/update.c b/src/update.c
index fb45563..5c21ab8 100644
--- a/src/update.c
+++ b/src/update.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
-** $Id: update.c,v 1.170 2008/01/19 03:35:59 drh Exp $
+** $Id: update.c,v 1.171 2008/02/12 16:52:14 drh Exp $
*/
#include "sqliteInt.h"
@@ -289,13 +289,6 @@
}
#endif
- /* Resolve the column names in all the expressions in the
- ** WHERE clause.
- */
- if( sqlite3ExprResolveNames(&sNC, pWhere) ){
- goto update_cleanup;
- }
-
/* Start the view context
*/
if( isView ){
@@ -335,14 +328,15 @@
** a ephemeral table.
*/
if( isView ){
- Select *pView;
- SelectDest dest;
+ sqlite3MaterializeView(pParse, pTab->pSelect, pWhere,
+ old_col_mask|new_col_mask, iCur);
+ }
- pView = sqlite3SelectDup(db, pTab->pSelect);
- sqlite3SelectMask(pParse, pView, old_col_mask|new_col_mask);
- sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
- sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
- sqlite3SelectDelete(pView);
+ /* Resolve the column names in all the expressions in the
+ ** WHERE clause.
+ */
+ if( sqlite3ExprResolveNames(&sNC, pWhere) ){
+ goto update_cleanup;
}
/* Begin the database scan