Collects queries about foreign keys to alter a table.

@param \Fridge\DBAL\Schema\Diff\TableDiff $tableDiff The table difference.
967619
private function collectForeignKeys(TableDiff $tableDiff)
    {
        foreach ($tableDiff->getCreatedForeignKeys() as $foreignKey) {
            $this->createForeignKeyQueries = array_merge(
                $this->createForeignKeyQueries,
                $this->platform->getCreateForeignKeySQLQueries($foreignKey, $tableDiff->getNewAsset()->getName())
            );
        }

        foreach ($tableDiff->getDroppedForeignKeys() as $foreignKey) {
            $this->dropForeignKeyQueries = array_merge(
                $this->dropForeignKeyQueries,
                $this->platform->getDropForeignKeySQLQueries($foreignKey, $tableDiff->getNewAsset()->getName())
            );
        }
    }
339077
public function diffChangeLogFromSchemaDiff(SchemaDiff $schemaDiff, $output = null)
    {
        $output = $this->sanitizeOutputParameter($output);

        $output->started($this->em);

        foreach ($schemaDiff->newNamespaces as $newNamespace) {
            $output->createSchema($newNamespace);
        }

        foreach ($schemaDiff->orphanedForeignKeys as $orphanedForeignKey) {
            $output->dropForeignKey($orphanedForeignKey, $orphanedForeignKey->getLocalTable());
        }

        foreach ($schemaDiff->changedSequences as $sequence) {
            $output->alterSequence($sequence);
        }

        foreach ($schemaDiff->removedSequences as $sequence) {
            $output->dropSequence($sequence);
        }

        foreach ($schemaDiff->newSequences as $sequence) {
            $output->createSequence($sequence);
        }

        foreach ($schemaDiff->newTables as $table) {
            $output->createTable($table);
            
            foreach ($table->getForeignKeys() as $foreignKey) {
                $output->createForeignKey($foreignKey, $table);
            }
        }

        foreach ($schemaDiff->removedTables as $table) {
            $output->dropTable($table);
        }

        foreach ($schemaDiff->changedTables as $tableDiff) {
            $output->alterTable($tableDiff);
        }

        $output->terminated();

        return $output->getResult();
    }
50454
private function getAddedIndexes($tableName, TableDiff $diff)
    {
        /** @var $index \Doctrine\DBAL\Schema\Index */
        foreach ($diff->addedIndexes as $index) {
            $this->addMessage($tableName, sprintf('missing index on `%s`', implode(', ', $index->getUnquotedColumns())));
        }
    }
356498
private function detectIndexRenamings(TableDiff $tableDifferences)
    {
        $renameCandidates = [];

        // Gather possible rename candidates by comparing each added and removed index based on semantics.
        foreach ($tableDifferences->addedIndexes as $addedIndexName => $addedIndex) {
            foreach ($tableDifferences->removedIndexes as $removedIndex) {
                if ($this->diffIndex($addedIndex, $removedIndex)) {
                    continue;
                }

                $renameCandidates[$addedIndex->getName()][] = [$removedIndex, $addedIndex, $addedIndexName];
            }
        }

        foreach ($renameCandidates as $candidateIndexes) {
            // If the current rename candidate contains exactly one semantically equal index,
            // we can safely rename it.
            // Otherwise it is unclear if a rename action is really intended,
            // therefore we let those ambiguous indexes be added/dropped.
            if (count($candidateIndexes) !== 1) {
                continue;
            }

            [$removedIndex, $addedIndex] = $candidateIndexes[0];

            $removedIndexName = strtolower($removedIndex->getName());
            $addedIndexName   = strtolower($addedIndex->getName());

            if (isset($tableDifferences->renamedIndexes[$removedIndexName])) {
                continue;
            }

            $tableDifferences->renamedIndexes[$removedIndexName] = $addedIndex;
            unset(
                $tableDifferences->addedIndexes[$addedIndexName],
                $tableDifferences->removedIndexes[$removedIndexName]
            );
        }
    }
1361390
private function diffTableMergeQueries(
        $table,
        &$fields,
        &$foQueries,
        &$soQueries
    ) {
        $key = $this->diffTableFieldPrimaryKey($fields);

        if ($key && count($foQueries) > 0) {
            $writer = $this->getWriter();

            $foQueries[] = $writer->alterTableDropPrimaryKey($table);

            $fields[$key]['Key'] = '';
            $fields[$key]['Extra'] = '';

            $foQueries[] = $writer->alterTableChange(
                $table,
                $key,
                $fields[$key]
            );
        }

        return array_merge(array_reverse($foQueries), $soQueries);
    }
1021651
private function collectSequences(SchemaDiff $schemaDiff)
    {
        foreach ($schemaDiff->getCreatedSequences() as $sequence) {
            $this->createSequenceQueries = array_merge(
                $this->createSequenceQueries,
                $this->platform->getCreateSequenceSQLQueries($sequence)
            );
        }

        foreach ($schemaDiff->getDroppedSequences() as $sequence) {
            $this->dropSequenceQueries = array_merge(
                $this->dropSequenceQueries,
                $this->platform->getDropSequenceSQLQueries($sequence)
            );
        }
    }
561798
protected function getPreAlterTableRenameIndexForeignKeySQL(TableDiff $diff)
    {
        $sql       = [];
        $tableName = $diff->getName($this)->getQuotedName($this);

        foreach ($this->getRemainingForeignKeyConstraintsRequiringRenamedIndexes($diff) as $foreignKey) {
            if (in_array($foreignKey, $diff->changedForeignKeys, true)) {
                continue;
            }

            $sql[] = $this->getDropForeignKeySQL($foreignKey, $tableName);
        }

        return $sql;
    }
1015627
private function getAlterColumnClausesSQL(ColumnDiff $columnDiff)
    {
        $column = $columnDiff->column->toArray();

        $alterClause = 'ALTER COLUMN ' . $columnDiff->column->getQuotedName($this);

        if ($column['columnDefinition']) {
            return [$alterClause . ' ' . $column['columnDefinition']];
        }

        $clauses = [];

        if ($columnDiff->hasChanged('type') ||
            $columnDiff->hasChanged('length') ||
            $columnDiff->hasChanged('precision') ||
            $columnDiff->hasChanged('scale') ||
            $columnDiff->hasChanged('fixed')
        ) {
            $clauses[] = $alterClause . ' SET DATA TYPE ' . $column['type']->getSQLDeclaration($column, $this);
        }

        if ($columnDiff->hasChanged('notnull')) {
            $clauses[] = $column['notnull'] ? $alterClause . ' SET NOT NULL' : $alterClause . ' DROP NOT NULL';
        }

        if ($columnDiff->hasChanged('default')) {
            if (isset($column['default'])) {
                $defaultClause = $this->getDefaultValueDeclarationSQL($column);

                if ($defaultClause) {
                    $clauses[] = $alterClause . ' SET' . $defaultClause;
                }
            } else {
                $clauses[] = $alterClause . ' DROP DEFAULT';
            }
        }

        return $clauses;
    }
444483
private function processDiffs(array $tables, Config $config)
    {
        $stat = $config['diff_col'];

        if ($config['compare']) {
            return $tables;
        }

        if (!in_array('diff', $config['cols'])) {
            return $tables;
        }

        if (!in_array($stat, $config['cols'])) {
            throw new \InvalidArgumentException(sprintf(
                'The "%s" column must be visible when using the diff column',
                $stat
            ));
        }

        return F\map($tables, function ($table) use ($stat) {
            $means = F\map($table, function ($row) use ($stat) {
                return $row[$stat];
            });
            $min = min($means);

            return F\map($table, function ($row) use ($min, $stat) {
                if ($row[$stat] === 0) {
                    $row['diff'] = 0;

                    return $row;
                }

                $row['diff'] = $row[$stat] / $min;

                return $row;
            });
        });
    }
869333
protected function filterAndSeparateForeignKeys($foreignKeys, $table)
    {
        $results = ['local' => [], 'remote' => []];
        foreach ($foreignKeys as $foreignKey) {
            if ($foreignKey->TABLE_NAME == $table) {
                $results['local'][] = $foreignKey;
            }
            if ($foreignKey->REFERENCED_TABLE_NAME == $table) {
                $results['remote'][] = $foreignKey;
            }
        }

        return $results;
    }
896407
private function detectColumnRenamings(TableDiff $tableDifferences)
    {
        $renameCandidates = [];
        foreach ($tableDifferences->addedColumns as $addedColumnName => $addedColumn) {
            foreach ($tableDifferences->removedColumns as $removedColumn) {
                if (count($this->diffColumn($addedColumn, $removedColumn)) !== 0) {
                    continue;
                }

                $renameCandidates[$addedColumn->getName()][] = [$removedColumn, $addedColumn, $addedColumnName];
            }
        }

        foreach ($renameCandidates as $candidateColumns) {
            if (count($candidateColumns) !== 1) {
                continue;
            }

            [$removedColumn, $addedColumn] = $candidateColumns[0];
            $removedColumnName             = strtolower($removedColumn->getName());
            $addedColumnName               = strtolower($addedColumn->getName());

            if (isset($tableDifferences->renamedColumns[$removedColumnName])) {
                continue;
            }

            $tableDifferences->renamedColumns[$removedColumnName] = $addedColumn;
            unset(
                $tableDifferences->addedColumns[$addedColumnName],
                $tableDifferences->removedColumns[$removedColumnName]
            );
        }
    }
480092
public function getModifyTablePrimaryKeyDDL(TableDiff $tableDiff)
    {
        $ret = '';

        if ($tableDiff->hasModifiedPk()) {
            $ret .= $this->getDropPrimaryKeyDDL($tableDiff->getFromTable());
            $ret .= $this->getAddPrimaryKeyDDL($tableDiff->getToTable());
        }

        return $ret;
    }
843479
protected function isSchemaDiffEmpty(SchemaDiff $diff) : bool
    {
        return empty(array_filter([
                $diff->changedSequences,
                $diff->changedTables,
                $diff->newNamespaces,
                $diff->newSequences,
                $diff->newTables,
                $diff->removedTables,
                $diff->removedNamespaces,
                $diff->removedSequences,
                $diff->orphanedForeignKeys,
        ]));
    }
1017429
protected function onSchemaAlterTableChangeColumn(ColumnDiff $columnDiff, TableDiff $diff, &$columnSql)
    {
        if ($this->_eventManager === null) {
            return false;
        }

        if (! $this->_eventManager->hasListeners(Events::onSchemaAlterTableChangeColumn)) {
            return false;
        }

        $eventArgs = new SchemaAlterTableChangeColumnEventArgs($columnDiff, $diff, $this);
        $this->_eventManager->dispatchEvent(Events::onSchemaAlterTableChangeColumn, $eventArgs);

        $columnSql = array_merge($columnSql, $eventArgs->getSql());

        return $eventArgs->isDefaultPrevented();
    }
379558
private function writeChangedTable( $tableName, ezcDbSchemaTableDiff $changedTable )
    {
        $this->writer->startElement( 'table' );
        $this->writer->startElement( 'name' );
        $this->writer->text( $tableName );
        $this->writer->endElement();
        $this->writer->flush();

        // added fields 
        $this->writer->startElement( 'added-fields' );
        $this->writer->flush();
        foreach ( $changedTable->addedFields as $fieldName => $field )
        {
            $this->writer->startElement( 'field' );
            $this->writeField( $fieldName, $field );

            $this->writer->endElement();
            $this->writer->flush();
        }
        $this->writer->endElement();
        $this->writer->flush();

        // changed fields 
        $this->writer->startElement( 'changed-fields' );
        $this->writer->flush();
        foreach ( $changedTable->changedFields as $fieldName => $field )
        {
            $this->writer->startElement( 'field' );
            $this->writeField( $fieldName, $field );

            $this->writer->endElement();
            $this->writer->flush();
        }
        $this->writer->endElement();
        $this->writer->flush();

        // Removed fields
        $this->writer->startElement( 'removed-fields' );
        $this->writer->flush();
        foreach ( $changedTable->removedFields as $fieldName => $fieldStatus )
        {
            $this->writer->startElement( 'field' );
            $this->writer->startElement( 'name' );
            $this->writer->text( $fieldName );
            $this->writer->endElement();
            $this->writer->startElement( 'removed' );
            $this->writer->text( $fieldStatus ? 'true' : 'false' );
            $this->writer->endElement();
            $this->writer->endElement();
            $this->writer->flush();
        }
        $this->writer->endElement();
        $this->writer->flush();

        // added indexes 
        $this->writer->startElement( 'added-indexes' );
        $this->writer->flush();
        foreach ( $changedTable->addedIndexes as $indexName => $index )
        {
            $this->writer->startElement( 'index' );
            $this->writeIndex( $indexName, $index );

            $this->writer->endElement();
            $this->writer->flush();
        }
        $this->writer->endElement();
        $this->writer->flush();

        // changed indexes 
        $this->writer->startElement( 'changed-indexes' );
        $this->writer->flush();
        foreach ( $changedTable->changedIndexes as $indexName => $index )
        {
            $this->writer->startElement( 'index' );
            $this->writeIndex( $indexName, $index );

            $this->writer->endElement();
            $this->writer->flush();
        }
        $this->writer->endElement();
        $this->writer->flush();

        // Removed indexes
        $this->writer->startElement( 'removed-indexes' );
        $this->writer->flush();
        foreach ( $changedTable->removedIndexes as $indexName => $indexStatus )
        {
            $this->writer->startElement( 'index' );
            $this->writer->startElement( 'name' );
            $this->writer->text( $indexName );
            $this->writer->endElement();
            $this->writer->startElement( 'removed' );
            $this->writer->text( $indexStatus ? 'true' : 'false' );
            $this->writer->endElement();
            $this->writer->endElement();
            $this->writer->flush();
        }

        $this->writer->endElement();
        $this->writer->flush();

        $this->writer->endElement();
    }
1317680
protected function adjustDiffs(array $protectedTableNames)
    {
        $diffUpdater = new DiffUpdater($this->ignoredChanges);

        /** @var TableDiff $tableDiff */
        foreach ($this->diffs as $tableName => $tableDiff) {
            $this->adjustContentTypeDiffs($tableDiff, $protectedTableNames);
            $this->diffs[$tableName] = $diffUpdater->adjustDiff($tableDiff);
            if ($this->diffs[$tableName] === false) {
                unset($this->diffs[$tableName]);
                continue;
            }
        }
    }
25952
private function getRenamedColumns($tableName, TableDiff $diff)
    {
        foreach (array_keys($diff->renamedColumns) as $colName) {
            $this->addMessage($tableName, sprintf('renamed column `%s`', $colName));
        }
    }