]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Move the generation of output column names earlier, to right after name
authordrh <drh@noemail.net>
Mon, 31 Jul 2017 13:11:26 +0000 (13:11 +0000)
committerdrh <drh@noemail.net>
Mon, 31 Jul 2017 13:11:26 +0000 (13:11 +0000)
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 a fix for ticket [de3403bf5ae5f72ed] and a cherry-pick
of check-in [09834279aeca3bda]

FossilOrigin-Name: 499942b3eece097a6b1695ebe60d7eb3d7f3de397bc28ebf6b1fe038116487e8

manifest
manifest.uuid
src/select.c

index ecf32ef85dde81eb2b668ed83a406015e5856d81..604bacc6ef992dd01663543ed80ed51fab544bfe 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Correctly\shandle\san\s"INTEGER\sPRIMARY\sKEY\sUNIQUE"\scolumn\sin\sa\sWITHOUT\sROWID\ntable.\s\sThis\sis\sa\sfix\sfor\sticket\s[bc115541132dad136],\scherry-picked\sfrom\ncheck-in\s[5216bfb73f1a49bdd8]
-D 2017-07-31T12:19:40.621
+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\sa\sfix\sfor\sticket\s[de3403bf5ae5f72ed]\sand\sa\scherry-pick\nof\scheck-in\s[09834279aeca3bda]
+D 2017-07-31T13:11:26.773
 F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
 F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
 F Makefile.msc 8eeb80162074004e906b53d7340a12a14c471a83743aab975947e95ce061efcc
@@ -403,7 +403,7 @@ F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
 F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
 F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
 F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
-F src/select.c c444ca057d48cf1a4eb8f6a58fbc13418a7f83ae94a6bd6f29f7ad6c704a9e4c
+F src/select.c 32194c97925b1115d86ceb0ee120161cab84ab865ef8a05e7c3e29126862642b
 F src/shell.c a37d96b20b3644d0eb905df5aa7a0fcf9f6e73c15898337230c760a24a8df794
 F src/sqlite.h.in 8dd468837a4f6d76713e3a4cc65bea48095009038593d41040ab46c1b351197f
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
@@ -1580,8 +1580,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P b77f297d38426a4d6da6d957f652d215f11327c09ed0f1d7e26306918dfa70ea
-Q +5216bfb73f1a49bdd879d470de139bf46a212474eaf6f38ad2390536d66a2afd
-R eb07fcc768c6f4ff6ae20a5819466310
+P 322a2ede6dae04a8e7e07fe0d99040f38f025fa142bd0493025ad6d65c2aaf6d
+Q +09834279aeca3bda63de684a369ed64f2cbf587b5f5df1454c0a3c009a1337ad
+R ee888609eec8840f4fd67e7c6e447810
 U drh
-Z 75dcf6651c63dcff0accc15625ce1b08
+Z eb821f3365754be8341001ca1d6fca99
index dc654207b46c8f68abb65f3c7c5dabca1be3e65a..46eb8bccc8d24ffb9954a4d2ff7144c9348f9f05 100644 (file)
@@ -1 +1 @@
-322a2ede6dae04a8e7e07fe0d99040f38f025fa142bd0493025ad6d65c2aaf6d
\ No newline at end of file
+499942b3eece097a6b1695ebe60d7eb3d7f3de397bc28ebf6b1fe038116487e8
\ No newline at end of file
index ff7d6c6e4749f8dfc10e7bab202b29646ac973b0..a038e824ee634822eae08cb4fa1be1ae8c6c74d9 100644 (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;
-}
-
 
 /*
 ** Generate code that will tell the VDBE the names of columns
@@ -1574,14 +1559,16 @@ static Table *tableWithCursor(SrcList *pList, int iCursor){
 */
 static void generateColumnNames(
   Parse *pParse,      /* Parser context */
-  SrcList *pTabList,  /* List of tables */
-  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 fullNames, shortNames;
+  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 */
@@ -1591,24 +1578,29 @@ 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;
-  fullNames = (db->flags & SQLITE_FullColNames)!=0;
-  shortNames = (db->flags & SQLITE_ShortColNames)!=0;
+  fullName = (db->flags & SQLITE_FullColNames)!=0;
+  srcName = (db->flags & SQLITE_ShortColNames)!=0 || fullName;
   sqlite3VdbeSetNumCols(v, pEList->nExpr);
   for(i=0; i<pEList->nExpr; i++){
-    Expr *p;
-    p = pEList->a[i].pExpr;
-    if( NEVER(p==0) ) continue;
+    Expr *p = pEList->a[i].pExpr;
+
+    assert( p!=0 );
     if( pEList->a[i].zName ){
+      /* An AS clause always takes first priority */
       char *zName = pEList->a[i].zName;
       sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_TRANSIENT);
-    }else if( (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 ){
@@ -1616,10 +1608,7 @@ static void generateColumnNames(
       }else{
         zCol = pTab->aCol[iCol].zName;
       }
-      if( !shortNames && !fullNames ){
-        sqlite3VdbeSetColName(v, i, COLNAME_NAME, 
-            sqlite3DbStrDup(db, pEList->a[i].zSpan), SQLITE_DYNAMIC);
-      }else if( fullNames ){
+      if( fullName ){
         char *zName = 0;
         zName = sqlite3MPrintf(db, "%s.%s", pTab->zName, zCol);
         sqlite3VdbeSetColName(v, i, COLNAME_NAME, zName, SQLITE_DYNAMIC);
@@ -2433,11 +2422,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);
@@ -2508,11 +2492,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);
@@ -3120,14 +3099,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 ){
@@ -3418,7 +3389,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 */    
@@ -3743,14 +3713,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
@@ -5077,6 +5039,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)
@@ -5112,11 +5082,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.
@@ -5903,12 +5868,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