protected function formatColumnNameImpl($uiMetaDataName) {
        $columnName = NULL;

        $formattedUIMetaDataName = parent::formatColumnNameImpl($uiMetaDataName);

        list($elementNameSpace, $elementName) = AbstractDatasetUIMetaDataGenerator::splitElementUIMetaDataName($formattedUIMetaDataName);
        switch ($elementNameSpace) {
            case AbstractAttributeUIMetaData::NAME_SPACE:
                list($dimensionName, $dimensionColumnName) = ParameterNameHelper::split($elementName);
                // TODO do we need to check for resource?
                list(, $columnName) = ReferencePathHelper::splitReference($dimensionName);

                $column = $this->dataset->getColumn($dimensionName);
                if ($column->type->getReferencedDatasetName() != NULL) {
                    // this column should not be used
                    if (isset($dimensionColumnName) && $column->type->getReferencedColumnName() != $dimensionColumnName) {
                        $columnName = NULL;
                    }
                }

                break;
            case AbstractMeasureUIMetaData::NAME_SPACE:
                throw new IllegalArgumentException(t('Measures are not supported by this result formatter'));
        }

        return $columnName;
    }
    public function serialize(AbstractQueryRequest $request) {
        $parameters = parent::serialize($request);

        $columns = NULL;
        // preparing dimension-related column
        if (isset($request->dimensions)) {
            foreach ($request->dimensions as $dimension) {
                if (isset($dimension->requestColumnIndex)) {
                    $columns[] = ParameterNameHelper::assemble($dimension->name);
                }
                if (isset($dimension->columns)) {
                    foreach ($dimension->columns as $column) {
                        $columns[] = ParameterNameHelper::assemble($dimension->name, $column->name);
                    }
                }
            }
        }
        // preparing measure-related columns
        if (isset($request->measures)) {
            foreach ($request->measures as $measure) {
                $columns[] = $measure->name;
            }
        }
        // serializing columns
        if (isset($columns)) {
            ArrayHelper::merge(
                $parameters,
                $this->serializeValue(
                    DataQueryControllerUIParameterNames::COLUMNS,
                    DataQueryControllerUIRequestPreparer::prepareColumns($columns)));
        }

        // serializing query
        if (isset($request->queries)) {
            $queryParameters = NULL;
            foreach ($request->queries as $query) {
                if ($query instanceof __AbstractCubeQueryRequest_DimensionQuery) {
                    if (isset($query->columns)) {
                        foreach ($query->columns as $column) {
                            ArrayHelper::merge(
                                $queryParameters,
                                DataQueryControllerUIRequestPreparer::prepareParameter(
                                    ParameterNameHelper::assemble($query->name, $column->name),
                                    $column->values));
                        }
                    }
                }
                elseif ($query instanceof __AbstractCubeQueryRequest_FactsDatasetColumnQuery) {
                    ArrayHelper::merge($queryParameters, DataQueryControllerUIRequestPreparer::prepareParameter($query->name, $query->values));
                }
                elseif ($query instanceof __AbstractCubeQueryRequest_MeasureQuery) {
                    ArrayHelper::merge($queryParameters, DataQueryControllerUIRequestPreparer::prepareParameter($query->name, $query->values));
                }
            }
            ArrayHelper::merge($parameters, $this->serializeValue(DataQueryControllerUIParameterNames::PARAMETERS, $queryParameters));
        }

        return $parameters;
    }
    public static function generateFromParameterElements($maximumLength, $rootName, $leafName = NULL) {
        $columnName = ParameterNameHelper::assemble(
            self::generateFromReference($rootName),
            self::generateFromReference($leafName),
            '_');

        return self::generateFromColumnName($maximumLength, $columnName);
    }
    protected function detectParameterKind(AbstractCubeQueryRequest $request, CubeMetaData $cube, $parameterName) {
        $metamodel = data_controller_get_metamodel();

        list($rootName, $leafName) = ParameterNameHelper::split($parameterName);

        list($referencedDatasetName, $referencedRootName) = ReferencePathHelper::splitReference($rootName);
        // checking that referenced cube exists
        $referencedCube = isset($referencedDatasetName)
            ? $metamodel->getCubeByDatasetName($referencedDatasetName)
            : NULL;

        $selectedCube = isset($referencedCube) ? $referencedCube : $cube;
        $selectedRequest = isset($referencedCube) ? $request->registerReferencedRequest($referencedCube->name) : $request;

        // detecting type of the parameter: dimension or measure
        $isDimension = $isMeasure = FALSE;
        if (isset($leafName)) {
            // if dimension column exists - dimension exists too :)
            $isDimension = TRUE;
        }
        else {
            // trying to find a measure
            $measure = $selectedCube->findMeasure($referencedRootName);
            if (isset($measure)) {
                $isMeasure = TRUE;
            }
            else {
                $formula = $request->findFormula($referencedRootName);
                if (isset($formula)) {
                    if (isset($formula->isMeasure) && $formula->isMeasure) {
                        $isMeasure = TRUE;
                    }
                    else {
                        $isDimension = TRUE;
                    }
                }
            }
            // trying to find a dimension
            $dimension = $selectedCube->findDimension($referencedRootName);
            if (isset($dimension)) {
                $isDimension = TRUE;
            }
        }
        if ($isDimension && $isMeasure) {
            throw new IllegalArgumentException(t(
                'The parameter refers to both a dimension and a measure: %parameterName',
                array('%parameterName' => $parameterName)));
        }

        if ($isDimension) {
            if (isset($referencedCube)) {
                throw new IllegalArgumentException(t('Referenced dimensions are not supported yet'));
            }
        }

        return array($selectedRequest, $isDimension, $isMeasure, $referencedRootName, $leafName);
    }
    public static function getExportColumnName ( $uiMetaDataName, MetaModel $metamodel ) {

        if ( trim($uiMetaDataName) == '' ) {
            $message = t('Empty columnName discovered');
            drupal_set_message($message, 'warning');
            LogHelper::log_warn($message);

            return $uiMetaDataName;
        }


        list($elementNameSpace, $name) = AbstractDatasetUIMetaDataGenerator::splitElementUIMetaDataName($uiMetaDataName);
        switch ( $elementNameSpace ) {

            case AbstractAttributeUIMetaData::NAME_SPACE:
                list($referencedDimensionName, $dimensionColumnName) = ParameterNameHelper::split($name);
                list($datasetName, $dimensionName) = ReferencePathHelper::splitReference($referencedDimensionName);
                if (isset($datasetName)) {
                    $adjustedReferencedDimensionName = ReferencePathHelper::assembleReference(self::getExportDatasetName($datasetName,$metamodel), $dimensionName);
                    $name = ParameterNameHelper::assemble($adjustedReferencedDimensionName, $dimensionColumnName);
                }
                break;

            case AbstractMeasureUIMetaData::NAME_SPACE:
                list($datasetName, $measureName) = ReferencePathHelper::splitReference($name);
                if (isset($datasetName)) {
                    $name = ReferencePathHelper::assembleReference(self::getExportDatasetName($datasetName,$metamodel), $measureName);
                }
                break;

            case FormulaUIMetaData::NAME_SPACE:
                list($datasetName, $formulaName) = ReferencePathHelper::splitReference($name);
                if (isset($datasetName)) {
                    $name = ReferencePathHelper::assembleReference(self::getExportDatasetName($datasetName,$metamodel), $formulaName);
                }
                break;

            default:
                $message = t('Unsupported UI Meta Data name space: @uiMetaDataName', array('@uiMetaDataName' => $uiMetaDataName));
                LogHelper::log_error($message);
                throw new UnsupportedOperationException($message);
        }

        return AbstractDatasetUIMetaDataGenerator::prepareElementUIMetaDataName($elementNameSpace, $name);
    }
    public function adjustCubeQueryRequest(DataSourceHandler $handler, AbstractQueryRequest &$request) {
        if (!isset($request->sortingConfigurations)) {
            // sorting configuration is required when pagination properties are present
            if ((isset($request->startWith) && ($request->startWith > 0)) || isset($request->limit)) {
                $columnNames = NULL;
                // adding dimensions and their columns
                if (isset($request->dimensions)) {
                    foreach ($request->dimensions as $dimension) {
                        if (isset($dimension->requestColumnIndex)) {
                            $columnNames[$dimension->requestColumnIndex] = ParameterNameHelper::assemble($dimension->name);
                        }
                        if (isset($dimension->columns)) {
                            foreach ($dimension->columns as $column) {
                                if (isset($column->requestColumnIndex)) {
                                    $columnNames[$column->requestColumnIndex] = ParameterNameHelper::assemble($dimension->name, $column->name);
                                }
                            }
                        }
                    }
                }
                // adding measures
                if (isset($request->measures)) {
                    foreach ($request->measures as $measure) {
                        if (isset($measure->requestColumnIndex)) {
                            $columnNames[$measure->requestColumnIndex] = $measure->name;
                        }
                    }
                }
                if (!isset($columnNames)) {
                    throw new IllegalStateException(t('Pagination requires sorting configuration'));
                }

                if (isset($columnNames)) {
                    // sorting by column index
                    ksort($columnNames);

                    $request->addOrderByColumns($columnNames);
                }
            }
        }
    }
    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);
    }
 public function getColumnName() {
     return ParameterNameHelper::assemble($this->rootName, $this->leafName);
 }
 public static function prepareAttributeUIMetaDataName($referencePath, $datasetName, $dimensionName, $dimensionColumnName) {
     return self::prepareElementUIMetaDataName(
         AbstractAttributeUIMetaData::NAME_SPACE,
         ParameterNameHelper::assemble(
             self::prepareReferencedElementName($referencePath, $datasetName, $dimensionName),
             $dimensionColumnName));
 }
    protected static function prepareCubeColumnMappings(array $cubes, array $parsedUIMetaDataNames) {
        $columnMappings = NULL;

        foreach ($parsedUIMetaDataNames as $columnName => $parsedUIMetaDataName) {
            if ($parsedUIMetaDataName instanceof AttributeParsedUIMetaDataName) {
                $columnMappings[$columnName] = ParameterNameHelper::assemble($parsedUIMetaDataName->name, $parsedUIMetaDataName->columnName);
            }
            elseif ($parsedUIMetaDataName instanceof MeasureParsedUIMetaDataName) {
                $columnMappings[$columnName] = $parsedUIMetaDataName->name;
            }
            elseif ($parsedUIMetaDataName instanceof FormulaAttributeParsedUIMetaDataName) {
                $columnMappings[$columnName] = $parsedUIMetaDataName->name;
            }
            elseif ($parsedUIMetaDataName instanceof FormulaMeasureParsedUIMetaDataName) {
                $columnMappings[$columnName] = $parsedUIMetaDataName->name;
            }
        }

        return $columnMappings;
    }
    protected function adjustCubeCountRequestImpl(DataControllerCallContext $callcontext, CubeCountRequest $request) {
        list($dimensionName) = ParameterNameHelper::split($this->enumerationColumnName);

        // we have to find corresponding dimension in this request
        $isDirectionFound = FALSE;
        if (isset($request->dimensions)) {
            foreach ($request->dimensions as $index => $dimension) {
                if ($dimension->name == $dimensionName) {
                    $isDirectionFound = TRUE;
                    unset($request->dimensions[$index]);

                    break;
                }
            }
        }
        if (!$isDirectionFound) {
            throw new IllegalStateException(t(
            	'Could not find configuration for %dimensionName dimension in the request',
                array('%dimensionName' => $dimensionName)));
        }
    }
    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 prepareSelectedCubeQueryStatement(AbstractSQLDataSourceQueryHandler $datasourceHandler, DataControllerCallContext $callcontext, AbstractCubeQueryRequest $request) {
        $metamodel = data_controller_get_metamodel();

        // loading cube configuration
        $cubeName = $request->getCubeName();
        $cube = $metamodel->getCube($cubeName);
        $factsDataset = $metamodel->getDataset($cube->factsDatasetName);

        $generationContext = $this->prepareStatementGenerationContext($request, $cube);

        $TABLE_ALIAS__SOURCE = 's';

        // to store configuration for each accessed table
        $datasetConfigs = NULL;

        // preparing facts dataset configuration
        $this->registerDatasetConfig($datasetConfigs, 0, $factsDataset, NULL, NULL);

        $columnReferenceFactory = new CompositeColumnReferenceFactory(array(
            $cube->factsDataset,
            new FormulaReferenceFactory($request->getFormulas())));
        $expressionAssembler = new FormulaExpressionAssembler($columnReferenceFactory);

        // statement for aggregation portion of final sql
        $aggrStatement = new Statement();

        // adding support for facts dataset column queries
        $factsDatasetColumnQueries = $request->findFactsDatasetColumnQueries();
        if (isset($factsDatasetColumnQueries)) {
            foreach ($factsDatasetColumnQueries as $queryColumn) {
                foreach ($queryColumn->values as $value) {
                    $this->registerDatasetConfig($datasetConfigs, 0, NULL, $queryColumn->name, NULL);
                    $aggrStatement->conditions[] = new WhereConditionSection(
                        $TABLE_ALIAS__SOURCE . '0',
                        $queryColumn->name,
                        new ExactConditionSectionValue(
                            $datasourceHandler->formatOperatorValue($callcontext, $request, $factsDataset->name, $queryColumn->name, $value)));
                }
            }
        }

        $possibleDimensions = NULL;
        // adding dimensions from a cube
        if (isset($cube->dimensions)) {
            foreach ($cube->dimensions as $dimension) {
                $possibleDimensions[$dimension->name] = $dimension;
            }
        }
        // creating 'virtual' dimensions from formulas
        if (isset($request->dimensions)) {
            foreach ($request->dimensions as $selectedDimension) {
                // it is predefined dimension
                if (isset($possibleDimensions[$selectedDimension->name])) {
                    continue;
                }

                // it could be a 'virtual' dimension defined by a formula
                $formula = $request->findFormula($selectedDimension->name);
                if (!isset($formula)) {
                    continue;
                }

                // defining 'virtual dimension'
                $formulaDimension = new DimensionMetaData();
                $formulaDimension->name = $selectedDimension->name;
                $formulaDimension->attributeColumnName = $selectedDimension->name;

                $possibleDimensions[$formulaDimension->name] = $formulaDimension;
            }
        }

        // FIXME why do we start with 1?
        $tableIndex = 1 + count($possibleDimensions);

        // preparing list of columns which are required to group data for the aggregation
        $aggrSelectColumns = NULL;
        // preparing list of measures which are calculated in the aggregation, preparing support for measure conditions
        $aggrSelectMeasureColumns = NULL;

        if (isset($possibleDimensions)) {
            foreach ($possibleDimensions as $dimension) {
                $dimensionName = $dimension->name;

                $selectedDimension = $request->findDimension($dimensionName);
                $queriedDimension = $request->findDimensionQuery($dimensionName);
                if (!isset($selectedDimension) && !isset($queriedDimension)) {
                    continue;
                }

                $factsColumn = $factsDataset->findColumn($dimension->attributeColumnName);

                $selectedColumnNames = isset($selectedDimension) ? $selectedDimension->getColumnNames() : NULL;
                list($selectedFactsColumnNames, $selectedDimensionColumnNames) = isset($selectedColumnNames) && isset($factsColumn)
                    ? $this->detectColumnNameOwner($factsColumn, $selectedColumnNames)
                    : array(NULL, $selectedColumnNames);

                $queriedColumnNames = isset($queriedDimension) ? $queriedDimension->getColumnNames() : NULL;
                list($queriedFactsColumnNames, $queriedDimensionColumnNames) = isset($queriedColumnNames) && isset($factsColumn)
                    ? $this->detectColumnNameOwner($factsColumn, $queriedColumnNames)
                    : array(NULL, $queriedColumnNames);

                $isJoinWithDimensionDatasetRequired = (isset($queriedDimension) && isset($queriedColumnNames) && (isset($dimension->datasetName) || isset($queriedDimensionColumnNames)))
                    || (
                        isset($generationContext->dimensionJoinPhase[__DefaultQueryEngine_StatementGenerationContext::DIMENSION_JOIN_PHASE__GROUPING_INITIAL][$dimensionName])
                            && $generationContext->dimensionJoinPhase[__DefaultQueryEngine_StatementGenerationContext::DIMENSION_JOIN_PHASE__GROUPING_INITIAL][$dimensionName]);

                $dimensionDataset = NULL;
                if (isset($dimension->datasetName)) {
                    $dimensionDataset = $metamodel->getDataset($dimension->datasetName);
                }
                elseif ($isJoinWithDimensionDatasetRequired) {
                    // 02/26/2014 there could be a case when dimension dataset does not exist but we try to connect with extension table using PK-to-PK connection
                    $dimensionDataset = $factsDataset;
                }
                $keyColumnName = isset($dimensionDataset)
                    ? $dimensionDataset->getKeyColumn()->name
                    : (isset($dimension->key) ? $dimension->key : NULL);

                // joining with dimension dataset ... if necessary
                if ($isJoinWithDimensionDatasetRequired) {
                    // registering the dimension dataset
                    $tableIndex--;
                    $this->registerDatasetConfig($datasetConfigs, $tableIndex, $dimensionDataset, NULL, NULL);

                    if (isset($queriedDimensionColumnNames)) {
                        foreach ($queriedDimension->columns as $queryColumn) {
                            if (!isset($queryColumn->name)) {
                                continue;
                            }
                            if (!in_array($queryColumn->name, $queriedDimensionColumnNames)) {
                                continue;
                            }

                            $this->registerDatasetConfig($datasetConfigs, $tableIndex, NULL, $queryColumn->name, NULL);
                            foreach ($queryColumn->values as $value) {
                                $aggrStatement->conditions[] = new WhereConditionSection(
                                    $TABLE_ALIAS__SOURCE . $tableIndex,
                                    $queryColumn->name,
                                    new ExactConditionSectionValue(
                                        $datasourceHandler->formatOperatorValue($callcontext, $request, $dimensionDataset->name, $queryColumn->name, $value)));
                            }
                        }
                    }

                    // selected columns are part of the dimension dataset
                    if (isset($selectedDimensionColumnNames)) {
                        foreach ($selectedDimensionColumnNames as $columnName) {
                            $responseColumnName = ParameterNameHelper::assemble($dimensionName, $columnName);
                            $databaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements(
                                $datasourceHandler->getMaximumEntityNameLength(),
                                ($request->referenced ? ReferencePathHelper::assembleReference($factsDataset->name, $dimensionName) : $dimensionName),
                                $columnName);
                            $callcontext->columnMapping[$databaseColumnName] = $responseColumnName;

                            $this->registerDatasetConfig($datasetConfigs, $tableIndex, $dimensionDataset, $columnName, NULL);

                            $aggrSelectColumns[$tableIndex][] = new ColumnSection($columnName, $databaseColumnName);
                        }
                    }
                }

                if (isset($selectedFactsColumnNames) || isset($selectedDimension->requestColumnIndex)) {
                    $responseColumnName = ParameterNameHelper::assemble($dimensionName);
                    $databaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements(
                        $datasourceHandler->getMaximumEntityNameLength(),
                        ($request->referenced ? ReferencePathHelper::assembleReference($factsDataset->name, $dimensionName) : $dimensionName));
                    $callcontext->columnMapping[$databaseColumnName] = $responseColumnName;

                    // selected columns are part of facts table
                    if (isset($selectedFactsColumnNames)) {
                        foreach ($selectedFactsColumnNames as $columnName) {
                            $responseSelectedColumnName = ParameterNameHelper::assemble($dimensionName, $columnName);
                            $databaseSelectedColumnName = DataSourceColumnNameHelper::generateFromParameterElements(
                                $datasourceHandler->getMaximumEntityNameLength(),
                                ($request->referenced ? ReferencePathHelper::assembleReference($factsDataset->name, $dimensionName) : $dimensionName),
                                $columnName);
                            $callcontext->columnMapping[$databaseSelectedColumnName] = $responseSelectedColumnName;

                            $this->registerDatasetConfig($datasetConfigs, 0, NULL, $columnName, NULL);

                            $aggrSelectColumns[0][] = new ColumnSection($columnName, $databaseSelectedColumnName);
                        }
                    }
                    elseif (isset($selectedDimension->requestColumnIndex)) {
                        $formula = $request->findFormula($dimension->name);
                        if (isset($formula)) {
                            $expression = $expressionAssembler->assemble($formula);

                            $column = new CompositeColumnSection($expression, $databaseColumnName);
                            if (isset($formula->isMeasure) && !$formula->isMeasure) {
                                $aggrSelectColumns[0][] = $column;
                            }
                            else {
                                $aggrSelectMeasureColumns[] = $column;
                            }
                        }
                        else {
                            $column = new ColumnSection(
                                DataSourceColumnNameHelper::generateFromParameterElements($datasourceHandler->getMaximumEntityNameLength(), $dimension->attributeColumnName),
                                $databaseColumnName);
                            $aggrSelectColumns[0][] = $column;
                        }

                        $this->registerDatasetConfig($datasetConfigs, 0, NULL, $dimension->attributeColumnName, NULL);
                    }
                }

                // adding facts table conditions
                if (isset($queriedDimension)) {
                    foreach ($queriedDimension->columns as $queryColumn) {
                        if (isset($queryColumn->name)) {
                            if (!isset($queriedFactsColumnNames) || !in_array($queryColumn->name, $queriedFactsColumnNames)) {
                                continue;
                            }
                        }

                        $queryColumnName = isset($queryColumn->name) ? $queryColumn->name : $dimension->attributeColumnName;

                        $this->registerDatasetConfig($datasetConfigs, 0, NULL, $queryColumnName, NULL);
                        foreach ($queryColumn->values as $value) {
                            $aggrStatement->conditions[] = new WhereConditionSection(
                                $TABLE_ALIAS__SOURCE . 0,
                                $queryColumnName,
                                new ExactConditionSectionValue(
                                    $datasourceHandler->formatOperatorValue($callcontext, $request, $factsDataset->name, $queryColumnName, $value)));
                        }
                    }
                }

                // linking the dimension dataset with master source
                if ($isJoinWithDimensionDatasetRequired) {
                    $this->registerDatasetConfig($datasetConfigs, 0, NULL, $dimension->attributeColumnName, NULL);
                    $this->registerDatasetConfig(
                        $datasetConfigs,
                        $tableIndex, NULL,
                        $keyColumnName,
                        new JoinConditionSection(
                            $keyColumnName,
                            new TableColumnConditionSectionValue($TABLE_ALIAS__SOURCE . '0', $dimension->attributeColumnName)));
                }
            }
        }

        // preparing a list of required measures
        $selectedMeasureNames = NULL;
        if (isset($request->measures)) {
            foreach ($request->measures as $measure) {
                $selectedMeasureNames[$measure->name] = TRUE;
            }
        }
        $measureQueries = $request->findMeasureQueries();
        if (isset($measureQueries)) {
            foreach ($measureQueries as $query) {
                $selectedMeasureNames[$query->name] = TRUE;
            }
        }
        // adding measures to the statement
        if (isset($selectedMeasureNames)) {
            foreach ($selectedMeasureNames as $measureName => $flag) {
                $measureExpression = NULL;
                // checking cube first
                $cubeMeasure = $cube->findMeasure($measureName);
                if (isset($cubeMeasure)) {
                    $measureExpression = $cubeMeasure->getFunction();
                }
                else {
                    $formula = $request->findFormula($measureName);
                    $measureExpression = $expressionAssembler->assemble($formula);
                }

                $selectedMeasure = $request->findMeasure($measureName);
                $queriedMeasure = $request->findMeasureQuery($measureName);

                if ($request->referenced) {
                    $measureName = ReferencePathHelper::assembleReference($factsDataset->name, $measureName);
                }
                $databaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements(
                    $datasourceHandler->getMaximumEntityNameLength(), $measureName);

                $columnSection = new CompositeColumnSection($measureExpression, $databaseColumnName);

                if (isset($selectedMeasure)) {
                    $callcontext->columnMapping[$databaseColumnName] = $measureName;
                    $aggrSelectMeasureColumns[] = $columnSection;
                }

                if (isset($queriedMeasure)) {
                    foreach ($queriedMeasure->values as $value) {
                        $aggrStatement->havingConditions[] = new HavingConditionSection(
                            $columnSection,
                            new ExactConditionSectionValue(
                                $datasourceHandler->formatOperatorValue($callcontext, $request, $factsDataset->name, NULL, $value)));
                    }
                }

                // looking for possible columns in the measure function. We need to retrieve those from the database
                $columnNames = $columnSection->parseColumns();
                if (isset($columnNames)) {
                    foreach ($columnNames as $columnName) {
                        $this->registerDatasetConfig($datasetConfigs, 0, NULL, $columnName, NULL);
                    }
                }
            }
        }

        // sorting configuration to support joins in correct order
        ksort($datasetConfigs, SORT_NUMERIC);

        // preparing dataset source statements
        foreach ($datasetConfigs as $orderIndex => $datasetConfig) {
            $tableStatement = $datasourceHandler->prepareDatasetSourceStatement($callcontext, $request, $datasetConfig->dataset, $datasetConfig->usedColumnNames);

            // adding join conditions
            if (isset($datasetConfig->conditions)) {
                foreach ($datasetConfig->conditions as $condition) {
                    $tableStatement->getColumnTable($condition->subjectColumnName)->conditions[] = $condition;
                }
            }

            // BLOCK 1: finding tables to which we want to attach columns which participate in aggregation
            // the code would be simpler if we supported several aliases per column
            // if we move the logic to BLOCK 3 getColumnTable(, TRUE) will not work
            $selectedAggregationTables = NULL;
            if (isset($aggrSelectColumns[$orderIndex])) {
                $tableSelectColumns = $aggrSelectColumns[$orderIndex];
                foreach ($tableSelectColumns as $aggrColumnIndex => $tableSelectColumn) {
                    // FIXME check other places to understand why I need to use parameter with TRUE value
                    // looking for a table in the statement which provides the column for SELECT section
                    if ($tableSelectColumn instanceof CompositeColumnSection) {
                        $tableSection = $tableStatement->tables[0];
                    }
                    else {
                        $tableSection = $tableStatement->getColumnTable($tableSelectColumn->name, TRUE);
                    }

                    $selectedAggregationTables[$orderIndex][$aggrColumnIndex] = $tableSection;
                }
            }

            // BLOCK 2: we do not need to return any columns from the table by default
            foreach ($tableStatement->tables as $table) {
                if (isset($table->columns)) {
                    foreach ($table->columns as $column) {
                        $column->visible = FALSE;
                    }
                }
                else {
                    $table->columns = array(); // We do not need any columns
                }
            }

            // preparing measures which we want to return. Adding those measures to facts table
            if (($orderIndex == 0) && isset($aggrSelectMeasureColumns)) {
                foreach ($aggrSelectMeasureColumns as $tableSelectMeasureColumn) {
                    $columnNames = $tableSelectMeasureColumn->parseColumns();
                    // searching which table contains the column
                    $tableSection = NULL;
                    if (isset($columnNames)) {
                        foreach ($columnNames as $columnName) {
                            $formattedColumnAlias = DataSourceColumnNameHelper::generateFromParameterElements(
                                $datasourceHandler->getMaximumEntityNameLength(), $columnName);
                            foreach ($tableStatement->tables as $table) {
                                if ($table->findColumnByAlias($formattedColumnAlias) != NULL) {
                                    if (isset($tableSection)) {
                                        if ($tableSection->alias !== $table->alias) {
                                            // FIXME we should not have such functionality
                                            // checking if the same column is used for several times in a table under different aliases
                                            $tableSectionColumns = $tableSection->findColumns($formattedColumnAlias);
                                            $tableColumns = $table->findColumns($formattedColumnAlias);
                                            $isTableSelected = FALSE;
                                            if (($tableSectionColumns > 0) && ($tableColumns > 0)) {
                                                if ($tableSectionColumns > $tableColumns) {
                                                    $tableSection = $table;
                                                    $isTableSelected = TRUE;
                                                }
                                                elseif ($tableColumns > $tableSectionColumns) {
                                                    $isTableSelected = TRUE;
                                                }
                                            }

                                            if (!$isTableSelected) {
                                                throw new UnsupportedOperationException(t('Aggregation function bases on several tables'));
                                            }
                                        }
                                    }
                                    else {
                                        $tableSection = $table;
                                    }
                                }
                            }
                        }
                    }
                    if (!isset($tableSection)) {
                        $tableSection = $tableStatement->tables[0];
                    }

                    $tableSelectMeasureColumn->attachTo($tableSection);
                }
            }

            // updating join statement table aliases
            $sourceTableAlias = $TABLE_ALIAS__SOURCE . $orderIndex;
            foreach ($tableStatement->tables as $table) {
                $oldTableAlias = $table->alias;
                $newTableAlias = $sourceTableAlias . (isset($oldTableAlias) ? '_' . $oldTableAlias : '');
                $tableStatement->updateTableAlias($oldTableAlias, $newTableAlias);

                // TODO Review. Probably is not needed anymore. Updating statement conditions which are used to join levels
                foreach ($datasetConfigs as $nextOrderIndex => $nextDatasetConfig) {
                    if (($nextOrderIndex <= $orderIndex) || !isset($nextDatasetConfig->conditions)) {
                        continue;
                    }

                    foreach ($nextDatasetConfig->conditions as $condition) {
                        if (($condition instanceof JoinConditionSection)
                                && ($condition->joinValue instanceof TableColumnConditionSectionValue)
                                && ($condition->joinValue->tableAlias === $sourceTableAlias)
                                && (($table->findColumn($condition->joinValue->columnName) != NULL) || (count($tableStatement->tables) === 1))) {
                            $condition->joinValue->tableAlias = $newTableAlias;
                        }
                    }
                }

                // updating aggregation statement conditions
                if (isset($aggrStatement->conditions)) {
                    foreach ($aggrStatement->conditions as $condition) {
                        if ($condition->subjectTableAlias != $sourceTableAlias) {
                            continue;
                        }

                        $tableColumn = $table->findColumn($condition->subjectColumnName);
                        if (!isset($tableColumn)) {
                            continue;
                        }

                        // checking if any other table in the statement support the column as an alias
                        $otherColumnFound = FALSE;
                        foreach ($tableStatement->tables as $subjectColumnTable) {
                            $subjectColumn = $subjectColumnTable->findColumnByAlias($condition->subjectColumnName);
                            if (isset($subjectColumn) && ($subjectColumn instanceof ColumnSection)) {
                                if ($subjectColumnTable->alias != $table->alias) {
                                    $condition->subjectTableAlias = $sourceTableAlias . (isset($subjectColumnTable->alias) ? '_' . $subjectColumnTable->alias : '');
                                    $condition->subjectColumnName = $subjectColumn->name;

                                    $otherColumnFound = TRUE;
                                }
                            }
                        }

                        if (!$otherColumnFound) {
                            $condition->subjectTableAlias = $newTableAlias;
                            if ($tableColumn instanceof ColumnSection) {
                                // $condition->subjectColumnName = $tableColumn->name;
                            }
                        }
                    }
                }
            }

            // BLOCK 3: preparing the table columns which we want to return
            if (isset($aggrSelectColumns[$orderIndex])) {
                $tableSelectColumns = $aggrSelectColumns[$orderIndex];
                foreach ($tableSelectColumns as $aggrColumnIndex => $tableSelectColumn) {
                    $tableSection = $selectedAggregationTables[$orderIndex][$aggrColumnIndex];

                    $relatedConditions = NULL;
                    if (isset($aggrStatement->conditions)) {
                        foreach ($aggrStatement->conditions as $condition) {
                            if (($tableSelectColumn instanceof ColumnSection)
                                    && ($condition->subjectColumnName == $tableSelectColumn->name)
                                    && ($condition->subjectTableAlias == $tableSection->alias)) {
                                $relatedConditions[] = $condition;
                            }
                        }
                    }

                    $attachedColumn = $tableSelectColumn->attachTo($tableSection);
                    if (isset($relatedConditions)) {
                        foreach ($relatedConditions as $relatedCondition) {
                            $relatedCondition->subjectColumnName = $attachedColumn->alias;
                        }
                    }

                    $aggrStatement->groupByColumns[] = new GroupByColumnSection($attachedColumn);
                }
            }

            $aggrStatement->merge($tableStatement);
        }

        return $aggrStatement;
    }
    public static function getAttributeRelatedMeasureName($attributeName, $functionName) {
        $adjustedAttributeName = ParameterNameHelper::replaceDelimiter($attributeName, self::MEASURE_NAME_DELIMITER);

        return $adjustedAttributeName . self::MEASURE_NAME_DELIMITER . strtolower($functionName);
    }
 public static function deinitializeByColumn(CubeMetaData $cube, DatasetMetaData $dataset, $columnName)
 {
     $metamodel = data_controller_get_metamodel();
     $column = $dataset->getColumn($columnName);
     $handler = DimensionLookupFactory::getInstance()->getHandler($column->type->getLogicalApplicationType());
     $handler->unprepareDimension($metamodel, $dataset, $column->name);
     // removing dimension
     $dimension = $cube->unregisterDimension($columnName);
     // removing measure which counts unique values
     $attributeName = ParameterNameHelper::assemble($dimension->name);
     $measureName = StarSchemaNamingConvention::getAttributeRelatedMeasureName($attributeName, StarSchemaNamingConvention::$MEASURE_NAME_SUFFIX__DISTINCT_COUNT);
     $measure = $cube->findMeasure($measureName);
     if (isset($measure)) {
         $cube->unregisterMeasure($measureName);
     }
     self::deinitializeColumnMeasures($cube, $dataset, $columnName);
 }