Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,11 @@ public boolean supportsColumnCheck() {
return getVersion().isSameOrAfter( 10, 2 );
}

@Override
public boolean supportsNamedColumnCheck() {
return false;
}

@Override
public boolean doesRoundTemporalOnOverflow() {
// See https://jira.mariadb.org/browse/MDEV-16991
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,7 @@ void applyCheckConstraints(jakarta.persistence.CheckConstraint[] checkConstraint
if ( isNotEmpty( checkConstraintAnnotationUsages ) ) {
for ( jakarta.persistence.CheckConstraint checkConstraintAnnotationUsage : checkConstraintAnnotationUsages ) {
addCheckConstraint(
checkConstraintAnnotationUsage.name(),
nullIfEmpty( checkConstraintAnnotationUsage.name() ),
checkConstraintAnnotationUsage.constraint(),
checkConstraintAnnotationUsage.options()
);
Expand All @@ -983,7 +983,7 @@ void applyCheckConstraint(PropertyData inferredData, int length) {
if ( checksAnn != null ) {
final Check[] checkAnns = checksAnn.value();
for ( Check checkAnn : checkAnns ) {
addCheckConstraint( checkAnn.name(), checkAnn.constraints() );
addCheckConstraint( nullIfEmpty( checkAnn.name() ), checkAnn.constraints() );
}
}
else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import static org.hibernate.internal.util.StringHelper.isNotEmpty;
import static org.hibernate.internal.util.StringHelper.isQuoted;
import static org.hibernate.internal.util.StringHelper.nullIfBlank;
import static org.hibernate.internal.util.StringHelper.nullIfEmpty;
import static org.hibernate.internal.util.StringHelper.unquote;
import static org.hibernate.internal.util.collections.CollectionHelper.isNotEmpty;

Expand Down Expand Up @@ -896,7 +897,7 @@ static void addTableCheck(
for ( jakarta.persistence.CheckConstraint checkConstraintAnnotationUsage : checkConstraintAnnotationUsages ) {
table.addCheck(
new CheckConstraint(
checkConstraintAnnotationUsage.name(),
nullIfEmpty( checkConstraintAnnotationUsage.name() ),
checkConstraintAnnotationUsage.constraint(),
checkConstraintAnnotationUsage.options()
)
Expand Down
10 changes: 10 additions & 0 deletions hibernate-core/src/main/java/org/hibernate/dialect/Dialect.java
Original file line number Diff line number Diff line change
Expand Up @@ -4186,6 +4186,16 @@ public boolean supportsColumnCheck() {
return true;
}

/**
* Does this dialect support named column-level check constraints?
*
* @return True if named column-level {@code check} constraints are supported;
* false otherwise.
*/
public boolean supportsNamedColumnCheck() {
return supportsColumnCheck();
}

/**
* Does this dialect support table-level check constraints?
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,11 @@ public boolean supportsColumnCheck() {
return true;
}

@Override
public boolean supportsNamedColumnCheck() {
return false;
}

@Override
public boolean doesRoundTemporalOnOverflow() {
// See https://jira.mariadb.org/browse/MDEV-16991
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,34 +144,41 @@ private static void appendConstraints(
}

if ( dialect.supportsColumnCheck() ) {
// some databases (Maria, SQL Server) don't like multiple 'check' clauses
final List<CheckConstraint> checkConstraints = column.getCheckConstraints();
long anonConstraints = checkConstraints.stream().filter(CheckConstraint::isAnonymous).count();
if ( anonConstraints == 1 ) {
for ( CheckConstraint constraint : checkConstraints ) {
definition.append( constraint.constraintString( dialect ) );
boolean hasAnonymousConstraints = false;
for ( CheckConstraint constraint : checkConstraints ) {
if ( constraint.isAnonymous() ) {
if ( !hasAnonymousConstraints ) {
definition.append(" check (");
hasAnonymousConstraints = true;
}
else {
definition.append(" and ");
}
definition.append( constraint.getConstraintInParens() );
}
}
else {
boolean first = true;
if ( hasAnonymousConstraints ) {
definition.append( ')' );
}

if ( !dialect.supportsTableCheck() ) {
// When table check constraints are not supported, try to render all named constraints
for ( CheckConstraint constraint : checkConstraints ) {
if ( constraint.isAnonymous() ) {
if ( first ) {
definition.append(" check (");
first = false;
}
else {
definition.append(" and ");
}
definition.append( constraint.getConstraintInParens() );
if ( constraint.isNamed() ) {
definition.append( constraint.constraintString( dialect ) );
}
}
if ( !first ) {
definition.append(")");
}
}
else if ( !hasAnonymousConstraints && dialect.supportsNamedColumnCheck() ) {
// Otherwise only render the first named constraint as column constraint if there are no anonymous
// constraints and named column check constraint are supported, because some database don't like
// multiple check clauses.
// Note that the TableExporter will take care of named constraints then
for ( CheckConstraint constraint : checkConstraints ) {
if ( constraint.isNamed() ) {
definition.append( constraint.constraintString( dialect ) );
break;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,37 +197,43 @@ protected void applyTableTypeString(StringBuilder buf) {

protected void applyTableCheck(Table table, StringBuilder buf) {
if ( dialect.supportsTableCheck() ) {
if ( !dialect.supportsColumnCheck() ) {
for ( Column column : table.getColumns() ) {
// some databases (Maria, SQL Server) don't like multiple 'check' clauses
final List<CheckConstraint> checkConstraints = column.getCheckConstraints();
long anonConstraints = checkConstraints.stream().filter( CheckConstraint::isAnonymous ).count();
if ( anonConstraints == 1 ) {
for ( CheckConstraint constraint : checkConstraints ) {
buf.append( "," ).append( constraint.constraintString( dialect ) );
}
}
else {
boolean first = true;
for ( CheckConstraint constraint : checkConstraints ) {
if ( constraint.isAnonymous() ) {
if ( first ) {
buf.append( "," ).append( " check (" );
first = false;
}
else {
buf.append( " and " );
}
buf.append( constraint.getConstraintInParens() );
for ( Column column : table.getColumns() ) {
final List<CheckConstraint> checkConstraints = column.getCheckConstraints();
boolean hasAnonymousConstraints = false;
if ( !dialect.supportsColumnCheck() ) {
for ( CheckConstraint constraint : checkConstraints ) {
if ( constraint.isAnonymous() ) {
if ( !hasAnonymousConstraints ) {
buf.append( ", check (" );
hasAnonymousConstraints = true;
}
else {
buf.append( " and " );
}
buf.append( constraint.getConstraintInParens() );
}
if ( !first ) {
buf.append( ")" );
}
if ( hasAnonymousConstraints ) {
buf.append( ')' );
}
}
else {
hasAnonymousConstraints = checkConstraints.stream().anyMatch( CheckConstraint::isAnonymous );
}

// Since some databases don't like when multiple check clauses appear for a colum definition,
// named constraints need to be hoisted to the table definition.
// Skip the first named constraint if the column has no anonymous constraints and the dialect
// supports named column check constraints, because ColumnDefinitions will render the first check
// constraint already.
boolean skipNextNamedConstraint = !hasAnonymousConstraints && dialect.supportsNamedColumnCheck();
for ( CheckConstraint constraint : checkConstraints ) {
if ( constraint.isNamed() ) {
if ( skipNextNamedConstraint ) {
skipNextNamedConstraint = false;
}
for ( CheckConstraint constraint : checkConstraints ) {
if ( constraint.isNamed() ) {
buf.append( constraint.constraintString( dialect ) );
}
else {
buf.append( ',' ).append( constraint.constraintString( dialect ) );
}
}
}
Expand Down