Minor optimizations for sub-selects in EXISTS(...) expressions: Discard any DISTINCT or ORDER BY clauses and do not calculate any column values. (CVS 4658)
FossilOrigin-Name: fbd17a8976cc9b4dd7c7c903d8beade9a7ef095f
diff --git a/src/select.c b/src/select.c
index 34b7d31..a854e3e 100644
--- a/src/select.c
+++ b/src/select.c
@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
-** $Id: select.c,v 1.376 2008/01/02 16:27:10 danielk1977 Exp $
+** $Id: select.c,v 1.377 2008/01/02 17:11:14 danielk1977 Exp $
*/
#include "sqliteInt.h"
@@ -548,7 +548,10 @@
for(i=0; i<nColumn; i++){
sqlite3VdbeOp3Int(v, OP_Column, srcTab, i, iMem+i+1);
}
- }else{
+ }else if( eDest!=SRT_Exists ){
+ /* If the destination is an EXISTS(...) expression, the actual
+ ** values returned by the SELECT are not required.
+ */
for(i=0; i<n; i++){
sqlite3ExprIntoReg(pParse, pEList->a[i].pExpr, iMem+i+1);
}
@@ -3143,6 +3146,13 @@
pOrderBy = p->pOrderBy;
if( IgnorableOrderby(pDest) ){
p->pOrderBy = 0;
+
+ /* In these cases the DISTINCT operator makes no difference to the
+ ** results, so remove it if it were specified.
+ */
+ assert(pDest->eDest==SRT_Exists || pDest->eDest==SRT_Union ||
+ pDest->eDest==SRT_Except || pDest->eDest==SRT_Discard);
+ p->isDistinct = 0;
}
if( sqlite3SelectResolve(pParse, p, 0) ){
goto select_end;
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 89b337b..c25f80e 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.629 2008/01/02 16:27:10 danielk1977 Exp $
+** @(#) $Id: sqliteInt.h,v 1.630 2008/01/02 17:11:14 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -1330,18 +1330,18 @@
*/
#define SRT_Union 1 /* Store result as keys in an index */
#define SRT_Except 2 /* Remove result from a UNION index */
-#define SRT_Discard 3 /* Do not save the results anywhere */
+#define SRT_Exists 3 /* Store 1 if the result is not empty */
+#define SRT_Discard 4 /* Do not save the results anywhere */
/* The ORDER BY clause is ignored for all of the above */
#define IgnorableOrderby(X) ((X->eDest)<=SRT_Discard)
-#define SRT_Callback 4 /* Invoke a callback with each row of result */
-#define SRT_Mem 5 /* Store result in a memory cell */
-#define SRT_Set 6 /* Store non-null results as keys in an index */
-#define SRT_Table 7 /* Store result as data with an automatic rowid */
-#define SRT_EphemTab 8 /* Create transient tab and store like SRT_Table */
-#define SRT_Subroutine 9 /* Call a subroutine to handle results */
-#define SRT_Exists 10 /* Store 1 if the result is not empty */
+#define SRT_Callback 5 /* Invoke a callback with each row of result */
+#define SRT_Mem 6 /* Store result in a memory cell */
+#define SRT_Set 7 /* Store non-null results as keys in an index */
+#define SRT_Table 8 /* Store result as data with an automatic rowid */
+#define SRT_EphemTab 9 /* Create transient tab and store like SRT_Table */
+#define SRT_Subroutine 10 /* Call a subroutine to handle results */
/*
** A structure used to customize the behaviour of sqlite3Select(). See