*/
public class DatabaseVersion implements BatchComponent, ServerComponent {
- public static final int LAST_VERSION = 524;
+ public static final int LAST_VERSION = 525;
public static enum Status {
UP_TO_DATE, REQUIRES_UPGRADE, REQUIRES_DOWNGRADE, FRESH_INSTALL
import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.lang.time.DateUtils;
+import org.sonar.api.utils.System2;
import javax.annotation.CheckForNull;
+
import java.util.Date;
public class PurgeConfiguration {
private final long rootProjectId;
private final String[] scopesWithoutHistoricalData;
private final int maxAgeInDaysOfClosedIssues;
+ private final System2 system2;
public PurgeConfiguration(long rootProjectId, String[] scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues) {
+ this(rootProjectId, scopesWithoutHistoricalData, maxAgeInDaysOfClosedIssues, System2.INSTANCE);
+ }
+
+ @VisibleForTesting
+ PurgeConfiguration(long rootProjectId, String[] scopesWithoutHistoricalData, int maxAgeInDaysOfClosedIssues, System2 system2) {
this.rootProjectId = rootProjectId;
this.scopesWithoutHistoricalData = scopesWithoutHistoricalData;
this.maxAgeInDaysOfClosedIssues = maxAgeInDaysOfClosedIssues;
+ this.system2 = system2;
}
public long rootProjectId() {
@CheckForNull
public Date maxLiveDateOfClosedIssues() {
- return maxLiveDateOfClosedIssues(new Date());
+ return maxLiveDateOfClosedIssues(new Date(system2.now()));
}
@VisibleForTesting
*/
package org.sonar.core.purge;
-import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import org.apache.commons.lang.ArrayUtils;
import org.apache.ibatis.session.ResultContext;
if (hasAbortedBuilds(project.getId(), commands)) {
LOG.info("<- Delete aborted builds");
PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
- .setIslast(false)
- .setStatus(new String[] {"U"})
- .setRootProjectId(project.getId());
+ .setIslast(false)
+ .setStatus(new String[]{"U"})
+ .setRootProjectId(project.getId());
commands.deleteSnapshots(query);
}
}
private boolean hasAbortedBuilds(Long projectId, PurgeCommands commands) {
PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
- .setIslast(false)
- .setStatus(new String[] {"U"})
- .setResourceId(projectId);
+ .setIslast(false)
+ .setStatus(new String[]{"U"})
+ .setResourceId(projectId);
return !commands.selectSnapshotIds(query).isEmpty();
}
private void purge(ResourceDto project, String[] scopesWithoutHistoricalData, PurgeCommands purgeCommands) {
List<Long> projectSnapshotIds = purgeCommands.selectSnapshotIds(
- PurgeSnapshotQuery.create()
- .setResourceId(project.getId())
- .setIslast(false)
- .setNotPurged(true));
+ PurgeSnapshotQuery.create()
+ .setResourceId(project.getId())
+ .setIslast(false)
+ .setNotPurged(true)
+ );
for (final Long projectSnapshotId : projectSnapshotIds) {
LOG.info("<- Clean snapshot " + projectSnapshotId);
if (!ArrayUtils.isEmpty(scopesWithoutHistoricalData)) {
PurgeSnapshotQuery query = PurgeSnapshotQuery.create()
- .setIslast(false)
- .setScopes(scopesWithoutHistoricalData)
- .setRootSnapshotId(projectSnapshotId);
+ .setIslast(false)
+ .setScopes(scopesWithoutHistoricalData)
+ .setRootSnapshotId(projectSnapshotId);
purgeCommands.deleteSnapshots(query);
}
commands.deleteResources(resourceIds);
}
- @VisibleForTesting
- void disableResource(long resourceId, PurgeMapper mapper) {
+ private void disableResource(long resourceId, PurgeMapper mapper) {
mapper.deleteResourceIndex(Arrays.asList(resourceId));
mapper.setSnapshotIsLastToFalse(resourceId);
mapper.disableResource(resourceId);
+ mapper.resolveResourceIssuesNotAlreadyResolved(resourceId);
}
public PurgeDao deleteSnapshots(PurgeSnapshotQuery query) {
List<Long> selectMetricIdsWithoutHistoricalData();
- List<Long> selectCharacteristicIdsToPurge();
-
void deleteSnapshotWastedMeasures(@Param("snapshotIds") List<Long> snapshotIds, @Param("mids") List<Long> metricIds);
- void deleteSnapshotMeasuresOnCharacteristics(@Param("snapshotIds") List<Long> snapshotIds, @Param("cids") List<Long> characteristicIds);
-
void updatePurgeStatusToOne(long snapshotId);
void disableResource(long resourceId);
+ void resolveResourceIssuesNotAlreadyResolved(long resourceId);
+
void deleteResourceIndex(@Param("resourceIds") List<Long> resourceIds);
void deleteEvent(long eventId);
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('522');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('523');
INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('524');
+INSERT INTO SCHEMA_MIGRATIONS(VERSION) VALUES ('525');
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;
update projects set enabled=${_false} where id=#{id}
</update>
+ <update id="resolveResourceIssuesNotAlreadyResolved" parameterType="long">
+ update issues set status='CLOSED',resolution='REMOVED' where component_id=#{id} AND resolution IS NULL
+ </update>
+
<delete id="deleteResourceIndex" parameterType="map">
delete from resource_index where resource_id in
<foreach collection="resourceIds" open="(" close=")" item="resourceId" separator=",">
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.resource.ResourceDao;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class PurgeDaoTest extends AbstractDaoTestCase {
- private PurgeDao dao;
+ System2 system2;
+
+ PurgeDao dao;
@Before
public void createDao() {
+ system2 = mock(System2.class);
+ when(system2.now()).thenReturn(DateUtils.parseDate("2014-04-09").getTime());
+
dao = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis()), new PurgeProfiler());
}
}
@Test
- public void shouldDisableResourcesWithoutLastSnapshot() {
- setupData("shouldDisableResourcesWithoutLastSnapshot");
- dao.purge(new PurgeConfiguration(1L, new String[0], 30));
- checkTables("shouldDisableResourcesWithoutLastSnapshot", "projects", "snapshots");
+ public void disable_resources_without_last_snapshot() {
+ setupData("disable_resources_without_last_snapshot");
+ dao.purge(new PurgeConfiguration(1L, new String[0], 30, system2));
+ checkTables("disable_resources_without_last_snapshot", "projects", "snapshots", "issues");
}
@Test
checkTables("should_delete_all_closed_issues", "issues", "issue_changes");
}
-
static final class SnapshotMatcher extends BaseMatcher<PurgeableSnapshotDto> {
long snapshotId;
boolean isLast;
--- /dev/null
+<!--
+
+What has been changed :
+* enabled=false on projects
+* purge_status=1 on snapshots
+* resolve not already resolved issues on all components
+
+-->
+<dataset>
+
+ <!-- the project -->
+ <projects id="1" enabled="[false]" root_id="[null]" created_at="[null]"
+ long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+ <!-- the directory -->
+ <projects id="2" enabled="[false]" root_id="1" created_at="[null]"
+ long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+ <!-- the file -->
+ <projects id="3" enabled="[false]" root_id="1" created_at="[null]"
+ long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+ <snapshots id="1"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+ <snapshots id="2"
+ project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+
+ <snapshots id="3"
+ project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+ <!-- Open issue on file -->
+ <issues id="1" kee="ISSUE-1"
+ component_id="3"
+ root_component_id="1"
+ status="CLOSED"
+ issue_close_date="[null]"
+ 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="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+
+ <!-- Open issue on directory -->
+ <issues id="2" kee="ISSUE-2"
+ component_id="2"
+ root_component_id="1"
+ status="CLOSED"
+ issue_close_date="[null]"
+ 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="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+
+ <!-- Open issue on project -->
+ <issues id="3" kee="ISSUE-3"
+ component_id="1"
+ root_component_id="1"
+ status="CLOSED"
+ issue_close_date="[null]"
+ 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="[null]" issue_creation_date="2013-04-16" issue_update_date="2013-04-16" created_at="2013-04-16"/>
+
+ <!-- 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"
+ 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"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <!-- the project -->
+ <projects id="1" enabled="[true]" root_id="[null]" created_at="[null]"
+ long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+ <!-- the directory -->
+ <projects id="2" enabled="[true]" root_id="1" created_at="[null]"
+ long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+ <!-- the file -->
+ <projects id="3" enabled="[true]" root_id="1" created_at="[null]"
+ long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java"
+ description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
+
+ <snapshots id="1"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[false]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+ <snapshots id="2"
+ project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[false]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+
+ <snapshots id="3"
+ project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[false]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
+ <!-- Open issue on file -->
+ <issues id="1" kee="ISSUE-1"
+ component_id="3"
+ root_component_id="1"
+ status="OPEN"
+ 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"/>
+
+ <!-- Open issue on directory -->
+ <issues id="2" kee="ISSUE-2"
+ component_id="2"
+ root_component_id="1"
+ status="OPEN"
+ 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"/>
+
+ <!-- Open issue on project -->
+ <issues id="3" kee="ISSUE-3"
+ component_id="1"
+ root_component_id="1"
+ status="CONFIRM"
+ 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"/>
+
+ <!-- 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"
+ 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"/>
+
+</dataset>
+++ /dev/null
-<!--
-
-What has been changed :
-* enabled=false on projects
-* purge_status=1 on snapshots
-
--->
-<dataset>
-
- <!-- the project -->
- <projects id="1" enabled="[false]" root_id="[null]" created_at="[null]"
- long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
- <!-- the directory -->
- <projects id="2" enabled="[false]" root_id="1" created_at="[null]"
- long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
- <!-- the file -->
- <projects id="3" enabled="[false]" root_id="1" created_at="[null]"
- long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
- <snapshots id="1"
- project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- status="P" islast="[false]" purge_status="1"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
-
- <snapshots id="2"
- project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
- status="P" islast="[false]" purge_status="1"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
-
-
- <snapshots id="3"
- project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
- status="P" islast="[false]" purge_status="1"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
-
-</dataset>
+++ /dev/null
-<dataset>
-
- <!-- the project -->
- <projects id="1" enabled="[true]" root_id="[null]" created_at="[null]"
- long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
- <!-- the directory -->
- <projects id="2" enabled="[true]" root_id="1" created_at="[null]"
- long_name="[null]" scope="DIR" qualifier="DIR" kee="project:my/dir" name="my/dir"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
- <!-- the file -->
- <projects id="3" enabled="[true]" root_id="1" created_at="[null]"
- long_name="[null]" scope="FIL" qualifier="FIL" kee="project:my/dir/File.java" name="my/dir/File.java"
- description="[null]" language="java" copy_resource_id="[null]" person_id="[null]" path="[null]" deprecated_kee="[null]" />
-
- <snapshots id="1"
- project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
- status="P" islast="[false]" purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
-
- <snapshots id="2"
- project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
- status="P" islast="[false]" purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
-
-
- <snapshots id="3"
- project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
- status="P" islast="[false]" purge_status="[null]"
- period1_mode="[null]" period1_param="[null]" period1_date="[null]"
- period2_mode="[null]" period2_param="[null]" period2_date="[null]"
- period3_mode="[null]" period3_param="[null]" period3_date="[null]"
- period4_mode="[null]" period4_param="[null]" period4_date="[null]"
- period5_mode="[null]" period5_param="[null]" period5_date="[null]"
- depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
-
-</dataset>
long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+ <snapshots id="1"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
<!-- old closed issues on file and project -->
<!--
long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+ <snapshots id="1"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
+
<!-- old closed issues on file and project -->
<issues id="1" kee="ISSUE-1"
long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+ <snapshots id="1"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
<!-- old closed issues on file and project -> to be purged -->
<!--
long_name="[null]" scope="PRJ" qualifier="TRK" kee="project" name="project"
description="[null]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+ <snapshots id="1"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ status="P" islast="[true]" purge_status="[null]"
+ period1_mode="[null]" period1_param="[null]" period1_date="[null]"
+ period2_mode="[null]" period2_param="[null]" period2_date="[null]"
+ period3_mode="[null]" period3_param="[null]" period3_date="[null]"
+ period4_mode="[null]" period4_param="[null]" period4_date="[null]"
+ period5_mode="[null]" period5_param="[null]" period5_date="[null]"
+ depth="[null]" scope="PRJ" qualifier="TRK" created_at="2008-12-02 13:58:00.00" build_date="2008-12-02 13:58:00.00" version="[null]" path="[null]"/>
<!-- old closed issues on file and project -> to be purged -->
<issues id="1" kee="ISSUE-1"
public interface DatabaseMigrations {
List<Class<? extends DatabaseMigration>> CLASSES = ImmutableList.of(
+ // 3.6
ViolationMigration.class,
+
+ // 4.2
+ PackageKeysMigration.class, CompleteIssueMessageMigration.class,
+
+ // 4.3
IssueMigration.class,
IssueChangelogMigration.class,
TechnicalDebtMeasuresMigration.class,
DevelopmentCostMeasuresMigration.class,
RequirementMeasuresMigration.class,
-
- // 4.2
- PackageKeysMigration.class, CompleteIssueMessageMigration.class
+ NotResolvedIssuesOnRemovedComponentsMigration.class
);
}
package org.sonar.server.db.migrations;
+import com.google.common.annotations.VisibleForTesting;
import org.apache.commons.dbutils.DbUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
} else {
stmt.setFetchSize(GROUP_SIZE);
}
- rs = stmt.executeQuery(inputLoader.selectSql());
+ rs = stmt.executeQuery(convertSelectSql(inputLoader.selectSql(), db));
int cursor = 0;
while (rs.next()) {
}
}
+ @VisibleForTesting
+ static String convertSelectSql(String selectSql, Database db){
+ // Replace ${_true}
+ selectSql = selectSql.replace("${_true}", db.getDialect().getTrueSqlValue());
+
+ // Replace ${_false}
+ selectSql = selectSql.replace("${_false}", db.getDialect().getFalseSqlValue());
+
+ return selectSql;
+ }
+
}
package org.sonar.server.db.migrations.v43;
import com.google.common.annotations.VisibleForTesting;
-import org.sonar.api.config.Settings;
+import org.sonar.api.issue.Issue;
import org.sonar.api.utils.System2;
import org.sonar.core.persistence.Database;
import org.sonar.server.db.migrations.DatabaseMigration;
/**
* Used in the Active Record Migration 525
+ *
* @since 4.3
*/
public class NotResolvedIssuesOnRemovedComponentsMigration implements DatabaseMigration {
- private final WorkDurationConvertor workDurationConvertor;
private final System2 system2;
private final Database db;
- public NotResolvedIssuesOnRemovedComponentsMigration(Database database, Settings settings) {
- this(database, settings, System2.INSTANCE);
+ public NotResolvedIssuesOnRemovedComponentsMigration(Database database) {
+ this(database, System2.INSTANCE);
}
@VisibleForTesting
- NotResolvedIssuesOnRemovedComponentsMigration(Database database, Settings settings, System2 system2) {
+ NotResolvedIssuesOnRemovedComponentsMigration(Database database, System2 system2) {
this.db = database;
- this.workDurationConvertor = new WorkDurationConvertor(settings);
this.system2 = system2;
}
new MassUpdater.InputLoader<Row>() {
@Override
public String selectSql() {
- return "SELECT i.id, i.technical_debt FROM issues i WHERE i.technical_debt IS NOT NULL";
+ return "SELECT i.id FROM issues i " +
+ "INNER JOIN projects p on p.id=i.component_id " +
+ "WHERE p.enabled=${_false} AND i.resolution IS NULL ";
}
@Override
public Row load(ResultSet rs) throws SQLException {
Row row = new Row();
row.id = SqlUtil.getLong(rs, 1);
- row.debt = SqlUtil.getLong(rs, 2);
return row;
}
},
new MassUpdater.InputConverter<Row>() {
@Override
public String updateSql() {
- return "UPDATE issues SET technical_debt=?,updated_at=? WHERE id=?";
+ return "UPDATE issues SET status=?,resolution=?,updated_at=? WHERE id=?";
}
@Override
public boolean convert(Row row, PreparedStatement updateStatement) throws SQLException {
- updateStatement.setLong(1, workDurationConvertor.createFromLong(row.debt));
- updateStatement.setTimestamp(2, new Timestamp(system2.now()));
- updateStatement.setLong(3, row.id);
+ updateStatement.setString(1, Issue.STATUS_CLOSED);
+ updateStatement.setString(2, Issue.RESOLUTION_REMOVED);
+ updateStatement.setTimestamp(3, new Timestamp(system2.now()));
+ updateStatement.setLong(4, row.id);
return true;
}
}
private static class Row {
private Long id;
- private Long debt;
}
}
--- /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 4.3
+# SONAR-5200
+#
+class UpdateNotResolvedIssuesOnRemovedComponents < ActiveRecord::Migration
+
+ def self.up
+ Java::OrgSonarServerUi::JRubyFacade.getInstance().databaseMigrator().executeMigration('org.sonar.server.db.migrations.v43.NotResolvedIssuesOnRemovedComponentsMigration')
+ 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.
+ */
+
+package org.sonar.server.db.migrations;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.core.persistence.Database;
+import org.sonar.core.persistence.dialect.Dialect;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class MassUpdaterTest {
+
+ @Mock
+ Database db;
+
+ @Test
+ public void convert_select_sql() throws Exception {
+ Dialect dialect = mock(Dialect.class);
+ when(dialect.getTrueSqlValue()).thenReturn("true");
+ when(dialect.getFalseSqlValue()).thenReturn("false");
+
+ when(db.getDialect()).thenReturn(dialect);
+
+ String result = MassUpdater.convertSelectSql("SELECT * FROM projects WHERE enabled=${_true} AND used=${_true} AND deleted=${_false}", db);
+ assertThat(result).isEqualTo("SELECT * FROM projects WHERE enabled=true AND used=true AND deleted=false");
+ }
+}
--- /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.v43;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.api.utils.System2;
+import org.sonar.core.persistence.TestDatabase;
+
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NotResolvedIssuesOnRemovedComponentsMigrationTest {
+
+ @ClassRule
+ public static TestDatabase db = new TestDatabase().schema(NotResolvedIssuesOnRemovedComponentsMigrationTest.class, "schema.sql");
+
+ @Mock
+ System2 system2;
+
+ NotResolvedIssuesOnRemovedComponentsMigration migration;
+
+ @Before
+ public void setUp() throws Exception {
+ when(system2.now()).thenReturn(DateUtils.parseDate("2014-04-09").getTime());
+
+ migration = new NotResolvedIssuesOnRemovedComponentsMigration(db.database(), system2);
+ }
+
+ @Test
+ public void migrate_issues() throws Exception {
+ db.prepareDbUnit(getClass(), "migrate_issues.xml");
+
+ migration.execute();
+
+ db.assertDbUnit(getClass(), "migrate_issues_result.xml", "issues");
+ }
+
+}
--- /dev/null
+<dataset>
+
+ <projects id="1" root_id="[null]" scope="FIL" qualifier="FIL" kee="org.struts:struts:/src/main/java/org/struts/Action.java" name="Action"
+ description="[null]" long_name="org.struts.Action"
+ enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" path="/foo/bar" deprecated_kee="org.struts:struts:org.struts.Action" />
+
+ <projects id="2" root_id="[null]" scope="FIL" qualifier="FIL" kee="org.struts:struts:/src/main/java/org/struts/Filter.java" name="Filter"
+ description="[null]" long_name="org.struts.Filter"
+ enabled="[false]" language="java" copy_resource_id="[null]" person_id="[null]" created_at="[null]" path="[null]" deprecated_kee="org.struts:struts:org.struts.Filter" />
+
+ <!-- Issue not resolved on not removed component -> Nothing to do -->
+ <issues ID="1" COMPONENT_ID="1" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="1"
+ ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+ EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+ ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+ RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+ TECHNICAL_DEBT="10"/>
+
+ <!-- Issue not resolved on removed component -> To be closed -->
+ <issues ID="2" COMPONENT_ID="2" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="2"
+ ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+ EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+ ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+ RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+ TECHNICAL_DEBT="10"/>
+
+ <!-- Issue resolved on removed component -> Nothing to do -->
+ <issues ID="3" COMPONENT_ID="2" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="3"
+ ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+ EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+ ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+ RESOLUTION="FIXED" STATUS="CLOSED" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+ TECHNICAL_DEBT="10"/>
+
+</dataset>
--- /dev/null
+<dataset>
+
+ <!-- Issue not resolved on not removed component -> Nothing to do -->
+ <issues ID="1" COMPONENT_ID="1" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="1"
+ ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+ EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+ ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+ RESOLUTION="[null]" STATUS="OPEN" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+ TECHNICAL_DEBT="10"/>
+
+ <!-- Issue not resolved on removed component -> To be closed -->
+ <issues ID="2" COMPONENT_ID="2" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="2"
+ ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+ EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+ ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+ RESOLUTION="REMOVED" STATUS="CLOSED" CREATED_AT="2012-01-05" UPDATED_AT="2014-04-09 00:00:00.0"
+ TECHNICAL_DEBT="10"/>
+
+ <!-- Issue resolved on removed component -> Nothing to do -->
+ <issues ID="3" COMPONENT_ID="2" ROOT_COMPONENT_ID="10" RULE_ID="20" SEVERITY="MINOR" KEE="3"
+ ACTION_PLAN_KEY="[null]" ASSIGNEE="[null]" AUTHOR_LOGIN="[null]" CHECKSUM="ABCDE"
+ EFFORT_TO_FIX="3.14" ISSUE_ATTRIBUTES="[null]" ISSUE_CLOSE_DATE="[null]" ISSUE_CREATION_DATE="2012-01-05"
+ ISSUE_UPDATE_DATE="2012-01-05" LINE="1234" MANUAL_SEVERITY="[false]" MESSAGE="the message" REPORTER="[null]"
+ RESOLUTION="FIXED" STATUS="CLOSED" CREATED_AT="2012-01-05" UPDATED_AT="2012-01-05"
+ TECHNICAL_DEBT="10"/>
+
+</dataset>
--- /dev/null
+-- 4.3
+
+CREATE TABLE "ISSUES" (
+ "ID" INTEGER 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,
+ "STATUS" VARCHAR(20),
+ "RESOLUTION" VARCHAR(20),
+ "CHECKSUM" VARCHAR(1000),
+ "REPORTER" VARCHAR(40),
+ "ASSIGNEE" VARCHAR(40),
+ "AUTHOR_LOGIN" VARCHAR(100),
+ "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,
+ "TECHNICAL_DEBT" INTEGER
+);
+
+CREATE TABLE "PROJECTS" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "NAME" VARCHAR(256),
+ "DESCRIPTION" VARCHAR(2000),
+ "ENABLED" BOOLEAN NOT NULL DEFAULT TRUE,
+ "SCOPE" VARCHAR(3),
+ "QUALIFIER" VARCHAR(10),
+ "KEE" VARCHAR(400),
+ "DEPRECATED_KEE" VARCHAR(400),
+ "PATH" VARCHAR(2000),
+ "ROOT_ID" INTEGER,
+ "LANGUAGE" VARCHAR(20),
+ "COPY_RESOURCE_ID" INTEGER,
+ "LONG_NAME" VARCHAR(256),
+ "PERSON_ID" INTEGER,
+ "CREATED_AT" TIMESTAMP
+);