Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch nextgen-query-planner Excluding Merge-Ins
This is equivalent to a diff from ed79d6f7fa to ed333d20c7
2013-07-22
| ||
12:50 | Merge the NGQP branch back into trunk. Currently 12 tests are failing in src4.test (all errors are artifacts of the test code). check-in: 4af30d63ec user: dan tags: trunk | |
2013-07-20
| ||
20:20 | Fix for optimization of DISTINCT. Leaf check-in: ed333d20c7 user: dan tags: nextgen-query-planner | |
16:32 | Update test script e_fkey.test. check-in: dd9849225b user: dan tags: nextgen-query-planner | |
2013-07-18
| ||
00:58 | Fix a typo in the "key format" documentation. check-in: 4beefed2c9 user: drh tags: trunk | |
2013-07-16
| ||
20:01 | Updates to use the next-generation-query-planner from the SQLite3 project. This branch is largely broken. check-in: bc9c9f73c5 user: dan tags: nextgen-query-planner | |
2013-07-06
| ||
23:14 | Add tests for sqlite4_num_sub with inf and nan. check-in: ed79d6f7fa user: peterreid tags: trunk | |
23:07 | Change some repetitive num tests into loops. check-in: abaf3f1abd user: peterreid tags: trunk | |
Changes to src/analyze.c.
︙ | ︙ | |||
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 | int regTabname = iMem++; /* Register containing table name */ int regIdxname = iMem++; /* Register containing index name */ int regStat1 = iMem++; /* The stat column of sqlite_stat1 */ #ifdef SQLITE4_ENABLE_STAT3 int regNumEq = regStat1; /* Number of instances. Same as regStat1 */ int regNumLt = iMem++; /* Number of keys less than regSample */ int regNumDLt = iMem++; /* Number of distinct keys less than regSample */ int regSample = iMem++; /* The next sample value */ int regAccum = iMem++; /* Register to hold Stat3Accum object */ int regLoop = iMem++; /* Loop counter */ int regCount = iMem++; /* Number of rows in the table or index */ int regTemp1 = iMem++; /* Intermediate register */ int regTemp2 = iMem++; /* Intermediate register */ int regNewSample = iMem++; int once = 1; /* One-time initialization */ | > > | 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 | int regTabname = iMem++; /* Register containing table name */ int regIdxname = iMem++; /* Register containing index name */ int regStat1 = iMem++; /* The stat column of sqlite_stat1 */ #ifdef SQLITE4_ENABLE_STAT3 int regNumEq = regStat1; /* Number of instances. Same as regStat1 */ int regNumLt = iMem++; /* Number of keys less than regSample */ int regNumDLt = iMem++; /* Number of distinct keys less than regSample */ #endif int regSample = iMem++; /* The next sample value */ #ifdef SQLITE4_ENABLE_STAT3 int regAccum = iMem++; /* Register to hold Stat3Accum object */ int regLoop = iMem++; /* Loop counter */ int regCount = iMem++; /* Number of rows in the table or index */ int regTemp1 = iMem++; /* Intermediate register */ int regTemp2 = iMem++; /* Intermediate register */ int regNewSample = iMem++; int once = 1; /* One-time initialization */ |
︙ | ︙ |
Changes to src/delete.c.
︙ | ︙ | |||
338 339 340 341 342 343 344 | ** regSet. After the scan is complete, the VM will loop through the set ** of keys in the RowSet and delete each row. Rows must be deleted after ** the scan is complete because deleting an item can change the scan ** order. */ sqlite4VdbeAddOp2(v, OP_Null, 0, regSet); VdbeComment((v, "initialize RowSet")); pWInfo = sqlite4WhereBegin( | | | 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | ** regSet. After the scan is complete, the VM will loop through the set ** of keys in the RowSet and delete each row. Rows must be deleted after ** the scan is complete because deleting an item can change the scan ** order. */ sqlite4VdbeAddOp2(v, OP_Null, 0, regSet); VdbeComment((v, "initialize RowSet")); pWInfo = sqlite4WhereBegin( pParse, pTabList, pWhere, 0, 0, WHERE_DUPLICATES_OK, 0 ); if( pWInfo==0 ) goto delete_from_cleanup; sqlite4VdbeAddOp2(v, OP_RowKey, iCur, regKey); sqlite4VdbeAddOp3(v, OP_RowSetAdd, regSet, 0, regKey); sqlite4WhereEnd(pWInfo); /* Unless this is a view, open cursors for all indexes on the table |
︙ | ︙ |
Changes to src/expr.c.
︙ | ︙ | |||
1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 | ** register = 1 ** } ** ** in order to avoid running the <test if data structure contains null> ** test more often than is necessary. */ #ifndef SQLITE4_OMIT_SUBQUERY int sqlite4FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ Index *pIdx; int eType = 0; /* Type of RHS table. IN_INDEX_* */ int iTab = pParse->nTab++; /* Cursor of the RHS table */ Vdbe *v = sqlite4GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); | > | 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 | ** register = 1 ** } ** ** in order to avoid running the <test if data structure contains null> ** test more often than is necessary. */ #ifndef SQLITE4_OMIT_SUBQUERY #if 0 int sqlite4FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ Index *pIdx; int eType = 0; /* Type of RHS table. IN_INDEX_* */ int iTab = pParse->nTab++; /* Cursor of the RHS table */ Vdbe *v = sqlite4GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); |
︙ | ︙ | |||
1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 | pParse->nQueryLoop = savedNQueryLoop; } return eType; } #endif /* ** Generate code for scalar subqueries used as a subquery expression, EXISTS, ** or IN operators. Examples: ** ** (SELECT a FROM b) -- subquery ** EXISTS (SELECT a FROM b) -- EXISTS subquery ** x IN (4,5,11) -- IN operator with list on right-hand side | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 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 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 | pParse->nQueryLoop = savedNQueryLoop; } return eType; } #endif /* ** This function is used by the implementation of the IN (...) operator. ** The pX parameter is the expression on the RHS of the IN operator, which ** might be either a list of expressions or a subquery. ** ** The job of this routine is to find or create a b-tree object that can ** be used either to test for membership in the RHS set or to iterate through ** all members of the RHS set, skipping duplicates. ** ** A cursor is opened on the b-tree object that the RHS of the IN operator ** and pX->iTable is set to the index of that cursor. ** ** The returned value of this function indicates the b-tree type, as follows: ** ** IN_INDEX_ROWID - The cursor was opened on a database table. ** IN_INDEX_INDEX_ASC - The cursor was opened on an ascending index. ** IN_INDEX_INDEX_DESC - The cursor was opened on a descending index. ** IN_INDEX_EPH - The cursor was opened on a specially created and ** populated epheremal table. ** ** An existing b-tree might be used if the RHS expression pX is a simple ** subquery such as: ** ** SELECT <column> FROM <table> ** ** If the RHS of the IN operator is a list or a more complex subquery, then ** an ephemeral table might need to be generated from the RHS and then ** pX->iTable made to point to the ephermeral table instead of an ** existing table. ** ** If the prNotFound parameter is 0, then the b-tree will be used to iterate ** through the set members, skipping any duplicates. In this case an ** epheremal table must be used unless the selected <column> is guaranteed ** to be unique - either because it is an INTEGER PRIMARY KEY or it ** has a UNIQUE constraint or UNIQUE index. ** ** If the prNotFound parameter is not 0, then the b-tree will be used ** for fast set membership tests. In this case an epheremal table must ** be used unless <column> is an INTEGER PRIMARY KEY or an index can ** be found with <column> as its left-most column. ** ** When the b-tree is being used for membership tests, the calling function ** needs to know whether or not the structure contains an SQL NULL ** value in order to correctly evaluate expressions like "X IN (Y, Z)". ** If there is any chance that the (...) might contain a NULL value at ** runtime, then a register is allocated and the register number written ** to *prNotFound. If there is no chance that the (...) contains a ** NULL value, then *prNotFound is left unchanged. ** ** If a register is allocated and its location stored in *prNotFound, then ** its initial value is NULL. If the (...) does not remain constant ** for the duration of the query (i.e. the SELECT within the (...) ** is a correlated subquery) then the value of the allocated register is ** reset to NULL each time the subquery is rerun. This allows the ** caller to use vdbe code equivalent to the following: ** ** if( register==NULL ){ ** has_null = <test if data structure contains null> ** register = 1 ** } ** ** in order to avoid running the <test if data structure contains null> ** test more often than is necessary. */ int sqlite4FindInIndex(Parse *pParse, Expr *pX, int *prNotFound){ Select *p; /* SELECT to the right of IN operator */ int eType = 0; /* Type of RHS table. IN_INDEX_* */ int iTab = pParse->nTab++; /* Cursor of the RHS table */ int mustBeUnique = (prNotFound==0); /* True if RHS must be unique */ Vdbe *v = sqlite4GetVdbe(pParse); /* Virtual machine being coded */ assert( pX->op==TK_IN ); /* Check to see if an existing table or index can be used to ** satisfy the query. This is preferable to generating a new ** ephemeral table. */ p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0); if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) && prNotFound ){ sqlite4 *db = pParse->db; /* Database connection */ Table *pTab; /* Table <table>. */ Expr *pExpr; /* Expression <column> */ int iCol; /* Index of column <column> */ int iDb; /* Database idx for pTab */ assert( p ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pEList->a[0].pExpr!=0 ); /* Because of isCandidateForInOpt(p) */ assert( p->pSrc!=0 ); /* Because of isCandidateForInOpt(p) */ pTab = p->pSrc->a[0].pTab; pExpr = p->pEList->a[0].pExpr; iCol = pExpr->iColumn; /* Code an OP_VerifyCookie for <table>. */ iDb = sqlite4SchemaToIndex(db, pTab->pSchema); sqlite4CodeVerifySchema(pParse, iDb); /* This function is only called from two places. In both cases the vdbe ** has already been allocated. So assume sqlite4GetVdbe() is always ** successful here. */ assert(v); #if 0 if( iCol<0 ){ int iAddr; iAddr = sqlite4CodeOnce(pParse); sqlite4OpenTable(pParse, iTab, iDb, pTab, OP_OpenRead); eType = IN_INDEX_ROWID; sqlite4VdbeJumpHere(v, iAddr); }else #endif { Index *pIdx; /* Iterator variable */ /* The collation sequence used by the comparison. If an index is to ** be used in place of a temp-table, it must be ordered according ** to this collation sequence. */ CollSeq *pReq = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pExpr); /* Check that the affinity that will be used to perform the ** comparison is the same as the affinity of the column. If ** it is not, it is not possible to use any index. */ int affinity_ok = sqlite4IndexAffinityOk(pX, pTab->aCol[iCol].affinity); for(pIdx=pTab->pIndex; pIdx && eType==0 && affinity_ok; pIdx=pIdx->pNext){ if( (pIdx->aiColumn[0]==iCol) && sqlite4FindCollSeq(db, pIdx->azColl[0], 0)==pReq && (!mustBeUnique || (pIdx->nColumn==1 && pIdx->onError!=OE_None)) ){ int iAddr; iAddr = sqlite4CodeOnce(pParse); sqlite4OpenIndex(pParse, iTab, iDb, pIdx, OP_OpenRead); assert( IN_INDEX_INDEX_DESC == IN_INDEX_INDEX_ASC+1 ); eType = IN_INDEX_INDEX_ASC + pIdx->aSortOrder[0]; sqlite4VdbeJumpHere(v, iAddr); if( prNotFound && !pTab->aCol[iCol].notNull ){ *prNotFound = ++pParse->nMem; sqlite4VdbeAddOp2(v, OP_Null, 0, *prNotFound); } } } } } if( eType==0 ){ /* Could not found an existing table or index to use as the RHS b-tree. ** We will have to generate an ephemeral table to do the job. */ u32 savedNQueryLoop = pParse->nQueryLoop; int rMayHaveNull = 0; eType = IN_INDEX_EPH; if( prNotFound ){ *prNotFound = rMayHaveNull = ++pParse->nMem; sqlite4VdbeAddOp2(v, OP_Null, 0, *prNotFound); }else{ testcase( pParse->nQueryLoop>0 ); pParse->nQueryLoop = 0; } sqlite4CodeSubselect(pParse, pX, rMayHaveNull, eType==IN_INDEX_ROWID); pParse->nQueryLoop = savedNQueryLoop; }else{ pX->iTable = iTab; } return eType; } #endif /* ** Generate code for scalar subqueries used as a subquery expression, EXISTS, ** or IN operators. Examples: ** ** (SELECT a FROM b) -- subquery ** EXISTS (SELECT a FROM b) -- EXISTS subquery ** x IN (4,5,11) -- IN operator with list on right-hand side |
︙ | ︙ |
Changes to src/fkey.c.
︙ | ︙ | |||
509 510 511 512 513 514 515 | sNameContext.pSrcList = pSrc; sNameContext.pParse = pParse; sqlite4ResolveExprNames(&sNameContext, pWhere); /* Create VDBE to loop through the entries in pSrc that match the WHERE ** clause. For each row found, increment the relevant constraint counter ** by nIncr. */ | | | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | sNameContext.pSrcList = pSrc; sNameContext.pParse = pParse; sqlite4ResolveExprNames(&sNameContext, pWhere); /* Create VDBE to loop through the entries in pSrc that match the WHERE ** clause. For each row found, increment the relevant constraint counter ** by nIncr. */ pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0, 0, 0, 0); if( nIncr>0 && pFKey->isDeferred==0 ){ sqlite4ParseToplevel(pParse)->mayAbort = 1; } sqlite4VdbeAddOp2(v, OP_FkCounter, pFKey->isDeferred, nIncr); if( pWInfo ){ sqlite4WhereEnd(pWInfo); } |
︙ | ︙ |
Changes to src/select.c.
︙ | ︙ | |||
3954 3955 3956 3957 3958 3959 3960 | } /* Aggregate and non-aggregate queries are handled differently */ if( !isAgg && pGroupBy==0 ){ ExprList *pDist = (isDistinct ? p->pEList : 0); /* Begin the database scan. */ | | > | > > | | | | | 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 | } /* Aggregate and non-aggregate queries are handled differently */ if( !isAgg && pGroupBy==0 ){ ExprList *pDist = (isDistinct ? p->pEList : 0); /* Begin the database scan. */ pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, pOrderBy, pDist, 0, 0); if( pWInfo==0 ) goto select_end; if( sqlite4WhereOutputRowCount(pWInfo)<p->nSelectRow ){ p->nSelectRow = sqlite4WhereOutputRowCount(pWInfo); } if( pOrderBy && sqlite4WhereIsOrdered(pWInfo) ) pOrderBy = 0; /* 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 ){ sqlite4VdbeChangeToNoop(v, addrSortIndex); p->addrOpenEphm[2] = -1; } if( sqlite4WhereIsDistinct(pWInfo) ){ VdbeOp *pOp; /* No longer required OpenEphemeral instr. */ assert( addrDistinctIndex>=0 ); pOp = sqlite4VdbeGetOp(v, addrDistinctIndex); assert( isDistinct ); assert( sqlite4WhereIsDistinct(pWInfo)==WHERE_DISTINCT_ORDERED || sqlite4WhereIsDistinct(pWInfo)==WHERE_DISTINCT_UNIQUE ); distinct = -1; if( sqlite4WhereIsDistinct(pWInfo)==WHERE_DISTINCT_ORDERED ){ int iJump; int iExpr; int iFlag = ++pParse->nMem; int iBase = pParse->nMem+1; int iBase2 = iBase + pEList->nExpr; pParse->nMem += (pEList->nExpr*2); |
︙ | ︙ | |||
4001 4002 4003 4004 4005 4006 4007 | sqlite4VdbeAddOp2(v, OP_If, iFlag, iJump-1); for(iExpr=0; iExpr<pEList->nExpr; iExpr++){ CollSeq *pColl = sqlite4ExprCollSeq(pParse, pEList->a[iExpr].pExpr); sqlite4VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr); sqlite4VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ); sqlite4VdbeChangeP5(v, SQLITE4_NULLEQ); } | | | > | 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 | sqlite4VdbeAddOp2(v, OP_If, iFlag, iJump-1); for(iExpr=0; iExpr<pEList->nExpr; iExpr++){ CollSeq *pColl = sqlite4ExprCollSeq(pParse, pEList->a[iExpr].pExpr); sqlite4VdbeAddOp3(v, OP_Ne, iBase+iExpr, iJump, iBase2+iExpr); sqlite4VdbeChangeP4(v, -1, (const char *)pColl, P4_COLLSEQ); sqlite4VdbeChangeP5(v, SQLITE4_NULLEQ); } sqlite4VdbeAddOp2(v, OP_Goto, 0, sqlite4WhereContinueLabel(pWInfo)); sqlite4VdbeAddOp2(v, OP_Integer, 0, iFlag); assert( sqlite4VdbeCurrentAddr(v)==iJump ); sqlite4VdbeAddOp3(v, OP_Move, iBase, iBase2, pEList->nExpr); }else{ pOp->opcode = OP_Noop; } } /* Use the standard inner loop. */ selectInnerLoop(pParse, p, pEList, 0, 0, pOrderBy, distinct, pDest, sqlite4WhereContinueLabel(pWInfo), sqlite4WhereBreakLabel(pWInfo) ); /* End the database scan loop. */ sqlite4WhereEnd(pWInfo); }else{ /* This is the processing for aggregate queries */ NameContext sNC; /* Name context for processing aggregate information */ |
︙ | ︙ | |||
4123 4124 4125 4126 4127 4128 4129 | /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite4VdbeAddOp2(v, OP_Gosub, regReset, addrReset); | | | | < | 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 | /* Begin a loop that will extract all source rows in GROUP BY order. ** This might involve two separate loops with an OP_Sort in between, or ** it might be a single loop that uses an index to extract information ** in the right order to begin with. */ sqlite4VdbeAddOp2(v, OP_Gosub, regReset, addrReset); pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, pGroupBy, 0, 0, 0); if( pWInfo==0 ) goto select_end; if( sqlite4WhereIsOrdered(pWInfo) ){ /* The optimizer is able to deliver rows in group by order so ** we do not have to sort. The OP_OpenEphemeral table will be ** cancelled later because we still need to use the pKeyInfo. */ groupBySort = 0; /* Evaluate the current GROUP BY terms and store in b0, b1, b2... ** (b0 is memory location iBMem+0, b1 is iBMem+1, and so forth) ** Then compare the current GROUP BY terms against the GROUP BY terms ** from the previous row currently stored in a0, a1, a2... */ |
︙ | ︙ | |||
4335 4336 4337 4338 4339 4340 4341 | } /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ resetAccumulator(pParse, &sAggInfo); | | | | | 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 | } /* This case runs if the aggregate has no GROUP BY clause. The ** processing is much simpler since there is only a single row ** of output. */ resetAccumulator(pParse, &sAggInfo); pWInfo = sqlite4WhereBegin(pParse, pTabList, pWhere, pMinMax, 0,flag,0); if( pWInfo==0 ){ sqlite4ExprListDelete(db, pDel); goto select_end; } updateAccumulator(pParse, &sAggInfo); if( sqlite4WhereIsOrdered(pWInfo) && flag ){ sqlite4VdbeAddOp2(v, OP_Goto, 0, sqlite4WhereBreakLabel(pWInfo)); VdbeComment((v, "%s() by index", (flag==WHERE_ORDERBY_MIN?"min":"max"))); } sqlite4WhereEnd(pWInfo); finalizeAggFunctions(pParse, &sAggInfo); } |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
345 346 347 348 349 350 351 352 353 354 355 356 357 358 | ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) #endif /* ** Check to see if this machine uses EBCDIC. (Yes, believe it or ** not, there are still machines out there that use EBCDIC.) */ #if 'A' == '\301' # define SQLITE4_EBCDIC 1 #else | > > > > > > | 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 | ** GCC does not define the offsetof() macro so we'll have to do it ** ourselves. */ #ifndef offsetof #define offsetof(STRUCTURE,FIELD) ((int)((char*)&((STRUCTURE*)0)->FIELD)) #endif /* ** Macros to compute minimum and maximum of two numbers. */ #define MIN(A,B) ((A)<(B)?(A):(B)) #define MAX(A,B) ((A)>(B)?(A):(B)) /* ** Check to see if this machine uses EBCDIC. (Yes, believe it or ** not, there are still machines out there that use EBCDIC.) */ #if 'A' == '\301' # define SQLITE4_EBCDIC 1 #else |
︙ | ︙ | |||
527 528 529 530 531 532 533 534 535 536 537 538 539 540 | /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) /* ** The following macros are used to suppress compiler warnings and to ** make it clear to human readers when a function parameter is deliberately ** left unused within the body of a function. This usually happens when ** a function is called via a function pointer. For example the ** implementation of an SQL aggregate step callback may not use the ** parameter indicating the number of arguments passed to the aggregate, | > > > > > | 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 | /* ** A convenience macro that returns the number of elements in ** an array. */ #define ArraySize(X) ((int)(sizeof(X)/sizeof(X[0]))) /* ** Determine if the argument is a power of two */ #define IsPowerOfTwo(X) (((X)&((X)-1))==0) /* ** The following macros are used to suppress compiler warnings and to ** make it clear to human readers when a function parameter is deliberately ** left unused within the body of a function. This usually happens when ** a function is called via a function pointer. For example the ** implementation of an SQL aggregate step callback may not use the ** parameter indicating the number of arguments passed to the aggregate, |
︙ | ︙ | |||
919 920 921 922 923 924 925 926 927 928 929 930 931 932 | #define SQLITE4_IndexCover 0x10 /* Disable index covering table */ #define SQLITE4_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */ #define SQLITE4_FactorOutConst 0x40 /* Disable factoring out constants */ #define SQLITE4_IdxRealAsInt 0x80 /* Store REAL as INT in indices */ #define SQLITE4_DistinctOpt 0x80 /* DISTINCT using indexes */ #define SQLITE4_OptMask 0xff /* Mask of all disablable opts */ /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other ** than being distinct from one another. */ #define SQLITE4_MAGIC_OPEN 0x4d06c919 /* Database is open */ #define SQLITE4_MAGIC_CLOSED 0x5f2246b4 /* Database is closed */ | > > > > > > > | 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 | #define SQLITE4_IndexCover 0x10 /* Disable index covering table */ #define SQLITE4_GroupByOrder 0x20 /* Disable GROUPBY cover of ORDERBY */ #define SQLITE4_FactorOutConst 0x40 /* Disable factoring out constants */ #define SQLITE4_IdxRealAsInt 0x80 /* Store REAL as INT in indices */ #define SQLITE4_DistinctOpt 0x80 /* DISTINCT using indexes */ #define SQLITE4_OptMask 0xff /* Mask of all disablable opts */ /* ** Some new things pulled in from SQLite3 use these macros. todo: Replace ** them with working versions. */ #define OptimizationDisabled(db, mask) 0 #define OptimizationEnabled(db, mask) 1 /* ** Possible values for the sqlite.magic field. ** The numbers are obtained at random and have no special meaning, other ** than being distinct from one another. */ #define SQLITE4_MAGIC_OPEN 0x4d06c919 /* Database is open */ #define SQLITE4_MAGIC_CLOSED 0x5f2246b4 /* Database is closed */ |
︙ | ︙ | |||
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 | char **azColl; /* Array of collation sequence names for index */ #ifdef SQLITE4_ENABLE_STAT3 int nSample; /* Number of elements in aSample[] */ tRowcnt avgEq; /* Average nEq value for key values not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif Fts5Index *pFts; /* Fts5 data (or NULL if this is not an fts index) */ }; /* Index.eIndexType must be set to one of the following. */ #define SQLITE4_INDEX_USER 0 /* Index created by CREATE INDEX statement */ #define SQLITE4_INDEX_UNIQUE 1 /* Index created by UNIQUE constraint */ #define SQLITE4_INDEX_PRIMARYKEY 2 /* Index is the tables PRIMARY KEY */ #define SQLITE4_INDEX_FTS5 3 /* Index is an FTS5 index */ | > > | 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 | char **azColl; /* Array of collation sequence names for index */ #ifdef SQLITE4_ENABLE_STAT3 int nSample; /* Number of elements in aSample[] */ tRowcnt avgEq; /* Average nEq value for key values not in aSample */ IndexSample *aSample; /* Samples of the left-most key */ #endif Fts5Index *pFts; /* Fts5 data (or NULL if this is not an fts index) */ unsigned bUnordered:1; /* Use this index for == or IN queries only */ }; /* Index.eIndexType must be set to one of the following. */ #define SQLITE4_INDEX_USER 0 /* Index created by CREATE INDEX statement */ #define SQLITE4_INDEX_UNIQUE 1 /* Index created by UNIQUE constraint */ #define SQLITE4_INDEX_PRIMARYKEY 2 /* Index is the tables PRIMARY KEY */ #define SQLITE4_INDEX_FTS5 3 /* Index is an FTS5 index */ |
︙ | ︙ | |||
1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 | union { Index *pIdx; /* Index when WHERE_INDEXED is true */ struct WhereTerm *pTerm; /* WHERE clause term for OR-search */ sqlite4_index_info *pVtabIdx; /* Virtual table index to use */ } u; }; /* ** For each nested loop in a WHERE clause implementation, the WhereInfo ** structure contains a single instance of this structure. This structure ** is intended to be private the the where.c module and should not be ** access or modified by other modules. ** ** The pIdxInfo field is used to help pick the best index on a | > | 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 | union { Index *pIdx; /* Index when WHERE_INDEXED is true */ struct WhereTerm *pTerm; /* WHERE clause term for OR-search */ sqlite4_index_info *pVtabIdx; /* Virtual table index to use */ } u; }; #if 0 /* ** For each nested loop in a WHERE clause implementation, the WhereInfo ** structure contains a single instance of this structure. This structure ** is intended to be private the the where.c module and should not be ** access or modified by other modules. ** ** The pIdxInfo field is used to help pick the best index on a |
︙ | ︙ | |||
1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 | ** we need a place to cache virtual table index information for each ** virtual table in the FROM clause and the WhereLevel structure is ** a convenient place since there is one WhereLevel for each FROM clause ** element. */ sqlite4_index_info *pIdxInfo; /* Index info for n-th source table */ }; /* ** Flags appropriate for the wctrlFlags parameter of sqlite4WhereBegin() ** and the WhereInfo.wctrlFlags member. */ #define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */ #define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */ #define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */ #define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */ #define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */ #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ #define WHERE_NO_AUTOINDEX 0x0020 /* Do not use an auto-index search */ #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ #define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */ /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed ** into the second half to give some continuity. */ struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ u16 wctrlFlags; /* Flags originally passed to sqlite4WhereBegin() */ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; SrcList *pTabList; /* List of tables in the join */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int nLevel; /* Number of nested loop */ struct WhereClause *pWC; /* Decomposition of the WHERE clause */ double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ double nRowOut; /* Estimated number of output rows */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; | > > > > > > > > > > > > > > > > > > > > > > > > > | | > > | 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 | ** we need a place to cache virtual table index information for each ** virtual table in the FROM clause and the WhereLevel structure is ** a convenient place since there is one WhereLevel for each FROM clause ** element. */ sqlite4_index_info *pIdxInfo; /* Index info for n-th source table */ }; #endif #if 0 /* ** Flags appropriate for the wctrlFlags parameter of sqlite4WhereBegin() ** and the WhereInfo.wctrlFlags member. */ #define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */ #define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */ #define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */ #define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */ #define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */ #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ #define WHERE_NO_AUTOINDEX 0x0020 /* Do not use an auto-index search */ #define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */ #define WHERE_AND_ONLY 0x0080 /* Don't use indices for OR terms */ #endif /* ** Flags appropriate for the wctrlFlags parameter of sqlite3WhereBegin() ** and the WhereInfo.wctrlFlags member. */ #define WHERE_ORDERBY_NORMAL 0x0000 /* No-op */ #define WHERE_ORDERBY_MIN 0x0001 /* ORDER BY processing for min() func */ #define WHERE_ORDERBY_MAX 0x0002 /* ORDER BY processing for max() func */ #define WHERE_ONEPASS_DESIRED 0x0004 /* Want to do one-pass UPDATE/DELETE */ #define WHERE_DUPLICATES_OK 0x0008 /* Ok to return a row more than once */ #define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */ #define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */ #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 */ /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed ** into the second half to give some continuity. */ #if 0 struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ u16 wctrlFlags; /* Flags originally passed to sqlite4WhereBegin() */ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE or DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; SrcList *pTabList; /* List of tables in the join */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int nLevel; /* Number of nested loop */ struct WhereClause *pWC; /* Decomposition of the WHERE clause */ double savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ double nRowOut; /* Estimated number of output rows */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; #endif #define WHERE_DISTINCT_NOOP 0 #define WHERE_DISTINCT_UNIQUE 1 #define WHERE_DISTINCT_ORDERED 2 #define WHERE_DISTINCT_UNORDERED 3 /* ** A NameContext defines a context in which to resolve table and column ** names. The context consists of a list of tables (the pSrcList) field and ** a list of named expression (pEList). The named expression list may ** be NULL. The pSrc corresponds to the FROM clause of a SELECT or ** to the table being operated on by INSERT, UPDATE, or DELETE. The |
︙ | ︙ | |||
2722 2723 2724 2725 2726 2727 2728 | void sqlite4OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE4_ENABLE_UPDATE_DELETE_LIMIT) \ && !defined(SQLITE4_OMIT_SUBQUERY) Expr *sqlite4LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); #endif void sqlite4DeleteFrom(Parse*, SrcList*, Expr*); void sqlite4Update(Parse*, SrcList*, ExprList*, Expr*, int); | | > > > > > > > | 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 | void sqlite4OpenTable(Parse*, int iCur, int iDb, Table*, int); #if defined(SQLITE4_ENABLE_UPDATE_DELETE_LIMIT) \ && !defined(SQLITE4_OMIT_SUBQUERY) Expr *sqlite4LimitWhere(Parse*,SrcList*,Expr*,ExprList*,Expr*,Expr*,char*); #endif void sqlite4DeleteFrom(Parse*, SrcList*, Expr*); void sqlite4Update(Parse*, SrcList*, ExprList*, Expr*, int); WhereInfo *sqlite4WhereBegin(Parse*,SrcList*,Expr*,ExprList*,ExprList*,u16,int); void sqlite4WhereEnd(WhereInfo*); u64 sqlite4WhereOutputRowCount(WhereInfo*); int sqlite4WhereIsDistinct(WhereInfo*); int sqlite4WhereIsOrdered(WhereInfo*); int sqlite4WhereContinueLabel(WhereInfo*); int sqlite4WhereBreakLabel(WhereInfo*); int sqlite4WhereOkOnePass(WhereInfo*); int sqlite4ExprCodeGetColumn(Parse*, Table*, int, int, int); void sqlite4ExprCodeGetColumnOfTable(Vdbe*, Table*, int, int, int); void sqlite4ExprCodeMove(Parse*, int, int, int); void sqlite4ExprCodeCopy(Parse*, int, int, int); void sqlite4ExprCacheStore(Parse*, int, int, int); void sqlite4ExprCachePush(Parse*); void sqlite4ExprCachePop(Parse*, int); |
︙ | ︙ | |||
3125 3126 3127 3128 3129 3130 3131 | #else #define sqlite4BeginBenignMalloc(X) #define sqlite4EndBenignMalloc(X) #endif #define IN_INDEX_ROWID 1 #define IN_INDEX_EPH 2 | | > | 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 | #else #define sqlite4BeginBenignMalloc(X) #define sqlite4EndBenignMalloc(X) #endif #define IN_INDEX_ROWID 1 #define IN_INDEX_EPH 2 #define IN_INDEX_INDEX_ASC 3 #define IN_INDEX_INDEX_DESC 4 int sqlite4FindInIndex(Parse *, Expr *, int*); Index *sqlite4FindExistingInIndex(Parse *, Expr *, int); #if SQLITE4_MAX_EXPR_DEPTH>0 void sqlite4ExprSetHeight(Parse *pParse, Expr *p); int sqlite4SelectExprHeight(Select *); |
︙ | ︙ |
Changes to src/update.c.
︙ | ︙ | |||
339 340 341 342 343 344 345 | ** ** There is one exception to the above: If static analysis of the WHERE ** clause indicates that the loop will visit at most one row, then the ** RowSet object is bypassed and the primary key of the single row (if ** any) left in register regOldKey. This is called the "one-pass" ** approach. Set okOnePass to true if it can be used in this case. */ sqlite4VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldKey); | | | | 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 | ** ** There is one exception to the above: If static analysis of the WHERE ** clause indicates that the loop will visit at most one row, then the ** RowSet object is bypassed and the primary key of the single row (if ** any) left in register regOldKey. This is called the "one-pass" ** approach. Set okOnePass to true if it can be used in this case. */ sqlite4VdbeAddOp3(v, OP_Null, 0, regRowSet, regOldKey); pWInfo = sqlite4WhereBegin(pParse, pSrc, pWhere, 0,0,WHERE_ONEPASS_DESIRED,0); if( pWInfo==0 ) goto update_cleanup; okOnePass = sqlite4WhereOkOnePass(pWInfo); sqlite4VdbeAddOp2(v, OP_RowKey, iCur+iPk, regOldKey); if( !okOnePass ){ sqlite4VdbeAddOp3(v, OP_RowSetAdd, regRowSet, 0, regOldKey); } sqlite4WhereEnd(pWInfo); /* Open every index that needs updating. If any index could potentially |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2146 2147 2148 2149 2150 2151 2152 | sqlite4VdbeDestroyDecoder(pCodec); } }else{ sqlite4VdbeMemSetNull(pDest); } UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); | | | 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 | sqlite4VdbeDestroyDecoder(pCodec); } }else{ sqlite4VdbeMemSetNull(pDest); } UPDATE_MAX_BLOBSIZE(pDest); REGISTER_TRACE(pOp->p3, pDest); assert( rc<100 ); break; } /* Opcode: Affinity P1 P2 * P4 * ** ** Apply affinities to a range of P2 registers starting with P1. ** |
︙ | ︙ |
Changes to src/vdbecodec.c.
︙ | ︙ | |||
474 475 476 477 478 479 480 | /* Write the encoded key to the output buffer. */ if( enlargeEncoderAllocation(p, pMem->n*4 + 2) ) return SQLITE4_NOMEM; p->aOut[p->nOut++] = 0x24; /* Text */ if( pColl==0 || pColl->xMkKey==0 ){ const char *z = (const char *)sqlite4ValueText(pMem, SQLITE4_UTF8); if( z ){ | | | | 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 | /* Write the encoded key to the output buffer. */ if( enlargeEncoderAllocation(p, pMem->n*4 + 2) ) return SQLITE4_NOMEM; p->aOut[p->nOut++] = 0x24; /* Text */ if( pColl==0 || pColl->xMkKey==0 ){ const char *z = (const char *)sqlite4ValueText(pMem, SQLITE4_UTF8); if( z ){ const char *zCsr = z; const char *zEnd = &z[pMem->n]; while( *zCsr && zCsr<zEnd ) zCsr++; memcpy(p->aOut+p->nOut, z, (zCsr-z)); p->nOut += (zCsr-z); } }else{ int rc; /* xMkKey() return code */ int nReq; /* Space required by xMkKey() */ |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
17 18 19 20 21 22 23 | ** indices, you might also think of this module as the "query optimizer". */ #include "sqliteInt.h" /* For VdbeCodecEncodeKey() - revisit this */ #include "vdbeInt.h" | < | | > > | | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 | ** indices, you might also think of this module as the "query optimizer". */ #include "sqliteInt.h" /* For VdbeCodecEncodeKey() - revisit this */ #include "vdbeInt.h" /* ** Trace output macros */ #if defined(SQLITE4_TEST) || defined(SQLITE4_DEBUG) /***/ int sqlite4WhereTrace = 0; #endif #if defined(SQLITE4_DEBUG) \ && (defined(SQLITE4_TEST) || defined(SQLITE4_ENABLE_WHERETRACE)) # define WHERETRACE(K,X) if(sqlite4WhereTrace&(K)) sqlite4DebugPrintf X # define WHERETRACE_ENABLED 1 #else # define WHERETRACE(K,X) #endif /* Forward reference */ typedef struct WhereClause WhereClause; typedef struct WhereMaskSet WhereMaskSet; typedef struct WhereOrInfo WhereOrInfo; typedef struct WhereAndInfo WhereAndInfo; typedef struct WhereLevel WhereLevel; typedef struct WhereLoop WhereLoop; typedef struct WherePath WherePath; typedef struct WhereTerm WhereTerm; typedef struct WhereLoopBuilder WhereLoopBuilder; typedef struct WhereScan WhereScan; /* ** Cost X is tracked as 10*log2(X) stored in a 16-bit integer. The ** maximum cost for ordinary tables is 64*(2**63) which becomes 6900. ** (Virtual tables can return a larger cost, but let's assume they do not.) ** So all costs can be stored in a 16-bit unsigned integer without risk ** of overflow. ** ** Costs are estimates, so don't go to the computational trouble to compute ** 10*log2(X) exactly. Instead, a close estimate is used. Any value of ** X<=1 is stored as 0. X=2 is 10. X=3 is 16. X=1000 is 99. etc. ** ** The tool/wherecosttest.c source file implements a command-line program ** that will convert between WhereCost to integers and do addition and ** multiplication on WhereCost values. That command-line program is a ** useful utility to have around when working with this module. */ typedef unsigned short int WhereCost; /* ** This object contains information needed to implement a single nested ** loop in WHERE clause. ** ** Contrast this object with WhereLoop. This object describes the ** implementation of the loop. WhereLoop describes the algorithm. ** This object contains a pointer to the WhereLoop algorithm as one of ** its elements. ** ** The WhereInfo object contains a single instance of this object for ** each term in the FROM clause (which is to say, for each of the ** nested loops as implemented). The order of WhereLevel objects determines ** the loop nested order, with WhereInfo.a[0] being the outer loop and ** WhereInfo.a[WhereInfo.nLevel-1] being the inner loop. */ struct WhereLevel { int iLeftJoin; /* Memory cell used to implement LEFT OUTER JOIN */ int iTabCur; /* The VDBE cursor used to access the table */ int iIdxCur; /* The VDBE cursor used to access pIdx */ int addrBrk; /* Jump here to break out of the loop */ int addrNxt; /* Jump here to start the next IN combination */ int addrCont; /* Jump here to continue with the next loop cycle */ int addrFirst; /* First instruction of interior of the loop */ u8 iFrom; /* Which entry in the FROM clause */ u8 op, p5; /* Opcode and P5 of the opcode that ends the loop */ int p1, p2; /* Operands of the opcode used to ends the loop */ union { /* Information that depends on pWLoop->wsFlags */ struct { int nIn; /* Number of entries in aInLoop[] */ struct InLoop { int iCur; /* The VDBE cursor used by this IN operator */ int addrInTop; /* Top of the IN loop */ u8 eEndLoopOp; /* IN Loop terminator. OP_Next or OP_Prev */ } *aInLoop; /* Information about each nested IN operator */ } in; /* Used when pWLoop->wsFlags&WHERE_IN_ABLE */ Index *pCovidx; /* Possible covering index for WHERE_MULTI_OR */ } u; struct WhereLoop *pWLoop; /* The selected WhereLoop object */ }; /* ** Each instance of this object represents an algorithm for evaluating one ** term of a join. Every term of the FROM clause will have at least ** one corresponding WhereLoop object (unless INDEXED BY constraints ** prevent a query solution - which is an error) and many terms of the ** FROM clause will have multiple WhereLoop objects, each describing a ** potential way of implementing that FROM-clause term, together with ** dependencies and cost estimates for using the chosen algorithm. ** ** Query planning consists of building up a collection of these WhereLoop ** objects, then computing a particular sequence of WhereLoop objects, with ** one WhereLoop object per FROM clause term, that satisfy all dependencies ** and that minimize the overall cost. */ struct WhereLoop { Bitmask prereq; /* Bitmask of other loops that must run first */ Bitmask maskSelf; /* Bitmask identifying table iTab */ #ifdef SQLITE4_DEBUG char cId; /* Symbolic ID of this loop for debugging use */ #endif u8 iTab; /* Position in FROM clause of table for this loop */ u8 iSortIdx; /* Sorting index number. 0==None */ WhereCost rSetup; /* One-time setup cost (ex: create transient index) */ WhereCost rRun; /* Cost of running each loop */ WhereCost nOut; /* Estimated number of output rows */ union { struct { /* Information for internal btree tables */ int nEq; /* Number of equality constraints */ Index *pIndex; /* Index used, or NULL */ } btree; struct { /* Information for virtual tables */ int idxNum; /* Index number */ u8 needFree; /* True if sqlite4_free(idxStr) is needed */ u8 isOrdered; /* True if satisfies ORDER BY */ u16 omitMask; /* Terms that may be omitted */ char *idxStr; /* Index identifier string */ } vtab; } u; u32 wsFlags; /* WHERE_* flags describing the plan */ u16 nLTerm; /* Number of entries in aLTerm[] */ /**** whereLoopXfer() copies fields above ***********************/ # define WHERE_LOOP_XFER_SZ offsetof(WhereLoop,nLSlot) u16 nLSlot; /* Number of slots allocated for aLTerm[] */ WhereTerm **aLTerm; /* WhereTerms used */ WhereLoop *pNextLoop; /* Next WhereLoop object in the WhereClause */ WhereTerm *aLTermSpace[4]; /* Initial aLTerm[] space */ }; /* Forward declaration of methods */ static int whereLoopResize(sqlite4*, WhereLoop*, int); /* ** Each instance of this object holds a sequence of WhereLoop objects ** that implement some or all of a query plan. ** ** Think of each WhereLoop object as a node in a graph with arcs ** showing dependences and costs for travelling between nodes. (That is ** not a completely accurate description because WhereLoop costs are a ** vector, not a scalar, and because dependences are many-to-one, not ** one-to-one as are graph nodes. But it is a useful visualization aid.) ** Then a WherePath object is a path through the graph that visits some ** or all of the WhereLoop objects once. ** ** The "solver" works by creating the N best WherePath objects of length ** 1. Then using those as a basis to compute the N best WherePath objects ** of length 2. And so forth until the length of WherePaths equals the ** number of nodes in the FROM clause. The best (lowest cost) WherePath ** at the end is the choosen query plan. */ struct WherePath { Bitmask maskLoop; /* Bitmask of all WhereLoop objects in this path */ Bitmask revLoop; /* aLoop[]s that should be reversed for ORDER BY */ WhereCost nRow; /* Estimated number of rows generated by this path */ WhereCost rCost; /* Total cost of this path */ u8 isOrdered; /* True if this path satisfies ORDER BY */ u8 isOrderedValid; /* True if the isOrdered field is valid */ WhereLoop **aLoop; /* Array of WhereLoop objects implementing this path */ }; /* ** The query generator uses an array of instances of this structure to ** help it analyze the subexpressions of the WHERE clause. Each WHERE ** clause subexpression is separated from the others by AND operators, ** usually, or sometimes subexpressions separated by OR. ** |
︙ | ︙ | |||
89 90 91 92 93 94 95 | ** bits in the Bitmask. So, in the example above, the cursor numbers ** would be mapped into integers 0 through 7. ** ** The number of terms in a join is limited by the number of bits ** in prereqRight and prereqAll. The default is 64 bits, hence SQLite ** is only able to process joins with 64 or fewer tables. */ | < | | | 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | ** bits in the Bitmask. So, in the example above, the cursor numbers ** would be mapped into integers 0 through 7. ** ** The number of terms in a join is limited by the number of bits ** in prereqRight and prereqAll. The default is 64 bits, hence SQLite ** is only able to process joins with 64 or fewer tables. */ struct WhereTerm { Expr *pExpr; /* Pointer to the subexpression that is this term */ int iParent; /* Disable pWC->a[iParent] when this term disabled */ int leftCursor; /* Cursor number of X in "X <op> <expr>" */ union { int leftColumn; /* Column number of X in "X <op> <expr>" */ WhereOrInfo *pOrInfo; /* Extra information if (eOperator & WO_OR)!=0 */ WhereAndInfo *pAndInfo; /* Extra information if (eOperator& WO_AND)!=0 */ } u; u16 eOperator; /* A WO_xx value describing <op> */ u8 wtFlags; /* TERM_xxx bit flags. See below */ u8 nChild; /* Number of children that must disable us */ WhereClause *pWC; /* The clause this term is part of */ Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */ Bitmask prereqAll; /* Bitmask of tables referenced by pExpr */ |
︙ | ︙ | |||
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | #define TERM_OR_OK 0x40 /* Used during OR-clause processing */ #ifdef SQLITE4_ENABLE_STAT3 # define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */ #else # define TERM_VNULL 0x00 /* Disabled if not using stat3 */ #endif /* ** An instance of the following structure holds all information about a ** WHERE clause. Mostly this is a container for one or more WhereTerms. ** ** Explanation of pOuter: For a WHERE clause of the form ** ** a AND ((b AND c) OR (d AND e)) AND f ** ** There are separate WhereClause objects for the whole clause and for ** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the ** subclauses points to the WhereClause object for the whole clause. */ struct WhereClause { | > > > > > > > > > > > > > > > > | < < < | 265 266 267 268 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 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 | #define TERM_OR_OK 0x40 /* Used during OR-clause processing */ #ifdef SQLITE4_ENABLE_STAT3 # define TERM_VNULL 0x80 /* Manufactured x>NULL or x<=NULL term */ #else # define TERM_VNULL 0x00 /* Disabled if not using stat3 */ #endif /* ** An instance of the WhereScan object is used as an iterator for locating ** terms in the WHERE clause that are useful to the query planner. */ struct WhereScan { WhereClause *pOrigWC; /* Original, innermost WhereClause */ WhereClause *pWC; /* WhereClause currently being scanned */ char *zCollName; /* Required collating sequence, if not NULL */ char idxaff; /* Must match this affinity, if zCollName!=NULL */ unsigned char nEquiv; /* Number of entries in aEquiv[] */ unsigned char iEquiv; /* Next unused slot in aEquiv[] */ u32 opMask; /* Acceptable operators */ int k; /* Resume scanning at this->pWC->a[this->k] */ int aEquiv[22]; /* Cursor,Column pairs for equivalence classes */ }; /* ** An instance of the following structure holds all information about a ** WHERE clause. Mostly this is a container for one or more WhereTerms. ** ** Explanation of pOuter: For a WHERE clause of the form ** ** a AND ((b AND c) OR (d AND e)) AND f ** ** There are separate WhereClause objects for the whole clause and for ** the subclauses "(b AND c)" and "(d AND e)". The pOuter field of the ** subclauses points to the WhereClause object for the whole clause. */ struct WhereClause { WhereInfo *pWInfo; /* WHERE clause processing context */ WhereClause *pOuter; /* Outer conjunction */ u8 op; /* Split operator. TK_AND or TK_OR */ int nTerm; /* Number of terms */ int nSlot; /* Number of entries in a[] */ WhereTerm *a; /* Each a[] describes a term of the WHERE cluase */ #if defined(SQLITE4_SMALL_STACK) WhereTerm aStatic[1]; /* Initial static space for a[] */ #else WhereTerm aStatic[8]; /* Initial static space for a[] */ |
︙ | ︙ | |||
174 175 176 177 178 179 180 | }; /* ** An instance of the following structure keeps track of a mapping ** between VDBE cursor numbers and bits of the bitmasks in WhereTerm. ** ** The VDBE cursor numbers are small integers contained in | | | 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 | }; /* ** An instance of the following structure keeps track of a mapping ** between VDBE cursor numbers and bits of the bitmasks in WhereTerm. ** ** The VDBE cursor numbers are small integers contained in ** SrcListItem.iCursor and Expr.iTable fields. For any given WHERE ** clause, the cursor numbers might not begin with 0 and they might ** contain gaps in the numbering sequence. But we want to make maximum ** use of the bits in our bitmasks. This structure provides a mapping ** from the sparse cursor numbers into consecutive integers beginning ** with 0. ** ** If WhereMaskSet.ix[A]==B it means that The A-th bit of a Bitmask |
︙ | ︙ | |||
201 202 203 204 205 206 207 | */ struct WhereMaskSet { int n; /* Number of assigned cursor values */ int ix[BMS]; /* Cursor assigned to each bit */ }; /* | > > > | > > > > > > | > > > > > > > > > | > > | > > > > > | > > > > > > > | > > > | > | > | | < < < | < < < < < | | | | > > > > > > | | | > > > | | > > > > > > > > > > > > > > > > > > > > > | | | | > > > | > > > > > > > | > > > > > > > | > > | > > > > | > > > > > > > > | < < | < < < | 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 | */ struct WhereMaskSet { int n; /* Number of assigned cursor values */ int ix[BMS]; /* Cursor assigned to each bit */ }; /* ** This object is a convenience wrapper holding all information needed ** to construct WhereLoop objects for a particular query. */ struct WhereLoopBuilder { WhereInfo *pWInfo; /* Information about this WHERE */ WhereClause *pWC; /* WHERE clause terms */ ExprList *pOrderBy; /* ORDER BY clause */ WhereLoop *pNew; /* Template WhereLoop */ WhereLoop *pBest; /* If non-NULL, store single best loop here */ }; /* ** The WHERE clause processing routine has two halves. The ** first part does the start of the WHERE loop and the second ** half does the tail of the WHERE loop. An instance of ** this structure is returned by the first half and passed ** into the second half to give some continuity. ** ** An instance of this object holds the complete state of the query ** planner. */ struct WhereInfo { Parse *pParse; /* Parsing and code generating context */ SrcList *pTabList; /* List of tables in the join */ ExprList *pOrderBy; /* The ORDER BY clause or NULL */ ExprList *pResultSet; /* Result set. DISTINCT operates on these */ WhereLoop *pLoops; /* List of all WhereLoop objects */ Bitmask revMask; /* Mask of ORDER BY terms that need reversing */ WhereCost nRowOut; /* Estimated number of output rows */ u16 wctrlFlags; /* Flags originally passed to sqlite4WhereBegin() */ u8 bOBSat; /* ORDER BY satisfied by indices */ u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ u8 nLevel; /* Number of nested loop */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ WhereClause sWC; /* Decomposition of the WHERE clause */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; /* ** Bitmasks for the operators on WhereTerm objects. These are all ** operators that are of interest to the query planner. An ** OR-ed combination of these values can be used when searching for ** particular WhereTerms within a WhereClause. */ #define WO_IN 0x001 #define WO_EQ 0x002 #define WO_LT (WO_EQ<<(TK_LT-TK_EQ)) #define WO_LE (WO_EQ<<(TK_LE-TK_EQ)) #define WO_GT (WO_EQ<<(TK_GT-TK_EQ)) #define WO_GE (WO_EQ<<(TK_GE-TK_EQ)) #define WO_MATCH 0x040 #define WO_ISNULL 0x080 #define WO_OR 0x100 /* Two or more OR-connected terms */ #define WO_AND 0x200 /* Two or more AND-connected terms */ #define WO_EQUIV 0x400 /* Of the form A==B, both columns */ #define WO_NOOP 0x800 /* This term does not restrict search space */ #define WO_ALL 0xfff /* Mask of all possible WO_* values */ #define WO_SINGLE 0x0ff /* Mask of all non-compound WO_* values */ /* ** These are definitions of bits in the WhereLoop.wsFlags field. ** The particular combination of bits in each WhereLoop help to ** determine the algorithm that WhereLoop represents. */ #define WHERE_COLUMN_EQ 0x00000001 /* x=EXPR */ #define WHERE_COLUMN_RANGE 0x00000002 /* x<EXPR and/or x>EXPR */ #define WHERE_COLUMN_IN 0x00000004 /* x IN (...) */ #define WHERE_COLUMN_NULL 0x00000008 /* x IS NULL */ #define WHERE_CONSTRAINT 0x0000000f /* Any of the WHERE_COLUMN_xxx values */ #define WHERE_TOP_LIMIT 0x00000010 /* x<EXPR or x<=EXPR constraint */ #define WHERE_BTM_LIMIT 0x00000020 /* x>EXPR or x>=EXPR constraint */ #define WHERE_BOTH_LIMIT 0x00000030 /* Both x>EXPR and x<EXPR */ #define WHERE_IDX_ONLY 0x00000040 /* Use index only - omit table */ #define WHERE_IPK 0x00000100 /* x is the INTEGER PRIMARY KEY */ #define WHERE_INDEXED 0x00000200 /* WhereLoop.u.btree.pIndex is valid */ #define WHERE_VIRTUALTABLE 0x00000400 /* WhereLoop.u.vtab is valid */ #define WHERE_IN_ABLE 0x00000800 /* Able to support an IN operator */ #define WHERE_ONEROW 0x00001000 /* Selects no more than one row */ #define WHERE_MULTI_OR 0x00002000 /* OR using multiple indices */ #define WHERE_AUTO_INDEX 0x00004000 /* Uses an ephemeral index */ /* Convert a WhereCost value (10 times log2(X)) into its integer value X. ** A rough approximation is used. The value returned is not exact. */ static u64 whereCostToInt(WhereCost x){ u64 n; if( x<10 ) return 1; n = x%10; x /= 10; if( n>=5 ) n -= 2; else if( n>=1 ) n -= 1; if( x>=3 ) return (n+8)<<(x-3); return (n+8)>>(3-x); } /* ** Return the estimated number of output rows from a WHERE clause */ u64 sqlite4WhereOutputRowCount(WhereInfo *pWInfo){ return whereCostToInt(pWInfo->nRowOut); } /* ** Return one of the WHERE_DISTINCT_xxxxx values to indicate how this ** WHERE clause returns outputs for DISTINCT processing. */ int sqlite4WhereIsDistinct(WhereInfo *pWInfo){ return pWInfo->eDistinct; } /* ** Return TRUE if the WHERE clause returns rows in ORDER BY order. ** Return FALSE if the output needs to be sorted. */ int sqlite4WhereIsOrdered(WhereInfo *pWInfo){ return pWInfo->bOBSat!=0; } /* ** Return the VDBE address or label to jump to in order to continue ** immediately with the next row of a WHERE clause. */ int sqlite4WhereContinueLabel(WhereInfo *pWInfo){ return pWInfo->iContinue; } /* ** Return the VDBE address or label to jump to in order to break ** out of a WHERE loop. */ int sqlite4WhereBreakLabel(WhereInfo *pWInfo){ return pWInfo->iBreak; } /* ** Return TRUE if an UPDATE or DELETE statement can operate directly on ** the rowids returned by a WHERE clause. Return FALSE if doing an ** UPDATE or DELETE might change subsequent WHERE clause results. */ int sqlite4WhereOkOnePass(WhereInfo *pWInfo){ return pWInfo->okOnePass; } /* ** Initialize a preallocated WhereClause structure. */ static void whereClauseInit( WhereClause *pWC, /* The WhereClause to be initialized */ WhereInfo *pWInfo /* The WHERE processing context */ ){ pWC->pWInfo = pWInfo; pWC->pOuter = 0; pWC->nTerm = 0; pWC->nSlot = ArraySize(pWC->aStatic); pWC->a = pWC->aStatic; } /* Forward reference */ static void whereClauseClear(WhereClause*); /* ** Deallocate all memory associated with a WhereOrInfo object. |
︙ | ︙ | |||
307 308 309 310 311 312 313 | /* ** Deallocate a WhereClause structure. The WhereClause structure ** itself is not freed. This routine is the inverse of whereClauseInit(). */ static void whereClauseClear(WhereClause *pWC){ int i; WhereTerm *a; | | > > > > > > > > > > > > > > > > > > > | 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 | /* ** Deallocate a WhereClause structure. The WhereClause structure ** itself is not freed. This routine is the inverse of whereClauseInit(). */ static void whereClauseClear(WhereClause *pWC){ int i; WhereTerm *a; sqlite4 *db = pWC->pWInfo->pParse->db; for(i=pWC->nTerm-1, a=pWC->a; i>=0; i--, a++){ if( a->wtFlags & TERM_DYNAMIC ){ sqlite4ExprDelete(db, a->pExpr); } if( a->wtFlags & TERM_ORINFO ){ whereOrInfoDelete(db, a->u.pOrInfo); }else if( a->wtFlags & TERM_ANDINFO ){ whereAndInfoDelete(db, a->u.pAndInfo); } } if( pWC->a!=pWC->aStatic ){ sqlite4DbFree(db, pWC->a); } } /* ** Skip over any TK_COLLATE and/or TK_AS operators at the root of ** an expression. */ Expr *sqlite4ExprSkipCollate(Expr *pExpr){ while( pExpr && (pExpr->op==TK_COLLATE || pExpr->op==TK_AS) ){ pExpr = pExpr->pLeft; } return pExpr; } /* ** A bit in a Bitmask */ #define MASKBIT(n) (((Bitmask)1)<<(n)) /* ** Add a single new WhereTerm entry to the WhereClause object pWC. ** The new WhereTerm object is constructed from Expr p and with wtFlags. ** The index in pWC->a[] of the new WhereTerm is returned on success. ** 0 is returned if the new WhereTerm could not be added due to a memory ** allocation error. The memory allocation failure will be recorded in |
︙ | ︙ | |||
348 349 350 351 352 353 354 | */ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ WhereTerm *pTerm; int idx; testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */ if( pWC->nTerm>=pWC->nSlot ){ WhereTerm *pOld = pWC->a; | | | | 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 | */ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){ WhereTerm *pTerm; int idx; testcase( wtFlags & TERM_VIRTUAL ); /* EV: R-00211-15100 */ if( pWC->nTerm>=pWC->nSlot ){ WhereTerm *pOld = pWC->a; sqlite4 *db = pWC->pWInfo->pParse->db; pWC->a = sqlite4DbMallocRaw(db, sizeof(pWC->a[0])*pWC->nSlot*2 ); if( pWC->a==0 ){ if( wtFlags & TERM_DYNAMIC ){ sqlite4ExprDelete(db, p); } pWC->a = pOld; return 0; } memcpy(pWC->a, pOld, sizeof(pWC->a[0])*pWC->nTerm); if( pOld!=pWC->aStatic ){ sqlite4DbFree(db, pOld); } pWC->nSlot = sqlite4DbMallocSize(db, pWC->a)/sizeof(pWC->a[0]); } pTerm = &pWC->a[idx = pWC->nTerm++]; pTerm->pExpr = sqlite4ExprSkipCollate(p); pTerm->wtFlags = wtFlags; pTerm->pWC = pWC; pTerm->iParent = -1; return idx; } /* |
︙ | ︙ | |||
388 389 390 391 392 393 394 | ** The original WHERE clause in pExpr is unaltered. All this routine ** does is make slot[] entries point to substructure within pExpr. ** ** In the previous sentence and in the diagram, "slot[]" refers to ** the WhereClause.a[] array. The slot[] array grows as needed to contain ** all terms of the WHERE clause. */ | | | | | | | < < < < < < < < < | 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 | ** The original WHERE clause in pExpr is unaltered. All this routine ** does is make slot[] entries point to substructure within pExpr. ** ** In the previous sentence and in the diagram, "slot[]" refers to ** the WhereClause.a[] array. The slot[] array grows as needed to contain ** all terms of the WHERE clause. */ static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){ pWC->op = op; if( pExpr==0 ) return; if( pExpr->op!=op ){ whereClauseInsert(pWC, pExpr, 0); }else{ whereSplit(pWC, pExpr->pLeft, op); whereSplit(pWC, pExpr->pRight, op); } } /* ** Initialize a WhereMaskSet object */ #define initMaskSet(P) (P)->n=0 /* ** Return the bitmask for the given cursor number. Return 0 if ** iCursor is not in the set. */ static Bitmask getMask(WhereMaskSet *pMaskSet, int iCursor){ int i; assert( pMaskSet->n<=(int)sizeof(Bitmask)*8 ); for(i=0; i<pMaskSet->n; i++){ if( pMaskSet->ix[i]==iCursor ){ return MASKBIT(i); } } return 0; } /* ** Create a new mask for cursor iCursor. ** ** There is one cursor per table in the FROM clause. The number of ** tables in the FROM clause is limited by a test early in the ** sqlite4WhereBegin() routine. So we know that the pMaskSet->ix[] ** array will never overflow. */ static void createMask(WhereMaskSet *pMaskSet, int iCursor){ assert( pMaskSet->n < ArraySize(pMaskSet->ix) ); pMaskSet->ix[pMaskSet->n++] = iCursor; } /* ** These routine walk (recursively) an expression tree and generates ** a bitmask indicating which tables are used in that expression ** tree. */ static Bitmask exprListTableUsage(WhereMaskSet*, ExprList*); static Bitmask exprSelectTableUsage(WhereMaskSet*, Select*); static Bitmask exprTableUsage(WhereMaskSet *pMaskSet, Expr *p){ Bitmask mask = 0; if( p==0 ) return 0; if( p->op==TK_COLUMN ){ |
︙ | ︙ | |||
498 499 500 501 502 503 504 | } return mask; } /* ** Return TRUE if the given operator is one of the operators that is ** allowed for an indexable WHERE clause term. The allowed operators are | | | 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 | } return mask; } /* ** Return TRUE if the given operator is one of the operators that is ** allowed for an indexable WHERE clause term. The allowed operators are ** "=", "<", ">", "<=", ">=", "IN", and "IS NULL" ** ** IMPLEMENTATION-OF: R-59926-26393 To be usable by an index a term must be ** of one of the following forms: column = expression column > expression ** column >= expression column < expression column <= expression ** expression = column expression > column expression >= column ** expression < column expression <= column column IN ** (expression-list) column IN (subquery) column IS NULL |
︙ | ︙ | |||
524 525 526 527 528 529 530 | */ #define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} /* ** Commute a comparison operator. Expressions of the form "X op Y" ** are converted into "Y op X". ** | > | | | < > > > > > | | < > | > | > > | 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 | */ #define SWAP(TYPE,A,B) {TYPE t=A; A=B; B=t;} /* ** Commute a comparison operator. Expressions of the form "X op Y" ** are converted into "Y op X". ** ** If left/right precedence rules come into play when determining the ** collating sequence, then COLLATE operators are adjusted to ensure ** that the collating sequence does not change. For example: ** "Y collate NOCASE op X" becomes "X op Y" because any collation sequence on ** the left hand side of a comparison overrides any collation sequence ** attached to the right. For the same reason the EP_ExpCollate flag ** is not commuted. */ static void exprCommute(Parse *pParse, Expr *pExpr){ u16 expRight = (pExpr->pRight->flags & EP_ExpCollate); u16 expLeft = (pExpr->pLeft->flags & EP_ExpCollate); assert( allowedOp(pExpr->op) && pExpr->op!=TK_IN ); if( expRight==expLeft ){ /* Either X and Y both have COLLATE operator or neither do */ if( expRight ){ /* Both X and Y have COLLATE operators. Make sure X is always ** used by clearing the EP_ExpCollate flag from Y. */ pExpr->pRight->flags &= ~EP_ExpCollate; }else if( sqlite4ExprCollSeq(pParse, pExpr->pLeft)!=0 ){ /* Neither X nor Y have COLLATE operators, but X has a non-default ** collating sequence. So add the EP_ExpCollate marker on X to cause ** it to be searched first. */ pExpr->pLeft->flags |= EP_ExpCollate; } } SWAP(Expr*,pExpr->pRight,pExpr->pLeft); if( pExpr->op>=TK_GT ){ assert( TK_LT==TK_GT+2 ); assert( TK_GE==TK_LE+2 ); assert( TK_GT>TK_EQ ); assert( TK_GT<TK_LE ); assert( pExpr->op>=TK_GT && pExpr->op<=TK_GE ); |
︙ | ︙ | |||
575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 | assert( op!=TK_EQ || c==WO_EQ ); assert( op!=TK_LT || c==WO_LT ); assert( op!=TK_LE || c==WO_LE ); assert( op!=TK_GT || c==WO_GT ); assert( op!=TK_GE || c==WO_GE ); return c; } /* ** Search for a term in the WHERE clause that is of the form "X <op> <expr>" ** where X is a reference to the iColumn of table iCur and <op> is one of ** the WO_xx operator codes specified by the op parameter. ** Return a pointer to the term. Return 0 if not found. */ static WhereTerm *findTerm( WhereClause *pWC, /* The WHERE clause to be searched */ int iCur, /* Cursor number of LHS */ int iColumn, /* Column number of LHS */ Bitmask notReady, /* RHS must not overlap with this mask */ u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ){ | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < | < | < < < < < < < < < < < < < < < < | < < | | < < | < < < | < < < < | < < < < | > > | < < < < < | 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 | assert( op!=TK_EQ || c==WO_EQ ); assert( op!=TK_LT || c==WO_LT ); assert( op!=TK_LE || c==WO_LE ); assert( op!=TK_GT || c==WO_GT ); assert( op!=TK_GE || c==WO_GE ); return c; } /* ** Advance to the next WhereTerm that matches according to the criteria ** established when the pScan object was initialized by whereScanInit(). ** Return NULL if there are no more matching WhereTerms. */ static WhereTerm *whereScanNext(WhereScan *pScan){ int iCur; /* The cursor on the LHS of the term */ int iColumn; /* The column on the LHS of the term. -1 for IPK */ Expr *pX; /* An expression being tested */ WhereClause *pWC; /* Shorthand for pScan->pWC */ WhereTerm *pTerm; /* The term being tested */ int k = pScan->k; /* Where to start scanning */ while( pScan->iEquiv<=pScan->nEquiv ){ iCur = pScan->aEquiv[pScan->iEquiv-2]; iColumn = pScan->aEquiv[pScan->iEquiv-1]; while( (pWC = pScan->pWC)!=0 ){ for(pTerm=pWC->a+k; k<pWC->nTerm; k++, pTerm++){ if( pTerm->leftCursor==iCur && pTerm->u.leftColumn==iColumn ){ if( (pTerm->eOperator & WO_EQUIV)!=0 && pScan->nEquiv<ArraySize(pScan->aEquiv) ){ int j; pX = sqlite4ExprSkipCollate(pTerm->pExpr->pRight); assert( pX->op==TK_COLUMN ); for(j=0; j<pScan->nEquiv; j+=2){ if( pScan->aEquiv[j]==pX->iTable && pScan->aEquiv[j+1]==pX->iColumn ){ break; } } if( j==pScan->nEquiv ){ pScan->aEquiv[j] = pX->iTable; pScan->aEquiv[j+1] = pX->iColumn; pScan->nEquiv += 2; } } if( (pTerm->eOperator & pScan->opMask)!=0 ){ /* Verify the affinity and collating sequence match */ if( pScan->zCollName && (pTerm->eOperator & WO_ISNULL)==0 ){ CollSeq *pColl; Parse *pParse = pWC->pWInfo->pParse; pX = pTerm->pExpr; if( !sqlite4IndexAffinityOk(pX, pScan->idxaff) ){ continue; } assert(pX->pLeft); pColl = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); if( pColl==0 ) pColl = pParse->db->pDfltColl; if( sqlite4_stricmp(pColl->zName, pScan->zCollName) ){ continue; } } if( (pTerm->eOperator & WO_EQ)!=0 && (pX = pTerm->pExpr->pRight)->op==TK_COLUMN && pX->iTable==pScan->aEquiv[0] && pX->iColumn==pScan->aEquiv[1] ){ continue; } pScan->k = k+1; return pTerm; } } } pScan->pWC = pScan->pWC->pOuter; k = 0; } pScan->pWC = pScan->pOrigWC; k = 0; pScan->iEquiv += 2; } return 0; } /* ** Return the table column number of the iIdxCol'th field in the index ** keys used by index pIdx, including any appended PRIMARY KEY fields. ** If there is no iIdxCol'th field in index pIdx, return -2. ** ** Example: ** ** CREATE TABLE t1(a, b, c, PRIMARY KEY(a, b)); ** CREATE INDEX i1 ON t1(c); ** ** Index i1 in the example above consists of three fields - the indexed ** field "c" followed by the two primary key fields. The automatic PRIMARY ** KEY index consists of two fields only. */ static int idxColumnNumber(Index *pIdx, Index *pPk, int iIdxCol){ int iRet = -2; if( iIdxCol<pIdx->nColumn ){ iRet = pIdx->aiColumn[iIdxCol]; }else if( pPk && iIdxCol<(pIdx->nColumn + pPk->nColumn) ){ iRet = pPk->aiColumn[iIdxCol - pIdx->nColumn]; } return iRet; } /* ** Return a pointer to a buffer containing the name of the collation ** sequence used with the iIdxCol'th field in index pIdx, including any ** appended PRIMARY KEY fields. */ static char *idxColumnCollation(Index *pIdx, Index *pPk, int iIdxCol){ char *zColl; assert( iIdxCol<(pIdx->nColumn + pPk->nColumn) ); if( iIdxCol<pIdx->nColumn ){ zColl = pIdx->azColl[iIdxCol]; }else if( pPk && iIdxCol<(pIdx->nColumn + pPk->nColumn) ){ zColl = pPk->azColl[iIdxCol - pIdx->nColumn]; } return zColl; } /* ** Return the sort order (SQLITE4_SO_ASC or DESC) used by the iIdxCol'th ** field in index pIdx, including any appended PRIMARY KEY fields. */ static int idxColumnSortOrder(Index *pIdx, Index *pPk, int iIdxCol){ int iRet = SQLITE4_SO_ASC; if( iIdxCol<pIdx->nColumn ){ iRet = pIdx->aSortOrder[iIdxCol]; } return iRet; } /* ** Return the total number of fields in the index pIdx, including any ** trailing primary key fields. */ static int idxColumnCount(Index *pIdx, Index *pPk){ return (pIdx->nColumn + (pIdx==pPk ? 0 : pPk->nColumn)); } /* ** Initialize a WHERE clause scanner object. Return a pointer to the ** first match. Return NULL if there are no matches. ** ** The scanner will be searching the WHERE clause pWC. It will look ** for terms of the form "X <op> <expr>" where X is column iColumn of table ** iCur. The <op> must be one of the operators described by opMask. ** ** If the search is for X and the WHERE clause contains terms of the ** form X=Y then this routine might also return terms of the form ** "Y <op> <expr>". The number of levels of transitivity is limited, ** but is enough to handle most commonly occurring SQL statements. ** ** If X is not the INTEGER PRIMARY KEY then X must be compatible with ** index pIdx. */ static WhereTerm *whereScanInit( WhereScan *pScan, /* The WhereScan object being initialized */ WhereClause *pWC, /* The WHERE clause to be scanned */ int iCur, /* Cursor to scan for */ int iColumn, /* Column to scan for */ u32 opMask, /* Operator(s) to scan for */ Index *pIdx /* Must be compatible with this index */ ){ int j; /* memset(pScan, 0, sizeof(*pScan)); */ pScan->pOrigWC = pWC; pScan->pWC = pWC; if( pIdx && iColumn>=0 ){ Index *pPk = sqlite4FindPrimaryKey(pIdx->pTable, 0); pScan->idxaff = pIdx->pTable->aCol[iColumn].affinity; for(j=0; idxColumnNumber(pIdx, pPk, j)!=iColumn; j++){ if( NEVER(j>=idxColumnCount(pIdx, pPk)) ) return 0; } pScan->zCollName = idxColumnCollation(pIdx, pPk, j); }else{ pScan->idxaff = 0; pScan->zCollName = 0; } pScan->opMask = opMask; pScan->k = 0; pScan->aEquiv[0] = iCur; pScan->aEquiv[1] = iColumn; pScan->nEquiv = 2; pScan->iEquiv = 2; return whereScanNext(pScan); } /* ** Search for a term in the WHERE clause that is of the form "X <op> <expr>" ** where X is a reference to the iColumn of table iCur and <op> is one of ** the WO_xx operator codes specified by the op parameter. ** Return a pointer to the term. Return 0 if not found. ** ** The term returned might by Y=<expr> if there is another constraint in ** the WHERE clause that specifies that X=Y. Any such constraints will be ** identified by the WO_EQUIV bit in the pTerm->eOperator field. The ** aEquiv[] array holds X and all its equivalents, with each SQL variable ** taking up two slots in aEquiv[]. The first slot is for the cursor number ** and the second is for the column number. There are 22 slots in aEquiv[] ** so that means we can look for X plus up to 10 other equivalent values. ** Hence a search for X will return <expr> if X=A1 and A1=A2 and A2=A3 ** and ... and A9=A10 and A10=<expr>. ** ** If there are multiple terms in the WHERE clause of the form "X <op> <expr>" ** then try for the one with no dependencies on <expr> - in other words where ** <expr> is a constant expression of some kind. Only return entries of ** the form "X <op> Y" where Y is a column in another table if no terms of ** the form "X <op> <const-expr>" exist. If no terms with a constant RHS ** exist, try to return a term that does not use WO_EQUIV. */ static WhereTerm *findTerm( WhereClause *pWC, /* The WHERE clause to be searched */ int iCur, /* Cursor number of LHS */ int iColumn, /* Column number of LHS */ Bitmask notReady, /* RHS must not overlap with this mask */ u32 op, /* Mask of WO_xx values describing operator */ Index *pIdx /* Must be compatible with this index, if not NULL */ ){ WhereTerm *pResult = 0; WhereTerm *p; WhereScan scan; p = whereScanInit(&scan, pWC, iCur, iColumn, op, pIdx); while( p ){ if( (p->prereqRight & notReady)==0 ){ if( p->prereqRight==0 && (p->eOperator&WO_EQ)!=0 ){ return p; } if( pResult==0 ) pResult = p; } p = whereScanNext(&scan); } return pResult; } /* Forward reference */ static void exprAnalyze(SrcList*, WhereClause*, int); /* ** Call exprAnalyze on all terms in a WHERE clause. */ static void exprAnalyzeAll( SrcList *pTabList, /* the FROM clause */ WhereClause *pWC /* the WHERE clause to be analyzed */ ){ int i; for(i=pWC->nTerm-1; i>=0; i--){ |
︙ | ︙ | |||
693 694 695 696 697 698 699 | return 0; } #ifdef SQLITE4_EBCDIC if( *pnoCase ) return 0; #endif pList = pExpr->x.pList; pLeft = pList->a[1].pExpr; | > | > > | | 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 | return 0; } #ifdef SQLITE4_EBCDIC if( *pnoCase ) return 0; #endif pList = pExpr->x.pList; pLeft = pList->a[1].pExpr; if( pLeft->op!=TK_COLUMN || sqlite4ExprAffinity(pLeft)!=SQLITE4_AFF_TEXT || IsVirtual(pLeft->pTab) ){ /* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must ** be the name of an indexed column with TEXT affinity. */ return 0; } assert( pLeft->iColumn!=(-1) ); /* Because IPK never has AFF_TEXT */ pRight = pList->a[0].pExpr; op = pRight->op; if( op==TK_REGISTER ){ op = pRight->op2; } if( op==TK_VARIABLE ){ Vdbe *pReprepare = pParse->pReprepare; int iCol = pRight->iColumn; pVal = sqlite4VdbeGetValue(pReprepare, iCol, SQLITE4_AFF_NONE); if( pVal && sqlite4_value_type(pVal)==SQLITE4_TEXT ){ z = (char *)sqlite4_value_text(pVal, 0); } sqlite4VdbeSetVarmask(pParse->pVdbe, iCol); assert( pRight->op==TK_VARIABLE || pRight->op==TK_REGISTER ); }else if( op==TK_STRING ){ z = pRight->u.zToken; } if( z ){ |
︙ | ︙ | |||
821 822 823 824 825 826 827 | ** (B) x=expr1 OR expr2=x OR x=expr3 ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) ** ** CASE 1: ** | | | 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 | ** (B) x=expr1 OR expr2=x OR x=expr3 ** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15) ** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*') ** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6) ** ** CASE 1: ** ** If all subterms are of the form T.C=expr for some single column of C and ** a single table T (as shown in example B above) then create a new virtual ** term that is an equivalent IN expression. In other words, if the term ** being analyzed is: ** ** x = expr1 OR expr2 = x OR x = expr3 ** ** then create a new virtual term like this: |
︙ | ︙ | |||
876 877 878 879 880 881 882 | ** zero. This term is not useful for search. */ static void exprAnalyzeOrTerm( SrcList *pSrc, /* the FROM clause */ WhereClause *pWC, /* the complete WHERE clause */ int idxTerm /* Index of the OR-term to be analyzed */ ){ | > | < | | < | | | | | | 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 | ** zero. This term is not useful for search. */ static void exprAnalyzeOrTerm( SrcList *pSrc, /* the FROM clause */ WhereClause *pWC, /* the complete WHERE clause */ int idxTerm /* Index of the OR-term to be analyzed */ ){ WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ Parse *pParse = pWInfo->pParse; /* Parser context */ sqlite4 *db = pParse->db; /* Database connection */ WhereTerm *pTerm = &pWC->a[idxTerm]; /* The term to be analyzed */ Expr *pExpr = pTerm->pExpr; /* The expression of the term */ int i; /* Loop counters */ WhereClause *pOrWc; /* Breakup of pTerm into subterms */ WhereTerm *pOrTerm; /* A Sub-term within the pOrWc */ WhereOrInfo *pOrInfo; /* Additional information associated with pTerm */ Bitmask chngToIN; /* Tables that might satisfy case 1 */ Bitmask indexable; /* Tables that are indexable, satisfying case 2 */ /* ** Break the OR clause into its separate subterms. The subterms are ** stored in a WhereClause structure containing within the WhereOrInfo ** object that is attached to the original OR clause term. */ assert( (pTerm->wtFlags & (TERM_DYNAMIC|TERM_ORINFO|TERM_ANDINFO))==0 ); assert( pExpr->op==TK_OR ); pTerm->u.pOrInfo = pOrInfo = sqlite4DbMallocZero(db, sizeof(*pOrInfo)); if( pOrInfo==0 ) return; pTerm->wtFlags |= TERM_ORINFO; pOrWc = &pOrInfo->wc; whereClauseInit(pOrWc, pWInfo); whereSplit(pOrWc, pExpr, TK_OR); exprAnalyzeAll(pSrc, pOrWc); if( db->mallocFailed ) return; assert( pOrWc->nTerm>=2 ); /* ** Compute the set of tables that might satisfy cases 1 or 2. */ indexable = ~(Bitmask)0; chngToIN = ~(Bitmask)0; for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0 && indexable; i--, pOrTerm++){ if( (pOrTerm->eOperator & WO_SINGLE)==0 ){ WhereAndInfo *pAndInfo; assert( (pOrTerm->wtFlags & (TERM_ANDINFO|TERM_ORINFO))==0 ); chngToIN = 0; pAndInfo = sqlite4DbMallocRaw(db, sizeof(*pAndInfo)); if( pAndInfo ){ WhereClause *pAndWC; WhereTerm *pAndTerm; int j; Bitmask b = 0; pOrTerm->u.pAndInfo = pAndInfo; pOrTerm->wtFlags |= TERM_ANDINFO; pOrTerm->eOperator = WO_AND; pAndWC = &pAndInfo->wc; whereClauseInit(pAndWC, pWC->pWInfo); whereSplit(pAndWC, pOrTerm->pExpr, TK_AND); exprAnalyzeAll(pSrc, pAndWC); pAndWC->pOuter = pWC; testcase( db->mallocFailed ); if( !db->mallocFailed ){ for(j=0, pAndTerm=pAndWC->a; j<pAndWC->nTerm; j++, pAndTerm++){ assert( pAndTerm->pExpr ); if( allowedOp(pAndTerm->pExpr->op) ){ b |= getMask(&pWInfo->sMaskSet, pAndTerm->leftCursor); } } } indexable &= b; } }else if( pOrTerm->wtFlags & TERM_COPIED ){ /* Skip this term for now. We revisit it when we process the ** corresponding TERM_VIRTUAL term */ }else{ Bitmask b; b = getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor); if( pOrTerm->wtFlags & TERM_VIRTUAL ){ WhereTerm *pOther = &pOrWc->a[pOrTerm->iParent]; b |= getMask(&pWInfo->sMaskSet, pOther->leftCursor); } indexable &= b; if( (pOrTerm->eOperator & WO_EQ)==0 ){ chngToIN = 0; }else{ chngToIN &= b; } } } |
︙ | ︙ | |||
1003 1004 1005 1006 1007 1008 1009 | ** will be recorded in iCursor and iColumn. There might not be any ** such table and column. Set okToChngToIN if an appropriate table ** and column is found but leave okToChngToIN false if not found. */ for(j=0; j<2 && !okToChngToIN; j++){ pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ | | | | | | | 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 | ** will be recorded in iCursor and iColumn. There might not be any ** such table and column. Set okToChngToIN if an appropriate table ** and column is found but leave okToChngToIN false if not found. */ for(j=0; j<2 && !okToChngToIN; j++){ pOrTerm = pOrWc->a; for(i=pOrWc->nTerm-1; i>=0; i--, pOrTerm++){ assert( pOrTerm->eOperator & WO_EQ ); pOrTerm->wtFlags &= ~TERM_OR_OK; if( pOrTerm->leftCursor==iCursor ){ /* This is the 2-bit case and we are on the second iteration and ** current term is from the first iteration. So skip this term. */ assert( j==1 ); continue; } if( (chngToIN & getMask(&pWInfo->sMaskSet, pOrTerm->leftCursor))==0 ){ /* This term must be of the form t1.a==t2.b where t2 is in the ** chngToIN set but t1 is not. This term will be either preceeded ** or follwed by an inverted copy (t2.b==t1.a). Skip this term ** and use its inversion. */ testcase( pOrTerm->wtFlags & TERM_COPIED ); testcase( pOrTerm->wtFlags & TERM_VIRTUAL ); assert( pOrTerm->wtFlags & (TERM_COPIED|TERM_VIRTUAL) ); continue; } iColumn = pOrTerm->u.leftColumn; iCursor = pOrTerm->leftCursor; break; } if( i<0 ){ /* No candidate table+column was found. This can only occur ** on the second iteration */ assert( j==1 ); assert( IsPowerOfTwo(chngToIN) ); assert( chngToIN==getMask(&pWInfo->sMaskSet, iCursor) ); break; } testcase( j==1 ); /* We have found a candidate table and column. Check to see if that ** table and column is common to every term in the OR clause */ okToChngToIN = 1; for(; i>=0 && okToChngToIN; i--, pOrTerm++){ assert( pOrTerm->eOperator & WO_EQ ); if( pOrTerm->leftCursor!=iCursor ){ pOrTerm->wtFlags &= ~TERM_OR_OK; }else if( pOrTerm->u.leftColumn!=iColumn ){ okToChngToIN = 0; }else{ int affLeft, affRight; /* If the right-hand side is also a column, then the affinities |
︙ | ︙ | |||
1075 1076 1077 1078 1079 1080 1081 | Expr *pDup; /* A transient duplicate expression */ ExprList *pList = 0; /* The RHS of the IN operator */ Expr *pLeft = 0; /* The LHS of the IN operator */ Expr *pNew; /* The complete IN operator */ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; | | | | 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 | Expr *pDup; /* A transient duplicate expression */ ExprList *pList = 0; /* The RHS of the IN operator */ Expr *pLeft = 0; /* The LHS of the IN operator */ Expr *pNew; /* The complete IN operator */ for(i=pOrWc->nTerm-1, pOrTerm=pOrWc->a; i>=0; i--, pOrTerm++){ if( (pOrTerm->wtFlags & TERM_OR_OK)==0 ) continue; assert( pOrTerm->eOperator & WO_EQ ); assert( pOrTerm->leftCursor==iCursor ); assert( pOrTerm->u.leftColumn==iColumn ); pDup = sqlite4ExprDup(db, pOrTerm->pExpr->pRight, 0); pList = sqlite4ExprListAppend(pWInfo->pParse, pList, pDup); pLeft = pOrTerm->pExpr->pLeft; } assert( pLeft!=0 ); pDup = sqlite4ExprDup(db, pLeft, 0); pNew = sqlite4PExpr(pParse, TK_IN, pDup, 0, 0); if( pNew ){ int idxNew; |
︙ | ︙ | |||
1105 1106 1107 1108 1109 1110 1111 | } pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ } } } #endif /* !SQLITE4_OMIT_OR_OPTIMIZATION && !SQLITE4_OMIT_SUBQUERY */ | < | 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 | } pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */ } } } #endif /* !SQLITE4_OMIT_OR_OPTIMIZATION && !SQLITE4_OMIT_SUBQUERY */ /* ** The input to this routine is an WhereTerm structure with only the ** "pExpr" field filled in. The job of this routine is to analyze the ** subexpression and populate all the other fields of the WhereTerm ** structure. ** ** If the expression is of the form "<expr> <op> X" it gets commuted |
︙ | ︙ | |||
1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 | ** and the copy has idxParent set to the index of the original term. */ static void exprAnalyze( SrcList *pSrc, /* the FROM clause */ WhereClause *pWC, /* the WHERE clause */ int idxTerm /* Index of the term to be analyzed */ ){ WhereTerm *pTerm; /* The term to be analyzed */ WhereMaskSet *pMaskSet; /* Set of table index masks */ Expr *pExpr; /* The expression to be analyzed */ Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ Bitmask prereqAll; /* Prerequesites of pExpr */ Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ int noCase = 0; /* LIKE/GLOB distinguishes case */ int op; /* Top-level operator. pExpr->op */ | > | | > | 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 | ** and the copy has idxParent set to the index of the original term. */ static void exprAnalyze( SrcList *pSrc, /* the FROM clause */ WhereClause *pWC, /* the WHERE clause */ int idxTerm /* Index of the term to be analyzed */ ){ WhereInfo *pWInfo = pWC->pWInfo; /* WHERE clause processing context */ WhereTerm *pTerm; /* The term to be analyzed */ WhereMaskSet *pMaskSet; /* Set of table index masks */ Expr *pExpr; /* The expression to be analyzed */ Bitmask prereqLeft; /* Prerequesites of the pExpr->pLeft */ Bitmask prereqAll; /* Prerequesites of pExpr */ Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */ Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */ int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */ int noCase = 0; /* LIKE/GLOB distinguishes case */ int op; /* Top-level operator. pExpr->op */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite4 *db = pParse->db; /* Database connection */ if( db->mallocFailed ){ return; } pTerm = &pWC->a[idxTerm]; pMaskSet = &pWInfo->sMaskSet; pExpr = pTerm->pExpr; assert( pExpr->op!=TK_AS && pExpr->op!=TK_COLLATE ); prereqLeft = exprTableUsage(pMaskSet, pExpr->pLeft); op = pExpr->op; if( op==TK_IN ){ assert( pExpr->pRight==0 ); if( ExprHasProperty(pExpr, EP_xIsSelect) ){ pTerm->prereqRight = exprSelectTableUsage(pMaskSet, pExpr->x.pSelect); }else{ |
︙ | ︙ | |||
1173 1174 1175 1176 1177 1178 1179 | extraRight = x-1; /* ON clause terms may not be used with an index ** on left table of a LEFT JOIN. Ticket #3015 */ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; | | | | > | > > > > > > > > | | | 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 | extraRight = x-1; /* ON clause terms may not be used with an index ** on left table of a LEFT JOIN. Ticket #3015 */ } pTerm->prereqAll = prereqAll; pTerm->leftCursor = -1; pTerm->iParent = -1; pTerm->eOperator = 0; if( allowedOp(op) ){ Expr *pLeft = sqlite4ExprSkipCollate(pExpr->pLeft); Expr *pRight = sqlite4ExprSkipCollate(pExpr->pRight); u16 opMask = (pTerm->prereqRight & prereqLeft)==0 ? WO_ALL : WO_EQUIV; if( pLeft->op==TK_COLUMN ){ pTerm->leftCursor = pLeft->iTable; pTerm->u.leftColumn = pLeft->iColumn; pTerm->eOperator = operatorMask(op) & opMask; } if( pRight && pRight->op==TK_COLUMN ){ WhereTerm *pNew; Expr *pDup; u16 eExtraOp = 0; /* Extra bits for pNew->eOperator */ if( pTerm->leftCursor>=0 ){ int idxNew; pDup = sqlite4ExprDup(db, pExpr, 0); if( db->mallocFailed ){ sqlite4ExprDelete(db, pDup); return; } idxNew = whereClauseInsert(pWC, pDup, TERM_VIRTUAL|TERM_DYNAMIC); if( idxNew==0 ) return; pNew = &pWC->a[idxNew]; pNew->iParent = idxTerm; pTerm = &pWC->a[idxTerm]; pTerm->nChild = 1; pTerm->wtFlags |= TERM_COPIED; if( pExpr->op==TK_EQ && !ExprHasProperty(pExpr, EP_FromJoin) && OptimizationEnabled(db, SQLITE4_Transitive) ){ pTerm->eOperator |= WO_EQUIV; eExtraOp = WO_EQUIV; } }else{ pDup = pExpr; pNew = pTerm; } exprCommute(pParse, pDup); pLeft = sqlite4ExprSkipCollate(pDup->pLeft); pNew->leftCursor = pLeft->iTable; pNew->u.leftColumn = pLeft->iColumn; testcase( (prereqLeft | extraRight) != prereqLeft ); pNew->prereqRight = prereqLeft | extraRight; pNew->prereqAll = prereqAll; pNew->eOperator = (operatorMask(pDup->op) + eExtraOp) & opMask; } } #ifndef SQLITE4_OMIT_BETWEEN_OPTIMIZATION /* If a term is the BETWEEN operator, create two new virtual terms ** that define the range that the BETWEEN implements. For example: ** |
︙ | ︙ | |||
1282 1283 1284 1285 1286 1287 1288 | ){ Expr *pLeft; /* LHS of LIKE/GLOB operator */ Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ Expr *pNewExpr1; Expr *pNewExpr2; int idxNew1; int idxNew2; | | | 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 | ){ Expr *pLeft; /* LHS of LIKE/GLOB operator */ Expr *pStr2; /* Copy of pStr1 - RHS of LIKE/GLOB operator */ Expr *pNewExpr1; Expr *pNewExpr2; int idxNew1; int idxNew2; Token sCollSeqName; /* Name of collating sequence */ pLeft = pExpr->x.pList->a[1].pExpr; pStr2 = sqlite4ExprDup(db, pStr1, 0); if( !db->mallocFailed ){ u8 c, *pC; /* Last character before the first wildcard */ pC = (u8*)&pStr2->u.zToken[sqlite4Strlen30(pStr2->u.zToken)-1]; c = *pC; |
︙ | ︙ | |||
1304 1305 1306 1307 1308 1309 1310 | if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */ c = sqlite4UpperToLower[c]; } *pC = c + 1; } | | > | | | | | | | 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 | if( c=='A'-1 ) isComplete = 0; /* EV: R-64339-08207 */ c = sqlite4UpperToLower[c]; } *pC = c + 1; } sCollSeqName.z = noCase ? "NOCASE" : "BINARY"; sCollSeqName.n = 6; pNewExpr1 = sqlite4ExprDup(db, pLeft, 0); sqlite4ExprSetCollByToken(pParse, pNewExpr1, &sCollSeqName); pNewExpr1 = sqlite4PExpr(pParse, TK_GE, pNewExpr1, pStr1, 0); idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew1==0 ); exprAnalyze(pSrc, pWC, idxNew1); pNewExpr2 = sqlite4ExprDup(db, pLeft, 0); sqlite4ExprSetCollByToken(pParse, pNewExpr2, &sCollSeqName); pNewExpr2 = sqlite4PExpr(pParse, TK_LT, pNewExpr2, pStr2, 0); idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC); testcase( idxNew2==0 ); exprAnalyze(pSrc, pWC, idxNew2); pTerm = &pWC->a[idxTerm]; if( isComplete ){ pWC->a[idxNew1].iParent = idxTerm; pWC->a[idxNew2].iParent = idxTerm; |
︙ | ︙ | |||
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 | ** TERM_VNULL tag will suppress the not-null check at the beginning ** of the loop. Without the TERM_VNULL flag, the not-null check at ** the start of the loop will prevent any results from being returned. */ if( pExpr->op==TK_NOTNULL && pExpr->pLeft->op==TK_COLUMN && pExpr->pLeft->iColumn>=0 ){ Expr *pNewExpr; Expr *pLeft = pExpr->pLeft; int idxNew; WhereTerm *pNewTerm; pNewExpr = sqlite4PExpr(pParse, TK_GT, | > | 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 | ** TERM_VNULL tag will suppress the not-null check at the beginning ** of the loop. Without the TERM_VNULL flag, the not-null check at ** the start of the loop will prevent any results from being returned. */ if( pExpr->op==TK_NOTNULL && pExpr->pLeft->op==TK_COLUMN && pExpr->pLeft->iColumn>=0 && OptimizationEnabled(db, SQLITE4_Stat3) ){ Expr *pNewExpr; Expr *pLeft = pExpr->pLeft; int idxNew; WhereTerm *pNewTerm; pNewExpr = sqlite4PExpr(pParse, TK_GT, |
︙ | ︙ | |||
1411 1412 1413 1414 1415 1416 1417 | /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ pTerm->prereqRight |= extraRight; } /* | < < < < < < < < < < < < < < < < < < < | < | < < | | < | < | < < | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | < | | | | | > > > | | | | > < | < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < | < < < < | < < < | < < < < < < < < < | | < | | < | | < < < | | | | | < < | > | | | | < < < < | < < | < < < | < < < < | < < < < < < < | < < < < < < < | < | < < < < < < < < < < < < < | < < < < < | < < < < < < < < < < < < < < < < | > > | > > > | < > > | < | < < < < | | > > > | > > > | < < < | | | | | < < | < < < < < | | < < < < < < < | < < < < < | < < < < | < | < < < < | | | 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 | /* Prevent ON clause terms of a LEFT JOIN from being used to drive ** an index for tables to the left of the join. */ pTerm->prereqRight |= extraRight; } /* ** This function searches pList for a entry that matches the iCol-th column ** of index pIdx. ** ** If such an expression is found, its index in pList->a[] is returned. If ** no expression is found, -1 is returned. */ static int findIndexCol( Parse *pParse, /* Parse context */ ExprList *pList, /* Expression list to search */ int iBase, /* Cursor for table associated with pIdx */ Index *pIdx, /* Index to match column of */ int iCol /* Column of index to match */ ){ int i; const char *zColl = pIdx->azColl[iCol]; for(i=0; i<pList->nExpr; i++){ Expr *p = sqlite4ExprSkipCollate(pList->a[i].pExpr); if( p->op==TK_COLUMN && p->iColumn==pIdx->aiColumn[iCol] && p->iTable==iBase ){ CollSeq *pColl = sqlite4ExprCollSeq(pParse, pList->a[i].pExpr); if( ALWAYS(pColl) && 0==sqlite4_stricmp(pColl->zName, zColl) ){ return i; } } } return -1; } /* ** Return true if the DISTINCT expression-list passed as the third argument ** is redundant. ** ** A DISTINCT list is redundant if the database contains some subset of ** columns that are unique and non-null. */ static int isDistinctRedundant( Parse *pParse, /* Parsing context */ SrcList *pTabList, /* The FROM clause */ WhereClause *pWC, /* The WHERE clause */ ExprList *pDistinct /* The result set that needs to be DISTINCT */ ){ Table *pTab; Index *pIdx; int i; int iBase; /* If there is more than one table or sub-select in the FROM clause of ** this query, then it will not be possible to show that the DISTINCT ** clause is redundant. */ if( pTabList->nSrc!=1 ) return 0; iBase = pTabList->a[0].iCursor; pTab = pTabList->a[0].pTab; /* If any of the expressions is an IPK column on table iBase, then return ** true. Note: The (p->iTable==iBase) part of this test may be false if the ** current SELECT is a correlated sub-query. */ for(i=0; i<pDistinct->nExpr; i++){ Expr *p = sqlite4ExprSkipCollate(pDistinct->a[i].pExpr); if( p->op==TK_COLUMN && p->iTable==iBase && p->iColumn<0 ) return 1; } /* Loop through all indices on the table, checking each to see if it makes ** the DISTINCT qualifier redundant. It does so if: ** ** 1. The index is itself UNIQUE, and ** ** 2. All of the columns in the index are either part of the pDistinct ** list, or else the WHERE clause contains a term of the form "col=X", ** where X is a constant value. The collation sequences of the ** comparison and select-list expressions must match those of the index. ** ** 3. All of those index columns for which the WHERE clause does not ** contain a "col=X" term are subject to a NOT NULL constraint. */ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->onError==OE_None ) continue; for(i=0; i<pIdx->nColumn; i++){ int iCol = pIdx->aiColumn[i]; if( 0==findTerm(pWC, iBase, iCol, ~(Bitmask)0, WO_EQ, pIdx) ){ int iIdxCol = findIndexCol(pParse, pDistinct, iBase, pIdx, i); if( iIdxCol<0 || pTab->aCol[pIdx->aiColumn[i]].notNull==0 ){ break; } } } if( i==pIdx->nColumn ){ /* This index implies that the DISTINCT qualifier is redundant. */ return 1; } } return 0; } /* ** The (an approximate) sum of two WhereCosts. This computation is ** not a simple "+" operator because WhereCost is stored as a logarithmic ** value. ** */ static WhereCost whereCostAdd(WhereCost a, WhereCost b){ static const unsigned char x[] = { 10, 10, /* 0,1 */ 9, 9, /* 2,3 */ 8, 8, /* 4,5 */ 7, 7, 7, /* 6,7,8 */ 6, 6, 6, /* 9,10,11 */ 5, 5, 5, /* 12-14 */ 4, 4, 4, 4, /* 15-18 */ 3, 3, 3, 3, 3, 3, /* 19-24 */ 2, 2, 2, 2, 2, 2, 2, /* 25-31 */ }; if( a>=b ){ if( a>b+49 ) return a; if( a>b+31 ) return a+1; return a+x[a-b]; }else{ if( b>a+49 ) return b; if( b>a+31 ) return b+1; return b+x[b-a]; } } /* ** Convert an integer into a WhereCost. In other words, compute a ** good approximatation for 10*log2(x). */ static WhereCost whereCost(tRowcnt x){ static WhereCost a[] = { 0, 2, 3, 5, 6, 7, 8, 9 }; WhereCost y = 40; if( x<8 ){ if( x<2 ) return 0; while( x<8 ){ y -= 10; x <<= 1; } }else{ while( x>255 ){ y += 40; x >>= 4; } while( x>15 ){ y += 10; x >>= 1; } } return a[x&7] + y - 10; } #ifndef SQLITE4_OMIT_VIRTUALTABLE /* ** Convert a double (as received from xBestIndex of a virtual table) ** into a WhereCost. In other words, compute an approximation for ** 10*log2(x). */ static WhereCost whereCostFromDouble(double x){ u64 a; WhereCost e; assert( sizeof(x)==8 && sizeof(a)==8 ); if( x<=1 ) return 0; if( x<=2000000000 ) return whereCost((tRowcnt)x); memcpy(&a, &x, 8); e = (a>>52) - 1022; return e*10; } #endif /* SQLITE4_OMIT_VIRTUALTABLE */ /* ** Estimate the logarithm of the input value to base 2. */ static WhereCost estLog(WhereCost N){ WhereCost x = whereCost(N); return x>33 ? x - 33 : 0; } /* ** Two routines for printing the content of an sqlite4_index_info ** structure. Used for testing and debugging only. If neither ** SQLITE4_TEST or SQLITE4_DEBUG are defined, then these routines ** are no-ops. */ #if !defined(SQLITE4_OMIT_VIRTUALTABLE) && defined(WHERETRACE_ENABLED) static void TRACE_IDX_INPUTS(sqlite4_index_info *p){ int i; if( !sqlite4WhereTrace ) return; for(i=0; i<p->nConstraint; i++){ sqlite4DebugPrintf(" constraint[%d]: col=%d termid=%d op=%d usabled=%d\n", i, p->aConstraint[i].iColumn, |
︙ | ︙ | |||
1842 1843 1844 1845 1846 1847 1848 | sqlite4DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); } #else #define TRACE_IDX_INPUTS(A) #define TRACE_IDX_OUTPUTS(A) #endif | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | | | < > > > < > > | | | | > | > > > > > > > | | > > > | > > > > > > > > > > > > > > > > > > | | | | | | < | | | | > > | > > > > > > > > > > > > > > > > > > | > | | | > | < < | < | > | | | | | | < < | | | | > | | | < > | | | | > > | | | | < | 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 | sqlite4DebugPrintf(" estimatedCost=%g\n", p->estimatedCost); } #else #define TRACE_IDX_INPUTS(A) #define TRACE_IDX_OUTPUTS(A) #endif /* ** Return TRUE if the WHERE clause term pTerm is of a form where it ** could be used with an index to access pSrc, assuming an appropriate ** index existed. */ static int termCanDriveIndex( WhereTerm *pTerm, /* WHERE clause term to check */ struct SrcListItem *pSrc, /* Table we are trying to access */ Bitmask notReady /* Tables in outer loops of the join */ ){ char aff; if( pTerm->leftCursor!=pSrc->iCursor ) return 0; if( (pTerm->eOperator & WO_EQ)==0 ) return 0; if( (pTerm->prereqRight & notReady)!=0 ) return 0; if( pTerm->u.leftColumn<0 ) return 0; aff = pSrc->pTab->aCol[pTerm->u.leftColumn].affinity; if( !sqlite4IndexAffinityOk(pTerm->pExpr, aff) ) return 0; return 1; } #ifndef SQLITE4_OMIT_AUTOMATIC_INDEX /* ** Generate code to construct the Index object for an automatic index ** and to set up the WhereLevel object pLevel so that the code generator ** makes use of the automatic index. */ static void constructAutomaticIndex( Parse *pParse, /* The parsing context */ WhereClause *pWC, /* The WHERE clause */ struct SrcListItem *pSrc, /* The FROM clause term to get the next index */ Bitmask notReady, /* Mask of cursors that are not available */ WhereLevel *pLevel /* Write new index here */ ){ int nColumn; /* Number of columns in the constructed index */ WhereTerm *pTerm; /* A single term of the WHERE clause */ WhereTerm *pWCEnd; /* End of pWC->a[] */ int nByte; /* Byte of memory needed for pIdx */ Index *pIdx; /* Object describing the transient index */ Vdbe *v; /* Prepared statement under construction */ int addrInit; /* Address of the initialization bypass jump */ Table *pTable; /* The table being indexed */ KeyInfo *pKeyinfo; /* Key information for the index */ int addrTop; /* Top of the index fill loop */ int regRecord; /* Register holding an index record */ int n; /* Column counter */ int i; /* Loop counter */ int mxBitCol; /* Maximum column in pSrc->colUsed */ CollSeq *pColl; /* Collating sequence to on a column */ WhereLoop *pLoop; /* The Loop object */ Bitmask idxCols; /* Bitmap of columns used for indexing */ Bitmask extraCols; /* Bitmap of additional columns */ u8 sentWarning = 0; /* True if a warnning has been issued */ /* 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 ); addrInit = sqlite4CodeOnce(pParse); /* 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]; pLoop = pLevel->pWLoop; idxCols = 0; for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( termCanDriveIndex(pTerm, pSrc, notReady) ){ int iCol = pTerm->u.leftColumn; Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); testcase( iCol==BMS ); testcase( iCol==BMS-1 ); if( !sentWarning ){ sqlite4_log(SQLITE4_WARNING_AUTOINDEX, "automatic index on %s(%s)", pTable->zName, pTable->aCol[iCol].zName); sentWarning = 1; } if( (idxCols & cMask)==0 ){ if( whereLoopResize(pParse->db, pLoop, nColumn+1) ) return; pLoop->aLTerm[nColumn++] = pTerm; idxCols |= cMask; } } } assert( nColumn>0 ); pLoop->u.btree.nEq = pLoop->nLTerm = nColumn; pLoop->wsFlags = WHERE_COLUMN_EQ | WHERE_IDX_ONLY | WHERE_INDEXED | WHERE_AUTO_INDEX; /* Count the number of additional columns needed to create a ** covering index. A "covering index" is an index that contains all ** columns that are needed by the query. With a covering index, the ** original table never needs to be accessed. Automatic indices must ** be a covering index because the index will not be updated if the ** original table changes and the index and table cannot both be used ** if they go out of sync. */ extraCols = pSrc->colUsed & (~idxCols | MASKBIT(BMS-1)); mxBitCol = (pTable->nCol >= BMS-1) ? BMS-1 : pTable->nCol; testcase( pTable->nCol==BMS-1 ); testcase( pTable->nCol==BMS-2 ); for(i=0; i<mxBitCol; i++){ if( extraCols & MASKBIT(i) ) nColumn++; } if( pSrc->colUsed & MASKBIT(BMS-1) ){ nColumn += pTable->nCol - BMS + 1; } pLoop->wsFlags |= WHERE_COLUMN_EQ | WHERE_IDX_ONLY; /* Construct the Index object to describe this index */ nByte = sizeof(Index); nByte += nColumn*sizeof(int); /* Index.aiColumn */ nByte += nColumn*sizeof(char*); /* Index.azColl */ nByte += nColumn; /* Index.aSortOrder */ pIdx = sqlite4DbMallocZero(pParse->db, nByte); if( pIdx==0 ) return; pLoop->u.btree.pIndex = pIdx; pIdx->azColl = (char**)&pIdx[1]; pIdx->aiColumn = (int*)&pIdx->azColl[nColumn]; pIdx->aSortOrder = (u8*)&pIdx->aiColumn[nColumn]; pIdx->zName = "auto-index"; pIdx->nColumn = nColumn; pIdx->pTable = pTable; n = 0; idxCols = 0; for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){ if( termCanDriveIndex(pTerm, pSrc, notReady) ){ int iCol = pTerm->u.leftColumn; Bitmask cMask = iCol>=BMS ? MASKBIT(BMS-1) : MASKBIT(iCol); testcase( iCol==BMS-1 ); testcase( iCol==BMS ); if( (idxCols & cMask)==0 ){ Expr *pX = pTerm->pExpr; idxCols |= cMask; pIdx->aiColumn[n] = pTerm->u.leftColumn; pColl = sqlite4BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight); pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY"; n++; } } } assert( (u32)n==pLoop->u.btree.nEq ); /* Add additional columns needed to make the automatic index into ** a covering index */ for(i=0; i<mxBitCol; i++){ if( extraCols & MASKBIT(i) ){ pIdx->aiColumn[n] = i; pIdx->azColl[n] = "BINARY"; n++; } } if( pSrc->colUsed & MASKBIT(BMS-1) ){ for(i=BMS-1; i<pTable->nCol; i++){ pIdx->aiColumn[n] = i; pIdx->azColl[n] = "BINARY"; n++; } } assert( n==nColumn ); /* Create the automatic index */ pKeyinfo = sqlite4IndexKeyinfo(pParse, pIdx); assert( pLevel->iIdxCur>=0 ); pLevel->iIdxCur = pParse->nTab++; sqlite4VdbeAddOp4(v, OP_OpenAutoindex, pLevel->iIdxCur, nColumn+1, 0, (char*)pKeyinfo, P4_KEYINFO_HANDOFF); VdbeComment((v, "for %s", pTable->zName)); /* Fill the automatic index with content */ addrTop = sqlite4VdbeAddOp1(v, OP_Rewind, pLevel->iTabCur); regRecord = sqlite4GetTempReg(pParse); sqlite4GenerateIndexKey(pParse, pIdx, pLevel->iTabCur, regRecord, 1); sqlite4VdbeAddOp2(v, OP_IdxInsert, pLevel->iIdxCur, regRecord); sqlite4VdbeChangeP5(v, OPFLAG_USESEEKRESULT); sqlite4VdbeAddOp2(v, OP_Next, pLevel->iTabCur, addrTop+1); sqlite4VdbeChangeP5(v, SQLITE4_STMTSTATUS_AUTOINDEX); sqlite4VdbeJumpHere(v, addrTop); sqlite4ReleaseTempReg(pParse, regRecord); /* Jump here when skipping the initialization */ sqlite4VdbeJumpHere(v, addrInit); } #endif /* SQLITE4_OMIT_AUTOMATIC_INDEX */ #ifndef SQLITE4_OMIT_VIRTUALTABLE /* ** Allocate and populate an sqlite4_index_info structure. It is the ** responsibility of the caller to eventually release the structure ** by passing the pointer returned by this function to sqlite4_free(). */ static sqlite4_index_info *allocateIndexInfo( Parse *pParse, WhereClause *pWC, struct SrcListItem *pSrc, ExprList *pOrderBy ){ int i, j; int nTerm; struct sqlite4_index_constraint *pIdxCons; struct sqlite4_index_orderby *pIdxOrderBy; struct sqlite4_index_constraint_usage *pUsage; WhereTerm *pTerm; int nOrderBy; sqlite4_index_info *pIdxInfo; /* Count the number of possible WHERE clause constraints referring ** to this virtual table */ for(i=nTerm=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_ISNULL ); if( pTerm->eOperator & (WO_ISNULL) ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; nTerm++; } /* If the ORDER BY clause contains only columns in the current ** virtual table then allocate space for the aOrderBy part of ** the sqlite4_index_info structure. */ nOrderBy = 0; if( pOrderBy ){ int n = pOrderBy->nExpr; for(i=0; i<n; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; if( pExpr->op!=TK_COLUMN || pExpr->iTable!=pSrc->iCursor ) break; } if( i==n){ nOrderBy = n; } } /* Allocate the sqlite4_index_info structure */ pIdxInfo = sqlite4DbMallocZero(pParse->db, sizeof(*pIdxInfo) + (sizeof(*pIdxCons) + sizeof(*pUsage))*nTerm + sizeof(*pIdxOrderBy)*nOrderBy ); if( pIdxInfo==0 ){ sqlite4ErrorMsg(pParse, "out of memory"); return 0; } /* Initialize the structure. The sqlite4_index_info structure contains ** many fields that are declared "const" to prevent xBestIndex from ** changing them. We have to do some funky casting in order to ** initialize those fields. */ pIdxCons = (struct sqlite4_index_constraint*)&pIdxInfo[1]; pIdxOrderBy = (struct sqlite4_index_orderby*)&pIdxCons[nTerm]; pUsage = (struct sqlite4_index_constraint_usage*)&pIdxOrderBy[nOrderBy]; *(int*)&pIdxInfo->nConstraint = nTerm; *(int*)&pIdxInfo->nOrderBy = nOrderBy; *(struct sqlite4_index_constraint**)&pIdxInfo->aConstraint = pIdxCons; *(struct sqlite4_index_orderby**)&pIdxInfo->aOrderBy = pIdxOrderBy; *(struct sqlite4_index_constraint_usage**)&pIdxInfo->aConstraintUsage = pUsage; for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){ u8 op; if( pTerm->leftCursor != pSrc->iCursor ) continue; assert( IsPowerOfTwo(pTerm->eOperator & ~WO_EQUIV) ); testcase( pTerm->eOperator & WO_IN ); testcase( pTerm->eOperator & WO_ISNULL ); if( pTerm->eOperator & (WO_ISNULL) ) continue; if( pTerm->wtFlags & TERM_VNULL ) continue; pIdxCons[j].iColumn = pTerm->u.leftColumn; pIdxCons[j].iTermOffset = i; op = (u8)pTerm->eOperator & WO_ALL; if( op==WO_IN ) op = WO_EQ; pIdxCons[j].op = op; /* The direct assignment in the previous line is possible only because ** the WO_ and SQLITE4_INDEX_CONSTRAINT_ codes are identical. The ** following asserts verify this fact. */ assert( WO_EQ==SQLITE4_INDEX_CONSTRAINT_EQ ); assert( WO_LT==SQLITE4_INDEX_CONSTRAINT_LT ); assert( WO_LE==SQLITE4_INDEX_CONSTRAINT_LE ); assert( WO_GT==SQLITE4_INDEX_CONSTRAINT_GT ); assert( WO_GE==SQLITE4_INDEX_CONSTRAINT_GE ); assert( WO_MATCH==SQLITE4_INDEX_CONSTRAINT_MATCH ); assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) ); j++; } for(i=0; i<nOrderBy; i++){ Expr *pExpr = pOrderBy->a[i].pExpr; pIdxOrderBy[i].iColumn = pExpr->iColumn; pIdxOrderBy[i].desc = pOrderBy->a[i].sortOrder; } return pIdxInfo; } /* ** The table object reference passed as the second argument to this function ** must represent a virtual table. This function invokes the xBestIndex() ** method of the virtual table with the sqlite4_index_info object that ** comes in as the 3rd argument to this function. ** ** If an error occurs, pParse is populated with an error message and a ** non-zero value is returned. Otherwise, 0 is returned and the output ** part of the sqlite4_index_info structure is left populated. ** ** Whether or not an error is returned, it is the responsibility of the ** caller to eventually free p->idxStr if p->needToFreeIdxStr indicates ** that this is required. */ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite4_index_info *p){ sqlite4_vtab *pVtab = sqlite4GetVTable(pParse->db, pTab)->pVtab; int i; int rc; TRACE_IDX_INPUTS(p); rc = pVtab->pModule->xBestIndex(pVtab, p); TRACE_IDX_OUTPUTS(p); if( rc!=SQLITE4_OK ){ if( rc==SQLITE4_NOMEM ){ pParse->db->mallocFailed = 1; |
︙ | ︙ | |||
2311 2312 2313 2314 2315 2316 2317 | sqlite4ErrorMsg(pParse, "table %s: xBestIndex returned an invalid plan", pTab->zName); } } return pParse->nErr; } | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | | > > < | > > > > > > > > > > > | < > > > | > > > > | > | > > > > > > > > > | > > > | > > > > | > > > > > > > > > > > > > > > > > > > > | > > > | > > | > > > > > > > > > > > > > > > > > > > | | | > > | 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536 2537 2538 2539 2540 2541 2542 2543 | sqlite4ErrorMsg(pParse, "table %s: xBestIndex returned an invalid plan", pTab->zName); } } return pParse->nErr; } #endif /* !defined(SQLITE4_OMIT_VIRTUALTABLE) */ #ifdef SQLITE4_ENABLE_STAT3 /* ** Estimate the location of a particular key among all keys in an ** index. Store the results in aStat as follows: ** ** aStat[0] Est. number of rows less than pVal ** aStat[1] Est. number of rows equal to pVal ** ** Return SQLITE4_OK on success. */ static int whereKeyStats( Parse *pParse, /* Database connection */ Index *pIdx, /* Index to consider domain of */ sqlite4_value *pVal, /* Value to consider */ int roundUp, /* Round up if true. Round down if false */ tRowcnt *aStat /* OUT: stats written here */ ){ tRowcnt n; IndexSample *aSample; int i, eType; int isEq = 0; i64 v; double r, rS; assert( roundUp==0 || roundUp==1 ); assert( pIdx->nSample>0 ); if( pVal==0 ) return SQLITE4_ERROR; n = pIdx->aiRowEst[0]; aSample = pIdx->aSample; eType = sqlite4_value_type(pVal); if( eType==SQLITE4_INTEGER ){ v = sqlite4_value_int64(pVal); r = (i64)v; for(i=0; i<pIdx->nSample; i++){ if( aSample[i].eType==SQLITE4_NULL ) continue; if( aSample[i].eType>=SQLITE4_TEXT ) break; if( aSample[i].eType==SQLITE4_INTEGER ){ if( aSample[i].u.i>=v ){ isEq = aSample[i].u.i==v; break; } }else{ assert( aSample[i].eType==SQLITE4_FLOAT ); if( aSample[i].u.r>=r ){ isEq = aSample[i].u.r==r; break; } } } }else if( eType==SQLITE4_FLOAT ){ r = sqlite4_value_double(pVal); for(i=0; i<pIdx->nSample; i++){ if( aSample[i].eType==SQLITE4_NULL ) continue; if( aSample[i].eType>=SQLITE4_TEXT ) break; if( aSample[i].eType==SQLITE4_FLOAT ){ rS = aSample[i].u.r; }else{ rS = aSample[i].u.i; } if( rS>=r ){ isEq = rS==r; break; } } }else if( eType==SQLITE4_NULL ){ i = 0; if( aSample[0].eType==SQLITE4_NULL ) isEq = 1; }else{ assert( eType==SQLITE4_TEXT || eType==SQLITE4_BLOB ); for(i=0; i<pIdx->nSample; i++){ if( aSample[i].eType==SQLITE4_TEXT || aSample[i].eType==SQLITE4_BLOB ){ break; } } if( i<pIdx->nSample ){ sqlite4 *db = pParse->db; CollSeq *pColl; const u8 *z; if( eType==SQLITE4_BLOB ){ z = (const u8 *)sqlite4_value_blob(pVal); pColl = db->pDfltColl; assert( pColl->enc==SQLITE4_UTF8 ); }else{ pColl = sqlite4GetCollSeq(pParse, SQLITE4_UTF8, 0, *pIdx->azColl); /* If the collating sequence was unavailable, we should have failed ** long ago and never reached this point. But we'll check just to ** be doubly sure. */ if( NEVER(pColl==0) ) return SQLITE4_ERROR; z = (const u8 *)sqlite4ValueText(pVal, pColl->enc); if( !z ){ return SQLITE4_NOMEM; } assert( z && pColl && pColl->xCmp ); } n = sqlite4ValueBytes(pVal, pColl->enc); for(; i<pIdx->nSample; i++){ int c; int eSampletype = aSample[i].eType; if( eSampletype<eType ) continue; if( eSampletype!=eType ) break; #ifndef SQLITE4_OMIT_UTF16 if( pColl->enc!=SQLITE4_UTF8 ){ int nSample; char *zSample = sqlite4Utf8to16( db, pColl->enc, aSample[i].u.z, aSample[i].nByte, &nSample ); if( !zSample ){ assert( db->mallocFailed ); return SQLITE4_NOMEM; } c = pColl->xCmp(pColl->pUser, nSample, zSample, n, z); sqlite4DbFree(db, zSample); }else #endif { c = pColl->xCmp(pColl->pUser, aSample[i].nByte, aSample[i].u.z, n, z); } if( c>=0 ){ if( c==0 ) isEq = 1; break; } } } } /* At this point, aSample[i] is the first sample that is greater than ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less ** than pVal. If aSample[i]==pVal, then isEq==1. */ |
︙ | ︙ | |||
2549 2550 2551 2552 2553 2554 2555 | aStat[0] = iLower + iGap; } return SQLITE4_OK; } #endif /* SQLITE4_ENABLE_STAT3 */ /* | | | | > > | > | | < | | | < < < < < < | < < < < < < < < | < | < < | < < < < < < < < < < < < < < < < | 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 | aStat[0] = iLower + iGap; } return SQLITE4_OK; } #endif /* SQLITE4_ENABLE_STAT3 */ /* ** If expression pExpr represents a literal value, set *pp to point to ** an sqlite4_value structure containing the same value, with affinity ** aff applied to it, before returning. It is the responsibility of the ** caller to eventually release this structure by passing it to ** sqlite4ValueFree(). ** ** If the current parse is a recompile (sqlite4Reprepare()) and pExpr ** is an SQL variable that currently has a non-NULL value bound to it, ** create an sqlite4_value structure containing this value, again with ** affinity aff applied to it, instead. ** ** If neither of the above apply, set *pp to NULL. ** ** If an error occurs, return an error code. Otherwise, SQLITE4_OK. */ #ifdef SQLITE4_ENABLE_STAT3 static int valueFromExpr( Parse *pParse, Expr *pExpr, u8 aff, sqlite4_value **pp ){ if( pExpr->op==TK_VARIABLE || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE) ){ int iVar = pExpr->iColumn; sqlite4VdbeSetVarmask(pParse->pVdbe, iVar); *pp = sqlite4VdbeGetValue(pParse->pReprepare, iVar, aff); return SQLITE4_OK; } return sqlite4ValueFromExpr(pParse->db, pExpr, SQLITE4_UTF8, aff, pp); } #endif /* ** This function is used to estimate the number of rows that will be visited ** by scanning an index for a range of values. The range may have an upper ** bound, a lower bound, or both. The WHERE clause terms that set the upper ** and lower bounds are represented by pLower and pUpper respectively. For ** example, assuming that index p is on t1(a): ** |
︙ | ︙ | |||
2659 2660 2661 2662 2663 2664 2665 | */ static int whereRangeScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index containing the range-compared column; "x" */ int nEq, /* index into p->aCol[] of the range-compared column */ WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ | | | | < < < < < | | | | | | | | | | | | > < > | < < | > | | | > > | > > | > > | 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 | */ static int whereRangeScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index containing the range-compared column; "x" */ int nEq, /* index into p->aCol[] of the range-compared column */ WhereTerm *pLower, /* Lower bound on the range. ex: "x>123" Might be NULL */ WhereTerm *pUpper, /* Upper bound on the range. ex: "x<455" Might be NULL */ WhereCost *pRangeDiv /* OUT: Reduce search space by this divisor */ ){ int rc = SQLITE4_OK; #ifdef SQLITE4_ENABLE_STAT3 if( nEq==0 && p->nSample && OptimizationEnabled(pParse->db, SQLITE4_Stat3) ){ sqlite4_value *pRangeVal; tRowcnt iLower = 0; tRowcnt iUpper = p->aiRowEst[0]; tRowcnt a[2]; u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; if( pLower ){ Expr *pExpr = pLower->pExpr->pRight; rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal); assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 ); if( rc==SQLITE4_OK && whereKeyStats(pParse, p, pRangeVal, 0, a)==SQLITE4_OK ){ iLower = a[0]; if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1]; } sqlite4ValueFree(pRangeVal); } if( rc==SQLITE4_OK && pUpper ){ Expr *pExpr = pUpper->pExpr->pRight; rc = valueFromExpr(pParse, pExpr, aff, &pRangeVal); assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 ); if( rc==SQLITE4_OK && whereKeyStats(pParse, p, pRangeVal, 1, a)==SQLITE4_OK ){ iUpper = a[0]; if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1]; } sqlite4ValueFree(pRangeVal); } if( rc==SQLITE4_OK ){ WhereCost iBase = whereCost(p->aiRowEst[0]); if( iUpper>iLower ){ iBase -= whereCost(iUpper - iLower); } *pRangeDiv = iBase; WHERETRACE(0x100, ("range scan regions: %u..%u div=%d\n", (u32)iLower, (u32)iUpper, *pRangeDiv)); return SQLITE4_OK; } } #else UNUSED_PARAMETER(pParse); UNUSED_PARAMETER(p); UNUSED_PARAMETER(nEq); #endif assert( pLower || pUpper ); *pRangeDiv = 0; /* TUNING: Each inequality constraint reduces the search space 4-fold. ** A BETWEEN operator, therefore, reduces the search space 16-fold */ if( pLower && (pLower->wtFlags & TERM_VNULL)==0 ){ *pRangeDiv += 20; assert( 20==whereCost(4) ); } if( pUpper ){ *pRangeDiv += 20; assert( 20==whereCost(4) ); } return rc; } #ifdef SQLITE4_ENABLE_STAT3 /* ** Estimate the number of rows that will be returned based on ** an equality constraint x=VALUE and where that VALUE occurs in |
︙ | ︙ | |||
2746 2747 2748 2749 2750 2751 2752 | ** for a UTF conversion required for comparison. The error is stored ** in the pParse structure. */ static int whereEqualScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index whose left-most column is pTerm */ Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ | | | < < < < < | | < < < | < | | | | | 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 | ** for a UTF conversion required for comparison. The error is stored ** in the pParse structure. */ static int whereEqualScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index whose left-most column is pTerm */ Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ tRowcnt *pnRow /* Write the revised row estimate here */ ){ sqlite4_value *pRhs = 0; /* VALUE on right-hand side of pTerm */ u8 aff; /* Column affinity */ int rc; /* Subfunction return code */ tRowcnt a[2]; /* Statistics */ assert( p->aSample!=0 ); assert( p->nSample>0 ); aff = p->pTable->aCol[p->aiColumn[0]].affinity; if( pExpr ){ rc = valueFromExpr(pParse, pExpr, aff, &pRhs); if( rc ) goto whereEqualScanEst_cancel; }else{ pRhs = sqlite4ValueNew(pParse->db); } if( pRhs==0 ) return SQLITE4_NOTFOUND; rc = whereKeyStats(pParse, p, pRhs, 0, a); if( rc==SQLITE4_OK ){ WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1])); *pnRow = a[1]; } whereEqualScanEst_cancel: sqlite4ValueFree(pRhs); return rc; } #endif /* defined(SQLITE4_ENABLE_STAT3) */ #ifdef SQLITE4_ENABLE_STAT3 /* ** Estimate the number of rows that will be returned based on |
︙ | ︙ | |||
2804 2805 2806 2807 2808 2809 2810 | ** for a UTF conversion required for comparison. The error is stored ** in the pParse structure. */ static int whereInScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index whose left-most column is pTerm */ ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 | ** for a UTF conversion required for comparison. The error is stored ** in the pParse structure. */ static int whereInScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index whose left-most column is pTerm */ ExprList *pList, /* The value list on the RHS of "x IN (v1,v2,v3,...)" */ tRowcnt *pnRow /* Write the revised row estimate here */ ){ int rc = SQLITE4_OK; /* Subfunction return code */ tRowcnt nEst; /* Number of rows for a single term */ tRowcnt nRowEst = 0; /* New estimate of the number of rows */ int i; /* Loop counter */ assert( p->aSample!=0 ); for(i=0; rc==SQLITE4_OK && i<pList->nExpr; i++){ nEst = p->aiRowEst[0]; rc = whereEqualScanEst(pParse, p, pList->a[i].pExpr, &nEst); nRowEst += nEst; } if( rc==SQLITE4_OK ){ if( nRowEst > p->aiRowEst[0] ) nRowEst = p->aiRowEst[0]; *pnRow = nRowEst; WHERETRACE(0x100,("IN row estimate: est=%g\n", nRowEst)); } return rc; } #endif /* defined(SQLITE4_ENABLE_STAT3) */ /* ** Disable a term in the WHERE clause. Except, do not disable the term ** if it controls a LEFT OUTER JOIN and it did not originate in the ON ** or USING clause of that join. ** ** Consider the term t2.z='ok' in the following queries: ** |
︙ | ︙ | |||
3486 3487 3488 3489 3490 3491 3492 | ** For a constraint of the form X=expr, the expression is evaluated and its ** result is left on the stack. For constraints of the form X IN (...) ** this routine sets up a loop that will iterate over all values of X. */ static int codeEqualityTerm( Parse *pParse, /* The parsing context */ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ | | > > < < < < < < < < | < < < < < < < > > > > > > > > > > > > > | < < < < < < < < < < < < < < < < < < < < | < < | | | | > > | > | < < | | | > < | 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 | ** For a constraint of the form X=expr, the expression is evaluated and its ** result is left on the stack. For constraints of the form X IN (...) ** this routine sets up a loop that will iterate over all values of X. */ static int codeEqualityTerm( Parse *pParse, /* The parsing context */ WhereTerm *pTerm, /* The term of the WHERE clause to be coded */ WhereLevel *pLevel, /* The level of the FROM clause we are working on */ int iEq, /* Index of the equality term within this level */ int bRev, /* True for reverse-order IN operations */ int iTarget /* Attempt to leave results in this register */ ){ Expr *pX = pTerm->pExpr; Vdbe *v = pParse->pVdbe; int iReg; /* Register holding results */ assert( iTarget>0 ); if( pX->op==TK_EQ ){ iReg = sqlite4ExprCodeTarget(pParse, pX->pRight, iTarget); }else if( pX->op==TK_ISNULL ){ iReg = iTarget; sqlite4VdbeAddOp2(v, OP_Null, 0, iReg); #ifndef SQLITE4_OMIT_SUBQUERY }else{ int eType; int iTab; struct InLoop *pIn; WhereLoop *pLoop = pLevel->pWLoop; if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 && pLoop->u.btree.pIndex!=0 && pLoop->u.btree.pIndex->aSortOrder[iEq] ){ testcase( iEq==0 ); testcase( bRev ); bRev = !bRev; } assert( pX->op==TK_IN ); iReg = iTarget; eType = sqlite4FindInIndex(pParse, pX, 0); if( eType==IN_INDEX_INDEX_DESC ){ testcase( bRev ); bRev = !bRev; } iTab = pX->iTable; sqlite4VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iTab, 0); assert( (pLoop->wsFlags & WHERE_MULTI_OR)==0 ); pLoop->wsFlags |= WHERE_IN_ABLE; if( pLevel->u.in.nIn==0 ){ pLevel->addrNxt = sqlite4VdbeMakeLabel(v); } pLevel->u.in.nIn++; pLevel->u.in.aInLoop = sqlite4DbReallocOrFree(pParse->db, pLevel->u.in.aInLoop, sizeof(pLevel->u.in.aInLoop[0])*pLevel->u.in.nIn); pIn = pLevel->u.in.aInLoop; if( pIn ){ pIn += pLevel->u.in.nIn - 1; pIn->iCur = iTab; if( eType==IN_INDEX_ROWID ){ pIn->addrInTop = sqlite4VdbeAddOp2(v, OP_Rowid, iTab, iReg); }else{ pIn->addrInTop = sqlite4VdbeAddOp3(v, OP_Column, iTab, 0, iReg); } pIn->eEndLoopOp = bRev ? OP_Prev : OP_Next; sqlite4VdbeAddOp1(v, OP_IsNull, iReg); }else{ pLevel->u.in.nIn = 0; } #endif } disableTerm(pLevel, pTerm); return iReg; } |
︙ | ︙ | |||
3617 3618 3619 3620 3621 3622 3623 | ** no conversion should be attempted before using a t2.b value as part of ** a key to search the index. Hence the first byte in the returned affinity ** string in this example would be set to SQLITE4_AFF_NONE. */ static int codeAllEqualityTerms( Parse *pParse, /* Parsing context */ WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */ | | < | < > > | > | > | | < | | | | 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 | ** no conversion should be attempted before using a t2.b value as part of ** a key to search the index. Hence the first byte in the returned affinity ** string in this example would be set to SQLITE4_AFF_NONE. */ static int codeAllEqualityTerms( Parse *pParse, /* Parsing context */ WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */ int bRev, /* Reverse the order of IN operators */ int nExtraReg, /* Number of extra registers to allocate */ char **pzAff /* OUT: Set to point to affinity string */ ){ int nEq; /* The number of == or IN constraints to code */ Vdbe *v = pParse->pVdbe; /* The vm under construction */ Index *pIdx; /* The index being used for this loop */ WhereTerm *pTerm; /* A single constraint term */ WhereLoop *pLoop; /* The WhereLoop object */ int j; /* Loop counter */ int regBase; /* Base register */ int nReg; /* Number of registers to allocate */ char *zAff; /* Affinity string to return */ /* This module is only called on query plans that use an index. */ pLoop = pLevel->pWLoop; assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ); nEq = pLoop->u.btree.nEq; pIdx = pLoop->u.btree.pIndex; assert( pIdx!=0 ); /* Figure out how many memory cells we will need then allocate them. */ regBase = pParse->nMem + 1; nReg = pLoop->u.btree.nEq + nExtraReg; pParse->nMem += nReg; zAff = sqlite4DbStrDup(pParse->db, sqlite4IndexAffinityStr(v, pIdx)); if( !zAff ){ pParse->db->mallocFailed = 1; } /* Evaluate the equality constraints */ assert( idxColumnCount(pIdx, sqlite4FindPrimaryKey(pIdx->pTable, 0))>=nEq ); for(j=0; j<nEq; j++){ int r1; pTerm = pLoop->aLTerm[j]; assert( pTerm!=0 ); /* The following true for indices with redundant columns. ** Ex: CREATE INDEX i1 ON t1(a,b,a); SELECT * FROM t1 WHERE a=0 AND b=0; */ testcase( (pTerm->wtFlags & TERM_CODED)!=0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ r1 = codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, regBase+j); if( r1!=regBase+j ){ if( nReg==1 ){ sqlite4ReleaseTempReg(pParse, regBase); regBase = r1; }else{ sqlite4VdbeAddOp2(v, OP_SCopy, r1, regBase+j); } |
︙ | ︙ | |||
3727 3728 3729 3730 3731 3732 3733 | ** ** "a=? AND b>?" ** ** The returned pointer points to memory obtained from sqlite4DbMalloc(). ** It is the responsibility of the caller to free the buffer when it is ** no longer required. */ | | < | < | | > > < | < < < | > > | | | | | | < | < > > > > < | > | | > > | < | | | | < | | > > > | > | > > | < < | > > > < | < < < < < < | > < | < > > | > | > | > > | > > | 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 | ** ** "a=? AND b>?" ** ** The returned pointer points to memory obtained from sqlite4DbMalloc(). ** It is the responsibility of the caller to free the buffer when it is ** no longer required. */ static char *explainIndexRange(sqlite4 *db, WhereLoop *pLoop, Table *pTab){ Index *pIndex = pLoop->u.btree.pIndex; int nEq = pLoop->u.btree.nEq; int i, j; Column *aCol = pTab->aCol; int *aiColumn = pIndex->aiColumn; StrAccum txt; if( nEq==0 && (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))==0 ){ return 0; } sqlite4StrAccumInit(&txt, 0, 0, SQLITE4_MAX_LENGTH); txt.db = db; sqlite4StrAccumAppend(&txt, " (", 2); for(i=0; i<nEq; i++){ explainAppendTerm(&txt, i, aCol[aiColumn[i]].zName, "="); } j = i; if( pLoop->wsFlags&WHERE_BTM_LIMIT ){ char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName; explainAppendTerm(&txt, i++, z, ">"); } if( pLoop->wsFlags&WHERE_TOP_LIMIT ){ char *z = (j==pIndex->nColumn ) ? "rowid" : aCol[aiColumn[j]].zName; explainAppendTerm(&txt, i, z, "<"); } sqlite4StrAccumAppend(&txt, ")", 1); return sqlite4StrAccumFinish(&txt); } /* ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN ** command. If the query being compiled is an EXPLAIN QUERY PLAN, a single ** record is added to the output to describe the table scan strategy in ** pLevel. */ static void explainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ int iLevel, /* Value for "level" column of output */ int iFrom, /* Value for "from" column of output */ u16 wctrlFlags /* Flags passed to sqlite4WhereBegin() */ ){ if( pParse->explain==2 ){ struct SrcListItem *pItem = &pTabList->a[pLevel->iFrom]; Vdbe *v = pParse->pVdbe; /* VM being constructed */ sqlite4 *db = pParse->db; /* Database handle */ char *zMsg; /* Text to add to EQP output */ int iId = pParse->iSelectId; /* Select id (left-most output column) */ int isSearch; /* True for a SEARCH. False for SCAN. */ WhereLoop *pLoop; /* The controlling WhereLoop object */ u32 flags; /* Flags that describe this loop */ pLoop = pLevel->pWLoop; flags = pLoop->wsFlags; if( (flags&WHERE_MULTI_OR) || (wctrlFlags&WHERE_ONETABLE_ONLY) ) return; isSearch = (flags&(WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 || ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0)) || (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX)); zMsg = sqlite4MPrintf(db, "%s", isSearch?"SEARCH":"SCAN"); if( pItem->pSelect ){ zMsg = sqlite4MAppendf(db, zMsg, "%s SUBQUERY %d", zMsg,pItem->iSelectId); }else{ zMsg = sqlite4MAppendf(db, zMsg, "%s TABLE %s", zMsg, pItem->zName); } if( pItem->zAlias ){ zMsg = sqlite4MAppendf(db, zMsg, "%s AS %s", zMsg, pItem->zAlias); } if( (flags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 && ALWAYS(pLoop->u.btree.pIndex!=0) ){ char *zWhere = explainIndexRange(db, pLoop, pItem->pTab); zMsg = sqlite4MAppendf(db, zMsg, ((flags & WHERE_AUTO_INDEX) ? "%s USING AUTOMATIC %sINDEX%.0s%s" : "%s USING %sINDEX %s%s"), zMsg, ((flags & WHERE_IDX_ONLY) ? "COVERING " : ""), pLoop->u.btree.pIndex->zName, zWhere); sqlite4DbFree(db, zWhere); }else if( (flags & WHERE_IPK)!=0 && (flags & WHERE_CONSTRAINT)!=0 ){ zMsg = sqlite4MAppendf(db, zMsg, "%s USING INTEGER PRIMARY KEY", zMsg); if( flags&(WHERE_COLUMN_EQ|WHERE_COLUMN_IN) ){ zMsg = sqlite4MAppendf(db, zMsg, "%s (rowid=?)", zMsg); }else if( (flags&WHERE_BOTH_LIMIT)==WHERE_BOTH_LIMIT ){ zMsg = sqlite4MAppendf(db, zMsg, "%s (rowid>? AND rowid<?)", zMsg); }else if( flags&WHERE_BTM_LIMIT ){ zMsg = sqlite4MAppendf(db, zMsg, "%s (rowid>?)", zMsg); }else if( ALWAYS(flags&WHERE_TOP_LIMIT) ){ zMsg = sqlite4MAppendf(db, zMsg, "%s (rowid<?)", zMsg); } } #ifndef SQLITE4_OMIT_VIRTUALTABLE else if( (flags & WHERE_VIRTUALTABLE)!=0 ){ zMsg = sqlite4MAppendf(db, zMsg, "%s VIRTUAL TABLE INDEX %d:%s", zMsg, pLoop->u.vtab.idxNum, pLoop->u.vtab.idxStr); } #endif zMsg = sqlite4MAppendf(db, zMsg, "%s", zMsg); sqlite4VdbeAddOp4(v, OP_Explain, iId, iLevel, iFrom, zMsg, P4_DYNAMIC); } } #else # define explainOneScan(u,v,w,x,y,z) #endif /* SQLITE4_OMIT_EXPLAIN */ /* ** Generate code for the start of the iLevel-th loop in the WHERE clause ** implementation described by pWInfo. */ static Bitmask codeOneLoopStart( WhereInfo *pWInfo, /* Complete information about the WHERE clause */ int iLevel, /* Which level of pWInfo->a[] should be coded */ Bitmask notReady /* Which tables are currently available */ ){ int j, k; /* Loop counters */ int iCur; /* The VDBE cursor for the table */ int addrNxt; /* Where to jump to continue with the next IN case */ int omitTable; /* True if we use the index only */ int bRev; /* True if we need to scan in reverse order */ WhereLevel *pLevel; /* The where level to be coded */ WhereLoop *pLoop; /* The WhereLoop object being coded */ WhereClause *pWC; /* Decomposition of the entire WHERE clause */ WhereTerm *pTerm; /* A WHERE clause term */ Parse *pParse; /* Parsing context */ Vdbe *v; /* The prepared stmt under constructions */ struct SrcListItem *pTabItem; /* FROM clause term being coded */ int addrBrk; /* Jump here to break out of the loop */ int addrCont; /* Jump here to continue with next cycle */ int iRowidReg = 0; /* Rowid is stored in this register, if not zero */ int iReleaseReg = 0; /* Temp register to free before returning */ Bitmask newNotReady; /* Return value */ pParse = pWInfo->pParse; v = pParse->pVdbe; pWC = &pWInfo->sWC; pLevel = &pWInfo->a[iLevel]; pLoop = pLevel->pWLoop; pTabItem = &pWInfo->pTabList->a[pLevel->iFrom]; iCur = pTabItem->iCursor; bRev = (pWInfo->revMask>>iLevel)&1; omitTable = (pLoop->wsFlags & WHERE_IDX_ONLY)!=0 && (pWInfo->wctrlFlags & WHERE_FORCE_TABLE)==0; VdbeNoopComment((v, "Begin Join Loop %d", iLevel)); /* Create labels for the "break" and "continue" instructions ** for the current loop. Jump to addrBrk to break out of a loop. ** Jump to cont to go immediately to the next iteration of the ** loop. ** ** When there is an IN operator, we also have a "addrNxt" label that |
︙ | ︙ | |||
3894 3895 3896 3897 3898 3899 3900 | */ if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite4VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } | | < < | < < < | | < < | | < < | < | | < | > > | | | | < < < < > | | > | | | < > | > < | | | > | | | | < | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 | */ if( pLevel->iFrom>0 && (pTabItem[0].jointype & JT_LEFT)!=0 ){ pLevel->iLeftJoin = ++pParse->nMem; sqlite4VdbeAddOp2(v, OP_Integer, 0, pLevel->iLeftJoin); VdbeComment((v, "init LEFT JOIN no-match flag")); } #if 0 /* Special case of a FROM clause subquery implemented as a co-routine */ if( pTabItem->viaCoroutine ){ int regYield = pTabItem->regReturn; sqlite4VdbeAddOp2(v, OP_Integer, pTabItem->addrFillSub-1, regYield); pLevel->p2 = sqlite4VdbeAddOp1(v, OP_Yield, regYield); VdbeComment((v, "next row of co-routine %s", pTabItem->pTab->zName)); sqlite4VdbeAddOp2(v, OP_If, regYield+1, addrBrk); pLevel->op = OP_Goto; }else #endif #ifndef SQLITE4_OMIT_VIRTUALTABLE if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ /* Case 1: The table is a virtual-table. Use the VFilter and VNext ** to access the data. */ int iReg; /* P3 Value for OP_VFilter */ int addrNotFound; int nConstraint = pLoop->nLTerm; sqlite4ExprCachePush(pParse); iReg = sqlite4GetTempRange(pParse, nConstraint+2); addrNotFound = pLevel->addrBrk; for(j=0; j<nConstraint; j++){ int iTarget = iReg+j+2; pTerm = pLoop->aLTerm[j]; if( pTerm==0 ) continue; if( pTerm->eOperator & WO_IN ){ codeEqualityTerm(pParse, pTerm, pLevel, j, bRev, iTarget); addrNotFound = pLevel->addrNxt; }else{ sqlite4ExprCode(pParse, pTerm->pExpr->pRight, iTarget); } } sqlite4VdbeAddOp2(v, OP_Integer, pLoop->u.vtab.idxNum, iReg); sqlite4VdbeAddOp2(v, OP_Integer, nConstraint, iReg+1); sqlite4VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pLoop->u.vtab.idxStr, pLoop->u.vtab.needFree ? P4_MPRINTF : P4_STATIC); pLoop->u.vtab.needFree = 0; for(j=0; j<nConstraint && j<16; j++){ if( (pLoop->u.vtab.omitMask>>j)&1 ){ disableTerm(pLevel, pLoop->aLTerm[j]); } } pLevel->op = OP_VNext; pLevel->p1 = iCur; pLevel->p2 = sqlite4VdbeCurrentAddr(v); sqlite4ReleaseTempRange(pParse, iReg, nConstraint+2); sqlite4ExprCachePop(pParse, 1); }else #endif /* SQLITE4_OMIT_VIRTUALTABLE */ if( (pLoop->wsFlags & WHERE_IPK)!=0 && (pLoop->wsFlags & (WHERE_COLUMN_IN|WHERE_COLUMN_EQ))!=0 ){ assert( 0 ); /* Case 2: We can directly reference a single row using an ** equality comparison against the ROWID field. Or ** we reference multiple rows using a "rowid IN (...)" ** construct. */ assert( pLoop->u.btree.nEq==1 ); iReleaseReg = sqlite4GetTempReg(pParse); pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); assert( pTerm->pExpr!=0 ); assert( omitTable==0 ); testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ iRowidReg = codeEqualityTerm(pParse, pTerm, pLevel, 0, bRev, iReleaseReg); addrNxt = pLevel->addrNxt; sqlite4VdbeAddOp2(v, OP_MustBeInt, iRowidReg, addrNxt); sqlite4VdbeAddOp3(v, OP_NotExists, iCur, addrNxt, iRowidReg); sqlite4ExprCacheAffinityChange(pParse, iRowidReg, 1); sqlite4ExprCacheStore(pParse, iCur, -1, iRowidReg); VdbeComment((v, "pk")); pLevel->op = OP_Noop; }else if( (pLoop->wsFlags & WHERE_IPK)!=0 && (pLoop->wsFlags & WHERE_COLUMN_RANGE)!=0 ){ /* Case 3: We have an inequality comparison against the ROWID field. */ int testOp = OP_Noop; int start; int memEndValue = 0; WhereTerm *pStart, *pEnd; assert( 0 ); assert( omitTable==0 ); j = 0; pStart = pEnd = 0; if( pLoop->wsFlags & WHERE_BTM_LIMIT ) pStart = pLoop->aLTerm[j++]; if( pLoop->wsFlags & WHERE_TOP_LIMIT ) pEnd = pLoop->aLTerm[j++]; assert( pStart!=0 || pEnd!=0 ); if( bRev ){ pTerm = pStart; pStart = pEnd; pEnd = pTerm; } if( pStart ){ Expr *pX; /* The expression that defines the start bound */ int r1, rTemp; /* Registers for holding the start boundary */ /* The following constant maps TK_xx codes into corresponding ** seek opcodes. It depends on a particular ordering of TK_xx */ const u8 aMoveOp[] = { /* TK_GT */ OP_SeekGt, /* TK_LE */ OP_SeekLe, /* TK_LT */ OP_SeekLt, /* TK_GE */ OP_SeekGe }; assert( TK_LE==TK_GT+1 ); /* Make sure the ordering.. */ assert( TK_LT==TK_GT+2 ); /* ... of the TK_xx values... */ assert( TK_GE==TK_GT+3 ); /* ... is correcct. */ assert( (pStart->wtFlags & TERM_VNULL)==0 ); testcase( pStart->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ pX = pStart->pExpr; assert( pX!=0 ); testcase( pStart->leftCursor!=iCur ); /* transitive constraints */ r1 = sqlite4ExprCodeTemp(pParse, pX->pRight, &rTemp); sqlite4VdbeAddOp3(v, aMoveOp[pX->op-TK_GT], iCur, addrBrk, r1); VdbeComment((v, "pk")); sqlite4ExprCacheAffinityChange(pParse, r1, 1); sqlite4ReleaseTempReg(pParse, rTemp); disableTerm(pLevel, pStart); }else{ sqlite4VdbeAddOp2(v, bRev ? OP_Last : OP_Rewind, iCur, addrBrk); } if( pEnd ){ Expr *pX; pX = pEnd->pExpr; assert( pX!=0 ); assert( (pEnd->wtFlags & TERM_VNULL)==0 ); testcase( pEnd->leftCursor!=iCur ); /* Transitive constraints */ testcase( pEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ memEndValue = ++pParse->nMem; sqlite4ExprCode(pParse, pX->pRight, memEndValue); if( pX->op==TK_LT || pX->op==TK_GT ){ testOp = bRev ? OP_Le : OP_Ge; }else{ testOp = bRev ? OP_Lt : OP_Gt; } disableTerm(pLevel, pEnd); } start = sqlite4VdbeCurrentAddr(v); pLevel->op = bRev ? OP_Prev : OP_Next; pLevel->p1 = iCur; pLevel->p2 = start; assert( pLevel->p5==0 ); if( testOp!=OP_Noop ){ iRowidReg = iReleaseReg = sqlite4GetTempReg(pParse); sqlite4VdbeAddOp2(v, OP_Rowid, iCur, iRowidReg); sqlite4ExprCacheStore(pParse, iCur, -1, iRowidReg); sqlite4VdbeAddOp3(v, testOp, memEndValue, addrBrk, iRowidReg); sqlite4VdbeChangeP5(v, SQLITE4_AFF_NUMERIC | SQLITE4_JUMPIFNULL); } }else if( pLoop->wsFlags & WHERE_INDEXED ){ /* Case 4: A scan using an index. ** ** The WHERE clause may contain zero or more equality ** terms ("==" or "IN" operators) that refer to the N ** left-most columns of the index. It may also contain ** inequality constraints (>, <, >= or <=) on the indexed ** column that immediately follows the N equalities. Only ** the right-most column can be an inequality - the rest must |
︙ | ︙ | |||
4009 4010 4011 4012 4013 4014 4015 | OP_Noop, /* 0: (!end_constraints) */ OP_IdxGE, /* 1: (end_constraints && !endEq && !bRev) */ OP_IdxLE, /* 2: (end_constraints && !endEq && bRev) */ OP_IdxGT, /* 3: (end_constraints && endEq && !bRev) */ OP_IdxLT /* 4: (end_constraints && endEq && bRev) */ }; | | | | | | | > > | | | | | < | < < < | > | | | | | 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 | OP_Noop, /* 0: (!end_constraints) */ OP_IdxGE, /* 1: (end_constraints && !endEq && !bRev) */ OP_IdxLE, /* 2: (end_constraints && !endEq && bRev) */ OP_IdxGT, /* 3: (end_constraints && endEq && !bRev) */ OP_IdxLT /* 4: (end_constraints && endEq && bRev) */ }; int nEq = pLoop->u.btree.nEq; /* Number of == or IN terms */ int isMinQuery = 0; /* If this is an optimized SELECT min(x).. */ int regBase; /* Base register holding constraint values */ int r1; /* Temp register */ WhereTerm *pRangeStart = 0; /* Inequality constraint at range start */ WhereTerm *pRangeEnd = 0; /* Inequality constraint at range end */ int startEq; /* True if range start uses ==, >= or <= */ int endEq; /* True if range end uses ==, >= or <= */ int start_constraints; /* Start of range is constrained */ int nConstraint; /* Number of constraint terms */ Index *pIdx; /* The index we will be using */ int iIdxCur; /* The VDBE cursor for the index */ int nExtraReg = 0; /* Number of extra registers needed */ int op; /* Instruction opcode */ char *zStartAff; /* Affinity for start of range constraint */ char *zEndAff; /* Affinity for end of range constraint */ int regEndKey; /* Register for end-key */ int iIneq; /* The table column subject to inequality */ Index *pPk; /* Primary key index on same table as pIdx */ pIdx = pLoop->u.btree.pIndex; pPk = sqlite4FindPrimaryKey(pIdx->pTable, 0); iIneq = idxColumnNumber(pIdx, pPk, nEq); iIdxCur = pLevel->iIdxCur; assert( iCur==pLevel->iTabCur ); /* If this loop satisfies a sort order (pOrderBy) request that ** was passed to this function to implement a "SELECT min(x) ..." ** query, then the caller will only allow the loop to run for ** a single iteration. This means that the first row returned ** should not have a NULL value stored in 'x'. If column 'x' is ** the first one after the nEq equality constraints in the index, ** this requires some special handling. */ if( (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)!=0 && (pWInfo->bOBSat!=0) && (pIdx->nColumn>nEq) ){ /* assert( pOrderBy->nExpr==1 ); */ /* assert( pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq] ); */ isMinQuery = 1; nExtraReg = 1; } /* Find any inequality constraint terms for the start and end ** of the range. */ j = nEq; if( pLoop->wsFlags & WHERE_BTM_LIMIT ){ pRangeStart = pLoop->aLTerm[j++]; nExtraReg = 1; } if( pLoop->wsFlags & WHERE_TOP_LIMIT ){ pRangeEnd = pLoop->aLTerm[j++]; nExtraReg = 1; } /* Generate code to evaluate all constraint terms using == or IN ** and store the values of those terms in an array of registers ** starting at regBase. */ regBase = codeAllEqualityTerms(pParse,pLevel,bRev,nExtraReg,&zStartAff); assert( (regBase+nEq+nExtraReg-1)<=pParse->nMem ); zEndAff = sqlite4DbStrDup(pParse->db, zStartAff); addrNxt = pLevel->addrNxt; /* If we are doing a reverse order scan on an ascending index, or ** a forward order scan on a descending index, interchange the ** start and end terms (pRangeStart and pRangeEnd). */ if( (nEq<pIdx->nColumn && bRev==(pIdx->aSortOrder[nEq]==SQLITE4_SO_ASC)) || (bRev && pIdx->nColumn==nEq) ){ SWAP(WhereTerm *, pRangeEnd, pRangeStart); } testcase( pRangeStart && (pRangeStart->eOperator & WO_LE)!=0 ); testcase( pRangeStart && (pRangeStart->eOperator & WO_GE)!=0 ); testcase( pRangeEnd && (pRangeEnd->eOperator & WO_LE)!=0 ); testcase( pRangeEnd && (pRangeEnd->eOperator & WO_GE)!=0 ); startEq = !pRangeStart || pRangeStart->eOperator & (WO_LE|WO_GE); endEq = !pRangeEnd || pRangeEnd->eOperator & (WO_LE|WO_GE); start_constraints = pRangeStart || nEq>0; /* Seek the index cursor to the start of the range. */ nConstraint = nEq; if( pRangeStart ){ |
︙ | ︙ | |||
4131 4132 4133 4134 4135 4136 4137 | testcase( op==OP_Rewind ); testcase( op==OP_Last ); testcase( op==OP_SeekGt ); testcase( op==OP_SeekGe ); testcase( op==OP_SeekLe ); testcase( op==OP_SeekLt ); sqlite4VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); | | | | > | | > | 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 | testcase( op==OP_Rewind ); testcase( op==OP_Last ); testcase( op==OP_SeekGt ); testcase( op==OP_SeekGe ); testcase( op==OP_SeekLe ); testcase( op==OP_SeekLt ); sqlite4VdbeAddOp4Int(v, op, iIdxCur, addrNxt, regBase, nConstraint); if( nEq<idxColumnCount(pIdx, pPk) ){ sqlite4VdbeChangeP5(v, OPFLAG_PARTIALKEY); } /* Set variable op to the instruction required to determine if the ** cursor is passed the end of the range. If the range is unbounded, ** then set op to OP_Noop. Nothing to do in this case. */ assert( (endEq==0 || endEq==1) ); op = aEndOp[(pRangeEnd || nEq) * (1 + (endEq+endEq) + bRev)]; testcase( op==OP_Noop ); testcase( op==OP_IdxGE ); testcase( op==OP_IdxLT ); testcase( op==OP_IdxLE ); testcase( op==OP_IdxGT ); if( op!=OP_Noop ){ /* Load the value for the inequality constraint at the end of the ** range (if any). */ nConstraint = nEq; if( pRangeEnd ){ Expr *pRight = pRangeEnd->pExpr->pRight; sqlite4ExprCacheRemove(pParse, regBase+nEq, 1); sqlite4ExprCode(pParse, pRight, regBase+nEq); if( (pRangeEnd->wtFlags & TERM_VNULL)==0 ){ sqlite4ExprCodeIsNullJump(v, pRight, regBase+nEq, addrNxt); } if( zEndAff ){ if( sqlite4CompareAffinity(pRight, zEndAff[nEq])==SQLITE4_AFF_NONE){ /* Since the comparison is to be performed with no conversions ** applied to the operands, set the affinity to apply to pRight to ** SQLITE4_AFF_NONE. */ zEndAff[nEq] = SQLITE4_AFF_NONE; } if( sqlite4ExprNeedsNoAffinityChange(pRight, zEndAff[nEq]) ){ zEndAff[nEq] = SQLITE4_AFF_NONE; } } codeApplyAffinity(pParse, regBase, nEq+1, zEndAff); nConstraint++; testcase( pRangeEnd->wtFlags & TERM_VIRTUAL ); /* EV: R-30575-11662 */ } /* Now compute an end-key using OP_MakeIdxKey */ regEndKey = ++pParse->nMem; sqlite4VdbeAddOp4Int( v, OP_MakeIdxKey, iIdxCur, regBase, regEndKey, nConstraint ); } sqlite4DbFree(pParse->db, zStartAff); sqlite4DbFree(pParse->db, zEndAff); /* Top of the loop body */ pLevel->p2 = sqlite4VdbeCurrentAddr(v); |
︙ | ︙ | |||
4200 4201 4202 4203 4204 4205 4206 | if( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY && pIdx->eIndexType!=SQLITE4_INDEX_TEMP ){ sqlite4VdbeAddOp3(v, OP_SeekPk, iCur, 0, iIdxCur); } /* If there are inequality constraints, check that the value | | | > | | | | > > > > | | | | 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 3745 | if( pIdx->eIndexType!=SQLITE4_INDEX_PRIMARYKEY && pIdx->eIndexType!=SQLITE4_INDEX_TEMP ){ sqlite4VdbeAddOp3(v, OP_SeekPk, iCur, 0, iIdxCur); } /* If there are inequality constraints, check that the value ** of the table column that the inequality contrains is not NULL. ** If it is, jump to the next iteration of the loop. */ r1 = sqlite4GetTempReg(pParse); testcase( pLoop->wsFlags & WHERE_BTM_LIMIT ); testcase( pLoop->wsFlags & WHERE_TOP_LIMIT ); if( (pLoop->wsFlags & (WHERE_BTM_LIMIT|WHERE_TOP_LIMIT))!=0 ){ sqlite4ExprCodeGetColumnOfTable(v, pIdx->pTable, iCur, iIneq, r1); sqlite4VdbeAddOp2(v, OP_IsNull, r1, addrCont); } sqlite4ReleaseTempReg(pParse, r1); /* Record the instruction used to terminate the loop. Disable ** WHERE clause terms made redundant by the index range scan. */ if( pLoop->wsFlags & WHERE_ONEROW ){ pLevel->op = OP_Noop; }else if( bRev ){ pLevel->op = OP_Prev; }else{ pLevel->op = OP_Next; } pLevel->p1 = iIdxCur; if( (pLoop->wsFlags & WHERE_CONSTRAINT)==0 ){ pLevel->p5 = SQLITE4_STMTSTATUS_FULLSCAN_STEP; }else{ assert( pLevel->p5==0 ); } }else #ifndef SQLITE4_OMIT_OR_OPTIMIZATION if( pLoop->wsFlags & WHERE_MULTI_OR ){ /* Case 5: Two or more separately indexed terms connected by OR ** ** Example: ** ** CREATE TABLE t1(a,b,c,d); ** CREATE INDEX i1 ON t1(a); ** CREATE INDEX i2 ON t1(b); ** CREATE INDEX i3 ON t1(c); |
︙ | ︙ | |||
4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 | ** Return 2 # Jump back to the Gosub ** ** B: <after the loop> ** */ WhereClause *pOrWc; /* The OR-clause broken out into subterms */ SrcList *pOrTab; /* Shortened table list or OR-clause generation */ int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */ int regKeyset = 0; /* Register for RowSet object */ int regKey = 0; /* Register holding key */ int iLoopBody = sqlite4VdbeMakeLabel(v); /* Start of loop body */ int iRetInit; /* Address of regReturn init */ int untestedTerms = 0; /* Some terms not completely tested */ int ii; /* Loop counter */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ | > > | | | | | | > > > > > > > > > > > > > > > > | > | > > | | | > > | | < | | < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > | > > > > > > > | > > > > | > > > > > > > > > > | < > > | > > > > > | > > | | | > > > > > > > > < | | < < < < < < < | | < < < | | < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 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 3861 3862 3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925 3926 3927 3928 3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211 4212 4213 4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228 4229 4230 4231 4232 4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434 5435 5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594 5595 5596 5597 5598 5599 5600 5601 5602 5603 5604 5605 5606 5607 5608 5609 5610 5611 5612 5613 5614 5615 5616 5617 5618 5619 5620 5621 5622 5623 | ** Return 2 # Jump back to the Gosub ** ** B: <after the loop> ** */ WhereClause *pOrWc; /* The OR-clause broken out into subterms */ SrcList *pOrTab; /* Shortened table list or OR-clause generation */ Index *pCov = 0; /* Potential covering index (or NULL) */ int iCovCur = pParse->nTab++; /* Cursor used for index scans (if any) */ int regReturn = ++pParse->nMem; /* Register used with OP_Gosub */ int regKeyset = 0; /* Register for RowSet object */ int regKey = 0; /* Register holding key */ int iLoopBody = sqlite4VdbeMakeLabel(v); /* Start of loop body */ int iRetInit; /* Address of regReturn init */ int untestedTerms = 0; /* Some terms not completely tested */ int ii; /* Loop counter */ Expr *pAndExpr = 0; /* An ".. AND (...)" expression */ pTerm = pLoop->aLTerm[0]; assert( pTerm!=0 ); assert( pTerm->eOperator & WO_OR ); assert( (pTerm->wtFlags & TERM_ORINFO)!=0 ); pOrWc = &pTerm->u.pOrInfo->wc; pLevel->op = OP_Return; pLevel->p1 = regReturn; /* Set up a new SrcList in pOrTab containing the table being scanned ** by this loop in the a[0] slot and all notReady tables in a[1..] slots. ** This becomes the SrcList in the recursive call to sqlite4WhereBegin(). */ if( pWInfo->nLevel>1 ){ int nNotReady; /* The number of notReady tables */ struct SrcListItem *origSrc; /* Original list of tables */ nNotReady = pWInfo->nLevel - iLevel - 1; pOrTab = sqlite4StackAllocRaw(pParse->db, sizeof(*pOrTab)+ nNotReady*sizeof(pOrTab->a[0])); if( pOrTab==0 ) return notReady; pOrTab->nAlloc = (u8)(nNotReady + 1); pOrTab->nSrc = pOrTab->nAlloc; memcpy(pOrTab->a, pTabItem, sizeof(*pTabItem)); origSrc = pWInfo->pTabList->a; for(k=1; k<=nNotReady; k++){ memcpy(&pOrTab->a[k], &origSrc[pLevel[k].iFrom], sizeof(pOrTab->a[k])); } }else{ pOrTab = pWInfo->pTabList; } /* Initialize the keyset register to contain NULL. An SQL NULL is ** equivalent to an empty keyset. ** ** Also initialize regReturn to contain the address of the instruction ** immediately following the OP_Return at the bottom of the loop. This ** is required in a few obscure LEFT JOIN cases where control jumps ** over the top of the loop into the body of it. In this case the ** correct response for the end-of-loop code (the OP_Return) is to ** fall through to the next instruction, just as an OP_Next does if ** called on an uninitialized cursor. */ if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ regKeyset = ++pParse->nMem; regKey = ++pParse->nMem; sqlite4VdbeAddOp2(v, OP_Null, 0, regKeyset); } iRetInit = sqlite4VdbeAddOp2(v, OP_Integer, 0, regReturn); /* If the original WHERE clause is z of the form: (x1 OR x2 OR ...) AND y ** Then for every term xN, evaluate as the subexpression: xN AND z ** That way, terms in y that are factored into the disjunction will ** be picked up by the recursive calls to sqlite4WhereBegin() below. ** ** Actually, each subexpression is converted to "xN AND w" where w is ** the "interesting" terms of z - terms that did not originate in the ** ON or USING clause of a LEFT JOIN, and terms that are usable as ** indices. ** ** This optimization also only applies if the (x1 OR x2 OR ...) term ** is not contained in the ON clause of a LEFT JOIN. ** See ticket http://www.sqlite.org/src/info/f2369304e4 */ if( pWC->nTerm>1 ){ int iTerm; for(iTerm=0; iTerm<pWC->nTerm; iTerm++){ Expr *pExpr = pWC->a[iTerm].pExpr; if( ExprHasProperty(pExpr, EP_FromJoin) ) continue; if( pWC->a[iTerm].wtFlags & (TERM_VIRTUAL|TERM_ORINFO) ) continue; if( (pWC->a[iTerm].eOperator & WO_ALL)==0 ) continue; pExpr = sqlite4ExprDup(pParse->db, pExpr, 0); pAndExpr = sqlite4ExprAnd(pParse->db, pAndExpr, pExpr); } if( pAndExpr ){ pAndExpr = sqlite4PExpr(pParse, TK_AND, 0, pAndExpr, 0); } } for(ii=0; ii<pOrWc->nTerm; ii++){ WhereTerm *pOrTerm = &pOrWc->a[ii]; if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){ WhereInfo *pSubWInfo; /* Info for single OR-term scan */ Expr *pOrExpr = pOrTerm->pExpr; if( pAndExpr && !ExprHasProperty(pOrExpr, EP_FromJoin) ){ pAndExpr->pLeft = pOrExpr; pOrExpr = pAndExpr; } /* Loop through table entries that match term pOrTerm. */ pSubWInfo = sqlite4WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, WHERE_OMIT_OPEN_CLOSE | WHERE_AND_ONLY | WHERE_FORCE_TABLE | WHERE_ONETABLE_ONLY, iCovCur); assert( pSubWInfo || pParse->nErr || pParse->db->mallocFailed ); if( pSubWInfo ){ WhereLoop *pSubLoop; explainOneScan( pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 ); if( (pWInfo->wctrlFlags & WHERE_DUPLICATES_OK)==0 ){ int iSet = ((ii==pOrWc->nTerm-1)?-1:ii); sqlite4VdbeAddOp2(v, OP_RowKey, iCur, regKey); sqlite4VdbeAddOp4Int(v, OP_RowSetTest, regKeyset, sqlite4VdbeCurrentAddr(v)+2, regKey, iSet); } sqlite4VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody); /* The pSubWInfo->untestedTerms flag means that this OR term ** contained one or more AND term from a notReady table. The ** terms from the notReady table could not be tested and will ** need to be tested later. */ if( pSubWInfo->untestedTerms ) untestedTerms = 1; /* If all of the OR-connected terms are optimized using the same ** index, and the index is opened using the same cursor number ** by each call to sqlite4WhereBegin() made by this loop, it may ** be possible to use that index as a covering index. ** ** If the call to sqlite4WhereBegin() above resulted in a scan that ** uses an index, and this is either the first OR-connected term ** processed or the index is the same as that used by all previous ** terms, set pCov to the candidate covering index. Otherwise, set ** pCov to NULL to indicate that no candidate covering index will ** be available. */ #if 0 pSubLoop = pSubWInfo->a[0].pWLoop; assert( (pSubLoop->wsFlags & WHERE_AUTO_INDEX)==0 ); if( (pSubLoop->wsFlags & WHERE_INDEXED)!=0 && (ii==0 || pSubLoop->u.btree.pIndex==pCov) ){ assert( pSubWInfo->a[0].iIdxCur==iCovCur ); pCov = pSubLoop->u.btree.pIndex; }else{ pCov = 0; } #endif /* Finish the loop through table entries that match term pOrTerm. */ sqlite4WhereEnd(pSubWInfo); } } } pLevel->u.pCovidx = pCov; if( pCov ) pLevel->iIdxCur = iCovCur; if( pAndExpr ){ pAndExpr->pLeft = 0; sqlite4ExprDelete(pParse->db, pAndExpr); } sqlite4VdbeChangeP1(v, iRetInit, sqlite4VdbeCurrentAddr(v)); sqlite4VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk); sqlite4VdbeResolveLabel(v, iLoopBody); if( pWInfo->nLevel>1 ) sqlite4StackFree(pParse->db, pOrTab); if( !untestedTerms ) disableTerm(pLevel, pTerm); }else #endif /* SQLITE4_OMIT_OR_OPTIMIZATION */ { /* TODO: This case is currently being used. Why can't it use the ** index case instead? */ /* Case 6: There is no usable index. We must do a complete ** scan of the entire table. */ static const u8 aStep[] = { OP_Next, OP_Prev }; static const u8 aStart[] = { OP_Rewind, OP_Last }; assert( bRev==0 || bRev==1 ); pLevel->op = aStep[bRev]; pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite4VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); pLevel->p5 = SQLITE4_STMTSTATUS_FULLSCAN_STEP; } newNotReady = notReady & ~getMask(&pWInfo->sMaskSet, iCur); /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. ** ** IMPLEMENTATION-OF: R-49525-50935 Terms that cannot be satisfied through ** the use of indices become tests that are evaluated against each row of ** the relevant input tables. */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */ testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & newNotReady)!=0 ){ testcase( pWInfo->untestedTerms==0 && (pWInfo->wctrlFlags & WHERE_ONETABLE_ONLY)!=0 ); pWInfo->untestedTerms = 1; continue; } pE = pTerm->pExpr; assert( pE!=0 ); if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){ continue; } sqlite4ExprIfFalse(pParse, pE, addrCont, SQLITE4_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; } /* Insert code to test for implied constraints based on transitivity ** of the "==" operator. ** ** Example: If the WHERE clause contains "t1.a=t2.b" and "t2.b=123" ** and we are coding the t1 loop and the t2 loop has not yet coded, ** then we cannot use the "t1.a=t2.b" constraint, but we can code ** the implied "t1.a=123" constraint. */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; WhereTerm *pAlt; Expr sEq; if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( pTerm->eOperator!=(WO_EQUIV|WO_EQ) ) continue; if( pTerm->leftCursor!=iCur ) continue; if( pLevel->iLeftJoin ) continue; pE = pTerm->pExpr; assert( !ExprHasProperty(pE, EP_FromJoin) ); assert( (pTerm->prereqRight & newNotReady)!=0 ); pAlt = findTerm(pWC, iCur, pTerm->u.leftColumn, notReady, WO_EQ|WO_IN, 0); if( pAlt==0 ) continue; if( pAlt->wtFlags & (TERM_CODED) ) continue; testcase( pAlt->eOperator & WO_EQ ); testcase( pAlt->eOperator & WO_IN ); VdbeNoopComment((v, "begin transitive constraint")); sEq = *pAlt->pExpr; sEq.pLeft = pE->pLeft; sqlite4ExprIfFalse(pParse, &sEq, addrCont, SQLITE4_JUMPIFNULL); } /* For a LEFT OUTER JOIN, generate code that will record the fact that ** at least one row of the right table has matched the left table. */ if( pLevel->iLeftJoin ){ pLevel->addrFirst = sqlite4VdbeCurrentAddr(v); sqlite4VdbeAddOp2(v, OP_Integer, 1, pLevel->iLeftJoin); VdbeComment((v, "record LEFT JOIN hit")); sqlite4ExprCacheClear(pParse); for(pTerm=pWC->a, j=0; j<pWC->nTerm; j++, pTerm++){ testcase( pTerm->wtFlags & TERM_VIRTUAL ); /* IMP: R-30575-11662 */ testcase( pTerm->wtFlags & TERM_CODED ); if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue; if( (pTerm->prereqAll & newNotReady)!=0 ){ assert( pWInfo->untestedTerms ); continue; } assert( pTerm->pExpr ); sqlite4ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE4_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; } } sqlite4ReleaseTempReg(pParse, iReleaseReg); return newNotReady; } #ifdef WHERETRACE_ENABLED /* ** Print a WhereLoop object for debugging purposes */ static void whereLoopPrint(WhereLoop *p, SrcList *pTabList){ int nb = 1+(pTabList->nSrc+7)/8; struct SrcListItem *pItem = pTabList->a + p->iTab; Table *pTab = pItem->pTab; sqlite4DebugPrintf("%c%2d.%0*llx.%0*llx", p->cId, p->iTab, nb, p->maskSelf, nb, p->prereq); sqlite4DebugPrintf(" %12s", pItem->zAlias ? pItem->zAlias : pTab->zName); if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ if( p->u.btree.pIndex ){ const char *zName = p->u.btree.pIndex->zName; if( zName==0 ) zName = "ipk"; if( strncmp(zName, "sqlite_autoindex_", 17)==0 ){ int i = sqlite4Strlen30(zName) - 1; while( zName[i]!='_' ) i--; zName += i; } sqlite4DebugPrintf(".%-16s %2d", zName, p->u.btree.nEq); }else{ sqlite4DebugPrintf("%20s",""); } }else{ char *z; if( p->u.vtab.idxStr ){ z = sqlite4_mprintf(0, "(%d,\"%s\",%x)", p->u.vtab.idxNum, p->u.vtab.idxStr, p->u.vtab.omitMask); }else{ z = sqlite4_mprintf(0, "(%d,%x)", p->u.vtab.idxNum, p->u.vtab.omitMask); } sqlite4DebugPrintf(" %-19s", z); sqlite4_free(0, z); } sqlite4DebugPrintf(" f %04x N %d", p->wsFlags, p->nLTerm); sqlite4DebugPrintf(" cost %d,%d,%d\n", p->rSetup, p->rRun, p->nOut); } #endif /* ** Convert bulk memory into a valid WhereLoop that can be passed ** to whereLoopClear harmlessly. */ static void whereLoopInit(WhereLoop *p){ p->aLTerm = p->aLTermSpace; p->nLTerm = 0; p->nLSlot = ArraySize(p->aLTermSpace); p->wsFlags = 0; } /* ** Clear the WhereLoop.u union. Leave WhereLoop.pLTerm intact. */ static void whereLoopClearUnion(sqlite4 *db, WhereLoop *p){ if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){ if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){ #if 0 sqlite4_free(p->u.vtab.idxStr); #endif p->u.vtab.needFree = 0; p->u.vtab.idxStr = 0; }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){ sqlite4DbFree(db, p->u.btree.pIndex->zColAff); sqlite4DbFree(db, p->u.btree.pIndex); p->u.btree.pIndex = 0; } } } /* ** Deallocate internal memory used by a WhereLoop object */ static void whereLoopClear(sqlite4 *db, WhereLoop *p){ if( p->aLTerm!=p->aLTermSpace ) sqlite4DbFree(db, p->aLTerm); whereLoopClearUnion(db, p); whereLoopInit(p); } /* ** Increase the memory allocation for pLoop->aLTerm[] to be at least n. */ static int whereLoopResize(sqlite4 *db, WhereLoop *p, int n){ WhereTerm **paNew; if( p->nLSlot>=n ) return SQLITE4_OK; n = (n+7)&~7; paNew = sqlite4DbMallocRaw(db, sizeof(p->aLTerm[0])*n); if( paNew==0 ) return SQLITE4_NOMEM; memcpy(paNew, p->aLTerm, sizeof(p->aLTerm[0])*p->nLSlot); if( p->aLTerm!=p->aLTermSpace ) sqlite4DbFree(db, p->aLTerm); p->aLTerm = paNew; p->nLSlot = n; return SQLITE4_OK; } /* ** Transfer content from the second pLoop into the first. */ static int whereLoopXfer(sqlite4 *db, WhereLoop *pTo, WhereLoop *pFrom){ if( whereLoopResize(db, pTo, pFrom->nLTerm) ) return SQLITE4_NOMEM; whereLoopClearUnion(db, pTo); memcpy(pTo, pFrom, WHERE_LOOP_XFER_SZ); memcpy(pTo->aLTerm, pFrom->aLTerm, pTo->nLTerm*sizeof(pTo->aLTerm[0])); if( pFrom->wsFlags & WHERE_VIRTUALTABLE ){ pFrom->u.vtab.needFree = 0; }else if( (pFrom->wsFlags & WHERE_AUTO_INDEX)!=0 ){ pFrom->u.btree.pIndex = 0; } return SQLITE4_OK; } /* ** Delete a WhereLoop object */ static void whereLoopDelete(sqlite4 *db, WhereLoop *p){ whereLoopClear(db, p); sqlite4DbFree(db, p); } /* ** Free a WhereInfo structure */ static void whereInfoFree(sqlite4 *db, WhereInfo *pWInfo){ if( ALWAYS(pWInfo) ){ whereClauseClear(&pWInfo->sWC); while( pWInfo->pLoops ){ WhereLoop *p = pWInfo->pLoops; pWInfo->pLoops = p->pNextLoop; whereLoopDelete(db, p); } sqlite4DbFree(db, pWInfo); } } /* ** Insert or replace a WhereLoop entry using the template supplied. ** ** An existing WhereLoop entry might be overwritten if the new template ** is better and has fewer dependencies. Or the template will be ignored ** and no insert will occur if an existing WhereLoop is faster and has ** fewer dependencies than the template. Otherwise a new WhereLoop is ** added based on the template. ** ** If pBuilder->pBest is not NULL then we only care about the very ** best template and that template should be stored in pBuilder->pBest. ** If pBuilder->pBest is NULL then a list of the best templates are stored ** in pBuilder->pWInfo->pLoops. ** ** When accumulating multiple loops (when pBuilder->pBest is NULL) we ** still might overwrite similar loops with the new template if the ** template is better. Loops may be overwritten if the following ** conditions are met: ** ** (1) They have the same iTab. ** (2) They have the same iSortIdx. ** (3) The template has same or fewer dependencies than the current loop ** (4) The template has the same or lower cost than the current loop ** (5) The template uses more terms of the same index but has no additional ** dependencies */ static int whereLoopInsert(WhereLoopBuilder *pBuilder, WhereLoop *pTemplate){ WhereLoop **ppPrev, *p, *pNext = 0; WhereInfo *pWInfo = pBuilder->pWInfo; sqlite4 *db = pWInfo->pParse->db; assert( pTemplate->u.btree.pIndex || !(pTemplate->wsFlags & WHERE_INDEXED) ); /* If pBuilder->pBest is defined, then only keep track of the single ** best WhereLoop. pBuilder->pBest->maskSelf==0 indicates that no ** prior WhereLoops have been evaluated and that the current pTemplate ** is therefore the first and hence the best and should be retained. */ if( (p = pBuilder->pBest)!=0 ){ if( p->maskSelf!=0 ){ WhereCost rCost = whereCostAdd(p->rRun,p->rSetup); WhereCost rTemplate = whereCostAdd(pTemplate->rRun,pTemplate->rSetup); if( rCost < rTemplate ){ testcase( rCost==rTemplate-1 ); goto whereLoopInsert_noop; } if( rCost==rTemplate && (p->prereq & pTemplate->prereq)==p->prereq ){ goto whereLoopInsert_noop; } } #if WHERETRACE_ENABLED if( sqlite4WhereTrace & 0x8 ){ sqlite4DebugPrintf(p->maskSelf==0 ? "ins-init: " : "ins-best: "); whereLoopPrint(pTemplate, pWInfo->pTabList); } #endif whereLoopXfer(db, p, pTemplate); return SQLITE4_OK; } /* Search for an existing WhereLoop to overwrite, or which takes ** priority over pTemplate. */ for(ppPrev=&pWInfo->pLoops, p=*ppPrev; p; ppPrev=&p->pNextLoop, p=*ppPrev){ if( p->iTab!=pTemplate->iTab || p->iSortIdx!=pTemplate->iSortIdx ){ /* If either the iTab or iSortIdx values for two WhereLoop are different ** then those WhereLoops need to be considered separately. Neither is ** a candidate to replace the other. */ continue; } /* In the current implementation, the rSetup value is either zero ** or the cost of building an automatic index (NlogN) and the NlogN ** is the same for compatible WhereLoops. */ assert( p->rSetup==0 || pTemplate->rSetup==0 || p->rSetup==pTemplate->rSetup ); /* whereLoopAddBtree() always generates and inserts the automatic index ** case first. Hence compatible candidate WhereLoops never have a larger ** rSetup. Call this SETUP-INVARIANT */ assert( p->rSetup>=pTemplate->rSetup ); if( (p->prereq & pTemplate->prereq)==p->prereq && p->rSetup<=pTemplate->rSetup && p->rRun<=pTemplate->rRun ){ /* This branch taken when p is equal or better than pTemplate in ** all of (1) dependences (2) setup-cost, and (3) run-cost. */ assert( p->rSetup==pTemplate->rSetup ); if( p->nLTerm<pTemplate->nLTerm && (p->wsFlags & WHERE_INDEXED)!=0 && (pTemplate->wsFlags & WHERE_INDEXED)!=0 && p->u.btree.pIndex==pTemplate->u.btree.pIndex && p->prereq==pTemplate->prereq ){ /* Overwrite an existing WhereLoop with an similar one that uses ** more terms of the index */ pNext = p->pNextLoop; break; }else{ /* pTemplate is not helpful. ** Return without changing or adding anything */ goto whereLoopInsert_noop; } } if( (p->prereq & pTemplate->prereq)==pTemplate->prereq && p->rRun>=pTemplate->rRun && ALWAYS(p->rSetup>=pTemplate->rSetup) /* See SETUP-INVARIANT above */ ){ /* Overwrite an existing WhereLoop with a better one: one that is ** better at one of (1) dependences, (2) setup-cost, or (3) run-cost ** and is no worse in any of those categories. */ pNext = p->pNextLoop; break; } } /* If we reach this point it means that either p[] should be overwritten ** with pTemplate[] if p[] exists, or if p==NULL then allocate a new ** WhereLoop and insert it. */ #if WHERETRACE_ENABLED if( sqlite4WhereTrace & 0x8 ){ if( p!=0 ){ sqlite4DebugPrintf("ins-del: "); whereLoopPrint(p, pWInfo->pTabList); } sqlite4DebugPrintf("ins-new: "); whereLoopPrint(pTemplate, pWInfo->pTabList); } #endif if( p==0 ){ p = sqlite4DbMallocRaw(db, sizeof(WhereLoop)); if( p==0 ) return SQLITE4_NOMEM; whereLoopInit(p); } whereLoopXfer(db, p, pTemplate); p->pNextLoop = pNext; *ppPrev = p; if( (p->wsFlags & WHERE_VIRTUALTABLE)==0 ){ Index *pIndex = p->u.btree.pIndex; if( pIndex && pIndex->tnum==0 ){ p->u.btree.pIndex = 0; } } return SQLITE4_OK; /* Jump here if the insert is a no-op */ whereLoopInsert_noop: #if WHERETRACE_ENABLED if( sqlite4WhereTrace & 0x8 ){ sqlite4DebugPrintf(pBuilder->pBest ? "ins-skip: " : "ins-noop: "); whereLoopPrint(pTemplate, pWInfo->pTabList); } #endif return SQLITE4_OK; } /* ** We have so far matched pBuilder->pNew->u.btree.nEq terms of the index pIndex. ** Try to match one more. */ static int whereLoopAddBtreeIndex( WhereLoopBuilder *pBuilder, /* The WhereLoop factory */ struct SrcListItem *pSrc, /* FROM clause term being analyzed */ Index *pProbe, /* An index on pSrc */ WhereCost nInMul /* log(Number of iterations due to IN) */ ){ WhereInfo *pWInfo = pBuilder->pWInfo; /* WHERE analyse context */ Parse *pParse = pWInfo->pParse; /* Parsing context */ sqlite4 *db = pParse->db; /* Database connection malloc context */ WhereLoop *pNew; /* Template WhereLoop under construction */ WhereTerm *pTerm; /* A WhereTerm under consideration */ int opMask; /* Valid operators for constraints */ WhereScan scan; /* Iterator for WHERE terms */ Bitmask saved_prereq; /* Original value of pNew->prereq */ u16 saved_nLTerm; /* Original value of pNew->nLTerm */ int saved_nEq; /* Original value of pNew->u.btree.nEq */ u32 saved_wsFlags; /* Original value of pNew->wsFlags */ WhereCost saved_nOut; /* Original value of pNew->nOut */ int iCol; /* Index of the column in the table */ int rc = SQLITE4_OK; /* Return code */ WhereCost nRowEst; /* Estimated index selectivity */ WhereCost rLogSize; /* Logarithm of table size */ WhereTerm *pTop = 0, *pBtm = 0; /* Top and bottom range constraints */ assert( pProbe->eIndexType==SQLITE4_INDEX_USER || pProbe->eIndexType==SQLITE4_INDEX_UNIQUE || pProbe->eIndexType==SQLITE4_INDEX_PRIMARYKEY ); pNew = pBuilder->pNew; if( db->mallocFailed ) return SQLITE4_NOMEM; assert( (pNew->wsFlags & WHERE_VIRTUALTABLE)==0 ); assert( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 ); if( pNew->wsFlags & WHERE_BTM_LIMIT ){ opMask = WO_LT|WO_LE; }else if( pProbe->tnum<=0 || (pSrc->jointype & JT_LEFT)!=0 ){ opMask = WO_EQ|WO_IN|WO_GT|WO_GE|WO_LT|WO_LE; }else{ opMask = WO_EQ|WO_IN|WO_ISNULL|WO_GT|WO_GE|WO_LT|WO_LE; } if( pProbe->bUnordered ) opMask &= ~(WO_GT|WO_GE|WO_LT|WO_LE); if( pNew->u.btree.nEq < pProbe->nColumn ){ iCol = pProbe->aiColumn[pNew->u.btree.nEq]; nRowEst = whereCost(pProbe->aiRowEst[pNew->u.btree.nEq+1]); if( nRowEst==0 && pProbe->onError==OE_None ) nRowEst = 1; }else if( pProbe->eIndexType!=SQLITE4_INDEX_PRIMARYKEY ){ Index *pPk; pPk = sqlite4FindPrimaryKey(pProbe->pTable, 0); iCol = idxColumnNumber(pProbe, pPk, pNew->u.btree.nEq); nRowEst = 0; }else{ return SQLITE4_OK; } assert( iCol>=-1 ); pTerm = whereScanInit(&scan, pBuilder->pWC, pSrc->iCursor, iCol, opMask, pProbe); saved_nEq = pNew->u.btree.nEq; saved_nLTerm = pNew->nLTerm; saved_wsFlags = pNew->wsFlags; saved_prereq = pNew->prereq; saved_nOut = pNew->nOut; pNew->rSetup = 0; rLogSize = estLog(whereCost(pProbe->aiRowEst[0])); for(; rc==SQLITE4_OK && pTerm!=0; pTerm = whereScanNext(&scan)){ int nIn = 0; if( pTerm->prereqRight & pNew->maskSelf ) continue; #ifdef SQLITE4_ENABLE_STAT3 if( (pTerm->wtFlags & TERM_VNULL)!=0 && pSrc->pTab->aCol[iCol].notNull ){ continue; /* skip IS NOT NULL constraints on a NOT NULL column */ } #endif pNew->wsFlags = saved_wsFlags; pNew->u.btree.nEq = saved_nEq; pNew->nLTerm = saved_nLTerm; if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */ pNew->aLTerm[pNew->nLTerm++] = pTerm; pNew->prereq = (saved_prereq | pTerm->prereqRight) & ~pNew->maskSelf; pNew->rRun = rLogSize; /* Baseline cost is log2(N). Adjustments below */ if( pTerm->eOperator & WO_IN ){ Expr *pExpr = pTerm->pExpr; pNew->wsFlags |= WHERE_COLUMN_IN; if( ExprHasProperty(pExpr, EP_xIsSelect) ){ /* "x IN (SELECT ...)": TUNING: the SELECT returns 25 rows */ nIn = 46; assert( 46==whereCost(25) ); }else if( ALWAYS(pExpr->x.pList && pExpr->x.pList->nExpr) ){ /* "x IN (value, value, ...)" */ nIn = whereCost(pExpr->x.pList->nExpr); } pNew->rRun += nIn; pNew->u.btree.nEq++; pNew->nOut = nRowEst + nInMul + nIn; }else if( pTerm->eOperator & (WO_EQ) ){ assert( (pNew->wsFlags & (WHERE_COLUMN_NULL|WHERE_COLUMN_IN))!=0 || nInMul==0 ); pNew->wsFlags |= WHERE_COLUMN_EQ; if( iCol<0 || (pProbe->onError!=OE_None && nInMul==0 && pNew->u.btree.nEq==pProbe->nColumn-1) ){ assert( (pNew->wsFlags & WHERE_COLUMN_IN)==0 || iCol<0 ); pNew->wsFlags |= WHERE_ONEROW; } pNew->u.btree.nEq++; pNew->nOut = nRowEst + nInMul; }else if( pTerm->eOperator & (WO_ISNULL) ){ pNew->wsFlags |= WHERE_COLUMN_NULL; pNew->u.btree.nEq++; /* TUNING: IS NULL selects 2 rows */ nIn = 10; assert( 10==whereCost(2) ); pNew->nOut = nRowEst + nInMul + nIn; }else if( pTerm->eOperator & (WO_GT|WO_GE) ){ testcase( pTerm->eOperator & WO_GT ); testcase( pTerm->eOperator & WO_GE ); pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT; pBtm = pTerm; pTop = 0; }else{ assert( pTerm->eOperator & (WO_LT|WO_LE) ); testcase( pTerm->eOperator & WO_LT ); testcase( pTerm->eOperator & WO_LE ); pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_TOP_LIMIT; pTop = pTerm; pBtm = (pNew->wsFlags & WHERE_BTM_LIMIT)!=0 ? pNew->aLTerm[pNew->nLTerm-2] : 0; } if( pNew->wsFlags & WHERE_COLUMN_RANGE ){ /* Adjust nOut and rRun for STAT3 range values */ WhereCost rDiv; whereRangeScanEst(pParse, pProbe, pNew->u.btree.nEq, pBtm, pTop, &rDiv); pNew->nOut = saved_nOut>rDiv+10 ? saved_nOut - rDiv : 10; } #ifdef SQLITE4_ENABLE_STAT3 if( pNew->u.btree.nEq==1 && pProbe->nSample && OptimizationEnabled(db, SQLITE4_Stat3) ){ tRowcnt nOut = 0; if( (pTerm->eOperator & (WO_EQ|WO_ISNULL))!=0 ){ testcase( pTerm->eOperator & WO_EQ ); testcase( pTerm->eOperator & WO_ISNULL ); rc = whereEqualScanEst(pParse, pProbe, pTerm->pExpr->pRight, &nOut); }else if( (pTerm->eOperator & WO_IN) && !ExprHasProperty(pTerm->pExpr, EP_xIsSelect) ){ rc = whereInScanEst(pParse, pProbe, pTerm->pExpr->x.pList, &nOut); } if( rc==SQLITE4_OK ) pNew->nOut = whereCost(nOut); } #endif if( (pNew->wsFlags & (WHERE_IDX_ONLY|WHERE_IPK))==0 ){ /* Each row involves a step of the index, then a binary search of ** the main table */ pNew->rRun = whereCostAdd(pNew->rRun, rLogSize>27 ? rLogSize-17 : 10); } /* Step cost for each output row */ pNew->rRun = whereCostAdd(pNew->rRun, pNew->nOut); /* TBD: Adjust nOut for additional constraints */ rc = whereLoopInsert(pBuilder, pNew); if( (pNew->wsFlags & WHERE_TOP_LIMIT)==0 && pNew->u.btree.nEq<(pProbe->nColumn + (pProbe->zName!=0)) ){ whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, nInMul+nIn); } } pNew->prereq = saved_prereq; pNew->u.btree.nEq = saved_nEq; pNew->wsFlags = saved_wsFlags; pNew->nOut = saved_nOut; pNew->nLTerm = saved_nLTerm; return rc; } /* ** Return True if it is possible that pIndex might be useful in ** implementing the ORDER BY clause in pBuilder. ** ** Return False if pBuilder does not contain an ORDER BY clause or ** if there is no way for pIndex to be useful in implementing that ** ORDER BY clause. */ static int indexMightHelpWithOrderBy( WhereLoopBuilder *pBuilder, Index *pIndex, int iCursor ){ ExprList *pOB; int ii, jj; if( pIndex->bUnordered ) return 0; if( (pOB = pBuilder->pWInfo->pOrderBy)==0 ) return 0; for(ii=0; ii<pOB->nExpr; ii++){ Expr *pExpr = sqlite4ExprSkipCollate(pOB->a[ii].pExpr); if( pExpr->op!=TK_COLUMN ) return 0; if( pExpr->iTable==iCursor ){ for(jj=0; jj<pIndex->nColumn; jj++){ if( pExpr->iColumn==pIndex->aiColumn[jj] ) return 1; } } } return 0; } /* ** Return a bitmask where 1s indicate that the corresponding column of ** the table is used by an index. Only the first 63 columns are considered. */ static Bitmask columnsInIndex(Index *pIdx){ Bitmask m = 0; int j; for(j=pIdx->nColumn-1; j>=0; j--){ int x = pIdx->aiColumn[j]; testcase( x==BMS-1 ); testcase( x==BMS-2 ); if( x<BMS-1 ) m |= MASKBIT(x); } return m; } /* ** Add all WhereLoop objects for a single table of the join where the table ** is idenfied by pBuilder->pNew->iTab. That table is guaranteed to be ** a b-tree table, not a virtual table. */ static int whereLoopAddBtree( WhereLoopBuilder *pBuilder, /* WHERE clause information */ Bitmask mExtra /* Extra prerequesites for using this table */ ){ WhereInfo *pWInfo; /* WHERE analysis context */ Index *pProbe; /* An index we are evaluating */ Index *pPk; /* Primary key index for table pSrc */ tRowcnt aiRowEstPk[2]; /* The aiRowEst[] value for the sPk index */ int aiColumnPk = -1; /* The aColumn[] value for the sPk index */ SrcList *pTabList; /* The FROM clause */ struct SrcListItem *pSrc; /* The FROM clause btree term to add */ WhereLoop *pNew; /* Template WhereLoop object */ int rc = SQLITE4_OK; /* Return code */ int iSortIdx = 1; /* Index number */ int b; /* A boolean value */ WhereCost rSize; /* number of rows in the table */ WhereCost rLogSize; /* Logarithm of the number of rows in the table */ pNew = pBuilder->pNew; pWInfo = pBuilder->pWInfo; pTabList = pWInfo->pTabList; pSrc = pTabList->a + pNew->iTab; assert( !IsVirtual(pSrc->pTab) ); pPk = sqlite4FindPrimaryKey(pSrc->pTab, 0); if( pSrc->pIndex ){ /* An INDEXED BY clause specifies a particular index to use */ pProbe = pSrc->pIndex; }else if( pSrc->notIndexed ){ /* A NOT INDEXED clause means use the PK index */ pProbe = pPk; }else{ /* Otherwise, consider all indexes */ pProbe = pSrc->pTab->pIndex; } rSize = whereCost(pSrc->pTab->nRowEst); rLogSize = estLog(rSize); #ifndef SQLITE4_OMIT_AUTOMATIC_INDEX /* Automatic indexes */ if( !pBuilder->pBest && (pWInfo->pParse->db->flags & SQLITE4_AutoIndex)!=0 && pSrc->pIndex==0 #if 0 && !pSrc->viaCoroutine #endif && !pSrc->notIndexed && !pSrc->isCorrelated ){ /* Generate auto-index WhereLoops */ WhereClause *pWC = pBuilder->pWC; WhereTerm *pTerm; WhereTerm *pWCEnd = pWC->a + pWC->nTerm; for(pTerm=pWC->a; rc==SQLITE4_OK && pTerm<pWCEnd; pTerm++){ if( pTerm->prereqRight & pNew->maskSelf ) continue; if( termCanDriveIndex(pTerm, pSrc, 0) ){ pNew->u.btree.nEq = 1; pNew->u.btree.pIndex = 0; pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; /* TUNING: One-time cost for computing the automatic index is ** approximately 7*N*log2(N) where N is the number of rows in ** the table being indexed. */ pNew->rSetup = rLogSize + rSize + 28; assert( 28==whereCost(7) ); /* TUNING: Each index lookup yields 20 rows in the table. This ** is more than the usual guess of 10 rows, since we have no way ** of knowning how selective the index will ultimately be. It would ** not be unreasonable to make this value much larger. */ pNew->nOut = 43; assert( 43==whereCost(20) ); pNew->rRun = whereCostAdd(rLogSize,pNew->nOut); pNew->wsFlags = WHERE_AUTO_INDEX; pNew->prereq = mExtra | pTerm->prereqRight; rc = whereLoopInsert(pBuilder, pNew); } } } #endif /* ifndef SQLITE4_OMIT_AUTOMATIC_INDEX */ /* If this table has no primary key, then it is either a materialized ** view or ephemeral table. Either way, add a WhereLoop for a full-scan ** of it. */ if( pPk==0 ){ assert( pSrc->pTab->pSelect || (pSrc->pTab->tabFlags & TF_Ephemeral) ); pNew->u.btree.nEq = 0; pNew->nLTerm = 0; pNew->iSortIdx = 0; pNew->rSetup = 0; pNew->prereq = mExtra; pNew->nOut = rSize; pNew->u.btree.pIndex = 0; pNew->wsFlags = 0; pNew->rRun = whereCostAdd(rSize,rLogSize) + 16; rc = whereLoopInsert(pBuilder, pNew); } /* Loop through the set of indices being considered. */ for(; rc==SQLITE4_OK && pProbe; pProbe=pProbe->pNext, iSortIdx++){ if( pProbe->eIndexType==SQLITE4_INDEX_FTS5 ) continue; assert( pProbe->tnum>0 ); pNew->u.btree.nEq = 0; pNew->nLTerm = 0; pNew->rSetup = 0; pNew->prereq = mExtra; pNew->nOut = rSize; pNew->u.btree.pIndex = pProbe; pNew->wsFlags = WHERE_INDEXED; b = indexMightHelpWithOrderBy(pBuilder, pProbe, pSrc->iCursor); /* The ONEPASS_DESIRED flags never occurs together with ORDER BY */ assert( (pWInfo->wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || b==0 ); pNew->iSortIdx = b ? iSortIdx : 0; if( pProbe==pPk || b ){ /* Add a WhereLoop for full-scan via primary key index. */ /* TUNING: Cost of full table scan is 3*(N + log2(N)). ** + The extra 3 factor is to encourage the use of indexed lookups ** over full scans. A smaller constant 2 is used for covering ** index scans so that a covering index scan will be favored over ** a table scan. */ /* TODO: Fix tuning for src4 as described in comment immediately above. */ pNew->rRun = whereCostAdd(rSize,rLogSize) + 16; rc = whereLoopInsert(pBuilder, pNew); if( rc ) break; } rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0); /* If there was an INDEXED BY or NOT INDEXED clause, then only one ** index is considered. */ if( pSrc->pIndex || pSrc->notIndexed ) break; } return rc; } #ifndef SQLITE4_OMIT_VIRTUALTABLE /* ** Add all WhereLoop objects for a table of the join identified by ** pBuilder->pNew->iTab. That table is guaranteed to be a virtual table. */ static int whereLoopAddVirtual( WhereLoopBuilder *pBuilder /* WHERE clause information */ ){ WhereInfo *pWInfo; /* WHERE analysis context */ Parse *pParse; /* The parsing context */ WhereClause *pWC; /* The WHERE clause */ struct SrcListItem *pSrc; /* The FROM clause term to search */ Table *pTab; sqlite4 *db; sqlite4_index_info *pIdxInfo; struct sqlite4_index_constraint *pIdxCons; struct sqlite4_index_constraint_usage *pUsage; WhereTerm *pTerm; int i, j; int iTerm, mxTerm; int nConstraint; int seenIn = 0; /* True if an IN operator is seen */ int seenVar = 0; /* True if a non-constant constraint is seen */ int iPhase; /* 0: const w/o IN, 1: const, 2: no IN, 2: IN */ WhereLoop *pNew; int rc = SQLITE4_OK; pWInfo = pBuilder->pWInfo; pParse = pWInfo->pParse; db = pParse->db; pWC = pBuilder->pWC; pNew = pBuilder->pNew; pSrc = &pWInfo->pTabList->a[pNew->iTab]; pTab = pSrc->pTab; assert( IsVirtual(pTab) ); pIdxInfo = allocateIndexInfo(pParse, pWC, pSrc, pBuilder->pOrderBy); if( pIdxInfo==0 ) return SQLITE4_NOMEM; pNew->prereq = 0; pNew->rSetup = 0; pNew->wsFlags = WHERE_VIRTUALTABLE; pNew->nLTerm = 0; pNew->u.vtab.needFree = 0; pUsage = pIdxInfo->aConstraintUsage; nConstraint = pIdxInfo->nConstraint; if( whereLoopResize(db, pNew, nConstraint) ){ sqlite4DbFree(db, pIdxInfo); return SQLITE4_NOMEM; } for(iPhase=0; iPhase<=3; iPhase++){ if( !seenIn && (iPhase&1)!=0 ){ iPhase++; if( iPhase>3 ) break; } if( !seenVar && iPhase>1 ) break; pIdxCons = *(struct sqlite4_index_constraint**)&pIdxInfo->aConstraint; for(i=0; i<pIdxInfo->nConstraint; i++, pIdxCons++){ j = pIdxCons->iTermOffset; pTerm = &pWC->a[j]; switch( iPhase ){ case 0: /* Constants without IN operator */ pIdxCons->usable = 0; if( (pTerm->eOperator & WO_IN)!=0 ){ seenIn = 1; } if( pTerm->prereqRight!=0 ){ seenVar = 1; }else if( (pTerm->eOperator & WO_IN)==0 ){ pIdxCons->usable = 1; } break; case 1: /* Constants with IN operators */ assert( seenIn ); pIdxCons->usable = (pTerm->prereqRight==0); break; case 2: /* Variables without IN */ assert( seenVar ); pIdxCons->usable = (pTerm->eOperator & WO_IN)==0; break; default: /* Variables with IN */ assert( seenVar && seenIn ); pIdxCons->usable = 1; break; } } memset(pUsage, 0, sizeof(pUsage[0])*pIdxInfo->nConstraint); if( pIdxInfo->needToFreeIdxStr ) sqlite4_free(pIdxInfo->idxStr); pIdxInfo->idxStr = 0; pIdxInfo->idxNum = 0; pIdxInfo->needToFreeIdxStr = 0; pIdxInfo->orderByConsumed = 0; pIdxInfo->estimatedCost = SQLITE4_BIG_DBL / (double)2; rc = vtabBestIndex(pParse, pTab, pIdxInfo); if( rc ) goto whereLoopAddVtab_exit; pIdxCons = *(struct sqlite4_index_constraint**)&pIdxInfo->aConstraint; pNew->prereq = 0; mxTerm = -1; assert( pNew->nLSlot>=nConstraint ); for(i=0; i<nConstraint; i++) pNew->aLTerm[i] = 0; pNew->u.vtab.omitMask = 0; for(i=0; i<nConstraint; i++, pIdxCons++){ if( (iTerm = pUsage[i].argvIndex - 1)>=0 ){ j = pIdxCons->iTermOffset; if( iTerm>=nConstraint || j<0 || j>=pWC->nTerm || pNew->aLTerm[iTerm]!=0 ){ rc = SQLITE4_ERROR; sqlite4ErrorMsg(pParse, "%s.xBestIndex() malfunction", pTab->zName); goto whereLoopAddVtab_exit; } testcase( iTerm==nConstraint-1 ); testcase( j==0 ); testcase( j==pWC->nTerm-1 ); pTerm = &pWC->a[j]; pNew->prereq |= pTerm->prereqRight; assert( iTerm<pNew->nLSlot ); pNew->aLTerm[iTerm] = pTerm; if( iTerm>mxTerm ) mxTerm = iTerm; testcase( iTerm==15 ); testcase( iTerm==16 ); if( iTerm<16 && pUsage[i].omit ) pNew->u.vtab.omitMask |= 1<<iTerm; if( (pTerm->eOperator & WO_IN)!=0 ){ if( pUsage[i].omit==0 ){ /* Do not attempt to use an IN constraint if the virtual table ** says that the equivalent EQ constraint cannot be safely omitted. ** If we do attempt to use such a constraint, some rows might be ** repeated in the output. */ break; } /* A virtual table that is constrained by an IN clause may not ** consume the ORDER BY clause because (1) the order of IN terms ** is not necessarily related to the order of output terms and ** (2) Multiple outputs from a single IN value will not merge ** together. */ pIdxInfo->orderByConsumed = 0; } } } if( i>=nConstraint ){ pNew->nLTerm = mxTerm+1; assert( pNew->nLTerm<=pNew->nLSlot ); pNew->u.vtab.idxNum = pIdxInfo->idxNum; pNew->u.vtab.needFree = pIdxInfo->needToFreeIdxStr; pIdxInfo->needToFreeIdxStr = 0; pNew->u.vtab.idxStr = pIdxInfo->idxStr; pNew->u.vtab.isOrdered = (u8)((pIdxInfo->nOrderBy!=0) && pIdxInfo->orderByConsumed); pNew->rSetup = 0; pNew->rRun = whereCostFromDouble(pIdxInfo->estimatedCost); /* TUNING: Every virtual table query returns 25 rows */ pNew->nOut = 46; assert( 46==whereCost(25) ); whereLoopInsert(pBuilder, pNew); if( pNew->u.vtab.needFree ){ sqlite4_free(pNew->u.vtab.idxStr); pNew->u.vtab.needFree = 0; } } } whereLoopAddVtab_exit: if( pIdxInfo->needToFreeIdxStr ) sqlite4_free(pIdxInfo->idxStr); sqlite4DbFree(db, pIdxInfo); return rc; } #endif /* SQLITE4_OMIT_VIRTUALTABLE */ /* ** Add WhereLoop entries to handle OR terms. This works for either ** btrees or virtual tables. */ static int whereLoopAddOr(WhereLoopBuilder *pBuilder, Bitmask mExtra){ WhereInfo *pWInfo = pBuilder->pWInfo; WhereClause *pWC; WhereLoop *pNew; WhereTerm *pTerm, *pWCEnd; int rc = SQLITE4_OK; int iCur; WhereClause tempWC; WhereLoopBuilder sSubBuild; WhereLoop sBest; struct SrcListItem *pItem; pWC = pBuilder->pWC; if( pWInfo->wctrlFlags & WHERE_AND_ONLY ) return SQLITE4_OK; pWCEnd = pWC->a + pWC->nTerm; pNew = pBuilder->pNew; for(pTerm=pWC->a; pTerm<pWCEnd && rc==SQLITE4_OK; pTerm++){ if( (pTerm->eOperator & WO_OR)!=0 && (pTerm->u.pOrInfo->indexable & pNew->maskSelf)!=0 ){ WhereClause * const pOrWC = &pTerm->u.pOrInfo->wc; WhereTerm * const pOrWCEnd = &pOrWC->a[pOrWC->nTerm]; WhereTerm *pOrTerm; WhereCost rTotal = 0; WhereCost nRow = 0; Bitmask prereq = mExtra; whereLoopInit(&sBest); pItem = pWInfo->pTabList->a + pNew->iTab; iCur = pItem->iCursor; sSubBuild = *pBuilder; sSubBuild.pOrderBy = 0; sSubBuild.pBest = &sBest; for(pOrTerm=pOrWC->a; pOrTerm<pOrWCEnd; pOrTerm++){ if( (pOrTerm->eOperator & WO_AND)!=0 ){ sSubBuild.pWC = &pOrTerm->u.pAndInfo->wc; }else if( pOrTerm->leftCursor==iCur ){ tempWC.pWInfo = pWC->pWInfo; tempWC.pOuter = pWC; tempWC.op = TK_AND; tempWC.nTerm = 1; tempWC.a = pOrTerm; sSubBuild.pWC = &tempWC; }else{ continue; } sBest.maskSelf = 0; sBest.rSetup = 0; sBest.rRun = 0; #ifndef SQLITE4_OMIT_VIRTUALTABLE if( IsVirtual(pItem->pTab) ){ rc = whereLoopAddVirtual(&sSubBuild); }else #endif { rc = whereLoopAddBtree(&sSubBuild, mExtra); } /* sBest.maskSelf is always zero if an error occurs */ assert( rc==SQLITE4_OK || sBest.maskSelf==0 ); if( sBest.maskSelf==0 ) break; assert( sBest.rSetup==0 ); rTotal = whereCostAdd(rTotal, sBest.rRun); nRow = whereCostAdd(nRow, sBest.nOut); prereq |= sBest.prereq; } assert( pNew->nLSlot>=1 ); if( sBest.maskSelf ){ pNew->nLTerm = 1; pNew->aLTerm[0] = pTerm; pNew->wsFlags = WHERE_MULTI_OR; pNew->rSetup = 0; /* TUNING: Multiple by 3.5 for the secondary table lookup */ pNew->rRun = rTotal + 18; assert( 18==whereCost(7)-whereCost(2) ); pNew->nOut = nRow; pNew->prereq = prereq; memset(&pNew->u, 0, sizeof(pNew->u)); rc = whereLoopInsert(pBuilder, pNew); } whereLoopClear(pWInfo->pParse->db, &sBest); } } return rc; } /* ** Add all WhereLoop objects for all tables */ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){ WhereInfo *pWInfo = pBuilder->pWInfo; Bitmask mExtra = 0; Bitmask mPrior = 0; int iTab; SrcList *pTabList = pWInfo->pTabList; struct SrcListItem *pItem; sqlite4 *db = pWInfo->pParse->db; int nTabList = pWInfo->nLevel; int rc = SQLITE4_OK; u8 priorJoinType = 0; WhereLoop *pNew; /* Loop over the tables in the join, from left to right */ pNew = pBuilder->pNew; whereLoopInit(pNew); for(iTab=0, pItem=pTabList->a; iTab<nTabList; iTab++, pItem++){ pNew->iTab = iTab; pNew->maskSelf = getMask(&pWInfo->sMaskSet, pItem->iCursor); if( ((pItem->jointype|priorJoinType) & (JT_LEFT|JT_CROSS))!=0 ){ mExtra = mPrior; } priorJoinType = pItem->jointype; #ifndef SQLITE4_OMIT_VIRTUALTABLE if( IsVirtual(pItem->pTab) ){ rc = whereLoopAddVirtual(pBuilder); }else #endif { rc = whereLoopAddBtree(pBuilder, mExtra); } if( rc==SQLITE4_OK ){ rc = whereLoopAddOr(pBuilder, mExtra); } mPrior |= pNew->maskSelf; if( rc || db->mallocFailed ) break; } whereLoopClear(db, pNew); return rc; } /* ** Examine a WherePath (with the addition of the extra WhereLoop of the 5th ** parameters) to see if it outputs rows in the requested ORDER BY ** (or GROUP BY) without requiring a separate sort operation. Return: ** ** 0: ORDER BY is not satisfied. Sorting required ** 1: ORDER BY is satisfied. Omit sorting ** -1: Unknown at this time ** ** Note that processing for WHERE_GROUPBY and WHERE_DISTINCTBY is not as ** strict. With GROUP BY and DISTINCT the only requirement is that ** equivalent rows appear immediately adjacent to one another. GROUP BY ** and DISTINT do not require rows to appear in any particular order as long ** as equivelent rows are grouped together. Thus for GROUP BY and DISTINCT ** the pOrderBy terms can be matched in any order. With ORDER BY, the ** pOrderBy terms must be matched in strict left-to-right order. */ static int wherePathSatisfiesOrderBy( WhereInfo *pWInfo, /* The WHERE clause */ ExprList *pOrderBy, /* ORDER BY or GROUP BY or DISTINCT clause to check */ WherePath *pPath, /* The WherePath to check */ u16 wctrlFlags, /* Might contain WHERE_GROUPBY or WHERE_DISTINCTBY */ u16 nLoop, /* Number of entries in pPath->aLoop[] */ WhereLoop *pLast, /* Add this WhereLoop to the end of pPath->aLoop[] */ Bitmask *pRevMask /* OUT: Mask of WhereLoops to run in reverse order */ ){ u8 revSet; /* True if rev is known */ u8 rev; /* Composite sort order */ u8 revIdx; /* Index sort order */ u8 isOrderDistinct; /* All prior WhereLoops are order-distinct */ u8 isMatch; /* iColumn matches a term of the ORDER BY clause */ u16 nColumn; /* Number of columns in pIndex */ u16 nOrderBy; /* Number terms in the ORDER BY clause */ int iLoop; /* Index of WhereLoop in pPath being processed */ int i, j; /* Loop counters */ int iCur; /* Cursor number for current WhereLoop */ int iColumn; /* A column number within table iCur */ WhereLoop *pLoop = 0; /* Current WhereLoop being processed. */ WhereTerm *pTerm; /* A single term of the WHERE clause */ Expr *pOBExpr; /* An expression from the ORDER BY clause */ CollSeq *pColl; /* COLLATE function from an ORDER BY clause term */ Index *pIndex; /* The index associated with pLoop */ sqlite4 *db = pWInfo->pParse->db; /* Database connection */ Bitmask obSat = 0; /* Mask of ORDER BY terms satisfied so far */ Bitmask obDone; /* Mask of all ORDER BY terms */ Bitmask orderDistinctMask; /* Mask of all well-ordered loops */ Bitmask ready; /* Mask of inner loops */ /* ** We say the WhereLoop is "one-row" if it generates no more than one ** row of output. A WhereLoop is one-row if all of the following are true: ** (a) All index columns match with WHERE_COLUMN_EQ. ** (b) The index is unique ** Any WhereLoop with an WHERE_COLUMN_EQ constraint on the rowid is one-row. ** Every one-row WhereLoop will have the WHERE_ONEROW bit set in wsFlags. ** ** We say the WhereLoop is "order-distinct" if the set of columns from ** that WhereLoop that are in the ORDER BY clause are different for every ** row of the WhereLoop. Every one-row WhereLoop is automatically ** order-distinct. A WhereLoop that has no columns in the ORDER BY clause ** is not order-distinct. To be order-distinct is not quite the same as being ** UNIQUE since a UNIQUE column or index can have multiple rows that ** are NULL and NULL values are equivalent for the purpose of order-distinct. ** To be order-distinct, the columns must be UNIQUE and NOT NULL. ** ** The rowid for a table is always UNIQUE and NOT NULL so whenever the ** rowid appears in the ORDER BY clause, the corresponding WhereLoop is ** automatically order-distinct. */ assert( pOrderBy!=0 ); /* Sortability of virtual tables is determined by the xBestIndex method ** of the virtual table itself */ if( pLast->wsFlags & WHERE_VIRTUALTABLE ){ testcase( nLoop>0 ); /* True when outer loops are one-row and match ** no ORDER BY terms */ return pLast->u.vtab.isOrdered; } if( nLoop && OptimizationDisabled(db, SQLITE4_OrderByIdxJoin) ) return 0; nOrderBy = pOrderBy->nExpr; testcase( nOrderBy==BMS-1 ); if( nOrderBy>BMS-1 ) return 0; /* Cannot optimize overly large ORDER BYs */ isOrderDistinct = 1; obDone = MASKBIT(nOrderBy)-1; orderDistinctMask = 0; ready = 0; for(iLoop=0; isOrderDistinct && obSat<obDone && iLoop<=nLoop; iLoop++){ if( iLoop>0 ) ready |= pLoop->maskSelf; pLoop = iLoop<nLoop ? pPath->aLoop[iLoop] : pLast; assert( (pLoop->wsFlags & WHERE_VIRTUALTABLE)==0 ); iCur = pWInfo->pTabList->a[pLoop->iTab].iCursor; /* Mark off any ORDER BY term X that is a column in the table of ** the current loop for which there is term in the WHERE ** clause of the form X IS NULL or X=? that reference only outer ** loops. */ for(i=0; i<nOrderBy; i++){ if( MASKBIT(i) & obSat ) continue; pOBExpr = sqlite4ExprSkipCollate(pOrderBy->a[i].pExpr); if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->iTable!=iCur ) continue; pTerm = findTerm(&pWInfo->sWC, iCur, pOBExpr->iColumn, ~ready, WO_EQ|WO_ISNULL, 0); if( pTerm==0 ) continue; if( (pTerm->eOperator&WO_EQ)!=0 && pOBExpr->iColumn>=0 ){ const char *z1, *z2; pColl = sqlite4ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); if( !pColl ) pColl = db->pDfltColl; z1 = pColl->zName; pColl = sqlite4ExprCollSeq(pWInfo->pParse, pTerm->pExpr); if( !pColl ) pColl = db->pDfltColl; z2 = pColl->zName; if( sqlite4_stricmp(z1, z2)!=0 ) continue; } obSat |= MASKBIT(i); } if( (pLoop->wsFlags & WHERE_ONEROW)==0 ){ Index *pPk = 0; if( pLoop->wsFlags & WHERE_IPK ){ pIndex = 0; nColumn = 0; }else if( (pIndex = pLoop->u.btree.pIndex)==0 || pIndex->bUnordered ){ return 0; }else{ isOrderDistinct = pIndex->onError!=OE_None; pPk = sqlite4FindPrimaryKey(pIndex->pTable, 0); nColumn = idxColumnCount(pIndex, pPk); } /* Loop through all columns of the index and deal with the ones ** that are not constrained by == or IN. */ rev = revSet = 0; for(j=0; j<nColumn; j++){ u8 bOnce; /* True to run the ORDER BY search loop */ /* Skip over == and IS NULL terms */ if( j<pLoop->u.btree.nEq && ((i = pLoop->aLTerm[j]->eOperator) & (WO_EQ|WO_ISNULL))!=0 ){ if( i & WO_ISNULL ){ testcase( isOrderDistinct ); isOrderDistinct = 0; } continue; } /* Get the column number in the table (iColumn) and sort order ** (revIdx) for the j-th column of the index. */ if( j<nColumn ){ /* Normal index columns */ iColumn = idxColumnNumber(pIndex, pPk, j); revIdx = idxColumnSortOrder(pIndex, pPk, j); }else{ /* The ROWID column at the end */ assert( j==nColumn ); iColumn = -1; revIdx = 0; } /* An unconstrained column that might be NULL means that this ** WhereLoop is not well-ordered */ if( isOrderDistinct && iColumn>=0 && j>=pLoop->u.btree.nEq && pIndex->pTable->aCol[iColumn].notNull==0 ){ isOrderDistinct = 0; } /* Find the ORDER BY term that corresponds to the j-th column ** of the index and and mark that ORDER BY term off */ bOnce = 1; isMatch = 0; for(i=0; bOnce && i<nOrderBy; i++){ if( MASKBIT(i) & obSat ) continue; pOBExpr = sqlite4ExprSkipCollate(pOrderBy->a[i].pExpr); testcase( wctrlFlags & WHERE_GROUPBY ); testcase( wctrlFlags & WHERE_DISTINCTBY ); if( (wctrlFlags & (WHERE_GROUPBY|WHERE_DISTINCTBY))==0 ) bOnce = 0; if( pOBExpr->op!=TK_COLUMN ) continue; if( pOBExpr->iTable!=iCur ) continue; if( pOBExpr->iColumn!=iColumn ) continue; if( iColumn>=0 ){ const char *zIdxColl; pColl = sqlite4ExprCollSeq(pWInfo->pParse, pOrderBy->a[i].pExpr); if( !pColl ) pColl = db->pDfltColl; zIdxColl = idxColumnCollation(pIndex, pPk, j); if( sqlite4_stricmp(pColl->zName, zIdxColl)!=0 ) continue; } isMatch = 1; break; } if( isMatch ){ obSat |= MASKBIT(i); if( (pWInfo->wctrlFlags & WHERE_GROUPBY)==0 ){ /* Make sure the sort order is compatible in an ORDER BY clause. ** Sort order is irrelevant for a GROUP BY clause. */ if( revSet ){ if( (rev ^ revIdx)!=pOrderBy->a[i].sortOrder ) return 0; }else{ rev = revIdx ^ pOrderBy->a[i].sortOrder; if( rev ) *pRevMask |= MASKBIT(iLoop); revSet = 1; } } }else{ /* No match found */ if( j==0 || j<nColumn ){ testcase( isOrderDistinct!=0 ); isOrderDistinct = 0; } break; } } /* end Loop over all index columns */ /* If (j==nColumn), then each column of the index, including any ** appended PK columns, corresponds to either an ORDER BY term or ** equality constraint. Since the PK columns are collectively UNIQUE ** and NOT NULL, consider the loop order-distinct. */ if( j==nColumn ){ testcase( isOrderDistinct==0 ); isOrderDistinct = 1; } } /* end-if not one-row */ /* Mark off any other ORDER BY terms that reference pLoop */ if( isOrderDistinct ){ orderDistinctMask |= pLoop->maskSelf; for(i=0; i<nOrderBy; i++){ Expr *p; if( MASKBIT(i) & obSat ) continue; p = pOrderBy->a[i].pExpr; if( (exprTableUsage(&pWInfo->sMaskSet, p)&~orderDistinctMask)==0 ){ obSat |= MASKBIT(i); } } } } /* End the loop over all WhereLoops from outer-most down to inner-most */ if( obSat==obDone ) return 1; if( !isOrderDistinct ) return 0; return -1; } #ifdef WHERETRACE_ENABLED /* For debugging use only: */ static const char *wherePathName(WherePath *pPath, int nLoop, WhereLoop *pLast){ static char zName[65]; int i; for(i=0; i<nLoop; i++){ zName[i] = pPath->aLoop[i]->cId; } if( pLast ) zName[i++] = pLast->cId; zName[i] = 0; return zName; } #endif /* ** Given the list of WhereLoop objects at pWInfo->pLoops, this routine ** attempts to find the lowest cost path that visits each WhereLoop ** once. This path is then loaded into the pWInfo->a[].pWLoop fields. ** ** Assume that the total number of output rows that will need to be sorted ** will be nRowEst (in the 10*log2 representation). Or, ignore sorting ** costs if nRowEst==0. ** ** Return SQLITE4_OK on success or SQLITE4_NOMEM of a memory allocation ** error occurs. */ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){ int mxChoice; /* Maximum number of simultaneous paths tracked */ int nLoop; /* Number of terms in the join */ Parse *pParse; /* Parsing context */ sqlite4 *db; /* The database connection */ int iLoop; /* Loop counter over the terms of the join */ int ii, jj; /* Loop counters */ WhereCost rCost; /* Cost of a path */ WhereCost mxCost = 0; /* Maximum cost of a set of paths */ WhereCost rSortCost; /* Cost to do a sort */ int nTo, nFrom; /* Number of valid entries in aTo[] and aFrom[] */ WherePath *aFrom; /* All nFrom paths at the previous level */ WherePath *aTo; /* The nTo best paths at the current level */ WherePath *pFrom; /* An element of aFrom[] that we are working on */ WherePath *pTo; /* An element of aTo[] that we are working on */ WhereLoop *pWLoop; /* One of the WhereLoop objects */ WhereLoop **pX; /* Used to divy up the pSpace memory */ char *pSpace; /* Temporary memory used by this routine */ pParse = pWInfo->pParse; db = pParse->db; nLoop = pWInfo->nLevel; /* TUNING: For simple queries, only the best path is tracked. ** For 2-way joins, the 5 best paths are followed. ** For joins of 3 or more tables, track the 10 best paths */ mxChoice = (nLoop==1) ? 1 : (nLoop==2 ? 5 : 10); assert( nLoop<=pWInfo->pTabList->nSrc ); WHERETRACE(0x002, ("---- begin solver\n")); /* Allocate and initialize space for aTo and aFrom */ ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2; pSpace = sqlite4DbMallocRaw(db, ii); if( pSpace==0 ) return SQLITE4_NOMEM; aTo = (WherePath*)pSpace; aFrom = aTo+mxChoice; memset(aFrom, 0, sizeof(aFrom[0])); pX = (WhereLoop**)(aFrom+mxChoice); for(ii=mxChoice*2, pFrom=aTo; ii>0; ii--, pFrom++, pX += nLoop){ pFrom->aLoop = pX; } /* Seed the search with a single WherePath containing zero WhereLoops. ** ** TUNING: Do not let the number of iterations go above 25. If the cost ** of computing an automatic index is not paid back within the first 25 ** rows, then do not use the automatic index. */ aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==whereCost(25) ); nFrom = 1; /* Precompute the cost of sorting the final result set, if the caller ** to sqlite4WhereBegin() was concerned about sorting */ rSortCost = 0; if( pWInfo->pOrderBy==0 || nRowEst==0 ){ aFrom[0].isOrderedValid = 1; }else{ /* TUNING: Estimated cost of sorting is N*log2(N) where N is the ** number of output rows. */ rSortCost = nRowEst + estLog(nRowEst); WHERETRACE(0x002,("---- sort cost=%-3d\n", rSortCost)); } /* Compute successively longer WherePaths using the previous generation ** of WherePaths as the basis for the next. Keep track of the mxChoice ** best paths at each generation */ for(iLoop=0; iLoop<nLoop; iLoop++){ nTo = 0; for(ii=0, pFrom=aFrom; ii<nFrom; ii++, pFrom++){ for(pWLoop=pWInfo->pLoops; pWLoop; pWLoop=pWLoop->pNextLoop){ Bitmask maskNew; Bitmask revMask = 0; u8 isOrderedValid = pFrom->isOrderedValid; u8 isOrdered = pFrom->isOrdered; if( (pWLoop->prereq & ~pFrom->maskLoop)!=0 ) continue; if( (pWLoop->maskSelf & pFrom->maskLoop)!=0 ) continue; /* At this point, pWLoop is a candidate to be the next loop. ** Compute its cost */ rCost = whereCostAdd(pWLoop->rSetup,pWLoop->rRun + pFrom->nRow); rCost = whereCostAdd(rCost, pFrom->rCost); maskNew = pFrom->maskLoop | pWLoop->maskSelf; if( !isOrderedValid ){ switch( wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy, pFrom, pWInfo->wctrlFlags, iLoop, pWLoop, &revMask) ){ case 1: /* Yes. pFrom+pWLoop does satisfy the ORDER BY clause */ isOrdered = 1; isOrderedValid = 1; break; case 0: /* No. pFrom+pWLoop will require a separate sort */ isOrdered = 0; isOrderedValid = 1; rCost = whereCostAdd(rCost, rSortCost); break; default: /* Cannot tell yet. Try again on the next iteration */ break; } }else{ revMask = pFrom->revLoop; } /* Check to see if pWLoop should be added to the mxChoice best so far */ for(jj=0, pTo=aTo; jj<nTo; jj++, pTo++){ if( pTo->maskLoop==maskNew && pTo->isOrderedValid==isOrderedValid ){ testcase( jj==nTo-1 ); break; } } if( jj>=nTo ){ if( nTo>=mxChoice && rCost>=mxCost ){ #ifdef WHERETRACE_ENABLED if( sqlite4WhereTrace&0x4 ){ sqlite4DebugPrintf("Skip %s cost=%3d order=%c\n", wherePathName(pFrom, iLoop, pWLoop), rCost, isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); } #endif continue; } /* Add a new Path to the aTo[] set */ if( nTo<mxChoice ){ /* Increase the size of the aTo set by one */ jj = nTo++; }else{ /* New path replaces the prior worst to keep count below mxChoice */ for(jj=nTo-1; aTo[jj].rCost<mxCost; jj--){ assert(jj>0); } } pTo = &aTo[jj]; #ifdef WHERETRACE_ENABLED if( sqlite4WhereTrace&0x4 ){ sqlite4DebugPrintf("New %s cost=%-3d order=%c\n", wherePathName(pFrom, iLoop, pWLoop), rCost, isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); } #endif }else{ if( pTo->rCost<=rCost ){ #ifdef WHERETRACE_ENABLED if( sqlite4WhereTrace&0x4 ){ sqlite4DebugPrintf( "Skip %s cost=%-3d order=%c", wherePathName(pFrom, iLoop, pWLoop), rCost, isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); sqlite4DebugPrintf(" vs %s cost=%-3d order=%c\n", wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); } #endif testcase( pTo->rCost==rCost ); continue; } testcase( pTo->rCost==rCost+1 ); /* A new and better score for a previously created equivalent path */ #ifdef WHERETRACE_ENABLED if( sqlite4WhereTrace&0x4 ){ sqlite4DebugPrintf( "Update %s cost=%-3d order=%c", wherePathName(pFrom, iLoop, pWLoop), rCost, isOrderedValid ? (isOrdered ? 'Y' : 'N') : '?'); sqlite4DebugPrintf(" was %s cost=%-3d order=%c\n", wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); } #endif } /* pWLoop is a winner. Add it to the set of best so far */ pTo->maskLoop = pFrom->maskLoop | pWLoop->maskSelf; pTo->revLoop = revMask; pTo->nRow = pFrom->nRow + pWLoop->nOut; pTo->rCost = rCost; pTo->isOrderedValid = isOrderedValid; pTo->isOrdered = isOrdered; memcpy(pTo->aLoop, pFrom->aLoop, sizeof(WhereLoop*)*iLoop); pTo->aLoop[iLoop] = pWLoop; if( nTo>=mxChoice ){ mxCost = aTo[0].rCost; for(jj=1, pTo=&aTo[1]; jj<mxChoice; jj++, pTo++){ if( pTo->rCost>mxCost ) mxCost = pTo->rCost; } } } } #ifdef WHERETRACE_ENABLED if( sqlite4WhereTrace>=2 ){ sqlite4DebugPrintf("---- after round %d ----\n", iLoop); for(ii=0, pTo=aTo; ii<nTo; ii++, pTo++){ sqlite4DebugPrintf(" %s cost=%-3d nrow=%-3d order=%c", wherePathName(pTo, iLoop+1, 0), pTo->rCost, pTo->nRow, pTo->isOrderedValid ? (pTo->isOrdered ? 'Y' : 'N') : '?'); if( pTo->isOrderedValid && pTo->isOrdered ){ sqlite4DebugPrintf(" rev=0x%llx\n", pTo->revLoop); }else{ sqlite4DebugPrintf("\n"); } } } #endif /* Swap the roles of aFrom and aTo for the next generation */ pFrom = aTo; aTo = aFrom; aFrom = pFrom; nFrom = nTo; } if( nFrom==0 ){ sqlite4ErrorMsg(pParse, "no query solution"); sqlite4DbFree(db, pSpace); return SQLITE4_ERROR; } /* Find the lowest cost path. pFrom will be left pointing to that path */ pFrom = aFrom; assert( nFrom==1 ); #if 0 /* The following is needed if nFrom is ever more than 1 */ for(ii=1; ii<nFrom; ii++){ if( pFrom->rCost>aFrom[ii].rCost ) pFrom = &aFrom[ii]; } #endif assert( pWInfo->nLevel==nLoop ); /* Load the lowest cost path into pWInfo */ for(iLoop=0; iLoop<nLoop; iLoop++){ WhereLevel *pLevel = pWInfo->a + iLoop; pLevel->pWLoop = pWLoop = pFrom->aLoop[iLoop]; pLevel->iFrom = pWLoop->iTab; pLevel->iTabCur = pWInfo->pTabList->a[pLevel->iFrom].iCursor; } if( (pWInfo->wctrlFlags & WHERE_WANT_DISTINCT)!=0 && (pWInfo->wctrlFlags & WHERE_DISTINCTBY)==0 && pWInfo->eDistinct==WHERE_DISTINCT_NOOP && nRowEst ){ Bitmask notUsed; int rc = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pResultSet, pFrom, WHERE_DISTINCTBY, nLoop-1, pFrom->aLoop[nLoop-1], ¬Used); if( rc==1 ) pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; } if( pFrom->isOrdered ){ if( pWInfo->wctrlFlags & WHERE_DISTINCTBY ){ pWInfo->eDistinct = WHERE_DISTINCT_ORDERED; }else{ pWInfo->bOBSat = 1; pWInfo->revMask = pFrom->revLoop; } } pWInfo->nRowOut = pFrom->nRow; /* Free temporary memory and return success */ sqlite4DbFree(db, pSpace); return SQLITE4_OK; } /* ** Most queries use only a single table (they are not joins) and have ** simple == constraints against indexed fields. This routine attempts ** to plan those simple cases using much less ceremony than the ** general-purpose query planner, and thereby yield faster sqlite4_prepare() ** times for the common case. ** ** Return non-zero on success, if this query can be handled by this ** no-frills query planner. Return zero if this query needs the ** general-purpose query planner. */ static int whereShortCut(WhereLoopBuilder *pBuilder){ WhereInfo *pWInfo; struct SrcListItem *pItem; WhereClause *pWC; WhereTerm *pTerm; WhereLoop *pLoop; int iCur; int j; Table *pTab; Index *pIdx; return 0; pWInfo = pBuilder->pWInfo; if( pWInfo->wctrlFlags & WHERE_FORCE_TABLE ) return 0; assert( pWInfo->pTabList->nSrc>=1 ); pItem = pWInfo->pTabList->a; pTab = pItem->pTab; if( IsVirtual(pTab) ) return 0; if( pItem->zIndex ) return 0; iCur = pItem->iCursor; pWC = &pWInfo->sWC; pLoop = pBuilder->pNew; pLoop->wsFlags = 0; pTerm = findTerm(pWC, iCur, -1, 0, WO_EQ, 0); if( pTerm ){ assert( 0 ); pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW; pLoop->aLTerm[0] = pTerm; pLoop->nLTerm = 1; pLoop->u.btree.nEq = 1; /* TUNING: Cost of a rowid lookup is 10 */ pLoop->rRun = 33; /* 33==whereCost(10) */ }else{ for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ if( pIdx->onError==OE_None ) continue; for(j=0; j<pIdx->nColumn; j++){ pTerm = findTerm(pWC, iCur, pIdx->aiColumn[j], 0, WO_EQ, pIdx); if( pTerm==0 ) break; whereLoopResize(pWInfo->pParse->db, pLoop, j); pLoop->aLTerm[j] = pTerm; } if( j!=pIdx->nColumn ) continue; pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_ONEROW|WHERE_INDEXED; if( (pItem->colUsed & ~columnsInIndex(pIdx))==0 ){ pLoop->wsFlags |= WHERE_IDX_ONLY; } pLoop->nLTerm = j; pLoop->u.btree.nEq = j; pLoop->u.btree.pIndex = pIdx; /* TUNING: Cost of a unique index lookup is 15 */ pLoop->rRun = 39; /* 39==whereCost(15) */ break; } } if( pLoop->wsFlags ){ pLoop->nOut = (WhereCost)1; pWInfo->a[0].pWLoop = pLoop; pLoop->maskSelf = getMask(&pWInfo->sMaskSet, iCur); pWInfo->a[0].iTabCur = iCur; pWInfo->nRowOut = 1; if( pWInfo->pOrderBy ) pWInfo->bOBSat = 1; if( pWInfo->wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } #ifdef SQLITE4_DEBUG pLoop->cId = '0'; #endif return 1; } return 0; } /* ** Generate the beginning of the loop used for WHERE clause processing. ** The return value is a pointer to an opaque structure that contains ** information needed to terminate the loop. Later, the calling routine ** should invoke sqlite4WhereEnd() with the return value of this function ** in order to complete the WHERE clause processing. |
︙ | ︙ | |||
4527 4528 4529 4530 4531 4532 4533 | ** ** Note that the loops might not be nested in the order in which they ** appear in the FROM clause if a different order is better able to make ** use of indices. Note also that when the IN operator appears in ** the WHERE clause, it might result in additional nested loops for ** scanning through all values on the right-hand side of the IN. ** | | | 5643 5644 5645 5646 5647 5648 5649 5650 5651 5652 5653 5654 5655 5656 5657 | ** ** Note that the loops might not be nested in the order in which they ** appear in the FROM clause if a different order is better able to make ** use of indices. Note also that when the IN operator appears in ** the WHERE clause, it might result in additional nested loops for ** scanning through all values on the right-hand side of the IN. ** ** There are Btree cursors associated with each table. t1 uses cursor ** number pTabList->a[0].iCursor. t2 uses the cursor pTabList->a[1].iCursor. ** And so forth. This routine generates code to open those VDBE cursors ** and sqlite4WhereEnd() generates the code to close them. ** ** The code that sqlite4WhereBegin() generates leaves the cursors named ** in pTabList pointing at their appropriate entries. The [...] code ** can use OP_Column and OP_Rowid opcodes on these cursors to extract |
︙ | ︙ | |||
4570 4571 4572 4573 4574 4575 4576 | ** move the row2 cursor to a null row ** goto start ** fi ** end ** ** ORDER BY CLAUSE PROCESSING ** | | > | < < < < < < < < < | | | | > < > < < | | | > > > > > > > > > > > > > > > | 5686 5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697 5698 5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711 5712 5713 5714 5715 5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 | ** move the row2 cursor to a null row ** goto start ** fi ** end ** ** ORDER BY CLAUSE PROCESSING ** ** pOrderBy is a pointer to the ORDER BY clause (or the GROUP BY clause ** if the WHERE_GROUPBY flag is set in wctrlFlags) of a SELECT statement ** if there is one. If there is no ORDER BY clause or if this routine ** is called from an UPDATE or DELETE statement, then pOrderBy is NULL. */ WhereInfo *sqlite4WhereBegin( Parse *pParse, /* The parser context */ SrcList *pTabList, /* FROM clause: A list of all tables to be scanned */ Expr *pWhere, /* The WHERE clause */ ExprList *pOrderBy, /* An ORDER BY clause, or NULL */ ExprList *pResultSet, /* Result set of the query */ u16 wctrlFlags, /* One of the WHERE_* flags defined in sqliteInt.h */ int iIdxCur /* If WHERE_ONETABLE_ONLY is set, index cursor number */ ){ int nByteWInfo; /* Num. bytes allocated for WhereInfo struct */ int nTabList; /* Number of elements in pTabList */ WhereInfo *pWInfo; /* Will become the return value of this function */ Vdbe *v = pParse->pVdbe; /* The virtual database engine */ Bitmask notReady; /* Cursors that are not yet positioned */ WhereLoopBuilder sWLB; /* The WhereLoop builder */ WhereMaskSet *pMaskSet; /* The expression mask set */ WhereLevel *pLevel; /* A single level in pWInfo->a[] */ WhereLoop *pLoop; /* Pointer to a single WhereLoop object */ int ii; /* Loop counter */ sqlite4 *db; /* Database connection */ int rc; /* Return code */ /* src4: In SQLite3, the caller would set this flag. */ if( pResultSet ) wctrlFlags |= WHERE_WANT_DISTINCT; /* Variable initialization */ db = pParse->db; memset(&sWLB, 0, sizeof(sWLB)); sWLB.pOrderBy = pOrderBy; /* Disable the DISTINCT optimization if SQLITE4_DistinctOpt is set via ** sqlite4_test_ctrl(SQLITE4_TESTCTRL_OPTIMIZATIONS,...) */ if( OptimizationDisabled(db, SQLITE4_DistinctOpt) ){ wctrlFlags &= ~WHERE_WANT_DISTINCT; } /* The number of tables in the FROM clause is limited by the number of ** bits in a Bitmask */ testcase( pTabList->nSrc==BMS ); if( pTabList->nSrc>BMS ){ sqlite4ErrorMsg(pParse, "at most %d tables in a join", BMS); |
︙ | ︙ | |||
4628 4629 4630 4631 4632 4633 4634 | /* Allocate and initialize the WhereInfo structure that will become the ** return value. A single allocation is used to store the WhereInfo ** struct, the contents of WhereInfo.a[], the WhereClause structure ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte ** field (type Bitmask) it must be aligned on an 8-byte boundary on ** some architectures. Hence the ROUND8() below. */ | < | < < < < > > < | | < | > > | > > | | > > > > > > > > > > < < < < < < | | < < < < < | | | > > > > | | | | | | > > | > > > | | < < < < < < < < < < < < < < < < < < < < > | | > | < | | | > > | < < < | < < < < < < < < < < < < < < < < < | | | | | > | < | < < < < < < < < < | > | < < < < < < < | > > > | | > > > < < < < < < < > | < | > | < | < < < < | < < < > > | < < < < < < | | < < < < < | | < | < < > > | < < | < < | > > > > | < < < < < < < < < < < < < < < < < < < < < < < | < < < < < < < < < < > | | > > | > > > > > > | < < < < | > | > > > | < | < < | > | < < < > | | < < > | < < < < < < < | | | | | < < > | < < < | < < < < | | < > | | < > | | < < < | < < > | > | < < | > < < > | > > | | | > > > > > > > > | > > > > > > > | | | | > | > | | | | | | | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < | < < < > > | | | | | | | | > | | | | > | < < < | > | < < | | | | > > > | < < < < | < < < < < | < < < | < > | > < | 5750 5751 5752 5753 5754 5755 5756 5757 5758 5759 5760 5761 5762 5763 5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805 5806 5807 5808 5809 5810 5811 5812 5813 5814 5815 5816 5817 5818 5819 5820 5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846 5847 5848 5849 5850 5851 5852 5853 5854 5855 5856 5857 5858 5859 5860 5861 5862 5863 5864 5865 5866 5867 5868 5869 5870 5871 5872 5873 5874 5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886 5887 5888 5889 5890 5891 5892 5893 5894 5895 5896 5897 5898 5899 5900 5901 5902 5903 5904 5905 5906 5907 5908 5909 5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947 5948 5949 5950 5951 5952 5953 5954 5955 5956 5957 5958 5959 5960 5961 5962 5963 5964 5965 5966 5967 5968 5969 5970 5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981 5982 5983 5984 5985 5986 5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002 6003 6004 6005 6006 6007 6008 6009 6010 6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037 6038 6039 6040 6041 6042 6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064 6065 6066 6067 6068 6069 6070 6071 6072 6073 6074 6075 6076 6077 6078 6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095 6096 6097 6098 6099 6100 6101 6102 6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122 6123 6124 6125 6126 6127 6128 6129 6130 6131 6132 6133 6134 6135 6136 6137 6138 6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151 6152 6153 6154 6155 6156 6157 6158 6159 6160 6161 6162 6163 6164 6165 6166 6167 6168 6169 6170 6171 6172 6173 6174 6175 6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192 6193 6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 | /* Allocate and initialize the WhereInfo structure that will become the ** return value. A single allocation is used to store the WhereInfo ** struct, the contents of WhereInfo.a[], the WhereClause structure ** and the WhereMaskSet structure. Since WhereClause contains an 8-byte ** field (type Bitmask) it must be aligned on an 8-byte boundary on ** some architectures. Hence the ROUND8() below. */ nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel)); pWInfo = sqlite4DbMallocZero(db, nByteWInfo + sizeof(WhereLoop)); if( db->mallocFailed ){ sqlite4DbFree(db, pWInfo); pWInfo = 0; goto whereBeginError; } pWInfo->nLevel = nTabList; pWInfo->pParse = pParse; pWInfo->pTabList = pTabList; pWInfo->pOrderBy = pOrderBy; pWInfo->pResultSet = pResultSet; pWInfo->iBreak = sqlite4VdbeMakeLabel(v); pWInfo->wctrlFlags = wctrlFlags; pWInfo->savedNQueryLoop = pParse->nQueryLoop; pMaskSet = &pWInfo->sMaskSet; sWLB.pWInfo = pWInfo; sWLB.pWC = &pWInfo->sWC; sWLB.pNew = (WhereLoop*)&pWInfo->a[nTabList]; whereLoopInit(sWLB.pNew); #ifdef SQLITE4_DEBUG sWLB.pNew->cId = '*'; #endif /* Split the WHERE clause into separate subexpressions where each ** subexpression is separated by an AND operator. */ initMaskSet(pMaskSet); whereClauseInit(&pWInfo->sWC, pWInfo); sqlite4ExprCodeConstants(pParse, pWhere); whereSplit(&pWInfo->sWC, pWhere, TK_AND); /* IMP: R-15842-53296 */ sqlite4CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */ /* Special case: a WHERE clause that is constant. Evaluate the ** expression and either jump over all of the code or fall thru. */ if( pWhere && (nTabList==0 || sqlite4ExprIsConstantNotJoin(pWhere)) ){ sqlite4ExprIfFalse(pParse, pWhere, pWInfo->iBreak, SQLITE4_JUMPIFNULL); pWhere = 0; } /* Special case: No FROM clause */ if( nTabList==0 ){ if( pOrderBy ) pWInfo->bOBSat = 1; if( wctrlFlags & WHERE_WANT_DISTINCT ){ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; } } /* Assign a bit from the bitmask to every term in the FROM clause. ** ** When assigning bitmask values to FROM clause cursors, it must be ** the case that if X is the bitmask for the N-th FROM clause term then ** the bitmask for all FROM clause terms to the left of the N-th term ** is (X-1). An expression from the ON clause of a LEFT JOIN can use ** its Expr.iRightJoinTable value to find the bitmask of the right table ** of the join. Subtracting one from the right table bitmask gives a ** bitmask for all tables to the left of the join. Knowing the bitmask ** for all tables to the left of a left join is important. Ticket #3015. ** ** Note that bitmasks are created for all pTabList->nSrc tables in ** pTabList, not just the first nTabList tables. nTabList is normally ** equal to pTabList->nSrc but might be shortened to 1 if the ** WHERE_ONETABLE_ONLY flag is set. */ for(ii=0; ii<pTabList->nSrc; ii++){ createMask(pMaskSet, pTabList->a[ii].iCursor); } #ifndef NDEBUG { Bitmask toTheLeft = 0; for(ii=0; ii<pTabList->nSrc; ii++){ Bitmask m = getMask(pMaskSet, pTabList->a[ii].iCursor); assert( (m-1)==toTheLeft ); toTheLeft |= m; } } #endif /* Analyze all of the subexpressions. Note that exprAnalyze() might ** add new virtual terms onto the end of the WHERE clause. We do not ** want to analyze these virtual terms, so start analyzing at the end ** and work forward so that the added virtual terms are never processed. */ exprAnalyzeAll(pTabList, &pWInfo->sWC); if( db->mallocFailed ){ goto whereBeginError; } /* If the ORDER BY (or GROUP BY) clause contains references to general ** expressions, then we won't be able to satisfy it using indices, so ** go ahead and disable it now. */ if( pOrderBy && (wctrlFlags & WHERE_WANT_DISTINCT)!=0 ){ for(ii=0; ii<pOrderBy->nExpr; ii++){ Expr *pExpr = sqlite4ExprSkipCollate(pOrderBy->a[ii].pExpr); if( pExpr->op!=TK_COLUMN ){ pWInfo->pOrderBy = pOrderBy = 0; break; }else if( pExpr->iColumn<0 ){ break; } } } if( wctrlFlags & WHERE_WANT_DISTINCT ){ if( isDistinctRedundant(pParse, pTabList, &pWInfo->sWC, pResultSet) ){ /* The DISTINCT marking is pointless. Ignore it. */ pWInfo->eDistinct = WHERE_DISTINCT_UNIQUE; }else if( pOrderBy==0 ){ /* Try to ORDER BY the result set to make distinct processing easier */ pWInfo->wctrlFlags |= WHERE_DISTINCTBY; pWInfo->pOrderBy = pResultSet; } } /* Construct the WhereLoop objects */ WHERETRACE(0xffff,("*** Optimizer Start ***\n")); if( nTabList!=1 || whereShortCut(&sWLB)==0 ){ rc = whereLoopAddAll(&sWLB); if( rc ) goto whereBeginError; /* Display all of the WhereLoop objects if wheretrace is enabled */ #ifdef WHERETRACE_ENABLED if( sqlite4WhereTrace ){ WhereLoop *p; int i; static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz" "ABCDEFGHIJKLMNOPQRSTUVWYXZ"; for(p=pWInfo->pLoops, i=0; p; p=p->pNextLoop, i++){ p->cId = zLabel[i%sizeof(zLabel)]; whereLoopPrint(p, pTabList); } } #endif wherePathSolver(pWInfo, 0); if( db->mallocFailed ) goto whereBeginError; if( pWInfo->pOrderBy ){ wherePathSolver(pWInfo, pWInfo->nRowOut+1); if( db->mallocFailed ) goto whereBeginError; } } if( pWInfo->pOrderBy==0 && (db->flags & SQLITE4_ReverseOrder)!=0 ){ pWInfo->revMask = (Bitmask)(-1); } if( pParse->nErr || NEVER(db->mallocFailed) ){ goto whereBeginError; } #ifdef WHERETRACE_ENABLED if( sqlite4WhereTrace ){ int ii; sqlite4DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut); if( pWInfo->bOBSat ){ sqlite4DebugPrintf(" ORDERBY=0x%llx", pWInfo->revMask); } switch( pWInfo->eDistinct ){ case WHERE_DISTINCT_UNIQUE: { sqlite4DebugPrintf(" DISTINCT=unique"); break; } case WHERE_DISTINCT_ORDERED: { sqlite4DebugPrintf(" DISTINCT=ordered"); break; } case WHERE_DISTINCT_UNORDERED: { sqlite4DebugPrintf(" DISTINCT=unordered"); break; } } sqlite4DebugPrintf("\n"); for(ii=0; ii<pWInfo->nLevel; ii++){ whereLoopPrint(pWInfo->a[ii].pWLoop, pTabList); } } #endif /* Attempt to omit tables from the join that do not effect the result */ if( pWInfo->nLevel>=2 && pResultSet!=0 && OptimizationEnabled(db, SQLITE4_OmitNoopJoin) ){ Bitmask tabUsed = exprListTableUsage(pMaskSet, pResultSet); if( pOrderBy ) tabUsed |= exprListTableUsage(pMaskSet, pOrderBy); while( pWInfo->nLevel>=2 ){ WhereTerm *pTerm, *pEnd; pLoop = pWInfo->a[pWInfo->nLevel-1].pWLoop; if( (pWInfo->pTabList->a[pLoop->iTab].jointype & JT_LEFT)==0 ) break; if( (wctrlFlags & WHERE_WANT_DISTINCT)==0 && (pLoop->wsFlags & WHERE_ONEROW)==0 ){ break; } if( (tabUsed & pLoop->maskSelf)!=0 ) break; pEnd = sWLB.pWC->a + sWLB.pWC->nTerm; for(pTerm=sWLB.pWC->a; pTerm<pEnd; pTerm++){ if( (pTerm->prereqAll & pLoop->maskSelf)!=0 && !ExprHasProperty(pTerm->pExpr, EP_FromJoin) ){ break; } } if( pTerm<pEnd ) break; WHERETRACE(0xffff, ("-> drop loop %c not used\n", pLoop->cId)); pWInfo->nLevel--; nTabList--; } } WHERETRACE(0xffff,("*** Optimizer Finished ***\n")); pWInfo->pParse->nQueryLoop += pWInfo->nRowOut; /* If the caller is an UPDATE or DELETE statement that is requesting ** to use a one-pass algorithm, determine if this is appropriate. ** The one-pass algorithm only works if the WHERE clause constraints ** the statement to update a single row. */ assert( (wctrlFlags & WHERE_ONEPASS_DESIRED)==0 || pWInfo->nLevel==1 ); if( (wctrlFlags & WHERE_ONEPASS_DESIRED)!=0 && (pWInfo->a[0].pWLoop->wsFlags & WHERE_ONEROW)!=0 ){ pWInfo->okOnePass = 1; pWInfo->a[0].pWLoop->wsFlags &= ~WHERE_IDX_ONLY; } /* Open all tables in the pTabList and any indices selected for ** searching those tables. */ notReady = ~(Bitmask)0; for(ii=0, pLevel=pWInfo->a; ii<nTabList; ii++, pLevel++){ Table *pTab; /* Table to open */ int iDb; /* Index of database containing table/index */ struct SrcListItem *pTabItem; pTabItem = &pTabList->a[pLevel->iFrom]; pTab = pTabItem->pTab; iDb = sqlite4SchemaToIndex(db, pTab->pSchema); pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)!=0 || pTab->pSelect ){ /* Do nothing */ }else #ifndef SQLITE4_OMIT_VIRTUALTABLE if( (pLoop->wsFlags & WHERE_VIRTUALTABLE)!=0 ){ const char *pVTab = (const char *)sqlite4GetVTable(db, pTab); int iCur = pTabItem->iCursor; sqlite4VdbeAddOp4(v, OP_VOpen, iCur, 0, 0, pVTab, P4_VTAB); }else if( IsVirtual(pTab) ){ /* noop */ }else #endif if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 && (wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int op = pWInfo->okOnePass ? OP_OpenWrite : OP_OpenRead; sqlite4OpenPrimaryKey(pParse, pTabItem->iCursor, iDb, pTab, op); testcase( !pWInfo->okOnePass && pTab->nCol==BMS-1 ); testcase( !pWInfo->okOnePass && pTab->nCol==BMS ); #if 0 if( !pWInfo->okOnePass && pTab->nCol<BMS ){ Bitmask b = pTabItem->colUsed; int n = 0; for(; b; b=b>>1, n++){} sqlite4VdbeChangeP4(v, sqlite4VdbeCurrentAddr(v)-1, SQLITE4_INT_TO_PTR(n), P4_INT32); assert( n<=pTab->nCol ); } #endif } #if 0 else{ sqlite4TableLock(pParse, iDb, pTab->tnum, 0, pTab->zName); } #endif #ifndef SQLITE4_OMIT_AUTOMATIC_INDEX if( (pLoop->wsFlags & WHERE_AUTO_INDEX)!=0 ){ constructAutomaticIndex(pParse, &pWInfo->sWC, pTabItem, notReady, pLevel); }else #endif if( pLoop->wsFlags & WHERE_INDEXED ){ Index *pIx = pLoop->u.btree.pIndex; if( pIx->eIndexType==SQLITE4_INDEX_PRIMARYKEY ){ pLevel->iIdxCur = pTabItem->iCursor; } else if( pIx->eIndexType!=SQLITE4_INDEX_FTS5 ){ KeyInfo *pKey = sqlite4IndexKeyinfo(pParse, pIx); /* FIXME: As an optimization use pTabItem->iCursor if WHERE_IDX_ONLY */ int iIndexCur = pLevel->iIdxCur = iIdxCur ? iIdxCur : pParse->nTab++; assert( pIx->pSchema==pTab->pSchema ); assert( iIndexCur>=0 ); sqlite4VdbeAddOp4(v, OP_OpenRead, iIndexCur, pIx->tnum, iDb, (char*)pKey, P4_KEYINFO_HANDOFF); VdbeComment((v, "%s", pIx->zName)); } } sqlite4CodeVerifySchema(pParse, iDb); notReady &= ~getMask(&pWInfo->sMaskSet, pTabItem->iCursor); } pWInfo->iTop = sqlite4VdbeCurrentAddr(v); if( db->mallocFailed ) goto whereBeginError; /* Generate the code to do the search. Each iteration of the for ** loop below generates code for a single nested loop of the VM ** program. */ notReady = ~(Bitmask)0; for(ii=0; ii<nTabList; ii++){ pLevel = &pWInfo->a[ii]; explainOneScan(pParse, pTabList, pLevel, ii, pLevel->iFrom, wctrlFlags); notReady = codeOneLoopStart(pWInfo, ii, notReady); pWInfo->iContinue = pLevel->addrCont; } /* Done. */ return pWInfo; /* Jump here if malloc fails */ whereBeginError: if( pWInfo ){ pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); } return 0; } /* ** Generate the end of the WHERE loop. See comments on ** sqlite4WhereBegin() for additional information. */ void sqlite4WhereEnd(WhereInfo *pWInfo){ Parse *pParse = pWInfo->pParse; Vdbe *v = pParse->pVdbe; int i; WhereLevel *pLevel; WhereLoop *pLoop; SrcList *pTabList = pWInfo->pTabList; sqlite4 *db = pParse->db; /* Generate loop termination code. */ sqlite4ExprCacheClear(pParse); for(i=pWInfo->nLevel-1; i>=0; i--){ pLevel = &pWInfo->a[i]; pLoop = pLevel->pWLoop; sqlite4VdbeResolveLabel(v, pLevel->addrCont); if( pLevel->op!=OP_Noop ){ sqlite4VdbeAddOp2(v, pLevel->op, pLevel->p1, pLevel->p2); sqlite4VdbeChangeP5(v, pLevel->p5); } if( pLoop->wsFlags & WHERE_IN_ABLE && pLevel->u.in.nIn>0 ){ struct InLoop *pIn; int j; sqlite4VdbeResolveLabel(v, pLevel->addrNxt); for(j=pLevel->u.in.nIn, pIn=&pLevel->u.in.aInLoop[j-1]; j>0; j--, pIn--){ sqlite4VdbeJumpHere(v, pIn->addrInTop+1); sqlite4VdbeAddOp2(v, pIn->eEndLoopOp, pIn->iCur, pIn->addrInTop); sqlite4VdbeJumpHere(v, pIn->addrInTop-1); } sqlite4DbFree(db, pLevel->u.in.aInLoop); } sqlite4VdbeResolveLabel(v, pLevel->addrBrk); if( pLevel->iLeftJoin ){ int addr; addr = sqlite4VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || (pLoop->wsFlags & WHERE_INDEXED)!=0 ); if( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 ){ sqlite4VdbeAddOp1(v, OP_NullRow, pTabList->a[i].iCursor); } if( pLoop->wsFlags & WHERE_INDEXED ){ sqlite4VdbeAddOp1(v, OP_NullRow, pLevel->iIdxCur); } if( pLevel->op==OP_Return ){ sqlite4VdbeAddOp2(v, OP_Gosub, pLevel->p1, pLevel->addrFirst); }else{ sqlite4VdbeAddOp2(v, OP_Goto, 0, pLevel->addrFirst); } sqlite4VdbeJumpHere(v, addr); } } /* The "break" point is here, just past the end of the outer loop. ** Set it. */ sqlite4VdbeResolveLabel(v, pWInfo->iBreak); /* Close all of the cursors that were opened by sqlite4WhereBegin. */ assert( pWInfo->nLevel<=pTabList->nSrc ); for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){ struct SrcListItem *pTabItem = &pTabList->a[pLevel->iFrom]; Table *pTab = pTabItem->pTab; assert( pTab!=0 ); pLoop = pLevel->pWLoop; if( (pTab->tabFlags & TF_Ephemeral)==0 && pTab->pSelect==0 && (pWInfo->wctrlFlags & WHERE_OMIT_OPEN_CLOSE)==0 ){ int ws = pLoop->wsFlags; if( !pWInfo->okOnePass && (ws & WHERE_IDX_ONLY)==0 ){ sqlite4VdbeAddOp1(v, OP_Close, pTabItem->iCursor); } if( (ws & WHERE_INDEXED)!=0 && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 ){ if( pLevel->iIdxCur!=pTabItem->iCursor ){ sqlite4VdbeAddOp1(v, OP_Close, pLevel->iIdxCur); } } } /* If this scan uses an index, make VDBE code substitutions to read data ** from the index instead of from the table where possible. In some cases ** this optimization prevents the table from ever being read, which can ** yield a significant performance boost. ** ** Calls to the code generator in between sqlite4WhereBegin and ** sqlite4WhereEnd will have created code that references the table ** directly. This loop scans all that code looking for opcodes ** that reference the table and converts them into opcodes that ** reference the index. */ if( (pLoop->wsFlags & WHERE_AUTO_INDEX) && !db->mallocFailed ){ int k, j, last; VdbeOp *pOp; Index *pIdx = pLoop->u.btree.pIndex; pOp = sqlite4VdbeGetOp(v, pWInfo->iTop); last = sqlite4VdbeCurrentAddr(v); for(k=pWInfo->iTop; k<last; k++, pOp++){ if( pOp->p1!=pLevel->iTabCur ) continue; if( pOp->opcode==OP_Column ){ for(j=0; j<pIdx->nColumn; j++){ if( pOp->p2==pIdx->aiColumn[j] ){ pOp->p2 = j; pOp->p1 = pLevel->iIdxCur; break; } } assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0 || j<pIdx->nColumn ); }else if( pOp->opcode==OP_Rowid ){ pOp->p1 = pLevel->iIdxCur; pOp->opcode = OP_IdxRowid; } } } } /* Final cleanup */ pParse->nQueryLoop = pWInfo->savedNQueryLoop; whereInfoFree(db, pWInfo); return; } |
Changes to test/analyze4.test.
︙ | ︙ | |||
34 35 36 37 38 39 40 | INSERT INTO t1 SELECT a+32, b FROM t1; INSERT INTO t1 SELECT a+64, b FROM t1; ANALYZE; } # Should choose the t1a index since it is more specific than t1b. db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL} | | | 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | INSERT INTO t1 SELECT a+32, b FROM t1; INSERT INTO t1 SELECT a+64, b FROM t1; ANALYZE; } # Should choose the t1a index since it is more specific than t1b. db eval {EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE a=5 AND b IS NULL} } {0 0 0 {SEARCH TABLE t1 USING INDEX t1a (a=?)}} # Verify that the t1b index shows that it does not narrow down the # search any at all. # do_test analyze4-1.1 { db eval { SELECT idx, stat FROM sqlite_stat1 WHERE tbl='t1' ORDER BY idx; |
︙ | ︙ |
Changes to test/between.test.
︙ | ︙ | |||
44 45 46 47 48 49 50 | CREATE INDEX i1zyx ON t1(z,y,x); COMMIT; } } {} # This procedure executes the SQL. Then it appends to the result the # "sort" or "nosort" keyword depending on whether or not any sorting | | > > > > > > > > > > | | | | | | | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 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 116 117 118 119 120 121 122 123 | CREATE INDEX i1zyx ON t1(z,y,x); COMMIT; } } {} # This procedure executes the SQL. Then it appends to the result the # "sort" or "nosort" keyword depending on whether or not any sorting # is done. Then it appends the names of the table and index used. # proc queryplan {sql} { set ::sqlite_sort_count 0 set data [execsql $sql] if {$::sqlite_sort_count} {set x sort} {set x nosort} lappend data $x set eqp [execsql "EXPLAIN QUERY PLAN $sql"] # puts eqp=$eqp foreach {a b c x} $eqp { if {[regexp { TABLE (\w+ AS )?(\w+) USING.* INDEX (\w+)\y} \ $x all as tab idx]} { lappend data $tab $idx } elseif {[regexp { TABLE (\w+ AS )?(\w+)\y} $x all as tab]} { lappend data $tab * } } return $data } do_test between-1.1.1 { queryplan { SELECT * FROM t1 WHERE w BETWEEN 5 AND 6 ORDER BY +w } } {5 2 36 38 6 2 49 51 sort t1 i1w} do_test between-1.1.2 { queryplan { SELECT * FROM t1 WHERE +w BETWEEN 5 AND 6 ORDER BY +w } } {5 2 36 38 6 2 49 51 sort t1 t1} do_test between-1.2.1 { queryplan { SELECT * FROM t1 WHERE w BETWEEN 5 AND 65-y ORDER BY +w } } {5 2 36 38 6 2 49 51 sort t1 i1w} do_test between-1.2.2 { queryplan { SELECT * FROM t1 WHERE +w BETWEEN 5 AND 65-y ORDER BY +w } } {5 2 36 38 6 2 49 51 sort t1 t1} do_test between-1.3.1 { queryplan { SELECT * FROM t1 WHERE w BETWEEN 41-y AND 6 ORDER BY +w } } {5 2 36 38 6 2 49 51 sort t1 i1w} do_test between-1.3.2 { queryplan { SELECT * FROM t1 WHERE +w BETWEEN 41-y AND 6 ORDER BY +w } } {5 2 36 38 6 2 49 51 sort t1 t1} do_test between-1.4 { queryplan { SELECT * FROM t1 WHERE w BETWEEN 41-y AND 65-y ORDER BY +w } } {5 2 36 38 6 2 49 51 sort t1 t1} do_test between-1.5.1 { queryplan { SELECT * FROM t1 WHERE 26 BETWEEN y AND z ORDER BY +w } } {4 2 25 27 sort t1 i1zyx} do_test between-1.5.2 { queryplan { SELECT * FROM t1 WHERE 26 BETWEEN +y AND z ORDER BY +w } } {4 2 25 27 sort t1 i1zyx} do_test between-1.5.3 { queryplan { SELECT * FROM t1 WHERE 26 BETWEEN y AND +z ORDER BY +w } } {4 2 25 27 sort t1 t1} finish_test |
Changes to test/collate4.test.
︙ | ︙ | |||
85 86 87 88 89 90 91 | cksort {SELECT b FROM collate4t1 ORDER BY b} } {{} A B a b nosort} do_test collate4-1.1.5 { cksort {SELECT b FROM collate4t1 ORDER BY b COLLATE TEXT} } {{} A B a b nosort} do_test collate4-1.1.6 { cksort {SELECT b FROM collate4t1 ORDER BY b COLLATE NOCASE} | | | 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | cksort {SELECT b FROM collate4t1 ORDER BY b} } {{} A B a b nosort} do_test collate4-1.1.5 { cksort {SELECT b FROM collate4t1 ORDER BY b COLLATE TEXT} } {{} A B a b nosort} do_test collate4-1.1.6 { cksort {SELECT b FROM collate4t1 ORDER BY b COLLATE NOCASE} } {{} A a B b sort} do_test collate4-1.1.7 { execsql { CREATE TABLE collate4t2( a PRIMARY KEY COLLATE NOCASE, b UNIQUE COLLATE TEXT ); |
︙ | ︙ | |||
162 163 164 165 166 167 168 | INSERT INTO collate4t4 VALUES( 'A', 'A' ); CREATE INDEX collate4i3 ON collate4t4(a COLLATE TEXT); CREATE INDEX collate4i4 ON collate4t4(b COLLATE NOCASE); } } {} do_test collate4-1.1.22 { cksort {SELECT a FROM collate4t4 ORDER BY a} | | | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 | INSERT INTO collate4t4 VALUES( 'A', 'A' ); CREATE INDEX collate4i3 ON collate4t4(a COLLATE TEXT); CREATE INDEX collate4i4 ON collate4t4(b COLLATE NOCASE); } } {} do_test collate4-1.1.22 { cksort {SELECT a FROM collate4t4 ORDER BY a} } {{} A a B b sort} do_test collate4-1.1.23 { cksort {SELECT a FROM collate4t4 ORDER BY a COLLATE NOCASE} } {{} A a B b sort} do_test collate4-1.1.24 { cksort {SELECT a FROM collate4t4 ORDER BY a COLLATE TEXT} } {{} A B a b nosort} do_test collate4-1.1.25 { cksort {SELECT b FROM collate4t4 ORDER BY b} } {{} A B a b sort} do_test collate4-1.1.26 { |
︙ | ︙ | |||
213 214 215 216 217 218 219 | cksort {SELECT a FROM collate4t1 ORDER BY a COLLATE text} } {{} A B a b sort} do_test collate4-1.2.4 { cksort {SELECT a FROM collate4t1 ORDER BY a, b} } {{} A a B b nosort} do_test collate4-1.2.5 { cksort {SELECT a FROM collate4t1 ORDER BY a, b COLLATE nocase} | | | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | cksort {SELECT a FROM collate4t1 ORDER BY a COLLATE text} } {{} A B a b sort} do_test collate4-1.2.4 { cksort {SELECT a FROM collate4t1 ORDER BY a, b} } {{} A a B b nosort} do_test collate4-1.2.5 { cksort {SELECT a FROM collate4t1 ORDER BY a, b COLLATE nocase} } {{} A a B b sort} do_test collate4-1.2.6 { cksort {SELECT a FROM collate4t1 ORDER BY a, b COLLATE text} } {{} A a B b nosort} do_test collate4-1.2.7 { execsql { CREATE TABLE collate4t2( |
︙ | ︙ | |||
262 263 264 265 266 267 268 | INSERT INTO collate4t3 VALUES( 'B', 'B' ); INSERT INTO collate4t3 VALUES( 'A', 'A' ); CREATE INDEX collate4i2 ON collate4t3(a COLLATE TEXT, b COLLATE NOCASE); } } {} do_test collate4-1.2.15 { cksort {SELECT a FROM collate4t3 ORDER BY a} | | | | 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | INSERT INTO collate4t3 VALUES( 'B', 'B' ); INSERT INTO collate4t3 VALUES( 'A', 'A' ); CREATE INDEX collate4i2 ON collate4t3(a COLLATE TEXT, b COLLATE NOCASE); } } {} do_test collate4-1.2.15 { cksort {SELECT a FROM collate4t3 ORDER BY a} } {{} A a B b sort} do_test collate4-1.2.16 { cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE nocase} } {{} A a B b sort} do_test collate4-1.2.17 { cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text} } {{} A B a b nosort} do_test collate4-1.2.18 { cksort {SELECT a FROM collate4t3 ORDER BY a COLLATE text, b} } {{} A B a b sort} do_test collate4-1.2.19 { |
︙ | ︙ | |||
605 606 607 608 609 610 611 | execsql { DROP INDEX collate4i1; CREATE INDEX collate4i1 ON collate4t1(a COLLATE NUMERIC); } count { SELECT min(a) FROM collate4t1; } | | | | 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 | execsql { DROP INDEX collate4i1; CREATE INDEX collate4i1 ON collate4t1(a COLLATE NUMERIC); } count { SELECT min(a) FROM collate4t1; } } {10 9} do_test collate4-4.6 { count { SELECT max(a) FROM collate4t1; } } {20 9} do_test collate4-4.7 { execsql { DROP TABLE collate4t1; } } {} # Also test the scalar min() and max() functions. |
︙ | ︙ |
Changes to test/descidx3.test.
︙ | ︙ | |||
107 108 109 110 111 112 113 | } {9 7 6 8 3 4 2 5} ifcapable subquery { # If the subquery capability is not compiled in to the binary, then # the IN(...) operator is not available. Hence these tests cannot be # run. do_test descidx3-4.1 { | | | | | 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | } {9 7 6 8 3 4 2 5} ifcapable subquery { # If the subquery capability is not compiled in to the binary, then # the IN(...) operator is not available. Hence these tests cannot be # run. do_test descidx3-4.1 { lsort [execsql { UPDATE t1 SET a=2 WHERE i<6; SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz'; }] } {2 3 4 6 8} do_test descidx3-4.2 { execsql { UPDATE t1 SET a=1; SELECT i FROM t1 WHERE a IN (1,2) AND b>0 AND b<'zzz'; } } {2 4 3 8 6} do_test descidx3-4.3 { |
︙ | ︙ |
Changes to test/e_createtable.test.
︙ | ︙ | |||
1352 1353 1354 1355 1356 1357 1358 | # do_execsql_test 4.10.0 { CREATE TABLE t1(a, b PRIMARY KEY); CREATE TABLE t2(a, b, c, UNIQUE(b, c)); } do_createtable_tests 4.10 { 1 "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 5" | | | | | 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 | # do_execsql_test 4.10.0 { CREATE TABLE t1(a, b PRIMARY KEY); CREATE TABLE t2(a, b, c, UNIQUE(b, c)); } do_createtable_tests 4.10 { 1 "EXPLAIN QUERY PLAN SELECT * FROM t1 WHERE b = 5" {0 0 0 {SEARCH TABLE t1 USING INDEX t1 (b=?)}} 2 "EXPLAIN QUERY PLAN SELECT * FROM t2 ORDER BY b, c" {0 0 0 {SCAN TABLE t2 USING INDEX sqlite_t2_unique1}} 3 "EXPLAIN QUERY PLAN SELECT * FROM t2 WHERE b=10 AND c>10" {0 0 0 {SEARCH TABLE t2 USING INDEX sqlite_t2_unique1 (b=? AND c>?)}} } # EVIDENCE-OF: R-45493-35653 A CHECK constraint may be attached to a # column definition or specified as a table constraint. In practice it # makes no difference. # # All the tests that deal with CHECK constraints below (4.11.* and |
︙ | ︙ |
Changes to test/e_fkey.test.
︙ | ︙ | |||
961 962 963 964 965 966 967 | } } {} do_execsql_test e_fkey-25.2 { PRAGMA foreign_keys = OFF; EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1; EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?; } { | | | | | | 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 | } } {} do_execsql_test e_fkey-25.2 { PRAGMA foreign_keys = OFF; EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1; EXPLAIN QUERY PLAN SELECT rowid FROM track WHERE trackartist = ?; } { 0 0 0 {SCAN TABLE artist USING INDEX artist} 0 0 0 {SCAN TABLE track USING INDEX track} } do_execsql_test e_fkey-25.3 { PRAGMA foreign_keys = ON; EXPLAIN QUERY PLAN DELETE FROM artist WHERE 1; } { 0 0 0 {SCAN TABLE artist USING INDEX artist} 0 0 0 {SCAN TABLE track USING INDEX track} } do_test e_fkey-25.4 { execsql { INSERT INTO artist VALUES(5, 'artist 5'); INSERT INTO artist VALUES(6, 'artist 6'); INSERT INTO artist VALUES(7, 'artist 7'); INSERT INTO track VALUES(1, 'track 1', 5); |
︙ | ︙ | |||
1086 1087 1088 1089 1090 1091 1092 | } {} do_test e_fkey-27.2 { eqp { INSERT INTO artist VALUES(?, ?) } } {} do_execsql_test e_fkey-27.3 { EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ? } { | | | | | | | 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 | } {} do_test e_fkey-27.2 { eqp { INSERT INTO artist VALUES(?, ?) } } {} do_execsql_test e_fkey-27.3 { EXPLAIN QUERY PLAN UPDATE artist SET artistid = ?, artistname = ? } { 0 0 0 {SCAN TABLE artist USING INDEX artist} 0 0 0 {SEARCH TABLE track USING INDEX trackindex (trackartist=?)} 0 0 0 {SEARCH TABLE track USING INDEX trackindex (trackartist=?)} } do_execsql_test e_fkey-27.4 { EXPLAIN QUERY PLAN DELETE FROM artist } { 0 0 0 {SCAN TABLE artist USING INDEX artist} 0 0 0 {SEARCH TABLE track USING INDEX trackindex (trackartist=?)} } ########################################################################### ### SECTION 4.1: Composite Foreign Key Constraints ########################################################################### |
︙ | ︙ |
Changes to test/like.test.
︙ | ︙ | |||
185 186 187 188 189 190 191 | # is performed. # do_test like-3.1 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; } | | | 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | # is performed. # do_test like-3.1 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; } } {ABC {ABC abc xyz} abc abcd sort t1 t1} do_test like-3.2 { set sqlite_like_count } {12} # With an index on t1.x and case sensitivity on, optimize completely. # do_test like-3.3 { |
︙ | ︙ | |||
298 299 300 301 302 303 304 | db eval { PRAGMA case_sensitive_like=on; DROP INDEX i1; } queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; } | | | | 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | db eval { PRAGMA case_sensitive_like=on; DROP INDEX i1; } queryplan { SELECT x FROM t1 WHERE x LIKE 'abc%' ORDER BY 1; } } {abc abcd sort t1 t1} do_test like-3.16 { set sqlite_like_count } 12 # No GLOB optimization without an index. # do_test like-3.17 { set sqlite_like_count 0 queryplan { SELECT x FROM t1 WHERE x GLOB 'abc*' ORDER BY 1; } } {abc abcd sort t1 t1} do_test like-3.18 { set sqlite_like_count } 12 # GLOB is optimized regardless of the case_sensitive_like setting. # do_test like-3.19 { |
︙ | ︙ | |||
824 825 826 827 828 829 830 | } } {12} do_test like-11.1 { db eval {PRAGMA case_sensitive_like=OFF;} queryplan { SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a; } | | | | | 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 | } } {12} do_test like-11.1 { db eval {PRAGMA case_sensitive_like=OFF;} queryplan { SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a; } } {abc abcd ABC ABCD nosort t11 t11} do_test like-11.2 { db eval {PRAGMA case_sensitive_like=ON;} queryplan { SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a; } } {abc abcd nosort t11 t11} do_test like-11.3 { db eval { PRAGMA case_sensitive_like=OFF; CREATE INDEX t11b ON t11(b); } queryplan { SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY +a; } } {abc abcd ABC ABCD sort t11 t11b} do_test like-11.4 { db eval {PRAGMA case_sensitive_like=ON;} queryplan { SELECT b FROM t11 WHERE b LIKE 'abc%' ORDER BY a; } } {abc abcd nosort t11 t11} do_test like-11.5 { db eval { PRAGMA case_sensitive_like=OFF; DROP INDEX t11b; CREATE INDEX t11bnc ON t11(b COLLATE nocase); } queryplan { |
︙ | ︙ |
Changes to test/permutations.test.
︙ | ︙ | |||
127 128 129 130 131 132 133 134 135 136 137 138 139 140 | # src4 # veryquick # quick # full # lappend ::testsuitelist xxx test_suite "src4" -prefix "" -description { } -files { simple.test simple2.test lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test csr1.test ckpt1.test mc1.test | > < < | 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 | # src4 # veryquick # quick # full # lappend ::testsuitelist xxx # fts5expr1.test fts5query1.test fts5rnd1.test fts5create.test fts5snippet.test test_suite "src4" -prefix "" -description { } -files { simple.test simple2.test lsm1.test lsm2.test lsm3.test lsm4.test lsm5.test csr1.test ckpt1.test mc1.test alter.test alter3.test alter4.test analyze.test analyze3.test analyze4.test analyze5.test analyze6.test analyze7.test analyze8.test auth.test auth2.test auth3.test auth4.test aggerror.test attach.test attach3.test attach4.test |
︙ | ︙ |
Changes to test/simple.test.
︙ | ︙ | |||
693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 | do_execsql_test 38.2 { CREATE VIEW v1 AS SELECT a, b FROM t1; CREATE TRIGGER tr1 INSTEAD OF DELETE ON v1 BEGIN INSERT INTO log VALUES(old.b, old.a); END; } do_execsql_test 38.3 { DELETE FROM v1 WHERE a = 3; SELECT * FROM log; } {4 3} #------------------------------------------------------------------------- reset_db do_execsql_test 39.1 { CREATE TABLE t1(a PRIMARY KEY, b); | > > > > > | 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 | do_execsql_test 38.2 { CREATE VIEW v1 AS SELECT a, b FROM t1; CREATE TRIGGER tr1 INSTEAD OF DELETE ON v1 BEGIN INSERT INTO log VALUES(old.b, old.a); END; } do_execsql_test 38.3 { SELECT * FROM v1; } {3 4} do_execsql_test 38.4 { DELETE FROM v1 WHERE a = 3; } do_execsql_test 38.5 { SELECT * FROM log; } {4 3} #------------------------------------------------------------------------- reset_db do_execsql_test 39.1 { CREATE TABLE t1(a PRIMARY KEY, b); |
︙ | ︙ | |||
1357 1358 1359 1360 1361 1362 1363 | CREATE INDEX joinme_id_int_idx on joinme(id_int); } do_catchsql_test 70.2 { select * from maintable as m inner join joinme as j indexed by joinme_id_text_idx on ( m.id = j.id_int) | | | | 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 | CREATE INDEX joinme_id_int_idx on joinme(id_int); } do_catchsql_test 70.2 { select * from maintable as m inner join joinme as j indexed by joinme_id_text_idx on ( m.id = j.id_int) } {1 {no query solution}} do_catchsql_test 70.3 { select * from maintable, joinme INDEXED by joinme_id_text_idx } {1 {no query solution}} #------------------------------------------------------------------------- # This is testing that the "phantom" runs feature works. # # UPDATE: Said feature was dropped early in development. But the test # remains valid. reset_db |
︙ | ︙ | |||
1611 1612 1613 1614 1615 1616 1617 | INSERT INTO t1(x,y) VALUES(2,CAST(x'02' AS TEXT)); CREATE TABLE t3(x INT, y COLLATE NOCASE); INSERT INTO t3 SELECT x, 'abc' || y || 'xyz' FROM t1; CREATE INDEX i3 ON t3(y); SELECT x FROM t3 WHERE y LIKE 'abcX%'; } {} | > > > > > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 | INSERT INTO t1(x,y) VALUES(2,CAST(x'02' AS TEXT)); CREATE TABLE t3(x INT, y COLLATE NOCASE); INSERT INTO t3 SELECT x, 'abc' || y || 'xyz' FROM t1; CREATE INDEX i3 ON t3(y); SELECT x FROM t3 WHERE y LIKE 'abcX%'; } {} #------------------------------------------------------------------------- reset_db do_execsql_test 86.0 { SELECT * FROM sqlite_master; } {} do_execsql_test 86.1 { CREATE TABLE t1(a PRIMARY KEY, b); } do_execsql_test 86.2 { INSERT INTO t1 VALUES(1, 'one'); } do_execsql_test 86.3 { SELECT * FROM t1; } {1 one} do_execsql_test 86.4 { SELECT * FROM t1 WHERE a = 1; } {1 one} #------------------------------------------------------------------------- reset_db do_execsql_test 87.1 { CREATE TABLE t6(a INTEGER PRIMARY KEY, b TEXT); CREATE INDEX t6i1 ON t6(b); } {} do_eqp_test 87.2 { SELECT * FROM t6 ORDER BY b, a; } {0 0 0 {SCAN TABLE t6 USING INDEX t6i1}} #------------------------------------------------------------------------- reset_db do_execsql_test 88.1 { CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT); CREATE UNIQUE INDEX t8i ON t8(b); } do_eqp_test 88.2 { SELECT * FROM t8 x ORDER BY x.b, x.a, x.b||x.a } {0 0 0 {SCAN TABLE t8 AS x USING INDEX t8i}} #------------------------------------------------------------------------- reset_db do_execsql_test 89.1 { CREATE TABLE t1(a COLLATE NOCASE); CREATE INDEX i1 ON t1(a); } do_eqp_test 89.2 { SELECT * FROM t1 ORDER BY a; } {0 0 0 {SCAN TABLE t1 USING INDEX i1}} finish_test |
Changes to test/subquery.test.
︙ | ︙ | |||
237 238 239 240 241 242 243 | execsql { CREATE INDEX t4i ON t4(x); SELECT * FROM t4 WHERE x IN (SELECT a FROM t3); } } {10.0} do_test subquery-2.5.3.2 { # Verify that the t4i index was not used in the previous query | | > > > | | 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | execsql { CREATE INDEX t4i ON t4(x); SELECT * FROM t4 WHERE x IN (SELECT a FROM t3); } } {10.0} do_test subquery-2.5.3.2 { # Verify that the t4i index was not used in the previous query execsql { EXPLAIN QUERY PLAN SELECT * FROM t4 WHERE x IN (SELECT a FROM t3); } } {/SCAN TABLE t4 /} do_test subquery-2.5.4 { execsql { DROP TABLE t3; DROP TABLE t4; } } {} |
︙ | ︙ | |||
326 327 328 329 330 331 332 333 334 335 336 337 338 | } } {1 one 2 two} do_test subquery-3.3.5 { execsql { SELECT a, (SELECT count(*) FROM t2 WHERE a=c) FROM t1; } } {1 1 2 1} #------------------------------------------------------------------ # These tests - subquery-4.* - use the TCL statement cache to try # and expose bugs to do with re-using statements that have been # passed to sqlite4_reset(). # | > | | 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | } } {1 one 2 two} do_test subquery-3.3.5 { execsql { SELECT a, (SELECT count(*) FROM t2 WHERE a=c) FROM t1; } } {1 1 2 1} #------------------------------------------------------------------ # These tests - subquery-4.* - use the TCL statement cache to try # and expose bugs to do with re-using statements that have been # passed to sqlite4_reset(). # # One problem was that VDBE memory cells were not being initialized # to NULL on the second and subsequent executions. # do_test subquery-4.1.1 { execsql { SELECT (SELECT a FROM t1); } } {1} |
︙ | ︙ |
Changes to test/test_main.c.
︙ | ︙ | |||
1495 1496 1497 1498 1499 1500 1501 | Tcl_Interp *interp; Tcl_Obj *pNeeded; Tcl_Obj *pDel; }; typedef struct TestNeededX TestNeededX; static void testCollationNeeded(void *pCtx, sqlite4 *db, const char *zReq){ | | | 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 | Tcl_Interp *interp; Tcl_Obj *pNeeded; Tcl_Obj *pDel; }; typedef struct TestNeededX TestNeededX; static void testCollationNeeded(void *pCtx, sqlite4 *db, const char *zReq){ TestNeededX *p = (TestNeededX *)pCtx; Tcl_Obj *pScript; int rc; pScript = Tcl_DuplicateObj(p->pNeeded); Tcl_IncrRefCount(pScript); Tcl_ListObjAppendElement(0, pScript, Tcl_NewStringObj(zReq, -1)); rc = Tcl_EvalObjEx(p->interp, pScript, TCL_EVAL_DIRECT|TCL_EVAL_GLOBAL); |
︙ | ︙ | |||
4120 4121 4122 4123 4124 4125 4126 | sqlite4_stmt *pStmt; int col; Tcl_Obj *pRet; const void *zName16; const void *(*xFunc)(sqlite4_stmt*, int, int*); int dummy; | | | 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131 4132 4133 4134 | sqlite4_stmt *pStmt; int col; Tcl_Obj *pRet; const void *zName16; const void *(*xFunc)(sqlite4_stmt*, int, int*); int dummy; xFunc = (const void *(*)(sqlite4_stmt*, int, int*))clientData; if( objc!=3 ){ Tcl_AppendResult(interp, "wrong # args: should be \"", Tcl_GetString(objv[0]), " STMT column", 0); return TCL_ERROR; } if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; |
︙ | ︙ | |||
4310 4311 4312 4313 4314 4315 4316 | extern int sqlite4_os_type; #endif #ifdef SQLITE4_DEBUG extern int sqlite4WhereTrace; extern int sqlite4OSTrace; #endif #ifdef SQLITE4_TEST | < < | 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 | extern int sqlite4_os_type; #endif #ifdef SQLITE4_DEBUG extern int sqlite4WhereTrace; extern int sqlite4OSTrace; #endif #ifdef SQLITE4_TEST #ifdef SQLITE4_ENABLE_FTS3 extern int sqlite4_fts3_enable_parentheses; #endif #endif for(i=0; i<sizeof(aCmd)/sizeof(aCmd[0]); i++){ Tcl_CreateCommand(interp, aCmd[i].zName, aCmd[i].xProc, 0, 0); |
︙ | ︙ | |||
4349 4350 4351 4352 4353 4354 4355 | #endif Tcl_LinkVar(interp, "sqlite4_xferopt_count", (char*)&sqlite4_xferopt_count, TCL_LINK_INT); #if SQLITE4_OS_WIN Tcl_LinkVar(interp, "sqlite_os_type", (char*)&sqlite4_os_type, TCL_LINK_INT); #endif | < < < < | 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 | #endif Tcl_LinkVar(interp, "sqlite4_xferopt_count", (char*)&sqlite4_xferopt_count, TCL_LINK_INT); #if SQLITE4_OS_WIN Tcl_LinkVar(interp, "sqlite_os_type", (char*)&sqlite4_os_type, TCL_LINK_INT); #endif #ifdef SQLITE4_DEBUG Tcl_LinkVar(interp, "sqlite_where_trace", (char*)&sqlite4WhereTrace, TCL_LINK_INT); #endif Tcl_LinkVar(interp, "sqlite_static_bind_value", (char*)&sqlite_static_bind_value, TCL_LINK_STRING); Tcl_LinkVar(interp, "sqlite_static_bind_nbyte", |
︙ | ︙ |
Changes to test/test_mem.c.
︙ | ︙ | |||
12 13 14 15 16 17 18 | #include <stdio.h> #include <assert.h> #include <string.h> #include "sqliteInt.h" #include "testInt.h" | < < | 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #include <stdio.h> #include <assert.h> #include <string.h> #include "sqliteInt.h" #include "testInt.h" #if defined(__GLIBC__) extern int backtrace(void**,int); extern void backtrace_symbols_fd(void*const*,int,int); # define TM_BACKTRACE 12 #else # define backtrace(A,B) 1 # define backtrace_symbols_fd(A,B,C) |
︙ | ︙ |
Changes to test/tester.tcl.
︙ | ︙ | |||
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 | if {![info exists ::G(match)] || [string match $::G(match) $name]} { if {[catch {uplevel #0 "$cmd;\n"} result]} { puts "\nError: $result" fail_test $name } else { if {[regexp {^~?/.*/$} $expected]} { if {[string index $expected 0]=="~"} { set re [string map {# {[-0-9.]+}} [string range $expected 2 end-1]] set ok [expr {![regexp $re $result]}] } else { set re [string map {# {[-0-9.]+}} [string range $expected 1 end-1]] set ok [regexp $re $result] } } else { set ok [expr {[string compare $result $expected]==0}] } if {!$ok} { # if {![info exists ::testprefix] || $::testprefix eq ""} { # error "no test prefix" | > > > > > > > > > > > > > | 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 | if {![info exists ::G(match)] || [string match $::G(match) $name]} { if {[catch {uplevel #0 "$cmd;\n"} result]} { puts "\nError: $result" fail_test $name } else { if {[regexp {^~?/.*/$} $expected]} { # "expected" is of the form "/PATTERN/" then the result if correct if # regular expression PATTERN matches the result. "~/PATTERN/" means # the regular expression must not match. if {[string index $expected 0]=="~"} { set re [string map {# {[-0-9.]+}} [string range $expected 2 end-1]] set ok [expr {![regexp $re $result]}] } else { set re [string map {# {[-0-9.]+}} [string range $expected 1 end-1]] set ok [regexp $re $result] } } elseif {[regexp {^~?\*.*\*$} $expected]} { # "expected" is of the form "*GLOB*" then the result if correct if # glob pattern GLOB matches the result. "~/GLOB/" means # the glob must not match. if {[string index $expected 0]=="~"} { set e [string range $expected 1 end] set ok [expr {![string match $e $result]}] } else { set ok [string match $expected $result] } } else { set ok [expr {[string compare $result $expected]==0}] } if {!$ok} { # if {![info exists ::testprefix] || $::testprefix eq ""} { # error "no test prefix" |
︙ | ︙ |
Changes to test/tkt3442.test.
︙ | ︙ | |||
45 46 47 48 49 50 51 | # These tests perform an EXPLAIN QUERY PLAN on both versions of the # SELECT referenced in ticket #3442 (both '5000' and "5000") # and verify that the query plan is the same. # ifcapable explain { do_test tkt3442-1.2 { EQP { SELECT node FROM listhash WHERE id='5000' LIMIT 1; } | | | | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 | # These tests perform an EXPLAIN QUERY PLAN on both versions of the # SELECT referenced in ticket #3442 (both '5000' and "5000") # and verify that the query plan is the same. # ifcapable explain { do_test tkt3442-1.2 { EQP { SELECT node FROM listhash WHERE id='5000' LIMIT 1; } } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}} } # Some extra tests testing other permutations of 5000. # ifcapable explain { do_test tkt3442-1.4 { EQP { SELECT node FROM listhash WHERE id=5000 LIMIT 1; } } {0 0 0 {SEARCH TABLE listhash USING INDEX ididx (id=?)}} } do_test tkt3442-1.5 { catchsql { SELECT node FROM listhash WHERE id=[5000] LIMIT 1; } } {1 {no such column: 5000}} |
︙ | ︙ |
Changes to test/where.test.
︙ | ︙ | |||
59 60 61 62 63 64 65 | proc count sql { kvwrap reset set res [execsql $sql] #puts "sql={$sql} seek=[kvwrap seek] step=[kvwrap step]" return [concat $res [expr [kvwrap step] + [kvwrap seek]]] } | | < | | | | | | | | | | | | | | | | | | | | | | | | | < | > | 59 60 61 62 63 64 65 66 67 68 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 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | proc count sql { kvwrap reset set res [execsql $sql] #puts "sql={$sql} seek=[kvwrap seek] step=[kvwrap step]" return [concat $res [expr [kvwrap step] + [kvwrap seek]]] } # Verify that queries use an index. By verifing that the KVWrap layer # xNext/xPrev/xSeek count is small we can be assured that indices are # being used properly. # do_test where-1.1.1 { count {SELECT x, y, w FROM t1 WHERE w=10} } {3 121 10 3} do_eqp_test where-1.1.2 { SELECT x, y, w FROM t1 WHERE w=10 } {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} do_test where-1.1.3 { db status step } {0} do_test where-1.1.4 { db eval {SELECT x, y, w FROM t1 WHERE +w=10} } {3 121 10} do_test where-1.1.5 { db status step } {99} do_eqp_test where-1.1.6 { SELECT x, y, w FROM t1 WHERE +w=10 } {*SCAN TABLE t1*} do_test where-1.1.7 { count {SELECT x, y, w AS abc FROM t1 WHERE abc=10} } {3 121 10 3} do_eqp_test where-1.1.8 { SELECT x, y, w AS abc FROM t1 WHERE abc=10 } {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} do_test where-1.1.9 { db status step } {0} do_test where-1.2.1 { count {SELECT x, y, w FROM t1 WHERE w=11} } {3 144 11 3} do_test where-1.2.2 { count {SELECT x, y, w AS abc FROM t1 WHERE abc=11} } {3 144 11 3} do_test where-1.3.1 { count {SELECT x, y, w AS abc FROM t1 WHERE 11=w} } {3 144 11 3} do_test where-1.3.2 { count {SELECT x, y, w AS abc FROM t1 WHERE 11=abc} } {3 144 11 3} do_test where-1.4.1 { count {SELECT w, x, y FROM t1 WHERE 11=w AND x>2} } {11 3 144 3} do_eqp_test where-1.4.2 { SELECT w, x, y FROM t1 WHERE 11=w AND x>2 } {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} do_test where-1.4.3 { count {SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2} } {11 3 144 3} do_eqp_test where-1.4.4 { SELECT w AS a, x AS b, y FROM t1 WHERE 11=a AND b>2 } {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} do_test where-1.5 { count {SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2} } {3 144 3} do_eqp_test where-1.5.2 { SELECT x, y FROM t1 WHERE y<200 AND w=11 AND x>2 } {*SEARCH TABLE t1 USING INDEX i1w (w=?)*} do_test where-1.6 { count {SELECT x, y FROM t1 WHERE y<200 AND x>2 AND w=11} } {3 144 3} do_test where-1.7 { count {SELECT x, y FROM t1 WHERE w=11 AND y<200 AND x>2} } {3 144 3} do_test where-1.8 { count {SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3} } {3 144 3} do_eqp_test where-1.8.2 { SELECT x, y FROM t1 WHERE w>10 AND y=144 AND x=3 } {*SEARCH TABLE t1 USING INDEX i1xy (x=? AND y=?)*} do_eqp_test where-1.8.3 { SELECT x, y FROM t1 WHERE y=144 AND x=3 } {*SEARCH TABLE t1 USING INDEX i1xy (x=? AND y=?)*} do_test where-1.9 { count {SELECT x, y FROM t1 WHERE y=144 AND w>10 AND x=3} } {3 144 3} do_test where-1.10 { count {SELECT x, y FROM t1 WHERE x=3 AND w>=10 AND y=121} } {3 121 3} do_test where-1.11 { count {SELECT x, y FROM t1 WHERE x=3 AND y=100 AND w<10} } {3 100 3} # New for SQLite version 2.1: Verify that that inequality constraints # are used correctly. # do_test where-1.12 { count {SELECT w FROM t1 WHERE x=3 AND y<100} } {8 3} |
︙ | ︙ | |||
510 511 512 513 514 515 516 | do_test where-6.6 { cksort { SELECT * FROM t3 WHERE a>0 ORDER BY a LIMIT 3 } } {1 100 4 2 99 9 3 98 16 nosort} do_test where-6.7 { | < < | | | 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 | do_test where-6.6 { cksort { SELECT * FROM t3 WHERE a>0 ORDER BY a LIMIT 3 } } {1 100 4 2 99 9 3 98 16 nosort} do_test where-6.7 { cksort { SELECT * FROM t3 WHERE b>0 ORDER BY a LIMIT 3 } } {1 100 4 2 99 9 3 98 16 nosort} ifcapable subquery { do_test where-6.8 { cksort { SELECT * FROM t3 WHERE a IN (3,5,7,1,9,4,2) ORDER BY a LIMIT 3 } } {1 100 4 2 99 9 3 98 16 nosort} } do_test where-6.9.1 { cksort { SELECT * FROM t3 WHERE a=1 AND c>0 ORDER BY a LIMIT 3 } } {1 100 4 nosort} do_test where-6.9.1.1 { |
︙ | ︙ | |||
1098 1099 1100 1101 1102 1103 1104 | CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT UNIQUE); INSERT INTO t8 VALUES(1,'one'); INSERT INTO t8 VALUES(4,'four'); } cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, y.b } | | | | 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 | CREATE TABLE t8(a INTEGER PRIMARY KEY, b TEXT UNIQUE); INSERT INTO t8 VALUES(1,'one'); INSERT INTO t8 VALUES(4,'four'); } cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, y.b } } {1/4 1/1 4/4 4/1 nosort} do_test where-14.2 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, y.b DESC } } {1/1 1/4 4/1 4/4 nosort} do_test where-14.3 { cksort { SELECT x.a || '/' || y.a FROM t8 x, t8 y ORDER BY x.a, x.b } } {1/1 1/4 4/1 4/4 nosort} do_test where-14.4 { cksort { |
︙ | ︙ |
Changes to test/where7.test.
︙ | ︙ | |||
23328 23329 23330 23331 23332 23333 23334 | ); CREATE INDEX t302_c3 on t302(c3); CREATE INDEX t302_c8_c3 on t302(c8, c3); CREATE INDEX t302_c5 on t302(c5); EXPLAIN QUERY PLAN SELECT t302.c1 | | | | | | 23328 23329 23330 23331 23332 23333 23334 23335 23336 23337 23338 23339 23340 23341 23342 23343 23344 23345 23346 23347 23348 | ); CREATE INDEX t302_c3 on t302(c3); CREATE INDEX t302_c8_c3 on t302(c8, c3); CREATE INDEX t302_c5 on t302(c5); EXPLAIN QUERY PLAN SELECT t302.c1 FROM t302 JOIN t301 ON t302.c8 = +t301.c8 WHERE t302.c2 = 19571 AND t302.c3 > 1287603136 AND (t301.c4 = 1407449685622784 OR t301.c8 = 1407424651264000) ORDER BY t302.c5 LIMIT 200; } { 0 0 1 {SEARCH TABLE t301 USING INDEX t301_c4 (c4=?)} 0 0 1 {SEARCH TABLE t301 USING INDEX t301 (c8=?)} 0 1 0 {SEARCH TABLE t302 USING INDEX t302_c8_c3 (c8=? AND c3>?)} 0 0 0 {USE TEMP B-TREE FOR ORDER BY} } finish_test |
Changes to test/where8.test.
︙ | ︙ | |||
252 253 254 255 256 257 258 | # The "OR c = 'IX'" term forces a linear scan. execsql_status2 { SELECT a, d FROM t1, t2 WHERE (a = 2 OR b = 'three' OR c = 'IX') AND (d = a OR e = 'sixteen') ORDER BY t1.rowid } | | | | 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 | # The "OR c = 'IX'" term forces a linear scan. execsql_status2 { SELECT a, d FROM t1, t2 WHERE (a = 2 OR b = 'three' OR c = 'IX') AND (d = a OR e = 'sixteen') ORDER BY t1.rowid } } {2 2 2 4 3 3 3 4 9 9 9 4 9 0 seek=13 step=16} do_test where8-3.10 { execsql_status { SELECT d FROM t2 WHERE e IS NULL OR e = 'four' } } {1 3 5 10 2 0 0} do_test where8-3.11 { execsql_status { SELECT a, d FROM t1, t2 WHERE (a=d OR b=e) AND a<5 ORDER BY a } } {1 1 2 2 3 3 4 2 4 4 0 0} do_test where8-3.12 { execsql_status { SELECT a, d FROM t1, t2 WHERE (a=d OR b=e) AND +a<5 ORDER BY a } } {1 1 2 2 3 3 4 2 4 4 9 0} do_test where8-3.13 { execsql_status { SELECT a, d FROM t1, t2 WHERE (a=d OR b=e) AND +a<5 } } {1 1 2 2 3 3 4 2 4 4 9 0} do_test where8-3.14 { |
︙ | ︙ |