The unified diff between revisions [5587f68e..] and [95cbeaa8..] is displayed below. It can also be downloaded as a raw diff.

This diff has been restricted to the following files: 'sqlite/select.c'

#
#
# patch "sqlite/select.c"
#  from [9ef1dddd436e1ea86a6bf64ae0ed71bf4a0b894f]
#    to [034c7f7447b8711f85bef578a437ea12ca7cac53]
#
============================================================
--- sqlite/select.c	9ef1dddd436e1ea86a6bf64ae0ed71bf4a0b894f
+++ sqlite/select.c	034c7f7447b8711f85bef578a437ea12ca7cac53
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.269 2005/09/12 23:03:17 drh Exp $
+** $Id: select.c,v 1.276 2005/09/20 18:13:24 drh Exp $
 */
 #include "sqliteInt.h"

@@ -179,6 +179,7 @@ static void addWhereTerm(
   const char *zAlias1,     /* Alias for first table.  May be NULL */
   const Table *pTab2,      /* Second table */
   const char *zAlias2,     /* Alias for second table.  May be NULL */
+  int iRightJoinTable,     /* VDBE cursor for the right table */
   Expr **ppExpr            /* Add the equality term to this expression */
 ){
   Expr *pE1a, *pE1b, *pE1c;
@@ -199,11 +200,14 @@ static void addWhereTerm(
   pE2c = sqlite3Expr(TK_DOT, pE2b, pE2a, 0);
   pE = sqlite3Expr(TK_EQ, pE1c, pE2c, 0);
   ExprSetProperty(pE, EP_FromJoin);
+  pE->iRightJoinTable = iRightJoinTable;
   *ppExpr = sqlite3ExprAnd(*ppExpr, pE);
 }

 /*
 ** Set the EP_FromJoin property on all terms of the given expression.
+** And set the Expr.iRightJoinTable to iTable for every term in the
+** expression.
 **
 ** The EP_FromJoin property is used on terms of an expression to tell
 ** the LEFT OUTER JOIN processing logic that this term is part of the
@@ -211,11 +215,26 @@ static void addWhereTerm(
 ** of the more general WHERE clause.  These terms are moved over to the
 ** WHERE clause during join processing but we need to remember that they
 ** originated in the ON or USING clause.
+**
+** The Expr.iRightJoinTable tells the WHERE clause processing that the
+** expression depends on table iRightJoinTable even if that table is not
+** explicitly mentioned in the expression.  That information is needed
+** for cases like this:
+**
+**    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.b AND t1.x=5
+**
+** The where clause needs to defer the handling of the t1.x=5
+** term until after the t2 loop of the join.  In that way, a
+** NULL t2 row will be inserted whenever t1.x!=5.  If we do not
+** defer the handling of t1.x=5, it will be processed immediately
+** after the t1 loop and rows with t1.x!=5 will never appear in
+** the output, which is incorrect.
 */
-static void setJoinExpr(Expr *p){
+static void setJoinExpr(Expr *p, int iTable){
   while( p ){
     ExprSetProperty(p, EP_FromJoin);
-    setJoinExpr(p->pLeft);
+    p->iRightJoinTable = iTable;
+    setJoinExpr(p->pLeft, iTable);
     p = p->pRight;
   }
 }
@@ -262,7 +281,9 @@ static int sqliteProcessJoin(Parse *pPar
         char *zName = pLeftTab->aCol[j].zName;
         if( columnIndex(pRightTab, zName)>=0 ){
           addWhereTerm(zName, pLeftTab, pLeft->zAlias,
-                              pRightTab, pRight->zAlias, &p->pWhere);
+                              pRightTab, pRight->zAlias,
+                              pRight->iCursor, &p->pWhere);
+
         }
       }
     }
@@ -279,7 +300,7 @@ static int sqliteProcessJoin(Parse *pPar
     ** an AND operator.
     */
     if( pLeft->pOn ){
-      setJoinExpr(pLeft->pOn);
+      setJoinExpr(pLeft->pOn, pRight->iCursor);
       p->pWhere = sqlite3ExprAnd(p->pWhere, pLeft->pOn);
       pLeft->pOn = 0;
     }
@@ -301,7 +322,8 @@ static int sqliteProcessJoin(Parse *pPar
           return 1;
         }
         addWhereTerm(zName, pLeftTab, pLeft->zAlias,
-                            pRightTab, pRight->zAlias, &p->pWhere);
+                            pRightTab, pRight->zAlias,
+                            pRight->iCursor, &p->pWhere);
       }
     }
   }
@@ -521,7 +543,7 @@ static int selectInnerLoop(
         sqlite3VdbeOp3(v, OP_MakeRecord, 1, 0, &aff, 1);
         sqlite3VdbeAddOp(v, OP_IdxInsert, (iParm&0x0000FFFF), 0);
       }
-      sqlite3VdbeChangeP2(v, addr2, sqlite3VdbeCurrentAddr(v));
+      sqlite3VdbeJumpHere(v, addr2);
       break;
     }

@@ -1571,6 +1593,7 @@ static int multiSelect(
       }
       p->pPrior = 0;
       p->pOrderBy = 0;
+      p->disallowOrderBy = pOrderBy!=0;
       pLimit = p->pLimit;
       p->pLimit = 0;
       pOffset = p->pOffset;
@@ -1786,6 +1809,7 @@ static int multiSelect(
       assert( p->addrOpenVirt[2]>=0 );
       addr = p->addrOpenVirt[2];
       sqlite3VdbeChangeP2(v, addr, p->pEList->nExpr+2);
+      pKeyInfo->nField = pOrderBy->nExpr;
       sqlite3VdbeChangeP3(v, addr, (char*)pKeyInfo, P3_KEYINFO_HANDOFF);
       pKeyInfo = 0;
       generateSortTail(pParse, p, v, p->pEList->nExpr, eDest, iParm);
@@ -1970,7 +1994,7 @@ static int flattenSubquery(
      return 0;
   }
   if( p->isDistinct && subqueryIsAgg ) return 0;
-  if( p->pOrderBy && pSub->pOrderBy ) return 0;
+  if( (p->disallowOrderBy || p->pOrderBy) && pSub->pOrderBy ) return 0;

   /* Restriction 3:  If the subquery is a join, make sure the subquery is
   ** not used as the right operand of an outer join.  Examples of why this
@@ -2424,17 +2448,15 @@ static void resetAccumulator(Parse *pPar
 static void resetAccumulator(Parse *pParse, AggInfo *pAggInfo){
   Vdbe *v = pParse->pVdbe;
   int i;
-  int addr;
   struct AggInfo_func *pFunc;
   if( pAggInfo->nFunc+pAggInfo->nColumn==0 ){
     return;
   }
-  sqlite3VdbeAddOp(v, OP_Null, 0, 0);
   for(i=0; i<pAggInfo->nColumn; i++){
-    addr = sqlite3VdbeAddOp(v, OP_MemStore, pAggInfo->aCol[i].iMem, 0);
+    sqlite3VdbeAddOp(v, OP_MemNull, pAggInfo->aCol[i].iMem, 0);
   }
   for(pFunc=pAggInfo->aFunc, i=0; i<pAggInfo->nFunc; i++, pFunc++){
-    addr = sqlite3VdbeAddOp(v, OP_MemStore, pFunc->iMem, 0);
+    sqlite3VdbeAddOp(v, OP_MemNull, pFunc->iMem, 0);
     if( pFunc->iDistinct>=0 ){
       Expr *pE = pFunc->pExpr;
       if( pE->pList==0 || pE->pList->nExpr!=1 ){
@@ -2448,7 +2470,6 @@ static void resetAccumulator(Parse *pPar
       }
     }
   }
-  sqlite3VdbeChangeP2(v, addr, 1);
 }

 /*
@@ -2762,9 +2783,10 @@ int sqlite3Select(

   /* Initialize the memory cell to NULL for SRT_Mem or 0 for SRT_Exists
   */
-  if( eDest==SRT_Mem || eDest==SRT_Exists ){
-    sqlite3VdbeAddOp(v, eDest==SRT_Mem ? OP_Null : OP_Integer, 0, 0);
-    sqlite3VdbeAddOp(v, OP_MemStore, iParm, 1);
+  if( eDest==SRT_Mem ){
+    sqlite3VdbeAddOp(v, OP_MemNull, iParm, 0);
+  }else if( eDest==SRT_Exists ){
+    sqlite3VdbeAddOp(v, OP_MemInt, 0, iParm);
   }

   /* Open a virtual index to use for the distinct set.
@@ -2828,6 +2850,7 @@ int sqlite3Select(
     int addrProcessRow;     /* Code to process a single input row */
     int addrEnd;            /* End of all processing */
     int addrSortingIdx;     /* The OP_OpenVirtual for the sorting index */
+    int addrReset;          /* Subroutine for resetting the accumulator */

     addrEnd = sqlite3VdbeMakeLabel(v);

@@ -2891,11 +2914,10 @@ int sqlite3Select(
       pParse->nMem += pGroupBy->nExpr;
       iBMem = pParse->nMem;
       pParse->nMem += pGroupBy->nExpr;
-      sqlite3VdbeAddOp(v, OP_Integer, 0, 0);
-      sqlite3VdbeAddOp(v, OP_MemStore, iAbortFlag, 0);
-      sqlite3VdbeAddOp(v, OP_MemStore, iUseFlag, 1);
-      sqlite3VdbeAddOp(v, OP_Null, 0, 0);
-      sqlite3VdbeAddOp(v, OP_MemStore, iAMem, 1);
+      sqlite3VdbeAddOp(v, OP_MemInt, 0, iAbortFlag);
+      VdbeComment((v, "# clear abort flag"));
+      sqlite3VdbeAddOp(v, OP_MemInt, 0, iUseFlag);
+      VdbeComment((v, "# indicate accumulator empty"));
       sqlite3VdbeAddOp(v, OP_Goto, 0, addrInitializeLoop);

       /* Generate a subroutine that outputs a single row of the result
@@ -2906,10 +2928,12 @@ int sqlite3Select(
       ** order to signal the caller to abort.
       */
       addrSetAbort = sqlite3VdbeCurrentAddr(v);
-      sqlite3VdbeAddOp(v, OP_MemIncr, iAbortFlag, 0);
+      sqlite3VdbeAddOp(v, OP_MemInt, 1, iAbortFlag);
+      VdbeComment((v, "# set abort flag"));
       sqlite3VdbeAddOp(v, OP_Return, 0, 0);
       addrOutputRow = sqlite3VdbeCurrentAddr(v);
       sqlite3VdbeAddOp(v, OP_IfMemPos, iUseFlag, addrOutputRow+2);
+      VdbeComment((v, "# Groupby result generator entry point"));
       sqlite3VdbeAddOp(v, OP_Return, 0, 0);
       finalizeAggFunctions(pParse, &sAggInfo);
       if( pHaving ){
@@ -2922,13 +2946,21 @@ int sqlite3Select(
         goto select_end;
       }
       sqlite3VdbeAddOp(v, OP_Return, 0, 0);
+      VdbeComment((v, "# end groupby result generator"));

+      /* Generate a subroutine that will reset the group-by accumulator
+      */
+      addrReset = sqlite3VdbeCurrentAddr(v);
+      resetAccumulator(pParse, &sAggInfo);
+      sqlite3VdbeAddOp(v, OP_Return, 0, 0);
+
       /* Begin a loop that will extract all source rows in GROUP BY order.
       ** This might involve two separate loops with an OP_Sort in between, or
       ** it might be a single loop that uses an index to extract information
       ** in the right order to begin with.
       */
       sqlite3VdbeResolveLabel(v, addrInitializeLoop);
+      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset);
       pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pGroupBy);
       if( pWInfo==0 ) goto select_end;
       if( pGroupBy==0 ){
@@ -2962,6 +2994,7 @@ int sqlite3Select(
         sqlite3VdbeAddOp(v, OP_IdxInsert, sAggInfo.sortingIdx, 0);
         sqlite3WhereEnd(pWInfo);
         sqlite3VdbeAddOp(v, OP_Sort, sAggInfo.sortingIdx, addrEnd);
+        VdbeComment((v, "# GROUP BY sort"));
         sAggInfo.useSortingIdx = 1;
       }

@@ -2986,9 +3019,9 @@ int sqlite3Select(
         }
         sqlite3VdbeAddOp(v, OP_MemLoad, iAMem+j, 0);
         if( j==0 ){
-          sqlite3VdbeAddOp(v, OP_Eq, 0, addrProcessRow);
+          sqlite3VdbeAddOp(v, OP_Eq, 0x200, addrProcessRow);
         }else{
-          sqlite3VdbeAddOp(v, OP_Ne, 0x100, addrGroupByChange);
+          sqlite3VdbeAddOp(v, OP_Ne, 0x200, addrGroupByChange);
         }
         sqlite3VdbeChangeP3(v, -1, (void*)pKeyInfo->aColl[j], P3_COLLSEQ);
       }
@@ -3004,19 +3037,22 @@ int sqlite3Select(
       */
       sqlite3VdbeResolveLabel(v, addrGroupByChange);
       for(j=0; j<pGroupBy->nExpr; j++){
-        sqlite3VdbeAddOp(v, OP_MemLoad, iBMem+j, 0);
-        sqlite3VdbeAddOp(v, OP_MemStore, iAMem+j, 1);
+        sqlite3VdbeAddOp(v, OP_MemMove, iAMem+j, iBMem+j);
       }
       sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow);
+      VdbeComment((v, "# output one row"));
       sqlite3VdbeAddOp(v, OP_IfMemPos, iAbortFlag, addrEnd);
-      resetAccumulator(pParse, &sAggInfo);
+      VdbeComment((v, "# check abort flag"));
+      sqlite3VdbeAddOp(v, OP_Gosub, 0, addrReset);
+      VdbeComment((v, "# reset accumulator"));

       /* Update the aggregate accumulators based on the content of
       ** the current row
       */
       sqlite3VdbeResolveLabel(v, addrProcessRow);
       updateAccumulator(pParse, &sAggInfo);
-      sqlite3VdbeAddOp(v, OP_MemIncr, iUseFlag, 0);
+      sqlite3VdbeAddOp(v, OP_MemInt, 1, iUseFlag);
+      VdbeComment((v, "# indicate data in accumulator"));

       /* End of the loop
       */
@@ -3030,6 +3066,7 @@ int sqlite3Select(
       /* Output the final row of result
       */
       sqlite3VdbeAddOp(v, OP_Gosub, 0, addrOutputRow);
+      VdbeComment((v, "# output final row"));

     } /* endif pGroupBy */
     else {