Handle "<vector> IN (<vector>, <vector> ...)" in the same way as "<vector> IN (VALUES(<vector>, <vector>, ...)".

FossilOrigin-Name: 981d230ece98ce89502dab02aa44f73699a9d0e4fce3e9e9dfd47444a5a9990f
This commit is contained in:
dan 2021-07-06 20:44:32 +00:00
parent b9324fea07
commit 9289f5103d
7 changed files with 173 additions and 22 deletions

View File

@ -1,5 +1,5 @@
C Do\snot\sallow\swrites\sto\san\sfts5\stable\sif\sthere\sare\sany\sopen\sfts5vocab\scursors. C Handle\s"<vector>\sIN\s(<vector>,\s<vector>\s...)"\sin\sthe\ssame\sway\sas\s"<vector>\sIN\s(VALUES(<vector>,\s<vector>,\s...)".
D 2021-07-05T19:01:09.054 D 2021-07-06T20:44:32.552
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@ -496,7 +496,7 @@ F src/date.c e0632f335952b32401482d099321bbf12716b29d6e72836b53ae49683ebae4bf
F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a
F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c F src/dbstat.c 3aa79fc3aed7ce906e4ea6c10e85d657299e304f6049861fe300053ac57de36c
F src/delete.c 62451bba9fe641159e9c0b7d9d2bab1c48d0cff11e16de2d14000603d2af1fcf F src/delete.c 62451bba9fe641159e9c0b7d9d2bab1c48d0cff11e16de2d14000603d2af1fcf
F src/expr.c 5c532072d91855d1b91b2581c2d4447e517932713f583ed02020b7129f1cfbd7 F src/expr.c ab3935a79da7f0aa0f2f26b16a7fdee527cd21e457876f1d53f009c472a43226
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4 F src/fkey.c e9063648396c58778f77583a678342fe4a9bc82436bf23c5f9f444f2df0fdaa4
F src/func.c c96ac6f7c4f2d684217c4673a80446e1b50e25b5ea79366f333f484622d010a0 F src/func.c c96ac6f7c4f2d684217c4673a80446e1b50e25b5ea79366f333f484622d010a0
@ -533,7 +533,7 @@ F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
F src/pager.c 95c255256b13827caf038c8f963d334784073f38ab6ef9d70371d9d04f3c43e0 F src/pager.c 95c255256b13827caf038c8f963d334784073f38ab6ef9d70371d9d04f3c43e0
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
F src/parse.y 8920f4444957d7827ca458029b2e41ffa32dd3b72917be0b52cae0aace3eadb5 F src/parse.y 50ef70ca8c7797a405139bbf92ee34812eaa4c0aff10822792672940de424e36
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177 F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586 F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
F src/pcache1.c 388304fd2d91c39591080b5e0f3c62cfba87db20370e7e0554062bfb29740e9f F src/pcache1.c 388304fd2d91c39591080b5e0f3c62cfba87db20370e7e0554062bfb29740e9f
@ -549,7 +549,7 @@ F src/shell.c.in 699910739eb7296fd47be19db71f6e5d15d0760f4352c62639d4d6cc7bd8d4c
F src/sqlite.h.in ecf5aa981da30c33da3e9f353bf3ebf055d3c380c80d6a4f954e58d18ccd6df1 F src/sqlite.h.in ecf5aa981da30c33da3e9f353bf3ebf055d3c380c80d6a4f954e58d18ccd6df1
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510 F src/sqlite3ext.h e97f4e9b509408fea4c4e9bef5a41608dfac343b4d3c7a990dedde1e19af9510
F src/sqliteInt.h b5e0732368e4a4f925b7994538cd3fd3b85027a1c4dcadf3fc944b36f35ce8cd F src/sqliteInt.h c78fbfc341832bad59299bfc1f932a48e3631d652ae7f443fed969d7c2de76ad
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1 F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@ -1317,7 +1317,8 @@ F test/rowvalue6.test d19b54feb604d5601f8614b15e214e0774c01087
F test/rowvalue7.test c1cbdbf407029db01f87764097c6ac02a1c5a37efd2776eff32a9cdfdf6f2dba F test/rowvalue7.test c1cbdbf407029db01f87764097c6ac02a1c5a37efd2776eff32a9cdfdf6f2dba
F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0 F test/rowvalue8.test 5900eddad9e2c3c2e26f1a95f74aafc1232ee5e0
F test/rowvalue9.test cb5380df82dca9db463081e26952c1e097b34fc2c2ac87453970c048d97df687 F test/rowvalue9.test cb5380df82dca9db463081e26952c1e097b34fc2c2ac87453970c048d97df687
F test/rowvaluefault.test 7cd9ccc6c2fbdd881672984087aad0491bb75504 F test/rowvalueA.test 1e73cc7d35491bb46352adaade23cecc9add6094434d85445a3251fc20079ebe
F test/rowvaluefault.test 1dbe9e2a57c4b1a2ee4fb78c7a08c13d4c62885125019713190594aa4847f740
F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f F test/rowvaluevtab.test cd9747bb3f308086944c07968f547ad6b05022e698d80b9ffbdfe09ce0b8da6f
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798 F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09 F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09
@ -1919,7 +1920,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
P e306952690bfb140e2c404a74b05ff2d070c487f7e52c62d62a004505fba0e15 P c49a6ed78a917d4972e048e2a9bbe4d400691f97ce7e022f0e4436ceaed7fb73
R 97f692da529fbbc0053b9965bcfd2834 R 088831e8438f8281d3a5f02f1fe2374b
U dan U dan
Z 35b3ccac90623680edbe1ba22c3e426c Z e8e70fe2aaf0c6a219c124f4d93d407b

View File

@ -1 +1 @@
c49a6ed78a917d4972e048e2a9bbe4d400691f97ce7e022f0e4436ceaed7fb73 981d230ece98ce89502dab02aa44f73699a9d0e4fce3e9e9dfd47444a5a9990f

View File

@ -945,6 +945,55 @@ void sqlite3PExprAddSelect(Parse *pParse, Expr *pExpr, Select *pSelect){
} }
} }
/*
** Expression list pEList is a list of vector values. This function
** converts the contents of pEList to a VALUES(...) Select statement
** returning 1 row for each element of the list. If there are any
** non-vector expressions in the list, the corresponding row returned
** by the values statement contains a single column, the value of
** the non-vector expression itself.
**
** For example, the expression list:
**
** ( (1, 2), 3, (3, 4, 5) )
**
** is translated to:
**
** VALUES(1, 2), (3), (3, 4, 5)
**
** This is used as part of processing IN(...) expressions with a list
** of vectors on the RHS. e.g. "... IN ((1,2), (3,4), (5,6))".
*/
Select *sqlite3ExprListToValues(Parse *pParse, ExprList *pEList){
int ii;
Select *pRet = 0;
for(ii=0; ii<pEList->nExpr; ii++){
Select *pSel;
ExprList *pList;
Expr *pExpr = pEList->a[ii].pExpr;
if( pExpr->op==TK_VECTOR ){
pList = pExpr->x.pList;
pExpr->x.pList = 0;
}else{
pList = sqlite3ExprListAppend(pParse, 0, pExpr);
pEList->a[ii].pExpr = 0;
}
pSel = sqlite3SelectNew(pParse, pList, 0, 0, 0, 0, 0, SF_Values, 0);
if( pSel ){
if( pRet ){
pSel->op = TK_ALL;
pSel->pPrior = pRet;
}
pRet = pSel;
}
}
if( pRet && pRet->pPrior ){
pRet->selFlags |= SF_MultiValue;
}
sqlite3ExprListDelete(pParse->db, pEList);
return pRet;
}
/* /*
** Join two expressions using an AND operator. If either expression is ** Join two expressions using an AND operator. If either expression is

View File

@ -1254,20 +1254,25 @@ expr(A) ::= expr(A) between_op(N) expr(X) AND expr(Y). [BETWEEN] {
*/ */
sqlite3ExprUnmapAndDelete(pParse, A); sqlite3ExprUnmapAndDelete(pParse, A);
A = sqlite3Expr(pParse->db, TK_INTEGER, N ? "1" : "0"); A = sqlite3Expr(pParse->db, TK_INTEGER, N ? "1" : "0");
}else if( Y->nExpr==1 && sqlite3ExprIsConstant(Y->a[0].pExpr) ){
Expr *pRHS = Y->a[0].pExpr;
Y->a[0].pExpr = 0;
sqlite3ExprListDelete(pParse->db, Y);
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
A = sqlite3PExpr(pParse, TK_EQ, A, pRHS);
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
}else{ }else{
A = sqlite3PExpr(pParse, TK_IN, A, 0); Expr *pRHS = Y->a[0].pExpr;
if( A ){ if( Y->nExpr==1 && sqlite3ExprIsConstant(pRHS) && pRHS->op!=TK_VECTOR ){
A->x.pList = Y; Y->a[0].pExpr = 0;
sqlite3ExprSetHeightAndFlags(pParse, A);
}else{
sqlite3ExprListDelete(pParse->db, Y); sqlite3ExprListDelete(pParse->db, Y);
pRHS = sqlite3PExpr(pParse, TK_UPLUS, pRHS, 0);
A = sqlite3PExpr(pParse, TK_EQ, A, pRHS);
}else{
A = sqlite3PExpr(pParse, TK_IN, A, 0);
if( pRHS->op==TK_VECTOR || A==0 ){
Select *pRHS = sqlite3ExprListToValues(pParse, Y);
if( pRHS ){
parserDoubleLinkSelect(pParse, pRHS);
sqlite3PExprAddSelect(pParse, A, pRHS);
}
}else{
A->x.pList = Y;
sqlite3ExprSetHeightAndFlags(pParse, A);
}
} }
if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0); if( N ) A = sqlite3PExpr(pParse, TK_NOT, A, 0);
} }

View File

@ -4324,6 +4324,7 @@ void sqlite3ExprDeferredDelete(Parse*, Expr*);
void sqlite3ExprUnmapAndDelete(Parse*, Expr*); void sqlite3ExprUnmapAndDelete(Parse*, Expr*);
ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*); ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*); ExprList *sqlite3ExprListAppendVector(Parse*,ExprList*,IdList*,Expr*);
Select *sqlite3ExprListToValues(Parse*, ExprList*);
void sqlite3ExprListSetSortOrder(ExprList*,int,int); void sqlite3ExprListSetSortOrder(ExprList*,int,int);
void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int); void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*); void sqlite3ExprListSetSpan(Parse*,ExprList*,const char*,const char*);

77
test/rowvalueA.test Normal file
View File

@ -0,0 +1,77 @@
# 2021 July 6
#
# 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.
#
#***********************************************************************
# This file implements regression tests for SQLite library.
#
set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix rowvalueA
do_execsql_test 1.0 {
SELECT (1, 2) IN ( (3, 4), (5, 6), (1, 3) );
} {0}
do_execsql_test 1.1 {
SELECT (1, 2) IN ( (3, 4), (5, 6), (1, 2) );
} {1}
do_execsql_test 1.2 {
SELECT (1, 2) IN ( (3, 2) );
} {0}
do_execsql_test 1.3 {
SELECT (1, 2) IN ( (1, 2) );
} {1}
do_execsql_test 1.4 {
SELECT (1, 2) IN ( );
} {0}
do_execsql_test 1.5 {
SELECT (1, 2) NOT IN ( );
} {1}
for {set ii 0} {$ii < 2000} {incr ii} {
lappend L "($ii, $ii)"
}
do_execsql_test 1.6.1 "
SELECT (400,400) IN ( [join $L ,] )
" 1
do_execsql_test 1.6.2 "
SELECT (1500,1500) IN ( [join $L ,] )
" 1
do_execsql_test 1.6.2 "
SELECT (1500,1499) IN ( [join $L ,] )
" 0
#-------------------------------------------------------------------------
do_catchsql_test 2.0 {
SELECT (1, 2) IN ( (1, 2), (3, 4, 5), (5, 6) )
} {1 {all VALUES must have the same number of terms}}
do_catchsql_test 2.1 {
SELECT (1, 2) IN ( (1, 2), 4, (5, 6) )
} {1 {all VALUES must have the same number of terms}}
do_catchsql_test 2.2 {
SELECT (1, 2, 3) IN ( (1, 2), (3, 4), (5, 6) )
} {1 {sub-select returns 2 columns - expected 3}}
do_catchsql_test 2.3 {
SELECT 2 IN ( (1, 2), (3, 4), (5, 6) )
} {1 {sub-select returns 2 columns - expected 1}}
finish_test

View File

@ -68,4 +68,22 @@ do_faultsim_test 6 -faults oom* -body {
faultsim_test_result {0 {2 3}} faultsim_test_result {0 {2 3}}
} }
do_faultsim_test 7 -faults oom* -body {
execsql {
SELECT fou FROM xyz
WHERE (one, two, thr) IN ( ('a','b','c'), ('A','A','A'), (1,2,3) );
}
} -test {
faultsim_test_result {0 1}
}
do_faultsim_test 8 -faults oom* -body {
execsql {
SELECT fou FROM xyz
WHERE two IN ( ('a','b','c'), ('A','A','A'), (1,2,3) );
}
} -test {
faultsim_test_result {1 {sub-select returns 3 columns - expected 1}}
}
finish_test finish_test