@@ -21,19 +21,28 @@ package org.sonar.server.platform.db.migration.version.v85; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.db.dialect.MsSql; | |||
import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import org.sonar.server.platform.db.migration.version.v85.util.DropMsSQLDefaultConstraintsBuilder; | |||
public class DropUnusedPeriodsInSnapshots extends DdlChange { | |||
private static final String TABLE_NAME = "snapshots"; | |||
private static final String[] COLUMNS = {"period2_mode", "period2_param", "period2_date", | |||
"period3_mode", "period3_param", "period3_date", "period4_mode", "period4_param", "period4_date", "period5_mode", | |||
"period5_param", "period5_date"}; | |||
private final Database db; | |||
public DropUnusedPeriodsInSnapshots(Database db) { | |||
super(db); | |||
this.db = db; | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new DropColumnsBuilder(getDialect(), TABLE_NAME, "period2_mode", "period2_param", "period2_date", | |||
"period3_mode", "period3_param", "period3_date", "period4_mode", "period4_param", "period4_date", "period5_mode", "period5_param", "period5_date").build()); | |||
if (MsSql.ID.equals(db.getDialect().getId())) { | |||
context.execute(new DropMsSQLDefaultConstraintsBuilder(db).setTable(TABLE_NAME).setColumns(COLUMNS).build()); | |||
} | |||
context.execute(new DropColumnsBuilder(getDialect(), TABLE_NAME, COLUMNS).build()); | |||
} | |||
} |
@@ -21,18 +21,26 @@ package org.sonar.server.platform.db.migration.version.v85; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.db.dialect.MsSql; | |||
import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import org.sonar.server.platform.db.migration.version.v85.util.DropMsSQLDefaultConstraintsBuilder; | |||
public class DropUnusedVariationsInProjectMeasures extends DdlChange { | |||
private static final String TABLE_NAME = "project_measures"; | |||
private static final String[] COLUMNS = {"variation_value_2", "variation_value_3", "variation_value_4", "variation_value_5"}; | |||
private final Database db; | |||
public DropUnusedVariationsInProjectMeasures(Database db) { | |||
super(db); | |||
this.db = db; | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new DropColumnsBuilder(getDialect(), TABLE_NAME, "variation_value_2", "variation_value_3", "variation_value_4", "variation_value_5").build()); | |||
if (MsSql.ID.equals(db.getDialect().getId())) { | |||
context.execute(new DropMsSQLDefaultConstraintsBuilder(db).setTable(TABLE_NAME).setColumns(COLUMNS).build()); | |||
} | |||
context.execute(new DropColumnsBuilder(getDialect(), TABLE_NAME, COLUMNS).build()); | |||
} | |||
} |
@@ -0,0 +1,90 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.platform.db.migration.version.v85.util; | |||
import com.google.common.base.Preconditions; | |||
import java.sql.Connection; | |||
import java.sql.PreparedStatement; | |||
import java.sql.ResultSet; | |||
import java.sql.SQLException; | |||
import java.util.Arrays; | |||
import java.util.LinkedList; | |||
import java.util.List; | |||
import java.util.stream.Collectors; | |||
import org.sonar.db.Database; | |||
import org.sonar.db.dialect.MsSql; | |||
import static java.lang.String.format; | |||
public class DropMsSQLDefaultConstraintsBuilder { | |||
private final Database db; | |||
private String tableName; | |||
private String[] columns; | |||
public DropMsSQLDefaultConstraintsBuilder(Database db) { | |||
this.db = db; | |||
} | |||
public DropMsSQLDefaultConstraintsBuilder setTable(String s) { | |||
this.tableName = s; | |||
return this; | |||
} | |||
public DropMsSQLDefaultConstraintsBuilder setColumns(String... columns) { | |||
this.columns = columns; | |||
return this; | |||
} | |||
public List<String> build() throws SQLException { | |||
Preconditions.checkArgument(columns.length > 0, "At least one column expected."); | |||
Preconditions.checkArgument(MsSql.ID.equals(db.getDialect().getId()), "Expected MsSql dialect was: " + db.getDialect().getId()); | |||
return getMsSqlDropDefaultConstraintQueries(); | |||
} | |||
private List<String> getMsSqlDropDefaultConstraintQueries() throws SQLException { | |||
List<String> dropQueries = new LinkedList<>(); | |||
if (MsSql.ID.equals(db.getDialect().getId())) { | |||
List<String> defaultConstraints = getMssqlDefaultConstraints(); | |||
for (String defaultConstraintName : defaultConstraints) { | |||
dropQueries.add("ALTER TABLE " + tableName + " DROP CONSTRAINT " + defaultConstraintName); | |||
} | |||
} | |||
return dropQueries; | |||
} | |||
private List<String> getMssqlDefaultConstraints() throws SQLException { | |||
List<String> defaultConstrainNames = new LinkedList<>(); | |||
String commaSeparatedListOfColumns = Arrays.stream(columns).map(s -> "'" + s + "'") | |||
.collect(Collectors.joining(",")); | |||
try (Connection connection = db.getDataSource().getConnection(); | |||
PreparedStatement pstmt = connection | |||
.prepareStatement(format("SELECT d.name FROM sys.tables t " | |||
+ "JOIN sys.default_constraints d ON d.parent_object_id = t.object_id " | |||
+ "JOIN sys.columns c ON c.object_id = t.object_id AND c.column_id = d.parent_column_id " | |||
+ "WHERE t.name = '%s' AND c.name in (%s)", tableName, commaSeparatedListOfColumns)); | |||
ResultSet rs = pstmt.executeQuery()) { | |||
while (rs.next()) { | |||
defaultConstrainNames.add(rs.getString(1)); | |||
} | |||
} | |||
return defaultConstrainNames; | |||
} | |||
} |
@@ -0,0 +1,77 @@ | |||
/* | |||
* SonarQube | |||
* Copyright (C) 2009-2020 SonarSource SA | |||
* mailto:info AT sonarsource DOT com | |||
* | |||
* This program is free software; you can redistribute it and/or | |||
* modify it under the terms of the GNU Lesser General Public | |||
* License as published by the Free Software Foundation; either | |||
* version 3 of the License, or (at your option) any later version. | |||
* | |||
* 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 program; if not, write to the Free Software Foundation, | |||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
*/ | |||
package org.sonar.server.platform.db.migration.version.v85.util; | |||
import java.sql.Connection; | |||
import java.sql.PreparedStatement; | |||
import java.sql.ResultSet; | |||
import javax.sql.DataSource; | |||
import org.junit.Test; | |||
import org.sonar.db.Database; | |||
import org.sonar.db.dialect.H2; | |||
import org.sonar.db.dialect.MsSql; | |||
import org.sonar.db.dialect.Oracle; | |||
import org.sonar.db.dialect.PostgreSql; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.mockito.ArgumentMatchers.anyString; | |||
import static org.mockito.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class DropMsSQLDefaultConstraintsBuilderTest { | |||
private final Database db = mock(Database.class); | |||
@Test(expected = IllegalArgumentException.class) | |||
public void fail_if_oracle() throws Exception { | |||
when(db.getDialect()).thenReturn(new Oracle()); | |||
new DropMsSQLDefaultConstraintsBuilder(db).setTable("snapshots").setColumns("variation_value_2", "variation_value_3").build(); | |||
} | |||
@Test(expected = IllegalArgumentException.class) | |||
public void fail_if_h2() throws Exception { | |||
when(db.getDialect()).thenReturn(new H2()); | |||
new DropMsSQLDefaultConstraintsBuilder(db).setTable("snapshots").setColumns("variation_value_2", "variation_value_3").build(); | |||
} | |||
@Test(expected = IllegalArgumentException.class) | |||
public void fail_if_postgres() throws Exception { | |||
when(db.getDialect()).thenReturn(new PostgreSql()); | |||
new DropMsSQLDefaultConstraintsBuilder(db).setTable("snapshots").setColumns("variation_value_2", "variation_value_3").build(); | |||
} | |||
@Test | |||
public void generate_queries_for_mssql() throws Exception { | |||
when(db.getDialect()).thenReturn(new MsSql()); | |||
DataSource dataSource = mock(DataSource.class); | |||
when(db.getDataSource()).thenReturn(dataSource); | |||
Connection connection = mock(Connection.class); | |||
when(dataSource.getConnection()).thenReturn(connection); | |||
PreparedStatement statement = mock(PreparedStatement.class); | |||
when(connection.prepareStatement(anyString())).thenReturn(statement); | |||
ResultSet rsMock = mock(ResultSet.class); | |||
when(statement.executeQuery()).thenReturn(rsMock); | |||
when(rsMock.next()).thenReturn(true, true, false); | |||
when(rsMock.getString(1)).thenReturn("DF__A1", "DF__A2"); | |||
assertThat(new DropMsSQLDefaultConstraintsBuilder(db).setTable("snapshots").setColumns("variation_value_2", "variation_value_3").build()) | |||
.containsExactly("ALTER TABLE snapshots DROP CONSTRAINT DF__A1", "ALTER TABLE snapshots DROP CONSTRAINT DF__A2"); | |||
} | |||
} |