📄 select.c
字号:
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 + -