protected function collectReferencedFormulaNames(AbstractQueryRequest $request) {
        $usedFormulaNames = NULL;

        // checking dimensions
        if (isset($request->dimensions)) {
            foreach ($request->dimensions as $dimension) {
                $dimensionName = $dimension->name;
                if ($request->findFormula($dimensionName) != NULL) {
                    ArrayHelper::addUniqueValue($usedFormulaNames, $dimensionName);
                }
            }
        }
        // checking measures
        if (isset($request->measures)) {
            foreach ($request->measures as $measure) {
                $measureName = $measure->name;
                if ($request->findFormula($measureName) != NULL) {
                    ArrayHelper::addUniqueValue($usedFormulaNames, $measureName);
                }
            }
        }
        // checking conditions
        if (isset($request->queries)) {
            foreach ($request->queries as $query) {
                $name = $query->name;
                if ($request->findFormula($name) != NULL) {
                    ArrayHelper::addUniqueValue($usedFormulaNames, $name);
                }
            }
        }

        return $usedFormulaNames;
    }
    private function registerDatasetConfig(array &$datasetConfigs = NULL, $index, DatasetMetaData $dataset = NULL, $columnName = NULL, AbstractConditionSection $condition = NULL) {
        if (isset($datasetConfigs[$index])) {
            $datasetConfig = $datasetConfigs[$index];
        }
        else {
            // TODO create a class
            $datasetConfig = new stdClass();
            $datasetConfig->dataset = NULL;
            $datasetConfig->usedColumnNames = NULL;
            $datasetConfig->conditions = NULL;

            $datasetConfigs[$index] = $datasetConfig;
        }

        if (isset($dataset)) {
            if (isset($datasetConfig->dataset)) {
                if ($datasetConfig->dataset->name !== $dataset->name) {
                    throw new IllegalStateException(t(
                    	'Inconsistent dataset configuration: [@datasetName, @tableDatasetName]',
                        array('@datasetName' => $dataset->publicName, '@tableDatasetName' => $datasetConfig->dataset->publicName)));
                }
            }
            else {
                $datasetConfig->dataset = $dataset;
            }
        }

        if (isset($columnName)) {
            ArrayHelper::addUniqueValue($datasetConfig->usedColumnNames, $columnName);
        }

        if (isset($condition)) {
            $datasetConfig->conditions[] = $condition;
        }
    }
    protected function collectReferencedFormulaNames(AbstractQueryRequest $request) {
        $usedFormulaNames = NULL;

        // checking conditions
        if (isset($request->queries)) {
            foreach ($request->queries as $index => $query) {
                foreach ($query as $columnName => $values) {
                    if ($request->findFormula($columnName) != NULL) {
                        ArrayHelper::addUniqueValue($usedFormulaNames, $columnName);
                    }
                }
            }
        }
        // checking columns
        if ($request instanceof DatasetQueryRequest) {
            if (isset($request->columns)) {
                foreach ($request->columns as $columnName) {
                    if ($request->findFormula($columnName) != NULL) {
                        ArrayHelper::addUniqueValue($usedFormulaNames, $columnName);
                    }
                }
            }
        }

        return $usedFormulaNames;
    }
    protected function processMetaModelFilters(array &$processedFilters = NULL, array $filters = NULL) {
        if (!isset($filters)) {
            return;
        }

        foreach ($filters as $className => $properties) {
            foreach ($properties as $propertyName => $values) {
                $uniqueValues = isset($processedFilters[$className][$propertyName])
                    ? $processedFilters[$className][$propertyName]
                    : NULL;
                if ($uniqueValues === FALSE) {
                    // this property should be ignored
                }
                else {
                    foreach ($values as $value) {
                        if (isset($value)) {
                            ArrayHelper::addUniqueValue($uniqueValues, $value);
                        }
                        else {
                            // if there is at least one NULL value we ignore the property completely
                            $uniqueValues = FALSE;
                            break;
                        }
                    }
                }

                $processedFilters[$className][$propertyName] = $uniqueValues;
            }
        }
    }
    public function generate(array $possiblyLinkableDatasetNames = NULL) {
        $adjustedPossiblyLinkableDatasetNames = NULL;
        if (isset($possiblyLinkableDatasetNames)) {
            foreach ($possiblyLinkableDatasetNames as $possiblyLinkableDatasetName) {
                $adjustedPossiblyLinkableDatasetName = $this->adjustDatasetName($possiblyLinkableDatasetName);
                // we should not try to link with itself
                if ($adjustedPossiblyLinkableDatasetName == $this->primaryDatasetName) {
                    continue;
                }

                ArrayHelper::addUniqueValue($adjustedPossiblyLinkableDatasetNames, $adjustedPossiblyLinkableDatasetName);
            }
        }

        // preparing reference paths for all datasets which we need to test for possible linkage
        $referencePaths = NULL;
        if (isset($adjustedPossiblyLinkableDatasetNames)) {
            foreach ($adjustedPossiblyLinkableDatasetNames as $adjustedPossiblyLinkableDatasetName) {
                // column name should not be provided because we just try to link with the dataset
                $referencePath = ReferencePathHelper::assembleReference($adjustedPossiblyLinkableDatasetName, NULL);

                $referencePaths[$referencePath] = FALSE; // FALSE - if we cannot find link it is ok. Not everything could be connected
            }
        }

        $linkBuilder = new ReferenceLinkBuilder();
        $link = $linkBuilder->prepareReferenceBranches($this->primaryDatasetName, $referencePaths);

        return $link;
    }
    public function insertOrUpdateOrDeleteDatasetRecords(DataControllerCallContext $callcontext, AbstractDatasetManipulationRequest $request) {
        $environment_metamodel = data_controller_get_environment_metamodel();
        $metamodel = data_controller_get_metamodel();

        $datasourceQueryHandler = DataSourceQueryFactory::getInstance()->getHandler($this->getDataSourceType());

        $dataset = $metamodel->getDataset($request->datasetName);
        $datasource = $environment_metamodel->getDataSource($dataset->datasourceName);
        $recordMetaData = isset($request->recordsHolder->recordMetaData) ? $request->recordsHolder->recordMetaData : $dataset;

        $isRecordIndexed = $request->recordsHolder instanceof IndexedRecordsHolder;

        $keyColumnNames = $recordMetaData->getKeyColumnNames();
        $nonkeyColumnNames = $recordMetaData->findNonKeyColumnNames();

        // preparing a request to find existing records
        $queryRequest = new DatasetQueryRequest($request->datasetName);
        // loading only key columns from database
        $queryRequest->addColumns($keyColumnNames);
        // a request can be more efficient for single column key
        if (count($keyColumnNames) == 1) {
            list($keyColumnIndex, $keyColumnName) = each($keyColumnNames);
            $keyColumnIdentifier = $isRecordIndexed ? $keyColumnIndex : $keyColumnName;

            $keyValues = NULL;
            foreach ($request->recordsHolder->records as $record) {
                ArrayHelper::addUniqueValue($keyValues, $record->getColumnValue($keyColumnIdentifier, TRUE));
            }

            $queryRequest->addQueryValue(
                0,
                $keyColumnName, OperatorFactory::getInstance()->initiateHandler(EqualOperatorHandler::OPERATOR__NAME, array($keyValues)));
        }
        else {
            for ($i = 0, $count = count($request->recordsHolder->records); $i < $count; $i++) {
                $record = $request->recordsHolder->records[$i];
                foreach ($keyColumnNames as $keyColumnIndex => $keyColumnName) {
                    $keyColumnIdentifier = $isRecordIndexed ? $keyColumnIndex : $keyColumnName;

                    $keyColumnValue = $record->getColumnValue($keyColumnIdentifier, TRUE);
                    $queryRequest->addQueryValue(
                        $i,
                        $keyColumnName, OperatorFactory::getInstance()->initiateHandler(EqualOperatorHandler::OPERATOR__NAME, $keyColumnValue));
                }
            }
        }

        // loading existing records ... if any
        $existingRecordFormatter = new QueryKeyResultFormatter($keyColumnNames);
        $existingRecords = $existingRecordFormatter->formatRecords($datasourceQueryHandler->queryDataset($callcontext, $queryRequest));

        // sorting out records for insert, update and delete operations
        $keyedRecords = $insertedRecordKeys = $updatedRecordKeys = $deletedRecordKeys = NULL;
        foreach ($request->recordsHolder->records as $record) {
            $keyParts = NULL;
            foreach ($keyColumnNames as $keyColumnIndex => $keyColumnName) {
                $keyColumnIdentifier = $isRecordIndexed ? $keyColumnIndex : $keyColumnName;
                $keyParts[] = $record->getColumnValue($keyColumnIdentifier, TRUE);
            }
            $key = ArrayHelper::prepareCompositeKey($keyParts);
            $keyedRecords[$key] = $record;

            // checking if the record has to be deleted
            $isDeletable = TRUE;
            if (isset($nonkeyColumnNames)) {
                foreach ($nonkeyColumnNames as $columnIndex => $columnName) {
                    $columnIdentifier = $isRecordIndexed ? $columnIndex : $columnName;
                    if ($record->getColumnValue($columnIdentifier) != NULL) {
                        $isDeletable = FALSE;
                        break;
                    }
                }
            }
            else {
                // the dataset has NO non-key columns. We should not delete these records
                $isDeletable = FALSE;
            }

            if ($isDeletable) {
                unset($insertedRecordKeys[$key]);
                unset($updatedRecordKeys[$key]);
                // the record physically present in database and needs to be deleted
                if (isset($existingRecords[$key])) {
                    unset($existingRecords[$key]);
                    $deletedRecordKeys[$key] = TRUE;
                }
            }
            elseif (isset($insertedRecordKeys[$key])) {
                // the key has been already used to insert a record within this batch. This record needs to be part of update operation
                $updatedRecordKeys[$key] = TRUE;
            }
            elseif (isset($existingRecords[$key])) {
                $updatedRecordKeys[$key] = TRUE;
            }
            else {
                $insertedRecordKeys[$key] = TRUE;
            }
        }

        $sqls = NULL;

        // deleting existing records
        $deletedRecordCount = 0;
        if (isset($deletedRecordKeys)) {
            $deleteRecordHolder = $this->prepareRecordHolder($request, $keyedRecords, $deletedRecordKeys);
            // preparing request
            $deleteRequest = new DatasetDeleteRequest($request->datasetName, $deleteRecordHolder);
            // preparing statements to delete records from the database
            ArrayHelper::appendValue($sqls, $this->prepareDeleteDatasetRecordStatements($callcontext, $deleteRequest));

            $deletedRecordCount = count($deleteRecordHolder->records);
        }

        // inserting new records
        $insertedRecordCount = 0;
        if (isset($insertedRecordKeys)) {
            $insertRecordHolder = $this->prepareRecordHolder($request, $keyedRecords, $insertedRecordKeys);
            // preparing request
            $insertRequest = new DatasetInsertRequest($request->datasetName, $insertRecordHolder);
            // preparing statements to insert records into the database
            ArrayHelper::appendValue($sqls, $this->prepareInsertDatasetRecordStatements($callcontext, $insertRequest));

            $insertedRecordCount = count($insertRecordHolder->records);
        }

        // updating existing records
        $updatedRecordCount = 0;
        if (isset($updatedRecordKeys)) {
            $updateRecordHolder = $this->prepareRecordHolder($request, $keyedRecords, $updatedRecordKeys);
            // preparing request
            $updateRequest = new DatasetUpdateRequest($request->datasetName, $updateRecordHolder);
            // preparing statements to update records in the database
            ArrayHelper::appendValue($sqls, $this->prepareUpdateDatasetRecordStatements($callcontext, $updateRequest));

            $updatedRecordCount = count($updateRecordHolder->records);
        }

        $affectedRecordCount = isset($sqls) ? $this->executeManipulationStatementBatch($datasource, $sqls) : 0;
        if (($insertedRecordCount + $updatedRecordCount + $deletedRecordCount) < $affectedRecordCount) {
            throw new IllegalStateException(t('Number of affected records is greater than expected number of inserted, updated and deleted records'));
        }

        return array($insertedRecordCount, $updatedRecordCount, $deletedRecordCount);
    }
    public function addColumn($column) {
        $isFormula = $this->findFormula($column) != NULL;
        ReferencePathHelper::checkReference($column, TRUE, !$isFormula);

        ArrayHelper::addUniqueValue($this->columns, $column);
    }
 public function queryCube(DataControllerCallContext $callcontext, CubeQueryRequest $request, ResultFormatter $resultFormatter)
 {
     $cubeName = $request->getCubeName();
     LogHelper::log_notice(t('Querying SQL-based cube: @cubeName', array('@cubeName' => $cubeName)));
     $environment_metamodel = data_controller_get_environment_metamodel();
     $metamodel = data_controller_get_metamodel();
     $callcontext->columnMapping = NULL;
     $cube = $metamodel->getCube($cubeName);
     LogHelper::log_debug($cube);
     $cubeDatasetName = $cube->sourceDatasetName;
     $cubeDataset = $metamodel->getDataset($cubeDatasetName);
     $datasource = $environment_metamodel->getDataSource($cubeDataset->datasourceName);
     // 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 porting 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, Statement::$INDENT_SUBQUERY, FALSE), $TABLE_ALIAS__JOIN);
         $joinStatement->tables[] = $aggregationTableSection;
     }
     // adding support for dimension level properties
     if (isset($request->dimensions)) {
         foreach ($request->dimensions as $requestDimension) {
             $dimensionName = $requestDimension->dimensionName;
             $dimension = $cube->getDimension($dimensionName);
             $levelName = $requestDimension->levelName;
             // we do not need to map the column. It was done in prepareCubeQueryStatement()
             $levelDatabaseColumnName = ParameterHelper::assembleDatabaseColumnName($this->getMaximumEntityNameLength(), $dimensionName, $levelName);
             // adding support for level root column
             $levelRootColumn = new ColumnSection($levelDatabaseColumnName);
             $levelRootColumn->requestColumnIndex = $requestDimension->requestColumnIndex;
             $levelRootColumn->visible = isset($requestDimension->requestColumnIndex);
             $aggregationTableSection->columns[] = $levelRootColumn;
             if (!isset($requestDimension->properties)) {
                 continue;
             }
             $tableJoinIndex++;
             $levelTableAlias = $TABLE_ALIAS__JOIN . $tableJoinIndex;
             $level = $dimension->getLevel($levelName);
             $levelDataset = $metamodel->getDataset($level->datasetName);
             // preparing list of columns which are accessed by this dataset
             $usedColumnNames = NULL;
             $levelColumnAliasMapping = NULL;
             foreach ($requestDimension->properties as $property) {
                 $propertyName = $property->name;
                 $responseColumnName = ParameterHelper::assembleParameterName($dimensionName, $levelName, $propertyName);
                 $databaseColumnName = ParameterHelper::assembleDatabaseColumnName($this->getMaximumEntityNameLength(), $dimensionName, $levelName, $propertyName);
                 $callcontext->columnMapping[$databaseColumnName] = $responseColumnName;
                 ArrayHelper::addUniqueValue($usedColumnNames, $propertyName);
                 $levelColumnAliasMapping[$propertyName] = $databaseColumnName;
             }
             $isLevelKeyColumnAdded = ArrayHelper::addUniqueValue($usedColumnNames, $level->key);
             $levelStatement = $this->prepareDatasetSourceStatement($callcontext, $levelDataset, $usedColumnNames);
             // updating level statement table aliases
             $levelStatement->addTableAliasPrefix($levelTableAlias);
             foreach ($levelStatement->tables as $table) {
                 if (!isset($table->columns)) {
                     $table->columns = array();
                     // We do not need any columns
                 }
             }
             // updating level statement column aliases
             foreach ($requestDimension->properties as $property) {
                 $oldColumnAlias = $property->name;
                 $newColumnAlias = $levelColumnAliasMapping[$oldColumnAlias];
                 $levelTableSection = $levelStatement->getColumnTable($oldColumnAlias, TRUE);
                 $levelColumnSection = $levelTableSection->findColumnByAlias($oldColumnAlias);
                 if (isset($levelColumnSection)) {
                     $levelColumnSection->alias = $newColumnAlias;
                 } else {
                     $levelColumnSection = new ColumnSection($oldColumnAlias, $newColumnAlias);
                     $levelTableSection->columns[] = $levelColumnSection;
                 }
                 $levelColumnSection->requestColumnIndex = $property->requestColumnIndex;
             }
             // adding condition to join with 'main' statement
             $levelKeyTableSection = $levelStatement->getColumnTable($level->key);
             $levelKeyTableSection->conditions[] = new JoinConditionSection($level->key, new TableColumnConditionSectionValue($TABLE_ALIAS__JOIN, $levelDatabaseColumnName));
             // merging with 'main' statement
             $joinStatement->merge($levelStatement);
             // we do not need to return level key column
             if ($isLevelKeyColumnAdded && isset($levelKeyTableSection)) {
                 // 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 = $levelStatement->getColumnTable($level->key, TRUE);
                 $keyColumn = $tableSection->findColumnByAlias($level->key);
                 if (isset($keyColumn)) {
                     $keyColumn->visible = FALSE;
                 }
             }
         }
     }
     $isJoinUsed = $tableJoinIndex > 0;
     if ($isJoinUsed) {
         // adding measures
         if (isset($request->measures)) {
             foreach ($request->measures as $requestMeasure) {
                 $measureName = $requestMeasure->measureName;
                 // we do not need to map the column. It was done in prepareCubeQueryStatement()
                 $databaseColumnName = ParameterHelper::assembleDatabaseColumnName($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 ordering
     $sql = $this->applyOrderBy($sql, $request);
     // 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, $resultFormatter);
 }
    protected function loadIdentifiers($lookupDatasetName, array $uniqueSetColumns, array &$lookupValues) {
        $dataQueryController = data_controller_get_instance();
        $metamodel = data_controller_get_metamodel();

        $lookupDataset = $metamodel->getDataset($lookupDatasetName);
        $identifierColumnName = $lookupDataset->getKeyColumn()->name;

        $lookupCacheKey = $this->prepareLookupCacheKey($lookupDataset->name);

        $isCompositeUniqueSet = count($uniqueSetColumns) > 1;

        // preparing parameters for the query
        $queryParameters = NULL;
        foreach ($lookupValues as $lookupKey => $lookupValue) {
            if (isset($lookupValue->identifier)) {
                continue;
            }

            if (isset($this->cachedIdentifiers[$lookupCacheKey][$lookupKey])) {
                $lookupValues[$lookupKey]->identifier = $this->cachedIdentifiers[$lookupCacheKey][$lookupKey];
                continue;
            }

            if ($isCompositeUniqueSet) {
                $keyColumnValues = NULL;
                foreach ($uniqueSetColumns as $column) {
                    $columnName = $column->name;
                    $keyColumnValues[$columnName] = $lookupValue->$columnName;
                }

                $queryParameters[] = $keyColumnValues;
            }
            else {
                $columnName = $uniqueSetColumns[0]->name;
                $queryParameters[$columnName][] = $lookupValue->$columnName;
            }
        }
        if (!isset($queryParameters)) {
            return;
        }

        // preparing columns for the query
        $queryColumns = array($identifierColumnName);
        foreach ($uniqueSetColumns as $column) {
            ArrayHelper::addUniqueValue($queryColumns, $column->name);
        }

        // loading data from database for 'missing' records
        $loadedLookupProperties = $dataQueryController->queryDataset($lookupDataset->name, $queryColumns, $queryParameters);

        // processing found records
        if (isset($loadedLookupProperties)) {
            $foundUnmatchedIdentifiers = FALSE;
            foreach ($loadedLookupProperties as $lookupProperties) {
                $identifier = $lookupProperties[$identifierColumnName];

                // preparing lookup key
                $keyItems = NULL;
                foreach ($uniqueSetColumns as $column) {
                    $keyItems[] = $lookupProperties[$column->name];
                }
                $lookupKey = self::prepareLookupKey($keyItems);

                if (!isset($lookupValues[$lookupKey])) {
                    if (count($lookupValues) == 1) {
                        // 04/23/2014 if only one record requested and one record received, but the received key does not match the request
                        // it means that character encoding functionality is more sophisticated on server and we actually have a match

                        // storing the value into cache for further usage
                        $this->cachedIdentifiers[$lookupCacheKey][$lookupKey] = $identifier;

                        reset($lookupValues);
                        $alternativeLookupKey = key($lookupValues);
                        $lookupKey = $alternativeLookupKey;
                    }
                    else {
                        $foundUnmatchedIdentifiers = TRUE;
                        continue;
                    }
                }
                if (isset($lookupValues[$lookupKey]->identifier)) {
                    $searchCriteria = array();
                    foreach ($uniqueSetColumns as $column) {
                        $searchCriteria[$column->name] = $lookupProperties[$column->name];
                    }
                    LogHelper::log_error(t(
                        'Key: @searchCriteria. Loaded identifiers: @identifiers',
                        array(
                            '@searchCriteria' => ArrayHelper::serialize($searchCriteria, ', ', TRUE, FALSE),
                            '@identifiers' => ArrayHelper::serialize(array($lookupValues[$lookupKey]->identifier, $identifier), ', ', TRUE, FALSE))));
                    throw new IllegalArgumentException(t(
                        'Several records in %datasetName dataset match search criteria',
                        array('%datasetName' => $lookupDataset->publicName)));
                }
                $lookupValues[$lookupKey]->identifier = $identifier;

                // storing the value into cache for further usage
                $this->cachedIdentifiers[$lookupCacheKey][$lookupKey] = $identifier;
            }

            // found unmatched values. Processing unprocessed lookups one by one
            if ($foundUnmatchedIdentifiers) {
                foreach ($lookupValues as $lookupKey => $lookupValue) {
                    if (!isset($lookupValue->identifier)) {
                        $singleLookupValue = array($lookupKey => $lookupValue);
                        $this->loadIdentifiers($lookupDatasetName, $uniqueSetColumns, $singleLookupValue);
                    }
                }
            }

            $this->freeSpaceInIdentifierCache($lookupDataset->name);
        }
    }
    protected function prepareDatasetSequence(ReferenceCallContext $callcontext, MetaModel $metamodel, ReferenceLink $link, $referencePath) {
        $referenceParts = ReferencePathHelper::splitReference($referencePath);

        $parentColumnName = array_pop($referenceParts);
        $parentDatasetName = array_pop($referenceParts);
        $referencedColumnName = $referencedDatasetName = NULL;

        $leftReferencePartCount = count($referenceParts);

        $nestedReferencePath = $referencePath;
        if ($link->dataset->name == $parentDatasetName) {
            // dataset is there and it is link's dataset
            if ($leftReferencePartCount == 0) {
                return;
            }

            // assembling new reference path
            $nestedReferencePath = ReferencePathHelper::assembleReferenceParts($referenceParts);

            $referencedColumnName = array_pop($referenceParts);
            $referencedDatasetName = array_pop($referenceParts);

            if (!isset($referencedDatasetName)) {
                throw new UnsupportedOperationException(t(
                    'Dataset name is not set in the reference path: %referencePath',
                    array('%referencePath' => $referencePath)));
            }
        }
        elseif (isset($parentDatasetName)) {
            $referencedColumnName = $parentColumnName;
            $referencedDatasetName = $parentDatasetName;
            $parentColumnName = $parentDatasetName = NULL;
        }
        else {
            if ($leftReferencePartCount > 0) {
                throw new UnsupportedOperationException(t(
                    'Dataset name is not set in the reference path: %referencePath',
                    array('%referencePath' => $referencePath)));
            }

            // it means that we just point to column in link's dataset
            return;
        }

        // checking if there any references which could be used to find required dataset
        $references = $metamodel->findReferencesByDatasetName($link->dataset->name);
        if (!isset($references)) {
            return;
        }

        // maximum number of columns in direct references
        $directReferencePointColumnCount = NULL;

        // checking if there is any reference which directly link to referenced dataset
        $parentReferencePointIndex4References = $directReferencePointIndex4References = $transitionalReferencePointIndexes4References = NULL;
        foreach ($references as $reference) {
            $referencePointColumnCount = $reference->getPointColumnCount();

            // checking if the reference can be used to link with other datasets
            $parentReferencePointIndex4Reference = $directReferencePointIndex4Reference = $transitionalReferencePointIndexes4Reference = NULL;
            for ($referencePointColumnIndex = 0; $referencePointColumnIndex < $referencePointColumnCount; $referencePointColumnIndex++) {
                $parentReferencePointIndex = $directReferencePointIndex = $transitionalReferencePointIndexes = NULL;
                foreach ($reference->points as $referencePointIndex => $referencePoint) {
                    $datasetName = $referencePoint->columns[$referencePointColumnIndex]->datasetName;

                    if (($link->dataset->name == $datasetName)
                            && (!isset($parentColumnName) || ($parentColumnName == $referencePoint->columns[$referencePointColumnIndex]->columnName))) {
                        if (isset($parentReferencePointIndex)) {
                            // Found several possible ways to start a join from the referring dataset.
                            // That happens because we do not have parent column name and possible join is ambiguous
                            // We cannot use this way to proceed
                            continue 3;
                        }
                        else {
                            $parentReferencePointIndex = $referencePointIndex;
                        }
                    }
                    elseif ($datasetName == $referencedDatasetName) {
                        if (isset($directReferencePointIndex)) {
                            // found several possible ways to join with the referenced dataset
                            continue 3;
                        }
                        else {
                            $directReferencePointIndex[$referencePointIndex] = TRUE;
                        }
                    }
                    else {
                        $transitionalReferencePointIndexes[$referencePointIndex] = FALSE;
                    }
                }

                // this reference cannot be used because none of the reference points linked with parent dataset
                if (!isset($parentReferencePointIndex)) {
                    continue 2;
                }

                if (isset($directReferencePointIndex)) {
                    // if we have direct reference we do not care about indirect ones
                    $transitionalReferencePointIndexes = NULL;
                }
                else {
                    // there is no direct or indirect ways. This reference is useless :)
                    if (!isset($transitionalReferencePointIndexes)) {
                        continue 2;
                    }
                }

                $parentReferencePointIndex4Reference[$referencePointColumnIndex] = $parentReferencePointIndex;
                if (isset($directReferencePointIndex)) {
                    $directReferencePointIndex4Reference[$referencePointColumnIndex] = $directReferencePointIndex;
                }
                if (isset($transitionalReferencePointIndexes)) {
                    $transitionalReferencePointIndexes4Reference[$referencePointColumnIndex] = $transitionalReferencePointIndexes;
                }
            }

            // we support only direct references between datasets
            // in this case we have direct reference based on some columns only. Rest columns are connected indirectly
            if (isset($directReferencePointIndex4Reference) && isset($transitionalReferencePointIndexes4Reference)) {
                continue;
            }

            $parentReferencePointIndex4References[$reference->name] = $parentReferencePointIndex4Reference;
            if (isset($directReferencePointIndex4Reference)) {
                $directReferencePointIndex4References[$reference->name] = $directReferencePointIndex4Reference;
                $directReferencePointColumnCount = MathHelper::max($directReferencePointColumnCount, $referencePointColumnCount);
            }
            if (isset($transitionalReferencePointIndexes4Reference)) {
                $transitionalReferencePointIndexes4References[$reference->name] = $transitionalReferencePointIndexes4Reference;
            }
        }
        // we could use none of the selected references
        if (!isset($parentReferencePointIndex4References)) {
            return;
        }

        // removing all useless direct and indirect references if there is a direct way
        if (isset($directReferencePointColumnCount)) {
            foreach ($parentReferencePointIndex4References as $referenceName => $parentReferencePointIndex4Reference) {
                $referencePointColumnCount = count($parentReferencePointIndex4Reference);

                if (isset($directReferencePointIndex4References[$referenceName])) {
                    // we preserve only direct ways with maximum number of columns
                    if ($referencePointColumnCount == $directReferencePointColumnCount) {
                        continue;
                    }
                }
                else {
                    // we preserve only indirect ways with more columns than in direct way
                    if ($referencePointColumnCount > $directReferencePointColumnCount) {
                        continue;
                    }
                }

                unset($parentReferencePointIndex4References[$referenceName]);
                unset($directReferencePointIndex4References[$referenceName]);
                unset($transitionalReferencePointIndexes4References[$referenceName]);
            }
        }

        foreach ($parentReferencePointIndex4References as $referenceName => $parentReferencePointIndex4Reference) {
            $reference = $references[ArrayHelper::search($references, 'name', $referenceName)];

            $referencePointColumnCount = $reference->getPointColumnCount();

            $referencePointIndexes4Reference = isset($directReferencePointIndex4References[$referenceName])
                ? $directReferencePointIndex4References[$referenceName]
                : NULL;
            $isDirectReference = isset($referencePointIndexes4Reference);

            if (!$isDirectReference) {
                // 01/09/2014 reference can be reused only for direct references
                if (isset($callcontext->referenceNameStack[$referenceName])) {
                    continue;
                }

                $referencePointIndexes4Reference = isset($transitionalReferencePointIndexes4References[$referenceName])
                    ? $transitionalReferencePointIndexes4References[$referenceName]
                    : NULL;
            }

            // registering the reference in a stack to avoid excessive calls
            // registration was moved here because we could have date[->month->quarter->year] and year columns in one dataset
            // if references related to date and year are registered before we start to process individual references
            // we will end up with nested links for date->month->quarter->year which do not contain a reference to year
            // which leads to GOVDB-1313 issue
            $callcontext->referenceNameStack[$reference->name] = TRUE;

            // preparing dataset names for each reference point
            $referencePointDatasetNames = NULL;
            for ($referencePointColumnIndex = 0; $referencePointColumnIndex < $referencePointColumnCount; $referencePointColumnIndex++) {
                foreach ($referencePointIndexes4Reference[$referencePointColumnIndex] as $referencePointIndex => $directReferencePointFlag) {
                    $referencePointColumn = $reference->points[$referencePointIndex]->columns[$referencePointColumnIndex];
                    $datasetName = $referencePointColumn->datasetName;

                    // it is expected that dataset name is the same for all columns in a reference point
                    if (isset($referencePointDatasetNames[$referencePointIndex])) {
                        if ($referencePointDatasetNames[$referencePointIndex] != $datasetName) {
                            // Dataset name is not the same for all columns for the reference point
                            $referencePointDatasetNames[$referencePointIndex] = FALSE;
                        }
                    }
                    else {
                        $referencePointDatasetNames[$referencePointIndex] = $datasetName;
                    }
                }
            }
            // removing all reference points which we cannot support now
            foreach ($referencePointDatasetNames as $referencePointIndex => $datasetName) {
                if ($datasetName === FALSE) {
                    unset($referencePointDatasetNames[$referencePointIndex]);
                }
            }
            // if nothing left there is not need to proceed
            if (count($referencePointDatasetNames) == 0) {
                continue;
            }

            // preparing list of parent column names
            $parentColumnNames = NULL;
            for ($referencePointColumnIndex = 0; $referencePointColumnIndex < $referencePointColumnCount; $referencePointColumnIndex++) {
                $parentReferencePointIndex = $parentReferencePointIndex4Reference[$referencePointColumnIndex];
                $parentReferencePointColumnName = $reference->points[$parentReferencePointIndex]->columns[$referencePointColumnIndex]->columnName;

                $parentColumnNames[$referencePointColumnIndex] = $parentReferencePointColumnName;
            }

            $referenceCallContext = $isDirectReference ? $callcontext : (clone $callcontext);

            // adding all indirect datasets in stack to prevent recursive calls
            if (!$isDirectReference) {
                foreach ($referencePointDatasetNames as $referencePointIndex => $datasetName) {
                    if (isset($referenceCallContext->datasetNameStack[$datasetName])) {
                        unset($referencePointDatasetNames[$referencePointIndex]);
                    }
                    else {
                        $referenceCallContext->datasetNameStack[$datasetName] = TRUE;
                    }
                }
            }

            foreach ($referencePointDatasetNames as $referencePointIndex => $datasetName) {
                // looking for existing link
                $referencedLink = $link->findNestedLinkByDatasetNameAndParentColumnNames($datasetName, $parentColumnNames);
                if (!isset($referencedLink)) {
                    $dataset = $metamodel->getDataset($datasetName);

                    $referencedLink = new ReferenceLink($dataset);
                    foreach ($parentColumnNames as $referencePointColumnIndex => $parentReferencePointColumnName) {
                        $referencePointColumn = $reference->points[$referencePointIndex]->columns[$referencePointColumnIndex];
                        $referencedLink->linkColumnWithParent($referencePointColumnIndex, $parentReferencePointColumnName, $referencePointColumn->columnName);
                    }

                    $link->registerNestedLink($referencedLink);
                }
                ArrayHelper::addUniqueValue($referencedLink->referenceNames, $referenceName);

                // marking the link as required for the branch so it will not be deleted by the optimizer later
                if ($isDirectReference) {
                    $referencedLink->required = TRUE;
                }

                // because this reference path is not processed completely we need to continue scanning this branch
                if (isset($nestedReferencePath)) {
                    LogHelper::log_debug(t(
                        'Checking sub-path[linkId: @linkId; stackSize: @stackSize]: @referencePath',
                        array('@linkId' => $referencedLink->linkId, '@stackSize' => count($callcontext->referenceNameStack), '@referencePath' => $referencePath)));
                    $referencePointCallContext = clone $referenceCallContext;
                    $this->prepareDatasetSequence($referencePointCallContext, $metamodel, $referencedLink, $nestedReferencePath);
                }
            }
        }
    }
    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);
    }
 public function collectExpressionInTotalFunctionCall(ParserCallback $callback, &$expressions) {
     ArrayHelper::addUniqueValue($expressions, $callback->marker);
 }
    public function assemble(AbstractSQLDataSourceQueryHandler $datasourceHandler, AbstractQueryRequest $request, DatasetMetaData $dataset, array $columnNames = NULL) {
        $statement = new Statement();

        $TABLE_ALIAS__FACTS = 'dsf';
        $TABLE_ALIAS__COLUMN_JOIN = 'cj';

        $metamodel = data_controller_get_metamodel();

        $cubeName = $dataset->name;
        $cube = $metamodel->getCube($cubeName);

        $factsDataset = $metamodel->getDataset($cube->factsDatasetName);

        self::$TABLE_ALIAS_SUFFIX__SEQUENCE++;
        $factsTable = new DatasetSection($factsDataset, $TABLE_ALIAS__FACTS . self::$TABLE_ALIAS_SUFFIX__SEQUENCE);
        $statement->tables[] = $factsTable;

        foreach ($dataset->getColumns() as $column) {
            $columnName = $column->name;

            $columnDefaultAlias = NULL;
            if (isset($columnNames)) {
                $columnDefaultAlias = array_search($columnName, $columnNames);
                if ($columnDefaultAlias === FALSE) {
                    continue;
                }

                // fixing the alias if the list of columns is not associative array
                if (is_int($columnDefaultAlias)) {
                    $columnDefaultAlias = NULL;
                }
            }

            // FIXME the following code does not work in the following situation:
            //   1) we need to query a dataset which is defined in GovDashboard using file upload
            //   2) column names are not provided
            //   3) for columns which are references to lookup, value from the primary key from lookup table is returned
            //      even if in definition of the dataset we have columns with the following application type: name@lookup, code @lookup and etc

            $isReferenceUsed = FALSE;
            $handler = DimensionLookupFactory::getInstance()->findHandler($column->type->getLogicalApplicationType());
            if (isset($handler)) {
                // FIXME remove this implementation when we implement 'Executable Tree' functionality
                list($connectedDatasetName, $connectedColumnName) = $handler->adjustReferencePointColumn($metamodel, $factsDataset->name, $columnName);
                if (($connectedDatasetName != $factsDataset->name) || ($connectedColumnName != $columnName)) {
                    self::$TABLE_ALIAS_SUFFIX__SEQUENCE++;
                    $columnJoinAliasPrefix = $TABLE_ALIAS__COLUMN_JOIN . self::$TABLE_ALIAS_SUFFIX__SEQUENCE;

                    $connectedDataset = $metamodel->getDataset($connectedDatasetName);
                    $connectedDatasetKeyColumnName = $connectedDataset->getKeyColumn()->name;

                    // preparing list of columns we want to get from connected dataset
                    $connectedDatasetColumnNames = NULL;
                    ArrayHelper::addUniqueValue($connectedDatasetColumnNames, $connectedDatasetKeyColumnName);
                    ArrayHelper::addUniqueValue($connectedDatasetColumnNames, $connectedColumnName);

                    $connectedStatement = $datasourceHandler->assembleDatasetSourceStatement($request, $connectedDataset, $connectedDatasetColumnNames);
                    $connectedStatement->addTableAliasPrefix($columnJoinAliasPrefix);

                    $connectedTable = $connectedStatement->getColumnTable($connectedColumnName);
                    // registering the column for facts table
                    $factsTableColumn = new ColumnSection($columnName, 'fact_' . $columnName);
                    $factsTableColumn->visible = FALSE;
                    $factsTable->columns[] = $factsTableColumn;
                    // adjusting key column from lookup
                    $connectedDatasetKeyColumn = $connectedTable->getColumn($connectedDatasetKeyColumnName);
                    $connectedDatasetKeyColumn->alias = 'lookup_' . $connectedDatasetKeyColumnName;
                    $connectedDatasetKeyColumn->visible = FALSE;
                    // adjusting value column from lookup
                    $connectedDatasetValueColumn = $connectedTable->getColumn($connectedColumnName);
                    $connectedDatasetValueColumn->alias = $columnName;
                    // the key column could be the same as value column
                    $connectedDatasetValueColumn->visible = TRUE;
                    // new value column which uses composite name as column alias
                    if (isset($columnDefaultAlias)) {
                        $connectedDatasetValueColumn2 = new ColumnSection(
                            $connectedColumnName,
                            DataSourceColumnNameHelper::generateFromParameterElements($datasourceHandler->getMaximumEntityNameLength(), $columnDefaultAlias));
                        $connectedDatasetValueColumn2->visible = FALSE;
                        $connectedTable->columns[] = $connectedDatasetValueColumn2;
                    }

                    // linking the lookup table with the facts table
                    $connectedTable->conditions[] = new JoinConditionSection(
                        $connectedDatasetKeyColumn->alias, new TableColumnConditionSectionValue($factsTable->alias, $columnName));

                    $statement->merge($connectedStatement);

                    $isReferenceUsed = TRUE;
                }
            }

            if (!$isReferenceUsed) {
                $factsTable->columns[] = new ColumnSection($columnName);
            }
        }

        return $statement;
    }
Example #14
0
 public function addColumn($column)
 {
     ReferencePathHelper::checkReference($column);
     ArrayHelper::addUniqueValue($this->columns, $column);
 }
 public function collectColumnNames(ParserCallback $callback, &$columnNames) {
     ArrayHelper::addUniqueValue($columnNames, $callback->marker);
 }
 public function autoDetectPrimaryDataType(array $values = NULL, $handlerType = DATA_TYPE__PRIMITIVE)
 {
     $primaryDataType = NULL;
     if (isset($values)) {
         $compatibleDataTypes = NULL;
         foreach ($values as $value) {
             $valueDateType = $this->autoDetectDataType($value, $handlerType);
             ArrayHelper::addUniqueValue($compatibleDataTypes, $valueDateType);
         }
         $primaryDataType = $this->selectDataType($compatibleDataTypes);
     }
     return $primaryDataType;
 }
    public function getConnectedDatasetNames($includeRoot = TRUE, $includeTransitional = TRUE) {
        $datasetNames = NULL;

        if ($includeRoot) {
            ArrayHelper::addUniqueValue($datasetNames, $this->dataset->name);
        }

        ArrayHelper::addUniqueValues($datasetNames, $this->getConnectedNestedDatasetNames($includeTransitional));

        return $datasetNames;
    }
    protected static function detectConnectedDatasetsBySelectedColumns(array $parsedUIMetaDataNames) {
        $datasetNames = NULL;

        foreach ($parsedUIMetaDataNames as $parsedUIMetaDataName) {
            ArrayHelper::addUniqueValue($datasetNames, $parsedUIMetaDataName->datasetName);
        }

        return $datasetNames;
    }