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

📄 select.c

📁 最新的sqlite3.6.2源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
          return 1;        }        addWhereTerm(pParse, zName, pLeftTab, pLeft->zAlias,                             pRightTab, pRight->zAlias,                            pRight->iCursor, &p->pWhere, isOuter);      }    }  }  return 0;}/*** Insert code into "v" that will push the record on the top of the** stack into the sorter.*/static void pushOntoSorter(  Parse *pParse,         /* Parser context */  ExprList *pOrderBy,    /* The ORDER BY clause */  Select *pSelect,       /* The whole SELECT statement */  int regData            /* Register holding data to be sorted */){  Vdbe *v = pParse->pVdbe;  int nExpr = pOrderBy->nExpr;  int regBase = sqlite3GetTempRange(pParse, nExpr+2);  int regRecord = sqlite3GetTempReg(pParse);  sqlite3ExprCodeExprList(pParse, pOrderBy, regBase, 0);  sqlite3VdbeAddOp2(v, OP_Sequence, pOrderBy->iECursor, regBase+nExpr);  sqlite3ExprCodeMove(pParse, regData, regBase+nExpr+1, 1);  sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);  sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);  sqlite3ReleaseTempReg(pParse, regRecord);  sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);  if( pSelect->iLimit ){    int addr1, addr2;    int iLimit;    if( pSelect->iOffset ){      iLimit = pSelect->iOffset+1;    }else{      iLimit = pSelect->iLimit;    }    addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit);    sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);    addr2 = sqlite3VdbeAddOp0(v, OP_Goto);    sqlite3VdbeJumpHere(v, addr1);    sqlite3VdbeAddOp1(v, OP_Last, pOrderBy->iECursor);    sqlite3VdbeAddOp1(v, OP_Delete, pOrderBy->iECursor);    sqlite3VdbeJumpHere(v, addr2);    pSelect->iLimit = 0;  }}/*** Add code to implement the OFFSET*/static void codeOffset(  Vdbe *v,          /* Generate code into this VM */  Select *p,        /* The SELECT statement being coded */  int iContinue     /* Jump here to skip the current record */){  if( p->iOffset && iContinue!=0 ){    int addr;    sqlite3VdbeAddOp2(v, OP_AddImm, p->iOffset, -1);    addr = sqlite3VdbeAddOp1(v, OP_IfNeg, p->iOffset);    sqlite3VdbeAddOp2(v, OP_Goto, 0, iContinue);    VdbeComment((v, "skip OFFSET records"));    sqlite3VdbeJumpHere(v, addr);  }}/*** Add code that will check to make sure the N registers starting at iMem** form a distinct entry.  iTab is a sorting index that holds previously** seen combinations of the N values.  A new entry is made in iTab** if the current N values are new.**** A jump to addrRepeat is made and the N+1 values are popped from the** stack if the top N elements are not distinct.*/static void codeDistinct(  Parse *pParse,     /* Parsing and code generating context */  int iTab,          /* A sorting index used to test for distinctness */  int addrRepeat,    /* Jump to here if not distinct */  int N,             /* Number of elements */  int iMem           /* First element */){  Vdbe *v;  int r1;  v = pParse->pVdbe;  r1 = sqlite3GetTempReg(pParse);  sqlite3VdbeAddOp3(v, OP_MakeRecord, iMem, N, r1);  sqlite3VdbeAddOp3(v, OP_Found, iTab, addrRepeat, r1);  sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, r1);  sqlite3ReleaseTempReg(pParse, r1);}/*** Generate an error message when a SELECT is used within a subexpression** (example:  "a IN (SELECT * FROM table)") but it has more than 1 result** column.  We do this in a subroutine because the error occurs in multiple** places.*/static int checkForMultiColumnSelectError(  Parse *pParse,       /* Parse context. */  SelectDest *pDest,   /* Destination of SELECT results */  int nExpr            /* Number of result columns returned by SELECT */){  int eDest = pDest->eDest;  if( nExpr>1 && (eDest==SRT_Mem || eDest==SRT_Set) ){    sqlite3ErrorMsg(pParse, "only a single result allowed for "       "a SELECT that is part of an expression");    return 1;  }else{    return 0;  }}/*** This routine generates the code for the inside of the inner loop** of a SELECT.**** If srcTab and nColumn are both zero, then the pEList expressions** are evaluated in order to get the data for this row.  If nColumn>0** then data is pulled from srcTab and pEList is used only to get the** datatypes for each column.*/static void selectInnerLoop(  Parse *pParse,          /* The parser context */  Select *p,              /* The complete select statement being coded */  ExprList *pEList,       /* List of values being extracted */  int srcTab,             /* Pull data from this table */  int nColumn,            /* Number of columns in the source table */  ExprList *pOrderBy,     /* If not NULL, sort results using this key */  int distinct,           /* If >=0, make sure results are distinct */  SelectDest *pDest,      /* How to dispose of the results */  int iContinue,          /* Jump here to continue with next row */  int iBreak              /* Jump here to break out of the inner loop */){  Vdbe *v = pParse->pVdbe;  int i;  int hasDistinct;        /* True if the DISTINCT keyword is present */  int regResult;              /* Start of memory holding result set */  int eDest = pDest->eDest;   /* How to dispose of results */  int iParm = pDest->iParm;   /* First argument to disposal method */  int nResultCol;             /* Number of result columns */  if( v==0 ) return;  assert( pEList!=0 );  hasDistinct = distinct>=0;  if( pOrderBy==0 && !hasDistinct ){    codeOffset(v, p, iContinue);  }  /* Pull the requested columns.  */  if( nColumn>0 ){    nResultCol = nColumn;  }else{    nResultCol = pEList->nExpr;  }  if( pDest->iMem==0 ){    pDest->iMem = pParse->nMem+1;    pDest->nMem = nResultCol;    pParse->nMem += nResultCol;  }else if( pDest->nMem!=nResultCol ){    /* This happens when two SELECTs of a compound SELECT have differing    ** numbers of result columns.  The error message will be generated by    ** a higher-level routine. */    return;  }  regResult = pDest->iMem;  if( nColumn>0 ){    for(i=0; i<nColumn; i++){      sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, regResult+i);    }  }else if( eDest!=SRT_Exists ){    /* If the destination is an EXISTS(...) expression, the actual    ** values returned by the SELECT are not required.    */    sqlite3ExprCodeExprList(pParse, pEList, regResult, eDest==SRT_Output);  }  nColumn = nResultCol;  /* If the DISTINCT keyword was present on the SELECT statement  ** and this row has been seen before, then do not make this row  ** part of the result.  */  if( hasDistinct ){    assert( pEList!=0 );    assert( pEList->nExpr==nColumn );    codeDistinct(pParse, distinct, iContinue, nColumn, regResult);    if( pOrderBy==0 ){      codeOffset(v, p, iContinue);    }  }  if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){    return;  }  switch( eDest ){    /* In this mode, write each query result to the key of the temporary    ** table iParm.    */#ifndef SQLITE_OMIT_COMPOUND_SELECT    case SRT_Union: {      int r1;      r1 = sqlite3GetTempReg(pParse);      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);      sqlite3ReleaseTempReg(pParse, r1);      break;    }    /* Construct a record from the query result, but instead of    ** saving that record, use it as a key to delete elements from    ** the temporary table iParm.    */    case SRT_Except: {      sqlite3VdbeAddOp3(v, OP_IdxDelete, iParm, regResult, nColumn);      break;    }#endif    /* Store the result as data using a unique key.    */    case SRT_Table:    case SRT_EphemTab: {      int r1 = sqlite3GetTempReg(pParse);      sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);      if( pOrderBy ){        pushOntoSorter(pParse, pOrderBy, p, r1);      }else{        int r2 = sqlite3GetTempReg(pParse);        sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, r2);        sqlite3VdbeAddOp3(v, OP_Insert, 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: {      assert( nColumn==1 );      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);      if( pOrderBy ){        /* At first glance you would think we could optimize out the        ** ORDER BY in this case since the order of entries in the set        ** does not matter.  But there might be a LIMIT clause, in which        ** case the order does matter */        pushOntoSorter(pParse, pOrderBy, p, regResult);      }else{        int r1 = sqlite3GetTempReg(pParse);        sqlite3VdbeAddOp4(v, OP_MakeRecord, regResult, 1, r1, &p->affinity, 1);        sqlite3ExprCacheAffinityChange(pParse, regResult, 1);        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, r1);        sqlite3ReleaseTempReg(pParse, r1);      }      break;    }    /* If any row exist in the result set, record that fact and abort.    */    case SRT_Exists: {      sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm);      /* The LIMIT clause will terminate the loop for us */      break;    }    /* 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( nColumn==1 );      if( pOrderBy ){        pushOntoSorter(pParse, pOrderBy, p, regResult);      }else{        sqlite3ExprCodeMove(pParse, regResult, iParm, 1);        /* The LIMIT clause will jump out of the loop for us */      }      break;    }#endif /* #ifndef SQLITE_OMIT_SUBQUERY */    /* Send the data to the callback function or to a subroutine.  In the    ** case of a subroutine, the subroutine itself is responsible for    ** popping the data from the stack.    */    case SRT_Coroutine:    case SRT_Output: {      if( pOrderBy ){        int r1 = sqlite3GetTempReg(pParse);        sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nColumn, r1);        pushOntoSorter(pParse, pOrderBy, p, r1);        sqlite3ReleaseTempReg(pParse, r1);      }else if( eDest==SRT_Coroutine ){        sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm);      }else{        sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, nColumn);        sqlite3ExprCacheAffinityChange(pParse, regResult, nColumn);      }      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: {      assert( eDest==SRT_Discard );      break;    }#endif  }  /* Jump to the end of the loop if the LIMIT is reached.  */  if( p->iLimit ){    assert( pOrderBy==0 );  /* If there is an ORDER BY, the call to                            ** pushOntoSorter() would have cleared p->iLimit */    sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);    sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);  }}/*** Given an expression list, generate a KeyInfo structure that records** the collating sequence for each expression in that expression list.**** If the ExprList is an ORDER BY or GROUP BY clause then the resulting** KeyInfo structure is appropriate for initializing a virtual index to** implement that clause.  If the ExprList is the result set of a SELECT** then the KeyInfo structure is appropriate for initializing a virtual** index to implement a DISTINCT test.**** Space to hold the KeyInfo structure is obtain from malloc.  The calling** function is responsible for seeing that this structure is eventually** freed.  Add the KeyInfo structure to the P4 field of an opcode using** P4_KEYINFO_HANDOFF is the usual way of dealing with this.*/static KeyInfo *keyInfoFromExprList(Parse *pParse, ExprList *pList){  sqlite3 *db = pParse->db;  int nExpr;  KeyInfo *pInfo;  struct ExprList_item *pItem;  int i;  nExpr = pList->nExpr;  pInfo = sqlite3DbMallocZero(db, sizeof(*pInfo) + nExpr*(sizeof(CollSeq*)+1) );  if( pInfo ){    pInfo->aSortOrder = (u8*)&pInfo->aColl[nExpr];    pInfo->nField = nExpr;    pInfo->enc = ENC(db);    for(i=0, pItem=pList->a; i<nExpr; i++, pItem++){      CollSeq *pColl;      pColl = sqlite3ExprCollSeq(pParse, pItem->pExpr);      if( !pColl ){        pColl = db->pDfltColl;      }      pInfo->aColl[i] = pColl;      pInfo->aSortOrder[i] = pItem->sortOrder;    }  }  return pInfo;}/*** If the inner loop was generated using a non-null pOrderBy argument,** then the results were placed in a sorter.  After the loop is terminated** we need to run the sorter and output the results.  The following** routine generates the code needed to do that.*/static void generateSortTail(  Parse *pParse,    /* Parsing context */  Select *p,        /* The SELECT statement */  Vdbe *v,          /* Generate code into this VDBE */  int nColumn,      /* Number of columns of data */  SelectDest *pDest /* Write the sorted results here */){  int brk = sqlite3VdbeMakeLabel(v);  int cont = sqlite3VdbeMakeLabel(v);  int addr;  int iTab;  int pseudoTab = 0;  ExprList *pOrderBy = p->pOrderBy;  int eDest = pDest->eDest;

⌨️ 快捷键说明

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