import org.sonar.server.platform.TempFolderProvider;
import org.sonar.server.qualityprofile.db.ActiveRuleDao;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
+import org.sonar.server.qualityprofile.index.ActiveRuleIndex2;
import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
import org.sonar.server.ruby.PlatformRackBridge;
import org.sonar.server.rule.db.RuleDao;
// rules/qprofiles
RuleIndex2.class,
+ ActiveRuleIndex2.class,
RuleNormalizer.class,
ActiveRuleNormalizer.class,
RuleIndex.class,
import org.sonar.server.qualityprofile.QProfiles;
import org.sonar.server.qualityprofile.RuleActivator;
import org.sonar.server.qualityprofile.RuleActivatorContextFactory;
+import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import org.sonar.server.qualityprofile.ws.BackupAction;
import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions;
import org.sonar.server.qualityprofile.ws.ChangeParentAction;
UpdateCenterWs.class,
// quality profile
+ ActiveRuleIndexer.class,
XMLProfileParser.class,
XMLProfileSerializer.class,
AnnotationProfileParser.class,
DoPrivileged.execute(new DoPrivileged.Task(getComponentByType(ThreadLocalUserSession.class)) {
@Override
protected void doPrivileged() {
- getComponentByType(IndexSynchronizer.class).executeDeprecated();
PlatformLevelStartup.super.start();
getComponentByType(IndexSynchronizer.class).execute();
getComponentByType(ServerLifecycleNotifier.class).notifyStart();
package org.sonar.server.qualityprofile;
import com.google.common.collect.ImmutableList;
-import org.sonar.db.qualityprofile.ActiveRuleKey;
-
-import javax.annotation.CheckForNull;
import java.util.Date;
import java.util.List;
import java.util.Map;
+import javax.annotation.CheckForNull;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
public interface ActiveRule {
- public enum Inheritance {
+ enum Inheritance {
NONE, OVERRIDES, INHERITED;
public static final List<Inheritance> ALL = ImmutableList.of(NONE, OVERRIDES, INHERITED);
}
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
-import org.sonar.api.server.ServerSide;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.CheckForNull;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.server.ServerSide;
+import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.ActiveRuleKey;
import org.sonar.db.qualityprofile.QualityProfileDto;
-import org.sonar.db.DbClient;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.rule.index.RuleQuery;
import org.sonar.server.search.FacetValue;
import org.sonar.server.search.IndexClient;
import org.sonar.server.search.QueryContext;
-
-import javax.annotation.CheckForNull;
-
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
import org.sonar.server.user.UserSession;
@ServerSide
return index.get(ActiveRuleIndex.class).findByProfile(key);
}
- public long countActiveRulesByProfile(String key) {
- return index.get(ActiveRuleIndex.class).countByQualityProfileKey(key);
- }
-
public Map<String, Long> countAllActiveRules() {
Map<String, Long> counts = new HashMap<>();
for (Map.Entry<String, Long> entry : index.get(ActiveRuleIndex.class).countAllByQualityProfileKey().entrySet()) {
return counts;
}
- public Multimap<String, FacetValue> getStatsByProfile(String key) {
- return index.get(ActiveRuleIndex.class).getStatsByProfileKey(key);
- }
-
public Map<String, Multimap<String, FacetValue>> getAllProfileStats() {
List<String> keys = Lists.newArrayList();
for (QualityProfileDto profile : this.findAll()) {
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Preconditions;
+import java.util.List;
+import javax.annotation.CheckForNull;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.CheckForNull;
import static java.util.Collections.emptyList;
+@Deprecated
public class ActiveRuleDao extends BaseDao<ActiveRuleMapper, ActiveRuleDto, ActiveRuleKey> {
private static final String QUALITY_PROFILE_IS_NOT_PERSISTED = "Quality profile is not persisted (missing id)";
package org.sonar.server.qualityprofile.index;
import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import java.util.Collections;
+import java.util.Date;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.db.qualityprofile.ActiveRuleKey;
import org.sonar.server.qualityprofile.ActiveRule;
import org.sonar.server.search.BaseDoc;
import org.sonar.server.search.IndexUtils;
-import javax.annotation.CheckForNull;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_CREATED_AT;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_KEY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PARENT_KEY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_REPOSITORY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_RULE_KEY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_UPDATED_AT;
public class ActiveRuleDoc extends BaseDoc implements ActiveRule {
public ActiveRuleDoc(Map<String, Object> fields) {
super(fields);
- this.key = ActiveRuleKey.parse((String) getField(ActiveRuleNormalizer.ActiveRuleField.KEY.field()));
- Preconditions.checkArgument(key!=null, "Invalid ActiveRuleKey!");
+ this.key = ActiveRuleKey.parse((String) getField(FIELD_ACTIVE_RULE_KEY));
+ Preconditions.checkArgument(key != null, "ActiveRuleKey cannot be null");
}
- @Override
- public Date createdAt() {
- return IndexUtils.parseDateTime((String) getNullableField(ActiveRuleNormalizer.ActiveRuleField.CREATED_AT.field()));
- }
-
- @Override
- public Date updatedAt() {
- return IndexUtils.parseDateTime((String) getNullableField(ActiveRuleNormalizer.ActiveRuleField.UPDATED_AT.field()));
+ public ActiveRuleDoc(ActiveRuleKey key) {
+ super(Maps.<String, Object>newHashMapWithExpectedSize(8));
+ Preconditions.checkNotNull(key, "ActiveRuleKey cannot be null");
+ this.key = key;
+ setField(FIELD_ACTIVE_RULE_KEY, key.toString());
+ setField(FIELD_ACTIVE_RULE_PROFILE_KEY, key.qProfile());
+ setField(FIELD_ACTIVE_RULE_RULE_KEY, key.ruleKey().toString());
+ setField(FIELD_ACTIVE_RULE_REPOSITORY, key.ruleKey().repository());
}
@Override
public ActiveRuleKey key() {
- return this.key;
+ return key;
}
@Override
public String severity() {
- return (String) getNullableField(ActiveRuleNormalizer.ActiveRuleField.SEVERITY.field());
+ return (String) getNullableField(FIELD_ACTIVE_RULE_SEVERITY);
+ }
+
+ public ActiveRuleDoc setSeverity(@Nullable String s) {
+ setField(FIELD_ACTIVE_RULE_SEVERITY, s);
+ return this;
}
@Override
public ActiveRule.Inheritance inheritance() {
- String inheritance = getNullableField(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field());
+ String inheritance = getNullableField(FIELD_ACTIVE_RULE_INHERITANCE);
if (inheritance == null || inheritance.isEmpty() ||
inheritance.toLowerCase().contains("none")) {
return Inheritance.NONE;
}
}
+ public ActiveRuleDoc setInheritance(@Nullable String s) {
+ setField(FIELD_ACTIVE_RULE_INHERITANCE, s);
+ return this;
+ }
+
@Override
@CheckForNull
public ActiveRuleKey parentKey() {
- String data = getNullableField(ActiveRuleNormalizer.ActiveRuleField.PARENT_KEY.field());
+ String data = getNullableField(FIELD_ACTIVE_RULE_PARENT_KEY);
if (data != null && !data.isEmpty()) {
return ActiveRuleKey.parse(data);
}
return null;
}
+ public ActiveRuleDoc setParentKey(@Nullable String s) {
+ setField(FIELD_ACTIVE_RULE_PARENT_KEY, s);
+ return this;
+ }
+
@Override
+ @Deprecated
public Map<String, String> params() {
- Map<String, String> params = new HashMap<>();
- List<Map<String, String>> allParams = getNullableField(ActiveRuleNormalizer.ActiveRuleField.PARAMS.field());
- if (allParams != null) {
- for (Map<String, String> param : allParams) {
- params.put(param.get(ActiveRuleNormalizer.ActiveRuleParamField.NAME.field()),
- param.get(ActiveRuleNormalizer.ActiveRuleParamField.VALUE.field()));
- }
- }
- return params;
+ return Collections.emptyMap();
+ }
+
+ @Override
+ @Deprecated
+ public Date createdAt() {
+ return IndexUtils.parseDateTime((String) getNullableField(FIELD_ACTIVE_RULE_CREATED_AT));
+ }
+
+ @CheckForNull
+ public Long createdAtAsLong() {
+ return (Long) getField(FIELD_ACTIVE_RULE_CREATED_AT);
+ }
+
+ public ActiveRuleDoc setCreatedAt(@Nullable Long l) {
+ setField(FIELD_ACTIVE_RULE_CREATED_AT, l);
+ return this;
+ }
+
+ @Override
+ @Deprecated
+ public Date updatedAt() {
+ return IndexUtils.parseDateTime((String) getNullableField(FIELD_ACTIVE_RULE_UPDATED_AT));
+ }
+
+ @CheckForNull
+ public Long updatedAtAsLong() {
+ return (Long) getField(FIELD_ACTIVE_RULE_UPDATED_AT);
+ }
+
+ public ActiveRuleDoc setUpdatedAt(@Nullable Long l) {
+ setField(FIELD_ACTIVE_RULE_UPDATED_AT, l);
+ return this;
}
}
*/
package org.sonar.server.qualityprofile.index;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multimap;
import java.util.ArrayList;
import java.util.HashMap;
import org.sonar.server.search.IndexField;
import org.sonar.server.search.SearchClient;
+@Deprecated
public class ActiveRuleIndex extends BaseIndex<ActiveRule, ActiveRuleDto, ActiveRuleKey> {
public static final String COUNT_ACTIVE_RULES = "countActiveRules";
.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), FilterBuilders.boolFilter()
.must(FilterBuilders.termFilter(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field(), key))
.mustNot(FilterBuilders.hasParentFilter(this.getParentType(),
- FilterBuilders.termFilter(RuleIndexDefinition.FIELD_STATUS, RuleStatus.REMOVED.name())))))
+ FilterBuilders.termFilter(RuleIndexDefinition.FIELD_RULE_STATUS, RuleStatus.REMOVED.name())))))
.setRouting(key);
SearchResponse response = request.get();
return countByField(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY,
FilterBuilders.hasParentFilter(IndexDefinition.RULE.getIndexType(),
FilterBuilders.notFilter(
- FilterBuilders.termFilter(RuleIndexDefinition.FIELD_STATUS, "REMOVED")))).get(key);
+ FilterBuilders.termFilter(RuleIndexDefinition.FIELD_RULE_STATUS, "REMOVED")))).get(key);
}
public Map<String, Long> countAllByQualityProfileKey() {
return countByField(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY,
FilterBuilders.hasParentFilter(IndexDefinition.RULE.getIndexType(),
FilterBuilders.notFilter(
- FilterBuilders.termFilter(RuleIndexDefinition.FIELD_STATUS, "REMOVED"))));
- }
-
- public Multimap<String, FacetValue> getStatsByProfileKey(String key) {
- return getStatsByProfileKeys(ImmutableList.of(key)).get(key);
+ FilterBuilders.termFilter(RuleIndexDefinition.FIELD_RULE_STATUS, "REMOVED"))));
}
public Map<String, Multimap<String, FacetValue>> getStatsByProfileKeys(List<String> keys) {
QueryBuilders.termsQuery(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field(), keys),
FilterBuilders.boolFilter()
.mustNot(FilterBuilders.hasParentFilter(this.getParentType(),
- FilterBuilders.termFilter(RuleIndexDefinition.FIELD_STATUS, RuleStatus.REMOVED.name())))))
+ FilterBuilders.termFilter(RuleIndexDefinition.FIELD_RULE_STATUS, RuleStatus.REMOVED.name())))))
.addAggregation(AggregationBuilders.terms(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field())
.field(ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field()).size(0)
.subAggregation(AggregationBuilders.terms(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field())
--- /dev/null
+/*
+ * 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.qualityprofile.index;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nonnull;
+import org.elasticsearch.action.get.GetRequestBuilder;
+import org.elasticsearch.action.get.GetResponse;
+import org.elasticsearch.action.search.SearchRequestBuilder;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.action.search.SearchType;
+import org.elasticsearch.common.unit.TimeValue;
+import org.elasticsearch.index.query.FilterBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.search.SearchHit;
+import org.elasticsearch.search.aggregations.Aggregation;
+import org.elasticsearch.search.aggregations.AggregationBuilders;
+import org.elasticsearch.search.aggregations.Aggregations;
+import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
+import org.elasticsearch.search.aggregations.bucket.terms.Terms;
+import org.elasticsearch.search.aggregations.metrics.valuecount.InternalValueCount;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.server.es.BaseIndex;
+import org.sonar.server.es.EsClient;
+import org.sonar.server.qualityprofile.ActiveRule;
+import org.sonar.server.rule.index.RuleIndexDefinition;
+import org.sonar.server.search.FacetValue;
+
+import static org.sonar.server.es.EsUtils.SCROLL_TIME_IN_MINUTES;
+import static org.sonar.server.es.EsUtils.scroll;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY;
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_RULE_STATUS;
+import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX;
+import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_ACTIVE_RULE;
+import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_RULE;
+
+/**
+ * The unique entry-point to interact with Elasticsearch index "active rules".
+ * All the requests are listed here.
+ */
+public class ActiveRuleIndex2 extends BaseIndex {
+
+ public static final String COUNT_ACTIVE_RULES = "countActiveRules";
+
+ public ActiveRuleIndex2(EsClient client) {
+ super(client);
+ }
+
+ /**
+ * @deprecated since 5.5, use {@link org.sonar.db.qualityprofile.ActiveRuleDao instead}
+ */
+ @Deprecated
+ @CheckForNull
+ public ActiveRule getNullableByKey(ActiveRuleKey key) {
+ GetRequestBuilder request = getClient().prepareGet()
+ .setIndex(RuleIndexDefinition.INDEX)
+ .setType(RuleIndexDefinition.TYPE_ACTIVE_RULE)
+ .setId(key.toString())
+ .setFetchSource(true)
+ .setRouting(key.ruleKey().repository());
+
+ GetResponse response = request.get();
+ if (response.isExists()) {
+ return new ActiveRuleDoc(response.getSource());
+ }
+ return null;
+ }
+
+ /**
+ * @deprecated since 5.5, use {@link org.sonar.db.qualityprofile.ActiveRuleDao instead}
+ */
+ @Deprecated
+ public List<ActiveRule> findByRule(RuleKey key) {
+ SearchRequestBuilder request = getClient().prepareSearch(RuleIndexDefinition.INDEX)
+ .setQuery(QueryBuilders
+ .hasParentQuery(RuleIndexDefinition.TYPE_RULE,
+ QueryBuilders.idsQuery(RuleIndexDefinition.TYPE_RULE)
+ .addIds(key.toString())
+ ))
+ .setRouting(key.repository())
+ .setSize(Integer.MAX_VALUE);
+
+ SearchResponse response = request.get();
+
+ List<ActiveRule> activeRules = new ArrayList<>();
+ for (SearchHit hit : response.getHits()) {
+ activeRules.add(new ActiveRuleDoc(hit.getSource()));
+ }
+ return activeRules;
+ }
+
+ /**
+ * @deprecated since 5.5, use {@link org.sonar.db.qualityprofile.ActiveRuleDao instead}
+ */
+ @Deprecated
+ public Iterator<ActiveRuleDoc> findByProfile(String key) {
+ SearchRequestBuilder request = getClient().prepareSearch(RuleIndexDefinition.INDEX)
+ .setTypes(RuleIndexDefinition.TYPE_ACTIVE_RULE)
+ .setSearchType(SearchType.SCAN)
+ .setScroll(TimeValue.timeValueMinutes(SCROLL_TIME_IN_MINUTES))
+ .setSize(100)
+ .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), FilterBuilders.boolFilter()
+ .must(FilterBuilders.termFilter(RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY, key))
+ .mustNot(FilterBuilders.hasParentFilter(RuleIndexDefinition.TYPE_RULE,
+ FilterBuilders.termFilter(RuleIndexDefinition.FIELD_RULE_STATUS, RuleStatus.REMOVED.name())))));
+
+ SearchResponse response = request.get();
+ return scroll(getClient(), response.getScrollId(), ToDoc.INSTANCE);
+ }
+
+ public Map<String, Long> countAllByQualityProfileKey() {
+ return countByField(FIELD_ACTIVE_RULE_PROFILE_KEY,
+ FilterBuilders.hasParentFilter(TYPE_RULE,
+ FilterBuilders.notFilter(
+ FilterBuilders.termFilter(FIELD_RULE_STATUS, "REMOVED"))));
+ }
+
+ private Map<String, Long> countByField(String indexField, FilterBuilder filter) {
+ Map<String, Long> counts = new HashMap<>();
+
+ SearchRequestBuilder request = getClient().prepareSearch(INDEX)
+ .setTypes(TYPE_ACTIVE_RULE)
+ .setQuery(QueryBuilders.filteredQuery(
+ QueryBuilders.matchAllQuery(),
+ filter))
+ .setSize(0)
+ .addAggregation(AggregationBuilders
+ .terms(indexField)
+ .field(indexField)
+ .order(Terms.Order.count(false))
+ .size(Integer.MAX_VALUE)
+ .minDocCount(0));
+
+ SearchResponse response = request.get();
+
+ Terms values =
+ response.getAggregations().get(indexField);
+
+ for (Terms.Bucket value : values.getBuckets()) {
+ counts.put(value.getKey(), value.getDocCount());
+ }
+ return counts;
+ }
+
+ public Map<String, Multimap<String, FacetValue>> getStatsByProfileKeys(List<String> keys) {
+ SearchRequestBuilder request = getClient().prepareSearch(INDEX)
+ .setQuery(QueryBuilders.filteredQuery(
+ QueryBuilders.termsQuery(FIELD_ACTIVE_RULE_PROFILE_KEY, keys),
+ FilterBuilders.boolFilter()
+ .mustNot(FilterBuilders.hasParentFilter(TYPE_RULE,
+ FilterBuilders.termFilter(FIELD_RULE_STATUS, RuleStatus.REMOVED.name())))))
+ .addAggregation(AggregationBuilders.terms(FIELD_ACTIVE_RULE_PROFILE_KEY)
+ .field(RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY).size(0)
+ .subAggregation(AggregationBuilders.terms(FIELD_ACTIVE_RULE_INHERITANCE)
+ .field(RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE))
+ .subAggregation(AggregationBuilders.terms(FIELD_ACTIVE_RULE_SEVERITY)
+ .field(RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY))
+ .subAggregation(AggregationBuilders.count(COUNT_ACTIVE_RULES)))
+ .setSize(0)
+ .setTypes(TYPE_ACTIVE_RULE);
+ SearchResponse response = request.get();
+ Map<String, Multimap<String, FacetValue>> stats = new HashMap<>();
+ Aggregation aggregation = response.getAggregations().get(FIELD_ACTIVE_RULE_PROFILE_KEY);
+ for (Terms.Bucket value : ((Terms) aggregation).getBuckets()) {
+ stats.put(value.getKey(), processAggregations(value.getAggregations()));
+ }
+
+ return stats;
+ }
+
+ private Multimap<String, FacetValue> processAggregations(Aggregations aggregations) {
+ Multimap<String, FacetValue> stats = ArrayListMultimap.create();
+ if (aggregations != null) {
+ for (Aggregation aggregation : aggregations.asList()) {
+ if (aggregation instanceof StringTerms) {
+ for (Terms.Bucket value : ((Terms) aggregation).getBuckets()) {
+ FacetValue facetValue = new FacetValue(value.getKey(), value.getDocCount());
+ stats.put(aggregation.getName(), facetValue);
+ }
+ } else if (aggregation instanceof InternalValueCount) {
+ InternalValueCount count = (InternalValueCount) aggregation;
+ FacetValue facetValue = new FacetValue(count.getName(), count.getValue());
+ stats.put(count.getName(), facetValue);
+ }
+ }
+ }
+ return stats;
+ }
+
+ private enum ToDoc implements Function<Map<String, Object>, ActiveRuleDoc> {
+ INSTANCE;
+
+ @Override
+ public ActiveRuleDoc apply(@Nonnull Map<String, Object> input) {
+ return new ActiveRuleDoc(input);
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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.qualityprofile.index;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import java.util.Iterator;
+import java.util.List;
+import javax.annotation.Nonnull;
+import org.elasticsearch.action.index.IndexRequest;
+import org.elasticsearch.action.search.SearchRequestBuilder;
+import org.elasticsearch.index.query.FilterBuilders;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.server.es.BaseIndexer;
+import org.sonar.server.es.BulkIndexer;
+import org.sonar.server.es.EsClient;
+import org.sonar.server.qualityprofile.ActiveRuleChange;
+import org.sonar.server.rule.index.RuleIndexDefinition;
+
+import static org.sonar.server.rule.index.RuleIndexDefinition.FIELD_ACTIVE_RULE_UPDATED_AT;
+import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX;
+import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_ACTIVE_RULE;
+
+public class ActiveRuleIndexer extends BaseIndexer {
+
+ private final DbClient dbClient;
+
+ public ActiveRuleIndexer(DbClient dbClient, EsClient esClient) {
+ super(esClient, 300, INDEX, TYPE_ACTIVE_RULE, FIELD_ACTIVE_RULE_UPDATED_AT);
+ this.dbClient = dbClient;
+ }
+
+ @Override
+ protected long doIndex(long lastUpdatedAt) {
+ return doIndex(createBulkIndexer(false), lastUpdatedAt);
+ }
+
+ public void index(Iterator<ActiveRuleDoc> rules) {
+ doIndex(createBulkIndexer(false), rules);
+ }
+
+ private long doIndex(BulkIndexer bulk, long lastUpdatedAt) {
+ DbSession dbSession = dbClient.openSession(false);
+ long maxDate;
+ try {
+ ActiveRuleResultSetIterator rowIt = ActiveRuleResultSetIterator.create(dbClient, dbSession, lastUpdatedAt);
+ maxDate = doIndex(bulk, rowIt);
+ rowIt.close();
+ return maxDate;
+ } finally {
+ dbSession.close();
+ }
+ }
+
+ private long doIndex(BulkIndexer bulk, Iterator<ActiveRuleDoc> activeRules) {
+ bulk.start();
+ long maxDate = 0L;
+ while (activeRules.hasNext()) {
+ ActiveRuleDoc activeRule = activeRules.next();
+ bulk.add(newIndexRequest(activeRule));
+
+ // it's more efficient to sort programmatically than in SQL on some databases (MySQL for instance)
+ maxDate = Math.max(maxDate, activeRule.updatedAtAsLong());
+ }
+ bulk.stop();
+ return maxDate;
+ }
+
+ public void index(List<ActiveRuleChange> changes) {
+ deleteKeys(FluentIterable.from(changes)
+ .filter(MatchDeactivatedRule.INSTANCE)
+ .transform(ActiveRuleChangeToKey.INSTANCE)
+ .toList());
+ index();
+ }
+
+ public void deleteProfile(String qualityProfileKey) {
+ BulkIndexer bulk = new BulkIndexer(esClient, INDEX);
+ bulk.start();
+ SearchRequestBuilder search = esClient.prepareSearch(INDEX)
+ .setTypes(TYPE_ACTIVE_RULE)
+ .setQuery(QueryBuilders.filteredQuery(
+ QueryBuilders.matchAllQuery(),
+ FilterBuilders.boolFilter().must(FilterBuilders.termsFilter(RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY, qualityProfileKey))
+ ));
+ bulk.addDeletion(search);
+ bulk.stop();
+ }
+
+ private void deleteKeys(List<ActiveRuleKey> keys) {
+ BulkIndexer bulk = new BulkIndexer(esClient, INDEX);
+ bulk.start();
+ SearchRequestBuilder search = esClient.prepareSearch(INDEX)
+ .setTypes(TYPE_ACTIVE_RULE)
+ .setQuery(QueryBuilders.filteredQuery(
+ QueryBuilders.matchAllQuery(),
+ FilterBuilders.boolFilter().must(FilterBuilders.termsFilter(RuleIndexDefinition.FIELD_ACTIVE_RULE_KEY, keys))
+ ));
+ bulk.addDeletion(search);
+ bulk.stop();
+ }
+
+ private BulkIndexer createBulkIndexer(boolean large) {
+ BulkIndexer bulk = new BulkIndexer(esClient, INDEX);
+ bulk.setLarge(large);
+ return bulk;
+ }
+
+ private IndexRequest newIndexRequest(ActiveRuleDoc doc) {
+ return new IndexRequest(INDEX, TYPE_ACTIVE_RULE, doc.key().toString())
+ .parent(doc.key().ruleKey().toString())
+ .routing(doc.key().ruleKey().repository())
+ .source(doc.getFields());
+ }
+
+ private enum MatchDeactivatedRule implements Predicate<ActiveRuleChange> {
+ INSTANCE;
+
+ @Override
+ public boolean apply(@Nonnull ActiveRuleChange input) {
+ return input.getType().equals(ActiveRuleChange.Type.DEACTIVATED);
+ }
+ }
+
+ private enum ActiveRuleChangeToKey implements Function<ActiveRuleChange, ActiveRuleKey> {
+ INSTANCE;
+
+ @Override
+ public ActiveRuleKey apply(@Nonnull ActiveRuleChange input) {
+ return input.getKey();
+ }
+ }
+
+}
/* Creating updateRequest */
requests.add(new UpdateRequest()
+ .id(key.toString())
.routing(key.ruleKey().toString())
- .id(activeRuleDto.getKey().toString())
- .parent(activeRuleDto.getKey().ruleKey().toString())
+ .parent(key.ruleKey().toString())
.doc(newRule)
.upsert(getUpsertFor(ActiveRuleField.ALL_FIELDS, newRule)));
--- /dev/null
+/*
+ * 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.qualityprofile.index;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.ResultSetIterator;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.db.rule.SeverityUtil;
+import org.sonar.server.qualityprofile.ActiveRule;
+
+/**
+ * Scrolls over table ACTIVE_RULES and reads documents to populate the active rules index
+ */
+public class ActiveRuleResultSetIterator extends ResultSetIterator<ActiveRuleDoc> {
+
+ private static final String[] FIELDS = {
+ // column 1
+ "a.failure_level",
+ "a.inheritance",
+ "r.plugin_rule_key",
+ "r.plugin_name",
+ "qp.kee",
+ "profile_parent.kee",
+ "a.created_at_ms",
+ "a.updated_at_ms"
+ };
+
+ private static final String SQL_ALL = "SELECT " + StringUtils.join(FIELDS, ",") + " FROM active_rules a " +
+ "INNER JOIN rules_profiles qp ON qp.id=a.profile_id " +
+ "INNER JOIN rules r ON r.id = a.rule_id " +
+ "LEFT JOIN rules_profiles profile_parent ON profile_parent.kee=qp.parent_kee ";
+
+ private static final String SQL_AFTER_DATE = SQL_ALL + " WHERE a.updated_at_ms>?";
+
+ private ActiveRuleResultSetIterator(PreparedStatement stmt) throws SQLException {
+ super(stmt);
+ }
+
+ static ActiveRuleResultSetIterator create(DbClient dbClient, DbSession session, long afterDate) {
+ try {
+ String sql = afterDate > 0L ? SQL_AFTER_DATE : SQL_ALL;
+ PreparedStatement stmt = dbClient.getMyBatis().newScrollingSelectStatement(session, sql);
+ if (afterDate > 0L) {
+ stmt.setLong(1, afterDate);
+ }
+ return new ActiveRuleResultSetIterator(stmt);
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to prepare SQL request to select all active rules", e);
+ }
+ }
+
+ @Override
+ protected ActiveRuleDoc read(ResultSet rs) throws SQLException {
+ RuleKey ruleKey = RuleKey.of(rs.getString(4), rs.getString(3));
+ ActiveRuleKey activeRuleKey = ActiveRuleKey.of(rs.getString(5), ruleKey);
+
+ ActiveRuleDoc doc = new ActiveRuleDoc(activeRuleKey);
+
+ // all the fields must be present, even if value is null
+ doc.setSeverity(SeverityUtil.getSeverityFromOrdinal(rs.getInt(1)));
+
+ String inheritance = rs.getString(2);
+ if (inheritance != null) {
+ doc.setInheritance(inheritance);
+ } else {
+ doc.setInheritance(ActiveRule.Inheritance.NONE.name());
+ }
+
+ String parentProfileKey = rs.getString(6);
+ if (parentProfileKey != null) {
+ doc.setParentKey(ActiveRuleKey.of(parentProfileKey, ruleKey).toString());
+ } else {
+ doc.setParentKey(null);
+ }
+
+ doc.setCreatedAt(rs.getLong(7));
+ doc.setUpdatedAt(rs.getLong(8));
+
+ return doc;
+ }
+
+}
package org.sonar.server.qualityprofile.ws;
import com.google.common.collect.Multimap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
import org.sonar.api.resources.Languages;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService.NewAction;
import org.sonar.api.server.ws.WebService.NewController;
import org.sonar.api.utils.text.JsonWriter;
+import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.QualityProfileDto;
-import org.sonar.db.DbClient;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.qualityprofile.QProfile;
import org.sonar.server.qualityprofile.QProfileFactory;
import org.sonar.server.qualityprofile.QProfileLoader;
import org.sonar.server.qualityprofile.QProfileLookup;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
-import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
+import org.sonar.server.rule.index.RuleIndexDefinition;
import org.sonar.server.search.FacetValue;
-import javax.annotation.Nullable;
-
-import java.util.List;
-import java.util.Map;
+import static org.sonar.server.qualityprofile.index.ActiveRuleIndex2.COUNT_ACTIVE_RULES;
public class InheritanceAction implements QProfileWsAction {
private Long getActiveRuleCount(Multimap<String, FacetValue> profileStats) {
Long result = null;
- if (profileStats.containsKey(ActiveRuleIndex.COUNT_ACTIVE_RULES)) {
- result = profileStats.get(ActiveRuleIndex.COUNT_ACTIVE_RULES).iterator().next().getValue();
+ if (profileStats.containsKey(COUNT_ACTIVE_RULES)) {
+ result = profileStats.get(COUNT_ACTIVE_RULES).iterator().next().getValue();
}
return result;
}
private Long getOverridingRuleCount(Multimap<String, FacetValue> profileStats) {
Long result = null;
- if (profileStats.containsKey(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field())) {
- for (FacetValue value : profileStats.get(ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field())) {
+ if (profileStats.containsKey(RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE)) {
+ for (FacetValue value : profileStats.get(RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE)) {
if ("OVERRIDES".equals(value.getKey())) {
result = value.getValue();
}
import org.sonar.server.es.EsClient;
import org.sonar.server.es.SearchIdResult;
import org.sonar.server.es.SearchOptions;
-import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer;
-import org.sonar.server.search.IndexDefinition;
import org.sonar.server.search.IndexField;
import org.sonar.server.search.StickyFacetBuilder;
// ActiveRule Filter (profile and inheritance)
BoolFilterBuilder childrenFilter = FilterBuilders.boolFilter();
- this.addTermFilter(childrenFilter, ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field(), query.getQProfileKey());
- this.addTermFilter(childrenFilter, ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field(), query.getInheritance());
- this.addTermFilter(childrenFilter, ActiveRuleNormalizer.ActiveRuleField.SEVERITY.field(), query.getActiveSeverities());
+ addTermFilter(childrenFilter, RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY, query.getQProfileKey());
+ addTermFilter(childrenFilter, RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance());
+ addTermFilter(childrenFilter, RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY, query.getActiveSeverities());
// ChildQuery
FilterBuilder childQuery;
/** Implementation of activation query */
if (Boolean.TRUE.equals(query.getActivation())) {
filters.put("activation",
- FilterBuilders.hasChildFilter(IndexDefinition.ACTIVE_RULE.getIndexType(),
+ FilterBuilders.hasChildFilter(RuleIndexDefinition.TYPE_ACTIVE_RULE,
childQuery));
} else if (Boolean.FALSE.equals(query.getActivation())) {
filters.put("activation",
FilterBuilders.boolFilter().mustNot(
- FilterBuilders.hasChildFilter(IndexDefinition.ACTIVE_RULE.getIndexType(),
+ FilterBuilders.hasChildFilter(RuleIndexDefinition.TYPE_ACTIVE_RULE,
childQuery)));
}
// so the rule filter has to be used as parent filter for active rules
// from which we remove filters that concern active rules ("activation")
HasParentFilterBuilder ruleFilter = FilterBuilders.hasParentFilter(
- IndexDefinition.RULE.getIndexType(),
+ RuleIndexDefinition.TYPE_RULE,
stickyFacetBuilder.getStickyFacetFilter("activation"));
// Rebuilding the active rule filter without severities
BoolFilterBuilder childrenFilter = FilterBuilders.boolFilter();
- this.addTermFilter(childrenFilter, ActiveRuleNormalizer.ActiveRuleField.PROFILE_KEY.field(), query.getQProfileKey());
- this.addTermFilter(childrenFilter, ActiveRuleNormalizer.ActiveRuleField.INHERITANCE.field(), query.getInheritance());
+ this.addTermFilter(childrenFilter, RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY, query.getQProfileKey());
+ this.addTermFilter(childrenFilter, RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE, query.getInheritance());
FilterBuilder activeRuleFilter;
if (childrenFilter.hasClauses()) {
activeRuleFilter = childrenFilter.must(ruleFilter);
}
AggregationBuilder activeSeverities = AggregationBuilders.children(FACET_ACTIVE_SEVERITIES + "_children")
- .childType(IndexDefinition.ACTIVE_RULE.getIndexType())
+ .childType(RuleIndexDefinition.TYPE_ACTIVE_RULE)
.subAggregation(AggregationBuilders.filter(FACET_ACTIVE_SEVERITIES + "_filter")
.filter(activeRuleFilter)
.subAggregation(
AggregationBuilders
.terms(FACET_ACTIVE_SEVERITIES)
- .field(ActiveRuleNormalizer.ActiveRuleField.SEVERITY.field())
+ .field(RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY)
.include(Joiner.on('|').join(Severity.ALL))
.size(Severity.ALL.size())));
RuleIndexDefinition.FIELD_RULE_KEY
);
+ // Active rule fields
+
+ public static final String TYPE_ACTIVE_RULE = "activeRule";
+ public static final String FIELD_ACTIVE_RULE_KEY = "key";
+ public static final String FIELD_ACTIVE_RULE_REPOSITORY = "repo";
+ public static final String FIELD_ACTIVE_RULE_INHERITANCE = "inheritance";
+ public static final String FIELD_ACTIVE_RULE_PROFILE_KEY = "profile";
+ public static final String FIELD_ACTIVE_RULE_SEVERITY = "severity";
+ public static final String FIELD_ACTIVE_RULE_PARENT_KEY = "parentKey";
+ public static final String FIELD_ACTIVE_RULE_RULE_KEY = "ruleKey";
+ public static final String FIELD_ACTIVE_RULE_CREATED_AT = "createdAt";
+ public static final String FIELD_ACTIVE_RULE_UPDATED_AT = "updatedAt";
+
private final Settings settings;
public RuleIndexDefinition(Settings settings) {
ruleMapping.createLongField(FIELD_RULE_CREATED_AT);
ruleMapping.createLongField(FIELD_RULE_UPDATED_AT);
+
+ // Active rule type
+ NewIndex.NewIndexType activeRuleMapping = index.createType(RuleIndexDefinition.TYPE_ACTIVE_RULE);
+ activeRuleMapping.setAttribute("_id", ImmutableMap.of("path", RuleIndexDefinition.FIELD_ACTIVE_RULE_KEY));
+ activeRuleMapping.setAttribute("_parent", ImmutableMap.of("type", RuleIndexDefinition.TYPE_RULE));
+ activeRuleMapping.setAttribute("_routing", ImmutableMap.of("required", true, "path", RuleIndexDefinition.FIELD_ACTIVE_RULE_REPOSITORY));
+
+ activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_KEY).enableSorting().enableGramSearch().build();
+ activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_RULE_KEY).disableSearch().docValues().build();
+ activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_REPOSITORY).disableSearch().docValues().build();
+ activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_PROFILE_KEY).docValues().build();
+ activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_INHERITANCE).docValues().build();
+ activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_SEVERITY).docValues().build();
+ activeRuleMapping.stringFieldBuilder(RuleIndexDefinition.FIELD_ACTIVE_RULE_PARENT_KEY).disableSearch().docValues().build();
+
+ activeRuleMapping.createLongField(RuleIndexDefinition.FIELD_ACTIVE_RULE_CREATED_AT);
+ activeRuleMapping.createLongField(RuleIndexDefinition.FIELD_ACTIVE_RULE_UPDATED_AT);
}
}
*/
package org.sonar.server.rule.index;
-import com.google.common.annotations.VisibleForTesting;
import java.util.Iterator;
import org.elasticsearch.action.index.IndexRequest;
import org.sonar.db.DbClient;
return doIndex(createBulkIndexer(false), lastUpdatedAt);
}
- @VisibleForTesting
- void index(Iterator<RuleDoc> rules) {
+ public void index(Iterator<RuleDoc> rules) {
doIndex(createBulkIndexer(false), rules);
}
while (rules.hasNext()) {
RuleDoc rule = rules.next();
// TODO when active rule is not more DAO v2, restore deleting of REMOVED rules and also remove active rules linked to this rule
-// if (rule.status() == RuleStatus.REMOVED) {
-// bulk.add(newDeleteRequest(rule));
-// } else {
-// }
- bulk.add(newUpsertRequest(rule));
+ // if (rule.status() == RuleStatus.REMOVED) {
+ // bulk.add(newDeleteRequest(rule));
+ // } else {
+ // }
+ bulk.add(newIndexRequest(rule));
// it's more efficient to sort programmatically than in SQL on some databases (MySQL for instance)
maxDate = Math.max(maxDate, rule.updatedAtAtAsLong());
return bulk;
}
- private IndexRequest newUpsertRequest(RuleDoc rule) {
+ private IndexRequest newIndexRequest(RuleDoc rule) {
return new IndexRequest(INDEX, TYPE_RULE, rule.key().toString())
.routing(rule.repository())
.source(rule.getFields());
}
-// private DeleteRequest newDeleteRequest(RuleDoc rule) {
-// return new DeleteRequest(INDEX, TYPE_RULE, rule.key().toString())
-// .routing(rule.repository());
-// }
+ // private DeleteRequest newDeleteRequest(RuleDoc rule) {
+ // return new DeleteRequest(INDEX, TYPE_RULE, rule.key().toString())
+ // .routing(rule.repository());
+ // }
}
*/
package org.sonar.server.search;
-import java.util.Date;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
-import org.sonar.db.DbSession;
import org.sonar.server.activity.index.ActivityIndexer;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.db.DeprecatedDao;
import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.issue.index.IssueIndexer;
-import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.test.index.TestIndexer;
import org.sonar.server.user.index.UserIndexer;
import org.sonar.server.view.index.ViewIndexer;
private static final Logger LOG = Loggers.get(IndexSynchronizer.class);
- private final DbClient db;
- private final IndexClient index;
private final TestIndexer testIndexer;
private final IssueAuthorizationIndexer issueAuthorizationIndexer;
private final IssueIndexer issueIndexer;
* because we need {@link org.sonar.server.issue.index.IssueAuthorizationIndexer} to be executed before
* {@link org.sonar.server.issue.index.IssueIndexer}
*/
- public IndexSynchronizer(DbClient db, IndexClient index,
- TestIndexer testIndexer, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
+ public IndexSynchronizer(TestIndexer testIndexer, IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer,
UserIndexer userIndexer, ViewIndexer viewIndexer, ActivityIndexer activityIndexer,
Settings settings) {
- this.db = db;
- this.index = index;
this.testIndexer = testIndexer;
this.issueAuthorizationIndexer = issueAuthorizationIndexer;
this.issueIndexer = issueIndexer;
this.settings = settings;
}
- public void executeDeprecated() {
- DbSession session = db.openSession(false);
- try {
- // synchronize(session, db.deprecatedRuleDao(), index.get(RuleIndex.class));
- synchronize(session, db.activeRuleDao(), index.get(ActiveRuleIndex.class));
- session.commit();
- } finally {
- session.close();
- }
- }
-
public void execute() {
if (!settings.getBoolean("sonar.internal.es.disableIndexes")) {
LOG.info("Index activities");
}
}
- void synchronize(DbSession session, DeprecatedDao dao, Index index) {
- long count = index.getIndexStat().getDocumentCount();
- Date lastSynch = index.getLastSynchronization();
- LOG.info("Index {}s", index.getIndexType());
- if (count <= 0) {
- dao.synchronizeAfter(session);
- } else {
- dao.synchronizeAfter(session, lastSynch);
- }
- }
}
}));
}
- public List<String> getIds(String indexName, String typeName){
+ public List<String> getIds(String indexName, String typeName) {
return FluentIterable.from(getDocuments(indexName, typeName)).transform(SearchHitToId.INSTANCE).toList();
}
return client;
}
- private enum SearchHitToId implements Function<SearchHit, String>{
+ private enum SearchHitToId implements Function<SearchHit, String> {
INSTANCE;
@Override
--- /dev/null
+/*
+ * 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.qualityprofile.index;
+
+import org.sonar.api.rule.Severity;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.db.rule.RuleTesting;
+
+public class ActiveRuleDocTesting {
+
+ public static ActiveRuleDoc newDoc() {
+ return newDoc(ActiveRuleKey.of("sonar-way", RuleTesting.XOO_X1));
+ }
+
+ public static ActiveRuleDoc newDoc(ActiveRuleKey key) {
+ return new ActiveRuleDoc(key)
+ .setSeverity(Severity.CRITICAL)
+ .setParentKey(null)
+ .setInheritance(null).setCreatedAt(150000000L)
+ .setUpdatedAt(160000000L);
+ }
+}
--- /dev/null
+/*
+ * 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.qualityprofile.index;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.db.rule.RuleTesting;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.qualityprofile.ActiveRule;
+import org.sonar.server.rule.index.RuleDoc;
+import org.sonar.server.rule.index.RuleDocTesting;
+import org.sonar.server.rule.index.RuleIndexDefinition;
+import org.sonar.server.rule.index.RuleIndexer;
+import org.sonar.server.search.FacetValue;
+
+import static java.util.Arrays.asList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.entry;
+import static org.sonar.api.rule.Severity.BLOCKER;
+import static org.sonar.api.rule.Severity.MAJOR;
+import static org.sonar.api.rule.Severity.MINOR;
+import static org.sonar.server.qualityprofile.ActiveRule.Inheritance.INHERITED;
+import static org.sonar.server.qualityprofile.ActiveRule.Inheritance.OVERRIDES;
+import static org.sonar.server.rule.index.RuleDocTesting.newDoc;
+import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX;
+import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_ACTIVE_RULE;
+
+public class ActiveRuleIndex2Test {
+
+ static final RuleKey RULE_KEY_1 = RuleTesting.XOO_X1;
+ static final RuleKey RULE_KEY_2 = RuleTesting.XOO_X2;
+
+ static final String QUALITY_PROFILE_KEY1 = "qp1";
+ static final String QUALITY_PROFILE_KEY2 = "qp2";
+
+ @ClassRule
+ public static EsTester tester = new EsTester().addDefinitions(new RuleIndexDefinition(new Settings()));
+
+ ActiveRuleIndex2 index;
+
+ ActiveRuleIndexer activeRuleIndexer;
+ RuleIndexer ruleIndexer;
+
+ @Before
+ public void setUp() {
+ tester.truncateIndices();
+ activeRuleIndexer = new ActiveRuleIndexer(null, tester.client());
+ ruleIndexer = new RuleIndexer(null, tester.client());
+ index = new ActiveRuleIndex2(tester.client());
+ }
+
+ @Test
+ public void count_all_by_quality_profile_key() {
+ indexRules(RuleDocTesting.newDoc(RULE_KEY_1));
+
+ indexActiveRules(
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1)),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_1)));
+
+ // 0. Test base case
+ assertThat(tester.countDocuments(INDEX, TYPE_ACTIVE_RULE)).isEqualTo(2);
+
+ // 1. Assert by term aggregation;
+ assertThat(index.countAllByQualityProfileKey()).containsOnly(entry(QUALITY_PROFILE_KEY1, 1L), entry(QUALITY_PROFILE_KEY2, 1L));
+ }
+
+ @Test
+ public void stats_for_all() {
+ indexRules(
+ newDoc(RULE_KEY_1),
+ newDoc(RULE_KEY_2));
+
+ ActiveRuleKey activeRuleKey1 = ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1);
+ ActiveRuleKey activeRuleKey2 = ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_2);
+
+ indexActiveRules(
+ ActiveRuleDocTesting.newDoc(activeRuleKey1).setSeverity(BLOCKER),
+ ActiveRuleDocTesting.newDoc(activeRuleKey2).setSeverity(MINOR),
+ // Profile 2 is a child a profile 1
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_1)).setSeverity(MAJOR)
+ .setParentKey(activeRuleKey1.toString()).setInheritance(INHERITED.name()),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_2)).setSeverity(BLOCKER)
+ .setParentKey(activeRuleKey2.toString()).setInheritance(OVERRIDES.name()));
+
+ // 0. Test base case
+ assertThat(tester.countDocuments(INDEX, TYPE_ACTIVE_RULE)).isEqualTo(4);
+
+ // 1. Assert by term aggregation;
+ Map<String, Multimap<String, FacetValue>> stats = index.getStatsByProfileKeys(ImmutableList.of(QUALITY_PROFILE_KEY1, QUALITY_PROFILE_KEY2));
+ assertThat(stats).hasSize(2);
+ }
+
+ /**
+ * SONAR-5844
+ */
+ @Test
+ public void stats_for_all_with_lof_of_profiles() {
+ indexRules(RuleDocTesting.newDoc(RULE_KEY_1), RuleDocTesting.newDoc(RULE_KEY_2));
+
+ indexActiveRules(
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1)),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_1)));
+
+ List<String> profileKeys = new ArrayList<>();
+ List<ActiveRuleDoc> docs = new ArrayList<>();
+ for (int i = 0; i < 30; i++) {
+ String profileKey = "profile-" + i;
+ profileKeys.add(profileKey);
+ docs.add(ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(profileKey, RULE_KEY_1)).setSeverity(BLOCKER));
+ docs.add(ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(profileKey, RULE_KEY_2)).setSeverity(MAJOR));
+ }
+ indexActiveRules(docs.toArray(new ActiveRuleDoc[]{}));
+
+ Map<String, Multimap<String, FacetValue>> stats = index.getStatsByProfileKeys(profileKeys);
+ assertThat(stats).hasSize(30);
+ }
+
+ @Test
+ public void get_by_key() {
+ indexRules(RuleDocTesting.newDoc(RULE_KEY_1));
+ ActiveRuleKey key = ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1);
+ indexActiveRules(ActiveRuleDocTesting.newDoc(key));
+
+ assertThat(index.getNullableByKey(key)).isNotNull();
+ assertThat(index.getNullableByKey(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_2))).isNull();
+ }
+
+ @Test
+ public void find_active_rules() {
+ indexRules(
+ RuleDocTesting.newDoc(RULE_KEY_1),
+ RuleDocTesting.newDoc(RULE_KEY_2),
+ RuleDocTesting.newDoc(RuleKey.of("xoo", "removed")).setStatus(RuleStatus.REMOVED.name())
+ );
+
+ indexActiveRules(
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1)),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_2)),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_2)),
+ // Removed rule can still be activated for instance when removing the checkstyle plugin, active rules related on checkstyle are not
+ // removed
+ // because if the plugin is re-install, quality profiles using these rule are not changed.
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RuleKey.of("xoo", "removed")))
+ );
+
+ // 1. find by rule key
+
+ // in es
+ List<ActiveRule> activeRules = index.findByRule(RULE_KEY_1);
+ assertThat(activeRules).hasSize(1);
+ assertThat(activeRules.get(0).key().ruleKey()).isEqualTo(RULE_KEY_1);
+
+ activeRules = index.findByRule(RULE_KEY_2);
+ assertThat(activeRules).hasSize(2);
+ assertThat(activeRules.get(0).key().ruleKey()).isEqualTo(RULE_KEY_2);
+
+ activeRules = index.findByRule(RuleKey.of("unknown", "unknown"));
+ assertThat(activeRules).isEmpty();
+
+ // 2. find by profile
+ List<ActiveRuleDoc> activeRuleDocs = Lists.newArrayList(index.findByProfile(QUALITY_PROFILE_KEY1));
+ assertThat(activeRuleDocs).hasSize(2);
+ assertThat(activeRuleDocs.get(0).key().qProfile()).isEqualTo(QUALITY_PROFILE_KEY1);
+ assertThat(activeRuleDocs.get(1).key().qProfile()).isEqualTo(QUALITY_PROFILE_KEY1);
+
+ activeRuleDocs = Lists.newArrayList(index.findByProfile(QUALITY_PROFILE_KEY2));
+ assertThat(activeRuleDocs).hasSize(1);
+ assertThat(activeRuleDocs.get(0).key().qProfile()).isEqualTo(QUALITY_PROFILE_KEY2);
+
+ activeRuleDocs = Lists.newArrayList(index.findByProfile("unknown"));
+ assertThat(activeRuleDocs).isEmpty();
+ }
+
+ @Test
+ public void find_many_active_rules_by_profile() {
+ int nb = 150;
+ RuleDoc[] ruleDocs = new RuleDoc[nb];
+ ActiveRuleDoc[] activeRuleDocs = new ActiveRuleDoc[nb];
+ for (int i = 0; i < nb; i++) {
+ RuleKey ruleKey = RuleKey.of("xoo", "S00" + i);
+ ruleDocs[i] = RuleDocTesting.newDoc(ruleKey);
+ activeRuleDocs[i] = ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, ruleKey));
+ }
+ indexRules(ruleDocs);
+ indexActiveRules(activeRuleDocs);
+
+ // verify index
+ assertThat(index.findByProfile(QUALITY_PROFILE_KEY1)).hasSize(nb);
+ }
+
+ @Test
+ public void find_many_active_rules_by_rule() {
+ indexRules(RuleDocTesting.newDoc(RULE_KEY_1));
+
+ int nb = 150;
+ ActiveRuleDoc[] activeRuleDocs = new ActiveRuleDoc[nb];
+ for (int i = 0; i < nb; i++) {
+ activeRuleDocs[i] = ActiveRuleDocTesting.newDoc(ActiveRuleKey.of("qp" + i, RULE_KEY_1));
+ }
+ indexActiveRules(activeRuleDocs);
+
+ // verify index
+ assertThat(index.findByRule(RULE_KEY_1)).hasSize(nb);
+ }
+
+ private void indexActiveRules(ActiveRuleDoc... docs) {
+ activeRuleIndexer.index(asList(docs).iterator());
+ }
+
+ private void indexRules(RuleDoc... rules) {
+ ruleIndexer.index(asList(rules).iterator());
+ }
+
+}
--- /dev/null
+/*
+ * 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.qualityprofile.index;
+
+import com.google.common.collect.Iterators;
+import java.util.Arrays;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.config.Settings;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.db.qualityprofile.ActiveRuleDto;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.db.rule.RuleDto;
+import org.sonar.db.rule.RuleTesting;
+import org.sonar.server.es.EsTester;
+import org.sonar.server.qualityprofile.ActiveRuleChange;
+import org.sonar.server.rule.index.RuleIndexDefinition;
+import org.sonar.test.DbTests;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.ACTIVATED;
+import static org.sonar.server.qualityprofile.ActiveRuleChange.Type.DEACTIVATED;
+import static org.sonar.server.qualityprofile.index.ActiveRuleDocTesting.newDoc;
+import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX;
+import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_ACTIVE_RULE;
+
+@Category(DbTests.class)
+public class ActiveRuleIndexerTest {
+
+ static final RuleKey RULE_KEY_1 = RuleTesting.XOO_X1;
+ static final RuleKey RULE_KEY_2 = RuleTesting.XOO_X2;
+ static final RuleKey RULE_KEY_3 = RuleTesting.XOO_X3;
+
+ static final String QUALITY_PROFILE_KEY1 = "qp1";
+ static final String QUALITY_PROFILE_KEY2 = "qp2";
+
+ @ClassRule
+ public static EsTester esTester = new EsTester().addDefinitions(new RuleIndexDefinition(new Settings()));
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ ActiveRuleIndexer indexer;
+
+ @Before
+ public void setUp() {
+ esTester.truncateIndices();
+ indexer = new ActiveRuleIndexer(dbTester.getDbClient(), esTester.client());
+ indexer.setEnabled(true);
+ }
+
+ @Test
+ public void index_nothing() {
+ indexer.index(Iterators.<ActiveRuleDoc>emptyIterator());
+ assertThat(esTester.countDocuments(INDEX, TYPE_ACTIVE_RULE)).isZero();
+ }
+
+ @Test
+ public void index_nothing_if_disabled() {
+ dbTester.prepareDbUnit(getClass(), "index.xml");
+
+ ActiveRuleIndexer indexer = new ActiveRuleIndexer(dbTester.getDbClient(), esTester.client());
+ indexer.setEnabled(false);
+ indexer.index();
+
+ assertThat(esTester.countDocuments(INDEX, TYPE_ACTIVE_RULE)).isZero();
+ }
+
+ @Test
+ public void index() {
+ dbTester.prepareDbUnit(getClass(), "index.xml");
+
+ indexer.index();
+
+ assertThat(esTester.countDocuments(INDEX, TYPE_ACTIVE_RULE)).isEqualTo(1);
+ }
+
+ @Test
+ public void delete_profile() throws Exception {
+ indexActiveRules(
+ newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1)),
+ newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_2)),
+ newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_2)),
+ newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_3)));
+
+ assertThat(esTester.getIds(INDEX, TYPE_ACTIVE_RULE)).hasSize(4);
+
+ indexer.deleteProfile(QUALITY_PROFILE_KEY1);
+
+ assertThat(esTester.getIds(INDEX, TYPE_ACTIVE_RULE)).containsOnly(
+ ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_2).toString(),
+ ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_3).toString()
+ );
+ }
+
+ @Test
+ public void index_from_changes_remove_deactivated_rules() throws Exception {
+ ActiveRuleKey activeRuleKey1 = ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1);
+ ActiveRuleKey activeRuleKey2 = ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_2);
+ ActiveRuleKey activeRuleKey3 = ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_2);
+ ActiveRuleKey activeRuleKey4 = ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_3);
+
+ indexActiveRules(
+ newDoc(activeRuleKey1),
+ newDoc(activeRuleKey2),
+ newDoc(activeRuleKey3),
+ newDoc(activeRuleKey4));
+
+ assertThat(esTester.getIds(INDEX, TYPE_ACTIVE_RULE)).hasSize(4);
+
+ indexer.index(Arrays.asList(
+ ActiveRuleChange.createFor(ACTIVATED, activeRuleKey1),
+ ActiveRuleChange.createFor(DEACTIVATED, activeRuleKey2),
+ ActiveRuleChange.createFor(DEACTIVATED, activeRuleKey3)
+ ));
+
+ assertThat(esTester.getIds(INDEX, TYPE_ACTIVE_RULE)).containsOnly(
+ activeRuleKey1.toString(),
+ activeRuleKey4.toString()
+ );
+ }
+
+ @Test
+ public void index_from_changes_index_new_active_rule() throws Exception {
+ long yesterday = 1000000L;
+ long now = 2000000L;
+
+ // Index one active rule
+ RuleDto rule = RuleTesting.newDto(RULE_KEY_1);
+ dbTester.getDbClient().ruleDao().insert(dbTester.getSession(), rule);
+ QualityProfileDto profile = QualityProfileDto.createFor("qp").setLanguage("xoo").setName("profile");
+ dbTester.getDbClient().qualityProfileDao().insert(dbTester.getSession(), profile);
+ ActiveRuleDto activeRule = ActiveRuleDto.createFor(profile, rule).setSeverity(Severity.BLOCKER)
+ .setCreatedAtInMs(yesterday).setUpdatedAtInMs(yesterday);
+// dbTester.getDbClient().activeRuleDao().insert(dbTester.getSession(), activeRule);
+ dbTester.getSession().commit();
+
+ indexer.index();
+
+ assertThat(esTester.getIds(INDEX, TYPE_ACTIVE_RULE)).containsOnly(activeRule.getKey().toString());
+
+ // Index another active rule
+ RuleDto rule2 = RuleTesting.newDto(RULE_KEY_2);
+ dbTester.getDbClient().ruleDao().insert(dbTester.getSession(), rule2);
+ ActiveRuleDto activeRule2 = ActiveRuleDto.createFor(profile, rule2).setSeverity(Severity.CRITICAL)
+ .setCreatedAtInMs(now).setUpdatedAtInMs(now);
+// dbTester.getDbClient().activeRuleDao().insert(dbTester.getSession(), activeRule2);
+ dbTester.getSession().commit();
+
+ indexer.index(singletonList(ActiveRuleChange.createFor(ACTIVATED, activeRule2.getKey())));
+
+ assertThat(esTester.getIds(INDEX, TYPE_ACTIVE_RULE)).containsOnly(
+ activeRule.getKey().toString(),
+ activeRule2.getKey().toString()
+ );
+ }
+
+ private void indexActiveRules(ActiveRuleDoc... docs) {
+ indexer.index(asList(docs).iterator());
+ }
+
+}
--- /dev/null
+/*
+ * 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.qualityprofile.index;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import javax.annotation.Nonnull;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.server.qualityprofile.ActiveRule;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.rule.Severity.BLOCKER;
+import static org.sonar.api.rule.Severity.CRITICAL;
+import static org.sonar.api.rule.Severity.INFO;
+import static org.sonar.server.qualityprofile.ActiveRule.Inheritance.INHERITED;
+
+@Category(DbTests.class)
+public class ActiveRuleResultSetIteratorTest {
+
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ @Before
+ public void setUp() {
+ dbTester.truncateTables();
+ }
+
+ @Test
+ public void iterator_over_one_active_rule() {
+ dbTester.prepareDbUnit(getClass(), "one_active_rule.xml");
+ ActiveRuleResultSetIterator it = ActiveRuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 0L);
+ Map<ActiveRuleKey, ActiveRuleDoc> activeRulesByKey = activeRulesByKey(it);
+ it.close();
+
+ assertThat(activeRulesByKey).hasSize(1);
+
+ ActiveRuleKey key = ActiveRuleKey.of("sonar-way", RuleKey.of("xoo", "S001"));
+ ActiveRuleDoc activeRule = activeRulesByKey.get(key);
+ assertThat(activeRule.key()).isEqualTo(key);
+ assertThat(activeRule.severity()).isEqualTo(CRITICAL);
+ assertThat(activeRule.inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
+ assertThat(activeRule.parentKey()).isNull();
+ assertThat(activeRule.createdAtAsLong()).isEqualTo(1500000000000L);
+ assertThat(activeRule.updatedAtAsLong()).isEqualTo(1600000000000L);
+ }
+
+ @Test
+ public void iterator_over_active_rules() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+ ActiveRuleResultSetIterator it = ActiveRuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 0L);
+ Map<ActiveRuleKey, ActiveRuleDoc> activeRulesByKey = activeRulesByKey(it);
+ it.close();
+
+ assertThat(activeRulesByKey).hasSize(3);
+
+ ActiveRuleKey key = ActiveRuleKey.of("sonar-way", RuleKey.of("xoo", "S002"));
+ ActiveRuleDoc activeRule = activeRulesByKey.get(key);
+ assertThat(activeRule.key()).isEqualTo(key);
+ assertThat(activeRule.severity()).isEqualTo(CRITICAL);
+ assertThat(activeRule.inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
+ assertThat(activeRule.parentKey()).isNull();
+ assertThat(activeRule.createdAtAsLong()).isEqualTo(2000000000000L);
+ assertThat(activeRule.updatedAtAsLong()).isEqualTo(2100000000000L);
+
+ key = ActiveRuleKey.of("parent", RuleKey.of("xoo", "S001"));
+ activeRule = activeRulesByKey.get(key);
+ assertThat(activeRule.key()).isEqualTo(key);
+ assertThat(activeRule.severity()).isEqualTo(INFO);
+ assertThat(activeRule.inheritance()).isEqualTo(ActiveRule.Inheritance.NONE);
+ assertThat(activeRule.parentKey()).isNull();
+ assertThat(activeRule.createdAtAsLong()).isEqualTo(1700000000000L);
+ assertThat(activeRule.updatedAtAsLong()).isEqualTo(1800000000000L);
+
+ key = ActiveRuleKey.of("child", RuleKey.of("xoo", "S001"));
+ activeRule = activeRulesByKey.get(key);
+ assertThat(activeRule.key()).isEqualTo(key);
+ assertThat(activeRule.severity()).isEqualTo(BLOCKER);
+ assertThat(activeRule.inheritance()).isEqualTo(INHERITED);
+ assertThat(activeRule.parentKey()).isEqualTo(ActiveRuleKey.of("parent", RuleKey.of("xoo", "S001")));
+ assertThat(activeRule.createdAtAsLong()).isEqualTo(1500000000000L);
+ assertThat(activeRule.updatedAtAsLong()).isEqualTo(1600000000000L);
+ }
+
+ @Test
+ public void active_rule_with_inherited_inheritance() {
+ dbTester.prepareDbUnit(getClass(), "active_rule_with_inherited_inheritance.xml");
+ ActiveRuleResultSetIterator it = ActiveRuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 0L);
+ Map<ActiveRuleKey, ActiveRuleDoc> activeRulesByKey = activeRulesByKey(it);
+ it.close();
+
+ assertThat(activeRulesByKey).hasSize(2);
+
+ ActiveRuleKey key = ActiveRuleKey.of("child", RuleKey.of("xoo", "S001"));
+ ActiveRuleDoc activeRule = activeRulesByKey.get(key);
+ assertThat(activeRule.inheritance()).isEqualTo(INHERITED);
+ assertThat(activeRule.parentKey()).isEqualTo(ActiveRuleKey.of("parent", RuleKey.of("xoo", "S001")));
+ }
+
+ @Test
+ public void active_rule_with_overrides_inheritance() {
+ dbTester.prepareDbUnit(getClass(), "active_rule_with_overrides_inheritance.xml");
+ ActiveRuleResultSetIterator it = ActiveRuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 0L);
+ Map<ActiveRuleKey, ActiveRuleDoc> activeRulesByKey = activeRulesByKey(it);
+ it.close();
+
+ assertThat(activeRulesByKey).hasSize(2);
+
+ ActiveRuleKey key = ActiveRuleKey.of("child", RuleKey.of("xoo", "S001"));
+ ActiveRuleDoc activeRule = activeRulesByKey.get(key);
+ assertThat(activeRule.inheritance()).isEqualTo(ActiveRule.Inheritance.OVERRIDES);
+ assertThat(activeRule.parentKey()).isEqualTo(ActiveRuleKey.of("parent", RuleKey.of("xoo", "S001")));
+ }
+
+ @Test
+ public void select_after_date() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+ ActiveRuleResultSetIterator it = ActiveRuleResultSetIterator.create(dbTester.getDbClient(), dbTester.getSession(), 1_900_000_000_000L);
+
+ assertThat(it.hasNext()).isTrue();
+ ActiveRuleDoc doc = it.next();
+ assertThat(doc.key()).isEqualTo(ActiveRuleKey.of("sonar-way", RuleKey.of("xoo", "S002")));
+
+ assertThat(it.hasNext()).isFalse();
+ it.close();
+ }
+
+ private static Map<ActiveRuleKey, ActiveRuleDoc> activeRulesByKey(ActiveRuleResultSetIterator it) {
+ return Maps.uniqueIndex(it, DocToKey.INSTANCE);
+ }
+
+ private enum DocToKey implements Function<ActiveRuleDoc, ActiveRuleKey> {
+ INSTANCE;
+
+ @Override
+ public ActiveRuleKey apply(@Nonnull ActiveRuleDoc doc) {
+ return doc.key();
+ }
+ }
+
+}
import java.util.Map;
import org.junit.Before;
import org.junit.ClassRule;
-import org.junit.Ignore;
import org.junit.Test;
import org.sonar.api.config.Settings;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
+import org.sonar.db.qualityprofile.ActiveRuleKey;
+import org.sonar.db.rule.RuleTesting;
import org.sonar.server.es.EsTester;
import org.sonar.server.es.SearchIdResult;
import org.sonar.server.es.SearchOptions;
+import org.sonar.server.qualityprofile.index.ActiveRuleDoc;
+import org.sonar.server.qualityprofile.index.ActiveRuleDocTesting;
+import org.sonar.server.qualityprofile.index.ActiveRuleIndexer;
import static java.util.Arrays.asList;
import static java.util.Collections.singleton;
import static org.assertj.core.data.MapEntry.entry;
import static org.junit.Assert.fail;
import static org.sonar.api.rule.Severity.BLOCKER;
+import static org.sonar.api.rule.Severity.CRITICAL;
import static org.sonar.api.rule.Severity.INFO;
+import static org.sonar.api.rule.Severity.MAJOR;
import static org.sonar.api.rule.Severity.MINOR;
+import static org.sonar.server.qualityprofile.ActiveRule.Inheritance.INHERITED;
+import static org.sonar.server.qualityprofile.ActiveRule.Inheritance.OVERRIDES;
import static org.sonar.server.rule.index.RuleDocTesting.newDoc;
import static org.sonar.server.rule.index.RuleIndex2.FACET_LANGUAGES;
import static org.sonar.server.rule.index.RuleIndex2.FACET_REPOSITORIES;
import static org.sonar.server.rule.index.RuleIndex2.FACET_TAGS;
+import static org.sonar.server.rule.index.RuleIndexDefinition.INDEX;
+import static org.sonar.server.rule.index.RuleIndexDefinition.TYPE_ACTIVE_RULE;
public class RuleIndex2Test {
+ static final RuleKey RULE_KEY_1 = RuleTesting.XOO_X1;
+ static final RuleKey RULE_KEY_2 = RuleTesting.XOO_X2;
+ static final RuleKey RULE_KEY_3 = RuleTesting.XOO_X3;
+ static final RuleKey RULE_KEY_4 = RuleKey.of("xoo", "x4");
+
+ static final String QUALITY_PROFILE_KEY1 = "qp1";
+ static final String QUALITY_PROFILE_KEY2 = "qp2";
+
@ClassRule
public static EsTester tester = new EsTester().addDefinitions(new RuleIndexDefinition(new Settings()));
RuleIndex2 index;
RuleIndexer ruleIndexer;
+ ActiveRuleIndexer activeRuleIndexer;
@Before
public void setUp() {
tester.truncateIndices();
ruleIndexer = new RuleIndexer(null, tester.client());
+ activeRuleIndexer = new ActiveRuleIndexer(null, tester.client());
index = new RuleIndex2(tester.client());
}
newDoc(RuleKey.of("java", "S002")).setStatus(RuleStatus.READY.name()));
RuleQuery query = new RuleQuery().setStatuses(asList(RuleStatus.DEPRECATED, RuleStatus.READY));
- SearchIdResult results = index.search(query, new SearchOptions());
+ SearchIdResult<RuleKey> results = index.search(query, new SearchOptions());
assertThat(results.getIds()).containsOnly(RuleKey.of("java", "S002"));
// no results
}
@Test
- @Ignore
- public void search_by_profile() {
- // QualityProfileDto qualityProfileDto1 = QProfileTesting.newXooP1();
- // QualityProfileDto qualityProfileDto2 = QProfileTesting.newXooP2();
- // db.qualityProfileDao().insert(dbSession, qualityProfileDto1, qualityProfileDto2);
- //
- // RuleDto rule1 = RuleTesting.newXooX1();
- // RuleDto rule2 = RuleTesting.newXooX2();
- // RuleDto rule3 = RuleTesting.newXooX3();
- // dao.insert(dbSession, rule1, rule2, rule3);
- //
- // db.activeRuleDao().insert(
- // dbSession,
- // ActiveRuleDto.createFor(qualityProfileDto1, rule1).setSeverity("BLOCKER"),
- // ActiveRuleDto.createFor(qualityProfileDto2, rule1).setSeverity("BLOCKER"),
- // ActiveRuleDto.createFor(qualityProfileDto1, rule2).setSeverity("BLOCKER"));
- // dbSession.commit();
- // dbSession.clearCache();
- //
- // // 1. get all active rules.
- // Result<org.sonar.server.rule.Rule> result = index.search(new RuleQuery().setActivation(true),
- // new SearchOptions());
- // assertThat(result.getHits()).hasSize(2);
- //
- // // 2. get all inactive rules.
- // result = index.search(new RuleQuery().setActivation(false),
- // new SearchOptions());
- // assertThat(result.getHits()).hasSize(1);
- // assertThat(result.getHits().get(0).name()).isEqualTo(rule3.getName());
- //
- // // 3. get all rules not active on profile
- // index.search(new RuleQuery().setActivation(false).setQProfileKey(qualityProfileDto2.getKey()),
- // new SearchOptions());
- // // TODO
- // assertThat(result.getHits()).hasSize(1);
- //
- // // 4. get all active rules on profile
- // result = index.search(new RuleQuery().setActivation(true)
- // .setQProfileKey(qualityProfileDto2.getKey()),
- // new SearchOptions());
- // assertThat(result.getHits()).hasSize(1);
- // assertThat(result.getHits().get(0).name()).isEqualTo(rule1.getName());
+ public void search_by_profile() throws InterruptedException {
+ indexRules(
+ newDoc(RULE_KEY_1),
+ newDoc(RULE_KEY_2),
+ newDoc(RULE_KEY_3));
+
+ indexActiveRules(
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1)),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_1)),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_2)));
+
+ assertThat(tester.countDocuments(INDEX, TYPE_ACTIVE_RULE)).isEqualTo(3);
+
+ // 1. get all active rules.
+ assertThat(index.search(new RuleQuery().setActivation(true), new SearchOptions()).getIds())
+ .containsOnly(RULE_KEY_1, RULE_KEY_2);
+
+ // 2. get all inactive rules.
+ assertThat(index.search(new RuleQuery().setActivation(false), new SearchOptions()).getIds())
+ .containsOnly(RULE_KEY_3);
+
+ // 3. get all rules not active on profile
+ assertThat(index.search(new RuleQuery().setActivation(false).setQProfileKey(QUALITY_PROFILE_KEY2), new SearchOptions()).getIds())
+ .containsOnly(RULE_KEY_2, RULE_KEY_3);
+
+ // 4. get all active rules on profile
+ assertThat(index.search(new RuleQuery().setActivation(true).setQProfileKey(QUALITY_PROFILE_KEY2), new SearchOptions()).getIds())
+ .containsOnly(RULE_KEY_1);
}
@Test
- @Ignore
public void search_by_profile_and_inheritance() {
- // QualityProfileDto qualityProfileDto1 = QProfileTesting.newXooP1();
- // QualityProfileDto qualityProfileDto2 = QProfileTesting.newXooP2().setParentKee(QProfileTesting.XOO_P1_KEY);
- // db.qualityProfileDao().insert(dbSession, qualityProfileDto1, qualityProfileDto2);
- //
- // RuleDto rule1 = RuleTesting.newDto(RuleKey.of("xoo", "S001"));
- // RuleDto rule2 = RuleTesting.newDto(RuleKey.of("xoo", "S002"));
- // RuleDto rule3 = RuleTesting.newDto(RuleKey.of("xoo", "S003"));
- // RuleDto rule4 = RuleTesting.newDto(RuleKey.of("xoo", "S004"));
- // dao.insert(dbSession, rule1, rule2, rule3, rule4);
- //
- // db.activeRuleDao().insert(
- // dbSession,
- // ActiveRuleDto.createFor(qualityProfileDto1, rule1)
- // .setSeverity("BLOCKER"),
- // ActiveRuleDto.createFor(qualityProfileDto1, rule2)
- // .setSeverity("BLOCKER"),
- // ActiveRuleDto.createFor(qualityProfileDto1, rule3)
- // .setSeverity("BLOCKER"),
- //
- // ActiveRuleDto.createFor(qualityProfileDto2, rule1)
- // .setSeverity("MINOR")
- // .setInheritance(ActiveRule.Inheritance.INHERITED.name()),
- // ActiveRuleDto.createFor(qualityProfileDto2, rule2)
- // .setSeverity("BLOCKER")
- // .setInheritance(ActiveRule.Inheritance.OVERRIDES.name()),
- // ActiveRuleDto.createFor(qualityProfileDto2, rule3)
- // .setSeverity("BLOCKER")
- // .setInheritance(ActiveRule.Inheritance.INHERITED.name())
- // );
- //
- // dbSession.commit();
- //
- // // 0. get all rules
- // Result<org.sonar.server.rule.Rule> result = index.search(new RuleQuery(),
- // new SearchOptions());
- // assertThat(result.getHits()).hasSize(4);
- //
- // // 1. get all active rules
- // result = index.search(new RuleQuery().setActivation(true),
- // new SearchOptions());
- // assertThat(result.getHits()).hasSize(3);
- //
- // // 2. get all inactive rules.
- // result = index.search(new RuleQuery().setActivation(false),
- // new SearchOptions());
- // assertThat(result.getHits()).hasSize(1);
- // assertThat(result.getHits().get(0).name()).isEqualTo(rule4.getName());
- //
- // // 3. get Inherited Rules on profile1
- // result = index.search(new RuleQuery().setActivation(true)
- // .setQProfileKey(qualityProfileDto1.getKey())
- // .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.INHERITED.name())),
- // new SearchOptions()
- // );
- // assertThat(result.getHits()).hasSize(0);
- //
- // // 4. get Inherited Rules on profile2
- // result = index.search(new RuleQuery().setActivation(true)
- // .setQProfileKey(qualityProfileDto2.getKey())
- // .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.INHERITED.name())),
- // new SearchOptions()
- // );
- // assertThat(result.getHits()).hasSize(2);
- //
- // // 5. get Overridden Rules on profile1
- // result = index.search(new RuleQuery().setActivation(true)
- // .setQProfileKey(qualityProfileDto1.getKey())
- // .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.OVERRIDES.name())),
- // new SearchOptions()
- // );
- // assertThat(result.getHits()).hasSize(0);
- //
- // // 6. get Overridden Rules on profile2
- // result = index.search(new RuleQuery().setActivation(true)
- // .setQProfileKey(qualityProfileDto2.getKey())
- // .setInheritance(ImmutableSet.of(ActiveRule.Inheritance.OVERRIDES.name())),
- // new SearchOptions()
- // );
- // assertThat(result.getHits()).hasSize(1);
- //
- // // 7. get Inherited AND Overridden Rules on profile1
- // result = index.search(new RuleQuery().setActivation(true)
- // .setQProfileKey(qualityProfileDto1.getKey())
- // .setInheritance(ImmutableSet.of(
- // ActiveRule.Inheritance.INHERITED.name(), ActiveRule.Inheritance.OVERRIDES.name())),
- // new SearchOptions()
- // );
- // assertThat(result.getHits()).hasSize(0);
- //
- // // 8. get Inherited AND Overridden Rules on profile2
- // result = index.search(new RuleQuery().setActivation(true)
- // .setQProfileKey(qualityProfileDto2.getKey())
- // .setInheritance(ImmutableSet.of(
- // ActiveRule.Inheritance.INHERITED.name(), ActiveRule.Inheritance.OVERRIDES.name())),
- // new SearchOptions()
- // );
- // assertThat(result.getHits()).hasSize(3);
+ indexRules(
+ newDoc(RULE_KEY_1),
+ newDoc(RULE_KEY_2),
+ newDoc(RULE_KEY_3),
+ newDoc(RULE_KEY_4));
+
+ ActiveRuleKey activeRuleKey1 = ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1);
+ ActiveRuleKey activeRuleKey2 = ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_2);
+ ActiveRuleKey activeRuleKey3 = ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_3);
+
+ indexActiveRules(
+ ActiveRuleDocTesting.newDoc(activeRuleKey1),
+ ActiveRuleDocTesting.newDoc(activeRuleKey2),
+ ActiveRuleDocTesting.newDoc(activeRuleKey3),
+ // Profile 2 is a child a profile 1
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_1))
+ .setParentKey(activeRuleKey1.toString()).setInheritance(INHERITED.name()),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_2))
+ .setParentKey(activeRuleKey2.toString()).setInheritance(OVERRIDES.name()),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_3))
+ .setParentKey(activeRuleKey3.toString()).setInheritance(INHERITED.name()));
+
+ // 0. get all rules
+ assertThat(index.search(new RuleQuery(), new SearchOptions()).getIds())
+ .hasSize(4);
+
+ // 1. get all active rules
+ assertThat(index.search(new RuleQuery()
+ .setActivation(true), new SearchOptions()).getIds())
+ .hasSize(3);
+
+ // 2. get all inactive rules.
+ assertThat(index.search(new RuleQuery()
+ .setActivation(false), new SearchOptions()).getIds())
+ .containsOnly(RULE_KEY_4);
+
+ // 3. get Inherited Rules on profile1
+ assertThat(index.search(new RuleQuery().setActivation(true)
+ .setQProfileKey(QUALITY_PROFILE_KEY1)
+ .setInheritance(ImmutableSet.of(INHERITED.name())),
+ new SearchOptions()).getIds())
+ .isEmpty();
+
+ // 4. get Inherited Rules on profile2
+ assertThat(index.search(new RuleQuery().setActivation(true)
+ .setQProfileKey(QUALITY_PROFILE_KEY2)
+ .setInheritance(ImmutableSet.of(INHERITED.name())),
+ new SearchOptions()).getIds())
+ .hasSize(2);
+
+ // 5. get Overridden Rules on profile1
+ assertThat(index.search(new RuleQuery().setActivation(true)
+ .setQProfileKey(QUALITY_PROFILE_KEY1)
+ .setInheritance(ImmutableSet.of(OVERRIDES.name())),
+ new SearchOptions()).getIds())
+ .isEmpty();
+
+ // 6. get Overridden Rules on profile2
+ assertThat(index.search(new RuleQuery().setActivation(true)
+ .setQProfileKey(QUALITY_PROFILE_KEY2)
+ .setInheritance(ImmutableSet.of(OVERRIDES.name())),
+ new SearchOptions()).getIds())
+ .hasSize(1);
+
+ // 7. get Inherited AND Overridden Rules on profile1
+ assertThat(index.search(new RuleQuery().setActivation(true)
+ .setQProfileKey(QUALITY_PROFILE_KEY1)
+ .setInheritance(ImmutableSet.of(INHERITED.name(), OVERRIDES.name())),
+ new SearchOptions()).getIds())
+ .isEmpty();
+
+ // 8. get Inherited AND Overridden Rules on profile2
+ assertThat(index.search(new RuleQuery().setActivation(true)
+ .setQProfileKey(QUALITY_PROFILE_KEY2)
+ .setInheritance(ImmutableSet.of(INHERITED.name(), OVERRIDES.name())),
+ new SearchOptions()).getIds())
+ .hasSize(3);
}
@Test
- @Ignore
public void search_by_profile_and_active_severity() {
- // QualityProfileDto qualityProfileDto1 = QProfileTesting.newXooP1();
- // QualityProfileDto qualityProfileDto2 = QProfileTesting.newXooP2();
- // db.qualityProfileDao().insert(dbSession, qualityProfileDto1, qualityProfileDto2);
- //
- // RuleDto rule1 = RuleTesting.newXooX1().setSeverity("MAJOR");
- // RuleDto rule2 = RuleTesting.newXooX2().setSeverity("MINOR");
- // RuleDto rule3 = RuleTesting.newXooX3().setSeverity("INFO");
- // dao.insert(dbSession, rule1, rule2, rule3);
- //
- // db.activeRuleDao().insert(
- // dbSession,
- // ActiveRuleDto.createFor(qualityProfileDto1, rule1).setSeverity("BLOCKER"),
- // ActiveRuleDto.createFor(qualityProfileDto2, rule1).setSeverity("BLOCKER"),
- // ActiveRuleDto.createFor(qualityProfileDto1, rule2).setSeverity("CRITICAL"));
- // dbSession.commit();
- // dbSession.clearCache();
- //
- // // 1. get all active rules.
- // Result<org.sonar.server.rule.Rule> result = index.search(new
- // RuleQuery().setActivation(true).setQProfileKey(qualityProfileDto1.getKey()),
- // new SearchOptions());
- // assertThat(result.getHits()).hasSize(2);
- //
- // // 2. get rules with active severity critical.
- // result = index.search(new
- // RuleQuery().setActivation(true).setQProfileKey(qualityProfileDto1.getKey()).setActiveSeverities(Arrays.asList("CRITICAL")),
- // new SearchOptions().addFacets(Arrays.asList(RuleIndex.FACET_ACTIVE_SEVERITIES)));
- // assertThat(result.getHits()).hasSize(1);
- // assertThat(result.getHits().get(0).name()).isEqualTo(rule2.getName());
- // // check stickyness of active severity facet
- // assertThat(result.getFacetValues(RuleIndex.FACET_ACTIVE_SEVERITIES)).containsOnly(new FacetValue("BLOCKER", 1), new
- // FacetValue("CRITICAL", 1));
- //
- // // 3. count activation severities of all active rules
- // result = index.search(new RuleQuery(),
- // new SearchOptions().addFacets(Arrays.asList(RuleIndex.FACET_ACTIVE_SEVERITIES)));
- // assertThat(result.getHits()).hasSize(3);
- // assertThat(result.getFacetValues(RuleIndex.FACET_ACTIVE_SEVERITIES)).containsOnly(new FacetValue("BLOCKER", 2), new
- // FacetValue("CRITICAL", 1));
+ indexRules(
+ newDoc(RULE_KEY_1).setSeverity(MAJOR),
+ newDoc(RULE_KEY_2).setSeverity(MINOR),
+ newDoc(RULE_KEY_3).setSeverity(INFO));
+
+ indexActiveRules(
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_1)).setSeverity(BLOCKER),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY2, RULE_KEY_1)).setSeverity(BLOCKER),
+ ActiveRuleDocTesting.newDoc(ActiveRuleKey.of(QUALITY_PROFILE_KEY1, RULE_KEY_2)).setSeverity(CRITICAL));
+
+ // 1. get all active rules.
+ assertThat(index.search(new RuleQuery().setActivation(true).setQProfileKey(QUALITY_PROFILE_KEY1), new SearchOptions()).getIds())
+ .hasSize(2);
+
+ // 2. get rules with active severity critical.
+ SearchIdResult<RuleKey> result = index.search(new RuleQuery().setActivation(true)
+ .setQProfileKey(QUALITY_PROFILE_KEY1).setActiveSeverities(singletonList(CRITICAL)),
+ new SearchOptions().addFacets(singletonList(RuleIndex2.FACET_ACTIVE_SEVERITIES)));
+ assertThat(result.getIds()).containsOnly(RULE_KEY_2);
+
+ // check stickyness of active severity facet
+ assertThat(result.getFacets().get(RuleIndex2.FACET_ACTIVE_SEVERITIES)).containsOnly(entry(BLOCKER, 1L), entry(CRITICAL, 1L));
+
+ // 3. count activation severities of all active rules
+ result = index.search(new RuleQuery(), new SearchOptions().addFacets(singletonList(RuleIndex2.FACET_ACTIVE_SEVERITIES)));
+ assertThat(result.getIds()).hasSize(3);
+ assertThat(result.getFacets().get(RuleIndex2.FACET_ACTIVE_SEVERITIES)).containsOnly(entry(BLOCKER, 2L), entry(CRITICAL, 1L));
}
@Test
private void indexRules(RuleDoc... rules) {
ruleIndexer.index(asList(rules).iterator());
}
+
+ private void indexActiveRules(ActiveRuleDoc... docs) {
+ activeRuleIndexer.index(asList(docs).iterator());
+ }
}
assertThat(underTest.getIndices()).hasSize(1);
NewIndex ruleIndex = underTest.getIndices().get("rules");
assertThat(ruleIndex).isNotNull();
- assertThat(ruleIndex.getTypes().keySet()).containsOnly("rule");
+ assertThat(ruleIndex.getTypes().keySet()).containsOnly("rule", "activeRule");
// no cluster by default
assertThat(ruleIndex.getSettings().get("index.number_of_shards")).isEqualTo(String.valueOf(NewIndex.DEFAULT_NUMBER_OF_SHARDS));
--- /dev/null
+<dataset>
+
+ <rules id="10" name="Null Pointer" plugin_name="xoo" plugin_rule_key="S001"
+ plugin_config_key="S1" description_format="HTML" description="S001 desc" language="xoo"
+ priority="4" status="READY" is_template="[false]" template_id="[null]"
+ tags="bug,performance" system_tags="cwe"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+ <rules_profiles id="100" name="Sonar Way" kee="sonar-way" language="xoo" parent_kee="[null]" is_default="[false]"/>
+
+ <active_rules id="1" profile_id="100" rule_id="10" failure_level="3" inheritance="[null]"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="10" name="Null Pointer" plugin_rule_key="S001" plugin_name="xoo"
+ plugin_config_key="S1" description_format="HTML" description="S001 desc" language="xoo"
+ priority="4" status="READY" is_template="[false]" template_id="[null]"
+ tags="bug,performance" system_tags="cwe"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+ <rules_profiles id="1" name="Parent" kee="parent" language="xoo" parent_kee="[null]" is_default="[false]"/>
+
+ <rules_profiles id="2" name="Child" kee="child" language="xoo" parent_kee="parent" is_default="[false]"/>
+
+ <active_rules id="1" profile_id="2" rule_id="10" failure_level="4" inheritance="INHERITED"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+ <!-- Parent of Active rule 1 -->
+ <active_rules id="2" profile_id="1" rule_id="10" failure_level="0" inheritance="[null]"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="10" name="Null Pointer" plugin_rule_key="S001" plugin_name="xoo"
+ plugin_config_key="S1" description_format="HTML" description="S001 desc" language="xoo"
+ priority="4" status="READY" is_template="[false]" template_id="[null]"
+ tags="bug,performance" system_tags="cwe"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+ <rules_profiles id="1" name="Parent" kee="parent" language="xoo" parent_kee="[null]" is_default="[false]"/>
+
+ <rules_profiles id="2" name="Child" kee="child" language="xoo" parent_kee="parent" is_default="[false]"/>
+
+ <active_rules id="1" profile_id="2" rule_id="10" failure_level="2" inheritance="OVERRIDES"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+ <!-- Parent of Active rule 1 -->
+ <active_rules id="2" profile_id="1" rule_id="10" failure_level="0" inheritance="[null]"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="10" name="Null Pointer" plugin_name="xoo" plugin_rule_key="S001"
+ plugin_config_key="S1" description_format="HTML" description="S001 desc" language="xoo"
+ priority="4" status="READY" is_template="[false]" template_id="[null]"
+ tags="bug,performance" system_tags="cwe"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+ <rules_profiles id="100" name="Sonar Way" kee="sonar-way" language="xoo" parent_kee="[null]" is_default="[false]"/>
+
+ <active_rules id="1" profile_id="100" rule_id="10" failure_level="3" inheritance="[null]"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+</dataset>
--- /dev/null
+<dataset>
+
+ <rules id="10" name="Null Pointer" plugin_rule_key="S001"
+ plugin_config_key="S1" plugin_name="xoo"
+ description_format="HTML" description="S001 desc" language="xoo"
+ priority="4" status="READY"
+ is_template="[false]" template_id="[null]"
+ tags="bug,performance" system_tags="cwe"
+ created_at="2014-05-10" updated_at="2014-05-11"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+ <rules id="11" name="Slow" plugin_rule_key="S002"
+ plugin_config_key="S2" plugin_name="xoo"
+ description_format="MARKDOWN" description="*S002 desc*" language="xoo"
+ priority="3" status="BETA"
+ is_template="[true]" template_id="[null]"
+ tags="[null]" system_tags="[null]"
+ created_at="2014-05-10" updated_at="2014-05-11"
+ created_at_ms="2000000000000" updated_at_ms="2100000000000"/>
+
+ <rules_profiles id="1" name="Parent" kee="parent" language="xoo" parent_kee="[null]" is_default="[false]"/>
+
+ <rules_profiles id="2" name="Child" kee="child" language="xoo" parent_kee="parent" is_default="[false]"/>
+
+ <active_rules id="1" profile_id="2" rule_id="10" failure_level="4" inheritance="INHERITED"
+ created_at_ms="1500000000000" updated_at_ms="1600000000000"/>
+
+ <!-- Parent of Active rule 1 -->
+ <active_rules id="2" profile_id="1" rule_id="10" failure_level="0" inheritance="[null]"
+ created_at_ms="1700000000000" updated_at_ms="1800000000000"/>
+
+ <rules_profiles id="3" name="Sonar Way" kee="sonar-way" language="xoo" parent_kee="[null]" is_default="[false]"/>
+
+ <active_rules id="3" profile_id="3" rule_id="11" failure_level="3" inheritance="[null]"
+ created_at_ms="2000000000000" updated_at_ms="2100000000000"/>
+
+</dataset>
--- /dev/null
+/*
+ * 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.qualityprofile;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+import org.sonar.db.RowNotFoundException;
+import org.sonar.db.rule.RuleDto;
+
+public class ActiveRuleDao implements Dao {
+
+ private static final String QUALITY_PROFILE_IS_NOT_PERSISTED = "Quality profile is not persisted (missing id)";
+ private static final String RULE_IS_NOT_PERSISTED = "Rule is not persisted";
+ private static final String RULE_PARAM_IS_NOT_PERSISTED = "Rule param is not persisted";
+ private static final String ACTIVE_RULE_KEY_CANNOT_BE_NULL = "ActiveRuleKey cannot be null";
+ private static final String ACTIVE_RULE_IS_NOT_PERSISTED = "ActiveRule is not persisted";
+ private static final String ACTIVE_RULE_IS_ALREADY_PERSISTED = "ActiveRule is already persisted";
+ private static final String ACTIVE_RULE_PARAM_IS_NOT_PERSISTED = "ActiveRuleParam is not persisted";
+ private static final String ACTIVE_RULE_PARAM_IS_ALREADY_PERSISTED = "ActiveRuleParam is already persisted";
+ private static final String PARAMETER_NAME_CANNOT_BE_NULL = "ParameterName cannot be null";
+
+ public Optional<ActiveRuleDto> selectByKey(DbSession session, ActiveRuleKey key) {
+ return Optional.fromNullable(mapper(session).selectByKey(key.qProfile(), key.ruleKey().repository(), key.ruleKey().rule()));
+ }
+
+ public ActiveRuleDto selectOrFailByKey(DbSession session, ActiveRuleKey key) {
+ Optional<ActiveRuleDto> activeRule = selectByKey(session, key);
+ if (activeRule.isPresent()) {
+ return activeRule.get();
+ }
+ throw new RowNotFoundException(String.format("Active rule with key '%s' does not exist", key));
+ }
+
+ public List<ActiveRuleDto> selectByRule(DbSession dbSession, RuleDto rule) {
+ Preconditions.checkNotNull(rule.getId(), RULE_IS_NOT_PERSISTED);
+ return mapper(dbSession).selectByRuleId(rule.getId());
+ }
+
+ public List<ActiveRuleParamDto> selectAllParams(DbSession dbSession) {
+ return mapper(dbSession).selectAllParams();
+ }
+
+ public ActiveRuleDto insert(DbSession session, ActiveRuleDto item) {
+ Preconditions.checkArgument(item.getProfileId() != null, QUALITY_PROFILE_IS_NOT_PERSISTED);
+ Preconditions.checkArgument(item.getRuleId() != null, RULE_IS_NOT_PERSISTED);
+ Preconditions.checkArgument(item.getId() == null, ACTIVE_RULE_IS_ALREADY_PERSISTED);
+ mapper(session).insert(item);
+ return item;
+ }
+
+ public ActiveRuleDto update(DbSession session, ActiveRuleDto item) {
+ Preconditions.checkArgument(item.getProfileId() != null, QUALITY_PROFILE_IS_NOT_PERSISTED);
+ Preconditions.checkArgument(item.getRuleId() != null, ActiveRuleDao.RULE_IS_NOT_PERSISTED);
+ Preconditions.checkArgument(item.getId() != null, ACTIVE_RULE_IS_NOT_PERSISTED);
+ mapper(session).update(item);
+ return item;
+ }
+
+ public void delete(DbSession session, ActiveRuleKey key) {
+ Optional<ActiveRuleDto> activeRule = selectByKey(session, key);
+ if (activeRule.isPresent()) {
+ mapper(session).deleteParameters(activeRule.get().getId());
+ mapper(session).delete(activeRule.get().getId());
+ }
+ }
+
+ /**
+ * Nested DTO ActiveRuleParams
+ */
+
+ public ActiveRuleParamDto insertParam(DbSession session, ActiveRuleDto activeRule, ActiveRuleParamDto activeRuleParam) {
+ Preconditions.checkArgument(activeRule.getId() != null, ACTIVE_RULE_IS_NOT_PERSISTED);
+ Preconditions.checkArgument(activeRuleParam.getId() == null, ACTIVE_RULE_PARAM_IS_ALREADY_PERSISTED);
+ Preconditions.checkNotNull(activeRuleParam.getRulesParameterId(), RULE_PARAM_IS_NOT_PERSISTED);
+
+ activeRuleParam.setActiveRuleId(activeRule.getId());
+ mapper(session).insertParameter(activeRuleParam);
+ return activeRuleParam;
+ }
+
+ public void deleteParamByKeyAndName(DbSession session, ActiveRuleKey key, String param) {
+ // TODO SQL rewrite to delete by key
+ Optional<ActiveRuleDto> activeRule = selectByKey(session, key);
+ if (activeRule.isPresent()) {
+ ActiveRuleParamDto activeRuleParam = mapper(session).selectParamByActiveRuleAndKey(activeRule.get().getId(), param);
+ if (activeRuleParam != null) {
+ mapper(session).deleteParameter(activeRuleParam.getId());
+ }
+ }
+ }
+
+ public void updateParam(DbSession session, ActiveRuleDto activeRule, ActiveRuleParamDto activeRuleParam) {
+ Preconditions.checkNotNull(activeRule.getId(), ACTIVE_RULE_IS_NOT_PERSISTED);
+ Preconditions.checkNotNull(activeRuleParam.getId(), ACTIVE_RULE_PARAM_IS_NOT_PERSISTED);
+ mapper(session).updateParameter(activeRuleParam);
+ }
+
+ public void deleteParam(DbSession session, ActiveRuleDto activeRule, ActiveRuleParamDto activeRuleParam) {
+ Preconditions.checkNotNull(activeRule.getId(), ACTIVE_RULE_IS_NOT_PERSISTED);
+ Preconditions.checkNotNull(activeRuleParam.getId(), ACTIVE_RULE_PARAM_IS_NOT_PERSISTED);
+ mapper(session).deleteParameter(activeRuleParam.getId());
+ }
+
+ public void deleteByProfileKey(DbSession session, String profileKey) {
+ /** Functional cascade for params */
+ for (ActiveRuleDto activeRule : selectByProfileKey(session, profileKey)) {
+ delete(session, activeRule.getKey());
+ }
+ }
+
+ public List<ActiveRuleDto> selectByProfileKey(DbSession session, String profileKey) {
+ return mapper(session).selectByProfileKey(profileKey);
+ }
+
+ /**
+ * Finder methods for ActiveRuleParams
+ */
+
+ public List<ActiveRuleParamDto> selectParamsByActiveRuleKey(DbSession session, ActiveRuleKey key) {
+ Preconditions.checkNotNull(key, ACTIVE_RULE_KEY_CANNOT_BE_NULL);
+ ActiveRuleDto activeRule = selectOrFailByKey(session, key);
+ return mapper(session).selectParamsByActiveRuleId(activeRule.getId());
+ }
+
+ @CheckForNull
+ public ActiveRuleParamDto selectParamByKeyAndName(ActiveRuleKey key, String name, DbSession session) {
+ Preconditions.checkNotNull(key, ACTIVE_RULE_KEY_CANNOT_BE_NULL);
+ Preconditions.checkNotNull(name, PARAMETER_NAME_CANNOT_BE_NULL);
+ Optional<ActiveRuleDto> activeRule = selectByKey(session, key);
+ if (activeRule.isPresent()) {
+ return mapper(session).selectParamByActiveRuleAndKey(activeRule.get().getId(), name);
+ }
+ return null;
+ }
+
+ public void deleteParamsByRuleParam(DbSession dbSession, RuleDto rule, String paramKey) {
+ List<ActiveRuleDto> activeRules = selectByRule(dbSession, rule);
+ for (ActiveRuleDto activeRule : activeRules) {
+ for (ActiveRuleParamDto activeParam : selectParamsByActiveRuleKey(dbSession, activeRule.getKey())) {
+ if (activeParam.getKey().equals(paramKey)) {
+ deleteParam(dbSession, activeRule, activeParam);
+ }
+ }
+ }
+ }
+
+ private ActiveRuleMapper mapper(DbSession session) {
+ return session.getMapper(ActiveRuleMapper.class);
+ }
+}
public static final String INHERITED = ActiveRule.INHERITED;
public static final String OVERRIDES = ActiveRule.OVERRIDES;
- private String repository;
- private String ruleField;
- private String profileKey;
-
private Integer id;
private Integer profileId;
private Integer ruleId;
private Integer severity;
private String inheritance;
- //This field do not exists in db, it's only retrieve by joins
+
+ private long createdAtInMs;
+ private long updatedAtInMs;
+
+ //These fields do not exists in db, it's only retrieve by joins
private Integer parentId;
+ private String repository;
+ private String ruleField;
+ private String profileKey;
/**
* @deprecated for internal use, should be private
return profileId;
}
- // TODO mark as private
public ActiveRuleDto setProfileId(Integer profileId) {
this.profileId = profileId;
return this;
return ruleId;
}
- // TODO mark as private
public ActiveRuleDto setRuleId(Integer ruleId) {
this.ruleId = ruleId;
return this;
}
@CheckForNull
+ @Deprecated
public Integer getParentId() {
return parentId;
}
+ @Deprecated
public ActiveRuleDto setParentId(@Nullable Integer parentId) {
this.parentId = parentId;
return this;
return StringUtils.equals(OVERRIDES, inheritance);
}
+ public long getUpdatedAtInMs() {
+ return updatedAtInMs;
+ }
+
+ public ActiveRuleDto setUpdatedAtInMs(long updatedAtInMs) {
+ this.updatedAtInMs = updatedAtInMs;
+ return this;
+ }
+
+ public long getCreatedAtInMs() {
+ return createdAtInMs;
+ }
+
+ public ActiveRuleDto setCreatedAtInMs(long createdAtInMs) {
+ this.createdAtInMs = createdAtInMs;
+ return this;
+ }
+
public static ActiveRuleDto createFor(QualityProfileDto profileDto, RuleDto ruleDto) {
Preconditions.checkNotNull(profileDto.getId(), "Profile is not persisted");
Preconditions.checkNotNull(ruleDto.getId(), "Rule is not persisted");
import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
-import org.sonar.db.component.ComponentDto;
import org.sonar.db.RowNotFoundException;
+import org.sonar.db.component.ComponentDto;
@ServerSide
public class QualityProfileDao implements Dao {
}
}
- /**
- * @deprecated Replaced by
- * {@link #selectByKey(DbSession, String)}
- */
- @Deprecated
@CheckForNull
public QualityProfileDto selectById(DbSession session, int id) {
return mapper(session).selectById(id);
}
- /**
- * @deprecated Replaced by
- * {@link #selectByKey(DbSession, String)}
- */
- @Deprecated
@CheckForNull
public QualityProfileDto selectById(int id) {
DbSession session = mybatis.openSession(false);
r.plugin_name as "repository",
qp.kee as "profileKey",
a.created_at as "createdAt",
- a.updated_at as "updatedAt"
+ a.updated_at as "updatedAt",
+ a.created_at_ms as "createdAtInMs",
+ a.updated_at_ms as "updatedAtInMs"
</sql>
<sql id="activeRuleKeyJoin">
INNER JOIN rules r ON r.id = a.rule_id
</sql>
+ <!-- Should be removed when ActiveRuleDao v2 will be removed -->
<sql id="activeRuleColumns">
a.id,
a.profile_id as profileId,
a.inheritance as inheritance,
active_rule_parent.id as parentId,
a.created_at as "createdAt",
- a.updated_at as "updatedAt"
+ a.updated_at as "updatedAt",
+ a.created_at_ms as "createdAtInMs",
+ a.updated_at_ms as "updatedAtInMs"
</sql>
+ <!-- Should be removed when ActiveRuleDao v2 will be removed -->
<sql id="activeRuleJoin">
INNER JOIN rules_profiles qp ON qp.id=a.profile_id
LEFT JOIN rules_profiles profile_parent ON profile_parent.kee=qp.parent_kee
</select>
<insert id="insert" parameterType="ActiveRule" keyColumn="id" useGeneratedKeys="true" keyProperty="id">
- INSERT INTO active_rules (profile_id, rule_id, failure_level, inheritance, created_at, updated_at)
- VALUES (#{profileId}, #{ruleId}, #{severity}, #{inheritance}, #{createdAt}, #{updatedAt})
+ INSERT INTO active_rules (profile_id, rule_id, failure_level, inheritance, created_at, updated_at, created_at_ms, updated_at_ms)
+ VALUES (#{profileId}, #{ruleId}, #{severity}, #{inheritance}, #{createdAt}, #{updatedAt}, #{createdAtInMs}, #{updatedAtInMs})
</insert>
<update id="update" parameterType="ActiveRule">
rule_id=#{ruleId},
failure_level=#{severity},
inheritance=#{inheritance},
- updated_at=#{updatedAt}
+ updated_at=#{updatedAt},
+ updated_at_ms=#{updatedAtInMs}
WHERE id=#{id}
</update>
--- /dev/null
+/*
+ * 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.qualityprofile;
+
+// TODO
+public class ActiveRuleDaoTest {
+
+}