/ Check-in [e651074b]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Simplify the interface to the subst() routines that are part of the query flattener by collecting common parameters into the SubstContext object and passing around a pointer to that object.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e651074be28b2077b8a298f513e2e699ceca99164ace9869ea50873c0637fd2e
User & Date: drh 2017-04-14 12:39:37
Context
2017-04-14
14:02
Enhance the sqlite3TreeView() display for Expr objects so that it shows the iRightJoinTable value for Expr nodes that have the EP_FromJoin property. check-in: 5159cb8f user: drh tags: trunk
12:39
Simplify the interface to the subst() routines that are part of the query flattener by collecting common parameters into the SubstContext object and passing around a pointer to that object. check-in: e651074b user: drh tags: trunk
12:27
Remove an incorrect ALWAYS(). check-in: f956f6ae user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/select.c.

  3140   3140     **** subqueries ****/
  3141   3141     explainComposite(pParse, p->op, iSub1, iSub2, 0);
  3142   3142     return pParse->nErr!=0;
  3143   3143   }
  3144   3144   #endif
  3145   3145   
  3146   3146   #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
         3147  +
         3148  +/* An instance of the SubstContext object describes an substitution edit
         3149  +** to be performed on a parse tree.
         3150  +**
         3151  +** All references to columns in table iTable are to be replaced by corresponding
         3152  +** expressions in pEList.
         3153  +*/
         3154  +typedef struct SubstContext {
         3155  +  Parse *pParse;            /* The parsing context */
         3156  +  int iTable;               /* Replace references to this table */
         3157  +  ExprList *pEList;         /* Replacement expressions */
         3158  +} SubstContext;
         3159  +
  3147   3160   /* Forward Declarations */
  3148         -static void substExprList(Parse*, ExprList*, int, ExprList*);
  3149         -static void substSelect(Parse*, Select *, int, ExprList*, int);
         3161  +static void substExprList(SubstContext*, ExprList*);
         3162  +static void substSelect(SubstContext*, Select*, int);
  3150   3163   
  3151   3164   /*
  3152   3165   ** Scan through the expression pExpr.  Replace every reference to
  3153   3166   ** a column in table number iTable with a copy of the iColumn-th
  3154   3167   ** entry in pEList.  (But leave references to the ROWID column 
  3155   3168   ** unchanged.)
  3156   3169   **
................................................................................
  3158   3171   ** whose result set is defined by pEList appears as entry in the
  3159   3172   ** FROM clause of a SELECT such that the VDBE cursor assigned to that
  3160   3173   ** FORM clause entry is iTable.  This routine makes the necessary 
  3161   3174   ** changes to pExpr so that it refers directly to the source table
  3162   3175   ** of the subquery rather the result set of the subquery.
  3163   3176   */
  3164   3177   static Expr *substExpr(
  3165         -  Parse *pParse,      /* Report errors here */
  3166         -  Expr *pExpr,        /* Expr in which substitution occurs */
  3167         -  int iTable,         /* Table to be substituted */
  3168         -  ExprList *pEList    /* Substitute expressions */
         3178  +  SubstContext *pSubst,  /* Description of the substitution */
         3179  +  Expr *pExpr            /* Expr in which substitution occurs */
  3169   3180   ){
  3170         -  sqlite3 *db = pParse->db;
  3171   3181     if( pExpr==0 ) return 0;
  3172         -  if( pExpr->op==TK_COLUMN && pExpr->iTable==iTable ){
         3182  +  if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
  3173   3183       if( pExpr->iColumn<0 ){
  3174   3184         pExpr->op = TK_NULL;
  3175   3185       }else{
  3176   3186         Expr *pNew;
  3177         -      Expr *pCopy = pEList->a[pExpr->iColumn].pExpr;
  3178         -      assert( pEList!=0 && pExpr->iColumn<pEList->nExpr );
         3187  +      Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
         3188  +      assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
  3179   3189         assert( pExpr->pLeft==0 && pExpr->pRight==0 );
  3180   3190         if( sqlite3ExprIsVector(pCopy) ){
  3181         -        sqlite3VectorErrorMsg(pParse, pCopy);
         3191  +        sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
  3182   3192         }else{
         3193  +        sqlite3 *db = pSubst->pParse->db;
  3183   3194           pNew = sqlite3ExprDup(db, pCopy, 0);
  3184   3195           if( pNew && (pExpr->flags & EP_FromJoin) ){
  3185   3196             pNew->iRightJoinTable = pExpr->iRightJoinTable;
  3186   3197             pNew->flags |= EP_FromJoin;
  3187   3198           }
  3188   3199           sqlite3ExprDelete(db, pExpr);
  3189   3200           pExpr = pNew;
  3190   3201         }
  3191   3202       }
  3192   3203     }else{
  3193         -    pExpr->pLeft = substExpr(pParse, pExpr->pLeft, iTable, pEList);
  3194         -    pExpr->pRight = substExpr(pParse, pExpr->pRight, iTable, pEList);
         3204  +    pExpr->pLeft = substExpr(pSubst, pExpr->pLeft);
         3205  +    pExpr->pRight = substExpr(pSubst, pExpr->pRight);
  3195   3206       if( ExprHasProperty(pExpr, EP_xIsSelect) ){
  3196         -      substSelect(pParse, pExpr->x.pSelect, iTable, pEList, 1);
         3207  +      substSelect(pSubst, pExpr->x.pSelect, 1);
  3197   3208       }else{
  3198         -      substExprList(pParse, pExpr->x.pList, iTable, pEList);
         3209  +      substExprList(pSubst, pExpr->x.pList);
  3199   3210       }
  3200   3211     }
  3201   3212     return pExpr;
  3202   3213   }
  3203   3214   static void substExprList(
  3204         -  Parse *pParse,       /* Report errors here */
  3205         -  ExprList *pList,     /* List to scan and in which to make substitutes */
  3206         -  int iTable,          /* Table to be substituted */
  3207         -  ExprList *pEList     /* Substitute values */
         3215  +  SubstContext *pSubst, /* Description of the substitution */
         3216  +  ExprList *pList       /* List to scan and in which to make substitutes */
  3208   3217   ){
  3209   3218     int i;
  3210   3219     if( pList==0 ) return;
  3211   3220     for(i=0; i<pList->nExpr; i++){
  3212         -    pList->a[i].pExpr = substExpr(pParse, pList->a[i].pExpr, iTable, pEList);
         3221  +    pList->a[i].pExpr = substExpr(pSubst, pList->a[i].pExpr);
  3213   3222     }
  3214   3223   }
  3215   3224   static void substSelect(
  3216         -  Parse *pParse,       /* Report errors here */
  3217         -  Select *p,           /* SELECT statement in which to make substitutions */
  3218         -  int iTable,          /* Table to be replaced */
  3219         -  ExprList *pEList,    /* Substitute values */
  3220         -  int doPrior          /* Do substitutes on p->pPrior too */
         3225  +  SubstContext *pSubst, /* Description of the substitution */
         3226  +  Select *p,            /* SELECT statement in which to make substitutions */
         3227  +  int doPrior           /* Do substitutes on p->pPrior too */
  3221   3228   ){
  3222   3229     SrcList *pSrc;
  3223   3230     struct SrcList_item *pItem;
  3224   3231     int i;
  3225   3232     if( !p ) return;
  3226   3233     do{
  3227         -    substExprList(pParse, p->pEList, iTable, pEList);
  3228         -    substExprList(pParse, p->pGroupBy, iTable, pEList);
  3229         -    substExprList(pParse, p->pOrderBy, iTable, pEList);
  3230         -    p->pHaving = substExpr(pParse, p->pHaving, iTable, pEList);
  3231         -    p->pWhere = substExpr(pParse, p->pWhere, iTable, pEList);
         3234  +    substExprList(pSubst, p->pEList);
         3235  +    substExprList(pSubst, p->pGroupBy);
         3236  +    substExprList(pSubst, p->pOrderBy);
         3237  +    p->pHaving = substExpr(pSubst, p->pHaving);
         3238  +    p->pWhere = substExpr(pSubst, p->pWhere);
  3232   3239       pSrc = p->pSrc;
  3233   3240       assert( pSrc!=0 );
  3234   3241       for(i=pSrc->nSrc, pItem=pSrc->a; i>0; i--, pItem++){
  3235         -      substSelect(pParse, pItem->pSelect, iTable, pEList, 1);
         3242  +      substSelect(pSubst, pItem->pSelect, 1);
  3236   3243         if( pItem->fg.isTabFunc ){
  3237         -        substExprList(pParse, pItem->u1.pFuncArg, iTable, pEList);
         3244  +        substExprList(pSubst, pItem->u1.pFuncArg);
  3238   3245         }
  3239   3246       }
  3240   3247     }while( doPrior && (p = p->pPrior)!=0 );
  3241   3248   }
  3242   3249   #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */
  3243   3250   
  3244   3251   #if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
................................................................................
  3756   3763         );
  3757   3764         assert( pParent->pGroupBy==0 );
  3758   3765         pParent->pGroupBy = sqlite3ExprListDup(db, pSub->pGroupBy, 0);
  3759   3766       }else{
  3760   3767         pParent->pWhere = sqlite3ExprAnd(db, pWhere, pParent->pWhere);
  3761   3768       }
  3762   3769       if( db->mallocFailed==0 ){
  3763         -      substSelect(pParse, pParent, iParent, pSub->pEList, 0);
         3770  +      SubstContext x;
         3771  +      x.pParse = pParse;
         3772  +      x.iTable = iParent;
         3773  +      x.pEList = pSub->pEList;
         3774  +      substSelect(&x, pParent, 0);
  3764   3775       }
  3765   3776     
  3766   3777       /* The flattened query is distinct if either the inner or the
  3767   3778       ** outer query is distinct. 
  3768   3779       */
  3769   3780       pParent->selFlags |= pSub->selFlags & SF_Distinct;
  3770   3781     
................................................................................
  3859   3870       nChng += pushDownWhereTerms(pParse, pSubq, pWhere->pRight, iCursor);
  3860   3871       pWhere = pWhere->pLeft;
  3861   3872     }
  3862   3873     if( ExprHasProperty(pWhere,EP_FromJoin) ) return 0; /* restriction 5 */
  3863   3874     if( sqlite3ExprIsTableConstant(pWhere, iCursor) ){
  3864   3875       nChng++;
  3865   3876       while( pSubq ){
         3877  +      SubstContext x;
  3866   3878         pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
  3867         -      pNew = substExpr(pParse, pNew, iCursor, pSubq->pEList);
         3879  +      x.pParse = pParse;
         3880  +      x.iTable = iCursor;
         3881  +      x.pEList = pSubq->pEList;
         3882  +      pNew = substExpr(&x, pNew);
  3868   3883         pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
  3869   3884         pSubq = pSubq->pPrior;
  3870   3885       }
  3871   3886     }
  3872   3887     return nChng;
  3873   3888   }
  3874   3889   #endif /* !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW) */