mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-19 21:43:15 +03:00
High-speed version of NGQP. Still has some minor problems.
FossilOrigin-Name: db2415fa677b84cd0f6dd424283c94e98d246e3b
This commit is contained in:
117
src/where.c
117
src/where.c
@@ -5168,6 +5168,75 @@ static int wherePathSolver(WhereInfo *pWInfo, WhereCost nRowEst){
|
||||
return SQLITE_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 sqlite3_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 whereSimpleFastCase(WhereLoopBuilder *pBuilder){
|
||||
WhereInfo *pWInfo;
|
||||
struct SrcList_item *pItem;
|
||||
WhereClause *pWC;
|
||||
WhereTerm *pTerm;
|
||||
WhereLoop *pLoop;
|
||||
int iCur;
|
||||
int i, j;
|
||||
int nOrderBy;
|
||||
Table *pTab;
|
||||
Index *pIdx;
|
||||
|
||||
pWInfo = pBuilder->pWInfo;
|
||||
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;
|
||||
pWInfo->a[0].pWLoop = pLoop;
|
||||
pLoop->wsFlags = 0;
|
||||
nOrderBy = pWInfo->pOrderBy ? pWInfo->pOrderBy->nExpr : 0;
|
||||
pTerm = findTerm(pWC, iCur, -1, 1, WO_EQ, 0);
|
||||
if( pTerm ){
|
||||
pLoop->wsFlags = WHERE_COLUMN_EQ|WHERE_IPK|WHERE_ONEROW;
|
||||
pLoop->aLTerm[0] = pTerm;
|
||||
pLoop->nLTerm = 1;
|
||||
pLoop->u.btree.nEq = 1;
|
||||
pLoop->rRun = (WhereCost)10;
|
||||
pLoop->nOut = (WhereCost)1;
|
||||
pWInfo->nRowOut = 1;
|
||||
pWInfo->nOBSat = nOrderBy;
|
||||
}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], 1, 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;
|
||||
pLoop->nLTerm = j;
|
||||
pLoop->u.btree.nEq = j;
|
||||
pLoop->u.btree.pIndex = pIdx;
|
||||
pLoop->rRun = (WhereCost)15;
|
||||
pLoop->nOut = (WhereCost)1;
|
||||
pWInfo->nRowOut = 1;
|
||||
pWInfo->nOBSat = nOrderBy;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return pLoop->wsFlags!=0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Generate the beginning of the loop used for WHERE clause processing.
|
||||
** The return value is a pointer to an opaque structure that contains
|
||||
@@ -5307,7 +5376,7 @@ WhereInfo *sqlite3WhereBegin(
|
||||
*/
|
||||
db = pParse->db;
|
||||
nByteWInfo = ROUND8(sizeof(WhereInfo)+(nTabList-1)*sizeof(WhereLevel));
|
||||
pWInfo = sqlite3DbMallocZero(db, nByteWInfo);
|
||||
pWInfo = sqlite3DbMallocZero(db, nByteWInfo + sizeof(WhereLoop));
|
||||
if( db->mallocFailed ){
|
||||
sqlite3DbFree(db, pWInfo);
|
||||
pWInfo = 0;
|
||||
@@ -5324,6 +5393,8 @@ WhereInfo *sqlite3WhereBegin(
|
||||
pMaskSet = &pWInfo->sMaskSet;
|
||||
sWLB.pWInfo = pWInfo;
|
||||
sWLB.pWC = &pWInfo->sWC;
|
||||
sWLB.pNew = (WhereLoop*)&pWInfo->a[nTabList];
|
||||
whereLoopInit(sWLB.pNew);
|
||||
|
||||
/* Disable the DISTINCT optimization if SQLITE_DistinctOpt is set via
|
||||
** sqlite3_test_ctrl(SQLITE_TESTCTRL_OPTIMIZATIONS,...) */
|
||||
@@ -5396,30 +5467,32 @@ WhereInfo *sqlite3WhereBegin(
|
||||
|
||||
/* Construct the WhereLoop objects */
|
||||
WHERETRACE(("*** Optimizer Start ***\n"));
|
||||
/* TBD: if( nTablist==1 ) whereCommonCase(&sWLB); */
|
||||
rc = whereLoopAddAll(&sWLB);
|
||||
if( rc ) goto whereBeginError;
|
||||
|
||||
/* Display all of the WhereLoop objects if wheretrace is enabled */
|
||||
if( nTabList!=1 || whereSimpleFastCase(&sWLB)==0 ){
|
||||
rc = whereLoopAddAll(&sWLB);
|
||||
if( rc ) goto whereBeginError;
|
||||
|
||||
/* Display all of the WhereLoop objects if wheretrace is enabled */
|
||||
#ifdef WHERETRACE_ENABLED
|
||||
if( sqlite3WhereTrace ){
|
||||
WhereLoop *p;
|
||||
int i = 0;
|
||||
static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
|
||||
for(p=pWInfo->pLoops; p; p=p->pNextLoop){
|
||||
p->cId = zLabel[(i++)%sizeof(zLabel)];
|
||||
whereLoopPrint(p, pTabList);
|
||||
if( sqlite3WhereTrace ){
|
||||
WhereLoop *p;
|
||||
int i = 0;
|
||||
static char zLabel[] = "0123456789abcdefghijklmnopqrstuvwyxz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWYXZ";
|
||||
for(p=pWInfo->pLoops; p; p=p->pNextLoop){
|
||||
p->cId = zLabel[(i++)%sizeof(zLabel)];
|
||||
whereLoopPrint(p, pTabList);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wherePathSolver(pWInfo, -1);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
if( pWInfo->pOrderBy ){
|
||||
wherePathSolver(pWInfo, pWInfo->nRowOut);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
wherePathSolver(pWInfo, -1);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
if( pWInfo->pOrderBy ){
|
||||
wherePathSolver(pWInfo, pWInfo->nRowOut);
|
||||
if( db->mallocFailed ) goto whereBeginError;
|
||||
}else if( db->flags & SQLITE_ReverseOrder ){
|
||||
if( pWInfo->pOrderBy==0 && (db->flags & SQLITE_ReverseOrder)!=0 ){
|
||||
pWInfo->revMask = (Bitmask)(-1);
|
||||
}
|
||||
if( pParse->nErr || db->mallocFailed ){
|
||||
|
||||
Reference in New Issue
Block a user