Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -882,11 +882,11 @@ 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 */ testcase( pExpr->op==TK_AGG_COLUMN ); testcase( pExpr->op==TK_COLUMN ); - while( ALWAYS(pNC) && !pTab ){ + while( pNC && !pTab ){ SrcList *pTabList = pNC->pSrcList; for(j=0;jnSrc && pTabList->a[j].iCursor!=pExpr->iTable;j++); if( jnSrc ){ pTab = pTabList->a[j].pTab; pS = pTabList->a[j].pSelect; @@ -893,22 +893,32 @@ }else{ pNC = pNC->pNext; } } - if( NEVER(pTab==0) ){ + if( pTab==0 ){ /* At one time, code such as "SELECT new.x" within a trigger would ** cause this condition to run. Since then, we have restructured how ** trigger code is generated and so this condition is no longer - ** possible. But it seems prudent to keep the test in place in - ** case something else changes. - */ - zType = "TEXT"; + ** possible. However, it can still be true for statements like + ** the following: + ** + ** CREATE TABLE t1(col INTEGER); + ** SELECT (SELECT t1.col) FROM FROM t1; + ** + ** when columnType() is called on the expression "t1.col" in the + ** sub-select. In this case, set the column type to NULL, even + ** though it should really be "INTEGER". + ** + ** This is not a problem, as the column type of "t1.col" is never + ** used. When columnType() is called on the expression + ** "(SELECT t1.col)", the correct type is returned (see the TK_SELECT + ** branch below. */ break; } - assert( pTab ); + assert( pTab && pExpr->pTab==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. */ @@ -918,11 +928,11 @@ ** 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.pNext = pNC; sNC.pParse = pNC->pParse; zType = columnType(&sNC, p, &zOriginDb, &zOriginTab, &zOriginCol); } }else if( ALWAYS(pTab->pSchema) ){ /* A real table */ Index: test/capi3c.test ================================================================== --- test/capi3c.test +++ test/capi3c.test @@ -1318,7 +1318,41 @@ sqlite3_column_text16 $STMT 2 sqlite3_column_text $STMT 3 } {one} sqlite3_finalize $STMT } + +# Test decltype on some SELECT statements that contain sub-selects. +# +proc decltype {zSql} { + set ret [list] + set STMT [sqlite3_prepare_v2 db $zSql -1 TAIL] + for {set i 0} {$i < [sqlite3_column_count $STMT]} {incr i} { + lappend ret [sqlite3_column_decltype $STMT $i] + } + sqlite3_finalize $STMT + return $ret +} +do_test capi3c-24.1 { + execsql { CREATE TABLE t5(a INTEGER, b STRING, c DATETIME) } + decltype {SELECT * FROM t5} +} {INTEGER STRING DATETIME} +do_test capi3c-24.2 { + decltype {SELECT (SELECT c) FROM t5} +} {DATETIME} +do_test capi3c-24.3 { + decltype {SELECT (SELECT * FROM (SELECT c)) FROM t5} +} {DATETIME} +do_test capi3c-24.4 { + decltype {SELECT * FROM (SELECT * FROM t5 ORDER BY c LIMIT 1) ORDER BY b} +} {INTEGER STRING DATETIME} +do_test capi3c-24.5 { + decltype { + SELECT (SELECT x FROM (SELECT c AS x)) + FROM (SELECT * FROM t5 ORDER BY c LIMIT 1) ORDER BY b + } +} {DATETIME} +do_test capi3c-24.3 { + decltype {SELECT (SELECT x FROM (SELECT t5.a AS x)) FROM t5} +} {INTEGER} finish_test