Move the generation of output column names earlier, to right after name

resolution and before query transformations such as flattening.  This prevents
the names from getting mangled by query transformations, and obviates hacks
in the query flattener that attempt to work around the name mangling.
The resulting code is smaller and faster and gives more consistent output.
This is an alternative fix to ticket [de3403bf5ae5f72ed].

FossilOrigin-Name: 09834279aeca3bda63de684a369ed64f2cbf587b5f5df1454c0a3c009a1337ad
This commit is contained in:
drh 2017-07-29 16:01:55 +00:00
parent 7751deb3e2
commit f35f2f92ed
3 changed files with 32 additions and 70 deletions

View File

@ -1,5 +1,5 @@
C Update\sTcl\sversion\sused\sby\sthe\sTclKit\sbatch\stool\sfor\sMSVC.
D 2017-07-28T22:22:15.250
C Move\sthe\sgeneration\sof\soutput\scolumn\snames\searlier,\sto\sright\safter\sname\nresolution\sand\sbefore\squery\stransformations\ssuch\sas\sflattening.\s\sThis\sprevents\nthe\snames\sfrom\sgetting\smangled\sby\squery\stransformations,\sand\sobviates\shacks\nin\sthe\squery\sflattener\sthat\sattempt\sto\swork\saround\sthe\sname\smangling.\nThe\sresulting\scode\sis\ssmaller\sand\sfaster\sand\sgives\smore\sconsistent\soutput.\nThis\sis\san\salternative\sfix\sto\sticket\s[de3403bf5ae5f72ed].
D 2017-07-29T16:01:55.238
F Makefile.in d9873c9925917cca9990ee24be17eb9613a668012c85a343aef7e5536ae266e8
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc 02b469e9dcd5b7ee63fc1fb05babc174260ee4cfa4e0ef2e48c3c6801567a016
@ -452,7 +452,7 @@ F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
F src/resolve.c 4324a94573b1e29286f8121e4881db59eaedc014afeb274c8d3e07ed282e0e20
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
F src/select.c c6bf96a7f9d7d68f929de84738c599a30d0a725ab0b54420e70545743cd5ee7b
F src/select.c 31b35ddf55f1021f7148a01306984b057c11ebb6e3463d94677225e0a1e301a3
F src/shell.c bd6a37cbe8bf64ef6a6a74fdc50f067d3148149b4ce2b4d03154663e66ded55f
F src/shell.c.in b5725acacba95ccefa57b6d068f710e29ba8239c3aa704628a1902a1f729c175
F src/sqlite.h.in 0e2603c23f0747c5660669f946e231730af000c76d1653b153dcf2c26fce0a6b
@ -1637,7 +1637,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P 3286e1a07b0693049a07f0865bf93749c461ea8f6d1175ec2d1642886673d8ac
R fa880debd22b5643c43c3f5ac12562f1
U mistachkin
Z 2ba3113508e5372bd91f947e270302b1
P bcec155e0d6c6b17ae09d5a366c080723d01ff40dbc1a0ad0bb669a91db1b850
R 1dd5a0c8909a7008cc7feb807ee35ff5
T *branch * early-column-names
T *sym-early-column-names *
T -sym-trunk *
U drh
Z 012e37d9c831aa36f84ce05878b8d813

View File

@ -1 +1 @@
bcec155e0d6c6b17ae09d5a366c080723d01ff40dbc1a0ad0bb669a91db1b850
09834279aeca3bda63de684a369ed64f2cbf587b5f5df1454c0a3c009a1337ad

View File

@ -1438,13 +1438,10 @@ static const char *columnTypeImpl(
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
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.
**
** The ALWAYS() is because iCol>=pS->pEList->nExpr will have been
** caught already by name resolution.
*/
NameContext sNC;
Expr *p = pS->pEList->a[iCol].pExpr;
@ -1554,18 +1551,6 @@ static void generateColumnTypes(
#endif /* !defined(SQLITE_OMIT_DECLTYPE) */
}
/*
** Return the Table objecct in the SrcList that has cursor iCursor.
** Or return NULL if no such Table object exists in the SrcList.
*/
static Table *tableWithCursor(SrcList *pList, int iCursor){
int j;
for(j=0; j<pList->nSrc; j++){
if( pList->a[j].iCursor==iCursor ) return pList->a[j].pTab;
}
return 0;
}
/*
** Compute the column names for a SELECT statement.
@ -1599,15 +1584,16 @@ static Table *tableWithCursor(SrcList *pList, int iCursor){
*/
static void generateColumnNames(
Parse *pParse, /* Parser context */
SrcList *pTabList, /* The FROM clause of the SELECT */
ExprList *pEList /* Expressions defining the result set */
Select *pSelect /* Generate column names for this SELECT statement */
){
Vdbe *v = pParse->pVdbe;
int i;
Table *pTab;
SrcList *pTabList;
ExprList *pEList;
sqlite3 *db = pParse->db;
int fullName; /* TABLE.COLUMN if no AS clause and is a direct table ref */
int srcName; /* COLUMN or TABLE.COLUMN if no AS clause and is direct */
int fullName; /* TABLE.COLUMN if no AS clause and is a direct table ref */
int srcName; /* COLUMN or TABLE.COLUMN if no AS clause and is direct */
#ifndef SQLITE_OMIT_EXPLAIN
/* If this is an EXPLAIN, skip this step */
@ -1617,6 +1603,10 @@ static void generateColumnNames(
#endif
if( pParse->colNamesSet || db->mallocFailed ) return;
/* Column names are determined by the left-most term of a compound select */
while( pSelect->pPrior ) pSelect = pSelect->pPrior;
pTabList = pSelect->pSrc;
pEList = pSelect->pEList;
assert( v!=0 );
assert( pTabList!=0 );
pParse->colNamesSet = 1;
@ -1631,12 +1621,11 @@ static void generateColumnNames(
/* An AS clause always takes first priority */
char *zName = pEList->a[i].zName;
sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
}else if( srcName
&& (p->op==TK_COLUMN || p->op==TK_AGG_COLUMN)
&& (pTab = tableWithCursor(pTabList, p->iTable))!=0
){
}else if( srcName && p->op==TK_COLUMN ){
char *zCol;
int iCol = p->iColumn;
pTab = p->pTab;
assert( pTab!=0 );
if( iCol<0 ) iCol = pTab->iPKey;
assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );
if( iCol<0 ){
@ -2468,11 +2457,6 @@ static int multiSelect(
if( dest.eDest!=priorOp ){
int iCont, iBreak, iStart;
assert( p->pEList );
if( dest.eDest==SRT_Output ){
Select *pFirst = p;
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
}
iBreak = sqlite3VdbeMakeLabel(v);
iCont = sqlite3VdbeMakeLabel(v);
computeLimitRegisters(pParse, p, iBreak);
@ -2543,11 +2527,6 @@ static int multiSelect(
** tables.
*/
assert( p->pEList );
if( dest.eDest==SRT_Output ){
Select *pFirst = p;
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
}
iBreak = sqlite3VdbeMakeLabel(v);
iCont = sqlite3VdbeMakeLabel(v);
computeLimitRegisters(pParse, p, iBreak);
@ -3155,14 +3134,6 @@ static int multiSelectOrderBy(
*/
sqlite3VdbeResolveLabel(v, labelEnd);
/* Set the number of output columns
*/
if( pDest->eDest==SRT_Output ){
Select *pFirst = pPrior;
while( pFirst->pPrior ) pFirst = pFirst->pPrior;
generateColumnNames(pParse, pFirst->pSrc, pFirst->pEList);
}
/* Reassembly the compound query so that it will be freed correctly
** by the calling function */
if( p->pPrior ){
@ -3457,7 +3428,6 @@ static int flattenSubquery(
Select *pSub1; /* Pointer to the rightmost select in sub-query */
SrcList *pSrc; /* The FROM clause of the outer query */
SrcList *pSubSrc; /* The FROM clause of the subquery */
ExprList *pList; /* The result set of the outer query */
int iParent; /* VDBE cursor number of the pSub result set temp table */
int iNewParent = -1;/* Replacement table for iParent */
int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
@ -3782,14 +3752,6 @@ static int flattenSubquery(
** 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; i<pList->nExpr; 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
@ -5219,6 +5181,14 @@ int sqlite3Select(
}
#endif
/* Get a pointer the VDBE under construction, allocating a new VDBE if one
** does not already exist */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto select_end;
if( pDest->eDest==SRT_Output ){
generateColumnNames(pParse, p);
}
/* Try to flatten subqueries in the FROM clause up into the main query
*/
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
@ -5254,11 +5224,6 @@ int sqlite3Select(
}
#endif
/* Get a pointer the VDBE under construction, allocating a new VDBE if one
** does not already exist */
v = sqlite3GetVdbe(pParse);
if( v==0 ) goto select_end;
#ifndef SQLITE_OMIT_COMPOUND_SELECT
/* Handle compound SELECT statements using the separate multiSelect()
** procedure.
@ -6058,12 +6023,6 @@ int sqlite3Select(
select_end:
explainSetInteger(pParse->iSelectId, iRestoreSelectId);
/* Identify column names if results of the SELECT are to be output.
*/
if( rc==SQLITE_OK && pDest->eDest==SRT_Output ){
generateColumnNames(pParse, pTabList, pEList);
}
sqlite3DbFree(db, sAggInfo.aCol);
sqlite3DbFree(db, sAggInfo.aFunc);
#if SELECTTRACE_ENABLED