// Send a MATCH message to the given qms process, and receive a result // descriptor in response. QRXmlMessageObj* MvQueryRewriteServer::sendMatchMessage(IpcServer* qms, XMLString* qryDescText, CollHeap * heap) { NAString optName("optimizer"); QRMessageStream msgStream(ipcEnv_, optName, heap, QR::MATCH_REQUEST); QRXmlMessageObj* msgPtr = new QRXmlMessageObj(qryDescText, QR::MATCH_REQUEST); // Add QMS process as a recipient of the message. assertLogAndThrow(CAT_SQL_COMP_QR_IPC, LL_ERROR, qms, QRLogicException, "Null qms passed to sendMatchMessage"); IpcConnection* conn = qms->getControlConnection(); msgStream.addRecipient(conn); msgStream.clearAllObjects(); // Insert message object into the message stream msgStream << *msgPtr; // Send the message stream to the server msgStream.send(); msgPtr->decrRefCount(); // Read the reply from the server msgStream.setType(QR::MATCH_RESPONSE); msgStream.receive(); QRXmlMessageObj* xmlResponse = NULL; if (msgStream.moreObjects()) { Lng32 t = msgStream.getNextObjType(); switch (t) { case QR::MATCH_RESPONSE: // Get the message object containing the result descriptor. This // is returned as the function result, and the caller must // decrement the reference count when through with it. xmlResponse = new QRXmlMessageObj(NULL, QR::MATCH_RESPONSE); msgStream >> *xmlResponse; break; case QR::STATUS_RESPONSE: { QRStatusMessageObj* statusResponse = new QRStatusMessageObj(); msgStream >> *statusResponse; QRLogger::log(CAT_SQL_COMP_QR_IPC, LL_DEBUG, "STATUS RESPONSE received: %d\n", (Int32)statusResponse->getStatusCode()); statusResponse->decrRefCount(); } break; // LCOV_EXCL_START :rfi default: QRLogger::log(CAT_SQL_COMP_QR_IPC, LL_ERROR, "Unexpected response type: %d.", t); // LCOV_EXCL_LINE :rfi break; // LCOV_EXCL_STOP } if (msgStream.moreObjects()) { // LCOV_EXCL_START :rfi QRLogger::log(CAT_SQL_COMP_QR_IPC, LL_WARN, "Match request received one or more extraneous response " "objects, which were discarded"); msgStream.clearAllObjects(); // LCOV_EXCL_STOP } }
RelExpr* MvQueryRewriteHandler::handleMvQueryRewrite(QueryAnalysis* qa, RelExpr* expr, NAString& warningMessage) { // Allocate a temporary heap for MV query rewrite // This heap will self-destruct when it goes out of scope at the end of this method. NAHeap mvqrHeap("Heap for MV Query Rewrite", NAMemory::DERIVED_FROM_SYS_HEAP, (Lng32)32768); CMPASSERT(expr->getOperatorType() == REL_ROOT); RelRoot* rootExpr = static_cast<RelRoot*>(expr); // For AnalyzeOnly queries, force the XML to be formatted. NABoolean formatXml = formatXml_; if (rootExpr->isAnalyzeOnly()) formatXml = true; // Do step 0 checks here. // ============================ // If there does not appear to be any likely benefit from applying query // rewrite, just return the original RelExpr. if (!rewriteWorthTrying(rootExpr)) { warningMessage = "Query too simple."; if (rootExpr->isAnalyzeOnly()) rootExpr = handleAnalyzeOnlyQuery(rootExpr, warningMessage); return rootExpr; } NAString MVName = ""; CmpCommon::getDefault(MVQR_WORKLOAD_ANALYSIS_MV_NAME, MVName); if (MVName != "") { // Add a log marker with query/MV name. QRLogger::log(CAT_QR_DESC_GEN, LL_INFO, "Log marker for query: %s", MVName.data()); } // Create the query descriptor // (or an MV descriptor if we are in workload analysis mode). // ============================ xmlText_ = NULL; QRDescriptorPtr requestDescriptor = NULL; QRDescGenerator descGenerator(formatXml, &mvqrHeap); if (rootExpr->isAnalyzeOnly() && CmpCommon::getDefault(MVQR_LOG_QUERY_DESCRIPTORS) == DF_DUMP_MV) { // Used for generating MV descriptors for queries in workload analysis mode. descGenerator.setDumpMvMode(); } try { if (descGenerator.isDumpMvMode()) { QRMVDescriptorPtr mvDesc = descGenerator.createMvDescriptor(qa, rootExpr); if (mvDesc) { requestDescriptor = mvDesc; mvDesc->setMvName(MVName, &mvqrHeap); mvDesc->getMisc()->setFromQuery(TRUE); } } else { requestDescriptor = descGenerator.createQueryDescriptor(qa, rootExpr); } xmlText_ = (requestDescriptor ? descGenerator.createXmlText(requestDescriptor) : NULL); } // LCOV_EXCL_START :rfi catch(QRDescriptorException e) { // Just ignore it and leave xmlText_ as NULL to skip the rest of this method. QRLogger::log(CAT_QR_HANDLER, LL_MVQR_FAIL, "DescriptorException thrown: %s, %s.", e.getMessage(), MVName.data()); if (rootExpr->isAnalyzeOnly()) rootExpr = handleAnalyzeOnlyQuery(rootExpr, e.getMessage()); warningMessage = e.getMessage(); return rootExpr; } catch(...) { // This exception was not yet logged. // Log it and then skip. QRLogger::log(CAT_QR_HANDLER, LL_MVQR_FAIL, "Unknown exception thrown during descriptor generation, %s.", MVName.data()); if (rootExpr->isAnalyzeOnly()) rootExpr = handleAnalyzeOnlyQuery(rootExpr, "Unknown exception thrown"); warningMessage = "Internal error"; return rootExpr; } // LCOV_EXCL_STOP if (xmlText_ == NULL) { if (rootExpr->isAnalyzeOnly()) rootExpr = handleAnalyzeOnlyQuery(rootExpr, "No descriptor generated"); } else { if (CmpCommon::getDefault(MVQR_LOG_QUERY_DESCRIPTORS) == DF_LOG) { // Dump the query descriptor to a file. //NAString queryDescFileName = fileNamePrefix_ + ".qd.xml"; //dumpToFile(queryDescFileName.data(), xmlText_->data()); } if (rootExpr->isAnalyzeOnly()) { // If this is an AnalyzeOnly query - handle that now. // ==================================================== qa->cleanup(rootExpr); RelExpr* result = handleAnalyzeOnlyQuery(rootExpr, xmlText_); delete xmlText_; return result; } else { try { // For R2.4 delivery only, don't go looking for a QMS process // unless we are going to publish to it as well. DefaultToken publishDest = CmpCommon::getDefault(MVQR_PUBLISH_TO); if (publishDest != DF_NONE) { // Do QMM ALLOCATE protocol here. // For now, each mxcmp uses its own private qms. // ============================ // Create server process if it doesn't already exist. IpcServer* qms = MvQueryRewriteServer::getQmsServer(publishDest); if (!qms) { // LCOV_EXCL_START :rfi QRLogger::log(CAT_QR_IPC, LL_MVQR_FAIL, "Match failed due to inability to connect to QMS."); if (rootExpr->isAnalyzeOnly()) rootExpr = handleAnalyzeOnlyQuery(rootExpr, "Can't connect to QMS"); return rootExpr; // Can't get a QMS // LCOV_EXCL_STOP } // Do QMS MATCH protocol here. // ============================ QRLogger::log(CAT_CMP_XML, LL_DEBUG, "MATCH REQUEST sent:"); QRLogger::log1(CAT_CMP_XML, LL_DEBUG, xmlText_->data()); QRXmlMessageObj* xmlResponse = MvQueryRewriteServer::sendMatchMessage(qms, xmlText_, STMTHEAP); // Handle MATCH response here. // ============================ // For non-success result, do nothing (no rewrite). Problem will have // already been logged. XMLElementPtr responseDescriptor = NULL; QRRequestResult result; if (xmlResponse) { result = parseXML(xmlResponse->getData(), xmlResponse->getLength(), responseDescriptor); QRLogger::log(CAT_CMP_XML, LL_DEBUG, "MATCH RESPONSE received:"); QRLogger::log1(CAT_CMP_XML, LL_DEBUG, xmlResponse->getData()); xmlResponse->decrRefCount(); } else result = ProtocolError; // LCOV_EXCL_LINE :rfi if (result == Success) { // Make sure the parsed document was a result descriptor. if (responseDescriptor->getElementType() != ET_ResultDescriptor) { // LCOV_EXCL_START :rfi QRLogger::log(CAT_QR_HANDLER, LL_MVQR_FAIL, "Response to MATCH request was an XML document with " "document element <%s> instead of <%s>", responseDescriptor->getElementName(), QRResultDescriptor::elemName); // LCOV_EXCL_STOP } else { MVCandidates mvCandidates(rootExpr, (QRQueryDescriptorPtr)requestDescriptor, descGenerator); QRResultDescriptorPtr resultDescriptor = static_cast<QRResultDescriptorPtr>(responseDescriptor); mvCandidates.analyzeResultDescriptor(resultDescriptor); } } } } // LCOV_EXCL_START :rfi catch(QRDescriptorException e) { // Exception has generated mx event, but not mvqr-logged. QRLogger::log(CAT_QR_HANDLER, LL_MVQR_FAIL, e.getMessage()); delete xmlText_; if (rootExpr->isAnalyzeOnly()) rootExpr = handleAnalyzeOnlyQuery(rootExpr, e.getMessage()); return rootExpr; } catch(MVCandidateException e) { // Exception has already been logged. delete xmlText_; if (rootExpr->isAnalyzeOnly()) rootExpr = handleAnalyzeOnlyQuery(rootExpr, e.getMessage()); return rootExpr; } catch(...) { // This exception was not yet logged. // Log it and then skip. QRLogger::log(CAT_QR_HANDLER, LL_MVQR_FAIL, "Unknown exception thrown during descriptor generation."); delete xmlText_; if (rootExpr->isAnalyzeOnly()) rootExpr = handleAnalyzeOnlyQuery(rootExpr, "Unknown exception thrown"); return rootExpr; } // LCOV_EXCL_STOP } delete xmlText_; xmlText_ = NULL; } return rootExpr; } // handleMvQueryRewrite()