if( distinct>=0 && pEList && pEList->nExpr>0 ){
if( hasDistinct ){
static int selectInnerLoop(  Parse *pParse,          /* The parser context */  Select *p,              /* The complete select statement being coded */  ExprList *pEList,       /* List of values being extracted */  int srcTab,             /* Pull data from this table */  int nColumn,            /* Number of columns in the source table */  ExprList *pOrderBy,     /* If not NULL, sort results using this key */  int distinct,           /* If >=0, make sure results are distinct */  int eDest,              /* How to dispose of the results */  int iParm,              /* An argument to the disposal method */  int iContinue,          /* Jump here to continue with next row */  int iBreak              /* Jump here to break out of the inner loop */){  Vdbe *v = pParse->pVdbe;  int i;  if( v==0 ) return 0;  assert( pEList!=0 );  /* If there was a LIMIT clause on the SELECT statement, then do the check  ** to see if this row should be output.  */  if( pOrderBy==0 ){    if( p->iOffset>=0 ){      int addr = sqliteVdbeCurrentAddr(v);      sqliteVdbeAddOp(v, OP_MemIncr, p->iOffset, addr+2);      sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);    }    if( p->iLimit>=0 ){      sqliteVdbeAddOp(v, OP_MemIncr, p->iLimit, iBreak);    }  }  /* Pull the requested columns.  */  if( nColumn>0 ){    for(i=0; i<nColumn; i++){      sqliteVdbeAddOp(v, OP_Column, srcTab, i);    }  }else{    nColumn = pEList->nExpr;    for(i=0; i<pEList->nExpr; i++){      sqliteExprCode(pParse, pEList->a[i].pExpr);    }  }  /* If the DISTINCT keyword was present on the SELECT statement  ** and this row has been seen before, then do not make this row  ** part of the result.  */  if( distinct>=0 && pEList && pEList->nExpr>0 ){#if NULL_ALWAYS_DISTINCT    sqliteVdbeAddOp(v, OP_IsNull, -pEList->nExpr, sqliteVdbeCurrentAddr(v)+7);#endif    sqliteVdbeAddOp(v, OP_MakeKey, pEList->nExpr, 1);    if( pParse->db->file_format>=4 ) sqliteAddKeyType(v, pEList);    sqliteVdbeAddOp(v, OP_Distinct, distinct, sqliteVdbeCurrentAddr(v)+3);    sqliteVdbeAddOp(v, OP_Pop, pEList->nExpr+1, 0);    sqliteVdbeAddOp(v, OP_Goto, 0, iContinue);    sqliteVdbeAddOp(v, OP_String, 0, 0);    sqliteVdbeAddOp(v, OP_PutStrKey, distinct, 0);  }  switch( eDest ){    /* In this mode, write each query result to the key of the temporary    ** table iParm.    */    case SRT_Union: {      sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);      sqliteVdbeAddOp(v, OP_String, 0, 0);      sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);      break;    }    /* Store the result as data using a unique key.    */    case SRT_Table:    case SRT_TempTable: {      sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);      if( pOrderBy ){        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqliteVdbeAddOp(v, OP_NewRecno, iParm, 0);        sqliteVdbeAddOp(v, OP_Pull, 1, 0);        sqliteVdbeAddOp(v, OP_PutIntKey, iParm, 0);      }      break;    }    /* Construct a record from the query result, but instead of    ** saving that record, use it as a key to delete elements from    ** the temporary table iParm.    */    case SRT_Except: {      int addr;      addr = sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, NULL_ALWAYS_DISTINCT);      sqliteVdbeAddOp(v, OP_NotFound, iParm, addr+3);      sqliteVdbeAddOp(v, OP_Delete, iParm, 0);      break;    }    /* If we are creating a set for an "expr IN (SELECT ...)" construct,    ** then there should be a single item on the stack.  Write this    ** item into the set table with bogus data.    */    case SRT_Set: {      int addr1 = sqliteVdbeCurrentAddr(v);      int addr2;      assert( nColumn==1 );      sqliteVdbeAddOp(v, OP_NotNull, -1, addr1+3);      sqliteVdbeAddOp(v, OP_Pop, 1, 0);      addr2 = sqliteVdbeAddOp(v, OP_Goto, 0, 0);      if( pOrderBy ){        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqliteVdbeAddOp(v, OP_String, 0, 0);        sqliteVdbeAddOp(v, OP_PutStrKey, iParm, 0);      }      sqliteVdbeChangeP2(v, addr2, sqliteVdbeCurrentAddr(v));      break;    }    /* If this is a scalar select that is part of an expression, then    ** store the results in the appropriate memory cell and break out    ** of the scan loop.    */    case SRT_Mem: {      assert( nColumn==1 );      if( pOrderBy ){        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqliteVdbeAddOp(v, OP_MemStore, iParm, 1);        sqliteVdbeAddOp(v, OP_Goto, 0, iBreak);      }      break;    }    /* Send the data to the callback function.    */    case SRT_Callback:    case SRT_Sorter: {      if( pOrderBy ){        sqliteVdbeAddOp(v, OP_SortMakeRec, nColumn, 0);        pushOntoSorter(pParse, v, pOrderBy);      }else{        assert( eDest==SRT_Callback );        sqliteVdbeAddOp(v, OP_Callback, nColumn, 0);      }      break;    }    /* Invoke a subroutine to handle the results.  The subroutine itself    ** is responsible for popping the results off of the stack.    */    case SRT_Subroutine: {      if( pOrderBy ){        sqliteVdbeAddOp(v, OP_MakeRecord, nColumn, 0);        pushOntoSorter(pParse, v, pOrderBy);      }else{        sqliteVdbeAddOp(v, OP_Gosub, 0, iParm);      }      break;    }    /* Discard the results.  This is used for SELECT statements inside    ** the body of a TRIGGER.  The purpose of such selects is to call    ** user-defined functions that have side effects.  We do not care    ** about the actual results of the select.    */    default: {      assert( eDest==SRT_Discard );      sqliteVdbeAddOp(v, OP_Pop, nColumn, 0);      break;    }  }  return 0;}