void CRUSimpleRefreshSQLComposer::AddDeltaDefListClause()
{
	RUASSERT(GetRefreshTask().GetDeltaDefList().GetCount() > 0);

	sql_ += "\n FROM ";
	sql_ += (TRUE == GetRefreshTask().IsSingleDeltaRefresh()) ? 
		"SINGLEDELTA " : "MULTIDELTA ";

	DSListPosition pos = GetRefreshTask().GetDeltaDefList().GetHeadPosition();

	for (;;)
	{
		CRUDeltaDef *pDdef = GetRefreshTask().GetDeltaDefList().GetNext(pos);

		CDSString fromEpoch(TInt32ToStr(pDdef->fromEpoch_)) ;
		CDSString toEpoch(TInt32ToStr(pDdef->toEpoch_));

		AddDeltaDefClause(pDdef,fromEpoch,toEpoch);

		if (NULL == pos)
		{
			break;	// The last clause
		}
		else
		{
			sql_ += ", ";
		}
	}	
	if (FALSE == GetRefreshTask().IsSingleDeltaRefresh())
	{
		AddPhaseParam();
	}
}
void CRUDupElimSQLComposer::ComposeUpdateRecsSearchPredicate(CDSString &pred)
{
	pred = "\nWHERE \n(";
	const CRULogCtlColDesc &desc1 = 
		iudLogCtlColDescVec[CRUDupElimConst::OFS_EPOCH];

	pred += ComposeQuotedColName(desc1.name_);
	pred += " BETWEEN " + TInt32ToStr(beginEpoch_) 
			+ " AND " + TInt32ToStr(endEpoch_) + ")\nAND ";

	CDSString ckClause;
	ComposeCKEqualSearchClause(ckClause);
	pred += ckClause;

	CDSString type1 = TInt32ToStr(CRUDupElimConst::IS_PART_OF_UPDATE);
	CDSString type2 = TInt32ToStr(
		CRUDupElimConst::IS_PART_OF_UPDATE + CRUDupElimConst::IS_DELETE);

	const CRULogCtlColDesc &desc2 = 
		iudLogCtlColDescVec[CRUDupElimConst::OFS_OPTYPE];
	CDSString optypeColName = ComposeQuotedColName(desc2.name_);

	pred += "\nAND (" + optypeColName + " = " + type1;
	pred += " OR " + optypeColName + " = " + type2 + ")";
}
void CRURefreshSQLComposer::
AddRngDeltaStatisticsClause(const CRUDeltaDef *pDdef)
{
	sql_ += "\n\t";

	if (FALSE == pDdef->isRangeLogNonEmpty_)
	{
		sql_ += " USE NO RANGELOG";
		return;
	}

	CRUDeltaStatistics *pStat = pDdef->pStat_;
	RUASSERT(CRUDeltaDef::NO_DE != pDdef->deLevel_ && NULL != pStat);

	// USE RANGELOG <number> NUM_OF_RANGES <number> ROWS_COVERED
	TInt32 nRanges = pStat->nRanges_;
	RUASSERT(nRanges > 0);

	sql_ += "USE RANGELOG " + TInt32ToStr(nRanges) + " NUM_OF_RANGES ";

	TInt32 nCoveredRows = pStat->nRangeCoveredRows_;
	if (CRUDeltaStatistics::RANGE_SIZE_UNKNOWN != nCoveredRows)
	{
		sql_ += TInt32ToStr(nCoveredRows) + " ROWS_COVERED";
	}
}
void CRURefreshSQLComposer::
AddIUDDeltaStatisticsClause(const CRUDeltaDef *pDdef)
{
	sql_ += "\n\t";

	if (FALSE == pDdef->isIUDLogNonEmpty_)
	{
		sql_ += " USE NO IUDLOG";
		return;
	}

	sql_ += "USE IUDLOG ";

	if (CRUDeltaDef::SINGLE_2_SINGLE != pDdef->deLevel_)
	{
		// We can only tell whether the delta is insert-only or not
		if (TRUE == pDdef->isIUDLogInsertOnly_)
		{
			// USE IUDLOG INSERT ONLY
			sql_ += "INSERT ONLY";
		}

		return;
	}

	// Single-row resolution was enforced. We have complete statistics.
	CRUDeltaStatistics *pStat = pDdef->pStat_;
	if (NULL == pStat)
	{
		// DE came up with empty stats.
		// Just write zeroes, and INTERNAL REFRESH will handle it.
		pStat = new CRUDeltaStatistics();
	}

	// USE IUDLOG
	//	<number> ROWS_INSERTED
	//	<number> ROWS_DELETED
	//	<number> ROWS_UPDATED [COLUMNS <col>,<col>,<col>...]

	sql_ += "\n\t" + TInt32ToStr(pStat->nInsertedRows_) + " ROWS_INSERTED ";
	sql_ += "\n\t" + TInt32ToStr(pStat->nDeletedRows_) + " ROWS_DELETED ";
	sql_ += "\n\t" + TInt32ToStr(pStat->nUpdatedRows_) + " ROWS_UPDATED ";

	if (0 != pStat->nUpdatedRows_)
	{
		CRUUpdateBitmap *pUpdateBitmap = pStat->pUpdateBitmap_;
		RUASSERT(NULL != pUpdateBitmap);

		AddUpdatedColumnsClause(pUpdateBitmap);
	}
}
void CRUDupElimSQLComposer::ComposeIUDUpdateBitmapText()
{
	CDSString pred;
	sql_ += "UPDATE " + iudLogName_;
	
	const CRULogCtlColDesc &desc = 
		iudLogCtlColDescVec[CRUDupElimConst::OFS_UPD_BMP];

	// Compose the real datatype 
	// of the @UPDATE_BITMAP column - CHAR(<size>)
	CDSString datatype(desc.datatype_);

	RUASSERT(updateBmpSize_ > 0);
	datatype += "(" + TInt32ToStr(updateBmpSize_) + ")";

	// -------------------------------------------------------------
    // Date: 2008-03-19  Caroline:
	// In UNICODE config: ISO_MAPPING=UTF8, DEFAULT_CHARSET= UCS2
	// The IUD_LOG_TABLE Clause: 
	//       SET "@UPDATE_BITMAP" = CAST (? AS CHAR(8)) 
	// The "@UPDATE_BITMAP" column is in ISO88591, and the CAST Clause 
	// is implied to UCS2, so we got the incompatible error. 
	// To fix the error, we explicitly say "CHARACTER SET ISO88591".

	datatype += " CHARACTER SET ISO88591 ";
	//---------------------------------------------

	sql_ += "\nSET " + ComposeQuotedColName(desc.name_) + " = ";
	sql_ += ComposeCastExpr(datatype);		

	ComposeUpdateRecsSearchPredicate(pred);
	sql_+= pred + ";";
}
void CRURefreshSQLComposer::
AddUpdatedColumnsClause(const CRUUpdateBitmap *pUpdateBitmap)
{
	sql_ += "COLUMNS (";

	BOOL isFirst = TRUE;
	Int32 numOfColumns = pUpdateBitmap->GetSize() * 8;
	
	for	(Int32 index=0;index < numOfColumns;index++)
	{
		if (FALSE == pUpdateBitmap->IsColumnUpdated(index))
		{
			continue;
		}
		
		if (TRUE == isFirst)
		{
			isFirst = FALSE;
		}
		else
		{
			sql_ += ",";
		}
		
		sql_ += TInt32ToStr(index);
	}

	sql_ += ") ";
}
void CRUDupElimSQLComposer::
ComposeQBlockForMultipleEpochsBasicPred(CDSString &to,
										CDSString &epochCol,
										TInt32 fromEp,
										TInt32 toEp,
										BOOL isPhase0Query)
{
	to = "\n(\n" + epochCol + " BETWEEN " + TInt32ToStr(fromEp) + 
		" AND " + TInt32ToStr(toEp);

	if (FALSE == isPhase0Query)
	{
		to += ComposeQBlockLowerBoundPredicate();
	}

	to += "\n)";
}
void CRURefreshSQLComposer::AddDeltaDefClause(const CRUDeltaDef *pDdef,
											  CDSString &fromEpoch,
											  CDSString &toEpoch)
{
	// <table-name> BETWEEN <begin-epoch> AND <end-epoch>
	sql_ += "\n\t" + pDdef->tblName_;
	sql_ += " BETWEEN " + fromEpoch + " AND " + toEpoch;
	sql_ += " DE LEVEL " + TInt32ToStr(pDdef->deLevel_);
		
	// The delta statistics clauses (based on the emptiness check
	// and the duplicate elimimation results)
	AddRngDeltaStatisticsClause(pDdef);	
	AddIUDDeltaStatisticsClause(pDdef);
}
void CRUDupElimSQLComposer::ComposeIUDUpdateOptypeText()
{
	CDSString pred;
	sql_ += "UPDATE " + iudLogName_;
	
	const CRULogCtlColDesc &desc = 
		iudLogCtlColDescVec[CRUDupElimConst::OFS_OPTYPE];
	CDSString name = ComposeQuotedColName(desc.name_);

	sql_ += "\nSET " + name + " = ";
	sql_ += name + "-" + TInt32ToStr(CRUDupElimConst::IS_PART_OF_UPDATE);

	ComposeUpdateRecsSearchPredicate(pred);
	sql_+= pred + ";";
}
void CRULogCleanupSQLComposer::ComposeHeader(const CDSString &tableName, CRULogCleanupTaskExecutor::SQL_STATEMENT type)
{
  sql_ = "DELETE ";
  switch(type)
  {
    case CRULogCleanupTaskExecutor::CLEAN_IUD_BASIC:
      break;

    case CRULogCleanupTaskExecutor::CLEAN_IUD_FIRSTN:
      sql_ += "[FIRST " + TInt32ToStr(MAX_ROW_TO_DELETE_IN_SINGLE_TXN) + "]";
      break;

    case CRULogCleanupTaskExecutor::CLEAN_IUD_MCOMMIT:
      sql_ += "WITH MULTI COMMIT ";
  }
  sql_ += "\nFROM " + tableName;
}
void CRUDupElimSQLComposer::
ComposeQBlockForEpoch(CDSString &qryBase, 
					  CDSString &epochCol, 
					  TInt32 ep,
					  BOOL isPhase0Query)
{
	if (0 != sql_.GetLength())
	{
		// This is not the first block
		sql_ += "\nUNION ALL\n";
	}

	CDSString pred("\n(\n" + epochCol + " = " + TInt32ToStr(ep));
	
	if (FALSE == isPhase0Query)
	{
		pred += ComposeQBlockLowerBoundPredicate();
	}

	pred += "\n)";

	sql_ += qryBase + pred;
}