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

📄 select.c

📁 sqlite 嵌入式数据库的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* Pull the requested columns.  */  if( nColumn>0 ){    for(i=0; i<nColumn; i++){      sqlite3VdbeAddOp(v, OP_Column, srcTab, i);    }  }else{    nColumn = pEList->nExpr;    for(i=0; i<pEList->nExpr; i++){      sqlite3ExprCode(pParse, pEList->a[i].pExpr);    }  }  /* 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 ){#if NULL_ALWAYS_DISTINCT    sqlite3VdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqlite3VdbeCurrentAddr(v)+7);#endif    /* Deliberately leave the affinity string off of the following    ** OP_MakeRecord */    sqlite3VdbeAddOp(v, OP_MakeRecord, pEList->nExpr * -1, 0);    sqlite3VdbeAddOp(v, OP_Distinct, distinct, sqlite3VdbeCurrentAddr(v)+3);    sqlite3VdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);    sqlite3VdbeAddOp(v, OP_Goto, 0, iContinue);    VdbeComment((v, "# skip indistinct records"));    sqlite3VdbeAddOp(v, OP_IdxInsert, distinct, 0);    if( pOrderBy==0 ){      codeLimiter(v, p, iContinue, iBreak, nColumn);    }  }  switch( eDest ){#ifndef SQLITE_OMIT_COMPOUND_SELECT    /* In this mode, write each query result to the key of the temporary    ** table iParm.    */    case SRT_Union: {      sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);      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_TempTable: {      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 ){        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);      }      sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v));      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.    */    case SRT_Callback:    case SRT_Sorter: {      if( pOrderBy ){        sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);        pushOntoSorter(pParse, v, pOrderBy);      }else{        assert( eDest==SRT_Callback );        sqlite3VdbeAddOp(v, OP_Callback, nColumn, 0);      }      break;    }    /* Invoke a subroutine to handle the results.  The subroutine itself    ** is responsible for popping the results off of the stack.    */    case SRT_Subroutine: {      if( pOrderBy ){        sqlite3VdbeAddOp(v, OP_MakeRecord, nColumn, 0);        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqlite3VdbeAddOp(v, OP_Gosub, 0, iParm);      }      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;}/*** 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 end1 = sqlite3VdbeMakeLabel(v);  int end2 = sqlite3VdbeMakeLabel(v);  int addr;  KeyInfo *pInfo;  ExprList *pOrderBy;  int nCol, i;  sqlite3 *db = pParse->db;  if( eDest==SRT_Sorter ) return;  pOrderBy = p->pOrderBy;  nCol = pOrderBy->nExpr;  pInfo = sqliteMalloc( sizeof(*pInfo) + nCol*(sizeof(CollSeq*)+1) );  if( pInfo==0 ) return;  pInfo->aSortOrder = (char*)&pInfo->aColl[nCol];  pInfo->nField = nCol;  for(i=0; i<nCol; i++){    /* If a collation sequence was specified explicity, then it    ** is stored in pOrderBy->a[i].zName. Otherwise, use the default    ** collation type for the expression.    */    pInfo->aColl[i] = sqlite3ExprCollSeq(pParse, pOrderBy->a[i].pExpr);    if( !pInfo->aColl[i] ){      pInfo->aColl[i] = db->pDfltColl;    }    pInfo->aSortOrder[i] = pOrderBy->a[i].sortOrder;  }  sqlite3VdbeOp3(v, OP_Sort, 0, 0, (char*)pInfo, P3_KEYINFO_HANDOFF);  addr = sqlite3VdbeAddOp(v, OP_SortNext, 0, end1);  codeLimiter(v, p, addr, end2, 1);  switch( eDest ){    case SRT_Table:    case SRT_TempTable: {      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, end1);      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;    }  }  sqlite3VdbeAddOp(v, OP_Goto, 0, addr);  sqlite3VdbeResolveLabel(v, end2);  sqlite3VdbeAddOp(v, OP_Pop, 1, 0);  sqlite3VdbeResolveLabel(v, end1);  sqlite3VdbeAddOp(v, OP_SortReset, 0, 0);}/*** 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:      zType = 0;  }    return zType;}/*** Generate code that will tell the VDBE the declaration types of columns** in the result set.*/static void generateColumnTypes(  Parse *pParse,      /* Parser context */  SrcList *pTabList,  /* List of tables */  ExprList *pEList    /* Expressions defining the result set */){  Vdbe *v = pParse->pVdbe;  int i;  NameContext sNC;  sNC.pSrcList = pTabList;  for(i=0; i<pEList->nExpr; i++){    Expr *p = pEList->a[i].pExpr;    const char *zType = columnType(&sNC, p);    if( zType==0 ) continue;    /* The vdbe must make it's own copy of the column-type, in case the     ** schema is reset before this virtual machine is deleted.    */    sqlite3VdbeSetColName(v, i+pEList->nExpr, zType, strlen(zType));  }}/*** Generate code that will tell the VDBE the names of columns** in the result set.  This information is used to provide the** azCol[] values in the callback.*/static void generateColumnNames(  Parse *pParse,      /* Parser context */  SrcList *pTabList,  /* List of tables */  ExprList *pEList    /* Expressions defining the result set */){  Vdbe *v = pParse->pVdbe;  int i, j;  sqlite3 *db = pParse->db;  int fullNames, shortNames;#ifndef SQLITE_OMIT_EXPLAIN  /* If this is an EXPLAIN, skip this step */  if( pParse->explain ){    return;  }#endif  assert( v!=0 );  if( pParse->colNamesSet || v==0 || sqlite3_malloc_failed ) return;  pParse->colNamesSet = 1;  fullNames = (db->flags & SQLITE_FullColNames)!=0;  shortNames = (db->flags & SQLITE_ShortColNames)!=0;  sqlite3VdbeSetNumCols(v, pEList->nExpr);  for(i=0; i<pEList->nExpr; i++){    Expr *p;    p = pEList->a[i].pExpr;    if( p==0 ) continue;    if( pEList->a[i].zName ){      char *zName = pEList->a[i].zName;      sqlite3VdbeSetColName(v, i, zName, strlen(zName));      continue;    }    if( p->op==TK_COLUMN && pTabList ){

⌨️ 快捷键说明

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