Add support for vector assignments in the SET clause of an UPDATE statement.
FossilOrigin-Name: f320d47d6b7b08d9552c8444004bc256348bda90
This commit is contained in:
parent
fc7f27b9d2
commit
a1251bc40d
19
manifest
19
manifest
@ -1,5 +1,5 @@
|
||||
C Change\sthe\sway\sTK_SELECT_COLUMN\sis\shandled\sso\sthat\sthe\ssubquery\sis\sonly\ngenerated\sonce\seven\sif\spart\sof\sthe\svector\scomparison\sis\sused\sfor\sindexing\nand\sthe\sother\spart\sis\snow.\s\sThis\schange\salso\sis\sa\spathway\sto\svector\sassignment\nin\sUPDATE\sstatements.
|
||||
D 2016-08-20T00:07:01.602
|
||||
C Add\ssupport\sfor\svector\sassignments\sin\sthe\sSET\sclause\sof\san\sUPDATE\sstatement.
|
||||
D 2016-08-20T00:51:37.333
|
||||
F Makefile.in cfd8fb987cd7a6af046daa87daa146d5aad0e088
|
||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||
F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a
|
||||
@ -338,7 +338,7 @@ F src/ctime.c e77f3dc297b4b65c96da78b4ae4272fdfae863d7
|
||||
F src/date.c 95c9a8d00767e7221a8e9a31f4e913fc8029bf6b
|
||||
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
|
||||
F src/delete.c 76c084f0265f4a3cd1ecf17eee112a94f1ccbc05
|
||||
F src/expr.c ff73eb6cae76c2423928d46ceff6f2fdc379a568
|
||||
F src/expr.c bdc98d3301358bac9b19e23a22375f5220a77274
|
||||
F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb
|
||||
F src/fkey.c e2be0968c1adc679c87e467aa5b4f167588f38a8
|
||||
F src/func.c 29cc9acb170ec1387b9f63eb52cd85f8de96c771
|
||||
@ -373,7 +373,7 @@ F src/os_win.c 520f23475f1de530c435d30b67b7b15fe90874b0
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c 40928c450320da78bb4bd3ae82818f4239e19b7e
|
||||
F src/pager.h 966d2769e76ae347c8a32c4165faf6e6cb64546d
|
||||
F src/parse.y 3d02d64f333c4371c4f08fbd79a64964fa27b576
|
||||
F src/parse.y 9895eddbbb03c4a47cd760ff4f51cb8d139884d2
|
||||
F src/pcache.c 5583c8ade4b05075a60ba953ef471d1c1a9c05df
|
||||
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
|
||||
F src/pcache1.c 4bb7a6a5300c67d0b033d25adb509c120c03e812
|
||||
@ -389,7 +389,7 @@ F src/shell.c 79dda477be6c96eba6e952a934957ad36f87acc7
|
||||
F src/sqlite.h.in 0f7580280d1b009b507d8beec1ff0f197ba0cc99
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 8648034aa702469afb553231677306cc6492a1ae
|
||||
F src/sqliteInt.h 84f32ad3a5bfaf698b82bf5a9c6939f3e3d79ee0
|
||||
F src/sqliteInt.h db8aa0c875b1a3cdb26e1cee47662c30a34882fd
|
||||
F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247
|
||||
F src/status.c a9e66593dfb28a9e746cba7153f84d49c1ddc4b1
|
||||
F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9
|
||||
@ -467,7 +467,7 @@ F src/walker.c 2d2cc7fb0f320f7f415215d7247f3c584141ac09
|
||||
F src/where.c c7cdfd54f383090bb801cdd50d36de1a24684bb2
|
||||
F src/whereInt.h 14dd243e13b81cbb0a66063d38b70f93a7d6e613
|
||||
F src/wherecode.c 0c790c422ea5ecb6c83d6a78f2c4ebc036eea90e
|
||||
F src/whereexpr.c 021469f11930cc705a26f7f31ec37640588df1d4
|
||||
F src/whereexpr.c 706b539d9fcc884b1b9d4692a87c78019fb59fd2
|
||||
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
|
||||
F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd
|
||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||
@ -1025,6 +1025,7 @@ F test/rowvalue3.test dbe935260851b197dfbbbcb0ac2a15cb5f324fd4
|
||||
F test/rowvalue4.test ed3f7974099f0fc508c9f95df55d37c49f43be65
|
||||
F test/rowvalue5.test 01c7e0bc4048f30b58e6eb27ecd26e5bd312635e
|
||||
F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
|
||||
F test/rowvalue7.test 3c9a127954d3da309a271babdfc43dbcc5c4da7f
|
||||
F test/rowvaluefault.test 7b16485e3f2b371f3e3d05455b8ded6d0c090244
|
||||
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
|
||||
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
|
||||
@ -1518,7 +1519,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P d4a5af69cc3bde6f8c02075c07b4d47a0252392d
|
||||
R 8a9288690d2190168e2ddd79f5078350
|
||||
P d8feea7dcde83179bff303072426561cfe825e58
|
||||
R d0cc8110f72472ebd6ad961310b5fb0d
|
||||
U drh
|
||||
Z 663c48e63b0d59d8fc6b403d2678eeeb
|
||||
Z 375b2bf2a6add0d9f506b37662f21e95
|
||||
|
@ -1 +1 @@
|
||||
d8feea7dcde83179bff303072426561cfe825e58
|
||||
f320d47d6b7b08d9552c8444004bc256348bda90
|
68
src/expr.c
68
src/expr.c
@ -370,23 +370,17 @@ Expr *sqlite3VectorFieldSubexpr(Expr *pVector, int i){
|
||||
** The caller owns the returned Expr object and is responsible for
|
||||
** ensuring that the returned value eventually gets freed.
|
||||
**
|
||||
** Ownership of pVector is controlled by the takeOwnership parameter. If
|
||||
** takeOwnership is true, this routine takes responsibility for freeing
|
||||
** pVector, and may do so before returning, hence the caller must not reference
|
||||
** pVector again. If takeOwnership is false, then the caller takes
|
||||
** responsibility for freeing pVector and must ensure the pVector remains
|
||||
** valid as long as the returned value remains in use.
|
||||
** The caller retains ownership of pVector and must ensure that pVector
|
||||
** remains valid as long as the returned value is in use.
|
||||
*/
|
||||
Expr *sqlite3ExprForVectorField(
|
||||
Parse *pParse, /* Parsing context */
|
||||
Expr *pVector, /* The vector. List of expressions or a sub-SELECT */
|
||||
int iField, /* Which column of the vector to return */
|
||||
int takeOwnership /* True to take ownership of pVector before returning */
|
||||
int iField /* Which column of the vector to return */
|
||||
){
|
||||
Expr *pRet;
|
||||
assert( sqlite3ExprIsVector(pVector) );
|
||||
/* FIXME: Add support for takeOwnership!=0 */ assert( takeOwnership==0 );
|
||||
if( pVector->flags & EP_xIsSelect ){
|
||||
if( pVector->op==TK_SELECT ){
|
||||
assert( pVector->flags & EP_xIsSelect );
|
||||
/* The TK_SELECT_COLUMN Expr node:
|
||||
**
|
||||
** pLeft: pVector containing TK_SELECT
|
||||
@ -405,7 +399,8 @@ Expr *sqlite3ExprForVectorField(
|
||||
if( pRet ) pRet->iColumn = iField;
|
||||
assert( pRet==0 || pRet->iTable==0 );
|
||||
}else{
|
||||
pRet = sqlite3ExprDup(pParse->db, pVector->x.pList->a[iField].pExpr, 0);
|
||||
if( pVector->op==TK_VECTOR ) pVector = pVector->x.pList->a[iField].pExpr;
|
||||
pRet = sqlite3ExprDup(pParse->db, pVector, 0);
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
@ -1440,6 +1435,55 @@ no_mem:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** pColumns and pExpr for a vector assignment, like this:
|
||||
**
|
||||
** (a,b,c) = (expr1,expr2,expr3)
|
||||
** Or: (a,b,c) = (SELECT x,y,z FROM ....)
|
||||
**
|
||||
** For each term of the vector assignment, append new entries to the
|
||||
** expression list. In the case of a subquery on the LHS, append
|
||||
** TK_SELECT_COLUMN expressions.
|
||||
*/
|
||||
ExprList *sqlite3ExprListAppendVector(
|
||||
Parse *pParse, /* Parsing context */
|
||||
ExprList *pList, /* List to which to append. Might be NULL */
|
||||
IdList *pColumns, /* List of names of LHS of the assignment */
|
||||
Expr *pExpr /* Vector expression to be appended. Might be NULL */
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
int n;
|
||||
int i;
|
||||
if( 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 ){
|
||||
pList->a[pList->nExpr-1].zName = pColumns->a[i].zName;
|
||||
pColumns->a[i].zName = 0;
|
||||
}
|
||||
}
|
||||
if( pExpr->op==TK_SELECT ){
|
||||
if( pList && pList->a[0].pExpr ){
|
||||
assert( pList->a[0].pExpr->op==TK_SELECT_COLUMN );
|
||||
pList->a[0].pExpr->pRight = pExpr;
|
||||
pExpr = 0;
|
||||
}
|
||||
}
|
||||
|
||||
vector_append_error:
|
||||
sqlite3ExprDelete(db, pExpr);
|
||||
sqlite3IdListDelete(db, pColumns);
|
||||
return pList;
|
||||
}
|
||||
|
||||
/*
|
||||
** Set the sort order for the last element on the given ExprList.
|
||||
*/
|
||||
|
@ -789,10 +789,16 @@ setlist(A) ::= setlist(A) COMMA nm(X) EQ expr(Y). {
|
||||
A = sqlite3ExprListAppend(pParse, A, Y.pExpr);
|
||||
sqlite3ExprListSetName(pParse, A, &X, 1);
|
||||
}
|
||||
setlist(A) ::= setlist(A) COMMA LP idlist(X) RP EQ expr(Y). {
|
||||
A = sqlite3ExprListAppendVector(pParse, A, X, Y.pExpr);
|
||||
}
|
||||
setlist(A) ::= nm(X) EQ expr(Y). {
|
||||
A = sqlite3ExprListAppend(pParse, 0, Y.pExpr);
|
||||
sqlite3ExprListSetName(pParse, A, &X, 1);
|
||||
}
|
||||
setlist(A) ::= LP idlist(X) RP EQ expr(Y). {
|
||||
A = sqlite3ExprListAppendVector(pParse, 0, X, Y.pExpr);
|
||||
}
|
||||
|
||||
////////////////////////// The INSERT command /////////////////////////////////
|
||||
//
|
||||
|
@ -3547,6 +3547,7 @@ Expr *sqlite3ExprFunction(Parse*,ExprList*, Token*);
|
||||
void sqlite3ExprAssignVarNumber(Parse*, Expr*);
|
||||
void sqlite3ExprDelete(sqlite3*, Expr*);
|
||||
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
|
||||
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
|
||||
void sqlite3ExprListSetSortOrder(ExprList*,int);
|
||||
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
|
||||
void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
|
||||
@ -4276,6 +4277,6 @@ int sqlite3DbstatRegister(sqlite3*);
|
||||
int sqlite3ExprVectorSize(Expr *pExpr);
|
||||
int sqlite3ExprIsVector(Expr *pExpr);
|
||||
Expr *sqlite3VectorFieldSubexpr(Expr*, int);
|
||||
Expr *sqlite3ExprForVectorField(Parse*,Expr*,int,int);
|
||||
Expr *sqlite3ExprForVectorField(Parse*,Expr*,int);
|
||||
|
||||
#endif /* SQLITEINT_H */
|
||||
|
@ -1188,8 +1188,8 @@ static void exprAnalyze(
|
||||
for(i=0; i<sqlite3ExprVectorSize(pExpr->pLeft); i++){
|
||||
int idxNew;
|
||||
Expr *pNew;
|
||||
Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i, 0);
|
||||
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i, 0);
|
||||
Expr *pLeft = sqlite3ExprForVectorField(pParse, pExpr->pLeft, i);
|
||||
Expr *pRight = sqlite3ExprForVectorField(pParse, pExpr->pRight, i);
|
||||
|
||||
pNew = sqlite3PExpr(pParse, pExpr->op, pLeft, pRight, 0);
|
||||
idxNew = whereClauseInsert(pWC, pNew, TERM_DYNAMIC);
|
||||
|
58
test/rowvalue7.test
Normal file
58
test/rowvalue7.test
Normal file
@ -0,0 +1,58 @@
|
||||
# 2016-08-18
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
# The focus of this file is vector assignments in the SET clause of
|
||||
# an UPDATE statement.
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set ::testprefix rowvalue7
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
CREATE TABLE t1(a,b,c,d);
|
||||
CREATE INDEX t1x ON t1(a,b);
|
||||
INSERT INTO t1(a,b,c,d) VALUES(1,2,0,0),(3,4,0,0),(5,6,0,0);
|
||||
CREATE TABLE t2(w,x,y,z);
|
||||
CREATE INDEX t2x ON t2(w,x);
|
||||
INSERT INTO t2(w,x,y,z) VALUES(1,2,11,22),(8,9,88,99),(3,5,33,55),(5,6,55,66);
|
||||
|
||||
SELECT *,'|' FROM t1 ORDER BY a;
|
||||
} {1 2 0 0 | 3 4 0 0 | 5 6 0 0 |}
|
||||
|
||||
do_execsql_test 1.2 {
|
||||
UPDATE t1 SET (c,d) = (SELECT y,z FROM t2 WHERE (w,x)=(a,b));
|
||||
SELECT *,'|' FROM t1 ORDER BY a;
|
||||
} {1 2 11 22 | 3 4 {} {} | 5 6 55 66 |}
|
||||
|
||||
do_execsql_test 1.3 {
|
||||
UPDATE t1 SET (c,d) = (SELECT y,z FROM t2 WHERE w=a);
|
||||
SELECT *,'|' FROM t1 ORDER BY a;
|
||||
} {1 2 11 22 | 3 4 33 55 | 5 6 55 66 |}
|
||||
|
||||
do_execsql_test 1.4 {
|
||||
UPDATE t1 SET (c) = 99 WHERE a=3;
|
||||
SELECT *,'|' FROM t1 ORDER BY a;
|
||||
} {1 2 11 22 | 3 4 99 55 | 5 6 55 66 |}
|
||||
|
||||
do_execsql_test 1.5 {
|
||||
UPDATE t1 SET b = 8, (c,d) = (123,456) WHERE a=3;
|
||||
SELECT *,'|' FROM t1 ORDER BY a;
|
||||
} {1 2 11 22 | 3 8 123 456 | 5 6 55 66 |}
|
||||
|
||||
do_catchsql_test 2.1 {
|
||||
UPDATE t1 SET (c,d) = (SELECT x,y,z FROM t2 WHERE w=a);
|
||||
} {1 {2 columns assigned 3 values}}
|
||||
|
||||
do_catchsql_test 2.2 {
|
||||
UPDATE t1 SET (b,c,d) = (SELECT x,y FROM t2 WHERE w=a);
|
||||
} {1 {3 columns assigned 2 values}}
|
||||
|
||||
finish_test
|
Loading…
x
Reference in New Issue
Block a user