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

📄 select.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      pDelete = p->pPrior;      p->pPrior = pPrior;      p->pOrderBy = 0;      sqlite3ExprDelete(db, p->pLimit);      p->pLimit = pLimit;      p->pOffset = pOffset;      p->iLimit = 0;      p->iOffset = 0;      if( rc ){        goto multi_select_end;      }      /* Convert the data in the temporary table into whatever form      ** it is that we currently need.      */            if( dest.eDest!=priorOp || unionTab!=dest.iParm ){        int iCont, iBreak, iStart;        assert( p->pEList );        if( dest.eDest==SRT_Output ){          Select *pFirst = p;          while( pFirst->pPrior ) pFirst = pFirst->pPrior;          generateColumnNames(pParse, 0, pFirst->pEList);        }        iBreak = sqlite3VdbeMakeLabel(v);        iCont = sqlite3VdbeMakeLabel(v);        computeLimitRegisters(pParse, p, iBreak);        sqlite3VdbeAddOp2(v, OP_Rewind, unionTab, iBreak);        iStart = sqlite3VdbeCurrentAddr(v);        selectInnerLoop(pParse, p, p->pEList, unionTab, p->pEList->nExpr,                        0, -1, &dest, iCont, iBreak);        sqlite3VdbeResolveLabel(v, iCont);        sqlite3VdbeAddOp2(v, OP_Next, unionTab, iStart);        sqlite3VdbeResolveLabel(v, iBreak);        sqlite3VdbeAddOp2(v, OP_Close, unionTab, 0);      }      break;    }    case TK_INTERSECT: {      int tab1, tab2;      int iCont, iBreak, iStart;      Expr *pLimit, *pOffset;      int addr;      SelectDest intersectdest;      int r1;      /* INTERSECT is different from the others since it requires      ** two temporary tables.  Hence it has its own case.  Begin      ** by allocating the tables we will need.      */      tab1 = pParse->nTab++;      tab2 = pParse->nTab++;      assert( p->pOrderBy==0 );      addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab1, 0);      assert( p->addrOpenEphm[0] == -1 );      p->addrOpenEphm[0] = addr;      p->pRightmost->selFlags |= SF_UsesEphemeral;      assert( p->pEList );      /* Code the SELECTs to our left into temporary table "tab1".      */      sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);      rc = sqlite3Select(pParse, pPrior, &intersectdest);      if( rc ){        goto multi_select_end;      }      /* Code the current SELECT into temporary table "tab2"      */      addr = sqlite3VdbeAddOp2(v, OP_OpenEphemeral, tab2, 0);      assert( p->addrOpenEphm[1] == -1 );      p->addrOpenEphm[1] = addr;      p->pPrior = 0;      pLimit = p->pLimit;      p->pLimit = 0;      pOffset = p->pOffset;      p->pOffset = 0;      intersectdest.iParm = tab2;      rc = sqlite3Select(pParse, p, &intersectdest);      pDelete = p->pPrior;      p->pPrior = pPrior;      sqlite3ExprDelete(db, p->pLimit);      p->pLimit = pLimit;      p->pOffset = pOffset;      if( rc ){        goto multi_select_end;      }      /* Generate code to take the intersection of the two temporary      ** tables.      */      assert( p->pEList );      if( dest.eDest==SRT_Output ){        Select *pFirst = p;        while( pFirst->pPrior ) pFirst = pFirst->pPrior;        generateColumnNames(pParse, 0, pFirst->pEList);      }      iBreak = sqlite3VdbeMakeLabel(v);      iCont = sqlite3VdbeMakeLabel(v);      computeLimitRegisters(pParse, p, iBreak);      sqlite3VdbeAddOp2(v, OP_Rewind, tab1, iBreak);      r1 = sqlite3GetTempReg(pParse);      iStart = sqlite3VdbeAddOp2(v, OP_RowKey, tab1, r1);      sqlite3VdbeAddOp3(v, OP_NotFound, tab2, iCont, r1);      sqlite3ReleaseTempReg(pParse, r1);      selectInnerLoop(pParse, p, p->pEList, tab1, p->pEList->nExpr,                      0, -1, &dest, iCont, iBreak);      sqlite3VdbeResolveLabel(v, iCont);      sqlite3VdbeAddOp2(v, OP_Next, tab1, iStart);      sqlite3VdbeResolveLabel(v, iBreak);      sqlite3VdbeAddOp2(v, OP_Close, tab2, 0);      sqlite3VdbeAddOp2(v, OP_Close, tab1, 0);      break;    }  }  /* Compute collating sequences used by   ** temporary tables needed to implement the compound select.  ** Attach the KeyInfo structure to all temporary tables.  **  ** This section is run by the right-most SELECT statement only.  ** SELECT statements to the left always skip this part.  The right-most  ** SELECT might also skip this part if it has no ORDER BY clause and  ** no temp tables are required.  */  if( p->selFlags & SF_UsesEphemeral ){    int i;                        /* Loop counter */    KeyInfo *pKeyInfo;            /* Collating sequence for the result set */    Select *pLoop;                /* For looping through SELECT statements */    CollSeq **apColl;             /* For looping through pKeyInfo->aColl[] */    int nCol;                     /* Number of columns in result set */    assert( p->pRightmost==p );    nCol = p->pEList->nExpr;    pKeyInfo = sqlite3DbMallocZero(db,                       sizeof(*pKeyInfo)+nCol*(sizeof(CollSeq*) + 1));    if( !pKeyInfo ){      rc = SQLITE_NOMEM;      goto multi_select_end;    }    pKeyInfo->enc = ENC(db);    pKeyInfo->nField = nCol;    for(i=0, apColl=pKeyInfo->aColl; i<nCol; i++, apColl++){      *apColl = multiSelectCollSeq(pParse, p, i);      if( 0==*apColl ){        *apColl = db->pDfltColl;      }    }    for(pLoop=p; pLoop; pLoop=pLoop->pPrior){      for(i=0; i<2; i++){        int addr = pLoop->addrOpenEphm[i];        if( addr<0 ){          /* If [0] is unused then [1] is also unused.  So we can          ** always safely abort as soon as the first unused slot is found */          assert( pLoop->addrOpenEphm[1]<0 );          break;        }        sqlite3VdbeChangeP2(v, addr, nCol);        sqlite3VdbeChangeP4(v, addr, (char*)pKeyInfo, P4_KEYINFO);        pLoop->addrOpenEphm[i] = -1;      }    }    sqlite3DbFree(db, pKeyInfo);  }multi_select_end:  pDest->iMem = dest.iMem;  pDest->nMem = dest.nMem;  sqlite3SelectDelete(db, pDelete);  return rc;}#endif /* SQLITE_OMIT_COMPOUND_SELECT *//*** Code an output subroutine for a coroutine implementation of a** SELECT statment.**** The data to be output is contained in pIn->iMem.  There are** pIn->nMem columns to be output.  pDest is where the output should** be sent.**** regReturn is the number of the register holding the subroutine** return address.**** If regPrev>0 then it is a the first register in a vector that** records the previous output.  mem[regPrev] is a flag that is false** if there has been no previous output.  If regPrev>0 then code is** generated to suppress duplicates.  pKeyInfo is used for comparing** keys.**** If the LIMIT found in p->iLimit is reached, jump immediately to** iBreak.*/static int generateOutputSubroutine(  Parse *pParse,          /* Parsing context */  Select *p,              /* The SELECT statement */  SelectDest *pIn,        /* Coroutine supplying data */  SelectDest *pDest,      /* Where to send the data */  int regReturn,          /* The return address register */  int regPrev,            /* Previous result register.  No uniqueness if 0 */  KeyInfo *pKeyInfo,      /* For comparing with previous entry */  int p4type,             /* The p4 type for pKeyInfo */  int iBreak              /* Jump here if we hit the LIMIT */){  Vdbe *v = pParse->pVdbe;  int iContinue;  int addr;  addr = sqlite3VdbeCurrentAddr(v);  iContinue = sqlite3VdbeMakeLabel(v);  /* Suppress duplicates for UNION, EXCEPT, and INTERSECT   */  if( regPrev ){    int j1, j2;    j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev);    j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iMem, regPrev+1, pIn->nMem,                              (char*)pKeyInfo, p4type);    sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);    sqlite3VdbeJumpHere(v, j1);    sqlite3ExprCodeCopy(pParse, pIn->iMem, regPrev+1, pIn->nMem);    sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);  }  if( pParse->db->mallocFailed ) return 0;  /* Suppress the the first OFFSET entries if there is an OFFSET clause  */  codeOffset(v, p, iContinue);  switch( pDest->eDest ){    /* Store the result as data using a unique key.    */    case SRT_Table:    case SRT_EphemTab: {      int r1 = sqlite3GetTempReg(pParse);      int r2 = sqlite3GetTempReg(pParse);      sqlite3VdbeAddOp3(v, OP_MakeRecord, pIn->iMem, pIn->nMem, r1);      sqlite3VdbeAddOp2(v, OP_NewRowid, pDest->iParm, r2);      sqlite3VdbeAddOp3(v, OP_Insert, pDest->iParm, r1, r2);      sqlite3VdbeChangeP5(v, OPFLAG_APPEND);      sqlite3ReleaseTempReg(pParse, r2);      sqlite3ReleaseTempReg(pParse, r1);      break;    }#ifndef SQLITE_OMIT_SUBQUERY    /* If we are creating a set for an "expr IN (SELECT ...)" construct,    ** then there should be a single item on the stack.  Write this    ** item into the set table with bogus data.    */    case SRT_Set: {      int r1;      assert( pIn->nMem==1 );      p->affinity =          sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affinity);      r1 = sqlite3GetTempReg(pParse);      sqlite3VdbeAddOp4(v, OP_MakeRecord, pIn->iMem, 1, r1, &p->affinity, 1);      sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, 1);      sqlite3VdbeAddOp2(v, OP_IdxInsert, pDest->iParm, r1);      sqlite3ReleaseTempReg(pParse, r1);      break;    }#if 0  /* Never occurs on an ORDER BY query */    /* If any row exist in the result set, record that fact and abort.    */    case SRT_Exists: {      sqlite3VdbeAddOp2(v, OP_Integer, 1, pDest->iParm);      /* The LIMIT clause will terminate the loop for us */      break;    }#endif    /* If this is a scalar select that is part of an expression, then    ** store the results in the appropriate memory cell and break out    ** of the scan loop.    */    case SRT_Mem: {      assert( pIn->nMem==1 );      sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iParm, 1);      /* The LIMIT clause will jump out of the loop for us */      break;    }#endif /* #ifndef SQLITE_OMIT_SUBQUERY */    /* The results are stored in a sequence of registers    ** starting at pDest->iMem.  Then the co-routine yields.    */    case SRT_Coroutine: {      if( pDest->iMem==0 ){        pDest->iMem = sqlite3GetTempRange(pParse, pIn->nMem);        pDest->nMem = pIn->nMem;      }      sqlite3ExprCodeMove(pParse, pIn->iMem, pDest->iMem, pDest->nMem);      sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);      break;    }    /* Results are stored in a sequence of registers.  Then the    ** OP_ResultRow opcode is used to cause sqlite3_step() to return    ** the next row of result.    */    case SRT_Output: {      sqlite3VdbeAddOp2(v, OP_ResultRow, pIn->iMem, pIn->nMem);      sqlite3ExprCacheAffinityChange(pParse, pIn->iMem, pIn->nMem);      break;    }#if !defined(SQLITE_OMIT_TRIGGER)    /* Discard the results.  This is used for SELECT statements inside    ** the body of a TRIGGER.  The purpose of such selects is to call    ** user-defined functions that have side effects.  We do not care    ** about the actual results of the select.    */    default: {      break;    }#endif  }  /* Jump to the end of the loop if the LIMIT is reached.  */  if( p->iLimit ){    sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);    sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);  }  /* Generate the subroutine return  */  sqlite3VdbeResolveLabel(v, iContinue);  sqlite3VdbeAddOp1(v, OP_Return, regReturn);  return addr;}/*** Alternative compound select code generator for cases when there** is an ORDER BY clause.**** We assume a query of the following form:****      <selectA>  <operator>  <selectB>  ORDER BY <orderbylist>**** <operator> is one of UNION ALL, UNION, EXCEPT, or INTERSECT.  The idea** is to code both <selectA> and <selectB> with the ORDER BY clause as** co-routines.  Then run the co-routines in parallel and merge the results** into the output.  In addition to the two coroutines (called selectA and** selectB) there are 7 subroutines:****    outA:    Move the output of the selectA coroutine into the output**             of the compound query.****    outB:    Move the output of the selectB coroutine into the output**             of the compound query.  (Only generated for UNION and**             UNION ALL.  EXCEPT and INSERTSECT never output a row that**             appears only in B.)****    AltB:    Called when there is data from both coroutines and A<B.****    AeqB:    Called when there is data from both coroutines and A==B.****    AgtB:    Called when there is data from both coroutines and A>B.****    EofA:    Called when data is exhausted from selectA.****    EofB:    Called when data is exhausted from selectB.**** The implementation of the latter five subroutines depend on which ** <operator> is used:******             UNION ALL         UNION            EXCEPT          INTERSECT**          -------------  -----------------  --------------  -----------------**   AltB:   outA, nextA      outA, nextA       outA, nextA         nextA****   AeqB:   outA, nextA         nextA             nextA         outA, nextA****   AgtB:   outB, nextB      outB, nextB          nextB            nextB****   EofA:   outB, nextB      outB, nextB          halt             halt****   EofB:   outA, nextA      outA, nextA       outA, nextA         halt**** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA** causes an immediate jump to EofA and an EOF on B following nextB causes** an immediate jump to EofB.  Within EofA and EofB, and EOF on entry or** following nextX causes a jump to the end of the select processing.**** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled** w

⌨️ 快捷键说明

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