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

📄 select.c

📁 sqlite-3.4.1,嵌入式数据库.是一个功能强大的开源数据库,给学习和研发以及小型公司的发展带来了全所未有的好处.
💻 C
📖 第 1 页 / 共 5 页
字号:
    sqlite3VdbeAddOp(v, OP_IfMemZero, p->iLimit, brk);  }  /* The bottom of the loop  */  sqlite3VdbeResolveLabel(v, cont);  sqlite3VdbeAddOp(v, OP_Next, iTab, addr);  sqlite3VdbeResolveLabel(v, brk);  if( eDest==SRT_Callback || eDest==SRT_Subroutine ){    sqlite3VdbeAddOp(v, OP_Close, pseudoTab, 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.**** 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 a ROWID field is INTEGER. Exactly when an expression** is considered a column can be complex in the presence of subqueries. The** result-set expression in all of the following SELECT statements is ** considered a column by this function.****   SELECT col FROM tbl;**   SELECT (SELECT col FROM tbl;**   SELECT (SELECT col FROM tbl);**   SELECT abc FROM (SELECT col AS abc FROM tbl);** ** The declaration type for any expression other than a column is NULL.*/static const char *columnType(  NameContext *pNC,   Expr *pExpr,  const char **pzOriginDb,  const char **pzOriginTab,  const char **pzOriginCol){  char const *zType = 0;  char const *zOriginDb = 0;  char const *zOriginTab = 0;  char const *zOriginCol = 0;  int j;  if( pExpr==0 || pNC->pSrcList==0 ) return 0;  switch( pExpr->op ){    case TK_AGG_COLUMN:    case TK_COLUMN: {      /* The expression is a column. Locate the table the column is being      ** extracted from in NameContext.pSrcList. This table may be real      ** database table or a subquery.      */      Table *pTab = 0;            /* Table structure column is extracted from */      Select *pS = 0;             /* Select the column is extracted from */      int iCol = pExpr->iColumn;  /* Index of column in pTab */      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;          pS = pTabList->a[j].pSelect;        }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( pS ){        /* The "table" is actually a sub-select or a view in the FROM clause        ** of the SELECT statement. Return the declaration type and origin        ** data for the result-set column of the sub-select.        */        if( iCol>=0 && iCol<pS->pEList->nExpr ){          /* If iCol is less than zero, then the expression requests the          ** rowid of the sub-select or view. This expression is legal (see           ** test case misc2.2.2) - it always evaluates to NULL.          */          NameContext sNC;          Expr *p = pS->pEList->a[iCol].pExpr;          sNC.pSrcList = pS->pSrc;          sNC.pNext = 0;          sNC.pParse = pNC->pParse;          zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);         }      }else if( pTab->pSchema ){        /* A real table */        assert( !pS );        if( iCol<0 ) iCol = pTab->iPKey;        assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );        if( iCol<0 ){          zType = "INTEGER";          zOriginCol = "rowid";        }else{          zType = pTab->aCol[iCol].zType;          zOriginCol = pTab->aCol[iCol].zName;        }        zOriginTab = pTab->zName;        if( pNC->pParse ){          int iDb = sqlite3SchemaToIndex(pNC->pParse->db, pTab->pSchema);          zOriginDb = pNC->pParse->db->aDb[iDb].zName;        }      }      break;    }#ifndef SQLITE_OMIT_SUBQUERY    case TK_SELECT: {      /* The expression is a sub-select. Return the declaration type and      ** origin info for the single column in the result set of the SELECT      ** statement.      */      NameContext sNC;      Select *pS = pExpr->pSelect;      Expr *p = pS->pEList->a[0].pExpr;      sNC.pSrcList = pS->pSrc;      sNC.pNext = pNC;      sNC.pParse = pNC->pParse;      zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol);       break;    }#endif  }    if( pzOriginDb ){    assert( pzOriginTab && pzOriginCol );    *pzOriginDb = zOriginDb;    *pzOriginTab = zOriginTab;    *pzOriginCol = zOriginCol;  }  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;  sNC.pParse = pParse;  for(i=0; i<pEList->nExpr; i++){    Expr *p = pEList->a[i].pExpr;    const char *zOrigDb = 0;    const char *zOrigTab = 0;    const char *zOrigCol = 0;    const char *zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol);    /* The vdbe must make it's own copy of the column-type and other     ** column specific strings, in case the schema is reset before this    ** virtual machine is deleted.    */    sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P3_TRANSIENT);    sqlite3VdbeSetColName(v, i, COLNAME_DATABASE, zOrigDb, P3_TRANSIENT);    sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P3_TRANSIENT);    sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P3_TRANSIENT);  }}/*** 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 || sqlite3MallocFailed() ) 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, COLNAME_NAME, zName, strlen(zName));      continue;    }    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";      }else{        zCol = pTab->aCol[iCol].zName;      }      if( !shortNames && !fullNames && p->span.z && p->span.z[0] ){        sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n);      }else if( fullNames || (!shortNames && pTabList->nSrc>1) ){        char *zName = 0;        char *zTab;         zTab = pTabList->a[j].zAlias;        if( fullNames || zTab==0 ) zTab = pTab->zName;        sqlite3SetString(&zName, zTab, ".", zCol, (char*)0);        sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P3_DYNAMIC);      }else{        sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol));      }    }else if( p->span.z && p->span.z[0] ){      sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n);      /* sqlite3VdbeCompressSpace(v, addr); */    }else{      char zName[30];      assert( p->op!=TK_COLUMN || pTabList==0 );      sqlite3_snprintf(sizeof(zName), zName, "column%d", i+1);      sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, 0);    }  }  generateColumnTypes(pParse, pTabList, pEList);}#ifndef SQLITE_OMIT_COMPOUND_SELECT/*** Name of the connection operator, used for error messages.*/static const char *selectOpName(int id){  char *z;  switch( id ){    case TK_ALL:       z = "UNION ALL";   break;    case TK_INTERSECT: z = "INTERSECT";   break;    case TK_EXCEPT:    z = "EXCEPT";      break;    default:           z = "UNION";       break;  }  return z;}#endif /* SQLITE_OMIT_COMPOUND_SELECT *//*** Forward declaration*/static int prepSelectStmt(Parse*, Select*);/*** Given a SELECT statement, generate a Table structure that describes** the result set of that SELECT.*/Table *sqlite3ResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){  Table *pTab;  int i, j;  ExprList *pEList;  Column *aCol, *pCol;  while( pSelect->pPrior ) pSelect = pSelect->pPrior;  if( prepSelectStmt(pParse, pSelect) ){    return 0;  }  if( sqlite3SelectResolve(pParse, pSelect, 0) ){    return 0;  }  pTab = sqliteMalloc( sizeof(Table) );  if( pTab==0 ){    return 0;  }  pTab->nRef = 1;  pTab->zName = zTabName ? sqliteStrDup(zTabName) : 0;  pEList = pSelect->pEList;  pTab->nCol = pEList->nExpr;  assert( pTab->nCol>0 );  pTab->aCol = aCol = sqliteMalloc( sizeof(pTab->aCol[0])*pTab->nCol );  for(i=0, pCol=aCol; i<pTab->nCol; i++, pCol++){    Expr *p, *pR;    char *zType;    char *zName;    int nName;    CollSeq *pColl;    int cnt;    NameContext sNC;        /* Get an appropriate name for the column    */    p = pEList->a[i].pExpr;    assert( p->pRight==0 || p->pRight->token.z==0 || p->pRight->token.z[0]!=0 );    if( (zName = pEList->a[i].zName)!=0 ){      /* If the column contains an "AS <name>" phrase, use <name> as the name */      zName = sqliteStrDup(zName);    }else if( p->op==TK_DOT               && (pR=p->pRight)!=0 && pR->token.z && pR->token.z[0] ){      /* For columns of the from A.B use B as the name */      zName = sqlite3MPrintf("%T", &pR->token);    }else if( p->span.z && p->span.z[0] ){      /* Use the original text of the column expression as its name */      zName = sqlite3MPrintf("%T", &p->span);    }else{      /* If all else fails, make up a name */      zName = sqlite3MPrintf("column%d", i+1);    }    sqlite3Dequote(zName);    if( sqlite3MallocFailed() ){      sqliteFree(zName);      sqlite3DeleteTable(pTab);      return 0;    }    /* Make sure the column name is unique.  If the name is not unique,    ** append a integer to the name so that it becomes unique.    */    nName = strlen(zName);    for(j=cnt=0; j<i; j++){      if( sqlite3StrICmp(aCol[j].zName, zName)==0 ){        zName[nName] = 0;        zName = sqlite3MPrintf("%z:%d", zName, ++cnt);        j = -1;        if( zName==0 ) break;      }    }    pCol->zName = zName;    /* Get the typename, type affinity, and collating sequence for the    ** column.    */    memset(&sNC, 0, sizeof(sNC));    sNC.pSrcList = pSelect->pSrc;    zType = sqliteStrDup(columnType(&sNC, p, 0, 0, 0));    pCol->zType = zType;    pCol->affinity = sqlite3ExprAffinity(p);    pColl = sqlite3ExprCollSeq(pParse, p);    if( pColl ){      pCol->zColl = sqliteStrDup(pColl->zName);    }  }  pTab->iPKey = -1;  return pTab;}/*** Prepare a SELECT statement for processing by doing the following** things:****    (1)  Make sure VDBE cursor numbers have been assigned to every**         element of the FROM clause.****    (2)  Fill in the pTabList->a[].pTab fields in the SrcList that **         defines FROM clause.  When views appear in the FROM clause,**         fill pTabList->a[].pSelect with a copy of the SELECT statement**         that implements the view.  A copy is made of the view's SELECT**         statement so that we can freely modify or delete that statement**         without worrying about messing up the presistent representation**         of the view.****    (3)  Add terms to the WHERE clause to accomodate the NATURAL keyword**         on joins and the ON and USING clause of joins.****    (4)  Scan the list of columns in the result set (pEList) looking**         for instances of the "*" operator or the TABLE.* operator.**         If found, expand each "*" to be every column in every table**         and TABLE.* to be every column in TABLE.**** Return 0 on success.  If there are problems, leave an error message** in pParse and return non-zero.*/static int prepSelectStmt(Parse *pParse, Select *p){

⌨️ 快捷键说明

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