⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 where.c

📁 调用sqlite开源数据的小程序
💻 C
📖 第 1 页 / 共 5 页
字号:
      cost = bestIndex(pParse, &wc, pTabItem, notReady,                       (i==0 && ppOrderBy) ? *ppOrderBy : 0,                       &pIdx, &flags, &nEq);      if( cost<lowestCost ){        lowestCost = cost;        pBest = pIdx;        bestFlags = flags;        bestNEq = nEq;        bestJ = j;      }      if( (pTabItem->jointype & (JT_LEFT|JT_CROSS))!=0         || (j>0 && (pTabItem[-1].jointype & (JT_LEFT|JT_CROSS))!=0)      ){        break;      }    }    TRACE(("*** Optimizer choose table %d for loop %d\n", bestJ,           pLevel-pWInfo->a));    if( (bestFlags & WHERE_ORDERBY)!=0 ){      *ppOrderBy = 0;    }    andFlags &= bestFlags;    pLevel->flags = bestFlags;    pLevel->pIdx = pBest;    pLevel->nEq = bestNEq;    pLevel->aInLoop = 0;    pLevel->nIn = 0;    if( pBest ){      pLevel->iIdxCur = pParse->nTab++;    }else{      pLevel->iIdxCur = -1;    }    notReady &= ~getMask(&maskSet, pTabList->a[bestJ].iCursor);    pLevel->iFrom = bestJ;  }  TRACE(("*** Optimizer Finished ***\n"));  /* If the total query only selects a single row, then the ORDER BY  ** clause is irrelevant.  */  if( (andFlags & WHERE_UNIQUE)!=0 && ppOrderBy ){    *ppOrderBy = 0;  }  /* Open all tables in the pTabList and any indices selected for  ** searching those tables.  */  sqlite3CodeVerifySchema(pParse, -1); /* Insert the cookie verifier Goto */  pLevel = pWInfo->a;  for(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){    Table *pTab;    Index *pIx;    int iIdxCur = pLevel->iIdxCur;#ifndef SQLITE_OMIT_EXPLAIN    if( pParse->explain==2 ){      char *zMsg;      struct SrcList_item *pItem = &pTabList->a[pLevel->iFrom];      zMsg = sqlite3MPrintf("TABLE %s", pItem->zName);      if( pItem->zAlias ){        zMsg = sqlite3MPrintf("%z AS %s", zMsg, pItem->zAlias);      }      if( (pIx = pLevel->pIdx)!=0 ){        zMsg = sqlite3MPrintf("%z WITH INDEX %s", zMsg, pIx->zName);      }      sqlite3VdbeOp3(v, OP_Explain, i, pLevel->iFrom, zMsg, P3_DYNAMIC);    }#endif /* SQLITE_OMIT_EXPLAIN */    pTabItem = &pTabList->a[pLevel->iFrom];    pTab = pTabItem->pTab;    if( pTab->isTransient || pTab->pSelect ) continue;    if( (pLevel->flags & WHERE_IDX_ONLY)==0 ){      sqlite3OpenTableForReading(v, pTabItem->iCursor, pTab);    }    pLevel->iTabCur = pTabItem->iCursor;    if( (pIx = pLevel->pIdx)!=0 ){      sqlite3VdbeAddOp(v, OP_Integer, pIx->iDb, 0);      VdbeComment((v, "# %s", pIx->zName));      sqlite3VdbeOp3(v, OP_OpenRead, iIdxCur, pIx->tnum,                     (char*)&pIx->keyInfo, P3_KEYINFO);    }    if( (pLevel->flags & WHERE_IDX_ONLY)!=0 ){      sqlite3VdbeAddOp(v, OP_SetNumColumns, iIdxCur, pIx->nColumn+1);    }    sqlite3CodeVerifySchema(pParse, pTab->iDb);  }  pWInfo->iTop = sqlite3VdbeCurrentAddr(v);  /* 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(i=0, pLevel=pWInfo->a; i<pTabList->nSrc; i++, pLevel++){    int j;    int iCur = pTabItem->iCursor;  /* The VDBE cursor for the table */    Index *pIdx;       /* The index we will be using */    int iIdxCur;       /* The VDBE cursor for the index */    int omitTable;     /* True if we use the index only */    int bRev;          /* True if we need to scan in reverse order */    pTabItem = &pTabList->a[pLevel->iFrom];    iCur = pTabItem->iCursor;    pIdx = pLevel->pIdx;    iIdxCur = pLevel->iIdxCur;    bRev = (pLevel->flags & WHERE_REVERSE)!=0;    omitTable = (pLevel->flags & WHERE_IDX_ONLY)!=0;    /* Create labels for the "break" and "continue" instructions    ** for the current loop.  Jump to brk to break out of a loop.    ** Jump to cont to go immediately to the next iteration of the    ** loop.    */    brk = pLevel->brk = sqlite3VdbeMakeLabel(v);    cont = pLevel->cont = sqlite3VdbeMakeLabel(v);    /* If this is the right table of a LEFT OUTER JOIN, allocate and    ** initialize a memory cell that records if this table matches any    ** row of the left table of the join.    */    if( pLevel->iFrom>0 && (pTabItem[-1].jointype & JT_LEFT)!=0 ){      if( !pParse->nMem ) pParse->nMem++;      pLevel->iLeftJoin = pParse->nMem++;      sqlite3VdbeAddOp(v, OP_MemInt, 0, pLevel->iLeftJoin);      VdbeComment((v, "# init LEFT JOIN no-match flag"));    }    if( pLevel->flags & WHERE_ROWID_EQ ){      /* Case 1:  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.      */      pTerm = findTerm(&wc, iCur, -1, notReady, WO_EQ|WO_IN, 0);      assert( pTerm!=0 );      assert( pTerm->pExpr!=0 );      assert( pTerm->leftCursor==iCur );      assert( omitTable==0 );      codeEqualityTerm(pParse, pTerm, brk, pLevel);      sqlite3VdbeAddOp(v, OP_MustBeInt, 1, brk);      sqlite3VdbeAddOp(v, OP_NotExists, iCur, brk);      VdbeComment((v, "pk"));      pLevel->op = OP_Noop;    }else if( pLevel->flags & WHERE_ROWID_RANGE ){      /* Case 2:  We have an inequality comparison against the ROWID field.      */      int testOp = OP_Noop;      int start;      WhereTerm *pStart, *pEnd;      assert( omitTable==0 );      pStart = findTerm(&wc, iCur, -1, notReady, WO_GT|WO_GE, 0);      pEnd = findTerm(&wc, iCur, -1, notReady, WO_LT|WO_LE, 0);      if( bRev ){        pTerm = pStart;        pStart = pEnd;        pEnd = pTerm;      }      if( pStart ){        Expr *pX;        pX = pStart->pExpr;        assert( pX!=0 );        assert( pStart->leftCursor==iCur );        sqlite3ExprCode(pParse, pX->pRight);        sqlite3VdbeAddOp(v, OP_ForceInt, pX->op==TK_LE || pX->op==TK_GT, brk);        sqlite3VdbeAddOp(v, bRev ? OP_MoveLt : OP_MoveGe, iCur, brk);        VdbeComment((v, "pk"));        disableTerm(pLevel, pStart);      }else{        sqlite3VdbeAddOp(v, bRev ? OP_Last : OP_Rewind, iCur, brk);      }      if( pEnd ){        Expr *pX;        pX = pEnd->pExpr;        assert( pX!=0 );        assert( pEnd->leftCursor==iCur );        sqlite3ExprCode(pParse, pX->pRight);        pLevel->iMem = pParse->nMem++;        sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);        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 = sqlite3VdbeCurrentAddr(v);      pLevel->op = bRev ? OP_Prev : OP_Next;      pLevel->p1 = iCur;      pLevel->p2 = start;      if( testOp!=OP_Noop ){        sqlite3VdbeAddOp(v, OP_Rowid, iCur, 0);        sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);        sqlite3VdbeAddOp(v, testOp, 'n', brk);      }    }else if( pLevel->flags & WHERE_COLUMN_RANGE ){      /* Case 3: The WHERE clause term that refers to the right-most      **         column of the index is an inequality.  For example, if      **         the index is on (x,y,z) and the WHERE clause is of the      **         form "x=5 AND y<10" then this case is used.  Only the      **         right-most column can be an inequality - the rest must      **         use the "==" and "IN" operators.      **      **         This case is also used when there are no WHERE clause      **         constraints but an index is selected anyway, in order      **         to force the output order to conform to an ORDER BY.      */      int start;      int nEq = pLevel->nEq;      int leFlag=0, geFlag=0;      int testOp;      int topLimit = (pLevel->flags & WHERE_TOP_LIMIT)!=0;      int btmLimit = (pLevel->flags & WHERE_BTM_LIMIT)!=0;      /* Generate code to evaluate all constraint terms using == or IN      ** and level the values of those terms on the stack.      */      codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk);      /* Duplicate the equality term values because they will all be      ** used twice: once to make the termination key and once to make the      ** start key.      */      for(j=0; j<nEq; j++){        sqlite3VdbeAddOp(v, OP_Dup, nEq-1, 0);      }      /* Generate the termination key.  This is the key value that      ** will end the search.  There is no termination key if there      ** are no equality terms and no "X<..." term.      **      ** 2002-Dec-04: On a reverse-order scan, the so-called "termination"      ** key computed here really ends up being the start key.      */      if( topLimit ){        Expr *pX;        int k = pIdx->aiColumn[j];        pTerm = findTerm(&wc, iCur, k, notReady, WO_LT|WO_LE, pIdx);        assert( pTerm!=0 );        pX = pTerm->pExpr;        assert( (pTerm->flags & TERM_CODED)==0 );        sqlite3ExprCode(pParse, pX->pRight);        leFlag = pX->op==TK_LE;        disableTerm(pLevel, pTerm);        testOp = OP_IdxGE;      }else{        testOp = nEq>0 ? OP_IdxGE : OP_Noop;        leFlag = 1;      }      if( testOp!=OP_Noop ){        int nCol = nEq + topLimit;        pLevel->iMem = pParse->nMem++;        buildIndexProbe(v, nCol, brk, pIdx);        if( bRev ){          int op = leFlag ? OP_MoveLe : OP_MoveLt;          sqlite3VdbeAddOp(v, op, iIdxCur, brk);        }else{          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);        }      }else if( bRev ){        sqlite3VdbeAddOp(v, OP_Last, iIdxCur, brk);      }      /* Generate the start key.  This is the key that defines the lower      ** bound on the search.  There is no start key if there are no      ** equality terms and if there is no "X>..." term.  In      ** that case, generate a "Rewind" instruction in place of the      ** start key search.      **      ** 2002-Dec-04: In the case of a reverse-order search, the so-called      ** "start" key really ends up being used as the termination key.      */      if( btmLimit ){        Expr *pX;        int k = pIdx->aiColumn[j];        pTerm = findTerm(&wc, iCur, k, notReady, WO_GT|WO_GE, pIdx);        assert( pTerm!=0 );        pX = pTerm->pExpr;        assert( (pTerm->flags & TERM_CODED)==0 );        sqlite3ExprCode(pParse, pX->pRight);        geFlag = pX->op==TK_GE;        disableTerm(pLevel, pTerm);      }else{        geFlag = 1;      }      if( nEq>0 || btmLimit ){        int nCol = nEq + btmLimit;        buildIndexProbe(v, nCol, brk, pIdx);        if( bRev ){          pLevel->iMem = pParse->nMem++;          sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);          testOp = OP_IdxLT;        }else{          int op = geFlag ? OP_MoveGe : OP_MoveGt;          sqlite3VdbeAddOp(v, op, iIdxCur, brk);        }      }else if( bRev ){        testOp = OP_Noop;      }else{        sqlite3VdbeAddOp(v, OP_Rewind, iIdxCur, brk);      }      /* Generate the the top of the loop.  If there is a termination      ** key we have to test for that key and abort at the top of the      ** loop.      */      start = sqlite3VdbeCurrentAddr(v);      if( testOp!=OP_Noop ){        sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);        sqlite3VdbeAddOp(v, testOp, iIdxCur, brk);        if( (leFlag && !bRev) || (!geFlag && bRev) ){          sqlite3VdbeChangeP3(v, -1, "+", P3_STATIC);        }      }      sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEq + topLimit, cont);      if( !omitTable ){        sqlite3VdbeAddOp(v, OP_IdxRowid, iIdxCur, 0);        sqlite3VdbeAddOp(v, OP_MoveGe, iCur, 0);      }      /* Record the instruction used to terminate the loop.      */      pLevel->op = bRev ? OP_Prev : OP_Next;      pLevel->p1 = iIdxCur;      pLevel->p2 = start;    }else if( pLevel->flags & WHERE_COLUMN_EQ ){      /* Case 4:  There is an index and all terms of the WHERE clause that      **          refer to the index using the "==" or "IN" operators.      */      int start;      int nEq = pLevel->nEq;      /* Generate code to evaluate all constraint terms using == or IN      ** and leave the values of those terms on the stack.      */      codeAllEqualityTerms(pParse, pLevel, &wc, notReady, brk);      /* Generate a single key that will be used to both start and terminate      ** the search      */      buildIndexProbe(v, nEq, brk, pIdx);      sqlite3VdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);      /* Generate code (1) to move to the first matching element of the table.      ** Then generate code (2) that jumps to "brk" after the cursor is past      ** the last matching element of the table.  The code (1) is executed      ** once to initialize the search, the code (2) is executed before each      ** iteration of the scan to see if the scan has finished. */      if( bRev ){        /* Scan in reverse order */        sqlite3VdbeAddOp(v, OP_MoveLe, iIdxCur, brk);        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);        sqlite3VdbeAddOp(v, OP_IdxLT, iIdxCur, brk);        pLevel->op = OP_Prev;      }else{        /* Scan in the forward order */        sqlite3VdbeAddOp(v, OP_MoveGe, iIdxCur, brk);        start = sqlite3VdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);        sqlite3VdbeOp3(v, OP_IdxGE, iIdxCur, brk, "+", P3_STATIC);        pLevel->op = OP_Next;      }      sqlite3VdbeAddOp(v, OP_RowKey, iIdxCur, 0);      sqlite3VdbeAddOp(v, OP_IdxIsNull, nEq, cont);      if( !omitTable ){        sqlite3VdbeAddO

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -