@Override
public void handleResult(ResultContext rc) {
IssueDto dto = (IssueDto) rc.getResultObject();
- dto.setSelectedAt(now);
+ dto.setSelectedAt(now.getTime());
initialOpenIssuesStack.addIssue(dto);
}
});
issue.setAssignee(users.next());
issue.setAuthorLogin(users.next());
issue.setLine(RandomUtils.nextInt());
- issue.setCreationDate(new Date());
- issue.setUpdateDate(new Date());
+ issue.setTechnicalCreationDate(new Date());
+ issue.setTechnicalUpdateDate(new Date());
issue.setFuncUpdateDate(new Date());
issue.setFuncCreationDate(new Date());
issue.setFuncCloseDate(null);
}
private void deleteFromIndices(String projectUuid) {
- // optimization : index issues is refreshed once at the end
+ // optimization : index "issues" is refreshed once at the end
issueAuthorizationIndexer.deleteProject(projectUuid, false);
issueIndexer.deleteProject(projectUuid, true);
sourceLineIndexer.deleteByProject(projectUuid);
package org.sonar.server.computation;
-import com.google.common.collect.ImmutableMap;
import org.sonar.core.component.ComponentDto;
import org.sonar.core.computation.db.AnalysisReportDto;
import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.issue.index.IssueNormalizer;
-import org.sonar.server.search.IndexClient;
-
-import java.util.Date;
+import org.sonar.server.issue.index.IssueAuthorizationIndexer;
+import org.sonar.server.issue.index.IssueIndexer;
public class IndexProjectIssuesStep implements ComputationStep {
- private final DbClient dbClient;
- private final IndexClient index;
- public IndexProjectIssuesStep(DbClient dbClient, IndexClient index) {
- this.dbClient = dbClient;
- this.index = index;
+ private final IssueAuthorizationIndexer authorizationIndexer;
+ private final IssueIndexer indexer;
+
+ public IndexProjectIssuesStep(IssueAuthorizationIndexer authorizationIndexer, IssueIndexer indexer) {
+ this.authorizationIndexer = authorizationIndexer;
+ this.indexer = indexer;
}
@Override
public void execute(DbSession session, AnalysisReportDto report, ComponentDto project) {
- indexProjectIssues(session, project);
+ authorizationIndexer.index();
+ indexer.index();
}
@Override
public String getDescription() {
return "Update issues index";
}
-
- private void indexProjectIssues(DbSession session, ComponentDto project) {
- dbClient.issueDao().synchronizeAfter(session,
- getLastIndexSynchronizationDate(project),
- parameters(project));
- session.commit();
- }
-
- private ImmutableMap<String, String> parameters(ComponentDto project) {
- return ImmutableMap.of(IssueNormalizer.IssueField.PROJECT.field(), project.uuid());
- }
-
- private Date getLastIndexSynchronizationDate(ComponentDto project) {
- return index.get(IssueIndex.class).getLastSynchronization(parameters(project));
- }
}
PopulateProjectsUuidColumnsMigration.class,
ReplaceIssueFiltersProjectKeyByUuid.class,
FeedSnapshotSourcesUpdatedAt.class,
- FeedFileSources.class
+ FeedFileSources.class,
+ FeedIssueLongDates.class
);
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.db.migrations.v50;
+
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.Database;
+import org.sonar.server.db.migrations.BaseDataChange;
+import org.sonar.server.db.migrations.MassUpdate;
+import org.sonar.server.db.migrations.Select;
+import org.sonar.server.db.migrations.SqlStatement;
+
+import java.sql.SQLException;
+import java.util.Date;
+
+public class FeedIssueLongDates extends BaseDataChange {
+
+ private final System2 system;
+
+ public FeedIssueLongDates(Database db, System2 system) {
+ super(db);
+ this.system = system;
+ }
+
+ @Override
+ public void execute(Context context) throws SQLException {
+ final long now = system.now();
+
+ MassUpdate massUpdate = context.prepareMassUpdate();
+ massUpdate.select("SELECT i.id, i.created_at, i.updated_at FROM issues i WHERE created_at_ms IS NULL");
+ massUpdate.update("UPDATE issues SET created_at_ms=?, updated_at_ms=? WHERE id=?");
+ massUpdate.rowPluralName("issues");
+ massUpdate.execute(new MassUpdate.Handler() {
+ @Override
+ public boolean handle(Select.Row row, SqlStatement update) throws SQLException {
+ Long id = row.getLong(1);
+ Date createdAt = row.getDate(2);
+ Date updatedAt = row.getDate(3);
+
+ update.setLong(1, Math.min(now, createdAt.getTime()));
+ update.setLong(2, Math.min(now, updatedAt.getTime()));
+ update.setLong(3, id);
+ return true;
+ }
+ });
+ }
+
+}
}
/**
- * Create a inner-field named "sort" with analyzer "sortable"
+ * Create an inner-field named "sort" with analyzer "sortable"
*/
public StringFieldBuilder enableSorting() {
this.sortable = true;
return this;
}
+ /**
+ * Create an inner-field named "words" with analyzer "words"
+ */
public StringFieldBuilder enableWordSearch() {
this.wordSearch = true;
return this;
}
+ /**
+ * Create a inner-field named "grams" with analyzer "grams"
+ */
public StringFieldBuilder enableGramSearch() {
this.gramSearch = true;
return this;
DbSession session = dbClient.openSession(false);
try {
- List<IssueDto> issueDtos = dbClient.issueDao().getByKeys(session, authorizedIssueKeys);
+ List<IssueDto> issueDtos = dbClient.issueDao().selectByKeys(session, authorizedIssueKeys);
return newArrayList(Iterables.transform(issueDtos, new Function<IssueDto, Issue>() {
@Override
public Issue apply(@Nullable IssueDto input) {
IssueDto getByKeyForUpdate(DbSession session, String key) {
// Load from index to check permission : if the user has no permission to see the issue an exception will be generated
Issue authorizedIssueIndex = getByKey(key);
- return dbClient.issueDao().getByKey(session, authorizedIssueIndex.key());
+ return dbClient.issueDao().selectByKey(session, authorizedIssueIndex.key());
}
void saveIssue(DbSession session, DefaultIssue issue, IssueChangeContext context, @Nullable String comment) {
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
import org.sonar.server.db.DbClient;
-
-import java.util.Date;
+import org.sonar.server.issue.index.IssueIndexer;
/**
* @since 3.6
public class ServerIssueStorage extends IssueStorage implements ServerComponent {
private final DbClient dbClient;
+ private final IssueIndexer indexer;
- public ServerIssueStorage(MyBatis mybatis, RuleFinder ruleFinder, DbClient dbClient) {
+ public ServerIssueStorage(MyBatis mybatis, RuleFinder ruleFinder, DbClient dbClient, IssueIndexer indexer) {
super(mybatis, ruleFinder);
this.dbClient = dbClient;
+ this.indexer = indexer;
}
@Override
- protected void doInsert(DbSession session, Date now, DefaultIssue issue) {
+ protected void doInsert(DbSession session, long now, DefaultIssue issue) {
ComponentDto component = component(session, issue);
ComponentDto project = project(session, issue);
int ruleId = ruleId(issue);
}
@Override
- protected void doUpdate(DbSession session, Date now, DefaultIssue issue) {
+ protected void doUpdate(DbSession session, long now, DefaultIssue issue) {
IssueDto dto = IssueDto.toDtoForUpdate(issue, project(session, issue).getId(), now);
dbClient.issueDao().update(session, dto);
}
+ @Override
+ protected void doAfterSave() {
+ indexer.index();
+ }
+
protected ComponentDto component(DbSession session, DefaultIssue issue) {
return dbClient.componentDao().getByKey(session, issue.componentKey());
}
*/
package org.sonar.server.issue.db;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Preconditions;
-import org.sonar.api.utils.System2;
import org.sonar.core.issue.db.IssueDto;
import org.sonar.core.issue.db.IssueMapper;
import org.sonar.core.persistence.DaoComponent;
import org.sonar.core.persistence.DbSession;
-import org.sonar.server.db.BaseDao;
-import org.sonar.server.issue.index.IssueNormalizer;
-import org.sonar.server.search.IndexDefinition;
+import org.sonar.core.persistence.MyBatis;
+import org.sonar.server.exceptions.NotFoundException;
-import javax.annotation.Nullable;
+import javax.annotation.CheckForNull;
import java.util.Collection;
-import java.util.Date;
import java.util.List;
-import java.util.Map;
-public class IssueDao extends BaseDao<IssueMapper, IssueDto, String> implements DaoComponent {
+public class IssueDao extends org.sonar.core.issue.db.IssueDao implements DaoComponent {
- public IssueDao() {
- this(System2.INSTANCE);
+ public IssueDao(MyBatis mybatis) {
+ super(mybatis);
}
- @VisibleForTesting
- public IssueDao(System2 system) {
- super(IndexDefinition.ISSUES, IssueMapper.class, system);
- }
-
- @Override
- protected IssueDto doGetNullableByKey(DbSession session, String key) {
+ @CheckForNull
+ public IssueDto selectNullableByKey(DbSession session, String key) {
return mapper(session).selectByKey(key);
}
- @Override
- protected List<IssueDto> doGetByKeys(DbSession session, Collection<String> keys) {
- return mapper(session).selectByKeys(keys);
+ public IssueDto selectByKey(DbSession session, String key) {
+ IssueDto issue = selectNullableByKey(session, key);
+ if (issue == null) {
+ throw new NotFoundException(String.format("Key '%s' not found", key));
+ }
+ return issue;
}
public List<IssueDto> findByActionPlan(DbSession session, String actionPlan) {
return mapper(session).selectByActionPlan(actionPlan);
}
- @Override
- protected IssueDto doUpdate(DbSession session, IssueDto issue) {
- mapper(session).update(issue);
- return issue;
+ public List<IssueDto> selectByKeys(DbSession session, Collection<String> keys) {
+ return mapper(session).selectByKeys(keys);
}
- @Override
- protected IssueDto doInsert(DbSession session, IssueDto issue) {
- Preconditions.checkNotNull(issue.getKey(), "Cannot insert Issue with empty key!");
- Preconditions.checkNotNull(issue.getComponentId(), "Cannot insert Issue with no Component!");
- mapper(session).insert(issue);
- return issue;
+ public void insert(DbSession session, IssueDto dto) {
+ mapper(session).insert(dto);
}
- @Override
- protected String getSynchronizationStatementName() {
- return "selectAfterDate";
+ public void insert(DbSession session, IssueDto dto, IssueDto... others) {
+ IssueMapper mapper = mapper(session);
+ mapper.insert(dto);
+ for (IssueDto other : others) {
+ mapper.insert(other);
+ }
}
- @Override
- protected Map<String, Object> getSynchronizationParams(@Nullable Date date, Map<String, String> params) {
- Map<String, Object> finalParams = super.getSynchronizationParams(date, params);
- finalParams.put(IssueNormalizer.IssueField.PROJECT.field(), params.get(IssueNormalizer.IssueField.PROJECT.field()));
- return finalParams;
+ public void update(DbSession session, IssueDto dto) {
+ mapper(session).update(dto);
}
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.issue.index;
+
+import org.sonar.core.persistence.Dto;
+
+public class FakeIssueDto extends Dto<String> {
+ @Override
+ public String getKey() {
+ throw new UnsupportedOperationException();
+ }
+}
@Override
public String componentUuid() {
- return getField(IssueNormalizer.IssueField.COMPONENT.field());
+ return getField(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID);
}
public String moduleUuid() {
- return getField(IssueNormalizer.IssueField.MODULE.field());
+ return getField(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID);
}
@Override
@Override
public String projectUuid() {
- return getField(IssueNormalizer.IssueField.PROJECT.field());
+ return getField(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID);
}
@Override
public RuleKey ruleKey() {
- return RuleKey.parse((String) getField(IssueNormalizer.IssueField.RULE_KEY.field()));
+ return RuleKey.parse((String) getField(IssueIndexDefinition.FIELD_ISSUE_RULE_KEY));
}
@Override
public String language() {
- return getField(IssueNormalizer.IssueField.LANGUAGE.field());
+ return getField(IssueIndexDefinition.FIELD_ISSUE_LANGUAGE);
}
@Override
public String severity() {
- return getField(IssueNormalizer.IssueField.SEVERITY.field());
+ return getField(IssueIndexDefinition.FIELD_ISSUE_SEVERITY);
}
@Override
@CheckForNull
public String message() {
- return getNullableField(IssueNormalizer.IssueField.MESSAGE.field());
+ return getNullableField(IssueIndexDefinition.FIELD_ISSUE_MESSAGE);
}
@Override
@CheckForNull
public Integer line() {
- return getNullableField(IssueNormalizer.IssueField.LINE.field());
+ return getNullableField(IssueIndexDefinition.FIELD_ISSUE_LINE);
}
@Override
@CheckForNull
public Double effortToFix() {
- return getNullableField(IssueNormalizer.IssueField.EFFORT.field());
+ return getNullableField(IssueIndexDefinition.FIELD_ISSUE_EFFORT);
}
@Override
public String status() {
- return getField(IssueNormalizer.IssueField.STATUS.field());
+ return getField(IssueIndexDefinition.FIELD_ISSUE_STATUS);
}
@Override
@CheckForNull
public String resolution() {
- return getNullableField(IssueNormalizer.IssueField.RESOLUTION.field());
+ return getNullableField(IssueIndexDefinition.FIELD_ISSUE_RESOLUTION);
}
@Override
@CheckForNull
public String reporter() {
- return getNullableField(IssueNormalizer.IssueField.REPORTER.field());
+ return getNullableField(IssueIndexDefinition.FIELD_ISSUE_REPORTER);
}
@Override
@CheckForNull
public String assignee() {
- return getNullableField(IssueNormalizer.IssueField.ASSIGNEE.field());
+ return getNullableField(IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE);
}
+ /**
+ * Functional date
+ */
@Override
public Date creationDate() {
- return getFieldAsDate(IssueNormalizer.IssueField.ISSUE_CREATED_AT.field());
+ return getFieldAsDate(IssueIndexDefinition.FIELD_ISSUE_FUNC_CREATED_AT);
}
+ /**
+ * Functional date
+ */
@Override
public Date updateDate() {
- return getFieldAsDate(IssueNormalizer.IssueField.ISSUE_UPDATED_AT.field());
+ return getFieldAsDate(IssueIndexDefinition.FIELD_ISSUE_FUNC_UPDATED_AT);
}
@Override
@CheckForNull
public Date closeDate() {
- return getNullableFieldAsDate(IssueNormalizer.IssueField.ISSUE_CLOSE_DATE.field());
+ return getNullableFieldAsDate(IssueIndexDefinition.FIELD_ISSUE_FUNC_CLOSED_AT);
}
@Override
@Override
public Map<String, String> attributes() {
- String data = getNullableField(IssueNormalizer.IssueField.ATTRIBUTES.field());
+ String data = getNullableField(IssueIndexDefinition.FIELD_ISSUE_ATTRIBUTES);
if (data == null) {
return Collections.emptyMap();
} else {
@Override
@CheckForNull
public String authorLogin() {
- return getNullableField(IssueNormalizer.IssueField.AUTHOR_LOGIN.field());
+ return getNullableField(IssueIndexDefinition.FIELD_ISSUE_AUTHOR_LOGIN);
}
@Override
@CheckForNull
public String actionPlanKey() {
- return getNullableField(IssueNormalizer.IssueField.ACTION_PLAN.field());
+ return getNullableField(IssueIndexDefinition.FIELD_ISSUE_ACTION_PLAN);
}
@Override
@Override
@CheckForNull
public Duration debt() {
- Number debt = getNullableField(IssueNormalizer.IssueField.DEBT.field());
+ Number debt = getNullableField(IssueIndexDefinition.FIELD_ISSUE_DEBT);
return (debt != null) ? Duration.create(debt.longValue()) : null;
}
@CheckForNull
public String filePath() {
- return getNullableField(IssueNormalizer.IssueField.FILE_PATH.field());
+ return getNullableField(IssueIndexDefinition.FIELD_ISSUE_FILE_PATH);
}
public void setKey(@Nullable String s) {
setField(IssueIndexDefinition.FIELD_ISSUE_ASSIGNEE, s);
}
- public void setCreationDate(@Nullable Date d) {
- setField(IssueIndexDefinition.FIELD_ISSUE_CREATED_AT, d);
+ public void setTechnicalCreationDate(@Nullable Date d) {
+ setField(IssueIndexDefinition.FIELD_ISSUE_TECHNICAL_CREATED_AT, d);
}
- public void setUpdateDate(@Nullable Date d) {
- setField(IssueIndexDefinition.FIELD_ISSUE_UPDATED_AT, d);
+ public void setFuncUpdateDate(@Nullable Date d) {
+ setField(IssueIndexDefinition.FIELD_ISSUE_FUNC_UPDATED_AT, d);
}
public void setFuncCreationDate(@Nullable Date d) {
setField(IssueIndexDefinition.FIELD_ISSUE_FUNC_CREATED_AT, d);
}
- public void setFuncUpdateDate(@Nullable Date d) {
- setField(IssueIndexDefinition.FIELD_ISSUE_FUNC_UPDATED_AT, d);
+ public void setTechnicalUpdateDate(@Nullable Date d) {
+ setField(IssueIndexDefinition.FIELD_ISSUE_TECHNICAL_UPDATED_AT, d);
}
public void setFuncCloseDate(@Nullable Date d) {
import org.elasticsearch.search.sort.SortOrder;
import org.sonar.api.issue.Issue;
import org.sonar.api.rule.Severity;
-import org.sonar.core.issue.db.IssueDto;
import org.sonar.server.issue.IssueQuery;
import org.sonar.server.issue.filter.IssueFilterParameters;
import org.sonar.server.search.BaseIndex;
import org.sonar.server.user.UserSession;
import javax.annotation.Nullable;
-
import java.util.Collection;
import java.util.Date;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
-public class IssueIndex extends BaseIndex<Issue, IssueDto, String> {
+public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> {
private static final String FACET_SUFFIX_MISSING = "_missing";
private ListMultimap<String, IndexField> sortColumns = ArrayListMultimap.create();
- public IssueIndex(IssueNormalizer normalizer, SearchClient client) {
- super(IndexDefinition.ISSUES, normalizer, client);
+ public IssueIndex(SearchClient client) {
+ super(IndexDefinition.ISSUES, null, client);
sortColumns.put(IssueQuery.SORT_BY_ASSIGNEE, IssueNormalizer.IssueField.ASSIGNEE);
sortColumns.put(IssueQuery.SORT_BY_STATUS, IssueNormalizer.IssueField.STATUS);
return null;
}
- @Override
- protected FilterBuilder getLastSynchronizationBuilder(Map<String, String> params) {
- String projectUuid = params.get(IssueNormalizer.IssueField.PROJECT.field());
- if (projectUuid != null) {
- return FilterBuilders.boolFilter().must(FilterBuilders.termsFilter(IssueNormalizer.IssueField.PROJECT.field(), projectUuid));
- }
- return super.getLastSynchronizationBuilder(params);
- }
-
public List<FacetValue> listAssignees(IssueQuery query) {
QueryContext queryContext = new QueryContext().setPage(1, 0);
import org.sonar.process.ProcessConstants;
import org.sonar.server.es.IndexDefinition;
import org.sonar.server.es.NewIndex;
-import org.sonar.server.search.BaseNormalizer;
/**
* Definition of ES index "issues", including settings and fields.
public static final String FIELD_AUTHORIZATION_PROJECT_UUID = "project";
public static final String FIELD_AUTHORIZATION_GROUPS = "groups";
public static final String FIELD_AUTHORIZATION_USERS = "users";
- public static final String FIELD_AUTHORIZATION_UPDATED_AT = BaseNormalizer.UPDATED_AT_FIELD;
+ public static final String FIELD_AUTHORIZATION_UPDATED_AT = "updatedAt";
public static final String FIELD_ISSUE_ACTION_PLAN = "actionPlan";
public static final String FIELD_ISSUE_ASSIGNEE = "assignee";
public static final String FIELD_ISSUE_ATTRIBUTES = "attributes";
public static final String FIELD_ISSUE_AUTHOR_LOGIN = "authorLogin";
public static final String FIELD_ISSUE_COMPONENT_UUID = "component";
- public static final String FIELD_ISSUE_CREATED_AT = "createdAt";
+ /**
+ * Technical date
+ */
+ public static final String FIELD_ISSUE_TECHNICAL_CREATED_AT = "createdAt";
public static final String FIELD_ISSUE_DEBT = "debt";
public static final String FIELD_ISSUE_EFFORT = "effort";
public static final String FIELD_ISSUE_FILE_PATH = "filePath";
+ /**
+ * Functional date
+ */
public static final String FIELD_ISSUE_FUNC_CREATED_AT = "issueCreatedAt";
+ /**
+ * Functional date
+ */
public static final String FIELD_ISSUE_FUNC_UPDATED_AT = "issueUpdatedAt";
+ /**
+ * Functional date
+ */
public static final String FIELD_ISSUE_FUNC_CLOSED_AT = "issueClosedAt";
public static final String FIELD_ISSUE_KEY = "key";
public static final String FIELD_ISSUE_LANGUAGE = "language";
public static final String FIELD_ISSUE_SEVERITY = "severity";
public static final String FIELD_ISSUE_SEVERITY_VALUE = "severityValue";
public static final String FIELD_ISSUE_STATUS = "status";
- public static final String FIELD_ISSUE_UPDATED_AT = "updatedAt";
+ /**
+ * Technical date
+ */
+ public static final String FIELD_ISSUE_TECHNICAL_UPDATED_AT = "updatedAt";
private final Settings settings;
// TODO do we really sort by status ? If yes, then we should sort by "int value", but not by string key
issueMapping.stringFieldBuilder(FIELD_ISSUE_STATUS).enableSorting().build();
// TODO is createdAt required ?
- issueMapping.createDateTimeField(FIELD_ISSUE_CREATED_AT);
- issueMapping.createDateTimeField(FIELD_ISSUE_UPDATED_AT);
+ issueMapping.createDateTimeField(FIELD_ISSUE_TECHNICAL_CREATED_AT);
+ issueMapping.createDateTimeField(FIELD_ISSUE_TECHNICAL_UPDATED_AT);
}
}
@Override
protected long doIndex(long lastUpdatedAt) {
- final BulkIndexer bulk = createBulkIndexer(lastUpdatedAt == 0L);
+ return doIndex(createBulkIndexer(false), lastUpdatedAt);
+ }
+
+ public void indexAll() {
+ doIndex(createBulkIndexer(true), 0L);
+ }
+ /**
+ * For benchmarks
+ */
+ public void index(Iterator<IssueDoc> issues) {
+ doIndex(createBulkIndexer(false), issues);
+ }
+
+ private long doIndex(BulkIndexer bulk, long lastUpdatedAt) {
DbSession dbSession = dbClient.openSession(false);
Connection dbConnection = dbSession.getConnection();
long maxDate;
}
}
- public void index(Iterator<IssueDoc> issues) {
- final BulkIndexer bulk = createBulkIndexer(false);
- doIndex(bulk, issues);
- }
-
- long doIndex(BulkIndexer bulk, Iterator<IssueDoc> issues) {
+ private long doIndex(BulkIndexer bulk, Iterator<IssueDoc> issues) {
bulk.start();
long maxDate = 0L;
while (issues.hasNext()) {
*/
package org.sonar.server.issue.index;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
import org.elasticsearch.action.update.UpdateRequest;
-import org.sonar.api.rule.Severity;
-import org.sonar.core.issue.db.IssueDto;
+import org.sonar.core.persistence.Dto;
import org.sonar.server.db.DbClient;
import org.sonar.server.search.BaseNormalizer;
import org.sonar.server.search.IndexField;
import org.sonar.server.search.Indexable;
import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import static com.google.common.collect.Maps.newHashMap;
-
-public class IssueNormalizer extends BaseNormalizer<IssueDto, String> {
+public class IssueNormalizer extends BaseNormalizer {
public IssueNormalizer(DbClient db) {
super(db);
}
+ @Override
+ public List<UpdateRequest> normalize(Dto dto) {
+ throw new UnsupportedOperationException();
+ }
+
public static final class IssueField extends Indexable {
public static final IndexField KEY = addSortable(IndexField.Type.STRING, "key");
public static final IndexField LANGUAGE = add(IndexField.Type.STRING, "language");
public static final IndexField RULE_KEY = add(IndexField.Type.STRING, "ruleKey");
public static final IndexField FILE_PATH = addSortable(IndexField.Type.STRING, "filePath");
-
- public static final Set<IndexField> ALL_FIELDS = ImmutableSet.of(KEY, CREATED_AT, UPDATED_AT, PROJECT, COMPONENT,
- MODULE, MODULE_PATH, ACTION_PLAN, ASSIGNEE, ATTRIBUTES, AUTHOR_LOGIN, DEBT, EFFORT, ISSUE_CREATED_AT,
- ISSUE_UPDATED_AT, ISSUE_CLOSE_DATE, LINE, MESSAGE, RESOLUTION, REPORTER, STATUS, SEVERITY, SEVERITY_VALUE,
- LANGUAGE, RULE_KEY, FILE_PATH);
}
- @Override
- public List<UpdateRequest> normalize(IssueDto dto) {
- Map<String, Object> update = newHashMap();
-
- Preconditions.checkNotNull(dto.getProjectUuid(), "Project uuid is null on issue %s", dto.getKey());
- Preconditions.checkNotNull(dto.getComponentUuid(), "Component uuid is null on issue %s", dto.getKey());
-
- update.put("_parent", dto.getProjectUuid());
- update.put(IssueField.KEY.field(), dto.getKey());
- update.put(IssueField.UPDATED_AT.field(), dto.getUpdatedAt());
- update.put(IssueField.CREATED_AT.field(), dto.getCreatedAt());
-
- update.put(IssueField.PROJECT.field(), dto.getProjectUuid());
- update.put(IssueField.COMPONENT.field(), dto.getComponentUuid());
- update.put(IssueField.MODULE.field(), dto.getModuleUuid());
- update.put(IssueField.MODULE_PATH.field(), dto.getModuleUuidPath());
-
- update.put(IssueField.ACTION_PLAN.field(), dto.getActionPlanKey());
- update.put(IssueField.ATTRIBUTES.field(), dto.getIssueAttributes());
- update.put(IssueField.ASSIGNEE.field(), dto.getAssignee());
- update.put(IssueField.AUTHOR_LOGIN.field(), dto.getAuthorLogin());
- update.put(IssueField.ISSUE_CLOSE_DATE.field(), dto.getIssueCloseDate());
- update.put(IssueField.ISSUE_CREATED_AT.field(), dto.getIssueCreationDate());
- update.put(IssueField.ISSUE_UPDATED_AT.field(), dto.getIssueUpdateDate());
- update.put(IssueField.EFFORT.field(), dto.getEffortToFix());
- update.put(IssueField.RESOLUTION.field(), dto.getResolution());
- update.put(IssueField.LINE.field(), dto.getLine());
- update.put(IssueField.MESSAGE.field(), dto.getMessage());
- update.put(IssueField.REPORTER.field(), dto.getReporter());
- update.put(IssueField.STATUS.field(), dto.getStatus());
- update.put(IssueField.SEVERITY.field(), dto.getSeverity());
- update.put(IssueField.SEVERITY_VALUE.field(), Severity.ALL.indexOf(dto.getSeverity()));
- update.put(IssueField.DEBT.field(), dto.getDebt());
- update.put(IssueField.LANGUAGE.field(), dto.getLanguage());
- update.put(IssueField.RULE_KEY.field(), dto.getRuleKey().toString());
- update.put(IssueField.FILE_PATH.field(), dto.getFilePath());
-
- /** Upsert elements */
- Map<String, Object> upsert = getUpsertFor(IssueField.ALL_FIELDS, update);
- upsert.put(IssueField.KEY.field(), dto.getKey());
-
- return ImmutableList.of(
- new UpdateRequest()
- .id(dto.getKey())
- .routing(dto.getProjectUuid())
- .parent(dto.getProjectUuid())
- .doc(update)
- .upsert(upsert));
- }
}
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.Timestamp;
import java.util.Date;
/**
String sql = afterDate > 0L ? SQL_AFTER_DATE : SQL_ALL;
PreparedStatement stmt = dbClient.newScrollingSelectStatement(connection, sql);
if (afterDate > 0L) {
- stmt.setTimestamp(1, new Timestamp(afterDate));
+ stmt.setLong(1, afterDate);
}
return new IssueResultSetIterator(stmt);
} catch (SQLException e) {
// all the keys must be present, even if value is null
doc.setKey(key);
doc.setProjectUuid(projectUuid);
- doc.setUpdateDate(SqlUtil.getDate(rs, 3));
- doc.setCreationDate(new Date(rs.getTimestamp(4).getTime()));
+ doc.setTechnicalUpdateDate(new Date(rs.getLong(3)));
+ doc.setTechnicalCreationDate(new Date(rs.getLong(4)));
doc.setActionPlanKey(rs.getString(5));
doc.setAssignee(rs.getString(6));
doc.setEffortToFix(SqlUtil.getDouble(rs, 7));
*/
package org.sonar.server.search;
-import com.google.common.collect.ImmutableMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.db.Dao;
import org.sonar.server.db.DbClient;
import org.sonar.server.issue.index.IssueAuthorizationIndexer;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.issue.index.IssueNormalizer;
+import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.qualityprofile.index.ActiveRuleIndex;
import org.sonar.server.rule.index.RuleIndex;
import org.sonar.server.source.index.SourceLineIndexer;
import java.util.Date;
-import java.util.List;
-import java.util.Map;
/**
* @since 4.4
private final IndexClient index;
private final SourceLineIndexer sourceLineIndexer;
private final IssueAuthorizationIndexer issueAuthorizationIndexer;
+ private final IssueIndexer issueIndexer;
public IndexSynchronizer(DbClient db, IndexClient index, SourceLineIndexer sourceLineIndexer,
- IssueAuthorizationIndexer issueAuthorizationIndexer) {
+ IssueAuthorizationIndexer issueAuthorizationIndexer, IssueIndexer issueIndexer) {
this.db = db;
this.index = index;
this.sourceLineIndexer = sourceLineIndexer;
this.issueAuthorizationIndexer = issueAuthorizationIndexer;
+ this.issueIndexer = issueIndexer;
}
public void execute() {
/* synchronize all activeRules until we have mng tables in INDEX */
DbSession session = db.openSession(true);
try {
- List<String> projectUuids = db.componentDao().findProjectUuids(session);
synchronize(session, db.ruleDao(), index.get(RuleIndex.class));
- issueAuthorizationIndexer.index();
- synchronizeByProject(session, db.issueDao(), index.get(IssueIndex.class),
- IssueNormalizer.IssueField.PROJECT.field(), projectUuids);
synchronize(session, db.activeRuleDao(), index.get(ActiveRuleIndex.class));
synchronize(session, db.activityDao(), index.get(ActivityIndex.class));
- LOG.info("Indexing of sourceLine records");
+ LOG.info("Indexing issues");
+ issueAuthorizationIndexer.index();
+ issueIndexer.indexAll();
+
+ LOG.info("Indexing source files");
sourceLineIndexer.index();
session.commit();
dao.synchronizeAfter(session, lastSynch);
}
}
-
- void synchronizeByProject(DbSession session, Dao dao, Index index, String projectField, List<String> projectUuids) {
- Long count = index.getIndexStat().getDocumentCount();
- if (count <= 0) {
- LOG.info("Initial indexing of {} records", index.getIndexType());
- dao.synchronizeAfter(session);
- } else {
- LOG.info("Synchronizing {} records for updates", index.getIndexType());
- for (String projectUuid : projectUuids) {
- Map<String, String> params = ImmutableMap.of(projectField, projectUuid);
- dao.synchronizeAfter(session, index.getLastSynchronization(params), params);
- }
- }
- }
}
import org.sonar.server.issue.IssueTesting;
import org.sonar.server.issue.db.IssueDao;
import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.PermissionChange;
import org.sonar.server.rule.RuleTesting;
tester.get(IssueDao.class).insert(session, IssueTesting.newDto(rule, file, project));
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
assertThat(tester.get(IssueIndex.class).countAll()).isEqualTo(1);
import org.sonar.api.security.DefaultGroups;
import org.sonar.api.web.UserRole;
import org.sonar.core.component.ComponentDto;
-import org.sonar.core.issue.db.IssueDto;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.issue.IssueTesting;
-import org.sonar.server.issue.index.IssueIndex;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.PermissionChange;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.IndexDefinition;
-import org.sonar.server.search.SearchClient;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
ComponentDto file = ComponentTesting.newFileDto(project).setKey("sample:root:src/File.xoo");
tester.get(ComponentDao.class).insert(session, file);
- IssueDto issue = IssueTesting.newDto(rule, file, project);
- db.issueDao().insert(session, issue);
-
session.commit();
MockUserSession.set().setLogin("john").addComponentPermission(UserRole.ADMIN, project.key(), project.key());
assertThat(service.getNullableByKey(file.key())).isNull();
assertThat(service.getNullableByKey("sample2:root:src/File.xoo")).isNotNull();
- // Check issues are still here
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentUuid()).isEqualTo(file.uuid());
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectUuid()).isEqualTo(project.uuid());
-
- // Check that no new issue has been added
- assertThat(tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES.getIndexName()).setTypes(IndexDefinition.ISSUES.getIndexType()).get().getCount()).isEqualTo(1);
-
// Check dry run cache have been updated
assertThat(db.propertiesDao().selectProjectProperties("sample2:root", session)).hasSize(1);
}
ComponentDto file = ComponentTesting.newFileDto(module).setKey("sample:root:module:src/File.xoo");
tester.get(ComponentDao.class).insert(session, file);
- IssueDto issue = IssueTesting.newDto(rule, file, project);
- db.issueDao().insert(session, issue);
-
session.commit();
MockUserSession.set().setLogin("john").addComponentPermission(UserRole.ADMIN, project.key(), module.key());
assertThat(service.getNullableByKey(file.key())).isNull();
assertThat(service.getNullableByKey("sample:root2:module:src/File.xoo")).isNotNull();
- // Check issues are still here
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentUuid()).isEqualTo(file.uuid());
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectUuid()).isEqualTo(project.uuid());
-
// Check dry run cache have been updated -> on a module it's the project cache that is updated
assertThat(db.propertiesDao().selectProjectProperties(project.key(), session)).hasSize(1);
}
ComponentDto file = ComponentTesting.newFileDto(module).setKey("sample:root:module:src/File.xoo");
tester.get(ComponentDao.class).insert(session, file);
- IssueDto issue = IssueTesting.newDto(rule, file, project);
- db.issueDao().insert(session, issue);
-
session.commit();
MockUserSession.set().setLogin("john").addProjectPermissions(UserRole.ADMIN, project.key());
assertThat(service.getNullableByKey(file.key())).isNull();
assertThat(service.getNullableByKey("sample2:root:module:src/File.xoo")).isNotNull();
- // Check issues are still here
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).componentUuid()).isEqualTo(file.uuid());
- assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey()).projectUuid()).isEqualTo(project.uuid());
-
- // Check that no new issue has been added
- assertThat(tester.get(SearchClient.class).prepareCount(IndexDefinition.ISSUES.getIndexName()).setTypes(IndexDefinition.ISSUES.getIndexType()).get().getCount()).isEqualTo(1);
-
// Check dry run cache have been updated
assertThat(db.propertiesDao().selectProjectProperties("sample2:root", session)).hasSize(1);
}
.setEnabled(true);
}
+ public static ComponentDto newFileDto(ComponentDto module, String fileUuid) {
+ return new ComponentDto()
+ .setUuid(fileUuid)
+ .setProjectUuid(module.projectUuid())
+ .setModuleUuid(module.uuid())
+ .setModuleUuidPath(module.moduleUuidPath() == null ? module.uuid() : module.moduleUuidPath() + "." + module.uuid())
+ .setKey("KEY_" + fileUuid)
+ .setName("NAME_" + fileUuid)
+ .setLongName("LONG_NAME_" + fileUuid)
+ .setParentProjectId(module.getId())
+ .setScope(Scopes.FILE)
+ .setQualifier(Qualifiers.FILE)
+ .setPath("src/main/xoo/org/sonar/samples/File.xoo")
+ .setLanguage("xoo")
+ .setEnabled(true);
+ }
+
public static ComponentDto newModuleDto(ComponentDto subProjectOrProject) {
return new ComponentDto()
.setUuid(Uuids.create())
.setEnabled(true);
}
+ public static ComponentDto newProjectDto(String uuid) {
+ return new ComponentDto()
+ .setUuid(uuid)
+ .setProjectUuid(uuid)
+ .setKey("KEY_" + uuid)
+ .setName("NAME_" + uuid)
+ .setLongName("LONG_NAME_" + uuid)
+ .setParentProjectId(null)
+ .setScope(Scopes.PROJECT)
+ .setQualifier(Qualifiers.PROJECT)
+ .setPath(null)
+ .setLanguage(null)
+ .setEnabled(true);
+ }
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+package org.sonar.server.db.migrations.v50;
+
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.TestDatabase;
+import org.sonar.server.db.migrations.DatabaseMigration;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class FeedIssueLongDatesTest {
+
+ @ClassRule
+ public static TestDatabase db = new TestDatabase().schema(FeedIssueLongDatesTest.class, "schema.sql");
+
+ @Test
+ public void execute() throws Exception {
+ db.prepareDbUnit(getClass(), "before.xml");
+
+ System2 system = mock(System2.class);
+ when(system.now()).thenReturn(1500000000000L);
+ DatabaseMigration migration = new FeedIssueLongDates(db.database(), system);
+ migration.execute();
+
+ int count = db.count("select count(*) from issues where created_at_ms is not null and updated_at_ms is not null");
+ assertThat(count).isEqualTo(2);
+ }
+
+}
import org.sonar.core.component.ComponentDto;
import org.sonar.core.issue.db.IssueDto;
import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.permission.PermissionFacade;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.rule.RuleDto;
import org.sonar.core.user.UserDto;
import org.sonar.server.component.db.SnapshotDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.issue.db.IssueDao;
+import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.PermissionChange;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.user.MockUserSession;
import org.sonar.server.user.UserSession;
-import java.util.Date;
import java.util.List;
import java.util.Map;
IssueDto issue2 = IssueTesting.newDto(rule, file, project).setAssignee("simon");
tester.get(IssueDao.class).insert(session, issue1, issue2);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
Map<String, Object> properties = newHashMap();
properties.put("issues", issue1.getKey() + "," + issue2.getKey());
issueKeys.add(issue.getKey());
}
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
Map<String, Object> properties = newHashMap();
properties.put("issues", Joiner.on(",").join(issueKeys));
org.sonar.server.search.Result<Issue> result = mock(org.sonar.server.search.Result.class);
when(result.getHits()).thenReturn(newArrayList((Issue) issue));
when(issueService.search(any(IssueQuery.class), any(QueryContext.class))).thenReturn(result);
- when(issueDao.getByKeys(dbSession, newArrayList(issue.key()))).thenReturn(newArrayList(issueDto));
+ when(issueDao.selectByKeys(dbSession, newArrayList(issue.key()))).thenReturn(newArrayList(issueDto));
actions = newArrayList();
service = new IssueBulkChangeService(dbClient, issueService, issueStorage, ruleFinder, issueNotifications, actions, mock(PreviewCache.class));
org.sonar.server.search.Result<Issue> resultIssues = mock(org.sonar.server.search.Result.class);
when(resultIssues.getHits()).thenReturn(Lists.<Issue>newArrayList(issueDto1.toDefaultIssue(), issueDto2.toDefaultIssue()));
when(issueService.search(any(IssueQuery.class), any(QueryContext.class))).thenReturn(resultIssues);
- when(issueDao.getByKeys(dbSession, newArrayList("ABCD", "EFGH"))).thenReturn(newArrayList(issueDto1, issueDto2));
+ when(issueDao.selectByKeys(dbSession, newArrayList("ABCD", "EFGH"))).thenReturn(newArrayList(issueDto1, issueDto2));
Map<String, Object> properties = newHashMap();
properties.put("issues", "ABCD,EFGH");
import org.sonar.core.component.ComponentDto;
import org.sonar.core.issue.db.IssueDto;
import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.permission.PermissionFacade;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.component.ComponentTesting;
import org.sonar.server.component.db.SnapshotDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.issue.db.IssueDao;
+import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.PermissionChange;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.tester.ServerTester;
import org.sonar.server.user.MockUserSession;
-import java.util.Date;
import java.util.List;
import static org.fest.assertions.Assertions.assertThat;
IssueDto issue = IssueTesting.newDto(rule, file, project);
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
service.addComment(issue.getKey(), "my comment", MockUserSession.get());
IssueDto issue = IssueTesting.newDto(removedRule, file, project).setStatus(Issue.STATUS_CLOSED).setResolution(Issue.RESOLUTION_REMOVED);
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
service.addComment(issue.getKey(), "my comment", MockUserSession.get());
import org.sonar.server.issue.db.IssueDao;
import org.sonar.server.issue.index.IssueDoc;
import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.PermissionChange;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.user.MockUserSession;
import java.util.Arrays;
-import java.util.Date;
import java.util.List;
import java.util.Map;
session.close();
}
+ private void index() {
+ tester.get(IssueIndexer.class).indexAll();
+ }
+
@Test
public void get_by_key() throws Exception {
IssueDto issue = newIssue();
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ index();
assertThat(service.getByKey(issue.getKey())).isNotNull();
}
IssueDto issue2 = newIssue().setActionPlanKey("P2").setResolution("NONE");
tester.get(IssueDao.class).insert(session, issue1, issue2);
session.commit();
+ index();
org.sonar.server.search.Result<Issue> result = service.search(IssueQuery.builder().build(), new QueryContext());
assertThat(result.getHits()).hasSize(2);
IssueDto issue = newIssue().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_FALSE_POSITIVE);
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ index();
List<Transition> result = service.listTransitions(issue.getKey());
assertThat(result).hasSize(1);
IssueDto issue = newIssue().setStatus(Issue.STATUS_OPEN);
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ index();
- assertThat(db.issueDao().getByKey(session, issue.getKey())).isNotNull();
+ assertThat(db.issueDao().selectByKey(session, issue.getKey())).isNotNull();
IssueTesting.assertIsEquivalent(issue, (IssueDoc) indexClient.get(IssueIndex.class).getByKey(issue.getKey()));
assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).status()).isEqualTo(Issue.STATUS_OPEN);
UserDto user = new UserDto().setLogin("perceval").setName("Perceval");
db.userDao().insert(session, user);
session.commit();
+ index();
assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isNull();
}
@Test
- public void un_assign() {
+ public void unassign() {
IssueDto issue = newIssue().setAssignee("perceval");
tester.get(IssueDao.class).insert(session, issue);
UserDto user = new UserDto().setLogin("perceval").setName("Perceval");
db.userDao().insert(session, user);
session.commit();
+ index();
assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).assignee()).isEqualTo("perceval");
IssueDto issue = newIssue();
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ index();
try {
service.assign(issue.getKey(), "unknown");
String actionPlanKey = "EFGH";
db.actionPlanDao().save(new ActionPlanDto().setKey(actionPlanKey).setProjectId(project.getId()));
session.commit();
+ index();
assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isNull();
IssueDto issue = newIssue().setActionPlanKey(actionPlanKey);
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ index();
assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).actionPlanKey()).isEqualTo(actionPlanKey);
public void fail_plan_if_action_plan_not_found() {
tester.get(IssueDao.class).insert(session, newIssue());
session.commit();
+ index();
try {
service.plan("ABCD", "unknown");
IssueDto issue = newIssue().setSeverity(Severity.BLOCKER);
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ index();
assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).severity()).isEqualTo(Severity.BLOCKER);
IssueDto issue = newIssue();
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ index();
List<Issue> result = service.search(IssueQuery.builder().build(), new QueryContext()).getHits();
assertThat(result).hasSize(1);
IssueTesting.newDto(rule, file, project),
IssueTesting.newDto(rule, file, project).setAssignee("steph"));
session.commit();
+ index();
Map<String, Long> results = service.findIssueAssignees(IssueQuery.builder().build());
*/
package org.sonar.server.issue;
+import com.google.common.collect.Maps;
import org.sonar.api.issue.Issue;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.Severity;
import org.sonar.core.issue.db.IssueDto;
import org.sonar.core.rule.RuleDto;
import org.sonar.server.issue.index.IssueDoc;
+import org.sonar.server.rule.RuleTesting;
import static org.fest.assertions.Assertions.assertThat;
.setSeverity(Severity.MAJOR)
.setDebt(10L)
.setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
- .setIssueUpdateDate(DateUtils.parseDate("2014-12-04"));
+ .setIssueUpdateDate(DateUtils.parseDate("2014-12-04"))
+ .setCreatedAt(1400000000000L)
+ .setUpdatedAt(1400000000000L);
+ }
+
+ public static IssueDoc newDoc() {
+ IssueDoc doc = new IssueDoc(Maps.<String, Object>newHashMap());
+ doc.setKey("ABC");
+ doc.setRuleKey(RuleTesting.XOO_X1.toString());
+ doc.setActionPlanKey(null);
+ doc.setReporter(null);
+ doc.setAssignee("steve");
+ doc.setAuthorLogin("roger");
+ doc.setLanguage("xoo");
+ doc.setComponentUuid("FILE_1");
+ doc.setEffortToFix(3.14);
+ doc.setFilePath("src/Foo.xoo");
+ doc.setMessage("the message");
+ doc.setModuleUuid("MODULE_1");
+ doc.setModuleUuidPath("MODULE_1");
+ doc.setProjectUuid("PROJECT_1");
+ doc.setLine(42);
+ doc.setAttributes(null);
+ doc.setStatus(Issue.STATUS_OPEN);
+ doc.setResolution(null);
+ doc.setSeverity(Severity.MAJOR);
+ doc.setDebt(10L);
+ doc.setFuncCreationDate(DateUtils.parseDate("2014-09-04"));
+ doc.setFuncUpdateDate(DateUtils.parseDate("2014-12-04"));
+ doc.setFuncCloseDate(null);
+ doc.setTechnicalCreationDate(DateUtils.parseDate("2014-09-04"));
+ doc.setTechnicalUpdateDate(DateUtils.parseDate("2014-12-04"));
+ return doc;
}
public static void assertIsEquivalent(IssueDto dto, IssueDoc issue) {
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.db.DbClient;
import org.sonar.server.issue.db.IssueDao;
+import org.sonar.server.issue.index.IssueIndexer;
import java.util.Collection;
import java.util.Date;
import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class ServerIssueStorageTest extends AbstractDaoTestCase {
@Before
public void setupDbClient() {
+ System2 system = mock(System2.class);
+ when(system.now()).thenReturn(2000000000L);
dbClient = new DbClient(getDatabase(), getMyBatis(),
- new ComponentDao(System2.INSTANCE),
- new IssueDao(System2.INSTANCE),
- new ResourceDao(getMyBatis(), System2.INSTANCE));
+ new ComponentDao(system),
+ new IssueDao(getMyBatis()),
+ new ResourceDao(getMyBatis(), system));
session = dbClient.openSession(false);
- storage = new ServerIssueStorage(getMyBatis(), new FakeRuleFinder(), dbClient);
+ storage = new ServerIssueStorage(getMyBatis(), new FakeRuleFinder(), dbClient, mock(IssueIndexer.class));
}
@After
+++ /dev/null
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2014 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-
-package org.sonar.server.issue.db;
-
-import com.google.common.collect.ImmutableMap;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Test;
-import org.sonar.api.issue.Issue;
-import org.sonar.api.rule.RuleKey;
-import org.sonar.api.security.DefaultGroups;
-import org.sonar.api.utils.KeyValueFormat;
-import org.sonar.api.web.UserRole;
-import org.sonar.core.component.ComponentDto;
-import org.sonar.core.issue.db.IssueDto;
-import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.core.persistence.DbSession;
-import org.sonar.core.rule.RuleDto;
-import org.sonar.server.component.ComponentTesting;
-import org.sonar.server.component.db.ComponentDao;
-import org.sonar.server.db.DbClient;
-import org.sonar.server.issue.IssueTesting;
-import org.sonar.server.issue.index.IssueIndex;
-import org.sonar.server.permission.InternalPermissionService;
-import org.sonar.server.permission.PermissionChange;
-import org.sonar.server.rule.RuleTesting;
-import org.sonar.server.rule.db.RuleDao;
-import org.sonar.server.search.IndexClient;
-import org.sonar.server.tester.ServerTester;
-import org.sonar.server.user.MockUserSession;
-
-import static org.fest.assertions.Assertions.assertThat;
-
-public class IssueBackendMediumTest {
-
- @ClassRule
- public static ServerTester tester = new ServerTester();
-
- DbClient dbClient;
- IndexClient indexClient;
- DbSession dbSession;
-
- @Before
- public void setUp() throws Exception {
- dbClient = tester.get(DbClient.class);
- indexClient = tester.get(IndexClient.class);
- dbSession = dbClient.openSession(false);
- tester.clearDbAndIndexes();
- }
-
- @After
- public void tearDown() throws Exception {
- if (dbSession != null) {
- dbSession.close();
- }
- }
-
- @Test
- public void insert_and_find_by_key() throws Exception {
- RuleDto rule = RuleTesting.newXooX1();
- tester.get(RuleDao.class).insert(dbSession, rule);
-
- ComponentDto project = ComponentTesting.newProjectDto();
- tester.get(ComponentDao.class).insert(dbSession, project);
-
- // project can be seen by anyone
- dbSession.commit();
- MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
- tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project.getKey()).setGroup(DefaultGroups.ANYONE).setPermission(UserRole.USER));
-
- ComponentDto file = ComponentTesting.newFileDto(project);
- tester.get(ComponentDao.class).insert(dbSession, file);
-
- IssueDto issue = IssueTesting.newDto(rule, file, project).setIssueAttributes(KeyValueFormat.format(ImmutableMap.of("key", "value")));
- dbClient.issueDao().insert(dbSession, issue);
-
- dbSession.commit();
-
- // Check that Issue is in Index
- assertThat(indexClient.get(IssueIndex.class).countAll()).isEqualTo(1);
-
- // should find by key
- Issue issueDoc = indexClient.get(IssueIndex.class).getByKey(issue.getKey());
-
- // Check all normalized fields
- assertThat(issueDoc.actionPlanKey()).isEqualTo(issue.getActionPlanKey());
- assertThat(issueDoc.assignee()).isEqualTo(issue.getAssignee());
- assertThat(issueDoc.authorLogin()).isEqualTo(issue.getAuthorLogin());
- assertThat(issueDoc.closeDate()).isEqualTo(issue.getIssueCloseDate());
- assertThat(issueDoc.effortToFix()).isEqualTo(issue.getEffortToFix());
- assertThat(issueDoc.resolution()).isEqualTo(issue.getResolution());
- assertThat(issueDoc.ruleKey()).isEqualTo(RuleKey.of(issue.getRuleRepo(), issue.getRule()));
- assertThat(issueDoc.line()).isEqualTo(issue.getLine());
- assertThat(issueDoc.message()).isEqualTo(issue.getMessage());
- assertThat(issueDoc.reporter()).isEqualTo(issue.getReporter());
- assertThat(issueDoc.key()).isEqualTo(issue.getKey());
- assertThat(issueDoc.updateDate()).isEqualTo(issue.getIssueUpdateDate());
- assertThat(issueDoc.status()).isEqualTo(issue.getStatus());
- assertThat(issueDoc.severity()).isEqualTo(issue.getSeverity());
- assertThat(issueDoc.attributes()).isEqualTo(KeyValueFormat.parse(issue.getIssueAttributes()));
- assertThat(issueDoc.attribute("key")).isEqualTo("value");
- }
-
-}
*/
package org.sonar.server.issue.db;
-import com.google.common.collect.ImmutableMap;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.sonar.core.persistence.DbSession;
import org.sonar.server.rule.RuleTesting;
-import java.util.Date;
+import java.util.Arrays;
import java.util.List;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
public class IssueDaoTest extends AbstractDaoTestCase {
public void before() throws Exception {
this.session = getMyBatis().openSession(false);
this.system2 = mock(System2.class);
- this.dao = new IssueDao(system2);
+ this.dao = new IssueDao(getMyBatis());
}
@After
public void get_by_key() {
setupData("shared", "get_by_key");
- IssueDto issue = dao.getByKey(session, "ABCDE");
+ IssueDto issue = dao.selectByKey(session, "ABCDE");
assertThat(issue.getKee()).isEqualTo("ABCDE");
assertThat(issue.getId()).isEqualTo(100L);
assertThat(issue.getComponentId()).isEqualTo(401);
assertThat(issue.getIssueCreationDate()).isNotNull();
assertThat(issue.getIssueUpdateDate()).isNotNull();
assertThat(issue.getIssueCloseDate()).isNotNull();
- assertThat(issue.getCreatedAt()).isNotNull();
- assertThat(issue.getUpdatedAt()).isNotNull();
+ assertThat(issue.getCreatedAt()).isEqualTo(1400000000000L);
+ assertThat(issue.getUpdatedAt()).isEqualTo(1450000000000L);
assertThat(issue.getRuleRepo()).isEqualTo("squid");
assertThat(issue.getRule()).isEqualTo("AvoidCycle");
assertThat(issue.getComponentKey()).isEqualTo("Action.java");
public void get_by_keys() {
setupData("shared", "get_by_key");
- List<IssueDto> issues = dao.getByKeys(session, "ABCDE");
+ List<IssueDto> issues = dao.selectByKeys(session, Arrays.asList("ABCDE"));
assertThat(issues).hasSize(1);
-
- IssueDto issue = issues.get(0);
- assertThat(issue.getKee()).isEqualTo("ABCDE");
- assertThat(issue.getId()).isEqualTo(100L);
- assertThat(issue.getComponentId()).isEqualTo(401);
- assertThat(issue.getProjectId()).isEqualTo(399);
- assertThat(issue.getRuleId()).isEqualTo(500);
- assertThat(issue.getLanguage()).isEqualTo("java");
- assertThat(issue.getSeverity()).isEqualTo("BLOCKER");
- assertThat(issue.isManualSeverity()).isFalse();
- assertThat(issue.getMessage()).isNull();
- assertThat(issue.getLine()).isEqualTo(200);
- assertThat(issue.getEffortToFix()).isEqualTo(4.2);
- assertThat(issue.getStatus()).isEqualTo("OPEN");
- assertThat(issue.getResolution()).isEqualTo("FIXED");
- assertThat(issue.getChecksum()).isEqualTo("XXX");
- assertThat(issue.getAuthorLogin()).isEqualTo("karadoc");
- assertThat(issue.getReporter()).isEqualTo("arthur");
- assertThat(issue.getAssignee()).isEqualTo("perceval");
- assertThat(issue.getIssueAttributes()).isEqualTo("JIRA=FOO-1234");
- assertThat(issue.getIssueCreationDate()).isNotNull();
- assertThat(issue.getIssueUpdateDate()).isNotNull();
- assertThat(issue.getIssueCloseDate()).isNotNull();
- assertThat(issue.getCreatedAt()).isNotNull();
- assertThat(issue.getUpdatedAt()).isNotNull();
- assertThat(issue.getRuleRepo()).isEqualTo("squid");
- assertThat(issue.getRule()).isEqualTo("AvoidCycle");
- assertThat(issue.getComponentKey()).isEqualTo("Action.java");
- assertThat(issue.getProjectKey()).isEqualTo("struts");
}
@Test
assertThat(issue.getProjectKey()).isEqualTo("struts");
}
- @Test
- public void find_after_dates() throws Exception {
- setupData("shared", "some_issues");
-
- Date t0 = new Date(0);
- assertThat(dao.findAfterDate(session, t0)).hasSize(3);
-
- Date t2014 = DateUtils.parseDate("2014-01-01");
- assertThat(dao.findAfterDate(session, t2014)).hasSize(1);
- }
-
- @Test
- public void find_after_dates_with_project() throws Exception {
- setupData("shared", "find_after_dates_with_project");
-
- assertThat(dao.findAfterDate(session, DateUtils.parseDate("2014-01-01"), ImmutableMap.of("project", "ABCD"))).hasSize(1);
- }
-
@Test
public void insert() throws Exception {
- when(system2.now()).thenReturn(DateUtils.parseDate("2013-05-22").getTime());
-
IssueDto dto = new IssueDto();
dto.setComponent(new ComponentDto().setKey("struts:Action").setId(123L));
dto.setProject(new ComponentDto().setKey("struts").setId(100L));
dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
- dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
- dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+ dto.setCreatedAt(1400000000000L);
+ dto.setUpdatedAt(1450000000000L);
dao.insert(session, dto);
session.commit();
@Test
public void update() throws Exception {
- when(system2.now()).thenReturn(DateUtils.parseDate("2013-05-22").getTime());
-
setupData("update");
IssueDto dto = new IssueDto();
dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
- dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
- dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+ dto.setCreatedAt(1400000000000L);
+ dto.setUpdatedAt(1450000000000L);
dao.update(session, dto);
session.commit();
package org.sonar.server.issue.index;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterators;
import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
+import org.junit.Ignore;
import org.junit.Test;
import org.sonar.api.issue.Issue;
import org.sonar.api.rule.RuleKey;
import org.sonar.server.issue.db.IssueDao;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.PermissionChange;
-import org.sonar.server.platform.BackendCleanup;
import org.sonar.server.rule.RuleTesting;
import org.sonar.server.rule.db.RuleDao;
import org.sonar.server.search.FacetValue;
-import org.sonar.server.search.IndexDefinition;
import org.sonar.server.search.QueryContext;
import org.sonar.server.search.Result;
import org.sonar.server.tester.ServerTester;
import static com.google.common.collect.Lists.newArrayList;
import static org.fest.assertions.Assertions.assertThat;
+@Ignore
public class IssueIndexMediumTest {
@ClassRule
DbClient db;
DbSession session;
IssueIndex index;
-
- RuleDto rule;
- ComponentDto project;
+ RuleDto rule = RuleTesting.newXooX1();
+ ComponentDto project = ComponentTesting.newProjectDto("P1");
ComponentDto file;
@Before
session = db.openSession(false);
index = tester.get(IssueIndex.class);
- rule = RuleTesting.newXooX1();
tester.get(RuleDao.class).insert(session, rule);
-
- project = ComponentTesting.newProjectDto();
tester.get(ComponentDao.class).insert(session, project);
-
- file = ComponentTesting.newFileDto(project);
+ file = ComponentTesting.newFileDto(project, "F1");
tester.get(ComponentDao.class).insert(session, file);
session.commit();
@Test
public void get_by_key() throws Exception {
- IssueDto issue = IssueTesting.newDto(rule, file, project);
- db.issueDao().insert(session, issue);
- session.commit();
+ IssueDoc issue = IssueTesting.newDoc();
+ tester.get(IssueIndexer.class).index(Iterators.singletonIterator(issue));
+
+ Issue loaded = index.getByKey(issue.key());
+ assertThat(loaded).isNotNull();
- Issue result = index.getByKey(issue.getKey());
- IssueTesting.assertIsEquivalent(issue, (IssueDoc) result);
}
@Test
public void get_by_key_with_attributes() throws Exception {
IssueDto issue = IssueTesting.newDto(rule, file, project);
- db.issueDao().insert(session, issue).setIssueAttributes(KeyValueFormat.format(ImmutableMap.of("jira-issue-key", "SONAR-1234")));
+ issue.setIssueAttributes(KeyValueFormat.format(ImmutableMap.of("jira-issue-key", "SONAR-1234")));
+ db.issueDao().insert(session, issue);
session.commit();
Issue result = index.getByKey(issue.getKey());
session.commit();
MockUserSession.set().setLogin("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project1.getKey()).setGroup(userGroup.getName()).setPermission(UserRole.USER));
- tester.get(InternalPermissionService.class).addPermission(new PermissionChange().setComponentKey(project2.getKey()).setGroup(adminGroup.getName()).setPermission(UserRole.USER));
-
+ tester.get(InternalPermissionService.class)
+ .addPermission(new PermissionChange().setComponentKey(project2.getKey()).setGroup(adminGroup.getName()).setPermission(UserRole.USER));
db.issueDao().insert(session,
IssueTesting.newDto(rule, file1, project1),
IssueTesting.newDto(rule, file2, project2),
tester.get(ComponentDao.class).insert(session, project1, project2, project3, file1, file2, file3);
-
// project1 can be seen by john and project2 by max. project3 cannot be seen by anyone
UserDto john = new UserDto().setLogin("john").setName("john").setActive(true);
UserDto max = new UserDto().setLogin("max").setName("max").setActive(true);
assertThat(index.search(query.build(), new QueryContext()).getHits()).hasSize(1);
}
- @Test
- public void synchronize_issue() throws Exception {
- IssueDto issue = IssueTesting.newDto(rule, file, project);
- tester.get(IssueDao.class).insert(session, issue);
- session.commit();
-
- // 0 Assert that all issues are both in ES and DB
- assertThat(db.issueDao().findAfterDate(session, new Date(0))).hasSize(1);
- assertThat(index.countAll()).isEqualTo(1);
-
- // Clear issue index in order to simulate these issues have been inserted without being indexed in E/S (from a previous version of SQ or
- // from batch)
- tester.get(BackendCleanup.class).clearIndex(IndexDefinition.ISSUES);
- tester.clearIndexes();
- assertThat(index.countAll()).isEqualTo(0);
-
- DbSession newSession = db.openSession(true);
- try {
- db.issueDao().synchronizeAfter(newSession, index.getLastSynchronization());
- newSession.commit();
-
- } finally {
- newSession.close();
- }
-
- assertThat(index.countAll()).isEqualTo(1);
- }
-
- @Test
- public void synchronize_all_issues() throws Exception {
- IssueDto issue = IssueTesting.newDto(rule, file, project);
- tester.get(IssueDao.class).insert(session, issue);
- session.commit();
-
- // 0 Assert that all issues are both in ES and DB
- assertThat(db.issueDao().findAfterDate(session, new Date(0))).hasSize(1);
- assertThat(index.countAll()).isEqualTo(1);
-
- // Clear issue index in order to simulate these issues have been inserted without being indexed in E/S (from a previous version of SQ or
- // from batch)
- tester.get(BackendCleanup.class).clearIndex(IndexDefinition.ISSUES);
- tester.clearIndexes();
- assertThat(index.countAll()).isEqualTo(0);
-
- DbSession newSession = db.openSession(true);
- try {
- db.issueDao().synchronizeAfter(newSession);
- newSession.commit();
-
- } finally {
- newSession.close();
- }
-
- assertThat(index.countAll()).isEqualTo(1);
- }
-
- @Test
- public void synchronize_a_lot_of_issues() throws Exception {
- Integer numberOfIssues = 1000;
-
- List<String> issueKeys = newArrayList();
- for (int i = 0; i < numberOfIssues; i++) {
- IssueDto issue = IssueTesting.newDto(rule, file, project);
- tester.get(IssueDao.class).insert(session, issue);
- issueKeys.add(issue.getKey());
- }
- session.commit();
-
- // 0 Assert that all issues are both in ES and DB
- assertThat(db.issueDao().findAfterDate(session, new Date(0))).hasSize(numberOfIssues);
- assertThat(index.countAll()).isEqualTo(numberOfIssues);
-
- // Clear issue index in order to simulate these issues have been inserted without being indexed in E/S (from a previous version of SQ or
- // from batch)
- tester.get(BackendCleanup.class).clearIndex(IndexDefinition.ISSUES);
- tester.clearIndexes();
- assertThat(index.countAll()).isEqualTo(0);
-
- DbSession newSession = db.openSession(true);
- try {
- db.issueDao().synchronizeAfter(newSession, index.getLastSynchronization());
- newSession.commit();
-
- } finally {
- newSession.close();
- }
-
- assertThat(index.countAll()).isEqualTo(numberOfIssues);
- }
-
@Test
public void list_assignees() throws Exception {
db.issueDao().insert(session,
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
-import org.sonar.api.utils.DateUtils;
import org.sonar.core.persistence.TestDatabase;
import org.sonar.server.db.DbClient;
import java.sql.Connection;
-import java.util.Date;
import static org.fest.assertions.Assertions.assertThat;
@Test
public void select_after_date() throws Exception {
dbTester.prepareDbUnit(getClass(), "shared.xml");
- Date date = DateUtils.parseDate("2014-01-01");
- IssueResultSetIterator it = IssueResultSetIterator.create(client, connection, date.getTime());
+ IssueResultSetIterator it = IssueResultSetIterator.create(client, connection, 1420000000000L);
assertThat(it.hasNext()).isTrue();
IssueDoc issue = it.next();
import org.sonar.server.issue.IssueTesting;
import org.sonar.server.issue.db.IssueDao;
import org.sonar.server.issue.filter.IssueFilterParameters;
+import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.PermissionChange;
import org.sonar.server.rule.RuleTesting;
.setIssueUpdateDate(DateUtils.parseDate("2017-12-04"));
db.issueDao().insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
// TODO date assertion is complex to test, and components id are not predictable, that's why strict boolean is set to false
.setIssueCreationDate(DateUtils.parseDate("2014-09-04"))
.setIssueUpdateDate(DateUtils.parseDate("2017-12-04"));
db.issueDao().insert(session, issue2);
-
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
result.assertJson(this.getClass(), "issues_on_different_projects.json", false);
.setUserLogin("fabrice")
.setCreatedAt(DateUtils.parseDate("2014-09-10")));
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
result.assertJson(this.getClass(), "issue_with_comment.json", false);
.setActionPlanKey("AP-ABCD");
db.issueDao().insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
result.assertJson(this.getClass(), "issue_with_action_plan.json", false);
.setIssueAttributes(KeyValueFormat.format(ImmutableMap.of("jira-issue-key", "SONAR-1234")));
db.issueDao().insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
result.assertJson(this.getClass(), "issue_with_attributes.json", false);
.setActionPlanKey("AP-ABCD");
db.issueDao().insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("extra_fields", "actions,transitions,assigneeName,reporterName,actionPlanName").execute();
.setIssueUpdateDate(DateUtils.parseDate("2017-12-04"));
db.issueDao().insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
result.assertJson(this.getClass(), "issue_linked_on_removed_file.json", false);
IssueDto issue = IssueTesting.newDto(rule, file, project);
db.issueDao().insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
assertThat(result.outputAsString()).contains("\"componentId\":" + file.getId() + ",");
public void search_by_project_uuid() throws Exception {
db.issueDao().insert(session, IssueTesting.newDto(rule, file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.PROJECT_UUIDS, project.uuid())
public void search_by_component_uuid() throws Exception {
db.issueDao().insert(session, IssueTesting.newDto(rule, file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2"));
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENT_UUIDS, file.uuid())
tester.get(IssueDao.class).insert(session, issue);
}
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENTS, file.getKey())
tester.get(IssueDao.class).insert(session, issue);
}
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam(IssueFilterParameters.COMPONENTS, file.getKey() + "," + otherFile.getKey())
tester.get(IssueDao.class).insert(session, issue);
}
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).setParam(IssueFilterParameters.COMPONENTS, file.getKey()).execute();
result.assertJson(this.getClass(), "apply_paging_with_one_component.json", false);
IssueDto issue = IssueTesting.newDto(rule, file, project);
db.issueDao().insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).execute();
result.assertJson(this.getClass(), "components_contains_sub_projects.json", false);
.setSeverity("MAJOR");
db.issueDao().insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("resolved", "false")
.setSeverity("MAJOR");
db.issueDao().insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION).setParam(IssueFilterParameters.HIDE_RULES, "true").execute();
result.assertJson(this.getClass(), "hide_rules.json", false);
db.issueDao().insert(session, IssueTesting.newDto(rule, file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac2").setIssueUpdateDate(DateUtils.parseDate("2014-11-01")));
db.issueDao().insert(session, IssueTesting.newDto(rule, file, project).setKee("82fd47d4-b650-4037-80bc-7b112bd4eac3").setIssueUpdateDate(DateUtils.parseDate("2014-11-03")));
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.Result result = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION)
.setParam("sort", IssueQuery.SORT_BY_UPDATE_DATE)
tester.get(IssueDao.class).insert(session, issue);
}
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION);
request.setParam(SearchAction.PARAM_PAGE, "2");
tester.get(IssueDao.class).insert(session, issue);
}
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION);
request.setParam(SearchAction.PARAM_PAGE, "1");
tester.get(IssueDao.class).insert(session, issue);
}
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
WsTester.TestRequest request = wsTester.newGetRequest(IssuesWs.API_ENDPOINT, SearchAction.SEARCH_ACTION);
request.setParam(IssueFilterParameters.PAGE_INDEX, "2");
import org.sonar.server.issue.IssueTesting;
import org.sonar.server.issue.db.IssueDao;
import org.sonar.server.issue.index.IssueIndex;
+import org.sonar.server.issue.index.IssueIndexer;
import org.sonar.server.permission.InternalPermissionService;
import org.sonar.server.permission.PermissionChange;
import org.sonar.server.rule.RuleTesting;
issue = IssueTesting.newDto(rule, file, project);
tester.get(IssueDao.class).insert(session, issue);
session.commit();
+ tester.get(IssueIndexer.class).indexAll();
}
@After
// Everything should be removed from db
assertThat(tester.get(ComponentDao.class).getNullableByKey(session, project.key())).isNull();
assertThat(tester.get(ComponentDao.class).getNullableByKey(session, file.key())).isNull();
- assertThat(tester.get(IssueDao.class).getNullableByKey(session, file.key())).isNull();
+ assertThat(tester.get(IssueDao.class).selectNullableByKey(session, file.key())).isNull();
assertThat(tester.get(RuleDao.class).getNullableByKey(session, rule.getKey())).isNull();
// Nothing should be removed from indexes
// Nothing should be removed from db
assertThat(tester.get(ComponentDao.class).getNullableByKey(session, project.key())).isNotNull();
assertThat(tester.get(ComponentDao.class).getNullableByKey(session, file.key())).isNotNull();
- assertThat(tester.get(IssueDao.class).getNullableByKey(session, issue.getKey())).isNotNull();
+ assertThat(tester.get(IssueDao.class).selectNullableByKey(session, issue.getKey())).isNotNull();
assertThat(tester.get(RuleDao.class).getNullableByKey(session, rule.getKey())).isNotNull();
// Everything should be removed from indexes
// Everything should be removed from db
assertThat(tester.get(ComponentDao.class).getNullableByKey(session, project.key())).isNull();
assertThat(tester.get(ComponentDao.class).getNullableByKey(session, file.key())).isNull();
- assertThat(tester.get(IssueDao.class).getNullableByKey(session, file.key())).isNull();
+ assertThat(tester.get(IssueDao.class).selectNullableByKey(session, file.key())).isNull();
assertThat(tester.get(RuleDao.class).getNullableByKey(session, rule.getKey())).isNull();
// Everything should be removed from indexes
// Every projects and issues are removed (from db and indexes)
assertThat(tester.get(ComponentDao.class).getNullableByKey(session, project.key())).isNull();
assertThat(tester.get(ComponentDao.class).getNullableByKey(session, file.key())).isNull();
- assertThat(tester.get(IssueDao.class).getNullableByKey(session, issue.getKey())).isNull();
+ assertThat(tester.get(IssueDao.class).selectNullableByKey(session, issue.getKey())).isNull();
assertThat(tester.get(IssueIndex.class).getNullableByKey(issue.getKey())).isNull();
// Every rules should not be removed (from db and indexes)
--- /dev/null
+<dataset>
+
+ <issues id="1" kee="ABC" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="200"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+ created_at="2014-05-12"
+ updated_at="2014-05-13"
+ CREATED_AT_MS="[null]"
+ UPDATED_AT_MS="[null]"
+ />
+
+ <!-- re-entrant migration - ignore the issues that are already fed with new dates -->
+ <issues id="2" kee="DEF" resolution="OPEN" status="OPEN" severity="BLOCKER" manual_severity="[false]"
+ assignee="[null]"
+ author_login="[null]"
+ checksum="[null]"
+ effort_to_fix="[null]"
+ technical_debt="10"
+ message="[null]"
+ line="5000"
+ component_id="100"
+ root_component_id="10"
+ rule_id="200"
+ reporter="emmerik"
+ issue_attributes="foo=bar"
+ action_plan_key="[null]"
+ issue_creation_date="2013-05-18"
+ issue_update_date="2013-05-18"
+ issue_close_date="2013-05-18"
+
+ created_at="2014-05-12"
+ updated_at="2014-05-13"
+ CREATED_AT_MS="1500000000000"
+ UPDATED_AT_MS="1500000000000"
+ />
+
+</dataset>
--- /dev/null
+CREATE TABLE "ISSUES" (
+ "ID" BIGINT NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "KEE" VARCHAR(50) UNIQUE NOT NULL,
+ "COMPONENT_ID" INTEGER NOT NULL,
+ "ROOT_COMPONENT_ID" INTEGER,
+ "RULE_ID" INTEGER,
+ "SEVERITY" VARCHAR(10),
+ "MANUAL_SEVERITY" BOOLEAN NOT NULL,
+ "MESSAGE" VARCHAR(4000),
+ "LINE" INTEGER,
+ "EFFORT_TO_FIX" DOUBLE,
+ "TECHNICAL_DEBT" INTEGER,
+ "STATUS" VARCHAR(20),
+ "RESOLUTION" VARCHAR(20),
+ "CHECKSUM" VARCHAR(1000),
+ "REPORTER" VARCHAR(255),
+ "ASSIGNEE" VARCHAR(255),
+ "AUTHOR_LOGIN" VARCHAR(255),
+ "ACTION_PLAN_KEY" VARCHAR(50) NULL,
+ "ISSUE_ATTRIBUTES" VARCHAR(4000),
+ "ISSUE_CREATION_DATE" TIMESTAMP,
+ "ISSUE_CLOSE_DATE" TIMESTAMP,
+ "ISSUE_UPDATE_DATE" TIMESTAMP,
+ "CREATED_AT" TIMESTAMP,
+ "UPDATED_AT" TIMESTAMP,
+ "CREATED_AT_MS" BIGINT,
+ "UPDATED_AT_MS" BIGINT
+);
component_id="100"
root_component_id="10"
rule_id="200"
- created_at="[null]"
- updated_at="[null]"
+ created_at="1000000000"
+ updated_at="1000000000"
reporter="emmerik"
issue_attributes="foo=bar"
action_plan_key="[null]"
component_id="100"
root_component_id="10"
rule_id="200"
- created_at="2013-05-18"
- updated_at="2013-05-18"
+ created_at="1000000000"
+ updated_at="2000000000"
reporter="emmerik"
issue_attributes="foo=bar"
action_plan_key="[null]"
component_id="100"
root_component_id="10"
rule_id="200"
- created_at="2010-01-01"
- updated_at="2011-02-02"
+ created_at="1000000000"
+ updated_at="1000000000"
reporter="emmerik"
issue_attributes="foo=bar"
action_plan_key="[null]"
+++ /dev/null
-<dataset>
-
- <projects id="1000" kee="other" root_id="[null]" qualifier="TRK" scope="PRJ" uuid="DBCA"/>
-
- <snapshots id="1000" project_id="1000" root_snapshot_id="[null]" parent_snapshot_id="[null]" root_project_id="1000"
- path="" islast="[true]"/>
-
- <!-- On struts project -->
- <issues
- id="100"
- kee="ABCDE-1"
- component_id="399"
- root_component_id="399"
- rule_id="500"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="4.2"
- status="OPEN"
- resolution="FIXED"
- checksum="XXX"
- reporter="arthur"
- assignee="perceval"
- author_login="[null]"
- issue_attributes="JIRA=FOO-1234"
- issue_creation_date="2013-04-16"
- issue_update_date="2013-04-16"
- issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
- />
-
- <issues
- id="101"
- kee="ABCDE-2"
- component_id="399"
- root_component_id="399"
- rule_id="500"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="4.2"
- status="OPEN"
- resolution="FIXED"
- checksum="XXX"
- reporter="arthur"
- assignee="perceval"
- author_login="[null]"
- issue_attributes="JIRA=FOO-1234"
- issue_creation_date="2013-04-16"
- issue_update_date="2013-04-16"
- issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2014-04-16"
- />
-
-
- <!-- On other project -->
- <issues
- id="102"
- kee="ABCDE-3"
- component_id="1000"
- root_component_id="1000"
- rule_id="501"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="4.2"
- status="OPEN"
- resolution="FIXED"
- checksum="XXX"
- reporter="arthur"
- assignee="perceval"
- author_login="[null]"
- issue_attributes="JIRA=FOO-1234"
- issue_creation_date="2014-04-16"
- issue_update_date="2014-04-16"
- issue_close_date="2014-04-16"
- created_at="2014-04-16"
- updated_at="2014-04-16"
- />
-</dataset>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
</dataset>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1450000000000"
/>
</dataset>
issue_creation_date="2013-05-18"
issue_update_date="2013-05-19"
issue_close_date="2013-05-20"
- created_at="2013-05-21"
- updated_at="2013-05-22"
+ created_at="1400000000000"
+ updated_at="1450000000000"
action_plan_key="current_sprint"
/>
</dataset>
+++ /dev/null
-<dataset>
-
- <!-- rule 500 -->
- <issues
- id="100"
- kee="ABCDE-1"
- component_id="401"
- root_component_id="399"
- rule_id="500"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="4.2"
- status="OPEN"
- resolution="FIXED"
- checksum="XXX"
- reporter="arthur"
- assignee="perceval"
- author_login="[null]"
- issue_attributes="JIRA=FOO-1234"
- issue_creation_date="2013-04-16"
- issue_update_date="2013-04-16"
- issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
- />
-
- <issues
- id="101"
- kee="ABCDE-2"
- component_id="401"
- root_component_id="399"
- rule_id="500"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="4.2"
- status="OPEN"
- resolution="FIXED"
- checksum="XXX"
- reporter="arthur"
- assignee="perceval"
- author_login="[null]"
- issue_attributes="JIRA=FOO-1234"
- issue_creation_date="2013-04-16"
- issue_update_date="2013-04-16"
- issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
- />
-
-
- <!-- rule 501 -->
- <issues
- id="102"
- kee="ABCDE-3"
- component_id="401"
- root_component_id="399"
- rule_id="501"
- severity="BLOCKER"
- manual_severity="[false]"
- message="[null]"
- line="200"
- effort_to_fix="4.2"
- status="OPEN"
- resolution="FIXED"
- checksum="XXX"
- reporter="arthur"
- assignee="perceval"
- author_login="[null]"
- issue_attributes="JIRA=FOO-1234"
- issue_creation_date="2014-04-16"
- issue_update_date="2014-04-16"
- issue_close_date="2014-04-16"
- created_at="2014-04-16"
- updated_at="2014-04-16"
- />
-</dataset>
issue_creation_date="2013-05-18"
issue_update_date="2013-05-19"
issue_close_date="2013-05-20"
- created_at="[null]"
- updated_at="2013-05-22"
+ created_at="1400000000000"
+ updated_at="1450000000000"
action_plan_key="current_sprint"
/>
</dataset>
issue_creation_date="[null]"
issue_update_date="[null]"
issue_close_date="[null]"
- created_at="[null]"
- updated_at="2009-01-01"
+ created_at="1400000000000"
+ updated_at="1400000000000"
action_plan_key="[null]"
/>
</dataset>
reporter="[null]"
issue_attributes="JIRA=http://jira.com"
action_plan_key="[null]"
- created_at="2005-05-12"
- updated_at="2013-05-18"
+ created_at="1000000000"
+ updated_at="2000000000"
issue_creation_date="2005-05-12 00:00:00.0"
issue_update_date="2013-05-18 00:00:00.0"
issue_close_date="[null]"
reporter="[null]"
issue_attributes="JIRA=http://jira.com"
action_plan_key="PLAN1"
- created_at="2005-05-12"
- updated_at="2013-01-01"
+ created_at="1400000000000"
+ updated_at="1400000000000"
issue_creation_date="2005-05-12 00:00:00.0"
issue_update_date="2013-01-01 00:00:00.0"
issue_close_date="[null]"/>
reporter="[null]"
issue_attributes="JIRA=http://jira.com"
action_plan_key="PLAN2"
- created_at="2005-05-12"
- updated_at="2014-05-18"
+ created_at="1400000000000"
+ updated_at="1450000000000"
issue_creation_date="2005-05-12 00:00:00.0"
issue_update_date="2013-05-18 00:00:00.0"
issue_close_date="[null]"/>
--- /dev/null
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+class AddIssueLongDates < ActiveRecord::Migration
+
+ def self.up
+ add_column 'issues', :created_at_ms, :big_integer, :null => true
+ add_column 'issues', :updated_at_ms, :big_integer, :null => true
+ end
+end
+
--- /dev/null
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+#
+# SonarQube 5.0
+#
+class FeedIssueLongDates < ActiveRecord::Migration
+
+ def self.up
+ execute_java_migration('org.sonar.server.db.migrations.v50.FeedIssueLongDates')
+ end
+
+end
+
--- /dev/null
+#
+# SonarQube, open source software quality management tool.
+# Copyright (C) 2008-2014 SonarSource
+# mailto:contact AT sonarsource DOT com
+#
+# SonarQube is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 3 of the License, or (at your option) any later version.
+#
+# SonarQube is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+
+class RenameIssueLongDates < ActiveRecord::Migration
+
+ def self.up
+ remove_index 'issues', :name => 'issues_updated_at'
+ remove_column 'issues', 'created_at'
+ remove_column 'issues', 'updated_at'
+ rename_column 'issues', 'created_at_ms', 'created_at'
+ rename_column 'issues', 'updated_at_ms', 'updated_at'
+ add_index 'issues', 'updated_at', :name => 'issues_updated_at'
+ end
+end
+
import org.sonar.core.resource.ResourceDto;
import org.sonar.core.resource.ResourceQuery;
-import java.util.Date;
-
public class ScanIssueStorage extends IssueStorage implements BatchComponent {
private final SnapshotCache snapshotCache;
}
@Override
- protected void doInsert(DbSession session, Date now, DefaultIssue issue) {
+ protected void doInsert(DbSession session, long now, DefaultIssue issue) {
IssueMapper issueMapper = session.getMapper(IssueMapper.class);
long componentId = componentId(issue);
long projectId = projectId();
}
@Override
- protected void doUpdate(DbSession session, Date now, DefaultIssue issue) {
+ protected void doUpdate(DbSession session, long now, DefaultIssue issue) {
IssueMapper issueMapper = session.getMapper(IssueMapper.class);
IssueDto dto = IssueDto.toDtoForUpdate(issue, projectId(), now);
if (Issue.STATUS_CLOSED.equals(issue.status()) || issue.selectedAt() == null) {
.setRuleKey(RuleKey.of("squid", "AvoidCycles"))
.setComponentKey("struts:Action")
- // issue in database has been updated in 2013, after the loading by scan
- .setSelectedAt(DateUtils.parseDate("2005-01-01"))
+ // issue in database has been updated in 2015, after the loading by scan
+ .setSelectedAt(1400000000000L)
// fields to be updated
.setLine(444)
reporter="[null]"
issue_attributes="JIRA=http://jira.com"
action_plan_key="[null]"
- created_at="2005-05-12"
- updated_at="2013-05-18"
+ created_at="1400000000000"
+ updated_at="1400000000000"
issue_creation_date="2005-05-12 00:00:00.0"
issue_update_date="2013-05-18 00:00:00.0"
issue_close_date="[null]"
reporter="[null]"
issue_attributes=""
action_plan_key="[null]"
- created_at="2005-05-12"
- updated_at="2013-05-18"
+ created_at="1400000000000"
+ updated_at="1500000000000"
issue_creation_date="2005-05-12 00:00:00.0"
issue_update_date="2013-05-18 00:00:00.0"
issue_close_date="[null]"
component_id="100"
root_component_id="10"
rule_id="200"
- created_at="2013-05-18"
- updated_at="2013-05-18"
+ created_at="1400000000000"
+ updated_at="1400000000000"
reporter="emmerik"
issue_attributes="foo=bar"
action_plan_key="[null]"
component_id="100"
root_component_id="10"
rule_id="200"
- created_at="2010-01-01"
- updated_at="2011-02-02"
+ created_at="1400000000000"
+ updated_at="1400000000000"
reporter="emmerik"
issue_attributes="foo=bar"
action_plan_key="[null]"
@CheckForNull
public IssueDto selectByKey(String key) {
- SqlSession session = mybatis.openSession(false);
+ DbSession session = mybatis.openSession(false);
try {
- IssueMapper mapper = session.getMapper(IssueMapper.class);
- return mapper.selectByKey(key);
+ return mapper(session).selectByKey(key);
} finally {
MyBatis.closeQuietly(session);
}
// TODO replace by aggregation in IssueIndex
public List<RuleDto> findRulesByComponent(String componentKey, @Nullable Date createdAtOrAfter, DbSession session) {
- return session.getMapper(IssueMapper.class).findRulesByComponent(componentKey, createdAtOrAfter);
+ return mapper(session).findRulesByComponent(componentKey, createdAtOrAfter);
}
// TODO replace by aggregation in IssueIndex
public List<String> findSeveritiesByComponent(String componentKey, @Nullable Date createdAtOrAfter, DbSession session) {
- return session.getMapper(IssueMapper.class).findSeveritiesByComponent(componentKey, createdAtOrAfter);
+ return mapper(session).findSeveritiesByComponent(componentKey, createdAtOrAfter);
+ }
+
+ protected IssueMapper mapper(DbSession session) {
+ return session.getMapper(IssueMapper.class);
}
+
}
import org.sonar.api.utils.KeyValueFormat;
import org.sonar.api.utils.internal.Uuids;
import org.sonar.core.component.ComponentDto;
-import org.sonar.core.persistence.Dto;
import org.sonar.core.rule.RuleDto;
import javax.annotation.CheckForNull;
/**
* @since 3.6
*/
-public final class IssueDto extends Dto<String> implements Serializable {
+public final class IssueDto implements Serializable {
private Long id;
private String kee;
private String authorLogin;
private String actionPlanKey;
private String issueAttributes;
+ private long createdAt;
+ private long updatedAt;
// functional dates
private Date issueCreationDate;
/**
* Temporary date used only during scan
*/
- private Date selectedAt;
+ private Long selectedAt;
// joins
private String ruleKey;
private String projectUuid;
private String filePath;
- @Override
public String getKey() {
return getKee();
}
return this;
}
- @Override
- public IssueDto setCreatedAt(Date createdAt) {
- super.setCreatedAt(createdAt);
+ public long getCreatedAt() {
+ return createdAt;
+ }
+
+ /**
+ * Technical date
+ */
+ public IssueDto setCreatedAt(long createdAt) {
+ this.createdAt = createdAt;
return this;
}
- @Override
- public IssueDto setUpdatedAt(@Nullable Date updatedAt) {
- super.setUpdatedAt(updatedAt);
+ public long getUpdatedAt() {
+ return updatedAt;
+ }
+
+ /**
+ * Technical date
+ */
+ public IssueDto setUpdatedAt(long updatedAt) {
+ this.updatedAt = updatedAt;
return this;
}
return ruleRepo;
}
- public RuleKey getRuleKey(){
+ public RuleKey getRuleKey() {
return RuleKey.of(ruleRepo, ruleKey);
}
- public String getLanguage(){
+ public String getLanguage() {
return language;
}
}
@CheckForNull
- public Date getSelectedAt() {
+ public Long getSelectedAt() {
return selectedAt;
}
- public IssueDto setSelectedAt(@Nullable Date d) {
+ public IssueDto setSelectedAt(@Nullable Long d) {
this.selectedAt = d;
return this;
}
/**
* On batch side, component keys and uuid are useless
*/
- public static IssueDto toDtoForBatchInsert(DefaultIssue issue, Long componentId, Long rootComponentId, Integer ruleId, Date now) {
+ public static IssueDto toDtoForBatchInsert(DefaultIssue issue, Long componentId, Long rootComponentId, Integer ruleId, long now) {
return new IssueDto()
.setKee(issue.key())
.setLine(issue.line())
.setIssueCloseDate(issue.closeDate())
.setIssueUpdateDate(issue.updateDate())
.setSelectedAt(issue.selectedAt())
+
+ // technical dates
.setCreatedAt(now)
.setUpdatedAt(now);
}
/**
* On server side, we need component keys and uuid
*/
- public static IssueDto toDtoForServerInsert(DefaultIssue issue, ComponentDto component, ComponentDto project, Integer ruleId, Date now) {
+ public static IssueDto toDtoForServerInsert(DefaultIssue issue, ComponentDto component, ComponentDto project, Integer ruleId, long now) {
return toDtoForBatchInsert(issue, component.getId(), project.getId(), ruleId, now)
.setComponent(component)
.setProject(project);
}
- public static IssueDto toDtoForUpdate(DefaultIssue issue, Long rootComponentId, Date now) {
+ public static IssueDto toDtoForUpdate(DefaultIssue issue, Long rootComponentId, long now) {
// Invariant fields, like key and rule, can't be updated
return new IssueDto()
.setKee(issue.key())
.setIssueCloseDate(issue.closeDate())
.setIssueUpdateDate(issue.updateDate())
.setSelectedAt(issue.selectedAt())
+
+ // technical date
.setUpdatedAt(now);
}
import org.sonar.core.rule.RuleDto;
import javax.annotation.Nullable;
-
-import java.sql.Timestamp;
import java.util.Collection;
import java.util.Date;
import java.util.List;
int updateIfBeforeSelectedDate(IssueDto issue);
- List<IssueDto> selectAfterDate(@Nullable @Param("date") Timestamp timestamp, @Nullable @Param("project") String projectUuid);
}
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.MyBatis;
-import java.util.Date;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
}
public void save(DbSession session, DefaultIssue issue) {
- save(session, newArrayList(issue));
+ doSave(session, newArrayList(issue));
}
public void save(Iterable<DefaultIssue> issues) {
DbSession session = mybatis.openSession(true);
try {
- save(session, issues);
- session.commit();
+ doSave(session, issues);
} finally {
MyBatis.closeQuietly(session);
}
}
- private void save(DbSession session, Iterable<DefaultIssue> issues) {
+ private void doSave(DbSession session, Iterable<DefaultIssue> issues) {
// Batch session can not be used for updates. It does not return the number of updated rows,
// required for detecting conflicts.
- Date now = new Date();
+ long now = System.currentTimeMillis();
List<DefaultIssue> toBeUpdated = batchInsert(session, issues, now);
update(toBeUpdated, now);
+ doAfterSave();
}
- private List<DefaultIssue> batchInsert(DbSession session, Iterable<DefaultIssue> issues, Date now) {
+ protected void doAfterSave() {
+ // overridden on server-side to index ES
+ }
+
+ private List<DefaultIssue> batchInsert(DbSession session, Iterable<DefaultIssue> issues, long now) {
List<DefaultIssue> toBeUpdated = newArrayList();
int count = 0;
IssueChangeMapper issueChangeMapper = session.getMapper(IssueChangeMapper.class);
toBeUpdated.add(issue);
}
}
+ session.commit();
return toBeUpdated;
}
- protected abstract void doInsert(DbSession batchSession, Date now, DefaultIssue issue);
+ protected abstract void doInsert(DbSession batchSession, long now, DefaultIssue issue);
- private void update(List<DefaultIssue> toBeUpdated, Date now) {
+ private void update(List<DefaultIssue> toBeUpdated, long now) {
if (!toBeUpdated.isEmpty()) {
DbSession session = mybatis.openSession(false);
try {
}
}
- protected abstract void doUpdate(DbSession batchSession, Date now, DefaultIssue issue);
+ protected abstract void doUpdate(DbSession batchSession, long now, DefaultIssue issue);
private void insertChanges(IssueChangeMapper mapper, DefaultIssue issue) {
for (IssueComment comment : issue.comments()) {
import org.slf4j.LoggerFactory;
import org.sonar.api.issue.internal.DefaultIssue;
-import java.util.Date;
-
/**
* See https://jira.codehaus.org/browse/SONAR-4309
*
IssueDto dbIssue = mapper.selectByKey(issue.key());
if (dbIssue != null) {
mergeFields(dbIssue, issue);
- mapper.update(IssueDto.toDtoForUpdate(issue, dbIssue.getProjectId(), new Date()));
+ mapper.update(IssueDto.toDtoForUpdate(issue, dbIssue.getProjectId(), System.currentTimeMillis()));
}
}
*/
public class DatabaseVersion implements BatchComponent, ServerComponent {
- public static final int LAST_VERSION = 717;
+ public static final int LAST_VERSION = 720;
+
/**
* List of all the tables.
* This list is hardcoded because we didn't succeed in using java.sql.DatabaseMetaData#getTables() in the same way
mapper.setSnapshotIsLastToFalse(resourceId);
mapper.deleteFileSourcesByUuid(resourceIdUuid.getUuid());
mapper.disableResource(resourceId);
- mapper.resolveResourceIssuesNotAlreadyResolved(resourceId, new Date(system2.now()));
+ mapper.resolveResourceIssuesNotAlreadyResolved(resourceId, new Date(system2.now()), system2.now());
}
public PurgeDao deleteSnapshots(PurgeSnapshotQuery query) {
void disableResource(long resourceId);
- void resolveResourceIssuesNotAlreadyResolved(@Param("resourceId") long resourceId, @Param("date") Date date);
+ void resolveResourceIssuesNotAlreadyResolved(@Param("resourceId") long resourceId, @Param("date") Date date, @Param("dateAsLong") Long dateAsLong);
void deleteResourceIndex(@Param("resourceIds") List<Long> resourceIds);
where i.kee=#{kee}
</select>
- <select id="selectAfterDate" resultType="Issue" fetchSize="${_scrollFetchSize}" resultSetType="FORWARD_ONLY">
- select
- <include refid="issueColumns"/>
- from issues i
- inner join rules r on r.id=i.rule_id
- inner join projects p on p.id=i.component_id
- inner join projects root on root.id=i.root_component_id
- <where>
- <if test="date != null">
- AND (i.updated_at IS NULL or i.updated_at >= #{date})
- </if>
- <if test="project != null">
- AND root.uuid = #{project}
- </if>
- </where>
- </select>
-
<select id="selectNonClosedIssuesByModule" parameterType="int" resultType="Issue">
select
i.id,
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('715');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('716');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('717');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('718');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('719');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('720');
INSERT INTO USERS(ID, LOGIN, NAME, EMAIL, CRYPTED_PASSWORD, SALT, CREATED_AT, UPDATED_AT, REMEMBER_TOKEN, REMEMBER_TOKEN_EXPIRES_AT) VALUES (1, 'admin', 'Administrator', '', 'a373a0e667abb2604c1fd571eb4ad47fe8cc0878', '48bc4b0d93179b5103fd3885ea9119498e9d161b', '2011-09-26 22:27:48.0', '2011-09-26 22:27:48.0', null, null);
ALTER TABLE USERS ALTER COLUMN ID RESTART WITH 2;
"ISSUE_CREATION_DATE" TIMESTAMP,
"ISSUE_CLOSE_DATE" TIMESTAMP,
"ISSUE_UPDATE_DATE" TIMESTAMP,
- "CREATED_AT" TIMESTAMP,
- "UPDATED_AT" TIMESTAMP
-
+ "CREATED_AT" BIGINT,
+ "UPDATED_AT" BIGINT
);
CREATE TABLE "ISSUE_CHANGES" (
</update>
<update id="resolveResourceIssuesNotAlreadyResolved" parameterType="map">
- UPDATE issues SET status='CLOSED',resolution='REMOVED',updated_at=#{date},issue_close_date=#{date},
+ UPDATE issues SET status='CLOSED',resolution='REMOVED',updated_at=#{dateAsLong},issue_close_date=#{date},
issue_update_date=#{date}
WHERE component_id=#{resourceId} AND resolution IS NULL
</update>
dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
- dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
- dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+ dto.setCreatedAt(1400000000000L);
+ dto.setUpdatedAt(1500000000000L);
mapper.insert(dto);
session.commit();
dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
- dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
- dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+ dto.setCreatedAt(1400000000000L);
+ dto.setUpdatedAt(1500000000000L);
mapper.update(dto);
session.commit();
dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
- dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
- dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+ dto.setCreatedAt(1400000000000L);
+ dto.setUpdatedAt(1500000000000L);
// selected after last update -> ok
- dto.setSelectedAt(DateUtils.parseDate("2015-01-01"));
+ dto.setSelectedAt(1500000000000L);
int count = mapper.updateIfBeforeSelectedDate(dto);
assertThat(count).isEqualTo(1);
dto.setIssueCreationDate(DateUtils.parseDate("2013-05-18"));
dto.setIssueUpdateDate(DateUtils.parseDate("2013-05-19"));
dto.setIssueCloseDate(DateUtils.parseDate("2013-05-20"));
- dto.setCreatedAt(DateUtils.parseDate("2013-05-21"));
- dto.setUpdatedAt(DateUtils.parseDate("2013-05-22"));
+ dto.setCreatedAt(1400000000000L);
+ dto.setUpdatedAt(1460000000000L);
// selected before last update -> ko
- dto.setSelectedAt(DateUtils.parseDate("2009-01-01"));
+ dto.setSelectedAt(1400000000000L);
int count = mapper.updateIfBeforeSelectedDate(dto);
assertThat(count).isEqualTo(0);
}
@Override
- protected void doInsert(DbSession session, Date now, DefaultIssue issue) {
+ protected void doInsert(DbSession session, long now, DefaultIssue issue) {
int ruleId = ruleId(issue);
IssueDto dto = IssueDto.toDtoForBatchInsert(issue, 100l, 10l, ruleId, now);
}
@Override
- protected void doUpdate(DbSession session, Date now, DefaultIssue issue) {
+ protected void doUpdate(DbSession session, long now, DefaultIssue issue) {
IssueDto dto = IssueDto.toDtoForUpdate(issue, 10l, now);
session.getMapper(IssueMapper.class).update(dto);
}
}
@Override
- protected void doInsert(DbSession session, Date now, DefaultIssue issue) {
+ protected void doInsert(DbSession session, long now, DefaultIssue issue) {
int ruleId = ruleId(issue);
IssueDto dto = IssueDto.toDtoForServerInsert(issue, component, project, ruleId, now);
}
@Override
- protected void doUpdate(DbSession session, Date now, DefaultIssue issue) {
+ protected void doUpdate(DbSession session, long now, DefaultIssue issue) {
IssueDto dto = IssueDto.toDtoForUpdate(issue, 10l, now);
session.getMapper(IssueMapper.class).update(dto);
}
import org.slf4j.LoggerFactory;
import org.sonar.api.config.Settings;
import org.sonar.core.cluster.NullQueue;
-import org.sonar.core.cluster.WorkQueue;
import org.sonar.core.config.Logback;
import org.sonar.core.persistence.dialect.Dialect;
private DatabaseCommands commands;
private IDatabaseTester tester;
private MyBatis myBatis;
- private WorkQueue queue = new NullQueue();
private String schemaPath = null;
public TestDatabase schema(Class baseClass, String filename) {
return this;
}
- public TestDatabase setQueue(WorkQueue queue) {
- this.queue = queue;
- return this;
- }
-
@Override
protected void before() throws Throwable {
Settings settings = new Settings().setProperties(Maps.fromProperties(System.getProperties()));
commands = DatabaseCommands.forDialect(db.getDialect());
tester = new DataSourceDatabaseTester(db.getDataSource());
- myBatis = new MyBatis(db, new Logback(), queue);
+ myBatis = new MyBatis(db, new Logback(), new NullQueue());
myBatis.start();
truncateTables();
}
}
-
public void prepareDbUnit(Class testClass, String... testNames) {
InputStream[] streams = new InputStream[testNames.length];
try {
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.resources.Scopes;
-import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.core.persistence.AbstractDaoTestCase;
import org.sonar.core.persistence.DbSession;
@Before
public void before() {
system2 = mock(System2.class);
- when(system2.now()).thenReturn(DateUtils.parseDate("2014-04-09").getTime());
+ when(system2.now()).thenReturn(1450000000000L);
dbSession = getMyBatis().openSession(false);
sut = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis(), system2), new PurgeProfiler(), system2);
}
-
@After
public void after() {
MyBatis.closeQuietly(dbSession);
public void disable_resources_without_last_snapshot() {
setupData("disable_resources_without_last_snapshot");
sut.purge(new PurgeConfiguration(1L, new String[0], 30, system2), PurgeListener.EMPTY);
- checkTables("disable_resources_without_last_snapshot", "projects", "snapshots", "issues");
+ checkTables("disable_resources_without_last_snapshot", new String[]{"issue_close_date", "issue_update_date"}, "projects", "snapshots", "issues");
}
@Test
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
<issues
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
<issues
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
</dataset>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
<issues
issue_creation_date="2013-04-17"
issue_update_date="2013-04-17"
issue_close_date="2013-04-17"
- created_at="2013-04-17"
- updated_at="2013-04-17"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
issue_creation_date="2013-04-18"
issue_update_date="2013-04-18"
issue_close_date="2013-04-18"
- created_at="2013-04-18"
- updated_at="2013-04-18"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
</dataset>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
<issues
issue_creation_date="2013-04-17"
issue_update_date="2013-04-17"
issue_close_date="2013-04-17"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
</dataset>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
</dataset>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
<issues
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
- updated_at="2013-04-16"
+ created_at="1400000000000"
+ updated_at="1400000000000"
/>
</dataset>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-16"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-04-16"
issue_update_date="2013-04-16"
issue_close_date="2013-04-16"
- created_at="2013-04-10"
+ created_at="1400000000000"
updated_at="[null]"
/>
issue_creation_date="2013-05-18"
issue_update_date="2013-05-19"
issue_close_date="2013-05-20"
- created_at="2013-05-21"
- updated_at="2013-05-22"
+ created_at="1400000000000"
+ updated_at="1500000000000"
action_plan_key="current_sprint"
/>
</dataset>
issue_creation_date="2013-05-18"
issue_update_date="2013-05-19"
issue_close_date="2013-05-20"
- created_at="[null]"
- updated_at="2013-05-22"
+ created_at="1400000000000"
+ updated_at="1500000000000"
action_plan_key="current_sprint"
/>
</dataset>
issue_creation_date="[null]"
issue_update_date="[null]"
issue_close_date="[null]"
- created_at="[null]"
- updated_at="2009-01-01"
+ created_at="1400000000000"
+ updated_at="1400000000000"
action_plan_key="[null]"
/>
</dataset>
issue_creation_date="[null]"
issue_update_date="[null]"
issue_close_date="[null]"
- created_at="[null]"
- updated_at="2013-06-01"
+ created_at="1400000000000"
+ updated_at="1450000000000"
action_plan_key="[null]"
/>
</dataset>
issue_creation_date="[null]"
issue_update_date="[null]"
issue_close_date="[null]"
- created_at="[null]"
- updated_at="2013-06-01"
+ created_at="1400000000000"
+ updated_at="1450000000000"
action_plan_key="[null]"
/>
</dataset>
component_id="100"
root_component_id="10"
rule_id="200"
- created_at="2010-01-01"
- updated_at="2011-02-02"
+ created_at="1400000000000"
+ updated_at="1400000000000"
reporter="emmerik"
issue_attributes="foo=bar"
action_plan_key="[null]"
issue_close_date="2014-04-09"
resolution="REMOVED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="2014-04-09" issue_creation_date="2013-04-16" issue_update_date="2014-04-09" created_at="2013-04-16"/>
+ updated_at="1450000000000" issue_creation_date="2013-04-16" issue_update_date="2014-04-09" created_at="1450000000000"/>
<!-- Open issue on directory -->
<issues id="2" kee="ISSUE-2"
issue_close_date="2014-04-09"
resolution="REMOVED" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="2014-04-09" issue_creation_date="2013-04-16" issue_update_date="2014-04-09" created_at="2013-04-16"/>
+ updated_at="1450000000000" issue_creation_date="2013-04-16" issue_update_date="2014-04-09" created_at="1450000000000"/>
<!-- Open issue on project -->
<issues id="3" kee="ISSUE-3"
issue_close_date="2014-04-09"
resolution="REMOVED" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="2014-04-09" issue_creation_date="2013-04-16" issue_update_date="2014-04-09" created_at="2013-04-16"/>
+ updated_at="1450000000000" issue_creation_date="2013-04-16" issue_update_date="2014-04-09" created_at="1450000000000"/>
<!-- Resolved issue on file -> not to be updated -->
<issues id="4" kee="ISSUE-4"
component_id="3"
root_component_id="1"
status="CLOSED"
- issue_close_date="2014-04-08"
+ issue_close_date="2015-12-08"
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2014-04-08" created_at="2013-04-16"/>
+ updated_at="1450000000000" issue_creation_date="2013-04-16" issue_update_date="2014-04-08" created_at="1450000000000"/>
</dataset>
issue_close_date="[null]"
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1450000000000"/>
<!-- Open issue on directory -->
<issues id="2" kee="ISSUE-2"
issue_close_date="[null]"
resolution="[null]" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1450000000000"/>
<!-- Open issue on project -->
<issues id="3" kee="ISSUE-3"
issue_close_date="[null]"
resolution="[null]" line="[null]" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1450000000000"/>
<!-- Resolved issue on file -> not to be updated -->
<issues id="4" kee="ISSUE-4"
component_id="3"
root_component_id="1"
status="CLOSED"
- issue_close_date="2014-04-08"
+ issue_close_date="2015-12-08"
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2014-04-08" created_at="2013-04-16"/>
+ updated_at="1450000000000" issue_creation_date="2013-04-16" issue_update_date="2014-04-08" created_at="1450000000000"/>
</dataset>
issue_close_date="[null]"
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- recent open and closed issues -->
issue_close_date="[null]"
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!--
issue_close_date="2010-01-01"
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="2" kee="ISSUE-2"
issue_close_date="2010-01-01"
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
issue_close_date="[null]"
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- recent open and closed issues -->
issue_close_date="[null]"
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="5" kee="ISSUE-5"
issue_close_date="2025-01-01"
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
</dataset>
issue_close_date="[null]"
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- recent open and closed issues -> do not purge -->
issue_close_date="[null]"
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="5" kee="ISSUE-5"
issue_close_date="2025-01-01"
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
</dataset>
issue_close_date="2010-01-01"
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="1" kee="[null]" issue_key="ISSUE-1" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="2" kee="ISSUE-2"
issue_close_date="2010-01-01"
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="2" kee="[null]" issue_key="ISSUE-2" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
issue_close_date="[null]"
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="3" kee="[null]" issue_key="ISSUE-3" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<!-- recent open and closed issues -> do not purge -->
issue_close_date="[null]"
resolution="[null]" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="4" kee="[null]" issue_key="ISSUE-4" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
<issues id="5" kee="ISSUE-5"
issue_close_date="2025-01-01"
resolution="FIXED" line="200" severity="BLOCKER" reporter="perceval" assignee="arthur" rule_id="500" manual_severity="[false]"
message="[null]" action_plan_key="[null]" effort_to_fix="[null]" technical_debt="[null]" issue_attributes="[null]" checksum="[null]" author_login="[null]"
- updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+ updated_at="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="1400000000000"/>
<issue_changes id="5" kee="[null]" issue_key="ISSUE-5" created_at="[null]" updated_at="[null]" user_login="admin" change_type="comment" change_data="abc" issue_change_creation_date="[null]"/>
</dataset>
private boolean sendNotifications = false;
// Date when issue was loaded from db (only when isNew=false)
- private Date selectedAt;
+ private Long selectedAt;
@Override
public String key() {
}
@CheckForNull
- public Date selectedAt() {
+ public Long selectedAt() {
return selectedAt;
}
- public DefaultIssue setSelectedAt(@Nullable Date d) {
+ public DefaultIssue setSelectedAt(@Nullable Long d) {
this.selectedAt = d;
return this;
}
.setCreationDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-19"))
.setUpdateDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-20"))
.setCloseDate(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-21"))
- .setSelectedAt(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-22"))
+ .setSelectedAt(1400000000000L)
;
assertThat(issue.key()).isEqualTo("ABCD");
assertThat(issue.creationDate()).isEqualTo(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-19"));
assertThat(issue.updateDate()).isEqualTo(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-20"));
assertThat(issue.closeDate()).isEqualTo(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-21"));
- assertThat(issue.selectedAt()).isEqualTo(new SimpleDateFormat("yyyy-MM-dd").parse("2013-08-22"));
+ assertThat(issue.selectedAt()).isEqualTo(1400000000000L);
}
@Test