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);
 }
示例#11
0
 public function importMeasureQueriesFrom(CubeQueryRequest $sourceQueryRequest)
 {
     $sourceMeasureQueries = $sourceQueryRequest->findMeasureQueries();
     if (isset($sourceMeasureQueries)) {
         foreach ($sourceMeasureQueries as $sourceMeasureQuery) {
             $this->importMeasureQueryFrom($sourceMeasureQuery);
         }
     }
 }