/ Check-in [696219b1]
Login

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

Overview
Comment:Improvements to the way vector assignment size checking is done. Size checks when the RHS is a SELECT are deferred until after "*" wildcards are expanded.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | vector-size-check
Files: files | file ages | folders
SHA1: 696219b11049930cdbc38f574820f4bbaf8621bb
User & Date: drh 2017-01-03 02:58:01
Context
2017-01-03
13:45
Defer size checking on row-value assignments for when the RHS is a SELECT until after the "*" wildcards have been expanded. check-in: 36944be6 user: drh tags: trunk
02:58
Improvements to the way vector assignment size checking is done. Size checks when the RHS is a SELECT are deferred until after "*" wildcards are expanded. Closed-Leaf check-in: 696219b1 user: drh tags: vector-size-check
01:24
Fix the row-values in UPDATE statements within TRIGGER problem identified by ticket [8c9458e7]. check-in: f12ed3ce user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

   410    410     int iField           /* Which column of the vector to return */
   411    411   ){
   412    412     Expr *pRet;
   413    413     if( pVector->op==TK_SELECT ){
   414    414       assert( pVector->flags & EP_xIsSelect );
   415    415       /* The TK_SELECT_COLUMN Expr node:
   416    416       **
   417         -    ** pLeft:           pVector containing TK_SELECT
          417  +    ** pLeft:           pVector containing TK_SELECT.  Not deleted.
   418    418       ** pRight:          not used.  But recursively deleted.
   419    419       ** iColumn:         Index of a column in pVector
          420  +    ** iTable:          0 or the number of columns on the LHS of an assignment
   420    421       ** pLeft->iTable:   First in an array of register holding result, or 0
   421    422       **                  if the result is not yet computed.
   422    423       **
   423    424       ** sqlite3ExprDelete() specifically skips the recursive delete of
   424    425       ** pLeft on TK_SELECT_COLUMN nodes.  But pRight is followed, so pVector
   425    426       ** can be attached to pRight to cause this node to take ownership of
   426    427       ** pVector.  Typically there will be multiple TK_SELECT_COLUMN nodes
................................................................................
  1515   1516     int n;
  1516   1517     int i;
  1517   1518     int iFirst = pList ? pList->nExpr : 0;
  1518   1519     /* pColumns can only be NULL due to an OOM but an OOM will cause an
  1519   1520     ** exit prior to this routine being invoked */
  1520   1521     if( NEVER(pColumns==0) ) goto vector_append_error;
  1521   1522     if( pExpr==0 ) goto vector_append_error;
  1522         -  n = sqlite3ExprVectorSize(pExpr);
  1523         -  if( pColumns->nId!=n ){
         1523  +
         1524  +  /* If the RHS is a vector, then we can immediately check to see that 
         1525  +  ** the size of the RHS and LHS match.  But if the RHS is a SELECT, 
         1526  +  ** wildcards ("*") in the result set of the SELECT must be expanded before
         1527  +  ** we can do the size check, so defer the size check until code generation.
         1528  +  */
         1529  +  if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){
  1524   1530       sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
  1525   1531                       pColumns->nId, n);
  1526   1532       goto vector_append_error;
  1527   1533     }
  1528         -  for(i=0; i<n; i++){
         1534  +
         1535  +  for(i=0; i<pColumns->nId; i++){
  1529   1536       Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
  1530   1537       pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
  1531   1538       if( pList ){
  1532   1539         assert( pList->nExpr==iFirst+i+1 );
  1533   1540         pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
  1534   1541         pColumns->a[i].zName = 0;
  1535   1542       }
  1536   1543     }
         1544  +
  1537   1545     if( pExpr->op==TK_SELECT ){
  1538   1546       if( pList && pList->a[iFirst].pExpr ){
  1539         -      assert( pList->a[iFirst].pExpr->op==TK_SELECT_COLUMN );
  1540         -      pList->a[iFirst].pExpr->pRight = pExpr;
         1547  +      Expr *pFirst = pList->a[iFirst].pExpr;
         1548  +      assert( pFirst->op==TK_SELECT_COLUMN );
         1549  +     
         1550  +      /* Store the SELECT statement in pRight so it will be deleted when
         1551  +      ** sqlite3ExprListDelete() is called */
         1552  +      pFirst->pRight = pExpr;
  1541   1553         pExpr = 0;
         1554  +
         1555  +      /* Remember the size of the LHS in iTable so that we can check that
         1556  +      ** the RHS and LHS sizes match during code generation. */
         1557  +      pFirst->iTable = pColumns->nId;
  1542   1558       }
  1543   1559     }
  1544   1560   
  1545   1561   vector_append_error:
  1546   1562     sqlite3ExprDelete(db, pExpr);
  1547   1563     sqlite3IdListDelete(db, pColumns);
  1548   1564     return pList;
................................................................................
  3728   3744           sqlite3SubselectError(pParse, nCol, 1);
  3729   3745         }else{
  3730   3746           return sqlite3CodeSubselect(pParse, pExpr, 0, 0);
  3731   3747         }
  3732   3748         break;
  3733   3749       }
  3734   3750       case TK_SELECT_COLUMN: {
         3751  +      int n;
  3735   3752         if( pExpr->pLeft->iTable==0 ){
  3736   3753           pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
         3754  +      }
         3755  +      assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
         3756  +      if( pExpr->iTable
         3757  +       && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) 
         3758  +      ){
         3759  +        sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
         3760  +                                pExpr->iTable, n);
  3737   3761         }
  3738   3762         return pExpr->pLeft->iTable + pExpr->iColumn;
  3739   3763       }
  3740   3764       case TK_IN: {
  3741   3765         int destIfFalse = sqlite3VdbeMakeLabel(v);
  3742   3766         int destIfNull = sqlite3VdbeMakeLabel(v);
  3743   3767         sqlite3VdbeAddOp2(v, OP_Null, 0, target);