diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java index 0542ca3a38..8a8717a2bd 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java @@ -1977,6 +1977,11 @@ public abstract class Dialect implements ConversionContext { return true; } + /** + * Does this dialect support columns that are both unique and not null. + * + * @return True if supported, false otherwise. + */ public boolean supportsNotNullUnique() { return true; } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java index 99066aa73e..25c4eaa9f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Table.java @@ -423,10 +423,13 @@ public class Table implements RelationalModel, Serializable { alter.append( " not null" ); } - boolean useUniqueConstraint = column.isUnique() && - dialect.supportsUnique() && - ( column.isNullable() || dialect.supportsNotNullUnique() ); - if ( useUniqueConstraint ) { + // If the column is 1.) unique, 2.) the dialect supports the + // unique syntax, 3.) the column is nullable or supports + // "not null unique", and 4.) a constraint will not be created + if ( column.isUnique() && dialect.supportsUnique() + && ( column.isNullable() + || dialect.supportsNotNullUnique() ) + && !dialect.supportsUniqueConstraintInCreateAlterTable() ) { alter.append( " unique" ); } @@ -524,17 +527,21 @@ public class Table implements RelationalModel, Serializable { } } - - boolean useUniqueConstraint = col.isUnique() && - ( col.isNullable() || dialect.supportsNotNullUnique() ); - if ( useUniqueConstraint ) { - if ( dialect.supportsUnique() ) { - buf.append( " unique" ); - } - else { + + // If the column is 1.) unique and nullable or 2.) unique, + // not null, and the dialect supports unique not null + if ( col.isUnique() + && ( col.isNullable() + || dialect.supportsNotNullUnique() ) ) { + if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) { + // If the constraint is supported, do not add to the column syntax. UniqueKey uk = getOrCreateUniqueKey( col.getQuotedName( dialect ) + '_' ); uk.addColumn( col ); } + else if ( dialect.supportsUnique() ) { + // Otherwise, add to the column syntax if supported. + buf.append( " unique" ); + } } if ( col.hasCheckConstraint() && dialect.supportsColumnCheck() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/UniqueKey.java b/hibernate-core/src/main/java/org/hibernate/mapping/UniqueKey.java index f703f88a4c..36cd559c6b 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/UniqueKey.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/UniqueKey.java @@ -35,23 +35,21 @@ import org.hibernate.engine.spi.Mapping; public class UniqueKey extends Constraint { public String sqlConstraintString(Dialect dialect) { + // TODO: This may not be necessary, but not all callers currently + // check it on their own. Go through their logic. + if ( !isGenerated( dialect ) ) return null; + StringBuilder buf = new StringBuilder( "unique (" ); - boolean hadNullableColumn = false; Iterator iter = getColumnIterator(); while ( iter.hasNext() ) { Column column = (Column) iter.next(); - if ( !hadNullableColumn && column.isNullable() ) { - hadNullableColumn = true; - } buf.append( column.getQuotedName( dialect ) ); if ( iter.hasNext() ) { buf.append( ", " ); } } - //do not add unique constraint on DB not supporting unique and nullable columns - return !hadNullableColumn || dialect.supportsNotNullUnique() ? - buf.append( ')' ).toString() : - null; + + return buf.append( ')' ).toString(); } @Override @@ -60,18 +58,19 @@ public class UniqueKey extends Constraint { String constraintName, String defaultCatalog, String defaultSchema) { + // TODO: This may not be necessary, but not all callers currently + // check it on their own. Go through their logic. + if ( !isGenerated( dialect ) ) return null; + StringBuilder buf = new StringBuilder( - dialect.getAddUniqueConstraintString( constraintName ) - ).append( '(' ); + dialect.getAddUniqueConstraintString( constraintName ) ).append( '(' ); Iterator iter = getColumnIterator(); - boolean nullable = false; while ( iter.hasNext() ) { Column column = (Column) iter.next(); - if ( !nullable && column.isNullable() ) nullable = true; buf.append( column.getQuotedName( dialect ) ); if ( iter.hasNext() ) buf.append( ", " ); } - return !nullable || dialect.supportsNotNullUnique() ? buf.append( ')' ).toString() : null; + return buf.append( ')' ).toString(); } @Override @@ -97,12 +96,13 @@ public class UniqueKey extends Constraint { @Override public boolean isGenerated(Dialect dialect) { + if ( !dialect.supportsUniqueConstraintInCreateAlterTable() ) return false; if ( dialect.supportsNotNullUnique() ) return true; + Iterator iter = getColumnIterator(); while ( iter.hasNext() ) { - if ( ( (Column) iter.next() ).isNullable() ) { - return false; - } + // Dialect does not support "not null unique" and this column is not null. + if ( ! ( (Column) iter.next() ).isNullable() ) return false; } return true; } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java index 4d7562a776..72ce0df0f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/Table.java @@ -199,16 +199,20 @@ public class Table extends AbstractTableSpecification implements Exportable { } - boolean useUniqueConstraint = col.isUnique() && - ( col.isNullable() || dialect.supportsNotNullUnique() ); - if ( useUniqueConstraint ) { - if ( dialect.supportsUnique() ) { - buf.append( " unique" ); - } - else { + // If the column is 1.) unique and nullable or 2.) unique, + // not null, and the dialect supports unique not null + if ( col.isUnique() + && ( col.isNullable() + || dialect.supportsNotNullUnique() ) ) { + if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) { + // If the constraint is supported, do not add to the column syntax. UniqueKey uk = getOrCreateUniqueKey( col.getColumnName().encloseInQuotesIfQuoted( dialect ) + '_' ); uk.addColumn( col ); } + else if ( dialect.supportsUnique() ) { + // Otherwise, add to the column syntax if supported. + buf.append( " unique" ); + } } if ( col.getCheckCondition() != null && dialect.supportsColumnCheck() ) { diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java index 4fbffeba1e..1c5413e473 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/relational/UniqueKey.java @@ -48,21 +48,22 @@ public class UniqueKey extends AbstractConstraint implements Constraint { @Override public boolean isCreationVetoed(Dialect dialect) { - if ( dialect.supportsNotNullUnique() ) { - return false; - } - + if ( !dialect.supportsUniqueConstraintInCreateAlterTable() ) return true; + if ( dialect.supportsNotNullUnique() ) return false; + for ( Column column : getColumns() ) { - if ( column.isNullable() ) { - return true; - } + // Dialect does not support "not null unique" and this column is not null. + if ( ! column.isNullable() ) return true; } return false; } public String sqlConstraintStringInCreateTable(Dialect dialect) { + // TODO: This may not be necessary, but not all callers currently + // check it on their own. Go through their logic. + if ( isCreationVetoed( dialect ) ) return null; + StringBuilder buf = new StringBuilder( "unique (" ); - boolean hadNullableColumn = false; boolean first = true; for ( Column column : getColumns() ) { if ( first ) { @@ -71,23 +72,19 @@ public class UniqueKey extends AbstractConstraint implements Constraint { else { buf.append( ", " ); } - if ( !hadNullableColumn && column.isNullable() ) { - hadNullableColumn = true; - } buf.append( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ); } - //do not add unique constraint on DB not supporting unique and nullable columns - return !hadNullableColumn || dialect.supportsNotNullUnique() ? - buf.append( ')' ).toString() : - null; + return buf.append( ')' ).toString(); } @Override public String sqlConstraintStringInAlterTable(Dialect dialect) { + // TODO: This may not be necessary, but not all callers currently + // check it on their own. Go through their logic. + if ( isCreationVetoed( dialect ) ) return null; + StringBuilder buf = new StringBuilder( - dialect.getAddUniqueConstraintString( getName() ) - ).append( '(' ); - boolean nullable = false; + dialect.getAddUniqueConstraintString( getName() ) ).append( '(' ); boolean first = true; for ( Column column : getColumns() ) { if ( first ) { @@ -96,11 +93,8 @@ public class UniqueKey extends AbstractConstraint implements Constraint { else { buf.append( ", " ); } - if ( !nullable && column.isNullable() ) { - nullable = true; - } buf.append( column.getColumnName().encloseInQuotesIfQuoted( dialect ) ); } - return !nullable || dialect.supportsNotNullUnique() ? buf.append( ')' ).toString() : null; + return buf.append( ')' ).toString(); } }