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); }