@@ -19,7 +19,6 @@ | |||
*/ | |||
package org.sonar.ce.task.projectanalysis.step; | |||
import com.google.common.base.Predicate; | |||
import java.util.Collection; | |||
import java.util.Date; | |||
import java.util.Map; | |||
@@ -27,8 +26,8 @@ import java.util.Optional; | |||
import java.util.Set; | |||
import java.util.function.Function; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.StreamSupport; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nonnull; | |||
import javax.annotation.Nullable; | |||
import org.apache.commons.lang.StringUtils; | |||
import org.sonar.api.resources.Qualifiers; | |||
@@ -51,7 +50,6 @@ import org.sonar.db.DbSession; | |||
import org.sonar.db.component.ComponentDto; | |||
import org.sonar.db.component.ComponentUpdateDto; | |||
import static com.google.common.collect.FluentIterable.from; | |||
import static java.util.Optional.ofNullable; | |||
import static org.sonar.ce.task.projectanalysis.component.ComponentVisitor.Order.PRE_ORDER; | |||
import static org.sonar.db.component.ComponentDto.UUID_PATH_OF_ROOT; | |||
@@ -166,7 +164,6 @@ public class PersistComponentsStep implements ComputationStep { | |||
private final DbSession dbSession; | |||
@Nullable | |||
private final String mainBranchProjectUuid; | |||
private int componentRef = 1; | |||
PersistComponentStepsVisitor(Map<String, ComponentDto> existingComponentDtosByUuids, DbSession dbSession, @Nullable String mainBranchProjectUuid) { | |||
super( | |||
@@ -395,9 +392,9 @@ public class PersistComponentsStep implements ComputationStep { | |||
private static void setParentModuleProperties(ComponentDto componentDto, PathAwareVisitor.Path<ComponentDtoHolder> path) { | |||
componentDto.setProjectUuid(path.root().getDto().uuid()); | |||
ComponentDto parentModule = from(path.getCurrentPath()) | |||
.filter(ParentModulePathElement.INSTANCE) | |||
.first() | |||
ComponentDto parentModule = StreamSupport.stream(path.getCurrentPath().spliterator(), false) | |||
.filter(p -> p.getComponent().getType() == Component.Type.PROJECT) | |||
.findFirst() | |||
.get() | |||
.getElement().getDto(); | |||
componentDto.setUuidPath(formatUuidPathFromParent(path.parent().getDto())); | |||
@@ -446,14 +443,4 @@ public class PersistComponentsStep implements ComputationStep { | |||
this.dto = dto; | |||
} | |||
} | |||
private enum ParentModulePathElement implements Predicate<PathAwareVisitor.PathElement<ComponentDtoHolder>> { | |||
INSTANCE; | |||
@Override | |||
public boolean apply(@Nonnull PathAwareVisitor.PathElement<ComponentDtoHolder> input) { | |||
return input.getComponent().getType() == Component.Type.PROJECT; | |||
} | |||
} | |||
} |
@@ -320,11 +320,11 @@ CREATE TABLE "GROUP_ROLES"( | |||
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL, | |||
"GROUP_ID" INTEGER, | |||
"ROLE" VARCHAR(64) NOT NULL, | |||
"COMPONENT_UUID" VARCHAR(50) | |||
"COMPONENT_UUID" VARCHAR(40) | |||
); | |||
ALTER TABLE "GROUP_ROLES" ADD CONSTRAINT "PK_GROUP_ROLES" PRIMARY KEY("ID"); | |||
CREATE INDEX "GROUP_ROLES_COMPONENT_UUID" ON "GROUP_ROLES"("COMPONENT_UUID"); | |||
CREATE UNIQUE INDEX "GROUP_ROLES_UNIQ" ON "GROUP_ROLES"("ORGANIZATION_UUID", "GROUP_ID", "COMPONENT_UUID", "ROLE"); | |||
CREATE UNIQUE INDEX "UNIQ_GROUP_ROLES" ON "GROUP_ROLES"("ORGANIZATION_UUID", "GROUP_ID", "COMPONENT_UUID", "ROLE"); | |||
CREATE TABLE "GROUPS"( | |||
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1), | |||
@@ -737,11 +737,10 @@ CREATE TABLE "PROPERTIES"( | |||
"TEXT_VALUE" VARCHAR(4000), | |||
"CLOB_VALUE" CLOB(2147483647), | |||
"CREATED_AT" BIGINT NOT NULL, | |||
"COMPONENT_UUID" VARCHAR(50) | |||
"COMPONENT_UUID" VARCHAR(40) | |||
); | |||
ALTER TABLE "PROPERTIES" ADD CONSTRAINT "PK_PROPERTIES" PRIMARY KEY("ID"); | |||
CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES"("PROP_KEY"); | |||
CREATE INDEX "PROPERTIES_COMPONENT_UUID" ON "PROPERTIES"("COMPONENT_UUID"); | |||
CREATE TABLE "QPROFILE_CHANGES"( | |||
"KEE" VARCHAR(40) NOT NULL, | |||
@@ -929,7 +928,7 @@ CREATE TABLE "USER_ROLES"( | |||
"ORGANIZATION_UUID" VARCHAR(40) NOT NULL, | |||
"USER_ID" INTEGER, | |||
"ROLE" VARCHAR(64) NOT NULL, | |||
"COMPONENT_UUID" VARCHAR(50) | |||
"COMPONENT_UUID" VARCHAR(40) | |||
); | |||
ALTER TABLE "USER_ROLES" ADD CONSTRAINT "PK_USER_ROLES" PRIMARY KEY("ID"); | |||
CREATE INDEX "USER_ROLES_USER" ON "USER_ROLES"("USER_ID"); |
@@ -29,6 +29,8 @@ import org.sonar.server.platform.db.migration.version.v80.DbVersion80; | |||
import org.sonar.server.platform.db.migration.version.v81.DbVersion81; | |||
import org.sonar.server.platform.db.migration.version.v82.DbVersion82; | |||
import org.sonar.server.platform.db.migration.version.v83.DbVersion83; | |||
import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator; | |||
import org.sonar.server.platform.db.migration.version.v83.util.GetConstraintHelper; | |||
public class MigrationConfigurationModule extends Module { | |||
@Override | |||
@@ -47,6 +49,10 @@ public class MigrationConfigurationModule extends Module { | |||
// history | |||
MigrationHistoryImpl.class, | |||
MigrationHistoryMeddler.class); | |||
MigrationHistoryMeddler.class, | |||
// Only needed for 8.3 | |||
GetConstraintHelper.class, | |||
DropPrimaryKeySqlGenerator.class); | |||
} | |||
} |
@@ -53,6 +53,8 @@ import static org.sonar.server.platform.db.migration.def.Validations.validateTab | |||
public class CreateTableBuilder { | |||
public static final String PRIMARY_KEY_PREFIX = "pk_"; | |||
private final Dialect dialect; | |||
private final String tableName; | |||
private final List<ColumnDef> columnDefs = new ArrayList<>(); | |||
@@ -234,7 +236,7 @@ public class CreateTableBuilder { | |||
private void appendPkConstraintName(StringBuilder res) { | |||
if (pkConstraintName == null) { | |||
res.append("pk_").append(tableName); | |||
res.append(PRIMARY_KEY_PREFIX).append(tableName); | |||
} else { | |||
res.append(pkConstraintName.toLowerCase(Locale.ENGLISH)); | |||
} |
@@ -26,14 +26,12 @@ import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import static org.sonar.server.platform.db.migration.def.IntegerColumnDef.newIntegerColumnDefBuilder; | |||
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; | |||
public class AddComponentUuidColumnToGroupRoles extends DdlChange { | |||
public class AddComponentUuidColumnToGroupRoles extends DdlChange { | |||
private static final String TABLE = "group_roles"; | |||
private static final String NEW_COLUMN = "component_uuid"; | |||
private static final String INDEX1 = "group_roles_component_uuid"; | |||
private static final String INDEX2 = "group_roles_uniq"; | |||
public AddComponentUuidColumnToGroupRoles(Database db) { | |||
super(db); | |||
@@ -43,7 +41,7 @@ public class AddComponentUuidColumnToGroupRoles extends DdlChange { | |||
public void execute(Context context) throws SQLException { | |||
VarcharColumnDef column = newVarcharColumnDefBuilder() | |||
.setColumnName(NEW_COLUMN) | |||
.setLimit(50) | |||
.setLimit(VarcharColumnDef.UUID_SIZE) | |||
.setIsNullable(true) | |||
.build(); | |||
context.execute(new AddColumnsBuilder(getDialect(), TABLE) | |||
@@ -56,17 +54,5 @@ public class AddComponentUuidColumnToGroupRoles extends DdlChange { | |||
.setName(INDEX1) | |||
.setUnique(false); | |||
context.execute(index1.build()); | |||
CreateIndexBuilder index2 = new CreateIndexBuilder() | |||
.setTable(TABLE) | |||
.addColumn(newVarcharColumnDefBuilder().setColumnName("organization_uuid").setLimit(40).build()) | |||
.addColumn(newIntegerColumnDefBuilder().setColumnName("group_id").build()) | |||
.addColumn(column) | |||
.addColumn(newVarcharColumnDefBuilder().setColumnName("role").setLimit(64).build()) | |||
.setName(INDEX2) | |||
.setUnique(true); | |||
context.execute(index2.build()); | |||
} | |||
} |
@@ -23,7 +23,6 @@ import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.def.VarcharColumnDef; | |||
import org.sonar.server.platform.db.migration.sql.AddColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; | |||
@@ -31,7 +30,6 @@ import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVar | |||
public class AddComponentUuidColumnToProperties extends DdlChange { | |||
private static final String TABLE = "properties"; | |||
private static final String NEW_COLUMN = "component_uuid"; | |||
private static final String INDEX = "properties_component_uuid"; | |||
public AddComponentUuidColumnToProperties(Database db) { | |||
super(db); | |||
@@ -41,19 +39,11 @@ public class AddComponentUuidColumnToProperties extends DdlChange { | |||
public void execute(Context context) throws SQLException { | |||
VarcharColumnDef column = newVarcharColumnDefBuilder() | |||
.setColumnName(NEW_COLUMN) | |||
.setLimit(50) | |||
.setLimit(VarcharColumnDef.UUID_SIZE) | |||
.setIsNullable(true) | |||
.build(); | |||
context.execute(new AddColumnsBuilder(getDialect(), TABLE) | |||
.addColumn(column) | |||
.build()); | |||
CreateIndexBuilder builder = new CreateIndexBuilder() | |||
.setTable(TABLE) | |||
.addColumn(column) | |||
.setName(INDEX) | |||
.setUnique(false); | |||
context.execute(builder.build()); | |||
} | |||
} |
@@ -41,18 +41,18 @@ public class AddComponentUuidColumnToUserRoles extends DdlChange { | |||
public void execute(Context context) throws SQLException { | |||
VarcharColumnDef column = newVarcharColumnDefBuilder() | |||
.setColumnName(NEW_COLUMN) | |||
.setLimit(50) | |||
.setLimit(VarcharColumnDef.UUID_SIZE) | |||
.setIsNullable(true) | |||
.build(); | |||
context.execute(new AddColumnsBuilder(getDialect(), TABLE) | |||
.addColumn(column) | |||
.build()); | |||
CreateIndexBuilder index1 = new CreateIndexBuilder() | |||
CreateIndexBuilder index = new CreateIndexBuilder() | |||
.setTable(TABLE) | |||
.addColumn(column) | |||
.setName(INDEX) | |||
.setUnique(false); | |||
context.execute(index1.build()); | |||
context.execute(index.build()); | |||
} | |||
} |
@@ -22,22 +22,24 @@ package org.sonar.server.platform.db.migration.version.v83; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.sql.DropConstraintBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator; | |||
public class DropIdFromComponentsTable extends DdlChange { | |||
static final String ORIGINAL_TABLE_NAME = "projects"; | |||
static final String TABLE_NAME = "components"; | |||
static final String INDEX_NAME = "pk_projects"; | |||
static final String COLUMN_NAME = "id"; | |||
public DropIdFromComponentsTable(Database db) { | |||
private final DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator; | |||
public DropIdFromComponentsTable(Database db, DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator) { | |||
super(db); | |||
this.dropPrimaryKeySqlGenerator = dropPrimaryKeySqlGenerator; | |||
} | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new DropConstraintBuilder(getDialect()).setTable(TABLE_NAME).setName(INDEX_NAME).build()); | |||
context.execute(dropPrimaryKeySqlGenerator.generate(TABLE_NAME, ORIGINAL_TABLE_NAME, COLUMN_NAME)); | |||
context.execute(new DropColumnsBuilder(getDialect(), TABLE_NAME, COLUMN_NAME).build()); | |||
} | |||
} |
@@ -21,14 +21,21 @@ package org.sonar.server.platform.db.migration.version.v83; | |||
import java.sql.SQLException; | |||
import org.sonar.db.Database; | |||
import org.sonar.server.platform.db.migration.def.VarcharColumnDef; | |||
import org.sonar.server.platform.db.migration.sql.CreateIndexBuilder; | |||
import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder; | |||
import org.sonar.server.platform.db.migration.sql.DropIndexBuilder; | |||
import org.sonar.server.platform.db.migration.step.DdlChange; | |||
import static org.sonar.server.platform.db.migration.def.IntegerColumnDef.newIntegerColumnDefBuilder; | |||
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder; | |||
public class DropResourceIdFromGroupRolesTable extends DdlChange { | |||
static final String TABLE = "group_roles"; | |||
static final String COLUMN = "resource_id"; | |||
static final String INDEX = "uniq_group_roles"; | |||
public DropResourceIdFromGroupRolesTable(Database db) { | |||
super(db); | |||
@@ -36,8 +43,18 @@ public class DropResourceIdFromGroupRolesTable extends DdlChange { | |||
@Override | |||
public void execute(Context context) throws SQLException { | |||
context.execute(new DropIndexBuilder(getDialect()).setTable(TABLE).setName("uniq_group_roles").build()); | |||
context.execute(new DropIndexBuilder(getDialect()).setTable(TABLE).setName(INDEX).build()); | |||
context.execute(new DropIndexBuilder(getDialect()).setTable(TABLE).setName("group_roles_resource").build()); | |||
context.execute(new DropColumnsBuilder(getDialect(), TABLE, COLUMN).build()); | |||
CreateIndexBuilder index = new CreateIndexBuilder() | |||
.setTable(TABLE) | |||
.addColumn(newVarcharColumnDefBuilder().setColumnName("organization_uuid").setLimit(VarcharColumnDef.UUID_SIZE).build()) | |||
.addColumn(newIntegerColumnDefBuilder().setColumnName("group_id").build()) | |||
.addColumn(newVarcharColumnDefBuilder().setColumnName("component_uuid").setLimit(VarcharColumnDef.UUID_SIZE).build()) | |||
.addColumn(newVarcharColumnDefBuilder().setColumnName("role").setLimit(64).build()) | |||
.setName(INDEX) | |||
.setUnique(true); | |||
context.execute(index.build()); | |||
} | |||
} |
@@ -31,25 +31,21 @@ public class MigrateResourceIdToUuidInGroupRoles extends DataChange { | |||
@Override protected void execute(Context context) throws SQLException { | |||
// remove roles associated with invalid resource | |||
context.prepareUpsert( | |||
"delete from group_roles gp where gp.resource_id is not null " | |||
+ "and not exists (select 1 from components c where gp.resource_id = c.id)") | |||
context.prepareUpsert("delete from group_roles " | |||
+ "where group_roles.resource_id is not null and not exists (select 1 from components c where group_roles.resource_id = c.id)") | |||
.execute(); | |||
MassUpdate massUpdate = context.prepareMassUpdate(); | |||
massUpdate.select("select gp.id as gp_id, c.uuid as c_uuid from group_roles gp left join components c on gp.resource_id = c.id"); | |||
massUpdate.select("select gp.id as gp_id, c.uuid as c_uuid from group_roles gp, components c where gp.resource_id = c.id and gp.component_uuid is null"); | |||
massUpdate.update("update group_roles set component_uuid = ? where id = ?"); | |||
massUpdate.execute((row, update) -> { | |||
String componentUuid = row.getString(2); | |||
if (componentUuid != null) { | |||
Long propertyId = row.getLong(1); | |||
Long propertyId = row.getLong(1); | |||
update.setString(1, componentUuid) | |||
.setLong(2, propertyId); | |||
return true; | |||
} | |||
return false; | |||
update.setString(1, componentUuid) | |||
.setLong(2, propertyId); | |||
return true; | |||
}); | |||
} | |||
} |
@@ -31,26 +31,21 @@ public class MigrateResourceIdToUuidInProperties extends DataChange { | |||
@Override protected void execute(Context context) throws SQLException { | |||
// remove properties associated with invalid resource | |||
context.prepareUpsert( | |||
"delete from properties p where p.resource_id is not null " | |||
+ "and not exists (select 1 from components c where p.resource_id = c.id)") | |||
context.prepareUpsert("delete from properties where properties.resource_id is not null and not exists (select 1 from components c where properties.resource_id = c.id)") | |||
.execute(); | |||
MassUpdate massUpdate = context.prepareMassUpdate(); | |||
massUpdate.select("select p.id as p_id, c.uuid as c_uuid from properties p left join components c on p.resource_id = c.id"); | |||
massUpdate.select("select p.id as p_id, c.uuid as c_uuid from properties p, components c where p.resource_id = c.id and p.component_uuid is null"); | |||
massUpdate.update("update properties set component_uuid = ? where id = ?"); | |||
massUpdate.execute((row, update) -> { | |||
String componentUuid = row.getString(2); | |||
if (componentUuid != null) { | |||
Long propertyId = row.getLong(1); | |||
Long propertyId = row.getLong(1); | |||
update.setString(1, componentUuid) | |||
.setLong(2, propertyId); | |||
return true; | |||
} | |||
return false; | |||
update.setString(1, componentUuid) | |||
.setLong(2, propertyId); | |||
return true; | |||
}); | |||
} | |||
} |
@@ -32,25 +32,21 @@ public class MigrateResourceIdToUuidInUserRoles extends DataChange { | |||
@Override protected void execute(Context context) throws SQLException { | |||
// remove roles associated with invalid resource | |||
context.prepareUpsert( | |||
"delete from user_roles ur where ur.resource_id is not null " | |||
+ "and not exists (select 1 from components c where ur.resource_id = c.id)") | |||
"delete from user_roles where user_roles.resource_id is not null and not exists (select 1 from components c where user_roles.resource_id = c.id)") | |||
.execute(); | |||
MassUpdate massUpdate = context.prepareMassUpdate(); | |||
massUpdate.select("select ur.id as ur_id, c.uuid as c_uuid from user_roles ur left join components c on ur.resource_id = c.id"); | |||
massUpdate.select("select ur.id as ur_id, c.uuid as c_uuid from user_roles ur, components c where ur.resource_id = c.id and ur.component_uuid is null"); | |||
massUpdate.update("update user_roles set component_uuid = ? where id = ?"); | |||
massUpdate.execute((row, update) -> { | |||
String componentUuid = row.getString(2); | |||
if (componentUuid != null) { | |||
Long id = row.getLong(1); | |||
Long id = row.getLong(1); | |||
update.setString(1, componentUuid) | |||
.setLong(2, id); | |||
return true; | |||
} | |||
return false; | |||
update.setString(1, componentUuid) | |||
.setLong(2, id); | |||
return true; | |||
}); | |||
} | |||
} |
@@ -0,0 +1,87 @@ | |||
/* | |||
* 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.v83.util; | |||
import java.sql.SQLException; | |||
import java.util.List; | |||
import org.sonar.db.Database; | |||
import org.sonar.db.dialect.Dialect; | |||
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 java.lang.String.format; | |||
import static java.util.Arrays.asList; | |||
import static java.util.Collections.singletonList; | |||
import static java.util.Locale.ENGLISH; | |||
import static org.sonar.server.platform.db.migration.sql.CreateTableBuilder.PRIMARY_KEY_PREFIX; | |||
public class DropPrimaryKeySqlGenerator { | |||
private final Database db; | |||
private final GetConstraintHelper getConstraintHelper; | |||
public DropPrimaryKeySqlGenerator(Database db, GetConstraintHelper getConstraintHelper) { | |||
this.db = db; | |||
this.getConstraintHelper = getConstraintHelper; | |||
} | |||
public List<String> generate(String tableName, String originalTableName, String columnName) throws SQLException { | |||
Dialect dialect = db.getDialect(); | |||
switch (dialect.getId()) { | |||
case PostgreSql.ID: | |||
return generateForPostgresSql(tableName, originalTableName, columnName, getConstraintHelper.getPostgresSqlConstraint(tableName)); | |||
case MsSql.ID: | |||
return generateForMsSql(tableName, getConstraintHelper.getMssqlConstraint(tableName)); | |||
case Oracle.ID: | |||
return generateForOracle(tableName, getConstraintHelper.getOracleConstraint(tableName)); | |||
case H2.ID: | |||
return generateForH2(tableName, originalTableName, columnName); | |||
default: | |||
throw new IllegalStateException(format("Unsupported database '%s'", dialect.getId())); | |||
} | |||
} | |||
private static List<String> generateForPostgresSql(String tableName, String originalTableName, String column, String constraintName) { | |||
return asList( | |||
format("ALTER TABLE %s ALTER COLUMN %s DROP DEFAULT", tableName, column), | |||
format("DROP SEQUENCE %s_%s_seq", originalTableName, column), | |||
format("ALTER TABLE %s DROP CONSTRAINT %s", tableName, constraintName)); | |||
} | |||
private static List<String> generateForOracle(String tableName, String constraintName) { | |||
return asList( | |||
format("DROP TRIGGER %s_IDT", tableName), | |||
format("DROP SEQUENCE %s_SEQ", tableName), | |||
format("ALTER TABLE %s DROP CONSTRAINT %s", tableName, constraintName)); | |||
} | |||
private static List<String> generateForMsSql(String tableName, String constraintName) { | |||
return singletonList(format("ALTER TABLE %s DROP CONSTRAINT %s", tableName, constraintName)); | |||
} | |||
private static List<String> generateForH2(String tableName, String originalTableName, String column) { | |||
return asList( | |||
format("ALTER TABLE %s DROP CONSTRAINT %s%s", tableName, PRIMARY_KEY_PREFIX.toUpperCase(ENGLISH), originalTableName), | |||
format("ALTER TABLE %s ALTER COLUMN %s INTEGER NOT NULL", tableName, column)); | |||
} | |||
} |
@@ -0,0 +1,104 @@ | |||
/* | |||
* 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.v83.util; | |||
import java.sql.Connection; | |||
import java.sql.PreparedStatement; | |||
import java.sql.ResultSet; | |||
import java.sql.SQLException; | |||
import java.util.Locale; | |||
import org.sonar.db.Database; | |||
import static java.lang.String.format; | |||
public class GetConstraintHelper { | |||
private final Database db; | |||
public GetConstraintHelper(Database db) { | |||
this.db = db; | |||
} | |||
String getH2Constraint(String tableName) throws SQLException { | |||
try (Connection connection = db.getDataSource().getConnection(); | |||
PreparedStatement pstmt = connection | |||
.prepareStatement(format("SELECT constraint_name " | |||
+ "FROM information_schema.constraints " | |||
+ "WHERE table_name = '%s' and constraint_type = 'PRIMARY KEY'", tableName.toUpperCase(Locale.ENGLISH))); | |||
ResultSet rs = pstmt.executeQuery()) { | |||
if (rs.next()) { | |||
return rs.getString(1); | |||
} | |||
throw contraintNotFoundException(tableName); | |||
} | |||
} | |||
String getPostgresSqlConstraint(String tableName) throws SQLException { | |||
try (Connection connection = db.getDataSource().getConnection(); | |||
PreparedStatement pstmt = connection | |||
.prepareStatement(format("SELECT conname " + | |||
"FROM pg_constraint " + | |||
"WHERE conrelid = " + | |||
" (SELECT oid " + | |||
" FROM pg_class " + | |||
" WHERE relname LIKE '%s')", tableName)); | |||
ResultSet rs = pstmt.executeQuery()) { | |||
if (rs.next()) { | |||
return rs.getString(1); | |||
} | |||
throw contraintNotFoundException(tableName); | |||
} | |||
} | |||
String getOracleConstraint(String tableName) throws SQLException { | |||
try (Connection connection = db.getDataSource().getConnection(); | |||
PreparedStatement pstmt = connection | |||
.prepareStatement(format("SELECT constraint_name " + | |||
"FROM user_constraints " + | |||
"WHERE table_name = UPPER('%s') " + | |||
"AND constraint_type='P'", tableName)); | |||
ResultSet rs = pstmt.executeQuery()) { | |||
if (rs.next()) { | |||
return rs.getString(1); | |||
} | |||
throw contraintNotFoundException(tableName); | |||
} | |||
} | |||
String getMssqlConstraint(String tableName) throws SQLException { | |||
try (Connection connection = db.getDataSource().getConnection(); | |||
PreparedStatement pstmt = connection | |||
.prepareStatement(format("SELECT name " + | |||
"FROM sys.key_constraints " + | |||
"WHERE type = 'PK' " + | |||
"AND OBJECT_NAME(parent_object_id) = '%s'", tableName)); | |||
ResultSet rs = pstmt.executeQuery()) { | |||
if (rs.next()) { | |||
return rs.getString(1); | |||
} | |||
throw contraintNotFoundException(tableName); | |||
} | |||
} | |||
private static IllegalStateException contraintNotFoundException(String tableName) { | |||
return new IllegalStateException(format("Cannot find constraint for table '%s'", tableName)); | |||
} | |||
} |
@@ -23,7 +23,6 @@ import org.junit.Test; | |||
import org.sonar.core.platform.ComponentContainer; | |||
import static org.assertj.core.api.Assertions.assertThat; | |||
import static org.sonar.core.platform.ComponentContainer.COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER; | |||
public class MigrationConfigurationModuleTest { | |||
private MigrationConfigurationModule underTest = new MigrationConfigurationModule(); | |||
@@ -34,12 +33,7 @@ public class MigrationConfigurationModuleTest { | |||
underTest.configure(container); | |||
assertThat(container.getPicoContainer().getComponentAdapters()) | |||
.hasSize(COMPONENTS_IN_EMPTY_COMPONENT_CONTAINER | |||
// DbVersion classes | |||
+ 5 | |||
// Others | |||
+ 4); | |||
assertThat(container.getPicoContainer().getComponentAdapters()).isNotEmpty(); | |||
} | |||
} |
@@ -41,8 +41,7 @@ public class AddComponentUuidColumnToGroupRolesTest { | |||
public void column_has_been_created() throws SQLException { | |||
underTest.execute(); | |||
dbTester.assertTableExists(TABLE_NAME); | |||
dbTester.assertColumnDefinition(TABLE_NAME, "component_uuid", VARCHAR, 50, true); | |||
dbTester.assertUniqueIndex(TABLE_NAME, "group_roles_uniq", "organization_uuid", "group_id", "component_uuid", "role"); | |||
dbTester.assertColumnDefinition(TABLE_NAME, "component_uuid", VARCHAR, 40, true); | |||
dbTester.assertIndex(TABLE_NAME, "group_roles_component_uuid", "component_uuid"); | |||
} | |||
@@ -41,7 +41,7 @@ public class AddComponentUuidColumnToPropertiesTest { | |||
public void column_has_been_created() throws SQLException { | |||
underTest.execute(); | |||
dbTester.assertTableExists(TABLE_NAME); | |||
dbTester.assertColumnDefinition(TABLE_NAME, "component_uuid", VARCHAR, 50, true); | |||
dbTester.assertColumnDefinition(TABLE_NAME, "component_uuid", VARCHAR, 40, true); | |||
} | |||
} |
@@ -41,7 +41,7 @@ public class AddComponentUuidColumnToUserRolesTest { | |||
public void column_has_been_created() throws SQLException { | |||
underTest.execute(); | |||
dbTester.assertTableExists(TABLE_NAME); | |||
dbTester.assertColumnDefinition(TABLE_NAME, "component_uuid", VARCHAR, 50, true); | |||
dbTester.assertColumnDefinition(TABLE_NAME, "component_uuid", VARCHAR, 40, true); | |||
dbTester.assertIndex(TABLE_NAME, "user_roles_component_uuid", "component_uuid"); | |||
} | |||
@@ -24,10 +24,11 @@ import org.junit.Rule; | |||
import org.junit.Test; | |||
import org.junit.rules.ExpectedException; | |||
import org.sonar.db.CoreDbTester; | |||
import org.sonar.server.platform.db.migration.version.v83.util.DropPrimaryKeySqlGenerator; | |||
import org.sonar.server.platform.db.migration.version.v83.util.GetConstraintHelper; | |||
import static java.sql.Types.INTEGER; | |||
import static org.sonar.server.platform.db.migration.version.v83.DropIdFromComponentsTable.COLUMN_NAME; | |||
import static org.sonar.server.platform.db.migration.version.v83.DropIdFromComponentsTable.INDEX_NAME; | |||
import static org.sonar.server.platform.db.migration.version.v83.DropIdFromComponentsTable.TABLE_NAME; | |||
public class DropIdFromComponentsTableTest { | |||
@@ -36,14 +37,13 @@ public class DropIdFromComponentsTableTest { | |||
@Rule | |||
public ExpectedException expectedException = ExpectedException.none(); | |||
private DropIdFromComponentsTable underTest = new DropIdFromComponentsTable(dbTester.database()); | |||
private DropPrimaryKeySqlGenerator dropPrimaryKeySqlGenerator = new DropPrimaryKeySqlGenerator(dbTester.database(), new GetConstraintHelper(dbTester.database())); | |||
private DropIdFromComponentsTable underTest = new DropIdFromComponentsTable(dbTester.database(), dropPrimaryKeySqlGenerator); | |||
@Test | |||
public void column_has_been_dropped() throws SQLException { | |||
dbTester.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, INTEGER, null, false); | |||
underTest.execute(); | |||
dbTester.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME); | |||
dbTester.assertIndexDoesNotExist(TABLE_NAME, INDEX_NAME); | |||
} | |||
} |
@@ -40,12 +40,12 @@ public class DropResourceIdFromGroupRolesTableTest { | |||
@Test | |||
public void column_has_been_dropped() throws SQLException { | |||
dbTester.assertColumnDefinition(TABLE_NAME, "resource_id", INTEGER, null, true); | |||
dbTester.assertUniqueIndex(TABLE_NAME, "UNIQ_GROUP_ROLES", "organization_uuid", "group_id", "resource_id", "role"); | |||
dbTester.assertIndex(TABLE_NAME, "GROUP_ROLES_RESOURCE", "resource_id"); | |||
dbTester.assertUniqueIndex(TABLE_NAME, "uniq_group_roles", "organization_uuid", "group_id", "resource_id", "role"); | |||
dbTester.assertIndex(TABLE_NAME, "group_roles_resource", "resource_id"); | |||
underTest.execute(); | |||
dbTester.assertColumnDoesNotExist(TABLE_NAME, "resource_id"); | |||
dbTester.assertIndexDoesNotExist(TABLE_NAME, "UNIQ_GROUP_ROLES"); | |||
dbTester.assertIndexDoesNotExist(TABLE_NAME, "GROUP_ROLES_RESOURCE"); | |||
dbTester.assertIndexDoesNotExist(TABLE_NAME, "group_roles_resource"); | |||
dbTester.assertUniqueIndex(TABLE_NAME, "uniq_group_roles", "organization_uuid", "group_id", "component_uuid", "role"); | |||
} | |||
} |
@@ -55,6 +55,9 @@ public class MigrateResourceIdToUuidInGroupRolesTest { | |||
.collect(Collectors.toList())).containsExactlyInAnyOrder( | |||
new Tuple(1L, 1L, "uuid1", 1L), | |||
new Tuple(3L, null, null, 1L)); | |||
// reentrant | |||
underTest.execute(); | |||
} | |||
private void insertRole(@Nullable Integer resourceId) { |
@@ -56,6 +56,8 @@ public class MigrateResourceIdToUuidInPropertiesTest { | |||
new Tuple(1L, 1L, "uuid1", "key", "value"), | |||
new Tuple(3L, null, null, "key", "value")); | |||
// reentrant | |||
underTest.execute(); | |||
} | |||
private void insertProperty(@Nullable Integer resourceId) { |
@@ -55,6 +55,9 @@ public class MigrateResourceIdToUuidInUserRolesTest { | |||
.collect(Collectors.toList())).containsExactlyInAnyOrder( | |||
new Tuple(1L, 1L, "uuid1", 1L), | |||
new Tuple(3L, null, null, 1L)); | |||
// reentrant | |||
underTest.execute(); | |||
} | |||
private void insertRole(@Nullable Integer resourceId) { |
@@ -0,0 +1,96 @@ | |||
/* | |||
* 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.v83.util; | |||
import java.sql.SQLException; | |||
import java.util.List; | |||
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.Mockito.mock; | |||
import static org.mockito.Mockito.when; | |||
public class DropPrimaryKeySqlGeneratorTest { | |||
private static final String TABLE_NAME = "issues"; | |||
private static final String ORIGINAL_TABLE_NAME = "original_issues"; | |||
private static final String PK_COLUMN = "id"; | |||
private static final String CONSTRAINT = "pk_id"; | |||
private static final PostgreSql POSTGRESQL = new PostgreSql(); | |||
private static final MsSql MS_SQL = new MsSql(); | |||
private static final Oracle ORACLE = new Oracle(); | |||
private static final org.sonar.db.dialect.H2 H2 = new H2(); | |||
private Database db = mock(Database.class); | |||
private GetConstraintHelper getConstraintHelper = mock(GetConstraintHelper.class); | |||
private DropPrimaryKeySqlGenerator underTest = new DropPrimaryKeySqlGenerator(db, getConstraintHelper); | |||
@Test | |||
public void generate_for_postgres_sql() throws SQLException { | |||
when(getConstraintHelper.getPostgresSqlConstraint(TABLE_NAME)).thenReturn(CONSTRAINT); | |||
when(db.getDialect()).thenReturn(POSTGRESQL); | |||
List<String> sqls = underTest.generate(TABLE_NAME, ORIGINAL_TABLE_NAME, PK_COLUMN); | |||
assertThat(sqls).containsExactly("ALTER TABLE issues ALTER COLUMN id DROP DEFAULT", | |||
"DROP SEQUENCE original_issues_id_seq", | |||
"ALTER TABLE issues DROP CONSTRAINT pk_id"); | |||
} | |||
@Test | |||
public void generate_for_ms_sql() throws SQLException { | |||
when(getConstraintHelper.getMssqlConstraint(TABLE_NAME)).thenReturn(CONSTRAINT); | |||
when(db.getDialect()).thenReturn(MS_SQL); | |||
List<String> sqls = underTest.generate(TABLE_NAME, ORIGINAL_TABLE_NAME, PK_COLUMN); | |||
assertThat(sqls).containsExactly("ALTER TABLE issues DROP CONSTRAINT pk_id"); | |||
} | |||
@Test | |||
public void generate_for_oracle() throws SQLException { | |||
when(getConstraintHelper.getOracleConstraint(TABLE_NAME)).thenReturn(CONSTRAINT); | |||
when(db.getDialect()).thenReturn(ORACLE); | |||
List<String> sqls = underTest.generate(TABLE_NAME, ORIGINAL_TABLE_NAME, PK_COLUMN); | |||
assertThat(sqls).containsExactly("DROP TRIGGER issues_IDT", | |||
"DROP SEQUENCE issues_SEQ", | |||
"ALTER TABLE issues DROP CONSTRAINT pk_id"); | |||
} | |||
@Test | |||
public void generate_for_h2() throws SQLException { | |||
when(getConstraintHelper.getH2Constraint(TABLE_NAME)).thenReturn(CONSTRAINT); | |||
when(db.getDialect()).thenReturn(H2); | |||
List<String> sqls = underTest.generate(TABLE_NAME, ORIGINAL_TABLE_NAME, PK_COLUMN); | |||
assertThat(sqls).containsExactly("ALTER TABLE issues DROP CONSTRAINT PK_original_issues", | |||
"ALTER TABLE issues ALTER COLUMN id INTEGER NOT NULL"); | |||
} | |||
} |
@@ -8,6 +8,5 @@ CREATE TABLE "GROUP_ROLES"( | |||
); | |||
ALTER TABLE "GROUP_ROLES" ADD CONSTRAINT "PK_GROUP_ROLES" PRIMARY KEY("ID"); | |||
CREATE UNIQUE INDEX "UNIQ_GROUP_ROLES" ON "GROUP_ROLES"("ORGANIZATION_UUID", "GROUP_ID", "RESOURCE_ID", "ROLE"); | |||
CREATE UNIQUE INDEX "GROUP_ROLES_UNIQ" ON "GROUP_ROLES"("ORGANIZATION_UUID", "GROUP_ID", "COMPONENT_UUID", "ROLE"); | |||
CREATE INDEX "GROUP_ROLES_RESOURCE" ON "GROUP_ROLES"("RESOURCE_ID"); | |||
CREATE INDEX "GROUP_ROLES_COMPONENT_UUID" ON "GROUP_ROLES"("COMPONENT_UUID"); |
@@ -11,4 +11,3 @@ CREATE TABLE "PROPERTIES"( | |||
); | |||
ALTER TABLE "PROPERTIES" ADD CONSTRAINT "PK_PROPERTIES" PRIMARY KEY("ID"); | |||
CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES"("PROP_KEY"); | |||
CREATE INDEX "PROPERTIES_COMPONENT_UUID" ON "PROPERTIES"("COMPONENT_UUID"); |
@@ -11,7 +11,6 @@ CREATE TABLE "PROPERTIES"( | |||
); | |||
ALTER TABLE "PROPERTIES" ADD CONSTRAINT "PK_PROPERTIES" PRIMARY KEY("ID"); | |||
CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES"("PROP_KEY"); | |||
CREATE INDEX "PROPERTIES_COMPONENT_UUID" ON "PROPERTIES"("COMPONENT_UUID"); | |||
CREATE TABLE "COMPONENTS"( | |||
"ID" INTEGER NOT NULL AUTO_INCREMENT (1,1), |
@@ -100,7 +100,7 @@ public class ProjectStatusAction implements QualityGatesWsAction { | |||
action.createParam(PARAM_PROJECT_ID) | |||
.setSince("5.4") | |||
.setDescription("Project id. Doesn't work with branches or pull requests") | |||
.setDescription("Project UUID. Doesn't work with branches or pull requests") | |||
.setExampleValue(Uuids.UUID_EXAMPLE_01); | |||
action.createParam(PARAM_PROJECT_KEY) |