+ "WHERE table_name = '%s' and constraint_type = 'PRIMARY KEY'", tableName.toUpperCase(Locale.ENGLISH));
}
- static IllegalStateException constraintNotFoundException(String tableName) {
- return new IllegalStateException(format("Cannot find constraint for table '%s'", tableName));
- }
-
// FIXME:: this method should be moved somewhere else
String getPostgresSqlSequence(String tableName, String columnName) throws SQLException {
try (Connection connection = db.getDataSource().getConnection();
return res;
}
+ protected Database getDatabase() {
+ return db;
+ }
+
public static class Context {
private final Database db;
private final Connection readConnection;
*/
package org.sonar.server.platform.db.migration.version.v91;
+import java.sql.SQLException;
import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
import org.sonar.server.platform.db.migration.def.BigIntegerColumnDef;
import org.sonar.server.platform.db.migration.def.ColumnDef;
import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder;
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
-import java.sql.SQLException;
public class CreateAuditTable extends DdlChange {
@Override
public void execute(Context context) throws SQLException {
+ if (auditTableExists()) {
+ return;
+ }
+
BigIntegerColumnDef createdAtColumn = newBigIntegerColumnDefBuilder().setColumnName("created_at").setIsNullable(false).build();
var tableName = "audits";
context.execute(new CreateTableBuilder(getDialect(), tableName)
private static VarcharColumnDef.Builder newVarcharColumnBuilder(String column) {
return newVarcharColumnDefBuilder().setColumnName(column);
}
+
+ private boolean auditTableExists() throws SQLException {
+ try (var connection = getDatabase().getDataSource().getConnection()) {
+ return DatabaseUtils.tableExists("audits", connection);
+ }
+ }
}
import java.sql.SQLException;
import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
import org.sonar.server.platform.db.migration.step.DataChange;
abstract class DropCustomMetricsData extends DataChange {
@Override
protected void execute(Context context) throws SQLException {
+ if (!checkIfUserManagedColumnExists()) {
+ return;
+ }
+
var massUpdate = context.prepareMassUpdate();
massUpdate.select(selectQuery()).setBoolean(1, true);
massUpdate.update(updateQuery());
});
}
+ private boolean checkIfUserManagedColumnExists() throws SQLException {
+ try (var connection = getDatabase().getDataSource().getConnection()) {
+ if (DatabaseUtils.tableColumnExists(connection, "metrics", "user_managed")) {
+ return true;
+ }
+ }
+ return false;
+ }
+
abstract String selectQuery();
abstract String updateQuery();
import java.sql.SQLException;
import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
import org.sonar.server.platform.db.migration.sql.DropTableBuilder;
import org.sonar.server.platform.db.migration.step.DdlChange;
@Override
public void execute(Context context) throws SQLException {
+ if (!manualMeasuresExists()) {
+ return;
+ }
context.execute(new DropTableBuilder(getDialect(), TABLE_NAME).build());
}
+
+ private boolean manualMeasuresExists() throws SQLException {
+ try (var connection = getDatabase().getDataSource().getConnection()) {
+ return DatabaseUtils.tableExists(TABLE_NAME, connection);
+ }
+ }
}
import java.sql.SQLException;
import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
import org.sonar.db.dialect.MsSql;
import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder;
import org.sonar.server.platform.db.migration.sql.DropMsSQLDefaultConstraintsBuilder;
private static final String TABLE_NAME = "metrics";
private static final String COLUMN = "user_managed";
- private final Database db;
-
public DropUserManagedColumnFromMetricsTable(Database db) {
super(db);
- this.db = db;
}
@Override
public void execute(Context context) throws SQLException {
- if (MsSql.ID.equals(db.getDialect().getId())) {
- context.execute(new DropMsSQLDefaultConstraintsBuilder(db).setTable(TABLE_NAME).setColumns(COLUMN).build());
+ if (!checkIfUseManagedColumnExists()) {
+ return;
+ }
+
+ if (MsSql.ID.equals(getDatabase().getDialect().getId())) {
+ context.execute(new DropMsSQLDefaultConstraintsBuilder(getDatabase()).setTable(TABLE_NAME).setColumns(COLUMN).build());
+ }
+ context.execute(new DropColumnsBuilder(getDatabase().getDialect(), TABLE_NAME, COLUMN).build());
+ }
+
+ private boolean checkIfUseManagedColumnExists() throws SQLException {
+ try (var connection = getDatabase().getDataSource().getConnection()) {
+ if (DatabaseUtils.tableColumnExists(connection, TABLE_NAME, COLUMN)) {
+ return true;
+ }
}
- context.execute(new DropColumnsBuilder(db.getDialect(), TABLE_NAME, COLUMN).build());
+ return false;
}
}
db.assertTableExists(TABLE_NAME);
db.assertIndex(TABLE_NAME, "audits_created_at", "created_at");
}
+
+ @Test
+ public void migration_should_be_reentrant() throws SQLException {
+ db.assertTableDoesNotExist(TABLE_NAME);
+
+ underTest.execute();
+ //re-entrant
+ underTest.execute();
+
+ db.assertTableExists(TABLE_NAME);
+ db.assertIndex(TABLE_NAME, "audits_created_at", "created_at");
+ }
}
@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(DropCustomMetricsLiveMeasuresDataTest.class, "schema.sql");
+ @Rule
+ public final CoreDbTester dbWithoutColumn = CoreDbTester.createForSchema(DropCustomMetricsLiveMeasuresDataTest.class, "no_user_managed_column.sql");
+
private final DataChange underTest = new DropCustomMetricsLiveMeasuresData(db.database());
@Test
.containsExactlyInAnyOrder("lm-1", "lm-2", "lm-3", "lm-4");
}
+ @Test
+ public void does_not_fail_when_no_user_managed_column() throws SQLException {
+ insertMetric("metric-1", false);
+ insertMetric("metric-2", false);
+
+ insertLiveMeasure("lm-1", "metric-1");
+ insertLiveMeasure("lm-2", "metric-1");
+ insertLiveMeasure("lm-3", "metric-2");
+ insertLiveMeasure("lm-4", "metric-2");
+
+ DataChange underTest = new DropCustomMetricsLiveMeasuresData(dbWithoutColumn.database());
+ underTest.execute();
+
+ assertThat(db.select("select uuid from live_measures").stream().map(row -> row.get("UUID")).collect(Collectors.toList()))
+ .containsExactlyInAnyOrder("lm-1", "lm-2", "lm-3", "lm-4");
+ }
+
private void insertLiveMeasure(String uuid, String metricUuid) {
db.executeInsert("live_measures",
"UUID", uuid,
@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(DropCustomMetricsProjectMeasuresDataTest.class, "schema.sql");
+ @Rule
+ public final CoreDbTester dbWithoutColumn = CoreDbTester.createForSchema(DropCustomMetricsProjectMeasuresDataTest.class, "no_user_managed_column.sql");
+
private final DataChange underTest = new DropCustomMetricsProjectMeasuresData(db.database());
@Test
.containsExactlyInAnyOrder("pm-1", "pm-2", "pm-3", "pm-4");
}
+ @Test
+ public void does_not_fail_when_no_user_managed_column() throws SQLException {
+ insertMetric("metric-1", false);
+ insertMetric("metric-2", false);
+
+ insertProjectMeasure("pm-1", "metric-1");
+ insertProjectMeasure("pm-2", "metric-1");
+ insertProjectMeasure("pm-3", "metric-2");
+ insertProjectMeasure("pm-4", "metric-2");
+
+ DataChange underTest = new DropCustomMetricsProjectMeasuresData(dbWithoutColumn.database());
+ underTest.execute();
+
+ assertThat(db.select("select uuid from project_measures").stream().map(row -> row.get("UUID")).collect(Collectors.toList()))
+ .containsExactlyInAnyOrder("pm-1", "pm-2", "pm-3", "pm-4");
+ }
+
private void insertProjectMeasure(String uuid, String metricUuid) {
db.executeInsert("project_measures",
"UUID", uuid,
underTest.execute();
db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
}
+
+ @Test
+ public void migration_should_be_reentrant() throws SQLException {
+ db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.BOOLEAN, null, true);
+ underTest.execute();
+ // re-entrant
+ underTest.execute();
+ db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
+ }
}
@Rule
public final CoreDbTester db = CoreDbTester.createForSchema(DropUserManagedMetricsDataTest.class, "schema.sql");
+ @Rule
+ public final CoreDbTester dbWithoutColumn = CoreDbTester.createForSchema(DropUserManagedMetricsDataTest.class, "no_user_managed_column.sql");
+
private final DataChange underTest = new DropUserManagedMetricsData(db.database());
@Test
assertThat(db.countRowsOfTable(TABLE_NAME)).isEqualTo(3);
}
+ @Test
+ public void does_not_fail_when_no_user_managed_column() throws SQLException {
+ insertMetric("1", false);
+ insertMetric("2", false);
+ insertMetric("3", false);
+
+ DataChange underTest = new DropCustomMetricsProjectMeasuresData(dbWithoutColumn.database());
+ underTest.execute();
+
+ assertThat(db.countRowsOfTable(TABLE_NAME)).isEqualTo(3);
+ }
+
private void insertMetric(String uuid, boolean userManaged) {
db.executeInsert(TABLE_NAME,
"UUID", uuid,
--- /dev/null
+CREATE TABLE "METRICS"(
+ "UUID" VARCHAR(40) NOT NULL,
+ "NAME" VARCHAR(64) NOT NULL,
+ "DESCRIPTION" VARCHAR(255),
+ "DIRECTION" INTEGER DEFAULT 0 NOT NULL,
+ "DOMAIN" VARCHAR(64),
+ "SHORT_NAME" VARCHAR(64),
+ "QUALITATIVE" BOOLEAN DEFAULT FALSE NOT NULL,
+ "VAL_TYPE" VARCHAR(8),
+ "ENABLED" BOOLEAN DEFAULT TRUE,
+ "WORST_VALUE" DOUBLE,
+ "BEST_VALUE" DOUBLE,
+ "OPTIMIZED_BEST_VALUE" BOOLEAN,
+ "HIDDEN" BOOLEAN,
+ "DELETE_HISTORICAL_DATA" BOOLEAN,
+ "DECIMAL_SCALE" INTEGER
+);
+ALTER TABLE "METRICS" ADD CONSTRAINT "PK_METRICS" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "METRICS_UNIQUE_NAME" ON "METRICS"("NAME");
--- /dev/null
+CREATE TABLE "METRICS"(
+ "UUID" VARCHAR(40) NOT NULL,
+ "NAME" VARCHAR(64) NOT NULL,
+ "DESCRIPTION" VARCHAR(255),
+ "DIRECTION" INTEGER DEFAULT 0 NOT NULL,
+ "DOMAIN" VARCHAR(64),
+ "SHORT_NAME" VARCHAR(64),
+ "QUALITATIVE" BOOLEAN DEFAULT FALSE NOT NULL,
+ "VAL_TYPE" VARCHAR(8),
+ "ENABLED" BOOLEAN DEFAULT TRUE,
+ "WORST_VALUE" DOUBLE,
+ "BEST_VALUE" DOUBLE,
+ "OPTIMIZED_BEST_VALUE" BOOLEAN,
+ "HIDDEN" BOOLEAN,
+ "DELETE_HISTORICAL_DATA" BOOLEAN,
+ "DECIMAL_SCALE" INTEGER
+);
+ALTER TABLE "METRICS" ADD CONSTRAINT "PK_METRICS" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "METRICS_UNIQUE_NAME" ON "METRICS"("NAME");
--- /dev/null
+CREATE TABLE "METRICS"(
+ "UUID" VARCHAR(40) NOT NULL,
+ "NAME" VARCHAR(64) NOT NULL,
+ "DESCRIPTION" VARCHAR(255),
+ "DIRECTION" INTEGER DEFAULT 0 NOT NULL,
+ "DOMAIN" VARCHAR(64),
+ "SHORT_NAME" VARCHAR(64),
+ "QUALITATIVE" BOOLEAN DEFAULT FALSE NOT NULL,
+ "VAL_TYPE" VARCHAR(8),
+ "ENABLED" BOOLEAN DEFAULT TRUE,
+ "WORST_VALUE" DOUBLE,
+ "BEST_VALUE" DOUBLE,
+ "OPTIMIZED_BEST_VALUE" BOOLEAN,
+ "HIDDEN" BOOLEAN,
+ "DELETE_HISTORICAL_DATA" BOOLEAN,
+ "DECIMAL_SCALE" INTEGER
+);
+ALTER TABLE "METRICS" ADD CONSTRAINT "PK_METRICS" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "METRICS_UNIQUE_NAME" ON "METRICS"("NAME");