diff --git a/manifest b/manifest index d7caafca7f..2ddab03949 100644 --- 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 diff --git a/manifest.uuid b/manifest.uuid index 79c505e502..28f9cf8ed0 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4c7f35da7751c61a9b61b1d95adddcc37fff3266 \ No newline at end of file +86dcdfe6d7d629618ccb3c3ff0ca09f2da2d06c7 \ No newline at end of file diff --git a/src/build.c b/src/build.c index e6759eab05..57f0f31418 100644 --- a/src/build.c +++ b/src/build.c @@ -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 @@ -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); diff --git a/src/delete.c b/src/delete.c index 4eafc1e08d..4dfa59ca27 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.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); } diff --git a/src/expr.c b/src/expr.c index c5e3a8fbd9..181e23c616 100644 --- a/src/expr.c +++ b/src/expr.c @@ -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 @@ -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; } } diff --git a/src/insert.c b/src/insert.c index 26eb7a28cb..943afcdbbf 100644 --- a/src/insert.c +++ b/src/insert.c @@ -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; } diff --git a/src/parse.y b/src/parse.y index 723e7a1bc2..19edda65b8 100644 --- a/src/parse.y +++ b/src/parse.y @@ -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); } diff --git a/src/select.c b/src/select.c index e684966ba4..34b7d3165e 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.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( nSetP2pLimit ); 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 results as keys of table 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 iParm +** SRT_Union Store results as a key in a temporary table pDest->iParm. ** -** SRT_Except Remove results from the temporary table iParm. +** SRT_Except Remove results from the temporary table pDest->iParm. ** -** SRT_Table Store results in temporary table iParm +** SRT_Table Store results in temporary table pDest->iParm ** -** 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. +** SRT_EphemTab Create an temporary table pDest->iParm and store +** the result there. The cursor is left open after +** returning. +** +** 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_Exists Store a 1 in memory cell pDest->iParm if the result +** set is not empty. +** +** SRT_Discard Throw the results away. +** +** 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); } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f6ff826981..89b337bf58 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -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*); diff --git a/src/trigger.c b/src/trigger.c index 2bde7c2f0d..196edfdfe6 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -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; diff --git a/src/update.c b/src/update.c index 7c6017a7ef..4c10ab6430 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.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