HHH-10934 - Check ForeignKey on function instead of only the name
This commit is contained in:
parent
736da3247c
commit
2867e070ea
|
@ -11,6 +11,9 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
|
@ -35,6 +38,7 @@ import org.hibernate.resource.transaction.spi.DdlTransactionIsolator;
|
|||
import org.hibernate.tool.hbm2ddl.UniqueConstraintSchemaUpdateStrategy;
|
||||
import org.hibernate.tool.schema.extract.spi.DatabaseInformation;
|
||||
import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation;
|
||||
import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation.ColumnReferenceMapping;
|
||||
import org.hibernate.tool.schema.extract.spi.IndexInformation;
|
||||
import org.hibernate.tool.schema.extract.spi.NameSpaceTablesInformation;
|
||||
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
|
||||
|
@ -414,14 +418,14 @@ public abstract class AbstractSchemaMigrator implements SchemaMigrator {
|
|||
while ( fkItr.hasNext() ) {
|
||||
final ForeignKey foreignKey = fkItr.next();
|
||||
if ( foreignKey.isPhysicalConstraint() && foreignKey.isCreationEnabled() ) {
|
||||
ForeignKeyInformation existingForeignKey = null;
|
||||
boolean existingForeignKeyFound = false;
|
||||
if ( tableInformation != null ) {
|
||||
existingForeignKey = findMatchingForeignKey(
|
||||
existingForeignKeyFound = checkForExistingForeignKey(
|
||||
foreignKey,
|
||||
tableInformation
|
||||
);
|
||||
}
|
||||
if ( existingForeignKey == null ) {
|
||||
if ( !existingForeignKeyFound ) {
|
||||
// todo : shouldn't we just drop+recreate if FK exists?
|
||||
// this follows the existing code from legacy SchemaUpdate which just skipped
|
||||
|
||||
|
@ -439,11 +443,41 @@ public abstract class AbstractSchemaMigrator implements SchemaMigrator {
|
|||
}
|
||||
}
|
||||
|
||||
private ForeignKeyInformation findMatchingForeignKey(ForeignKey foreignKey, TableInformation tableInformation) {
|
||||
if ( foreignKey.getName() == null ) {
|
||||
return null;
|
||||
/**
|
||||
* Check if the ForeignKey already exists. First check based on definition and if that is not matched check if a key
|
||||
* with the exact same name exists. Keys with the same name are presumed to be functional equal.
|
||||
*
|
||||
* @param foreignKey - ForeignKey, new key to be created
|
||||
* @param tableInformation - TableInformation, information of existing keys
|
||||
* @return boolean, true if key already exists
|
||||
*/
|
||||
private boolean checkForExistingForeignKey(ForeignKey foreignKey, TableInformation tableInformation) {
|
||||
if ( foreignKey.getName() == null || tableInformation == null ) {
|
||||
return false;
|
||||
}
|
||||
return tableInformation.getForeignKey( Identifier.toIdentifier( foreignKey.getName() ) );
|
||||
|
||||
final String referencingColumn = foreignKey.getColumn( 0 ).getName();
|
||||
final String referencedTable = foreignKey.getReferencedTable().getName();
|
||||
|
||||
/*
|
||||
* Find existing keys based on referencing column and referencedTable. "referencedColumnName" is not checked
|
||||
* because that always is the primary key of the "referencedTable".
|
||||
*/
|
||||
Predicate<ColumnReferenceMapping> mappingPredicate = m -> {
|
||||
String existingReferencingColumn = m.getReferencingColumnMetadata().getColumnIdentifier().getText();
|
||||
String existingReferencedTable = m.getReferencedColumnMetadata().getContainingTableInformation().getName().getTableName().getCanonicalName();
|
||||
return referencingColumn.equals( existingReferencingColumn ) && referencedTable.equals( existingReferencedTable );
|
||||
};
|
||||
Stream<ForeignKeyInformation> keyStream = StreamSupport.stream( tableInformation.getForeignKeys().spliterator(), false );
|
||||
Stream<ColumnReferenceMapping> mappingStream = keyStream.flatMap( k -> StreamSupport.stream( k.getColumnReferenceMappings().spliterator(), false ) );
|
||||
boolean found = mappingStream.anyMatch( mappingPredicate );
|
||||
if ( found ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// And at the end just compare the name of the key. If a key with the same name exists we assume the function is
|
||||
// also the same...
|
||||
return tableInformation.getForeignKey( Identifier.toIdentifier( foreignKey.getName() ) ) != null;
|
||||
}
|
||||
|
||||
protected void checkExportIdentifier(Exportable exportable, Set<String> exportIdentifiers) {
|
||||
|
|
Loading…
Reference in New Issue