MVCandidatesForJBBSubsetPtr QRGroupLattice::search(QRJBBPtr queryJbb, MVCandidatesForJBBPtr mvCandidates, QRJoinSubGraphMapPtr map, ElementPtrList* minimizedGroupingList) { QRTRACER("QRGroupLattice::search()"); DescriptorDetailsPtr queryDetails = mvCandidates->getAllCandidates()->getQueryDetails(); LatticeKeyList keyList(heap_); if (minimizedGroupingList) { if (!elementListToKeyList(*minimizedGroupingList, keyList, map, queryDetails, FALSE)) return NULL; } else { // Get the grouping columns of the passed query JBB, and create a key list // from them. Return now if there are no grouping items -- a query without a // Group By can't match an MV that has one. QRGroupByPtr groupBy = queryJbb->getGroupBy(); if (!groupBy) return NULL; // An aggregate query with no GroupBy has an empty key list. if (!getGroupingLatticeKeys(keyList, map, queryDetails, queryJbb, TRUE, FALSE)) return NULL; } // Create the search node, disallowing the addition of any new keys to the hash // table used by the lattice; if the key isn't already used, the node can have // no supersets. QRLatticeIndexSearchNode searchNode(keyList, lattice_, TRUE, heap_); if (!searchNode.isValid()) // because a key wasn't added return NULL; NAString keysText; searchNode.dumpNode(keysText, *lattice_->getKeyArr()); QRLogger::log(CAT_GRP_LATTCE_INDX, LL_DEBUG, "Searching LatticeIndex for: %s.", keysText.data()); // Find the supersets of the query's group-by list in the MV group lattice // index. For each lattice index node returned, create an MVCandidate // corresponding to each MV represented by that node, and add it to the // candidate list passed by the caller. NAPtrList<QRLatticeIndexNodePtr> nodes; lattice_->findSupersets(searchNode, nodes); if (nodes.entries() == 0) { QRLogger::log(CAT_GRP_LATTCE_INDX, LL_DEBUG, "No match found."); return NULL; } MVCandidatesForJBBSubsetPtr jbbSubset = new(heap_) MVCandidatesForJBBSubset(mvCandidates, ADD_MEMCHECK_ARGS(heap_)); jbbSubset->setSubGraphMap(map); jbbSubset->setGroupBy(TRUE); if (minimizedGroupingList != NULL) jbbSubset->setMinimizedGroupingList(minimizedGroupingList); for (CollIndex i=0; i<nodes.entries(); i++) { QRLatticeIndexNodePtr thisNode = nodes[i]; const SubGraphMapList& matchingMVs = thisNode->getMVs(); NABoolean isPreferred = (*thisNode == searchNode); // preferred if exact match GroupingList* extraGroupingColumns = new(heap_) GroupingList(heap_); if (!isPreferred) { // For preferred match modes, there are no extraGroupingColumns. LatticeKeySubArray* diff = thisNode->computeDiff(searchNode, heap_); for(CollIndex i = 0; diff->nextUsed(i); i++) { LatticeIndexablePtr key = diff->element(i); QRElementPtr elem = keyToElement(key, map); extraGroupingColumns->insert(elem); } delete diff; } for (CollIndex j=0; j<matchingMVs.entries(); j++) { MVDetailsPtr mv = matchingMVs[j]->getMVDetails(); QRLogger::log(CAT_GRP_LATTCE_INDX, LL_DEBUG, "Found MV: %s!", mv->getMVName().data() ); jbbSubset->insert(mv, queryJbb, isPreferred, extraGroupingColumns, NULL, heap_); } } return jbbSubset; } // QRGroupLattice::search()
NABoolean MVCandidate::CheckExtraHubTables() { if (extraHubTables_.entries() == 0) return TRUE; // Allocate a new subGraph and subGraphMap for the MV - the one we have is from MVMemo, // so its considered read-only. QRJoinSubGraphMapPtr mvSubGraphMap = new(heap_) QRJoinSubGraphMap(*getMvSubGraphMap(), ADD_MEMCHECK_ARGS(heap_)); // The query subGraph is shared between the MVCandidates that were found // in the same MVMemo group, so work on a copy. QRJoinSubGraphMapPtr querySubGraphMap = new(heap_) QRJoinSubGraphMap(*getJbbSubset()->getQuerySubGraphMap(), ADD_MEMCHECK_ARGS(heap_)); // Loop over the list, each time picking an extra-hub table that is // directly connected to a table already in the matched sub-graph, // until all the tables are checked. do { NABoolean extraHubTableWasAdded = FALSE; // Do the loop backwards because we remove checked extra-hub tables from the list. for (Int32 i=(CollIndex)extraHubTables_.entries()-1; i>=0; i--) { if (CheckAnExtraHubTable(extraHubTables_[i], mvSubGraphMap, // IN/OUT querySubGraphMap, // IN/OUT extraHubTableWasAdded) == FALSE) return FALSE; } // for // Keep looping as long as there are extra-hub tables that are not connected, // and as long as we keep adding them. if (!extraHubTableWasAdded && extraHubTables_.entries() > 0) { logMVWasDisqualified1("Extra hub table %s is needed but cannot be matched.", extraHubTables_[0]->data()); return FALSE; } // assertLogAndThrow(extraHubTableWasAdded, QRLogicException, // "Extra-hub table is not connected to the hub."); } while (extraHubTables_.entries() > 0); // Update the MV new subGraphMap mvSubGraphMap_ = mvSubGraphMap; // We have added at least one extra-hub table - // now we need to reorg the JBBSubsets accordingly. MVCandidatesForJBBPtr jbb = getJbbSubset()->getJbbCandidates(); MVCandidatesForJBBSubsetPtr newJbbSubset = NULL; QRJoinSubGraphPtr querySubGraph = querySubGraphMap->getSubGraph(); if (jbb->contains(querySubGraph)) { // The JBBSubset with the new extra-hub tables already exists. newJbbSubset = jbb->getJbbSubsetFor(querySubGraph); } else { // Need to create a new JBBSubset. newJbbSubset = new (heap_) MVCandidatesForJBBSubset(jbb, ADD_MEMCHECK_ARGS(heap_)); newJbbSubset->setSubGraphMap(querySubGraphMap); // Add the new JbbSubset to the JBB. jbb->insert(newJbbSubset); } // Move the candidate from the current JbbSubset to the new one. getJbbSubset()->remove(this); newJbbSubset->insert(this); setJbbSubset(newJbbSubset); return TRUE; } // CheckExtraHubTables()