From 9504c102cfbaa6462e6344d1aba3992def9e269a Mon Sep 17 00:00:00 2001 From: Brett Meyer Date: Fri, 21 Mar 2014 14:35:55 -0400 Subject: [PATCH] HHH-8796 corrected MySQL index create/drop, corrected qualifyIndexName() use --- .../java/org/hibernate/dialect/H2Dialect.java | 5 ++ .../org/hibernate/dialect/HSQLDialect.java | 5 ++ .../org/hibernate/dialect/MySQLDialect.java | 18 +++++ .../constraint/ConstraintDelegate.java | 16 ++--- .../constraint/MySQLIndexExporter.java | 67 +++++++++++++++++++ .../constraint/MySQLUniqueKeyExporter.java | 66 ++++++++++++++++++ .../schema/internal/SchemaDropperImpl.java | 15 +++-- .../internal/StandardIndexExporter.java | 3 +- 8 files changed, 176 insertions(+), 19 deletions(-) create mode 100644 hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLIndexExporter.java create mode 100644 hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLUniqueKeyExporter.java diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java index 719e5e4c30..f5256ae6f1 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/H2Dialect.java @@ -436,4 +436,9 @@ public class H2Dialect extends Dialect { public String getCurrentSchemaCommand() { return "call schema()"; } + + @Override + public boolean qualifyIndexName() { + return false; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java index 2f50f88d90..0cd0e620f3 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/HSQLDialect.java @@ -688,4 +688,9 @@ public class HSQLDialect extends Dialect { public String getCascadeConstraintsString() { return " CASCADE "; } + + @Override + public boolean qualifyIndexName() { + return false; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java index ea70243990..e328a4e417 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/MySQLDialect.java @@ -31,6 +31,8 @@ import java.sql.Types; import org.hibernate.JDBCException; import org.hibernate.NullPrecedence; import org.hibernate.cfg.Environment; +import org.hibernate.dialect.constraint.MySQLIndexExporter; +import org.hibernate.dialect.constraint.MySQLUniqueKeyExporter; import org.hibernate.dialect.function.NoArgSQLFunction; import org.hibernate.dialect.function.StandardSQLFunction; import org.hibernate.dialect.pagination.AbstractLimitHandler; @@ -42,6 +44,9 @@ import org.hibernate.exception.LockTimeoutException; import org.hibernate.exception.spi.SQLExceptionConversionDelegate; import org.hibernate.internal.util.JdbcExceptionHelper; import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.tool.schema.spi.Exporter; import org.hibernate.type.StandardBasicTypes; /** @@ -51,6 +56,9 @@ import org.hibernate.type.StandardBasicTypes; */ public class MySQLDialect extends Dialect { + private final MySQLUniqueKeyExporter uniqueKeyExporter = new MySQLUniqueKeyExporter( this ); + private final MySQLIndexExporter indexExporter = new MySQLIndexExporter( this ); + /** * Constructs a MySQLDialect */ @@ -469,4 +477,14 @@ public class MySQLDialect extends Dialect { public String getNotExpression(String expression) { return "not (" + expression + ")"; } + + @Override + public Exporter getUniqueKeyExporter() { + return uniqueKeyExporter; + } + + @Override + public Exporter getIndexExporter() { + return indexExporter; + } } diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/constraint/ConstraintDelegate.java b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/ConstraintDelegate.java index d7672bd131..b1f73e28d6 100644 --- a/hibernate-core/src/main/java/org/hibernate/dialect/constraint/ConstraintDelegate.java +++ b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/ConstraintDelegate.java @@ -27,16 +27,12 @@ import java.util.List; import javax.persistence.Column; import javax.persistence.UniqueConstraint; -import org.hibernate.boot.registry.internal.BootstrapServiceRegistryImpl; import org.hibernate.dialect.Dialect; import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; -import org.hibernate.internal.CoreMessageLogger; import org.hibernate.metamodel.spi.relational.AbstractConstraint; -import org.hibernate.metamodel.spi.relational.Constraint; import org.hibernate.metamodel.spi.relational.Index; import org.hibernate.metamodel.spi.relational.Table; import org.hibernate.metamodel.spi.relational.UniqueKey; -import org.hibernate.tool.schema.spi.Exporter; import org.jboss.logging.Logger; /** @@ -64,13 +60,9 @@ public class ConstraintDelegate { private static final Logger LOG = Logger.getLogger( ConstraintDelegate.class ); final protected Dialect dialect; - final protected Exporter indexExporter; - final protected Exporter uniqueExporter; public ConstraintDelegate(Dialect dialect) { this.dialect = dialect; - this.indexExporter = dialect.getIndexExporter(); - this.uniqueExporter = dialect.getUniqueKeyExporter(); } /** @@ -128,7 +120,7 @@ public class ConstraintDelegate { + " sequence of columns: %s", index.getColumnNames()); } else { - sqlStrings.addAll(Arrays.asList( indexExporter.getSqlCreateStrings( index, jdbcEnvironment ) ) ); + sqlStrings.addAll(Arrays.asList( dialect.getIndexExporter().getSqlCreateStrings( index, jdbcEnvironment ) ) ); } indexColumnListIds.add( index.columnListId() ); } @@ -152,7 +144,7 @@ public class ConstraintDelegate { + " for a unique index. %s", constraint.getColumnNames()); } else { - sqlStrings.addAll(Arrays.asList( uniqueExporter.getSqlCreateStrings( + sqlStrings.addAll(Arrays.asList( dialect.getUniqueKeyExporter().getSqlCreateStrings( constraint, jdbcEnvironment ) ) ); } uniqueColumnListIds.add( constraint.columnListAlphabeticalId() ); @@ -209,7 +201,7 @@ public class ConstraintDelegate { } else { if (! indexColumnListIds.contains( index.columnListId() )) { - sqlStrings.addAll(Arrays.asList( indexExporter.getSqlDropStrings( index, jdbcEnvironment ) ) ); + sqlStrings.addAll(Arrays.asList( dialect.getIndexExporter().getSqlDropStrings( index, jdbcEnvironment ) ) ); } indexColumnListIds.add( index.columnListId() ); } @@ -229,7 +221,7 @@ public class ConstraintDelegate { List uniqueColumnListIds, JdbcEnvironment jdbcEnvironment) { // A unique Index may have already exported the constraint. if (! uniqueColumnListIds.contains( constraint.columnListAlphabeticalId() )) { - sqlStrings.addAll(Arrays.asList( uniqueExporter.getSqlDropStrings( + sqlStrings.addAll(Arrays.asList( dialect.getUniqueKeyExporter().getSqlDropStrings( constraint, jdbcEnvironment ) ) ); } uniqueColumnListIds.add( constraint.columnListAlphabeticalId() ); diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLIndexExporter.java b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLIndexExporter.java new file mode 100644 index 0000000000..77e3de6e99 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLIndexExporter.java @@ -0,0 +1,67 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * 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, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY 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 + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.dialect.constraint; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.internal.util.StringHelper; +import org.hibernate.metamodel.spi.relational.Index; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.internal.StandardIndexExporter; + +/** + * MySQL requires "ON table" at the end of a "DROP INDEX". + * + * TODO: If other Dialects need that as well, consider adding a "requiresOnTable" type of method on Dialect and + * work it into StandardIndexExporter itself. + * + * @author Brett Meyer + */ +public class MySQLIndexExporter extends StandardIndexExporter { + private final Dialect dialect; + + public MySQLIndexExporter(Dialect dialect) { + super(dialect); + this.dialect = dialect; + } + + @Override + public String[] getSqlDropStrings(Index index, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.dropConstraints() ) { + return NO_COMMANDS; + } + + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) index.getTable() ).getTableName() + ); + + StringBuilder sb = new StringBuilder(); + sb.append( "drop index " ); + sb.append( ( dialect.qualifyIndexName() + ? StringHelper.qualify( tableName, index.getName() ) : index.getName() ) ); + sb.append( " on " + tableName ); + + return new String[] { sb.toString() }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLUniqueKeyExporter.java b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLUniqueKeyExporter.java new file mode 100644 index 0000000000..f007f5bb7b --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/dialect/constraint/MySQLUniqueKeyExporter.java @@ -0,0 +1,66 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2012, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * 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, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY 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 + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.dialect.constraint; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; +import org.hibernate.metamodel.spi.relational.Constraint; +import org.hibernate.metamodel.spi.relational.Table; +import org.hibernate.tool.schema.internal.StandardUniqueKeyExporter; + +/** + * MySQL does not support "DROP CONSTRAINT". Must use "DROP INDEX" instead. + * + * @author Brett Meyer + */ +public class MySQLUniqueKeyExporter extends StandardUniqueKeyExporter { + private final Dialect dialect; + + public MySQLUniqueKeyExporter(Dialect dialect) { + super( dialect ); + this.dialect = dialect; + } + + @Override + public String[] getSqlDropStrings(Constraint constraint, JdbcEnvironment jdbcEnvironment) { + if ( ! dialect.dropConstraints() ) { + return NO_COMMANDS; + } + + final String tableName = jdbcEnvironment.getQualifiedObjectNameSupport().formatName( + ( (Table) constraint.getTable() ).getTableName() + ); + final StringBuilder sb = new StringBuilder( "alter table " ); + sb.append( tableName ); + sb.append(" drop index " ); + if ( dialect.supportsIfExistsBeforeConstraintName() ) { + sb.append( "if exists " ); + } + sb.append( dialect.quote( constraint.getName() ) ); + if ( dialect.supportsIfExistsAfterConstraintName() ) { + sb.append( " if exists" ); + } + return new String[] { sb.toString() }; + } +} diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java index 15a9d3e20e..7181616e63 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/SchemaDropperImpl.java @@ -77,17 +77,14 @@ public class SchemaDropperImpl implements SchemaDropper { } for ( Schema schema : database.getSchemas() ) { - // we need to drop constraints prior to dropping table - applySqlStrings( targets, dialect.dropConstraints( schema.getTables(), jdbcEnvironment ) ); + // we need to drop all constraints/indexes prior to dropping the tables + applySqlStrings( targets, dialect.dropConstraints( schema.getTables(), jdbcEnvironment ) ); for ( Table table : schema.getTables() ) { if( !table.isPhysicalTable() ){ continue; } - if ( dialect.dropConstraints() ) { - // we need to drop constraints prior to dropping table - for ( ForeignKey foreignKey : table.getForeignKeys() ) { // only add the foreign key if its source and target are both physical tables // and if the target table does not have any denormalized tables. @@ -107,7 +104,13 @@ public class SchemaDropperImpl implements SchemaDropper { } } } - + } + + // now it's safe to drop the tables + for ( Table table : schema.getTables() ) { + if( !table.isPhysicalTable() ){ + continue; + } checkExportIdentifier( table, exportIdentifiers ); applySqlStrings( targets, dialect.getTableExporter().getSqlDropStrings( table, jdbcEnvironment ) ); } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java index df4b016e5f..6de812c1a4 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/internal/StandardIndexExporter.java @@ -77,7 +77,8 @@ public class StandardIndexExporter implements Exporter { ( (Table) index.getTable() ).getTableName() ); return new String[] { - "drop index " + StringHelper.qualify( tableName, index.getName() ) + "drop index " + ( dialect.qualifyIndexName() + ? StringHelper.qualify( tableName, index.getName() ) : index.getName() ) }; } }