//----------------------------------------------------------------------------
// Transform each aggregate in the MAV select list, to use the @OP column in
// order to calculate deleted rows correctly:
// COUNT(*) => SUM(@OP)
// COUNT(a) => SUM(IF (a IS NULL) THEN 0 ELSE @OP) 
// SUM(a)   => SUM(a * @OP)
// MIN(a) & MAX(a) => Special treatment (see handleDeltaMinMaxColumns()).
// AVG, STDDEV and VARIANCE are derived from other COUNT and SUM columns. 
// They are removed from this select list to avoid divide by zero problems
// in case COUNT=0.
void MavRelRootBuilder::fixDeltaColumns(RelExpr   *mvSelectTree, 
					NABoolean  canSkipMinMax,
				        NABoolean  wasFullDE)
{
  // Get the MAV select list from the mvSelectTree.
  CMPASSERT(mvSelectTree->getOperatorType() == REL_ROOT);
  RelRoot *mavSelectRoot = (RelRoot *)mvSelectTree;

  ItemExprList mavSelectList(mavSelectRoot->removeCompExprTree(), heap_);
  ItemExprList newSelectList(heap_);

  const NAString& opName = MavBuilder::getVirtualOpColumnName();

  for (CollIndex i=0; i<mavSelectList.entries(); i++)
  {
    ItemExpr *selectListExpr = mavSelectList[i];

    CMPASSERT(selectListExpr->getOperatorType() == ITM_RENAME_COL);
    const NAString& colName = 
      ((RenameCol*)selectListExpr)->getNewColRefName()->getColName();
    ItemExpr *aggregateExpr = selectListExpr;
    while ((aggregateExpr->getOperatorType() == ITM_RENAME_COL) ||
           (aggregateExpr->getOperatorType() == ITM_CAST))
      aggregateExpr = aggregateExpr->child(0);

    // Assuming all aggregates are top-most functions as explained in the 
    // MV external spec.
    ItemExpr *aggregateOperand = aggregateExpr->child(0);
    ItemExpr *newExpr   = NULL;

    if (!aggregateExpr->containsAnAggregate())
    {
      // Non-aggregate columns (group-by cols) are added unchanged.
    }
    else
      switch (aggregateExpr->getOperatorType())
      {
	case ITM_COUNT_NONULL:
	  // COUNT(a) => SUM(IF (a IS NULL) THEN 0 ELSE @OP) 
	  newExpr = new(heap_) 
	    Aggregate(ITM_SUM, new(heap_) 
	      Case(NULL, new(heap_)
		IfThenElse (new(heap_) UnLogic(ITM_IS_NULL, aggregateOperand),
    			    new(heap_) SystemLiteral(0),
			    new(heap_) ColReference(new(heap_) 
			      ColRefName(opName)))));
	  selectListExpr->child(0) = newExpr;
	  break;

	case ITM_COUNT:
	  // COUNT(*) => SUM(@OP)
	  newExpr = new(heap_) 
	    Aggregate(ITM_SUM, 
    		      new(heap_) ColReference(new(heap_) ColRefName(opName)));
	  selectListExpr->child(0) = newExpr;
	  break;

	case ITM_SUM:
	  // SUM(a) => SUM(a * @OP)
	  newExpr = new(heap_)
	    BiArith(ITM_TIMES,
		    aggregateOperand,
		    new(heap_) ColReference(new(heap_) ColRefName(opName)));
	  aggregateExpr->child(0) = newExpr;
	  break;

	case ITM_MIN:
	case ITM_MAX:
	  // Handle Min/Max if not all deltas are INSERT ONLY.
	  if (!canSkipMinMax)
	    handleDeltaMinMaxColumns(aggregateExpr, colName, newSelectList, wasFullDE);
	  // Add the SYS_DELTA Min/Max aggregate as is.
	  break;

	case ITM_AVG:
	case ITM_DIVIDE:
	case ITM_VARIANCE:
	case ITM_STDDEV:
	  // Remove these expressions from the select list.
	  selectListExpr = NULL;
	  break;

	default:
	  // A new type of aggregate?
	  CMPASSERT(FALSE);
	  break;
      }

    if (selectListExpr!=NULL)
      newSelectList.insert(selectListExpr);
  }

  ItemExpr *selList = newSelectList.convertToItemExpr();
  mavSelectRoot->addCompExprTree(selList);

  mavSelectList.clear(); // Don't delete all the entries from the Dtor.
}  // MavRelRootBuilder::fixDeltaColumns()