diff options
Diffstat (limited to 'src/select.c')
-rw-r--r-- | src/select.c | 96 |
1 files changed, 52 insertions, 44 deletions
diff --git a/src/select.c b/src/select.c index 5e2b30462..f2441e490 100644 --- a/src/select.c +++ b/src/select.c @@ -1298,9 +1298,6 @@ static void selectInnerLoop( testcase( eDest==SRT_Fifo ); testcase( eDest==SRT_DistFifo ); sqlite3VdbeAddOp3(v, OP_MakeRecord, regResult, nResultCol, r1+nPrefixReg); - if( pDest->zAffSdst ){ - sqlite3VdbeChangeP4(v, -1, pDest->zAffSdst, nResultCol); - } #ifndef SQLITE_OMIT_CTE if( eDest==SRT_DistFifo ){ /* If the destination is DistFifo, then cursor (iParm+1) is open @@ -2291,39 +2288,38 @@ int sqlite3ColumnsFromExprList( /* ** This bit, when added to the "aff" parameter of -** sqlite3SelectAddColumnTypeAndCollation() means that result set +** sqlite3ColumnTypeOfSubquery() means that result set ** expressions of the form "CAST(expr AS NUMERIC)" should result in ** NONE affinity rather than NUMERIC affinity. */ #define SQLITE_AFF_FLAG1 0x10 /* -** Add type and collation information to a column list based on -** a SELECT statement. -** -** The column list presumably came from selectColumnNamesFromExprList(). -** The column list has only names, not types or collations. This -** routine goes through and adds the types and collations. +** pTab is a transient Table object that represents a subquery of some +** kind (maybe a parenthesized subquery in the FROM clause of a larger +** query, or a VIEW, or a CTE). This routine computes type information +** for that Table object based on the Select object that implements the +** subquery. For the purposes of this routine, "type infomation" means: ** -** This routine requires that all identifiers in the SELECT -** statement be resolved. +** * The datatype name, as it might appear in a CREATE TABLE statement +** * Which collating sequence to use for the column +** * The affinity of the column ** ** The SQLITE_AFF_FLAG1 bit added to parameter aff means that a ** result set column of the form "CAST(expr AS NUMERIC)" should use ** NONE affinity rather than NUMERIC affinity. See the ** 2022-12-10 "reopen" of ticket https://sqlite.org/src/tktview/57c47526c3. */ -void sqlite3SelectAddColumnTypeAndCollation( - Parse *pParse, /* Parsing contexts */ - Table *pTab, /* Add column type information to this table */ - Select *pSelect, /* SELECT used to determine types and collations */ - char aff /* Default affinity. Maybe with SQLITE_AFF_FLAG1 too */ +void sqlite3SubqueryColumnTypes( + Parse *pParse, /* Parsing contexts */ + Table *pTab, /* Add column type information to this table */ + Select *pSelect, /* SELECT used to determine types and collations */ + char aff /* Default affinity. Maybe with SQLITE_AFF_FLAG1 too */ ){ sqlite3 *db = pParse->db; - NameContext sNC; Column *pCol; CollSeq *pColl; - int i; + int i,j; Expr *p; struct ExprList_item *a; @@ -2332,22 +2328,42 @@ void sqlite3SelectAddColumnTypeAndCollation( assert( pTab->nCol==pSelect->pEList->nExpr || db->mallocFailed ); if( db->mallocFailed ) return; while( pSelect->pPrior ) pSelect = pSelect->pPrior; - memset(&sNC, 0, sizeof(sNC)); - sNC.pSrcList = pSelect->pSrc; a = pSelect->pEList->a; for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){ const char *zType; i64 n, m; pTab->tabFlags |= (pCol->colFlags & COLFLAG_NOINSERT); p = a[i].pExpr; - zType = columnType(&sNC, p, 0, 0, 0); /* pCol->szEst = ... // Column size est for SELECT tables never used */ pCol->affinity = sqlite3ExprAffinity(p); - if( pCol->affinity==SQLITE_AFF_NUMERIC - && p->op==TK_CAST - && (aff & SQLITE_AFF_FLAG1)!=0 - ){ - pCol->affinity = SQLITE_AFF_NONE; + if( pCol->affinity<=SQLITE_AFF_NONE ){ + assert( (SQLITE_AFF_FLAG1 & SQLITE_AFF_MASK)==0 ); + pCol->affinity = aff & SQLITE_AFF_MASK; + } + if( aff & SQLITE_AFF_FLAG1 ){ + if( pCol->affinity==SQLITE_AFF_NUMERIC && p->op==TK_CAST ){ + pCol->affinity = SQLITE_AFF_NONE; + } + } + if( pCol->affinity>=SQLITE_AFF_TEXT && pSelect->pNext ){ + int m = 0; + Select *pS2; + for(m=0, pS2=pSelect->pNext; pS2; pS2=pS2->pNext){ + m |= sqlite3ExprDataType(pS2->pEList->a[i].pExpr); + } + if( pCol->affinity==SQLITE_AFF_TEXT && (m&0x01)!=0 ){ + pCol->affinity = SQLITE_AFF_BLOB; + }else + if( pCol->affinity>=SQLITE_AFF_NUMERIC && (m&0x02)!=0 ){ + pCol->affinity = SQLITE_AFF_BLOB; + } + } + zType = 0; + for(j=0; j<SQLITE_N_STDTYPE; j++){ + if( sqlite3StdTypeAffinity[j]==pCol->affinity ){ + zType = sqlite3StdType[j]; + break; + } } if( zType ){ m = sqlite3Strlen30(zType); @@ -2361,10 +2377,6 @@ void sqlite3SelectAddColumnTypeAndCollation( pCol->colFlags &= ~(COLFLAG_HASTYPE|COLFLAG_HASCOLL); } } - if( pCol->affinity<=SQLITE_AFF_NONE ){ - assert( (SQLITE_AFF_FLAG1 & SQLITE_AFF_MASK)==0 ); - pCol->affinity = aff & SQLITE_AFF_MASK; - } pColl = sqlite3ExprCollSeq(pParse, p); if( pColl ){ assert( pTab->pIndex==0 ); @@ -2398,7 +2410,7 @@ Table *sqlite3ResultSetOfSelect(Parse *pParse, Select *pSelect, char aff){ pTab->zName = 0; pTab->nRowLogEst = 200; assert( 200==sqlite3LogEst(1048576) ); sqlite3ColumnsFromExprList(pParse, pSelect->pEList, &pTab->nCol, &pTab->aCol); - sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSelect, aff); + sqlite3SubqueryColumnTypes(pParse, pTab, pSelect, aff); pTab->iPKey = -1; if( db->mallocFailed ){ sqlite3DeleteTable(db, pTab); @@ -6209,14 +6221,14 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){ ** This is a Walker.xSelectCallback callback for the sqlite3SelectTypeInfo() ** interface. ** -** For each FROM-clause subquery, add Column.zType and Column.zColl -** information to the Table structure that represents the result set -** of that subquery. +** For each FROM-clause subquery, add Column.zType, Column.zColl, and +** Column.affinity information to the Table structure that represents +** the result set of that subquery. ** ** The Table structure that represents the result set was constructed -** by selectExpander() but the type and collation information was omitted -** at that point because identifiers had not yet been resolved. This -** routine is called after identifier resolution. +** by selectExpander() but the type and collation and affinity information +** was omitted at that point because identifiers had not yet been resolved. +** This routine is called after identifier resolution. */ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ Parse *pParse; @@ -6236,9 +6248,8 @@ static void selectAddSubqueryTypeInfo(Walker *pWalker, Select *p){ /* A sub-query in the FROM clause of a SELECT */ Select *pSel = pFrom->pSelect; if( pSel ){ - while( pSel->pPrior ) pSel = pSel->pPrior; - sqlite3SelectAddColumnTypeAndCollation(pParse, pTab, pSel, - SQLITE_AFF_NONE|SQLITE_AFF_FLAG1); + sqlite3SubqueryColumnTypes(pParse, pTab, pSel, + SQLITE_AFF_NONE|SQLITE_AFF_FLAG1); } } } @@ -7350,10 +7361,7 @@ int sqlite3Select( sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor); ExplainQueryPlan2(addrExplain, (pParse, 1, "MATERIALIZE %!S", pItem)); - dest.zAffSdst = sqlite3TableAffinityStr(db, pItem->pTab); sqlite3Select(pParse, pSub, &dest); - sqlite3DbFree(db, dest.zAffSdst); - dest.zAffSdst = 0; pItem->pTab->nRowLogEst = pSub->nSelectRow; if( onceAddr ) sqlite3VdbeJumpHere(v, onceAddr); sqlite3VdbeAddOp2(v, OP_Return, pItem->regReturn, topAddr+1); |