Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Materialize subqueries using a subroutine and invoke that subroutine prior to each use of the materialization. Fix for ticket [002caede898aee4] |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | tkt-002caede898 |
Files: | files | file ages | folders |
SHA1: |
4b8357ee3c4ccdbd34e0cd077efd84cc |
User & Date: | drh 2011-09-15 23:58:14.314 |
Original Comment: | Materialize subqueries using a subroutine and invoke that subroutine prior to each use of the subqueries manifestation. Fix for ticket [002caede898aee4] |
Context
2011-09-16
| ||
01:34 | Add the new OP_Once opcode. Use it to clean up and simplify various one-time initialization sections in the code, including the fix for ticket [002caede898ae]. (Closed-Leaf check-in: 7f00552b73 user: drh tags: tkt-002caede898) | |
2011-09-15
| ||
23:58 | Materialize subqueries using a subroutine and invoke that subroutine prior to each use of the materialization. Fix for ticket [002caede898aee4] (check-in: 4b8357ee3c user: drh tags: tkt-002caede898) | |
19:39 | Adding test case for ticket [002caede898] (check-in: 62dfc51a49 user: drh tags: tkt-002caede898) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
897 898 899 900 901 902 903 | struct SrcList_item *pOldItem = &p->a[i]; Table *pTab; pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; | > | | 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 | struct SrcList_item *pOldItem = &p->a[i]; Table *pTab; pNewItem->zDatabase = sqlite3DbStrDup(db, pOldItem->zDatabase); pNewItem->zName = sqlite3DbStrDup(db, pOldItem->zName); pNewItem->zAlias = sqlite3DbStrDup(db, pOldItem->zAlias); pNewItem->jointype = pOldItem->jointype; pNewItem->iCursor = pOldItem->iCursor; pNewItem->addrFillSub = pOldItem->addrFillSub; pNewItem->regReturn = pOldItem->regReturn; pNewItem->isCorrelated = pOldItem->isCorrelated; pNewItem->zIndex = sqlite3DbStrDup(db, pOldItem->zIndex); pNewItem->notIndexed = pOldItem->notIndexed; pNewItem->pIndex = pOldItem->pIndex; pTab = pNewItem->pTab = pOldItem->pTab; if( pTab ){ pTab->nRef++; |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
3797 3798 3799 3800 3801 3802 3803 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; SelectDest dest; Select *pSub = pItem->pSelect; int isAggSub; | | > > > > < > > > > > > > > > > > > > > > > > > > < < > > > > | 3797 3798 3799 3800 3801 3802 3803 3804 3805 3806 3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819 3820 3821 3822 3823 3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835 3836 3837 3838 3839 3840 3841 3842 3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 | #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) for(i=0; !p->pPrior && i<pTabList->nSrc; i++){ struct SrcList_item *pItem = &pTabList->a[i]; SelectDest dest; Select *pSub = pItem->pSelect; int isAggSub; if( pSub==0 ) continue; if( pItem->addrFillSub ){ sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, pItem->addrFillSub); continue; } /* Increment Parse.nHeight by the height of the largest expression ** tree refered to by this, the parent select. The child select ** may contain expression trees of at most ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit ** more conservative than necessary, but much easier than enforcing ** an exact limit. */ pParse->nHeight += sqlite3SelectExprHeight(p); isAggSub = (pSub->selFlags & SF_Aggregate)!=0; if( flattenSubquery(pParse, p, i, isAgg, isAggSub) ){ /* This subquery can be absorbed into its parent. */ if( isAggSub ){ isAgg = 1; p->selFlags |= SF_Aggregate; } i = -1; }else{ /* Generate a subroutine that will fill an ephemeral table with ** the content of this subquery. pItem->addrFillSub will point ** to the address of the generated subroutine. pItem->regReturn ** is a register allocated to hold the subroutine return address */ int topAddr = sqlite3VdbeAddOp0(v, OP_Goto); int regOnce = 0; assert( pItem->addrFillSub==0 ); pItem->addrFillSub = topAddr+1; pItem->regReturn = ++pParse->nMem; if( pItem->isCorrelated==0 && pParse->pTriggerTab==0 ){ /* If the subquery is no correlated and if we are not inside of ** a trigger, then we only need to compute the value of the subquery ** once. */ regOnce = ++pParse->nMem; sqlite3VdbeAddOp1(v, OP_If, regOnce); sqlite3VdbeAddOp2(v, OP_Integer, 1, regOnce); } sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; if( regOnce ) sqlite3VdbeJumpHere(v, topAddr+1); sqlite3VdbeAddOp1(v, OP_Return, pItem->regReturn); sqlite3VdbeJumpHere(v, topAddr); sqlite3VdbeAddOp2(v, OP_Gosub, pItem->regReturn, topAddr+1); } if( /*pParse->nErr ||*/ db->mallocFailed ){ goto select_end; } pParse->nHeight -= sqlite3SelectExprHeight(p); pTabList = p->pSrc; if( !IgnorableOrderby(pDest) ){ |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1848 1849 1850 1851 1852 1853 1854 | i16 nAlloc; /* Number of entries allocated in a[] below */ struct SrcList_item { char *zDatabase; /* Name of database holding this table */ char *zName; /* Name of the table */ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ | | > | 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 | i16 nAlloc; /* Number of entries allocated in a[] below */ struct SrcList_item { char *zDatabase; /* Name of database holding this table */ char *zName; /* Name of the table */ char *zAlias; /* The "B" part of a "A AS B" phrase. zName is the "A" */ Table *pTab; /* An SQL table corresponding to zName */ Select *pSelect; /* A SELECT statement used in place of a table name */ int addrFillSub; /* Address of subroutine to manifest a subquery */ int regReturn; /* Register holding return address of addrFillSub */ u8 jointype; /* Type of join between this able and the previous */ u8 notIndexed; /* True if there is a NOT INDEXED clause */ u8 isCorrelated; /* True if sub-query is correlated */ #ifndef SQLITE_OMIT_EXPLAIN u8 iSelectId; /* If pSelect!=0, the id of the sub-select in EQP */ #endif int iCursor; /* The VDBE cursor number used to access this table */ |
︙ | ︙ |