diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/where.c | 18 | ||||
-rw-r--r-- | src/whereInt.h | 1 | ||||
-rw-r--r-- | src/wherecode.c | 35 |
3 files changed, 52 insertions, 2 deletions
diff --git a/src/where.c b/src/where.c index 338501090..a5fab2cd5 100644 --- a/src/where.c +++ b/src/where.c @@ -5870,8 +5870,22 @@ 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)); + assert( pTab==pTabItem->pTab ); + pLevel->iRJMatch = pParse->nTab++; + if( HasRowid(pTab) ){ + KeyInfo *pInfo; + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pLevel->iRJMatch, 1); + pInfo = sqlite3KeyInfoAlloc(pParse->db, 1, 0); + if( pInfo ){ + pInfo->aColl[0] = 0; + pInfo->aSortFlags[0] = 0; + sqlite3VdbeAppendP4(v, pInfo, P4_KEYINFO); + } + }else{ + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + sqlite3VdbeAddOp2(v, OP_OpenEphemeral, pLevel->iRJMatch, pPk->nKeyCol); + sqlite3VdbeSetP4KeyInfo(pParse, pPk); + } } } pWInfo->iTop = sqlite3VdbeCurrentAddr(v); diff --git a/src/whereInt.h b/src/whereInt.h index e0f44d6ba..df62db4f1 100644 --- a/src/whereInt.h +++ b/src/whereInt.h @@ -75,6 +75,7 @@ struct WhereLevel { int addrLikeRep; /* LIKE range processing address */ #endif int regFilter; /* Bloom filter */ + int iRJMatch; /* Cursor or rowset used for matched RIGHT JOIN rows */ u8 iFrom; /* Which entry in the FROM clause */ u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */ int p1, p2; /* Operands of the opcode used to end the loop */ diff --git a/src/wherecode.c b/src/wherecode.c index 74873de09..5b8ed8934 100644 --- a/src/wherecode.c +++ b/src/wherecode.c @@ -2721,6 +2721,41 @@ Bitmask sqlite3WhereCodeOneLoopStart( } } + /* For a RIGHT OUTER JOIN, record the fact that the current row has + ** been matched at least once. + */ + if( pLevel->iRJMatch ){ + Table *pTab; + int nPk; + int r; + int jmp1 = 0; + + pTab = pWInfo->pTabList->a[pLevel->iFrom].pTab; + if( HasRowid(pTab) ){ + r = sqlite3GetTempRange(pParse, 2); + sqlite3ExprCodeGetColumnOfTable(v, pTab, pLevel->iTabCur, -1, r+1); + nPk = 1; + }else{ + int iPk; + Index *pPk = sqlite3PrimaryKeyIndex(pTab); + nPk = pPk->nKeyCol; + r = sqlite3GetTempRange(pParse, nPk+1); + for(iPk=0; iPk<nPk; iPk++){ + int iCol = pPk->aiColumn[iPk]; + sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, iCol,r+1+iPk); + } + } + jmp1 = sqlite3VdbeAddOp4Int(v, OP_Found, pLevel->iRJMatch, 0, r+1, nPk); + VdbeCoverage(v); + sqlite3VdbeAddOp3(v, OP_MakeRecord, r+1, nPk, r); + sqlite3VdbeAddOp4Int(v, OP_IdxInsert, pLevel->iRJMatch, r, r+1, nPk); + sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT); + sqlite3VdbeJumpHere(v, jmp1); + + /* Release the array of temp registers */ + sqlite3ReleaseTempRange(pParse, r, nPk+1); + } + #if WHERETRACE_ENABLED /* 0x20800 */ if( sqlite3WhereTrace & 0x20000 ){ sqlite3DebugPrintf("All WHERE-clause terms after coding level %d:\n", |