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

📄 where.c

📁 sqlite数据库管理系统开放源码
💻 C
📖 第 1 页 / 共 3 页
字号:
      }      pLevel->iMem = pParse->nMem++;      cont = pLevel->cont = sqliteVdbeMakeLabel(v);      sqliteVdbeAddOp(v, OP_NotNull, -nColumn, sqliteVdbeCurrentAddr(v)+3);      sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);      sqliteVdbeAddOp(v, OP_Goto, 0, brk);      sqliteVdbeAddOp(v, OP_MakeKey, nColumn, 0);      sqliteAddIdxKeyType(v, pIdx);      if( nColumn==pIdx->nColumn || pLevel->bRev ){        sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 0);        testOp = OP_IdxGT;      }else{        sqliteVdbeAddOp(v, OP_Dup, 0, 0);        sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);        sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);        testOp = OP_IdxGE;      }      if( pLevel->bRev ){        /* Scan in reverse order */        sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);        sqliteVdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);        start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);        sqliteVdbeAddOp(v, OP_IdxLT, pLevel->iCur, brk);        pLevel->op = OP_Prev;      }else{        /* Scan in the forward order */        sqliteVdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);        start = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);        sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk);        pLevel->op = OP_Next;      }      sqliteVdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);      sqliteVdbeAddOp(v, OP_IdxIsNull, nColumn, cont);      sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);      if( i==pTabList->nSrc-1 && pushKey ){        haveKey = 1;      }else{        sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);        haveKey = 0;      }      pLevel->p1 = pLevel->iCur;      pLevel->p2 = start;    }else if( i<ARRAYSIZE(iDirectLt) && (iDirectLt[i]>=0 || iDirectGt[i]>=0) ){      /* Case 3:  We have an inequality comparison against the ROWID field.      */      int testOp = OP_Noop;      int start;      brk = pLevel->brk = sqliteVdbeMakeLabel(v);      cont = pLevel->cont = sqliteVdbeMakeLabel(v);      if( iDirectGt[i]>=0 ){        k = iDirectGt[i];        assert( k<nExpr );        assert( aExpr[k].p!=0 );        assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );        if( aExpr[k].idxLeft==iCur ){          sqliteExprCode(pParse, aExpr[k].p->pRight);        }else{          sqliteExprCode(pParse, aExpr[k].p->pLeft);        }        sqliteVdbeAddOp(v, OP_ForceInt,          aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT, brk);        sqliteVdbeAddOp(v, OP_MoveTo, iCur, brk);        disableTerm(pLevel, &aExpr[k].p);      }else{        sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);      }      if( iDirectLt[i]>=0 ){        k = iDirectLt[i];        assert( k<nExpr );        assert( aExpr[k].p!=0 );        assert( aExpr[k].idxLeft==iCur || aExpr[k].idxRight==iCur );        if( aExpr[k].idxLeft==iCur ){          sqliteExprCode(pParse, aExpr[k].p->pRight);        }else{          sqliteExprCode(pParse, aExpr[k].p->pLeft);        }        /* sqliteVdbeAddOp(v, OP_MustBeInt, 0, sqliteVdbeCurrentAddr(v)+1); */        pLevel->iMem = pParse->nMem++;        sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);        if( aExpr[k].p->op==TK_LT || aExpr[k].p->op==TK_GT ){          testOp = OP_Ge;        }else{          testOp = OP_Gt;        }        disableTerm(pLevel, &aExpr[k].p);      }      start = sqliteVdbeCurrentAddr(v);      pLevel->op = OP_Next;      pLevel->p1 = iCur;      pLevel->p2 = start;      if( testOp!=OP_Noop ){        sqliteVdbeAddOp(v, OP_Recno, iCur, 0);        sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);        sqliteVdbeAddOp(v, testOp, 0, brk);      }      haveKey = 0;    }else if( pIdx==0 ){      /* Case 4:  There is no usable index.  We must do a complete      **          scan of the entire database table.      */      int start;      brk = pLevel->brk = sqliteVdbeMakeLabel(v);      cont = pLevel->cont = sqliteVdbeMakeLabel(v);      sqliteVdbeAddOp(v, OP_Rewind, iCur, brk);      start = sqliteVdbeCurrentAddr(v);      pLevel->op = OP_Next;      pLevel->p1 = iCur;      pLevel->p2 = start;      haveKey = 0;    }else{      /* Case 5: 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 "==" operator.      **      **         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 score = pLevel->score;      int nEqColumn = score/8;      int start;      int leFlag, geFlag;      int testOp;      /* Evaluate the equality constraints      */      for(j=0; j<nEqColumn; j++){        for(k=0; k<nExpr; k++){          if( aExpr[k].p==0 ) continue;          if( aExpr[k].idxLeft==iCur             && aExpr[k].p->op==TK_EQ             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight              && aExpr[k].p->pLeft->iColumn==pIdx->aiColumn[j]          ){            sqliteExprCode(pParse, aExpr[k].p->pRight);            disableTerm(pLevel, &aExpr[k].p);            break;          }          if( aExpr[k].idxRight==iCur             && aExpr[k].p->op==TK_EQ             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft             && aExpr[k].p->pRight->iColumn==pIdx->aiColumn[j]          ){            sqliteExprCode(pParse, aExpr[k].p->pLeft);            disableTerm(pLevel, &aExpr[k].p);            break;          }        }      }      /* 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<nEqColumn; j++){        sqliteVdbeAddOp(v, OP_Dup, nEqColumn-1, 0);      }      /* Labels for the beginning and end of the loop      */      cont = pLevel->cont = sqliteVdbeMakeLabel(v);      brk = pLevel->brk = sqliteVdbeMakeLabel(v);      /* 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( (score & 1)!=0 ){        for(k=0; k<nExpr; k++){          Expr *pExpr = aExpr[k].p;          if( pExpr==0 ) continue;          if( aExpr[k].idxLeft==iCur             && (pExpr->op==TK_LT || pExpr->op==TK_LE)             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight              && pExpr->pLeft->iColumn==pIdx->aiColumn[j]          ){            sqliteExprCode(pParse, pExpr->pRight);            leFlag = pExpr->op==TK_LE;            disableTerm(pLevel, &aExpr[k].p);            break;          }          if( aExpr[k].idxRight==iCur             && (pExpr->op==TK_GT || pExpr->op==TK_GE)             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft             && pExpr->pRight->iColumn==pIdx->aiColumn[j]          ){            sqliteExprCode(pParse, pExpr->pLeft);            leFlag = pExpr->op==TK_GE;            disableTerm(pLevel, &aExpr[k].p);            break;          }        }        testOp = OP_IdxGE;      }else{        testOp = nEqColumn>0 ? OP_IdxGE : OP_Noop;        leFlag = 1;      }      if( testOp!=OP_Noop ){        int nCol = nEqColumn + (score & 1);        pLevel->iMem = pParse->nMem++;        sqliteVdbeAddOp(v, OP_NotNull, -nCol, sqliteVdbeCurrentAddr(v)+3);        sqliteVdbeAddOp(v, OP_Pop, nCol, 0);        sqliteVdbeAddOp(v, OP_Goto, 0, brk);        sqliteVdbeAddOp(v, OP_MakeKey, nCol, 0);        sqliteAddIdxKeyType(v, pIdx);        if( leFlag ){          sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);        }        if( pLevel->bRev ){          sqliteVdbeAddOp(v, OP_MoveLt, pLevel->iCur, brk);        }else{          sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);        }      }else if( pLevel->bRev ){        sqliteVdbeAddOp(v, OP_Last, pLevel->iCur, 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( (score & 2)!=0 ){        for(k=0; k<nExpr; k++){          Expr *pExpr = aExpr[k].p;          if( pExpr==0 ) continue;          if( aExpr[k].idxLeft==iCur             && (pExpr->op==TK_GT || pExpr->op==TK_GE)             && (aExpr[k].prereqRight & loopMask)==aExpr[k].prereqRight              && pExpr->pLeft->iColumn==pIdx->aiColumn[j]          ){            sqliteExprCode(pParse, pExpr->pRight);            geFlag = pExpr->op==TK_GE;            disableTerm(pLevel, &aExpr[k].p);            break;          }          if( aExpr[k].idxRight==iCur             && (pExpr->op==TK_LT || pExpr->op==TK_LE)             && (aExpr[k].prereqLeft & loopMask)==aExpr[k].prereqLeft             && pExpr->pRight->iColumn==pIdx->aiColumn[j]          ){            sqliteExprCode(pParse, pExpr->pLeft);            geFlag = pExpr->op==TK_LE;            disableTerm(pLevel, &aExpr[k].p);            break;          }        }      }else{        geFlag = 1;      }      if( nEqColumn>0 || (score&2)!=0 ){        int nCol = nEqColumn + ((score&2)!=0);        sqliteVdbeAddOp(v, OP_NotNull, -nCol, sqliteVdbeCurrentAddr(v)+3);        sqliteVdbeAddOp(v, OP_Pop, nCol, 0);        sqliteVdbeAddOp(v, OP_Goto, 0, brk);        sqliteVdbeAddOp(v, OP_MakeKey, nCol, 0);        sqliteAddIdxKeyType(v, pIdx);        if( !geFlag ){          sqliteVdbeAddOp(v, OP_IncrKey, 0, 0);        }        if( pLevel->bRev ){          pLevel->iMem = pParse->nMem++;          sqliteVdbeAddOp(v, OP_MemStore, pLevel->iMem, 1);          testOp = OP_IdxLT;        }else{          sqliteVdbeAddOp(v, OP_MoveTo, pLevel->iCur, brk);        }      }else if( pLevel->bRev ){        testOp = OP_Noop;      }else{        sqliteVdbeAddOp(v, OP_Rewind, pLevel->iCur, 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 = sqliteVdbeCurrentAddr(v);      if( testOp!=OP_Noop ){        sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iMem, 0);        sqliteVdbeAddOp(v, testOp, pLevel->iCur, brk);      }      sqliteVdbeAddOp(v, OP_RowKey, pLevel->iCur, 0);      sqliteVdbeAddOp(v, OP_IdxIsNull, nEqColumn + (score & 1), cont);      sqliteVdbeAddOp(v, OP_IdxRecno, pLevel->iCur, 0);      if( i==pTabList->nSrc-1 && pushKey ){        haveKey = 1;      }else{        sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);        haveKey = 0;      }      /* Record the instruction used to terminate the loop.      */      pLevel->op = pLevel->bRev ? OP_Prev : OP_Next;      pLevel->p1 = pLevel->iCur;      pLevel->p2 = start;    }    loopMask |= getMask(&maskSet, iCur);    /* Insert code to test every subexpression that can be completely    ** computed using the current set of tables.    */    for(j=0; j<nExpr; j++){      if( aExpr[j].p==0 ) continue;      if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;      if( pLevel->iLeftJoin && !ExprHasProperty(aExpr[j].p,EP_FromJoin) ){        continue;      }      if( haveKey ){        haveKey = 0;        sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);      }      sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);      aExpr[j].p = 0;    }    brk = cont;    /* 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->top = sqliteVdbeCurrentAddr(v);      sqliteVdbeAddOp(v, OP_Integer, 1, 0);      sqliteVdbeAddOp(v, OP_MemStore, pLevel->iLeftJoin, 1);      for(j=0; j<nExpr; j++){        if( aExpr[j].p==0 ) continue;        if( (aExpr[j].prereqAll & loopMask)!=aExpr[j].prereqAll ) continue;        if( haveKey ){          /* Cannot happen.  "haveKey" can only be true if pushKey is true          ** an pushKey can only be true for DELETE and UPDATE and there are          ** no outer joins with DELETE and UPDATE.          */          haveKey = 0;          sqliteVdbeAddOp(v, OP_MoveTo, iCur, 0);        }        sqliteExprIfFalse(pParse, aExpr[j].p, cont, 1);        aExpr[j].p = 0;      }    }  }  pWInfo->iContinue = cont;  if( pushKey && !haveKey ){    sqliteVdbeAddOp(v, OP_Recno, pTabList->a[0].iCursor, 0);  }  freeMaskSet(&maskSet);  return pWInfo;}/*** Generate the end of the WHERE loop.  See comments on ** sqliteWhereBegin() for additional information.*/void sqliteWhereEnd(WhereInfo *pWInfo){  Vdbe *v = pWInfo->pParse->pVdbe;  int i;  WhereLevel *pLevel;  SrcList *pTabList = pWInfo->pTabList;  for(i=pTabList->nSrc-1; i>=0; i--){    pLevel = &pWInfo->a[i];    sqliteVdbeResolveLabel(v, pLevel->cont);    if( pLevel->op!=OP_Noop ){      sqliteVdbeAddOp(v, pLevel->op, pLevel->p1, pLevel->p2);    }    sqliteVdbeResolveLabel(v, pLevel->brk);    if( pLevel->inOp!=OP_Noop ){      sqliteVdbeAddOp(v, pLevel->inOp, pLevel->inP1, pLevel->inP2);    }    if( pLevel->iLeftJoin ){      int addr;      addr = sqliteVdbeAddOp(v, OP_MemLoad, pLevel->iLeftJoin, 0);      sqliteVdbeAddOp(v, OP_NotNull, 1, addr+4 + (pLevel->iCur>=0));      sqliteVdbeAddOp(v, OP_NullRow, pTabList->a[i].iCursor, 0);      if( pLevel->iCur>=0 ){        sqliteVdbeAddOp(v, OP_NullRow, pLevel->iCur, 0);      }      sqliteVdbeAddOp(v, OP_Goto, 0, pLevel->top);    }  }  sqliteVdbeResolveLabel(v, pWInfo->iBreak);  for(i=0; i<pTabList->nSrc; i++){    Table *pTab = pTabList->a[i].pTab;    assert( pTab!=0 );    if( pTab->isTransient || pTab->pSelect ) continue;    pLevel = &pWInfo->a[i];    sqliteVdbeAddOp(v, OP_Close, pTabList->a[i].iCursor, 0);    if( pLevel->pIdx!=0 ){      sqliteVdbeAddOp(v, OP_Close, pLevel->iCur, 0);    }  }#if 0  /* Never reuse a cursor */  if( pWInfo->pParse->nTab==pWInfo->peakNTab ){    pWInfo->pParse->nTab = pWInfo->savedNTab;  }#endif  sqliteFree(pWInfo);  return;}

⌨️ 快捷键说明

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