/ Changes On Branch vector-size-check
Login

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

Changes In Branch vector-size-check Excluding Merge-Ins

This is equivalent to a diff from f12ed3ce0b to 696219b110

2017-01-03
15:57
Fix the row-values in UPDATE statements within TRIGGER problem identified by ticket [8c9458e7]. (check-in: bf984e980c user: drh tags: branch-3.16)
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: 36944be6be user: drh tags: trunk)
08:11
Add test cases for the fix in [f12ed3ce]. No problems discovered. (check-in: 548532fdcf user: dan 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: 696219b110 user: drh tags: vector-size-check)
01:24
Fix the row-values in UPDATE statements within TRIGGER problem identified by ticket [8c9458e7]. (check-in: f12ed3ce0b user: drh tags: trunk)
00:27
Improved assert()s on the sqlite3ExprListDup() logic for TK_SELECT_COLUMN. (Closed-Leaf check-in: 14da99d41f user: drh tags: rowvalue-update-trigger)
2017-01-02
19:10
Increase the version number to 3.17.0 for the next release cycle. (check-in: 16415b5aad user: drh tags: trunk)

Changes to src/expr.c.

410
411
412
413
414
415
416
417
418
419

420
421
422
423
424
425
426
  int iField           /* Which column of the vector to return */
){
  Expr *pRet;
  if( pVector->op==TK_SELECT ){
    assert( pVector->flags & EP_xIsSelect );
    /* The TK_SELECT_COLUMN Expr node:
    **
    ** pLeft:           pVector containing TK_SELECT
    ** pRight:          not used.  But recursively deleted.
    ** iColumn:         Index of a column in pVector

    ** pLeft->iTable:   First in an array of register holding result, or 0
    **                  if the result is not yet computed.
    **
    ** sqlite3ExprDelete() specifically skips the recursive delete of
    ** pLeft on TK_SELECT_COLUMN nodes.  But pRight is followed, so pVector
    ** can be attached to pRight to cause this node to take ownership of
    ** pVector.  Typically there will be multiple TK_SELECT_COLUMN nodes







|


>







410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
  int iField           /* Which column of the vector to return */
){
  Expr *pRet;
  if( pVector->op==TK_SELECT ){
    assert( pVector->flags & EP_xIsSelect );
    /* The TK_SELECT_COLUMN Expr node:
    **
    ** pLeft:           pVector containing TK_SELECT.  Not deleted.
    ** pRight:          not used.  But recursively deleted.
    ** iColumn:         Index of a column in pVector
    ** iTable:          0 or the number of columns on the LHS of an assignment
    ** pLeft->iTable:   First in an array of register holding result, or 0
    **                  if the result is not yet computed.
    **
    ** sqlite3ExprDelete() specifically skips the recursive delete of
    ** pLeft on TK_SELECT_COLUMN nodes.  But pRight is followed, so pVector
    ** can be attached to pRight to cause this node to take ownership of
    ** pVector.  Typically there will be multiple TK_SELECT_COLUMN nodes
1515
1516
1517
1518
1519
1520
1521
1522





1523
1524
1525
1526
1527

1528
1529
1530
1531
1532
1533
1534
1535
1536

1537
1538

1539



1540
1541




1542
1543
1544
1545
1546
1547
1548
  int n;
  int i;
  int iFirst = pList ? pList->nExpr : 0;
  /* pColumns can only be NULL due to an OOM but an OOM will cause an
  ** exit prior to this routine being invoked */
  if( NEVER(pColumns==0) ) goto vector_append_error;
  if( pExpr==0 ) goto vector_append_error;
  n = sqlite3ExprVectorSize(pExpr);





  if( pColumns->nId!=n ){
    sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
                    pColumns->nId, n);
    goto vector_append_error;
  }

  for(i=0; i<n; i++){
    Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
    pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
    if( pList ){
      assert( pList->nExpr==iFirst+i+1 );
      pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
      pColumns->a[i].zName = 0;
    }
  }

  if( pExpr->op==TK_SELECT ){
    if( pList && pList->a[iFirst].pExpr ){

      assert( pList->a[iFirst].pExpr->op==TK_SELECT_COLUMN );



      pList->a[iFirst].pExpr->pRight = pExpr;
      pExpr = 0;




    }
  }

vector_append_error:
  sqlite3ExprDelete(db, pExpr);
  sqlite3IdListDelete(db, pColumns);
  return pList;







|
>
>
>
>
>
|




>
|








>


>
|
>
>
>
|

>
>
>
>







1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
  int n;
  int i;
  int iFirst = pList ? pList->nExpr : 0;
  /* pColumns can only be NULL due to an OOM but an OOM will cause an
  ** exit prior to this routine being invoked */
  if( NEVER(pColumns==0) ) goto vector_append_error;
  if( pExpr==0 ) goto vector_append_error;

  /* If the RHS is a vector, then we can immediately check to see that 
  ** the size of the RHS and LHS match.  But if the RHS is a SELECT, 
  ** wildcards ("*") in the result set of the SELECT must be expanded before
  ** we can do the size check, so defer the size check until code generation.
  */
  if( pExpr->op!=TK_SELECT && pColumns->nId!=(n=sqlite3ExprVectorSize(pExpr)) ){
    sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
                    pColumns->nId, n);
    goto vector_append_error;
  }

  for(i=0; i<pColumns->nId; i++){
    Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
    pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
    if( pList ){
      assert( pList->nExpr==iFirst+i+1 );
      pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
      pColumns->a[i].zName = 0;
    }
  }

  if( pExpr->op==TK_SELECT ){
    if( pList && pList->a[iFirst].pExpr ){
      Expr *pFirst = pList->a[iFirst].pExpr;
      assert( pFirst->op==TK_SELECT_COLUMN );
     
      /* Store the SELECT statement in pRight so it will be deleted when
      ** sqlite3ExprListDelete() is called */
      pFirst->pRight = pExpr;
      pExpr = 0;

      /* Remember the size of the LHS in iTable so that we can check that
      ** the RHS and LHS sizes match during code generation. */
      pFirst->iTable = pColumns->nId;
    }
  }

vector_append_error:
  sqlite3ExprDelete(db, pExpr);
  sqlite3IdListDelete(db, pColumns);
  return pList;
3728
3729
3730
3731
3732
3733
3734

3735
3736







3737
3738
3739
3740
3741
3742
3743
        sqlite3SubselectError(pParse, nCol, 1);
      }else{
        return sqlite3CodeSubselect(pParse, pExpr, 0, 0);
      }
      break;
    }
    case TK_SELECT_COLUMN: {

      if( pExpr->pLeft->iTable==0 ){
        pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);







      }
      return pExpr->pLeft->iTable + pExpr->iColumn;
    }
    case TK_IN: {
      int destIfFalse = sqlite3VdbeMakeLabel(v);
      int destIfNull = sqlite3VdbeMakeLabel(v);
      sqlite3VdbeAddOp2(v, OP_Null, 0, target);







>


>
>
>
>
>
>
>







3744
3745
3746
3747
3748
3749
3750
3751
3752
3753
3754
3755
3756
3757
3758
3759
3760
3761
3762
3763
3764
3765
3766
3767
        sqlite3SubselectError(pParse, nCol, 1);
      }else{
        return sqlite3CodeSubselect(pParse, pExpr, 0, 0);
      }
      break;
    }
    case TK_SELECT_COLUMN: {
      int n;
      if( pExpr->pLeft->iTable==0 ){
        pExpr->pLeft->iTable = sqlite3CodeSubselect(pParse, pExpr->pLeft, 0, 0);
      }
      assert( pExpr->iTable==0 || pExpr->pLeft->op==TK_SELECT );
      if( pExpr->iTable
       && pExpr->iTable!=(n = sqlite3ExprVectorSize(pExpr->pLeft)) 
      ){
        sqlite3ErrorMsg(pParse, "%d columns assigned %d values",
                                pExpr->iTable, n);
      }
      return pExpr->pLeft->iTable + pExpr->iColumn;
    }
    case TK_IN: {
      int destIfFalse = sqlite3VdbeMakeLabel(v);
      int destIfNull = sqlite3VdbeMakeLabel(v);
      sqlite3VdbeAddOp2(v, OP_Null, 0, target);