diff options
-rw-r--r-- | manifest | 20 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/select.c | 33 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/where.c | 8 | ||||
-rw-r--r-- | src/whereexpr.c | 6 | ||||
-rw-r--r-- | test/join7.test | 11 |
7 files changed, 53 insertions, 31 deletions
@@ -1,5 +1,5 @@ -C Fix\ssome\scomments\sthat\srefer\sto\sLEFT\sJOIN\sthat\sshould\srefer\sto\sOUTER\sJOIN.\nNo\schanges\sto\scode. -D 2022-04-11T11:59:25.896 +C Make\sa\sdistinction\sbetween\s(1)\sWHERE\sclause\sconstraints,\s(2)\sON/USING\nconstraints\son\souter\sjoins,\sand\s(3)\sON/USING\sclause\sconstraints\son\sinner\njoins.\s\sFormerly,\sthere\swas\sno\sdistinctionb\sbetween\s1\sand\s3,\sbut\sRIGHT\sJOIN\nneeds\sto\sknow\sthe\sdifference.\s\sMake\sRIGHT\sJOIN\saware\sof\sthis\sdifference\sand\nadd\stest\scases. +D 2022-04-11T12:38:06.753 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -552,12 +552,12 @@ F src/printf.c 05d8dfd2018bc4fc3ddb8b37eb97ccef7abf985643fa1caebdcf2916ca90fa32 F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c F src/resolve.c 7110fc3b5a4dec5d11559141c1906c4a125349fb602f541b05db3a3d448d4b95 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92 -F src/select.c 178edb7fc4e6f5dabbd9c3755eb601151af78eaf69af73cc6bfe8195121c3d41 +F src/select.c 41d1b171d123a98bff4a2ddbe5ef7c47324274ca967030615506c4e246e96c12 F src/shell.c.in eb7f10d5e2c47bd014d92ec5db1def21fcc1ed56ffaaa4ee715b6c37c370b47f F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8 F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e -F src/sqliteInt.h 8a804f402410b06958bf6376daa91f11e2667ebd60e149eb5a371654a71ce448 +F src/sqliteInt.h fa220cb1b04ae45fa34de634efec4c04ce668ddcb6316c8f3260a8cf1a31310b F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657 F src/status.c 4a3da6d77eeb3531cb0dbdf7047772a2a1b99f98c69e90ce009c75fe6328b2c0 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -639,10 +639,10 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9 F src/wal.c b9df133a705093da8977da5eb202eaadb844839f1c7297c08d33471f5491843d F src/wal.h c3aa7825bfa2fe0d85bef2db94655f99870a285778baa36307c0a16da32b226a F src/walker.c f890a3298418d7cba3b69b8803594fdc484ea241206a8dfa99db6dd36f8cbb3b -F src/where.c e05c2c85a894d0175983241789344e48ed134f79bb84adda23a6bff53c39cf42 +F src/where.c 8d8e54e2e29ac503ac5824cac0d368a9a45b0a2a3f129b0f2d50a1e3a891c62f F src/whereInt.h ecf0d9fe3e35f2546e660c6389e56aedb6fd2434e31a0449b261ff55ebc6df2d F src/wherecode.c 808e94b66f1bf052cbb77665ba08625ba93fbb0c343fe0ecafdfdd264bf0c6c9 -F src/whereexpr.c d79dd55b6ad4d072c16838e9709d7b144c321e463ebd216de224821c06bc1fd3 +F src/whereexpr.c 174d4ad5be165c610c907abb779ef4a97974d22b84e1ce7898d2d9f6947249e5 F src/window.c 42a71595263dbd8ef8248218e4fc7d4b5ddccece52146ad48e079342d93f6f8f F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627 @@ -1146,7 +1146,7 @@ F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916 F test/join5.test 0d63c7e43b3160b9d4b93f196ef83b6efc7751b9edd0d18c53a46fbec7a49cfc F test/join6.test f809c025fa253f9e150c0e9afd4cef8813257bceeb6f46e04041228c9403cc2c -F test/join7.test 059f7ab42737fbd835dfc791354f1b182585566b540b013f3ed46bfa1e80ba42 +F test/join7.test 87f08f814012b4593a7b6021ebfbcc0d2c837045cad012a3a38e810182fe268a F test/journal1.test c7b768041b7f494471531e17abc2f4f5ebf9e5096984f43ed17c4eb80ba34497 F test/journal2.test 9dac6b4ba0ca79c3b21446bbae993a462c2397c4 F test/journal3.test 7c3cf23ffc77db06601c1fcfc9743de8441cb77db9d1aa931863d94f5ffa140e @@ -1946,8 +1946,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 29927926eb32acd963e2c496ad67d55177615ec4150fd218afaf2f9a730cabec -R 6a36a3a28fad2aa38e4b5d7c8bda927a +P 5be5ede5cca1cd5ef863fe0feb2b4a990f4a42865281a6c2e4eb816f48847dc6 +R 9c8f191b416653ff62ae70d11a61358b U drh -Z 390b95acc02a593d1c52fcc716321c1e +Z e1bd204470110fd5d9bea7467b9ac13a # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.uuid b/manifest.uuid index 11566ff6d..41dbfa450 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -5be5ede5cca1cd5ef863fe0feb2b4a990f4a42865281a6c2e4eb816f48847dc6
\ No newline at end of file +0f6f61c3664cc87209c2a6f9b6df3a750d1510723fcde209c33db8feaf48bcf3
\ No newline at end of file diff --git a/src/select.c b/src/select.c index 3e4f783a3..79ff500f4 100644 --- a/src/select.c +++ b/src/select.c @@ -373,7 +373,7 @@ static void addWhereTerm( int iColLeft, /* Index of column in first table */ int iRight, /* Index of second table in pSrc */ int iColRight, /* Index of column in second table */ - int isOuterJoin, /* True if this is an OUTER join */ + u32 joinType, /* EP_FromJoin or EP_InnerJoin */ Expr **ppWhere /* IN/OUT: The WHERE clause to add to */ ){ sqlite3 *db = pParse->db; @@ -393,8 +393,8 @@ static void addWhereTerm( assert( pE2!=0 || pEq==0 ); /* Due to db->mallocFailed test ** in sqlite3DbMallocRawNN() called from ** sqlite3PExpr(). */ - if( pEq && isOuterJoin ){ - ExprSetProperty(pEq, EP_FromJoin); + if( pEq ){ + ExprSetProperty(pEq, joinType); assert( !ExprHasProperty(pEq, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(pEq, EP_NoReduce); pEq->w.iJoin = pE2->iTable; @@ -428,9 +428,10 @@ static void addWhereTerm( ** after the t1 loop and rows with t1.x!=5 will never appear in ** the output, which is incorrect. */ -void sqlite3SetJoinExpr(Expr *p, int iTable){ +void sqlite3SetJoinExpr(Expr *p, int iTable, u32 joinFlag){ + assert( joinFlag==EP_FromJoin || joinFlag==EP_InnerJoin ); while( p ){ - ExprSetProperty(p, EP_FromJoin); + ExprSetProperty(p, joinFlag); assert( !ExprHasProperty(p, EP_TokenOnly|EP_Reduced) ); ExprSetVVAProperty(p, EP_NoReduce); p->w.iJoin = iTable; @@ -439,11 +440,11 @@ void sqlite3SetJoinExpr(Expr *p, int iTable){ if( p->x.pList ){ int i; for(i=0; i<p->x.pList->nExpr; i++){ - sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable); + sqlite3SetJoinExpr(p->x.pList->a[i].pExpr, iTable, joinFlag); } } } - sqlite3SetJoinExpr(p->pLeft, iTable); + sqlite3SetJoinExpr(p->pLeft, iTable, joinFlag); p = p->pRight; } } @@ -459,6 +460,7 @@ static void unsetJoinExpr(Expr *p, int iTable){ if( ExprHasProperty(p, EP_FromJoin) && (iTable<0 || p->w.iJoin==iTable) ){ ExprClearProperty(p, EP_FromJoin); + ExprSetProperty(p, EP_InnerJoin); } if( p->op==TK_COLUMN && p->iTable==iTable ){ ExprClearProperty(p, EP_CanBeNull); @@ -502,10 +504,10 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ pRight = &pLeft[1]; for(i=0; i<pSrc->nSrc-1; i++, pRight++, pLeft++){ Table *pRightTab = pRight->pTab; - int isOuter; + u32 joinType; if( NEVER(pLeft->pTab==0 || pRightTab==0) ) continue; - isOuter = (pRight->fg.jointype & JT_OUTER)!=0; + joinType = (pRight->fg.jointype & JT_OUTER)!=0 ? EP_FromJoin : EP_InnerJoin; /* When the NATURAL keyword is present, add WHERE clause terms for ** every column that the two tables have in common. @@ -525,7 +527,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ zName = pRightTab->aCol[j].zCnName; if( tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 1) ){ addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, j, - isOuter, &p->pWhere); + joinType, &p->pWhere); } } } @@ -556,7 +558,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ return 1; } addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol, - isOuter, &p->pWhere); + joinType, &p->pWhere); } } @@ -564,7 +566,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){ ** an AND operator. */ else if( pRight->u3.pOn ){ - if( isOuter ) sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor); + sqlite3SetJoinExpr(pRight->u3.pOn, pRight->iCursor, joinType); p->pWhere = sqlite3ExprAnd(pParse, p->pWhere, pRight->u3.pOn); pRight->u3.pOn = 0; } @@ -3724,8 +3726,9 @@ static Expr *substExpr( if( pSubst->isLeftJoin ){ ExprSetProperty(pNew, EP_CanBeNull); } - if( ExprHasProperty(pExpr,EP_FromJoin) ){ - sqlite3SetJoinExpr(pNew, pExpr->w.iJoin); + if( ExprHasProperty(pExpr,EP_FromJoin|EP_InnerJoin) ){ + sqlite3SetJoinExpr(pNew, pExpr->w.iJoin, + pExpr->flags & (EP_FromJoin|EP_InnerJoin)); } sqlite3ExprDelete(db, pExpr); pExpr = pNew; @@ -4452,7 +4455,7 @@ static int flattenSubquery( pWhere = pSub->pWhere; pSub->pWhere = 0; if( isLeftJoin>0 ){ - sqlite3SetJoinExpr(pWhere, iNewParent); + sqlite3SetJoinExpr(pWhere, iNewParent, EP_FromJoin); } if( pWhere ){ if( pParent->pWhere ){ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 7f8a8e015..b9eb970c7 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2887,7 +2887,7 @@ struct Expr { #define EP_ConstFunc 0x080000 /* A SQLITE_FUNC_CONSTANT or _SLOCHNG function */ #define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */ #define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */ - /* 0x400000 // Available */ +#define EP_InnerJoin 0x400000 /* Originates in ON/USING of an inner join */ #define EP_Leaf 0x800000 /* Expr.pLeft, .pRight, .u.pSelect all NULL */ #define EP_WinFunc 0x1000000 /* TK_FUNCTION with Expr.y.pWin set */ #define EP_Subrtn 0x2000000 /* Uses Expr.y.sub. TK_IN, _SELECT, or _EXISTS */ @@ -4829,7 +4829,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int); int sqlite3JoinType(Parse*, Token*, Token*, Token*); int sqlite3ColumnIndex(Table *pTab, const char *zCol); -void sqlite3SetJoinExpr(Expr*,int); +void sqlite3SetJoinExpr(Expr*,int,u32); void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int); void sqlite3DeferForeignKey(Parse*, int); #ifndef SQLITE_OMIT_AUTHORIZATION diff --git a/src/where.c b/src/where.c index 3fbe69e59..1cd8f4ded 100644 --- a/src/where.c +++ b/src/where.c @@ -6172,14 +6172,18 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){ WhereInfo *pSubWInfo; SrcList sFrom; Bitmask mAll = 0; - for(k=0; k<=i; k++){ + for(k=0; k<i; k++){ + int iIdxCur; mAll |= pWInfo->a[k].pWLoop->maskSelf; + iIdxCur = pWInfo->a[k].iIdxCur; + if( iIdxCur ) sqlite3VdbeAddOp1(v, OP_NullRow, iIdxCur); } + mAll |= pLoop->maskSelf; for(k=0; k<pWC->nTerm; k++){ WhereTerm *pTerm = &pWC->a[k]; if( pTerm->wtFlags & TERM_VIRTUAL ) break; if( pTerm->prereqAll & ~mAll ) continue; - if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) continue; + if( ExprHasProperty(pTerm->pExpr, EP_FromJoin|EP_InnerJoin) ) continue; pSubWhere = sqlite3ExprAnd(pParse, pSubWhere, sqlite3ExprDup(db, pTerm->pExpr, 0)); } diff --git a/src/whereexpr.c b/src/whereexpr.c index b622eed1b..90c344806 100644 --- a/src/whereexpr.c +++ b/src/whereexpr.c @@ -1809,6 +1809,7 @@ void sqlite3WhereTabFuncArgs( if( pArgs==0 ) return; for(j=k=0; j<pArgs->nExpr; j++){ Expr *pRhs; + u32 joinType; while( k<pTab->nCol && (pTab->aCol[k].colFlags & COLFLAG_HIDDEN)==0 ){k++;} if( k>=pTab->nCol ){ sqlite3ErrorMsg(pParse, "too many arguments on %s() - max %d", @@ -1826,8 +1827,11 @@ void sqlite3WhereTabFuncArgs( sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0); pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs); if( pItem->fg.jointype & (JT_LEFT|JT_LTORJ) ){ - sqlite3SetJoinExpr(pTerm, pItem->iCursor); + joinType = EP_FromJoin; + }else{ + joinType = EP_InnerJoin; } + sqlite3SetJoinExpr(pTerm, pItem->iCursor, joinType); whereClauseInsert(pWC, pTerm, TERM_DYNAMIC); } } diff --git a/test/join7.test b/test/join7.test index c1cd9ff6c..3b7d1f684 100644 --- a/test/join7.test +++ b/test/join7.test @@ -175,5 +175,16 @@ foreach {id schema} { 1 3 NULL NULL 1 4 NULL NULL } + do_execsql_test join7-$id.12 { + SELECT a, b, c, d + FROM t2 FULL OUTER JOIN t1 ON b=c AND d<=0 ORDER BY +b, +d; + } { + NULL NULL 3 33 + NULL NULL 4 44 + NULL NULL 5 55 + 1 2 NULL NULL + 1 3 NULL NULL + 1 4 NULL NULL + } } finish_test |