From: Julien Lancelot Date: Fri, 21 Feb 2014 16:00:57 +0000 (+0100) Subject: SONAR-4996 Create migration on debt measures X-Git-Tag: 4.3~704 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=73226c06cf490ef5b82cc7e9816fba82723871e8;p=sonarqube.git SONAR-4996 Create migration on debt measures --- diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java index b506de48605..756e5ec3e76 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java @@ -33,7 +33,7 @@ import java.util.List; */ public class DatabaseVersion implements BatchComponent, ServerComponent { - public static final int LAST_VERSION = 514; + public static final int LAST_VERSION = 515; public static enum Status { UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL diff --git a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql index 558541de844..c19f22072d7 100644 --- a/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql +++ b/sonar-core/src/main/resources/org/sonar/core/persistence/rows-h2.sql @@ -212,6 +212,7 @@ INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('510'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('511'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('513'); INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('514'); +INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('515'); INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null); ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2; diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java index 154e09fcfe9..14cd9a5d9b5 100644 --- a/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java +++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/DatabaseMigrations.java @@ -22,6 +22,7 @@ package org.sonar.server.db.migrations; import com.google.common.collect.ImmutableList; import org.sonar.server.db.migrations.debt.IssueChangelogMigration; import org.sonar.server.db.migrations.debt.IssueMigration; +import org.sonar.server.db.migrations.debt.TechnicalDebtMeasureMigration; import org.sonar.server.db.migrations.violation.ViolationMigration; import java.util.List; @@ -31,7 +32,8 @@ public interface DatabaseMigrations { List> CLASSES = ImmutableList.of( ViolationMigration.class, IssueMigration.class, - IssueChangelogMigration.class + IssueChangelogMigration.class, + TechnicalDebtMeasureMigration.class ); } diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DebtConvertor.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DebtConvertor.java index 4ae3b4ef185..ed47bd785c5 100644 --- a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DebtConvertor.java +++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/DebtConvertor.java @@ -57,6 +57,10 @@ class DebtConvertor { return durationInSeconds; } + long createFromDays(double days) { + return ((Double) (days * hoursInDay() * 3600L)).longValue(); + } + private int hoursInDay() { int hoursInDay = settings.getInt(HOURS_IN_DAY_PROPERTY); if (hoursInDay < 0) { diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java index 432039cd254..df57ca9a389 100644 --- a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java +++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/IssueChangelogMigration.java @@ -60,7 +60,7 @@ public class IssueChangelogMigration implements DatabaseMigration { private static final String SQL_SELECT = "SELECT * FROM issue_changes WHERE change_type = 'diff' and change_data LIKE '%technicalDebt%'"; private static final String SQL_UPDATE = "UPDATE issue_changes SET change_data=?,updated_at=? WHERE id=?"; - static final String SQL_SELECT_ISSUES; + static final String SQL_SELECT_ALL; static { StringBuilder sb = new StringBuilder("SELECT c.id AS "+ ID +", c.change_data AS " + CHANGE_DATA + @@ -72,7 +72,7 @@ public class IssueChangelogMigration implements DatabaseMigration { } sb.append("c.id=?"); } - SQL_SELECT_ISSUES = sb.toString(); + SQL_SELECT_ALL = sb.toString(); } private final DebtConvertor debtConvertor; @@ -126,7 +126,7 @@ public class IssueChangelogMigration implements DatabaseMigration { try { readConnection = db.getDataSource().getConnection(); RowHandler rowHandler = new RowHandler(); - return new QueryRunner().query(readConnection, SQL_SELECT_ISSUES, rowHandler, ids); + return new QueryRunner().query(readConnection, SQL_SELECT_ALL, rowHandler, ids); } finally { DbUtils.closeQuietly(readConnection); diff --git a/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigration.java b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigration.java new file mode 100644 index 00000000000..6e59af22a32 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigration.java @@ -0,0 +1,188 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.db.migrations.debt; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.commons.dbutils.DbUtils; +import org.apache.commons.dbutils.QueryRunner; +import org.apache.commons.dbutils.handlers.AbstractListHandler; +import org.picocontainer.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.MessageException; +import org.sonar.core.persistence.Database; +import org.sonar.server.db.migrations.DatabaseMigration; +import org.sonar.server.db.migrations.util.SqlUtil; + +import javax.annotation.CheckForNull; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.List; +import java.util.Map; + +/** + * Used in the Active Record Migration 515 + */ +public class TechnicalDebtMeasureMigration implements DatabaseMigration { + + private Logger logger = LoggerFactory.getLogger(TechnicalDebtMeasureMigration.class); + + private static final String ID = "id"; + private static final String VALUE = "changeData"; + private static final String VAR1 = "var1"; + private static final String VAR2 = "var2"; + private static final String VAR3 = "var3"; + private static final String VAR4 = "var4"; + private static final String VAR5 = "var5"; + + private static final String FAILURE_MESSAGE = "Fail to migrate data"; + + private static final String SQL_SELECT = "SELECT * FROM project_measures INNER JOIN metrics on metrics.id=project_measures.metric_id " + + "WHERE metrics.name='sqale_index' or metrics.name='new_technical_debt'"; + private static final String SQL_UPDATE = "UPDATE project_measures SET value=?," + + "variation_value_1=?,variation_value_2=?,variation_value_3=?,variation_value_4=?,variation_value_5=? WHERE id=?"; + private static final String SQL_SELECT_ALL; + + static { + StringBuilder sb = new StringBuilder("SELECT pm.id AS " + ID + ", pm.value AS " + VALUE + + ", pm.variation_value_1 AS " + VAR1 + ", pm.variation_value_2 AS " + VAR2 + ", pm.variation_value_3 AS " + VAR3 + + ", pm.variation_value_4 AS " + VAR4 + ", pm.variation_value_5 AS " + VAR5 + + " FROM project_measures pm " + + " WHERE "); + for (int i = 0; i < Referentials.GROUP_SIZE; i++) { + if (i > 0) { + sb.append(" OR "); + } + sb.append("pm.id=?"); + } + SQL_SELECT_ALL = sb.toString(); + } + + private final DebtConvertor debtConvertor; + private final Database db; + + public TechnicalDebtMeasureMigration(Database database, Settings settings) { + this.db = database; + this.debtConvertor = new DebtConvertor(settings); + } + + @Override + public void execute() { + try { + logger.info("Initialize input"); + Referentials referentials = new Referentials(db, SQL_SELECT); + if (referentials.size() > 0) { + logger.info("Migrate {} rows", referentials.size()); + convert(referentials); + } + } catch (SQLException e) { + logger.error(FAILURE_MESSAGE, e); + SqlUtil.log(logger, e); + throw MessageException.of(FAILURE_MESSAGE); + + } catch (Exception e) { + logger.error(FAILURE_MESSAGE, e); + throw MessageException.of(FAILURE_MESSAGE); + } + } + + public Object convert(Referentials referentials) throws Exception { + Long[] ids = referentials.pollGroupOfIds(); + while (ids.length > 0) { + List> rows = selectRows(ids); + convert(rows, ids); + + ids = referentials.pollGroupOfIds(); + } + return null; + } + + private List> selectRows(Long[] ids) throws SQLException { + Connection readConnection = null; + try { + readConnection = db.getDataSource().getConnection(); + RowHandler rowHandler = new RowHandler(); + return new QueryRunner().query(readConnection, SQL_SELECT_ALL, rowHandler, ids); + + } finally { + DbUtils.closeQuietly(readConnection); + } + } + + private void convert(List> rows, Long[] ids) throws SQLException { + Connection readConnection = null; + Connection writeConnection = null; + try { + readConnection = db.getDataSource().getConnection(); + writeConnection = db.getDataSource().getConnection(); + writeConnection.setAutoCommit(false); + + List allParams = Lists.newArrayList(); + QueryRunner runner = new QueryRunner(); + for (Map row : rows) { + Object[] params = new Object[7]; + params[0] = convertDebtForDays((Double) row.get(VALUE)); + params[1] = convertDebtForDays((Double) row.get(VAR1)); + params[2] = convertDebtForDays((Double) row.get(VAR2)); + params[3] = convertDebtForDays((Double) row.get(VAR3)); + params[4] = convertDebtForDays((Double) row.get(VAR4)); + params[5] = convertDebtForDays((Double) row.get(VAR5)); + params[6] = row.get(ID); + allParams.add(params); + } + runner.batch(writeConnection, SQL_UPDATE, allParams.toArray(new Object[allParams.size()][])); + writeConnection.commit(); + + } finally { + DbUtils.closeQuietly(readConnection); + DbUtils.closeQuietly(writeConnection); + } + } + + @VisibleForTesting + @CheckForNull + Long convertDebtForDays(@Nullable Double data) { + if (data == null) { + return null; + } + return debtConvertor.createFromDays(data); + } + + private static class RowHandler extends AbstractListHandler> { + @Override + protected Map handleRow(ResultSet rs) throws SQLException { + Map map = Maps.newHashMap(); + map.put(ID, SqlUtil.getLong(rs, ID)); + map.put(VALUE, SqlUtil.getDouble(rs, VALUE)); + map.put(VAR1, SqlUtil.getDouble(rs, VAR1)); + map.put(VAR2, SqlUtil.getDouble(rs, VAR2)); + map.put(VAR3, SqlUtil.getDouble(rs, VAR3)); + map.put(VAR4, SqlUtil.getDouble(rs, VAR4)); + map.put(VAR5, SqlUtil.getDouble(rs, VAR5)); + return map; + } + } + +} diff --git a/sonar-server/src/main/webapp/WEB-INF/db/migrate/515_update_measures_debt_to_seconds.rb b/sonar-server/src/main/webapp/WEB-INF/db/migrate/515_update_measures_debt_to_seconds.rb new file mode 100644 index 00000000000..0db6ccadc2c --- /dev/null +++ b/sonar-server/src/main/webapp/WEB-INF/db/migrate/515_update_measures_debt_to_seconds.rb @@ -0,0 +1,30 @@ +# +# SonarQube, open source software quality management tool. +# Copyright (C) 2008-2013 SonarSource +# mailto:contact AT sonarsource DOT com +# +# SonarQube 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. +# +# SonarQube 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. +# + +# +# Sonar 4.3 +# SONAR-4996 +# +class UpdateMeasuresDebtToSeconds < ActiveRecord::Migration + + def self.up + Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.debt.TechnicalDebtMeasureMigration') + end +end diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/DatabaseMigrationsTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/DatabaseMigrationsTest.java index b53d7741755..478277f04bf 100644 --- a/sonar-server/src/test/java/org/sonar/server/db/migrations/DatabaseMigrationsTest.java +++ b/sonar-server/src/test/java/org/sonar/server/db/migrations/DatabaseMigrationsTest.java @@ -28,6 +28,6 @@ public class DatabaseMigrationsTest { @Test public void check_number_of_migrations() throws Exception { - assertThat(DatabaseMigrations.CLASSES).hasSize(3); + assertThat(DatabaseMigrations.CLASSES).isNotEmpty(); } } diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtConvertorTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtConvertorTest.java index 398dea4d8c5..2d53bec7214 100644 --- a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtConvertorTest.java +++ b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/DebtConvertorTest.java @@ -39,7 +39,7 @@ public class DebtConvertorTest { } @Test - public void convert() throws Exception { + public void convert_fromn_long() throws Exception { settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, 8); assertThat(convertor.createFromLong(1)).isEqualTo(60); @@ -49,12 +49,12 @@ public class DebtConvertorTest { } @Test - public void use_default_value_for_hours_in_day_when_no_property() throws Exception { + public void convert_fromn_long_use_default_value_for_hours_in_day_when_no_property() throws Exception { assertThat(convertor.createFromLong(1)).isEqualTo(60); } @Test - public void fail_on_bad_hours_in_day_property() throws Exception { + public void fail_convert_fromn_long_on_bad_hours_in_day_property() throws Exception { try { settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, -2); convertor.createFromLong(1); @@ -64,4 +64,15 @@ public class DebtConvertorTest { } } + @Test + public void convert_from_days() throws Exception { + settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, 8); + + assertThat(convertor.createFromDays(1.0)).isEqualTo(28800); + assertThat(convertor.createFromDays(0.1)).isEqualTo(2880); + + // Should be 1.88 but as it's a long it's truncated after comma + assertThat(convertor.createFromDays(0.0001)).isEqualTo(2); + } + } diff --git a/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest.java b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest.java new file mode 100644 index 00000000000..fb5c590b361 --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest.java @@ -0,0 +1,67 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.db.migrations.debt; + +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.config.Settings; +import org.sonar.core.persistence.TestDatabase; + +@RunWith(MockitoJUnitRunner.class) +public class TechnicalDebtMeasureMigrationTest { + + @ClassRule + public static TestDatabase db = new TestDatabase().schema(TechnicalDebtMeasureMigrationTest.class, "schema.sql"); + + Settings settings; + + TechnicalDebtMeasureMigration migration; + + @Before + public void setUp() throws Exception { + settings = new Settings(); + settings.setProperty(DebtConvertor.HOURS_IN_DAY_PROPERTY, 8); + + migration = new TechnicalDebtMeasureMigration(db.database(), settings); + } + + @Test + public void migrate_technical_debt_measures() throws Exception { + db.prepareDbUnit(getClass(), "migrate_technical_debt_measures.xml"); + + migration.execute(); + + db.assertDbUnit(getClass(), "migrate_technical_debt_measures_result.xml", "project_measures"); + } + + @Test + public void migrate_added_technical_debt_measures() throws Exception { + db.prepareDbUnit(getClass(), "migrate_new_technical_debt_measures.xml"); + + migration.execute(); + + db.assertDbUnit(getClass(), "migrate_new_technical_debt_measures_result.xml", "project_measures"); + } + +} diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures.xml new file mode 100644 index 00000000000..186b86bf6c7 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures.xml @@ -0,0 +1,29 @@ + + + + diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures_result.xml new file mode 100644 index 00000000000..591506c8276 --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_new_technical_debt_measures_result.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures.xml new file mode 100644 index 00000000000..e7e24866b7c --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures.xml @@ -0,0 +1,35 @@ + + + + diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures_result.xml b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures_result.xml new file mode 100644 index 00000000000..150674c514f --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/migrate_technical_debt_measures_result.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + diff --git a/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/schema.sql b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/schema.sql new file mode 100644 index 00000000000..1e29613934e --- /dev/null +++ b/sonar-server/src/test/resources/org/sonar/server/db/migrations/debt/TechnicalDebtMeasureMigrationTest/schema.sql @@ -0,0 +1,45 @@ +-- 4.3 + +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, + "SNAPSHOT_ID" INTEGER, + "RULE_ID" INTEGER, + "RULES_CATEGORY_ID" INTEGER, + "TEXT_VALUE" VARCHAR(96), + "TENDENCY" INTEGER, + "MEASURE_DATE" TIMESTAMP, + "PROJECT_ID" INTEGER, + "ALERT_STATUS" VARCHAR(5), + "ALERT_TEXT" VARCHAR(4000), + "URL" VARCHAR(2000), + "DESCRIPTION" VARCHAR(4000), + "RULE_PRIORITY" INTEGER, + "CHARACTERISTIC_ID" INTEGER, + "PERSON_ID" INTEGER, + "VARIATION_VALUE_1" DOUBLE, + "VARIATION_VALUE_2" DOUBLE, + "VARIATION_VALUE_3" DOUBLE, + "VARIATION_VALUE_4" DOUBLE, + "VARIATION_VALUE_5" DOUBLE +); + +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, + "ORIGIN" VARCHAR(3), + "WORST_VALUE" DOUBLE, + "BEST_VALUE" DOUBLE, + "OPTIMIZED_BEST_VALUE" BOOLEAN, + "HIDDEN" BOOLEAN, + "DELETE_HISTORICAL_DATA" BOOLEAN +);