HHH-18619 add support for @ForeignKey(options), @UniqueConstraint(options), @Index(options)

This commit is contained in:
Gavin King 2024-09-14 15:21:50 +02:00
parent 9f2beca226
commit 5f8bf125fc
29 changed files with 196 additions and 104 deletions

View File

@ -2075,6 +2075,7 @@ public abstract class CollectionBinder {
else { else {
key.setForeignKeyName( nullIfEmpty( foreignKey.name() ) ); key.setForeignKeyName( nullIfEmpty( foreignKey.name() ) );
key.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) ); key.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) );
key.setForeignKeyOptions( foreignKey.options() );
if ( key.getForeignKeyName() == null if ( key.getForeignKeyName() == null
&& key.getForeignKeyDefinition() == null && key.getForeignKeyDefinition() == null
&& collectionTableAnn.joinColumns().length == 1 ) { && collectionTableAnn.joinColumns().length == 1 ) {
@ -2082,6 +2083,7 @@ public abstract class CollectionBinder {
final ForeignKey nestedForeignKey = joinColumn.foreignKey(); final ForeignKey nestedForeignKey = joinColumn.foreignKey();
key.setForeignKeyName( nullIfEmpty( nestedForeignKey.name() ) ); key.setForeignKeyName( nullIfEmpty( nestedForeignKey.name() ) );
key.setForeignKeyDefinition( nullIfEmpty( nestedForeignKey.foreignKeyDefinition() ) ); key.setForeignKeyDefinition( nullIfEmpty( nestedForeignKey.foreignKeyDefinition() ) );
key.setForeignKeyOptions( nestedForeignKey.options() );
} }
} }
} }
@ -2091,6 +2093,7 @@ public abstract class CollectionBinder {
final ForeignKey foreignKey = joinTableAnn.foreignKey(); final ForeignKey foreignKey = joinTableAnn.foreignKey();
String foreignKeyName = foreignKey.name(); String foreignKeyName = foreignKey.name();
String foreignKeyDefinition = foreignKey.foreignKeyDefinition(); String foreignKeyDefinition = foreignKey.foreignKeyDefinition();
String foreignKeyOptions = foreignKey.options();
ConstraintMode foreignKeyValue = foreignKey.value(); ConstraintMode foreignKeyValue = foreignKey.value();
final JoinColumn[] joinColumnAnnotations = joinTableAnn.joinColumns(); final JoinColumn[] joinColumnAnnotations = joinTableAnn.joinColumns();
if ( !ArrayHelper.isEmpty( joinColumnAnnotations ) ) { if ( !ArrayHelper.isEmpty( joinColumnAnnotations ) ) {
@ -2099,6 +2102,7 @@ public abstract class CollectionBinder {
if ( foreignKeyName.isEmpty() ) { if ( foreignKeyName.isEmpty() ) {
foreignKeyName = joinColumnForeignKey.name(); foreignKeyName = joinColumnForeignKey.name();
foreignKeyDefinition = joinColumnForeignKey.foreignKeyDefinition(); foreignKeyDefinition = joinColumnForeignKey.foreignKeyDefinition();
foreignKeyOptions = joinColumnForeignKey.options();
} }
if ( foreignKeyValue != NO_CONSTRAINT ) { if ( foreignKeyValue != NO_CONSTRAINT ) {
foreignKeyValue = joinColumnForeignKey.value(); foreignKeyValue = joinColumnForeignKey.value();
@ -2111,6 +2115,7 @@ public abstract class CollectionBinder {
else { else {
key.setForeignKeyName( nullIfEmpty( foreignKeyName ) ); key.setForeignKeyName( nullIfEmpty( foreignKeyName ) );
key.setForeignKeyDefinition( nullIfEmpty( foreignKeyDefinition ) ); key.setForeignKeyDefinition( nullIfEmpty( foreignKeyDefinition ) );
key.setForeignKeyOptions( foreignKeyOptions );
} }
} }
else { else {
@ -2155,6 +2160,7 @@ public abstract class CollectionBinder {
else { else {
key.setForeignKeyName( nullIfEmpty( foreignKey.name() ) ); key.setForeignKeyName( nullIfEmpty( foreignKey.name() ) );
key.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) ); key.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) );
key.setForeignKeyOptions( foreignKey.options() );
} }
} }
@ -2425,6 +2431,7 @@ public abstract class CollectionBinder {
final ForeignKey inverseForeignKey = joinTableAnn.inverseForeignKey(); final ForeignKey inverseForeignKey = joinTableAnn.inverseForeignKey();
String foreignKeyName = inverseForeignKey.name(); String foreignKeyName = inverseForeignKey.name();
String foreignKeyDefinition = inverseForeignKey.foreignKeyDefinition(); String foreignKeyDefinition = inverseForeignKey.foreignKeyDefinition();
String foreignKeyOptions = inverseForeignKey.options();
final JoinColumn[] inverseJoinColumns = joinTableAnn.inverseJoinColumns(); final JoinColumn[] inverseJoinColumns = joinTableAnn.inverseJoinColumns();
if ( !ArrayHelper.isEmpty( inverseJoinColumns ) ) { if ( !ArrayHelper.isEmpty( inverseJoinColumns ) ) {
@ -2433,6 +2440,7 @@ public abstract class CollectionBinder {
final ForeignKey inverseJoinColumnForeignKey = joinColumnAnn.foreignKey(); final ForeignKey inverseJoinColumnForeignKey = joinColumnAnn.foreignKey();
foreignKeyName = inverseJoinColumnForeignKey.name(); foreignKeyName = inverseJoinColumnForeignKey.name();
foreignKeyDefinition = inverseJoinColumnForeignKey.foreignKeyDefinition(); foreignKeyDefinition = inverseJoinColumnForeignKey.foreignKeyDefinition();
foreignKeyOptions = inverseJoinColumnForeignKey.options();
} }
} }
@ -2445,6 +2453,7 @@ public abstract class CollectionBinder {
else { else {
element.setForeignKeyName( nullIfEmpty( foreignKeyName ) ); element.setForeignKeyName( nullIfEmpty( foreignKeyName ) );
element.setForeignKeyDefinition( nullIfEmpty( foreignKeyDefinition ) ); element.setForeignKeyDefinition( nullIfEmpty( foreignKeyDefinition ) );
element.setForeignKeyOptions( foreignKeyOptions );
} }
} }
return element; return element;

View File

@ -54,7 +54,6 @@ import org.hibernate.annotations.Synchronize;
import org.hibernate.annotations.TypeBinderType; import org.hibernate.annotations.TypeBinderType;
import org.hibernate.annotations.View; import org.hibernate.annotations.View;
import org.hibernate.binder.TypeBinder; import org.hibernate.binder.TypeBinder;
import org.hibernate.boot.model.IdentifierGeneratorDefinition;
import org.hibernate.boot.model.NamedEntityGraphDefinition; import org.hibernate.boot.model.NamedEntityGraphDefinition;
import org.hibernate.boot.model.internal.InheritanceState.ElementsToProcess; import org.hibernate.boot.model.internal.InheritanceState.ElementsToProcess;
import org.hibernate.boot.model.naming.EntityNaming; import org.hibernate.boot.model.naming.EntityNaming;
@ -896,6 +895,7 @@ public class EntityBinder {
else if ( foreignKey != null ) { else if ( foreignKey != null ) {
key.setForeignKeyName( nullIfEmpty( foreignKey.name() ) ); key.setForeignKeyName( nullIfEmpty( foreignKey.name() ) );
key.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) ); key.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) );
key.setForeignKeyOptions( foreignKey.options() );
} }
else if ( noConstraintByDefault ) { else if ( noConstraintByDefault ) {
key.disableForeignKey(); key.disableForeignKey();
@ -904,11 +904,13 @@ public class EntityBinder {
final ForeignKey nestedFk = pkJoinColumns.foreignKey(); final ForeignKey nestedFk = pkJoinColumns.foreignKey();
key.setForeignKeyName( nullIfEmpty( nestedFk.name() ) ); key.setForeignKeyName( nullIfEmpty( nestedFk.name() ) );
key.setForeignKeyDefinition( nullIfEmpty( nestedFk.foreignKeyDefinition() ) ); key.setForeignKeyDefinition( nullIfEmpty( nestedFk.foreignKeyDefinition() ) );
key.setForeignKeyOptions( nestedFk.options() );
} }
else if ( pkJoinColumn != null ) { else if ( pkJoinColumn != null ) {
final ForeignKey nestedFk = pkJoinColumn.foreignKey(); final ForeignKey nestedFk = pkJoinColumn.foreignKey();
key.setForeignKeyName( nullIfEmpty( nestedFk.name() ) ); key.setForeignKeyName( nullIfEmpty( nestedFk.name() ) );
key.setForeignKeyDefinition( nullIfEmpty( nestedFk.foreignKeyDefinition() ) ); key.setForeignKeyDefinition( nullIfEmpty( nestedFk.foreignKeyDefinition() ) );
key.setForeignKeyOptions( nestedFk.options() );
} }
} }
} }
@ -1987,6 +1989,7 @@ public class EntityBinder {
else { else {
key.setForeignKeyName( nullIfEmpty( jpaSecondaryTable.foreignKey().name() ) ); key.setForeignKeyName( nullIfEmpty( jpaSecondaryTable.foreignKey().name() ) );
key.setForeignKeyDefinition( nullIfEmpty( jpaSecondaryTable.foreignKey().foreignKeyDefinition() ) ); key.setForeignKeyDefinition( nullIfEmpty( jpaSecondaryTable.foreignKey().foreignKeyDefinition() ) );
key.setForeignKeyOptions( jpaSecondaryTable.foreignKey().options() );
} }
} }
} }

View File

@ -160,6 +160,7 @@ class IndexBinder {
String[] columnNames, String[] columnNames,
String[] orderings, String[] orderings,
boolean unique, boolean unique,
String options,
Selectable[] columns) { Selectable[] columns) {
final IndexOrUniqueKeyNameSource source = final IndexOrUniqueKeyNameSource source =
new IndexOrUniqueKeyNameSource( context, table, columnNames, originalKeyName ); new IndexOrUniqueKeyNameSource( context, table, columnNames, originalKeyName );
@ -174,6 +175,7 @@ class IndexBinder {
final UniqueKey uniqueKey = table.getOrCreateUniqueKey( keyName ); final UniqueKey uniqueKey = table.getOrCreateUniqueKey( keyName );
uniqueKey.setExplicit( true ); uniqueKey.setExplicit( true );
uniqueKey.setNameExplicit( nameExplicit ); uniqueKey.setNameExplicit( nameExplicit );
uniqueKey.setOptions( options );
for ( int i = 0; i < columns.length; i++ ) { for ( int i = 0; i < columns.length; i++ ) {
uniqueKey.addColumn( (Column) columns[i], orderings != null ? orderings[i] : null ); uniqueKey.addColumn( (Column) columns[i], orderings != null ? orderings[i] : null );
} }
@ -182,6 +184,7 @@ class IndexBinder {
final String keyName = getImplicitNamingStrategy().determineIndexName( source ).render( getDialect() ); final String keyName = getImplicitNamingStrategy().determineIndexName( source ).render( getDialect() );
final Index index = table.getOrCreateIndex( keyName ); final Index index = table.getOrCreateIndex( keyName );
index.setUnique( unique ); index.setUnique( unique );
index.setOptions( options );
for ( int i = 0; i < columns.length; i++ ) { for ( int i = 0; i < columns.length; i++ ) {
index.addColumn( columns[i], orderings != null ? orderings[i] : null ); index.addColumn( columns[i], orderings != null ? orderings[i] : null );
} }
@ -203,6 +206,7 @@ class IndexBinder {
initializeColumns( columnExpressions, ordering, parsed ); initializeColumns( columnExpressions, ordering, parsed );
final String name = index.name(); final String name = index.name();
final boolean unique = index.unique(); final boolean unique = index.unique();
final String options = index.options();
createIndexOrUniqueKey( createIndexOrUniqueKey(
table, table,
name, name,
@ -210,6 +214,7 @@ class IndexBinder {
columnExpressions, columnExpressions,
ordering, ordering,
unique, unique,
options,
selectables( table, name, columnExpressions ) selectables( table, name, columnExpressions )
); );
} }
@ -219,6 +224,7 @@ class IndexBinder {
for ( UniqueConstraint constraint : constraints ) { for ( UniqueConstraint constraint : constraints ) {
final String name = constraint.name(); final String name = constraint.name();
final String[] columnNames = constraint.columnNames(); final String[] columnNames = constraint.columnNames();
final String options = constraint.options();
createIndexOrUniqueKey( createIndexOrUniqueKey(
table, table,
name, name,
@ -226,6 +232,7 @@ class IndexBinder {
columnNames, columnNames,
null, null,
true, true,
options,
columns( table, name, columnNames ) columns( table, name, columnNames )
); );
} }

View File

@ -319,6 +319,7 @@ public class MapBinder extends CollectionBinder {
else { else {
element.setForeignKeyName( nullIfEmpty( foreignKey.name() ) ); element.setForeignKeyName( nullIfEmpty( foreignKey.name() ) );
element.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) ); element.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) );
element.setForeignKeyOptions( foreignKey.options() );
} }
} }
} }
@ -495,8 +496,7 @@ public class MapBinder extends CollectionBinder {
private SimpleValue createTargetValue(Table mapKeyTable, SimpleValue sourceValue) { private SimpleValue createTargetValue(Table mapKeyTable, SimpleValue sourceValue) {
final SimpleValue targetValue; final SimpleValue targetValue;
if ( sourceValue instanceof ManyToOne ) { if ( sourceValue instanceof ManyToOne sourceManyToOne ) {
final ManyToOne sourceManyToOne = (ManyToOne) sourceValue;
final ManyToOne targetManyToOne = new ManyToOne( getBuildingContext(), mapKeyTable); final ManyToOne targetManyToOne = new ManyToOne( getBuildingContext(), mapKeyTable);
targetManyToOne.setFetchMode( FetchMode.DEFAULT ); targetManyToOne.setFetchMode( FetchMode.DEFAULT );
targetManyToOne.setLazy( true ); targetManyToOne.setLazy( true );

View File

@ -609,6 +609,7 @@ public class ToOneBinder {
else if ( foreignKey != null ) { else if ( foreignKey != null ) {
value.setForeignKeyName( nullIfEmpty( foreignKey.name() ) ); value.setForeignKeyName( nullIfEmpty( foreignKey.name() ) );
value.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) ); value.setForeignKeyDefinition( nullIfEmpty( foreignKey.foreignKeyDefinition() ) );
value.setForeignKeyOptions( foreignKey.options() );
} }
else if ( noConstraintByDefault ) { else if ( noConstraintByDefault ) {
value.disableForeignKey(); value.disableForeignKey();
@ -617,11 +618,13 @@ public class ToOneBinder {
final ForeignKey joinColumnsForeignKey = joinColumns.foreignKey(); final ForeignKey joinColumnsForeignKey = joinColumns.foreignKey();
value.setForeignKeyName( nullIfEmpty( joinColumnsForeignKey.name() ) ); value.setForeignKeyName( nullIfEmpty( joinColumnsForeignKey.name() ) );
value.setForeignKeyDefinition( nullIfEmpty( joinColumnsForeignKey.foreignKeyDefinition() ) ); value.setForeignKeyDefinition( nullIfEmpty( joinColumnsForeignKey.foreignKeyDefinition() ) );
value.setForeignKeyOptions( joinColumnsForeignKey.options() );
} }
else if ( joinColumn != null ) { else if ( joinColumn != null ) {
final ForeignKey joinColumnForeignKey = joinColumn.foreignKey(); final ForeignKey joinColumnForeignKey = joinColumn.foreignKey();
value.setForeignKeyName( nullIfEmpty( joinColumnForeignKey.name() ) ); value.setForeignKeyName( nullIfEmpty( joinColumnForeignKey.name() ) );
value.setForeignKeyDefinition( nullIfEmpty( joinColumnForeignKey.foreignKeyDefinition() ) ); value.setForeignKeyDefinition( nullIfEmpty( joinColumnForeignKey.foreignKeyDefinition() ) );
value.setForeignKeyOptions( joinColumnForeignKey.options() );
} }
} }
} }

View File

@ -112,10 +112,10 @@ import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.loader.ast.spi.MultiKeyLoadSizingStrategy; import org.hibernate.loader.ast.spi.MultiKeyLoadSizingStrategy;
import org.hibernate.mapping.CheckConstraint; import org.hibernate.mapping.CheckConstraint;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
import org.hibernate.mapping.Constraint;
import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.Index; import org.hibernate.mapping.Index;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.mapping.UserDefinedType; import org.hibernate.mapping.UserDefinedType;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
@ -3274,7 +3274,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
} }
/** /**
* Get an {@link Exporter} for {@link UserDefinedType}s, * Get an {@link Exporter} for {@link UserDefinedType user defined types},
* usually {@link StandardUserDefinedTypeExporter}. * usually {@link StandardUserDefinedTypeExporter}.
*/ */
public Exporter<UserDefinedType> getUserDefinedTypeExporter() { public Exporter<UserDefinedType> getUserDefinedTypeExporter() {
@ -3282,7 +3282,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
} }
/** /**
* Get an {@link Exporter} for {@link Sequence}s, * Get an {@link Exporter} for {@linkplain Sequence sequences},
* usually {@link StandardSequenceExporter}. * usually {@link StandardSequenceExporter}.
*/ */
public Exporter<Sequence> getSequenceExporter() { public Exporter<Sequence> getSequenceExporter() {
@ -3290,7 +3290,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
} }
/** /**
* Get an {@link Exporter} for {@link Index}es, * Get an {@link Exporter} for {@linkplain Index indexes},
* usually {@link StandardIndexExporter}. * usually {@link StandardIndexExporter}.
*/ */
public Exporter<Index> getIndexExporter() { public Exporter<Index> getIndexExporter() {
@ -3298,7 +3298,7 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
} }
/** /**
* Get an {@link Exporter} for {@link ForeignKey}s, * Get an {@link Exporter} for {@linkplain ForeignKey foreign key} constraints,
* usually {@link StandardForeignKeyExporter}. * usually {@link StandardForeignKeyExporter}.
*/ */
public Exporter<ForeignKey> getForeignKeyExporter() { public Exporter<ForeignKey> getForeignKeyExporter() {
@ -3306,10 +3306,10 @@ public abstract class Dialect implements ConversionContext, TypeContributor, Fun
} }
/** /**
* Get an {@link Exporter} for unique key {@link Constraint}s, * Get an {@link Exporter} for {@linkplain UniqueKey unique key} constraints,
* usually {@link StandardUniqueKeyExporter}. * usually {@link StandardUniqueKeyExporter}.
*/ */
public Exporter<Constraint> getUniqueKeyExporter() { public Exporter<UniqueKey> getUniqueKeyExporter() {
return uniqueKeyExporter; return uniqueKeyExporter;
} }

View File

@ -49,10 +49,10 @@ import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
import org.hibernate.exception.spi.ViolatedConstraintNameExtractor; import org.hibernate.exception.spi.ViolatedConstraintNameExtractor;
import org.hibernate.loader.ast.spi.MultiKeyLoadSizingStrategy; import org.hibernate.loader.ast.spi.MultiKeyLoadSizingStrategy;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
import org.hibernate.mapping.Constraint;
import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.Index; import org.hibernate.mapping.Index;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey;
import org.hibernate.mapping.UserDefinedType; import org.hibernate.mapping.UserDefinedType;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.spi.RuntimeModelCreationContext; import org.hibernate.metamodel.spi.RuntimeModelCreationContext;
@ -866,7 +866,7 @@ public class DialectDelegateWrapper extends Dialect {
} }
@Override @Override
public Exporter<Constraint> getUniqueKeyExporter() { public Exporter<UniqueKey> getUniqueKeyExporter() {
return wrapped.getUniqueKeyExporter(); return wrapped.getUniqueKeyExporter();
} }

View File

@ -30,7 +30,6 @@ import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.util.collections.ArrayHelper; import org.hibernate.internal.util.collections.ArrayHelper;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
import org.hibernate.mapping.Constraint;
import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey; import org.hibernate.mapping.UniqueKey;
@ -802,7 +801,7 @@ public class SpannerDialect extends Dialect {
} }
@Override @Override
public Exporter<Constraint> getUniqueKeyExporter() { public Exporter<UniqueKey> getUniqueKeyExporter() {
return NOOP_EXPORTER; return NOOP_EXPORTER;
} }

View File

@ -13,6 +13,8 @@ import org.hibernate.mapping.Column;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
import org.hibernate.mapping.UniqueKey; import org.hibernate.mapping.UniqueKey;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
/** /**
* A {@link UniqueDelegate} which uses {@code alter table} commands to create and drop * A {@link UniqueDelegate} which uses {@code alter table} commands to create and drop
* the unique constraint. When possible, prefer {@link CreateTableUniqueDelegate}. * the unique constraint. When possible, prefer {@link CreateTableUniqueDelegate}.
@ -68,7 +70,11 @@ public class AlterTableUniqueDelegate implements UniqueDelegate {
fragment.append( " " ).append( uniqueKey.getColumnOrderMap().get( column ) ); fragment.append( " " ).append( uniqueKey.getColumnOrderMap().get( column ) );
} }
} }
return fragment.append( ')' ).toString(); fragment.append( ')' );
if ( isNotEmpty( uniqueKey.getOptions() ) ) {
fragment.append( " " ).append( uniqueKey.getOptions() );
}
return fragment.toString();
} }
@Override @Override

View File

@ -76,7 +76,7 @@ public class CreateTableUniqueDelegate extends AlterTableUniqueDelegate {
if ( uniqueKey.isNameExplicit() ) { if ( uniqueKey.isNameExplicit() ) {
fragment.append( "constraint " ).append( uniqueKey.getName() ).append( " " ); fragment.append( "constraint " ).append( uniqueKey.getName() ).append( " " );
} }
fragment.append( uniqueConstraintSql(uniqueKey) ); fragment.append( uniqueConstraintSql( uniqueKey ) );
} }
private static boolean isSingleColumnUnique(Table table, UniqueKey uniqueKey) { private static boolean isSingleColumnUnique(Table table, UniqueKey uniqueKey) {

View File

@ -351,8 +351,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
} }
private static Type getUnderlyingType(Mapping mapping, Type type, int typeIndex) { private static Type getUnderlyingType(Mapping mapping, Type type, int typeIndex) {
if ( type instanceof ComponentType ) { if ( type instanceof ComponentType componentType ) {
final ComponentType componentType = (ComponentType) type;
int cols = 0; int cols = 0;
for ( Type subtype : componentType.getSubtypes() ) { for ( Type subtype : componentType.getSubtypes() ) {
int columnSpan = subtype.getColumnSpan( mapping ); int columnSpan = subtype.getColumnSpan( mapping );
@ -363,8 +362,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
} }
throw new IndexOutOfBoundsException(); throw new IndexOutOfBoundsException();
} }
else if ( type instanceof EntityType ) { else if ( type instanceof EntityType entityType ) {
final EntityType entityType = (EntityType) type;
final Type idType = entityType.getIdentifierOrUniqueKeyType( mapping ); final Type idType = entityType.getIdentifierOrUniqueKeyType( mapping );
return getUnderlyingType( mapping, idType, typeIndex ); return getUnderlyingType( mapping, idType, typeIndex );
} }
@ -454,8 +452,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
if ( type instanceof ComponentType ) { if ( type instanceof ComponentType ) {
type = getTypeForComponentValue( mapping, type, getTypeIndex() ); type = getTypeForComponentValue( mapping, type, getTypeIndex() );
} }
if ( type instanceof BasicType ) { if ( type instanceof BasicType<?> basicType ) {
final BasicType<?> basicType = (BasicType<?>) type;
if ( isTemporal( basicType.getExpressibleJavaType() ) ) { if ( isTemporal( basicType.getExpressibleJavaType() ) ) {
precisionToUse = getTemporalPrecision(); precisionToUse = getTemporalPrecision();
lengthToUse = null; lengthToUse = null;
@ -510,12 +507,11 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
private Type getTypeForEntityValue(Mapping mapping, Type type, int typeIndex) { private Type getTypeForEntityValue(Mapping mapping, Type type, int typeIndex) {
int index = 0; int index = 0;
if ( type instanceof EntityType ) { if ( type instanceof EntityType entityType ) {
final EntityType entityType = (EntityType) type;
return getTypeForEntityValue( mapping, entityType.getIdentifierOrUniqueKeyType( mapping ), typeIndex ); return getTypeForEntityValue( mapping, entityType.getIdentifierOrUniqueKeyType( mapping ), typeIndex );
} }
else if ( type instanceof ComponentType ) { else if ( type instanceof ComponentType componentType ) {
for ( Type subtype : ((ComponentType) type).getSubtypes() ) { for ( Type subtype : componentType.getSubtypes() ) {
final Type result = getTypeForEntityValue( mapping, subtype, typeIndex - index ); final Type result = getTypeForEntityValue( mapping, subtype, typeIndex - index );
if ( result != null ) { if ( result != null ) {
return result; return result;
@ -672,7 +668,7 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
@Override @Override
public String getWriteExpr() { public String getWriteExpr() {
return customWrite != null && customWrite.length() > 0 ? customWrite : "?"; return customWrite != null && !customWrite.isEmpty() ? customWrite : "?";
} }
@Override @Override

View File

@ -24,6 +24,7 @@ public abstract class Constraint implements Exportable, Serializable {
private String name; private String name;
private final ArrayList<Column> columns = new ArrayList<>(); private final ArrayList<Column> columns = new ArrayList<>();
private Table table; private Table table;
private String options = "";
public String getName() { public String getName() {
return name; return name;
@ -33,6 +34,14 @@ public abstract class Constraint implements Exportable, Serializable {
this.name = name; this.name = name;
} }
public String getOptions() {
return options;
}
public void setOptions(String options) {
this.options = options;
}
public void addColumn(Column column) { public void addColumn(Column column) {
if ( !columns.contains( column ) ) { if ( !columns.contains( column ) ) {
columns.add( column ); columns.add( column );

View File

@ -79,6 +79,7 @@ public class DenormalizedTable extends Table {
foreignKey.getColumns(), foreignKey.getColumns(),
foreignKey.getReferencedEntityName(), foreignKey.getReferencedEntityName(),
foreignKey.getKeyDefinition(), foreignKey.getKeyDefinition(),
foreignKey.getOptions(),
foreignKey.getReferencedColumns() foreignKey.getReferencedColumns()
); );
} }
@ -88,6 +89,7 @@ public class DenormalizedTable extends Table {
final ForeignKey denormalizedForeignKey = new ForeignKey(this); final ForeignKey denormalizedForeignKey = new ForeignKey(this);
denormalizedForeignKey.setReferencedEntityName( includedTableFk.getReferencedEntityName() ); denormalizedForeignKey.setReferencedEntityName( includedTableFk.getReferencedEntityName() );
denormalizedForeignKey.setKeyDefinition( includedTableFk.getKeyDefinition() ); denormalizedForeignKey.setKeyDefinition( includedTableFk.getKeyDefinition() );
denormalizedForeignKey.setOptions( includedTableFk.getOptions() );
denormalizedForeignKey.setReferencedTable( includedTableFk.getReferencedTable() ); denormalizedForeignKey.setReferencedTable( includedTableFk.getReferencedTable() );
denormalizedForeignKey.addReferencedColumns( includedTableFk.getReferencedColumns() ); denormalizedForeignKey.addReferencedColumns( includedTableFk.getReferencedColumns() );
for ( Column keyColumn : includedTableFk.getColumns() ) { for ( Column keyColumn : includedTableFk.getColumns() ) {

View File

@ -18,7 +18,6 @@ import org.hibernate.dialect.Dialect;
import static java.util.Collections.unmodifiableList; import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableMap;
import static java.util.stream.Collectors.toUnmodifiableList;
import static java.util.stream.Collectors.toUnmodifiableMap; import static java.util.stream.Collectors.toUnmodifiableMap;
import static org.hibernate.internal.util.StringHelper.isNotEmpty; import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.internal.util.StringHelper.qualify; import static org.hibernate.internal.util.StringHelper.qualify;
@ -35,6 +34,7 @@ public class Index implements Exportable, Serializable {
private Identifier name; private Identifier name;
private Table table; private Table table;
private boolean unique; private boolean unique;
private String options = "";
private final java.util.List<Selectable> selectables = new ArrayList<>(); private final java.util.List<Selectable> selectables = new ArrayList<>();
private final java.util.Map<Selectable, String> selectableOrderMap = new HashMap<>(); private final java.util.Map<Selectable, String> selectableOrderMap = new HashMap<>();
@ -54,6 +54,14 @@ public class Index implements Exportable, Serializable {
return unique; return unique;
} }
public String getOptions() {
return options;
}
public void setOptions(String options) {
this.options = options;
}
public int getColumnSpan() { public int getColumnSpan() {
return selectables.size(); return selectables.size();
} }
@ -71,8 +79,7 @@ public class Index implements Exportable, Serializable {
*/ */
@Deprecated(since = "6.3") @Deprecated(since = "6.3")
public java.util.List<Column> getColumns() { public java.util.List<Column> getColumns() {
return selectables.stream() return selectables.stream().map( s -> (Column) s ).toList();
.map( s -> (Column) s ).collect( toUnmodifiableList() );
} }
/** /**

View File

@ -24,7 +24,7 @@ public class ManyToOne extends ToOne {
private boolean isLogicalOneToOne; private boolean isLogicalOneToOne;
private NotFoundAction notFoundAction; private NotFoundAction notFoundAction;
private Type resolvedType; private transient Type resolvedType;
public ManyToOne(MetadataBuildingContext buildingContext, Table table) { public ManyToOne(MetadataBuildingContext buildingContext, Table table) {
super( buildingContext, table ); super( buildingContext, table );
@ -95,8 +95,8 @@ public class ManyToOne extends ToOne {
} }
else { else {
// Make sure synthetic properties are sorted // Make sure synthetic properties are sorted
if ( property.getValue() instanceof Component ) { if ( property.getValue() instanceof Component component ) {
( (Component) property.getValue() ).sortProperties(); component.sortProperties();
} }
// todo : if "none" another option is to create the ForeignKey object still but to set its #disableCreation flag // todo : if "none" another option is to create the ForeignKey object still but to set its #disableCreation flag
if ( isForeignKeyEnabled() && !hasFormula() ) { if ( isForeignKeyEnabled() && !hasFormula() ) {
@ -105,6 +105,7 @@ public class ManyToOne extends ToOne {
getConstraintColumns(), getConstraintColumns(),
( (EntityType) getType() ).getAssociatedEntityName(), ( (EntityType) getType() ).getAssociatedEntityName(),
getForeignKeyDefinition(), getForeignKeyDefinition(),
getForeignKeyOptions(),
new ArrayList<>( property.getColumns() ) new ArrayList<>( property.getColumns() )
); );
foreignKey.setReferencedTable( property.getValue().getTable() ); foreignKey.setReferencedTable( property.getValue().getTable() );

View File

@ -96,6 +96,7 @@ public abstract class SimpleValue implements KeyValue {
private Table table; private Table table;
private String foreignKeyName; private String foreignKeyName;
private String foreignKeyDefinition; private String foreignKeyDefinition;
private String foreignKeyOptions;
private boolean alternateUniqueKey; private boolean alternateUniqueKey;
private OnDeleteAction onDeleteAction; private OnDeleteAction onDeleteAction;
private boolean foreignKeyEnabled = true; private boolean foreignKeyEnabled = true;
@ -347,7 +348,8 @@ public abstract class SimpleValue implements KeyValue {
getForeignKeyName(), getForeignKeyName(),
getConstraintColumns(), getConstraintColumns(),
entityName, entityName,
getForeignKeyDefinition() getForeignKeyDefinition(),
getForeignKeyOptions()
); );
foreignKey.setOnDeleteAction( onDeleteAction ); foreignKey.setOnDeleteAction( onDeleteAction );
return foreignKey; return foreignKey;
@ -443,6 +445,14 @@ public abstract class SimpleValue implements KeyValue {
return isForeignKeyEnabled() && !hasFormula(); return isForeignKeyEnabled() && !hasFormula();
} }
public String getForeignKeyOptions() {
return foreignKeyOptions;
}
public void setForeignKeyOptions(String foreignKeyOptions) {
this.foreignKeyOptions = foreignKeyOptions;
}
public String getForeignKeyDefinition() { public String getForeignKeyDefinition() {
return foreignKeyDefinition; return foreignKeyDefinition;
} }

View File

@ -576,8 +576,13 @@ public class Table implements Serializable, ContributableDatabaseObject {
public void createForeignKeys(MetadataBuildingContext context) { public void createForeignKeys(MetadataBuildingContext context) {
} }
@Deprecated(since="7.0", forRemoval = true)
public ForeignKey createForeignKey(String keyName, List<Column> keyColumns, String referencedEntityName, String keyDefinition) { public ForeignKey createForeignKey(String keyName, List<Column> keyColumns, String referencedEntityName, String keyDefinition) {
return createForeignKey( keyName, keyColumns, referencedEntityName, keyDefinition, null ); return createForeignKey( keyName, keyColumns, referencedEntityName, keyDefinition, null, null );
}
public ForeignKey createForeignKey(String keyName, List<Column> keyColumns, String referencedEntityName, String keyDefinition, String options) {
return createForeignKey( keyName, keyColumns, referencedEntityName, keyDefinition, options, null );
} }
public ForeignKey createForeignKey( public ForeignKey createForeignKey(
@ -585,6 +590,7 @@ public class Table implements Serializable, ContributableDatabaseObject {
List<Column> keyColumns, List<Column> keyColumns,
String referencedEntityName, String referencedEntityName,
String keyDefinition, String keyDefinition,
String options,
List<Column> referencedColumns) { List<Column> referencedColumns) {
final ForeignKeyKey key = new ForeignKeyKey( keyColumns, referencedEntityName, referencedColumns ); final ForeignKeyKey key = new ForeignKeyKey( keyColumns, referencedEntityName, referencedColumns );
@ -593,6 +599,7 @@ public class Table implements Serializable, ContributableDatabaseObject {
foreignKey = new ForeignKey( this ); foreignKey = new ForeignKey( this );
foreignKey.setReferencedEntityName( referencedEntityName ); foreignKey.setReferencedEntityName( referencedEntityName );
foreignKey.setKeyDefinition( keyDefinition ); foreignKey.setKeyDefinition( keyDefinition );
foreignKey.setOptions( options );
for ( Column keyColumn : keyColumns ) { for ( Column keyColumn : keyColumns ) {
foreignKey.addColumn( keyColumn ); foreignKey.addColumn( keyColumn );
} }
@ -773,12 +780,11 @@ public class Table implements Serializable, ContributableDatabaseObject {
} }
public boolean equals(Object other) { public boolean equals(Object other) {
if ( !( other instanceof ForeignKeyKey ) ) { if ( !(other instanceof ForeignKeyKey foreignKeyKey) ) {
return false; return false;
} }
ForeignKeyKey fkk = (ForeignKeyKey) other; return Arrays.equals( foreignKeyKey.columns, columns )
return Arrays.equals( fkk.columns, columns ) && Arrays.equals( foreignKeyKey.referencedColumns, referencedColumns );
&& Arrays.equals( fkk.referencedColumns, referencedColumns );
} }
@Override @Override

View File

@ -175,8 +175,7 @@ public abstract class ToOne extends SimpleValue implements Fetchable, SortableVa
final Value value = referencedPropertyName == null final Value value = referencedPropertyName == null
? entityBinding.getIdentifier() ? entityBinding.getIdentifier()
: entityBinding.getRecursiveProperty( referencedPropertyName ).getValue(); : entityBinding.getRecursiveProperty( referencedPropertyName ).getValue();
if ( value instanceof Component ) { if ( value instanceof Component component ) {
final Component component = (Component) value;
final int[] originalPropertyOrder = component.sortProperties(); final int[] originalPropertyOrder = component.sortProperties();
if ( !sorted ) { if ( !sorted ) {
if ( originalPropertyOrder != null ) { if ( originalPropertyOrder != null ) {
@ -201,15 +200,15 @@ public abstract class ToOne extends SimpleValue implements Fetchable, SortableVa
if ( isConstrained() ) { if ( isConstrained() ) {
final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0); final AnnotatedJoinColumn firstColumn = joinColumns.getJoinColumns().get(0);
final Object owner = findReferencedColumnOwner( referencedEntity, firstColumn, getBuildingContext() ); final Object owner = findReferencedColumnOwner( referencedEntity, firstColumn, getBuildingContext() );
if ( owner instanceof Join ) { if ( owner instanceof Join join ) {
// Here we handle the case of a foreign key that refers to the // Here we handle the case of a foreign key that refers to the
// primary key of a secondary table of the referenced entity // primary key of a secondary table of the referenced entity
final Join join = (Join) owner;
final ForeignKey foreignKey = getTable().createForeignKey( final ForeignKey foreignKey = getTable().createForeignKey(
getForeignKeyName(), getForeignKeyName(),
getConstraintColumns(), getConstraintColumns(),
referencedEntity.getEntityName(), referencedEntity.getEntityName(),
getForeignKeyDefinition(), getForeignKeyDefinition(),
getForeignKeyOptions(),
join.getKey().getColumns() join.getKey().getColumns()
); );
foreignKey.setOnDeleteAction( getOnDeleteAction() ); foreignKey.setOnDeleteAction( getOnDeleteAction() );

View File

@ -28,7 +28,6 @@ import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.internal.Formatter; import org.hibernate.engine.jdbc.internal.Formatter;
import org.hibernate.internal.util.StringHelper; import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.collections.CollectionHelper; import org.hibernate.internal.util.collections.CollectionHelper;
import org.hibernate.mapping.Constraint;
import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.ForeignKey;
import org.hibernate.mapping.Index; import org.hibernate.mapping.Index;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
@ -388,7 +387,7 @@ public abstract class AbstractSchemaMigrator implements SchemaMigrator {
} }
if ( uniqueConstraintStrategy != SKIP ) { if ( uniqueConstraintStrategy != SKIP ) {
final Exporter<Constraint> exporter = dialect.getUniqueKeyExporter(); final Exporter<UniqueKey> exporter = dialect.getUniqueKeyExporter();
for ( UniqueKey uniqueKey : table.getUniqueKeys().values() ) { for ( UniqueKey uniqueKey : table.getUniqueKeys().values() ) {
// Skip if index already exists. Most of the time, this // Skip if index already exists. Most of the time, this
// won't work since most Dialects use Constraints. However, // won't work since most Dialects use Constraints. However,

View File

@ -11,7 +11,6 @@ import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.Size; import org.hibernate.engine.jdbc.Size;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.mapping.CheckConstraint; import org.hibernate.mapping.CheckConstraint;
import org.hibernate.mapping.Column; import org.hibernate.mapping.Column;
import org.hibernate.mapping.Table; import org.hibernate.mapping.Table;
@ -27,6 +26,7 @@ import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.type.SqlTypes.isNumericOrDecimal; import static org.hibernate.type.SqlTypes.isNumericOrDecimal;
import static org.hibernate.type.SqlTypes.isStringType; import static org.hibernate.type.SqlTypes.isStringType;
@ -122,7 +122,7 @@ class ColumnDefinitions {
private static void appendOptions(StringBuilder statement, Column column, Dialect dialect) { private static void appendOptions(StringBuilder statement, Column column, Dialect dialect) {
final String options = column.getOptions(); final String options = column.getOptions();
if ( StringHelper.isNotEmpty( options ) ) { if ( isNotEmpty( options ) ) {
statement.append( " " ).append( options ); statement.append( " " ).append( options );
} }
} }

View File

@ -96,13 +96,14 @@ public class SchemaCreatorImpl implements SchemaCreator {
} }
public SchemaCreatorImpl(ServiceRegistry serviceRegistry, SchemaFilter schemaFilter) { public SchemaCreatorImpl(ServiceRegistry serviceRegistry, SchemaFilter schemaFilter) {
SchemaManagementTool smt = serviceRegistry.getService( SchemaManagementTool.class ); if ( serviceRegistry.getService( SchemaManagementTool.class )
if ( !(smt instanceof HibernateSchemaManagementTool) ) { instanceof HibernateSchemaManagementTool schemaManagementTool ) {
smt = new HibernateSchemaManagementTool(); tool = schemaManagementTool;
( (HibernateSchemaManagementTool) smt ).injectServices( (ServiceRegistryImplementor) serviceRegistry ); }
else {
tool = new HibernateSchemaManagementTool();
tool.injectServices( (ServiceRegistryImplementor) serviceRegistry );
} }
this.tool = (HibernateSchemaManagementTool) smt;
this.schemaFilter = schemaFilter; this.schemaFilter = schemaFilter;
} }

View File

@ -93,13 +93,14 @@ public class SchemaDropperImpl implements SchemaDropper {
} }
public SchemaDropperImpl(ServiceRegistry serviceRegistry, SchemaFilter schemaFilter) { public SchemaDropperImpl(ServiceRegistry serviceRegistry, SchemaFilter schemaFilter) {
SchemaManagementTool smt = serviceRegistry.getService( SchemaManagementTool.class ); if ( serviceRegistry.getService( SchemaManagementTool.class )
if ( !(smt instanceof HibernateSchemaManagementTool) ) { instanceof HibernateSchemaManagementTool schemaManagementTool ) {
smt = new HibernateSchemaManagementTool(); tool = schemaManagementTool;
( (HibernateSchemaManagementTool) smt ).injectServices( (ServiceRegistryImplementor) serviceRegistry ); }
else {
tool = new HibernateSchemaManagementTool();
tool.injectServices( (ServiceRegistryImplementor) serviceRegistry );
} }
this.tool = (HibernateSchemaManagementTool) smt;
this.schemaFilter = schemaFilter; this.schemaFilter = schemaFilter;
} }
@ -401,7 +402,8 @@ public class SchemaDropperImpl implements SchemaDropper {
GenerationTarget[] targets) { GenerationTarget[] targets) {
for ( Namespace namespace : metadata.getDatabase().getNamespaces() ) { for ( Namespace namespace : metadata.getDatabase().getNamespaces() ) {
if ( schemaFilter.includeNamespace( namespace ) ) { if ( schemaFilter.includeNamespace( namespace ) ) {
final List<UserDefinedType> dependencyOrderedUserDefinedTypes = namespace.getDependencyOrderedUserDefinedTypes(); final List<UserDefinedType> dependencyOrderedUserDefinedTypes =
namespace.getDependencyOrderedUserDefinedTypes();
Collections.reverse( dependencyOrderedUserDefinedTypes ); Collections.reverse( dependencyOrderedUserDefinedTypes );
for ( UserDefinedType userDefinedType : dependencyOrderedUserDefinedTypes ) { for ( UserDefinedType userDefinedType : dependencyOrderedUserDefinedTypes ) {
applySqlStrings( applySqlStrings(

View File

@ -39,6 +39,7 @@ import org.jboss.logging.Logger;
import java.net.URL; import java.net.URL;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
import static org.hibernate.cfg.AvailableSettings.HBM2DDL_CHARSET_NAME; import static org.hibernate.cfg.AvailableSettings.HBM2DDL_CHARSET_NAME;
@ -73,9 +74,11 @@ public class SchemaTruncatorImpl implements SchemaTruncator {
ContributableMatcher contributableInclusionFilter, ContributableMatcher contributableInclusionFilter,
TargetDescriptor targetDescriptor) { TargetDescriptor targetDescriptor) {
final JdbcContext jdbcContext = tool.resolveJdbcContext( options.getConfigurationValues() ); final Map<String, Object> configurationValues = options.getConfigurationValues();
final GenerationTarget[] targets = tool.buildGenerationTargets( targetDescriptor, jdbcContext, options.getConfigurationValues(), final JdbcContext jdbcContext = tool.resolveJdbcContext(configurationValues);
true ); //we need autocommit on for DB2 at least final GenerationTarget[] targets =
tool.buildGenerationTargets( targetDescriptor, jdbcContext, configurationValues,
true ); //we need autocommit on for DB2 at least
doTruncate( metadata, options, contributableInclusionFilter, jdbcContext.getDialect(), targets ); doTruncate( metadata, options, contributableInclusionFilter, jdbcContext.getDialect(), targets );
} }
@ -211,9 +214,7 @@ public class SchemaTruncatorImpl implements SchemaTruncator {
for ( ForeignKey foreignKey : table.getForeignKeys().values() ) { for ( ForeignKey foreignKey : table.getForeignKeys().values() ) {
if ( dialect.canDisableConstraints() ) { if ( dialect.canDisableConstraints() ) {
applySqlString( applySqlString(
dialect.getTableCleaner().getSqlDisableConstraintString( foreignKey, metadata, dialect.getTableCleaner().getSqlDisableConstraintString( foreignKey, metadata, context ),
context
),
formatter, formatter,
options, options,
targets targets
@ -221,9 +222,7 @@ public class SchemaTruncatorImpl implements SchemaTruncator {
} }
else if ( !dialect.canBatchTruncate() ) { else if ( !dialect.canBatchTruncate() ) {
applySqlStrings( applySqlStrings(
dialect.getForeignKeyExporter().getSqlDropStrings( foreignKey, metadata, dialect.getForeignKeyExporter().getSqlDropStrings( foreignKey, metadata, context ),
context
),
formatter, formatter,
options, options,
targets targets
@ -258,9 +257,7 @@ public class SchemaTruncatorImpl implements SchemaTruncator {
for ( ForeignKey foreignKey : table.getForeignKeys().values() ) { for ( ForeignKey foreignKey : table.getForeignKeys().values() ) {
if ( dialect.canDisableConstraints() ) { if ( dialect.canDisableConstraints() ) {
applySqlString( applySqlString(
dialect.getTableCleaner().getSqlEnableConstraintString( foreignKey, metadata, dialect.getTableCleaner().getSqlEnableConstraintString( foreignKey, metadata, context ),
context
),
formatter, formatter,
options, options,
targets targets
@ -268,9 +265,7 @@ public class SchemaTruncatorImpl implements SchemaTruncator {
} }
else if ( !dialect.canBatchTruncate() ) { else if ( !dialect.canBatchTruncate() ) {
applySqlStrings( applySqlStrings(
dialect.getForeignKeyExporter().getSqlCreateStrings( foreignKey, metadata, dialect.getForeignKeyExporter().getSqlCreateStrings( foreignKey, metadata, context ),
context
),
formatter, formatter,
options, options,
targets targets

View File

@ -18,6 +18,8 @@ import org.hibernate.mapping.Column;
import org.hibernate.mapping.ForeignKey; import org.hibernate.mapping.ForeignKey;
import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.tool.schema.spi.Exporter;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
/** /**
* An {@link Exporter} for {@linkplain ForeignKey foreign key constraints}. * An {@link Exporter} for {@linkplain ForeignKey foreign key constraints}.
* *
@ -78,12 +80,16 @@ public class StandardForeignKeyExporter implements Exporter<ForeignKey> {
); );
if ( dialect.supportsCascadeDelete() ) { if ( dialect.supportsCascadeDelete() ) {
OnDeleteAction onDeleteAction = foreignKey.getOnDeleteAction(); final OnDeleteAction onDeleteAction = foreignKey.getOnDeleteAction();
if ( onDeleteAction != null && onDeleteAction != OnDeleteAction.NO_ACTION ) { if ( onDeleteAction != null && onDeleteAction != OnDeleteAction.NO_ACTION ) {
buffer.append( " on delete " ).append( onDeleteAction.toSqlString() ); buffer.append( " on delete " ).append( onDeleteAction.toSqlString() );
} }
} }
if ( isNotEmpty( foreignKey.getOptions() ) ) {
buffer.append( " " ).append( foreignKey.getOptions() );
}
return new String[] { buffer.toString() }; return new String[] { buffer.toString() };
} }

View File

@ -17,6 +17,7 @@ import org.hibernate.mapping.Index;
import org.hibernate.mapping.Selectable; import org.hibernate.mapping.Selectable;
import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.tool.schema.spi.Exporter;
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.internal.util.StringHelper.qualify; import static org.hibernate.internal.util.StringHelper.qualify;
/** /**
@ -47,6 +48,9 @@ public class StandardIndexExporter implements Exporter<Index> {
.append( " (" ); .append( " (" );
appendColumnList( index, createIndex ); appendColumnList( index, createIndex );
createIndex.append( ")" ); createIndex.append( ")" );
if ( isNotEmpty( index.getOptions() ) ) {
createIndex.append( " " ).append( index.getOptions() );
}
return new String[] { createIndex.toString() }; return new String[] { createIndex.toString() };
} }

View File

@ -14,7 +14,7 @@ import org.hibernate.dialect.Dialect;
import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.tool.schema.spi.Exporter;
/** /**
* An {@link Exporter} for {@link Sequence sequences}. * An {@link Exporter} for {@linkplain Sequence sequences}.
* *
* @author Steve Ebersole * @author Steve Ebersole
*/ */

View File

@ -186,8 +186,7 @@ public class StandardTableExporter implements Exporter<Table> {
final AggregateSupport aggregateSupport = dialect.getAggregateSupport(); final AggregateSupport aggregateSupport = dialect.getAggregateSupport();
if ( aggregateSupport != null && aggregateSupport.supportsComponentCheckConstraints() ) { if ( aggregateSupport != null && aggregateSupport.supportsComponentCheckConstraints() ) {
for ( Column column : table.getColumns() ) { for ( Column column : table.getColumns() ) {
if ( column instanceof AggregateColumn ) { if ( column instanceof AggregateColumn aggregateColumn ) {
final AggregateColumn aggregateColumn = (AggregateColumn) column;
if ( !isArray( aggregateColumn ) ) { if ( !isArray( aggregateColumn ) ) {
applyAggregateColumnCheck( buf, aggregateColumn ); applyAggregateColumnCheck( buf, aggregateColumn );
} }
@ -241,8 +240,7 @@ public class StandardTableExporter implements Exporter<Table> {
String aggregatePath, String aggregatePath,
AggregateSupport aggregateSupport, AggregateSupport aggregateSupport,
Value value) { Value value) {
if ( value instanceof Component ) { if ( value instanceof Component component ) {
final Component component = (Component) value;
final AggregateColumn subAggregateColumn = component.getAggregateColumn(); final AggregateColumn subAggregateColumn = component.getAggregateColumn();
if ( subAggregateColumn != null && !isArray( subAggregateColumn ) ) { if ( subAggregateColumn != null && !isArray( subAggregateColumn ) ) {
final String subAggregatePath = subAggregateColumn.getAggregateReadExpressionTemplate( dialect ) final String subAggregatePath = subAggregateColumn.getAggregateReadExpressionTemplate( dialect )

View File

@ -9,18 +9,15 @@ package org.hibernate.tool.schema.internal;
import org.hibernate.boot.Metadata; import org.hibernate.boot.Metadata;
import org.hibernate.boot.model.relational.SqlStringGenerationContext; import org.hibernate.boot.model.relational.SqlStringGenerationContext;
import org.hibernate.dialect.Dialect; import org.hibernate.dialect.Dialect;
import org.hibernate.mapping.Constraint;
import org.hibernate.mapping.UniqueKey; import org.hibernate.mapping.UniqueKey;
import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.tool.schema.spi.Exporter;
/** /**
* An {@link Exporter} for {@link UniqueKey unique constraints}. The type argument is * An {@link Exporter} for {@linkplain UniqueKey unique constraints}.
* {@link Constraint}, rather than {@link UniqueKey}, allowing for {@link Dialect}s
* which create unique constraints for unique indexes.
* *
* @author Brett Meyer * @author Brett Meyer
*/ */
public class StandardUniqueKeyExporter implements Exporter<Constraint> { public class StandardUniqueKeyExporter implements Exporter<UniqueKey> {
private final Dialect dialect; private final Dialect dialect;
public StandardUniqueKeyExporter(Dialect dialect) { public StandardUniqueKeyExporter(Dialect dialect) {
@ -28,26 +25,14 @@ public class StandardUniqueKeyExporter implements Exporter<Constraint> {
} }
@Override @Override
public String[] getSqlCreateStrings(Constraint constraint, Metadata metadata, public String[] getSqlCreateStrings(UniqueKey constraint, Metadata metadata, SqlStringGenerationContext context) {
SqlStringGenerationContext context) { return new String[] { dialect.getUniqueDelegate()
return new String[] { .getAlterTableToAddUniqueKeyCommand( constraint, metadata, context ) };
dialect.getUniqueDelegate().getAlterTableToAddUniqueKeyCommand(
(UniqueKey) constraint,
metadata,
context
)
};
} }
@Override @Override
public String[] getSqlDropStrings(Constraint constraint, Metadata metadata, public String[] getSqlDropStrings(UniqueKey constraint, Metadata metadata, SqlStringGenerationContext context) {
SqlStringGenerationContext context) { return new String[] { dialect.getUniqueDelegate()
return new String[] { .getAlterTableToDropUniqueKeyCommand( constraint, metadata, context ) };
dialect.getUniqueDelegate().getAlterTableToDropUniqueKeyCommand(
(UniqueKey) constraint,
metadata,
context
)
};
} }
} }

View File

@ -0,0 +1,45 @@
package org.hibernate.orm.test.schemaupdate.options;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.ForeignKey;
import jakarta.persistence.Id;
import jakarta.persistence.Index;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.SchemaManager;
import jakarta.persistence.SchemaValidationException;
import jakarta.persistence.Table;
import jakarta.persistence.UniqueConstraint;
import org.hibernate.dialect.PostgreSQLDialect;
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
import org.hibernate.testing.orm.junit.Jpa;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.junit.jupiter.api.Test;
@Jpa(annotatedClasses = OptionsTest.WithOptions.class,
useCollectingStatementInspector = true)
@RequiresDialect(PostgreSQLDialect.class)
public class OptionsTest {
@Test void test(EntityManagerFactoryScope scope) throws SchemaValidationException {
SchemaManager schemaManager = scope.getEntityManagerFactory().getSchemaManager();
schemaManager.drop(true);
schemaManager.create(true);
schemaManager.validate();
}
@Entity
@Table(name = "TableWithOptions",
indexes = @Index(columnList = "name", options = "nulls distinct"),
uniqueConstraints = @UniqueConstraint(columnNames = "name", options = "deferrable"))
static class WithOptions {
@Id
long id;
@Column(name = "name", options = "compression pglz")
String name;
@ManyToOne
@JoinColumn(foreignKey = @ForeignKey(name = "ToOther", options = "match full"))
WithOptions other;
}
}