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

📄 select.c

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 C
📖 第 1 页 / 共 5 页
字号:
**** A jump to addrRepeat is made and the K 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 */  int K              /* Pop K elements from the stack if indistinct */){#if NULL_ALWAYS_DISTINCT  sqlite3VdbeAddOp(v, OP_IsNull, -N, sqlite3VdbeCurrentAddr(v)+6);#endif  sqlite3VdbeAddOp(v, OP_MakeRecord, -N, 0);  sqlite3VdbeAddOp(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3);  sqlite3VdbeAddOp(v, OP_Pop, K, 0);  sqlite3VdbeAddOp(v, OP_Goto, 0, addrRepeat);  VdbeComment((v, "# skip indistinct records"));  sqlite3VdbeAddOp(v, OP_IdxInsert, iTab, 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 && pEList->nExpr>0;  if( pOrderBy==0 && !hasDistinct ){    codeLimiter(v, p, iContinue, iBreak, 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 ){    int n = pEList->nExpr;    codeDistinct(v, distinct, iContinue, n, n+1);    if( pOrderBy==0 ){      codeLimiter(v, p, iContinue, iBreak, nColumn);    }  }  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, NULL_ALWAYS_DISTINCT);      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, NULL_ALWAYS_DISTINCT);      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_VirtualTab: {      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);      if( pOrderBy ){        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);        sqlite3VdbeAddOp(v, OP_Pull, 1, 0);        sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);      }      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);      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, v, pOrderBy);      }else{        char aff = (iParm>>16)&0xFF;        aff = sqlite3CompareAffinity(pEList->a[0].pExpr, aff);        sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1);        sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);      }      sqlite3VdbeJumpHere(v, addr2);      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_Exists:    case SRT_Mem: {      assert( nColumn==1 );      if( pOrderBy ){        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);        sqlite3VdbeAddOp(v, OP_Goto, 0, iBreak);      }      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, v, pOrderBy);      }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  }  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 = (char*)&pInfo->aColl[nExpr];    pInfo->nField = nExpr;    pInfo->enc = db->enc;    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,   /* The 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;  ExprList *pOrderBy = p->pOrderBy;  iTab = pOrderBy->iECursor;  addr = 1 + sqlite3VdbeAddOp(v, OP_Sort, iTab, brk);  codeLimiter(v, p, cont, brk, 0);  sqlite3VdbeAddOp(v, OP_Column, iTab, pOrderBy->nExpr + 1);  switch( eDest ){    case SRT_Table:    case SRT_VirtualTab: {      sqlite3VdbeAddOp(v, OP_NewRowid, iParm, 0);      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);      sqlite3VdbeAddOp(v, OP_Insert, iParm, 0);      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, "n", P3_STATIC);      sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);      break;    }    case SRT_Exists:    case SRT_Mem: {      assert( nColumn==1 );      sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);      sqlite3VdbeAddOp(v, OP_Goto, 0, brk);      break;    }#endif    case SRT_Callback:    case SRT_Subroutine: {      int i;      sqlite3VdbeAddOp(v, OP_Integer, p->pEList->nExpr, 0);      sqlite3VdbeAddOp(v, OP_Pull, 1, 0);      for(i=0; i<nColumn; i++){        sqlite3VdbeAddOp(v, OP_Column, -1-i, i);      }      if( eDest==SRT_Callback ){        sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);      }else{        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);      }      sqlite3VdbeAddOp(v, OP_Pop, 2, 0);      break;    }    default: {      /* Do nothing */      break;    }  }  sqlite3VdbeResolveLabel(v, cont);  sqlite3VdbeAddOp(v, OP_Next, iTab, addr);  sqlite3VdbeResolveLabel(v, brk);}/*** Return a pointer to a string containing the 'declaration type' of the** expression pExpr. The string may be treated as static by the caller.**** If the declaration type is the exact datatype definition extracted from** the original CREATE TABLE statement if the expression is a column.** ** The declaration type for an expression is either TEXT, NUMERIC or ANY.** The declaration type for a ROWID field is INTEGER.*/static const char *columnType(NameContext *pNC, Expr *pExpr){  char const *zType;  int j;  if( pExpr==0 || pNC->pSrcList==0 ) return 0;  /* The TK_AS operator can only occur in ORDER BY, GROUP BY, HAVING,  ** and LIMIT clauses.  But pExpr originates in the result set of a  ** SELECT.  So pExpr can never contain an AS operator.  */  assert( pExpr->op!=TK_AS );  switch( pExpr->op ){    case TK_COLUMN: {      Table *pTab = 0;      int iCol = pExpr->iColumn;      while( pNC && !pTab ){        SrcList *pTabList = pNC->pSrcList;        for(j=0;j<pTabList->nSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++);        if( j<pTabList->nSrc ){          pTab = pTabList->a[j].pTab;        }else{          pNC = pNC->pNext;        }      }      if( pTab==0 ){        /* FIX ME:        ** This can occurs if you have something like "SELECT new.x;" inside        ** a trigger.  In other words, if you reference the special "new"        ** table in the result set of a select.  We do not have a good way        ** to find the actual table type, so call it "TEXT".  This is really        ** something of a bug, but I do not know how to fix it.        **        ** This code does not produce the correct answer - it just prevents        ** a segfault.  See ticket #1229.        */        zType = "TEXT";        break;      }      assert( pTab );      if( iCol<0 ) iCol = pTab->iPKey;      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );      if( iCol<0 ){        zType = "INTEGER";      }else{        zType = pTab->aCol[iCol].zType;      }      break;    }#ifndef SQLITE_OMIT_SUBQUERY    case TK_SELECT: {      NameContext sNC;      Select *pS = pExpr->pSelect;      sNC.pSrcList = pExpr->pSelect->pSrc;      sNC.pNext = pNC;      zType = columnType(&sNC, pS->pEList->a[0].pExpr);       break;    }#endif    default:

⌨️ 快捷键说明

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