//---------------------------------------------------------------------------- // 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()
////////////////////////////////////////////////////////////////////////////// // 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()