);
ALTER TABLE "QUALITY_GATES" ADD CONSTRAINT "PK_QUALITY_GATES" PRIMARY KEY("UUID");
+CREATE TABLE "RULE_DESC_SECTIONS"(
+ "UUID" CHARACTER VARYING(40) NOT NULL,
+ "RULE_UUID" CHARACTER VARYING(40) NOT NULL,
+ "KEE" CHARACTER VARYING(50) NOT NULL,
+ "DESCRIPTION" CHARACTER LARGE OBJECT NOT NULL
+);
+ALTER TABLE "RULE_DESC_SECTIONS" ADD CONSTRAINT "PK_RULE_DESC_SECTIONS" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "UNIQ_RULE_DESC_SECTIONS_KEE" ON "RULE_DESC_SECTIONS"("RULE_UUID" NULLS FIRST, "KEE" NULLS FIRST);
+
CREATE TABLE "RULE_REPOSITORIES"(
"KEE" CHARACTER VARYING(200) NOT NULL,
"LANGUAGE" CHARACTER VARYING(20) NOT NULL,
"PLUGIN_CONFIG_KEY" CHARACTER VARYING(200),
"PLUGIN_NAME" CHARACTER VARYING(255) NOT NULL,
"SCOPE" CHARACTER VARYING(20) NOT NULL,
- "DESCRIPTION" CHARACTER LARGE OBJECT,
"PRIORITY" INTEGER,
"STATUS" CHARACTER VARYING(40),
"LANGUAGE" CHARACTER VARYING(20),
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.step;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder;
+
+public abstract class DropColumnChange extends DdlChange {
+
+ private final String tableName;
+ private final String columnName;
+
+ protected DropColumnChange(Database db, String tableName, String columnName) {
+ super(db);
+ this.tableName = tableName;
+ this.columnName = columnName;
+ }
+
+ @Override
+ public void execute(DdlChange.Context context) throws SQLException {
+ if (!checkIfUseManagedColumnExists()) {
+ return;
+ }
+
+ context.execute(new DropColumnsBuilder(getDatabase().getDialect(), tableName, columnName).build());
+ }
+
+ private boolean checkIfUseManagedColumnExists() throws SQLException {
+ try (var connection = getDatabase().getDataSource().getConnection()) {
+ if (DatabaseUtils.tableColumnExists(connection, tableName, columnName)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+}
+++ /dev/null
-/*
- * SonarQube
- * Copyright (C) 2009-2022 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.v94;
-
-import java.sql.SQLException;
-import org.sonar.db.Database;
-import org.sonar.db.DatabaseUtils;
-import org.sonar.server.platform.db.migration.sql.DropColumnsBuilder;
-import org.sonar.server.platform.db.migration.step.DdlChange;
-
-public abstract class AbstractDropColumn extends DdlChange {
-
- private final String tableName;
- private final String columnName;
-
- protected AbstractDropColumn(Database db, String tableName, String columnName) {
- super(db);
- this.tableName = tableName;
- this.columnName = columnName;
- }
-
- @Override
- public void execute(DdlChange.Context context) throws SQLException {
- if (!checkIfUseManagedColumnExists()) {
- return;
- }
-
- context.execute(new DropColumnsBuilder(getDatabase().getDialect(), tableName, columnName).build());
- }
-
- private boolean checkIfUseManagedColumnExists() throws SQLException {
- try (var connection = getDatabase().getDataSource().getConnection()) {
- if (DatabaseUtils.tableColumnExists(connection, tableName, columnName)) {
- return true;
- }
- }
- return false;
- }
-
-}
package org.sonar.server.platform.db.migration.version.v94;
import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DropColumnChange;
-public class DropActionPlanKeyIssueColumn extends AbstractDropColumn {
+public class DropActionPlanKeyIssueColumn extends DropColumnChange {
public static final String TABLE_NAME = "issues";
public static final String COLUMN_NAME = "action_plan_key";
package org.sonar.server.platform.db.migration.version.v94;
import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DropColumnChange;
-public class DropIssuesAttributesIssueColumn extends AbstractDropColumn{
+public class DropIssuesAttributesIssueColumn extends DropColumnChange {
public static final String TABLE_NAME = "issues";
public static final String COLUMN_NAME = "issue_attributes";
package org.sonar.server.platform.db.migration.version.v94;
import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DropColumnChange;
-public class DropReporterIssueColumn extends AbstractDropColumn {
+public class DropReporterIssueColumn extends DropColumnChange {
public static final String TABLE_NAME = "issues";
public static final String COLUMN_NAME = "reporter";
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.v95;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+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.version.v95.CreateRuleDescSectionsTable.RULE_DESCRIPTION_SECTIONS_TABLE;
+
+public class CreateIndexForRuleDescSections extends DdlChange {
+ @VisibleForTesting
+ static final String INDEX_NAME = "uniq_rule_desc_sections_kee";
+
+ public CreateIndexForRuleDescSections(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ try (Connection c = getDatabase().getDataSource().getConnection()) {
+ if (!DatabaseUtils.indexExistsIgnoreCase(RULE_DESCRIPTION_SECTIONS_TABLE, INDEX_NAME, c)) {
+ context.execute(new CreateIndexBuilder()
+ .setTable(RULE_DESCRIPTION_SECTIONS_TABLE)
+ .setName(INDEX_NAME)
+ .addColumn("rule_uuid")
+ .addColumn("kee")
+ .setUnique(true)
+ .build());
+ }
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.v95;
+
+import java.sql.SQLException;
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.sql.CreateTableBuilder;
+import org.sonar.server.platform.db.migration.step.CreateTableChange;
+
+import static org.sonar.server.platform.db.migration.def.ClobColumnDef.newClobColumnDefBuilder;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.UUID_SIZE;
+import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
+
+public class CreateRuleDescSectionsTable extends CreateTableChange {
+
+ static final String RULE_DESCRIPTION_SECTIONS_TABLE = "rule_desc_sections";
+
+ public CreateRuleDescSectionsTable(Database db) {
+ super(db, RULE_DESCRIPTION_SECTIONS_TABLE);
+ }
+
+ @Override
+ public void execute(Context context, String tableName) throws SQLException {
+ context.execute(new CreateTableBuilder(getDialect(), tableName)
+ .addPkColumn(newVarcharColumnDefBuilder().setColumnName("uuid").setIsNullable(false).setLimit(UUID_SIZE).build())
+ .addColumn(newVarcharColumnDefBuilder().setColumnName("rule_uuid").setIsNullable(false).setLimit(40).build())
+ .addColumn(newVarcharColumnDefBuilder().setColumnName("kee").setIsNullable(false).setLimit(50).build())
+ .addColumn(newClobColumnDefBuilder().setColumnName("description").setIsNullable(false).build())
+ .build());
+ }
+}
.add(6401, "Add column 'project_key' to 'user_tokens'", AddProjectKeyColumnToUserTokens.class)
.add(6402, "Add column 'type' to 'user_tokens'", AddTypeColumnToUserTokens.class)
.add(6403, "Upsert value of type in 'user_tokens'", UpsertUserTokensTypeValue.class)
- .add(6404, "Make column 'type' in 'user_tokens' not nullable", MakeTypeColumnNotNullableOnUserTokens.class);
+ .add(6404, "Make column 'type' in 'user_tokens' not nullable", MakeTypeColumnNotNullableOnUserTokens.class)
+ .add(6405, "Create table RULE_DESC_SECTIONS", CreateRuleDescSectionsTable.class)
+ .add(6406, "Insert descriptions from RULES into RULE_DESC_SECTIONS", InsertRuleDescriptionIntoRuleDescSections.class)
+ .add(6407, "Create index for RULE_DESC_SECTIONS", CreateIndexForRuleDescSections.class)
+ .add(6408, "Drop column DESCRIPTIONS from RULES table", DropRuleDescriptionColumn.class)
+ ;
}
}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.v95;
+
+import org.sonar.db.Database;
+import org.sonar.server.platform.db.migration.step.DropColumnChange;
+
+public class DropRuleDescriptionColumn extends DropColumnChange {
+
+ public static final String TABLE_NAME = "rules";
+ public static final String COLUMN_NAME = "description";
+
+ public DropRuleDescriptionColumn(Database db) {
+ super(db, TABLE_NAME, COLUMN_NAME);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.v95;
+
+import com.google.common.annotations.VisibleForTesting;
+import java.sql.SQLException;
+import java.util.List;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.db.Database;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.server.platform.db.migration.step.DataChange;
+import org.sonar.server.platform.db.migration.step.Upsert;
+
+import static org.sonar.server.platform.db.migration.version.v95.CreateRuleDescSectionsTable.RULE_DESCRIPTION_SECTIONS_TABLE;
+
+public class InsertRuleDescriptionIntoRuleDescSections extends DataChange {
+ @VisibleForTesting
+ static final String DEFAULT_DESCRIPTION_KEY = "default";
+
+ private static final String SELECT_EXISTING_RULE_DESCRIPTIONS = "select uuid, description from rules where description is not null "
+ + "and uuid not in (select rule_uuid from " + RULE_DESCRIPTION_SECTIONS_TABLE + ")";
+ private static final String INSERT_INTO_RULE_DESC_SECTIONS = "insert into " + RULE_DESCRIPTION_SECTIONS_TABLE + " (uuid, rule_uuid, kee, description) values "
+ + "(?,?,?,?)";
+
+ private final UuidFactory uuidFactory;
+
+ public InsertRuleDescriptionIntoRuleDescSections(Database db, UuidFactory uuidFactory) {
+ super(db);
+ this.uuidFactory = uuidFactory;
+ }
+
+ @Override
+ protected void execute(Context context) throws SQLException {
+ try (var connection = getDatabase().getDataSource().getConnection()) {
+ if (!DatabaseUtils.tableColumnExists(connection, "rules", "description")) {
+ return;
+ }
+ }
+ List<RuleDb> selectRuleDb = findExistingRuleDescriptions(context);
+ if (selectRuleDb.isEmpty()) {
+ return;
+ }
+ insertRuleDescSections(context, selectRuleDb);
+ }
+
+ private List<RuleDb> findExistingRuleDescriptions(Context context) throws SQLException {
+ return context.prepareSelect(SELECT_EXISTING_RULE_DESCRIPTIONS)
+ .list(r -> new RuleDb(r.getString(1), r.getString(2)));
+ }
+
+ private void insertRuleDescSections(Context context, List<RuleDb> selectRuleDb) throws SQLException {
+ Upsert insertRuleDescSections = context.prepareUpsert(INSERT_INTO_RULE_DESC_SECTIONS);
+ for (RuleDb ruleDb : selectRuleDb) {
+ insertRuleDescSections
+ .setString(1, uuidFactory.create())
+ .setString(2, ruleDb.getUuid())
+ .setString(3, DEFAULT_DESCRIPTION_KEY)
+ .setString(4, ruleDb.getDescription())
+ .addBatch();
+ }
+ insertRuleDescSections.execute().commit();
+ }
+
+ private static class RuleDb {
+ private final String uuid;
+ private final String description;
+
+ private RuleDb(String uuid, String description) {
+ this.uuid = uuid;
+ this.description = description;
+ }
+
+ public String getUuid() {
+ return uuid;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.v95;
+
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.lang.RandomStringUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
+import static org.sonar.server.platform.db.migration.version.v95.CreateIndexForRuleDescSections.INDEX_NAME;
+import static org.sonar.server.platform.db.migration.version.v95.CreateRuleDescSectionsTable.RULE_DESCRIPTION_SECTIONS_TABLE;
+
+public class CreateIndexForRuleDescSectionsTest {
+
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(CreateIndexForRuleDescSectionsTest.class, "schema.sql");
+
+ private final CreateIndexForRuleDescSections createIndex = new CreateIndexForRuleDescSections(db.database());
+
+ @Test
+ public void should_create_index() throws SQLException {
+ db.assertIndexDoesNotExist(RULE_DESCRIPTION_SECTIONS_TABLE, INDEX_NAME);
+ createIndex.execute();
+ db.assertUniqueIndex(RULE_DESCRIPTION_SECTIONS_TABLE, INDEX_NAME, "rule_uuid", "kee");
+ }
+
+ @Test
+ public void migration_should_be_reentrant() throws SQLException {
+ db.assertIndexDoesNotExist(RULE_DESCRIPTION_SECTIONS_TABLE, INDEX_NAME);
+
+ createIndex.execute();
+ //re-entrant
+ createIndex.execute();
+
+ db.assertUniqueIndex(RULE_DESCRIPTION_SECTIONS_TABLE, INDEX_NAME, "rule_uuid", "kee");
+ }
+
+ @Test
+ public void index_should_prevent_two_descriptions_with_same_key_on_same_rule() throws SQLException {
+ createIndex.execute();
+
+ insertRuleDescSection("default", "rule1");
+ insertRuleDescSection("default", "rule2");
+ insertRuleDescSection("non_default", "rule2");
+ assertThatExceptionOfType(IllegalStateException.class)
+ .isThrownBy(() -> this.insertRuleDescSection("default", "rule1"));
+ }
+
+ private void insertRuleDescSection(String key, String ruleUuid) {
+ Map<String, Object> ruleParams = new HashMap<>();
+ ruleParams.put("uuid", RandomStringUtils.randomAlphanumeric(40));
+ ruleParams.put("rule_uuid", ruleUuid);
+ ruleParams.put("kee", key);
+ ruleParams.put("description", "descriptions");
+
+ db.executeInsert("rule_desc_sections", ruleParams);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.v95;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+
+public class CreateRuleDescSectionsTableTest {
+ private static final String TABLE_NAME = "rule_desc_sections";
+
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createEmpty();
+
+ private final CreateRuleDescSectionsTable createRuleDescSectionsTable = new CreateRuleDescSectionsTable(db.database());
+
+ @Test
+ public void migration_should_create_table() throws SQLException {
+ db.assertTableDoesNotExist(TABLE_NAME);
+
+ createRuleDescSectionsTable.execute();
+
+ db.assertTableExists(TABLE_NAME);
+ }
+
+ @Test
+ public void migration_should_be_reentrant() throws SQLException {
+ db.assertTableDoesNotExist(TABLE_NAME);
+
+ createRuleDescSectionsTable.execute();
+ //re-entrant
+ createRuleDescSectionsTable.execute();
+
+ db.assertTableExists(TABLE_NAME);
+ }
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.v95;
+
+import java.sql.SQLException;
+import java.sql.Types;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class DropRuleDescriptionColumnTest {
+
+ private static final String COLUMN_NAME = "description";
+ private static final String TABLE_NAME = "rules";
+
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(DropRuleDescriptionColumnTest.class, "schema.sql");
+
+ private final DdlChange dropRuleDescriptionColumn = new DropRuleDescriptionColumn(db.database());
+
+ @Test
+ public void migration_should_drop_action_plan_column() throws SQLException {
+ db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.CLOB, null, true);
+ dropRuleDescriptionColumn.execute();
+ db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
+ }
+
+ @Test
+ public void migration_should_be_reentrant() throws SQLException {
+ db.assertColumnDefinition(TABLE_NAME, COLUMN_NAME, Types.CLOB, null, true);
+ dropRuleDescriptionColumn.execute();
+ // re-entrant
+ dropRuleDescriptionColumn.execute();
+ db.assertColumnDoesNotExist(TABLE_NAME, COLUMN_NAME);
+ }
+
+}
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2022 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.v95;
+
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.commons.lang.RandomStringUtils;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.core.util.UuidFactory;
+import org.sonar.core.util.UuidFactoryFast;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.DataChange;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.sonar.server.platform.db.migration.version.v95.CreateRuleDescSectionsTable.RULE_DESCRIPTION_SECTIONS_TABLE;
+import static org.sonar.server.platform.db.migration.version.v95.InsertRuleDescriptionIntoRuleDescSections.DEFAULT_DESCRIPTION_KEY;
+
+public class InsertRuleDescriptionIntoRuleDescSectionsTest {
+
+ @Rule
+ public final CoreDbTester db = CoreDbTester.createForSchema(InsertRuleDescriptionIntoRuleDescSectionsTest.class, "schema.sql");
+
+ private final UuidFactory uuidFactory = UuidFactoryFast.getInstance();
+
+ private final DataChange insertRuleDescriptions = new InsertRuleDescriptionIntoRuleDescSections(db.database(), uuidFactory);
+
+ @Test
+ public void insertRuleDescriptions_doesNotFailIfRulesTableIsEmpty() {
+ assertThatCode(insertRuleDescriptions::execute)
+ .doesNotThrowAnyException();
+ }
+
+ @Test
+ public void insertRuleDescriptions_whenDifferentRules_createsRelevantSectionDescription() throws SQLException {
+ String description1 = RandomStringUtils.randomAlphanumeric(5000);
+ String uuid1 = "uuid1";
+ insertRule(uuid1, description1);
+
+ String description2 = RandomStringUtils.randomAlphanumeric(5000);
+ String uuid2 = "uuid2";
+ insertRule(uuid2, description2);
+
+ insertRuleDescriptions.execute();
+
+ assertThat(db.countRowsOfTable(RULE_DESCRIPTION_SECTIONS_TABLE)).isEqualTo(2);
+ assertRuleDescriptionCreated(uuid1, description1);
+ assertRuleDescriptionCreated(uuid2, description2);
+ }
+
+ @Test
+ public void insertRuleDescriptions_whenReentrant_doesNotFail() throws SQLException {
+ String description1 = RandomStringUtils.randomAlphanumeric(5000);
+ String uuid1 = "uuid1";
+ insertRule(uuid1, description1);
+
+ insertRuleDescriptions.execute();
+ insertRuleDescriptions.execute();
+ insertRuleDescriptions.execute();
+
+ assertThat(db.countRowsOfTable(RULE_DESCRIPTION_SECTIONS_TABLE)).isEqualTo(1);
+ assertRuleDescriptionCreated(uuid1, description1);
+ }
+
+ @Test
+ public void insertRuleDescriptions_whenNoDescription_doesNotCreateRuleDescriptionSection() throws SQLException {
+ String uuid1 = "uuid1";
+ insertRule(uuid1, null);
+
+ insertRuleDescriptions.execute();
+
+ assertThat(db.countRowsOfTable(RULE_DESCRIPTION_SECTIONS_TABLE)).isZero();
+ }
+
+ private void assertRuleDescriptionCreated(String uuid1, String description1) {
+ Map<String, Object> result1 = findRuleSectionDescription(uuid1);
+ assertThat(result1)
+ .containsEntry("RULE_UUID", uuid1)
+ .containsEntry("KEE", DEFAULT_DESCRIPTION_KEY)
+ .containsEntry("DESCRIPTION", description1)
+ .extractingByKey("UUID").isNotNull();
+ }
+
+ private Map<String, Object> findRuleSectionDescription(String uuid) {
+ return db.selectFirst("select uuid, kee, rule_uuid, description from "
+ + RULE_DESCRIPTION_SECTIONS_TABLE + " where rule_uuid = '" + uuid + "'");
+ }
+
+ private void insertRule(String uuid, String description) {
+ Map<String, Object> ruleParams = new HashMap<>();
+ ruleParams.put("uuid", uuid);
+ ruleParams.put("plugin_rule_key", uuid);
+ ruleParams.put("plugin_name", "plugin_name");
+ ruleParams.put("scope", "ALL");
+ ruleParams.put("is_template", false);
+ ruleParams.put("is_external", true);
+ ruleParams.put("is_ad_hoc", false);
+ ruleParams.put("description", description);
+
+ db.executeInsert("rules", ruleParams);
+ }
+
+}
--- /dev/null
+CREATE TABLE "RULE_DESC_SECTIONS"(
+ "UUID" CHARACTER VARYING(40) NOT NULL,
+ "RULE_UUID" CHARACTER VARYING(40) NOT NULL,
+ "KEE" CHARACTER VARYING(50) NOT NULL,
+ "DESCRIPTION" CHARACTER LARGE OBJECT NOT NULL
+);
+ALTER TABLE "RULE_DESC_SECTIONS" ADD CONSTRAINT "PK_RULE_DESC_SECTIONS" PRIMARY KEY("UUID");
--- /dev/null
+CREATE TABLE "RULES"(
+ "UUID" CHARACTER VARYING(40) NOT NULL,
+ "NAME" CHARACTER VARYING(200),
+ "PLUGIN_RULE_KEY" CHARACTER VARYING(200) NOT NULL,
+ "PLUGIN_KEY" CHARACTER VARYING(200),
+ "PLUGIN_CONFIG_KEY" CHARACTER VARYING(200),
+ "PLUGIN_NAME" CHARACTER VARYING(255) NOT NULL,
+ "SCOPE" CHARACTER VARYING(20) NOT NULL,
+ "DESCRIPTION" CHARACTER LARGE OBJECT,
+ "PRIORITY" INTEGER,
+ "STATUS" CHARACTER VARYING(40),
+ "LANGUAGE" CHARACTER VARYING(20),
+ "DEF_REMEDIATION_FUNCTION" CHARACTER VARYING(20),
+ "DEF_REMEDIATION_GAP_MULT" CHARACTER VARYING(20),
+ "DEF_REMEDIATION_BASE_EFFORT" CHARACTER VARYING(20),
+ "GAP_DESCRIPTION" CHARACTER VARYING(4000),
+ "SYSTEM_TAGS" CHARACTER VARYING(4000),
+ "IS_TEMPLATE" BOOLEAN DEFAULT FALSE NOT NULL,
+ "DESCRIPTION_FORMAT" CHARACTER VARYING(20),
+ "RULE_TYPE" TINYINT,
+ "SECURITY_STANDARDS" CHARACTER VARYING(4000),
+ "IS_AD_HOC" BOOLEAN NOT NULL,
+ "IS_EXTERNAL" BOOLEAN NOT NULL,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "TEMPLATE_UUID" CHARACTER VARYING(40)
+);
+ALTER TABLE "RULES" ADD CONSTRAINT "PK_RULES" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES"("PLUGIN_RULE_KEY" NULLS FIRST, "PLUGIN_NAME" NULLS FIRST);
--- /dev/null
+CREATE TABLE "RULE_DESC_SECTIONS"(
+ "UUID" CHARACTER VARYING(40) NOT NULL,
+ "RULE_UUID" CHARACTER VARYING(40) NOT NULL,
+ "KEE" CHARACTER VARYING(50) NOT NULL,
+ "DESCRIPTION" CHARACTER LARGE OBJECT NOT NULL
+);
+ALTER TABLE "RULE_DESC_SECTIONS" ADD CONSTRAINT "PK_RULE_DESC_SECTIONS" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "UNIQ_RULE_DESC_SECTIONS_KEE" ON "RULE_DESC_SECTIONS"("RULE_UUID" NULLS FIRST, "KEE" NULLS FIRST);
+
+CREATE TABLE "RULES"(
+ "UUID" CHARACTER VARYING(40) NOT NULL,
+ "NAME" CHARACTER VARYING(200),
+ "PLUGIN_RULE_KEY" CHARACTER VARYING(200) NOT NULL,
+ "PLUGIN_KEY" CHARACTER VARYING(200),
+ "PLUGIN_CONFIG_KEY" CHARACTER VARYING(200),
+ "PLUGIN_NAME" CHARACTER VARYING(255) NOT NULL,
+ "SCOPE" CHARACTER VARYING(20) NOT NULL,
+ "DESCRIPTION" CHARACTER LARGE OBJECT,
+ "PRIORITY" INTEGER,
+ "STATUS" CHARACTER VARYING(40),
+ "LANGUAGE" CHARACTER VARYING(20),
+ "DEF_REMEDIATION_FUNCTION" CHARACTER VARYING(20),
+ "DEF_REMEDIATION_GAP_MULT" CHARACTER VARYING(20),
+ "DEF_REMEDIATION_BASE_EFFORT" CHARACTER VARYING(20),
+ "GAP_DESCRIPTION" CHARACTER VARYING(4000),
+ "SYSTEM_TAGS" CHARACTER VARYING(4000),
+ "IS_TEMPLATE" BOOLEAN DEFAULT FALSE NOT NULL,
+ "DESCRIPTION_FORMAT" CHARACTER VARYING(20),
+ "RULE_TYPE" TINYINT,
+ "SECURITY_STANDARDS" CHARACTER VARYING(4000),
+ "IS_AD_HOC" BOOLEAN NOT NULL,
+ "IS_EXTERNAL" BOOLEAN NOT NULL,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "TEMPLATE_UUID" CHARACTER VARYING(40)
+);
+ALTER TABLE "RULES" ADD CONSTRAINT "PK_RULES" PRIMARY KEY("UUID");
+CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES"("PLUGIN_RULE_KEY" NULLS FIRST, "PLUGIN_NAME" NULLS FIRST);