-C Fix\sthe\srow-values\sin\sUPDATE\sstatements\swithin\sTRIGGER\sproblem\sidentified\nby\sticket\s[8c9458e7].
-D 2017-01-03T15:57:18.816
+C Defer\ssize\schecking\son\srow-value\sassignments\sfor\swhen\sthe\sRHS\sis\sa\sSELECT\nuntil\safter\sthe\s"*"\swildcards\shave\sbeen\sexpanded.
+D 2017-01-03T15:59:29.597
F Makefile.in 41bd4cad981487345c4a84081074bcdb876e4b2e
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
F Makefile.msc b8ca53350ae545e3562403d5da2a69cec79308da
F src/date.c dc3f1391d9297f8c748132813aaffcb117090d6e
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
F src/delete.c c8bc10d145c9666a34ae906250326fdaa8d58fa5
-F src/expr.c e115097aa866a462051ac8430757638dc1d73f1c
+F src/expr.c 1df03961abc008b46154edca14bcbb38e7a3be90
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c 2e9aabe1aee76273aff8a84ee92c464e095400ae
F src/func.c d8582ee91975975645f206db332c38f534b783ad
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 04ac0b75b1716541b2b97704f4809cb7ef19cccf
-Q +f12ed3ce0bfb2d94c9baad23fdcbd816c72439a1
-R cf923ffcf348cd32ea5d06c3e1c77d24
-T *branch * branch-3.16
-T *sym-branch-3.16 *
-T -sym-trunk *
+P bf984e980c14c9adc54ad010d3a7d199dd53edd6
+Q +36944be6be5c42096f5da84187ff203af26b08ae
+R 0526d39f4fb848c58d26920a7a0cd54f
U drh
-Z 8f14fba7a63b9f6a29946074d4bfc5c2
+Z a5f0228fea1e23b002b3472ec397935f
assert( pVector->flags & EP_xIsSelect );
/* The TK_SELECT_COLUMN Expr node:
**
- ** pLeft: pVector containing TK_SELECT
+ ** 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.
**
** 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 ){
+
+ /* 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<n; i++){
+
+ for(i=0; i<pColumns->nId; i++){
Expr *pSubExpr = sqlite3ExprForVectorField(pParse, pExpr, i);
pList = sqlite3ExprListAppend(pParse, pList, pSubExpr);
if( pList ){
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;
+ 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;
}
}
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: {