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

📄 select.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
    addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);    sqlite3VdbeJumpHere(v, addr1);    sqlite3VdbeAddOp(v, OP_Last, pOrderBy->iECursor, 0);    sqlite3VdbeAddOp(v, OP_Delete, pOrderBy->iECursor, 0);    sqlite3VdbeJumpHere(v, addr2);    pSelect->iLimit = -1;  }}/*** 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 */  int nPop          /* Number of times to pop stack when jumping */){  if( p->iOffset>=0 && iContinue!=0 ){    int addr;    sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iOffset);    addr = sqlite3VdbeAddOp(v, OP_IfMemNeg, p->iOffset, 0);    if( nPop>0 ){      sqlite3VdbeAddOp(v, OP_Pop, nPop, 0);    }    sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);    VdbeComment((v, "# skip OFFSET records"));    sqlite3VdbeJumpHere(v, addr);  }}/*** Add code that will check to make sure the top N elements of the** stack are distinct.  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(  Vdbe *v,           /* Generate code into this VM */  int iTab,          /* A sorting index used to test for distinctness */  int addrRepeat,    /* Jump to here if not distinct */  int N              /* The top N elements of the stack must be distinct */){  sqlite3VdbeAddOp(v, OP_MakeRecord, -N, 0);  sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3);  sqlite3VdbeAddOp(v, OP_Pop, N+1, 0);  sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat);  VdbeComment((v, "# skip indistinct records"));  sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 0);}/*** 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, int eDest, int nExpr){  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 int 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 */  int eDest,              /* How to dispose of the results */  int iParm,              /* An argument to the disposal method */  int iContinue,          /* Jump here to continue with next row */  int iBreak,             /* Jump here to break out of the inner loop */  char *aff               /* affinity string if eDest is SRT_Union */){  Vdbe *v = pParse->pVdbe;  int i;  int hasDistinct;        /* True if the DISTINCT keyword is present */  if( v==0 ) return 0;  assert( pEList!=0 );  /* If there was a LIMIT clause on the SELECT statement, then do the check  ** to see if this row should be output.  */  hasDistinct = distinct>=0 && pEList->nExpr>0;  if( pOrderBy==0 && !hasDistinct ){    codeOffset(v, p, iContinue, 0);  }  /* Pull the requested columns.  */  if( nColumn>0 ){    for(i=0; i<nColumn; i++){      sqlite3VdbeAddOp(v, OP_Column, srcTab, i);    }  }else{    nColumn = pEList->nExpr;    sqlite3ExprCodeExprList(pParse, pEList);  }  /* 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(v, distinct, iContinue, nColumn);    if( pOrderBy==0 ){      codeOffset(v, p, iContinue, nColumn);    }  }  if( checkForMultiColumnSelectError(pParse, eDest, pEList->nExpr) ){    return 0;  }  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: {      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);      if( aff ){        sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);      }      sqlite3VdbeAddOp(v, OP_IdxInsert, iParm, 0);      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: {      int addr;      addr = sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);      sqlite3VdbeChangeP3(v, -1, aff, P3_STATIC);      sqlite3VdbeAddOp(v, OP_NotFound, iParm, addr+3);      sqlite3VdbeAddOp(v, OP_Delete, iParm, 0);      break;    }#endif    /* Store the result as data using a unique key.    */    case SRT_Table:    case SRT_EphemTab: {      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);      if( pOrderBy ){        pushOntoSorter(pParse, pOrderBy, p);      }else{        sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);        sqlite3VdbeAddOp(v, OP_Pull, 1, 0);        sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND);      }      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 addr1 = sqlite3VdbeCurrentAddr(v);      int addr2;      assert( nColumn==1 );      sqlite3VdbeAddOp(v, OP_NotNull, -1, addr1+3);      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);      addr2 = sqlite3VdbeAddOp(v, OP_Goto, 0, 0);      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr,(iParm>>16)&0xff);      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);      }else{        sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1);        sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);      }      sqlite3VdbeJumpHere(v, addr2);      break;    }    /* If any row exist in the result set, record that fact and abort.    */    case SRT_Exists: {      sqlite3VdbeAddOp(v, OP_MemInt, 1, iParm);      sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);      /* 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);      }else{        sqlite3VdbeAddOp(v, OP_MemStore, 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_Subroutine:    case SRT_Callback: {      if( pOrderBy ){        sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);        pushOntoSorter(pParse, pOrderBy, p);      }else if( eDest==SRT_Subroutine ){        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);      }else{        sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);      }      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 );      sqlite3VdbeAddOp(v, OP_Pop, nColumn, 0);      break;    }#endif  }  /* Jump to the end of the loop if the LIMIT is reached.  */  if( p->iLimit>=0 && pOrderBy==0 ){    sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit);    sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, iBreak);  }  return 0;}/*** 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 P3 field of an opcode using** P3_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 = sqliteMalloc( 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 */  int eDest,       /* Write the sorted results here */  int iParm        /* Optional parameter associated with eDest */){  int brk = sqlite3VdbeMakeLabel(v);  int cont = sqlite3VdbeMakeLabel(v);  int addr;  int iTab;  int pseudoTab = 0;  ExprList *pOrderBy = p->pOrderBy;  iTab = pOrderBy->iECursor;  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){    pseudoTab = pParse->nTab++;    sqlite3VdbeAddOp(v, OP_OpenPseudo, pseudoTab, 0);    sqlite3VdbeAddOp(v, OP_SetNumColumns, pseudoTab, nColumn);  }  addr = 1 + sqlite3VdbeAddOp(v, OP_Sort, iTab, brk);  codeOffset(v, p, cont, 0);  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){    sqlite3VdbeAddOp(v, OP_Integer, 1, 0);  }  sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1);  switch( eDest ){    case SRT_Table:    case SRT_EphemTab: {      sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);      sqlite3VdbeAddOp(v, OP_Insert, iParm, OPFLAG_APPEND);      break;    }#ifndef SQLITE_OMIT_SUBQUERY    case SRT_Set: {      assert( nColumn==1 );      sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);      sqlite3VdbeAddOp(v, OP_Pop, 1, 0);      sqlite3VdbeAddOp(v, OP_Goto, 0, sqlite3VdbeCurrentAddr(v)+3);      sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &p->affinity, 1);      sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);      break;    }    case SRT_Mem: {      assert( nColumn==1 );      sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);      /* The LIMIT clause will terminate the loop for us */      break;    }#endif    case SRT_Callback:    case SRT_Subroutine: {      int i;      sqlite3VdbeAddOp(v, OP_Insert, pseudoTab, 0);      for(i=0; i<nColumn; i++){        sqlite3VdbeAddOp(v, OP_Column, pseudoTab, i);      }      if( eDest==SRT_Callback ){        sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);      }else{        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);      }      break;    }    default: {      /* Do nothing */      break;    }  }  /* Jump to the end of the loop when the LIMIT is reached  */  if( p->iLimit>=0 ){    sqlite3VdbeAddOp(v, OP_MemIncr, -1, p->iLimit);

⌨️ 快捷键说明

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