HHH-17103 allow SQL expressions in @Index(columnList)
This commit is contained in:
parent
f1fa09ab42
commit
24646ece2c
|
@ -48,7 +48,7 @@ import org.hibernate.boot.model.internal.CreateKeySecondPass;
|
|||
import org.hibernate.boot.model.internal.FkSecondPass;
|
||||
import org.hibernate.boot.model.internal.IdGeneratorResolverSecondPass;
|
||||
import org.hibernate.boot.model.internal.ImplicitToOneJoinTableSecondPass;
|
||||
import org.hibernate.boot.model.internal.JPAIndexHolder;
|
||||
import org.hibernate.boot.model.internal.IndexHolder;
|
||||
import org.hibernate.boot.model.internal.OptionalDeterminationSecondPass;
|
||||
import org.hibernate.boot.model.internal.QuerySecondPass;
|
||||
import org.hibernate.boot.model.internal.SecondaryTableFromAnnotationSecondPass;
|
||||
|
@ -58,6 +58,7 @@ import org.hibernate.boot.model.internal.UniqueConstraintHolder;
|
|||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.naming.ImplicitForeignKeyNameSource;
|
||||
import org.hibernate.boot.model.naming.ImplicitIndexNameSource;
|
||||
import org.hibernate.boot.model.naming.ImplicitNamingStrategy;
|
||||
import org.hibernate.boot.model.naming.ImplicitUniqueKeyNameSource;
|
||||
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
||||
import org.hibernate.boot.model.relational.Database;
|
||||
|
@ -91,6 +92,7 @@ import org.hibernate.mapping.Component;
|
|||
import org.hibernate.mapping.DenormalizedTable;
|
||||
import org.hibernate.mapping.FetchProfile;
|
||||
import org.hibernate.mapping.ForeignKey;
|
||||
import org.hibernate.mapping.Formula;
|
||||
import org.hibernate.mapping.IdentifierCollection;
|
||||
import org.hibernate.mapping.Index;
|
||||
import org.hibernate.mapping.Join;
|
||||
|
@ -99,6 +101,7 @@ import org.hibernate.mapping.MappedSuperclass;
|
|||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.RootClass;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.mapping.SimpleValue;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.UniqueKey;
|
||||
|
@ -119,6 +122,7 @@ import jakarta.persistence.Entity;
|
|||
import jakarta.persistence.MapsId;
|
||||
|
||||
import static java.util.Collections.emptyList;
|
||||
import static org.hibernate.internal.util.StringHelper.isEmpty;
|
||||
import static org.hibernate.internal.util.collections.CollectionHelper.arrayList;
|
||||
|
||||
/**
|
||||
|
@ -178,7 +182,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
private Map<String, String> propertyRefResolver;
|
||||
private Set<DelayedPropertyReferenceHandler> delayedPropertyReferenceHandlers;
|
||||
private Map<Table, List<UniqueConstraintHolder>> uniqueConstraintHoldersByTable;
|
||||
private Map<Table, List<JPAIndexHolder>> jpaIndexHoldersByTable;
|
||||
private Map<Table, List<IndexHolder>> indexHoldersByTable;
|
||||
private List<Function<MetadataBuildingContext, Boolean>> valueResolvers;
|
||||
|
||||
public InFlightMetadataCollectorImpl(
|
||||
|
@ -1442,7 +1446,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
for ( String[] columns : uniqueConstraints ) {
|
||||
final String keyName = "key" + keyNameBase++;
|
||||
constraintHolders.add(
|
||||
new UniqueConstraintHolder().setName( keyName ).setColumns( columns )
|
||||
new UniqueConstraintHolder( keyName, columns )
|
||||
);
|
||||
}
|
||||
addUniqueConstraintHolders( table, constraintHolders );
|
||||
|
@ -1454,7 +1458,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addUniqueConstraintHolders(Table table, List<UniqueConstraintHolder> uniqueConstraintHolders) {
|
||||
public void addUniqueConstraintHolders(Table table, List<UniqueConstraintHolder> holders) {
|
||||
List<UniqueConstraintHolder> holderList = null;
|
||||
|
||||
if ( uniqueConstraintHoldersByTable == null ) {
|
||||
|
@ -1469,23 +1473,23 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
uniqueConstraintHoldersByTable.put( table, holderList );
|
||||
}
|
||||
|
||||
holderList.addAll( uniqueConstraintHolders );
|
||||
holderList.addAll( holders );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJpaIndexHolders(Table table, List<JPAIndexHolder> holders) {
|
||||
List<JPAIndexHolder> holderList = null;
|
||||
public void addIndexHolders(Table table, List<IndexHolder> holders) {
|
||||
List<IndexHolder> holderList = null;
|
||||
|
||||
if ( jpaIndexHoldersByTable == null ) {
|
||||
jpaIndexHoldersByTable = new HashMap<>();
|
||||
if ( indexHoldersByTable == null ) {
|
||||
indexHoldersByTable = new HashMap<>();
|
||||
}
|
||||
else {
|
||||
holderList = jpaIndexHoldersByTable.get( table );
|
||||
holderList = indexHoldersByTable.get( table );
|
||||
}
|
||||
|
||||
if ( holderList == null ) {
|
||||
holderList = new ArrayList<>();
|
||||
jpaIndexHoldersByTable.put( table, holderList );
|
||||
indexHoldersByTable.put( table, holderList );
|
||||
}
|
||||
|
||||
holderList.addAll( holders );
|
||||
|
@ -1845,7 +1849,7 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
secondPassCompileForeignKeys( buildingContext );
|
||||
|
||||
processUniqueConstraintHolders( buildingContext );
|
||||
processJPAIndexHolders( buildingContext );
|
||||
processIndexHolders( buildingContext );
|
||||
|
||||
processNaturalIdUniqueKeyBinders();
|
||||
|
||||
|
@ -2099,8 +2103,8 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
String keyName,
|
||||
boolean nameExplicit,
|
||||
String[] columnNames,
|
||||
MetadataBuildingContext buildingContext) {
|
||||
buildUniqueKeyFromColumnNames( table, keyName, nameExplicit, columnNames, null, true, buildingContext );
|
||||
MetadataBuildingContext context) {
|
||||
buildUniqueKeyFromColumnNames( table, keyName, nameExplicit, columnNames, null, true, context );
|
||||
}
|
||||
|
||||
private void buildUniqueKeyFromColumnNames(
|
||||
|
@ -2110,38 +2114,49 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
final String[] columnNames,
|
||||
String[] orderings,
|
||||
boolean unique,
|
||||
final MetadataBuildingContext buildingContext) {
|
||||
int size = columnNames.length;
|
||||
Column[] columns = new Column[size];
|
||||
Set<Column> unbound = new HashSet<>();
|
||||
Set<Column> unboundNoLogical = new HashSet<>();
|
||||
for ( int index = 0; index < size; index++ ) {
|
||||
final String logicalColumnName = columnNames[index];
|
||||
try {
|
||||
Column column = table.getColumn( buildingContext.getMetadataCollector(), logicalColumnName );
|
||||
if ( column == null ) {
|
||||
throw new AnnotationException(
|
||||
"Table '" + table.getName() + "' has no column named '" + logicalColumnName
|
||||
+ "' matching the column specified in '@UniqueConstraint'"
|
||||
);
|
||||
}
|
||||
columns[index] = column;
|
||||
unbound.add( column );
|
||||
//column equals and hashcode is based on column name
|
||||
}
|
||||
catch ( MappingException e ) {
|
||||
// If at least 1 columnName does exist, 'columns' will contain a mix of Columns and nulls.
|
||||
// In order to exhaustively report all the unbound columns at once, w/o an NPE in
|
||||
// Constraint#generateName's array sorting, simply create a fake Column.
|
||||
columns[index] = new Column( logicalColumnName );
|
||||
unboundNoLogical.add( columns[index] );
|
||||
}
|
||||
final MetadataBuildingContext context) {
|
||||
final int size = columnNames.length;
|
||||
if ( size == 0 ) {
|
||||
throw new AnnotationException( ( unique ? "Unique constraint" : "Index" )
|
||||
+ ( isEmpty( keyName ) ? "" : " '" + keyName + "'" )
|
||||
+ " on table '" + table.getName() + "' has no columns" );
|
||||
}
|
||||
final Selectable[] columns = new Selectable[size];
|
||||
for ( int index = 0; index < size; index++ ) {
|
||||
final String columnName = columnNames[index];
|
||||
if ( isEmpty( columnName ) ) {
|
||||
throw new AnnotationException( ( unique ? "Unique constraint" : "Index" )
|
||||
+ ( isEmpty( keyName ) ? "" : " '" + keyName + "'" )
|
||||
+ " on table '" + table.getName() + "' has an empty column name" );
|
||||
}
|
||||
columns[index] = indexColumn( table, context, columnName);
|
||||
}
|
||||
createIndexOrUniqueKey( table, keyName, nameExplicit, columnNames, orderings, unique, context, columns );
|
||||
}
|
||||
|
||||
createIndexOrUniqueKey( table, keyName, nameExplicit, columnNames, orderings, unique, buildingContext, columns, unbound );
|
||||
|
||||
if ( unbound.size() > 0 || unboundNoLogical.size() > 0 ) {
|
||||
throwUnableToCreateConstraint( table, columnNames, unique, unbound, unboundNoLogical );
|
||||
private static Selectable indexColumn(Table table, MetadataBuildingContext buildingContext, String logicalColumnName) {
|
||||
if ( logicalColumnName.startsWith("(") ) {
|
||||
return new Formula( logicalColumnName );
|
||||
}
|
||||
else {
|
||||
Column column;
|
||||
try {
|
||||
column = table.getColumn( buildingContext.getMetadataCollector(), logicalColumnName );
|
||||
}
|
||||
catch (MappingException me) {
|
||||
column = null;
|
||||
}
|
||||
if ( column != null ) {
|
||||
return column;
|
||||
}
|
||||
else {
|
||||
// assume it's a SQL formula with missing parens
|
||||
return new Formula( "(" + logicalColumnName + ")" );
|
||||
// throw new AnnotationException(
|
||||
// "Table '" + table.getName() + "' has no column named '" + logicalColumnName
|
||||
// + "' matching the column specified in '@UniqueConstraint'"
|
||||
// );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2152,112 +2167,52 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector,
|
|||
String[] columnNames,
|
||||
String[] orderings,
|
||||
boolean unique,
|
||||
MetadataBuildingContext buildingContext,
|
||||
Column[] columns,
|
||||
Set<Column> unbound) {
|
||||
if (unique) {
|
||||
createUniqueKey( table, originalKeyName, nameExplicit, columnNames, orderings, buildingContext, columns, unbound );
|
||||
MetadataBuildingContext context,
|
||||
Selectable[] columns) {
|
||||
final ImplicitNamingStrategy naming = getMetadataBuildingOptions().getImplicitNamingStrategy();
|
||||
final IndexOrUniqueKeyNameSource source =
|
||||
new IndexOrUniqueKeyNameSource( context, table, columnNames, originalKeyName );
|
||||
final Dialect dialect = getDatabase().getJdbcEnvironment().getDialect();
|
||||
boolean hasFormula = false;
|
||||
for ( Selectable selectable : columns ) {
|
||||
if ( selectable.isFormula() ) {
|
||||
hasFormula = true;
|
||||
}
|
||||
}
|
||||
if ( unique && !hasFormula ) {
|
||||
final String keyName = naming.determineUniqueKeyName( source ).render( dialect );
|
||||
final UniqueKey uniqueKey = table.getOrCreateUniqueKey( keyName );
|
||||
uniqueKey.setNameExplicit( nameExplicit );
|
||||
for ( int i = 0; i < columns.length; i++ ) {
|
||||
uniqueKey.addColumn( (Column) columns[i], orderings != null ? orderings[i] : null );
|
||||
}
|
||||
}
|
||||
else {
|
||||
createIndex( table, originalKeyName, columnNames, orderings, buildingContext, columns, unbound );
|
||||
}
|
||||
}
|
||||
|
||||
private void createIndex(
|
||||
Table table,
|
||||
String originalKeyName,
|
||||
String[] columnNames,
|
||||
String[] orderings,
|
||||
MetadataBuildingContext buildingContext,
|
||||
Column[] columns,
|
||||
Set<Column> unbound) {
|
||||
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy()
|
||||
.determineIndexName( new IndexOrUniqueKeyNameSource( buildingContext, table, columnNames, originalKeyName ) );
|
||||
final String keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
|
||||
|
||||
final Index index = table.getOrCreateIndex( keyName );
|
||||
for (int i = 0; i < columns.length; i++ ) {
|
||||
Column column = columns[i];
|
||||
String order = orderings != null ? orderings[i] : null;
|
||||
if ( table.containsColumn( column ) ) {
|
||||
index.addColumn( column, order );
|
||||
unbound.remove( column );
|
||||
final String keyName = naming.determineIndexName( source ).render( dialect );
|
||||
final Index index = table.getOrCreateIndex( keyName );
|
||||
index.setUnique( unique );
|
||||
for ( int i = 0; i < columns.length; i++ ) {
|
||||
index.addColumn( columns[i], orderings != null ? orderings[i] : null );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void createUniqueKey(
|
||||
Table table,
|
||||
String originalKeyName,
|
||||
boolean nameExplicit,
|
||||
String[] columnNames,
|
||||
String[] orderings,
|
||||
MetadataBuildingContext buildingContext,
|
||||
Column[] columns,
|
||||
Set<Column> unbound) {
|
||||
final Identifier keyNameIdentifier = getMetadataBuildingOptions().getImplicitNamingStrategy()
|
||||
.determineUniqueKeyName( new IndexOrUniqueKeyNameSource( buildingContext, table, columnNames, originalKeyName ) );
|
||||
final String keyName = keyNameIdentifier.render( getDatabase().getJdbcEnvironment().getDialect() );
|
||||
|
||||
final UniqueKey uk = table.getOrCreateUniqueKey( keyName );
|
||||
uk.setNameExplicit(nameExplicit);
|
||||
for (int i = 0; i < columns.length; i++ ) {
|
||||
Column column = columns[i];
|
||||
String order = orderings != null ? orderings[i] : null;
|
||||
if ( table.containsColumn( column ) ) {
|
||||
uk.addColumn( column, order );
|
||||
unbound.remove( column );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void throwUnableToCreateConstraint(
|
||||
Table table,
|
||||
String[] columnNames,
|
||||
boolean unique,
|
||||
Set<Column> unbound,
|
||||
Set<Column> unboundNoLogical) {
|
||||
final StringBuilder message = new StringBuilder( "Unable to create " );
|
||||
if (unique) {
|
||||
message.append( "unique key constraint (" );
|
||||
}
|
||||
else {
|
||||
message.append( "index (" );
|
||||
}
|
||||
for ( String columnName : columnNames) {
|
||||
message.append( columnName ).append( ", " );
|
||||
}
|
||||
message.setLength( message.length() - 2 );
|
||||
message.append( ") on table '" ).append( table.getName() ).append( "' since the column " );
|
||||
for ( Column column : unbound) {
|
||||
message.append("'").append( column.getName() ).append( "', " );
|
||||
}
|
||||
for ( Column column : unboundNoLogical) {
|
||||
message.append("'").append( column.getName() ).append( "', " );
|
||||
}
|
||||
message.setLength( message.length() - 2 );
|
||||
message.append( " was not found (specify the correct column name, which depends on the naming strategy, and may not be the same as the entity property name)" );
|
||||
throw new AnnotationException( message.toString() );
|
||||
}
|
||||
|
||||
private void processJPAIndexHolders(MetadataBuildingContext buildingContext) {
|
||||
if ( jpaIndexHoldersByTable == null ) {
|
||||
return;
|
||||
}
|
||||
|
||||
for ( Map.Entry<Table, List<JPAIndexHolder>> entry : jpaIndexHoldersByTable.entrySet() ) {
|
||||
final Table table = entry.getKey();
|
||||
final List<JPAIndexHolder> jpaIndexHolders = entry.getValue();
|
||||
for ( JPAIndexHolder holder : jpaIndexHolders ) {
|
||||
buildUniqueKeyFromColumnNames(
|
||||
table,
|
||||
holder.getName(),
|
||||
!holder.getName().isEmpty(),
|
||||
holder.getColumns(),
|
||||
holder.getOrdering(),
|
||||
holder.isUnique(),
|
||||
buildingContext
|
||||
);
|
||||
private void processIndexHolders(MetadataBuildingContext context) {
|
||||
if ( indexHoldersByTable != null ) {
|
||||
for ( Map.Entry<Table, List<IndexHolder>> entry : indexHoldersByTable.entrySet() ) {
|
||||
final Table table = entry.getKey();
|
||||
final List<IndexHolder> indexHolders = entry.getValue();
|
||||
for ( IndexHolder holder : indexHolders) {
|
||||
buildUniqueKeyFromColumnNames(
|
||||
table,
|
||||
holder.getName(),
|
||||
!holder.getName().isEmpty(),
|
||||
holder.getColumns(),
|
||||
holder.getOrdering(),
|
||||
holder.isUnique(),
|
||||
context
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -644,21 +644,21 @@ public class EntityBinder {
|
|||
final String schema;
|
||||
final String table;
|
||||
final String catalog;
|
||||
final List<UniqueConstraintHolder> uniqueConstraints;
|
||||
final UniqueConstraint[] uniqueConstraints;
|
||||
boolean hasTableAnnotation = annotatedClass.isAnnotationPresent( jakarta.persistence.Table.class );
|
||||
if ( hasTableAnnotation ) {
|
||||
final jakarta.persistence.Table tableAnnotation = annotatedClass.getAnnotation( jakarta.persistence.Table.class );
|
||||
table = tableAnnotation.name();
|
||||
schema = tableAnnotation.schema();
|
||||
catalog = tableAnnotation.catalog();
|
||||
uniqueConstraints = TableBinder.buildUniqueConstraintHolders( tableAnnotation.uniqueConstraints() );
|
||||
uniqueConstraints = tableAnnotation.uniqueConstraints();
|
||||
}
|
||||
else {
|
||||
//might be no @Table annotation on the annotated class
|
||||
schema = "";
|
||||
table = "";
|
||||
catalog = "";
|
||||
uniqueConstraints = Collections.emptyList();
|
||||
uniqueConstraints = new UniqueConstraint[0];
|
||||
}
|
||||
|
||||
final InFlightMetadataCollector collector = context.getMetadataCollector();
|
||||
|
@ -684,7 +684,7 @@ public class EntityBinder {
|
|||
String schema,
|
||||
String table,
|
||||
String catalog,
|
||||
List<UniqueConstraintHolder> uniqueConstraints,
|
||||
UniqueConstraint[] uniqueConstraints,
|
||||
InFlightMetadataCollector collector) {
|
||||
final RowId rowId = annotatedClass.getAnnotation( RowId.class );
|
||||
final View view = annotatedClass.getAnnotation( View.class );
|
||||
|
@ -1749,7 +1749,7 @@ public class EntityBinder {
|
|||
String schema,
|
||||
String catalog,
|
||||
String tableName,
|
||||
List<UniqueConstraintHolder> uniqueConstraints,
|
||||
UniqueConstraint[] uniqueConstraints,
|
||||
String rowId,
|
||||
String viewQuery,
|
||||
InFlightMetadataCollector.EntityTableXref denormalizedSuperTableXref) {
|
||||
|
@ -2050,7 +2050,9 @@ public class EntityBinder {
|
|||
secondaryTable.pkJoinColumns(),
|
||||
secondaryTable.uniqueConstraints()
|
||||
);
|
||||
TableBinder.addIndexes( join.getTable(), secondaryTable.indexes(), context );
|
||||
final Table table = join.getTable();
|
||||
context.getMetadataCollector()
|
||||
.addIndexHolders( table, TableBinder.buildIndexHolders( secondaryTable.indexes() ) );
|
||||
return join;
|
||||
}
|
||||
|
||||
|
@ -2083,7 +2085,7 @@ public class EntityBinder {
|
|||
catalog,
|
||||
logicalName.getTableName(),
|
||||
false,
|
||||
TableBinder.buildUniqueConstraintHolders( uniqueConstraints ),
|
||||
uniqueConstraints,
|
||||
context
|
||||
)
|
||||
);
|
||||
|
@ -2237,7 +2239,9 @@ public class EntityBinder {
|
|||
|
||||
public void processComplementaryTableDefinitions(jakarta.persistence.Table table) {
|
||||
if ( table != null ) {
|
||||
TableBinder.addIndexes( persistentClass.getTable(), table.indexes(), context );
|
||||
final Table classTable = persistentClass.getTable();
|
||||
context.getMetadataCollector()
|
||||
.addIndexHolders( classTable, TableBinder.buildIndexHolders( table.indexes() ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,23 +16,26 @@ import jakarta.persistence.Index;
|
|||
/**
|
||||
* @author Strong Liu
|
||||
*/
|
||||
public class JPAIndexHolder {
|
||||
public class IndexHolder {
|
||||
private final String name;
|
||||
private final String[] columns;
|
||||
private final String[] ordering;
|
||||
private final boolean unique;
|
||||
|
||||
public JPAIndexHolder(Index index) {
|
||||
StringTokenizer tokenizer = new StringTokenizer( index.columnList(), "," );
|
||||
List<String> tmp = new ArrayList<>();
|
||||
public IndexHolder(Index index) {
|
||||
final StringTokenizer tokenizer = new StringTokenizer( index.columnList(), "," );
|
||||
final List<String> parsed = new ArrayList<>();
|
||||
while ( tokenizer.hasMoreElements() ) {
|
||||
tmp.add( tokenizer.nextToken().trim() );
|
||||
final String trimmed = tokenizer.nextToken().trim();
|
||||
if ( !trimmed.isEmpty() ) {
|
||||
parsed.add( trimmed ) ;
|
||||
}
|
||||
}
|
||||
this.name = index.name();
|
||||
this.columns = new String[tmp.size()];
|
||||
this.ordering = new String[tmp.size()];
|
||||
this.columns = new String[parsed.size()];
|
||||
this.ordering = new String[parsed.size()];
|
||||
this.unique = index.unique();
|
||||
initializeColumns( columns, ordering, tmp );
|
||||
initializeColumns( columns, ordering, parsed );
|
||||
}
|
||||
|
||||
public String[] getColumns() {
|
|
@ -65,7 +65,6 @@ public class TableBinder {
|
|||
private String catalog;
|
||||
private String name;
|
||||
private boolean isAbstract;
|
||||
private List<UniqueConstraintHolder> uniqueConstraints;
|
||||
private String ownerEntityTable;
|
||||
private String associatedEntityTable;
|
||||
private String propertyName;
|
||||
|
@ -76,7 +75,8 @@ public class TableBinder {
|
|||
private String associatedEntity;
|
||||
private String associatedJpaEntity;
|
||||
private boolean isJPA2ElementCollection;
|
||||
private List<JPAIndexHolder> jpaIndexHolders;
|
||||
private UniqueConstraint[] uniqueConstraints;
|
||||
private Index[] indexes;
|
||||
|
||||
public void setBuildingContext(MetadataBuildingContext buildingContext) {
|
||||
this.buildingContext = buildingContext;
|
||||
|
@ -103,11 +103,11 @@ public class TableBinder {
|
|||
}
|
||||
|
||||
public void setUniqueConstraints(UniqueConstraint[] uniqueConstraints) {
|
||||
this.uniqueConstraints = TableBinder.buildUniqueConstraintHolders( uniqueConstraints );
|
||||
this.uniqueConstraints = uniqueConstraints;
|
||||
}
|
||||
|
||||
public void setJpaIndex(Index[] jpaIndex){
|
||||
this.jpaIndexHolders = buildJpaIndexHolder( jpaIndex );
|
||||
public void setJpaIndex(Index[] indexes){
|
||||
this.indexes = indexes;
|
||||
}
|
||||
|
||||
public void setJPA2ElementCollection(boolean isJPA2ElementCollection) {
|
||||
|
@ -292,7 +292,7 @@ public class TableBinder {
|
|||
: namingStrategyHelper.determineImplicitName( buildingContext ),
|
||||
isAbstract,
|
||||
uniqueConstraints,
|
||||
jpaIndexHolders,
|
||||
indexes,
|
||||
buildingContext,
|
||||
null,
|
||||
null
|
||||
|
@ -434,7 +434,7 @@ public class TableBinder {
|
|||
String catalog,
|
||||
Identifier logicalName,
|
||||
boolean isAbstract,
|
||||
List<UniqueConstraintHolder> uniqueConstraints,
|
||||
UniqueConstraint[] uniqueConstraints,
|
||||
MetadataBuildingContext buildingContext) {
|
||||
return buildAndFillTable(
|
||||
schema,
|
||||
|
@ -454,7 +454,7 @@ public class TableBinder {
|
|||
String catalog,
|
||||
Identifier logicalName,
|
||||
boolean isAbstract,
|
||||
List<UniqueConstraintHolder> uniqueConstraints,
|
||||
UniqueConstraint[] uniqueConstraints,
|
||||
MetadataBuildingContext buildingContext,
|
||||
String subselect,
|
||||
InFlightMetadataCollector.EntityTableXref denormalizedSuperTableXref) {
|
||||
|
@ -476,8 +476,8 @@ public class TableBinder {
|
|||
String catalog,
|
||||
Identifier logicalName,
|
||||
boolean isAbstract,
|
||||
List<UniqueConstraintHolder> uniqueConstraints,
|
||||
List<JPAIndexHolder> jpaIndexHolders,
|
||||
UniqueConstraint[] uniqueConstraints,
|
||||
Index[] indexes,
|
||||
MetadataBuildingContext buildingContext,
|
||||
String subselect,
|
||||
InFlightMetadataCollector.EntityTableXref denormalizedSuperTableXref) {
|
||||
|
@ -489,11 +489,11 @@ public class TableBinder {
|
|||
denormalizedSuperTableXref, metadataCollector );
|
||||
|
||||
if ( isNotEmpty( uniqueConstraints ) ) {
|
||||
metadataCollector.addUniqueConstraintHolders( table, uniqueConstraints );
|
||||
metadataCollector.addUniqueConstraintHolders( table, buildUniqueConstraintHolders( uniqueConstraints ) );
|
||||
}
|
||||
|
||||
if ( isNotEmpty( jpaIndexHolders ) ) {
|
||||
metadataCollector.addJpaIndexHolders( table, jpaIndexHolders );
|
||||
if ( isNotEmpty( indexes ) ) {
|
||||
metadataCollector.addIndexHolders( table, buildIndexHolders( indexes ) );
|
||||
}
|
||||
|
||||
metadataCollector.addTableNameBinding( logicalName, table );
|
||||
|
@ -806,7 +806,7 @@ public class TableBinder {
|
|||
}
|
||||
}
|
||||
|
||||
public static void addIndexes(Table table, org.hibernate.annotations.Index[] indexes, MetadataBuildingContext context) {
|
||||
static void addIndexes(Table table, org.hibernate.annotations.Index[] indexes, MetadataBuildingContext context) {
|
||||
for ( org.hibernate.annotations.Index index : indexes ) {
|
||||
//no need to handle inSecondPass here since it is only called from EntityBinder
|
||||
context.getMetadataCollector().addSecondPass(
|
||||
|
@ -815,38 +815,33 @@ public class TableBinder {
|
|||
}
|
||||
}
|
||||
|
||||
public static void addIndexes(Table table, Index[] indexes, MetadataBuildingContext context) {
|
||||
context.getMetadataCollector().addJpaIndexHolders( table, buildJpaIndexHolder( indexes ) );
|
||||
}
|
||||
|
||||
public static List<JPAIndexHolder> buildJpaIndexHolder(Index[] indexes) {
|
||||
List<JPAIndexHolder> holders = new ArrayList<>( indexes.length );
|
||||
/**
|
||||
* Build a list of {@link IndexHolder} instances given a
|
||||
* list of {@link Index} annotations.
|
||||
*/
|
||||
static List<IndexHolder> buildIndexHolders(Index[] indexes) {
|
||||
List<IndexHolder> holders = new ArrayList<>( indexes.length );
|
||||
for ( Index index : indexes ) {
|
||||
holders.add( new JPAIndexHolder( index ) );
|
||||
holders.add( new IndexHolder( index ) );
|
||||
}
|
||||
return holders;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a list of {@link UniqueConstraintHolder} instances given a list of
|
||||
* {@link UniqueConstraint} annotations.
|
||||
*
|
||||
* @param annotations The {@link UniqueConstraint} annotations.
|
||||
*
|
||||
* @return The built {@link UniqueConstraintHolder} instances.
|
||||
* Build a list of {@link UniqueConstraintHolder} instances
|
||||
* given a list of {@link UniqueConstraint} annotations.
|
||||
*/
|
||||
public static List<UniqueConstraintHolder> buildUniqueConstraintHolders(UniqueConstraint[] annotations) {
|
||||
List<UniqueConstraintHolder> result;
|
||||
if ( annotations == null || annotations.length == 0 ) {
|
||||
result = emptyList();
|
||||
static List<UniqueConstraintHolder> buildUniqueConstraintHolders(UniqueConstraint[] uniqueConstraints) {
|
||||
if ( uniqueConstraints == null || uniqueConstraints.length == 0 ) {
|
||||
return emptyList();
|
||||
}
|
||||
else {
|
||||
result = arrayList( annotations.length );
|
||||
for ( UniqueConstraint uc : annotations ) {
|
||||
result.add( new UniqueConstraintHolder().setName( uc.name(), !uc.name().isEmpty() ).setColumns( uc.columnNames() ) );
|
||||
final List<UniqueConstraintHolder> result = arrayList( uniqueConstraints.length );
|
||||
for ( UniqueConstraint uniqueConstraint : uniqueConstraints ) {
|
||||
result.add( new UniqueConstraintHolder( uniqueConstraint ) );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setDefaultName(
|
||||
|
|
|
@ -7,28 +7,33 @@
|
|||
package org.hibernate.boot.model.internal;
|
||||
|
||||
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
|
||||
/**
|
||||
* {@link jakarta.persistence.UniqueConstraint} annotations are handled via second pass. I do not
|
||||
* {@link jakarta.persistence.UniqueConstraint} annotations are handled via second pass. I do not
|
||||
* understand the reasons why at this time, so here I use a holder object to hold the information
|
||||
* needed to create the unique constraint. The ability to name it is new, and so the code used to
|
||||
* needed to create the unique constraint. The ability to name it is new, and so the code used to
|
||||
* simply keep this as a String array (the column names).
|
||||
*
|
||||
* Isn't this ultimately the same as org.hibernate.cfg.IndexOrUniqueKeySecondPass?
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
// Isn't this ultimately the same as IndexOrUniqueKeySecondPass?
|
||||
public class UniqueConstraintHolder {
|
||||
private String name;
|
||||
private boolean nameExplicit;
|
||||
private String[] columns;
|
||||
private final String name;
|
||||
private final String[] columns;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public UniqueConstraintHolder setName(String name) {
|
||||
public UniqueConstraintHolder(UniqueConstraint uniqueConstraint) {
|
||||
this.name = uniqueConstraint.name();
|
||||
this.columns = uniqueConstraint.columnNames();
|
||||
}
|
||||
|
||||
public UniqueConstraintHolder(String name, String[] columns) {
|
||||
this.name = name;
|
||||
return this;
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
public boolean isNameExplicit() {
|
||||
|
@ -38,14 +43,4 @@ public class UniqueConstraintHolder {
|
|||
public String[] getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public UniqueConstraintHolder setColumns(String[] columns) {
|
||||
this.columns = columns;
|
||||
return this;
|
||||
}
|
||||
|
||||
public UniqueConstraintHolder setName(String name, boolean nameExplicit) {
|
||||
this.nameExplicit = nameExplicit;
|
||||
return setName(name);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.hibernate.boot.model.convert.spi.ConverterDescriptor;
|
|||
import org.hibernate.boot.model.convert.spi.ConverterRegistry;
|
||||
import org.hibernate.boot.model.convert.spi.RegisteredConversion;
|
||||
import org.hibernate.boot.model.internal.AnnotatedClassType;
|
||||
import org.hibernate.boot.model.internal.JPAIndexHolder;
|
||||
import org.hibernate.boot.model.internal.IndexHolder;
|
||||
import org.hibernate.boot.model.internal.UniqueConstraintHolder;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.relational.AuxiliaryDatabaseObject;
|
||||
|
@ -359,7 +359,7 @@ public interface InFlightMetadataCollector extends MetadataImplementor {
|
|||
@Deprecated(forRemoval = true)
|
||||
void addUniqueConstraints(Table table, List<String[]> uniqueConstraints);
|
||||
void addUniqueConstraintHolders(Table table, List<UniqueConstraintHolder> uniqueConstraints);
|
||||
void addJpaIndexHolders(Table table, List<JPAIndexHolder> jpaIndexHolders);
|
||||
void addIndexHolders(Table table, List<IndexHolder> indexHolders);
|
||||
|
||||
|
||||
interface EntityTableXref {
|
||||
|
|
|
@ -9,10 +9,14 @@ package org.hibernate.dialect.unique;
|
|||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.UniqueKey;
|
||||
|
||||
import static org.hibernate.mapping.Index.buildSqlCreateIndexString;
|
||||
import static org.hibernate.mapping.Index.buildSqlDropIndexString;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||
import static org.hibernate.internal.util.StringHelper.unqualify;
|
||||
|
||||
/**
|
||||
* A {@link UniqueDelegate} which uses {@code create unique index} commands when necessary.
|
||||
|
@ -36,15 +40,34 @@ public class AlterTableUniqueIndexDelegate extends AlterTableUniqueDelegate {
|
|||
public String getAlterTableToAddUniqueKeyCommand(UniqueKey uniqueKey, Metadata metadata,
|
||||
SqlStringGenerationContext context) {
|
||||
if ( uniqueKey.hasNullableColumn() ) {
|
||||
return buildSqlCreateIndexString(
|
||||
context,
|
||||
uniqueKey.getName(),
|
||||
uniqueKey.getTable(),
|
||||
uniqueKey.getColumns(),
|
||||
uniqueKey.getColumnOrderMap(),
|
||||
true,
|
||||
metadata
|
||||
);
|
||||
final Dialect dialect = context.getDialect();
|
||||
final String name = uniqueKey.getName();
|
||||
final String tableName = context.format( uniqueKey.getTable().getQualifiedTableName() );
|
||||
final List<Column> columns = uniqueKey.getColumns();
|
||||
final Map<Column, String> columnOrderMap = uniqueKey.getColumnOrderMap();
|
||||
final StringBuilder statement =
|
||||
new StringBuilder( dialect.getCreateIndexString( true ) )
|
||||
.append( " " )
|
||||
.append( dialect.qualifyIndexName() ? name : unqualify( name ) )
|
||||
.append( " on " )
|
||||
.append( tableName )
|
||||
.append( " (" );
|
||||
boolean first = true;
|
||||
for ( Column column : columns ) {
|
||||
if ( first ) {
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
statement.append(", ");
|
||||
}
|
||||
statement.append( column.getQuotedName(dialect) );
|
||||
if ( columnOrderMap.containsKey( column ) ) {
|
||||
statement.append( " " ).append( columnOrderMap.get( column ) );
|
||||
}
|
||||
}
|
||||
statement.append( ")" );
|
||||
statement.append( dialect.getCreateIndexTail( true, columns ) );
|
||||
return statement.toString();
|
||||
}
|
||||
else {
|
||||
return super.getAlterTableToAddUniqueKeyCommand( uniqueKey, metadata, context );
|
||||
|
@ -55,13 +78,12 @@ public class AlterTableUniqueIndexDelegate extends AlterTableUniqueDelegate {
|
|||
public String getAlterTableToDropUniqueKeyCommand(UniqueKey uniqueKey, Metadata metadata,
|
||||
SqlStringGenerationContext context) {
|
||||
if ( uniqueKey.hasNullableColumn() ) {
|
||||
return buildSqlDropIndexString(
|
||||
uniqueKey.getName(),
|
||||
context.format( uniqueKey.getTable().getQualifiedTableName() )
|
||||
);
|
||||
final String tableName = context.format( uniqueKey.getTable().getQualifiedTableName() );
|
||||
return "drop index " + qualify( tableName, uniqueKey.getName() );
|
||||
}
|
||||
else {
|
||||
return super.getAlterTableToDropUniqueKeyCommand( uniqueKey, metadata, context );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -571,8 +571,8 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getText(Dialect d) {
|
||||
return assignmentExpression != null ? assignmentExpression : getQuotedName( d );
|
||||
public String getText(Dialect dialect) {
|
||||
return assignmentExpression != null ? assignmentExpression : getQuotedName( dialect );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -12,7 +12,6 @@ import java.security.NoSuchAlgorithmException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.io.Serializable;
|
|||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.loader.internal.AliasConstantsHelper;
|
||||
import org.hibernate.query.sqm.function.SqmFunctionRegistry;
|
||||
import org.hibernate.type.spi.TypeConfiguration;
|
||||
|
@ -95,4 +94,15 @@ public class Formula implements Selectable, Serializable {
|
|||
public String toString() {
|
||||
return getClass().getSimpleName() + "( " + formula + " )";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof Formula
|
||||
&& ( (Formula) obj ).formula.equals( formula );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return formula.hashCode();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,19 +9,22 @@ package org.hibernate.mapping;
|
|||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.model.naming.Identifier;
|
||||
import org.hibernate.boot.model.relational.Exportable;
|
||||
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
|
||||
import static java.util.Collections.unmodifiableList;
|
||||
import static java.util.Collections.unmodifiableMap;
|
||||
import static java.util.stream.Collectors.toUnmodifiableList;
|
||||
import static java.util.stream.Collectors.toUnmodifiableMap;
|
||||
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
|
||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||
import static org.hibernate.internal.util.StringHelper.unqualify;
|
||||
|
||||
/**
|
||||
* A mapping model object representing an {@linkplain jakarta.persistence.Index index} on a relational database table.
|
||||
|
@ -34,15 +37,22 @@ import static org.hibernate.internal.util.StringHelper.qualify;
|
|||
public class Index implements Exportable, Serializable {
|
||||
private Identifier name;
|
||||
private Table table;
|
||||
private final java.util.List<Column> columns = new ArrayList<>();
|
||||
private final java.util.Map<Column, String> columnOrderMap = new HashMap<>( );
|
||||
private boolean unique;
|
||||
private final java.util.List<Selectable> selectables = new ArrayList<>();
|
||||
private final java.util.Map<Selectable, String> selectableOrderMap = new HashMap<>();
|
||||
|
||||
public static String buildSqlDropIndexString(
|
||||
String name,
|
||||
String tableName) {
|
||||
/**
|
||||
* @deprecated This method will be removed in the next release
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static String buildSqlDropIndexString(String name, String tableName) {
|
||||
return "drop index " + qualify( tableName, name );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in the next release
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static String buildSqlCreateIndexString(
|
||||
Dialect dialect,
|
||||
String name,
|
||||
|
@ -52,7 +62,7 @@ public class Index implements Exportable, Serializable {
|
|||
boolean unique) {
|
||||
StringBuilder statement = new StringBuilder( dialect.getCreateIndexString( unique ) )
|
||||
.append( " " )
|
||||
.append( dialect.qualifyIndexName() ? name : StringHelper.unqualify( name ) )
|
||||
.append( dialect.qualifyIndexName() ? name : unqualify( name ) )
|
||||
.append( " on " )
|
||||
.append( tableName )
|
||||
.append( " (" );
|
||||
|
@ -75,6 +85,10 @@ public class Index implements Exportable, Serializable {
|
|||
return statement.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated This method will be removed in the next release
|
||||
*/
|
||||
@Deprecated(forRemoval = true)
|
||||
public static String buildSqlCreateIndexString(
|
||||
SqlStringGenerationContext context,
|
||||
String name,
|
||||
|
@ -101,39 +115,73 @@ public class Index implements Exportable, Serializable {
|
|||
this.table = table;
|
||||
}
|
||||
|
||||
public void setUnique(boolean unique) {
|
||||
this.unique = unique;
|
||||
}
|
||||
|
||||
public boolean isUnique() {
|
||||
return unique;
|
||||
}
|
||||
|
||||
public int getColumnSpan() {
|
||||
return columns.size();
|
||||
return selectables.size();
|
||||
}
|
||||
|
||||
public List<Selectable> getSelectables() {
|
||||
return unmodifiableList( selectables );
|
||||
}
|
||||
|
||||
public Map<Selectable, String> getSelectableOrderMap() {
|
||||
return unmodifiableMap( selectableOrderMap );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getSelectables()}
|
||||
*/
|
||||
@Deprecated(since = "6.3")
|
||||
public java.util.List<Column> getColumns() {
|
||||
return unmodifiableList( columns );
|
||||
return selectables.stream()
|
||||
.map( s -> (Column) s ).collect( toUnmodifiableList() );
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getSelectableOrderMap()}
|
||||
*/
|
||||
@Deprecated(since = "6.3")
|
||||
public java.util.Map<Column, String> getColumnOrderMap() {
|
||||
return unmodifiableMap( columnOrderMap );
|
||||
return selectableOrderMap.entrySet().stream()
|
||||
.collect( toUnmodifiableMap( e -> (Column) e.getKey(), Map.Entry::getValue ) );
|
||||
}
|
||||
|
||||
public void addColumn(Column column) {
|
||||
if ( !columns.contains( column ) ) {
|
||||
columns.add( column );
|
||||
public void addColumn(Selectable selectable) {
|
||||
if ( !selectables.contains( selectable ) ) {
|
||||
selectables.add( selectable );
|
||||
}
|
||||
}
|
||||
|
||||
public void addColumn(Column column, String order) {
|
||||
addColumn( column );
|
||||
public void addColumn(Selectable selectable, String order) {
|
||||
addColumn( selectable );
|
||||
if ( isNotEmpty( order ) ) {
|
||||
columnOrderMap.put( column, order );
|
||||
selectableOrderMap.put( selectable, order );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getSelectableOrderMap()}
|
||||
*/
|
||||
@Deprecated(since = "6.3", forRemoval = true)
|
||||
public void addColumns(java.util.List<Column> extraColumns) {
|
||||
for ( Column column : extraColumns ) {
|
||||
addColumn( column );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link #getSelectableOrderMap()}
|
||||
*/
|
||||
@Deprecated(since = "6.3", forRemoval = true)
|
||||
public boolean containsColumn(Column column) {
|
||||
return columns.contains( column );
|
||||
return selectables.contains( column );
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
|
|
@ -10,14 +10,15 @@ import java.util.Map;
|
|||
|
||||
import org.hibernate.boot.Metadata;
|
||||
import org.hibernate.boot.model.relational.QualifiedNameImpl;
|
||||
import org.hibernate.boot.model.relational.QualifiedTableName;
|
||||
import org.hibernate.boot.model.relational.SqlStringGenerationContext;
|
||||
import org.hibernate.dialect.Dialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.Index;
|
||||
import org.hibernate.mapping.Selectable;
|
||||
import org.hibernate.tool.schema.spi.Exporter;
|
||||
|
||||
import static org.hibernate.internal.util.StringHelper.qualify;
|
||||
|
||||
/**
|
||||
* An {@link Exporter} for {@linkplain Index indexes}.
|
||||
*
|
||||
|
@ -37,45 +38,50 @@ public class StandardIndexExporter implements Exporter<Index> {
|
|||
|
||||
@Override
|
||||
public String[] getSqlCreateStrings(Index index, Metadata metadata, SqlStringGenerationContext context) {
|
||||
final JdbcEnvironment jdbcEnvironment = metadata.getDatabase().getJdbcEnvironment();
|
||||
final String tableName = context.format( index.getTable().getQualifiedTableName() );
|
||||
final StringBuilder createIndex = new StringBuilder()
|
||||
.append( dialect.getCreateIndexString( index.isUnique() ) )
|
||||
.append( " " )
|
||||
.append( indexName( index, context, metadata ) )
|
||||
.append( " on " )
|
||||
.append( context.format( index.getTable().getQualifiedTableName() ) )
|
||||
.append( " (" );
|
||||
appendColumnList( index, createIndex );
|
||||
createIndex.append( ")" );
|
||||
return new String[] { createIndex.toString() };
|
||||
}
|
||||
|
||||
final String indexNameForCreation;
|
||||
private String indexName(Index index, SqlStringGenerationContext context, Metadata metadata) {
|
||||
if ( dialect.qualifyIndexName() ) {
|
||||
indexNameForCreation = context.format(
|
||||
final QualifiedTableName qualifiedTableName = index.getTable().getQualifiedTableName();
|
||||
return context.format(
|
||||
new QualifiedNameImpl(
|
||||
index.getTable().getQualifiedTableName().getCatalogName(),
|
||||
index.getTable().getQualifiedTableName().getSchemaName(),
|
||||
jdbcEnvironment.getIdentifierHelper().toIdentifier( index.getQuotedName( dialect ) )
|
||||
qualifiedTableName.getCatalogName(),
|
||||
qualifiedTableName.getSchemaName(),
|
||||
metadata.getDatabase().getJdbcEnvironment().getIdentifierHelper()
|
||||
.toIdentifier( index.getQuotedName( dialect ) )
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
indexNameForCreation = index.getName();
|
||||
return index.getName();
|
||||
}
|
||||
final StringBuilder buf = new StringBuilder()
|
||||
.append( "create index " )
|
||||
.append( indexNameForCreation )
|
||||
.append( " on " )
|
||||
.append( tableName )
|
||||
.append( " (" );
|
||||
}
|
||||
|
||||
private void appendColumnList(Index index, StringBuilder createIndex) {
|
||||
boolean first = true;
|
||||
final Map<Column, String> columnOrderMap = index.getColumnOrderMap();
|
||||
for ( Column column : index.getColumns() ) {
|
||||
final Map<Selectable, String> columnOrderMap = index.getSelectableOrderMap();
|
||||
for ( Selectable column : index.getSelectables() ) {
|
||||
if ( first ) {
|
||||
first = false;
|
||||
}
|
||||
else {
|
||||
buf.append( ", " );
|
||||
createIndex.append( ", " );
|
||||
}
|
||||
buf.append( ( column.getQuotedName( dialect ) ) );
|
||||
createIndex.append( column.getText( dialect ) );
|
||||
if ( columnOrderMap.containsKey( column ) ) {
|
||||
buf.append( " " ).append( columnOrderMap.get( column ) );
|
||||
createIndex.append( " " ).append( columnOrderMap.get( column ) );
|
||||
}
|
||||
}
|
||||
buf.append( ")" );
|
||||
return new String[] { buf.toString() };
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,7 +93,7 @@ public class StandardIndexExporter implements Exporter<Index> {
|
|||
final String tableName = context.format( index.getTable().getQualifiedTableName() );
|
||||
|
||||
final String indexNameForCreation = dialect.qualifyIndexName()
|
||||
? StringHelper.qualify( tableName, index.getName() )
|
||||
? qualify( tableName, index.getName() )
|
||||
: index.getName();
|
||||
|
||||
return new String[] { "drop index " + indexNameForCreation };
|
||||
|
|
|
@ -33,12 +33,12 @@ public class UniqueConstraintValidationTest extends BaseUnitTestCase {
|
|||
buildSessionFactory(EmptyColumnNameEntity.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(expected = AnnotationException.class)
|
||||
public void testUniqueConstraintWithEmptyColumnNameList() {
|
||||
buildSessionFactory(EmptyColumnNameListEntity.class);
|
||||
}
|
||||
|
||||
@Test(expected = AnnotationException.class)
|
||||
@Test
|
||||
public void testUniqueConstraintWithNotExistsColumnName() {
|
||||
buildSessionFactory(NotExistsColumnEntity.class);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue