// 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
        }
    }
Пример #2
0
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()