diff options
Diffstat (limited to 'ext/sqlite/libsqlite/src/select.c')
| -rw-r--r-- | ext/sqlite/libsqlite/src/select.c | 394 | 
1 files changed, 205 insertions, 189 deletions
diff --git a/ext/sqlite/libsqlite/src/select.c b/ext/sqlite/libsqlite/src/select.c index 03eb861c9e..9bed641be7 100644 --- a/ext/sqlite/libsqlite/src/select.c +++ b/ext/sqlite/libsqlite/src/select.c @@ -120,9 +120,8 @@ int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){      pParse->nErr++;      jointype = JT_INNER;    }else if( jointype & JT_RIGHT ){ -    sqliteSetString(&pParse->zErrMsg,  -      "RIGHT and FULL OUTER JOINs are not currently supported", 0); -    pParse->nErr++; +    sqliteErrorMsg(pParse,  +      "RIGHT and FULL OUTER JOINs are not currently supported");      jointype = JT_INNER;    }    return jointype; @@ -218,9 +217,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){      if( pTerm->jointype & JT_NATURAL ){        Table *pTab;        if( pTerm->pOn || pTerm->pUsing ){ -        sqliteSetString(&pParse->zErrMsg, "a NATURAL join may not have " +        sqliteErrorMsg(pParse, "a NATURAL join may not have "             "an ON or USING clause", 0); -        pParse->nErr++;          return 1;        }        pTab = pTerm->pTab; @@ -234,9 +232,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){      /* Disallow both ON and USING clauses in the same join      */      if( pTerm->pOn && pTerm->pUsing ){ -      sqliteSetString(&pParse->zErrMsg, "cannot have both ON and USING " -        "clauses in the same join", 0); -      pParse->nErr++; +      sqliteErrorMsg(pParse, "cannot have both ON and USING " +        "clauses in the same join");        return 1;      } @@ -268,9 +265,8 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){        for(j=0; j<pList->nId; j++){          if( columnIndex(pTerm->pTab, pList->a[j].zName)<0 ||              columnIndex(pOther->pTab, pList->a[j].zName)<0 ){ -          sqliteSetString(&pParse->zErrMsg, "cannot join using column ", -            pList->a[j].zName, " - column not present in both tables", 0); -          pParse->nErr++; +          sqliteErrorMsg(pParse, "cannot join using column %s - column " +            "not present in both tables", pList->a[j].zName);            return 1;          }          addWhereTerm(pList->a[j].zName, pTerm->pTab, pOther->pTab, &p->pWhere); @@ -300,13 +296,15 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){  ** will work correctly for both SQLite and Oracle8.  */  static int sqliteOracle8JoinFixup( -  int base,         /* VDBE cursor number for first table in pSrc */    SrcList *pSrc,    /* List of tables being joined */    Expr *pWhere      /* The WHERE clause of the SELECT statement */  ){    int rc = 0;    if( ExprHasProperty(pWhere, EP_Oracle8Join) && pWhere->op==TK_COLUMN ){ -    int idx = pWhere->iTable - base; +    int idx; +    for(idx=0; idx<pSrc->nSrc; idx++){ +      if( pSrc->a[idx].iCursor==pWhere->iTable ) break; +    }      assert( idx>=0 && idx<pSrc->nSrc );      if( idx>0 ){        pSrc->a[idx-1].jointype &= ~JT_INNER; @@ -315,16 +313,16 @@ static int sqliteOracle8JoinFixup(      }    }    if( pWhere->pRight ){ -    rc = sqliteOracle8JoinFixup(base, pSrc, pWhere->pRight); +    rc = sqliteOracle8JoinFixup(pSrc, pWhere->pRight);    }    if( pWhere->pLeft ){ -    rc |= sqliteOracle8JoinFixup(base, pSrc, pWhere->pLeft); +    rc |= sqliteOracle8JoinFixup(pSrc, pWhere->pLeft);    }    if( pWhere->pList ){      int i;      ExprList *pList = pWhere->pList;      for(i=0; i<pList->nExpr && rc==0; i++){ -      rc |= sqliteOracle8JoinFixup(base, pSrc, pList->a[i].pExpr); +      rc |= sqliteOracle8JoinFixup(pSrc, pList->a[i].pExpr);      }    }    if( rc==1 && (pWhere->op==TK_AND || pWhere->op==TK_EQ) ){ @@ -691,12 +689,11 @@ static void generateSortTail(  */  static void generateColumnTypes(    Parse *pParse,      /* Parser context */ -  int base,           /* VDBE cursor corresponding to first entry in pTabList */    SrcList *pTabList,  /* List of tables */    ExprList *pEList    /* Expressions defining the result set */  ){    Vdbe *v = pParse->pVdbe; -  int i; +  int i, j;    if( pParse->useCallback && (pParse->db->flags & SQLITE_ReportTypes)==0 ){      return;    } @@ -705,8 +702,11 @@ static void generateColumnTypes(      char *zType = 0;      if( p==0 ) continue;      if( p->op==TK_COLUMN && pTabList ){ -      Table *pTab = pTabList->a[p->iTable - base].pTab; +      Table *pTab;        int iCol = p->iColumn; +      for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){} +      assert( j<pTabList->nSrc ); +      pTab = pTabList->a[j].pTab;        if( iCol<0 ) iCol = pTab->iPKey;        assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );        if( iCol<0 ){ @@ -733,12 +733,11 @@ static void generateColumnTypes(  */  static void generateColumnNames(    Parse *pParse,      /* Parser context */ -  int base,           /* VDBE cursor corresponding to first entry in pTabList */    SrcList *pTabList,  /* List of tables */    ExprList *pEList    /* Expressions defining the result set */  ){    Vdbe *v = pParse->pVdbe; -  int i; +  int i, j;    if( pParse->colNamesSet || v==0 || sqlite_malloc_failed ) return;    pParse->colNamesSet = 1;    for(i=0; i<pEList->nExpr; i++){ @@ -755,9 +754,12 @@ static void generateColumnNames(      }      showFullNames = (pParse->db->flags & SQLITE_FullColNames)!=0;      if( p->op==TK_COLUMN && pTabList ){ -      Table *pTab = pTabList->a[p->iTable - base].pTab; +      Table *pTab;        char *zCol;        int iCol = p->iColumn; +      for(j=0; j<pTabList->nSrc && pTabList->a[j].iCursor!=p->iTable; j++){} +      assert( j<pTabList->nSrc ); +      pTab = pTabList->a[j].pTab;        if( iCol<0 ) iCol = pTab->iPKey;        assert( iCol==-1 || (iCol>=0 && iCol<pTab->nCol) );        if( iCol<0 ){ @@ -775,7 +777,7 @@ static void generateColumnNames(          char *zName = 0;          char *zTab; -        zTab = pTabList->a[p->iTable - base].zAlias; +        zTab = pTabList->a[j].zAlias;          if( showFullNames || zTab==0 ) zTab = pTab->zName;          sqliteSetString(&zName, zTab, ".", zCol, 0);          sqliteVdbeAddOp(v, OP_ColumnName, i, 0); @@ -863,7 +865,12 @@ Table *sqliteResultSetOfSelect(Parse *pParse, char *zTabName, Select *pSelect){  ** For the given SELECT statement, do three things.  **  **    (1)  Fill in the pTabList->a[].pTab fields in the SrcList that  -**         defines the set of tables that should be scanned.  +**         defines the set of tables that should be scanned.  For views, +**         fill pTabList->a[].pSelect with a copy of the SELECT statement +**         that implements the view.  A copy is made of the view's SELECT +**         statement so that we can freely modify or delete that statement +**         without worrying about messing up the presistent representation +**         of the view.  **  **    (2)  Add terms to the WHERE clause to accomodate the NATURAL keyword  **         on joins and the ON and USING clause of joins. @@ -908,23 +915,31 @@ static int fillInColumnList(Parse *pParse, Select *p){        if( pTab==0 ){          return 1;        } +      /* The isTransient flag indicates that the Table structure has been +      ** dynamically allocated and may be freed at any time.  In other words, +      ** pTab is not pointing to a persistent table structure that defines +      ** part of the schema. */        pTab->isTransient = 1;      }else{        /* An ordinary table or view name in the FROM clause */        pTabList->a[i].pTab = pTab =  -        sqliteFindTable(pParse->db, pTabList->a[i].zName); +        sqliteLocateTable(pParse,pTabList->a[i].zName,pTabList->a[i].zDatabase);        if( pTab==0 ){ -        sqliteSetString(&pParse->zErrMsg, "no such table: ",  -           pTabList->a[i].zName, 0); -        pParse->nErr++;          return 1;        }        if( pTab->pSelect ){ +        /* We reach here if the named table is a really a view */          if( sqliteViewGetColumnNames(pParse, pTab) ){            return 1;          } -        sqliteSelectDelete(pTabList->a[i].pSelect); -        pTabList->a[i].pSelect = sqliteSelectDup(pTab->pSelect); +        /* If pTabList->a[i].pSelect!=0 it means we are dealing with a +        ** view within a view.  The SELECT structure has already been +        ** copied by the outer view so we can skip the copy step here +        ** in the inner view. +        */ +        if( pTabList->a[i].pSelect==0 ){ +          pTabList->a[i].pSelect = sqliteSelectDup(pTab->pSelect); +        }        }      }    } @@ -1032,10 +1047,9 @@ static int fillInColumnList(Parse *pParse, Select *p){          }          if( !tableSeen ){            if( pName ){ -            sqliteSetNString(&pParse->zErrMsg, "no such table: ", -1,  -              pName->z, pName->n, 0); +            sqliteErrorMsg(pParse, "no such table: %T", pName);            }else{ -            sqliteSetString(&pParse->zErrMsg, "no tables specified", 0); +            sqliteErrorMsg(pParse, "no tables specified");            }            rc = 1;          } @@ -1056,6 +1070,9 @@ static int fillInColumnList(Parse *pParse, Select *p){  ** This routine is called on the Select structure that defines a  ** VIEW in order to undo any bindings to tables.  This is necessary  ** because those tables might be DROPed by a subsequent SQL command. +** If the bindings are not removed, then the Select.pSrc->a[].pTab field +** will be left pointing to a deallocated Table structure after the +** DROP and a coredump will occur the next time the VIEW is used.  */  void sqliteSelectUnbind(Select *p){    int i; @@ -1066,10 +1083,6 @@ void sqliteSelectUnbind(Select *p){      if( (pTab = pSrc->a[i].pTab)!=0 ){        if( pTab->isTransient ){          sqliteDeleteTable(0, pTab); -#if 0 -        sqliteSelectDelete(pSrc->a[i].pSelect); -        pSrc->a[i].pSelect = 0; -#endif        }        pSrc->a[i].pTab = 0;        if( pSrc->a[i].pSelect ){ @@ -1129,11 +1142,9 @@ static int matchOrderbyToColumn(      if( pOrderBy->a[i].done ) continue;      if( sqliteExprIsInteger(pE, &iCol) ){        if( iCol<=0 || iCol>pEList->nExpr ){ -        char zBuf[200]; -        sprintf(zBuf,"ORDER BY position %d should be between 1 and %d", -           iCol, pEList->nExpr); -        sqliteSetString(&pParse->zErrMsg, zBuf, 0); -        pParse->nErr++; +        sqliteErrorMsg(pParse, +          "ORDER BY position %d should be between 1 and %d", +          iCol, pEList->nExpr);          nErr++;          break;        } @@ -1163,11 +1174,8 @@ static int matchOrderbyToColumn(        pOrderBy->a[i].done = 1;      }      if( iCol<0 && mustComplete ){ -      char zBuf[30]; -      sprintf(zBuf,"%d",i+1); -      sqliteSetString(&pParse->zErrMsg, "ORDER BY term number ", zBuf,  -        " does not match any result column", 0); -      pParse->nErr++; +      sqliteErrorMsg(pParse, +        "ORDER BY term number %d does not match any result column", i+1);        nErr++;        break;      } @@ -1277,9 +1285,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){    if( p==0 || p->pPrior==0 ) return 1;    pPrior = p->pPrior;    if( pPrior->pOrderBy ){ -    sqliteSetString(&pParse->zErrMsg,"ORDER BY clause should come after ", -      selectOpName(p->op), " not before", 0); -    pParse->nErr++; +    sqliteErrorMsg(pParse,"ORDER BY clause should come after %s not before", +      selectOpName(p->op));      return 1;    } @@ -1367,8 +1374,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){          int iCont, iBreak, iStart;          assert( p->pEList );          if( eDest==SRT_Callback ){ -          generateColumnNames(pParse, p->base, 0, p->pEList); -          generateColumnTypes(pParse, p->base, p->pSrc, p->pEList); +          generateColumnNames(pParse, 0, p->pEList); +          generateColumnTypes(pParse, p->pSrc, p->pEList);          }          iBreak = sqliteVdbeMakeLabel(v);          iCont = sqliteVdbeMakeLabel(v); @@ -1424,8 +1431,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){        */        assert( p->pEList );        if( eDest==SRT_Callback ){ -        generateColumnNames(pParse, p->base, 0, p->pEList); -        generateColumnTypes(pParse, p->base, p->pSrc, p->pEList); +        generateColumnNames(pParse, 0, p->pEList); +        generateColumnTypes(pParse, p->pSrc, p->pEList);        }        iBreak = sqliteVdbeMakeLabel(v);        iCont = sqliteVdbeMakeLabel(v); @@ -1450,9 +1457,8 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){    }    assert( p->pEList && pPrior->pEList );    if( p->pEList->nExpr!=pPrior->pEList->nExpr ){ -    sqliteSetString(&pParse->zErrMsg, "SELECTs to the left and right of ", -      selectOpName(p->op), " do not have the same number of result columns", 0); -    pParse->nErr++; +    sqliteErrorMsg(pParse, "SELECTs to the left and right of %s" +      " do not have the same number of result columns", selectOpName(p->op));      return 1;    } @@ -1467,36 +1473,10 @@ static int multiSelect(Parse *pParse, Select *p, int eDest, int iParm){  }  /* -** Recursively scan through an expression tree.  For every reference -** to a column in table number iFrom, change that reference to the -** same column in table number iTo. -*/ -static void changeTablesInList(ExprList*, int, int);  /* Forward Declaration */ -static void changeTables(Expr *pExpr, int iFrom, int iTo){ -  if( pExpr==0 ) return; -  if( pExpr->op==TK_COLUMN && pExpr->iTable==iFrom ){ -    pExpr->iTable = iTo; -  }else{ -    changeTables(pExpr->pLeft, iFrom, iTo); -    changeTables(pExpr->pRight, iFrom, iTo); -    changeTablesInList(pExpr->pList, iFrom, iTo); -  } -} -static void changeTablesInList(ExprList *pList, int iFrom, int iTo){ -  if( pList ){ -    int i; -    for(i=0; i<pList->nExpr; i++){ -      changeTables(pList->a[i].pExpr, iFrom, iTo); -    } -  } -} - -/*  ** Scan through the expression pExpr.  Replace every reference to -** a column in table number iTable with a copy of the corresponding +** a column in table number iTable with a copy of the iColumn-th  ** entry in pEList.  (But leave references to the ROWID column  -** unchanged.)  When making a copy of an expression in pEList, change -** references to columns in table iSub into references to table iTable. +** unchanged.)  **  ** This routine is part of the flattening procedure.  A subquery  ** whose result set is defined by pEList appears as entry in the @@ -1505,8 +1485,8 @@ static void changeTablesInList(ExprList *pList, int iFrom, int iTo){  ** changes to pExpr so that it refers directly to the source table  ** of the subquery rather the result set of the subquery.  */ -static void substExprList(ExprList*,int,ExprList*,int);  /* Forward Decl */ -static void substExpr(Expr *pExpr, int iTable, ExprList *pEList, int iSub){ +static void substExprList(ExprList*,int,ExprList*);  /* Forward Decl */ +static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){    if( pExpr==0 ) return;    if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable && pExpr->iColumn>=0 ){      Expr *pNew; @@ -1527,21 +1507,18 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList, int iSub){      pExpr->iAgg = pNew->iAgg;      sqliteTokenCopy(&pExpr->token, &pNew->token);      sqliteTokenCopy(&pExpr->span, &pNew->span); -    if( iSub!=iTable ){ -      changeTables(pExpr, iSub, iTable); -    }    }else{ -    substExpr(pExpr->pLeft, iTable, pEList, iSub); -    substExpr(pExpr->pRight, iTable, pEList, iSub); -    substExprList(pExpr->pList, iTable, pEList, iSub); +    substExpr(pExpr->pLeft, iTable, pEList); +    substExpr(pExpr->pRight, iTable, pEList); +    substExprList(pExpr->pList, iTable, pEList);    }  }  static void  -substExprList(ExprList *pList, int iTable, ExprList *pEList, int iSub){ +substExprList(ExprList *pList, int iTable, ExprList *pEList){    int i;    if( pList==0 ) return;    for(i=0; i<pList->nExpr; i++){ -    substExpr(pList->a[i].pExpr, iTable, pEList, iSub); +    substExpr(pList->a[i].pExpr, iTable, pEList);    }  } @@ -1578,7 +1555,8 @@ substExprList(ExprList *pList, int iTable, ExprList *pEList, int iSub){  **  **   (2)  The subquery is not an aggregate or the outer query is not a join.  ** -**   (3)  The subquery is not a join. +**   (3)  The subquery is not the right operand of a left outer join, or +**        the subquery is not itself a join.  (Ticket #306)  **  **   (4)  The subquery is not DISTINCT or the outer query is not a join.  ** @@ -1604,7 +1582,7 @@ substExprList(ExprList *pList, int iTable, ExprList *pEList, int iSub){  ** The subquery is p->pSrc->a[iFrom].  isAgg is true if the outer query  ** uses aggregates and subqueryIsAgg is true if the subquery uses aggregates.  ** -** If flattening is not attempted, this routine is a no-op and return 0. +** If flattening is not attempted, this routine is a no-op and returns 0.  ** If flattening is attempted this routine returns 1.  **  ** All of the expression analysis must occur on both the outer query and @@ -1621,8 +1599,8 @@ static int flattenSubquery(    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 i; -  int iParent, iSub;    Expr *pWhere;    /* Check to see if flattening is permitted.  Return 0 if not. @@ -1636,19 +1614,81 @@ static int flattenSubquery(    if( subqueryIsAgg && pSrc->nSrc>1 ) return 0;    pSubSrc = pSub->pSrc;    assert( pSubSrc ); -  if( pSubSrc->nSrc!=1 ) return 0; +  if( pSubSrc->nSrc==0 ) return 0;    if( (pSub->isDistinct || pSub->nLimit>=0) &&  (pSrc->nSrc>1 || isAgg) ){       return 0;    }    if( (p->isDistinct || p->nLimit>=0) && subqueryIsAgg ) return 0;    if( p->pOrderBy && pSub->pOrderBy ) return 0; +  /* Restriction 3:  If the subquery is a join, make sure the subquery is  +  ** not used as the right operand of an outer join.  Examples of why this +  ** is not allowed: +  ** +  **         t1 LEFT OUTER JOIN (t2 JOIN t3) +  ** +  ** If we flatten the above, we would get +  ** +  **         (t1 LEFT OUTER JOIN t2) JOIN t3 +  ** +  ** which is not at all the same thing. +  */ +  if( pSubSrc->nSrc>1 && iFrom>0 && (pSrc->a[iFrom-1].jointype & JT_OUTER)!=0 ){ +    return 0; +  } +    /* If we reach this point, it means flattening is permitted for the -  ** i-th entry of the FROM clause in the outer query. +  ** iFrom-th entry of the FROM clause in the outer query. +  */ + +  /* Move all of the FROM elements of the subquery into the +  ** the FROM clause of the outer query.  Before doing this, remember +  ** the cursor number for the original outer query FROM element in +  ** iParent.  The iParent cursor will never be used.  Subsequent code +  ** will scan expressions looking for iParent references and replace +  ** those references with expressions that resolve to the subquery FROM +  ** elements we are now copying in. +  */ +  iParent = pSrc->a[iFrom].iCursor; +  { +    int nSubSrc = pSubSrc->nSrc; +    int jointype = pSrc->a[iFrom].jointype; + +    if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){ +      sqliteDeleteTable(0, pSrc->a[iFrom].pTab); +    } +    sqliteFree(pSrc->a[iFrom].zName); +    sqliteFree(pSrc->a[iFrom].zAlias); +    if( nSubSrc>1 ){ +      int extra = nSubSrc - 1; +      for(i=1; i<nSubSrc; i++){ +        pSrc = sqliteSrcListAppend(pSrc, 0, 0); +      } +      p->pSrc = pSrc; +      for(i=pSrc->nSrc-1; i-extra>=iFrom; i--){ +        pSrc->a[i] = pSrc->a[i-extra]; +      } +    } +    for(i=0; i<nSubSrc; i++){ +      pSrc->a[i+iFrom] = pSubSrc->a[i]; +      memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i])); +    } +    pSrc->a[iFrom+nSubSrc-1].jointype = jointype; +  } + +  /* Now begin substituting subquery result set expressions for  +  ** references to the iParent in the outer query. +  **  +  ** Example: +  ** +  **   SELECT a+5, b*10 FROM (SELECT x*3 AS a, y+10 AS b FROM t1) WHERE a>b; +  **   \                     \_____________ subquery __________/          / +  **    \_____________________ 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".    */ -  iParent = p->base + iFrom; -  iSub = pSub->base; -  substExprList(p->pEList, iParent, pSub->pEList, iSub); +  substExprList(p->pEList, iParent, pSub->pEList);    pList = p->pEList;    for(i=0; i<pList->nExpr; i++){      Expr *pExpr; @@ -1657,22 +1697,18 @@ static int flattenSubquery(      }    }    if( isAgg ){ -    substExprList(p->pGroupBy, iParent, pSub->pEList, iSub); -    substExpr(p->pHaving, iParent, pSub->pEList, iSub); +    substExprList(p->pGroupBy, iParent, pSub->pEList); +    substExpr(p->pHaving, iParent, pSub->pEList);    }    if( pSub->pOrderBy ){      assert( p->pOrderBy==0 );      p->pOrderBy = pSub->pOrderBy;      pSub->pOrderBy = 0; -    changeTablesInList(p->pOrderBy, iSub, iParent);    }else if( p->pOrderBy ){ -    substExprList(p->pOrderBy, iParent, pSub->pEList, iSub); +    substExprList(p->pOrderBy, iParent, pSub->pEList);    }    if( pSub->pWhere ){      pWhere = sqliteExprDup(pSub->pWhere); -    if( iParent!=iSub ){ -      changeTables(pWhere, iSub, iParent); -    }    }else{      pWhere = 0;    } @@ -1680,12 +1716,9 @@ static int flattenSubquery(      assert( p->pHaving==0 );      p->pHaving = p->pWhere;      p->pWhere = pWhere; -    substExpr(p->pHaving, iParent, pSub->pEList, iSub); +    substExpr(p->pHaving, iParent, pSub->pEList);      if( pSub->pHaving ){        Expr *pHaving = sqliteExprDup(pSub->pHaving); -      if( iParent!=iSub ){ -        changeTables(pHaving, iSub, iParent); -      }        if( p->pHaving ){          p->pHaving = sqliteExpr(TK_AND, p->pHaving, pHaving, 0);        }else{ @@ -1694,19 +1727,23 @@ static int flattenSubquery(      }      assert( p->pGroupBy==0 );      p->pGroupBy = sqliteExprListDup(pSub->pGroupBy); -    if( iParent!=iSub ){ -      changeTablesInList(p->pGroupBy, iSub, iParent); -    }    }else if( p->pWhere==0 ){      p->pWhere = pWhere;    }else{ -    substExpr(p->pWhere, iParent, pSub->pEList, iSub); +    substExpr(p->pWhere, iParent, pSub->pEList);      if( pWhere ){        p->pWhere = sqliteExpr(TK_AND, p->pWhere, pWhere, 0);      }    } + +  /* The flattened query is distinct if either the inner or the +  ** outer query is distinct.  +  */    p->isDistinct = p->isDistinct || pSub->isDistinct; +  /* Transfer the limit expression from the subquery to the outer +  ** query. +  */    if( pSub->nLimit>=0 ){      if( p->nLimit<0 ){        p->nLimit = pSub->nLimit; @@ -1716,27 +1753,9 @@ static int flattenSubquery(    }    p->nOffset += pSub->nOffset; -  /* If the subquery contains subqueries of its own, that were not -  ** flattened, then code will have already been generated to put -  ** the results of those sub-subqueries into VDBE cursors relative -  ** to the subquery.  We must translate the cursor number into values -  ** suitable for use by the outer query. +  /* Finially, delete what is left of the subquery and return +  ** success.    */ -  for(i=0; i<pSubSrc->nSrc; i++){ -    Vdbe *v; -    if( pSubSrc->a[i].pSelect==0 ) continue; -    v = sqliteGetVdbe(pParse); -    sqliteVdbeAddOp(v, OP_RenameCursor, pSub->base+i, p->base+i); -  } - -  if( pSrc->a[iFrom].pTab && pSrc->a[iFrom].pTab->isTransient ){ -    sqliteDeleteTable(0, pSrc->a[iFrom].pTab); -  } -  pSrc->a[iFrom].pTab = pSubSrc->a[0].pTab; -  pSubSrc->a[0].pTab = 0; -  assert( pSrc->a[iFrom].pSelect==pSub ); -  pSrc->a[iFrom].pSelect = pSubSrc->a[0].pSelect; -  pSubSrc->a[0].pSelect = 0;    sqliteSelectDelete(pSub);    return 1;  } @@ -1768,7 +1787,6 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){    Index *pIdx;    int base;    Vdbe *v; -  int openOp;    int seekOp;    int cont;    ExprList eList; @@ -1818,8 +1836,8 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){    v = sqliteGetVdbe(pParse);    if( v==0 ) return 0;    if( eDest==SRT_Callback ){ -    generateColumnNames(pParse, p->base, p->pSrc, p->pEList); -    generateColumnTypes(pParse, p->base, p->pSrc, p->pEList); +    generateColumnNames(pParse, p->pSrc, p->pEList); +    generateColumnTypes(pParse, p->pSrc, p->pEList);    }    /* Generating code to find the min or the max.  Basically all we have @@ -1827,18 +1845,17 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){    ** the min() or max() is on the INTEGER PRIMARY KEY, then find the first    ** or last entry in the main table.    */ -  if( !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){ -    sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0); -    pParse->schemaVerified = 1; -  } -  openOp = pTab->isTemp ? OP_OpenAux : OP_Open; -  base = p->base; -  sqliteVdbeAddOp(v, openOp, base, pTab->tnum); +  sqliteCodeVerifySchema(pParse, pTab->iDb); +  base = p->pSrc->a[0].iCursor; +  sqliteVdbeAddOp(v, OP_Integer, pTab->iDb, 0); +  sqliteVdbeAddOp(v, OP_OpenRead, base, pTab->tnum);    sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); +  cont = sqliteVdbeMakeLabel(v);    if( pIdx==0 ){      sqliteVdbeAddOp(v, seekOp, base, 0);    }else{ -    sqliteVdbeAddOp(v, openOp, base+1, pIdx->tnum); +    sqliteVdbeAddOp(v, OP_Integer, pIdx->iDb, 0); +    sqliteVdbeAddOp(v, OP_OpenRead, base+1, pIdx->tnum);      sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC);      sqliteVdbeAddOp(v, seekOp, base+1, 0);      sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0); @@ -1849,7 +1866,6 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){    memset(&eListItem, 0, sizeof(eListItem));    eList.a = &eListItem;    eList.a[0].pExpr = pExpr; -  cont = sqliteVdbeMakeLabel(v);    selectInnerLoop(pParse, p, &eList, 0, 0, 0, -1, eDest, iParm, cont, cont);    sqliteVdbeResolveLabel(v, cont);    sqliteVdbeAddOp(v, OP_Close, base, 0); @@ -1929,11 +1945,10 @@ int sqliteSelect(    Expr *pHaving;         /* The HAVING clause.  May be NULL */    int isDistinct;        /* True if the DISTINCT keyword is present */    int distinct;          /* Table to use for the distinct set */ -  int base;              /* First cursor available for use */    int rc = 1;            /* Value to return from this function */    if( sqlite_malloc_failed || pParse->nErr || p==0 ) return 1; -  if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0) ) return 1; +  if( sqliteAuthCheck(pParse, SQLITE_SELECT, 0, 0, 0) ) return 1;    /* If there is are a sequence of queries, do the earlier ones first.    */ @@ -1950,12 +1965,9 @@ int sqliteSelect(    pHaving = p->pHaving;    isDistinct = p->isDistinct; -  /* Allocate a block of VDBE cursors, one for each table in the FROM clause. -  ** The WHERE processing requires that the cursors for the tables in the -  ** FROM clause be consecutive. +  /* Allocate VDBE cursors for each table in the FROM clause    */ -  base = p->base = pParse->nTab; -  pParse->nTab += pTabList->nSrc; +  sqliteSrcListAssignCursors(pParse, pTabList);    /*     ** Do not even attempt to generate any code if we have already seen @@ -1978,9 +1990,8 @@ int sqliteSelect(    ** only a single column may be output.    */    if( (eDest==SRT_Mem || eDest==SRT_Set) && pEList->nExpr>1 ){ -    sqliteSetString(&pParse->zErrMsg, "only a single result allowed for " -       "a SELECT that is part of an expression", 0); -    pParse->nErr++; +    sqliteErrorMsg(pParse, "only a single result allowed for " +       "a SELECT that is part of an expression");      goto select_end;    } @@ -2002,7 +2013,7 @@ int sqliteSelect(    ** Resolve the column names and do a semantics check on all the expressions.    */    for(i=0; i<pEList->nExpr; i++){ -    if( sqliteExprResolveIds(pParse, base, pTabList, 0, pEList->a[i].pExpr) ){ +    if( sqliteExprResolveIds(pParse, pTabList, 0, pEList->a[i].pExpr) ){        goto select_end;      }      if( sqliteExprCheck(pParse, pEList->a[i].pExpr, 1, &isAgg) ){ @@ -2010,22 +2021,20 @@ int sqliteSelect(      }    }    if( pWhere ){ -    if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pWhere) ){ +    if( sqliteExprResolveIds(pParse, pTabList, pEList, pWhere) ){        goto select_end;      }      if( sqliteExprCheck(pParse, pWhere, 0, 0) ){        goto select_end;      } -    sqliteOracle8JoinFixup(base, pTabList, pWhere); +    sqliteOracle8JoinFixup(pTabList, pWhere);    }    if( pHaving ){      if( pGroupBy==0 ){ -      sqliteSetString(&pParse->zErrMsg, "a GROUP BY clause is required " -         "before HAVING", 0); -      pParse->nErr++; +      sqliteErrorMsg(pParse, "a GROUP BY clause is required before HAVING");        goto select_end;      } -    if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pHaving) ){ +    if( sqliteExprResolveIds(pParse, pTabList, pEList, pHaving) ){        goto select_end;      }      if( sqliteExprCheck(pParse, pHaving, 1, &isAgg) ){ @@ -2040,7 +2049,7 @@ int sqliteSelect(          sqliteExprDelete(pE);          pE = pOrderBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr);        } -      if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pE) ){ +      if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){          goto select_end;        }        if( sqliteExprCheck(pParse, pE, isAgg, 0) ){ @@ -2048,16 +2057,13 @@ int sqliteSelect(        }        if( sqliteExprIsConstant(pE) ){          if( sqliteExprIsInteger(pE, &iCol)==0 ){ -          sqliteSetString(&pParse->zErrMsg,  -               "ORDER BY terms must not be non-integer constants", 0); -          pParse->nErr++; +          sqliteErrorMsg(pParse, +             "ORDER BY terms must not be non-integer constants");            goto select_end;          }else if( iCol<=0 || iCol>pEList->nExpr ){ -          char zBuf[2000]; -          sprintf(zBuf,"ORDER BY column number %d out of range - should be " +          sqliteErrorMsg(pParse,  +             "ORDER BY column number %d out of range - should be "               "between 1 and %d", iCol, pEList->nExpr); -          sqliteSetString(&pParse->zErrMsg, zBuf, 0); -          pParse->nErr++;            goto select_end;          }        } @@ -2071,7 +2077,7 @@ int sqliteSelect(          sqliteExprDelete(pE);          pE = pGroupBy->a[i].pExpr = sqliteExprDup(pEList->a[iCol-1].pExpr);        } -      if( sqliteExprResolveIds(pParse, base, pTabList, pEList, pE) ){ +      if( sqliteExprResolveIds(pParse, pTabList, pEList, pE) ){          goto select_end;        }        if( sqliteExprCheck(pParse, pE, isAgg, 0) ){ @@ -2079,16 +2085,13 @@ int sqliteSelect(        }        if( sqliteExprIsConstant(pE) ){          if( sqliteExprIsInteger(pE, &iCol)==0 ){ -          sqliteSetString(&pParse->zErrMsg,  -               "GROUP BY terms must not be non-integer constants", 0); -          pParse->nErr++; +          sqliteErrorMsg(pParse, +            "GROUP BY terms must not be non-integer constants");            goto select_end;          }else if( iCol<=0 || iCol>pEList->nExpr ){ -          char zBuf[2000]; -          sprintf(zBuf,"GROUP BY column number %d out of range - should be " +          sqliteErrorMsg(pParse, +             "GROUP BY column number %d out of range - should be "               "between 1 and %d", iCol, pEList->nExpr); -          sqliteSetString(&pParse->zErrMsg, zBuf, 0); -          pParse->nErr++;            goto select_end;          }        } @@ -2112,7 +2115,7 @@ int sqliteSelect(    ** step is skipped if the output is going to some other destination.    */    if( eDest==SRT_Callback ){ -    generateColumnNames(pParse, p->base, pTabList, pEList); +    generateColumnNames(pParse, pTabList, pEList);    }    /* Set the limiter @@ -2138,12 +2141,25 @@ int sqliteSelect(    /* Generate code for all sub-queries in the FROM clause    */    for(i=0; i<pTabList->nSrc; i++){ +    const char *zSavedAuthContext; +    int needRestoreContext; +      if( pTabList->a[i].pSelect==0 ) continue; -    sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable, base+i, -                 p, i, &isAgg); +    if( pTabList->a[i].zName!=0 ){ +      zSavedAuthContext = pParse->zAuthContext; +      pParse->zAuthContext = pTabList->a[i].zName; +      needRestoreContext = 1; +    }else{ +      needRestoreContext = 0; +    } +    sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_TempTable,  +                 pTabList->a[i].iCursor, p, i, &isAgg); +    if( needRestoreContext ){ +      pParse->zAuthContext = zSavedAuthContext; +    }      pTabList = p->pSrc;      pWhere = p->pWhere; -    if( eDest==SRT_Callback ){ +    if( eDest!=SRT_Union && eDest!=SRT_Except && eDest!=SRT_Discard ){        pOrderBy = p->pOrderBy;      }      pGroupBy = p->pGroupBy; @@ -2165,7 +2181,7 @@ int sqliteSelect(    ** than a callback.    */    if( eDest==SRT_Callback ){ -    generateColumnTypes(pParse, p->base, pTabList, pEList); +    generateColumnTypes(pParse, pTabList, pEList);    }    /* If the output is destined for a temporary table, open that table. @@ -2239,7 +2255,7 @@ int sqliteSelect(    /* Begin the database scan    */ -  pWInfo = sqliteWhereBegin(pParse, p->base, pTabList, pWhere, 0,  +  pWInfo = sqliteWhereBegin(pParse, pTabList, pWhere, 0,                               pGroupBy ? 0 : &pOrderBy);    if( pWInfo==0 ) goto select_end;  | 
