public function assemble(AbstractSQLDataSourceQueryHandler $datasourceHandler, AbstractQueryRequest $request, DatasetMetaData $dataset, array $columnNames = NULL) {
        $engine = QueryEngineFactory::getInstance()->getHandler();

        $statement = $engine->newSelectStatement();

        // FIXME use the following code
/*      // the following code was commended out because functionality in Statement::findColumnTableByReferencePath() $table->dataset->name
        $tableName = assemble_database_entity_name($datasourceHandler, $dataset->datasourceName, $dataset->source);

        $table = $statement->newTable($tableName);
*/
        $table = new DatasetSection($dataset);
        $statement->tables[] = $table;

        if (isset($columnNames)) {
            $columnReferenceFactory = new CompositeColumnReferenceFactory(array(
                $dataset,
                new FormulaReferenceFactory($request->getFormulas())));

            $expressionAssembler = new FormulaExpressionAssembler($columnReferenceFactory);

            foreach ($columnNames as $columnName) {
                $column = $columnReferenceFactory->findColumn($columnName);

                if (isset($column) && ($column->persistence == FormulaMetaData::PERSISTENCE__CALCULATED)) {
                    $table->newCalculatedColumn($expressionAssembler->assemble($column), $columnName);
                }
                else {
                    $table->newColumn($columnName);
                }
            }
        }

        return $statement;
    }
    protected function finalizeRequest4Total(AbstractQueryRequest $request, AbstractQueryRequest $request4Total, array $columnNames4Total) {
        $totalExpressions = $request4Total->getOption(self::OPTION__TOTAL_FORMULA_EXPRESSION);

        // preparing returned columns
        $columnIndex = 0;
        foreach ($columnNames4Total as $columnName) {
            $formula = $request4Total->getFormula($columnName);
            // updating expression to summarize data for the expression
            $formula->source = 'SUM(' . $formula->source . ')';
            $formula->isMeasure = TRUE;

            $request4Total->addMeasure($columnIndex++, $columnName);
        }

        // preparing data querying
        if (isset($request->queries)) {
            if (count($request->queries) > 1) {
                throw new UnsupportedOperationException('Composite requests are not supported');
            }

            foreach ($request->queries as $index => $queries) {
                foreach ($queries as $name => $values) {
                    $formula = $request->getFormula($name);
                    if (isset($formula)) {
                        // checking if the formula contains reference to TOTAL function
                        if (isset($totalExpressions[$formula->name])) {
                            // excluding the condition
                            continue;
                        }
                    }
                    $request4Total->addFactsDatasetColumnQueryValues($name, $values);
                }
            }
        }
    }
    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 finalizeRequest4Total(AbstractQueryRequest $request, AbstractQueryRequest $request4Total, array $columnNames4Total) {
        $totalExpressions = $request4Total->getOption(self::OPTION__TOTAL_FORMULA_EXPRESSION);

        // preparing returned columns
        $columnIndex = 0;
        // ... TODO existing dimensions (to support non-additive measures)
        /*
        if (isset($request->dimensions)) {
            foreach ($request->dimensions as $dimension) {
                if (isset($dimension->columns)) {
                    foreach ($dimension->columns as $column) {
                        $request4Total->addDimensionColumn($columnIndex++, $dimension->name, $column->name);
                    }
                }
                else {
                    $formula = $request->getFormula($dimension->name);
                    if (isset($formula)) {
                    // checking if the formula contains reference to TOTAL function
                        if (isset($totalExpressions[$formula->name])) {
                            // excluding the formula
                            continue;
                        }
                    }

                    $request4Total->addDimension($columnIndex++, $dimension->name);
                }
            }
        } */
        // ... measures to calculate total
        foreach ($columnNames4Total as $measureName) {
            $formula = $request4Total->getFormula($measureName);

            // TODO checking if the formula expression contains any aggregation functions (eliminate when non-additive measures are supported)
            $handler = FormulaExpressionLanguageFactory::getInstance()->getHandler($formula->expressionLanguage);
            $lexemes = $handler->lex($formula->source);
            $syntaxTree = $handler->parse($lexemes);
            $isMeasure = $handler->isMeasure($syntaxTree);
            if (!isset($isMeasure) || !$isMeasure) {
                // updating expression to summarize data for the expression
                $formula->source = 'SUM(' . $formula->source . ')';
            }

            $formula->isMeasure = TRUE;

            $request4Total->addMeasure($columnIndex++, $measureName);
        }

        // preparing data querying
        $dimensionQueries = $request->findDimensionQueries();
        if (isset($dimensionQueries)) {
            foreach ($dimensionQueries as $query) {
                foreach ($query->columns as $queryColumn) {
                    $request4Total->addDimensionColumnQueryValues($query->name, $queryColumn->name, $queryColumn->values);
                }
            }
        }

        $factsDatasetColumnQueries = $request->findFactsDatasetColumnQueries();
        if (isset($factsDatasetColumnQueries)) {
            foreach ($factsDatasetColumnQueries as $query) {
                $request4Total->addFactsDatasetColumnQueryValues($query->name, $query->values);
            }
        }

        $measureQueries = $request->findMeasureQueries();
        if (isset($measureQueries)) {
            foreach ($measureQueries as $query) {
                $formula = $request->getFormula($query->name);
                if (isset($formula)) {
                    // checking if the formula contains reference to TOTAL function
                    if (isset($totalExpressions[$formula->name])) {
                        // excluding the condition
                        continue;
                    }
                }

                $request4Total->addMeasureQueryValues($query->name, $query->values);
            }
        }
    }
 public function __clone() {
     parent::__clone();
     $this->referencedRequests = ArrayHelper::copy($this->referencedRequests);
 }
    public function updateTotals(AbstractQueryRequest $request, AbstractQueryRequest $request4Total, array $totals) {
        $totalExpressionColumnMapping = $request4Total->getOption(self::OPTION__TOTAL_EXPRESSION_COLUMN_MAPPING);

        $adjustedTotals = NULL;
        foreach ($totals as $columnName => $value) {
            $totalExpression = $totalExpressionColumnMapping[$columnName];
            $adjustedTotals[$totalExpression] = $value;
        }

        $columnReferenceFactory = new CompositeColumnReferenceFactory(array(
            $this->prepareRequestDataset($request),
            new FormulaReferenceFactory($request->getFormulas())));
        $expressionAssembler = new FormulaExpressionAssembler($columnReferenceFactory);
        $parser = new TotalInFormulaExpressionParser();
        // preparing new formula expressions in separate loop to prevent interference
        $newExpressions = NULL;
        foreach ($request->getFormulas() as $formula) {
            $oldExpression = $expressionAssembler->assemble($formula);

            $columnNameCollector = new __TotalInFormulaExpressionRequestPreparer__TotalUpdater();
            $newExpression = $parser->parse($oldExpression, array($columnNameCollector, 'updateTotal'), $adjustedTotals);
            if ($newExpression != $oldExpression) {
                $newExpressions[$formula->name] = $newExpression;
            }
        }
        // assigning new expressions
        if (isset($newExpressions)) {
            foreach ($newExpressions as $formulaName => $newExpression) {
                $formula = $request->getFormula($formulaName);
                $formula->source = $newExpression;
            }
        }
    }