From: Teryk Bellahsene Date: Wed, 22 Jun 2016 09:38:41 +0000 (+0200) Subject: SONAR-7789 Add and populate DB column RULES_PROFILES.LAST_USED X-Git-Tag: 6.0-RC1~259 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=655df791c25001f56578ef00643fd0b5ae935357;p=sonarqube.git SONAR-7789 Add and populate DB column RULES_PROFILES.LAST_USED --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportComputationSteps.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportComputationSteps.java index fa6c1a570bc..1d129631367 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportComputationSteps.java +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/ReportComputationSteps.java @@ -98,6 +98,7 @@ public class ReportComputationSteps extends AbstractComputationSteps { // Switch snapshot and purge SwitchSnapshotStep.class, + UpdateQualityProfilesLastUsedDateStep.class, IndexComponentsStep.class, PurgeDatastoresStep.class, ApplyPermissionsStep.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/computation/step/UpdateQualityProfilesLastUsedDateStep.java b/server/sonar-server/src/main/java/org/sonar/server/computation/step/UpdateQualityProfilesLastUsedDateStep.java new file mode 100644 index 00000000000..1f6a47b7ed2 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/computation/step/UpdateQualityProfilesLastUsedDateStep.java @@ -0,0 +1,97 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.computation.step; + +import com.google.common.base.Optional; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.qualityprofile.QualityProfileDto; +import org.sonar.server.computation.analysis.AnalysisMetadataHolder; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.TreeRootHolder; +import org.sonar.server.computation.measure.Measure; +import org.sonar.server.computation.measure.MeasureRepository; +import org.sonar.server.computation.metric.Metric; +import org.sonar.server.computation.metric.MetricRepository; +import org.sonar.server.computation.qualityprofile.QPMeasureData; +import org.sonar.server.computation.qualityprofile.QualityProfile; + +import static java.util.Collections.emptySet; + +public class UpdateQualityProfilesLastUsedDateStep implements ComputationStep { + + private final DbClient dbClient; + private final AnalysisMetadataHolder analysisMetadataHolder; + private final TreeRootHolder treeRootHolder; + private final MetricRepository metricRepository; + private final MeasureRepository measureRepository; + + public UpdateQualityProfilesLastUsedDateStep(DbClient dbClient, AnalysisMetadataHolder analysisMetadataHolder, TreeRootHolder treeRootHolder, MetricRepository metricRepository, + MeasureRepository measureRepository) { + this.dbClient = dbClient; + this.analysisMetadataHolder = analysisMetadataHolder; + this.treeRootHolder = treeRootHolder; + this.metricRepository = metricRepository; + this.measureRepository = measureRepository; + } + + @Override + public void execute() { + DbSession dbSession = dbClient.openSession(true); + try { + Component root = treeRootHolder.getRoot(); + Metric metric = metricRepository.getByKey(CoreMetrics.QUALITY_PROFILES_KEY); + Set qualityProfiles = parseQualityProfiles(measureRepository.getRawMeasure(root, metric)); + if (qualityProfiles.isEmpty()) { + return; + } + + List dtos = dbClient.qualityProfileDao().selectByKeys(dbSession, qualityProfiles.stream().map(QualityProfile::getQpKey).collect(Collectors.toList())); + long analysisDate = analysisMetadataHolder.getAnalysisDate(); + dtos.forEach(dto -> { + dto.setLastUsed(analysisDate); + dbClient.qualityProfileDao().update(dbSession, dto); + }); + + dbSession.commit(); + } finally { + dbClient.closeSession(dbSession); + } + } + + @Override + public String getDescription() { + return "Update quality profiles"; + } + + private static Set parseQualityProfiles(Optional measure) { + if (!measure.isPresent()) { + return emptySet(); + } + + String data = measure.get().getStringValue(); + return data == null ? emptySet() : QPMeasureData.fromJson(data).getProfiles(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/UpdateQualityProfilesLastUsedDateStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/UpdateQualityProfilesLastUsedDateStepTest.java new file mode 100644 index 00000000000..a3dcdca6d82 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/UpdateQualityProfilesLastUsedDateStepTest.java @@ -0,0 +1,133 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +package org.sonar.server.computation.step; + +import java.util.Arrays; +import java.util.Date; +import java.util.stream.Collectors; +import javax.annotation.CheckForNull; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.api.utils.System2; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.qualityprofile.QualityProfileDbTester; +import org.sonar.db.qualityprofile.QualityProfileDto; +import org.sonar.server.computation.analysis.AnalysisMetadataHolderRule; +import org.sonar.server.computation.batch.TreeRootHolderRule; +import org.sonar.server.computation.component.Component; +import org.sonar.server.computation.component.ReportComponent; +import org.sonar.server.computation.measure.Measure; +import org.sonar.server.computation.measure.MeasureRepositoryRule; +import org.sonar.server.computation.metric.Metric.MetricType; +import org.sonar.server.computation.metric.MetricImpl; +import org.sonar.server.computation.metric.MetricRepositoryRule; +import org.sonar.server.computation.qualityprofile.QPMeasureData; +import org.sonar.server.computation.qualityprofile.QualityProfile; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.api.measures.CoreMetrics.QUALITY_PROFILES_KEY; +import static org.sonar.db.qualityprofile.QualityProfileTesting.newQualityProfileDto; + +public class UpdateQualityProfilesLastUsedDateStepTest { + static final long ANALYSIS_DATE = 1_123_456_789L; + private static final Component PROJECT = ReportComponent.DUMB_PROJECT; + private QualityProfileDto sonarWayJava = newQualityProfileDto().setKey("sonar-way-java"); + private QualityProfileDto sonarWayPhp = newQualityProfileDto().setKey("sonar-way-php"); + private QualityProfileDto myQualityProfile = newQualityProfileDto().setKey("my-qp"); + + @Rule + public DbTester db = DbTester.create(System2.INSTANCE); + DbClient dbClient = db.getDbClient(); + DbSession dbSession = db.getSession(); + QualityProfileDbTester qualityProfileDb = new QualityProfileDbTester(db); + @Rule + public AnalysisMetadataHolderRule analysisMetadataHolder = new AnalysisMetadataHolderRule(); + @Rule + public TreeRootHolderRule treeRootHolder = new TreeRootHolderRule(); + @Rule + public MetricRepositoryRule metricRepository = new MetricRepositoryRule(); + @Rule + public MeasureRepositoryRule measureRepository = MeasureRepositoryRule.create(treeRootHolder, metricRepository); + + UpdateQualityProfilesLastUsedDateStep underTest; + + @Before + public void setUp() { + underTest = new UpdateQualityProfilesLastUsedDateStep(dbClient, analysisMetadataHolder, treeRootHolder, metricRepository, measureRepository); + analysisMetadataHolder.setAnalysisDate(ANALYSIS_DATE); + treeRootHolder.setRoot(PROJECT); + Metric metric = CoreMetrics.QUALITY_PROFILES; + metricRepository.add(new MetricImpl(1, metric.getKey(), metric.getName(), MetricType.STRING)); + + qualityProfileDb.insertQualityProfiles(sonarWayJava, sonarWayPhp, myQualityProfile); + } + + @Test + public void project_without_quality_profiles() { + underTest.execute(); + + assertQualityProfileIsTheSame(sonarWayJava); + assertQualityProfileIsTheSame(sonarWayPhp); + assertQualityProfileIsTheSame(myQualityProfile); + } + + @Test + public void analysis_quality_profiles_are_updated() { + measureRepository.addRawMeasure(1, QUALITY_PROFILES_KEY, Measure.newMeasureBuilder().create( + toJson(sonarWayJava.getKey(), myQualityProfile.getKey()))); + + underTest.execute(); + + assertQualityProfileIsTheSame(sonarWayPhp); + assertQualityProfileIsUpdated(sonarWayJava); + assertQualityProfileIsUpdated(myQualityProfile); + } + + @Test + public void description() { + assertThat(underTest.getDescription()).isEqualTo("Update quality profiles"); + } + + private void assertQualityProfileIsUpdated(QualityProfileDto qp) { + assertThat(selectLastUser(qp.getKey())).withFailMessage("Quality profile '%s' hasn't been updated. Value: %d", qp.getKey(), qp.getLastUsed()).isEqualTo(ANALYSIS_DATE); + } + + private void assertQualityProfileIsTheSame(QualityProfileDto qp) { + assertThat(selectLastUser(qp.getKey())).isEqualTo(qp.getLastUsed()); + } + + @CheckForNull + private Long selectLastUser(String qualityProfileKey) { + return dbClient.qualityProfileDao().selectByKey(dbSession, qualityProfileKey).getLastUsed(); + } + + private static String toJson(String... keys) { + return QPMeasureData.toJson(new QPMeasureData( + Arrays.stream(keys) + .map(key -> new QualityProfile(key, key, key, new Date())) + .collect(Collectors.toList()))); + } +} diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1246_add_last_used_column_to_rules_profiles.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1246_add_last_used_column_to_rules_profiles.rb new file mode 100644 index 00000000000..345bdd5d7e7 --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1246_add_last_used_column_to_rules_profiles.rb @@ -0,0 +1,28 @@ +# +# SonarQube, open source software quality management tool. +# Copyright (C) 2008-2014 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. +# +# +# SonarQube 6.0 +# SONAR-7789 +# +class AddLastUsedColumnToRulesProfiles < ActiveRecord::Migration + def self.up + execute_java_migration('org.sonar.db.version.v60.AddLastUsedColumnToRulesProfiles') + end +end diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1247_populate_last_used_of_rules_profiles.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1247_populate_last_used_of_rules_profiles.rb new file mode 100644 index 00000000000..b210393b83a --- /dev/null +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1247_populate_last_used_of_rules_profiles.rb @@ -0,0 +1,28 @@ +# +# SonarQube, open source software quality management tool. +# Copyright (C) 2008-2014 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. +# +# +# SonarQube 6.0 +# SONAR-7789 +# +class PopulateLastUsedOfRulesProfiles < ActiveRecord::Migration + def self.up + execute_java_migration('org.sonar.db.version.v60.PopulateLastUsedColumnOfRulesProfiles') + end +end diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java index b1d54d299e9..a88742ac859 100644 --- a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDao.java @@ -61,6 +61,10 @@ public class QualityProfileDao implements Dao { return dto; } + public List selectByKeys(DbSession session, List keys) { + return executeLargeInputs(keys, mapper(session)::selectByKeys); + } + public List selectAll(DbSession session) { return mapper(session).selectAll(); } diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDto.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDto.java index addb250f35e..944b3353c8a 100644 --- a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDto.java +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileDto.java @@ -33,6 +33,7 @@ public class QualityProfileDto extends Dto { private String language; private String parentKee; private String rulesUpdatedAt; + private Long lastUsed; private boolean isDefault; /** @@ -112,6 +113,16 @@ public class QualityProfileDto extends Dto { return this; } + @CheckForNull + public Long getLastUsed() { + return lastUsed; + } + + public QualityProfileDto setLastUsed(@Nullable Long lastUsed) { + this.lastUsed = lastUsed; + return this; + } + public boolean isDefault() { return isDefault; } diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java index b8a6ef79c09..50a67bc3ddf 100644 --- a/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/qualityprofile/QualityProfileMapper.java @@ -52,6 +52,8 @@ public interface QualityProfileMapper { List selectByLanguage(String language); + List selectByKeys(@Param("keys") List keys); + // INHERITANCE @CheckForNull diff --git a/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java b/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java index c5c58f99d32..9e699e2d1b9 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java +++ b/sonar-db/src/main/java/org/sonar/db/version/DatabaseVersion.java @@ -30,7 +30,7 @@ import org.sonar.db.MyBatis; public class DatabaseVersion { - public static final int LAST_VERSION = 1_245; + public static final int LAST_VERSION = 1_247; /** * The minimum supported version which can be upgraded. Lower @@ -90,8 +90,7 @@ public class DatabaseVersion { "user_roles", "user_tokens", "widgets", - "widget_properties" - ); + "widget_properties"); private MyBatis mybatis; public DatabaseVersion(MyBatis mybatis) { diff --git a/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java b/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java index 4f4d7cfef7b..df052f0228d 100644 --- a/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java +++ b/sonar-db/src/main/java/org/sonar/db/version/MigrationStepModule.java @@ -88,6 +88,7 @@ import org.sonar.db.version.v60.AddAnalysisUuidColumnToDuplicationsIndex; import org.sonar.db.version.v60.AddComponentUuidColumnToDuplicationsIndex; import org.sonar.db.version.v60.AddComponentUuidColumnToMeasures; import org.sonar.db.version.v60.AddComponentUuidColumnsToSnapshots; +import org.sonar.db.version.v60.AddLastUsedColumnToRulesProfiles; import org.sonar.db.version.v60.AddUuidColumnToSnapshots; import org.sonar.db.version.v60.AddUuidColumnsToProjects; import org.sonar.db.version.v60.AddUuidColumnsToResourceIndex; @@ -117,6 +118,7 @@ import org.sonar.db.version.v60.PopulateAnalysisUuidOfDuplicationsIndex; import org.sonar.db.version.v60.PopulateComponentUuidColumnsOfSnapshots; import org.sonar.db.version.v60.PopulateComponentUuidOfDuplicationsIndex; import org.sonar.db.version.v60.PopulateComponentUuidOfMeasures; +import org.sonar.db.version.v60.PopulateLastUsedColumnOfRulesProfiles; import org.sonar.db.version.v60.PopulateUuidColumnOnSnapshots; import org.sonar.db.version.v60.PopulateUuidColumnsOfProjects; import org.sonar.db.version.v60.PopulateUuidColumnsOfResourceIndex; @@ -227,6 +229,8 @@ public class MigrationStepModule extends Module { CleanOrphanRowsInProjects.class, MakeUuidColumnsNotNullOnProjects.class, DropIdColumnsFromProjects.class, + AddLastUsedColumnToRulesProfiles.class, + PopulateLastUsedColumnOfRulesProfiles.class, // SNAPSHOTS.UUID AddUuidColumnToSnapshots.class, diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/AddLastUsedColumnToRulesProfiles.java b/sonar-db/src/main/java/org/sonar/db/version/v60/AddLastUsedColumnToRulesProfiles.java new file mode 100644 index 00000000000..bcdcfe4cf2a --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v60/AddLastUsedColumnToRulesProfiles.java @@ -0,0 +1,45 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.version.v60; + +import java.sql.SQLException; +import org.sonar.db.Database; +import org.sonar.db.version.AddColumnsBuilder; +import org.sonar.db.version.DdlChange; + +import static org.sonar.db.version.BigDecimalColumnDef.newBigDecimalColumnDefBuilder; + +public class AddLastUsedColumnToRulesProfiles extends DdlChange { + + private static final String TABLE_QUALITY_PROFILES = "rules_profiles"; + + public AddLastUsedColumnToRulesProfiles(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + context.execute(new AddColumnsBuilder(getDatabase().getDialect(), TABLE_QUALITY_PROFILES) + .addColumn(newBigDecimalColumnDefBuilder().setColumnName("last_used").setIsNullable(true).build()) + .build()); + } + +} diff --git a/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateLastUsedColumnOfRulesProfiles.java b/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateLastUsedColumnOfRulesProfiles.java new file mode 100644 index 00000000000..66f98d233f7 --- /dev/null +++ b/sonar-db/src/main/java/org/sonar/db/version/v60/PopulateLastUsedColumnOfRulesProfiles.java @@ -0,0 +1,91 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact 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.version.v60; + +import java.sql.SQLException; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.sonar.db.Database; +import org.sonar.db.version.BaseDataChange; +import org.sonar.db.version.MassUpdate; +import org.sonar.db.version.Select; +import org.sonar.db.version.SqlStatement; + +public class PopulateLastUsedColumnOfRulesProfiles extends BaseDataChange { + + private static final Pattern PATTERN_QP_KEY = Pattern.compile("\"key\"\\s*:\\s*\"(.*?)\""); + + public PopulateLastUsedColumnOfRulesProfiles(Database db) { + super(db); + } + + @Override + public void execute(Context context) throws SQLException { + Map lastAnalysisDatesByQualityProfileKey = buildQualityProfilesMap(context); + if (lastAnalysisDatesByQualityProfileKey.isEmpty()) { + return; + } + + populateLastUsedColumn(context, lastAnalysisDatesByQualityProfileKey); + } + + private static Map buildQualityProfilesMap(Context context) throws SQLException { + Map lastAnalysisDatesByQPKeys = new HashMap<>(); + + context.prepareSelect("select s.created_at, pm.text_value " + + "from project_measures pm " + + " inner join snapshots s on pm.snapshot_id = s.id " + + " inner join metrics m on pm.metric_id=m.id " + + "where s.islast=? " + + " and m.name='quality_profiles' " + + "order by s.created_at ") + .setBoolean(1, true) + .scroll(row -> { + long analysisDate = row.getLong(1); + String json = row.getString(2); + Matcher matcher = PATTERN_QP_KEY.matcher(json); + while (matcher.find()) { + lastAnalysisDatesByQPKeys.put(matcher.group(1), analysisDate); + } + }); + return lastAnalysisDatesByQPKeys; + } + + private static void populateLastUsedColumn(Context context, Map lastAnalysisDatesByQualityProfileKey) throws SQLException { + MassUpdate massUpdate = context.prepareMassUpdate(); + massUpdate.select("select id, kee from rules_profiles where last_used is null"); + massUpdate.update("update rules_profiles set last_used=? where id=?"); + massUpdate.rowPluralName("rules_profiles"); + massUpdate.execute((row, update) -> handle(lastAnalysisDatesByQualityProfileKey, row, update)); + } + + private static boolean handle(Map lastAnalysisDatesByQualityProfileKey, Select.Row row, SqlStatement update) throws SQLException { + int qualityProfileId = row.getInt(1); + String qualityProfileKey = row.getString(2); + + update.setLong(1, lastAnalysisDatesByQualityProfileKey.get(qualityProfileKey)); + update.setInt(2, qualityProfileId); + + return true; + } +} diff --git a/sonar-db/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml b/sonar-db/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml index edc2563f8e2..e33f92db1d2 100644 --- a/sonar-db/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/qualityprofile/QualityProfileMapper.xml @@ -12,22 +12,25 @@ p.is_default as isDefault, p.created_at as createdAt, p.updated_at as updatedAt, - p.rules_updated_at as rulesUpdatedAt + p.rules_updated_at as rulesUpdatedAt, + p.last_used as lastUsed - INSERT INTO rules_profiles (kee, parent_kee, name, language, is_default, created_at, updated_at, rules_updated_at) - VALUES (#{kee}, #{parentKee}, #{name}, #{language}, #{isDefault}, #{createdAt}, #{updatedAt}, #{rulesUpdatedAt,}) + INSERT INTO rules_profiles (kee, parent_kee, name, language, is_default, created_at, updated_at, rules_updated_at, last_used) + VALUES (#{kee, jdbcType=VARCHAR}, #{parentKee,jdbcType=VARCHAR}, #{name, jdbcType=VARCHAR}, #{language, jdbcType=VARCHAR}, #{isDefault, jdbcType=BOOLEAN}, + #{createdAt, jdbcType=TIMESTAMP}, #{updatedAt, jdbcType=TIMESTAMP}, #{rulesUpdatedAt, jdbcType=VARCHAR}, #{lastUsed, jdbcType=BIGINT}) UPDATE rules_profiles SET - name=#{name}, - language=#{language}, - is_default=#{isDefault}, - parent_kee=#{parentKee}, - updated_at=#{updatedAt}, - rules_updated_at=#{rulesUpdatedAt} + name=#{name, jdbcType=VARCHAR}, + language=#{language, jdbcType=VARCHAR}, + is_default=#{isDefault, jdbcType=BOOLEAN}, + parent_kee=#{parentKee, jdbcType=VARCHAR}, + updated_at=#{updatedAt, jdbcType=TIMESTAMP}, + rules_updated_at=#{rulesUpdatedAt, jdbcType=VARCHAR}, + last_used=#{lastUsed, jdbcType=BIGINT} WHERE id=#{id} @@ -69,6 +72,16 @@ WHERE p.kee=#{id} + +