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

📄 select.c

📁 SQLite 2.8.6 源代码,用来在Linux/Unix/Windows上编译安装.它是一个小型的数据库,但是非常好用,速度也快,一般的数据库查询之类的操作据统计比MySQL,PostgreSQL
💻 C
📖 第 1 页 / 共 5 页
字号:
  }  zSortOrder[pOrderBy->nExpr] = 0;  sqliteVdbeAddOp(v, OP_SortMakeKey, pOrderBy->nExpr, 0);  sqliteVdbeChangeP3(v, -1, zSortOrder, strlen(zSortOrder));  sqliteFree(zSortOrder);  sqliteVdbeAddOp(v, OP_SortPut, 0, 0);}/*** This routine adds a P3 argument to the last VDBE opcode that was** inserted. The P3 argument added is a string suitable for the ** OP_MakeKey or OP_MakeIdxKey opcodes.  The string consists of** characters 't' or 'n' depending on whether or not the various** fields of the key to be generated should be treated as numeric** or as text.  See the OP_MakeKey and OP_MakeIdxKey opcode** documentation for additional information about the P3 string.** See also the sqliteAddIdxKeyType() routine.*/void sqliteAddKeyType(Vdbe *v, ExprList *pEList){  int nColumn = pEList->nExpr;  char *zType = sqliteMalloc( nColumn+1 );  int i;  if( zType==0 ) return;  for(i=0; i<nColumn; i++){    zType[i] = sqliteExprType(pEList->a[i].pExpr)==SQLITE_SO_NUM ? 'n' : 't';  }  zType[i] = 0;  sqliteVdbeChangeP3(v, -1, zType, nColumn);  sqliteFree(zType);}/*** 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 */){  Vdbe *v = pParse->pVdbe;  int i;  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.  */  if( pOrderBy==0 ){    if( p->iOffset>=0 ){      int addr = sqliteVdbeCurrentAddr(v);      sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+2);      sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);    }    if( p->iLimit>=0 ){      sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);    }  }  /* Pull the requested columns.  */  if( nColumn>0 ){    for(i=0; i<nColumn; i++){      sqliteVdbeAddOp(v, OP_Column, srcTab, i);    }  }else{    nColumn = pEList->nExpr;    for(i=0; i<pEList->nExpr; i++){      sqliteExprCode(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( distinct>=0 && pEList && pEList->nExpr>0 ){#if NULL_ALWAYS_DISTINCT    sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);#endif    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);    if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pEList);    sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3);    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);    sqliteVdbeAddOp(v, OP_String, 0, 0);    sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);  }  switch( eDest ){    /* In this mode, write each query result to the key of the temporary    ** table iParm.    */    case SRT_Union: {      sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);      sqliteVdbeAddOp(v, OP_String, 0, 0);      sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);      break;    }    /* Store the result as data using a unique key.    */    case SRT_Table:    case SRT_TempTable: {      sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);      if( pOrderBy ){        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);        sqliteVdbeAddOp(v, OP_Pull, 1, 0);        sqliteVdbeAddOp(v, OP_PutIntKey, 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 = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);      sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3);      sqliteVdbeAddOp(v, OP_Delete, iParm, 0);      break;    }    /* 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 lbl = sqliteVdbeMakeLabel(v);      assert( nColumn==1 );      sqliteVdbeAddOp(v, OP_IsNull, -1, lbl);      if( pOrderBy ){        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqliteVdbeAddOp(v, OP_String, 0, 0);        sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);      }      sqliteVdbeResolveLabel(v, lbl);      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, v, pOrderBy);      }else{        sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);        sqliteVdbeAddOp(v, OP_Goto, 0, iBreak);      }      break;    }    /* Send the data to the callback function.    */    case SRT_Callback:    case SRT_Sorter: {      if( pOrderBy ){        sqliteVdbeAddOp(v, OP_SortMakeRec, nColumn, 0);        pushOntoSorter(pParse, v, pOrderBy);      }else{        assert( eDest==SRT_Callback );        sqliteVdbeAddOp(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 ){        sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqliteVdbeAddOp(v, OP_Gosub, 0, iParm);      }      break;    }    /* 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 );      sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);      break;    }  }  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(  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 end = sqliteVdbeMakeLabel(v);  int addr;  if( eDest==SRT_Sorter ) return;  sqliteVdbeAddOp(v, OP_Sort, 0, 0);  addr = sqliteVdbeAddOp(v, OP_SortNext, 0, end);  if( p->iOffset>=0 ){    sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+4);    sqliteVdbeAddOp(v, OP_Pop, 1, 0);    sqliteVdbeAddOp(v, OP_Goto, 0, addr);  }  if( p->iLimit>=0 ){    sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, end);  }  switch( eDest ){    case SRT_Callback: {      sqliteVdbeAddOp(v, OP_SortCallback, nColumn, 0);      break;    }    case SRT_Table:    case SRT_TempTable: {      sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);      sqliteVdbeAddOp(v, OP_Pull, 1, 0);      sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0);      break;    }    case SRT_Set: {      assert( nColumn==1 );      sqliteVdbeAddOp(v, OP_IsNull, -1, sqliteVdbeCurrentAddr(v)+3);      sqliteVdbeAddOp(v, OP_String, 0, 0);      sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);      break;    }    case SRT_Mem: {      assert( nColumn==1 );      sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);      sqliteVdbeAddOp(v, OP_Goto, 0, end);      break;    }    case SRT_Subroutine: {      int i;      for(i=0; i<nColumn; i++){        sqliteVdbeAddOp(v, OP_Column, -1-i, i);      }      sqliteVdbeAddOp(v, OP_Gosub, 0, iParm);      sqliteVdbeAddOp(v, OP_Pop, 1, 0);      break;    }    default: {      /* Do nothing */      break;    }  }  sqliteVdbeAddOp(v, OP_Goto, 0, addr);  sqliteVdbeResolveLabel(v, end);  sqliteVdbeAddOp(v, OP_SortReset, 0, 0);}/*** Generate code that will tell the VDBE the datatypes of** columns in the result set.**** This routine only generates code if the "PRAGMA show_datatypes=on"** has been executed.  The datatypes are reported out in the azCol** parameter to the callback function.  The first N azCol[] entries** are the names of the columns, and the second N entries are the** datatypes for the columns.**** The "datatype" for a result that is a column of a type is the** datatype definition extracted from the CREATE TABLE statement.** The datatype for an expression is either TEXT or NUMERIC.  The** datatype for a ROWID field is INTEGER.*/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, j;  if( pParse->useCallback && (pParse->db->flags & SQLITE_ReportTypes)==0 ){    return;  }  for(i=0; i<pEList->nExpr; i++){    Expr *p = pEList->a[i].pExpr;    char *zType = 0;    if( p==0 ) continue;    if( p->op==TK_COLUMN && pTabList ){      Table *pTab;      int iCol = p->iColumn;      for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){}      assert( j<pTabList->nSrc );      pTab = pTabList->a[j].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;      }    }else{      if( sqliteExprType(p)==SQLITE_SO_TEXT ){        zType = "TEXT";      }else{        zType = "NUMERIC";      }    }    sqliteVdbeAddOp(v, OP_ColumnName, i + pEList->nExpr, 0);    sqliteVdbeChangeP3(v, -1, zType, P3_STATIC);  }}/*** Generate code that will tell the VDBE the names of columns** in the result set.  This information is used to provide the** azCol[] vaolues 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;  if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return;  pParse->colNamesSet = 1;  for(i=0; i<pEList->nExpr; i++){    Expr *p;    char *zType = 0;    int showFullNames;    p = pEList->a[i].pExpr;    if( p==0 ) continue;    if( pEList->a[i].zName ){      char *zName = pEList->a[i].zName;      sqliteVdbeAddOp(v, OP_ColumnName, i, 0);      sqliteVdbeChangeP3(v, -1, zName, strlen(zName));      continue;    }    showFullNames = (pParse->db->flags & SQLITE_FullColNames)!=0;    if( p->op==TK_COLUMN && pTabList ){      Table *pTab;      char *zCol;      int iCol = p->iColumn;      for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){}      assert( j<pTabList->nSrc );      pTab = pTabList->a[j].pTab;      if( iCol<0 ) iCol = pTab->iPKey;      assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );      if( iCol<0 ){        zCol = "_ROWID_";        zType = "INTEGER";      }else{        zCol = pTab->aCol[iCol].zName;        zType = pTab->aCol[iCol].zType;      }      if( p->span.z && p->span.z[0] && !showFullNames ){        int addr = sqliteVdbeAddOp(v,OP_ColumnName, i, 0);        sqliteVdbeChangeP3(v, -1, p->span.z, p->span.n);        sqliteVdbeCompressSpace(v, addr);      }else if( pTabList->nSrc>1 || showFullNames ){        char *zName = 0;        char *zTab;         zTab = pTabList->a[j].zAlias;

⌨️ 快捷键说明

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