// *************************************************************************** // Initialize the hash of tables in the descriptor. // For every table in the JBBC list of the Hub as well as the extraHub, // insert an entry into the hash table, using the table's name as the hash key. // *************************************************************************** void MVDetails::initTables(const QRJBBPtr jbb, CollHeap* heap) { // Map all the table names // Start with the Hub tables. const ElementPtrList& hubTables = jbb->getHub()->getJbbcList()->getList(); for (CollIndex i=0; i<hubTables.entries(); i++) { QRElementPtr element = hubTables[i]; // Ignore JBBCs that are not tables - they must be child-JBB references, // so we will get to them when looping over the JBB list. if (element->getElementType() == ET_Table) { const QRTablePtr table = element->downCastToQRTable(); const NAString& name = table->getTableName(); tableByNameHash_.insert(&name, table); } } // Continue with the extra-hub tables. const QRExtraHubPtr extraHub = jbb->getExtraHub(); if (extraHub != NULL) { QRTableListPtr extraHubTables = extraHub->getTableList(); if (extraHubTables != NULL) { for (CollIndex j=0; j<extraHubTables->entries(); j++) { QRTablePtr table = (*extraHubTables)[j]; const NAString& name = table->getTableName(); tableByNameHash_.insert(&name, table); } } } }
// *************************************************************************** // *************************************************************************** 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
// *************************************************************************** // Get the table element (from the JBBC list) with this name (or NULL if not found). // This method must NOT be used to find a specific table instance, because // with self-joins, multiple tables have the same name. // Use MVCandidate::getMvTableForQueryID() instead. // *************************************************************************** const QRTablePtr MVDetails::getTableFromName(const NAString& name) { QRElementPtr table = tableByNameHash_.getFirstValue(&name); if (table == NULL) return NULL; return table->downCastToQRTable(); }
// *************************************************************************** // Is this column from a table that has an LOJ parent? // *************************************************************************** NABoolean DescriptorDetails::isColumnFromLojTable(const QRColumnPtr col) { const NAString& tableID = col->getTableID(); const QRElementPtr tableElem = getElementForID(tableID); assertLogAndThrow(CAT_MATCHTST_MVDETAILS, LL_MVQR_FAIL, tableElem, QRLogicException, "Table not found in JBB."); const QRTablePtr table = tableElem->downCastToQRTable(); return table->hasLOJParent(); }
// *************************************************************************** // *************************************************************************** const NAString& DescriptorDetails::getTableNameFromColumn(QRColumnPtr colElem) { static const NAString empty(""); const NAString& tableID = colElem->getReferencedElement()->downCastToQRColumn()->getTableID(); const QRElementPtr tableElem = getElementForID(tableID); if (tableElem==NULL) { // This table is in a JBB that was ommitted from the query descriptor. // Return an empty table name. return empty; } const QRTablePtr table = tableElem->downCastToQRTable(); return table->getTableName(); }
// *************************************************************************** // *************************************************************************** void JBBDetails::initBaseTables(CollHeap* heap) { // Create BaseTableDetails objects for the JBB hub tables. const ElementPtrList& hubTables = jbbDesc_->getHub()->getJbbcList()->getList(); for (CollIndex i=0; i<hubTables.entries(); i++) { const QRElementPtr jbbc = hubTables[i]; if (jbbc->getElementType() != ET_Table) continue; // Skip reference to other JBBs. const QRTablePtr table = jbbc->downCastToQRTable(); if (table->hasLOJParent()) hasLOJs_ = TRUE; // Rest of the stuff only needed for MVs. if (!isAnMV_) continue; BaseTableDetailsPtr tableDetails = new(heap) BaseTableDetails(table, TRUE, ADD_MEMCHECK_ARGS(heap)); baseTablesByID_.insert(&tableDetails->getID(), tableDetails); } // Now do the same for the extra-hub tables. const QRTableListPtr extraHubTables = jbbDesc_->getExtraHub()->getTableList(); if (extraHubTables != NULL) { for (CollIndex j=0; j<extraHubTables->entries(); j++) { const QRTablePtr table = (*extraHubTables)[j]; if (table->hasLOJParent()) hasLOJs_ = TRUE; // Rest of the stuff only needed for MVs. if (!isAnMV_) continue; BaseTableDetailsPtr tableDetails = new(heap) BaseTableDetails(table, FALSE, ADD_MEMCHECK_ARGS(heap)); baseTablesByID_.insert(&tableDetails->getID(), tableDetails); } } }
// *************************************************************************** // Initialize the several hash tables that map output list elements: // outputByIDHash_ - Using the ID of the output item as the key. // outputByColumnName_ - Using the "ID Qualified" column name as the key. // outputByExprText_ - Using the expression text as the key. // outputByInputColumns_ - Using the name of expression input column as the key. // *************************************************************************** void MVDetails::initOutputs(const QRJBBPtr jbb, CollHeap* heap) { // Match the output elements with their names. const QROutputListPtr outputList = jbb->getOutputList(); assertLogAndThrow(CAT_MATCHTST_MVDETAILS, LL_MVQR_FAIL, outputList != NULL, QRLogicException, "Output list is null."); // For each output list element for (CollIndex i=0; i<outputList->entries(); i++) { QROutputPtr output = (*outputList)[i]; // Set the ordinal number of the output element. output->setColPos(i+1); // Get the output item (column or expression). QRElementPtr outputItem = output->getOutputItem()->getReferencedElement(); const NAString& id = outputItem->getID(); // Insert the ID of the output item (whatever it is) into the ID hash. outputByIDHash_.insert(&id, output); // OK, now lets check what type of output item it is. switch (outputItem->getElementType()) { case ET_Column: { // If its an output column, add it to the output column by name hash. const QRColumnPtr col = outputItem->downCastToQRColumn(); const QRElementPtr tableElem = getElementForID(col->getTableID()); NABoolean hasLOJParent = tableElem->downCastToQRTable()->hasLOJParent(); if (!isFromJoin(col) || hasLOJParent) { // Compute the "ID Qualified" column name as the key. const NAString* idQualifiedColName = calcIDQualifiedColumnName(col->getTableID(), col->getColumnName(), heap); // Insert into the hash table. outputByColumnName_.insert(idQualifiedColName, output); } else { // If its an equality set, insert all the participating columns // as pointing to the same MV output column. const QRJoinPredPtr jp = getJoinPred(col); const QRJoinPredPtr joinPredElement = jp->downCastToQRJoinPred(); addEqualitySet(joinPredElement, FALSE, output, heap); } break; } case ET_JoinPred: { assertLogAndThrow(CAT_MATCHTST_MVDETAILS, LL_MVQR_FAIL, (outputItem->getElementType() == ET_JoinPred), QRLogicException, "Unexpected JoinPred element."); // If its an equality set, insert all the participating columns // as pointing to the same MV output column. const QRJoinPredPtr joinPredElement = outputItem->downCastToQRJoinPred(); addEqualitySet(joinPredElement, FALSE, output, heap); break; } case ET_Expr: { // This is an expression. Insert the expression text into the expression hash. const QRExprPtr expr = outputItem->downCastToQRExpr(); const NAString& exprText = expr->getExprText(); outputByExprText_.insert(&exprText, output); QRLogger::log(CAT_MATCHTST_MVDETAILS, LL_DEBUG, "Adding output expression: %s.", exprText.data()); // Also map the expressions's input columns to it. // This call to getInitColumns() also inits the input list using the // right heap. const ElementPtrList& inputs = expr->getInputColumns(heap); if (inputs.entries() > 0) { for (CollIndex j=0; j<inputs.entries(); j++) { QRElementPtr inputElem = inputs[j]->getReferencedElement(); if (inputElem->getElementType() == ET_Column) { QRColumnPtr inputCol = inputElem->downCastToQRColumn(); // Compute the "ID Qualified" column name as the key. const NAString* idQualifiedColName = calcIDQualifiedColumnName(inputCol->getTableID(), inputCol->getColumnName(), heap); outputByInputColumns_.insert(idQualifiedColName, output); } else { QRJoinPredPtr inputJoinPred = inputElem->downCastToQRJoinPred(); addEqualitySet(inputJoinPred, TRUE, output, heap); } } } // Check if this is the COUNT(*) function. QRExplicitExprPtr rootExpr = expr->getExprRoot(); if (rootExpr->getElementType() == ET_Function) { QRFunctionPtr func = rootExpr->downCastToQRFunction(); if (func->getAggregateFunc() == QRFunction::AFT_COUNTSTAR) { // Found it, now remember it for later use. // If a COUNT(*) equivalent function has already been found // (see below) - overwrite it. countStar_ = output; } else if (countStar_ == NULL && func->isCountStarEquivalent(heap) ) { // Well, we didn't find a COUNT(*) yet, but we found a COUNT(a) // and the input column is NOT NOLL, we can use it as a COUNT(*) column. countStar_ = output; } } } // end of case ET_Expr break; } // switch on element type } // for on output list elements } // MVDetails::initOutputs()