Index: src/select.c ================================================================== --- src/select.c +++ src/select.c @@ -3767,11 +3767,50 @@ pSrc->a[i+iFrom] = pSubSrc->a[i]; iNewParent = pSubSrc->a[i].iCursor; memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); } pSrc->a[iFrom].fg.jointype = jointype; - + + /* For every result column in the outer query that does not have an AS + ** clause, if that column is a reference to an output column from the + ** inner query, then preserve the name of the column by adding an AS clause. + ** This prevents the outer query column from taking on a name derived + ** from inner query column name. + ** + ** Example: + ** CREATE TABLE t1(a,b); + ** CREATE VIEW v1(x,y) AS SELECT a,b FROM t1; + ** SELECT x,y FROM v1; + ** + ** The inner "v1" subquery will get flattened into the outer query. After + ** flattening, the outer query becomes: "SELECT a,b FROM t1". But the + ** new query gives column names of "a" and "b", not the "x" and "y" that + ** the programmer expected. This step adds AS clauses so that the + ** flattened query becomes: "SELECT a AS x, b AS y FROM t1". + ** + ** Update on 2017-07-29: The current implementation only adds AS clauses + ** to outer query result columns that are substituted directly for + ** columns of the inner query. Formerly, all result columns in the outer + ** query got new AS clauses if they didn't have them all ready. Also, + ** the name of the AS clause is taken from the result column name of + ** the inner query. Formerly, the name was a copy of the text of the + ** original SQL statement that specified the column. + */ + pList = pParent->pEList; + for(i=0; inExpr; i++){ + Expr *p; + if( pList->a[i].zName==0 + && (p = pList->a[i].pExpr)->op==TK_COLUMN + && p->iTable==iParent + && p->iColumn>=0 + && ALWAYS(p->pTab!=0) + ){ + char *zName = sqlite3DbStrDup(db, p->pTab->aCol[p->iColumn].zName); + pList->a[i].zName = zName; + } + } + /* Now begin substituting subquery result set expressions for ** references to the iParent in the outer query. ** ** Example: ** @@ -3780,18 +3819,10 @@ ** \_____________________ outer query ______________________________/ ** ** We look at every expression in the outer query and every place we see ** "a" we substitute "x*3" and every place we see "b" we substitute "y+10". */ - pList = pParent->pEList; - for(i=0; inExpr; i++){ - if( pList->a[i].zName==0 ){ - char *zName = sqlite3DbStrDup(db, pList->a[i].zSpan); - sqlite3Dequote(zName); - pList->a[i].zName = zName; - } - } if( pSub->pOrderBy ){ /* At this point, any non-zero iOrderByCol values indicate that the ** ORDER BY column expression is identical to the iOrderByCol'th ** expression returned by SELECT statement pSub. Since these values ** do not necessarily correspond to columns in SELECT statement pParent,