From: dan Date: Wed, 27 Jul 2016 19:33:04 +0000 (+0000) Subject: Fix some problems with multi-column IN(SELECT...) processing. X-Git-Tag: version-3.15.0~110^2~102 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=d49fd4e89a1a9a48a14f79ba6356165b04e6e295;p=thirdparty%2Fsqlite.git Fix some problems with multi-column IN(SELECT...) processing. FossilOrigin-Name: 719a3b2035a335ca8b9704646b1d641011e3ea0e --- d49fd4e89a1a9a48a14f79ba6356165b04e6e295 diff --cc manifest index fd048d6c5d,185e06b3cc..8b4409d2ff --- a/manifest +++ b/manifest @@@ -1,5 -1,5 +1,5 @@@ - C Merge\slatest\strunk\schanges\sinto\sthis\sbranch. - D 2016-07-26T18:15:35.133 -C Initialize\sa\svariable\sin\swhere.c\sto\savoid\sa\svalgrind\swarning. -D 2016-07-27T16:03:54.108 ++C Fix\ssome\sproblems\swith\smulti-column\sIN(SELECT...)\sprocessing. ++D 2016-07-27T19:33:04.107 F Makefile.in 6c20d44f72d4564f11652b26291a214c8367e5db F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434 F Makefile.msc d66d0395c38571aab3804f8db0fa20707ae4609a @@@ -337,7 -337,7 +337,7 @@@ F src/ctime.c 61949e83c4c36e37195a8398e F src/date.c 1cc9fb516ec9932c6fd4d2a0d2f8bc4480145c39 F src/dbstat.c 4f6f7f52b49beb9636ffbd517cfe44a402ba4ad0 F src/delete.c 4aba4214a377ce8ddde2d2e609777bcc8235200f - F src/expr.c f84861eaaf557df45bb8f4513a78a05fbb0ad368 -F src/expr.c 21b153e1046c624e9387a17d3261f69b461e700c ++F src/expr.c bee29fbb017db26ad1189d35b2a7fe6ff8da3722 F src/fault.c 160a0c015b6c2629d3899ed2daf63d75754a32bb F src/fkey.c bc4145347595b7770f9a598cff1c848302cf5413 F src/func.c 61a4114cf7004f10c542cfabbab9f2bcb9033045 @@@ -381,14 -381,14 +381,14 @@@ F src/pragma.h 64c78a648751b9f4f297276c F src/prepare.c 22df6171aec1d86904ed2ad30c2348a5748aa04e F src/printf.c a5f0ca08ddede803c241266abb46356ec748ded1 F src/random.c ba2679f80ec82c4190062d756f22d0c358180696 - F src/resolve.c 5c4d301a855d0245ddcc27365ddcbddd2f244665 -F src/resolve.c cca3aa77b95706df5d635a2141a4d1de60ae6598 ++F src/resolve.c d5516a3818748c50f98c18e4601a746e90929f1c F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac -F src/select.c f3c6e9065fb34f6a23af27ec7f1f717ffbfc2ee4 +F src/select.c 0115f5d222f5cf9b5511ec4072088417354d738a F src/shell.c 9351fc6de11e1d908648c0a92d85627138e3dee5 F src/sqlite.h.in c6e68a4a47610631822a4f8f83a44c9f75339331 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h 46f300b6e300e0fa916d7d58c44b53415b8471a9 - F src/sqliteInt.h a78e53083262e9a10fd1f09a8777755253c00b44 -F src/sqliteInt.h 49081ceab08eda9943d555aee57392c5b35d1c60 ++F src/sqliteInt.h 9a6af8787f03f54ce02ff88bd45f89bb600c3a4c F src/sqliteLimit.h c0373387c287c8d0932510b5547ecde31b5da247 F src/status.c 5b18f9526900f61189ab0b83f1ef41d9f871a2ab F src/table.c 5226df15ab9179b9ed558d89575ea0ce37b03fc9 @@@ -463,10 -463,10 +463,10 @@@ F src/vxworks.h d2988f4e5a61a4dfe82c652 F src/wal.c 02eeecc265f6ffd0597378f5d8ae9070b62a406a F src/wal.h 6dd221ed384afdc204bc61e25c23ef7fd5a511f2 F src/walker.c 0f142b5bd3ed2041fc52d773880748b212e63354 - F src/where.c e7054b2c1fe31fef5136e5735d7958f5c2c7707d -F src/where.c 9981707ac01438baea5caa0ca6108237be6630da -F src/whereInt.h e5b939701a7ceffc5a3a8188a37f9746416ebcd0 -F src/wherecode.c 99707d11907c71d289ee9553d2d1a22f1fd8ba41 -F src/whereexpr.c d7dcbf14ce1b5876c1f76496162c30fcba669563 ++F src/where.c 0b370db8ce08fac93a098f27eaf425d2269be376 +F src/whereInt.h 14dd243e13b81cbb0a66063d38b70f93a7d6e613 +F src/wherecode.c 3aff7683566af3428f865904aafa7efb1fbd8701 +F src/whereexpr.c b896f8ff6a53cbd3daaee84ec33e39098762bb46 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test a6d901b436328bd67a79b41bb0ac2663918fe3bd F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@@ -822,7 -822,7 +822,7 @@@ F test/hook.test 3b7b99d0eece6d279812c2 F test/icu.test 73956798bace8982909c00476b216714a6d0559a F test/ieee754.test 806fc0ce7f305f57e3331eaceeddcfec9339e607 F test/imposter1.test c3f1db2d3db2c24611a6596a3fc0ffc14f1466c8 - F test/in.test 41d18d4bcd27c55d0bc6b6ddc8ff9e85e91728a4 -F test/in.test 61d940ced6817bee66e4e0b09d5bc8608f57134b ++F test/in.test 20c5529986998949908f889c8208b2cd894b2cc9 F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75 F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0 F test/in4.test d2b38cba404bc4320f4fe1b595b3d163f212c068 @@@ -1017,9 -1017,6 +1017,9 @@@ F test/rollbackfault.test 0e646aeab8840 F test/rowallock.test 3f88ec6819489d0b2341c7a7528ae17c053ab7cc F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81 F test/rowid.test 5b7509f384f4f6fae1af3c8c104c8ca299fea18d +F test/rowvalue.test 979738b3d49f1d93e3fee56a71d4446217917abc +F test/rowvalue2.test 8d5dfe75b8f4d1868a2f91f0356f20d36cba64ff - F test/rowvalue3.test eeec47b4de27217a012dd142956b01af4e9bd6f2 ++F test/rowvalue3.test 587c1056016fa6b7a40a9bf6cb85d5443fa47d96 F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798 F test/run-wordcount.sh 891e89c4c2d16e629cd45951d4ed899ad12afc09 F test/savepoint.test c671fdbd34cd3bfe1518a777526ada595180cf8d @@@ -1510,7 -1507,7 +1510,7 @@@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a9 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 - P 061b8006034f06a0311b4304c8b14d2c8b0153df 483994a54dee3c7a3801e0e9d3c96fa9dbd8d2fd - R 675e1e72a3d3f117d790dda9dd43e7d1 -P 483994a54dee3c7a3801e0e9d3c96fa9dbd8d2fd -R d3646a4fd33e16c76415db60501a55b1 ++P d4f3d52c5a11fc7ad7e8cad76361edbcef13a12f 4d59df02d3713b3e3804e1a88e676749b2794286 ++R 1d3755c62e27d021f9887ac09a170360 U dan - Z b0c1b915de5ec6a4159f97e64d5655ae -Z 64999ea9da24ca9027e2e455a4d899cc ++Z 2549ddc5292b60c5848a8cde952880f9 diff --cc manifest.uuid index e9f6e44c64,83f63152b3..21c7478815 --- a/manifest.uuid +++ b/manifest.uuid @@@ -1,1 -1,1 +1,1 @@@ - d4f3d52c5a11fc7ad7e8cad76361edbcef13a12f -4d59df02d3713b3e3804e1a88e676749b2794286 ++719a3b2035a335ca8b9704646b1d641011e3ea0e diff --cc src/expr.c index f35ac56f80,ea52d66253..3c95136c5c --- a/src/expr.c +++ b/src/expr.c @@@ -2480,20 -2208,20 +2480,20 @@@ static void sqlite3ExprCodeIN }else{ /* If the LHS is NULL, then the result is either false or NULL depending -- ** on whether the RHS is empty or not, respectively. -- */ - if( nVector==1 && sqlite3ExprCanBeNull(pExpr->pLeft) ){ - if( sqlite3ExprCanBeNull(pExpr->pLeft) ){ -- if( destIfNull==destIfFalse ){ -- /* Shortcut for the common case where the false and NULL outcomes are -- ** the same. */ -- sqlite3VdbeAddOp2(v, OP_IsNull, r1, destIfNull); VdbeCoverage(v); -- }else{ -- int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); -- sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); -- VdbeCoverage(v); -- sqlite3VdbeGoto(v, destIfNull); -- sqlite3VdbeJumpHere(v, addr1); ++ ** on whether the RHS is empty or not, respectively. */ ++ if( destIfNull==destIfFalse ){ ++ for(i=0; ipLeft, i); ++ if( sqlite3ExprCanBeNull(p) ){ ++ sqlite3VdbeAddOp2(v, OP_IsNull, r1+aiMap[i], destIfNull); ++ } } ++ }else if( nVector==1 && sqlite3ExprCanBeNull(pExpr->pLeft) ){ ++ int addr1 = sqlite3VdbeAddOp1(v, OP_NotNull, r1); VdbeCoverage(v); ++ sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); ++ VdbeCoverage(v); ++ sqlite3VdbeGoto(v, destIfNull); ++ sqlite3VdbeJumpHere(v, addr1); } if( eType==IN_INDEX_ROWID ){ @@@ -2501,46 -2229,6 +2501,46 @@@ */ sqlite3VdbeAddOp3(v, OP_SeekRowid, pExpr->iTable, destIfFalse, r1); VdbeCoverage(v); - }else if( nVector>1 && eType==IN_INDEX_EPH ){ ++ }else if( nVector>1 && eType==IN_INDEX_EPH && destIfNull!=destIfFalse ){ + int regNull = sqlite3GetTempReg(pParse); + int r2 = sqlite3GetTempReg(pParse); + int r3 = sqlite3GetTempReg(pParse); + int r4 = sqlite3GetTempReg(pParse); + int addrNext; + int addrIf; + + if( destIfFalse!=destIfNull ){ + sqlite3VdbeAddOp2(v, OP_Integer, 0, regNull); + } + addrNext = sqlite3VdbeAddOp2(v, OP_Rewind, pExpr->iTable, destIfFalse); + for(i=0; iiTable, i, r2); + sqlite3VdbeAddOp4(v, OP_Eq, r1+i, i?r3:r4, r2, (void*)pColl,P4_COLLSEQ); + sqlite3VdbeChangeP5(v, SQLITE_STOREP2); + if( i!=0 ){ + sqlite3VdbeAddOp3(v, OP_And, r3, r4, r4); + } + } + addrIf = sqlite3VdbeAddOp1(v, OP_If, r4); + if( destIfNull!=destIfFalse ){ + sqlite3VdbeAddOp2(v, OP_IfNot, r4, sqlite3VdbeCurrentAddr(v)+2); + sqlite3VdbeAddOp2(v, OP_Integer, 1, regNull); + } + sqlite3VdbeAddOp2(v, OP_Next, pExpr->iTable, addrNext+1); + if( destIfNull!=destIfFalse ){ + sqlite3VdbeAddOp2(v, OP_If, regNull, destIfNull); + } + sqlite3VdbeAddOp2(v, OP_Goto, 0, destIfFalse); + sqlite3VdbeChangeP2(v, addrIf, sqlite3VdbeCurrentAddr(v)); + sqlite3ReleaseTempReg(pParse, regNull); + sqlite3ReleaseTempReg(pParse, r2); + sqlite3ReleaseTempReg(pParse, r3); + sqlite3ReleaseTempReg(pParse, r4); }else{ /* In this case, the RHS is an index b-tree. */ @@@ -3493,22 -3172,6 +3493,22 @@@ int sqlite3ExprCodeTarget(Parse *pParse break; } + case TK_VECTOR: { - sqlite3ErrorMsg(pParse, "invalid use of row value (1)"); ++ sqlite3ErrorMsg(pParse, "invalid use of row value"); + break; + } + + case TK_SELECT_COLUMN: { + Expr *pLeft = pExpr->pLeft; + assert( pLeft ); + assert( pLeft->op==TK_SELECT || pLeft->op==TK_REGISTER ); + if( pLeft->op==TK_SELECT ){ + pLeft->iTable = sqlite3CodeSubselect(pParse, pLeft, 0, 0); + pLeft->op = TK_REGISTER; + } + inReg = pLeft->iTable + pExpr->iColumn; + break; + } /* ** Form A: diff --cc src/resolve.c index cb9f2fbaa6,77ce37f6d7..4d8873963a --- a/src/resolve.c +++ b/src/resolve.c @@@ -765,17 -765,6 +765,10 @@@ static int resolveExprStep(Walker *pWal ExprSetProperty(pExpr, EP_VarSelect); pNC->ncFlags |= NC_VarSelect; } + + if( pExpr->op==TK_SELECT && pExpr->x.pSelect->pEList->nExpr>1 ){ - if( !ExprHasProperty(pExpr, EP_VectorOk) && 0 ){ - sqlite3ErrorMsg(pParse, "invalid use of row value"); - }else{ - ExprSetProperty(pExpr, EP_Vector); - } - } - if( pExpr->op==TK_IN ){ - ExprSetProperty(pExpr->pLeft, EP_VectorOk); ++ ExprSetProperty(pExpr, EP_Vector); + } } break; } @@@ -783,30 -772,6 +776,11 @@@ notValid(pParse, pNC, "parameters", NC_IsCheck|NC_PartIdx|NC_IdxExpr); break; } + - case TK_BETWEEN: { - ExprSetProperty(pExpr->pLeft, EP_VectorOk); - ExprSetProperty(pExpr->x.pList->a[0].pExpr, EP_VectorOk); - ExprSetProperty(pExpr->x.pList->a[1].pExpr, EP_VectorOk); - break; - } - - case TK_EQ: case TK_NE: case TK_IS: case TK_ISNOT: - case TK_LE: case TK_LT: case TK_GE: case TK_GT: - { - ExprSetProperty(pExpr->pLeft, EP_VectorOk); - ExprSetProperty(pExpr->pRight, EP_VectorOk); - break; - }; - + case TK_VECTOR: { - if( !ExprHasProperty(pExpr, EP_VectorOk) ){ - sqlite3ErrorMsg(pParse, "invalid use of row value"); - }else{ - ExprSetProperty(pExpr, EP_Vector); - } ++ ExprSetProperty(pExpr, EP_Vector); + break; + } } return (pParse->nErr || pParse->db->mallocFailed) ? WRC_Abort : WRC_Continue; } diff --cc src/sqliteInt.h index 1f653c08f8,879e6703ca..7219732bc3 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@@ -2327,8 -2327,6 +2327,7 @@@ struct Expr #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ #define EP_Alias 0x400000 /* Is an alias for a result set column */ - #define EP_VectorOk 0x800000 /* This expression may be a row value */ - #define EP_Vector 0x1000000/* This expression is a row value */ ++#define EP_Vector 0x800000 /* This expression is a row value */ /* ** Combinations of two or more EP_* flags diff --cc src/where.c index 095891842f,23ec21c160..6c039c6b7c --- a/src/where.c +++ b/src/where.c @@@ -3477,20 -3414,20 +3477,38 @@@ static i8 wherePathSatisfiesOrderBy rev = revSet = 0; distinctColumns = 0; for(j=0; ju.btree.nEq -- && pLoop->nSkip==0 -- && ((i = pLoop->aLTerm[j]->eOperator) & eqOpMask)!=0 -- ){ -- if( i & WO_ISNULL ){ -- testcase( isOrderDistinct ); -- isOrderDistinct = 0; ++ assert( j>=pLoop->u.btree.nEq ++ || (pLoop->aLTerm[j]==0)==(jnSkip) ++ ); ++ if( ju.btree.nEq && j>=pLoop->nSkip ){ ++ u16 eOp = pLoop->aLTerm[j]->eOperator; ++ ++ /* Skip over == and IS and ISNULL terms. (Also skip IN terms when ++ ** doing WHERE_ORDERBY_LIMIT processing). ++ ** ++ ** If the current term is a column of an ((?,?) IN (SELECT...)) ++ ** expression for which the SELECT returns more than one column, ++ ** check that it is the only column used by this loop. Otherwise, ++ ** if it is one of two or more, none of the columns can be ++ ** considered to match an ORDER BY term. */ ++ if( (eOp & eqOpMask)!=0 ){ ++ if( eOp & WO_ISNULL ){ ++ testcase( isOrderDistinct ); ++ isOrderDistinct = 0; ++ } ++ continue; ++ }else if( eOp & WO_IN ){ ++ Expr *pX = pLoop->aLTerm[j]->pExpr; ++ for(i=j+1; iu.btree.nEq; i++){ ++ if( pLoop->aLTerm[i]->pExpr==pX ){ ++ assert( (pLoop->aLTerm[i]->eOperator & WO_IN) ); ++ bOnce = 0; ++ break; ++ } ++ } } -- continue; } /* Get the column number in the table (iColumn) and sort order @@@ -3519,7 -3456,7 +3537,6 @@@ /* Find the ORDER BY term that corresponds to the j-th column ** of the index and mark that ORDER BY term off */ -- bOnce = 1; isMatch = 0; for(i=0; bOnce && i