}
}
+ public static boolean tableColumnExists(Connection connection, String tableName, String columnName) {
+ try {
+ return columnExists(connection, tableName.toLowerCase(Locale.US), columnName)
+ || columnExists(connection, tableName.toUpperCase(Locale.US), columnName);
+ } catch (SQLException e) {
+ throw wrapSqlException(e, "Can not check that column %s exists", columnName);
+ }
+ }
+
+ private static boolean columnExists(Connection connection, String tableName, String columnName) throws SQLException {
+ String schema = getSchema(connection);
+ try (ResultSet rs = connection.getMetaData().getColumns(connection.getCatalog(), schema, tableName, null)) {
+ while (rs.next()) {
+ for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
+ String name = rs.getString(i);
+ if (columnName.equalsIgnoreCase(name)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ }
+
@CheckForNull
private static String getSchema(Connection connection) {
String schema = null;
}
}
+ @Test
+ public void find_column_with_lower_case_table_name_and_upper_case_column_name() throws SQLException {
+ String tableName = "tablea";
+ String columnName = "COLUMNA";
+ try (Connection connection = dbTester.openConnection()) {
+ assertThat(DatabaseUtils.tableColumnExists(connection, tableName, columnName)).isTrue();
+ assertThat(DatabaseUtils.tableColumnExists(connection, tableName.toLowerCase(Locale.US), columnName)).isTrue();
+ }
+ }
+ @Test
+ public void find_column_with_upper_case_table_name_and_upper_case_column_name() throws SQLException {
+ String tableName = "TABLEA";
+ String columnName = "COLUMNA";
+ try (Connection connection = dbTester.openConnection()) {
+ assertThat(DatabaseUtils.tableColumnExists(connection, tableName, columnName)).isTrue();
+ assertThat(DatabaseUtils.tableColumnExists(connection, tableName.toLowerCase(Locale.US), columnName)).isTrue();
+ }
+ }
+
+ @Test
+ public void find_column_with_lower_case_table_name_and_lower_case_column_name() throws SQLException {
+ String tableName = "tablea";
+ String columnName = "columna";
+ try (Connection connection = dbTester.openConnection()) {
+ assertThat(DatabaseUtils.tableColumnExists(connection, tableName, columnName)).isTrue();
+ assertThat(DatabaseUtils.tableColumnExists(connection, tableName.toLowerCase(Locale.US), columnName)).isTrue();
+ }
+ }
+
+ @Test
+ public void find_column_with_upper_case_table_name_and_lower_case_column_name() throws SQLException {
+ String tableName = "TABLEA";
+ String columnName = "columna";
+ try (Connection connection = dbTester.openConnection()) {
+ assertThat(DatabaseUtils.tableColumnExists(connection, tableName, columnName)).isTrue();
+ assertThat(DatabaseUtils.tableColumnExists(connection, tableName, columnName.toLowerCase(Locale.US))).isTrue();
+ assertThat(DatabaseUtils.tableColumnExists(connection, tableName.toLowerCase(Locale.US), columnName.toLowerCase(Locale.US))).isTrue();
+ }
+ }
+
@Test
public void should_close_connection() throws Exception {
try (Connection connection = dbTester.openConnection()) {
"version" VARCHAR(256) NOT NULL
);
+CREATE TABLE "TABLEA" (
+ "COLUMNA" VARCHAR(256) NOT NULL
+);
+
CREATE INDEX UPPER_CASE_NAME ON schema_migrations (version);
CREATE INDEX lower_case_name ON schema_migrations (version);
import org.sonar.server.platform.db.migration.version.v84.usertokens.DropPrimaryKeyOnIdColumnOfUserTokensTable;
import org.sonar.server.platform.db.migration.version.v84.usertokens.MakeUserTokensUuidNotNullable;
import org.sonar.server.platform.db.migration.version.v84.usertokens.PopulateUserTokensUuid;
+import org.sonar.server.platform.db.migration.version.v85.AddIndexOnProjectUuidOnIssueChangesTable;
public class DbVersion84 implements DbVersion {
@Override
.add(3479, "Add index on 'ISSUE_KEY' of 'ISSUE_CHANGES' table", AddIndexOnIssueKeyOfIssueChangesTable.class)
.add(3480, "Add index on 'KEE' of 'ISSUE_CHANGES' table", AddIndexOnKeeOfIssueChangesTable.class)
.add(3481, "Add primary key on 'UUID' column of 'ISSUE_CHANGES' table", AddPrimaryKeyOnUuidColumnOfIssueChangesTable.class)
+ .add(3482, "Add index on 'project_uuid' for table 'ISSUE_CHANGES'", AddIndexOnProjectUuidOnIssueChangesTable.class)
// Migration of QUALITY_GATE_CONDITIONS table
.add(3483, "Add 'UUID' column on 'QUALITY_GATE_CONDITIONS' table", AddUuidColumnToQualityGateConditionsTable.class)
.add(3804, "Populate 'need_issue_sync' of 'project_branches'", PopulateProjectBranchesNeedIssueSync.class)
.add(3805, "Make 'need_issue_sync' of 'project_branches' not null", MakeProjectBranchesNeedIssueSyncNonNull.class)
- .add(3806, "Drop local webhooks", DropLocalWebhooks.class)
+ .add(3806, "Drop local webhooks", DropLocalWebhooks.class)
// Migration of ALM_SETTINGS table
.add(3807, "Add columns 'CLIENT_ID' and 'CLIENT_SECRET' to 'ALM_SETTINGS' table", AddClientIdAndClientSecretColumns.class)
import java.sql.SQLException;
import org.sonar.db.Database;
-import org.sonar.server.platform.db.migration.sql.CreateTableAsBuilder;
+import org.sonar.db.dialect.MsSql;
+import org.sonar.server.platform.db.migration.def.VarcharColumnDef;
+import org.sonar.server.platform.db.migration.sql.AlterColumnsBuilder;
import org.sonar.server.platform.db.migration.step.DdlChange;
-import static org.sonar.server.platform.db.migration.def.BigIntegerColumnDef.newBigIntegerColumnDefBuilder;
-import static org.sonar.server.platform.db.migration.def.ClobColumnDef.newClobColumnDefBuilder;
import static org.sonar.server.platform.db.migration.def.VarcharColumnDef.newVarcharColumnDefBuilder;
public class CopyIssueChangesTable extends DdlChange {
+ private static final String COPY_NAME = "issue_changes_copy";
+
public CopyIssueChangesTable(Database db) {
super(db);
}
- @Override public void execute(Context context) throws SQLException {
- CreateTableAsBuilder builder = new CreateTableAsBuilder(getDialect(), "issue_changes_copy", "issue_changes")
- // this will cause the following changes:
- // * Add UUID with values in ID casted to varchar
- .addColumnWithCast(newVarcharColumnDefBuilder().setColumnName("uuid").setLimit(40).setIsNullable(false).build(), "id")
- .addColumn(newVarcharColumnDefBuilder().setColumnName("kee").setLimit(50).build())
- .addColumn(newVarcharColumnDefBuilder().setColumnName("issue_key").setLimit(50).setIsNullable(false).build())
- .addColumn(newVarcharColumnDefBuilder().setColumnName("user_login").setLimit(255).build())
- .addColumn(newVarcharColumnDefBuilder().setColumnName("change_type").setLimit(20).build())
- .addColumn(newClobColumnDefBuilder().setColumnName("change_data").build())
- .addColumn(newBigIntegerColumnDefBuilder().setColumnName("created_at").build())
- .addColumn(newBigIntegerColumnDefBuilder().setColumnName("updated_at").build())
- .addColumn(newBigIntegerColumnDefBuilder().setColumnName("issue_change_creation_date").build());
- context.execute(builder.build());
- /*
- "UUID VARCHAR(40) NOT NULL",
- "KEE VARCHAR(50)",
- "ISSUE_KEY VARCHAR(50) NOT NULL",
- "USER_LOGIN VARCHAR(255)",
- "CHANGE_TYPE VARCHAR(20)",
- "CHANGE_DATA CLOB(2147483647)",
- "CREATED_AT BIGINT",
- "UPDATED_AT BIGINT",
- "ISSUE_CHANGE_CREATION_DATE BIGINT"
- */
+ @Override
+ public void execute(Context context) throws SQLException {
+
+ String query;
+ if (getDatabase().getDialect().getId().equals(MsSql.ID)) {
+ query = "select cast (ic.id AS VARCHAR(40)) AS uuid, ic.kee, ic.issue_key, ic.user_login, ic.change_type, " +
+ "ic.change_data, ic.created_at, ic.updated_at, ic.issue_change_creation_date, i.project_uuid " +
+ "INTO issue_changes_copy " +
+ "FROM issue_changes AS ic inner join issues i on i.kee = ic.issue_key";
+ } else {
+ query = "create table issue_changes_copy " +
+ "(uuid, kee, issue_key, user_login, change_type, change_data, created_at, updated_at, issue_change_creation_date, project_uuid)" +
+ "as (" +
+ "SELECT cast (ic.id AS VARCHAR(40)) AS uuid, ic.kee, ic.issue_key, ic.user_login, ic.change_type, ic.change_data, ic.created_at, ic.updated_at, "
+ + "ic.issue_change_creation_date, i.project_uuid " +
+ "FROM issue_changes ic " +
+ "inner join issues i on i.kee = ic.issue_key " +
+ ")";
+ }
+
+ context.execute(query);
+ context.execute(new AlterColumnsBuilder(getDialect(), COPY_NAME).updateColumn(
+ newVarcharColumnDefBuilder()
+ .setColumnName("project_uuid")
+ .setIsNullable(false)
+ .setDefaultValue(null)
+ .setLimit(VarcharColumnDef.UUID_VARCHAR_SIZE)
+ .build()).build());
+ context.execute(new AlterColumnsBuilder(getDialect(), COPY_NAME).updateColumn(
+ newVarcharColumnDefBuilder()
+ .setColumnName("issue_key")
+ .setIsNullable(false)
+ .setDefaultValue(null)
+ .setLimit(VarcharColumnDef.UUID_VARCHAR_SIZE)
+ .build()).build());
+ context.execute(new AlterColumnsBuilder(getDialect(), COPY_NAME).updateColumn(
+ newVarcharColumnDefBuilder()
+ .setColumnName("uuid")
+ .setIsNullable(false)
+ .setDefaultValue(null)
+ .setLimit(VarcharColumnDef.UUID_SIZE)
+ .build()).build());
}
}
super(db);
}
- @Override public void execute(Context context) throws SQLException {
+ @Override
+ public void execute(Context context) throws SQLException {
context.execute(new DropTableBuilder(getDialect(), "issue_changes").build());
}
}
*/
package org.sonar.server.platform.db.migration.version.v85;
+import java.sql.Connection;
import java.sql.SQLException;
import org.sonar.db.Database;
import org.sonar.server.platform.db.migration.sql.AddPrimaryKeyBuilder;
+import org.sonar.db.DatabaseUtils;
import org.sonar.server.platform.db.migration.step.DdlChange;
public class AddPrimaryKeyOnUuidForIssueChangesTable extends DdlChange {
@Override
public void execute(Context context) throws SQLException {
- context.execute(new AddPrimaryKeyBuilder(TABLE, "uuid").build());
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ if (!DatabaseUtils.indexExistsIgnoreCase(TABLE, "issue_changes_project_uuid", connection)) {
+ context.execute(new AddPrimaryKeyBuilder(TABLE, "uuid").build());
+ }
+ }
}
}
*/
package org.sonar.server.platform.db.migration.version.v85;
+import java.sql.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.step.DdlChange;
@Override
public void execute(Context context) throws SQLException {
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ if (DatabaseUtils.tableColumnExists(connection, "issue_changes", "project_uuid")) {
+ // This migration might already have been done in v84 (#3476) if using SQ >= 8.7.
+ return;
+ }
+ String query;
+ if (getDatabase().getDialect().getId().equals(MsSql.ID)) {
+ query = "SELECT ic.uuid, ic.kee, ic.issue_key, ic.user_login, ic.change_type, " +
+ "ic.change_data, ic.created_at, ic.updated_at, ic.issue_change_creation_date, i.project_uuid " +
+ "INTO tmp_issue_changes " +
+ "FROM issue_changes AS ic inner join issues i on i.kee = ic.issue_key";
+ } else {
+ query = "create table tmp_issue_changes " +
+ "(uuid, kee, issue_key, user_login, change_type, change_data, created_at, updated_at, issue_change_creation_date, project_uuid)" +
+ "as (" +
+ "SELECT ic.uuid, ic.kee, ic.issue_key, ic.user_login, ic.change_type, ic.change_data, ic.created_at, ic.updated_at, ic.issue_change_creation_date, i.project_uuid " +
+ "FROM issue_changes ic " +
+ "inner join issues i on i.kee = ic.issue_key " +
+ ")";
+ }
- String query;
- if (getDatabase().getDialect().getId().equals(MsSql.ID)) {
- query = "SELECT ic.uuid, ic.kee, ic.issue_key, ic.user_login, ic.change_type, " +
- "ic.change_data, ic.created_at, ic.updated_at, ic.issue_change_creation_date, i.project_uuid " +
- "INTO tmp_issue_changes " +
- "FROM issue_changes AS ic inner join issues i on i.kee = ic.issue_key";
- } else {
- query = "create table tmp_issue_changes " +
- "(uuid, kee, issue_key, user_login, change_type, change_data, created_at, updated_at, issue_change_creation_date, project_uuid)" +
- "as (" +
- "SELECT ic.uuid, ic.kee, ic.issue_key, ic.user_login, ic.change_type, ic.change_data, ic.created_at, ic.updated_at, ic.issue_change_creation_date, i.project_uuid " +
- "FROM issue_changes ic " +
- "inner join issues i on i.kee = ic.issue_key " +
- ")";
+ context.execute(query);
}
-
- context.execute(query);
}
}
import org.sonar.server.platform.db.migration.step.MigrationStepRegistry;
import org.sonar.server.platform.db.migration.version.DbVersion;
-import org.sonar.server.platform.db.migration.version.v84.issuechanges.DropIssueChangesTable;
public class DbVersion85 implements DbVersion {
.add(4003, "Drop unused variation values columns in 'project_measures' table", DropUnusedVariationsInProjectMeasures.class)
.add(4004, "Drop unused periods in 'snapshots' table", DropUnusedPeriodsInSnapshots.class)
.add(4005, "Drop orphan favorites from 'properties' table", DropOrphanFavoritesFromProperties.class)
+
.add(4006, "create 'tmp_issue_changes' table", CreateTmpIssueChangesTable.class)
.add(4007, "drop 'issue_changes' table", DropIssueChangesTable.class)
.add(4008, "rename 'tmp_issue_changes' table to 'issue_changes'", RenameTmpIssueChangesToIssueChanges.class)
.add(4013, "add index on 'issue_key' for table 'issue_changes'", AddIndexOnIssueKeyForIssueChangesTable.class)
.add(4014, "add index on 'kee' for table 'issue_changes'", AddIndexOnKeeForIssueChangesTable.class)
.add(4015, "add index on 'project_uuid' for table 'issue_changes'", AddIndexOnProjectUuidOnIssueChangesTable.class)
+
.add(4016, "Add 'type' column to 'plugins' table", AddTypeToPlugins.class)
.add(4017, "Populate 'type' column in 'plugins' table", PopulateTypeInPlugins.class)
.add(4018, "Alter 'type' column in 'plugins' to not nullable", AlterTypeInPluginNotNullable.class)
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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;
+
+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.DropTableBuilder;
+import org.sonar.server.platform.db.migration.step.DdlChange;
+
+public class DropIssueChangesTable extends DdlChange {
+ public DropIssueChangesTable(Database db) {
+ super(db);
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ if (DatabaseUtils.tableExists("tmp_issue_changes", connection)) {
+ context.execute(new DropTableBuilder(getDialect(), "issue_changes").build());
+ }
+ }
+ }
+}
*/
package org.sonar.server.platform.db.migration.version.v85;
+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.RenameTableBuilder;
import org.sonar.server.platform.db.migration.step.DdlChange;
@Override
public void execute(Context context) throws SQLException {
- context.execute(new RenameTableBuilder(getDialect())
- .setName("tmp_issue_changes").setNewName("issue_changes")
- .setAutoGeneratedId(false)
- .build());
+ try (Connection connection = getDatabase().getDataSource().getConnection()) {
+ if (DatabaseUtils.tableExists("tmp_issue_changes", connection)) {
+ context.execute(new RenameTableBuilder(getDialect())
+ .setName("tmp_issue_changes").setNewName("issue_changes")
+ .setAutoGeneratedId(false)
+ .build());
+ }
+ }
}
}
underTest.execute();
db.assertIndex(TABLE_NAME, INDEX_NAME, "issue_key");
}
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ underTest.execute();
+ underTest.execute();
+ db.assertIndex(TABLE_NAME, INDEX_NAME, "issue_key");
+ }
}
underTest.execute();
db.assertIndex(TABLE_NAME, INDEX_NAME, "kee");
}
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ underTest.execute();
+ underTest.execute();
+ db.assertIndex(TABLE_NAME, INDEX_NAME, "kee");
+ }
}
db.assertIndex(TABLE_NAME, INDEX_NAME, "project_uuid");
}
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ underTest.execute();
+ underTest.execute();
+ db.assertIndex(TABLE_NAME, INDEX_NAME, "project_uuid");
+ }
+
}
db.assertPrimaryKey("issue_changes", "pk_issue_changes", "uuid");
}
+ @Test
+ public void skip_if_project_uuid_index_exists() throws SQLException {
+ db.executeDdl("create index issue_changes_project_uuid on issue_changes ( issue_key)");
+
+ underTest.execute();
+
+ db.assertNoPrimaryKey("issue_changes");
+ }
+
@Test
public void migration_is_not_re_entrant() throws SQLException {
underTest.execute();
private CreateTmpIssueChangesTable underTest = new CreateTmpIssueChangesTable(dbTester.database());
+ @Test
+ public void skip_if_project_uuid_column_exists() throws SQLException {
+ dbTester.executeDdl("ALTER TABLE issue_changes ADD project_uuid VARCHAR");
+
+ underTest.execute();
+ dbTester.assertTableDoesNotExist(TABLE_NAME);
+ }
+
@Test
public void table_has_been_created() throws SQLException {
underTest.execute();
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 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;
+
+import java.sql.SQLException;
+import org.junit.Rule;
+import org.junit.Test;
+import org.sonar.db.CoreDbTester;
+import org.sonar.server.platform.db.migration.step.MigrationStep;
+
+public class DropIssueChangesTableTest {
+ @Rule
+ public CoreDbTester db = CoreDbTester.createForSchema(DropIssueChangesTableTest.class, "schema.sql");
+
+ private MigrationStep underTest = new DropIssueChangesTable(db.database());
+
+ @Test
+ public void dont_drop_if_tmp_table_doesnt_exist() throws SQLException {
+ db.executeDdl("drop table tmp_issue_changes");
+ underTest.execute();
+ db.assertTableExists("issue_changes");
+ }
+
+ @Test
+ public void execute() throws SQLException {
+ db.assertTableExists("issue_changes");
+ underTest.execute();
+ db.assertTableDoesNotExist("issue_changes");
+ }
+
+ @Test
+ public void migration_is_re_entrant() throws SQLException {
+ db.assertTableExists("issue_changes");
+
+ underTest.execute();
+
+ // re-entrant
+ underTest.execute();
+ db.assertTableDoesNotExist("issue_changes");
+ }
+}
db.assertColumnDefinition("issue_changes", "issue_key", VARCHAR, 50, false);
}
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ underTest.execute();
+ underTest.execute();
+
+ db.assertColumnDefinition("issue_changes", "issue_key", VARCHAR, 50, false);
+ }
}
db.assertColumnDefinition("issue_changes", "project_uuid", VARCHAR, 50, false);
}
+
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ underTest.execute();
+ underTest.execute();
+
+ db.assertColumnDefinition("issue_changes", "project_uuid", VARCHAR, 50, false);
+ }
}
db.assertColumnDefinition("issue_changes", "uuid", VARCHAR, 40, false);
}
+ @Test
+ public void migration_is_reentrant() throws SQLException {
+ underTest.execute();
+ underTest.execute();
+
+ db.assertColumnDefinition("issue_changes", "uuid", VARCHAR, 40, false);
+ }
+
}
private final RenameTmpIssueChangesToIssueChanges underTest = new RenameTmpIssueChangesToIssueChanges(dbTester.database());
+ @Test
+ public void only_rename_if_tmp_table_exists() throws SQLException {
+ dbTester.executeDdl("drop table " + OLD_TABLE_NAME);
+ underTest.execute();
+
+ dbTester.assertTableDoesNotExist(OLD_TABLE_NAME);
+ dbTester.assertTableDoesNotExist(NEW_TABLE_NAME);
+ }
+
@Test
public void table_has_been_renamed() throws SQLException {
underTest.execute();
);
CREATE INDEX "ISSUE_CHANGES_ISSUE_KEY" ON "ISSUE_CHANGES"("ISSUE_KEY");
CREATE INDEX "ISSUE_CHANGES_KEE" ON "ISSUE_CHANGES"("KEE");
+
+CREATE TABLE "ISSUES"(
+ "KEE" VARCHAR(50) NOT NULL,
+ "RULE_UUID" VARCHAR(40),
+ "SEVERITY" VARCHAR(10),
+ "MANUAL_SEVERITY" BOOLEAN NOT NULL,
+ "MESSAGE" VARCHAR(4000),
+ "LINE" INTEGER,
+ "GAP" DOUBLE,
+ "STATUS" VARCHAR(20),
+ "RESOLUTION" VARCHAR(20),
+ "CHECKSUM" VARCHAR(1000),
+ "REPORTER" VARCHAR(255),
+ "ASSIGNEE" VARCHAR(255),
+ "AUTHOR_LOGIN" VARCHAR(255),
+ "ACTION_PLAN_KEY" VARCHAR(50),
+ "ISSUE_ATTRIBUTES" VARCHAR(4000),
+ "EFFORT" INTEGER,
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "ISSUE_CREATION_DATE" BIGINT,
+ "ISSUE_UPDATE_DATE" BIGINT,
+ "ISSUE_CLOSE_DATE" BIGINT,
+ "TAGS" VARCHAR(4000),
+ "COMPONENT_UUID" VARCHAR(50),
+ "PROJECT_UUID" VARCHAR(50),
+ "LOCATIONS" BLOB,
+ "ISSUE_TYPE" TINYINT,
+ "FROM_HOTSPOT" BOOLEAN
+);
+ALTER TABLE "ISSUES" ADD CONSTRAINT "PK_ISSUES" PRIMARY KEY("KEE");
+CREATE INDEX "ISSUES_ASSIGNEE" ON "ISSUES"("ASSIGNEE");
+CREATE INDEX "ISSUES_COMPONENT_UUID" ON "ISSUES"("COMPONENT_UUID");
+CREATE INDEX "ISSUES_CREATION_DATE" ON "ISSUES"("ISSUE_CREATION_DATE");
+CREATE UNIQUE INDEX "ISSUES_KEE" ON "ISSUES"("KEE");
+CREATE INDEX "ISSUES_PROJECT_UUID" ON "ISSUES"("PROJECT_UUID");
+CREATE INDEX "ISSUES_RESOLUTION" ON "ISSUES"("RESOLUTION");
+CREATE INDEX "ISSUES_UPDATED_AT" ON "ISSUES"("UPDATED_AT");
+CREATE INDEX "ISSUES_RULE_UUID" ON "ISSUES"("RULE_UUID");
--- /dev/null
+CREATE TABLE "ISSUE_CHANGES"(
+ "ID" BIGINT NOT NULL AUTO_INCREMENT (1,1),
+ "KEE" VARCHAR(50),
+ "ISSUE_KEY" VARCHAR(50) NOT NULL,
+ "USER_LOGIN" VARCHAR(255),
+ "CHANGE_TYPE" VARCHAR(20),
+ "CHANGE_DATA" CLOB(2147483647),
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "ISSUE_CHANGE_CREATION_DATE" BIGINT
+);
+CREATE INDEX "ISSUE_CHANGES_ISSUE_KEY" ON "ISSUE_CHANGES"("ISSUE_KEY");
+CREATE INDEX "ISSUE_CHANGES_KEE" ON "ISSUE_CHANGES"("KEE");
+
+CREATE TABLE "TMP_ISSUE_CHANGES"(
+ "UUID" VARCHAR(40),
+ "KEE" VARCHAR(50),
+ "ISSUE_KEY" VARCHAR(50),
+ "USER_LOGIN" VARCHAR(255),
+ "CHANGE_TYPE" VARCHAR(20),
+ "CHANGE_DATA" CLOB(2147483647),
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "PROJECT_UUID" VARCHAR(50),
+ "ISSUE_CHANGE_CREATION_DATE" BIGINT
+);
+
+CREATE TABLE "ISSUE_CHANGES_COPY"(
+ "UUID" VARCHAR(40) NOT NULL,
+ "KEE" VARCHAR(50),
+ "ISSUE_KEY" VARCHAR(50) NOT NULL,
+ "USER_LOGIN" VARCHAR(255),
+ "CHANGE_TYPE" VARCHAR(20),
+ "CHANGE_DATA" CLOB(2147483647),
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT,
+ "ISSUE_CHANGE_CREATION_DATE" BIGINT
+);
+