// *************************************************************************** // *************************************************************************** void MVDetails::addEqualitySet(QRJoinPredPtr joinPredElement, NABoolean isFromExpr, QROutputPtr output, CollHeap* heap) { const ElementPtrList& equalitySet = joinPredElement->getEqualityList(); for (CollIndex i=0; i<equalitySet.entries(); i++) { const QRElementPtr halfPred = equalitySet[i]; // Now lets look at the equality set members // Ignore members that are not simple columns. if (halfPred->getElementType() != ET_Column) continue; const QRColumnPtr eqSetColumn = halfPred->getReferencedElement()->downCastToQRColumn(); // If this JoinPred element is a column of an LOJ table, // skip it because it is not really equal to the others. const QRElementPtr tableElem = getElementForID(eqSetColumn->getTableID()); if (tableElem->downCastToQRTable()->hasLOJParent()) continue; // Compute the "ID Qualified" column name as the key. const NAString* idQualifiedColName = calcIDQualifiedColumnName(eqSetColumn->getTableID(), eqSetColumn->getColumnName(), heap); // Insert into the hash table. if (isFromExpr) outputByInputColumns_.insert(idQualifiedColName, output); else outputByColumnName_.insert(idQualifiedColName, output); } } // MVDetails::addEqualitySet
// *************************************************************************** // *************************************************************************** void DescriptorDetails::initJoinPredList(const QRJoinPredListPtr jpList) { if (jpList == NULL) return; CollIndex maxEntries = jpList->entries(); //Iterate over JoinPred list for (CollIndex i=0; i<maxEntries; i++) { const QRJoinPredPtr joinPred = (*jpList)[i]; const ElementPtrList& equalitySet = joinPred->getEqualityList(); // Iterate over equality set in JoinPred. for (CollIndex i=0; i<equalitySet.entries(); i++) { const QRElementPtr halfPred = equalitySet[i]->getReferencedElement(); // Now lets look at the equality set members // Ignore members that are not simple columns. if (halfPred->getElementType() != ET_Column) continue; const QRColumnPtr eqSetColumn = halfPred->getReferencedElement()->downCastToQRColumn(); // Skip columns from other JBBs. if (getElementForID(eqSetColumn->getTableID()) == NULL) continue; // Skip columns from LOJ tables. if (isColumnFromLojTable(eqSetColumn)) continue; const NAString& columnID = eqSetColumn->getID(); joinPredHash_.insert(&columnID, joinPred); } } }
// *************************************************************************** // *************************************************************************** void JBBDetails::initRangePreds(CollHeap* heap) { // Initialize the Range predicates. const QRRangePredListPtr rangePreds = jbbDesc_->getHub()->getRangePredList(); if (rangePreds==NULL || rangePreds->entries() == 0) { hasNoRangePredicates_ = TRUE; return; } for (CollIndex k=0; k<rangePreds->entries(); k++) { const QRRangePredPtr rangePred = (*rangePreds)[k]; const QRElementPtr rangeElem = rangePred->getRangeItem()->getReferencedElement(); if (rangeElem->getElementType() == ET_Column && rangePred->isSingleValue()) { constColumns_.insert(&rangeElem->getID()); } // For query descriptors, only check for const columns. if (!isAnMV_) continue; if (rangeElem->getElementType() == ET_Column) { const QRColumnPtr rangeColumn = rangeElem->downCastToQRColumn(); if (!descDetails_->isFromJoin(rangeColumn)) { // This column is NOT part of a join predicate. BaseTableDetailsPtr rangeTable = getBaseTableByID(rangeColumn->getTableID()); rangeTable->addRangePredicateOnColumn(rangePred, rangeColumn); } else { // This column IS part of a join predicate. // Insert the range pred for all the participating columns. const QRJoinPredPtr jp = descDetails_->getJoinPred(rangeColumn); const ElementPtrList& equalitySet = jp->getEqualityList(); for (CollIndex i=0; i<equalitySet.entries(); i++) { const QRElementPtr halfPred = equalitySet[i]; // Now lets look at the equality set members // Ignore members that are not simple columns. if (halfPred->getElementType() != ET_Column) continue; const QRColumnPtr eqSetColumn = halfPred->getReferencedElement()->downCastToQRColumn(); BaseTableDetailsPtr rangeTable = getBaseTableByID(eqSetColumn->getTableID()); rangeTable->addRangePredicateOnColumn(rangePred, eqSetColumn); } } } else if (rangeElem->getElementType() == ET_JoinPred) { assertLogAndThrow(CAT_MATCHTST_MVDETAILS, LL_MVQR_FAIL, (rangeElem->getElementType() == ET_JoinPred), QRLogicException, "Unexpected JoinPred element."); // If its an equality set, insert the range pred for all the participating columns. const QRJoinPredPtr joinPredElement = rangeElem->downCastToQRJoinPred(); const ElementPtrList& equalitySet = joinPredElement->getEqualityList(); for (CollIndex i=0; i<equalitySet.entries(); i++) { const QRElementPtr halfPred = equalitySet[i]; // Now lets look at the equality set members // Ignore members that are not simple columns. if (halfPred->getElementType() != ET_Column) continue; const QRColumnPtr eqSetColumn = halfPred->getReferencedElement()->downCastToQRColumn(); BaseTableDetailsPtr rangeTable = getBaseTableByID(eqSetColumn->getTableID()); rangeTable->addRangePredicateOnColumn(rangePred, eqSetColumn); } } else { // The range pred is on an expression. Insert it for all the expression's input columns. const QRExprPtr rangeExpr = rangeElem->downCastToQRExpr(); if (rangeExpr->getExprRoot()->containsAnAggregate(heap)) { hasHavingPredicates_ = TRUE; } // Verify we have a single input column // No input columns mean its a COUNT(*), which is OK too. const ElementPtrList& inputs = rangeExpr->getInputColumns(heap); assertLogAndThrow(CAT_MATCHTST_MVDETAILS, LL_MVQR_FAIL, (inputs.entries() <= 1), QRLogicException, "Range predicate expression must have a single input at most."); const NAString& predText = rangeExpr->getExprText(); // Look it up in the hash table: do we already have a range pred with this text? RangePredPtrList* predList = getRangePredsOnExpression(predText); if (predList == NULL) { // No, its the first one. Create a new list. predList = new(heap) RangePredPtrList(heap); // And insert it into the hash table. rangePredicates_.insert(&predText, predList); } // Insert the predicate into the pred list. predList->insert(rangePred); } } } // JBBDetails::init()
LatticeIndexablePtr QRGroupLattice::elementToKey(const QRElementPtr element, QRJoinSubGraphMapPtr map, DescriptorDetailsPtr queryDetails, NABoolean insertMode, NABoolean isRecursive) { QRElementPtr elem = element->getReferencedElement(); QRColumnPtr col = NULL; if (elem->getElementType() == ET_Column) { col = elem->downCastToQRColumn(); if (queryDetails->isFromJoin(col) && !isRecursive) { // This groupby element is a join pred. // During insert, this loop inserts the first column. // During search, try each equality set element until we find one that // appears in our array. const QRJoinPredPtr eqSet = queryDetails->getJoinPred(col); const ElementPtrList& equalityList = eqSet->getEqualityList(); if (insertMode) { // Insert mode - pick the first column of the equality set. col = equalityList[0]->downCastToQRColumn(); } else { // Search mode - pick the first equality set entry that is found in this LatticeIndex. for (CollIndex i=0; i<equalityList.entries(); i++) { QRElementPtr entry = equalityList[i]->getReferencedElement(); // Call recursively for each join pred column. LatticeIndexablePtr entryKey = elementToKey(entry, map, queryDetails, insertMode, TRUE); if (entryKey == NULL) continue; if (lattice_->contains(entryKey)) { // Found it in the lattice index. col = entry->downCastToQRColumn(); break; } } // for ( ) // If none of the entries was found - give up now. if (col == NULL) return NULL; } // if insert mode } // if JoinPred } // if Column NAString* key = NULL; if (col != NULL) { col = col->getReferencedElement()->downCastToQRColumn(); const NAString& tableID = col->getTableID(); Int32 Inx = map->getIndexForTable(tableID); if (Inx == -1) { assertLogAndThrow(CAT_GRP_LATTCE_INDX, LL_ERROR, !insertMode, QRLogicException, "Table index not found in Insert mode (Inserting a multi-JBB MV?)."); return NULL; } char buffer[4096+5]; sprintf(buffer, "%d.%s", Inx, col->getColumnName().data() ); key = new(heap_) NAString(buffer, heap_); } else { // This is an expression. // TBD We still do not handle expressions using columns from self-join tables. key = new(heap_) NAString(element->getSortName(), heap_); } // The reverseKeyHash should always use the most recent MV inserted. if (insertMode) { reverseKeyHash_.remove(key); reverseKeyHash_.insert(key, element); } return key; }