Index: src/expr.c ================================================================== --- src/expr.c +++ src/expr.c @@ -1866,10 +1866,11 @@ } sqlite3ExprDelete(pParse->db, pSel->pLimit); pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, &sqlite3IntTokens[1]); pSel->iLimit = 0; + dest.wctrlFlags |= WHERE_OPEN_ONCE; if( sqlite3Select(pParse, pSel, &dest) ){ return 0; } rReg = dest.iSDParm; ExprSetVVAProperty(pExpr, EP_NoReduce); Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -35,10 +35,11 @@ /* ** Initialize a SelectDest structure. */ void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){ pDest->eDest = (u8)eDest; + pDest->wctrlFlags = 0; pDest->iSDParm = iParm; pDest->affSdst = 0; pDest->iSdst = 0; pDest->nSdst = 0; } @@ -1925,10 +1926,11 @@ /* Execute the recursive SELECT taking the single row in Current as ** the value for the recursive-table. Store the results in the Queue. */ p->pPrior = 0; + destQueue.wctrlFlags |= WHERE_OPEN_ONCE; sqlite3Select(pParse, p, &destQueue); assert( p->pPrior==0 ); p->pPrior = pSetup; /* Keep running the loop until the Queue is empty */ @@ -4725,11 +4727,12 @@ sDistinct.eTnctType = WHERE_DISTINCT_NOOP; } if( !isAgg && pGroupBy==0 ){ /* No aggregate functions and no GROUP BY clause */ - u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0); + u16 wctrlFlags = (sDistinct.isTnct ? WHERE_WANT_DISTINCT : 0) + | pDest->wctrlFlags; /* Begin the database scan. */ pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, pOrderBy, p->pEList, wctrlFlags, 0); if( pWInfo==0 ) goto select_end; Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -2073,10 +2073,11 @@ #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ #define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */ #define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */ #define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */ #define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */ +#define WHERE_OPEN_ONCE 0x0800 /* Open on first iteration only */ /* Allowed return values from sqlite3WhereIsDistinct() */ #define WHERE_DISTINCT_NOOP 0 /* DISTINCT keyword not used */ #define WHERE_DISTINCT_UNIQUE 1 /* No duplicates */ @@ -2267,10 +2268,11 @@ ** a SELECT statement. */ struct SelectDest { u8 eDest; /* How to dispose of the results. On of SRT_* above. */ char affSdst; /* Affinity used when eDest==SRT_Set */ + u16 wctrlFlags; /* Extra flags for sqlite3WhereBegin() */ int iSDParm; /* A parameter used by the eDest disposal method */ int iSdst; /* Base register where results are written */ int nSdst; /* Number of registers allocated */ ExprList *pOrderBy; /* Key columns for SRT_Queue and SRT_DistQueue */ }; Index: src/where.c ================================================================== --- src/where.c +++ src/where.c @@ -5671,10 +5671,11 @@ notReady = ~(Bitmask)0; for(ii=0, pLevel=pWInfo->a; iia[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); pLoop = pLevel->pWLoop; @@ -5695,10 +5696,14 @@ int op = OP_OpenRead; if( pWInfo->okOnePass ){ op = OP_OpenWrite; pWInfo->aiCurOnePass[0] = pTabItem->iCursor; }; + if( wctrlFlags & WHERE_OPEN_ONCE ){ + addrOnce = sqlite3CodeOnce(pParse); + VdbeCoverage(v); + } sqlite3OpenTable(pParse, pTabItem->iCursor, iDb, pTab, op); assert( pTabItem->iCursor==pLevel->iTabCur ); testcase( !pWInfo->okOnePass && pTab->nCol==BMS-1 ); testcase( !pWInfo->okOnePass && pTab->nCol==BMS ); if( !pWInfo->okOnePass && pTab->nCol=0 ); sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb); sqlite3VdbeSetP4KeyInfo(pParse, pIx); VdbeComment((v, "%s", pIx->zName)); } + if( addrOnce ) sqlite3VdbeJumpHere(v, addrOnce); if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb); notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor); } pWInfo->iTop = sqlite3VdbeCurrentAddr(v); if( db->mallocFailed ) goto whereBeginError; @@ -5895,11 +5901,11 @@ ** (WHERE_OMIT_OPEN_CLOSE). And do not close the OP_OpenWrite cursors ** created for the ONEPASS optimization. */ if( (pTab->tabFlags & TF_Ephemeral)==0 && pTab->pSelect==0 - && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 + && (pWInfo->wctrlFlags & (WHERE_OMIT_OPEN_CLOSE|WHERE_OPEN_ONCE))==0 ){ int ws = pLoop->wsFlags; if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){ sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor); }