-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
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
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
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
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.
-5be5ede5cca1cd5ef863fe0feb2b4a990f4a42865281a6c2e4eb816f48847dc6
\ No newline at end of file
+0f6f61c3664cc87209c2a6f9b6df3a750d1510723fcde209c33db8feaf48bcf3
\ No newline at end of file
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;
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;
** 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;
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;
}
}
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);
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.
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);
}
}
}
return 1;
}
addWhereTerm(pParse, pSrc, iLeft, iLeftCol, i+1, iRightCol,
- isOuter, &p->pWhere);
+ joinType, &p->pWhere);
}
}
** 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;
}
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;
pWhere = pSub->pWhere;
pSub->pWhere = 0;
if( isLeftJoin>0 ){
- sqlite3SetJoinExpr(pWhere, iNewParent);
+ sqlite3SetJoinExpr(pWhere, iNewParent, EP_FromJoin);
}
if( pWhere ){
if( pParent->pWhere ){
#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 */
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
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));
}
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",
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);
}
}
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