aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/where.c18
-rw-r--r--src/whereInt.h1
-rw-r--r--src/wherecode.c35
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",