From: Sébastien Lesaint Date: Mon, 20 Mar 2017 09:39:05 +0000 (+0100) Subject: SONAR-8867 split insert/update of definition and metadata in DAO X-Git-Tag: 6.4-RC1~587 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=219bcb4ea74e0d46054755b712cba5e96de96e20;p=sonarqube.git SONAR-8867 split insert/update of definition and metadata in DAO --- diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java index 68a896175b0..a5b35e3cf6c 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java @@ -80,11 +80,54 @@ public class RuleDao implements Dao { } public void insert(DbSession session, RuleDto dto) { - mapper(session).insert(dto); + RuleDefinitionDto ruleDefinitionDto = definitionOf(dto); + mapper(session).insert(ruleDefinitionDto); + dto.setId(ruleDefinitionDto.getId()); + // FIXME it doesn't make sense to insert metadata when creating a new rule in table RULES unless it is a custom rule + mapper(session).updateMetadata(metadataOf(dto)); } public void update(DbSession session, RuleDto dto) { - mapper(session).update(dto); + mapper(session).updateDefinition(definitionOf(dto).setId(dto.getId())); + RuleMetadataDto ruleMetadata = metadataOf(dto); + mapper(session).updateMetadata(ruleMetadata); + } + + private static RuleMetadataDto metadataOf(RuleDto dto) { + return new RuleMetadataDto() + .setRuleId(dto.getId()) + .setNoteData(dto.getNoteData()) + .setNoteUserLogin(dto.getNoteUserLogin()) + .setNoteCreatedAt(dto.getNoteCreatedAt()) + .setNoteUpdatedAt(dto.getNoteUpdatedAt()) + .setRemediationFunction(dto.getRemediationFunction()) + .setRemediationGapMultiplier(dto.getRemediationGapMultiplier()) + .setRemediationBaseEffort(dto.getRemediationBaseEffort()) + .setTags(dto.getTags()) + .setUpdatedAt(dto.getUpdatedAt()); + } + + private static RuleDefinitionDto definitionOf(RuleDto dto) { + return new RuleDefinitionDto() + .setRepositoryKey(dto.getRepositoryKey()) + .setRuleKey(dto.getRuleKey()) + .setDescription(dto.getDescription()) + .setDescriptionFormat(dto.getDescriptionFormat()) + .setStatus(dto.getStatus()) + .setName(dto.getName()) + .setConfigKey(dto.getConfigKey()) + .setSeverity(dto.getSeverity()) + .setIsTemplate(dto.isTemplate()) + .setLanguage(dto.getLanguage()) + .setTemplateId(dto.getTemplateId()) + .setDefaultRemediationFunction(dto.getDefaultRemediationFunction()) + .setDefaultRemediationGapMultiplier(dto.getDefaultRemediationGapMultiplier()) + .setDefaultRemediationBaseEffort(dto.getDefaultRemediationBaseEffort()) + .setGapDescription(dto.getGapDescription()) + .setSystemTags(dto.getSystemTags()) + .setType(dto.getType()) + .setCreatedAt(dto.getCreatedAt()) + .setUpdatedAt(dto.getUpdatedAt()); } private static RuleMapper mapper(DbSession session) { diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDefinitionDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDefinitionDto.java new file mode 100644 index 00000000000..a5a9bafb476 --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDefinitionDto.java @@ -0,0 +1,319 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.db.rule; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.commons.lang.builder.HashCodeBuilder; +import org.apache.commons.lang.builder.ReflectionToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.rules.RuleType; + +import static com.google.common.base.Preconditions.checkArgument; + +public class RuleDefinitionDto { + + private Integer id; + private String repositoryKey; + private String ruleKey; + private String description; + private RuleDto.Format descriptionFormat; + private RuleStatus status; + private String name; + private String configKey; + private Integer severity; + private boolean isTemplate; + private String language; + private Integer templateId; + private String defRemediationFunction; + private String defRemediationGapMultiplier; + private String defRemediationBaseEffort; + private String gapDescription; + private String systemTags; + private int type; + + private RuleKey key; + + private long createdAt; + private long updatedAt; + + public RuleKey getKey() { + if (key == null) { + key = RuleKey.of(getRepositoryKey(), getRuleKey()); + } + return key; + } + + public Integer getId() { + return id; + } + + public RuleDefinitionDto setId(Integer id) { + this.id = id; + return this; + } + + public String getRepositoryKey() { + return repositoryKey; + } + + public RuleDefinitionDto setRepositoryKey(String s) { + checkArgument(s.length() <= 255, "Rule repository is too long: %s", s); + this.repositoryKey = s; + return this; + } + + public String getRuleKey() { + return ruleKey; + } + + public RuleDefinitionDto setRuleKey(String s) { + checkArgument(s.length() <= 200, "Rule key is too long: %s", s); + this.ruleKey = s; + return this; + } + + public String getDescription() { + return description; + } + + public RuleDefinitionDto setDescription(String description) { + this.description = description; + return this; + } + + public RuleDto.Format getDescriptionFormat() { + return descriptionFormat; + } + + public RuleDefinitionDto setDescriptionFormat(RuleDto.Format descriptionFormat) { + this.descriptionFormat = descriptionFormat; + return this; + } + + public RuleStatus getStatus() { + return status; + } + + public RuleDefinitionDto setStatus(@Nullable RuleStatus s) { + this.status = s; + return this; + } + + public String getName() { + return name; + } + + public RuleDefinitionDto setName(@Nullable String s) { + checkArgument(s == null || s.length() <= 255, "Rule name is too long: %s", s); + this.name = s; + return this; + } + + public String getConfigKey() { + return configKey; + } + + public RuleDefinitionDto setConfigKey(@Nullable String configKey) { + this.configKey = configKey; + return this; + } + + @CheckForNull + public Integer getSeverity() { + return severity; + } + + @CheckForNull + public String getSeverityString() { + return severity != null ? SeverityUtil.getSeverityFromOrdinal(severity) : null; + } + + public RuleDefinitionDto setSeverity(@Nullable String severity) { + return this.setSeverity(severity != null ? SeverityUtil.getOrdinalFromSeverity(severity) : null); + } + + public RuleDefinitionDto setSeverity(@Nullable Integer severity) { + this.severity = severity; + return this; + } + + public boolean isTemplate() { + return isTemplate; + } + + public RuleDefinitionDto setIsTemplate(boolean isTemplate) { + this.isTemplate = isTemplate; + return this; + } + + @CheckForNull + public String getLanguage() { + return language; + } + + public RuleDefinitionDto setLanguage(String language) { + this.language = language; + return this; + } + + @CheckForNull + public Integer getTemplateId() { + return templateId; + } + + public RuleDefinitionDto setTemplateId(@Nullable Integer templateId) { + this.templateId = templateId; + return this; + } + + @CheckForNull + public String getDefaultRemediationFunction() { + return defRemediationFunction; + } + + public RuleDefinitionDto setDefaultRemediationFunction(@Nullable String defaultRemediationFunction) { + this.defRemediationFunction = defaultRemediationFunction; + return this; + } + + @CheckForNull + public String getDefaultRemediationGapMultiplier() { + return defRemediationGapMultiplier; + } + + public RuleDefinitionDto setDefaultRemediationGapMultiplier(@Nullable String defaultRemediationGapMultiplier) { + this.defRemediationGapMultiplier = defaultRemediationGapMultiplier; + return this; + } + + @CheckForNull + public String getDefaultRemediationBaseEffort() { + return defRemediationBaseEffort; + } + + public RuleDefinitionDto setDefaultRemediationBaseEffort(@Nullable String defaultRemediationBaseEffort) { + this.defRemediationBaseEffort = defaultRemediationBaseEffort; + return this; + } + + @CheckForNull + public String getGapDescription() { + return gapDescription; + } + + public RuleDefinitionDto setGapDescription(@Nullable String s) { + this.gapDescription = s; + return this; + } + + public Set getSystemTags() { + return systemTags == null ? new HashSet<>() : new TreeSet<>(Arrays.asList(StringUtils.split(systemTags, ','))); + } + + private String getSystemTagsField() { + return systemTags; + } + + private void setSystemTagsField(String s) { + systemTags = s; + } + + public RuleDefinitionDto setSystemTags(Set tags) { + this.systemTags = tags.isEmpty() ? null : StringUtils.join(tags, ','); + return this; + } + + public int getType() { + return type; + } + + public RuleDefinitionDto setType(int type) { + this.type = type; + return this; + } + + public RuleDefinitionDto setType(RuleType type) { + this.type = type.getDbConstant(); + return this; + } + + public long getCreatedAt() { + return createdAt; + } + + public RuleDefinitionDto setCreatedAt(long createdAt) { + this.createdAt = createdAt; + return this; + } + + public long getUpdatedAt() { + return updatedAt; + } + + public RuleDefinitionDto setUpdatedAt(long updatedAt) { + this.updatedAt = updatedAt; + return this; + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof RuleDto)) { + return false; + } + if (this == obj) { + return true; + } + RuleDto other = (RuleDto) obj; + return new EqualsBuilder() + .append(repositoryKey, other.getRepositoryKey()) + .append(ruleKey, other.getRuleKey()) + .isEquals(); + } + + @Override + public int hashCode() { + return new HashCodeBuilder(17, 37) + .append(repositoryKey) + .append(ruleKey) + .toHashCode(); + } + + @Override + public String toString() { + return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString(); + } + + public static RuleDto createFor(RuleKey key) { + return new RuleDto() + .setRepositoryKey(key.repository()) + .setRuleKey(key.rule()); + } + +} + diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java index 5314b1d80a0..898a6fcb14c 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDto.java @@ -20,8 +20,8 @@ package org.sonar.db.rule; import java.util.Arrays; +import java.util.Collections; import java.util.Date; -import java.util.HashSet; import java.util.Set; import java.util.TreeSet; import javax.annotation.CheckForNull; @@ -316,11 +316,11 @@ public class RuleDto { } public Set getTags() { - return tags == null ? new HashSet<>() : new TreeSet<>(Arrays.asList(StringUtils.split(tags, ','))); + return tags == null ? Collections.emptySet() : new TreeSet<>(Arrays.asList(StringUtils.split(tags, ','))); } public Set getSystemTags() { - return systemTags == null ? new HashSet<>() : new TreeSet<>(Arrays.asList(StringUtils.split(systemTags, ','))); + return systemTags == null ? Collections.emptySet() : new TreeSet<>(Arrays.asList(StringUtils.split(systemTags, ','))); } private String getTagsField() { diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java index c6d16a708d9..faf89439578 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java @@ -41,9 +41,11 @@ public interface RuleMapper { List selectByQuery(@Param("query") RuleQuery ruleQuery); - void update(RuleDto rule); + void insert(RuleDefinitionDto ruleDefinitionDto); - void insert(RuleDto rule); + void updateDefinition(RuleDefinitionDto ruleDefinitionDto); + + void updateMetadata(RuleMetadataDto ruleMetadataDto); List selectParamsByRuleIds(@Param("ruleIds") List ruleIds); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMetadataDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMetadataDto.java new file mode 100644 index 00000000000..29ebe3da75f --- /dev/null +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMetadataDto.java @@ -0,0 +1,151 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.db.rule; + +import java.util.Arrays; +import java.util.Date; +import java.util.HashSet; +import java.util.Set; +import java.util.TreeSet; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.apache.commons.lang.StringUtils; + +import static com.google.common.base.Preconditions.checkArgument; + +public class RuleMetadataDto { + private int ruleId; + private String noteData; + private String noteUserLogin; + private Date noteCreatedAt; + private Date noteUpdatedAt; + private String remediationFunction; + private String remediationGapMultiplier; + private String remediationBaseEffort; + private String tags; + private long updatedAt; + + public int getRuleId() { + return ruleId; + } + + public RuleMetadataDto setRuleId(int ruleId) { + this.ruleId = ruleId; + return this; + } + + @CheckForNull + public String getNoteData() { + return noteData; + } + + public RuleMetadataDto setNoteData(@Nullable String s) { + this.noteData = s; + return this; + } + + @CheckForNull + public String getNoteUserLogin() { + return noteUserLogin; + } + + public RuleMetadataDto setNoteUserLogin(@Nullable String noteUserLogin) { + this.noteUserLogin = noteUserLogin; + return this; + } + + @CheckForNull + public Date getNoteCreatedAt() { + return noteCreatedAt; + } + + public RuleMetadataDto setNoteCreatedAt(@Nullable Date noteCreatedAt) { + this.noteCreatedAt = noteCreatedAt; + return this; + } + + @CheckForNull + public Date getNoteUpdatedAt() { + return noteUpdatedAt; + } + + public RuleMetadataDto setNoteUpdatedAt(@Nullable Date noteUpdatedAt) { + this.noteUpdatedAt = noteUpdatedAt; + return this; + } + + @CheckForNull + public String getRemediationFunction() { + return remediationFunction; + } + + public RuleMetadataDto setRemediationFunction(@Nullable String remediationFunction) { + this.remediationFunction = remediationFunction; + return this; + } + + @CheckForNull + public String getRemediationGapMultiplier() { + return remediationGapMultiplier; + } + + public RuleMetadataDto setRemediationGapMultiplier(@Nullable String remediationGapMultiplier) { + this.remediationGapMultiplier = remediationGapMultiplier; + return this; + } + + @CheckForNull + public String getRemediationBaseEffort() { + return remediationBaseEffort; + } + + public RuleMetadataDto setRemediationBaseEffort(@Nullable String remediationBaseEffort) { + this.remediationBaseEffort = remediationBaseEffort; + return this; + } + + public Set getTags() { + return tags == null ? new HashSet<>() : new TreeSet<>(Arrays.asList(StringUtils.split(tags, ','))); + } + + public RuleMetadataDto setTags(Set tags) { + String raw = tags.isEmpty() ? null : StringUtils.join(tags, ','); + checkArgument(raw == null || raw.length() <= 4000, "Rule tags are too long: %s", raw); + this.tags = raw; + return this; + } + + private String getTagsField() { + return tags; + } + + private void setTagsField(String s) { + tags = s; + } + + public long getUpdatedAt() { + return updatedAt; + } + + public RuleMetadataDto setUpdatedAt(long updatedAt) { + this.updatedAt = updatedAt; + return this; + } +} diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml index 8284b1b2c04..263c13afe7c 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml @@ -111,39 +111,7 @@ r.updated_at desc - - update rules set - plugin_rule_key=#{ruleKey,jdbcType=VARCHAR}, - plugin_name=#{repositoryKey,jdbcType=VARCHAR}, - description=#{description,jdbcType=VARCHAR}, - description_format=#{descriptionFormat,jdbcType=VARCHAR}, - status=#{status,jdbcType=VARCHAR}, - name=#{name,jdbcType=VARCHAR}, - plugin_config_key=#{configKey,jdbcType=VARCHAR}, - priority=#{severity,jdbcType=INTEGER}, - is_template=#{isTemplate,jdbcType=BOOLEAN}, - language=#{language,jdbcType=VARCHAR}, - template_id=#{templateId,jdbcType=INTEGER}, - note_data=#{noteData,jdbcType=CLOB}, - note_user_login=#{noteUserLogin,jdbcType=VARCHAR}, - note_created_at=#{noteCreatedAt,jdbcType=TIMESTAMP}, - note_updated_at=#{noteUpdatedAt,jdbcType=TIMESTAMP}, - remediation_function=#{remediationFunction,jdbcType=VARCHAR}, - def_remediation_function=#{defRemediationFunction,jdbcType=VARCHAR}, - remediation_gap_mult=#{remediationGapMultiplier,jdbcType=VARCHAR}, - def_remediation_gap_mult=#{defRemediationGapMultiplier,jdbcType=VARCHAR}, - remediation_base_effort=#{remediationBaseEffort,jdbcType=VARCHAR}, - def_remediation_base_effort=#{defRemediationBaseEffort,jdbcType=VARCHAR}, - gap_description=#{gapDescription,jdbcType=VARCHAR}, - tags=#{tagsField,jdbcType=VARCHAR}, - system_tags=#{systemTagsField,jdbcType=VARCHAR}, - rule_type=#{type,jdbcType=TINYINT}, - updated_at=#{updatedAt,jdbcType=BIGINT} - where - id=#{id,jdbcType=INTEGER} - - - + insert into rules ( plugin_rule_key, plugin_name, @@ -156,20 +124,12 @@ is_template, language, template_id, - remediation_function, def_remediation_function, - remediation_gap_mult, def_remediation_gap_mult, - remediation_base_effort, def_remediation_base_effort, gap_description, - tags, system_tags, rule_type, - note_data, - note_user_login, - note_created_at, - note_updated_at, created_at, updated_at ) @@ -185,25 +145,56 @@ #{isTemplate,jdbcType=BOOLEAN}, #{language,jdbcType=VARCHAR}, #{templateId,jdbcType=INTEGER}, - #{remediationFunction,jdbcType=VARCHAR}, #{defRemediationFunction,jdbcType=VARCHAR}, - #{remediationGapMultiplier,jdbcType=VARCHAR}, #{defRemediationGapMultiplier,jdbcType=VARCHAR}, - #{remediationBaseEffort,jdbcType=VARCHAR}, #{defRemediationBaseEffort,jdbcType=VARCHAR}, #{gapDescription,jdbcType=VARCHAR}, - #{tagsField,jdbcType=VARCHAR}, #{systemTagsField,jdbcType=VARCHAR}, #{type,jdbcType=TINYINT}, - #{noteData,jdbcType=CLOB}, - #{noteUserLogin,jdbcType=VARCHAR}, - #{noteCreatedAt,jdbcType=TIMESTAMP}, - #{noteUpdatedAt,jdbcType=TIMESTAMP}, #{createdAt,jdbcType=BIGINT}, #{updatedAt,jdbcType=BIGINT} ) + + update rules set + plugin_rule_key=#{ruleKey,jdbcType=VARCHAR}, + plugin_name=#{repositoryKey,jdbcType=VARCHAR}, + description=#{description,jdbcType=VARCHAR}, + description_format=#{descriptionFormat,jdbcType=VARCHAR}, + status=#{status,jdbcType=VARCHAR}, + name=#{name,jdbcType=VARCHAR}, + plugin_config_key=#{configKey,jdbcType=VARCHAR}, + priority=#{severity,jdbcType=INTEGER}, + is_template=#{isTemplate,jdbcType=BOOLEAN}, + language=#{language,jdbcType=VARCHAR}, + template_id=#{templateId,jdbcType=INTEGER}, + def_remediation_function=#{defRemediationFunction,jdbcType=VARCHAR}, + def_remediation_gap_mult=#{defRemediationGapMultiplier,jdbcType=VARCHAR}, + def_remediation_base_effort=#{defRemediationBaseEffort,jdbcType=VARCHAR}, + gap_description=#{gapDescription,jdbcType=VARCHAR}, + system_tags=#{systemTagsField,jdbcType=VARCHAR}, + rule_type=#{type,jdbcType=TINYINT}, + updated_at=#{updatedAt,jdbcType=BIGINT} + where + id=#{id,jdbcType=INTEGER} + + + + update rules set + note_data=#{noteData,jdbcType=CLOB}, + note_user_login=#{noteUserLogin,jdbcType=VARCHAR}, + note_created_at=#{noteCreatedAt,jdbcType=TIMESTAMP}, + note_updated_at=#{noteUpdatedAt,jdbcType=TIMESTAMP}, + remediation_function=#{remediationFunction,jdbcType=VARCHAR}, + remediation_gap_mult=#{remediationGapMultiplier,jdbcType=VARCHAR}, + remediation_base_effort=#{remediationBaseEffort,jdbcType=VARCHAR}, + tags=#{tagsField,jdbcType=VARCHAR}, + updated_at=#{updatedAt,jdbcType=BIGINT} + where + id=#{ruleId,jdbcType=INTEGER} + + delete from active_rule_parameters diff --git a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml index c75cc533f11..b862d51da43 100644 --- a/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml +++ b/server/sonar-db-dao/src/test/resources/org/sonar/db/rule/RuleDaoTest/update.xml @@ -1,8 +1,18 @@ - +