/ Check-in [6a5cceee]
Login

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

Overview
Comment:Factor out the common operation of setting the Expr.x.pSelect field of an Expr object into a subroutine.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6a5cceee486c5e3625556e4c7076ff90e9d8fa43
User & Date: drh 2016-04-11 01:06:47
Context
2016-04-11
01:26
Small size reduction and performance improvement in the parser. check-in: 16df7128 user: drh tags: trunk
01:06
Factor out the common operation of setting the Expr.x.pSelect field of an Expr object into a subroutine. check-in: 6a5cceee user: drh tags: trunk
2016-04-09
18:04
Fix a problem in the code generator for joins on virtual tables where the outer loop of the join uses the IN operator. check-in: 6c56b3a0 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/delete.c.

   139    139     SrcList *pSelectSrc = NULL;  /* SELECT rowid FROM x ... (dup of pSrc) */
   140    140     Select *pSelect = NULL;      /* Complete SELECT tree */
   141    141   
   142    142     /* Check that there isn't an ORDER BY without a LIMIT clause.
   143    143     */
   144    144     if( pOrderBy && (pLimit == 0) ) {
   145    145       sqlite3ErrorMsg(pParse, "ORDER BY without LIMIT on %s", zStmtType);
   146         -    goto limit_where_cleanup_2;
          146  +    goto limit_where_cleanup;
   147    147     }
   148    148   
   149    149     /* We only need to generate a select expression if there
   150    150     ** is a limit/offset term to enforce.
   151    151     */
   152    152     if( pLimit == 0 ) {
   153    153       /* if pLimit is null, pOffset will always be null as well. */
................................................................................
   161    161     ** becomes:
   162    162     **   DELETE FROM table_a WHERE rowid IN ( 
   163    163     **     SELECT rowid FROM table_a WHERE col1=1 ORDER BY col2 LIMIT 1 OFFSET 1
   164    164     **   );
   165    165     */
   166    166   
   167    167     pSelectRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
   168         -  if( pSelectRowid == 0 ) goto limit_where_cleanup_2;
          168  +  if( pSelectRowid == 0 ) goto limit_where_cleanup;
   169    169     pEList = sqlite3ExprListAppend(pParse, 0, pSelectRowid);
   170         -  if( pEList == 0 ) goto limit_where_cleanup_2;
          170  +  if( pEList == 0 ) goto limit_where_cleanup;
   171    171   
   172    172     /* duplicate the FROM clause as it is needed by both the DELETE/UPDATE tree
   173    173     ** and the SELECT subtree. */
   174    174     pSelectSrc = sqlite3SrcListDup(pParse->db, pSrc, 0);
   175    175     if( pSelectSrc == 0 ) {
   176    176       sqlite3ExprListDelete(pParse->db, pEList);
   177         -    goto limit_where_cleanup_2;
          177  +    goto limit_where_cleanup;
   178    178     }
   179    179   
   180    180     /* generate the SELECT expression tree. */
   181    181     pSelect = sqlite3SelectNew(pParse,pEList,pSelectSrc,pWhere,0,0,
   182    182                                pOrderBy,0,pLimit,pOffset);
   183    183     if( pSelect == 0 ) return 0;
   184    184   
   185    185     /* now generate the new WHERE rowid IN clause for the DELETE/UDPATE */
   186    186     pWhereRowid = sqlite3PExpr(pParse, TK_ROW, 0, 0, 0);
   187         -  if( pWhereRowid == 0 ) goto limit_where_cleanup_1;
   188         -  pInClause = sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0);
   189         -  if( pInClause == 0 ) goto limit_where_cleanup_1;
   190         -
   191         -  pInClause->x.pSelect = pSelect;
   192         -  pInClause->flags |= EP_xIsSelect;
   193         -  sqlite3ExprSetHeightAndFlags(pParse, pInClause);
          187  +  pInClause = pWhereRowid ? sqlite3PExpr(pParse, TK_IN, pWhereRowid, 0, 0) : 0;
          188  +  sqlite3PExprAddSelect(pParse, pInClause, pSelect);
   194    189     return pInClause;
   195    190   
   196         -  /* something went wrong. clean up anything allocated. */
   197         -limit_where_cleanup_1:
   198         -  sqlite3SelectDelete(pParse->db, pSelect);
   199         -  return 0;
   200         -
   201         -limit_where_cleanup_2:
          191  +limit_where_cleanup:
   202    192     sqlite3ExprDelete(pParse->db, pWhere);
   203    193     sqlite3ExprListDelete(pParse->db, pOrderBy);
   204    194     sqlite3ExprDelete(pParse->db, pLimit);
   205    195     sqlite3ExprDelete(pParse->db, pOffset);
   206    196     return 0;
   207    197   }
   208    198   #endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) */

Changes to src/expr.c.

   557    557       sqlite3ExprAttachSubtrees(pParse->db, p, pLeft, pRight);
   558    558     }
   559    559     if( p ) {
   560    560       sqlite3ExprCheckHeight(pParse, p->nHeight);
   561    561     }
   562    562     return p;
   563    563   }
          564  +
          565  +/*
          566  +** Add pSelect to the Expr.x.pSelect field.  Or, if pExpr is NULL (due
          567  +** do a memory allocation failure) then delete the pSelect object.
          568  +*/
          569  +void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
          570  +  if( pExpr ){
          571  +    pExpr->x.pSelect = pSelect;
          572  +    ExprSetProperty(pExpr, EP_xIsSelect|EP_Subquery);
          573  +    sqlite3ExprSetHeightAndFlags(pParse, pExpr);
          574  +  }else{
          575  +    assert( pParse->db->mallocFailed );
          576  +    sqlite3SelectDelete(pParse->db, pSelect);
          577  +  }
          578  +}
          579  +
   564    580   
   565    581   /*
   566    582   ** If the expression is always either TRUE or FALSE (respectively),
   567    583   ** then return 1.  If one cannot determine the truth value of the
   568    584   ** expression at compile-time return 0.
   569    585   **
   570    586   ** This is an optimization.  If is OK to return 0 here even if

Changes to src/parse.y.

  1118   1118         exprNot(pParse, N, &A);
  1119   1119       }
  1120   1120       A.zEnd = &E.z[E.n];
  1121   1121     }
  1122   1122     expr(A) ::= LP(B) select(X) RP(E). {
  1123   1123       spanSet(&A,&B,&E); /*A-overwrites-B*/
  1124   1124       A.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
  1125         -    if( A.pExpr ){
  1126         -      A.pExpr->x.pSelect = X;
  1127         -      ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
  1128         -      sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
  1129         -    }else{
  1130         -      sqlite3SelectDelete(pParse->db, X);
  1131         -    }
         1125  +    sqlite3PExprAddSelect(pParse, A.pExpr, X);
  1132   1126     }
  1133   1127     expr(A) ::= expr(A) in_op(N) LP select(Y) RP(E).  [IN] {
  1134   1128       A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0);
  1135         -    if( A.pExpr ){
  1136         -      A.pExpr->x.pSelect = Y;
  1137         -      ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
  1138         -      sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
  1139         -    }else{
  1140         -      sqlite3SelectDelete(pParse->db, Y);
  1141         -    }
         1129  +    sqlite3PExprAddSelect(pParse, A.pExpr, Y);
  1142   1130       exprNot(pParse, N, &A);
  1143   1131       A.zEnd = &E.z[E.n];
  1144   1132     }
  1145   1133     expr(A) ::= expr(A) in_op(N) nm(Y) dbnm(Z). [IN] {
  1146   1134       SrcList *pSrc = sqlite3SrcListAppend(pParse->db, 0,&Y,&Z);
         1135  +    Select *pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
  1147   1136       A.pExpr = sqlite3PExpr(pParse, TK_IN, A.pExpr, 0, 0);
  1148         -    if( A.pExpr ){
  1149         -      A.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
  1150         -      ExprSetProperty(A.pExpr, EP_xIsSelect|EP_Subquery);
  1151         -      sqlite3ExprSetHeightAndFlags(pParse, A.pExpr);
  1152         -    }else{
  1153         -      sqlite3SrcListDelete(pParse->db, pSrc);
  1154         -    }
         1137  +    sqlite3PExprAddSelect(pParse, A.pExpr, pSelect);
  1155   1138       exprNot(pParse, N, &A);
  1156   1139       A.zEnd = Z.z ? &Z.z[Z.n] : &Y.z[Y.n];
  1157   1140     }
  1158   1141     expr(A) ::= EXISTS(B) LP select(Y) RP(E). {
  1159   1142       Expr *p;
  1160   1143       spanSet(&A,&B,&E); /*A-overwrites-B*/
  1161   1144       p = A.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
  1162         -    if( p ){
  1163         -      p->x.pSelect = Y;
  1164         -      ExprSetProperty(p, EP_xIsSelect|EP_Subquery);
  1165         -      sqlite3ExprSetHeightAndFlags(pParse, p);
  1166         -    }else{
  1167         -      sqlite3SelectDelete(pParse->db, Y);
  1168         -    }
         1145  +    sqlite3PExprAddSelect(pParse, p, Y);
  1169   1146     }
  1170   1147   %endif SQLITE_OMIT_SUBQUERY
  1171   1148   
  1172   1149   /* CASE expressions */
  1173   1150   expr(A) ::= CASE(C) case_operand(X) case_exprlist(Y) case_else(Z) END(E). {
  1174   1151     spanSet(&A,&C,&E);  /*A-overwrites-C*/
  1175   1152     A.pExpr = sqlite3PExpr(pParse, TK_CASE, X, 0, 0);

Changes to src/sqliteInt.h.

  3445   3445   #ifdef SQLITE_DEBUG
  3446   3446   int sqlite3NoTempsInRange(Parse*,int,int);
  3447   3447   #endif
  3448   3448   Expr *sqlite3ExprAlloc(sqlite3*,int,const Token*,int);
  3449   3449   Expr *sqlite3Expr(sqlite3*,int,const char*);
  3450   3450   void sqlite3ExprAttachSubtrees(sqlite3*,Expr*,Expr*,Expr*);
  3451   3451   Expr *sqlite3PExpr(Parse*, int, Expr*, Expr*, const Token*);
         3452  +void sqlite3PExprAddSelect(Parse*, Expr*, Select*);
  3452   3453   Expr *sqlite3ExprAnd(sqlite3*,Expr*, Expr*);
  3453   3454   Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
  3454   3455   void sqlite3ExprAssignVarNumber(Parse*, Expr*);
  3455   3456   void sqlite3ExprDelete(sqlite3*, Expr*);
  3456   3457   ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
  3457   3458   void sqlite3ExprListSetSortOrder(ExprList*,int);
  3458   3459   void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);