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";
|
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
|
* Slight variation on {@link #getCreateTableString}. Here, we have the
|
||||||
* command used to create a table when there is no primary key and
|
* 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;
|
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
|
* Generate a DROP TABLE statement
|
||||||
*
|
*
|
||||||
|
|
|
@ -22,4 +22,10 @@ public class PostgreSQL92Dialect extends PostgreSQL91Dialect {
|
||||||
super();
|
super();
|
||||||
this.registerColumnType( Types.JAVA_OBJECT, "json" );
|
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() );
|
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) {
|
protected String uniqueConstraintSql(UniqueKey uniqueKey) {
|
||||||
|
@ -83,8 +84,7 @@ public class DefaultUniqueDelegate implements UniqueDelegate {
|
||||||
dialect
|
dialect
|
||||||
);
|
);
|
||||||
|
|
||||||
final StringBuilder buf = new StringBuilder( "alter table " );
|
final StringBuilder buf = new StringBuilder( dialect.getAlterTableString(tableName) );
|
||||||
buf.append( tableName );
|
|
||||||
buf.append( getDropUnique() );
|
buf.append( getDropUnique() );
|
||||||
if ( dialect.supportsIfExistsBeforeConstraintName() ) {
|
if ( dialect.supportsIfExistsBeforeConstraintName() ) {
|
||||||
buf.append( "if exists " );
|
buf.append( "if exists " );
|
||||||
|
|
|
@ -32,7 +32,8 @@ public class InformixUniqueDelegate extends DefaultUniqueDelegate {
|
||||||
metadata.getDatabase().getJdbcEnvironment().getDialect()
|
metadata.getDatabase().getJdbcEnvironment().getDialect()
|
||||||
);
|
);
|
||||||
final String constraintName = dialect.quote( uniqueKey.getName() );
|
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) {
|
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
|
||||||
if ( isGenerated( dialect ) ) {
|
if ( isGenerated( dialect ) ) {
|
||||||
|
final String tableName = getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema );
|
||||||
return String.format(
|
return String.format(
|
||||||
Locale.ROOT,
|
Locale.ROOT,
|
||||||
"alter table %s drop constraint %s",
|
"%s drop constraint %s",
|
||||||
getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema ),
|
dialect.getAlterTableString( tableName ),
|
||||||
dialect.quote( getName() )
|
dialect.quote( getName() )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -184,8 +185,8 @@ public abstract class Constraint implements RelationalModel, Exportable, Seriali
|
||||||
// empty string. Prevent blank "alter table" statements.
|
// empty string. Prevent blank "alter table" statements.
|
||||||
String constraintString = sqlConstraintString( dialect, getName(), defaultCatalog, defaultSchema );
|
String constraintString = sqlConstraintString( dialect, getName(), defaultCatalog, defaultSchema );
|
||||||
if ( !StringHelper.isEmpty( constraintString ) ) {
|
if ( !StringHelper.isEmpty( constraintString ) ) {
|
||||||
return "alter table " + getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema )
|
final String tableName = getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema );
|
||||||
+ constraintString;
|
return dialect.getAlterTableString( tableName ) + " " + constraintString;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -173,8 +173,8 @@ public class ForeignKey extends Constraint {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
|
public String sqlDropString(Dialect dialect, String defaultCatalog, String defaultSchema) {
|
||||||
final StringBuilder buf = new StringBuilder( "alter table " );
|
String tableName = getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema );
|
||||||
buf.append( getTable().getQualifiedName( dialect, defaultCatalog, defaultSchema ) );
|
final StringBuilder buf = new StringBuilder( dialect.getAlterTableString( tableName ) );
|
||||||
buf.append( dialect.getDropForeignKeyString() );
|
buf.append( dialect.getDropForeignKeyString() );
|
||||||
if ( dialect.supportsIfExistsBeforeConstraintName() ) {
|
if ( dialect.supportsIfExistsBeforeConstraintName() ) {
|
||||||
buf.append( "if exists " );
|
buf.append( "if exists " );
|
||||||
|
|
|
@ -447,13 +447,12 @@ public class Table implements RelationalModel, Serializable, Exportable {
|
||||||
|
|
||||||
final JdbcEnvironment jdbcEnvironment = metadata.getDatabase().getJdbcEnvironment();
|
final JdbcEnvironment jdbcEnvironment = metadata.getDatabase().getJdbcEnvironment();
|
||||||
|
|
||||||
StringBuilder root = new StringBuilder( "alter table " )
|
final String tableName = jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
||||||
.append(
|
tableInfo.getName(),
|
||||||
jdbcEnvironment.getQualifiedObjectNameFormatter().format(
|
dialect
|
||||||
tableInfo.getName(),
|
);
|
||||||
dialect
|
|
||||||
)
|
StringBuilder root = new StringBuilder( dialect.getAlterTableString( tableName ) )
|
||||||
)
|
|
||||||
.append( ' ' )
|
.append( ' ' )
|
||||||
.append( dialect.getAddColumnString() );
|
.append( dialect.getAddColumnString() );
|
||||||
|
|
||||||
|
|
|
@ -100,8 +100,7 @@ public class StandardForeignKeyExporter implements Exporter<ForeignKey> {
|
||||||
dialect
|
dialect
|
||||||
);
|
);
|
||||||
|
|
||||||
final StringBuilder buffer = new StringBuilder( "alter table " )
|
final StringBuilder buffer = new StringBuilder( dialect.getAlterTableString( sourceTableName ) )
|
||||||
.append( sourceTableName )
|
|
||||||
.append(
|
.append(
|
||||||
foreignKey.getKeyDefinition() != null ?
|
foreignKey.getKeyDefinition() != null ?
|
||||||
dialect.getAddForeignKeyConstraintString(
|
dialect.getAddForeignKeyConstraintString(
|
||||||
|
@ -146,7 +145,8 @@ public class StandardForeignKeyExporter implements Exporter<ForeignKey> {
|
||||||
dialect
|
dialect
|
||||||
);
|
);
|
||||||
return new String[] {
|
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() );
|
final List<String> sqlLines = Files.readAllLines( output.toPath(), Charset.defaultCharset() );
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for ( String line : sqlLines ) {
|
for ( String line : sqlLines ) {
|
||||||
if ( line.contains( expectedAlterTableStatement ) ) {
|
if ( line.matches( expectedAlterTableStatement ) ) {
|
||||||
found = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -187,7 +186,7 @@ public class ForeignKeyGenerationTest extends BaseUnitTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toSQL() {
|
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() );
|
final List<String> sqlLines = Files.readAllLines( output.toPath(), Charset.defaultCharset() );
|
||||||
boolean found = false;
|
boolean found = false;
|
||||||
for ( String line : sqlLines ) {
|
for ( String line : sqlLines ) {
|
||||||
if ( line.contains( expectedAlterTableStatement ) ) {
|
if ( line.matches( expectedAlterTableStatement ) ) {
|
||||||
found = true;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +103,7 @@ public class JoinedInheritanceForeignKeyTest extends BaseUnitTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toSQL() {
|
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.registry.StandardServiceRegistryBuilder;
|
||||||
import org.hibernate.boot.spi.MetadataImplementor;
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
import org.hibernate.dialect.DB2Dialect;
|
import org.hibernate.dialect.DB2Dialect;
|
||||||
|
import org.hibernate.dialect.PostgreSQL81Dialect;
|
||||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||||
import org.hibernate.tool.schema.TargetType;
|
import org.hibernate.tool.schema.TargetType;
|
||||||
|
@ -73,7 +74,7 @@ public class SchemaCreationTest {
|
||||||
for ( String statement : sqlLines ) {
|
for ( String statement : sqlLines ) {
|
||||||
assertThat(
|
assertThat(
|
||||||
"Should not try to create the unique constraint for the non existing table element",
|
"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 )
|
is( false )
|
||||||
);
|
);
|
||||||
if (ssr.getService(JdbcEnvironment.class).getDialect() instanceof DB2Dialect) {
|
if (ssr.getService(JdbcEnvironment.class).getDialect() instanceof DB2Dialect) {
|
||||||
|
@ -81,7 +82,14 @@ public class SchemaCreationTest {
|
||||||
&& statement.toLowerCase().contains("category (code)")) {
|
&& statement.toLowerCase().contains("category (code)")) {
|
||||||
isUniqueConstraintCreated = true;
|
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")
|
if (statement.toLowerCase().startsWith("alter table category add constraint")
|
||||||
&& statement.toLowerCase().contains("unique (code)")) {
|
&& statement.toLowerCase().contains("unique (code)")) {
|
||||||
isUniqueConstraintCreated = true;
|
isUniqueConstraintCreated = true;
|
||||||
|
|
|
@ -126,7 +126,7 @@ public class UniqueConstraintDropTest {
|
||||||
|
|
||||||
private boolean checkDropConstraint(String tableName, String columnName) throws IOException {
|
private boolean checkDropConstraint(String tableName, String columnName) throws IOException {
|
||||||
boolean matches = false;
|
boolean matches = false;
|
||||||
String regex = "alter table " + tableName + " drop constraint";
|
String regex = "alter table (?:if exists) " + tableName + " drop constraint";
|
||||||
|
|
||||||
if ( getDialect().supportsIfExistsBeforeConstraintName() ) {
|
if ( getDialect().supportsIfExistsBeforeConstraintName() ) {
|
||||||
regex += " if exists";
|
regex += " if exists";
|
||||||
|
|
|
@ -19,6 +19,7 @@ import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
|
||||||
import org.hibernate.boot.spi.MetadataImplementor;
|
import org.hibernate.boot.spi.MetadataImplementor;
|
||||||
import org.hibernate.cfg.Environment;
|
import org.hibernate.cfg.Environment;
|
||||||
import org.hibernate.dialect.DB2Dialect;
|
import org.hibernate.dialect.DB2Dialect;
|
||||||
|
import org.hibernate.dialect.PostgreSQL81Dialect;
|
||||||
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
|
||||||
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
import org.hibernate.tool.hbm2ddl.SchemaExport;
|
||||||
import org.hibernate.tool.schema.TargetType;
|
import org.hibernate.tool.schema.TargetType;
|
||||||
|
@ -70,7 +71,8 @@ public class UniqueConstraintGenerationTest {
|
||||||
isCreateUniqueIndexGenerated("test_entity_item", "item"),
|
isCreateUniqueIndexGenerated("test_entity_item", "item"),
|
||||||
is(true)
|
is(true)
|
||||||
);
|
);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
assertThat(
|
assertThat(
|
||||||
"The test_entity_item table unique constraint has not been generated",
|
"The test_entity_item table unique constraint has not been generated",
|
||||||
isUniqueConstraintGenerated("test_entity_item", "item"),
|
isUniqueConstraintGenerated("test_entity_item", "item"),
|
||||||
|
@ -87,7 +89,7 @@ public class UniqueConstraintGenerationTest {
|
||||||
|
|
||||||
private boolean isUniqueConstraintGenerated(String tableName, String columnName) throws IOException {
|
private boolean isUniqueConstraintGenerated(String tableName, String columnName) throws IOException {
|
||||||
boolean matches = false;
|
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 fileContent = new String( Files.readAllBytes( output.toPath() ) ).toLowerCase();
|
||||||
final String[] split = fileContent.split( System.lineSeparator() );
|
final String[] split = fileContent.split( System.lineSeparator() );
|
||||||
|
|
Loading…
Reference in New Issue