]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8520 move H2 scripts to sonar-db-dao
authorSébastien Lesaint <sebastien.lesaint@sonarsource.com>
Fri, 19 Jul 2019 12:17:16 +0000 (14:17 +0200)
committerSonarTech <sonartech@sonarsource.com>
Fri, 9 Aug 2019 18:21:24 +0000 (20:21 +0200)
27 files changed:
server/sonar-db-core/build.gradle
server/sonar-db-core/src/main/java/org/sonar/db/CoreDdlUtils.java [new file with mode: 0644]
server/sonar-db-core/src/main/java/org/sonar/db/DdlUtils.java [deleted file]
server/sonar-db-core/src/main/resources/org/sonar/db/version/rows-h2.sql [deleted file]
server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl [deleted file]
server/sonar-db-core/src/main/resources/org/sonar/db/version/schema_migrations-h2.ddl [deleted file]
server/sonar-db-core/src/test/java/org/sonar/db/AbstractDbTester.java
server/sonar-db-core/src/test/java/org/sonar/db/CoreDbTester.java
server/sonar-db-core/src/test/java/org/sonar/db/CoreDdlUtilsTest.java [new file with mode: 0644]
server/sonar-db-core/src/test/java/org/sonar/db/CoreH2Database.java [new file with mode: 0644]
server/sonar-db-core/src/test/java/org/sonar/db/CoreTestDb.java
server/sonar-db-core/src/test/java/org/sonar/db/DdlUtilsTest.java [deleted file]
server/sonar-db-core/src/test/java/org/sonar/db/H2Database.java [deleted file]
server/sonar-db-core/src/test/java/org/sonar/db/H2DatabaseTest.java [deleted file]
server/sonar-db-core/src/test/java/org/sonar/db/TestDb.java [new file with mode: 0644]
server/sonar-db-dao/build.gradle
server/sonar-db-dao/src/main/java/org/sonar/db/DdlUtils.java [new file with mode: 0644]
server/sonar-db-dao/src/main/resources/org/sonar/db/rows-h2.sql [new file with mode: 0644]
server/sonar-db-dao/src/main/resources/org/sonar/db/schema-h2.ddl [new file with mode: 0644]
server/sonar-db-dao/src/main/resources/org/sonar/db/schema_migrations-h2.ddl [new file with mode: 0644]
server/sonar-db-dao/src/test/java/org/sonar/db/DbTester.java
server/sonar-db-dao/src/test/java/org/sonar/db/DdlUtilsTest.java [new file with mode: 0644]
server/sonar-db-dao/src/test/java/org/sonar/db/H2Database.java [new file with mode: 0644]
server/sonar-db-dao/src/test/java/org/sonar/db/H2DatabaseTest.java [new file with mode: 0644]
server/sonar-db-dao/src/test/java/org/sonar/db/TestDb.java [deleted file]
server/sonar-db-dao/src/test/java/org/sonar/db/TestDbImpl.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/platform/db/migration/AutoDbMigration.java

index 77ecbeb8818f13079b6b7519fa0a66a701c8459b..5a89af7bac344a23564d86bfd3b6d95d3c8d71f0 100644 (file)
@@ -24,6 +24,7 @@ dependencies {
   compileOnly 'com.google.code.findbugs:jsr305'
 
   testCompile 'com.google.code.findbugs:jsr305'
+  testCompile 'com.h2database:h2'
   testCompile 'com.microsoft.sqlserver:mssql-jdbc'
   testCompile 'com.oracle.jdbc:ojdbc8'
   testCompile 'com.tngtech.java:junit-dataprovider'
diff --git a/server/sonar-db-core/src/main/java/org/sonar/db/CoreDdlUtils.java b/server/sonar-db-core/src/main/java/org/sonar/db/CoreDdlUtils.java
new file mode 100644 (file)
index 0000000..a219ff5
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.db;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import org.apache.commons.io.output.NullWriter;
+import org.apache.ibatis.io.Resources;
+import org.apache.ibatis.jdbc.ScriptRunner;
+
+/**
+ * Util class to create Sonar database tables
+ *
+ * @since 2.12
+ */
+public final class CoreDdlUtils {
+
+  private CoreDdlUtils() {
+  }
+
+  public static boolean supportsDialect(String dialect) {
+    return "h2".equals(dialect);
+  }
+
+  public static void executeScript(Connection connection, String path) {
+    ScriptRunner scriptRunner = newScriptRunner(connection);
+    try {
+      scriptRunner.runScript(Resources.getResourceAsReader(path));
+      connection.commit();
+
+    } catch (Exception e) {
+      throw new IllegalStateException("Fail to restore: " + path, e);
+    }
+  }
+
+  private static ScriptRunner newScriptRunner(Connection connection) {
+    ScriptRunner scriptRunner = new ScriptRunner(connection);
+    scriptRunner.setDelimiter(";");
+    scriptRunner.setStopOnError(true);
+    scriptRunner.setLogWriter(new PrintWriter(new NullWriter()));
+    return scriptRunner;
+  }
+}
diff --git a/server/sonar-db-core/src/main/java/org/sonar/db/DdlUtils.java b/server/sonar-db-core/src/main/java/org/sonar/db/DdlUtils.java
deleted file mode 100644 (file)
index 67c0050..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.db;
-
-import java.io.PrintWriter;
-import java.sql.Connection;
-import org.apache.commons.io.output.NullWriter;
-import org.apache.ibatis.io.Resources;
-import org.apache.ibatis.jdbc.ScriptRunner;
-
-/**
- * Util class to create Sonar database tables
- *
- * @since 2.12
- */
-public final class DdlUtils {
-
-  private DdlUtils() {
-  }
-
-  public static boolean supportsDialect(String dialect) {
-    return "h2".equals(dialect);
-  }
-
-  /**
-   * The connection is commited in this method but not closed.
-   */
-  public static void createSchema(Connection connection, String dialect, boolean createSchemaMigrations) {
-    if (createSchemaMigrations) {
-      executeScript(connection, "org/sonar/db/version/schema_migrations-" + dialect + ".ddl");
-    }
-    executeScript(connection, "org/sonar/db/version/schema-" + dialect + ".ddl");
-    executeScript(connection, "org/sonar/db/version/rows-" + dialect + ".sql");
-  }
-
-  public static void executeScript(Connection connection, String path) {
-    ScriptRunner scriptRunner = newScriptRunner(connection);
-    try {
-      scriptRunner.runScript(Resources.getResourceAsReader(path));
-      connection.commit();
-
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to restore: " + path, e);
-    }
-  }
-
-  private static ScriptRunner newScriptRunner(Connection connection) {
-    ScriptRunner scriptRunner = new ScriptRunner(connection);
-    scriptRunner.setDelimiter(";");
-    scriptRunner.setStopOnError(true);
-    scriptRunner.setLogWriter(new PrintWriter(new NullWriter()));
-    return scriptRunner;
-  }
-}
diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/rows-h2.sql b/server/sonar-db-core/src/main/resources/org/sonar/db/version/rows-h2.sql
deleted file mode 100644 (file)
index fb12115..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-INSERT INTO USERS(ID, UUID, LOGIN, NAME, EMAIL, EXTERNAL_ID, EXTERNAL_LOGIN, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, HASH_METHOD, IS_ROOT, ONBOARDED, CREATED_AT, UPDATED_AT) VALUES (1, 'UuidnciQUUs7Zd3KPvFD', 'admin', 'Administrator', null, 'admin', 'admin', 'sonarqube', true, '$2a$12$uCkkXmhW5ThVK8mpBvnXOOJRLd64LJeHTeCkSuB3lfaR2N0AYBaSi', null, 'BCRYPT', false, true, '1418215735482', '1418215735482');
-ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
-
-INSERT INTO GROUPS(ID, ORGANIZATION_UUID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (1, 'AVdqnciQUUs7Zd3KPvFD', 'sonar-administrators', 'System administrators', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
-INSERT INTO GROUPS(ID, ORGANIZATION_UUID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (2, 'AVdqnciQUUs7Zd3KPvFD', 'sonar-users', 'Any new users created will automatically join this group', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
-ALTER TABLE GROUPS ALTER COLUMN ID RESTART WITH 3;
-
-INSERT INTO QUALITY_GATES(ID, UUID, NAME, IS_BUILT_IN, CREATED_AT, UPDATED_AT) VALUES (1, 'AWASGWAKYOI_InFKS3UF', 'Sonar way', true, '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
-
-INSERT INTO ORGANIZATIONS (UUID, KEE, NAME, GUARDED, NEW_PROJECT_PRIVATE, DEFAULT_GROUP_ID, DEFAULT_QUALITY_GATE_UUID, SUBSCRIPTION, CREATED_AT, UPDATED_AT) VALUES ('AVdqnciQUUs7Zd3KPvFD', 'default-organization', 'Default Organization', true, false, 2, 'AWASGWAKYOI_InFKS3UF', 'SONARQUBE', '1474962596482', '1474962596482');
-INSERT INTO ORG_QUALITY_GATES (UUID, ORGANIZATION_UUID, QUALITY_GATE_UUID) VALUES ('AWAwlGzz-5zzlJtFU9G5', 'AVdqnciQUUs7Zd3KPvFD', 'AWASGWAKYOI_InFKS3UF');
-
-INSERT INTO INTERNAL_PROPERTIES (KEE, IS_EMPTY, TEXT_VALUE, CREATED_AT) VALUES ('organization.default', false, 'AVdqnciQUUs7Zd3KPvFD', '1474962596482');
-
-INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (1, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'admin');
-INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (2, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'profileadmin');
-INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (3, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'gateadmin');
-INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (4, 'AVdqnciQUUs7Zd3KPvFD', null, null, 'scan');
-INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (5, 'AVdqnciQUUs7Zd3KPvFD', null, null, 'provisioning');
-INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (6, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'provisioning');
-INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (7, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'applicationcreator');
-INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (8, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'portfoliocreator');
-ALTER TABLE GROUP_ROLES ALTER COLUMN ID RESTART WITH 9;
-
-INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 1);
-INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 2);
-
-INSERT INTO ORGANIZATION_MEMBERS(ORGANIZATION_UUID, USER_ID) VALUES ('AVdqnciQUUs7Zd3KPvFD', 1);
diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema-h2.ddl
deleted file mode 100644 (file)
index 157cdd5..0000000
+++ /dev/null
@@ -1,976 +0,0 @@
-CREATE TABLE "ORGANIZATIONS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "KEE" VARCHAR(300) NOT NULL,
-  "NAME" VARCHAR(300) NOT NULL,
-  "DESCRIPTION" VARCHAR(256),
-  "URL" VARCHAR(256),
-  "AVATAR_URL" VARCHAR(256),
-  "GUARDED" BOOLEAN,
-  "DEFAULT_PERM_TEMPLATE_PROJECT" VARCHAR(40),
-  "DEFAULT_PERM_TEMPLATE_APP" VARCHAR(40),
-  "DEFAULT_PERM_TEMPLATE_PORT" VARCHAR(40),
-  "DEFAULT_GROUP_ID" INTEGER,
-  "DEFAULT_QUALITY_GATE_UUID" VARCHAR(40) NOT NULL,
-  "NEW_PROJECT_PRIVATE" BOOLEAN NOT NULL,
-  "SUBSCRIPTION" VARCHAR(40) NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_ORGANIZATIONS" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "ORGANIZATION_KEY" ON "ORGANIZATIONS" ("KEE");
-
-CREATE TABLE "ORGANIZATION_MEMBERS" (
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "USER_ID" INTEGER NOT NULL,
-
-  CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY ("ORGANIZATION_UUID", "USER_ID")
-);
-CREATE INDEX "IX_ORG_MEMBERS_ON_USER_ID" ON "ORGANIZATION_MEMBERS" ("USER_ID");
-
-CREATE TABLE "GROUPS_USERS" (
-  "USER_ID" INTEGER,
-  "GROUP_ID" INTEGER
-);
-CREATE INDEX "INDEX_GROUPS_USERS_ON_GROUP_ID" ON "GROUPS_USERS" ("GROUP_ID");
-CREATE INDEX "INDEX_GROUPS_USERS_ON_USER_ID" ON "GROUPS_USERS" ("USER_ID");
-CREATE UNIQUE INDEX "GROUPS_USERS_UNIQUE" ON "GROUPS_USERS" ("GROUP_ID", "USER_ID");
-
-
-CREATE TABLE "RULES_PARAMETERS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "RULE_ID" INTEGER NOT NULL,
-  "NAME" VARCHAR(128) NOT NULL,
-  "PARAM_TYPE" VARCHAR(512) NOT NULL,
-  "DEFAULT_VALUE" VARCHAR(4000),
-  "DESCRIPTION" VARCHAR(4000)
-);
-CREATE INDEX "RULES_PARAMETERS_RULE_ID" ON "RULES_PARAMETERS" ("RULE_ID");
-CREATE UNIQUE INDEX "RULES_PARAMETERS_UNIQUE" ON "RULES_PARAMETERS" ("RULE_ID", "NAME");
-
-
-CREATE TABLE "RULES_PROFILES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "NAME" VARCHAR(100) NOT NULL,
-  "LANGUAGE" VARCHAR(20),
-  "KEE" VARCHAR(255) NOT NULL,
-  "RULES_UPDATED_AT" VARCHAR(100),
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP,
-  "IS_BUILT_IN" BOOLEAN NOT NULL
-);
-CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES" ("KEE");
-
-
-CREATE TABLE "ORG_QPROFILES" (
-  "UUID" VARCHAR(255) NOT NULL,
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "RULES_PROFILE_UUID" VARCHAR(255) NOT NULL,
-  "PARENT_UUID" VARCHAR(255),
-  "LAST_USED" BIGINT,
-  "USER_UPDATED_AT" BIGINT,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_ORG_QPROFILES" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "ORG_QPROFILES_ORG_UUID" ON "ORG_QPROFILES" ("ORGANIZATION_UUID");
-CREATE INDEX "ORG_QPROFILES_RP_UUID" ON "ORG_QPROFILES" ("RULES_PROFILE_UUID");
-CREATE INDEX "ORG_QPROFILES_PARENT_UUID" ON "ORG_QPROFILES" ("PARENT_UUID");
-
-
-CREATE TABLE "DEFAULT_QPROFILES" (
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "LANGUAGE" VARCHAR(20) NOT NULL,
-  "QPROFILE_UUID" VARCHAR(255) NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_DEFAULT_QPROFILES" PRIMARY KEY ("ORGANIZATION_UUID", "LANGUAGE")
-);
-CREATE UNIQUE INDEX "UNIQ_DEFAULT_QPROFILES_UUID" ON "DEFAULT_QPROFILES" ("QPROFILE_UUID");
-
-
-CREATE TABLE "PROJECT_QPROFILES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "PROJECT_UUID" VARCHAR(50) NOT NULL,
-  "PROFILE_KEY" VARCHAR(50) NOT NULL
-);
-CREATE UNIQUE INDEX "UNIQ_PROJECT_QPROFILES" ON "PROJECT_QPROFILES" ("PROJECT_UUID", "PROFILE_KEY");
-
-
-CREATE TABLE "QPROFILE_EDIT_USERS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "USER_ID" INTEGER NOT NULL,
-  "QPROFILE_UUID" VARCHAR(255) NOT NULL,
-  "CREATED_AT" BIGINT,
-
-  CONSTRAINT "PK_QPROFILE_EDIT_USERS" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "QPROFILE_EDIT_USERS_QPROFILE" ON "QPROFILE_EDIT_USERS" ("QPROFILE_UUID");
-CREATE UNIQUE INDEX "QPROFILE_EDIT_USERS_UNIQUE" ON "QPROFILE_EDIT_USERS" ("USER_ID", "QPROFILE_UUID");
-
-
-CREATE TABLE "QPROFILE_EDIT_GROUPS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "GROUP_ID" INTEGER NOT NULL,
-  "QPROFILE_UUID" VARCHAR(255) NOT NULL,
-  "CREATED_AT" BIGINT,
-
-  CONSTRAINT "PK_QPROFILE_EDIT_GROUPS" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "QPROFILE_EDIT_GROUPS_QPROFILE" ON "QPROFILE_EDIT_GROUPS" ("QPROFILE_UUID");
-CREATE UNIQUE INDEX "QPROFILE_EDIT_GROUPS_UNIQUE" ON "QPROFILE_EDIT_GROUPS" ("GROUP_ID", "QPROFILE_UUID");
-
-
-CREATE TABLE "GROUPS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "NAME" VARCHAR(500),
-  "DESCRIPTION" VARCHAR(200),
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP
-);
-
-
-CREATE TABLE "SNAPSHOTS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "UUID" VARCHAR(50) NOT NULL,
-  "CREATED_AT" BIGINT,
-  "BUILD_DATE" BIGINT,
-  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
-  "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
-  "PURGE_STATUS" INTEGER,
-  "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
-  "VERSION" VARCHAR(500),
-  "BUILD_STRING" VARCHAR(100),
-  "PERIOD1_MODE" VARCHAR(100),
-  "PERIOD1_PARAM" VARCHAR(100),
-  "PERIOD1_DATE" BIGINT,
-  "PERIOD2_MODE" VARCHAR(100),
-  "PERIOD2_PARAM" VARCHAR(100),
-  "PERIOD2_DATE" BIGINT,
-  "PERIOD3_MODE" VARCHAR(100),
-  "PERIOD3_PARAM" VARCHAR(100),
-  "PERIOD3_DATE" BIGINT,
-  "PERIOD4_MODE" VARCHAR(100),
-  "PERIOD4_PARAM" VARCHAR(100),
-  "PERIOD4_DATE" BIGINT,
-  "PERIOD5_MODE" VARCHAR(100),
-  "PERIOD5_PARAM" VARCHAR(100),
-  "PERIOD5_DATE" BIGINT,
-  "REVISION" VARCHAR(100)
-);
-CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS" ("COMPONENT_UUID");
-CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS" ("UUID");
-
-CREATE TABLE "GROUP_ROLES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "GROUP_ID" INTEGER,
-  "RESOURCE_ID" INTEGER,
-  "ROLE" VARCHAR(64) NOT NULL
-);
-CREATE INDEX "GROUP_ROLES_RESOURCE" ON "GROUP_ROLES" ("RESOURCE_ID");
-CREATE UNIQUE INDEX "UNIQ_GROUP_ROLES" ON "GROUP_ROLES" ("ORGANIZATION_UUID", "GROUP_ID", "RESOURCE_ID", "ROLE");
-
-
-CREATE TABLE "RULE_REPOSITORIES" (
-  "KEE" VARCHAR(200) NOT NULL,
-  "LANGUAGE" VARCHAR(20) NOT NULL,
-  "NAME" VARCHAR(4000) NOT NULL,
-  "CREATED_AT" BIGINT,
-
-  CONSTRAINT "PK_RULE_REPOSITORIES" PRIMARY KEY ("KEE")
-);
-
-CREATE TABLE "DEPRECATED_RULE_KEYS" (
-  "UUID"  VARCHAR(40) NOT NULL,
-  "RULE_ID" INTEGER NOT NULL,
-  "OLD_REPOSITORY_KEY" VARCHAR(200) NOT NULL,
-  "OLD_RULE_KEY" VARCHAR(255) NOT NULL,
-  "CREATED_AT" BIGINT,
-
-  CONSTRAINT "PK_DEPRECATED_RULE_KEYS" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "UNIQ_DEPRECATED_RULE_KEYS" ON "DEPRECATED_RULE_KEYS" ("OLD_REPOSITORY_KEY", "OLD_RULE_KEY");
-CREATE INDEX "RULE_ID_DEPRECATED_RULE_KEYS" ON "DEPRECATED_RULE_KEYS" ("RULE_ID");
-
-CREATE TABLE "RULES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "PLUGIN_KEY" VARCHAR(200),
-  "PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL,
-  "PLUGIN_NAME" VARCHAR(255) NOT NULL,
-  "DESCRIPTION" VARCHAR(16777215),
-  "DESCRIPTION_FORMAT" VARCHAR(20),
-  "PRIORITY" INTEGER,
-  "IS_TEMPLATE" BOOLEAN DEFAULT FALSE,
-  "IS_EXTERNAL" BOOLEAN NOT NULL,
-  "IS_AD_HOC" BOOLEAN NOT NULL,
-  "TEMPLATE_ID" INTEGER,
-  "PLUGIN_CONFIG_KEY" VARCHAR(200),
-  "NAME" VARCHAR(200),
-  "STATUS" VARCHAR(40),
-  "LANGUAGE" VARCHAR(20),
-  "SCOPE" VARCHAR(20) NOT NULL,
-  "DEF_REMEDIATION_FUNCTION" VARCHAR(20),
-  "DEF_REMEDIATION_GAP_MULT" VARCHAR(20),
-  "DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20),
-  "GAP_DESCRIPTION" VARCHAR(4000),
-  "SYSTEM_TAGS" VARCHAR(4000),
-  "SECURITY_STANDARDS" VARCHAR(4000),
-  "RULE_TYPE" TINYINT,
-  "CREATED_AT" BIGINT,
-  "UPDATED_AT" BIGINT
-);
-CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY");
-
-CREATE TABLE "RULES_METADATA" (
-  "RULE_ID" INTEGER NOT NULL,
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "NOTE_DATA" CLOB,
-  "NOTE_USER_UUID" VARCHAR(255),
-  "NOTE_CREATED_AT" BIGINT,
-  "NOTE_UPDATED_AT" BIGINT,
-  "REMEDIATION_FUNCTION" VARCHAR(20),
-  "REMEDIATION_GAP_MULT" VARCHAR(20),
-  "REMEDIATION_BASE_EFFORT" VARCHAR(20),
-  "TAGS" VARCHAR(4000),
-  "AD_HOC_NAME" VARCHAR(200),
-  "AD_HOC_DESCRIPTION" VARCHAR(16777215),
-  "AD_HOC_SEVERITY" VARCHAR(10),
-  "AD_HOC_TYPE" TINYINT,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_RULES_METADATA" PRIMARY KEY ("RULE_ID", "ORGANIZATION_UUID")
-);
-
-CREATE TABLE "EVENTS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "UUID" VARCHAR(40) NOT NULL,
-  "NAME" VARCHAR(400),
-  "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
-  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
-  "CATEGORY" VARCHAR(50),
-  "EVENT_DATE" BIGINT NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "DESCRIPTION" VARCHAR(4000),
-  "EVENT_DATA"  VARCHAR(4000)
-);
-CREATE INDEX "EVENTS_ANALYSIS" ON "EVENTS" ("ANALYSIS_UUID");
-CREATE INDEX "EVENTS_COMPONENT_UUID" ON "EVENTS" ("COMPONENT_UUID");
-CREATE UNIQUE INDEX "EVENTS_UUID" ON "EVENTS" ("UUID");
-
-CREATE TABLE "EVENT_COMPONENT_CHANGES" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "EVENT_UUID" VARCHAR(40) NOT NULL,
-  "EVENT_COMPONENT_UUID" VARCHAR(50) NOT NULL,
-  "EVENT_ANALYSIS_UUID" VARCHAR(50) NOT NULL,
-  "CHANGE_CATEGORY" VARCHAR(20) NOT NULL,
-  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
-  "COMPONENT_KEY" VARCHAR(400) NOT NULL,
-  "COMPONENT_NAME" VARCHAR(2000) NOT NULL,
-  "COMPONENT_BRANCH_KEY" VARCHAR(255),
-  "CREATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_EVENT_COMPONENT_CHANGES" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "EVENT_COMPONENT_CHANGES_UNIQUE" ON "EVENT_COMPONENT_CHANGES" ("EVENT_UUID", "CHANGE_CATEGORY", "COMPONENT_UUID");
-CREATE INDEX "EVENT_CPNT_CHANGES_CPNT" ON "EVENT_COMPONENT_CHANGES" ("EVENT_COMPONENT_UUID");
-CREATE INDEX "EVENT_CPNT_CHANGES_ANALYSIS" ON "EVENT_COMPONENT_CHANGES" ("EVENT_ANALYSIS_UUID");
-
-
-CREATE TABLE "QUALITY_GATES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "UUID" VARCHAR(40) NOT NULL,
-  "NAME" VARCHAR(100) NOT NULL,
-  "IS_BUILT_IN" BOOLEAN NOT NULL,
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP,
-);
-CREATE UNIQUE INDEX "UNIQ_QUALITY_GATES_UUID" ON "QUALITY_GATES" ("UUID");
-
-
-CREATE TABLE "QUALITY_GATE_CONDITIONS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "QGATE_ID" INTEGER,
-  "METRIC_ID" INTEGER,
-  "OPERATOR" VARCHAR(3),
-  "VALUE_ERROR" VARCHAR(64),
-  "VALUE_WARNING" VARCHAR(64),
-  "PERIOD" INTEGER,
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP,
-);
-
-CREATE TABLE "ORG_QUALITY_GATES" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "QUALITY_GATE_UUID" VARCHAR(40) NOT NULL,
-
-  CONSTRAINT "PK_ORG_QUALITY_GATES" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "UNIQ_ORG_QUALITY_GATES" ON "ORG_QUALITY_GATES" ("ORGANIZATION_UUID","QUALITY_GATE_UUID");
-
-CREATE TABLE "PROJECT_QGATES" (
-"PROJECT_UUID" VARCHAR(40) NOT NULL,
-"QUALITY_GATE_UUID" VARCHAR(40) NOT NULL,
-
-CONSTRAINT "PK_PROJECT_QGATES" PRIMARY KEY ("PROJECT_UUID")
-);
-CREATE UNIQUE INDEX "UNIQ_PROJECT_QGATES" ON "PROJECT_QGATES" ("PROJECT_UUID", "QUALITY_GATE_UUID");
-
-CREATE TABLE "PROPERTIES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "PROP_KEY" VARCHAR(512) NOT NULL,
-  "RESOURCE_ID" INTEGER,
-  "USER_ID" INTEGER,
-  "IS_EMPTY" BOOLEAN NOT NULL,
-  "TEXT_VALUE" VARCHAR(4000),
-  "CLOB_VALUE" CLOB,
-  "CREATED_AT" BIGINT
-);
-CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");
-
-
-CREATE TABLE "PROJECT_LINKS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "PROJECT_UUID" VARCHAR(50) NOT NULL,
-  "LINK_TYPE" VARCHAR(20) NOT NULL,
-  "NAME" VARCHAR(128),
-  "HREF" VARCHAR(2048) NOT NULL,
-  "CREATED_AT" BIGINT,
-  "UPDATED_AT" BIGINT,
-
-   CONSTRAINT "PK_PROJECT_LINKS" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "PROJECT_LINKS_PROJECT" ON "PROJECT_LINKS" ("PROJECT_UUID");
-
-
-CREATE TABLE "DUPLICATIONS_INDEX" (
-  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
-  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
-  "HASH" VARCHAR(50) NOT NULL,
-  "INDEX_IN_FILE" INTEGER NOT NULL,
-  "START_LINE" INTEGER NOT NULL,
-  "END_LINE" INTEGER NOT NULL
-);
-CREATE INDEX "DUPLICATIONS_INDEX_HASH" ON "DUPLICATIONS_INDEX" ("HASH");
-CREATE INDEX "DUPLICATION_ANALYSIS_COMPONENT" ON "DUPLICATIONS_INDEX" ("ANALYSIS_UUID", "COMPONENT_UUID");
-
-
-CREATE TABLE "LIVE_MEASURES" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "PROJECT_UUID" VARCHAR(50) NOT NULL,
-  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
-  "METRIC_ID" INTEGER NOT NULL,
-  "VALUE" DOUBLE,
-  "TEXT_VALUE" VARCHAR(4000),
-  "VARIATION" DOUBLE,
-  "MEASURE_DATA" BINARY,
-  "UPDATE_MARKER" VARCHAR(40),
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_LIVE_MEASURES" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "LIVE_MEASURES_PROJECT" ON "LIVE_MEASURES" ("PROJECT_UUID");
-CREATE UNIQUE INDEX "LIVE_MEASURES_COMPONENT" ON "LIVE_MEASURES" ("COMPONENT_UUID", "METRIC_ID");
-
-
-CREATE TABLE "PROJECT_MEASURES" (
-  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "VALUE" DOUBLE,
-  "METRIC_ID" INTEGER NOT NULL,
-  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
-  "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
-  "TEXT_VALUE" VARCHAR(4000),
-  "ALERT_STATUS" VARCHAR(5),
-  "ALERT_TEXT" VARCHAR(4000),
-  "DESCRIPTION" VARCHAR(4000),
-  "PERSON_ID" INTEGER,
-  "VARIATION_VALUE_1" DOUBLE,
-  "VARIATION_VALUE_2" DOUBLE,
-  "VARIATION_VALUE_3" DOUBLE,
-  "VARIATION_VALUE_4" DOUBLE,
-  "VARIATION_VALUE_5" DOUBLE,
-  "MEASURE_DATA" BINARY
-);
-CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES" ("COMPONENT_UUID");
-CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES" ("ANALYSIS_UUID", "METRIC_ID");
-
-
-CREATE TABLE "INTERNAL_PROPERTIES" (
-  "KEE" VARCHAR(20) NOT NULL,
-  "IS_EMPTY" BOOLEAN NOT NULL,
-  "TEXT_VALUE" VARCHAR(4000),
-  "CLOB_VALUE" CLOB,
-  "CREATED_AT" BIGINT,
-
-  CONSTRAINT "PK_INTERNAL_PROPERTIES" PRIMARY KEY ("KEE")
-);
-
-
-CREATE TABLE "PROJECTS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "KEE" VARCHAR(400),
-  "UUID" VARCHAR(50) NOT NULL,
-  "UUID_PATH" VARCHAR(1500) NOT NULL,
-  "ROOT_UUID" VARCHAR(50) NOT NULL,
-  "PROJECT_UUID" VARCHAR(50) NOT NULL,
-  "MODULE_UUID" VARCHAR(50),
-  "MODULE_UUID_PATH" VARCHAR(1500),
-  "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
-  "NAME" VARCHAR(2000),
-  "DESCRIPTION" VARCHAR(2000),
-  "PRIVATE" BOOLEAN NOT NULL,
-  "TAGS" VARCHAR(500),
-  "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
-  "SCOPE" VARCHAR(3),
-  "QUALIFIER" VARCHAR(10),
-  "DEPRECATED_KEE" VARCHAR(400),
-  "PATH" VARCHAR(2000),
-  "LANGUAGE" VARCHAR(20),
-  "COPY_COMPONENT_UUID" VARCHAR(50),
-  "LONG_NAME" VARCHAR(2000),
-  "DEVELOPER_UUID" VARCHAR(50),
-  "CREATED_AT" TIMESTAMP,
-  "AUTHORIZATION_UPDATED_AT" BIGINT,
-  "B_CHANGED" BOOLEAN,
-  "B_COPY_COMPONENT_UUID" VARCHAR(50),
-  "B_DESCRIPTION" VARCHAR(2000),
-  "B_ENABLED" BOOLEAN,
-  "B_UUID_PATH" VARCHAR(1500),
-  "B_LANGUAGE" VARCHAR(20),
-  "B_LONG_NAME" VARCHAR(500),
-  "B_MODULE_UUID" VARCHAR(50),
-  "B_MODULE_UUID_PATH" VARCHAR(1500),
-  "B_NAME" VARCHAR(500),
-  "B_PATH" VARCHAR(2000),
-  "B_QUALIFIER" VARCHAR(10)
-);
-CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID");
-CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
-CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
-CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
-CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
-CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
-CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
-
-CREATE TABLE "INTERNAL_COMPONENT_PROPS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
-  "KEE" VARCHAR(512) NOT NULL,
-  "VALUE" VARCHAR(4000),
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-  CONSTRAINT "INTERNAL_COMPONENT_PROPS_UUID" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "UNIQUE_COMPONENT_UUID_KEE" ON "INTERNAL_COMPONENT_PROPS" ("COMPONENT_UUID", "KEE");
-
-CREATE TABLE "MANUAL_MEASURES" (
-  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "METRIC_ID" INTEGER NOT NULL,
-  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
-  "VALUE" DOUBLE,
-  "TEXT_VALUE" VARCHAR(4000),
-  "USER_UUID" VARCHAR(255),
-  "DESCRIPTION" VARCHAR(4000),
-  "CREATED_AT" BIGINT,
-  "UPDATED_AT" BIGINT
-);
-CREATE INDEX "MANUAL_MEASURES_COMPONENT_UUID" ON "MANUAL_MEASURES" ("COMPONENT_UUID");
-
-
-CREATE TABLE "ACTIVE_RULES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "PROFILE_ID" INTEGER NOT NULL,
-  "RULE_ID" INTEGER NOT NULL,
-  "FAILURE_LEVEL" INTEGER NOT NULL,
-  "INHERITANCE" VARCHAR(10),
-  "CREATED_AT" BIGINT,
-  "UPDATED_AT" BIGINT
-);
-CREATE UNIQUE INDEX "ACTIVE_RULES_UNIQUE" ON "ACTIVE_RULES" ("PROFILE_ID","RULE_ID");
-
-
-CREATE TABLE "NOTIFICATIONS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "DATA" BLOB
-);
-
-
-CREATE TABLE "USER_ROLES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "USER_ID" INTEGER,
-  "RESOURCE_ID" INTEGER,
-  "ROLE" VARCHAR(64) NOT NULL
-);
-CREATE INDEX "USER_ROLES_RESOURCE" ON "USER_ROLES" ("RESOURCE_ID");
-CREATE INDEX "USER_ROLES_USER" ON "USER_ROLES" ("USER_ID");
-
-
-CREATE TABLE "ACTIVE_RULE_PARAMETERS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "ACTIVE_RULE_ID" INTEGER NOT NULL,
-  "RULES_PARAMETER_ID" INTEGER NOT NULL,
-  "RULES_PARAMETER_KEY" VARCHAR(128),
-  "VALUE" VARCHAR(4000)
-);
-CREATE INDEX "IX_ARP_ON_ACTIVE_RULE_ID" ON "ACTIVE_RULE_PARAMETERS" ("ACTIVE_RULE_ID");
-
-
-CREATE TABLE "USERS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "UUID" VARCHAR(255) NOT NULL,
-  "LOGIN" VARCHAR(255) NOT NULL,
-  "NAME" VARCHAR(200),
-  "EMAIL" VARCHAR(100),
-  "CRYPTED_PASSWORD" VARCHAR(100),
-  "SALT" VARCHAR(40),
-  "HASH_METHOD" VARCHAR(10),
-  "ACTIVE" BOOLEAN DEFAULT TRUE,
-  "SCM_ACCOUNTS" VARCHAR(4000),
-  "EXTERNAL_ID" VARCHAR(255) NOT NULL,
-  "EXTERNAL_LOGIN" VARCHAR(255) NOT NULL,
-  "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100) NOT NULL,
-  "IS_ROOT" BOOLEAN NOT NULL,
-  "USER_LOCAL" BOOLEAN,
-  "ONBOARDED" BOOLEAN NOT NULL,
-  "HOMEPAGE_TYPE" VARCHAR(40),
-  "HOMEPAGE_PARAMETER" VARCHAR(40),
-  "ORGANIZATION_UUID" VARCHAR(40),
-  "LAST_CONNECTION_DATE" BIGINT,
-  "CREATED_AT" BIGINT,
-  "UPDATED_AT" BIGINT
-);
-CREATE UNIQUE INDEX "USERS_UUID" ON "USERS" ("UUID");
-CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
-CREATE UNIQUE INDEX "UNIQ_EXTERNAL_ID" ON "USERS" ("EXTERNAL_IDENTITY_PROVIDER", "EXTERNAL_ID");
-CREATE UNIQUE INDEX "UNIQ_EXTERNAL_LOGIN" ON "USERS" ("EXTERNAL_IDENTITY_PROVIDER", "EXTERNAL_LOGIN");
-CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
-
-
-CREATE TABLE "METRICS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "NAME" VARCHAR(64) NOT NULL,
-  "DESCRIPTION" VARCHAR(255),
-  "DIRECTION" INTEGER NOT NULL DEFAULT 0,
-  "DOMAIN" VARCHAR(64),
-  "SHORT_NAME" VARCHAR(64),
-  "QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE,
-  "VAL_TYPE" VARCHAR(8),
-  "USER_MANAGED" BOOLEAN DEFAULT FALSE,
-  "ENABLED" BOOLEAN DEFAULT TRUE,
-  "WORST_VALUE" DOUBLE,
-  "BEST_VALUE" DOUBLE,
-  "OPTIMIZED_BEST_VALUE" BOOLEAN,
-  "HIDDEN" BOOLEAN,
-  "DELETE_HISTORICAL_DATA" BOOLEAN,
-  "DECIMAL_SCALE" INTEGER
-);
-CREATE UNIQUE INDEX "METRICS_UNIQUE_NAME" ON "METRICS" ("NAME");
-
-
-CREATE TABLE "ISSUES" (
-  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "KEE" VARCHAR(50) UNIQUE NOT NULL,
-  "COMPONENT_UUID" VARCHAR(50),
-  "PROJECT_UUID" VARCHAR(50),
-  "RULE_ID" INTEGER,
-  "SEVERITY" VARCHAR(10),
-  "MANUAL_SEVERITY" BOOLEAN NOT NULL,
-  "MESSAGE" VARCHAR(4000),
-  "LINE" INTEGER,
-  "GAP" DOUBLE,
-  "EFFORT" INTEGER,
-  "STATUS" VARCHAR(20),
-  "RESOLUTION" VARCHAR(20),
-  "CHECKSUM" VARCHAR(1000),
-  "REPORTER" VARCHAR(255),
-  "ASSIGNEE" VARCHAR(255),
-  "AUTHOR_LOGIN" VARCHAR(255),
-  "ACTION_PLAN_KEY" VARCHAR(50) NULL,
-  "ISSUE_ATTRIBUTES" VARCHAR(4000),
-  "TAGS" VARCHAR(4000),
-  "ISSUE_CREATION_DATE" BIGINT,
-  "ISSUE_CLOSE_DATE" BIGINT,
-  "ISSUE_UPDATE_DATE" BIGINT,
-  "CREATED_AT" BIGINT,
-  "UPDATED_AT" BIGINT,
-  "LOCATIONS" BLOB,
-  "ISSUE_TYPE" TINYINT,
-  "FROM_HOTSPOT" BOOLEAN NULL
-);
-CREATE UNIQUE INDEX "ISSUES_KEE" ON "ISSUES" ("KEE");
-CREATE INDEX "ISSUES_COMPONENT_UUID" ON "ISSUES" ("COMPONENT_UUID");
-CREATE INDEX "ISSUES_PROJECT_UUID" ON "ISSUES" ("PROJECT_UUID");
-CREATE INDEX "ISSUES_RULE_ID" ON "ISSUES" ("RULE_ID");
-CREATE INDEX "ISSUES_RESOLUTION" ON "ISSUES" ("RESOLUTION");
-CREATE INDEX "ISSUES_ASSIGNEE" ON "ISSUES" ("ASSIGNEE");
-CREATE INDEX "ISSUES_CREATION_DATE" ON "ISSUES" ("ISSUE_CREATION_DATE");
-CREATE INDEX "ISSUES_UPDATED_AT" ON "ISSUES" ("UPDATED_AT");
-
-
-CREATE TABLE "ISSUE_CHANGES" (
-  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "KEE" VARCHAR(50),
-  "ISSUE_KEY" VARCHAR(50) NOT NULL,
-  "USER_LOGIN" VARCHAR(255),
-  "CHANGE_TYPE" VARCHAR(40),
-  "CHANGE_DATA"  VARCHAR(16777215),
-  "CREATED_AT" BIGINT,
-  "UPDATED_AT" BIGINT,
-  "ISSUE_CHANGE_CREATION_DATE" BIGINT
-);
-CREATE INDEX "ISSUE_CHANGES_KEE" ON "ISSUE_CHANGES" ("KEE");
-CREATE INDEX "ISSUE_CHANGES_ISSUE_KEY" ON "ISSUE_CHANGES" ("ISSUE_KEY");
-
-
-CREATE TABLE "PERMISSION_TEMPLATES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "NAME" VARCHAR(100) NOT NULL,
-  "KEE" VARCHAR(100) NOT NULL,
-  "DESCRIPTION" VARCHAR(4000),
-  "KEY_PATTERN" VARCHAR(500),
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP
-);
-
-
-CREATE TABLE "PERM_TPL_CHARACTERISTICS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "TEMPLATE_ID" INTEGER NOT NULL,
-  "PERMISSION_KEY" VARCHAR(64) NOT NULL,
-  "WITH_PROJECT_CREATOR" BOOLEAN NOT NULL DEFAULT FALSE,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL
-);
-CREATE UNIQUE INDEX "UNIQ_PERM_TPL_CHARAC" ON "PERM_TPL_CHARACTERISTICS" ("TEMPLATE_ID", "PERMISSION_KEY");
-
-
-CREATE TABLE "PERM_TEMPLATES_USERS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "USER_ID" INTEGER NOT NULL,
-  "TEMPLATE_ID" INTEGER NOT NULL,
-  "PERMISSION_REFERENCE" VARCHAR(64) NOT NULL,
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP
-);
-
-
-CREATE TABLE "PERM_TEMPLATES_GROUPS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "GROUP_ID" INTEGER,
-  "TEMPLATE_ID" INTEGER NOT NULL,
-  "PERMISSION_REFERENCE" VARCHAR(64) NOT NULL,
-  "CREATED_AT" TIMESTAMP,
-  "UPDATED_AT" TIMESTAMP
-);
-
-
-CREATE TABLE "QPROFILE_CHANGES" (
-  "KEE" VARCHAR(40) NOT NULL,
-  "RULES_PROFILE_UUID" VARCHAR(255) NOT NULL,
-  "CHANGE_TYPE" VARCHAR(20) NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "USER_UUID" VARCHAR(255),
-  "CHANGE_DATA" CLOB,
-
-  CONSTRAINT "PK_QPROFILE_CHANGES" PRIMARY KEY ("KEE")
-);
-CREATE INDEX "QP_CHANGES_RULES_PROFILE_UUID" ON "QPROFILE_CHANGES" ("RULES_PROFILE_UUID");
-
-
-CREATE TABLE "FILE_SOURCES" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "PROJECT_UUID" VARCHAR(50) NOT NULL,
-  "FILE_UUID" VARCHAR(50) NOT NULL,
-  "LINE_HASHES" CLOB,
-  "LINE_HASHES_VERSION" INTEGER,
-  "LINE_COUNT" INTEGER NOT NULL,
-  "BINARY_DATA" BLOB,
-  "DATA_HASH" VARCHAR(50),
-  "SRC_HASH" VARCHAR(50),
-  "REVISION" VARCHAR(100),
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL
-);
-CREATE INDEX "FILE_SOURCES_PROJECT_UUID" ON "FILE_SOURCES" ("PROJECT_UUID");
-CREATE UNIQUE INDEX "FILE_SOURCES_FILE_UUID" ON "FILE_SOURCES" ("FILE_UUID");
-CREATE INDEX "FILE_SOURCES_UPDATED_AT" ON "FILE_SOURCES" ("UPDATED_AT");
-
-
-CREATE TABLE "CE_QUEUE" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "UUID" VARCHAR(40) NOT NULL,
-  "TASK_TYPE" VARCHAR(15) NOT NULL,
-  "COMPONENT_UUID" VARCHAR(40) NULL,
-  "MAIN_COMPONENT_UUID" VARCHAR(40) NULL,
-  "STATUS" VARCHAR(15) NOT NULL,
-  "SUBMITTER_UUID" VARCHAR(255) NULL,
-  "WORKER_UUID" VARCHAR(40) NULL,
-  "EXECUTION_COUNT" INTEGER NOT NULL,
-  "STARTED_AT" BIGINT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL
-);
-CREATE UNIQUE INDEX "CE_QUEUE_UUID" ON "CE_QUEUE" ("UUID");
-CREATE INDEX "CE_QUEUE_COMPONENT" ON "CE_QUEUE" ("COMPONENT_UUID");
-CREATE INDEX "CE_QUEUE_MAIN_COMPONENT" ON "CE_QUEUE" ("MAIN_COMPONENT_UUID");
-CREATE INDEX "CE_QUEUE_STATUS" ON "CE_QUEUE" ("STATUS");
-
-
-CREATE TABLE "CE_ACTIVITY" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "UUID" VARCHAR(40) NOT NULL,
-  "TASK_TYPE" VARCHAR(15) NOT NULL,
-  "COMPONENT_UUID" VARCHAR(40) NULL,
-  "MAIN_COMPONENT_UUID" VARCHAR(40) NULL,
-  "ANALYSIS_UUID" VARCHAR(50) NULL,
-  "STATUS" VARCHAR(15) NOT NULL,
-  "IS_LAST" BOOLEAN,
-  "IS_LAST_KEY" VARCHAR(55),
-  "MAIN_IS_LAST" BOOLEAN,
-  "MAIN_IS_LAST_KEY" VARCHAR(55),
-  "SUBMITTER_UUID" VARCHAR(255) NULL,
-  "WORKER_UUID" VARCHAR(40) NULL,
-  "EXECUTION_COUNT" INTEGER NOT NULL,
-  "SUBMITTED_AT" BIGINT NOT NULL,
-  "STARTED_AT" BIGINT NULL,
-  "EXECUTED_AT" BIGINT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-  "EXECUTION_TIME_MS" BIGINT NULL,
-  "ERROR_MESSAGE" VARCHAR(1000),
-  "ERROR_STACKTRACE" CLOB,
-  "ERROR_TYPE" VARCHAR(20)
-);
-CREATE UNIQUE INDEX "CE_ACTIVITY_UUID" ON "CE_ACTIVITY" ("UUID");
-CREATE INDEX "CE_ACTIVITY_COMPONENT" ON "CE_ACTIVITY" ("COMPONENT_UUID");
-CREATE INDEX "CE_ACTIVITY_MAIN_COMPONENT" ON "CE_ACTIVITY" ("COMPONENT_UUID");
-CREATE INDEX "CE_ACTIVITY_ISLAST_KEY" ON "CE_ACTIVITY" ("IS_LAST_KEY");
-CREATE INDEX "CE_ACTIVITY_ISLAST" ON "CE_ACTIVITY" ("IS_LAST", "STATUS");
-CREATE INDEX "CE_ACTIVITY_MAIN_ISLAST_KEY" ON "CE_ACTIVITY" ("MAIN_IS_LAST_KEY");
-CREATE INDEX "CE_ACTIVITY_MAIN_ISLAST" ON "CE_ACTIVITY" ("MAIN_IS_LAST", "STATUS");
-
-
-CREATE TABLE "CE_TASK_CHARACTERISTICS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "TASK_UUID" VARCHAR(40) NOT NULL,
-  "KEE" VARCHAR(50) NOT NULL,
-  "TEXT_VALUE" VARCHAR(4000),
-
-  CONSTRAINT "PK_CE_TASK_CHARACTERISTICS" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "CE_TASK_CHARACTERISTICS_TASK_UUID" ON "CE_TASK_CHARACTERISTICS" ("TASK_UUID");
-
-
-CREATE TABLE "CE_TASK_INPUT" (
-  "TASK_UUID" VARCHAR(40) NOT NULL,
-  "INPUT_DATA" BLOB,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_CE_TASK_INPUT" PRIMARY KEY ("TASK_UUID")
-);
-
-
-CREATE TABLE "CE_SCANNER_CONTEXT" (
-  "TASK_UUID" VARCHAR(40) NOT NULL,
-  "CONTEXT_DATA" BLOB NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_CE_SCANNER_CONTEXT" PRIMARY KEY ("TASK_UUID")
-);
-
-CREATE TABLE "CE_TASK_MESSAGE" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "TASK_UUID" VARCHAR(40) NOT NULL,
-  "MESSAGE" VARCHAR(4000) NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "CE_TASK_MESSAGE" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "CE_TASK_MESSAGE_TASK" ON "CE_TASK_MESSAGE" ("TASK_UUID");
-
-
-CREATE TABLE "USER_TOKENS" (
-  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
-  "USER_UUID" VARCHAR(255) NOT NULL,
-  "NAME" VARCHAR(100) NOT NULL,
-  "TOKEN_HASH" VARCHAR(255) NOT NULL,
-  "LAST_CONNECTION_DATE" BIGINT,
-  "CREATED_AT" BIGINT NOT NULL
-);
-CREATE UNIQUE INDEX "USER_TOKENS_TOKEN_HASH" ON "USER_TOKENS" ("TOKEN_HASH");
-CREATE UNIQUE INDEX "USER_TOKENS_USER_UUID_NAME" ON "USER_TOKENS" ("USER_UUID", "NAME");
-
-
-CREATE TABLE "ES_QUEUE" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "DOC_TYPE" VARCHAR(40) NOT NULL,
-  "DOC_ID" VARCHAR(4000) NOT NULL,
-  "DOC_ID_TYPE" VARCHAR(20),
-  "DOC_ROUTING" VARCHAR(4000),
-  "CREATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_ES_QUEUE" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "ES_QUEUE_CREATED_AT" ON "ES_QUEUE" ("CREATED_AT");
-
-
-CREATE TABLE "PLUGINS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "KEE" VARCHAR(200) NOT NULL,
-  "BASE_PLUGIN_KEY" VARCHAR(200),
-  "FILE_HASH" VARCHAR(200) NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_PLUGINS" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "PLUGINS_KEY" ON "PLUGINS" ("KEE");
-
-
-CREATE TABLE "PROJECT_BRANCHES" (
-  "UUID" VARCHAR(50) NOT NULL,
-  "PROJECT_UUID" VARCHAR(50) NOT NULL,
-  "KEE" VARCHAR(255) NOT NULL,
-  "KEY_TYPE" VARCHAR(12) NOT NULL,
-  "BRANCH_TYPE" VARCHAR(12),
-  "MERGE_BRANCH_UUID" VARCHAR(50),
-  "PULL_REQUEST_BINARY" BLOB,
-  "MANUAL_BASELINE_ANALYSIS_UUID" VARCHAR(40),
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_PROJECT_BRANCHES" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "PROJECT_BRANCHES_KEE_KEY_TYPE" ON "PROJECT_BRANCHES" ("PROJECT_UUID", "KEE", "KEY_TYPE");
-
-
-CREATE TABLE "ANALYSIS_PROPERTIES" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "ANALYSIS_UUID" VARCHAR(40) NOT NULL,
-  "KEE" VARCHAR(512) NOT NULL,
-  "TEXT_VALUE" VARCHAR(4000),
-  "CLOB_VALUE" CLOB,
-  "IS_EMPTY" BOOLEAN NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_ANALYSIS_PROPERTIES" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "ANALYSIS_PROPERTIES_ANALYSIS" ON "ANALYSIS_PROPERTIES" ("ANALYSIS_UUID");
-
-
-CREATE TABLE "WEBHOOKS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "NAME" VARCHAR(100) NOT NULL,
-  "URL" VARCHAR(2000) NOT NULL,
-  "ORGANIZATION_UUID" VARCHAR(40),
-  "PROJECT_UUID" VARCHAR(40),
-  "SECRET" VARCHAR(200),
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_WEBHOOKS" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "ORGANIZATION_WEBHOOK" ON "WEBHOOKS" ("ORGANIZATION_UUID");
-CREATE INDEX "PROJECT_WEBHOOK" ON "WEBHOOKS" ("PROJECT_UUID");
-
-
-CREATE TABLE "WEBHOOK_DELIVERIES" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "WEBHOOK_UUID" VARCHAR(40) NOT NULL,
-  "COMPONENT_UUID" VARCHAR(40) NOT NULL,
-  "ANALYSIS_UUID" VARCHAR(40),
-  "CE_TASK_UUID" VARCHAR(40),
-  "NAME" VARCHAR(100) NOT NULL,
-  "URL" VARCHAR(2000) NOT NULL,
-  "SUCCESS" BOOLEAN NOT NULL,
-  "HTTP_STATUS" INT,
-  "DURATION_MS" INT NOT NULL,
-  "PAYLOAD" CLOB NOT NULL,
-  "ERROR_STACKTRACE" CLOB,
-  "CREATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_WEBHOOK_DELIVERIES" PRIMARY KEY ("UUID")
-);
-CREATE INDEX "COMPONENT_UUID" ON "WEBHOOK_DELIVERIES" ("COMPONENT_UUID");
-CREATE INDEX "CE_TASK_UUID" ON "WEBHOOK_DELIVERIES" ("CE_TASK_UUID");
-CREATE INDEX "ANALYSIS_UUID" ON "WEBHOOK_DELIVERIES" ("ANALYSIS_UUID");
-
-
-CREATE TABLE "ALM_APP_INSTALLS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "ALM_ID" VARCHAR(40) NOT NULL,
-  "OWNER_ID" VARCHAR(4000) NOT NULL,
-  "IS_OWNER_USER" BOOLEAN NOT NULL,
-  "INSTALL_ID" VARCHAR(4000) NOT NULL,
-  "USER_EXTERNAL_ID" VARCHAR(255),
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_ALM_APP_INSTALLS" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "ALM_APP_INSTALLS_OWNER" ON "ALM_APP_INSTALLS" ("ALM_ID", "OWNER_ID");
-CREATE UNIQUE INDEX "ALM_APP_INSTALLS_INSTALL" ON "ALM_APP_INSTALLS" ("ALM_ID", "INSTALL_ID");
-CREATE INDEX "ALM_APP_INSTALLS_EXTERNAL_ID" ON "ALM_APP_INSTALLS" ("USER_EXTERNAL_ID");
-
-CREATE TABLE "PROJECT_ALM_BINDINGS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "ALM_ID" VARCHAR(40) NOT NULL,
-  "REPO_ID" VARCHAR(256) NOT NULL,
-  "PROJECT_UUID" VARCHAR(40) NOT NULL,
-  "GITHUB_SLUG" VARCHAR(256) NULL,
-  "URL" VARCHAR(2000) NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-  CONSTRAINT "PK_PROJECT_ALM_BINDINGS" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "PROJECT_ALM_BINDINGS_ALM_REPO" ON "PROJECT_ALM_BINDINGS" ("ALM_ID", "REPO_ID");
-CREATE UNIQUE INDEX "PROJECT_ALM_BINDINGS_PROJECT" ON "PROJECT_ALM_BINDINGS" ("PROJECT_UUID");
-
-CREATE TABLE "PROJECT_MAPPINGS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "KEY_TYPE" VARCHAR(200) NOT NULL,
-  "KEE" VARCHAR(4000) NOT NULL,
-  "PROJECT_UUID" VARCHAR(40) NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  CONSTRAINT "PK_PROJECT_MAPPINGS" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "KEY_TYPE_KEE" ON "PROJECT_MAPPINGS" ("KEY_TYPE", "KEE");
-CREATE INDEX "PROJECT_UUID" ON "PROJECT_MAPPINGS" ("PROJECT_UUID");
-
-CREATE TABLE "ORGANIZATION_ALM_BINDINGS" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
-  "ALM_APP_INSTALL_UUID" VARCHAR(40) NOT NULL,
-  "ALM_ID" VARCHAR(40) NOT NULL,
-  "URL" VARCHAR(2000) NOT NULL,
-  "USER_UUID" VARCHAR(255) NOT NULL,
-  "MEMBERS_SYNC_ENABLED" BOOLEAN,
-  "CREATED_AT" BIGINT NOT NULL,
-  CONSTRAINT "PK_ORGANIZATION_ALM_BINDINGS" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "ORG_ALM_BINDINGS_ORG" ON "ORGANIZATION_ALM_BINDINGS" ("ORGANIZATION_UUID");
-CREATE UNIQUE INDEX "ORG_ALM_BINDINGS_INSTALL" ON "ORGANIZATION_ALM_BINDINGS" ("ALM_APP_INSTALL_UUID");
-
-CREATE TABLE "USER_PROPERTIES" (
-  "UUID" VARCHAR(40) NOT NULL,
-  "USER_UUID" VARCHAR(255) NOT NULL,
-  "KEE" VARCHAR(100) NOT NULL,
-  "TEXT_VALUE" VARCHAR(4000) NOT NULL,
-  "CREATED_AT" BIGINT NOT NULL,
-  "UPDATED_AT" BIGINT NOT NULL,
-
-  CONSTRAINT "PK_USER_PROPERTIES" PRIMARY KEY ("UUID")
-);
-CREATE UNIQUE INDEX "USER_PROPERTIES_USER_UUID_KEE" ON "USER_PROPERTIES" ("USER_UUID", "KEE");
diff --git a/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema_migrations-h2.ddl b/server/sonar-db-core/src/main/resources/org/sonar/db/version/schema_migrations-h2.ddl
deleted file mode 100644 (file)
index aad2a07..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-CREATE TABLE "SCHEMA_MIGRATIONS" (
-  "VERSION" VARCHAR(256) NOT NULL
-);
-CREATE INDEX "UNIQUE_SCHEMA_MIGRATIONS" ON "SCHEMA_MIGRATIONS" ("VERSION");
index 23ae8e7dd329f4b16e50a0ac6b321a2f0d3cdd89..2d3c7df948d1b0edf15898f6689cc8a6f9d70749 100644 (file)
@@ -76,8 +76,8 @@ import static java.sql.ResultSetMetaData.columnNullable;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.junit.Assert.fail;
 
-public class AbstractDbTester<T extends CoreTestDb> extends ExternalResource {
-  protected static final Joiner COMMA_JOINER = Joiner.on(", ");
+public class AbstractDbTester<T extends TestDb> extends ExternalResource {
+  private static final Joiner COMMA_JOINER = Joiner.on(", ");
   protected final T db;
 
   public AbstractDbTester(T db) {
index 68826bdb35c37eba444bb95e494ade65be0d7157..6df2eccaba2eb8ff902dbbb3265a5f077be4fd34 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.db;
 
-import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
 
 /**
@@ -29,7 +28,7 @@ import org.apache.commons.lang.StringUtils;
 public class CoreDbTester extends AbstractDbTester<CoreTestDb> {
   private final DefaultOrganizationTesting defaultOrganizationTesting;
 
-  private CoreDbTester(@Nullable String schemaPath) {
+  private CoreDbTester(String schemaPath) {
     super(CoreTestDb.create(schemaPath));
     this.defaultOrganizationTesting = new DefaultOrganizationTesting(this);
   }
diff --git a/server/sonar-db-core/src/test/java/org/sonar/db/CoreDdlUtilsTest.java b/server/sonar-db-core/src/test/java/org/sonar/db/CoreDdlUtilsTest.java
new file mode 100644 (file)
index 0000000..20acb79
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.db;
+
+import org.assertj.core.api.Assertions;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class CoreDdlUtilsTest {
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
+  @Test
+  public void shouldSupportOnlyH2() {
+    Assertions.assertThat(CoreDdlUtils.supportsDialect("h2")).isTrue();
+    assertThat(CoreDdlUtils.supportsDialect("postgresql")).isFalse();
+    assertThat(CoreDdlUtils.supportsDialect("oracle")).isFalse();
+    assertThat(CoreDdlUtils.supportsDialect("mssql")).isFalse();
+  }
+}
diff --git a/server/sonar-db-core/src/test/java/org/sonar/db/CoreH2Database.java b/server/sonar-db-core/src/test/java/org/sonar/db/CoreH2Database.java
new file mode 100644 (file)
index 0000000..08c7f2b
--- /dev/null
@@ -0,0 +1,104 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.db;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import javax.sql.DataSource;
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.apache.commons.dbutils.DbUtils;
+import org.sonar.db.dialect.Dialect;
+import org.sonar.db.dialect.H2;
+
+import static java.lang.String.format;
+
+/**
+ * H2 in-memory database, used for unit tests only.
+ *
+ * @since 3.2
+ */
+public class CoreH2Database implements Database {
+  private final String name;
+  private BasicDataSource datasource;
+
+  /**
+   * IMPORTANT: change DB name in order to not conflict with {@link DefaultDatabaseTest}
+   */
+  public CoreH2Database(String name) {
+    this.name = name;
+  }
+
+  @Override
+  public void start() {
+    startDatabase();
+  }
+
+  private void startDatabase() {
+    try {
+      datasource = new BasicDataSource();
+      datasource.setDriverClassName("org.h2.Driver");
+      datasource.setUsername("sonar");
+      datasource.setPassword("sonar");
+      datasource.setUrl("jdbc:h2:mem:" + name);
+    } catch (Exception e) {
+      throw new IllegalStateException("Fail to start H2", e);
+    }
+  }
+
+  public void executeScript(String classloaderPath) {
+    Connection connection = null;
+    try {
+      connection = datasource.getConnection();
+      CoreDdlUtils.executeScript(connection, classloaderPath);
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("Fail to execute script: " + classloaderPath, e);
+    } finally {
+      DbUtils.closeQuietly(connection);
+    }
+  }
+
+  @Override
+  public void stop() {
+    try {
+      datasource.close();
+    } catch (SQLException e) {
+      // Ignore error
+    }
+  }
+
+  public DataSource getDataSource() {
+    return datasource;
+  }
+
+  public Dialect getDialect() {
+    return new H2();
+  }
+
+  @Override
+  public void enableSqlLogging(boolean enable) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String toString() {
+    return format("H2 Database[%s]", name);
+  }
+}
index e673d167ac4457096316584be7ba5d7f66a1b429..6699612c5bbb944e643604f35edef25093ee96a1 100644 (file)
@@ -23,19 +23,16 @@ import java.io.File;
 import java.io.InputStream;
 import java.net.HttpURLConnection;
 import java.net.URI;
-import java.sql.SQLException;
 import java.util.Map;
 import java.util.Properties;
 import java.util.function.BiConsumer;
-import javax.annotation.Nullable;
+import java.util.function.Function;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
-import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.text.StrSubstitutor;
 import org.dbunit.DataSourceDatabaseTester;
 import org.dbunit.IDatabaseTester;
-import org.dbunit.dataset.datatype.IDataTypeFactory;
 import org.junit.AssumptionViolatedException;
 import org.sonar.api.config.Settings;
 import org.sonar.api.config.internal.MapSettings;
@@ -44,123 +41,125 @@ import org.sonar.api.utils.log.Loggers;
 import org.sonar.db.dialect.H2;
 import org.sonar.process.logging.LogbackHelper;
 
-import static org.apache.commons.lang.StringUtils.isNotEmpty;
+import static java.util.Objects.requireNonNull;
+import static org.apache.commons.lang.StringUtils.isEmpty;
 import static org.sonar.process.ProcessProperties.Property.JDBC_USERNAME;
 
 /**
  * This class should be call using @ClassRule in order to create the schema once (if @Rule is used
  * the schema will be recreated before each test).
  */
-class CoreTestDb {
-
-  private static CoreTestDb DEFAULT;
-
-  private static final Logger LOG = Loggers.get(CoreTestDb.class);
+class CoreTestDb implements TestDb {
 
   private Database db;
   private DatabaseCommands commands;
   private IDatabaseTester tester;
-  private boolean isDefault;
 
   protected CoreTestDb() {
     // use static factory method
   }
+  protected CoreTestDb(Database db, DatabaseCommands commands, IDatabaseTester tester) {
+    this.db = db;
+    this.commands = commands;
+    this.tester = tester;
+  }
 
-  protected CoreTestDb(CoreTestDb base) {
-    this.db = base.db;
-    this.isDefault = base.isDefault;
-    this.commands = base.commands;
-    this.tester = base.tester;
+  static CoreTestDb create(String schemaPath) {
+    return new CoreTestDb().init(schemaPath);
   }
 
-  CoreTestDb init(@Nullable String schemaPath, BiConsumer<Database, Boolean> extendedStart) {
-    if (db == null) {
-      Settings settings = new MapSettings().addProperties(System.getProperties());
-      if (isNotEmpty(settings.getString("orchestrator.configUrl"))) {
-        loadOrchestratorSettings(settings);
-      }
-      String login = settings.getString(JDBC_USERNAME.getKey());
-      for (String key : settings.getKeysStartingWith("sonar.jdbc")) {
-        LOG.info(key + ": " + settings.getString(key));
-      }
+  private CoreTestDb init(String schemaPath) {
+    requireNonNull(schemaPath, "schemaPath can't be null");
+
+    Function<Settings, Database> databaseCreator = settings -> {
       String dialect = settings.getString("sonar.jdbc.dialect");
       if (dialect != null && !"h2".equals(dialect)) {
-        db = new DefaultDatabase(new LogbackHelper(), settings);
-      } else {
-        db = new H2Database("h2Tests" + DigestUtils.md5Hex(StringUtils.defaultString(schemaPath)), schemaPath == null);
+        return new DefaultDatabase(new LogbackHelper(), settings);
+      }
+      return new CoreH2Database("h2Tests-" + DigestUtils.md5Hex(schemaPath));
+    };
+    Function<Database, Boolean> databaseInitializer = database -> {
+      // will fail if not H2
+      if (!database.getDialect().getId().equals("h2")) {
+        return false;
       }
+
+      ((CoreH2Database) database).executeScript(schemaPath);
+      return true;
+    };
+    BiConsumer<Database, Boolean> noPostStartAction = (db, created) -> {
+    };
+
+    init(databaseCreator, databaseInitializer, noPostStartAction);
+    return this;
+  }
+
+  protected void init(Function<Settings, Database> databaseSupplier,
+    Function<Database, Boolean> databaseInitializer,
+    BiConsumer<Database, Boolean> extendedStart) {
+    if (db == null) {
+      Settings settings = new MapSettings().addProperties(System.getProperties());
+      loadOrchestratorSettings(settings);
+      logJdbcSettings(settings);
+      db = databaseSupplier.apply(settings);
       db.start();
-      if (schemaPath != null) {
-        // will fail if not H2
-        if (db.getDialect().getId().equals("h2")) {
-          ((H2Database) db).executeScript(schemaPath);
-        } else {
-          db.stop();
-        }
+
+      if (!databaseInitializer.apply(db)) {
+        db.stop();
+        throw new IllegalStateException("Can't apply init script");
       }
-      isDefault = (schemaPath == null);
-      LOG.debug("Test Database: " + db);
+      Loggers.get(getClass()).debug("Test Database: " + db);
 
       commands = DatabaseCommands.forDialect(db.getDialect());
+      String login = settings.getString(JDBC_USERNAME.getKey());
       tester = new DataSourceDatabaseTester(db.getDataSource(), commands.useLoginAsSchema() ? login : null);
 
       extendedStart.accept(db, true);
     } else {
       extendedStart.accept(db, false);
     }
-    return this;
   }
 
-  static CoreTestDb create(@Nullable String schemaPath) {
-    if (schemaPath == null) {
-      if (DEFAULT == null) {
-        DEFAULT = new CoreTestDb().init(null, (db, created) -> {
-        });
-      }
-      return DEFAULT;
-    }
-    return new CoreTestDb().init(schemaPath, (db, created) -> {
-    });
+  @Override
+  public Database getDatabase() {
+    return db;
   }
 
-  public void start() {
-    if (!isDefault && !H2.ID.equals(db.getDialect().getId())) {
-      throw new AssumptionViolatedException("Test disabled because it supports only H2");
-    }
+  @Override
+  public DatabaseCommands getCommands() {
+    return commands;
   }
 
-  void stop() {
-    if (!isDefault) {
-      db.stop();
-    }
+  @Override
+  public IDatabaseTester getDbUnitTester() {
+    return tester;
   }
 
-  void truncateTables() {
-    try {
-      commands.truncateDatabase(db.getDataSource());
-    } catch (SQLException e) {
-      throw new IllegalStateException("Fail to truncate db tables", e);
+  @Override
+  public void start() {
+    if (!H2.ID.equals(db.getDialect().getId())) {
+      throw new AssumptionViolatedException("Test disabled because it supports only H2");
     }
   }
 
-  Database getDatabase() {
-    return db;
-  }
-
-  DatabaseCommands getCommands() {
-    return commands;
+  @Override
+  public void stop() {
+    db.stop();
   }
 
-  IDatabaseTester getDbUnitTester() {
-    return tester;
-  }
-
-  IDataTypeFactory getDbUnitFactory() {
-    return commands.getDbUnitFactory();
+  private void logJdbcSettings(Settings settings) {
+    Logger logger = Loggers.get(getClass());
+    for (String key : settings.getKeysStartingWith("sonar.jdbc")) {
+      logger.info(key + ": " + settings.getString(key));
+    }
   }
 
-  private void loadOrchestratorSettings(Settings settings) {
+  private static void loadOrchestratorSettings(Settings settings) {
     String url = settings.getString("orchestrator.configUrl");
+    if (isEmpty(url)) {
+      return;
+    }
+
     InputStream input = null;
     try {
       URI uri = new URI(url);
diff --git a/server/sonar-db-core/src/test/java/org/sonar/db/DdlUtilsTest.java b/server/sonar-db-core/src/test/java/org/sonar/db/DdlUtilsTest.java
deleted file mode 100644 (file)
index 4972d77..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.db;
-
-import java.sql.Connection;
-import java.sql.DriverManager;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import org.assertj.core.api.Assertions;
-import org.h2.Driver;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DdlUtilsTest {
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Test
-  public void shouldSupportOnlyH2() {
-    Assertions.assertThat(DdlUtils.supportsDialect("h2")).isTrue();
-    assertThat(DdlUtils.supportsDialect("postgresql")).isFalse();
-    assertThat(DdlUtils.supportsDialect("oracle")).isFalse();
-    assertThat(DdlUtils.supportsDialect("mssql")).isFalse();
-  }
-
-  @Test
-  public void shouldCreateSchema_with_schema_migrations() throws SQLException {
-    DriverManager.registerDriver(new Driver());
-    try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:sonar_test")) {
-      DdlUtils.createSchema(connection, "h2", true);
-
-      int tableCount = countTables(connection);
-      assertThat(tableCount).isGreaterThan(30);
-
-      verifySchemaMigrationsNotPopulated(connection);
-    }
-  }
-
-  @Test
-  public void shouldCreateSchema_without_schema_migrations() throws SQLException {
-    DriverManager.registerDriver(new Driver());
-    try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:sonar_test2")) {
-      try (Statement statement = connection.createStatement()) {
-        statement.execute("create table schema_migrations (version varchar(255) not null)");
-      }
-      DdlUtils.createSchema(connection, "h2", false);
-
-      verifySchemaMigrationsNotPopulated(connection);
-    }
-  }
-
-  static int countTables(Connection connection) throws SQLException {
-    int count = 0;
-    ResultSet resultSet = connection.getMetaData().getTables("", null, null, new String[] {"TABLE"});
-    while (resultSet.next()) {
-      count++;
-    }
-    resultSet.close();
-    return count;
-  }
-
-  private void verifySchemaMigrationsNotPopulated(Connection connection) throws SQLException {
-    try (Statement statement = connection.createStatement();
-      ResultSet resultSet = statement.executeQuery("select count(*) from schema_migrations")) {
-      assertThat(resultSet.next()).isTrue();
-      assertThat(resultSet.getLong(1)).isEqualTo(0);
-      assertThat(resultSet.next()).isFalse();
-    }
-  }
-}
diff --git a/server/sonar-db-core/src/test/java/org/sonar/db/H2Database.java b/server/sonar-db-core/src/test/java/org/sonar/db/H2Database.java
deleted file mode 100644 (file)
index d6ab7c1..0000000
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.db;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import javax.sql.DataSource;
-import org.apache.commons.dbcp2.BasicDataSource;
-import org.apache.commons.dbutils.DbUtils;
-import org.sonar.db.dialect.Dialect;
-import org.sonar.db.dialect.H2;
-
-import static java.lang.String.format;
-
-/**
- * H2 in-memory database, used for unit tests only.
- *
- * @since 3.2
- */
-public class H2Database implements Database {
-  private final String name;
-  private final boolean createSchema;
-  private BasicDataSource datasource;
-
-  /**
-   * IMPORTANT: change DB name in order to not conflict with {@link DefaultDatabaseTest}
-   */
-  public H2Database(String name, boolean createSchema) {
-    this.name = name;
-    this.createSchema = createSchema;
-  }
-
-  @Override
-  public void start() {
-    startDatabase();
-    if (createSchema) {
-      createSchema();
-    }
-  }
-
-  private void startDatabase() {
-    try {
-      datasource = new BasicDataSource();
-      datasource.setDriverClassName("org.h2.Driver");
-      datasource.setUsername("sonar");
-      datasource.setPassword("sonar");
-      datasource.setUrl("jdbc:h2:mem:" + name);
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to start H2", e);
-    }
-  }
-
-  private void createSchema() {
-    Connection connection = null;
-    try {
-      connection = datasource.getConnection();
-      DdlUtils.createSchema(connection, "h2", true);
-
-    } catch (SQLException e) {
-      throw new IllegalStateException("Fail to create schema", e);
-    } finally {
-      DbUtils.closeQuietly(connection);
-    }
-  }
-
-  public void executeScript(String classloaderPath) {
-    Connection connection = null;
-    try {
-      connection = datasource.getConnection();
-      DdlUtils.executeScript(connection, classloaderPath);
-
-    } catch (SQLException e) {
-      throw new IllegalStateException("Fail to execute script: " + classloaderPath, e);
-    } finally {
-      DbUtils.closeQuietly(connection);
-    }
-  }
-
-  @Override
-  public void stop() {
-    try {
-      datasource.close();
-    } catch (SQLException e) {
-      // Ignore error
-    }
-  }
-
-  public DataSource getDataSource() {
-    return datasource;
-  }
-
-  public Dialect getDialect() {
-    return new H2();
-  }
-
-  @Override
-  public void enableSqlLogging(boolean enable) {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String toString() {
-    return format("H2 Database[%s]", name);
-  }
-}
diff --git a/server/sonar-db-core/src/test/java/org/sonar/db/H2DatabaseTest.java b/server/sonar-db-core/src/test/java/org/sonar/db/H2DatabaseTest.java
deleted file mode 100644 (file)
index e4dec16..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.db;
-
-import java.sql.Connection;
-import java.sql.SQLException;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class H2DatabaseTest {
-  H2Database db = new H2Database("sonar2", true);
-
-  @Before
-  public void startDb() {
-    db.start();
-  }
-
-  @After
-  public void stopDb() {
-    db.stop();
-  }
-
-  @Test
-  public void shouldExecuteDdlAtStartup() throws SQLException {
-    Connection connection = db.getDataSource().getConnection();
-    int tableCount = DdlUtilsTest.countTables(connection);
-    connection.close();
-
-    assertThat(tableCount).isGreaterThan(30);
-  }
-}
diff --git a/server/sonar-db-core/src/test/java/org/sonar/db/TestDb.java b/server/sonar-db-core/src/test/java/org/sonar/db/TestDb.java
new file mode 100644 (file)
index 0000000..22645af
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.db;
+
+import java.sql.SQLException;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.datatype.IDataTypeFactory;
+
+public interface TestDb {
+  void start();
+
+  void stop();
+
+  Database getDatabase();
+
+  DatabaseCommands getCommands();
+
+  IDatabaseTester getDbUnitTester();
+
+  default void truncateTables() {
+    try {
+      getCommands().truncateDatabase(getDatabase().getDataSource());
+    } catch (SQLException e) {
+      throw new IllegalStateException("Fail to truncate db tables", e);
+    }
+  }
+
+  default IDataTypeFactory getDbUnitFactory() {
+    return getCommands().getDbUnitFactory();
+  }
+}
index 0443ad91e387f461d67fe6c1d44308714cadd535..18f3fefcfe85b09b07f85c26687ce23d0d22e042 100644 (file)
@@ -21,6 +21,7 @@ dependencies {
 
   compileOnly 'com.google.code.findbugs:jsr305'
 
+  testCompile 'com.h2database:h2'
   testCompile 'com.tngtech.java:junit-dataprovider'
   testCompile 'junit:junit'
   testCompile 'org.assertj:assertj-core'
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/DdlUtils.java b/server/sonar-db-dao/src/main/java/org/sonar/db/DdlUtils.java
new file mode 100644 (file)
index 0000000..b3bf45b
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.db;
+
+import java.sql.Connection;
+
+import static org.sonar.db.CoreDdlUtils.executeScript;
+
+public class DdlUtils {
+
+  private DdlUtils() {
+    // prevents instantiation
+  }
+
+  /**
+   * The connection is commited in this method but not closed.
+   */
+  public static void createSchema(Connection connection, String dialect, boolean createSchemaMigrations) {
+    if (createSchemaMigrations) {
+      executeScript(connection, "org/sonar/db/schema_migrations-" + dialect + ".ddl");
+    }
+    executeScript(connection, "org/sonar/db/schema-" + dialect + ".ddl");
+    executeScript(connection, "org/sonar/db/rows-" + dialect + ".sql");
+  }
+}
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/rows-h2.sql b/server/sonar-db-dao/src/main/resources/org/sonar/db/rows-h2.sql
new file mode 100644 (file)
index 0000000..fb12115
--- /dev/null
@@ -0,0 +1,28 @@
+INSERT INTO USERS(ID, UUID, LOGIN, NAME, EMAIL, EXTERNAL_ID, EXTERNAL_LOGIN, EXTERNAL_IDENTITY_PROVIDER, USER_LOCAL, CRYPTED_PASSWORD, SALT, HASH_METHOD, IS_ROOT, ONBOARDED, CREATED_AT, UPDATED_AT) VALUES (1, 'UuidnciQUUs7Zd3KPvFD', 'admin', 'Administrator', null, 'admin', 'admin', 'sonarqube', true, '$2a$12$uCkkXmhW5ThVK8mpBvnXOOJRLd64LJeHTeCkSuB3lfaR2N0AYBaSi', null, 'BCRYPT', false, true, '1418215735482', '1418215735482');
+ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
+
+INSERT INTO GROUPS(ID, ORGANIZATION_UUID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (1, 'AVdqnciQUUs7Zd3KPvFD', 'sonar-administrators', 'System administrators', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
+INSERT INTO GROUPS(ID, ORGANIZATION_UUID, NAME, DESCRIPTION, CREATED_AT, UPDATED_AT) VALUES (2, 'AVdqnciQUUs7Zd3KPvFD', 'sonar-users', 'Any new users created will automatically join this group', '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
+ALTER TABLE GROUPS ALTER COLUMN ID RESTART WITH 3;
+
+INSERT INTO QUALITY_GATES(ID, UUID, NAME, IS_BUILT_IN, CREATED_AT, UPDATED_AT) VALUES (1, 'AWASGWAKYOI_InFKS3UF', 'Sonar way', true, '2011-09-26 22:27:51.0', '2011-09-26 22:27:51.0');
+
+INSERT INTO ORGANIZATIONS (UUID, KEE, NAME, GUARDED, NEW_PROJECT_PRIVATE, DEFAULT_GROUP_ID, DEFAULT_QUALITY_GATE_UUID, SUBSCRIPTION, CREATED_AT, UPDATED_AT) VALUES ('AVdqnciQUUs7Zd3KPvFD', 'default-organization', 'Default Organization', true, false, 2, 'AWASGWAKYOI_InFKS3UF', 'SONARQUBE', '1474962596482', '1474962596482');
+INSERT INTO ORG_QUALITY_GATES (UUID, ORGANIZATION_UUID, QUALITY_GATE_UUID) VALUES ('AWAwlGzz-5zzlJtFU9G5', 'AVdqnciQUUs7Zd3KPvFD', 'AWASGWAKYOI_InFKS3UF');
+
+INSERT INTO INTERNAL_PROPERTIES (KEE, IS_EMPTY, TEXT_VALUE, CREATED_AT) VALUES ('organization.default', false, 'AVdqnciQUUs7Zd3KPvFD', '1474962596482');
+
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (1, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'admin');
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (2, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'profileadmin');
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (3, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'gateadmin');
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (4, 'AVdqnciQUUs7Zd3KPvFD', null, null, 'scan');
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (5, 'AVdqnciQUUs7Zd3KPvFD', null, null, 'provisioning');
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (6, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'provisioning');
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (7, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'applicationcreator');
+INSERT INTO GROUP_ROLES(ID, ORGANIZATION_UUID, GROUP_ID, RESOURCE_ID, ROLE) VALUES (8, 'AVdqnciQUUs7Zd3KPvFD', 1, null, 'portfoliocreator');
+ALTER TABLE GROUP_ROLES ALTER COLUMN ID RESTART WITH 9;
+
+INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 1);
+INSERT INTO GROUPS_USERS(USER_ID, GROUP_ID) VALUES (1, 2);
+
+INSERT INTO ORGANIZATION_MEMBERS(ORGANIZATION_UUID, USER_ID) VALUES ('AVdqnciQUUs7Zd3KPvFD', 1);
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/schema-h2.ddl b/server/sonar-db-dao/src/main/resources/org/sonar/db/schema-h2.ddl
new file mode 100644 (file)
index 0000000..157cdd5
--- /dev/null
@@ -0,0 +1,976 @@
+CREATE TABLE "ORGANIZATIONS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "KEE" VARCHAR(300) NOT NULL,
+  "NAME" VARCHAR(300) NOT NULL,
+  "DESCRIPTION" VARCHAR(256),
+  "URL" VARCHAR(256),
+  "AVATAR_URL" VARCHAR(256),
+  "GUARDED" BOOLEAN,
+  "DEFAULT_PERM_TEMPLATE_PROJECT" VARCHAR(40),
+  "DEFAULT_PERM_TEMPLATE_APP" VARCHAR(40),
+  "DEFAULT_PERM_TEMPLATE_PORT" VARCHAR(40),
+  "DEFAULT_GROUP_ID" INTEGER,
+  "DEFAULT_QUALITY_GATE_UUID" VARCHAR(40) NOT NULL,
+  "NEW_PROJECT_PRIVATE" BOOLEAN NOT NULL,
+  "SUBSCRIPTION" VARCHAR(40) NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_ORGANIZATIONS" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "ORGANIZATION_KEY" ON "ORGANIZATIONS" ("KEE");
+
+CREATE TABLE "ORGANIZATION_MEMBERS" (
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "USER_ID" INTEGER NOT NULL,
+
+  CONSTRAINT "PK_ORGANIZATION_MEMBERS" PRIMARY KEY ("ORGANIZATION_UUID", "USER_ID")
+);
+CREATE INDEX "IX_ORG_MEMBERS_ON_USER_ID" ON "ORGANIZATION_MEMBERS" ("USER_ID");
+
+CREATE TABLE "GROUPS_USERS" (
+  "USER_ID" INTEGER,
+  "GROUP_ID" INTEGER
+);
+CREATE INDEX "INDEX_GROUPS_USERS_ON_GROUP_ID" ON "GROUPS_USERS" ("GROUP_ID");
+CREATE INDEX "INDEX_GROUPS_USERS_ON_USER_ID" ON "GROUPS_USERS" ("USER_ID");
+CREATE UNIQUE INDEX "GROUPS_USERS_UNIQUE" ON "GROUPS_USERS" ("GROUP_ID", "USER_ID");
+
+
+CREATE TABLE "RULES_PARAMETERS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "RULE_ID" INTEGER NOT NULL,
+  "NAME" VARCHAR(128) NOT NULL,
+  "PARAM_TYPE" VARCHAR(512) NOT NULL,
+  "DEFAULT_VALUE" VARCHAR(4000),
+  "DESCRIPTION" VARCHAR(4000)
+);
+CREATE INDEX "RULES_PARAMETERS_RULE_ID" ON "RULES_PARAMETERS" ("RULE_ID");
+CREATE UNIQUE INDEX "RULES_PARAMETERS_UNIQUE" ON "RULES_PARAMETERS" ("RULE_ID", "NAME");
+
+
+CREATE TABLE "RULES_PROFILES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "NAME" VARCHAR(100) NOT NULL,
+  "LANGUAGE" VARCHAR(20),
+  "KEE" VARCHAR(255) NOT NULL,
+  "RULES_UPDATED_AT" VARCHAR(100),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+  "IS_BUILT_IN" BOOLEAN NOT NULL
+);
+CREATE UNIQUE INDEX "UNIQ_QPROF_KEY" ON "RULES_PROFILES" ("KEE");
+
+
+CREATE TABLE "ORG_QPROFILES" (
+  "UUID" VARCHAR(255) NOT NULL,
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "RULES_PROFILE_UUID" VARCHAR(255) NOT NULL,
+  "PARENT_UUID" VARCHAR(255),
+  "LAST_USED" BIGINT,
+  "USER_UPDATED_AT" BIGINT,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_ORG_QPROFILES" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "ORG_QPROFILES_ORG_UUID" ON "ORG_QPROFILES" ("ORGANIZATION_UUID");
+CREATE INDEX "ORG_QPROFILES_RP_UUID" ON "ORG_QPROFILES" ("RULES_PROFILE_UUID");
+CREATE INDEX "ORG_QPROFILES_PARENT_UUID" ON "ORG_QPROFILES" ("PARENT_UUID");
+
+
+CREATE TABLE "DEFAULT_QPROFILES" (
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "LANGUAGE" VARCHAR(20) NOT NULL,
+  "QPROFILE_UUID" VARCHAR(255) NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_DEFAULT_QPROFILES" PRIMARY KEY ("ORGANIZATION_UUID", "LANGUAGE")
+);
+CREATE UNIQUE INDEX "UNIQ_DEFAULT_QPROFILES_UUID" ON "DEFAULT_QPROFILES" ("QPROFILE_UUID");
+
+
+CREATE TABLE "PROJECT_QPROFILES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "PROJECT_UUID" VARCHAR(50) NOT NULL,
+  "PROFILE_KEY" VARCHAR(50) NOT NULL
+);
+CREATE UNIQUE INDEX "UNIQ_PROJECT_QPROFILES" ON "PROJECT_QPROFILES" ("PROJECT_UUID", "PROFILE_KEY");
+
+
+CREATE TABLE "QPROFILE_EDIT_USERS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "USER_ID" INTEGER NOT NULL,
+  "QPROFILE_UUID" VARCHAR(255) NOT NULL,
+  "CREATED_AT" BIGINT,
+
+  CONSTRAINT "PK_QPROFILE_EDIT_USERS" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "QPROFILE_EDIT_USERS_QPROFILE" ON "QPROFILE_EDIT_USERS" ("QPROFILE_UUID");
+CREATE UNIQUE INDEX "QPROFILE_EDIT_USERS_UNIQUE" ON "QPROFILE_EDIT_USERS" ("USER_ID", "QPROFILE_UUID");
+
+
+CREATE TABLE "QPROFILE_EDIT_GROUPS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "GROUP_ID" INTEGER NOT NULL,
+  "QPROFILE_UUID" VARCHAR(255) NOT NULL,
+  "CREATED_AT" BIGINT,
+
+  CONSTRAINT "PK_QPROFILE_EDIT_GROUPS" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "QPROFILE_EDIT_GROUPS_QPROFILE" ON "QPROFILE_EDIT_GROUPS" ("QPROFILE_UUID");
+CREATE UNIQUE INDEX "QPROFILE_EDIT_GROUPS_UNIQUE" ON "QPROFILE_EDIT_GROUPS" ("GROUP_ID", "QPROFILE_UUID");
+
+
+CREATE TABLE "GROUPS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "NAME" VARCHAR(500),
+  "DESCRIPTION" VARCHAR(200),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP
+);
+
+
+CREATE TABLE "SNAPSHOTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(50) NOT NULL,
+  "CREATED_AT" BIGINT,
+  "BUILD_DATE" BIGINT,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "STATUS" VARCHAR(4) NOT NULL DEFAULT 'U',
+  "PURGE_STATUS" INTEGER,
+  "ISLAST" BOOLEAN NOT NULL DEFAULT FALSE,
+  "VERSION" VARCHAR(500),
+  "BUILD_STRING" VARCHAR(100),
+  "PERIOD1_MODE" VARCHAR(100),
+  "PERIOD1_PARAM" VARCHAR(100),
+  "PERIOD1_DATE" BIGINT,
+  "PERIOD2_MODE" VARCHAR(100),
+  "PERIOD2_PARAM" VARCHAR(100),
+  "PERIOD2_DATE" BIGINT,
+  "PERIOD3_MODE" VARCHAR(100),
+  "PERIOD3_PARAM" VARCHAR(100),
+  "PERIOD3_DATE" BIGINT,
+  "PERIOD4_MODE" VARCHAR(100),
+  "PERIOD4_PARAM" VARCHAR(100),
+  "PERIOD4_DATE" BIGINT,
+  "PERIOD5_MODE" VARCHAR(100),
+  "PERIOD5_PARAM" VARCHAR(100),
+  "PERIOD5_DATE" BIGINT,
+  "REVISION" VARCHAR(100)
+);
+CREATE INDEX "SNAPSHOT_COMPONENT" ON "SNAPSHOTS" ("COMPONENT_UUID");
+CREATE UNIQUE INDEX "ANALYSES_UUID" ON "SNAPSHOTS" ("UUID");
+
+CREATE TABLE "GROUP_ROLES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "GROUP_ID" INTEGER,
+  "RESOURCE_ID" INTEGER,
+  "ROLE" VARCHAR(64) NOT NULL
+);
+CREATE INDEX "GROUP_ROLES_RESOURCE" ON "GROUP_ROLES" ("RESOURCE_ID");
+CREATE UNIQUE INDEX "UNIQ_GROUP_ROLES" ON "GROUP_ROLES" ("ORGANIZATION_UUID", "GROUP_ID", "RESOURCE_ID", "ROLE");
+
+
+CREATE TABLE "RULE_REPOSITORIES" (
+  "KEE" VARCHAR(200) NOT NULL,
+  "LANGUAGE" VARCHAR(20) NOT NULL,
+  "NAME" VARCHAR(4000) NOT NULL,
+  "CREATED_AT" BIGINT,
+
+  CONSTRAINT "PK_RULE_REPOSITORIES" PRIMARY KEY ("KEE")
+);
+
+CREATE TABLE "DEPRECATED_RULE_KEYS" (
+  "UUID"  VARCHAR(40) NOT NULL,
+  "RULE_ID" INTEGER NOT NULL,
+  "OLD_REPOSITORY_KEY" VARCHAR(200) NOT NULL,
+  "OLD_RULE_KEY" VARCHAR(255) NOT NULL,
+  "CREATED_AT" BIGINT,
+
+  CONSTRAINT "PK_DEPRECATED_RULE_KEYS" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "UNIQ_DEPRECATED_RULE_KEYS" ON "DEPRECATED_RULE_KEYS" ("OLD_REPOSITORY_KEY", "OLD_RULE_KEY");
+CREATE INDEX "RULE_ID_DEPRECATED_RULE_KEYS" ON "DEPRECATED_RULE_KEYS" ("RULE_ID");
+
+CREATE TABLE "RULES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "PLUGIN_KEY" VARCHAR(200),
+  "PLUGIN_RULE_KEY" VARCHAR(200) NOT NULL,
+  "PLUGIN_NAME" VARCHAR(255) NOT NULL,
+  "DESCRIPTION" VARCHAR(16777215),
+  "DESCRIPTION_FORMAT" VARCHAR(20),
+  "PRIORITY" INTEGER,
+  "IS_TEMPLATE" BOOLEAN DEFAULT FALSE,
+  "IS_EXTERNAL" BOOLEAN NOT NULL,
+  "IS_AD_HOC" BOOLEAN NOT NULL,
+  "TEMPLATE_ID" INTEGER,
+  "PLUGIN_CONFIG_KEY" VARCHAR(200),
+  "NAME" VARCHAR(200),
+  "STATUS" VARCHAR(40),
+  "LANGUAGE" VARCHAR(20),
+  "SCOPE" VARCHAR(20) NOT NULL,
+  "DEF_REMEDIATION_FUNCTION" VARCHAR(20),
+  "DEF_REMEDIATION_GAP_MULT" VARCHAR(20),
+  "DEF_REMEDIATION_BASE_EFFORT" VARCHAR(20),
+  "GAP_DESCRIPTION" VARCHAR(4000),
+  "SYSTEM_TAGS" VARCHAR(4000),
+  "SECURITY_STANDARDS" VARCHAR(4000),
+  "RULE_TYPE" TINYINT,
+  "CREATED_AT" BIGINT,
+  "UPDATED_AT" BIGINT
+);
+CREATE UNIQUE INDEX "RULES_REPO_KEY" ON "RULES" ("PLUGIN_NAME", "PLUGIN_RULE_KEY");
+
+CREATE TABLE "RULES_METADATA" (
+  "RULE_ID" INTEGER NOT NULL,
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "NOTE_DATA" CLOB,
+  "NOTE_USER_UUID" VARCHAR(255),
+  "NOTE_CREATED_AT" BIGINT,
+  "NOTE_UPDATED_AT" BIGINT,
+  "REMEDIATION_FUNCTION" VARCHAR(20),
+  "REMEDIATION_GAP_MULT" VARCHAR(20),
+  "REMEDIATION_BASE_EFFORT" VARCHAR(20),
+  "TAGS" VARCHAR(4000),
+  "AD_HOC_NAME" VARCHAR(200),
+  "AD_HOC_DESCRIPTION" VARCHAR(16777215),
+  "AD_HOC_SEVERITY" VARCHAR(10),
+  "AD_HOC_TYPE" TINYINT,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_RULES_METADATA" PRIMARY KEY ("RULE_ID", "ORGANIZATION_UUID")
+);
+
+CREATE TABLE "EVENTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(40) NOT NULL,
+  "NAME" VARCHAR(400),
+  "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "CATEGORY" VARCHAR(50),
+  "EVENT_DATE" BIGINT NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "DESCRIPTION" VARCHAR(4000),
+  "EVENT_DATA"  VARCHAR(4000)
+);
+CREATE INDEX "EVENTS_ANALYSIS" ON "EVENTS" ("ANALYSIS_UUID");
+CREATE INDEX "EVENTS_COMPONENT_UUID" ON "EVENTS" ("COMPONENT_UUID");
+CREATE UNIQUE INDEX "EVENTS_UUID" ON "EVENTS" ("UUID");
+
+CREATE TABLE "EVENT_COMPONENT_CHANGES" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "EVENT_UUID" VARCHAR(40) NOT NULL,
+  "EVENT_COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "EVENT_ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+  "CHANGE_CATEGORY" VARCHAR(20) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "COMPONENT_KEY" VARCHAR(400) NOT NULL,
+  "COMPONENT_NAME" VARCHAR(2000) NOT NULL,
+  "COMPONENT_BRANCH_KEY" VARCHAR(255),
+  "CREATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_EVENT_COMPONENT_CHANGES" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "EVENT_COMPONENT_CHANGES_UNIQUE" ON "EVENT_COMPONENT_CHANGES" ("EVENT_UUID", "CHANGE_CATEGORY", "COMPONENT_UUID");
+CREATE INDEX "EVENT_CPNT_CHANGES_CPNT" ON "EVENT_COMPONENT_CHANGES" ("EVENT_COMPONENT_UUID");
+CREATE INDEX "EVENT_CPNT_CHANGES_ANALYSIS" ON "EVENT_COMPONENT_CHANGES" ("EVENT_ANALYSIS_UUID");
+
+
+CREATE TABLE "QUALITY_GATES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(40) NOT NULL,
+  "NAME" VARCHAR(100) NOT NULL,
+  "IS_BUILT_IN" BOOLEAN NOT NULL,
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+);
+CREATE UNIQUE INDEX "UNIQ_QUALITY_GATES_UUID" ON "QUALITY_GATES" ("UUID");
+
+
+CREATE TABLE "QUALITY_GATE_CONDITIONS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "QGATE_ID" INTEGER,
+  "METRIC_ID" INTEGER,
+  "OPERATOR" VARCHAR(3),
+  "VALUE_ERROR" VARCHAR(64),
+  "VALUE_WARNING" VARCHAR(64),
+  "PERIOD" INTEGER,
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP,
+);
+
+CREATE TABLE "ORG_QUALITY_GATES" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "QUALITY_GATE_UUID" VARCHAR(40) NOT NULL,
+
+  CONSTRAINT "PK_ORG_QUALITY_GATES" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "UNIQ_ORG_QUALITY_GATES" ON "ORG_QUALITY_GATES" ("ORGANIZATION_UUID","QUALITY_GATE_UUID");
+
+CREATE TABLE "PROJECT_QGATES" (
+"PROJECT_UUID" VARCHAR(40) NOT NULL,
+"QUALITY_GATE_UUID" VARCHAR(40) NOT NULL,
+
+CONSTRAINT "PK_PROJECT_QGATES" PRIMARY KEY ("PROJECT_UUID")
+);
+CREATE UNIQUE INDEX "UNIQ_PROJECT_QGATES" ON "PROJECT_QGATES" ("PROJECT_UUID", "QUALITY_GATE_UUID");
+
+CREATE TABLE "PROPERTIES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "PROP_KEY" VARCHAR(512) NOT NULL,
+  "RESOURCE_ID" INTEGER,
+  "USER_ID" INTEGER,
+  "IS_EMPTY" BOOLEAN NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "CLOB_VALUE" CLOB,
+  "CREATED_AT" BIGINT
+);
+CREATE INDEX "PROPERTIES_KEY" ON "PROPERTIES" ("PROP_KEY");
+
+
+CREATE TABLE "PROJECT_LINKS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "PROJECT_UUID" VARCHAR(50) NOT NULL,
+  "LINK_TYPE" VARCHAR(20) NOT NULL,
+  "NAME" VARCHAR(128),
+  "HREF" VARCHAR(2048) NOT NULL,
+  "CREATED_AT" BIGINT,
+  "UPDATED_AT" BIGINT,
+
+   CONSTRAINT "PK_PROJECT_LINKS" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "PROJECT_LINKS_PROJECT" ON "PROJECT_LINKS" ("PROJECT_UUID");
+
+
+CREATE TABLE "DUPLICATIONS_INDEX" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "HASH" VARCHAR(50) NOT NULL,
+  "INDEX_IN_FILE" INTEGER NOT NULL,
+  "START_LINE" INTEGER NOT NULL,
+  "END_LINE" INTEGER NOT NULL
+);
+CREATE INDEX "DUPLICATIONS_INDEX_HASH" ON "DUPLICATIONS_INDEX" ("HASH");
+CREATE INDEX "DUPLICATION_ANALYSIS_COMPONENT" ON "DUPLICATIONS_INDEX" ("ANALYSIS_UUID", "COMPONENT_UUID");
+
+
+CREATE TABLE "LIVE_MEASURES" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "PROJECT_UUID" VARCHAR(50) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "METRIC_ID" INTEGER NOT NULL,
+  "VALUE" DOUBLE,
+  "TEXT_VALUE" VARCHAR(4000),
+  "VARIATION" DOUBLE,
+  "MEASURE_DATA" BINARY,
+  "UPDATE_MARKER" VARCHAR(40),
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_LIVE_MEASURES" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "LIVE_MEASURES_PROJECT" ON "LIVE_MEASURES" ("PROJECT_UUID");
+CREATE UNIQUE INDEX "LIVE_MEASURES_COMPONENT" ON "LIVE_MEASURES" ("COMPONENT_UUID", "METRIC_ID");
+
+
+CREATE TABLE "PROJECT_MEASURES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "VALUE" DOUBLE,
+  "METRIC_ID" INTEGER NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "ANALYSIS_UUID" VARCHAR(50) NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "ALERT_STATUS" VARCHAR(5),
+  "ALERT_TEXT" VARCHAR(4000),
+  "DESCRIPTION" VARCHAR(4000),
+  "PERSON_ID" INTEGER,
+  "VARIATION_VALUE_1" DOUBLE,
+  "VARIATION_VALUE_2" DOUBLE,
+  "VARIATION_VALUE_3" DOUBLE,
+  "VARIATION_VALUE_4" DOUBLE,
+  "VARIATION_VALUE_5" DOUBLE,
+  "MEASURE_DATA" BINARY
+);
+CREATE INDEX "MEASURES_COMPONENT_UUID" ON "PROJECT_MEASURES" ("COMPONENT_UUID");
+CREATE INDEX "MEASURES_ANALYSIS_METRIC" ON "PROJECT_MEASURES" ("ANALYSIS_UUID", "METRIC_ID");
+
+
+CREATE TABLE "INTERNAL_PROPERTIES" (
+  "KEE" VARCHAR(20) NOT NULL,
+  "IS_EMPTY" BOOLEAN NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "CLOB_VALUE" CLOB,
+  "CREATED_AT" BIGINT,
+
+  CONSTRAINT "PK_INTERNAL_PROPERTIES" PRIMARY KEY ("KEE")
+);
+
+
+CREATE TABLE "PROJECTS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "KEE" VARCHAR(400),
+  "UUID" VARCHAR(50) NOT NULL,
+  "UUID_PATH" VARCHAR(1500) NOT NULL,
+  "ROOT_UUID" VARCHAR(50) NOT NULL,
+  "PROJECT_UUID" VARCHAR(50) NOT NULL,
+  "MODULE_UUID" VARCHAR(50),
+  "MODULE_UUID_PATH" VARCHAR(1500),
+  "MAIN_BRANCH_PROJECT_UUID" VARCHAR(50),
+  "NAME" VARCHAR(2000),
+  "DESCRIPTION" VARCHAR(2000),
+  "PRIVATE" BOOLEAN NOT NULL,
+  "TAGS" VARCHAR(500),
+  "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+  "SCOPE" VARCHAR(3),
+  "QUALIFIER" VARCHAR(10),
+  "DEPRECATED_KEE" VARCHAR(400),
+  "PATH" VARCHAR(2000),
+  "LANGUAGE" VARCHAR(20),
+  "COPY_COMPONENT_UUID" VARCHAR(50),
+  "LONG_NAME" VARCHAR(2000),
+  "DEVELOPER_UUID" VARCHAR(50),
+  "CREATED_AT" TIMESTAMP,
+  "AUTHORIZATION_UPDATED_AT" BIGINT,
+  "B_CHANGED" BOOLEAN,
+  "B_COPY_COMPONENT_UUID" VARCHAR(50),
+  "B_DESCRIPTION" VARCHAR(2000),
+  "B_ENABLED" BOOLEAN,
+  "B_UUID_PATH" VARCHAR(1500),
+  "B_LANGUAGE" VARCHAR(20),
+  "B_LONG_NAME" VARCHAR(500),
+  "B_MODULE_UUID" VARCHAR(50),
+  "B_MODULE_UUID_PATH" VARCHAR(1500),
+  "B_NAME" VARCHAR(500),
+  "B_PATH" VARCHAR(2000),
+  "B_QUALIFIER" VARCHAR(10)
+);
+CREATE INDEX "PROJECTS_ORGANIZATION" ON "PROJECTS" ("ORGANIZATION_UUID");
+CREATE UNIQUE INDEX "PROJECTS_KEE" ON "PROJECTS" ("KEE");
+CREATE INDEX "PROJECTS_ROOT_UUID" ON "PROJECTS" ("ROOT_UUID");
+CREATE UNIQUE INDEX "PROJECTS_UUID" ON "PROJECTS" ("UUID");
+CREATE INDEX "PROJECTS_PROJECT_UUID" ON "PROJECTS" ("PROJECT_UUID");
+CREATE INDEX "PROJECTS_MODULE_UUID" ON "PROJECTS" ("MODULE_UUID");
+CREATE INDEX "PROJECTS_QUALIFIER" ON "PROJECTS" ("QUALIFIER");
+
+CREATE TABLE "INTERNAL_COMPONENT_PROPS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "KEE" VARCHAR(512) NOT NULL,
+  "VALUE" VARCHAR(4000),
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+  CONSTRAINT "INTERNAL_COMPONENT_PROPS_UUID" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "UNIQUE_COMPONENT_UUID_KEE" ON "INTERNAL_COMPONENT_PROPS" ("COMPONENT_UUID", "KEE");
+
+CREATE TABLE "MANUAL_MEASURES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "METRIC_ID" INTEGER NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50) NOT NULL,
+  "VALUE" DOUBLE,
+  "TEXT_VALUE" VARCHAR(4000),
+  "USER_UUID" VARCHAR(255),
+  "DESCRIPTION" VARCHAR(4000),
+  "CREATED_AT" BIGINT,
+  "UPDATED_AT" BIGINT
+);
+CREATE INDEX "MANUAL_MEASURES_COMPONENT_UUID" ON "MANUAL_MEASURES" ("COMPONENT_UUID");
+
+
+CREATE TABLE "ACTIVE_RULES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "PROFILE_ID" INTEGER NOT NULL,
+  "RULE_ID" INTEGER NOT NULL,
+  "FAILURE_LEVEL" INTEGER NOT NULL,
+  "INHERITANCE" VARCHAR(10),
+  "CREATED_AT" BIGINT,
+  "UPDATED_AT" BIGINT
+);
+CREATE UNIQUE INDEX "ACTIVE_RULES_UNIQUE" ON "ACTIVE_RULES" ("PROFILE_ID","RULE_ID");
+
+
+CREATE TABLE "NOTIFICATIONS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "DATA" BLOB
+);
+
+
+CREATE TABLE "USER_ROLES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "USER_ID" INTEGER,
+  "RESOURCE_ID" INTEGER,
+  "ROLE" VARCHAR(64) NOT NULL
+);
+CREATE INDEX "USER_ROLES_RESOURCE" ON "USER_ROLES" ("RESOURCE_ID");
+CREATE INDEX "USER_ROLES_USER" ON "USER_ROLES" ("USER_ID");
+
+
+CREATE TABLE "ACTIVE_RULE_PARAMETERS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ACTIVE_RULE_ID" INTEGER NOT NULL,
+  "RULES_PARAMETER_ID" INTEGER NOT NULL,
+  "RULES_PARAMETER_KEY" VARCHAR(128),
+  "VALUE" VARCHAR(4000)
+);
+CREATE INDEX "IX_ARP_ON_ACTIVE_RULE_ID" ON "ACTIVE_RULE_PARAMETERS" ("ACTIVE_RULE_ID");
+
+
+CREATE TABLE "USERS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(255) NOT NULL,
+  "LOGIN" VARCHAR(255) NOT NULL,
+  "NAME" VARCHAR(200),
+  "EMAIL" VARCHAR(100),
+  "CRYPTED_PASSWORD" VARCHAR(100),
+  "SALT" VARCHAR(40),
+  "HASH_METHOD" VARCHAR(10),
+  "ACTIVE" BOOLEAN DEFAULT TRUE,
+  "SCM_ACCOUNTS" VARCHAR(4000),
+  "EXTERNAL_ID" VARCHAR(255) NOT NULL,
+  "EXTERNAL_LOGIN" VARCHAR(255) NOT NULL,
+  "EXTERNAL_IDENTITY_PROVIDER" VARCHAR(100) NOT NULL,
+  "IS_ROOT" BOOLEAN NOT NULL,
+  "USER_LOCAL" BOOLEAN,
+  "ONBOARDED" BOOLEAN NOT NULL,
+  "HOMEPAGE_TYPE" VARCHAR(40),
+  "HOMEPAGE_PARAMETER" VARCHAR(40),
+  "ORGANIZATION_UUID" VARCHAR(40),
+  "LAST_CONNECTION_DATE" BIGINT,
+  "CREATED_AT" BIGINT,
+  "UPDATED_AT" BIGINT
+);
+CREATE UNIQUE INDEX "USERS_UUID" ON "USERS" ("UUID");
+CREATE UNIQUE INDEX "USERS_LOGIN" ON "USERS" ("LOGIN");
+CREATE UNIQUE INDEX "UNIQ_EXTERNAL_ID" ON "USERS" ("EXTERNAL_IDENTITY_PROVIDER", "EXTERNAL_ID");
+CREATE UNIQUE INDEX "UNIQ_EXTERNAL_LOGIN" ON "USERS" ("EXTERNAL_IDENTITY_PROVIDER", "EXTERNAL_LOGIN");
+CREATE INDEX "USERS_UPDATED_AT" ON "USERS" ("UPDATED_AT");
+
+
+CREATE TABLE "METRICS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "NAME" VARCHAR(64) NOT NULL,
+  "DESCRIPTION" VARCHAR(255),
+  "DIRECTION" INTEGER NOT NULL DEFAULT 0,
+  "DOMAIN" VARCHAR(64),
+  "SHORT_NAME" VARCHAR(64),
+  "QUALITATIVE" BOOLEAN NOT NULL DEFAULT FALSE,
+  "VAL_TYPE" VARCHAR(8),
+  "USER_MANAGED" BOOLEAN DEFAULT FALSE,
+  "ENABLED" BOOLEAN DEFAULT TRUE,
+  "WORST_VALUE" DOUBLE,
+  "BEST_VALUE" DOUBLE,
+  "OPTIMIZED_BEST_VALUE" BOOLEAN,
+  "HIDDEN" BOOLEAN,
+  "DELETE_HISTORICAL_DATA" BOOLEAN,
+  "DECIMAL_SCALE" INTEGER
+);
+CREATE UNIQUE INDEX "METRICS_UNIQUE_NAME" ON "METRICS" ("NAME");
+
+
+CREATE TABLE "ISSUES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(50) UNIQUE NOT NULL,
+  "COMPONENT_UUID" VARCHAR(50),
+  "PROJECT_UUID" VARCHAR(50),
+  "RULE_ID" INTEGER,
+  "SEVERITY" VARCHAR(10),
+  "MANUAL_SEVERITY" BOOLEAN NOT NULL,
+  "MESSAGE" VARCHAR(4000),
+  "LINE" INTEGER,
+  "GAP" DOUBLE,
+  "EFFORT" INTEGER,
+  "STATUS" VARCHAR(20),
+  "RESOLUTION" VARCHAR(20),
+  "CHECKSUM" VARCHAR(1000),
+  "REPORTER" VARCHAR(255),
+  "ASSIGNEE" VARCHAR(255),
+  "AUTHOR_LOGIN" VARCHAR(255),
+  "ACTION_PLAN_KEY" VARCHAR(50) NULL,
+  "ISSUE_ATTRIBUTES" VARCHAR(4000),
+  "TAGS" VARCHAR(4000),
+  "ISSUE_CREATION_DATE" BIGINT,
+  "ISSUE_CLOSE_DATE" BIGINT,
+  "ISSUE_UPDATE_DATE" BIGINT,
+  "CREATED_AT" BIGINT,
+  "UPDATED_AT" BIGINT,
+  "LOCATIONS" BLOB,
+  "ISSUE_TYPE" TINYINT,
+  "FROM_HOTSPOT" BOOLEAN NULL
+);
+CREATE UNIQUE INDEX "ISSUES_KEE" ON "ISSUES" ("KEE");
+CREATE INDEX "ISSUES_COMPONENT_UUID" ON "ISSUES" ("COMPONENT_UUID");
+CREATE INDEX "ISSUES_PROJECT_UUID" ON "ISSUES" ("PROJECT_UUID");
+CREATE INDEX "ISSUES_RULE_ID" ON "ISSUES" ("RULE_ID");
+CREATE INDEX "ISSUES_RESOLUTION" ON "ISSUES" ("RESOLUTION");
+CREATE INDEX "ISSUES_ASSIGNEE" ON "ISSUES" ("ASSIGNEE");
+CREATE INDEX "ISSUES_CREATION_DATE" ON "ISSUES" ("ISSUE_CREATION_DATE");
+CREATE INDEX "ISSUES_UPDATED_AT" ON "ISSUES" ("UPDATED_AT");
+
+
+CREATE TABLE "ISSUE_CHANGES" (
+  "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "KEE" VARCHAR(50),
+  "ISSUE_KEY" VARCHAR(50) NOT NULL,
+  "USER_LOGIN" VARCHAR(255),
+  "CHANGE_TYPE" VARCHAR(40),
+  "CHANGE_DATA"  VARCHAR(16777215),
+  "CREATED_AT" BIGINT,
+  "UPDATED_AT" BIGINT,
+  "ISSUE_CHANGE_CREATION_DATE" BIGINT
+);
+CREATE INDEX "ISSUE_CHANGES_KEE" ON "ISSUE_CHANGES" ("KEE");
+CREATE INDEX "ISSUE_CHANGES_ISSUE_KEY" ON "ISSUE_CHANGES" ("ISSUE_KEY");
+
+
+CREATE TABLE "PERMISSION_TEMPLATES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "NAME" VARCHAR(100) NOT NULL,
+  "KEE" VARCHAR(100) NOT NULL,
+  "DESCRIPTION" VARCHAR(4000),
+  "KEY_PATTERN" VARCHAR(500),
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP
+);
+
+
+CREATE TABLE "PERM_TPL_CHARACTERISTICS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "TEMPLATE_ID" INTEGER NOT NULL,
+  "PERMISSION_KEY" VARCHAR(64) NOT NULL,
+  "WITH_PROJECT_CREATOR" BOOLEAN NOT NULL DEFAULT FALSE,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL
+);
+CREATE UNIQUE INDEX "UNIQ_PERM_TPL_CHARAC" ON "PERM_TPL_CHARACTERISTICS" ("TEMPLATE_ID", "PERMISSION_KEY");
+
+
+CREATE TABLE "PERM_TEMPLATES_USERS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "USER_ID" INTEGER NOT NULL,
+  "TEMPLATE_ID" INTEGER NOT NULL,
+  "PERMISSION_REFERENCE" VARCHAR(64) NOT NULL,
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP
+);
+
+
+CREATE TABLE "PERM_TEMPLATES_GROUPS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "GROUP_ID" INTEGER,
+  "TEMPLATE_ID" INTEGER NOT NULL,
+  "PERMISSION_REFERENCE" VARCHAR(64) NOT NULL,
+  "CREATED_AT" TIMESTAMP,
+  "UPDATED_AT" TIMESTAMP
+);
+
+
+CREATE TABLE "QPROFILE_CHANGES" (
+  "KEE" VARCHAR(40) NOT NULL,
+  "RULES_PROFILE_UUID" VARCHAR(255) NOT NULL,
+  "CHANGE_TYPE" VARCHAR(20) NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "USER_UUID" VARCHAR(255),
+  "CHANGE_DATA" CLOB,
+
+  CONSTRAINT "PK_QPROFILE_CHANGES" PRIMARY KEY ("KEE")
+);
+CREATE INDEX "QP_CHANGES_RULES_PROFILE_UUID" ON "QPROFILE_CHANGES" ("RULES_PROFILE_UUID");
+
+
+CREATE TABLE "FILE_SOURCES" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "PROJECT_UUID" VARCHAR(50) NOT NULL,
+  "FILE_UUID" VARCHAR(50) NOT NULL,
+  "LINE_HASHES" CLOB,
+  "LINE_HASHES_VERSION" INTEGER,
+  "LINE_COUNT" INTEGER NOT NULL,
+  "BINARY_DATA" BLOB,
+  "DATA_HASH" VARCHAR(50),
+  "SRC_HASH" VARCHAR(50),
+  "REVISION" VARCHAR(100),
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL
+);
+CREATE INDEX "FILE_SOURCES_PROJECT_UUID" ON "FILE_SOURCES" ("PROJECT_UUID");
+CREATE UNIQUE INDEX "FILE_SOURCES_FILE_UUID" ON "FILE_SOURCES" ("FILE_UUID");
+CREATE INDEX "FILE_SOURCES_UPDATED_AT" ON "FILE_SOURCES" ("UPDATED_AT");
+
+
+CREATE TABLE "CE_QUEUE" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(40) NOT NULL,
+  "TASK_TYPE" VARCHAR(15) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(40) NULL,
+  "MAIN_COMPONENT_UUID" VARCHAR(40) NULL,
+  "STATUS" VARCHAR(15) NOT NULL,
+  "SUBMITTER_UUID" VARCHAR(255) NULL,
+  "WORKER_UUID" VARCHAR(40) NULL,
+  "EXECUTION_COUNT" INTEGER NOT NULL,
+  "STARTED_AT" BIGINT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL
+);
+CREATE UNIQUE INDEX "CE_QUEUE_UUID" ON "CE_QUEUE" ("UUID");
+CREATE INDEX "CE_QUEUE_COMPONENT" ON "CE_QUEUE" ("COMPONENT_UUID");
+CREATE INDEX "CE_QUEUE_MAIN_COMPONENT" ON "CE_QUEUE" ("MAIN_COMPONENT_UUID");
+CREATE INDEX "CE_QUEUE_STATUS" ON "CE_QUEUE" ("STATUS");
+
+
+CREATE TABLE "CE_ACTIVITY" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "UUID" VARCHAR(40) NOT NULL,
+  "TASK_TYPE" VARCHAR(15) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(40) NULL,
+  "MAIN_COMPONENT_UUID" VARCHAR(40) NULL,
+  "ANALYSIS_UUID" VARCHAR(50) NULL,
+  "STATUS" VARCHAR(15) NOT NULL,
+  "IS_LAST" BOOLEAN,
+  "IS_LAST_KEY" VARCHAR(55),
+  "MAIN_IS_LAST" BOOLEAN,
+  "MAIN_IS_LAST_KEY" VARCHAR(55),
+  "SUBMITTER_UUID" VARCHAR(255) NULL,
+  "WORKER_UUID" VARCHAR(40) NULL,
+  "EXECUTION_COUNT" INTEGER NOT NULL,
+  "SUBMITTED_AT" BIGINT NOT NULL,
+  "STARTED_AT" BIGINT NULL,
+  "EXECUTED_AT" BIGINT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+  "EXECUTION_TIME_MS" BIGINT NULL,
+  "ERROR_MESSAGE" VARCHAR(1000),
+  "ERROR_STACKTRACE" CLOB,
+  "ERROR_TYPE" VARCHAR(20)
+);
+CREATE UNIQUE INDEX "CE_ACTIVITY_UUID" ON "CE_ACTIVITY" ("UUID");
+CREATE INDEX "CE_ACTIVITY_COMPONENT" ON "CE_ACTIVITY" ("COMPONENT_UUID");
+CREATE INDEX "CE_ACTIVITY_MAIN_COMPONENT" ON "CE_ACTIVITY" ("COMPONENT_UUID");
+CREATE INDEX "CE_ACTIVITY_ISLAST_KEY" ON "CE_ACTIVITY" ("IS_LAST_KEY");
+CREATE INDEX "CE_ACTIVITY_ISLAST" ON "CE_ACTIVITY" ("IS_LAST", "STATUS");
+CREATE INDEX "CE_ACTIVITY_MAIN_ISLAST_KEY" ON "CE_ACTIVITY" ("MAIN_IS_LAST_KEY");
+CREATE INDEX "CE_ACTIVITY_MAIN_ISLAST" ON "CE_ACTIVITY" ("MAIN_IS_LAST", "STATUS");
+
+
+CREATE TABLE "CE_TASK_CHARACTERISTICS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "TASK_UUID" VARCHAR(40) NOT NULL,
+  "KEE" VARCHAR(50) NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+
+  CONSTRAINT "PK_CE_TASK_CHARACTERISTICS" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "CE_TASK_CHARACTERISTICS_TASK_UUID" ON "CE_TASK_CHARACTERISTICS" ("TASK_UUID");
+
+
+CREATE TABLE "CE_TASK_INPUT" (
+  "TASK_UUID" VARCHAR(40) NOT NULL,
+  "INPUT_DATA" BLOB,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_CE_TASK_INPUT" PRIMARY KEY ("TASK_UUID")
+);
+
+
+CREATE TABLE "CE_SCANNER_CONTEXT" (
+  "TASK_UUID" VARCHAR(40) NOT NULL,
+  "CONTEXT_DATA" BLOB NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_CE_SCANNER_CONTEXT" PRIMARY KEY ("TASK_UUID")
+);
+
+CREATE TABLE "CE_TASK_MESSAGE" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "TASK_UUID" VARCHAR(40) NOT NULL,
+  "MESSAGE" VARCHAR(4000) NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "CE_TASK_MESSAGE" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "CE_TASK_MESSAGE_TASK" ON "CE_TASK_MESSAGE" ("TASK_UUID");
+
+
+CREATE TABLE "USER_TOKENS" (
+  "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+  "USER_UUID" VARCHAR(255) NOT NULL,
+  "NAME" VARCHAR(100) NOT NULL,
+  "TOKEN_HASH" VARCHAR(255) NOT NULL,
+  "LAST_CONNECTION_DATE" BIGINT,
+  "CREATED_AT" BIGINT NOT NULL
+);
+CREATE UNIQUE INDEX "USER_TOKENS_TOKEN_HASH" ON "USER_TOKENS" ("TOKEN_HASH");
+CREATE UNIQUE INDEX "USER_TOKENS_USER_UUID_NAME" ON "USER_TOKENS" ("USER_UUID", "NAME");
+
+
+CREATE TABLE "ES_QUEUE" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "DOC_TYPE" VARCHAR(40) NOT NULL,
+  "DOC_ID" VARCHAR(4000) NOT NULL,
+  "DOC_ID_TYPE" VARCHAR(20),
+  "DOC_ROUTING" VARCHAR(4000),
+  "CREATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_ES_QUEUE" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "ES_QUEUE_CREATED_AT" ON "ES_QUEUE" ("CREATED_AT");
+
+
+CREATE TABLE "PLUGINS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "KEE" VARCHAR(200) NOT NULL,
+  "BASE_PLUGIN_KEY" VARCHAR(200),
+  "FILE_HASH" VARCHAR(200) NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_PLUGINS" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "PLUGINS_KEY" ON "PLUGINS" ("KEE");
+
+
+CREATE TABLE "PROJECT_BRANCHES" (
+  "UUID" VARCHAR(50) NOT NULL,
+  "PROJECT_UUID" VARCHAR(50) NOT NULL,
+  "KEE" VARCHAR(255) NOT NULL,
+  "KEY_TYPE" VARCHAR(12) NOT NULL,
+  "BRANCH_TYPE" VARCHAR(12),
+  "MERGE_BRANCH_UUID" VARCHAR(50),
+  "PULL_REQUEST_BINARY" BLOB,
+  "MANUAL_BASELINE_ANALYSIS_UUID" VARCHAR(40),
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_PROJECT_BRANCHES" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "PROJECT_BRANCHES_KEE_KEY_TYPE" ON "PROJECT_BRANCHES" ("PROJECT_UUID", "KEE", "KEY_TYPE");
+
+
+CREATE TABLE "ANALYSIS_PROPERTIES" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "ANALYSIS_UUID" VARCHAR(40) NOT NULL,
+  "KEE" VARCHAR(512) NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000),
+  "CLOB_VALUE" CLOB,
+  "IS_EMPTY" BOOLEAN NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_ANALYSIS_PROPERTIES" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "ANALYSIS_PROPERTIES_ANALYSIS" ON "ANALYSIS_PROPERTIES" ("ANALYSIS_UUID");
+
+
+CREATE TABLE "WEBHOOKS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "NAME" VARCHAR(100) NOT NULL,
+  "URL" VARCHAR(2000) NOT NULL,
+  "ORGANIZATION_UUID" VARCHAR(40),
+  "PROJECT_UUID" VARCHAR(40),
+  "SECRET" VARCHAR(200),
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_WEBHOOKS" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "ORGANIZATION_WEBHOOK" ON "WEBHOOKS" ("ORGANIZATION_UUID");
+CREATE INDEX "PROJECT_WEBHOOK" ON "WEBHOOKS" ("PROJECT_UUID");
+
+
+CREATE TABLE "WEBHOOK_DELIVERIES" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "WEBHOOK_UUID" VARCHAR(40) NOT NULL,
+  "COMPONENT_UUID" VARCHAR(40) NOT NULL,
+  "ANALYSIS_UUID" VARCHAR(40),
+  "CE_TASK_UUID" VARCHAR(40),
+  "NAME" VARCHAR(100) NOT NULL,
+  "URL" VARCHAR(2000) NOT NULL,
+  "SUCCESS" BOOLEAN NOT NULL,
+  "HTTP_STATUS" INT,
+  "DURATION_MS" INT NOT NULL,
+  "PAYLOAD" CLOB NOT NULL,
+  "ERROR_STACKTRACE" CLOB,
+  "CREATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_WEBHOOK_DELIVERIES" PRIMARY KEY ("UUID")
+);
+CREATE INDEX "COMPONENT_UUID" ON "WEBHOOK_DELIVERIES" ("COMPONENT_UUID");
+CREATE INDEX "CE_TASK_UUID" ON "WEBHOOK_DELIVERIES" ("CE_TASK_UUID");
+CREATE INDEX "ANALYSIS_UUID" ON "WEBHOOK_DELIVERIES" ("ANALYSIS_UUID");
+
+
+CREATE TABLE "ALM_APP_INSTALLS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "ALM_ID" VARCHAR(40) NOT NULL,
+  "OWNER_ID" VARCHAR(4000) NOT NULL,
+  "IS_OWNER_USER" BOOLEAN NOT NULL,
+  "INSTALL_ID" VARCHAR(4000) NOT NULL,
+  "USER_EXTERNAL_ID" VARCHAR(255),
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_ALM_APP_INSTALLS" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "ALM_APP_INSTALLS_OWNER" ON "ALM_APP_INSTALLS" ("ALM_ID", "OWNER_ID");
+CREATE UNIQUE INDEX "ALM_APP_INSTALLS_INSTALL" ON "ALM_APP_INSTALLS" ("ALM_ID", "INSTALL_ID");
+CREATE INDEX "ALM_APP_INSTALLS_EXTERNAL_ID" ON "ALM_APP_INSTALLS" ("USER_EXTERNAL_ID");
+
+CREATE TABLE "PROJECT_ALM_BINDINGS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "ALM_ID" VARCHAR(40) NOT NULL,
+  "REPO_ID" VARCHAR(256) NOT NULL,
+  "PROJECT_UUID" VARCHAR(40) NOT NULL,
+  "GITHUB_SLUG" VARCHAR(256) NULL,
+  "URL" VARCHAR(2000) NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+  CONSTRAINT "PK_PROJECT_ALM_BINDINGS" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "PROJECT_ALM_BINDINGS_ALM_REPO" ON "PROJECT_ALM_BINDINGS" ("ALM_ID", "REPO_ID");
+CREATE UNIQUE INDEX "PROJECT_ALM_BINDINGS_PROJECT" ON "PROJECT_ALM_BINDINGS" ("PROJECT_UUID");
+
+CREATE TABLE "PROJECT_MAPPINGS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "KEY_TYPE" VARCHAR(200) NOT NULL,
+  "KEE" VARCHAR(4000) NOT NULL,
+  "PROJECT_UUID" VARCHAR(40) NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  CONSTRAINT "PK_PROJECT_MAPPINGS" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "KEY_TYPE_KEE" ON "PROJECT_MAPPINGS" ("KEY_TYPE", "KEE");
+CREATE INDEX "PROJECT_UUID" ON "PROJECT_MAPPINGS" ("PROJECT_UUID");
+
+CREATE TABLE "ORGANIZATION_ALM_BINDINGS" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "ORGANIZATION_UUID" VARCHAR(40) NOT NULL,
+  "ALM_APP_INSTALL_UUID" VARCHAR(40) NOT NULL,
+  "ALM_ID" VARCHAR(40) NOT NULL,
+  "URL" VARCHAR(2000) NOT NULL,
+  "USER_UUID" VARCHAR(255) NOT NULL,
+  "MEMBERS_SYNC_ENABLED" BOOLEAN,
+  "CREATED_AT" BIGINT NOT NULL,
+  CONSTRAINT "PK_ORGANIZATION_ALM_BINDINGS" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "ORG_ALM_BINDINGS_ORG" ON "ORGANIZATION_ALM_BINDINGS" ("ORGANIZATION_UUID");
+CREATE UNIQUE INDEX "ORG_ALM_BINDINGS_INSTALL" ON "ORGANIZATION_ALM_BINDINGS" ("ALM_APP_INSTALL_UUID");
+
+CREATE TABLE "USER_PROPERTIES" (
+  "UUID" VARCHAR(40) NOT NULL,
+  "USER_UUID" VARCHAR(255) NOT NULL,
+  "KEE" VARCHAR(100) NOT NULL,
+  "TEXT_VALUE" VARCHAR(4000) NOT NULL,
+  "CREATED_AT" BIGINT NOT NULL,
+  "UPDATED_AT" BIGINT NOT NULL,
+
+  CONSTRAINT "PK_USER_PROPERTIES" PRIMARY KEY ("UUID")
+);
+CREATE UNIQUE INDEX "USER_PROPERTIES_USER_UUID_KEE" ON "USER_PROPERTIES" ("USER_UUID", "KEE");
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/schema_migrations-h2.ddl b/server/sonar-db-dao/src/main/resources/org/sonar/db/schema_migrations-h2.ddl
new file mode 100644 (file)
index 0000000..aad2a07
--- /dev/null
@@ -0,0 +1,4 @@
+CREATE TABLE "SCHEMA_MIGRATIONS" (
+  "VERSION" VARCHAR(256) NOT NULL
+);
+CREATE INDEX "UNIQUE_SCHEMA_MIGRATIONS" ON "SCHEMA_MIGRATIONS" ("VERSION");
index 930250b29438431fc428624df7356f5b7974b2ca..52a064a1ac2dd33718368a0ef770f3ceaae97243 100644 (file)
@@ -63,7 +63,7 @@ import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
  * This class should be called using @Rule.
  * Data is truncated between each tests. The schema is created between each test.
  */
-public class DbTester extends AbstractDbTester<TestDb> {
+public class DbTester extends AbstractDbTester<TestDbImpl> {
 
   private final System2 system2;
   private DbClient client;
@@ -96,7 +96,7 @@ public class DbTester extends AbstractDbTester<TestDb> {
   private final InternalComponentPropertyDbTester internalComponentPropertyTester;
 
   private DbTester(System2 system2, @Nullable String schemaPath, MyBatisConfExtension... confExtensions) {
-    super(TestDb.create(schemaPath, confExtensions));
+    super(TestDbImpl.create(schemaPath, confExtensions));
     this.system2 = system2;
 
     initDbClient();
@@ -374,7 +374,7 @@ public class DbTester extends AbstractDbTester<TestDb> {
   }
 
   private static class DbTesterMyBatisConfExtension implements MyBatisConfExtension {
-    // do not replace with a lambda to allow cache of MyBatis instances in TestDb to work
+    // do not replace with a lambda to allow cache of MyBatis instances in TestDbImpl to work
     private final Class<?>[] mapperClasses;
 
     public DbTesterMyBatisConfExtension(Class<?> firstMapperClass, Class<?>... otherMapperClasses) {
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/DdlUtilsTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/DdlUtilsTest.java
new file mode 100644 (file)
index 0000000..0423d6d
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.db;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import org.h2.Driver;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DdlUtilsTest {
+
+  @Test
+  public void shouldCreateSchema_with_schema_migrations() throws SQLException {
+    DriverManager.registerDriver(new Driver());
+    try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:sonar_test")) {
+      DdlUtils.createSchema(connection, "h2", true);
+
+      int tableCount = countTables(connection);
+      assertThat(tableCount).isGreaterThan(30);
+
+      verifySchemaMigrationsNotPopulated(connection);
+    }
+  }
+
+  @Test
+  public void shouldCreateSchema_without_schema_migrations() throws SQLException {
+    DriverManager.registerDriver(new Driver());
+    try (Connection connection = DriverManager.getConnection("jdbc:h2:mem:sonar_test2")) {
+      try (Statement statement = connection.createStatement()) {
+        statement.execute("create table schema_migrations (version varchar(255) not null)");
+      }
+      DdlUtils.createSchema(connection, "h2", false);
+
+      verifySchemaMigrationsNotPopulated(connection);
+    }
+  }
+
+  static int countTables(Connection connection) throws SQLException {
+    int count = 0;
+    ResultSet resultSet = connection.getMetaData().getTables("", null, null, new String[] {"TABLE"});
+    while (resultSet.next()) {
+      count++;
+    }
+    resultSet.close();
+    return count;
+  }
+
+  private void verifySchemaMigrationsNotPopulated(Connection connection) throws SQLException {
+    try (Statement statement = connection.createStatement();
+      ResultSet resultSet = statement.executeQuery("select count(*) from schema_migrations")) {
+      assertThat(resultSet.next()).isTrue();
+      assertThat(resultSet.getLong(1)).isEqualTo(0);
+      assertThat(resultSet.next()).isFalse();
+    }
+  }
+
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/H2Database.java b/server/sonar-db-dao/src/test/java/org/sonar/db/H2Database.java
new file mode 100644 (file)
index 0000000..44bbaf9
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.db;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import javax.sql.DataSource;
+import org.apache.commons.dbcp2.BasicDataSource;
+import org.apache.commons.dbutils.DbUtils;
+import org.sonar.db.dialect.Dialect;
+import org.sonar.db.dialect.H2;
+
+import static java.lang.String.format;
+
+/**
+ * H2 in-memory database, used for unit tests only.
+ *
+ * @since 3.2
+ */
+public class H2Database implements Database {
+  private final String name;
+  private final boolean createSchema;
+  private BasicDataSource datasource;
+
+  /**
+   * IMPORTANT: change DB name in order to not conflict with {@link DefaultDatabaseTest}
+   */
+  public H2Database(String name, boolean createSchema) {
+    this.name = name;
+    this.createSchema = createSchema;
+  }
+
+  @Override
+  public void start() {
+    startDatabase();
+    if (createSchema) {
+      createSchema();
+    }
+  }
+
+  private void startDatabase() {
+    try {
+      datasource = new BasicDataSource();
+      datasource.setDriverClassName("org.h2.Driver");
+      datasource.setUsername("sonar");
+      datasource.setPassword("sonar");
+      datasource.setUrl("jdbc:h2:mem:" + name);
+    } catch (Exception e) {
+      throw new IllegalStateException("Fail to start H2", e);
+    }
+  }
+
+  private void createSchema() {
+    Connection connection = null;
+    try {
+      connection = datasource.getConnection();
+      DdlUtils.createSchema(connection, "h2", true);
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("Fail to create schema", e);
+    } finally {
+      DbUtils.closeQuietly(connection);
+    }
+  }
+
+  public void executeScript(String classloaderPath) {
+    Connection connection = null;
+    try {
+      connection = datasource.getConnection();
+      CoreDdlUtils.executeScript(connection, classloaderPath);
+
+    } catch (SQLException e) {
+      throw new IllegalStateException("Fail to execute script: " + classloaderPath, e);
+    } finally {
+      DbUtils.closeQuietly(connection);
+    }
+  }
+
+  @Override
+  public void stop() {
+    try {
+      datasource.close();
+    } catch (SQLException e) {
+      // Ignore error
+    }
+  }
+
+  public DataSource getDataSource() {
+    return datasource;
+  }
+
+  public Dialect getDialect() {
+    return new H2();
+  }
+
+  @Override
+  public void enableSqlLogging(boolean enable) {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public String toString() {
+    return format("H2 Database[%s]", name);
+  }
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/H2DatabaseTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/H2DatabaseTest.java
new file mode 100644 (file)
index 0000000..e4dec16
--- /dev/null
@@ -0,0 +1,51 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.db;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class H2DatabaseTest {
+  H2Database db = new H2Database("sonar2", true);
+
+  @Before
+  public void startDb() {
+    db.start();
+  }
+
+  @After
+  public void stopDb() {
+    db.stop();
+  }
+
+  @Test
+  public void shouldExecuteDdlAtStartup() throws SQLException {
+    Connection connection = db.getDataSource().getConnection();
+    int tableCount = DdlUtilsTest.countTables(connection);
+    connection.close();
+
+    assertThat(tableCount).isGreaterThan(30);
+  }
+}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/TestDb.java b/server/sonar-db-dao/src/test/java/org/sonar/db/TestDb.java
deleted file mode 100644 (file)
index cd04e02..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.db;
-
-import java.util.HashMap;
-import java.util.Map;
-import javax.annotation.Nullable;
-
-class TestDb extends CoreTestDb {
-
-  private static TestDb defaultSchemaBaseTestDb;
-  // instantiating MyBatis objects is costly => we cache them for default schema
-  private static final Map<MyBatisConfExtension[], TestDb> defaultSchemaTestDbsWithExtensions = new HashMap<>();
-
-  private MyBatis myBatis;
-
-  private TestDb(@Nullable String schemaPath, MyBatisConfExtension... confExtensions) {
-    super();
-    init(schemaPath, (db, created) -> myBatis = newMyBatis(db, confExtensions));
-  }
-
-  private TestDb(TestDb base, MyBatis myBatis) {
-    super(base);
-    this.myBatis = myBatis;
-  }
-
-  private static MyBatis newMyBatis(Database db, MyBatisConfExtension[] extensions) {
-    MyBatis newMyBatis = new MyBatis(db, extensions);
-    newMyBatis.start();
-    return newMyBatis;
-  }
-
-  static TestDb create(@Nullable String schemaPath, MyBatisConfExtension... confExtensions) {
-    MyBatisConfExtension[] extensionArray = confExtensions == null || confExtensions.length == 0 ? null : confExtensions;
-    if (schemaPath == null) {
-      if (defaultSchemaBaseTestDb == null) {
-        defaultSchemaBaseTestDb = new TestDb((String) null);
-      }
-      if (extensionArray != null) {
-        return defaultSchemaTestDbsWithExtensions.computeIfAbsent(
-          extensionArray,
-          extensions -> new TestDb(defaultSchemaBaseTestDb, newMyBatis(defaultSchemaBaseTestDb.getDatabase(), extensions)));
-      }
-      return defaultSchemaBaseTestDb;
-    }
-    return new TestDb(schemaPath, confExtensions);
-  }
-
-  MyBatis getMyBatis() {
-    return myBatis;
-  }
-}
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/TestDbImpl.java b/server/sonar-db-dao/src/test/java/org/sonar/db/TestDbImpl.java
new file mode 100644 (file)
index 0000000..e5ef68b
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.db;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import javax.annotation.Nullable;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.lang.StringUtils;
+import org.junit.AssumptionViolatedException;
+import org.sonar.api.config.Settings;
+import org.sonar.db.dialect.H2;
+import org.sonar.process.logging.LogbackHelper;
+
+class TestDbImpl extends CoreTestDb {
+  private static TestDbImpl defaultSchemaBaseTestDb;
+  // instantiating MyBatis objects is costly => we cache them for default schema
+  private static final Map<MyBatisConfExtension[], TestDbImpl> defaultSchemaTestDbsWithExtensions = new HashMap<>();
+
+  private boolean isDefault;
+  private MyBatis myBatis;
+
+  private TestDbImpl(@Nullable String schemaPath, MyBatisConfExtension... confExtensions) {
+    super();
+    isDefault = (schemaPath == null);
+    init(schemaPath, confExtensions);
+  }
+
+  private TestDbImpl(TestDbImpl base, MyBatis myBatis) {
+    super(base.getDatabase(), base.getCommands(), base.getDbUnitTester());
+    this.isDefault = base.isDefault;
+    this.myBatis = myBatis;
+  }
+
+  void init(@Nullable String schemaPath, MyBatisConfExtension[] confExtensions) {
+    Function<Settings, Database> databaseCreator = settings -> {
+      String dialect = settings.getString("sonar.jdbc.dialect");
+      if (dialect != null && !"h2".equals(dialect)) {
+        return new DefaultDatabase(new LogbackHelper(), settings);
+      }
+      return new H2Database("h2Tests" + DigestUtils.md5Hex(StringUtils.defaultString(schemaPath)), schemaPath == null);
+    };
+    Function<Database, Boolean> schemaPathExecutor = database -> {
+      if (schemaPath != null) {
+        // will fail if not H2
+        if (!database.getDialect().getId().equals("h2")) {
+          return false;
+        }
+        ((H2Database) database).executeScript(schemaPath);
+      }
+      return true;
+    };
+    BiConsumer<Database, Boolean> createMyBatis = (db, created) -> myBatis = newMyBatis(db, confExtensions);
+    init(databaseCreator, schemaPathExecutor, createMyBatis);
+  }
+
+  private static MyBatis newMyBatis(Database db, MyBatisConfExtension[] extensions) {
+    MyBatis newMyBatis = new MyBatis(db, extensions);
+    newMyBatis.start();
+    return newMyBatis;
+  }
+
+  static TestDbImpl create(@Nullable String schemaPath, MyBatisConfExtension... confExtensions) {
+    MyBatisConfExtension[] extensionArray = confExtensions == null || confExtensions.length == 0 ? null : confExtensions;
+    if (schemaPath == null) {
+      if (defaultSchemaBaseTestDb == null) {
+        defaultSchemaBaseTestDb = new TestDbImpl((String) null);
+      }
+      if (extensionArray != null) {
+        return defaultSchemaTestDbsWithExtensions.computeIfAbsent(
+          extensionArray,
+          extensions -> new TestDbImpl(defaultSchemaBaseTestDb, newMyBatis(defaultSchemaBaseTestDb.getDatabase(), extensions)));
+      }
+      return defaultSchemaBaseTestDb;
+    }
+    return new TestDbImpl(schemaPath, confExtensions);
+  }
+
+  @Override
+  public void start() {
+    if (!isDefault && !H2.ID.equals(getDatabase().getDialect().getId())) {
+      throw new AssumptionViolatedException("Test disabled because it supports only H2");
+    }
+  }
+
+  @Override
+  public void stop() {
+    if (!isDefault) {
+      super.stop();
+    }
+  }
+
+  MyBatis getMyBatis() {
+    return myBatis;
+  }
+}
index bac37c6cefe333e49d3c4cb343ab3628e6878e19..a54d45ec9e0daae648ee3a620a86d6c736c8aa97 100644 (file)
@@ -41,7 +41,7 @@ import static org.sonar.server.property.InternalProperties.INSTALLATION_DATE;
 import static org.sonar.server.property.InternalProperties.INSTALLATION_VERSION;
 
 /**
- * FIXME fix this class to remove use of DdlUtils.createSchema
+ * FIXME fix this class to remove use of CoreDdlUtils.createSchema
  */
 public class AutoDbMigration implements Startable {
   private final DefaultServerUpgradeStatus serverUpgradeStatus;