HHH-11647 - Use ALTER TABLE IF EXISTS on Postgres
This commit is contained in:
parent
72e0d593b9
commit
f85737cb0b
|
@ -1451,6 +1451,22 @@ public abstract class Dialect implements ConversionContext {
|
|||
return "create table";
|
||||
}
|
||||
|
||||
/**
|
||||
* Command used to alter a table.
|
||||
*
|
||||
* @param tableName The name of the table to alter
|
||||
* @return The command used to alter a table.
|
||||
* @since 5.2.11
|
||||
*/
|
||||
public String getAlterTableString(String tableName) {
|
||||
final StringBuilder sb = new StringBuilder( "alter table " );
|
||||
if ( supportsIfExistsAfterAlterTable() ) {
|
||||
sb.append( "if exists " );
|
||||
}
|
||||
sb.append( tableName );
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Slight variation on {@link #getCreateTableString}. Here, we have the
|
||||
* command used to create a table when there is no primary key and
|
||||
|
@ -2241,6 +2257,16 @@ public abstract class Dialect implements ConversionContext {
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* For an "alter table", can the phrase "if exists" be applied?
|
||||
*
|
||||
* @return {@code true} if the "if exists" can be applied after ALTER TABLE
|
||||
* @since 5.2.11
|
||||
*/
|
||||
public boolean supportsIfExistsAfterAlterTable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a DROP TABLE statement
|
||||
*
|
||||
|
|
|
@ -22,4 +22,10 @@ public class PostgreSQL92Dialect extends PostgreSQL91Dialect {
|
|||
super();
|
||||
this.registerColumnType( Types.JAVA_OBJECT, "json" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsIfExistsAfterAlterTable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -53,7 +53,8 @@ public class DefaultUniqueDelegate implements UniqueDelegate {
|
|||
);
|
||||
|
||||
final String constraintName = dialect.quote( uniqueKey.getName() );
|
||||
return "alter table " + tableName + " add constraint " + constraintName + " " + uniqueConstraintSql( uniqueKey );
|
||||
return dialect.getAlterTableString( tableName )
|
||||
+ " add constraint " + constraintName + " " + uniqueConstraintSql( uniqueKey );
|
||||
}
|
||||
|
||||
protected String uniqueConstraintSql(UniqueKey uniqueKey) {
|
||||
|
@ -83,8 +84,7 @@ public class DefaultUniqueDelegate implements UniqueDelegate {
|
|||
dialect
|
||||
);
|
||||
|
||||
final StringBuilder buf = new StringBuilder( "alter table " );
|
||||
buf.append( tableName );
|
||||
final StringBuilder buf = new StringBuilder( dialect.getAlterTableString(tableName) );
|
||||
buf.append( getDropUnique() );
|
||||
if ( dialect.supportsIfExistsBeforeConstraintName() ) {
|
||||
buf.append( "if exists " );
|
||||
|
|
|
@ -32,7 +32,8 @@ public class InformixUniqueDelegate extends DefaultUniqueDelegate {
|
|||
metadata.getDatabase().getJdbcEnvironment().getDialect()
|
||||
);
|
||||
final String constraintName = dialect.quote( uniqueKey.getName() );
|
||||
return "alter table " + tableName + " add constraint " + uniqueConstraintSql( uniqueKey ) + " constraint " + constraintName;
|
||||
return dialect.getAlterTableString( tableName )
|
||||
+ " add constraint " + uniqueConstraintSql( uniqueKey ) + " constraint " + constraintName;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -165,10 +165,11 @@ public abstract class Constraint implements RelationalModel, Exportable, Seriali
|
|||
|
||||
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
|
||||
if ( isGenerated( dialect ) ) {
|
||||
final String tableName = getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema );
|
||||
return String.format(
|
||||
Locale.ROOT,
|
||||
"alter table %s drop constraint %s",
|
||||
getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema ),
|
||||
"%s drop constraint %s",
|
||||
dialect.getAlterTableString( tableName ),
|
||||
dialect.quote( getName() )
|
||||
);
|
||||
}
|
||||
|
@ -184,8 +185,8 @@ public abstract class Constraint implements RelationalModel, Exportable, Seriali
|
|||
// empty string. Prevent blank "alter table" statements.
|
||||
String constraintString = sqlConstraintString( dialect, getName(), defaultCatalog, defaultSchema );
|
||||
if ( !StringHelper.isEmpty( constraintString ) ) {
|
||||
return "alter table " + getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema )
|
||||
+ constraintString;
|
||||
final String tableName = getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema );
|
||||
return dialect.getAlterTableString( tableName ) + " " + constraintString;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -173,8 +173,8 @@ public class ForeignKey extends Constraint {
|
|||
}
|
||||
|
||||
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
|
||||
final StringBuilder buf = new StringBuilder( "alter table " );
|
||||
buf.append( getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema ) );
|
||||
String tableName = getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema );
|
||||
final StringBuilder buf = new StringBuilder( dialect.getAlterTableString( tableName ) );
|
||||
buf.append( dialect.getDropForeignKeyString() );
|
||||
if ( dialect.supportsIfExistsBeforeConstraintName() ) {
|
||||
buf.append( "if exists " );
|
||||
|
|
|
@ -447,13 +447,12 @@ public class Table implements RelationalModel, Serializable, Exportable {
|
|||
|
||||
final JdbcEnvironment jdbcEnvironment = metadata.getDatabase().getJdbcEnvironment();
|
||||
|
||||
StringBuilder root = new StringBuilder( "alter table " )
|
||||
.append(
|
||||
jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
||||
tableInfo.getName(),
|
||||
dialect
|
||||
)
|
||||
)
|
||||
final String tableName = jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
||||
tableInfo.getName(),
|
||||
dialect
|
||||
);
|
||||
|
||||
StringBuilder root = new StringBuilder( dialect.getAlterTableString( tableName ) )
|
||||
.append( ' ' )
|
||||
.append( dialect.getAddColumnString() );
|
||||
|
||||
|
|
|
@ -100,8 +100,7 @@ public class StandardForeignKeyExporter implements Exporter<ForeignKey> {
|
|||
dialect
|
||||
);
|
||||
|
||||
final StringBuilder buffer = new StringBuilder( "alter table " )
|
||||
.append( sourceTableName )
|
||||
final StringBuilder buffer = new StringBuilder( dialect.getAlterTableString( sourceTableName ) )
|
||||
.append(
|
||||
foreignKey.getKeyDefinition() != null ?
|
||||
dialect.getAddForeignKeyConstraintString(
|
||||
|
@ -146,7 +145,8 @@ public class StandardForeignKeyExporter implements Exporter<ForeignKey> {
|
|||
dialect
|
||||
);
|
||||
return new String[] {
|
||||
"alter table " + sourceTableName + dialect.getDropForeignKeyString() + foreignKey.getName()
|
||||
dialect.getAlterTableString( sourceTableName )
|
||||
+ dialect.getDropForeignKeyString() + foreignKey.getName()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.dialect;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.junit4.BaseUnitTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
/**
|
||||
* Test case for PostgreSQL 9.2 specific things.
|
||||
*
|
||||
* @author Christoph Dreis
|
||||
*/
|
||||
public class PostgreSQL92DialectTestCase extends BaseUnitTestCase {
|
||||
|
||||
/**
|
||||
* Tests that getAlterTableString() will make use of IF EXISTS syntax
|
||||
*/
|
||||
@Test
|
||||
@TestForIssue( jiraKey = "HHH-11647" )
|
||||
public void testGetAlterTableString() {
|
||||
PostgreSQL92Dialect dialect = new PostgreSQL92Dialect();
|
||||
|
||||
assertEquals("alter table if exists table_name", dialect.getAlterTableString( "table_name" ));
|
||||
}
|
||||
|
||||
}
|
|
@ -161,8 +161,7 @@ public class ForeignKeyGenerationTest extends BaseUnitTestCase {
|
|||
final List<String> sqlLines = Files.readAllLines( output.toPath(), Charset.defaultCharset() );
|
||||
boolean found = false;
|
||||
for ( String line : sqlLines ) {
|
||||
if ( line.contains( expectedAlterTableStatement ) ) {
|
||||
found = true;
|
||||
if ( line.matches( expectedAlterTableStatement ) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -187,7 +186,7 @@ public class ForeignKeyGenerationTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
public String toSQL() {
|
||||
return "alter table " + tableName + " add constraint " + fkConstraintName + " foreign key (" + fkColumnName + ") references " + referenceTableName;
|
||||
return "alter table (?:if exists) " + tableName + " add constraint " + fkConstraintName + " foreign key \\(" + fkColumnName + "\\) references " + referenceTableName;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -78,8 +78,7 @@ public class JoinedInheritanceForeignKeyTest extends BaseUnitTestCase {
|
|||
final List<String> sqlLines = Files.readAllLines( output.toPath(), Charset.defaultCharset() );
|
||||
boolean found = false;
|
||||
for ( String line : sqlLines ) {
|
||||
if ( line.contains( expectedAlterTableStatement ) ) {
|
||||
found = true;
|
||||
if ( line.matches( expectedAlterTableStatement ) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -104,7 +103,7 @@ public class JoinedInheritanceForeignKeyTest extends BaseUnitTestCase {
|
|||
}
|
||||
|
||||
public String toSQL() {
|
||||
return "alter table " + tableName + " add constraint " + fkConstraintName + " foreign key (" + fkColumnName + ") references " + referenceTableName;
|
||||
return "alter table (?:if exists) " + tableName + " add constraint " + fkConstraintName + " foreign key \\(" + fkColumnName + "\\) references " + referenceTableName;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ import org.hibernate.boot.registry.StandardServiceRegistry;
|
|||
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.dialect.PostgreSQL81Dialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.hibernate.tool.schema.TargetType;
|
||||
|
@ -73,7 +74,7 @@ public class SchemaCreationTest {
|
|||
for ( String statement : sqlLines ) {
|
||||
assertThat(
|
||||
"Should not try to create the unique constraint for the non existing table element",
|
||||
statement.toLowerCase().contains( "alter table element" ),
|
||||
statement.toLowerCase().matches( "alter table (?:if exists) element" ),
|
||||
is( false )
|
||||
);
|
||||
if (ssr.getService(JdbcEnvironment.class).getDialect() instanceof DB2Dialect) {
|
||||
|
@ -81,7 +82,14 @@ public class SchemaCreationTest {
|
|||
&& statement.toLowerCase().contains("category (code)")) {
|
||||
isUniqueConstraintCreated = true;
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else if (ssr.getService(JdbcEnvironment.class).getDialect() instanceof PostgreSQL81Dialect) {
|
||||
if (statement.toLowerCase().startsWith("alter table if exists category add constraint")
|
||||
&& statement.toLowerCase().contains("unique (code)")) {
|
||||
isUniqueConstraintCreated = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (statement.toLowerCase().startsWith("alter table category add constraint")
|
||||
&& statement.toLowerCase().contains("unique (code)")) {
|
||||
isUniqueConstraintCreated = true;
|
||||
|
|
|
@ -126,7 +126,7 @@ public class UniqueConstraintDropTest {
|
|||
|
||||
private boolean checkDropConstraint(String tableName, String columnName) throws IOException {
|
||||
boolean matches = false;
|
||||
String regex = "alter table " + tableName + " drop constraint";
|
||||
String regex = "alter table (?:if exists) " + tableName + " drop constraint";
|
||||
|
||||
if ( getDialect().supportsIfExistsBeforeConstraintName() ) {
|
||||
regex += " if exists";
|
||||
|
|
|
@ -19,6 +19,7 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
|||
import org.hibernate.boot.spi.MetadataImplementor;
|
||||
import org.hibernate.cfg.Environment;
|
||||
import org.hibernate.dialect.DB2Dialect;
|
||||
import org.hibernate.dialect.PostgreSQL81Dialect;
|
||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||
import org.hibernate.tool.schema.TargetType;
|
||||
|
@ -70,7 +71,8 @@ public class UniqueConstraintGenerationTest {
|
|||
isCreateUniqueIndexGenerated("test_entity_item", "item"),
|
||||
is(true)
|
||||
);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
assertThat(
|
||||
"The test_entity_item table unique constraint has not been generated",
|
||||
isUniqueConstraintGenerated("test_entity_item", "item"),
|
||||
|
@ -87,7 +89,7 @@ public class UniqueConstraintGenerationTest {
|
|||
|
||||
private boolean isUniqueConstraintGenerated(String tableName, String columnName) throws IOException {
|
||||
boolean matches = false;
|
||||
final String regex = "alter table " + tableName + " add constraint uk_(.)* unique \\(" + columnName + "\\)";
|
||||
final String regex = "alter table (?:if exists) " + tableName + " add constraint uk_(.)* unique \\(" + columnName + "\\)";
|
||||
|
||||
final String fileContent = new String( Files.readAllBytes( output.toPath() ) ).toLowerCase();
|
||||
final String[] split = fileContent.split( System.lineSeparator() );
|
||||
|
|
Loading…
Reference in New Issue