protected function selectBoundary4CubeRequest(DataControllerCallContext $callcontext, AbstractCubeQueryRequest $request, $datasetName, $columnName) { $isSortAscending = $this->isSortAscending(); $resultColumnName = NULL; // preparing new cube meta data $expressionRequest = new CubeQueryRequest($request->getCubeName()); // needs to be called before any additional methods are called $expressionRequest->addOptions($request->options); // copying ONLY some query objects (excluding at least a reference to this operator) // -- dimension queries $dimensionQueries = $request->findDimensionQueries(); if (isset($dimensionQueries)) { foreach ($dimensionQueries as $query) { foreach ($query->columns as $queryColumn) { foreach ($queryColumn->values as $value) { if ($this->shouldValueBeSkipped($value)) { continue; } // updating request configuration for the value supported by this class if ($this->operatorHandler === $value) { $resultColumnName = ParameterNameHelper::assemble($query->name, $queryColumn->name); // returning only observing column of the dimension $expressionRequest->addDimensionColumn(0, $query->name, $queryColumn->name); // ... and excluding NULL values from evaluation $expressionRequest->addDimensionColumnQueryValue( $query->name, $queryColumn->name, OperatorFactory::getInstance()->initiateHandler(NotEqualOperatorHandler::OPERATOR__NAME, NULL)); // sorting data $expressionRequest->addOrderByColumn( ColumnBasedComparator_AbstractSortingConfiguration::assembleDirectionalColumnName($resultColumnName, $isSortAscending)); } else { $expressionRequest->addDimensionColumnQueryValue($query->name, $queryColumn->name, $value); } } } } } // -- facts dataset column queries $factsDatasetColumnQueries = $request->findFactsDatasetColumnQueries(); if (isset($factsDatasetColumnQueries)) { foreach ($factsDatasetColumnQueries as $query) { $values = NULL; foreach ($query->values as $value) { if ($this->shouldValueBeSkipped($value)) { continue; } if ($this->operatorHandler === $value) { $metamodel = data_controller_get_metamodel(); $cube = $metamodel->getCube($expressionRequest->getCubeName()); // finding dimension associated with this fact column $selectedDimension = NULL; if (isset($cube->dimensions)) { foreach ($cube->dimensions as $dimension) { if ($dimension->attributeColumnName == $query->name) { $selectedDimension = $dimension; break; } } } if (!isset($selectedDimension)) { throw new IllegalArgumentException(t( 'Boundary-related operator cannot be applied to the facts dataset column: %columnName', array('%columnName' => $query->name))); } $resultColumnName = ParameterNameHelper::assemble($selectedDimension->name); // returning only observing column from facts dataset $expressionRequest->addDimension(0, $selectedDimension->name); // ... and excluding NULL values from evaluation $expressionRequest->addFactsDatasetColumnQueryValue( $query->name, OperatorFactory::getInstance()->initiateHandler(NotEqualOperatorHandler::OPERATOR__NAME, NULL)); // sorting data $expressionRequest->addOrderByColumn( ColumnBasedComparator_AbstractSortingConfiguration::assembleDirectionalColumnName($resultColumnName, $isSortAscending)); } else { $values[] = $value; } } if (isset($values)) { $expressionRequest->addFactsDatasetColumnQueryValues($query->name, $values); } } } // -- measure queries $measureQueries = $request->findMeasureQueries(); if (isset($measureQueries)) { foreach ($measureQueries as $query) { foreach ($query->values as $value) { if ($this->shouldValueBeSkipped($value)) { throw new IllegalArgumentException(t('Boundary-related operator cannot be applied to measures')); } } $expressionRequest->queries[] = clone $query; } } // limiting response to one record $expressionRequest->setPagination(1, 0); return $this->processCubeExpressionRequest($callcontext, $expressionRequest, $resultColumnName); }
protected function prepareReferencedCubeQueryStatement( AbstractSQLDataSourceQueryHandler $datasourceHandler, DataControllerCallContext $callcontext, Statement $combinedStatement, array $datasetMappedCubeRequests, ReferenceLink $link) { if (!isset($link->nestedLinks)) { return; } $metamodel = data_controller_get_metamodel(); foreach ($link->nestedLinks as $referencedLink) { $referencedRequest = NULL; if (isset($datasetMappedCubeRequests[$referencedLink->dataset->name])) { $referencedRequest = clone $datasetMappedCubeRequests[$referencedLink->dataset->name]; } else { // checking if there is corresponding cube for the referenced dataset $possibleReferencedCube = $metamodel->findCubeByDatasetName($referencedLink->dataset->name); if (isset($possibleReferencedCube)) { $referencedRequest = new CubeQueryRequest($possibleReferencedCube->name); $referencedRequest->referenced = TRUE; $datasetMappedCubeRequests[$possibleReferencedCube->factsDatasetName] = $referencedRequest; } } if (isset($referencedRequest)) { // preparing parent cube $parentRequest = $datasetMappedCubeRequests[$link->dataset->name]; $parentCubeName = $parentRequest->getCubeName(); $parentCube = $metamodel->getCube($parentCubeName); // preparing referenced cube $referencedCubeName = $referencedRequest->getCubeName(); $referencedCube = $metamodel->getCube($referencedCubeName); // adding required dimensions $joinConditions = NULL; foreach ($referencedLink->parentColumnNames as $columnIndex => $parentColumnName) { // looking for a dimension in parent cube $parentDimension = $parentCube->getDimensionByAttributeColumnName($parentColumnName); // looking for a dimension in referenced cube $referencedColumnName = $referencedLink->columnNames[$columnIndex]; $referencedDimension = $referencedCube->getDimensionByAttributeColumnName($referencedColumnName); // checking if this dimension is part of query portion of parent request $parentRequestDimensionQuery = $parentRequest->findDimensionQuery($parentDimension->name); if (isset($parentRequestDimensionQuery)) { // copying the query request to referenced cube $referencedRequestDimensionQuery = new __AbstractCubeQueryRequest_DimensionQuery($referencedDimension->name); $referencedRequestDimensionQuery->columns = $parentRequestDimensionQuery->columns; $referencedRequest->importDimensionQueryFrom($referencedRequestDimensionQuery); } // checking if there is a related query for parent column name $parentRequestFactsDatasetColumnQuery = $parentRequest->findFactsDatasetColumnQuery($parentColumnName); if (isset($parentRequestFactsDatasetColumnQuery)) { // copying the query request to referenced cube $referencedRequest->addFactsDatasetColumnQueryValues($referencedColumnName, $parentRequestFactsDatasetColumnQuery->values); } // checking if this dimension is part of parent request $parentRequestDimension = $parentRequest->findDimension($parentDimension->name); if (!isset($parentRequestDimension)) { // because this dimension is not in list of returned columns we should not use it to link with referenced cube continue; } $referencedRequestDimension = $referencedRequest->addDimension( NULL, // TODO support requestColumnIndex here $referencedDimension->name); $columnNames = $parentRequestDimension->getColumnNames(); if (isset($columnNames)) { foreach ($columnNames as $columnName) { $referencedRequestDimension->registerColumnName( NULL, // TODO support requestColumnIndex here $columnName); } } else { // to help the following loop to link cubes by dimension $columnNames = array(NULL); } foreach ($columnNames as $columnName) { $parentDatabaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements( $datasourceHandler->getMaximumEntityNameLength(), ($parentRequest->referenced ? ReferencePathHelper::assembleReference($parentCube->factsDatasetName, $parentDimension->name) : $parentDimension->name), $columnName); $referencedDatabaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements( $datasourceHandler->getMaximumEntityNameLength(), ReferencePathHelper::assembleReference($referencedCube->factsDatasetName, $referencedDimension->name), $columnName); $joinConditions[] = new JoinConditionSection( $referencedDatabaseColumnName, new TableColumnConditionSectionValue(self::$TABLE_ALIAS__REFERENCED . $link->linkId, $parentDatabaseColumnName)); } } if (!isset($joinConditions)) { throw new IllegalArgumentException(t( 'There is no common columns to join %datasetNameA and %datasetNameB datasets', array('%datasetNameA' => $parentCube->publicName, '%datasetNameB' => $referencedCube->publicName))); } // preparing aggregation statement for referenced cube $referencedAggregationStatement = $this->prepareSelectedCubeQueryStatement($datasourceHandler, $callcontext, $referencedRequest); list($isSubqueryRequired, $assembledReferencedCubeSections) = $referencedAggregationStatement->prepareSections(NULL); $referencedCubeSubquerySection = new SubquerySection( Statement::assemble($isSubqueryRequired, NULL, $assembledReferencedCubeSections, SelectStatementPrint::INDENT__LEFT_OUTER_JOIN__SUBQUERY, FALSE), self::$TABLE_ALIAS__REFERENCED . $referencedLink->linkId); // preparing columns which are returned by referenced aggregation foreach ($referencedAggregationStatement->tables as $table) { if (!isset($table->columns)) { continue; } foreach ($table->columns as $column) { if (!$column->visible) { continue; } $referencedCubeSubquerySection->columns[] = new ColumnSection($column->alias); } } // linking with parent cube foreach ($joinConditions as $joinCondition) { // we do not need to return columns which are used to join with parent cube $referencedCubeSubquerySection->getColumn($joinCondition->subjectColumnName)->visible = FALSE; $referencedCubeSubquerySection->conditions[] = $joinCondition; } // adding to resulting statement $combinedStatement->tables[] = $referencedCubeSubquerySection; // applying referenced cubes measure conditions on resulting statement as well $measureQueries = $referencedRequest->findMeasureQueries(); if (isset($measureQueries)) { foreach ($measureQueries as $measureQuery) { $measureName = ReferencePathHelper::assembleReference($referencedCube->factsDatasetName, $measureQuery->name); $measureDatabaseColumnName = DataSourceColumnNameHelper::generateFromParameterElements( $datasourceHandler->getMaximumEntityNameLength(), $measureName); foreach ($measureQuery->values as $value) { $combinedStatement->conditions[] = new WhereConditionSection( self::$TABLE_ALIAS__REFERENCED . $referencedLink->linkId, $measureDatabaseColumnName, new ExactConditionSectionValue( $datasourceHandler->formatOperatorValue($callcontext, $referencedRequest, $referencedCube->factsDatasetName, NULL, $value))); } } } } else { throw new UnsupportedOperationException(t('Cube joins using intermediate dataset is not supported yet')); // preparing statement for intermediate dataset $requiredColumnNames = $referencedLink->columnNames; $referencedIntermediateDatasetStatement = $datasourceHandler->prepareDatasetSourceStatement($callcontext, NULL, $referencedLink->dataset, $requiredColumnNames); // adding condition to join with parent statement $referencedIntermediateDatasetTableSection = $referencedIntermediateDatasetStatement->tables[0]; foreach ($referencedLink->columnNames as $columnIndex => $referencedColumnName) { $referencedDatabaseColumnName = $referencedColumnName; $parentColumnName = $referencedLink->parentColumnNames[$columnIndex]; $parentDatabaseColumnName = $parentColumnName; $referencedIntermediateDatasetTableSection->conditions[] = new JoinConditionSection( $referencedDatabaseColumnName, new TableColumnConditionSectionValue(self::$TABLE_ALIAS__REFERENCED . $link->linkId, $parentDatabaseColumnName)); } $combinedStatement->merge($referencedIntermediateDatasetStatement); } // recursively check nested levels $this->prepareReferencedCubeQueryStatement($datasourceHandler, $callcontext, $combinedStatement, $datasetMappedCubeRequests, $referencedLink); } }