Beispiel #1
0
 /**
  * @param $root Response root element.
  *
  * @throws OLAPException
  */
 private function createMetaData(DOMElement $root)
 {
     $olapInfo = XMLAUtil::findChild($root, XMLAUtil::MDDATASET_NS, "OlapInfo");
     $cubeInfo = XMLAUtil::findChild($olapInfo, XMLAUtil::MDDATASET_NS, "CubeInfo");
     $cubeNode = XMLAUtil::findChild($cubeInfo, XMLAUtil::MDDATASET_NS, "Cube");
     $cubeNameNode = XMLAUtil::findChild($cubeNode, XMLAUtil::MDDATASET_NS, "CubeName");
     $cubeName = XMLAUtil::gatherText($cubeNameNode);
     // REVIEW: If there are multiple cubes with the same name, we should
     // qualify by catalog and schema. Currently we just take the first.
     $cube = $this->lookupCube($this->statement->getConnection()->getMetadata(), $cubeName);
     if ($cube == null) {
         throw new OLAPException("Internal error: cube '{$cubeName}' not found.");
     }
     // REVIEW: We should not modify the connection. It is not safe, because
     // connection might be shared between multiple statements with different
     // cubes. Caller should call
     //
     // connection.setCatalog(
     //   cellSet.getMetaData().getCube().getSchema().getCatalog().getName())
     //
     // before doing metadata queries.
     $this->statement->getConnection()->setCatalog($cube->getSchema()->getCatalog()->getName());
     $axesInfo = XMLAUtil::findChild($olapInfo, XMLAUtil::MDDATASET_NS, "AxesInfo");
     $axisInfos = XMLAUtil::findChildren($axesInfo, XMLAUtil::MDDATASET_NS, "AxisInfo");
     $axisMetaDataList = array();
     $filterAxisMetaData = null;
     foreach ($axisInfos as $axisInfo) {
         $axisName = $axisInfo->getAttribute('name');
         $axis = $this->lookupAxis($axisName);
         $hierarchyInfos = XMLAUtil::findChildren($axisInfo, XMLAUtil::MDDATASET_NS, 'HierarchyInfo');
         $hierarchyList = array();
         /*
                 <OlapInfo>
            <AxesInfo>
                <AxisInfo name="Axis0">
                    <HierarchyInfo name="Customers">
                        <UName name="[Customers].[MEMBER_UNIQUE_NAME]"/>
                        <Caption name="[Customers].[MEMBER_CAPTION]"/>
                        <LName name="[Customers].[LEVEL_UNIQUE_NAME]"/>
                        <LNum name="[Customers].[LEVEL_NUMBER]"/>
                        <DisplayInfo name="[Customers].[DISPLAY_INFO]"/>
                    </HierarchyInfo>
                </AxisInfo>
                ...
            </AxesInfo>
            <CellInfo>
                <Value name="VALUE"/>
                <FmtValue name="FORMATTED_VALUE"/>
                <FormatString name="FORMAT_STRING"/>
            </CellInfo>
                 </OlapInfo>
         */
         $propertyList = array();
         foreach ($hierarchyInfos as $hierarchyInfo) {
             $hierarchyName = $hierarchyInfo->getAttribute('name');
             $hierarchy = $this->lookupHierarchy($cube, $hierarchyName);
             $hierarchyList[] = $hierarchy;
             foreach (XMLAUtil::childElements($hierarchyInfo) as $childNode) {
                 $tag = $childNode->localName;
                 if (in_array($tag, self::$standardProperties)) {
                     continue;
                 }
                 $propertyUniqueName = $childNode->getAttribute('name');
                 $property = new XMLACellSetMemberProperty($propertyUniqueName, $hierarchy, $tag);
                 $propertyList[] = $property;
             }
         }
         $axisMetaData = new XMLACellSetAxisMetaData($this->statement->getConnection(), $axis, $hierarchyList, $propertyList);
         if ($axis->isFilter()) {
             $filterAxisMetaData = $axisMetaData;
         } else {
             $axisMetaDataList[] = $axisMetaData;
         }
     }
     if ($filterAxisMetaData == null) {
         $filterAxisMetaData = new XMLACellSetAxisMetaData($this->statement->getConnection(), Axis::getEnum(Axis::FILTER), array(), array());
     }
     $cellInfo = XMLAUtil::findChild($olapInfo, XMLAUtil::MDDATASET_NS, 'CellInfo');
     $cellProperties = array();
     foreach (XMLAUtil::childElements($cellInfo) as $element) {
         $cellProperties[] = new XMLACellProperty($element->localName, $element->getAttribute('name'));
     }
     return new XMLACellSetMetaData($this->statement, $cube, $filterAxisMetaData, $axisMetaDataList, $cellProperties);
 }
 /**
  * Executes an XMLA metadata request and returns the root element of the
  * response.
  *
  * @param $request XMLA request string
  *
  * @return DOMElement Root element of the response
  * @throws OLAPException on error
  */
 public function executeMetadataRequest($request, $cachable = true)
 {
     // check the cache for data before executing the meta data request
     $requestHash = crc32($request);
     if (array_key_exists($requestHash, $this->localCache)) {
         return $this->localCache[$requestHash];
     } else {
         if ($cachable && $this->cache != null && ($cachedResponseXML = $this->cache->get($requestHash)) != false) {
             if ($this->logger && $this->debug) {
                 $this->logger->debug(__CLASS__, '********************** Cache hit **********************');
             }
             $doc = new \DOMDocument();
             $doc->loadXML($cachedResponseXML);
         } else {
             if ($this->logger && $this->debug) {
                 $this->logger->debug(__CLASS__, '********************** SENDING REQUEST **********************');
                 $this->logger->debug(__CLASS__, $request);
             }
             $doc = $this->sendXMLA($request);
             if ($this->logger && $this->debug) {
                 $this->logger->debug(__CLASS__, '******* RECEIVED RESPONSE *******');
                 $this->logger->debug(__CLASS__, $doc->saveXML());
             }
             $cachableXML = $doc->saveXML();
             if ($cachable && $this->cache != null) {
                 $this->cache->set($requestHash, $cachableXML);
             }
         }
     }
     // <SOAP-ENV:Envelope>
     //   <SOAP-ENV:Header/>
     //   <SOAP-ENV:Body>
     //     <xmla:DiscoverResponse>
     //       <xmla:return>
     //         <root>
     //           (see below)
     //         </root>
     //       <xmla:return>
     //     </xmla:DiscoverResponse>
     //   </SOAP-ENV:Body>
     // </SOAP-ENV:Envelope>
     $envelope = $doc->documentElement;
     //if (DEBUG) {
     //   System.out.println("** SERVER RESPONSE :");
     //   System.out.println(XmlaOlap4jUtil.toString(doc, true));
     //}
     assert($envelope->localName == 'Envelope');
     assert($envelope->namespaceURI == XMLAUtil::SOAP_NS);
     $body = XMLAUtil::findChild($envelope, XMLAUtil::SOAP_NS, 'Body');
     $fault = XMLAUtil::findChild($body, XMLAUtil::SOAP_NS, 'Fault');
     if ($fault != null) {
         // had an error, need to invalidate the cached item so we don't end up
         // caching invalid data
         if ($cachable && $this->cache != null) {
             $this->cache->delete($requestHash);
         }
         /*
                 <SOAP-ENV:Fault>
           <faultcode>SOAP-ENV:Client.00HSBC01</faultcode>
           <faultstring>XMLA connection datasource not found</faultstring>
           <faultactor>Mondrian</faultactor>
           <detail>
               <XA:error xmlns:XA="http://mondrian.sourceforge.net">
                   <code>00HSBC01</code>
                   <desc>The Mondrian XML: Mondrian Error:Internal
                       error: no catalog named 'LOCALDB'</desc>
               </XA:error>
           </detail>
                 </SOAP-ENV:Fault>
         */
         // TODO: log doc to logfile
         $fault = $fault->ownerDocument->saveXML($fault);
         //$request = $request->ownerDocument->saveXML ( $request );
         throw new OLAPException('XMLA provider gave exception: ' . $fault . ' Request [' . $request . ']');
         //throw getHelper().createException(
         //    "XMLA provider gave exception: "
         //    + XmlaOlap4jUtil.prettyPrint(fault)
         //    + "\n"
         //    + "Request was:\n"
         //    + request);
     }
     $discoverResponse = XMLAUtil::findChild($body, XMLAUtil::XMLA_NS, 'DiscoverResponse');
     $returnElement = XMLAUtil::findChild($discoverResponse, XMLAUtil::XMLA_NS, 'return');
     $rootElement = XMLAUtil::findChild($returnElement, XMLAUtil::ROWSET_NS, 'root');
     // cache this element locally for future retrieval
     $this->localCache[$requestHash] = $rootElement;
     return $rootElement;
 }