HHH-8149 Revert HHH-7797 in 4.1.x
This commit is contained in:
parent
5dd220393c
commit
40aaaa9ca7
|
@ -50,7 +50,6 @@ import java.util.StringTokenizer;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
|
|
||||||
import javax.persistence.Embeddable;
|
import javax.persistence.Embeddable;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.MapsId;
|
import javax.persistence.MapsId;
|
||||||
|
@ -59,6 +58,10 @@ import org.dom4j.Attribute;
|
||||||
import org.dom4j.Document;
|
import org.dom4j.Document;
|
||||||
import org.dom4j.DocumentException;
|
import org.dom4j.DocumentException;
|
||||||
import org.dom4j.Element;
|
import org.dom4j.Element;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
import org.xml.sax.EntityResolver;
|
||||||
|
import org.xml.sax.InputSource;
|
||||||
|
|
||||||
import org.hibernate.AnnotationException;
|
import org.hibernate.AnnotationException;
|
||||||
import org.hibernate.DuplicateMappingException;
|
import org.hibernate.DuplicateMappingException;
|
||||||
import org.hibernate.EmptyInterceptor;
|
import org.hibernate.EmptyInterceptor;
|
||||||
|
@ -142,9 +145,6 @@ import org.hibernate.type.Type;
|
||||||
import org.hibernate.type.TypeResolver;
|
import org.hibernate.type.TypeResolver;
|
||||||
import org.hibernate.usertype.CompositeUserType;
|
import org.hibernate.usertype.CompositeUserType;
|
||||||
import org.hibernate.usertype.UserType;
|
import org.hibernate.usertype.UserType;
|
||||||
import org.jboss.logging.Logger;
|
|
||||||
import org.xml.sax.EntityResolver;
|
|
||||||
import org.xml.sax.InputSource;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance of <tt>Configuration</tt> allows the application
|
* An instance of <tt>Configuration</tt> allows the application
|
||||||
|
@ -1045,15 +1045,17 @@ public class Configuration implements Serializable {
|
||||||
Table table = (Table) iter.next();
|
Table table = (Table) iter.next();
|
||||||
if ( table.isPhysicalTable() ) {
|
if ( table.isPhysicalTable() ) {
|
||||||
|
|
||||||
Iterator subIter = table.getUniqueKeyIterator();
|
if ( !dialect.supportsUniqueConstraintInCreateAlterTable() ) {
|
||||||
while ( subIter.hasNext() ) {
|
Iterator subIter = table.getUniqueKeyIterator();
|
||||||
UniqueKey uk = (UniqueKey) subIter.next();
|
while ( subIter.hasNext() ) {
|
||||||
String constraintString = uk.sqlCreateString( dialect, mapping, defaultCatalog, defaultSchema );
|
UniqueKey uk = (UniqueKey) subIter.next();
|
||||||
if (constraintString != null) script.add( constraintString );
|
String constraintString = uk.sqlCreateString( dialect, mapping, defaultCatalog, defaultSchema );
|
||||||
|
if (constraintString != null) script.add( constraintString );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
subIter = table.getIndexIterator();
|
Iterator subIter = table.getIndexIterator();
|
||||||
while ( subIter.hasNext() ) {
|
while ( subIter.hasNext() ) {
|
||||||
Index index = (Index) subIter.next();
|
Index index = (Index) subIter.next();
|
||||||
script.add(
|
script.add(
|
||||||
|
@ -1224,6 +1226,15 @@ public class Configuration implements Serializable {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//broken, 'cos we don't generate these with names in SchemaExport
|
||||||
|
// subIter = table.getUniqueKeyIterator();
|
||||||
|
// while ( subIter.hasNext() ) {
|
||||||
|
// UniqueKey uk = (UniqueKey) subIter.next();
|
||||||
|
// if ( tableInfo==null || tableInfo.getIndexMetadata( uk.getFilterName() ) == null ) {
|
||||||
|
// script.add( uk.sqlCreateString(dialect, mapping) );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1531,6 +1542,7 @@ public class Configuration implements Serializable {
|
||||||
private void buildUniqueKeyFromColumnNames(Table table, String keyName, String[] columnNames) {
|
private void buildUniqueKeyFromColumnNames(Table table, String keyName, String[] columnNames) {
|
||||||
keyName = normalizer.normalizeIdentifierQuoting( keyName );
|
keyName = normalizer.normalizeIdentifierQuoting( keyName );
|
||||||
|
|
||||||
|
UniqueKey uc;
|
||||||
int size = columnNames.length;
|
int size = columnNames.length;
|
||||||
Column[] columns = new Column[size];
|
Column[] columns = new Column[size];
|
||||||
Set<Column> unbound = new HashSet<Column>();
|
Set<Column> unbound = new HashSet<Column>();
|
||||||
|
@ -1547,10 +1559,10 @@ public class Configuration implements Serializable {
|
||||||
unboundNoLogical.add( new Column( column ) );
|
unboundNoLogical.add( new Column( column ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
UniqueKey uk = table.getOrCreateUniqueKey( keyName );
|
|
||||||
for ( Column column : columns ) {
|
for ( Column column : columns ) {
|
||||||
if ( table.containsColumn( column ) ) {
|
if ( table.containsColumn( column ) ) {
|
||||||
uk.addColumn( column );
|
uc = table.getOrCreateUniqueKey( keyName );
|
||||||
|
uc.addColumn( table.getColumn( column ) );
|
||||||
unbound.remove( column );
|
unbound.remove( column );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -401,6 +401,11 @@ public class Cache71Dialect extends Dialect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportsUnique() {
|
||||||
|
// Does this dialect support the UNIQUE column syntax?
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The syntax used to add a foreign key constraint to a table.
|
* The syntax used to add a foreign key constraint to a table.
|
||||||
*
|
*
|
||||||
|
|
|
@ -30,13 +30,12 @@ import java.sql.Types;
|
||||||
|
|
||||||
import org.hibernate.JDBCException;
|
import org.hibernate.JDBCException;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
|
import org.hibernate.dialect.function.AnsiTrimEmulationFunction;
|
||||||
import org.hibernate.dialect.function.AvgWithArgumentCastFunction;
|
import org.hibernate.dialect.function.AvgWithArgumentCastFunction;
|
||||||
import org.hibernate.dialect.function.NoArgSQLFunction;
|
import org.hibernate.dialect.function.NoArgSQLFunction;
|
||||||
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
import org.hibernate.dialect.function.SQLFunctionTemplate;
|
||||||
import org.hibernate.dialect.function.StandardSQLFunction;
|
import org.hibernate.dialect.function.StandardSQLFunction;
|
||||||
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
import org.hibernate.dialect.function.VarArgsSQLFunction;
|
||||||
import org.hibernate.dialect.unique.DB2UniqueDelegate;
|
|
||||||
import org.hibernate.dialect.unique.UniqueDelegate;
|
|
||||||
import org.hibernate.exception.LockTimeoutException;
|
import org.hibernate.exception.LockTimeoutException;
|
||||||
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
import org.hibernate.exception.spi.SQLExceptionConversionDelegate;
|
||||||
import org.hibernate.internal.util.JdbcExceptionHelper;
|
import org.hibernate.internal.util.JdbcExceptionHelper;
|
||||||
|
@ -50,8 +49,6 @@ import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
|
||||||
* @author Gavin King
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class DB2Dialect extends Dialect {
|
public class DB2Dialect extends Dialect {
|
||||||
|
|
||||||
private final UniqueDelegate uniqueDelegate;
|
|
||||||
|
|
||||||
public DB2Dialect() {
|
public DB2Dialect() {
|
||||||
super();
|
super();
|
||||||
|
@ -178,8 +175,6 @@ public class DB2Dialect extends Dialect {
|
||||||
registerKeyword( "only" );
|
registerKeyword( "only" );
|
||||||
|
|
||||||
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH );
|
getDefaultProperties().setProperty( Environment.STATEMENT_BATCH_SIZE, NO_BATCH );
|
||||||
|
|
||||||
uniqueDelegate = new DB2UniqueDelegate( this );
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String getLowercaseFunction() {
|
public String getLowercaseFunction() {
|
||||||
|
@ -284,6 +279,10 @@ public class DB2Dialect extends Dialect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
|
public boolean supportsNotNullUnique() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
public boolean supportsExistsInSelect() {
|
public boolean supportsExistsInSelect() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -458,11 +457,6 @@ public class DB2Dialect extends Dialect {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public UniqueDelegate getUniqueDelegate() {
|
|
||||||
return uniqueDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getNotExpression( String expression ) {
|
public String getNotExpression( String expression ) {
|
||||||
return "not (" + expression + ")";
|
return "not (" + expression + ")";
|
||||||
|
|
|
@ -58,8 +58,6 @@ import org.hibernate.dialect.lock.PessimisticWriteSelectLockingStrategy;
|
||||||
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
import org.hibernate.dialect.lock.SelectLockingStrategy;
|
||||||
import org.hibernate.dialect.pagination.LegacyLimitHandler;
|
import org.hibernate.dialect.pagination.LegacyLimitHandler;
|
||||||
import org.hibernate.dialect.pagination.LimitHandler;
|
import org.hibernate.dialect.pagination.LimitHandler;
|
||||||
import org.hibernate.dialect.unique.DefaultUniqueDelegate;
|
|
||||||
import org.hibernate.dialect.unique.UniqueDelegate;
|
|
||||||
import org.hibernate.engine.jdbc.LobCreator;
|
import org.hibernate.engine.jdbc.LobCreator;
|
||||||
import org.hibernate.engine.spi.RowSelection;
|
import org.hibernate.engine.spi.RowSelection;
|
||||||
import org.hibernate.engine.spi.SessionImplementor;
|
import org.hibernate.engine.spi.SessionImplementor;
|
||||||
|
@ -117,8 +115,6 @@ public abstract class Dialect implements ConversionContext {
|
||||||
private final Properties properties = new Properties();
|
private final Properties properties = new Properties();
|
||||||
private final Map<String, SQLFunction> sqlFunctions = new HashMap<String, SQLFunction>();
|
private final Map<String, SQLFunction> sqlFunctions = new HashMap<String, SQLFunction>();
|
||||||
private final Set<String> sqlKeywords = new HashSet<String>();
|
private final Set<String> sqlKeywords = new HashSet<String>();
|
||||||
|
|
||||||
private final UniqueDelegate uniqueDelegate;
|
|
||||||
|
|
||||||
|
|
||||||
// constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// constructors and factory methods ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -207,8 +203,6 @@ public abstract class Dialect implements ConversionContext {
|
||||||
registerHibernateType( Types.BLOB, StandardBasicTypes.BLOB.getName() );
|
registerHibernateType( Types.BLOB, StandardBasicTypes.BLOB.getName() );
|
||||||
registerHibernateType( Types.CLOB, StandardBasicTypes.CLOB.getName() );
|
registerHibernateType( Types.CLOB, StandardBasicTypes.CLOB.getName() );
|
||||||
registerHibernateType( Types.REAL, StandardBasicTypes.FLOAT.getName() );
|
registerHibernateType( Types.REAL, StandardBasicTypes.FLOAT.getName() );
|
||||||
|
|
||||||
uniqueDelegate = new DefaultUniqueDelegate( this );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1834,6 +1828,23 @@ public abstract class Dialect implements ConversionContext {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this dialect support the <tt>UNIQUE</tt> column syntax?
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean supportsUnique() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does this dialect support adding Unique constraints via create and alter table ?
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public boolean supportsUniqueConstraintInCreateAlterTable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The syntax used to add a column to a table (optional).
|
* The syntax used to add a column to a table (optional).
|
||||||
*
|
*
|
||||||
|
@ -1899,6 +1910,16 @@ public abstract class Dialect implements ConversionContext {
|
||||||
return " add constraint " + constraintName + " primary key ";
|
return " add constraint " + constraintName + " primary key ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The syntax used to add a unique constraint to a table.
|
||||||
|
*
|
||||||
|
* @param constraintName The name of the unique constraint.
|
||||||
|
* @return The "add unique" fragment
|
||||||
|
*/
|
||||||
|
public String getAddUniqueConstraintString(String constraintName) {
|
||||||
|
return " add constraint " + constraintName + " unique ";
|
||||||
|
}
|
||||||
|
|
||||||
public boolean hasSelfReferentialForeignKeyBug() {
|
public boolean hasSelfReferentialForeignKeyBug() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1968,6 +1989,10 @@ public abstract class Dialect implements ConversionContext {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportsNotNullUnique() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completely optional cascading drop clause
|
* Completely optional cascading drop clause
|
||||||
*
|
*
|
||||||
|
@ -2320,56 +2345,7 @@ public abstract class Dialect implements ConversionContext {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UniqueDelegate getUniqueDelegate() {
|
|
||||||
return uniqueDelegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNotExpression( String expression ) {
|
public String getNotExpression( String expression ) {
|
||||||
return "not " + expression;
|
return "not " + expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Does this dialect support the <tt>UNIQUE</tt> column syntax?
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @deprecated {@link #getUniqueDelegate()} should be overridden instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public boolean supportsUnique() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Does this dialect support adding Unique constraints via create and alter table ?
|
|
||||||
*
|
|
||||||
* @return boolean
|
|
||||||
*
|
|
||||||
* @deprecated {@link #getUniqueDelegate()} should be overridden instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public boolean supportsUniqueConstraintInCreateAlterTable() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The syntax used to add a unique constraint to a table.
|
|
||||||
*
|
|
||||||
* @param constraintName The name of the unique constraint.
|
|
||||||
* @return The "add unique" fragment
|
|
||||||
*
|
|
||||||
* @deprecated {@link #getUniqueDelegate()} should be overridden instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public String getAddUniqueConstraintString(String constraintName) {
|
|
||||||
return " add constraint " + constraintName + " unique ";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated {@link #getUniqueDelegate()} should be overridden instead.
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public boolean supportsNotNullUnique() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -216,6 +216,10 @@ public class H2Dialect extends Dialect {
|
||||||
return " for update";
|
return " for update";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportsUnique() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean supportsLimit() {
|
public boolean supportsLimit() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,6 +246,10 @@ public class HSQLDialect extends Dialect {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportsUnique() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean supportsLimit() {
|
public boolean supportsLimit() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,6 +306,13 @@ public class IngresDialect extends Dialect {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ingres explicitly needs "unique not null", because "with null" is default
|
||||||
|
*/
|
||||||
|
public boolean supportsNotNullUnique() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does this dialect support temporary tables?
|
* Does this dialect support temporary tables?
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -240,6 +240,13 @@ public class RDMSOS2200Dialect extends Dialect {
|
||||||
return ""; // Original Dialect.java returns " for update";
|
return ""; // Original Dialect.java returns " for update";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RDMS does not support adding Unique constraints via create and alter table.
|
||||||
|
*/
|
||||||
|
public boolean supportsUniqueConstraintInCreateAlterTable() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
// Verify the state of this new method in Hibernate 3.0 Dialect.java
|
// Verify the state of this new method in Hibernate 3.0 Dialect.java
|
||||||
/**
|
/**
|
||||||
* RDMS does not support Cascade Deletes.
|
* RDMS does not support Cascade Deletes.
|
||||||
|
|
|
@ -422,6 +422,10 @@ public class SybaseASE15Dialect extends SybaseDialect {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportsUniqueConstraintInCreateAlterTable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public String getCrossJoinSeparator() {
|
public String getCrossJoinSeparator() {
|
||||||
return ", ";
|
return ", ";
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,14 @@ public class TimesTenDialect extends Dialect {
|
||||||
public boolean qualifyIndexName() {
|
public boolean qualifyIndexName() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean supportsUnique() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsUniqueConstraintInCreateAlterTable() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public String getAddColumnString() {
|
public String getAddColumnString() {
|
||||||
return "add";
|
return "add";
|
||||||
|
|
|
@ -1,109 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* JBoss, Home of Professional Open Source
|
|
||||||
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
|
|
||||||
* as indicated by the @authors tag. All rights reserved.
|
|
||||||
* See the copyright.txt in the distribution for a
|
|
||||||
* full listing of individual contributors.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU Lesser General Public License, v. 2.1.
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT A
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License,
|
|
||||||
* v.2.1 along with this distribution; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
package org.hibernate.dialect.unique;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
|
||||||
import org.hibernate.metamodel.relational.Column;
|
|
||||||
import org.hibernate.metamodel.relational.Index;
|
|
||||||
import org.hibernate.metamodel.relational.UniqueKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* DB2 does not allow unique constraints on nullable columns. Rather than
|
|
||||||
* forcing "not null", use unique *indexes* instead.
|
|
||||||
*
|
|
||||||
* @author Brett Meyer
|
|
||||||
*/
|
|
||||||
public class DB2UniqueDelegate extends DefaultUniqueDelegate {
|
|
||||||
|
|
||||||
public DB2UniqueDelegate( Dialect dialect ) {
|
|
||||||
super( dialect );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String applyUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
|
|
||||||
String defaultCatalog, String defaultSchema ) {
|
|
||||||
if ( hasNullable( uniqueKey ) ) {
|
|
||||||
return org.hibernate.mapping.Index.buildSqlCreateIndexString(
|
|
||||||
dialect, uniqueKey.getName(), uniqueKey.getTable(),
|
|
||||||
uniqueKey.columnIterator(), true, defaultCatalog,
|
|
||||||
defaultSchema );
|
|
||||||
} else {
|
|
||||||
return super.applyUniquesOnAlter(
|
|
||||||
uniqueKey, defaultCatalog, defaultSchema );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String applyUniquesOnAlter( UniqueKey uniqueKey ) {
|
|
||||||
if ( hasNullable( uniqueKey ) ) {
|
|
||||||
return Index.buildSqlCreateIndexString(
|
|
||||||
dialect, uniqueKey.getName(), uniqueKey.getTable(),
|
|
||||||
uniqueKey.getColumns(), true );
|
|
||||||
} else {
|
|
||||||
return super.applyUniquesOnAlter( uniqueKey );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String dropUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
|
|
||||||
String defaultCatalog, String defaultSchema ) {
|
|
||||||
if ( hasNullable( uniqueKey ) ) {
|
|
||||||
return org.hibernate.mapping.Index.buildSqlDropIndexString(
|
|
||||||
dialect, uniqueKey.getTable(), uniqueKey.getName(),
|
|
||||||
defaultCatalog, defaultSchema );
|
|
||||||
} else {
|
|
||||||
return super.dropUniquesOnAlter(
|
|
||||||
uniqueKey, defaultCatalog, defaultSchema );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String dropUniquesOnAlter( UniqueKey uniqueKey ) {
|
|
||||||
if ( hasNullable( uniqueKey ) ) {
|
|
||||||
return Index.buildSqlDropIndexString(
|
|
||||||
dialect, uniqueKey.getTable(), uniqueKey.getName() );
|
|
||||||
} else {
|
|
||||||
return super.dropUniquesOnAlter( uniqueKey );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasNullable( org.hibernate.mapping.UniqueKey uniqueKey ) {
|
|
||||||
Iterator iter = uniqueKey.getColumnIterator();
|
|
||||||
while ( iter.hasNext() ) {
|
|
||||||
if ( ( ( org.hibernate.mapping.Column ) iter.next() ).isNullable() ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean hasNullable( UniqueKey uniqueKey ) {
|
|
||||||
Iterator iter = uniqueKey.getColumns().iterator();
|
|
||||||
while ( iter.hasNext() ) {
|
|
||||||
if ( ( ( Column ) iter.next() ).isNullable() ) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,148 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* JBoss, Home of Professional Open Source
|
|
||||||
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
|
|
||||||
* as indicated by the @authors tag. All rights reserved.
|
|
||||||
* See the copyright.txt in the distribution for a
|
|
||||||
* full listing of individual contributors.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU Lesser General Public License, v. 2.1.
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT A
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License,
|
|
||||||
* v.2.1 along with this distribution; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
package org.hibernate.dialect.unique;
|
|
||||||
|
|
||||||
import java.util.Iterator;
|
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
|
||||||
import org.hibernate.metamodel.relational.Column;
|
|
||||||
import org.hibernate.metamodel.relational.Table;
|
|
||||||
import org.hibernate.metamodel.relational.UniqueKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default UniqueDelegate implementation for most dialects. Uses
|
|
||||||
* separate create/alter statements to apply uniqueness to a column.
|
|
||||||
*
|
|
||||||
* @author Brett Meyer
|
|
||||||
*/
|
|
||||||
public class DefaultUniqueDelegate implements UniqueDelegate {
|
|
||||||
|
|
||||||
protected final Dialect dialect;
|
|
||||||
|
|
||||||
public DefaultUniqueDelegate( Dialect dialect ) {
|
|
||||||
this.dialect = dialect;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String applyUniqueToColumn( org.hibernate.mapping.Column column ) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String applyUniqueToColumn( Column column ) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String applyUniquesToTable( org.hibernate.mapping.Table table ) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String applyUniquesToTable( Table table ) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String applyUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
|
|
||||||
String defaultCatalog, String defaultSchema ) {
|
|
||||||
// Do this here, rather than allowing UniqueKey/Constraint to do it.
|
|
||||||
// We need full, simplified control over whether or not it happens.
|
|
||||||
return new StringBuilder( "alter table " )
|
|
||||||
.append( uniqueKey.getTable().getQualifiedName(
|
|
||||||
dialect, defaultCatalog, defaultSchema ) )
|
|
||||||
.append( " add constraint " )
|
|
||||||
.append( uniqueKey.getName() )
|
|
||||||
.append( uniqueConstraintSql( uniqueKey ) )
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String applyUniquesOnAlter( UniqueKey uniqueKey ) {
|
|
||||||
// Do this here, rather than allowing UniqueKey/Constraint to do it.
|
|
||||||
// We need full, simplified control over whether or not it happens.
|
|
||||||
return new StringBuilder( "alter table " )
|
|
||||||
.append( uniqueKey.getTable().getQualifiedName( dialect ) )
|
|
||||||
.append( " add constraint " )
|
|
||||||
.append( uniqueKey.getName() )
|
|
||||||
.append( uniqueConstraintSql( uniqueKey ) )
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String dropUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
|
|
||||||
String defaultCatalog, String defaultSchema ) {
|
|
||||||
// Do this here, rather than allowing UniqueKey/Constraint to do it.
|
|
||||||
// We need full, simplified control over whether or not it happens.
|
|
||||||
return new StringBuilder( "alter table " )
|
|
||||||
.append( uniqueKey.getTable().getQualifiedName(
|
|
||||||
dialect, defaultCatalog, defaultSchema ) )
|
|
||||||
.append( " drop constraint " )
|
|
||||||
.append( dialect.quote( uniqueKey.getName() ) )
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String dropUniquesOnAlter( UniqueKey uniqueKey ) {
|
|
||||||
// Do this here, rather than allowing UniqueKey/Constraint to do it.
|
|
||||||
// We need full, simplified control over whether or not it happens.
|
|
||||||
return new StringBuilder( "alter table " )
|
|
||||||
.append( uniqueKey.getTable().getQualifiedName( dialect ) )
|
|
||||||
.append( " drop constraint " )
|
|
||||||
.append( dialect.quote( uniqueKey.getName() ) )
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String uniqueConstraintSql( org.hibernate.mapping.UniqueKey uniqueKey ) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append( " unique (" );
|
|
||||||
Iterator columnIterator = uniqueKey.getColumnIterator();
|
|
||||||
while ( columnIterator.hasNext() ) {
|
|
||||||
org.hibernate.mapping.Column column
|
|
||||||
= (org.hibernate.mapping.Column) columnIterator.next();
|
|
||||||
sb.append( column.getQuotedName( dialect ) );
|
|
||||||
if ( columnIterator.hasNext() ) {
|
|
||||||
sb.append( ", " );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.append( ')' ).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String uniqueConstraintSql( UniqueKey uniqueKey ) {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
sb.append( " unique (" );
|
|
||||||
Iterator columnIterator = uniqueKey.getColumns().iterator();
|
|
||||||
while ( columnIterator.hasNext() ) {
|
|
||||||
org.hibernate.mapping.Column column
|
|
||||||
= (org.hibernate.mapping.Column) columnIterator.next();
|
|
||||||
sb.append( column.getQuotedName( dialect ) );
|
|
||||||
if ( columnIterator.hasNext() ) {
|
|
||||||
sb.append( ", " );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.append( ')' ).toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,146 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* JBoss, Home of Professional Open Source
|
|
||||||
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
|
|
||||||
* as indicated by the @authors tag. All rights reserved.
|
|
||||||
* See the copyright.txt in the distribution for a
|
|
||||||
* full listing of individual contributors.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU Lesser General Public License, v. 2.1.
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT A
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License,
|
|
||||||
* v.2.1 along with this distribution; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
package org.hibernate.dialect.unique;
|
|
||||||
|
|
||||||
import org.hibernate.metamodel.relational.Column;
|
|
||||||
import org.hibernate.metamodel.relational.Table;
|
|
||||||
import org.hibernate.metamodel.relational.UniqueKey;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dialect-level delegate in charge of applying "uniqueness" to a column.
|
|
||||||
* Uniqueness can be defined in 1 of 3 ways:
|
|
||||||
*
|
|
||||||
* 1.) Add a unique constraint via separate alter table statements.
|
|
||||||
* 2.) Add a unique constraint via dialect-specific syntax in table create statement.
|
|
||||||
* 3.) Add "unique" syntax to the column itself.
|
|
||||||
*
|
|
||||||
* #1 & #2 are preferred, if possible -- #3 should be solely a fall-back.
|
|
||||||
*
|
|
||||||
* TODO: This could eventually be simplified. With AST, 1 "applyUniqueness"
|
|
||||||
* method might be possible. But due to .cfg and .mapping still resolving
|
|
||||||
* around StringBuilders, separate methods were needed.
|
|
||||||
*
|
|
||||||
* See HHH-7797.
|
|
||||||
*
|
|
||||||
* @author Brett Meyer
|
|
||||||
*/
|
|
||||||
public interface UniqueDelegate {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the dialect does not supports unique constraints, this method should
|
|
||||||
* return the syntax necessary to mutate the column definition
|
|
||||||
* (usually "unique").
|
|
||||||
*
|
|
||||||
* @param column
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String applyUniqueToColumn( org.hibernate.mapping.Column column );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If the dialect does not supports unique constraints, this method should
|
|
||||||
* return the syntax necessary to mutate the column definition
|
|
||||||
* (usually "unique").
|
|
||||||
*
|
|
||||||
* @param column
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String applyUniqueToColumn( Column column );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If constraints are supported, but not in seperate alter statements,
|
|
||||||
* return uniqueConstraintSql in order to add the constraint to the
|
|
||||||
* original table definition.
|
|
||||||
*
|
|
||||||
* @param table
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String applyUniquesToTable( org.hibernate.mapping.Table table );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If constraints are supported, but not in seperate alter statements,
|
|
||||||
* return uniqueConstraintSql in order to add the constraint to the
|
|
||||||
* original table definition.
|
|
||||||
*
|
|
||||||
* @param table
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String applyUniquesToTable( Table table );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If creating unique constraints in separate alter statements is
|
|
||||||
* supported, generate the necessary "alter" syntax for the given key.
|
|
||||||
*
|
|
||||||
* @param uniqueKey
|
|
||||||
* @param defaultCatalog
|
|
||||||
* @param defaultSchema
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String applyUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
|
|
||||||
String defaultCatalog, String defaultSchema );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If creating unique constraints in separate alter statements is
|
|
||||||
* supported, generate the necessary "alter" syntax for the given key.
|
|
||||||
*
|
|
||||||
* @param uniqueKey
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String applyUniquesOnAlter( UniqueKey uniqueKey );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If dropping unique constraints in separate alter statements is
|
|
||||||
* supported, generate the necessary "alter" syntax for the given key.
|
|
||||||
*
|
|
||||||
* @param uniqueKey
|
|
||||||
* @param defaultCatalog
|
|
||||||
* @param defaultSchema
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String dropUniquesOnAlter( org.hibernate.mapping.UniqueKey uniqueKey,
|
|
||||||
String defaultCatalog, String defaultSchema );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If dropping unique constraints in separate alter statements is
|
|
||||||
* supported, generate the necessary "alter" syntax for the given key.
|
|
||||||
*
|
|
||||||
* @param uniqueKey
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String dropUniquesOnAlter( UniqueKey uniqueKey );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the syntax necessary to create the unique constraint (reused
|
|
||||||
* by all methods). Ex: "unique (column1, column2, ...)"
|
|
||||||
*
|
|
||||||
* @param uniqueKey
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String uniqueConstraintSql( org.hibernate.mapping.UniqueKey uniqueKey );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generates the syntax necessary to create the unique constraint (reused
|
|
||||||
* by all methods). Ex: "unique (column1, column2, ...)"
|
|
||||||
*
|
|
||||||
* @param uniqueKey
|
|
||||||
* @return String
|
|
||||||
*/
|
|
||||||
public String uniqueConstraintSql( UniqueKey uniqueKey );
|
|
||||||
}
|
|
|
@ -79,6 +79,7 @@ public class Index implements RelationalModel, Serializable {
|
||||||
String defaultCatalog,
|
String defaultCatalog,
|
||||||
String defaultSchema
|
String defaultSchema
|
||||||
) {
|
) {
|
||||||
|
//TODO handle supportsNotNullUnique=false, but such a case does not exist in the wild so far
|
||||||
StringBuilder buf = new StringBuilder( "create" )
|
StringBuilder buf = new StringBuilder( "create" )
|
||||||
.append( unique ?
|
.append( unique ?
|
||||||
" unique" :
|
" unique" :
|
||||||
|
|
|
@ -26,6 +26,7 @@ package org.hibernate.mapping;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
|
@ -422,13 +423,11 @@ public class Table implements RelationalModel, Serializable {
|
||||||
alter.append( " not null" );
|
alter.append( " not null" );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( column.isUnique() ) {
|
boolean useUniqueConstraint = column.isUnique() &&
|
||||||
uniqueIndexInteger++;
|
dialect.supportsUnique() &&
|
||||||
UniqueKey uk = getOrCreateUniqueKey(
|
( column.isNullable() || dialect.supportsNotNullUnique() );
|
||||||
"UK_" + name + "_" + uniqueIndexInteger);
|
if ( useUniqueConstraint ) {
|
||||||
uk.addColumn( column );
|
alter.append( " unique" );
|
||||||
alter.append( dialect.getUniqueDelegate()
|
|
||||||
.applyUniqueToColumn( column ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( column.hasCheckConstraint() && dialect.supportsColumnCheck() ) {
|
if ( column.hasCheckConstraint() && dialect.supportsColumnCheck() ) {
|
||||||
|
@ -526,16 +525,20 @@ public class Table implements RelationalModel, Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( col.isUnique() ) {
|
boolean useUniqueConstraint = col.isUnique() &&
|
||||||
uniqueIndexInteger++;
|
( col.isNullable() || dialect.supportsNotNullUnique() );
|
||||||
UniqueKey uk = getOrCreateUniqueKey(
|
if ( useUniqueConstraint ) {
|
||||||
"uc_" + name + "_" + uniqueIndexInteger);
|
if ( dialect.supportsUnique() ) {
|
||||||
uk.addColumn( col );
|
buf.append( " unique" );
|
||||||
buf.append( dialect.getUniqueDelegate()
|
}
|
||||||
.applyUniqueToColumn( col ) );
|
else {
|
||||||
|
UniqueKey uk = getOrCreateUniqueKey(
|
||||||
|
"UK_" + name + '_' + uniqueIndexInteger );
|
||||||
|
uk.addColumn( col );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( col.hasCheckConstraint() && dialect.supportsColumnCheck() ) {
|
if ( col.hasCheckConstraint() && dialect.supportsColumnCheck() ) {
|
||||||
buf.append( " check (" )
|
buf.append( " check (" )
|
||||||
.append( col.getCheckConstraint() )
|
.append( col.getCheckConstraint() )
|
||||||
|
@ -557,7 +560,21 @@ public class Table implements RelationalModel, Serializable {
|
||||||
.append( getPrimaryKey().sqlConstraintString( dialect ) );
|
.append( getPrimaryKey().sqlConstraintString( dialect ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append( dialect.getUniqueDelegate().applyUniquesToTable( this ) );
|
if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) {
|
||||||
|
Iterator ukiter = getUniqueKeyIterator();
|
||||||
|
while ( ukiter.hasNext() ) {
|
||||||
|
UniqueKey uk = (UniqueKey) ukiter.next();
|
||||||
|
String constraint = uk.sqlConstraintString( dialect );
|
||||||
|
if ( constraint != null ) {
|
||||||
|
buf.append( ", " ).append( constraint );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*Iterator idxiter = getIndexIterator();
|
||||||
|
while ( idxiter.hasNext() ) {
|
||||||
|
Index idx = (Index) idxiter.next();
|
||||||
|
buf.append(',').append( idx.sqlConstraintString(dialect) );
|
||||||
|
}*/
|
||||||
|
|
||||||
if ( dialect.supportsTableCheck() ) {
|
if ( dialect.supportsTableCheck() ) {
|
||||||
Iterator chiter = checkConstraints.iterator();
|
Iterator chiter = checkConstraints.iterator();
|
||||||
|
|
|
@ -22,39 +22,89 @@
|
||||||
* Boston, MA 02110-1301 USA
|
* Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
package org.hibernate.mapping;
|
package org.hibernate.mapping;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
import org.hibernate.dialect.Dialect;
|
import org.hibernate.dialect.Dialect;
|
||||||
import org.hibernate.engine.spi.Mapping;
|
import org.hibernate.engine.spi.Mapping;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A relational unique key constraint
|
* A relational unique key constraint
|
||||||
*
|
*
|
||||||
* @author Brett Meyer
|
* @author Gavin King
|
||||||
*/
|
*/
|
||||||
public class UniqueKey extends Constraint {
|
public class UniqueKey extends Constraint {
|
||||||
|
|
||||||
|
public String sqlConstraintString(Dialect dialect) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String sqlConstraintString(
|
public String sqlConstraintString(
|
||||||
Dialect dialect,
|
Dialect dialect,
|
||||||
String constraintName,
|
String constraintName,
|
||||||
String defaultCatalog,
|
String defaultCatalog,
|
||||||
String defaultSchema) {
|
String defaultSchema) {
|
||||||
// return dialect.getUniqueDelegate().uniqueConstraintSql( this );
|
StringBuilder buf = new StringBuilder(
|
||||||
// Not used.
|
dialect.getAddUniqueConstraintString( constraintName )
|
||||||
return "";
|
).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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String sqlCreateString(Dialect dialect, Mapping p,
|
public String sqlCreateString(Dialect dialect, Mapping p, String defaultCatalog, String defaultSchema) {
|
||||||
String defaultCatalog, String defaultSchema) {
|
if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) {
|
||||||
return dialect.getUniqueDelegate().applyUniquesOnAlter(
|
return super.sqlCreateString( dialect, p, defaultCatalog, defaultSchema );
|
||||||
this, defaultCatalog, defaultSchema );
|
}
|
||||||
|
else {
|
||||||
|
return Index.buildSqlCreateIndexString( dialect, getName(), getTable(), getColumnIterator(), true,
|
||||||
|
defaultCatalog, defaultSchema );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String sqlDropString(Dialect dialect, String defaultCatalog,
|
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
|
||||||
String defaultSchema) {
|
if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) {
|
||||||
return dialect.getUniqueDelegate().dropUniquesOnAlter(
|
return super.sqlDropString( dialect, defaultCatalog, defaultSchema );
|
||||||
this, defaultCatalog, defaultSchema );
|
}
|
||||||
|
else {
|
||||||
|
return Index.buildSqlDropIndexString( dialect, getTable(), getName(), defaultCatalog, defaultSchema );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isGenerated(Dialect dialect) {
|
||||||
|
if ( dialect.supportsNotNullUnique() ) return true;
|
||||||
|
Iterator iter = getColumnIterator();
|
||||||
|
while ( iter.hasNext() ) {
|
||||||
|
if ( ( (Column) iter.next() ).isNullable() ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,8 +115,10 @@ public class Database {
|
||||||
for ( Schema schema : schemaMap.values() ) {
|
for ( Schema schema : schemaMap.values() ) {
|
||||||
for ( Table table : schema.getTables() ) {
|
for ( Table table : schema.getTables() ) {
|
||||||
|
|
||||||
for ( UniqueKey uniqueKey : table.getUniqueKeys() ) {
|
if ( ! dialect.supportsUniqueConstraintInCreateAlterTable() ) {
|
||||||
addSqlCreateStrings( dialect, exportIdentifiers, script, uniqueKey );
|
for ( UniqueKey uniqueKey : table.getUniqueKeys() ) {
|
||||||
|
addSqlCreateStrings( dialect, exportIdentifiers, script, uniqueKey );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( Index index : table.getIndexes() ) {
|
for ( Index index : table.getIndexes() ) {
|
||||||
|
|
|
@ -63,6 +63,7 @@ public class Index extends AbstractConstraint implements Constraint {
|
||||||
Iterable<Column> columns,
|
Iterable<Column> columns,
|
||||||
boolean unique
|
boolean unique
|
||||||
) {
|
) {
|
||||||
|
//TODO handle supportsNotNullUnique=false, but such a case does not exist in the wild so far
|
||||||
StringBuilder buf = new StringBuilder( "create" )
|
StringBuilder buf = new StringBuilder( "create" )
|
||||||
.append( unique ?
|
.append( unique ?
|
||||||
" unique" :
|
" unique" :
|
||||||
|
@ -88,18 +89,6 @@ public class Index extends AbstractConstraint implements Constraint {
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String buildSqlDropIndexString(
|
|
||||||
Dialect dialect,
|
|
||||||
TableSpecification table,
|
|
||||||
String name
|
|
||||||
) {
|
|
||||||
return "drop index " +
|
|
||||||
StringHelper.qualify(
|
|
||||||
table.getQualifiedName( dialect ),
|
|
||||||
name
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String sqlConstraintStringInAlterTable(Dialect dialect) {
|
public String sqlConstraintStringInAlterTable(Dialect dialect) {
|
||||||
StringBuilder buf = new StringBuilder( " index (" );
|
StringBuilder buf = new StringBuilder( " index (" );
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
|
|
|
@ -199,12 +199,16 @@ public class Table extends AbstractTableSpecification implements Exportable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( col.isUnique() ) {
|
boolean useUniqueConstraint = col.isUnique() &&
|
||||||
UniqueKey uk = getOrCreateUniqueKey( col.getColumnName()
|
( col.isNullable() || dialect.supportsNotNullUnique() );
|
||||||
.encloseInQuotesIfQuoted( dialect ) + '_' );
|
if ( useUniqueConstraint ) {
|
||||||
uk.addColumn( col );
|
if ( dialect.supportsUnique() ) {
|
||||||
buf.append( dialect.getUniqueDelegate()
|
buf.append( " unique" );
|
||||||
.applyUniqueToColumn( col ) );
|
}
|
||||||
|
else {
|
||||||
|
UniqueKey uk = getOrCreateUniqueKey( col.getColumnName().encloseInQuotesIfQuoted( dialect ) + '_' );
|
||||||
|
uk.addColumn( col );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( col.getCheckCondition() != null && dialect.supportsColumnCheck() ) {
|
if ( col.getCheckCondition() != null && dialect.supportsColumnCheck() ) {
|
||||||
|
@ -223,7 +227,14 @@ public class Table extends AbstractTableSpecification implements Exportable {
|
||||||
.append( getPrimaryKey().sqlConstraintStringInCreateTable( dialect ) );
|
.append( getPrimaryKey().sqlConstraintStringInCreateTable( dialect ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
buf.append( dialect.getUniqueDelegate().applyUniquesToTable( this ) );
|
if ( dialect.supportsUniqueConstraintInCreateAlterTable() ) {
|
||||||
|
for ( UniqueKey uk : uniqueKeys.values() ) {
|
||||||
|
String constraint = uk.sqlConstraintStringInCreateTable( dialect );
|
||||||
|
if ( constraint != null ) {
|
||||||
|
buf.append( ", " ).append( constraint );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ( dialect.supportsTableCheck() ) {
|
if ( dialect.supportsTableCheck() ) {
|
||||||
for ( CheckConstraint checkConstraint : checkConstraints ) {
|
for ( CheckConstraint checkConstraint : checkConstraints ) {
|
||||||
|
|
|
@ -48,20 +48,60 @@ public class UniqueKey extends AbstractConstraint implements Constraint {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] sqlCreateStrings(Dialect dialect) {
|
public boolean isCreationVetoed(Dialect dialect) {
|
||||||
String s = dialect.getUniqueDelegate().applyUniquesOnAlter(this);
|
if ( dialect.supportsNotNullUnique() ) {
|
||||||
return StringHelper.toArrayElement( s );
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Column column : getColumns() ) {
|
||||||
|
if ( column.isNullable() ) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String sqlConstraintStringInCreateTable(Dialect dialect) {
|
||||||
|
StringBuilder buf = new StringBuilder( "unique (" );
|
||||||
|
boolean hadNullableColumn = false;
|
||||||
|
boolean first = true;
|
||||||
|
for ( Column column : getColumns() ) {
|
||||||
|
if ( first ) {
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String[] sqlDropStrings(Dialect dialect) {
|
public String sqlConstraintStringInAlterTable(Dialect dialect) {
|
||||||
String s = dialect.getUniqueDelegate().dropUniquesOnAlter(this);
|
StringBuilder buf = new StringBuilder(
|
||||||
return StringHelper.toArrayElement( s );
|
dialect.getAddUniqueConstraintString( getName() )
|
||||||
}
|
).append( '(' );
|
||||||
|
boolean nullable = false;
|
||||||
@Override
|
boolean first = true;
|
||||||
protected String sqlConstraintStringInAlterTable(Dialect dialect) {
|
for ( Column column : getColumns() ) {
|
||||||
// not used
|
if ( first ) {
|
||||||
return "";
|
first = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buf.append( ", " );
|
||||||
|
}
|
||||||
|
if ( !nullable && column.isNullable() ) {
|
||||||
|
nullable = true;
|
||||||
|
}
|
||||||
|
buf.append( column.getColumnName().encloseInQuotesIfQuoted( dialect ) );
|
||||||
|
}
|
||||||
|
return !nullable || dialect.supportsNotNullUnique() ? buf.append( ')' ).toString() : null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,8 @@ import org.hibernate.JDBCException;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.Transaction;
|
import org.hibernate.Transaction;
|
||||||
import org.hibernate.mapping.UniqueKey;
|
import org.hibernate.mapping.UniqueKey;
|
||||||
|
import org.hibernate.testing.DialectChecks;
|
||||||
|
import org.hibernate.testing.RequiresDialectFeature;
|
||||||
import org.hibernate.testing.TestForIssue;
|
import org.hibernate.testing.TestForIssue;
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -35,6 +37,7 @@ public class UniqueConstraintTest extends BaseCoreFunctionalTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@RequiresDialectFeature( DialectChecks.SupportNotNullUnique.class )
|
||||||
public void testUniquenessConstraintWithSuperclassProperty() throws Exception {
|
public void testUniquenessConstraintWithSuperclassProperty() throws Exception {
|
||||||
Session s = openSession();
|
Session s = openSession();
|
||||||
Transaction tx = s.beginTransaction();
|
Transaction tx = s.beginTransaction();
|
||||||
|
@ -72,7 +75,7 @@ public class UniqueConstraintTest extends BaseCoreFunctionalTestCase {
|
||||||
Iterator<org.hibernate.mapping.Table> iterator = configuration().getTableMappings();
|
Iterator<org.hibernate.mapping.Table> iterator = configuration().getTableMappings();
|
||||||
org.hibernate.mapping.Table tableA = null;
|
org.hibernate.mapping.Table tableA = null;
|
||||||
org.hibernate.mapping.Table tableB = null;
|
org.hibernate.mapping.Table tableB = null;
|
||||||
while( iterator.hasNext() ) {
|
while ( iterator.hasNext() ) {
|
||||||
org.hibernate.mapping.Table table = iterator.next();
|
org.hibernate.mapping.Table table = iterator.next();
|
||||||
if ( table.getName().equals( "UniqueNoNameA" ) ) {
|
if ( table.getName().equals( "UniqueNoNameA" ) ) {
|
||||||
tableA = table;
|
tableA = table;
|
||||||
|
@ -81,14 +84,13 @@ public class UniqueConstraintTest extends BaseCoreFunctionalTestCase {
|
||||||
tableB = table;
|
tableB = table;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( tableA == null || tableB == null ) {
|
if ( tableA == null || tableB == null ) {
|
||||||
fail( "Could not find the expected tables." );
|
fail( "Could not find the expected tables." );
|
||||||
}
|
}
|
||||||
|
|
||||||
UniqueKey ukA = (UniqueKey) tableA.getUniqueKeyIterator().next();
|
assertFalse( ( (UniqueKey) tableA.getUniqueKeyIterator().next() ).getName().equals(
|
||||||
UniqueKey ukB = (UniqueKey) tableB.getUniqueKeyIterator().next();
|
( (UniqueKey) tableB.getUniqueKeyIterator().next() ).getName() ) );
|
||||||
assertFalse( ukA.getName().equals( ukB.getName() ) );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
|
|
|
@ -1,85 +0,0 @@
|
||||||
/*
|
|
||||||
* Hibernate, Relational Persistence for Idiomatic Java
|
|
||||||
*
|
|
||||||
* JBoss, Home of Professional Open Source
|
|
||||||
* Copyright 2012 Red Hat Inc. and/or its affiliates and other contributors
|
|
||||||
* as indicated by the @authors tag. All rights reserved.
|
|
||||||
* See the copyright.txt in the distribution for a
|
|
||||||
* full listing of individual contributors.
|
|
||||||
*
|
|
||||||
* This copyrighted material is made available to anyone wishing to use,
|
|
||||||
* modify, copy, or redistribute it subject to the terms and conditions
|
|
||||||
* of the GNU Lesser General Public License, v. 2.1.
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT A
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
|
|
||||||
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License,
|
|
||||||
* v.2.1 along with this distribution; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
||||||
* MA 02110-1301, USA.
|
|
||||||
*/
|
|
||||||
package org.hibernate.test.constraint;
|
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import javax.persistence.Entity;
|
|
||||||
import javax.persistence.GeneratedValue;
|
|
||||||
import javax.persistence.Id;
|
|
||||||
import javax.persistence.Table;
|
|
||||||
|
|
||||||
import org.hibernate.mapping.Column;
|
|
||||||
import org.hibernate.testing.TestForIssue;
|
|
||||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* HHH-7797 re-wrote the way dialects handle unique constraints. Test
|
|
||||||
* variations of unique & not null to ensure the constraints are created
|
|
||||||
* correctly for each dialect.
|
|
||||||
*
|
|
||||||
* @author Brett Meyer
|
|
||||||
*/
|
|
||||||
@TestForIssue( jiraKey = "HHH-7797" )
|
|
||||||
public class ConstraintTest extends BaseCoreFunctionalTestCase {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Class<?>[] getAnnotatedClasses() {
|
|
||||||
return new Class<?>[] {
|
|
||||||
Entity1.class
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testConstraints() {
|
|
||||||
Column column = (Column) configuration().getClassMapping( Entity1.class.getName() )
|
|
||||||
.getProperty( "foo1" ).getColumnIterator().next();
|
|
||||||
assertFalse( column.isNullable() );
|
|
||||||
assertTrue( column.isUnique() );
|
|
||||||
|
|
||||||
column = (Column) configuration().getClassMapping( Entity1.class.getName() )
|
|
||||||
.getProperty( "foo2" ).getColumnIterator().next();
|
|
||||||
assertTrue( column.isNullable() );
|
|
||||||
assertTrue( column.isUnique() );
|
|
||||||
|
|
||||||
column = (Column) configuration().getClassMapping( Entity1.class.getName() )
|
|
||||||
.getProperty( "id" ).getColumnIterator().next();
|
|
||||||
assertFalse( column.isNullable() );
|
|
||||||
assertTrue( column.isUnique() );
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
@Table( name = "Entity1" )
|
|
||||||
public static class Entity1 {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
@javax.persistence.Column( nullable = false, unique = true)
|
|
||||||
public long id;
|
|
||||||
|
|
||||||
@javax.persistence.Column( nullable = false, unique = true)
|
|
||||||
public String foo1;
|
|
||||||
|
|
||||||
@javax.persistence.Column( nullable = true, unique = true)
|
|
||||||
public String foo2;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -92,6 +92,12 @@ abstract public class DialectChecks {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class SupportNotNullUnique implements DialectCheck {
|
||||||
|
public boolean isMatch(Dialect dialect) {
|
||||||
|
return dialect.supportsNotNullUnique();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class SupportLimitCheck implements DialectCheck {
|
public static class SupportLimitCheck implements DialectCheck {
|
||||||
public boolean isMatch(Dialect dialect) {
|
public boolean isMatch(Dialect dialect) {
|
||||||
return dialect.supportsLimit();
|
return dialect.supportsLimit();
|
||||||
|
|
Loading…
Reference in New Issue