📄 select.c
字号:
int iParm = pDest->iParm; int regRow; int regRowid; iTab = pOrderBy->iECursor; if( eDest==SRT_Output || eDest==SRT_Coroutine ){ pseudoTab = pParse->nTab++; sqlite3VdbeAddOp2(v, OP_SetNumColumns, 0, nColumn); sqlite3VdbeAddOp2(v, OP_OpenPseudo, pseudoTab, eDest==SRT_Output); } addr = 1 + sqlite3VdbeAddOp2(v, OP_Sort, iTab, brk); codeOffset(v, p, cont); regRow = sqlite3GetTempReg(pParse); regRowid = sqlite3GetTempReg(pParse); sqlite3VdbeAddOp3(v, OP_Column, iTab, pOrderBy->nExpr + 1, regRow); switch( eDest ){ case SRT_Table: case SRT_EphemTab: { sqlite3VdbeAddOp2(v, OP_NewRowid, iParm, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, iParm, regRow, regRowid); sqlite3VdbeChangeP5(v, OPFLAG_APPEND); break; }#ifndef SQLITE_OMIT_SUBQUERY case SRT_Set: { assert( nColumn==1 ); sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, 1, regRowid, &p->affinity, 1); sqlite3ExprCacheAffinityChange(pParse, regRow, 1); sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, regRowid); break; } case SRT_Mem: { assert( nColumn==1 ); sqlite3ExprCodeMove(pParse, regRow, iParm, 1); /* The LIMIT clause will terminate the loop for us */ break; }#endif case SRT_Output: case SRT_Coroutine: { int i; sqlite3VdbeAddOp2(v, OP_Integer, 1, regRowid); sqlite3VdbeAddOp3(v, OP_Insert, pseudoTab, regRow, regRowid); for(i=0; i<nColumn; i++){ assert( regRow!=pDest->iMem+i ); sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i); } if( eDest==SRT_Output ){ sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn); sqlite3ExprCacheAffinityChange(pParse, pDest->iMem, nColumn); }else{ sqlite3VdbeAddOp1(v, OP_Yield, pDest->iParm); } break; } default: { /* Do nothing */ break; } } sqlite3ReleaseTempReg(pParse, regRow); sqlite3ReleaseTempReg(pParse, regRowid); /* LIMIT has been implemented by the pushOntoSorter() routine. */ assert( p->iLimit==0 ); /* The bottom of the loop */ sqlite3VdbeResolveLabel(v, cont); sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); sqlite3VdbeResolveLabel(v, brk); if( eDest==SRT_Output || eDest==SRT_Coroutine ){ sqlite3VdbeAddOp2(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 */){#ifndef SQLITE_OMIT_DECLTYPE 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 *zType;#ifdef SQLITE_ENABLE_COLUMN_METADATA const char *zOrigDb = 0; const char *zOrigTab = 0; const char *zOrigCol = 0; zType = columnType(&sNC, p, &zOrigDb, &zOrigTab, &zOrigCol); /* The vdbe must make its 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_DATABASE, zOrigDb, P4_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_TABLE, zOrigTab, P4_TRANSIENT); sqlite3VdbeSetColName(v, i, COLNAME_COLUMN, zOrigCol, P4_TRANSIENT);#else zType = columnType(&sNC, p, 0, 0, 0);#endif sqlite3VdbeSetColName(v, i, COLNAME_DECLTYPE, zType, P4_TRANSIENT); }#endif /* SQLITE_OMIT_DECLTYPE */}/*** 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 || db->mallocFailed ) 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)); }else 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 ){ 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; zName = sqlite3MPrintf(db, "%s.%s", zTab, zCol); sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, P4_DYNAMIC); }else{ sqlite3VdbeSetColName(v, i, COLNAME_NAME, zCol, strlen(zCol)); } }else{ sqlite3VdbeSetColName(v, i, COLNAME_NAME, (char*)p->span.z, p->span.n); } } 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 *//*** Given a an expression list (which is really the list of expressions** that form the result set of a SELECT statement) compute appropriate** column names for a table that would hold the expression list.**** All column names will be unique.**** Only the column names are computed. Column.zType, Column.zColl,** and other fields of Column are zeroed.**** Return SQLITE_OK on success. If a memory allocation error occurs,** store NULL in *paCol and 0 in *pnCol and return SQLITE_NOMEM.*/static int selectColumnsFromExprList( Parse *pParse, /* Parsing context */ ExprList *pEList, /* Expr list from which to derive column names */ int *pnCol, /* Write the number of columns here */ Column **paCol /* Write the new column list here */){ sqlite3 *db = pParse->db; int i, j, cnt; Column *aCol, *pCol; int nCol; Expr *p; char *zName; int nName; *pnCol = nCol = pEList->nExpr; aCol = *paCol = sqlite3DbMallocZero(db, sizeof(aCol[0])*nCol); if( aCol==0 ) return SQLITE_NOMEM; for(i=0, pCol=aCol; i<nCol; i++, pCol++){ /* 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 = sqlite3DbStrDup(db, zName); }else{ Expr *pCol = p; Table *pTab; while( pCol->op==TK_DOT ) pCol = pCol->pRight; if( pCol->op==TK_COLUMN && (pTab = pCol->pTab)!=0 ){ /* For columns use the column name name */ int iCol = pCol->iColumn; if( iCol<0 ) iCol = pTab->iPKey; zName = sqlite3MPrintf(db, "%s", iCol>=0 ? pTab->aCol[iCol].zName : "rowid"); }else{ /* Use the original text of the column expression as its name */ zName = sqlite3MPrintf(db, "%T", &pCol->span); } } if( db->mallocFailed ){ sqlite3DbFree(db, zName); break; } sqlite3Dequote(zName); /* Make sure the column name is unique. If the name is not unique, ** append a integer to the name so that it becomes unique.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -