From b7f34795df817055080126b19e75bf862cad6ff6 Mon Sep 17 00:00:00 2001 From: Gavin Date: Mon, 2 Jan 2023 20:31:02 +0100 Subject: [PATCH] fix for databases which don't like multiple 'check' keywords - also check for dupe constraints (for some reason they get added) --- .../hibernate/mapping/CheckConstraint.java | 31 ++++++++++++++++ .../java/org/hibernate/mapping/Column.java | 4 ++- .../schema/internal/ColumnDefinitions.java | 36 +++++++++++++++++-- 3 files changed, 67 insertions(+), 4 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/CheckConstraint.java b/hibernate-core/src/main/java/org/hibernate/mapping/CheckConstraint.java index a31ccc430e..10de5db9f2 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/CheckConstraint.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/CheckConstraint.java @@ -6,6 +6,8 @@ */ package org.hibernate.mapping; +import java.util.Objects; + /** * Represents a table or column level {@code check} constraint. * @@ -24,6 +26,14 @@ public class CheckConstraint { this.constraint = constraint; } + public boolean isNamed() { + return name != null; + } + + public boolean isAnonymous() { + return name == null; + } + public String getName() { return name; } @@ -36,6 +46,10 @@ public class CheckConstraint { return constraint; } + public String getConstraintInParens() { + return "(" + constraint + ")"; + } + public void setConstraint(String constraint) { this.constraint = constraint; } @@ -45,4 +59,21 @@ public class CheckConstraint { ? " check (" + constraint + ")" : " constraint " + name + " check (" + constraint + ")"; } + + @Override + public boolean equals(Object object) { + if ( object instanceof CheckConstraint ) { + CheckConstraint other = (CheckConstraint) object; + return Objects.equals( name, other.name ) + && Objects.equals( constraint, other.constraint ); + } + else { + return false; + } + } + + @Override + public int hashCode() { + return constraint.hashCode(); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java index 0af393d38c..e07df5bbd5 100644 --- a/hibernate-core/src/main/java/org/hibernate/mapping/Column.java +++ b/hibernate-core/src/main/java/org/hibernate/mapping/Column.java @@ -493,7 +493,9 @@ public class Column implements Selectable, Serializable, Cloneable, ColumnTypeIn } public void addCheckConstraint(CheckConstraint checkConstraint) { - this.checkConstraints.add( checkConstraint ); + if ( !checkConstraints.contains( checkConstraint) ) { + checkConstraints.add( checkConstraint ); + } } public java.util.List getCheckConstraints() { diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/ColumnDefinitions.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/ColumnDefinitions.java index c8c39676fd..a5e8abf0a1 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/ColumnDefinitions.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/ColumnDefinitions.java @@ -19,6 +19,8 @@ import org.hibernate.mapping.UniqueKey; import org.hibernate.tool.schema.extract.spi.ColumnInformation; import org.hibernate.type.descriptor.jdbc.JdbcType; +import java.util.List; + class ColumnDefinitions { static boolean hasMatchingType(Column column, ColumnInformation columnInformation, Metadata metadata, Dialect dialect) { @@ -97,13 +99,41 @@ class ColumnDefinitions { if ( column.isUnique() && !table.isPrimaryKey( column ) ) { final String keyName = Constraint.generateName( "UK_", table, column); final UniqueKey uniqueKey = table.getOrCreateUniqueKey( keyName ); - uniqueKey.addColumn(column); + uniqueKey.addColumn( column ); definition.append( dialect.getUniqueDelegate().getColumnDefinitionUniquenessFragment( column, context ) ); } if ( dialect.supportsColumnCheck() ) { - for ( CheckConstraint checkConstraint : column.getCheckConstraints() ) { - definition.append( checkConstraint.constraintString() ); + // some databases (Maria, SQL Server) don't like multiple 'check' clauses + final List checkConstraints = column.getCheckConstraints(); + long anonConstraints = checkConstraints.stream().filter(CheckConstraint::isAnonymous).count(); + if ( anonConstraints == 1 ) { + for ( CheckConstraint constraint : checkConstraints ) { + definition.append( constraint.constraintString() ); + } + } + else { + boolean first = true; + for ( CheckConstraint constraint : checkConstraints ) { + if ( constraint.isAnonymous() ) { + if ( first ) { + definition.append(" check ("); + first = false; + } + else { + definition.append(" and "); + } + definition.append( constraint.getConstraintInParens() ); + } + } + if ( !first ) { + definition.append(")"); + } + for ( CheckConstraint constraint : checkConstraints ) { + if ( constraint.isNamed() ) { + definition.append( constraint.constraintString() ); + } + } } } }