//----------------------------------------------------------------------------
// Prepare for creating the SYS_CALC columns, by divide the list of MAV 
// columns to 4 groups:
// 1. GroupBy columns - inserted directly into the RETDesc without change.
// 2. COUNT columns               - collected in countCols_, done in phase1.
// 3. SUM, MIN and MAX columns    - collected in sumCols_, done in phase2.
// 4. AVG, STDDEV, VARIANCE cols  - collected in otherCols_, done in phase3.
void MavRelRootBuilder::init()
{
  // Divide the MAV columns to groups:
  for (CollIndex i=0; i<mavCols_.entries(); i++)
  {
#pragma nowarn(1506)   // warning elimination 
    MVColumnInfo *currentCol = mavCols_[i];
#pragma warn(1506)  // warning elimination 

    if (currentCol->getColType() != COM_MVCOL_AGGREGATE)
    {  
      // This is a group-by column, or a constant that does not change.
      groupByCols_.insert(currentCol);
    }
    else
    {
      // This is an aggregate column. insert into the correct list.
      switch (currentCol->getOperatorType())
      {
	case ITM_COUNT: 
	case ITM_COUNT_NONULL: 
	  // No dependent columns, done in phase1.
	  countCols_.insert(currentCol);
	  break;

	case ITM_SUM:
	case ITM_MIN:
	case ITM_MAX:
	  // Use the SYS_CALC COUNT columns, done in phase2.
	  sumCols_.insert(currentCol);
	  break;

	case ITM_AVG:
	case ITM_STDDEV:
	case ITM_VARIANCE:
	  // Use the SYS_CALC COUNT and SUM columns, done in phase3.
	  otherCols_.insert(currentCol);
	  break;

	default:
	  CMPASSERT(FALSE);
      }
    }
  }
}  // MavRelRootBuilder::init()
//----------------------------------------------------------------------------
// First, do the COUNT columns.
// The select list of this root is (*, <count cols>).
// For COUNT, the SYS_CALC.col expr is:
//   SYS_MAV.col + SYS_DELTA.col
// For MAVs without a GROUP BY clause, this is later fixed by 
// buildRootForNoGroupBy().
//----------------------------------------------------------------------------
RelRoot *MavRelRootBuilder::buildRootForCount(RelExpr *topNode)
{
  // Start the select list with *
  ItemExprList selectList(heap_);
  addStarToSelectList(selectList);

  addColsToSelectList(groupByCols_, selectList, deltaCorrName_, &calcCorrName_);

  // For each column in the COUNT list
  for (CollIndex i=0; i<countCols_.entries(); i++)
  {
    MVColumnInfo *currentCol = countCols_[i];
    const NAString& colName = currentCol->getColName();

    // Find the column in the SYS_DELTA and SYS_MAV lists.
    ItemExpr *sysDeltaColExpr = new(heap_)
      ColReference(new(heap_) ColRefName(colName, deltaCorrName_));

    ItemExpr *sysMavColExpr = new(heap_)
      ColReference(new(heap_) ColRefName(colName, mavCorrName_));
      
    ItemExpr *newCalcExpr = new(heap_) 
      BiArith(ITM_PLUS, sysDeltaColExpr, sysMavColExpr);

    // Add the col expression as SYS_CALC.col
    ColRefName *calcColName = new(heap_) ColRefName(colName, calcCorrName_);
    ItemExpr *newCalcCol = new(heap_) RenameCol(newCalcExpr, calcColName);

    selectList.insert(newCalcCol);
  }

  // The select list is ready. Create the root over topNode.
  RelRoot *newRoot = new(heap_) 
    RelRoot(topNode, REL_ROOT, selectList.convertToItemExpr());
  newRoot->setDontOpenNewScope();

  selectList.clear();
  return newRoot;
}  // MavRelRootBuilder::buildRootForCount()
示例#3
0
//////////////////////////////////////////////////////////////////////////////
// Does this base table have a supporting index on the MAV GroupBy columns?
// (Supporting index means that the MAV GroupBy columns must be a prefix
// of the index columns).
//////////////////////////////////////////////////////////////////////////////
NABoolean Refresh::doesBaseTableHaveSupportingIndex(BindWA *bindWA,
        MVInfoForDML *mvInfo) const
{
    CollIndex i;
    LIST (MVUsedObjectInfo*)& UsedObjList = mvInfo->getUsedObjectsList();
    MVUsedObjectInfo* pUsedTable = UsedObjList[0];

    // Extract GroupBy columns
    const MVColumns& pMvInfoColumnList =
        mvInfo->getMVColumns();
    LIST (MVColumnInfo *) mvGroupByColumns(bindWA->wHeap());
    for (	i = 0 ; i < pMvInfoColumnList.entries() ; i++)
    {
#pragma nowarn(1506)   // warning elimination 
        MVColumnInfo *currentMvColInfo = pMvInfoColumnList[i];
#pragma warn(1506)  // warning elimination 
        if (COM_MVCOL_GROUPBY == currentMvColInfo->getColType())
        {
            mvGroupByColumns.insert(currentMvColInfo);
        }
    }

    // If the MAV does not have any group by columns - than there is
    // no supporting index.
    if (mvGroupByColumns.entries() == 0)
        return FALSE;

    // Get the NATable
    QualifiedName underlyingTableName = pUsedTable->getObjectName();
    CorrName corrTableName(underlyingTableName);
    NATable * pNaTable = bindWA->getNATable(corrTableName, FALSE);

    // Construct table GroupBy
    NAColumnArray tableGroupByArray;
    const NAColumnArray & columnArray = pNaTable->getNAColumnArray();
    for ( i = 0 ; i < mvGroupByColumns.entries() ; i++)
    {
        Int32 tableColNum = (mvGroupByColumns)[i]->getOrigColNumber();
        NAColumn * pColumn = columnArray.getColumn(tableColNum);
        tableGroupByArray.insert(pColumn);
    }

    // Check the clustering Index.
    const NAFileSet *pClusteringIndexFileSet = pNaTable->getClusteringIndex();
    const NAColumnArray& ciColumns =
        pClusteringIndexFileSet->getIndexKeyColumns();

    if (TRUE == areGroupByColsAnIndexPrefix(tableGroupByArray, ciColumns))
    {
        return TRUE;
    }

    // Check any secondary indices.
    const NAFileSetList & indexFileSetList = pNaTable->getIndexList();
    for ( i = 0 ; i < indexFileSetList.entries() ; i++)
    {
        const NAFileSet *pSecondaryIndexFileSet = indexFileSetList[i];
        const NAColumnArray& siColumns =
            pSecondaryIndexFileSet->getIndexKeyColumns();

        if (TRUE == areGroupByColsAnIndexPrefix(tableGroupByArray, siColumns))
        {
            return TRUE;
        }
    }

    return FALSE;
}
//----------------------------------------------------------------------------
// Next, do the other columns (AVG, STDDEV, VARIANCE), using the already
// calculated and bound COUNT and SUM columns.
// There are 3 dependent columns here (found using MVInfo):
//   dep1 is COUNT(a),
//   dep2 is SUM(a),
//   dep3 is SUM(a*a) (only for STDDEV and VARIANCE)
//   depCount is COUNT(a)
// In the case of STDDEV with a weight parameter - STDDEV(a,b), then
//   dep1 is SUM(b),
//   dep2 is SUM(a*b),
//   dep3 is SUM(a*a*b)
//   depCount is COUNT(a*b) and is the dependent column of dep2.
//
// For col=AVG(a), the new expr is:
//   CASE
//      WHEN (SYS_CALC.depCount = 0)  THEN NULL
//      ELSE SYS_CALC.dep2 / SYS_CALC.dep1
//   END
//
// For STDDEV and VARIANCE its:
//   CASE
//      WHEN (SYS_CALC.depCount = 0)  THEN NULL
//      ELSE ScalarVariance(SYS_CALC.dep3, SYS_CALC.dep2, SYS_CALC.dep1)
//   END
// depCount is the COUNT dependent column of dep2. This works also in the
// case of STDDEV with a weight parameter
//----------------------------------------------------------------------------
RelRoot *MavRelRootBuilder::buildRootForOthers(RelExpr *topNode)
{
  // Start the select list with *
  ItemExprList selectList(heap_);
  addStarToSelectList(selectList);

  // For each column in the COUNT list
  for (CollIndex i=0; i<otherCols_.entries(); i++)
  {
    MVColumnInfo *currentCol = otherCols_[i];
    const NAString& colName = currentCol->getColName();

    const NAType *desiredType = new(heap_) SQLDoublePrecision(TRUE);

    // Find the dependent SYS_CALC COUNT and SUM columns.
    ItemExpr *calcDep1 = 
      buildDepColExpr(calcCorrName_, currentCol->getDepCol1());
    ItemExpr *calcDep2 = 
      buildDepColExpr(calcCorrName_, currentCol->getDepCol2());
    ItemExpr *calcDep3 = NULL;
    ItemExpr *calcDepCount = NULL;
    if (currentCol->getOperatorType() == ITM_AVG)
    {
      calcDepCount = calcDep1;
    }
    else
    {
      // dep3 and depCount are needed only for STDDEV and VARIANCE.
      calcDep3 = buildDepColExpr(calcCorrName_, currentCol->getDepCol3());

      // depCount is the dereferenced dep1 column of dep2.
      MVColumnInfo *dep2ColInfo =
	mavCols_.getMvColInfoByIndex(currentCol->getDepCol2());
      calcDepCount = 
	buildDepColExpr(calcCorrName_, dep2ColInfo->getDepCol1());
    }

    // Build the condition bottom-up - do the ELSE clause first.
    ItemExpr *elseClause = NULL;
    if (currentCol->getOperatorType() == ITM_AVG)
    {
      // For AVG, the ELSE clause is (SYS_CALC.dep2 / SYS_CALC.dep1).
      elseClause = new(heap_)
        BiArith(ITM_DIVIDE, calcDep2, calcDep1);
    }
    else
    {
      // For STDDEV and VARIANCE, the ELSE clause is
      // ScalarVariance(SYS_CALC.dep3, SYS_CALC.dep2, SYS_CALC.dep1)
      elseClause = new(heap_)
        ScalarVariance(currentCol->getOperatorType(), 
		       new(heap_) Cast(calcDep3, desiredType), 
		       new(heap_) Cast(calcDep2, desiredType), 
		       new(heap_) Cast(calcDep1, desiredType));
    }

    // The WHEN clause is the same for AVG, STDDEV and VARIANCE:
    // WHEN (SYS_CALC.depCount = 0)  THEN NULL
    ItemExpr *whenClause = new(heap_)
      IfThenElse(new(heap_) BiRelat(ITM_EQUAL, 
				    calcDepCount,
				    new(heap_) SystemLiteral(0)),
		 new(heap_) SystemLiteral(), // NULL constant
		 elseClause);

    // Put the CASE on top.
    ItemExpr *newCalcExpr = new(heap_) Case(NULL, whenClause);

    // Add the col expression as SYS_CALC.col
    ColRefName *calcColName = new(heap_) ColRefName(colName, calcCorrName_);
    ItemExpr *newCalcCol = new(heap_) RenameCol(newCalcExpr, calcColName);

    selectList.insert(newCalcCol);
  }

  // The select list is ready. Create the root over topNode.
  RelRoot *newRoot = new(heap_) 
    RelRoot(topNode, REL_ROOT, selectList.convertToItemExpr());
  newRoot->setDontOpenNewScope();

  selectList.clear();
  return newRoot;
}  // MavRelRootBuilder::buildRootForOthers()
//----------------------------------------------------------------------------
// Next, do the SUM, MIN and MAX columns, using the already calculated 
// and bound COUNT columns (SYS_CALC.dep1).
// For col=SUM(a), the new expr is:
//   CASE
// 1)  	WHEN (SYS_CALC.dep1 = 0)     THEN NULL
// 2)  	WHEN (SYS_MAV.col IS NULL)   THEN SYS_DELTA.col
// 3)  	WHEN (SYS_DELTA.col IS NULL) THEN SYS_MAV.col
//   	ELSE SYS_MAV.col + SYS_DELTA.col
//   END
// For col=MIN(a), the else clause is replaced by (no MIN ItemExpr):
//      WHEN (SYS_MAV.col < SYS_DELTA.col) THEN SYS_MAV.col
//      ELSE SYS_DELTA.col
// For col=MAX(a), the else clause is:
//      WHEN (SYS_MAV.col > SYS_DELTA.col) THEN SYS_MAV.col
//      ELSE SYS_DELTA.col
//----------------------------------------------------------------------------
RelRoot *MavRelRootBuilder::buildRootForSum(RelExpr *topNode)
{
  // Start the select list with *
  ItemExprList selectList(heap_);
  addStarToSelectList(selectList);

  // For each column in the COUNT list
  for (CollIndex i=0; i<sumCols_.entries(); i++)
  {
    MVColumnInfo *currentCol = sumCols_[i];
    const NAString& colName = currentCol->getColName();

    // Find the column in the SYS_DELTA and SYS_MAV lists.
    ItemExpr *sysDeltaColExpr = new(heap_)
      ColReference(new(heap_) ColRefName(colName, deltaCorrName_));

    ItemExpr *sysMavColExpr = new(heap_)
      ColReference(new(heap_) ColRefName(colName, mavCorrName_));
      
    // Find the dependent SYS_CALC COUNT column.
    ItemExpr *calcDep1 = 
      buildDepColExpr(calcCorrName_, currentCol->getDepCol1());

    // Build the condition bottom-up - do the ELSE clause first.
    ItemExpr *elseClause = NULL;
    if (currentCol->getOperatorType() == ITM_SUM)
    {
      // The ELSE clause for SUM is (SYS_MAV.col + SYS_DELTA.col).
      elseClause = new(heap_) 
        BiArith(ITM_PLUS, sysDeltaColExpr, sysMavColExpr);
    }
    else
    {
      // The ELSE clause for MIN is:
      //    WHEN (SYS_MAV.col < SYS_DELTA.col) THEN SYS_MAV.col
      //    ELSE SYS_DELTA.col
      // For MAX the < operator is replaced by >.
      OperatorTypeEnum sign = 
        (currentCol->getOperatorType()==ITM_MIN ? ITM_LESS : ITM_GREATER);
      elseClause = new(heap_) 
        IfThenElse(new(heap_) BiRelat(sign, sysMavColExpr, sysDeltaColExpr),
  		   sysMavColExpr,
		   sysDeltaColExpr);
    }

    // The 3rd WHEN clause: WHEN (SYS_DELTA.col IS NULL) THEN SYS_MAV.col
    ItemExpr *when3Clause = new(heap_)
      IfThenElse(new(heap_) UnLogic(ITM_IS_NULL, sysDeltaColExpr),
		 sysMavColExpr,
		 elseClause);

    // The 2nd WHEN clause: WHEN (SYS_MAV.col IS NULL) THEN SYS_DELTA.col
    ItemExpr *when2Clause = new(heap_)
      IfThenElse(new(heap_) UnLogic(ITM_IS_NULL, sysMavColExpr),
		 sysDeltaColExpr,
		 when3Clause);

    // The 1st WHEN clause: WHEN (SYS_CALC.dep1 = 0) THEN NULL
    ItemExpr *when1Clause = new(heap_)
      IfThenElse(new(heap_) BiRelat(ITM_EQUAL, 
    				    calcDep1,
				    new(heap_) SystemLiteral(0)),
		 new(heap_) SystemLiteral(), // NULL constant
		 when2Clause);

    // Build the CASE on top.
    ItemExpr *newCalcExpr = new(heap_) Case(NULL, when1Clause);

    // Add the col expression as SYS_CALC.col
    ColRefName *calcColName = new(heap_) ColRefName(colName, calcCorrName_);
    ItemExpr *newCalcCol = new(heap_) RenameCol(newCalcExpr, calcColName);

    selectList.insert(newCalcCol);
  }

  // The select list is ready. Create the root over topNode.
  RelRoot *newRoot = new(heap_) 
    RelRoot(topNode, REL_ROOT, selectList.convertToItemExpr());
  newRoot->setDontOpenNewScope();

  selectList.clear();
  return newRoot;
}  // MavRelRootBuilder::buildRootForSum()