]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Combine the eDest and iParm arguments to sqlite3Select() into a single type - "Select...
authordanielk1977 <danielk1977@noemail.net>
Wed, 2 Jan 2008 16:27:09 +0000 (16:27 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Wed, 2 Jan 2008 16:27:09 +0000 (16:27 +0000)
FossilOrigin-Name: 86dcdfe6d7d629618ccb3c3ff0ca09f2da2d06c7

manifest
manifest.uuid
src/build.c
src/delete.c
src/expr.c
src/insert.c
src/parse.y
src/select.c
src/sqliteInt.h
src/trigger.c
src/update.c

index d7caafca7f36c2ab68719a72f69032ce4198dbdb..2ddab039498d955b526e8ef1e69b595894d281fb 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sopcodes\sOP_ResultRow\sand\sOP_RegMakeRec\swhich\sare\sregister-based\nequivalents\sto\sOP_Callback\sand\sOP_MakeRecord.\s\sUse\sthe\snew\sopcodes.\s(CVS\s4656)
-D 2008-01-02T14:28:13
+C Combine\sthe\seDest\sand\siParm\sarguments\sto\ssqlite3Select()\sinto\sa\ssingle\stype\s-\s"SelectDest".\s(CVS\s4657)
+D 2008-01-02T16:27:10
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -86,17 +86,17 @@ F src/btmutex.c 5d39da37c9d1282f3c6f9967afae6a34ee36b7ff
 F src/btree.c 5164b32950cfd41f2c5c31e8ff82c4a499918aef
 F src/btree.h 19dcf5ad23c17b98855da548e9a8e3eb4429d5eb
 F src/btreeInt.h 1c5a9da165718ef7de81e35ce9ab5d9ba9283f76
-F src/build.c cbfd98ceb95c61c226cd60a845fa7967b66c8931
+F src/build.c 640c2a2a22baa16622c0aa74ae948a3643c1d6d6
 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
-F src/delete.c 9a98d854ac2613d14616f5023577a6bec53b2d0e
+F src/delete.c 0114a9582305e2348bed4bc94ffa3e603da489ff
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c 9f46128496d750edc0a2b32585a109defd9ce74c
+F src/expr.c c5c784ffdd8e55d6e9730fbaebe482a34136ab60
 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
 F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 1946d8c7431fc2b614a4b15155f960f999b14ba5
+F src/insert.c 5b8061104f91f74f96427e7b7962ed623ccf73df
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
@@ -126,17 +126,17 @@ F src/os_win.c c832d528ea774c7094d887749d71884984c9034c
 F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
 F src/pager.c 0cb6ccea4b9615627d61d7c4417cedc45776d429
 F src/pager.h f504f7ae84060fee0416a853e368d3d113c3d6fa
-F src/parse.y a780b33ef45dd7b3272319cf91e609d6f109a31c
+F src/parse.y 2ae06e8d3190faace49c5b82e7cea1fc60d084a1
 F src/pragma.c 4a7f377a509eb14e35b09d4bf7b808ef647aad0b
 F src/prepare.c 7aeba7851773fbe3950a26b35d3389bef0eb1c62
 F src/printf.c eb27822ba2eec669161409ca31279a24c26ac910
 F src/random.c 4a22746501bf36b0a088c66e38dde5daba6a35da
-F src/select.c c0a225dc3133f914760908c7a73fce83b2834fbb
+F src/select.c 6a3790a03f10b2dfce9011d93e817b2cff7746d4
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 77895a54c2082157e169c857a2e244525ec25af7
 F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h 942a52122bbffb8a16d606ceb531a3529f3557a1
+F src/sqliteInt.h ff7a5de4ac31a974eab8cc5286fef01d4ed2e148
 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
@@ -163,8 +163,8 @@ F src/test_server.c a6ece6c835e7eae835054124e09e947e422b1ac5
 F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
 F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
-F src/trigger.c f8e2d42cf1782ffc14a9d7cee1d1a406f9b0c8c4
-F src/update.c 24ab2157d360bc20ac4447f50d3a70cd993a7d98
+F src/trigger.c 907b819d87eb3a15d1372ecd81e4ca969f5bcf1a
+F src/update.c 608ecf1f508442d8b05cc258a0573e6fe3573b8b
 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
 F src/vacuum.c 25ffbd766f25bca099ead1c1e11f5528c86102b8
@@ -603,7 +603,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 03cc91b3b0ff9be192532f8a404b3c7b827e1449
-R 7a6df4f12366724f53264755c79c306d
-U drh
-Z 99aefce3e13cf9b619d1d8015ce6d124
+P 4c7f35da7751c61a9b61b1d95adddcc37fff3266
+R cf4761a43ed1fe7db5bce1f482fb074b
+U danielk1977
+Z 493527b5521ff75db65bcee76afc559a
index 79c505e502f3e2ade5a77d9be4592dd1d94717c0..28f9cf8ed013dad75f94d3803705bfa4861447b6 100644 (file)
@@ -1 +1 @@
-4c7f35da7751c61a9b61b1d95adddcc37fff3266
\ No newline at end of file
+86dcdfe6d7d629618ccb3c3ff0ca09f2da2d06c7
\ No newline at end of file
index e6759eab0599034405773e72d9ae6670dbc78603..57f0f3141820df8691d97e56b7376f8b734012b3 100644 (file)
@@ -22,7 +22,7 @@
 **     COMMIT
 **     ROLLBACK
 **
-** $Id: build.c,v 1.451 2007/12/27 15:12:17 danielk1977 Exp $
+** $Id: build.c,v 1.452 2008/01/02 16:27:10 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1491,12 +1491,13 @@ void sqlite3EndTable(
     ** be redundant.
     */
     if( pSelect ){
+      SelectDest dest = {SRT_Table, 1, 0};
       Table *pSelTab;
       sqlite3VdbeAddOp(v, OP_Dup, 0, 0);
       sqlite3VdbeAddOp(v, OP_Integer, iDb, 0);
       sqlite3VdbeAddOp(v, OP_OpenWrite, 1, 0);
       pParse->nTab = 2;
-      sqlite3Select(pParse, pSelect, SRT_Table, 1, 0, 0, 0, 0);
+      sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
       sqlite3VdbeAddOp(v, OP_Close, 1, 0);
       if( pParse->nErr==0 ){
         pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
index 4eafc1e08df36b48b15878ee1349cec6b18feaf5..4dfa59ca27c0f9dcf1ebeaafdb4b1b91b8eed555 100644 (file)
@@ -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.138 2008/01/02 13:05:51 drh Exp $
+** $Id: delete.c,v 1.139 2008/01/02 16:27:10 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -220,9 +220,11 @@ void sqlite3DeleteFrom(
   ** a ephemeral table.
   */
   if( isView ){
+    SelectDest dest = {SRT_EphemTab, 0, 0};
     Select *pView = sqlite3SelectDup(db, pTab->pSelect);
     sqlite3SelectMask(pParse, pView, old_col_mask);
-    sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
+    dest.iParm = iCur;
+    sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
     sqlite3SelectDelete(pView);
   }
 
index c5e3a8fbd967165fd75cab3f816494f1f789bf34..181e23c616b58ef740ad17ed4014111458c404f7 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.323 2008/01/02 14:28:13 drh Exp $
+** $Id: expr.c,v 1.324 2008/01/02 16:27:10 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1738,10 +1738,12 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
         ** Generate code to write the results of the select into the temporary
         ** table allocated and opened above.
         */
-        int iParm = pExpr->iTable +  (((int)affinity)<<16);
+        SelectDest dest = {SRT_Set, 0, 0};
+        dest.iParm = pExpr->iTable;
+        dest.affinity = (int)affinity;
         ExprList *pEList;
         assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
-        if( sqlite3Select(pParse, pExpr->pSelect, SRT_Set, iParm, 0, 0, 0, 0) ){
+        if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0, 0) ){
           return;
         }
         pEList = pExpr->pSelect->pEList;
@@ -1798,26 +1800,25 @@ void sqlite3CodeSubselect(Parse *pParse, Expr *pExpr){
       */
       static const Token one = { (u8*)"1", 0, 1 };
       Select *pSel;
-      int sop;
-      int iMem;
+      SelectDest dest;
 
       pSel = pExpr->pSelect;
-      iMem = pParse->nMem++;
+      dest.iParm = pParse->nMem++;
       if( pExpr->op==TK_SELECT ){
-        sop = SRT_Mem;
-        sqlite3VdbeAddOp(v, OP_MemNull, 0, iMem);
+        dest.eDest = SRT_Mem;
+        sqlite3VdbeAddOp(v, OP_MemNull, 0, dest.iParm);
         VdbeComment((v, "Init subquery result"));
       }else{
-        sop = SRT_Exists;
-        sqlite3VdbeAddOp(v, OP_MemInt, 0, iMem);
+        dest.eDest = SRT_Exists;
+        sqlite3VdbeAddOp(v, OP_MemInt, 0, dest.iParm);
         VdbeComment((v, "Init EXISTS result"));
       }
       sqlite3ExprDelete(pSel->pLimit);
       pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &one);
-      if( sqlite3Select(pParse, pSel, sop, iMem, 0, 0, 0, 0) ){
+      if( sqlite3Select(pParse, pSel, &dest, 0, 0, 0, 0) ){
         return;
       }
-      pExpr->iColumn = iMem;
+      pExpr->iColumn = dest.iParm;
       break;
     }
   }
index 26eb7a28cb120823207bf064fbe624a4add387e5..943afcdbbffa0c84bba3c8de3a7692704f1b940b 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.200 2008/01/02 11:50:51 danielk1977 Exp $
+** $Id: insert.c,v 1.201 2008/01/02 16:27:10 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -476,13 +476,15 @@ void sqlite3Insert(
   if( pSelect ){
     /* Data is coming from a SELECT.  Generate code to implement that SELECT
     */
+    SelectDest dest = {SRT_Subroutine, 0, 0};
     int rc, iInitCode;
     iInitCode = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);
     iSelectLoop = sqlite3VdbeCurrentAddr(v);
     iInsertBlock = sqlite3VdbeMakeLabel(v);
+    dest.iParm = iInsertBlock;
 
     /* Resolve the expressions in the SELECT statement and execute it. */
-    rc = sqlite3Select(pParse, pSelect, SRT_Subroutine, iInsertBlock,0,0,0,0);
+    rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
     if( rc || pParse->nErr || db->mallocFailed ){
       goto insert_cleanup;
     }
index 723e7a1bc201b4de3a4fc44836edf578b61764fa..19edda65b83ef80acc55d5f61b7d8cfbc3db813b 100644 (file)
@@ -14,7 +14,7 @@
 ** the parser.  Lemon will also generate a header file containing
 ** numeric codes for all of the tokens.
 **
-** @(#) $Id: parse.y,v 1.236 2007/11/17 22:23:28 drh Exp $
+** @(#) $Id: parse.y,v 1.237 2008/01/02 16:27:10 danielk1977 Exp $
 */
 
 // All token codes are small integers with #defines that begin with "TK_"
@@ -365,7 +365,8 @@ cmd ::= DROP VIEW ifexists(E) fullname(X). {
 //////////////////////// The SELECT statement /////////////////////////////////
 //
 cmd ::= select(X).  {
-  sqlite3Select(pParse, X, SRT_Callback, 0, 0, 0, 0, 0);
+  SelectDest dest = {SRT_Callback, 0, 0};
+  sqlite3Select(pParse, X, &dest, 0, 0, 0, 0);
   sqlite3SelectDelete(X);
 }
 
index e684966ba463df42283b44199750a1bd901baa39..34b7d3165e5a1c3f9c6b74251974fc9aaf17036f 100644 (file)
@@ -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.375 2008/01/02 14:28:13 drh Exp $
+** $Id: select.c,v 1.376 2008/01/02 16:27:10 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -479,7 +479,12 @@ static void codeDistinct(
 ** column.  We do this in a subroutine because the error occurs in multiple
 ** places.
 */
-static int checkForMultiColumnSelectError(Parse *pParse, int eDest, int nExpr){
+static int checkForMultiColumnSelectError(
+  Parse *pParse,       /* Parse context. */
+  SelectDest *pDest,   /* Destination of SELECT results */
+  int nExpr            /* Number of result columns returned by SELECT */
+){
+  int eDest = pDest->eDest;
   if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){
     sqlite3ErrorMsg(pParse, "only a single result allowed for "
        "a SELECT that is part of an expression");
@@ -506,8 +511,7 @@ static int selectInnerLoop(
   int nColumn,            /* Number of columns in the source table */
   ExprList *pOrderBy,     /* If not NULL, sort results using this key */
   int distinct,           /* If >=0, make sure results are distinct */
-  int eDest,              /* How to dispose of the results */
-  int iParm,              /* An argument to the disposal method */
+  SelectDest *pDest,      /* How to dispose of the results */
   int iContinue,          /* Jump here to continue with next row */
   int iBreak,             /* Jump here to break out of the inner loop */
   char *aff               /* affinity string if eDest is SRT_Union */
@@ -516,6 +520,8 @@ static int selectInnerLoop(
   int i, n;
   int hasDistinct;        /* True if the DISTINCT keyword is present */
   int iMem;               /* Start of memory holding result set */
+  int eDest = pDest->eDest;
+  int iParm = pDest->iParm;
 
   if( v==0 ) return 0;
   assert( pEList!=0 );
@@ -562,7 +568,7 @@ static int selectInnerLoop(
     }
   }
 
-  if( checkForMultiColumnSelectError(pParse, eDest, pEList->nExpr) ){
+  if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){
     return 0;
   }
 
@@ -619,7 +625,7 @@ static int selectInnerLoop(
 
       assert( nColumn==1 );
       addr2 = sqlite3VdbeAddOp(v, OP_IfMemNull, iMem+1, 0);
-      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr,(iParm>>16)&0xff);
+      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
       if( pOrderBy ){
         /* At first glance you would think we could optimize out the
         ** ORDER BY in this case since the order of entries in the set
@@ -629,7 +635,7 @@ static int selectInnerLoop(
         pushOntoSorter(pParse, pOrderBy, p);
       }else{
         sqlite3VdbeOp3(v, OP_RegMakeRec, iMem, 0, &p->affinity, 1);
-        sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
+        sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0);
       }
       sqlite3VdbeJumpHere(v, addr2);
       break;
@@ -749,12 +755,11 @@ static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){
 ** routine generates the code needed to do that.
 */
 static void generateSortTail(
-  Parse *pParse,   /* Parsing context */
-  Select *p,       /* The SELECT statement */
-  Vdbe *v,         /* Generate code into this VDBE */
-  int nColumn,     /* Number of columns of data */
-  int eDest,       /* Write the sorted results here */
-  int iParm        /* Optional parameter associated with eDest */
+  Parse *pParse,    /* Parsing context */
+  Select *p,        /* The SELECT statement */
+  Vdbe *v,          /* Generate code into this VDBE */
+  int nColumn,      /* Number of columns of data */
+  SelectDest *pDest /* Write the sorted results here */
 ){
   int brk = sqlite3VdbeMakeLabel(v);
   int cont = sqlite3VdbeMakeLabel(v);
@@ -763,6 +768,9 @@ static void generateSortTail(
   int pseudoTab = 0;
   ExprList *pOrderBy = p->pOrderBy;
 
+  int eDest = pDest->eDest;
+  int iParm = pDest->iParm;
+
   iTab = pOrderBy->iECursor;
   if( eDest==SRT_Callback || eDest==SRT_Subroutine ){
     pseudoTab = pParse->nTab++;
@@ -790,7 +798,7 @@ static void generateSortTail(
       sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
       sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);
       sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1);
-      sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
+      sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0);
       break;
     }
     case SRT_Mem: {
@@ -1846,8 +1854,7 @@ static CollSeq *multiSelectCollSeq(Parse *pParse, Select *p, int iCol){
 static int multiSelect(
   Parse *pParse,        /* Parsing context */
   Select *p,            /* The right-most of SELECTs to be coded */
-  int eDest,            /* \___  Store query results as specified */
-  int iParm,            /* /     by these two parameters.         */
+  SelectDest *pDest,    /* What to do with query results */
   char *aff             /* If eDest is SRT_Union, the affinity string */
 ){
   int rc = SQLITE_OK;   /* Success code from a subroutine */
@@ -1858,6 +1865,11 @@ static int multiSelect(
   int aSetP2[2];        /* Set P2 value of these op to number of columns */
   int nSetP2 = 0;       /* Number of slots in aSetP2[] used */
 
+  SelectDest dest;
+  dest.eDest = pDest->eDest;
+  dest.iParm = pDest->iParm;
+  dest.affinity = pDest->affinity;
+
   /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
   ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
   */
@@ -1891,11 +1903,11 @@ static int multiSelect(
 
   /* Create the destination temporary table if necessary
   */
-  if( eDest==SRT_EphemTab ){
+  if( dest.eDest==SRT_EphemTab ){
     assert( p->pEList );
     assert( nSetP2<sizeof(aSetP2)/sizeof(aSetP2[0]) );
-    aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 0);
-    eDest = SRT_Table;
+    aSetP2[nSetP2++] = sqlite3VdbeAddOp(v, OP_OpenEphemeral, dest.iParm, 0);
+    dest.eDest = SRT_Table;
   }
 
   /* Generate code for the left and right SELECT statements.
@@ -1908,7 +1920,7 @@ static int multiSelect(
         assert( !pPrior->pLimit );
         pPrior->pLimit = p->pLimit;
         pPrior->pOffset = p->pOffset;
-        rc = sqlite3Select(pParse, pPrior, eDest, iParm, 0, 0, 0, aff);
+        rc = sqlite3Select(pParse, pPrior, &dest, 0, 0, 0, aff);
         p->pLimit = 0;
         p->pOffset = 0;
         if( rc ){
@@ -1921,7 +1933,7 @@ static int multiSelect(
           addr = sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, 0);
           VdbeComment((v, "Jump ahead if LIMIT reached"));
         }
-        rc = sqlite3Select(pParse, p, eDest, iParm, 0, 0, 0, aff);
+        rc = sqlite3Select(pParse, p, &dest, 0, 0, 0, aff);
         p->pPrior = pPrior;
         if( rc ){
           goto multi_select_end;
@@ -1940,13 +1952,14 @@ static int multiSelect(
       int priorOp;     /* The SRT_ operation to apply to prior selects */
       Expr *pLimit, *pOffset; /* Saved values of p->nLimit and p->nOffset */
       int addr;
+      SelectDest uniondest;
 
       priorOp = p->op==TK_ALL ? SRT_Table : SRT_Union;
-      if( eDest==priorOp && pOrderBy==0 && !p->pLimit && !p->pOffset ){
+      if( dest.eDest==priorOp && pOrderBy==0 && !p->pLimit && !p->pOffset ){
         /* We can reuse a temporary table generated by a SELECT to our
         ** right.
         */
-        unionTab = iParm;
+        unionTab = dest.iParm;
       }else{
         /* We will need to create our own temporary table to hold the
         ** intermediate results.
@@ -1972,7 +1985,9 @@ static int multiSelect(
       /* Code the SELECT statements to our left
       */
       assert( !pPrior->pOrderBy );
-      rc = sqlite3Select(pParse, pPrior, priorOp, unionTab, 0, 0, 0, aff);
+      uniondest.eDest = priorOp;
+      uniondest.iParm = unionTab;
+      rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0, aff);
       if( rc ){
         goto multi_select_end;
       }
@@ -1991,7 +2006,8 @@ static int multiSelect(
       p->pLimit = 0;
       pOffset = p->pOffset;
       p->pOffset = 0;
-      rc = sqlite3Select(pParse, p, op, unionTab, 0, 0, 0, aff);
+      uniondest.eDest = op;
+      rc = sqlite3Select(pParse, p, &uniondest, 0, 0, 0, aff);
       /* Query flattening in sqlite3Select() might refill p->pOrderBy.
       ** Be sure to delete p->pOrderBy, therefore, to avoid a memory leak. */
       sqlite3ExprListDelete(p->pOrderBy);
@@ -2010,10 +2026,10 @@ static int multiSelect(
       /* Convert the data in the temporary table into whatever form
       ** it is that we currently need.
       */      
-      if( eDest!=priorOp || unionTab!=iParm ){
+      if( dest.eDest!=priorOp || unionTab!=dest.iParm ){
         int iCont, iBreak, iStart;
         assert( p->pEList );
-        if( eDest==SRT_Callback ){
+        if( dest.eDest==SRT_Callback ){
           Select *pFirst = p;
           while( pFirst->pPrior ) pFirst = pFirst->pPrior;
           generateColumnNames(pParse, 0, pFirst->pEList);
@@ -2024,8 +2040,7 @@ static int multiSelect(
         sqlite3VdbeAddOp(v, OP_Rewind, unionTab, iBreak);
         iStart = sqlite3VdbeCurrentAddr(v);
         rc = selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,
-                             pOrderBy, -1, eDest, iParm, 
-                             iCont, iBreak, 0);
+                             pOrderBy, -1, &dest, iCont, iBreak, 0);
         if( rc ){
           rc = 1;
           goto multi_select_end;
@@ -2042,6 +2057,7 @@ static int multiSelect(
       int iCont, iBreak, iStart;
       Expr *pLimit, *pOffset;
       int addr;
+      SelectDest intersectdest = {SRT_Union, 0, 0};
 
       /* INTERSECT is different from the others since it requires
       ** two temporary tables.  Hence it has its own case.  Begin
@@ -2063,7 +2079,8 @@ static int multiSelect(
 
       /* Code the SELECTs to our left into temporary table "tab1".
       */
-      rc = sqlite3Select(pParse, pPrior, SRT_Union, tab1, 0, 0, 0, aff);
+      intersectdest.iParm = tab1;
+      rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0, aff);
       if( rc ){
         goto multi_select_end;
       }
@@ -2078,7 +2095,8 @@ static int multiSelect(
       p->pLimit = 0;
       pOffset = p->pOffset;
       p->pOffset = 0;
-      rc = sqlite3Select(pParse, p, SRT_Union, tab2, 0, 0, 0, aff);
+      intersectdest.iParm = tab2;
+      rc = sqlite3Select(pParse, p, &intersectdest, 0, 0, 0, aff);
       p->pPrior = pPrior;
       sqlite3ExprDelete(p->pLimit);
       p->pLimit = pLimit;
@@ -2091,7 +2109,7 @@ static int multiSelect(
       ** tables.
       */
       assert( p->pEList );
-      if( eDest==SRT_Callback ){
+      if( dest.eDest==SRT_Callback ){
         Select *pFirst = p;
         while( pFirst->pPrior ) pFirst = pFirst->pPrior;
         generateColumnNames(pParse, 0, pFirst->pEList);
@@ -2103,8 +2121,7 @@ static int multiSelect(
       iStart = sqlite3VdbeAddOp(v, OP_RowKey, tab1, 0);
       sqlite3VdbeAddOp(v, OP_NotFound, tab2, iCont);
       rc = selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,
-                             pOrderBy, -1, eDest, iParm, 
-                             iCont, iBreak, 0);
+                             pOrderBy, -1, &dest, iCont, iBreak, 0);
       if( rc ){
         rc = 1;
         goto multi_select_end;
@@ -2229,7 +2246,7 @@ static int multiSelect(
       pKeyInfo->nField = nOrderByExpr;
       sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
       pKeyInfo = 0;
-      generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm);
+      generateSortTail(pParse, p, v, p->pEList->nExpr, &dest);
     }
 
     sqlite3_free(pKeyInfo);
@@ -2625,7 +2642,7 @@ static int flattenSubquery(
 ** The parameters to this routine are the same as for sqlite3Select().
 ** See the header comment on that routine for additional information.
 */
-static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
+static int simpleMinMaxQuery(Parse *pParse, Select *p, SelectDest *pDest){
   Expr *pExpr;
   int iCol;
   Table *pTab;
@@ -2697,8 +2714,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
 
   /* If the output is destined for a temporary table, open that table.
   */
-  if( eDest==SRT_EphemTab ){
-    sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, 1);
+  if( pDest->eDest==SRT_EphemTab ){
+    sqlite3VdbeAddOp(v, OP_OpenEphemeral, pDest->iParm, 1);
   }
 
   /* Generating code to find the min or the max.  Basically all we have
@@ -2756,7 +2773,7 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){
   memset(&eListItem, 0, sizeof(eListItem));
   eList.a = &eListItem;
   eList.a[0].pExpr = pExpr;
-  selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, brk, brk, 0);
+  selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, pDest, brk, brk, 0);
   sqlite3VdbeResolveLabel(v, brk);
   sqlite3VdbeAddOp(v, OP_Close, base, 0);
   
@@ -3027,25 +3044,39 @@ int sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){
 ** Generate code for the given SELECT statement.
 **
 ** The results are distributed in various ways depending on the
-** value of eDest and iParm.
+** contents of the SelectDest structure pointed to by argument pDest
+** as follows:
 **
-**     eDest Value       Result
+**     pDest->eDest    Result
 **     ------------    -------------------------------------------
 **     SRT_Callback    Invoke the callback for each row of the result.
 **
-**     SRT_Mem         Store first result in memory cell iParm
+**     SRT_Mem         Store first result in memory cell pDest->iParm
+**
+**     SRT_Set         Store non-null results as keys of table pDest->iParm. 
+**                     Apply the affinity pDest->affinity before storing them.
+**
+**     SRT_Union       Store results as a key in a temporary table pDest->iParm.
+**
+**     SRT_Except      Remove results from the temporary table pDest->iParm.
+**
+**     SRT_Table       Store results in temporary table pDest->iParm
 **
-**     SRT_Set         Store results as keys of table iParm.
+**     SRT_EphemTab    Create an temporary table pDest->iParm and store
+**                     the result there. The cursor is left open after
+**                     returning.
 **
-**     SRT_Union       Store results as a key in a temporary table iParm
+**     SRT_Subroutine  For each row returned, push the results onto the
+**                     vdbe stack and call the subroutine (via OP_Gosub)
+**                     at address pDest->iParm.
 **
-**     SRT_Except      Remove results from the temporary table iParm.
+**     SRT_Exists      Store a 1 in memory cell pDest->iParm if the result
+**                     set is not empty.
 **
-**     SRT_Table       Store results in temporary table iParm
+**     SRT_Discard     Throw the results away.
 **
-** The table above is incomplete.  Additional eDist value have be added
-** since this comment was written.  See the selectInnerLoop() function for
-** a complete listing of the allowed values of eDest and their meanings.
+** See the selectInnerLoop() function for a canonical listing of the 
+** allowed values of eDest and their meanings.
 **
 ** This routine returns the number of errors.  If any errors are
 ** encountered, then an appropriate error message is left in
@@ -3078,8 +3109,7 @@ int sqlite3SelectMask(Parse *pParse, Select *p, u32 mask){
 int sqlite3Select(
   Parse *pParse,         /* The parser context */
   Select *p,             /* The SELECT statement being coded. */
-  int eDest,             /* How to dispose of the results */
-  int iParm,             /* A parameter used by the eDest disposal method */
+  SelectDest *pDest,     /* What to do with the query results */
   Select *pParent,       /* Another SELECT for which this is a sub-query */
   int parentTab,         /* Index in pParent->pSrc of this query */
   int *pParentAgg,       /* True if pParent uses aggregate functions */
@@ -3111,7 +3141,7 @@ int sqlite3Select(
   memset(&sAggInfo, 0, sizeof(sAggInfo));
 
   pOrderBy = p->pOrderBy;
-  if( IgnorableOrderby(eDest) ){
+  if( IgnorableOrderby(pDest) ){
     p->pOrderBy = 0;
   }
   if( sqlite3SelectResolve(pParse, p, 0) ){
@@ -3136,7 +3166,7 @@ int sqlite3Select(
         return 1;
       }
     }
-    return multiSelect(pParse, p, eDest, iParm, aff);
+    return multiSelect(pParse, p, pDest, aff);
   }
 #endif
 
@@ -3161,14 +3191,14 @@ int sqlite3Select(
   ** only a single column may be output.
   */
 #ifndef SQLITE_OMIT_SUBQUERY
-  if( checkForMultiColumnSelectError(pParse, eDest, pEList->nExpr) ){
+  if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){
     goto select_end;
   }
 #endif
 
   /* ORDER BY is ignored for some destinations.
   */
-  if( IgnorableOrderby(eDest) ){
+  if( IgnorableOrderby(pDest) ){
     pOrderBy = 0;
   }
 
@@ -3184,6 +3214,7 @@ int sqlite3Select(
     const char *zSavedAuthContext = 0;
     int needRestoreContext;
     struct SrcList_item *pItem = &pTabList->a[i];
+    SelectDest dest = {SRT_EphemTab, 0, 0};
 
     if( pItem->pSelect==0 || pItem->isPopulated ) continue;
     if( pItem->zName!=0 ){
@@ -3203,8 +3234,8 @@ int sqlite3Select(
     */
     pParse->nHeight += sqlite3SelectExprHeight(p);
 #endif
-    sqlite3Select(pParse, pItem->pSelect, SRT_EphemTab, 
-                 pItem->iCursor, p, i, &isAgg, 0);
+    dest.iParm = pItem->iCursor;
+    sqlite3Select(pParse, pItem->pSelect, &dest, p, i, &isAgg, 0);
     if( db->mallocFailed ){
       goto select_end;
     }
@@ -3216,7 +3247,7 @@ int sqlite3Select(
     }
     pTabList = p->pSrc;
     pWhere = p->pWhere;
-    if( !IgnorableOrderby(eDest) ){
+    if( !IgnorableOrderby(pDest) ){
       pOrderBy = p->pOrderBy;
     }
     pGroupBy = p->pGroupBy;
@@ -3228,7 +3259,7 @@ int sqlite3Select(
   /* Check for the special case of a min() or max() function by itself
   ** in the result set.
   */
-  if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){
+  if( simpleMinMaxQuery(pParse, p, pDest) ){
     rc = 0;
     goto select_end;
   }
@@ -3276,8 +3307,8 @@ int sqlite3Select(
 
   /* If the output is destined for a temporary table, open that table.
   */
-  if( eDest==SRT_EphemTab ){
-    sqlite3VdbeAddOp(v, OP_OpenEphemeral, iParm, pEList->nExpr);
+  if( pDest->eDest==SRT_EphemTab ){
+    sqlite3VdbeAddOp(v, OP_OpenEphemeral, pDest->iParm, pEList->nExpr);
   }
 
   /* Set the limiter.
@@ -3318,8 +3349,8 @@ int sqlite3Select(
     /* Use the standard inner loop
     */
     assert(!isDistinct);
-    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, eDest,
-                    iParm, pWInfo->iContinue, pWInfo->iBreak, aff) ){
+    if( selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, -1, pDest,
+                    pWInfo->iContinue, pWInfo->iBreak, aff) ){
        goto select_end;
     }
 
@@ -3438,7 +3469,7 @@ int sqlite3Select(
         sqlite3ExprIfFalse(pParse, pHaving, addrOutputRow+1, 1);
       }
       rc = selectInnerLoop(pParse, p, p->pEList, 0, 0, pOrderBy,
-                           distinct, eDest, iParm, 
+                           distinct, pDest,
                            addrOutputRow+1, addrSetAbort, aff);
       if( rc ){
         goto select_end;
@@ -3579,7 +3610,7 @@ int sqlite3Select(
         sqlite3ExprIfFalse(pParse, pHaving, addrEnd, 1);
       }
       selectInnerLoop(pParse, p, p->pEList, 0, 0, 0, -1, 
-                      eDest, iParm, addrEnd, addrEnd, aff);
+                      pDest, addrEnd, addrEnd, aff);
     }
     sqlite3VdbeResolveLabel(v, addrEnd);
     
@@ -3589,7 +3620,7 @@ int sqlite3Select(
   ** and send them to the callback one by one.
   */
   if( pOrderBy ){
-    generateSortTail(pParse, p, v, pEList->nExpr, eDest, iParm);
+    generateSortTail(pParse, p, v, pEList->nExpr, pDest);
   }
 
 #ifndef SQLITE_OMIT_SUBQUERY
@@ -3622,7 +3653,7 @@ select_end:
   /* Identify column names if we will be using them in a callback.  This
   ** step is skipped if the output is going to some other destination.
   */
-  if( rc==SQLITE_OK && eDest==SRT_Callback ){
+  if( rc==SQLITE_OK && pDest->eDest==SRT_Callback ){
     generateColumnNames(pParse, pTabList, pEList);
   }
 
index f6ff826981369ddbb360bbfc9d6232290d2db6ab..89b337bf582c158ebc5eeb5a4bf0bc363b9f9849 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.628 2008/01/02 00:34:37 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.629 2008/01/02 16:27:10 danielk1977 Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1333,7 +1333,7 @@ struct Select {
 #define SRT_Discard      3  /* Do not save the results anywhere */
 
 /* The ORDER BY clause is ignored for all of the above */
-#define IgnorableOrderby(X) (X<=SRT_Discard)
+#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 */
@@ -1343,6 +1343,17 @@ struct Select {
 #define SRT_Subroutine   9  /* Call a subroutine to handle results */
 #define SRT_Exists      10  /* Store 1 if the result is not empty */
 
+/*
+** A structure used to customize the behaviour of sqlite3Select(). See
+** comments above sqlite3Select() for details.
+*/
+typedef struct SelectDest SelectDest;
+struct SelectDest {
+  int eDest;        /* How to dispose of the results */
+  int iParm;        /* A parameter used by the eDest disposal method */
+  int affinity;     /* Affinity used when eDest==SRT_Set */
+};
+
 /*
 ** An SQL parser context.  A copy of this structure is passed through
 ** the parser and down into all the parser action routine in order to
@@ -1714,7 +1725,7 @@ void sqlite3SrcListDelete(SrcList*);
 void sqlite3CreateIndex(Parse*,Token*,Token*,SrcList*,ExprList*,int,Token*,
                         Token*, int, int);
 void sqlite3DropIndex(Parse*, SrcList*, int);
-int sqlite3Select(Parse*, Select*, int, int, Select*, int, int*, char *aff);
+int sqlite3Select(Parse*, Select*, SelectDest*, Select*, int, int*, char *aff);
 Select *sqlite3SelectNew(Parse*,ExprList*,SrcList*,Expr*,ExprList*,
                          Expr*,ExprList*,int,Expr*,Expr*);
 void sqlite3SelectDelete(Select*);
index 2bde7c2f0d0e38fb42999e47b05b1972bdfafd9a..196edfdfe65203c5a244fb64a6d5cd47dd17aa82 100644 (file)
@@ -685,8 +685,9 @@ static int codeTriggerProgram(
       case TK_SELECT: {
         Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect);
         if( ss ){
+          SelectDest dest = {SRT_Discard, 0, 0};
           sqlite3SelectResolve(pParse, ss, 0);
-          sqlite3Select(pParse, ss, SRT_Discard, 0, 0, 0, 0, 0);
+          sqlite3Select(pParse, ss, &dest, 0, 0, 0, 0);
           sqlite3SelectDelete(ss);
         }
         break;
index 7c6017a7efc7b9a196e8cb2119d011e16e69a605..4c10ab64303386ae3dd941daad4d8c1b5a4035c2 100644 (file)
@@ -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.147 2008/01/02 11:50:51 danielk1977 Exp $
+** $Id: update.c,v 1.148 2008/01/02 16:27:10 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -329,9 +329,11 @@ void sqlite3Update(
   */
   if( isView ){
     Select *pView;
+    SelectDest dest = {SRT_EphemTab, 0, 0};
     pView = sqlite3SelectDup(db, pTab->pSelect);
     sqlite3SelectMask(pParse, pView, old_col_mask|new_col_mask);
-    sqlite3Select(pParse, pView, SRT_EphemTab, iCur, 0, 0, 0, 0);
+    dest.iParm = iCur;
+    sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
     sqlite3SelectDelete(pView);
   }
 
@@ -597,6 +599,7 @@ static void updateVirtualTable(
   int i;                    /* Loop counter */
   int addr;                 /* Address of top of loop */
   sqlite3 *db = pParse->db; /* Database connection */
+  SelectDest dest = {SRT_Table, 0, 0};
 
   /* Construct the SELECT statement that will find the new values for
   ** all updated rows. 
@@ -627,7 +630,8 @@ static void updateVirtualTable(
 
   /* fill the ephemeral table 
   */
-  sqlite3Select(pParse, pSelect, SRT_Table, ephemTab, 0, 0, 0, 0);
+  dest.iParm = ephemTab;
+  sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
 
   /*
   ** Generate code to scan the ephemeral table and call VDelete and