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