public function prepareQueryRequest(DataQueryControllerCubeRequest $request) { $metamodel = data_controller_get_metamodel(); $cube = $metamodel->getCubeByDatasetName($request->datasetName); $datasourceRequest = new CubeQueryRequest($cube->name); // needs to be called before any additional methods are called $datasourceRequest->addOptions($request->options); $this->prepareRequestColumns($datasourceRequest, $cube, $request->columns); $this->prepareRequestQueries($datasourceRequest, $cube, $request->parameters); $datasourceRequest->addOrderByColumns($request->orderBy); $datasourceRequest->setPagination($request->limit, $request->startWith); return $datasourceRequest; }
protected function processCubeExpressionRequest(DataControllerCallContext $callcontext, CubeQueryRequest $expressionRequest, $resultColumnName) { // we need to return 2 records: first - 'the latest' and second is 'previous' $expressionRequest->setPagination(2, 0); return parent::processCubeExpressionRequest($callcontext, $expressionRequest, $resultColumnName); }
protected function selectBoundary4CubeRequest(DataControllerCallContext $callcontext, AbstractCubeQueryRequest $request, $datasetName, $columnName) { $isSortAscending = $this->isSortAscending(); $resultColumnName = NULL; // preparing new cube meta data $expressionRequest = new CubeQueryRequest($request->getCubeName()); // needs to be called before any additional methods are called $expressionRequest->addOptions($request->options); // copying ONLY some query objects (excluding at least a reference to this operator) // -- dimension queries $dimensionQueries = $request->findDimensionQueries(); if (isset($dimensionQueries)) { foreach ($dimensionQueries as $query) { foreach ($query->columns as $queryColumn) { foreach ($queryColumn->values as $value) { if ($this->shouldValueBeSkipped($value)) { continue; } // updating request configuration for the value supported by this class if ($this->operatorHandler === $value) { $resultColumnName = ParameterNameHelper::assemble($query->name, $queryColumn->name); // returning only observing column of the dimension $expressionRequest->addDimensionColumn(0, $query->name, $queryColumn->name); // ... and excluding NULL values from evaluation $expressionRequest->addDimensionColumnQueryValue( $query->name, $queryColumn->name, OperatorFactory::getInstance()->initiateHandler(NotEqualOperatorHandler::OPERATOR__NAME, NULL)); // sorting data $expressionRequest->addOrderByColumn( ColumnBasedComparator_AbstractSortingConfiguration::assembleDirectionalColumnName($resultColumnName, $isSortAscending)); } else { $expressionRequest->addDimensionColumnQueryValue($query->name, $queryColumn->name, $value); } } } } } // -- facts dataset column queries $factsDatasetColumnQueries = $request->findFactsDatasetColumnQueries(); if (isset($factsDatasetColumnQueries)) { foreach ($factsDatasetColumnQueries as $query) { $values = NULL; foreach ($query->values as $value) { if ($this->shouldValueBeSkipped($value)) { continue; } if ($this->operatorHandler === $value) { $metamodel = data_controller_get_metamodel(); $cube = $metamodel->getCube($expressionRequest->getCubeName()); // finding dimension associated with this fact column $selectedDimension = NULL; if (isset($cube->dimensions)) { foreach ($cube->dimensions as $dimension) { if ($dimension->attributeColumnName == $query->name) { $selectedDimension = $dimension; break; } } } if (!isset($selectedDimension)) { throw new IllegalArgumentException(t( 'Boundary-related operator cannot be applied to the facts dataset column: %columnName', array('%columnName' => $query->name))); } $resultColumnName = ParameterNameHelper::assemble($selectedDimension->name); // returning only observing column from facts dataset $expressionRequest->addDimension(0, $selectedDimension->name); // ... and excluding NULL values from evaluation $expressionRequest->addFactsDatasetColumnQueryValue( $query->name, OperatorFactory::getInstance()->initiateHandler(NotEqualOperatorHandler::OPERATOR__NAME, NULL)); // sorting data $expressionRequest->addOrderByColumn( ColumnBasedComparator_AbstractSortingConfiguration::assembleDirectionalColumnName($resultColumnName, $isSortAscending)); } else { $values[] = $value; } } if (isset($values)) { $expressionRequest->addFactsDatasetColumnQueryValues($query->name, $values); } } } // -- measure queries $measureQueries = $request->findMeasureQueries(); if (isset($measureQueries)) { foreach ($measureQueries as $query) { foreach ($query->values as $value) { if ($this->shouldValueBeSkipped($value)) { throw new IllegalArgumentException(t('Boundary-related operator cannot be applied to measures')); } } $expressionRequest->queries[] = clone $query; } } // limiting response to one record $expressionRequest->setPagination(1, 0); return $this->processCubeExpressionRequest($callcontext, $expressionRequest, $resultColumnName); }
protected function prepareCubeRequestMetaData(CubeQueryRequest $request) { $metamodel = data_controller_get_metamodel(); $cube = $metamodel->getCube($request->getCubeName()); $this->getDatasetMetaData($cube->sourceDatasetName); if (isset($request->referencedRequests)) { foreach ($request->referencedRequests as $referencedRequest) { $referencedCube = $metamodel->getCube($referencedRequest->getCubeName()); $this->getDatasetMetaData($referencedCube->sourceDatasetName); } } }
public function queryCube(DataControllerCallContext $callcontext, CubeQueryRequest $request, ResultFormatter $resultFormatter) { $records = NULL; $environment_metamodel = data_controller_get_environment_metamodel(); $metamodel = data_controller_get_metamodel(); $cubeName = $request->getCubeName(); $cube = $metamodel->getCube($cubeName); $cubeDatasetName = $cube->sourceDatasetName; $cubeDataset = $metamodel->getDataset($cubeDatasetName); $datasource = $environment_metamodel->getDataSource($cubeDataset->datasourceName); $designDocumentName = NameSpaceHelper::removeNameSpace($cubeName); $viewName = NameSpaceHelper::removeNameSpace($cubeName); $url = '/' . $cubeDataset->source->database . "/_design/$designDocumentName/_view/$viewName"; $dimensionCount = $cube->getDimensionCount(); $queryKeys = NULL; // TODO list of dimensions could be empty foreach ($cube->dimensions as $dimension) { $queryDimension = $request->findDimensionQuery($dimension->name); if (isset($queryDimension)) { $queryKeys[] = $queryDimension->values; } else { $queryKeys[] = NULL; } } // TODO develop more comprehensive validation or mapping if ($cube->getMeasureCount() != 1) { throw new UnsupportedOperationException(t('Only one measure is supported')); } $cubeMeasurePropertyName = NULL; foreach ($cube->measures as $measureName => $measure) { $cubeMeasurePropertyName = $measureName; } // preparing set of keys to access data $requestKeys = NULL; $this->prepareCubeRequestKeys($requestKeys, $queryKeys, 0, NULL); // preparing server requests if (isset($requestKeys)) { foreach ($requestKeys as $requestKey) { $parameterKey = ''; foreach ($requestKey as $dimensionKey) { $parameterKey .= self::prepareSingleValue($dimensionKey); } $parameterKey = '[' . substr($parameterKey, 0, strlen($parameterKey) - 1) . ']'; $serverRequest = NULL; $serverRequest->url = $url . "?key=$parameterKey"; // executing the server request $serverResponse = $this->communicateWithServer($datasource, $serverRequest); $this->checkDocumentExistence($serverResponse, TRUE); if (isset($serverResponse->rows[0])) { $record = NULL; // adding dimension-related properties for ($i = 0; $i < $dimensionCount; $i++) { // we should have data for a dimension to report related property if (!isset($requestKey[$i])) { continue; } $dimension = $cube->dimensions[$i]; $dimensionKey = $requestKey[$i]; // FIXME there is no support for targetKey any more $record[$dimension->targetKey] = $dimensionKey; } // adding measure value $record[$cubeMeasurePropertyName] = $serverResponse->rows[0]->value; $records[] = $record; } } } return $records; }
public function countCubeRecords(DataControllerCallContext $callcontext, CubeQueryRequest $request, ResultFormatter $resultFormatter) { $cubeName = $request->getCubeName(); LogHelper::log_notice(t('Counting SQL-based cube records: @cubeName', array('@cubeName' => $cubeName))); $environment_metamodel = data_controller_get_environment_metamodel(); $metamodel = data_controller_get_metamodel(); $cube = $metamodel->getCube($cubeName); $cubeDatasetName = $cube->sourceDatasetName; $cubeDataset = $metamodel->getDataset($cubeDatasetName); $datasource = $environment_metamodel->getDataSource($cubeDataset->datasourceName); $statement = $this->prepareCubeQueryStatement($callcontext, $request); list($isSubqueryRequired, $assembledSections) = $statement->prepareSections(NULL); $statement = new Statement(); $statement->tables[] = new SubquerySection(Statement::assemble($isSubqueryRequired, NULL, $assembledSections)); return $this->countRecords($callcontext, $datasource, array($statement)); }
public function queryCube(DataControllerCallContext $callcontext, CubeQueryRequest $request) { $cubeName = $request->getCubeName(); LogHelper::log_info(t('Querying SQL-based cube: @cubeName', array('@cubeName' => $cubeName))); $environment_metamodel = data_controller_get_environment_metamodel(); $metamodel = data_controller_get_metamodel(); $this->getExtension('adjustRequest')->adjustCubeQueryRequest($this, $request); $callcontext->columnMapping = NULL; $cube = $metamodel->getCube($cubeName); $factsDataset = $metamodel->getDataset($cube->factsDatasetName); $datasource = $environment_metamodel->getDataSource($factsDataset->datasourceName); $engine = QueryEngineFactory::getInstance()->getHandler(); $generationContext = $engine->prepareStatementGenerationContext($request, $cube); // aliases for tables $TABLE_ALIAS__JOIN = 'j'; $tableJoinIndex = 0; // preparing statement which aggregates data $aggrStatement = $this->prepareCubeQueryStatement($callcontext, $request); list($isSubqueryRequired, $assembledAggregationSections) = $aggrStatement->prepareSections(NULL); // assembling portion of SQL which is responsible for aggregation if (isset($request->referencedRequests)) { $joinStatement = $aggrStatement; // changing alias of first table. This new alias is expected the following code to join with lookup tables $joinStatement->updateTableAlias($joinStatement->tables[0]->alias, $TABLE_ALIAS__JOIN); } else { $joinStatement = new Statement(); $aggregationTableSection = new SubquerySection( Statement::assemble($isSubqueryRequired, NULL, $assembledAggregationSections, SelectStatementPrint::INDENT__SUBQUERY, FALSE), $TABLE_ALIAS__JOIN); $joinStatement->tables[] = $aggregationTableSection; } // adding support for dimension columns if (isset($request->dimensions)) { foreach ($request->dimensions as $requestDimension) { $dimensionName = $requestDimension->name; $dimension = $cube->findDimension($dimensionName); // we do not need to map the column. It was done in prepareCubeQueryStatement() $dimensionDatabaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements($this->getMaximumEntityNameLength(), $dimensionName); // adding support for dimension column $dimensionColumn = new ColumnSection($dimensionDatabaseColumnName); $dimensionColumn->requestColumnIndex = $requestDimension->requestColumnIndex; $dimensionColumn->visible = isset($requestDimension->requestColumnIndex); $aggregationTableSection->columns[] = $dimensionColumn; if (!isset($requestDimension->columns)) { continue; } // preparing list of columns which are accessed by this dataset $usedColumnNames = NULL; $dimensionColumnAliasMapping = NULL; foreach ($requestDimension->columns as $requestColumn) { $responseColumnName = ParameterNameHelper::assemble($dimensionName, $requestColumn->name); $databaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements( $this->getMaximumEntityNameLength(), $dimensionName, $requestColumn->name); $callcontext->columnMapping[$databaseColumnName] = $responseColumnName; ArrayHelper::addUniqueValue($usedColumnNames, $requestColumn->name); $dimensionColumnAliasMapping[$requestColumn->name] = $databaseColumnName; } $isJoinWithDimensionDatasetRequired = $generationContext->dimensionJoinPhase[__DefaultQueryEngine_StatementGenerationContext::DIMENSION_JOIN_PHASE__GROUPING_WITH_LOOKUP_AFTER][$dimensionName]; if ($isJoinWithDimensionDatasetRequired) { $tableJoinIndex++; $dimensionTableAlias = $TABLE_ALIAS__JOIN . $tableJoinIndex; $dimensionDataset = $metamodel->getDataset($dimension->datasetName); $isDimensionKeyColumnAdded = ArrayHelper::addUniqueValue($usedColumnNames, $dimension->key); $dimensionStatement = $this->prepareDatasetSourceStatement($callcontext, $request, $dimensionDataset, $usedColumnNames); // updating dimension statement table aliases $dimensionStatement->addTableAliasPrefix($dimensionTableAlias); foreach ($dimensionStatement->tables as $table) { if (!isset($table->columns)) { $table->columns = array(); // We do not need any columns } } // updating dimension statement column aliases foreach ($requestDimension->columns as $requestColumn) { $oldColumnAlias = $requestColumn->name; $newColumnAlias = $dimensionColumnAliasMapping[$oldColumnAlias]; $dimensionTableSection = $dimensionStatement->getColumnTable($oldColumnAlias, TRUE); $dimensionColumnSection = $dimensionTableSection->findColumnByAlias($oldColumnAlias); if (isset($dimensionColumnSection)) { $dimensionColumnSection->alias = $newColumnAlias; } else { $dimensionColumnSection = new ColumnSection($oldColumnAlias, $newColumnAlias); $dimensionTableSection->columns[] = $dimensionColumnSection; } $dimensionColumnSection->requestColumnIndex = $requestColumn->requestColumnIndex; } // adding condition to join with 'main' statement $dimensionKeyTableSection = $dimensionStatement->getColumnTable($dimension->key); $dimensionKeyTableSection->conditions[] = new JoinConditionSection( $dimension->key, new TableColumnConditionSectionValue($TABLE_ALIAS__JOIN, $dimensionDatabaseColumnName)); // merging with 'main' statement $joinStatement->merge($dimensionStatement); // we do not need to return dimension key column if ($isDimensionKeyColumnAdded && isset($dimensionKeyTableSection)) { // FIXME this code does not work in the following case: // - our lookup dataset is fact dataset // - we need to work with project_id column from that dataset // - the column is present in *_facts and contains numeric value // - the column is present in *_c_project_id table and contains numeric value // - column 'value' in *_c_project_id table assigned an alias project_id // - more about implementation is in ReferenceDimensionDatasetAssembler // - the code is partially fixed by using $visibleOnly parameter $tableSection = $dimensionStatement->getColumnTable($dimension->key, TRUE); $keyColumn = $tableSection->findColumnByAlias($dimension->key); if (isset($keyColumn)) { $keyColumn->visible = FALSE; } } } else { foreach ($requestDimension->columns as $requestColumn) { $oldColumnAlias = $requestColumn->name; $newColumnAlias = $dimensionColumnAliasMapping[$oldColumnAlias]; $column = new ColumnSection($newColumnAlias); $column->requestColumnIndex = $requestColumn->requestColumnIndex; $aggregationTableSection->columns[] = $column; } } } } $isJoinUsed = $tableJoinIndex > 0; if ($isJoinUsed) { // adding measures if (isset($request->measures)) { foreach ($request->measures as $requestMeasure) { $measureName = $requestMeasure->name; // we do not need to map the column. It was done in prepareCubeQueryStatement() $databaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements( $this->getMaximumEntityNameLength(), $measureName); $measureSection = new ColumnSection($databaseColumnName); $measureSection->requestColumnIndex = $requestMeasure->requestColumnIndex; $aggregationTableSection->columns[] = $measureSection; } } list($isSubqueryRequired, $assembledJoinSections) = $joinStatement->prepareSections(NULL); $sql = Statement::assemble($isSubqueryRequired, NULL, $assembledJoinSections); } else { $sql = Statement::assemble($isSubqueryRequired, NULL, $assembledAggregationSections); } // applying sorting if (isset($request->sortingConfigurations)) { $adjustedColumns = NULL; foreach ($request->sortingConfigurations as $sortingConfiguration) { // TODO try to use the same functionality for list and cube requests $adjustedColumn = DataSourceColumnNameHelper::generateFromParameterElements( $this->getMaximumEntityNameLength(), $sortingConfiguration->rootName, $sortingConfiguration->leafName); // adjusting direction of the sorting if (!$sortingConfiguration->isSortAscending) { $adjustedColumn = $adjustedColumn . ' DESC'; } $adjustedColumns[] = $adjustedColumn; } if (count($adjustedColumns) > 0) { $sql .= "\n ORDER BY " . implode(', ', $adjustedColumns); } } // applying pagination $this->applyPagination($request, $sql); // processing prepared sql and returning data LogHelper::log_info(new StatementLogMessage('cube.query', $sql)); return $this->executeQuery($callcontext, $datasource, $sql); }
protected function prepareReferencedCubeQueryStatement( AbstractSQLDataSourceQueryHandler $datasourceHandler, DataControllerCallContext $callcontext, Statement $combinedStatement, array $datasetMappedCubeRequests, ReferenceLink $link) { if (!isset($link->nestedLinks)) { return; } $metamodel = data_controller_get_metamodel(); foreach ($link->nestedLinks as $referencedLink) { $referencedRequest = NULL; if (isset($datasetMappedCubeRequests[$referencedLink->dataset->name])) { $referencedRequest = clone $datasetMappedCubeRequests[$referencedLink->dataset->name]; } else { // checking if there is corresponding cube for the referenced dataset $possibleReferencedCube = $metamodel->findCubeByDatasetName($referencedLink->dataset->name); if (isset($possibleReferencedCube)) { $referencedRequest = new CubeQueryRequest($possibleReferencedCube->name); $referencedRequest->referenced = TRUE; $datasetMappedCubeRequests[$possibleReferencedCube->factsDatasetName] = $referencedRequest; } } if (isset($referencedRequest)) { // preparing parent cube $parentRequest = $datasetMappedCubeRequests[$link->dataset->name]; $parentCubeName = $parentRequest->getCubeName(); $parentCube = $metamodel->getCube($parentCubeName); // preparing referenced cube $referencedCubeName = $referencedRequest->getCubeName(); $referencedCube = $metamodel->getCube($referencedCubeName); // adding required dimensions $joinConditions = NULL; foreach ($referencedLink->parentColumnNames as $columnIndex => $parentColumnName) { // looking for a dimension in parent cube $parentDimension = $parentCube->getDimensionByAttributeColumnName($parentColumnName); // looking for a dimension in referenced cube $referencedColumnName = $referencedLink->columnNames[$columnIndex]; $referencedDimension = $referencedCube->getDimensionByAttributeColumnName($referencedColumnName); // checking if this dimension is part of query portion of parent request $parentRequestDimensionQuery = $parentRequest->findDimensionQuery($parentDimension->name); if (isset($parentRequestDimensionQuery)) { // copying the query request to referenced cube $referencedRequestDimensionQuery = new __AbstractCubeQueryRequest_DimensionQuery($referencedDimension->name); $referencedRequestDimensionQuery->columns = $parentRequestDimensionQuery->columns; $referencedRequest->importDimensionQueryFrom($referencedRequestDimensionQuery); } // checking if there is a related query for parent column name $parentRequestFactsDatasetColumnQuery = $parentRequest->findFactsDatasetColumnQuery($parentColumnName); if (isset($parentRequestFactsDatasetColumnQuery)) { // copying the query request to referenced cube $referencedRequest->addFactsDatasetColumnQueryValues($referencedColumnName, $parentRequestFactsDatasetColumnQuery->values); } // checking if this dimension is part of parent request $parentRequestDimension = $parentRequest->findDimension($parentDimension->name); if (!isset($parentRequestDimension)) { // because this dimension is not in list of returned columns we should not use it to link with referenced cube continue; } $referencedRequestDimension = $referencedRequest->addDimension( NULL, // TODO support requestColumnIndex here $referencedDimension->name); $columnNames = $parentRequestDimension->getColumnNames(); if (isset($columnNames)) { foreach ($columnNames as $columnName) { $referencedRequestDimension->registerColumnName( NULL, // TODO support requestColumnIndex here $columnName); } } else { // to help the following loop to link cubes by dimension $columnNames = array(NULL); } foreach ($columnNames as $columnName) { $parentDatabaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements( $datasourceHandler->getMaximumEntityNameLength(), ($parentRequest->referenced ? ReferencePathHelper::assembleReference($parentCube->factsDatasetName, $parentDimension->name) : $parentDimension->name), $columnName); $referencedDatabaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements( $datasourceHandler->getMaximumEntityNameLength(), ReferencePathHelper::assembleReference($referencedCube->factsDatasetName, $referencedDimension->name), $columnName); $joinConditions[] = new JoinConditionSection( $referencedDatabaseColumnName, new TableColumnConditionSectionValue(self::$TABLE_ALIAS__REFERENCED . $link->linkId, $parentDatabaseColumnName)); } } if (!isset($joinConditions)) { throw new IllegalArgumentException(t( 'There is no common columns to join %datasetNameA and %datasetNameB datasets', array('%datasetNameA' => $parentCube->publicName, '%datasetNameB' => $referencedCube->publicName))); } // preparing aggregation statement for referenced cube $referencedAggregationStatement = $this->prepareSelectedCubeQueryStatement($datasourceHandler, $callcontext, $referencedRequest); list($isSubqueryRequired, $assembledReferencedCubeSections) = $referencedAggregationStatement->prepareSections(NULL); $referencedCubeSubquerySection = new SubquerySection( Statement::assemble($isSubqueryRequired, NULL, $assembledReferencedCubeSections, SelectStatementPrint::INDENT__LEFT_OUTER_JOIN__SUBQUERY, FALSE), self::$TABLE_ALIAS__REFERENCED . $referencedLink->linkId); // preparing columns which are returned by referenced aggregation foreach ($referencedAggregationStatement->tables as $table) { if (!isset($table->columns)) { continue; } foreach ($table->columns as $column) { if (!$column->visible) { continue; } $referencedCubeSubquerySection->columns[] = new ColumnSection($column->alias); } } // linking with parent cube foreach ($joinConditions as $joinCondition) { // we do not need to return columns which are used to join with parent cube $referencedCubeSubquerySection->getColumn($joinCondition->subjectColumnName)->visible = FALSE; $referencedCubeSubquerySection->conditions[] = $joinCondition; } // adding to resulting statement $combinedStatement->tables[] = $referencedCubeSubquerySection; // applying referenced cubes measure conditions on resulting statement as well $measureQueries = $referencedRequest->findMeasureQueries(); if (isset($measureQueries)) { foreach ($measureQueries as $measureQuery) { $measureName = ReferencePathHelper::assembleReference($referencedCube->factsDatasetName, $measureQuery->name); $measureDatabaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements( $datasourceHandler->getMaximumEntityNameLength(), $measureName); foreach ($measureQuery->values as $value) { $combinedStatement->conditions[] = new WhereConditionSection( self::$TABLE_ALIAS__REFERENCED . $referencedLink->linkId, $measureDatabaseColumnName, new ExactConditionSectionValue( $datasourceHandler->formatOperatorValue($callcontext, $referencedRequest, $referencedCube->factsDatasetName, NULL, $value))); } } } } else { throw new UnsupportedOperationException(t('Cube joins using intermediate dataset is not supported yet')); // preparing statement for intermediate dataset $requiredColumnNames = $referencedLink->columnNames; $referencedIntermediateDatasetStatement = $datasourceHandler->prepareDatasetSourceStatement($callcontext, NULL, $referencedLink->dataset, $requiredColumnNames); // adding condition to join with parent statement $referencedIntermediateDatasetTableSection = $referencedIntermediateDatasetStatement->tables[0]; foreach ($referencedLink->columnNames as $columnIndex => $referencedColumnName) { $referencedDatabaseColumnName = $referencedColumnName; $parentColumnName = $referencedLink->parentColumnNames[$columnIndex]; $parentDatabaseColumnName = $parentColumnName; $referencedIntermediateDatasetTableSection->conditions[] = new JoinConditionSection( $referencedDatabaseColumnName, new TableColumnConditionSectionValue(self::$TABLE_ALIAS__REFERENCED . $link->linkId, $parentDatabaseColumnName)); } $combinedStatement->merge($referencedIntermediateDatasetStatement); } // recursively check nested levels $this->prepareReferencedCubeQueryStatement($datasourceHandler, $callcontext, $combinedStatement, $datasetMappedCubeRequests, $referencedLink); } }
protected function selectBoundary4CubeRequest(DataControllerCallContext $callcontext, CubeQueryRequest $request, $datasetName, $columnName) { $isSortAscending = $this->isSortAscending(); $resultColumnName = NULL; // preparing new cube meta data $expressionRequest = new CubeQueryRequest($request->getCubeName()); // copying ONLY some query objects (excluding at least a reference to this operator) // -- dimension queries $dimensionQueries = $request->findDimensionQueries(); if (isset($dimensionQueries)) { foreach ($dimensionQueries as $query) { foreach ($query->values as $propertyValue) { foreach ($propertyValue->values as $value) { if ($value->isSubsetBased()) { // skipping other instances which are based on subset of data if their weight is greater than of this operator if (isset($value->weight) && $value->weight > $this->operatorHandler->weight) { continue; } } // updating request configuration for the value supported by this class if ($this->operatorHandler === $value) { $resultColumnName = ParameterHelper::assembleParameterName($query->dimensionName, $query->levelName, $propertyValue->name); // returning only observing property of the dimension level $expressionRequest->addDimensionLevelProperty(0, $query->dimensionName, $query->levelName, $propertyValue->name); // ... and excluding NULL values from evaluation $expressionRequest->addDimensionLevelPropertyQueryValue($query->dimensionName, $query->levelName, $propertyValue->name, data_controller_get_operator_factory_instance()->initiateHandler(NotEqualOperatorHandler::$OPERATOR__NAME, NULL)); // sorting data $expressionRequest->addOrderByColumn(PropertyBasedComparator_DefaultSortingConfiguration::assembleDirectionalPropertyName($resultColumnName, $isSortAscending)); } else { $expressionRequest->addDimensionLevelPropertyQueryValue($query->dimensionName, $query->levelName, $propertyValue->name, $value); } } } } } // -- source dataset property queries $sourceDatasetPropertyQueries = $request->findSourceDatasetPropertyQueries(); if (isset($sourceDatasetPropertyQueries)) { foreach ($sourceDatasetPropertyQueries as $query) { foreach ($query->values as $value) { if ($value->isSubsetBased()) { throw new UnsupportedOperationException(t('Boundary-related operator cannot filter cube source dataset property values yet')); } } $expressionRequest->queries[] = clone $query; } } // -- measure queries $measureQueries = $request->findMeasureQueries(); if (isset($measureQueries)) { foreach ($measureQueries as $query) { foreach ($query->values as $value) { if ($value->isSubsetBased()) { throw new UnsupportedOperationException(t('Boundary-related operator cannot filter measure values yet')); } } $expressionRequest->queries[] = clone $query; } } // limiting response to one record $expressionRequest->setPagination(1, 0); return $this->processCubeExpressionRequest($callcontext, $expressionRequest, $resultColumnName); }
protected function useApplicableCubeRegions(CubeQueryRequest $request, CubeMetaData $cube) { $metamodel = data_controller_get_metamodel(); if (!isset($cube->regions)) { return; } // FIXME add support for measures in query list. Selected region needs to suport not only returning measures but also querying onces $isExactMatchRequired = FALSE; if (isset($request->measures)) { foreach ($request->measures as $requestMeasure) { $measureName = $requestMeasure->measureName; $cubeMeasure = $cube->findMeasure($measureName); if (isset($cubeMeasure) && isset($cubeMeasure->aggregationType)) { switch ($cubeMeasure->aggregationType) { case MeasureTypes::ADDITIVE: break; case MeasureTypes::SEMI_ADDITIVE: case MeasureTypes::NON_ADDITIVE: $isExactMatchRequired = TRUE; break; default: throw new UnsupportedOperationException(t('Unsupported measure aggregation type: @measureAggregationType', array('@measureAggregationType' => $cubeMeasure->aggregationType))); } } } } // collecting possible eligible regions $eligibleRegionNames = NULL; foreach ($cube->regions as $regionName => $region) { // checking if the region supports all requested measures if (isset($request->measures)) { foreach ($request->measures as $requestMeasure) { if (!isset($region->measures[$requestMeasure->measureName])) { continue 2; } } } $eligibleRegionNames[] = $regionName; } if (!isset($eligibleRegionNames)) { return; } // filtering eligible regions based on requested or queried dimensions if (isset($request->dimensions)) { $this->excludeIneligibleRegions($cube, $eligibleRegionNames, $request->dimensions, $isExactMatchRequired); } if (isset($request->queries)) { $this->excludeIneligibleRegions($cube, $eligibleRegionNames, $request->queries, $isExactMatchRequired); } // do we still have any regions which could be used for the request if (count($eligibleRegionNames) === 0) { return; } // we select first region suitable for the request $selectedRegionName = reset($eligibleRegionNames); $selectedRegion = $cube->regions->{$selectedRegionName}; // preparing new cube configuration $regionCube = new CubeMetaData(); $regionCube->name = "{$cube->name}_using_{$selectedRegionName}_region"; // source dataset $regionCube->sourceDatasetName = $selectedRegion->datasetName; // dimensions if (isset($cube->dimensions)) { foreach ($cube->dimensions as $dimension) { $dimensionName = $dimension->name; if (!isset($selectedRegion->dimensions->{$dimensionName})) { continue; } $regionCubeDimension = $regionCube->registerDimension($dimensionName); $selectedRegionDimension = $selectedRegion->dimensions->{$dimensionName}; if (isset($selectedRegionDimension->levels)) { // we need to prepare new dimension which contains levels which are supported by this region $sourceLevel = NULL; $isSelectedLevelFound = FALSE; foreach ($dimension->levels as $level) { $levelName = $level->name; if (!$isSelectedLevelFound && isset($level->sourceColumnName)) { $sourceLevel = $level; } $isLevelPresent = isset($selectedRegionDimension->levels->{$levelName}); if ($isLevelPresent) { if ($isSelectedLevelFound) { throw new UnsupportedOperationException(t("Only one level is supported yet for each dimension in '@selectedRegionName' region of '@cubeName' cube", array('@selectedRegionName' => $selectedRegionName, '@cubeName' => $cube->publicName))); } $isSelectedLevelFound = TRUE; } if ($isSelectedLevelFound) { $regionLevel = $regionCubeDimension->registerLevel($levelName); $regionLevel->initializeFrom($level); if ($isLevelPresent) { $regionLevel->sourceColumnName = $sourceLevel->sourceColumnName; } elseif (isset($regionLevel->sourceColumnName)) { // we cannot support source key on consecutive levels. It is only supported for 'virtual' cubes unset($regionLevel->sourceColumnName); } } } } else { $regionCubeDimension->initializeFrom($dimension); } } } // measures if (isset($request->measures)) { foreach ($request->measures as $requestMeasure) { $measureName = $requestMeasure->measureName; $cubeMeasure = $cube->getMeasure($measureName); $regionMeasure = $regionCube->registerMeasure($measureName); $regionMeasure->initializeFrom($cubeMeasure); } } // FIXME the following code will throw an exception if we try to reuse the same region during execution of a PHP script // registering the cube in meta model $regionCube->temporary = TRUE; // FIXME when loading meta model automatically create cubes for all regions $metamodel->registerCube($regionCube); // updating the request to use new cube LogHelper::log_notice(t("Using '@selectedRegionName' region of '@cubeName' cube", array('@selectedRegionName' => $selectedRegionName, '@cubeName' => $cube->name))); LogHelper::log_info(t('Creating temporary cube to satisfy this request: @regionCubeName', array('@regionCubeName' => $regionCube->name))); // FIXME create new request and delete the following method in request class $request->setCubeName($regionCube->name); }
public function importMeasureQueriesFrom(CubeQueryRequest $sourceQueryRequest) { $sourceMeasureQueries = $sourceQueryRequest->findMeasureQueries(); if (isset($sourceMeasureQueries)) { foreach ($sourceMeasureQueries as $sourceMeasureQuery) { $this->importMeasureQueryFrom($sourceMeasureQuery); } } }