]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Preliminary code to support RIGHT JOIN. Everything seems to work, except that
authordrh <>
Fri, 8 Apr 2022 19:20:12 +0000 (19:20 +0000)
committerdrh <>
Fri, 8 Apr 2022 19:20:12 +0000 (19:20 +0000)
the code to compute the unmatched rows for the RIGHT JOIN has not yet been
added, so the result of a RIGHT JOIN is currently the same as an INNER JOIN.

FossilOrigin-Name: 415abd6731b8e8a605adabfa6066c8a852a8531c300df41325d5f7e75cae5a70

12 files changed:
manifest
manifest.uuid
src/build.c
src/resolve.c
src/select.c
src/sqliteInt.h
src/treeview.c
src/where.c
src/wherecode.c
src/whereexpr.c
test/join.test
test/vtab6.test

index 4dcfbdb9c9f8e5074b9ee24c0ab286636019aa5c..3f80acc376a8357a75891552621776c12dbdb16b 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Enhance\sthe\ssqlite_dbpage\sfix\sat\s[/info/642a0b4752743216|check-in\s642a0b4752743]\nfrom\sabout\sa\smonth\sago\ssuch\sthat\sit\sstill\stakes\sa\stransaction\son\sall\sattached\ndatabases,\sbut\sit\sonly\sstarts\sa\sread\stransaction\sfor\sread-only\soperations,\nrather\sthan\sstarting\sa\swrite\stransaction\sfor\severything.
-D 2022-04-08T17:01:29.519
+C Preliminary\scode\sto\ssupport\sRIGHT\sJOIN.\sEverything\sseems\sto\swork,\sexcept\sthat\nthe\scode\sto\scompute\sthe\sunmatched\srows\sfor\sthe\sRIGHT\sJOIN\shas\snot\syet\sbeen\nadded,\sso\sthe\sresult\sof\sa\sRIGHT\sJOIN\sis\scurrently\sthe\ssame\sas\san\sINNER\sJOIN.
+D 2022-04-08T19:20:12.051
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
@@ -495,7 +495,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6
 F src/btree.c 45161c2d5c9527b9c9bbfd7478daf3e0a619cf4bbe3278378aaea3d4b4e4f5b5
 F src/btree.h 74d64b8f28cfa4a894d14d4ed64fa432cd697b98b61708d4351482ae15913e22
 F src/btreeInt.h 8ce1332edd89dfd2461d561ac10a0ab5601c8e06200cb5230596c3caaf54482e
-F src/build.c ff119be98394a65bc8be7afc39d4a791a66f03a778d396de3ec456f5dfaf39e8
+F src/build.c 4a35acbeb5a73e5dfb0ed199a4ba601179cd22216654f9eb14c1dcfe993673e8
 F src/callback.c 4c19af69835787bfe790ac560f3071a824eb629f34e41f97b52ce5235c77de1c
 F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e
 F src/ctime.c 026dbdcdbd8c3cde98a88483ee88310ff43150ab164ad768f12cc700a11495ad
@@ -550,14 +550,14 @@ F src/pragma.h e690a356c18e98414d2e870ea791c1be1545a714ba623719deb63f7f226d8bb7
 F src/prepare.c fd940149c691684e7c1073c3787a7170e44852b02d1275d2e30a5b58e89cfcaf
 F src/printf.c 05d8dfd2018bc4fc3ddb8b37eb97ccef7abf985643fa1caebdcf2916ca90fa32
 F src/random.c 097dc8b31b8fba5a9aca1697aeb9fd82078ec91be734c16bffda620ced7ab83c
-F src/resolve.c 18d99e7146852d6064559561769fcca0743eb32b14a97da6dbed373a30ee0e76
+F src/resolve.c 7110fc3b5a4dec5d11559141c1906c4a125349fb602f541b05db3a3d448d4b95
 F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
-F src/select.c 7c106b3f36d483242b0a9c696614cd53d6f29e1ac81da6a3f0e9ea92f4211cc3
+F src/select.c cfa10564953f08eae09e0e92038b168403aade2879ba772cd5a47a08474da5fe
 F src/shell.c.in 1a8fbf932ecd582b1a5f66c1e8294f92c30d954616f5c7cc54c9623fcdbb028d
 F src/sqlite.h.in 2a35f62185eb5e7ecc64a2f68442b538ce9be74f80f28a00abc24837edcf1c17
 F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
 F src/sqlite3ext.h f49e28c25bd941e79794db5415fdf7b202deb3bc072ed6f1ed273d578703684e
-F src/sqliteInt.h 364699d46b6cd2fbcaedfb907cedd42c8ed6e32a671f7f72edb257cad861c40b
+F src/sqliteInt.h f8dc31c997573ac608a52bd98af91f21298d46b392732267aefa84b705be0e5c
 F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
 F src/status.c 4a3da6d77eeb3531cb0dbdf7047772a2a1b99f98c69e90ce009c75fe6328b2c0
 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
@@ -617,7 +617,7 @@ F src/test_window.c cdae419fdcea5bad6dcd9368c685abdad6deb59e9fc8b84b153de513d394
 F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
 F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
 F src/tokenize.c a38f52058b517929e264094abd0b5fd1e8e145a1aa43bc6f6a72ae5218f96c98
-F src/treeview.c 80a3d70bbc112399aa3cc7e777acc5d07c452e44c652630fc158d4594d86afd1
+F src/treeview.c d1401c129c980ace571f5071b91c349b8ad00bdb3d6f7112fb97a3da8bac85ff
 F src/trigger.c 372ada38f667c6823a3db15749eb668338e65c793394e55a37e56a489f2d1b55
 F src/update.c 2cfaded82ca80ff56afb8c3ae5e88284e0824bfd86119827cc22481959f96f92
 F src/upsert.c 8789047a8f0a601ea42fa0256d1ba3190c13746b6ba940fe2d25643a7e991937
@@ -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 a17d57807aa63dca4f3204d01db7a863bc0290bd7913928582236d65c9ad4212
+F src/where.c c752850f0d4b21656ef2901484fb7c799a6d20efe1d13fa5e77a3554b7568625
 F src/whereInt.h 15d2975c3b4c193c78c26674400a840da8647fe1777ae3b026e2d15937b38a03
-F src/wherecode.c 6292d7bf2d751b1ce68139a70e5468dd6615a9a9dab5b5e61c0053836723bb7a
-F src/whereexpr.c 612f58f5f6e3e3bb94d10e2c56672ade8bbf94d4a928d3edb4e84e2ed3c00dca
+F src/wherecode.c 7025f2a5b8b160af7ec4837e5d3c5befc2e61f0aafeea3f5f0403e46674f284f
+F src/whereexpr.c a4542ee72e05e4ab9dfadb5ddc0116007dc2420763992a79dbe83aaf73212311
 F src/window.c 42a71595263dbd8ef8248218e4fc7d4b5ddccece52146ad48e079342d93f6f8f
 F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
 F test/affinity2.test ce1aafc86e110685b324e9a763eab4f2a73f737842ec3b687bd965867de90627
@@ -1140,7 +1140,7 @@ F test/ioerr4.test f130fe9e71008577b342b8874d52984bd04ede2c
 F test/ioerr5.test 2edfa4fb0f896f733071303b42224df8bedd9da4
 F test/ioerr6.test a395a6ab144b26a9e3e21059a1ab6a7149cca65b
 F test/istrue.test e7f285bb70282625c258e866ce6337d4c762922f5a300e1b50f958aef6e7d9c9
-F test/join.test 85e9c88bf4700b45a48a6362cd47e0c0aefc572629827c31aa58a5978cabdfc5
+F test/join.test a1832675aa30f2b422ff934b553e30294ca899484710242a2119ebf21f20a66a
 F test/join2.test 9bdc615841b91c97a16d68bad9508aea11fa0c6b34e5689847bcc4dac70e4990
 F test/join3.test 6f0c774ff1ba0489e6c88a3e77b9d3528fb4fda0
 F test/join4.test 1a352e4e267114444c29266ce79e941af5885916
@@ -1711,7 +1711,7 @@ F test/vtab2.test 14d4ab26cee13ba6cf5c5601b158e4f57552d3b055cdd9406cf7f711e9c840
 F test/vtab3.test b45f47d20f225ccc9c28dc915d92740c2dee311e
 F test/vtab4.test 8e73ed268f3d596bc3590f45fc948fb40f28e9c3
 F test/vtab5.test 889f444970393c73f1e077e2bdc5d845e157a391
-F test/vtab6.test 7167e8e526bc2e719e7818e18b2fd7bb8c455fa018b74e611943a86782e10125
+F test/vtab6.test 5f5c10c694763d9cb438ec12aab7d6899f0bd6e2fa120551e11dea3daa8063ca
 F test/vtab7.test 70c6f4a1d6177144a8236e4172d5fba92e683440374664ad1f04851fbb335d3c
 F test/vtab8.test e19fa4a538fcd1bb66c22825fa8f71618fb13583
 F test/vtab9.test ea58d2b95d61955f87226381716b2d0b1d4e4f9b
@@ -1945,8 +1945,11 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
 F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
 F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
-P 48f2e5a1fbaa8ceb32e08066766be74233b0c67ab430bbf7adfdff42cdb7b8ec
-R 20c6686a28e5cb126a28d0c27a5e917b
+P 8efd61e8518594e3e9c84681fc35796a78fe8885a97ad4dd19f1573ee8065b18
+R 322c8c2f976fdab57b24f3e90a096129
+T *branch * right-join
+T *sym-right-join *
+T -sym-trunk *
 U drh
-Z 5fb2265312a791be3cfc50f876b63b0a
+Z 04b77679382a7e72969224c19421c972
 # Remove this line to create a well-formed Fossil manifest.
index 081aaf79398b5fc2355f65c75a7457e4dd78b802..9efedb98ec905e182232126c6c952529207808f4 100644 (file)
@@ -1 +1 @@
-8efd61e8518594e3e9c84681fc35796a78fe8885a97ad4dd19f1573ee8065b18
\ No newline at end of file
+415abd6731b8e8a605adabfa6066c8a852a8531c300df41325d5f7e75cae5a70
\ No newline at end of file
index da862fa70797ac6491e0bfda14601dd1f46a0d72..7181011c3291908ca6116614e071f1e572786170 100644 (file)
@@ -5071,10 +5071,22 @@ void sqlite3SrcListFuncArgs(Parse *pParse, SrcList *p, ExprList *pList){
 void sqlite3SrcListShiftJoinType(SrcList *p){
   if( p ){
     int i;
+    u8 allFlags = 0;
     for(i=p->nSrc-1; i>0; i--){
-      p->a[i].fg.jointype = p->a[i-1].fg.jointype;
+      allFlags |= p->a[i].fg.jointype = p->a[i-1].fg.jointype;
     }
     p->a[0].fg.jointype = 0;
+
+    /* All terms to the left of a RIGHT JOIN should be tagged with the
+    ** JT_LTORJ flags */
+    if( allFlags & JT_RIGHT ){
+      for(i=p->nSrc-1; ALWAYS(i>0) && (p->a[i].fg.jointype&JT_RIGHT)==0; i--){}
+      i--;
+      assert( i>=0 );
+      do{
+        p->a[i--].fg.jointype |= JT_LTORJ;
+      }while( i>=0 );
+    }
   }
 }
 
index 30785ca706ec6fafaf3bac243cdb85f099ac75df..ac00564daa03e3b3a39b2624916cdc6779234dd3 100644 (file)
@@ -367,9 +367,7 @@ static int lookupName(
         pExpr->iTable = pMatch->iCursor;
         assert( ExprUseYTab(pExpr) );
         pExpr->y.pTab = pMatch->pTab;
-        /* RIGHT JOIN not (yet) supported */
-        assert( (pMatch->fg.jointype & JT_RIGHT)==0 );
-        if( (pMatch->fg.jointype & JT_LEFT)!=0 ){
+        if( (pMatch->fg.jointype & (JT_LEFT|JT_LTORJ))!=0 ){
           ExprSetProperty(pExpr, EP_CanBeNull);
         }
         pSchema = pExpr->y.pTab->pSchema;
index 7ac23bd388929aa7a11949c9870ae08b44227fe8..b9321aece7fd939ec224e1ef1d65406882539097 100644 (file)
@@ -301,10 +301,6 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
     sqlite3ErrorMsg(pParse, "unknown or unsupported join type: "
        "%T%s%T%s%T", pA, zSp1, pB, zSp2, pC);
     jointype = JT_INNER;
-  }else if( (jointype & JT_RIGHT)!=0 ){
-    sqlite3ErrorMsg(pParse, 
-      "RIGHT and FULL OUTER JOINs are not currently supported");
-    jointype = JT_INNER;
   }
   return jointype;
 }
@@ -6589,7 +6585,7 @@ int sqlite3Select(
      && i==0
      && (p->selFlags & SF_ComplexResult)!=0
      && (pTabList->nSrc==1
-         || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)
+         || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0)
     ){
       continue;
     }
@@ -6741,8 +6737,8 @@ int sqlite3Select(
     */
     if( i==0
      && (pTabList->nSrc==1
-            || (pTabList->a[1].fg.jointype&(JT_LEFT|JT_CROSS))!=0)  /* (1) */
-     && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes)  /* (2) */
+            || (pTabList->a[1].fg.jointype&(JT_OUTER|JT_CROSS))!=0)  /* (1) */
+     && (pItem->fg.isCte==0 || pItem->u2.pCteUse->eM10d!=M10d_Yes)   /* (2) */
     ){
       /* Implement a co-routine that will return a single row of the result
       ** set on each invocation.
index ead20c9a2fa20bb502810e2c04a3a3ee621ecf6d..264a9d37317c133f4abae06f9fa3f7397d798ad5 100644 (file)
@@ -3132,13 +3132,14 @@ struct SrcList {
 /*
 ** Permitted values of the SrcList.a.jointype field
 */
-#define JT_INNER     0x0001    /* Any kind of inner or cross join */
-#define JT_CROSS     0x0002    /* Explicit use of the CROSS keyword */
-#define JT_NATURAL   0x0004    /* True for a "natural" join */
-#define JT_LEFT      0x0008    /* Left outer join */
-#define JT_RIGHT     0x0010    /* Right outer join */
-#define JT_OUTER     0x0020    /* The "OUTER" keyword is present */
-#define JT_ERROR     0x0040    /* unknown or unsupported join type */
+#define JT_INNER     0x01    /* Any kind of inner or cross join */
+#define JT_CROSS     0x02    /* Explicit use of the CROSS keyword */
+#define JT_NATURAL   0x04    /* True for a "natural" join */
+#define JT_LEFT      0x08    /* Left outer join */
+#define JT_RIGHT     0x10    /* Right outer join */
+#define JT_OUTER     0x20    /* The "OUTER" keyword is present */
+#define JT_LTORJ     0x40    /* One of the LEFT operands of a RIGHT JOIN */
+#define JT_ERROR     0x80    /* unknown or unsupported join type */
 
 
 /*
index 91aff8ddf1b47bf9832ac2a881f3d33f02882969..f32064cd8efa48103618e8ac88fca58d2edddcb4 100644 (file)
@@ -144,8 +144,12 @@ void sqlite3TreeViewSrcList(TreeView *pView, const SrcList *pSrc){
       sqlite3_str_appendf(&x, " tab=%Q nCol=%d ptr=%p used=%llx",
            pItem->pTab->zName, pItem->pTab->nCol, pItem->pTab, pItem->colUsed);
     }
-    if( pItem->fg.jointype & JT_LEFT ){
+    if( (pItem->fg.jointype & (JT_LEFT|JT_RIGHT))==(JT_LEFT|JT_RIGHT) ){
+      sqlite3_str_appendf(&x, " FULL-OUTER-JOIN");
+    }else if( pItem->fg.jointype & JT_LEFT ){
       sqlite3_str_appendf(&x, " LEFT-JOIN");
+    }else if( pItem->fg.jointype & JT_RIGHT ){
+      sqlite3_str_appendf(&x, " RIGHT-JOIN");
     }else if( pItem->fg.jointype & JT_CROSS ){
       sqlite3_str_appendf(&x, " CROSS-JOIN");
     }
index f08c350b067d96c64eb2a9d5e2b5a7282e7cc9e6..60e314e7581369c601ce39eb884d06f419cba379 100644 (file)
@@ -732,13 +732,13 @@ static int termCanDriveIndex(
   char aff;
   if( pTerm->leftCursor!=pSrc->iCursor ) return 0;
   if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) return 0;
-  if( (pSrc->fg.jointype & JT_LEFT) 
+  if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ))!=0
    && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
    && (pTerm->eOperator & WO_IS)
   ){
     /* Cannot use an IS term from the WHERE clause as an index driver for
-    ** the RHS of a LEFT JOIN. Such a term can only be used if it is from
-    ** the ON clause.  */
+    ** the RHS of a LEFT JOIN or for the LHS of a RIGHT JOIN. Such a term
+    ** can only be used if it is from the ON clause.  */
     return 0;
   }
   if( (pTerm->prereqRight & notReady)!=0 ) return 0;
@@ -808,7 +808,8 @@ static SQLITE_NOINLINE void constructAutomaticIndex(
     ** WHERE clause (or the ON clause of a LEFT join) that constrain which
     ** rows of the target table (pSrc) that can be used. */
     if( (pTerm->wtFlags & TERM_VIRTUAL)==0
-     && ((pSrc->fg.jointype&JT_LEFT)==0 || ExprHasProperty(pExpr,EP_FromJoin))
+     && ((pSrc->fg.jointype&(JT_LEFT|JT_LTORJ))==0
+               || ExprHasProperty(pExpr,EP_FromJoin))
      && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor)
     ){
       pPartial = sqlite3ExprAnd(pParse, pPartial,
@@ -1081,7 +1082,7 @@ static SQLITE_NOINLINE void sqlite3ConstructBloomFilter(
       const SrcItem *pTabItem;
       pLevel = &pWInfo->a[iLevel];
       pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
-      if( pTabItem->fg.jointype & JT_LEFT ) continue;
+      if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ) ) continue;
       pLoop = pLevel->pWLoop;
       if( NEVER(pLoop==0) ) continue;
       if( pLoop->prereq & notReady ) continue;
@@ -1154,9 +1155,10 @@ static sqlite3_index_info *allocateIndexInfo(
     assert( pTerm->u.x.leftColumn<pTab->nCol );
 
     /* tag-20191211-002: WHERE-clause constraints are not useful to the
-    ** right-hand table of a LEFT JOIN.  See tag-20191211-001 for the
+    ** right-hand table of a LEFT JOIN nor to the left-hand table of a
+    ** RIGHT JOIN.  See tag-20191211-001 for the
     ** equivalent restriction for ordinary tables. */
-    if( (pSrc->fg.jointype & JT_LEFT)!=0
+    if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ))!=0
      && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
     ){
       continue;
@@ -2600,10 +2602,11 @@ static void whereLoopOutputAdjust(
         **
         ** 2022-03-24:  Self-culling only applies if either the extra terms
         ** are straight comparison operators that are non-true with NULL
-        ** operand, or if the loop is not a LEFT JOIN.
+        ** operand, or if the loop is not an OUTER JOIN.
         */
         if( (pTerm->eOperator & 0x3f)!=0
-         || (pWC->pWInfo->pTabList->a[pLoop->iTab].fg.jointype & JT_LEFT)==0
+         || (pWC->pWInfo->pTabList->a[pLoop->iTab].fg.jointype
+                  & (JT_LEFT|JT_LTORJ))==0
         ){
           pLoop->wsFlags |= WHERE_SELFCULL;
         }
@@ -2810,9 +2813,10 @@ static int whereLoopAddBtreeIndex(
     if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
 
     /* tag-20191211-001:  Do not allow constraints from the WHERE clause to
-    ** be used by the right table of a LEFT JOIN.  Only constraints in the
+    ** be used by the right table of a LEFT JOIN nor by the left table of a
+    ** RIGHT JOIN.  Only constraints in the
     ** ON clause are allowed.  See tag-20191211-002 for the vtab equivalent. */
-    if( (pSrc->fg.jointype & JT_LEFT)!=0
+    if( (pSrc->fg.jointype & (JT_LEFT|JT_LTORJ))!=0
      && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
     ){
       continue;
@@ -4114,9 +4118,9 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
     pNew->iTab = iTab;
     pBuilder->iPlanLimit += SQLITE_QUERY_PLANNER_LIMIT_INCR;
     pNew->maskSelf = sqlite3WhereGetMask(&pWInfo->sMaskSet, pItem->iCursor);
-    if( (pItem->fg.jointype & (JT_LEFT|JT_CROSS))!=0 ){
+    if( (pItem->fg.jointype & (JT_OUTER|JT_CROSS))!=0 ){
       /* This condition is true when pItem is the FROM clause term on the
-      ** right-hand-side of a LEFT or CROSS JOIN.  */
+      ** right-hand-side of a OUTER or CROSS JOIN.  */
       mPrereq = mPrior;
     }else{
       mPrereq = 0;
@@ -4125,7 +4129,7 @@ static int whereLoopAddAll(WhereLoopBuilder *pBuilder){
     if( IsVirtual(pItem->pTab) ){
       SrcItem *p;
       for(p=&pItem[1]; p<pEnd; p++){
-        if( mUnusable || (p->fg.jointype & (JT_LEFT|JT_CROSS)) ){
+        if( mUnusable || (p->fg.jointype & (JT_OUTER|JT_CROSS)) ){
           mUnusable |= sqlite3WhereGetMask(&pWInfo->sMaskSet, p->iCursor);
         }
       }
@@ -5844,6 +5848,10 @@ WhereInfo *sqlite3WhereBegin(
       }
     }
     if( iDb>=0 ) sqlite3CodeVerifySchema(pParse, iDb);
+    if( pTabItem->fg.jointype & JT_RIGHT ){
+      VdbeModuleComment((v, "TO-DO: Setup for the RIGHT JOIN of %s",
+                         pTab->zName));
+    }
   }
   pWInfo->iTop = sqlite3VdbeCurrentAddr(v);
   if( db->mallocFailed ) goto whereBeginError;
@@ -6091,11 +6099,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
                      pWInfo->pTabList->a[pLevel->iFrom].pTab->zName));
   }
 
-  /* The "break" point is here, just past the end of the outer loop.
-  ** Set it.
-  */
-  sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
-
   assert( pWInfo->nLevel<=pTabList->nSrc );
   for(i=0, pLevel=pWInfo->a; i<pWInfo->nLevel; i++, pLevel++){
     int k, last;
@@ -6106,6 +6109,16 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
     assert( pTab!=0 );
     pLoop = pLevel->pWLoop;
 
+    /* Do RIGHT JOIN processing.  Generate code that will output the
+    ** unmatched rows of the right operand of the RIGHT JOIN with
+    ** all of the columns of the left operand set to NULL.
+    */
+    if( pTabItem->fg.jointype & JT_RIGHT ){
+      VdbeModuleComment((v, "TO-DO: RIGHT JOIN post-processing for %s",
+                            pTab->zName));
+
+    }
+
     /* For a co-routine, change all OP_Column references to the table of
     ** the co-routine into OP_Copy of result contained in a register.
     ** OP_Rowid becomes OP_Null.
@@ -6117,29 +6130,6 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
       continue;
     }
 
-#ifdef SQLITE_ENABLE_EARLY_CURSOR_CLOSE
-    /* Close all of the cursors that were opened by sqlite3WhereBegin.
-    ** Except, do not close cursors that will be reused by the OR optimization
-    ** (WHERE_OR_SUBCLAUSE).  And do not close the OP_OpenWrite cursors
-    ** created for the ONEPASS optimization.
-    */
-    if( (pTab->tabFlags & TF_Ephemeral)==0
-     && !IsView(pTab)
-     && (pWInfo->wctrlFlags & WHERE_OR_SUBCLAUSE)==0
-    ){
-      int ws = pLoop->wsFlags;
-      if( pWInfo->eOnePass==ONEPASS_OFF && (ws & WHERE_IDX_ONLY)==0 ){
-        sqlite3VdbeAddOp1(v, OP_Close, pTabItem->iCursor);
-      }
-      if( (ws & WHERE_INDEXED)!=0
-       && (ws & (WHERE_IPK|WHERE_AUTO_INDEX))==0 
-       && pLevel->iIdxCur!=pWInfo->aiCurOnePass[1]
-      ){
-        sqlite3VdbeAddOp1(v, OP_Close, pLevel->iIdxCur);
-      }
-    }
-#endif
-
     /* If this scan uses an index, make VDBE code substitutions to read data
     ** from the index instead of from the table where possible.  In some cases
     ** this optimization prevents the table from ever being read, which can
@@ -6240,6 +6230,11 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
     }
   }
 
+  /* The "break" point is here, just past the end of the outer loop.
+  ** Set it.
+  */
+  sqlite3VdbeResolveLabel(v, pWInfo->iBreak);
+
   /* Final cleanup
   */
   if( pWInfo->pExprMods ) whereUndoExprMods(pWInfo);
index bab514a693f13502c26584fc897511f930910e5d..d349a940246e5a1893120f74f01c2f45407dcb43 100644 (file)
@@ -2604,7 +2604,9 @@ Bitmask sqlite3WhereCodeOneLoopStart(
       }
       pE = pTerm->pExpr;
       assert( pE!=0 );
-      if( (pTabItem->fg.jointype&JT_LEFT) && !ExprHasProperty(pE,EP_FromJoin) ){
+      if( (pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ))
+       && !ExprHasProperty(pE,EP_FromJoin)
+      ){
         continue;
       }
       
@@ -2666,7 +2668,7 @@ Bitmask sqlite3WhereCodeOneLoopStart(
     if( (pTerm->eOperator & (WO_EQ|WO_IS))==0 ) continue;
     if( (pTerm->eOperator & WO_EQUIV)==0 ) continue;
     if( pTerm->leftCursor!=iCur ) continue;
-    if( pTabItem->fg.jointype & JT_LEFT ) continue;
+    if( pTabItem->fg.jointype & (JT_LEFT|JT_LTORJ) ) continue;
     pE = pTerm->pExpr;
 #ifdef WHERETRACE_ENABLED /* 0x800 */
     if( sqlite3WhereTrace & 0x800 ){
index 26a521fffd8c6d595f64cccbe3fbc1d8d3a12e8a..b74164d1f50714e31e08c488d3b02cf5158dd3d8 100644 (file)
@@ -1831,7 +1831,7 @@ void sqlite3WhereTabFuncArgs(
     pRhs = sqlite3PExpr(pParse, TK_UPLUS, 
         sqlite3ExprDup(pParse->db, pArgs->a[j].pExpr, 0), 0);
     pTerm = sqlite3PExpr(pParse, TK_EQ, pColRef, pRhs);
-    if( pItem->fg.jointype & JT_LEFT ){
+    if( pItem->fg.jointype & (JT_LEFT|JT_LTORJ) ){
       sqlite3SetJoinExpr(pTerm, pItem->iCursor);
     }
     whereClauseInsert(pWC, pTerm, TERM_DYNAMIC);
index f48a1a149d4af749783acc14618d61f60be04d5f..fdacfc25c2687e0820acdeb0c4a382d55146bd60 100644 (file)
@@ -272,11 +272,13 @@ do_test join-2.2 {
     SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1;
   }
 } {1 2 3 {} 2 3 4 1 3 4 5 2}
-do_test join-2.3 {
-  catchsql {
-    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
-  }
-} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
+
+#do_test join-2.3 {
+#  catchsql {
+#    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
+#  }
+#} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
+
 do_test join-2.4 {
   execsql {
     SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d
index ab52c9f15c23949d618f6beaa99e6f9d4cea9c40..d8016e02f4e0e263893ab28397935acf861dba78 100644 (file)
@@ -223,11 +223,11 @@ do_test vtab6-2.2 {
     SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1;
   }
 } {1 2 3 {} 2 3 4 1 3 4 5 2}
-do_test vtab6-2.3 {
-  catchsql {
-    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
-  }
-} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
+#do_test vtab6-2.3 {
+#  catchsql {
+#    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
+#  }
+#} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
 do_test vtab6-2.4 {
   execsql {
     SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d