protected function revertIneligibleColumnPropertyValues(DatasetMetaData $dataset) {
        // excluded columns cannot be part of primary key
        foreach ($dataset->getColumns(FALSE) as $column) {
            if ($column->isUsed()) {
                continue;
            }

            if ($column->isKey()) {
                $column->key = FALSE;
            }
        }
    }
 protected function isDependent(DatasetMetaData $dataset, DatasetMetaData $datasetB)
 {
     $referenceCount = 0;
     foreach ($dataset->getColumns() as $column) {
         list($referencedDatasetName) = ReferencePathHelper::splitReference($column->type->applicationType);
         if (isset($referencedDatasetName)) {
             $referenceCount++;
         } else {
             continue;
         }
         if ($referencedDatasetName == $datasetB->name) {
             return array(TRUE, NULL);
         }
     }
     return array(FALSE, $referenceCount);
 }
    public function generate(DatasetUIMetaData $datasetUIMetaData, DatasetMetaData $dataset, $referencePath = NULL) {
        // to prevent recursive references
        $datasetStack = array($dataset->name => TRUE);

        $datasetUIMetaData->name = $dataset->name;
        $datasetUIMetaData->publicName = $dataset->publicName;
        $datasetUIMetaData->description = $dataset->description;

        foreach ($dataset->getColumns() as $column) {
            if (!$column->isVisible()) {
                continue;
            }

            $columnUIMetaData = $this->prepareColumnUIMetaData($datasetStack, $referencePath, $dataset, $column->name);
            $datasetUIMetaData->registerAttribute($columnUIMetaData);
        }
    }
    /**
     * @param DataControllerCallContext $callcontext
     * @param DatasetMetaData $dataset
     * @param DatasetStorageObserver[] $observers
     * @throws Exception
     */
    protected function dropColumnStorage(DataControllerCallContext $callcontext, DatasetMetaData $dataset, array $observers = NULL) {
        if (isset($observers)) {
            // dropping physical storage of the dataset columns
            foreach ($dataset->getColumns(FALSE) as $column) {
                if ($column->persistence != ColumnMetaData::PERSISTENCE__STORAGE_CREATED) {
                    continue;
                }

                MetaModelFactory::getInstance()->startGlobalModification();
                try {
                    $transaction = db_transaction();
                    try {
                        if (isset($observers)) {
                            foreach ($observers as $observer) {
                                $observer->dropColumnStorage(
                                    $callcontext, $this->datasourceStructureHandler,
                                    $dataset, $column->name, DatasetStorageObserver::STAGE__BEFORE);
                            }
                        }

                        $column->persistence = ColumnMetaData::PERSISTENCE__NO_STORAGE;
                        $column->used = FALSE;

                        if (isset($observers)) {
                            foreach ($observers as $observer) {
                                $observer->dropColumnStorage(
                                    $callcontext, $this->datasourceStructureHandler,
                                    $dataset, $column->name, DatasetStorageObserver::STAGE__AFTER);
                            }
                        }
                    }
                    catch (Exception $e) {
                        $transaction->rollback();
                        throw $e;
                    }
                }
                catch (Exception $e) {
                    MetaModelFactory::getInstance()->finishGlobalModification(FALSE);
                    throw $e;
                }
                MetaModelFactory::getInstance()->finishGlobalModification(TRUE);
            }
        }
    }
 protected function assembleForeignKeyConstraints(DataSourceHandler $handler, DatasetMetaData $dataset, $indent, &$sql)
 {
     $metamodel = data_controller_get_metamodel();
     foreach ($dataset->getColumns() as $column) {
         $columnName = $column->name;
         if (!isset($column->type->sourceApplicationType)) {
             continue;
         }
         // the column has to contain a reference to another dataset
         $dimensionLookupHandler = DimensionLookupFactory::getInstance()->getHandler($column->type->sourceApplicationType);
         list($referencedDatasetName) = $dimensionLookupHandler->adjustReferencePointColumn($metamodel, $dataset->name, $column->name);
         if ($dataset->name == $referencedDatasetName) {
             continue;
         }
         $referencedDataset = $metamodel->getDataset($referencedDatasetName);
         // we can create a foreign key constraint referenced to a table only
         $referencedDatasetSourceType = DatasetTypeHelper::detectDatasetSourceType($referencedDataset);
         if ($referencedDatasetSourceType != DatasetTypeHelper::DATASET_SOURCE_TYPE__TABLE) {
             continue;
         }
         $referencedOwner = NULL;
         if ($dataset->datasourceName != $referencedDataset->datasourceName) {
             // if we cannot join datasets we cannot create a foreign key constraint
             $datasourceQueryHandler = DataSourceQueryFactory::getInstance()->getHandler($handler->getDataSourceType());
             if (!$datasourceQueryHandler->isJoinSupported($dataset->datasourceName, $referencedDataset->datasourceName)) {
                 continue;
             }
             $referencedOwner = $handler->getDataSourceOwner($referencedDataset->datasourceName);
         }
         $referencedTableName = $referencedDataset->source;
         $referencedColumnName = $referencedDataset->getKeyColumn()->name;
         $sql .= ",\n{$indent}CONSTRAINT fk_{$dataset->source}_{$columnName} FOREIGN KEY ({$columnName}) REFERENCES " . (isset($referencedOwner) ? $referencedOwner . '.' : '') . "{$referencedTableName} ({$referencedColumnName})";
     }
 }
    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;
    }
 public static function deinitializeByDataset(MetaModel $metamodel, DatasetMetaData $dataset)
 {
     $cubeName = $dataset->name;
     $cube = $metamodel->unregisterCube($cubeName);
     // de-initializing dimensions
     foreach ($dataset->getColumns() as $column) {
         self::deinitializeByColumn($cube, $dataset, $column->name);
     }
     $metamodel->unregisterDataset($cube->factsDatasetName);
 }
    protected function gatherChanges(DataControllerCallContext $callcontext, DatasetMetaData $originalDataset, DatasetMetaData $modifiedDataset, array $observers = NULL) {
        foreach ($modifiedDataset->getColumns(FALSE) as $modifiedColumn) {
            $originalColumn = $originalDataset->findColumn($modifiedColumn->name);
            if (!isset($originalColumn)) {
                // preparing new included & excluded columns
                if ($modifiedColumn->isUsed()) {
                    $callcontext->changeAction->newIncludedColumns[$modifiedColumn->name] = $modifiedColumn;
                }
                else {
                    $callcontext->changeAction->newExcludedColumns[$modifiedColumn->name] = $modifiedColumn;
                }

                // checking if new column marked as part of primary key
                if ($modifiedColumn->isKey()) {
                    $callcontext->changeAction->isKeyUpdated = TRUE;
                }
            }
        }

        foreach ($originalDataset->getColumns(FALSE) as $originalColumn) {
            $modifiedColumn = $modifiedDataset->findColumn($originalColumn->name);
            if (isset($modifiedColumn)) {
                $isColumnUpdated = FALSE;

                // preparing restored columns
                if (!$originalColumn->isUsed() && $modifiedColumn->isUsed()) {
                    $callcontext->changeAction->restoredColumns[$originalColumn->name] = $originalColumn;
                }

                // preparing excluded columns
                if ($originalColumn->isUsed() && !$modifiedColumn->isUsed()) {
                    $callcontext->changeAction->excludedColumns[$originalColumn->name] = $originalColumn;
                    // excluding a column which is part of primary key
                    if ($originalColumn->isKey()) {
                        $callcontext->changeAction->isKeyUpdated = TRUE;
                    }
                }

                // preparing relocated columns
                if ($originalColumn->columnIndex != $modifiedColumn->columnIndex) {
                    $callcontext->changeAction->updatedIndexColumns[$originalColumn->name] = $originalColumn;
                }

                // preparing columns with changed data type
                if (($originalColumn->type->applicationType != $modifiedColumn->type->applicationType)
                        || ($originalColumn->type->getLogicalApplicationType() != $modifiedColumn->type->getLogicalApplicationType())) {
                    // marking that the column data type was updated
                    if ($modifiedColumn->isUsed()) {
                        $callcontext->changeAction->updatedDataTypeIncludedColumns[$originalColumn->name] = $originalColumn;
                        // updating type a column which is part of the primary key
                        if ($originalColumn->isKey()) {
                            $callcontext->changeAction->isKeyUpdated = TRUE;
                        }
                    }
                    else {
                        $callcontext->changeAction->updatedDataTypeExcludedColumns[$originalColumn->name] = $originalColumn;
                    }
                    // checking if old & new types are compatible
                    if ($this->checkIfDataTypeCompatible($originalColumn->type, $modifiedColumn->type)) {
                        $callcontext->changeAction->updatedDataTypeCompatibleColumns[$originalColumn->name] = $originalColumn;
                    }

                    $isColumnUpdated = TRUE;
                }

                // checking if any column properties were updated
                if (($originalColumn->publicName != $modifiedColumn->publicName)
                        || ($originalColumn->description != $modifiedColumn->description)
                        || ($originalColumn->source != $modifiedColumn->source)) {
                    $isColumnUpdated = TRUE;
                }

                // checking if a column in primary key was added or removed
                if ($originalColumn->isKey() != $modifiedColumn->isKey()) {
                    $isColumnUpdated = TRUE;
                    $callcontext->changeAction->isKeyUpdated = TRUE;
                }

                // preparing updated columns
                if ($isColumnUpdated) {
                    $callcontext->changeAction->updatedColumns[$originalColumn->name] = $originalColumn;
                }
            }
            else {
                // preparing deleted columns
                $callcontext->changeAction->deletedColumns[$originalColumn->name] = $originalColumn;

                // deleting a column which is part of the primary key
                if ($originalColumn->isKey()) {
                    $callcontext->changeAction->isKeyUpdated = TRUE;
                }
            }
        }

        // preparing updated dataset
        if (($originalDataset->publicName != $modifiedDataset->publicName)
                || ($originalDataset->description != $modifiedDataset->description)
                || (compare_values($originalDataset->source, $modifiedDataset->source) != 0)
                || (compare_values($originalDataset->aliases, $modifiedDataset->aliases) != 0)) {
            $callcontext->changeAction->isDatasetUpdated = TRUE;
        }
    }
    protected function prepareColumnCreateStatements(DataSourceHandler $handler, DatasetMetaData $dataset) {
        $columnSQLs = NULL;
        foreach ($dataset->getColumns() as $column) {
            $columnSQLs[$column->columnIndex] = $this->prepareColumnCreateStatement($handler, $column, $column->isKey());
        }
        if (!isset($columnSQLs)) {
            throw new IllegalArgumentException(t(
                "'@datasetName' dataset must have at least one column to create permanent storage",
                array('@datasetName' => $dataset->publicName)));
        }

        // sorting columns by column index
        ksort($columnSQLs);

        return $columnSQLs;
    }