Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch tkt-002caede898 Excluding Merge-Ins
This is equivalent to a diff from 3fc566ac to 7f00552b
2011-09-16
| ||
01:38 | Merge the [002caede898] fix into trunk. (check-in: 95708ae2 user: drh tags: trunk) | |
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: 7f00552b 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: 4b8357ee user: drh tags: tkt-002caede898) | |
19:39 | Adding test case for ticket [002caede898] (check-in: 62dfc51a user: drh tags: tkt-002caede898) | |
00:40 | Cleanup/fix error handling when no arguments are supplied to the SQLite analyzer. (check-in: 3fc566ac user: mistachkin tags: trunk) | |
2011-09-14
| ||
18:19 | Remove 'const' from a variable that might actually be written when an OOM error occurs. Also, fix a couple MSVC/Win32 compiler warnings. (check-in: 3035dc1c user: mistachkin tags: trunk) | |
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++; |
︙ | ︙ | |||
1457 1458 1459 1460 1461 1462 1463 | ** successful here. */ assert(v); if( iCol<0 ){ int iMem = ++pParse->nMem; int iAddr; | | < | 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 | ** successful here. */ assert(v); if( iCol<0 ){ int iMem = ++pParse->nMem; int iAddr; iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem); sqlite3OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); eType = IN_INDEX_ROWID; sqlite3VdbeJumpHere(v, iAddr); }else{ Index *pIdx; /* Iterator variable */ |
︙ | ︙ | |||
1489 1490 1491 1492 1493 1494 1495 | && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) ){ int iMem = ++pParse->nMem; int iAddr; char *pKey; pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx); | | < | 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 | && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) ){ int iMem = ++pParse->nMem; int iAddr; char *pKey; pKey = (char *)sqlite3IndexKeyinfo(pParse, pIdx); iAddr = sqlite3VdbeAddOp1(v, OP_Once, iMem); sqlite3VdbeAddOp4(v, OP_OpenRead, iTab, pIdx->tnum, iDb, pKey,P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIdx->zName)); eType = IN_INDEX_INDEX; sqlite3VdbeJumpHere(v, iAddr); |
︙ | ︙ | |||
1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 | int rMayHaveNull, /* Register that records whether NULLs exist in RHS */ int isRowid /* If true, LHS of IN operator is a rowid */ ){ int testAddr = 0; /* One-time test address */ int rReg = 0; /* Register storing resulting */ Vdbe *v = sqlite3GetVdbe(pParse); if( NEVER(v==0) ) return 0; sqlite3ExprCachePush(pParse); /* This code must be run in its entirety every time it is encountered ** if any of the following is true: ** ** * The right-hand side is a correlated subquery ** * The right-hand side is an expression list containing variables ** * We are inside a trigger ** ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){ int mem = ++pParse->nMem; | > < | | 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 | int rMayHaveNull, /* Register that records whether NULLs exist in RHS */ int isRowid /* If true, LHS of IN operator is a rowid */ ){ int testAddr = 0; /* One-time test address */ int rReg = 0; /* Register storing resulting */ Vdbe *v = sqlite3GetVdbe(pParse); if( NEVER(v==0) ) return 0; assert( sqlite3VdbeCurrentAddr(v)>0 ); sqlite3ExprCachePush(pParse); /* This code must be run in its entirety every time it is encountered ** if any of the following is true: ** ** * The right-hand side is a correlated subquery ** * The right-hand side is an expression list containing variables ** * We are inside a trigger ** ** If all of the above are false, then we can run this code just once ** save the results, and reuse the same result on subsequent invocations. */ if( !ExprHasAnyProperty(pExpr, EP_VarSelect) && !pParse->pTriggerTab ){ int mem = ++pParse->nMem; testAddr = sqlite3VdbeAddOp1(v, OP_Once, mem); assert( testAddr>0 || pParse->db->mallocFailed ); } #ifndef SQLITE_OMIT_EXPLAIN if( pParse->explain==2 ){ char *zMsg = sqlite3MPrintf( pParse->db, "EXECUTE %s%s SUBQUERY %d", testAddr?"":"CORRELATED ", |
︙ | ︙ | |||
1690 1691 1692 1693 1694 1695 1696 | /* If the expression is not constant then we will need to ** disable the test that was generated above that makes sure ** this code only executes once. Because for a non-constant ** expression we need to rerun this code each time. */ if( testAddr && !sqlite3ExprIsConstant(pE2) ){ | | | 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 | /* If the expression is not constant then we will need to ** disable the test that was generated above that makes sure ** this code only executes once. Because for a non-constant ** expression we need to rerun this code each time. */ if( testAddr && !sqlite3ExprIsConstant(pE2) ){ sqlite3VdbeChangeToNoop(v, testAddr); testAddr = 0; } /* Evaluate the expression and insert it into the temp table */ if( isRowid && sqlite3ExprIsInteger(pE2, &iValToIns) ){ sqlite3VdbeAddOp3(v, OP_InsertInt, pExpr->iTable, r2, iValToIns); }else{ |
︙ | ︙ | |||
1761 1762 1763 1764 1765 1766 1767 | rReg = dest.iParm; ExprSetIrreducible(pExpr); break; } } if( testAddr ){ | | | 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 | rReg = dest.iParm; ExprSetIrreducible(pExpr); break; } } if( testAddr ){ sqlite3VdbeJumpHere(v, testAddr); } sqlite3ExprCachePop(pParse, 1); return rReg; } #endif /* SQLITE_OMIT_SUBQUERY */ |
︙ | ︙ |
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 | #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 onceAddr = 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. */ int regOnce = ++pParse->nMem; onceAddr = sqlite3VdbeAddOp1(v, OP_Once, regOnce); } sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); explainSetInteger(pItem->iSelectId, (u8)pParse->iNextSelectId); sqlite3Select(pParse, pSub, &dest); pItem->pTab->nRowEst = (unsigned)pSub->nSelectRow; if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); 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) ){ |
︙ | ︙ | |||
3963 3964 3965 3966 3967 3968 3969 | if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut; /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if( addrSortIndex>=0 && pOrderBy==0 ){ | | | 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 | if( pWInfo->nRowOut < p->nSelectRow ) p->nSelectRow = pWInfo->nRowOut; /* If sorting index that was created by a prior OP_OpenEphemeral ** instruction ended up not being needed, then change the OP_OpenEphemeral ** into an OP_Noop. */ if( addrSortIndex>=0 && pOrderBy==0 ){ sqlite3VdbeChangeToNoop(v, addrSortIndex); p->addrOpenEphm[2] = -1; } if( pWInfo->eDistinct ){ VdbeOp *pOp; /* No longer required OpenEphemeral instr. */ assert( addrDistinctIndex>=0 ); |
︙ | ︙ | |||
4246 4247 4248 4249 4250 4251 4252 | /* End of the loop */ if( groupBySort ){ sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); }else{ sqlite3WhereEnd(pWInfo); | | | 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 | /* End of the loop */ if( groupBySort ){ sqlite3VdbeAddOp2(v, OP_SorterNext, sAggInfo.sortingIdx, addrTopOfLoop); }else{ sqlite3WhereEnd(pWInfo); sqlite3VdbeChangeToNoop(v, addrSortingIdx); } /* Output the final row of result */ sqlite3VdbeAddOp2(v, OP_Gosub, regOutputRow, addrOutputRow); VdbeComment((v, "output final row")); |
︙ | ︙ |
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 */ |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 | sqlite3VdbeMemSetNull(pOut); }else{ sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1)); } break; } /* Opcode: If P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is true. The value ** is considered true if it is numeric and non-zero. If the value ** in P1 is NULL then take the jump if P3 is true. */ /* Opcode: IfNot P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is False. The value ** is considered true if it has a numeric value of zero. If the value ** in P1 is NULL then take the jump if P3 is true. */ case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ int c; pIn1 = &aMem[pOp->p1]; if( pIn1->flags & MEM_Null ){ c = pOp->p3; }else{ #ifdef SQLITE_OMIT_FLOATING_POINT c = sqlite3VdbeIntValue(pIn1)!=0; #else c = sqlite3VdbeRealValue(pIn1)!=0.0; #endif if( pOp->opcode==OP_IfNot ) c = !c; } if( c ){ pc = pOp->p2-1; } break; } /* Opcode: IsNull P1 P2 * * * ** ** Jump to P2 if the value in register P1 is NULL. | > > > > > > > > > > > > > > > > > | 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 | sqlite3VdbeMemSetNull(pOut); }else{ sqlite3VdbeMemSetInt64(pOut, ~sqlite3VdbeIntValue(pIn1)); } break; } /* Opcode: Once P1 P2 * * * ** ** Jump to P2 if the value in register P1 is a not null or zero. If ** the value is NULL or zero, fall through and change the P1 register ** to an integer 1. ** ** When P1 is not used otherwise in a program, this opcode falls through ** once and jumps on all subsequent invocations. It is the equivalent ** of "OP_If P1 P2", followed by "OP_Integer 1 P1". */ /* Opcode: If P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is true. The value ** is considered true if it is numeric and non-zero. If the value ** in P1 is NULL then take the jump if P3 is true. */ /* Opcode: IfNot P1 P2 P3 * * ** ** Jump to P2 if the value in register P1 is False. The value ** is considered true if it has a numeric value of zero. If the value ** in P1 is NULL then take the jump if P3 is true. */ case OP_Once: /* jump, in1 */ case OP_If: /* jump, in1 */ case OP_IfNot: { /* jump, in1 */ int c; pIn1 = &aMem[pOp->p1]; if( pIn1->flags & MEM_Null ){ c = pOp->p3; }else{ #ifdef SQLITE_OMIT_FLOATING_POINT c = sqlite3VdbeIntValue(pIn1)!=0; #else c = sqlite3VdbeRealValue(pIn1)!=0.0; #endif if( pOp->opcode==OP_IfNot ) c = !c; } if( c ){ pc = pOp->p2-1; }else if( pOp->opcode==OP_Once ){ assert( (pIn1->flags & (MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_Frame))==0 ); memAboutToChange(p, pIn1); pIn1->flags = MEM_Int; pIn1->u.i = 1; REGISTER_TRACE(pOp->p1, pIn1); } break; } /* Opcode: IsNull P1 P2 * * * ** ** Jump to P2 if the value in register P1 is NULL. |
︙ | ︙ |
Changes to src/vdbe.h.
︙ | ︙ | |||
176 177 178 179 180 181 182 | int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); void sqlite3VdbeChangeP5(Vdbe*, u8 P5); void sqlite3VdbeJumpHere(Vdbe*, int addr); | | | 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 | int sqlite3VdbeAddOpList(Vdbe*, int nOp, VdbeOpList const *aOp); void sqlite3VdbeAddParseSchemaOp(Vdbe*,int,char*); void sqlite3VdbeChangeP1(Vdbe*, u32 addr, int P1); void sqlite3VdbeChangeP2(Vdbe*, u32 addr, int P2); void sqlite3VdbeChangeP3(Vdbe*, u32 addr, int P3); void sqlite3VdbeChangeP5(Vdbe*, u8 P5); void sqlite3VdbeJumpHere(Vdbe*, int addr); void sqlite3VdbeChangeToNoop(Vdbe*, int addr); void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N); void sqlite3VdbeUsesBtree(Vdbe*, int); VdbeOp *sqlite3VdbeGetOp(Vdbe*, int); int sqlite3VdbeMakeLabel(Vdbe*); void sqlite3VdbeRunOnlyOnce(Vdbe*); void sqlite3VdbeDelete(Vdbe*); void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*); |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
666 667 668 669 670 671 672 | */ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){ p->pNext = pVdbe->pProgram; pVdbe->pProgram = p; } /* | | | < | | | < < | 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 | */ void sqlite3VdbeLinkSubProgram(Vdbe *pVdbe, SubProgram *p){ p->pNext = pVdbe->pProgram; pVdbe->pProgram = p; } /* ** Change the opcode at addr into OP_Noop */ void sqlite3VdbeChangeToNoop(Vdbe *p, int addr){ if( p->aOp ){ VdbeOp *pOp = &p->aOp[addr]; sqlite3 *db = p->db; freeP4(db, pOp->p4type, pOp->p4.p); memset(pOp, 0, sizeof(pOp[0])); pOp->opcode = OP_Noop; } } /* ** Change the value of the P4 operand for a specific instruction. ** This routine is useful when a large program is loaded from a ** static array using sqlite3VdbeAddOpList but we want to make a |
︙ | ︙ |
Changes to src/vdbeblob.c.
︙ | ︙ | |||
269 270 271 272 273 274 275 | sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration); /* Make sure a mutex is held on the table to be accessed */ sqlite3VdbeUsesBtree(v, iDb); /* Configure the OP_TableLock instruction */ #ifdef SQLITE_OMIT_SHARED_CACHE | | | | 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 | sqlite3VdbeChangeP3(v, 1, pTab->pSchema->iGeneration); /* Make sure a mutex is held on the table to be accessed */ sqlite3VdbeUsesBtree(v, iDb); /* Configure the OP_TableLock instruction */ #ifdef SQLITE_OMIT_SHARED_CACHE sqlite3VdbeChangeToNoop(v, 2); #else sqlite3VdbeChangeP1(v, 2, iDb); sqlite3VdbeChangeP2(v, 2, pTab->tnum); sqlite3VdbeChangeP3(v, 2, flags); sqlite3VdbeChangeP4(v, 2, pTab->zName, P4_TRANSIENT); #endif /* Remove either the OP_OpenWrite or OpenRead. Set the P2 ** parameter of the other to pTab->tnum. */ sqlite3VdbeChangeToNoop(v, 4 - flags); sqlite3VdbeChangeP2(v, 3 + flags, pTab->tnum); sqlite3VdbeChangeP3(v, 3 + flags, iDb); /* Configure the number of columns. Configure the cursor to ** think that the table has one more column than it really ** does. An OP_Column to retrieve this imaginary column will ** always return an SQL NULL. This is useful because it means |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
1990 1991 1992 1993 1994 1995 1996 | Bitmask extraCols; /* Bitmap of additional columns */ /* Generate code to skip over the creation and initialization of the ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); regIsInit = ++pParse->nMem; | | < | 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 | Bitmask extraCols; /* Bitmap of additional columns */ /* Generate code to skip over the creation and initialization of the ** transient index on 2nd and subsequent iterations of the loop. */ v = pParse->pVdbe; assert( v!=0 ); regIsInit = ++pParse->nMem; addrInit = sqlite3VdbeAddOp1(v, OP_Once, regIsInit); /* Count the number of columns that will be added to the index ** and used to match WHERE clause constraints */ nColumn = 0; pTable = pSrc->pTab; pWCEnd = &pWC->a[pWC->nTerm]; idxCols = 0; |
︙ | ︙ |
Changes to test/tkt-31338dca7e.test.
︙ | ︙ | |||
69 70 71 72 73 74 75 76 77 | CREATE INDEX t4x ON t4(x); SELECT * FROM t3, t4, t5 WHERE (v=111 AND x=w AND z!=999) OR (v=333 AND x=444) ORDER BY v, w, x, y, z; } } {111 222 222 333 888 333 444 444 555 888 333 444 444 555 999} finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | CREATE INDEX t4x ON t4(x); SELECT * FROM t3, t4, t5 WHERE (v=111 AND x=w AND z!=999) OR (v=333 AND x=444) ORDER BY v, w, x, y, z; } } {111 222 222 333 888 333 444 444 555 888 333 444 444 555 999} # Ticket [2c2de252666662f5459904fc33a9f2956cbff23c] # do_test tkt-31338-3.1 { foreach x [db eval {SELECT name FROM sqlite_master WHERE type='table'}] { db eval "DROP TABLE $x" } db eval { CREATE TABLE t1(a,b,c,d); CREATE TABLE t2(e,f); INSERT INTO t1 VALUES(1,2,3,4); INSERT INTO t2 VALUES(10,-8); CREATE INDEX t1a ON t1(a); CREATE INDEX t1b ON t1(b); CREATE TABLE t3(g); INSERT INTO t3 VALUES(4); CREATE TABLE t4(h); INSERT INTO t4 VALUES(5); SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h WHERE (a=1 AND h=4) OR (b IN ( SELECT x FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2) GROUP BY e )); } } {4 1 2 3 4 {}} do_test tkt-31338-3.2 { db eval { SELECT * FROM t3 LEFT JOIN t1 ON d=g LEFT JOIN t4 ON c=h WHERE (a=1 AND h=4) OR (b=2 AND b NOT IN ( SELECT x+1 FROM (SELECT e+f AS x, e FROM t2 ORDER BY 1 LIMIT 2) GROUP BY e )); } } {4 1 2 3 4 {}} finish_test |