aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-db/src
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@sonarsource.com>2015-07-05 10:06:55 +0200
committerSimon Brandhof <simon.brandhof@sonarsource.com>2015-07-06 09:22:44 +0200
commit32af292b745b7226bacc3f34d612437664af0ba3 (patch)
tree538d0b9852eaeb08ad685d426ea61c8170210e40 /sonar-db/src
parent1df148803610cd54f182b8636f01c0e6ece92b19 (diff)
downloadsonarqube-32af292b745b7226bacc3f34d612437664af0ba3.tar.gz
sonarqube-32af292b745b7226bacc3f34d612437664af0ba3.zip
Move some classes from sonar-server to sonar-db
Diffstat (limited to 'sonar-db/src')
-rw-r--r--sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java2
-rw-r--r--sonar-db/src/main/java/org/sonar/db/AbstractDao.java (renamed from sonar-db/src/main/java/org/sonar/db/component/ComponentIndexMapper.java)22
-rw-r--r--sonar-db/src/main/java/org/sonar/db/DaoUtils.java88
-rw-r--r--sonar-db/src/main/java/org/sonar/db/DatabaseChecker.java86
-rw-r--r--sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java61
-rw-r--r--sonar-db/src/main/java/org/sonar/db/DbClient2.java253
-rw-r--r--sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java17
-rw-r--r--sonar-db/src/main/java/org/sonar/db/MyBatis.java47
-rw-r--r--sonar-db/src/main/java/org/sonar/db/ResultSetIterator.java115
-rw-r--r--sonar-db/src/main/java/org/sonar/db/activity/ActivityDao.java49
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDao.java45
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java71
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java21
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java5
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java3
-rw-r--r--sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java107
-rw-r--r--sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDao.java107
-rw-r--r--sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java2
-rw-r--r--sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java20
-rw-r--r--sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDao.java76
-rw-r--r--sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDao.java90
-rw-r--r--sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java3
-rw-r--r--sonar-db/src/main/java/org/sonar/db/event/EventDao.java (renamed from sonar-db/src/main/java/org/sonar/batch/index/ResourceCopy.java)24
-rw-r--r--sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java2
-rw-r--r--sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java12
-rw-r--r--sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java49
-rw-r--r--sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java3
-rw-r--r--sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java87
-rw-r--r--sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java3
-rw-r--r--sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java3
-rw-r--r--sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java5
-rw-r--r--sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java3
-rw-r--r--sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java24
-rw-r--r--sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java11
-rw-r--r--sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java67
-rw-r--r--sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java3
-rw-r--r--sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java6
-rw-r--r--sonar-db/src/main/java/org/sonar/db/source/FileSourceDao.java146
-rw-r--r--sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java3
-rw-r--r--sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java3
-rw-r--r--sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java5
-rw-r--r--sonar-db/src/main/java/org/sonar/db/user/UserGroupDao.java (renamed from sonar-db/src/main/java/org/sonar/core/issue/db/package-info.java)26
-rw-r--r--sonar-db/src/main/resources/org/sonar/db/component/ComponentIndexMapper.xml16
-rw-r--r--sonar-db/src/main/resources/org/sonar/db/component/ResourceIndexerMapper.xml10
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java55
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DatabaseCheckerTest.java114
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java51
-rw-r--r--sonar-db/src/test/java/org/sonar/db/DbTester.java196
-rw-r--r--sonar-db/src/test/java/org/sonar/db/MyBatisTest.java2
-rw-r--r--sonar-db/src/test/java/org/sonar/db/ResultSetIteratorTest.java176
-rw-r--r--sonar-db/src/test/java/org/sonar/db/TestDb.java175
-rw-r--r--sonar-db/src/test/java/org/sonar/db/activity/ActivityDaoTest.java59
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java100
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java27
-rw-r--r--sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java305
-rw-r--r--sonar-db/src/test/java/org/sonar/db/compute/AnalysisReportDaoTest.java212
-rw-r--r--sonar-db/src/test/java/org/sonar/db/dashboard/WidgetDaoTest.java (renamed from sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java)64
-rw-r--r--sonar-db/src/test/java/org/sonar/db/event/EventDaoTest.java116
-rw-r--r--sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java17
-rw-r--r--sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java117
-rw-r--r--sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java333
-rw-r--r--sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java20
-rw-r--r--sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java8
-rw-r--r--sonar-db/src/test/java/org/sonar/db/rule/RuleTesting.java105
-rw-r--r--sonar-db/src/test/java/org/sonar/db/source/FileSourceDaoTest.java175
-rw-r--r--sonar-db/src/test/java/org/sonar/db/user/UserGroupDaoTest.java69
-rw-r--r--sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java229
-rw-r--r--sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/feed.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/schema.sql4
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml (renamed from sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/empty.xml)0
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml7
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/select_project_ids_from_query_and_view_or_sub_view_uuid.xml32
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/empty.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/insert-result.xml13
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/modules.xml90
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_previous_version_snapshots.xml48
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_snapshots_by_query.xml64
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/shared.xml13
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/snapshots.xml65
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/any-analysis-reports.xml26
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml18
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/empty.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/insert-result.xml24
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/one_analysis_report.xml12
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml27
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_oldest_pending.xml37
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/select.xml29
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/three_analysis_reports.xml26
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/truncate-result.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending-result.xml36
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending.xml35
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/zip.zipbin0 -> 578 bytes
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/dashboard/WidgetDaoTest/before.xml18
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/delete.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/empty.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/insert-result.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/shared.xml13
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_by_action_plan.xml29
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/get_by_key.xml28
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/insert-result.xml29
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update-result.xml29
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update.xml28
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/empty.xml3
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml27
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures.xml59
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_characteristic_id.xml28
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml22
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_rule_id.xml32
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/shared.xml21
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml11
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml10
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml11
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml14
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml14
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml19
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml19
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml22
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml12
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml8
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/insert-result.xml17
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/no_line_hashes_when_only_test_data.xml9
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/shared.xml9
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update-result.xml11
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml18
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml16
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id-result.xml6
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id.xml8
-rw-r--r--sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/insert-result.xml5
-rw-r--r--sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml7
136 files changed, 4895 insertions, 915 deletions
diff --git a/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java b/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java
index 2d16c7137d0..9a70977c140 100644
--- a/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java
+++ b/sonar-db/src/main/java/org/sonar/core/timemachine/Periods.java
@@ -30,11 +30,9 @@ import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.database.model.Snapshot;
import org.sonar.api.i18n.I18n;
-import org.sonar.api.server.ServerSide;
import static org.sonar.api.utils.DateUtils.longToDate;
-@ServerSide
public class Periods {
private final Settings settings;
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentIndexMapper.java b/sonar-db/src/main/java/org/sonar/db/AbstractDao.java
index 44eafac3a24..245f0e87ec9 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ComponentIndexMapper.java
+++ b/sonar-db/src/main/java/org/sonar/db/AbstractDao.java
@@ -17,13 +17,25 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+package org.sonar.db;
-package org.sonar.db.component;
+import org.sonar.api.utils.System2;
-import java.util.List;
-import org.apache.ibatis.annotations.Param;
+public abstract class AbstractDao implements Dao {
-public interface ComponentIndexMapper {
+ private final MyBatis myBatis;
+ private final System2 system2;
- List<Long> selectProjectIdsFromQueryAndViewOrSubViewUuid(@Param("query") String query, @Param("viewUuidQuery") String viewUuidQuery);
+ public AbstractDao(MyBatis myBatis, System2 system2) {
+ this.myBatis = myBatis;
+ this.system2 = system2;
+ }
+
+ protected MyBatis myBatis() {
+ return myBatis;
+ }
+
+ protected long now() {
+ return system2.now();
+ }
}
diff --git a/sonar-db/src/main/java/org/sonar/db/DaoUtils.java b/sonar-db/src/main/java/org/sonar/db/DaoUtils.java
index 5c0d3269e3c..7e3773f2b0d 100644
--- a/sonar-db/src/main/java/org/sonar/db/DaoUtils.java
+++ b/sonar-db/src/main/java/org/sonar/db/DaoUtils.java
@@ -19,19 +19,22 @@
*/
package org.sonar.db;
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import java.util.Collection;
-import java.util.Collections;
+import java.util.Arrays;
import java.util.List;
+import org.sonar.db.activity.ActivityDao;
+import org.sonar.db.component.ComponentLinkDao;
import org.sonar.db.component.ResourceDao;
import org.sonar.db.component.ResourceIndexerDao;
import org.sonar.db.component.ResourceKeyUpdaterDao;
+import org.sonar.db.component.SnapshotDao;
+import org.sonar.db.compute.AnalysisReportDao;
import org.sonar.db.dashboard.ActiveDashboardDao;
import org.sonar.db.dashboard.DashboardDao;
+import org.sonar.db.dashboard.WidgetDao;
+import org.sonar.db.dashboard.WidgetPropertyDao;
import org.sonar.db.debt.CharacteristicDao;
import org.sonar.db.duplication.DuplicationDao;
+import org.sonar.db.event.EventDao;
import org.sonar.db.issue.ActionPlanDao;
import org.sonar.db.issue.ActionPlanStatsDao;
import org.sonar.db.issue.IssueChangeDao;
@@ -39,48 +42,53 @@ import org.sonar.db.issue.IssueDao;
import org.sonar.db.issue.IssueFilterDao;
import org.sonar.db.issue.IssueFilterFavouriteDao;
import org.sonar.db.loadedtemplate.LoadedTemplateDao;
+import org.sonar.db.measure.MeasureDao;
+import org.sonar.db.measure.MeasureFilterDao;
import org.sonar.db.notification.NotificationQueueDao;
import org.sonar.db.permission.PermissionDao;
import org.sonar.db.permission.PermissionTemplateDao;
import org.sonar.db.property.PropertiesDao;
import org.sonar.db.purge.PurgeDao;
import org.sonar.db.qualitygate.QualityGateConditionDao;
-import org.sonar.db.qualityprofile.ActiveRuleDao;
import org.sonar.db.qualityprofile.QualityProfileDao;
import org.sonar.db.rule.RuleDao;
import org.sonar.db.semaphore.SemaphoreDao;
+import org.sonar.db.source.FileSourceDao;
import org.sonar.db.user.AuthorDao;
import org.sonar.db.user.AuthorizationDao;
import org.sonar.db.user.GroupMembershipDao;
import org.sonar.db.user.RoleDao;
import org.sonar.db.user.UserDao;
-
-import static com.google.common.collect.Lists.newArrayList;
+import org.sonar.db.user.UserGroupDao;
public final class DaoUtils {
- private static final int PARTITION_SIZE_FOR_ORACLE = 1000;
-
private DaoUtils() {
// only static stuff
}
- public static List<Class> getDaoClasses() {
- return ImmutableList.<Class>of(
+ public static List<Class<? extends Dao>> getDaoClasses() {
+ return Arrays.asList(
ActionPlanDao.class,
ActionPlanStatsDao.class,
ActiveDashboardDao.class,
- ActiveRuleDao.class,
+ ActivityDao.class,
+ AnalysisReportDao.class,
AuthorDao.class,
AuthorizationDao.class,
+ ComponentLinkDao.class,
DashboardDao.class,
DuplicationDao.class,
+ EventDao.class,
+ FileSourceDao.class,
GroupMembershipDao.class,
IssueDao.class,
IssueChangeDao.class,
IssueFilterDao.class,
IssueFilterFavouriteDao.class,
LoadedTemplateDao.class,
+ MeasureDao.class,
+ MeasureFilterDao.class,
NotificationQueueDao.class,
PermissionDao.class,
PermissionTemplateDao.class,
@@ -95,55 +103,11 @@ public final class DaoUtils {
RoleDao.class,
RuleDao.class,
SemaphoreDao.class,
- UserDao.class
+ SnapshotDao.class,
+ UserDao.class,
+ UserGroupDao.class,
+ WidgetDao.class,
+ WidgetPropertyDao.class
);
}
-
- /**
- * Partition by 1000 elements a list of input and execute a function on each part.
- *
- * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)'
- * and with MsSQL when there's more than 2000 parameters in a query
- */
- public static <OUTPUT, INPUT> List<OUTPUT> executeLargeInputs(Collection<INPUT> input, Function<List<INPUT>, List<OUTPUT>> function) {
- if (input.isEmpty()) {
- return Collections.emptyList();
- }
- List<OUTPUT> results = newArrayList();
- List<List<INPUT>> partitionList = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE);
- for (List<INPUT> partition : partitionList) {
- List<OUTPUT> subResults = function.apply(partition);
- results.addAll(subResults);
- }
- return results;
- }
-
- /**
- * Partition by 1000 elements a list of input and execute a function on each part.
- * The function has not output (ex: delete operation)
- *
- * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)'
- * and with MsSQL when there's more than 2000 parameters in a query
- */
- public static <INPUT> void executeLargeInputsWithoutOutput(Collection<INPUT> input, Function<List<INPUT>, Void> function) {
- if (input.isEmpty()) {
- return;
- }
-
- List<List<INPUT>> partitions = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE);
- for (List<INPUT> partition : partitions) {
- function.apply(partition);
- }
- }
-
- public static String repeatCondition(String sql, int count, String separator) {
- StringBuilder sb = new StringBuilder();
- for (int i = 0; i < count; i++) {
- sb.append(sql);
- if (i < count - 1) {
- sb.append(" ").append(separator).append(" ");
- }
- }
- return sb.toString();
- }
}
diff --git a/sonar-db/src/main/java/org/sonar/db/DatabaseChecker.java b/sonar-db/src/main/java/org/sonar/db/DatabaseChecker.java
new file mode 100644
index 00000000000..31dc571008f
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/DatabaseChecker.java
@@ -0,0 +1,86 @@
+/*
+ * 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.db;
+
+import com.google.common.base.Throwables;
+import java.sql.Connection;
+import java.sql.SQLException;
+import org.apache.commons.dbutils.DbUtils;
+import org.apache.commons.lang.StringUtils;
+import org.picocontainer.Startable;
+import org.sonar.api.utils.MessageException;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.dialect.H2;
+import org.sonar.db.dialect.Oracle;
+
+public class DatabaseChecker implements Startable {
+
+ public static final int ORACLE_MIN_MAJOR_VERSION = 11;
+
+ private final Database db;
+
+ public DatabaseChecker(Database db) {
+ this.db = db;
+ }
+
+ @Override
+ public void start() {
+ try {
+ if (H2.ID.equals(db.getDialect().getId())) {
+ Loggers.get(DatabaseChecker.class).warn("H2 database should be used for evaluation purpose only");
+ } else if (Oracle.ID.equals(db.getDialect().getId())) {
+ checkOracleVersion();
+ }
+ } catch (Exception e) {
+ Throwables.propagate(e);
+ }
+ }
+
+ @Override
+ public void stop() {
+ // nothing to do
+ }
+
+ private void checkOracleVersion() throws SQLException {
+ Connection connection = db.getDataSource().getConnection();
+ try {
+ // check version of db
+ // See http://jira.sonarsource.com/browse/SONAR-6434
+ int majorVersion = connection.getMetaData().getDatabaseMajorVersion();
+ if (majorVersion < ORACLE_MIN_MAJOR_VERSION) {
+ throw MessageException.of(String.format(
+ "Unsupported Oracle version: %s. Minimal required version is %d.", connection.getMetaData().getDatabaseProductVersion(), ORACLE_MIN_MAJOR_VERSION));
+ }
+
+ // check version of driver
+ String driverVersion = connection.getMetaData().getDriverVersion();
+ String[] parts = StringUtils.split(driverVersion, ".");
+ int intVersion = Integer.parseInt(parts[0]) * 100 + Integer.parseInt(parts[1]);
+ if (intVersion < 1102) {
+ throw MessageException.of(String.format(
+ "Unsupported Oracle JDBC driver version: %s. Minimal required version is 11.2.", driverVersion));
+ }
+
+ } finally {
+ DbUtils.closeQuietly(connection);
+ }
+ }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java b/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java
index 28ac5923b72..6d74d2474cc 100644
--- a/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java
+++ b/sonar-db/src/main/java/org/sonar/db/DatabaseUtils.java
@@ -19,17 +19,24 @@
*/
package org.sonar.db;
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
import javax.annotation.Nullable;
import org.slf4j.LoggerFactory;
-/**
- * @since 2.13
- */
+import static com.google.common.collect.Lists.newArrayList;
+
public final class DatabaseUtils {
+
+ private static final int PARTITION_SIZE_FOR_ORACLE = 1000;
+
private DatabaseUtils() {
// only static methods
}
@@ -66,4 +73,52 @@ public final class DatabaseUtils {
}
}
}
+
+ /**
+ * Partition by 1000 elements a list of input and execute a function on each part.
+ *
+ * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)'
+ * and with MsSQL when there's more than 2000 parameters in a query
+ */
+ public static <OUTPUT, INPUT> List<OUTPUT> executeLargeInputs(Collection<INPUT> input, Function<List<INPUT>, List<OUTPUT>> function) {
+ if (input.isEmpty()) {
+ return Collections.emptyList();
+ }
+ List<OUTPUT> results = newArrayList();
+ List<List<INPUT>> partitionList = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE);
+ for (List<INPUT> partition : partitionList) {
+ List<OUTPUT> subResults = function.apply(partition);
+ results.addAll(subResults);
+ }
+ return results;
+ }
+
+ /**
+ * Partition by 1000 elements a list of input and execute a function on each part.
+ * The function has not output (ex: delete operation)
+ *
+ * The goal is to prevent issue with ORACLE when there's more than 1000 elements in a 'in ('X', 'Y', ...)'
+ * and with MsSQL when there's more than 2000 parameters in a query
+ */
+ public static <INPUT> void executeLargeInputsWithoutOutput(Collection<INPUT> input, Function<List<INPUT>, Void> function) {
+ if (input.isEmpty()) {
+ return;
+ }
+
+ List<List<INPUT>> partitions = Lists.partition(newArrayList(input), PARTITION_SIZE_FOR_ORACLE);
+ for (List<INPUT> partition : partitions) {
+ function.apply(partition);
+ }
+ }
+
+ public static String repeatCondition(String sql, int count, String separator) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < count; i++) {
+ sb.append(sql);
+ if (i < count - 1) {
+ sb.append(" ").append(separator).append(" ");
+ }
+ }
+ return sb.toString();
+ }
}
diff --git a/sonar-db/src/main/java/org/sonar/db/DbClient2.java b/sonar-db/src/main/java/org/sonar/db/DbClient2.java
new file mode 100644
index 00000000000..92cbd39c2c5
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/DbClient2.java
@@ -0,0 +1,253 @@
+/*
+ * 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.db;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.sonar.db.activity.ActivityDao;
+import org.sonar.db.component.ComponentLinkDao;
+import org.sonar.db.component.ResourceDao;
+import org.sonar.db.component.ResourceIndexerDao;
+import org.sonar.db.component.SnapshotDao;
+import org.sonar.db.compute.AnalysisReportDao;
+import org.sonar.db.dashboard.DashboardDao;
+import org.sonar.db.dashboard.WidgetDao;
+import org.sonar.db.dashboard.WidgetPropertyDao;
+import org.sonar.db.debt.CharacteristicDao;
+import org.sonar.db.event.EventDao;
+import org.sonar.db.issue.ActionPlanDao;
+import org.sonar.db.issue.ActionPlanStatsDao;
+import org.sonar.db.issue.IssueChangeDao;
+import org.sonar.db.issue.IssueDao;
+import org.sonar.db.issue.IssueFilterDao;
+import org.sonar.db.loadedtemplate.LoadedTemplateDao;
+import org.sonar.db.measure.MeasureDao;
+import org.sonar.db.permission.PermissionTemplateDao;
+import org.sonar.db.property.PropertiesDao;
+import org.sonar.db.purge.PurgeDao;
+import org.sonar.db.qualitygate.QualityGateConditionDao;
+import org.sonar.db.qualityprofile.QualityProfileDao;
+import org.sonar.db.source.FileSourceDao;
+import org.sonar.db.user.AuthorDao;
+import org.sonar.db.user.AuthorizationDao;
+import org.sonar.db.user.GroupMembershipDao;
+import org.sonar.db.user.RoleDao;
+import org.sonar.db.user.UserGroupDao;
+
+public class DbClient2 {
+
+ private final MyBatis myBatis;
+ private final QualityProfileDao qualityProfileDao;
+ private final CharacteristicDao debtCharacteristicDao;
+ private final LoadedTemplateDao loadedTemplateDao;
+ private final PropertiesDao propertiesDao;
+ private final SnapshotDao snapshotDao;
+ private final ResourceDao resourceDao;
+ private final MeasureDao measureDao;
+ private final ActivityDao activityDao;
+ private final AuthorizationDao authorizationDao;
+ private final UserGroupDao userGroupDao;
+ private final GroupMembershipDao groupMembershipDao;
+ private final RoleDao roleDao;
+ private final PermissionTemplateDao permissionTemplateDao;
+ private final IssueDao issueDao;
+ private final IssueFilterDao issueFilterDao;
+ private final IssueChangeDao issueChangeDao;
+ private final ActionPlanDao actionPlanDao;
+ private final ActionPlanStatsDao actionPlanStatsDao;
+ private final AnalysisReportDao analysisReportDao;
+ private final DashboardDao dashboardDao;
+ private final WidgetDao widgetDao;
+ private final WidgetPropertyDao widgetPropertyDao;
+ private final FileSourceDao fileSourceDao;
+ private final AuthorDao authorDao;
+ private final ResourceIndexerDao componentIndexDao;
+ private final ComponentLinkDao componentLinkDao;
+ private final EventDao eventDao;
+ private final PurgeDao purgeDao;
+ private final QualityGateConditionDao gateConditionDao;
+
+ public DbClient2(MyBatis myBatis, Dao[] daos) {
+ this.myBatis = myBatis;
+
+ Map<Class, Dao> map = new IdentityHashMap<>();
+ for (Dao dao : daos) {
+ map.put(dao.getClass(), dao);
+ }
+ debtCharacteristicDao = getDao(map, CharacteristicDao.class);
+ qualityProfileDao = getDao(map, QualityProfileDao.class);
+ loadedTemplateDao = getDao(map, LoadedTemplateDao.class);
+ propertiesDao = getDao(map, PropertiesDao.class);
+ snapshotDao = getDao(map, SnapshotDao.class);
+ resourceDao = getDao(map, ResourceDao.class);
+ measureDao = getDao(map, MeasureDao.class);
+ activityDao = getDao(map, ActivityDao.class);
+ authorizationDao = getDao(map, AuthorizationDao.class);
+ userGroupDao = getDao(map, UserGroupDao.class);
+ groupMembershipDao = getDao(map, GroupMembershipDao.class);
+ roleDao = getDao(map, RoleDao.class);
+ permissionTemplateDao = getDao(map, PermissionTemplateDao.class);
+ issueDao = getDao(map, IssueDao.class);
+ issueFilterDao = getDao(map, IssueFilterDao.class);
+ issueChangeDao = getDao(map, IssueChangeDao.class);
+ actionPlanDao = getDao(map, ActionPlanDao.class);
+ actionPlanStatsDao = getDao(map, ActionPlanStatsDao.class);
+ analysisReportDao = getDao(map, AnalysisReportDao.class);
+ dashboardDao = getDao(map, DashboardDao.class);
+ widgetDao = getDao(map, WidgetDao.class);
+ widgetPropertyDao = getDao(map, WidgetPropertyDao.class);
+ fileSourceDao = getDao(map, FileSourceDao.class);
+ authorDao = getDao(map, AuthorDao.class);
+ componentIndexDao = getDao(map, ResourceIndexerDao.class);
+ componentLinkDao = getDao(map, ComponentLinkDao.class);
+ eventDao = getDao(map, EventDao.class);
+ purgeDao = getDao(map, PurgeDao.class);
+ gateConditionDao = getDao(map, QualityGateConditionDao.class);
+ }
+
+ public DbSession openSession(boolean batch) {
+ return myBatis.openSession(batch);
+ }
+
+ public void closeSession(@Nullable DbSession session) {
+ MyBatis.closeQuietly(session);
+ }
+
+ public IssueDao issueDao() {
+ return issueDao;
+ }
+
+ public IssueFilterDao issueFilterDao() {
+ return issueFilterDao;
+ }
+
+ public IssueChangeDao issueChangeDao() {
+ return issueChangeDao;
+ }
+
+ public QualityProfileDao qualityProfileDao() {
+ return qualityProfileDao;
+ }
+
+ public CharacteristicDao debtCharacteristicDao() {
+ return debtCharacteristicDao;
+ }
+
+ public LoadedTemplateDao loadedTemplateDao() {
+ return loadedTemplateDao;
+ }
+
+ public PropertiesDao propertiesDao() {
+ return propertiesDao;
+ }
+
+ public SnapshotDao snapshotDao() {
+ return snapshotDao;
+ }
+
+ public ResourceDao resourceDao() {
+ return resourceDao;
+ }
+
+ public MeasureDao measureDao() {
+ return measureDao;
+ }
+
+ public ActivityDao activityDao() {
+ return activityDao;
+ }
+
+ public AuthorizationDao authorizationDao() {
+ return authorizationDao;
+ }
+
+ public UserGroupDao userGroupDao() {
+ return userGroupDao;
+ }
+
+ public GroupMembershipDao groupMembershipDao() {
+ return groupMembershipDao;
+ }
+
+ public RoleDao roleDao() {
+ return roleDao;
+ }
+
+ public PermissionTemplateDao permissionTemplateDao() {
+ return permissionTemplateDao;
+ }
+
+ public ActionPlanDao actionPlanDao() {
+ return actionPlanDao;
+ }
+
+ public AnalysisReportDao analysisReportDao() {
+ return analysisReportDao;
+ }
+
+ public DashboardDao dashboardDao() {
+ return dashboardDao;
+ }
+
+ public WidgetDao widgetDao() {
+ return widgetDao;
+ }
+
+ public WidgetPropertyDao widgetPropertyDao() {
+ return widgetPropertyDao;
+ }
+
+ public FileSourceDao fileSourceDao() {
+ return fileSourceDao;
+ }
+
+ public AuthorDao authorDao() {
+ return authorDao;
+ }
+
+ public ResourceIndexerDao componentIndexDao() {
+ return componentIndexDao;
+ }
+
+ public ComponentLinkDao componentLinkDao() {
+ return componentLinkDao;
+ }
+
+ public EventDao eventDao() {
+ return eventDao;
+ }
+
+ public PurgeDao purgeDao() {
+ return purgeDao;
+ }
+
+ public ActionPlanStatsDao getActionPlanStatsDao() {
+ return actionPlanStatsDao;
+ }
+
+ public QualityGateConditionDao gateConditionDao() {
+ return gateConditionDao;
+ }
+
+ private <K extends Dao> K getDao(Map<Class, Dao> map, Class<K> clazz) {
+ return (K) map.get(clazz);
+ }
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java b/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java
index c5e5e1c12b8..47db0259f00 100644
--- a/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java
+++ b/sonar-db/src/main/java/org/sonar/db/DefaultDatabase.java
@@ -30,10 +30,10 @@ import org.apache.commons.dbcp.BasicDataSource;
import org.apache.commons.dbcp.BasicDataSourceFactory;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.sonar.api.config.Settings;
import org.sonar.api.database.DatabaseProperties;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.db.dialect.Dialect;
import org.sonar.db.dialect.DialectUtils;
import org.sonar.db.profiling.ProfiledDataSource;
@@ -43,7 +43,7 @@ import org.sonar.db.profiling.ProfiledDataSource;
*/
public class DefaultDatabase implements Database {
- private static final Logger LOG = LoggerFactory.getLogger(Database.class);
+ private static final Logger LOG = Loggers.get(Database.class);
private static final String DEFAULT_URL = "jdbc:h2:tcp://localhost/sonar";
private static final String SONAR_JDBC = "sonar.jdbc.";
@@ -65,20 +65,12 @@ public class DefaultDatabase implements Database {
initSettings();
initDatasource();
checkConnection();
- doAfterStart();
} catch (Exception e) {
throw new IllegalStateException("Fail to connect to database", e);
}
}
- /**
- * Override to execute post-startup code.
- */
- protected void doAfterStart() {
- // nothing to do
- }
-
@VisibleForTesting
void initSettings() {
properties = new Properties();
@@ -104,7 +96,6 @@ public class DefaultDatabase implements Database {
private void checkConnection() {
Connection connection = null;
try {
- LOG.debug("Testing JDBC connection");
connection = datasource.getConnection();
} catch (SQLException e) {
throw new IllegalStateException("Can not connect to database. Please check connectivity and settings (see the properties prefixed by 'sonar.jdbc.').", e);
@@ -176,7 +167,7 @@ public class DefaultDatabase implements Database {
}
private static void completeDefaultProperty(Properties props, String key, String defaultValue) {
- if (props.getProperty(key) == null && defaultValue != null) {
+ if (props.getProperty(key) == null) {
props.setProperty(key, defaultValue);
}
}
diff --git a/sonar-db/src/main/java/org/sonar/db/MyBatis.java b/sonar-db/src/main/java/org/sonar/db/MyBatis.java
index a6aa01cbc4f..5926def8753 100644
--- a/sonar-db/src/main/java/org/sonar/db/MyBatis.java
+++ b/sonar-db/src/main/java/org/sonar/db/MyBatis.java
@@ -23,6 +23,9 @@ package org.sonar.db;
import ch.qos.logback.classic.Level;
import com.google.common.io.Closeables;
import java.io.InputStream;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
import javax.annotation.Nullable;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.logging.LogFactory;
@@ -35,10 +38,10 @@ import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.apache.ibatis.type.JdbcType;
import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.db.activity.ActivityDto;
import org.sonar.db.activity.ActivityMapper;
import org.sonar.db.component.ComponentDto;
-import org.sonar.db.component.ComponentIndexMapper;
import org.sonar.db.component.ComponentLinkDto;
import org.sonar.db.component.ComponentLinkMapper;
import org.sonar.db.component.ComponentMapper;
@@ -144,8 +147,6 @@ public class MyBatis {
private final Database database;
private SqlSessionFactory sessionFactory;
-
- // TODO this queue should directly be an IndexQueue. Pending move of persistence to sonar-server
private WorkQueue<?> queue;
public MyBatis(Database database, WorkQueue<?> queue) {
@@ -153,12 +154,13 @@ public class MyBatis {
this.queue = queue;
}
+ // FIXME should be visible only to DAOs -> to be moved to AbstractDao
public static void closeQuietly(@Nullable SqlSession session) {
if (session != null) {
try {
session.close();
} catch (Exception e) {
- LoggerFactory.getLogger(MyBatis.class).warn("Fail to close session", e);
+ Loggers.get(MyBatis.class).warn("Fail to close db session", e);
// do not re-throw the exception
}
}
@@ -255,7 +257,7 @@ public class MyBatis {
GroupMembershipMapper.class, QualityProfileMapper.class, ActiveRuleMapper.class,
MeasureMapper.class, MetricMapper.class, CustomMeasureMapper.class, QualityGateMapper.class, QualityGateConditionMapper.class, ComponentMapper.class, SnapshotMapper.class,
ProjectQgateAssociationMapper.class, EventMapper.class,
- AnalysisReportMapper.class, ComponentIndexMapper.class, ComponentLinkMapper.class,
+ AnalysisReportMapper.class, ComponentLinkMapper.class,
Migration45Mapper.class, Migration50Mapper.class
};
loadMappers(conf, mappers);
@@ -277,14 +279,6 @@ public class MyBatis {
}
/**
- * @deprecated since 4.4. Replaced by <code>openSession(true)</code>.
- */
- @Deprecated
- public BatchSession openBatchSession() {
- return (BatchSession) openSession(true);
- }
-
- /**
* @since 4.4
*/
public DbSession openSession(boolean batch) {
@@ -323,4 +317,31 @@ public class MyBatis {
private void loadAlias(Configuration conf, String alias, Class dtoClass) {
conf.getTypeAliasRegistry().registerAlias(alias, dtoClass);
}
+
+ /**
+ * Create a PreparedStatement for SELECT requests with scrolling of results
+ */
+ public PreparedStatement newScrollingSelectStatement(DbSession session, String sql) {
+ int fetchSize = database.getDialect().getScrollDefaultFetchSize();
+ return newScrollingSelectStatement(session, sql, fetchSize);
+ }
+
+ /**
+ * Create a PreparedStatement for SELECT requests with scrolling of results row by row (only one row
+ * in memory at a time)
+ */
+ public PreparedStatement newScrollingSingleRowSelectStatement(DbSession session, String sql) {
+ int fetchSize = database.getDialect().getScrollSingleRowFetchSize();
+ return newScrollingSelectStatement(session, sql, fetchSize);
+ }
+
+ private PreparedStatement newScrollingSelectStatement(DbSession session, String sql, int fetchSize) {
+ try {
+ PreparedStatement stmt = session.getConnection().prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
+ stmt.setFetchSize(fetchSize);
+ return stmt;
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to create SQL statement: " + sql, e);
+ }
+ }
}
diff --git a/sonar-db/src/main/java/org/sonar/db/ResultSetIterator.java b/sonar-db/src/main/java/org/sonar/db/ResultSetIterator.java
new file mode 100644
index 00000000000..e96a9577141
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/ResultSetIterator.java
@@ -0,0 +1,115 @@
+/*
+ * 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.db;
+
+import org.apache.commons.dbutils.DbUtils;
+
+import java.io.Closeable;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * Forward-only {@link java.util.Iterator} over a {@link java.sql.ResultSet}. Rows are
+ * lazily loaded. The underlying ResultSet must be closed by calling the method
+ * {@link #close()}
+ * <p/>
+ * As a safeguard, the ResultSet is automatically closed after the last element has
+ * been retrieved via {@link #next()} or {@link #hasNext()} is called (which will return false).
+ * This automagic behavior is not enough to remove explicit calls to {@link #close()}
+ * from caller methods. Errors raised before end of traversal must still be handled.
+ */
+public abstract class ResultSetIterator<E> implements Iterator<E>, Closeable {
+
+ private final ResultSet rs;
+ private final PreparedStatement stmt;
+
+ private volatile boolean didNext = false;
+ private volatile boolean hasNext = false;
+ private volatile boolean closed = false;
+
+ public ResultSetIterator(PreparedStatement stmt) throws SQLException {
+ this.stmt = stmt;
+ this.rs = stmt.executeQuery();
+ }
+
+ protected ResultSetIterator(ResultSet rs) {
+ this.stmt = null;
+ this.rs = rs;
+ }
+
+ @Override
+ public boolean hasNext() {
+ if (closed) {
+ return false;
+ }
+ if (!didNext) {
+ hasNext = doNextQuietly();
+ if (hasNext) {
+ didNext = true;
+ } else {
+ close();
+ }
+ }
+ return hasNext;
+ }
+
+ @Override
+ public E next() {
+ if (!hasNext()) {
+ close();
+ throw new NoSuchElementException();
+ }
+ try {
+ return read(rs);
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to read result set row", e);
+ } finally {
+ hasNext = doNextQuietly();
+ if (!hasNext) {
+ close();
+ }
+ }
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public void close() {
+ closed = true;
+ DbUtils.closeQuietly(rs);
+ DbUtils.closeQuietly(stmt);
+ }
+
+ protected abstract E read(ResultSet rs) throws SQLException;
+
+ private boolean doNextQuietly() {
+ try {
+ return rs.next();
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to read row of JDBC result set", e);
+ }
+ }
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/activity/ActivityDao.java b/sonar-db/src/main/java/org/sonar/db/activity/ActivityDao.java
new file mode 100644
index 00000000000..25b7539beba
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/activity/ActivityDao.java
@@ -0,0 +1,49 @@
+/*
+ * 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.db.activity;
+
+import java.util.Date;
+import org.sonar.api.utils.System2;
+import org.sonar.db.AbstractDao;
+import org.sonar.db.DbSession;
+import org.sonar.db.MyBatis;
+
+public class ActivityDao extends AbstractDao {
+
+ public ActivityDao(MyBatis mybatis, System2 system) {
+ super(mybatis, system);
+ }
+
+ public void insert(ActivityDto dto) {
+ DbSession session = myBatis().openSession(false);
+ try {
+ insert(session, dto);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void insert(DbSession session, ActivityDto dto) {
+ dto.setCreatedAt(new Date(now()));
+ session.getMapper(ActivityMapper.class).insert(dto);
+ }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDao.java b/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDao.java
new file mode 100644
index 00000000000..9c4f2940936
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/component/ComponentLinkDao.java
@@ -0,0 +1,45 @@
+/*
+ * 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.db.component;
+
+import java.util.List;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+public class ComponentLinkDao implements Dao {
+
+ public List<ComponentLinkDto> selectByComponentUuid(DbSession session, String componentUuid) {
+ return session.getMapper(ComponentLinkMapper.class).selectByComponentUuid(componentUuid);
+ }
+
+ public void insert(DbSession session, ComponentLinkDto dto) {
+ session.getMapper(ComponentLinkMapper.class).insert(dto);
+ }
+
+ public void update(DbSession session, ComponentLinkDto dto) {
+ session.getMapper(ComponentLinkMapper.class).update(dto);
+ }
+
+ public void delete(DbSession session, long id) {
+ session.getMapper(ComponentLinkMapper.class).delete(id);
+ }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java
index 2ebd03ec015..80addc6dd54 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceDao.java
@@ -32,27 +32,24 @@ import org.sonar.api.component.Component;
import org.sonar.api.resources.Scopes;
import org.sonar.api.utils.System2;
import org.sonar.api.utils.internal.Uuids;
-import org.sonar.db.Dao;
+import org.sonar.db.AbstractDao;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
import static com.google.common.collect.Lists.newArrayList;
-public class ResourceDao implements Dao {
- private MyBatis mybatis;
- private System2 system2;
+public class ResourceDao extends AbstractDao {
- public ResourceDao(MyBatis mybatis, System2 system2) {
- this.mybatis = mybatis;
- this.system2 = system2;
+ public ResourceDao(MyBatis myBatis, System2 system2) {
+ super(myBatis, system2);
}
public List<ResourceDto> getResources(ResourceQuery query) {
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return session.getMapper(ResourceMapper.class).selectResources(query);
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -66,11 +63,11 @@ public class ResourceDao implements Dao {
*/
@CheckForNull
public ResourceDto getResource(ResourceQuery query) {
- DbSession session = mybatis.openSession(false);
+ DbSession session = myBatis().openSession(false);
try {
return getResource(query, session);
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -84,30 +81,30 @@ public class ResourceDao implements Dao {
}
public List<Long> getResourceIds(ResourceQuery query) {
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return session.getMapper(ResourceMapper.class).selectResourceIds(query);
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
public ResourceDto getResource(long projectId) {
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return getResource(projectId, session);
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@CheckForNull
public ResourceDto getResource(String componentUuid) {
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return session.getMapper(ResourceMapper.class).selectResourceByUuid(componentUuid);
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -126,11 +123,11 @@ public class ResourceDao implements Dao {
}
public List<ResourceDto> getDescendantProjects(long projectId) {
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return getDescendantProjects(projectId, session);
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -153,9 +150,9 @@ public class ResourceDao implements Dao {
* Used by the Views Plugin
*/
public ResourceDao insertOrUpdate(ResourceDto... resources) {
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
ResourceMapper mapper = session.getMapper(ResourceMapper.class);
- Date now = new Date(system2.now());
+ Date now = new Date(now());
try {
for (ResourceDto resource : resources) {
if (resource.getId() == null) {
@@ -175,7 +172,7 @@ public class ResourceDao implements Dao {
}
session.commit();
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
return this;
}
@@ -184,7 +181,7 @@ public class ResourceDao implements Dao {
* Should not be called from batch side (used to reindex permission in E/S)
*/
public void updateAuthorizationDate(Long projectId, SqlSession session) {
- session.getMapper(ResourceMapper.class).updateAuthorizationDate(projectId, system2.now());
+ session.getMapper(ResourceMapper.class).updateAuthorizationDate(projectId, now());
}
@CheckForNull
@@ -222,11 +219,11 @@ public class ResourceDao implements Dao {
@CheckForNull
public ResourceDto getRootProjectByComponentKey(String componentKey) {
- DbSession session = mybatis.openSession(false);
+ DbSession session = myBatis().openSession(false);
try {
return getRootProjectByComponentKey(session, componentKey);
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -253,7 +250,7 @@ public class ResourceDao implements Dao {
*/
@CheckForNull
public ResourceDto getRootProjectByComponentId(long componentId) {
- DbSession session = mybatis.openSession(false);
+ DbSession session = myBatis().openSession(false);
try {
ResourceDto component = getParentModuleByComponentId(componentId, session);
Long rootId = component != null ? component.getRootId() : null;
@@ -263,7 +260,7 @@ public class ResourceDao implements Dao {
return component;
}
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -271,11 +268,11 @@ public class ResourceDao implements Dao {
if (qualifiers.isEmpty()) {
return Collections.emptyList();
}
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return toComponents(session.getMapper(ResourceMapper.class).selectProjectsByQualifiers(qualifiers));
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -286,11 +283,11 @@ public class ResourceDao implements Dao {
if (qualifiers.isEmpty()) {
return Collections.emptyList();
}
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return toComponents(session.getMapper(ResourceMapper.class).selectProjectsIncludingNotCompletedOnesByQualifiers(qualifiers));
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -304,11 +301,11 @@ public class ResourceDao implements Dao {
if (qualifiers.isEmpty()) {
return Collections.emptyList();
}
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return toComponents(session.getMapper(ResourceMapper.class).selectGhostsProjects(qualifiers));
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -319,11 +316,11 @@ public class ResourceDao implements Dao {
if (qualifiers.isEmpty()) {
return Collections.emptyList();
}
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return session.getMapper(ResourceMapper.class).selectProvisionedProjects(qualifiers);
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
@@ -335,11 +332,11 @@ public class ResourceDao implements Dao {
}
public ResourceDto selectProvisionedProject(String key) {
- DbSession session = mybatis.openSession(false);
+ DbSession session = myBatis().openSession(false);
try {
return selectProvisionedProject(session, key);
} finally {
- MyBatis.closeQuietly(session);
+ myBatis().closeQuietly(session);
}
}
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java
index 6a61ef714e6..827ece8fd1b 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerDao.java
@@ -19,16 +19,19 @@
*/
package org.sonar.db.component;
+import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.ResultContext;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.SqlSession;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Scopes;
+import org.sonar.api.utils.System2;
+import org.sonar.db.AbstractDao;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
-public class ResourceIndexerDao {
+public class ResourceIndexerDao extends AbstractDao {
private static final String SELECT_RESOURCES = "org.sonar.db.component.ResourceIndexerMapper.selectResources";
public static final int MINIMUM_KEY_SIZE = 3;
@@ -41,17 +44,19 @@ public class ResourceIndexerDao {
private static final String[] NOT_RENAMABLE_QUALIFIERS = {Qualifiers.FILE, Qualifiers.UNIT_TEST_FILE, Qualifiers.CLASS};
private static final String[] NOT_RENAMABLE_SCOPES = {Scopes.FILE};
- private final MyBatis mybatis;
+ public ResourceIndexerDao(MyBatis myBatis, System2 system2) {
+ super(myBatis, system2);
+ }
- public ResourceIndexerDao(MyBatis mybatis) {
- this.mybatis = mybatis;
+ public List<Long> selectProjectIdsFromQueryAndViewOrSubViewUuid(DbSession session, String query, String viewOrSubViewUuid) {
+ return session.getMapper(ResourceIndexerMapper.class).selectProjectIdsFromQueryAndViewOrSubViewUuid(query + "%", "%." + viewOrSubViewUuid + ".%");
}
/**
* This method is reentrant. It can be executed even if the project is already indexed.
*/
public ResourceIndexerDao indexProject(final long rootProjectId) {
- DbSession session = mybatis.openSession(true);
+ DbSession session = myBatis().openSession(true);
try {
indexProject(rootProjectId, session);
session.commit();
@@ -71,7 +76,7 @@ public class ResourceIndexerDao {
* This method is reentrant. It can be executed even if some projects are already indexed.
*/
public ResourceIndexerDao indexProjects() {
- final DbSession session = mybatis.openSession(true);
+ final DbSession session = myBatis().openSession(true);
try {
final ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class);
session.select("org.sonar.db.component.ResourceIndexerMapper.selectRootProjectIds", /* workaround to get booleans */ResourceIndexerQuery.create(), new ResultHandler() {
@@ -132,7 +137,7 @@ public class ResourceIndexerDao {
}
public boolean indexResource(long id) {
- DbSession session = mybatis.openSession(false);
+ DbSession session = myBatis().openSession(false);
try {
return indexResource(session, id);
} finally {
@@ -156,7 +161,7 @@ public class ResourceIndexerDao {
public boolean indexResource(int id, String name, String qualifier, int rootId) {
boolean indexed = false;
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
ResourceIndexerMapper mapper = session.getMapper(ResourceIndexerMapper.class);
try {
indexed = indexResource(id, name, qualifier, rootId, session, mapper);
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java
index ecbacc7da82..a0cb17b2ccf 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceIndexerMapper.java
@@ -19,8 +19,13 @@
*/
package org.sonar.db.component;
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+
public interface ResourceIndexerMapper {
+ List<Long> selectProjectIdsFromQueryAndViewOrSubViewUuid(@Param("query") String query, @Param("viewUuidQuery") String viewUuidQuery);
+
ResourceIndexDto selectMasterIndexByResourceId(long resourceId);
ResourceDto selectResourceToIndex(long resourceId);
diff --git a/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java
index 6441c88df37..78217f48edd 100644
--- a/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/component/ResourceKeyUpdaterDao.java
@@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
@@ -36,7 +37,7 @@ import org.sonar.db.MyBatis;
*
* @since 3.2
*/
-public class ResourceKeyUpdaterDao {
+public class ResourceKeyUpdaterDao implements Dao {
private MyBatis mybatis;
public ResourceKeyUpdaterDao(MyBatis mybatis) {
diff --git a/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java
new file mode 100644
index 00000000000..d23eeb5a934
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/component/SnapshotDao.java
@@ -0,0 +1,107 @@
+/*
+ * 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.db.component;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.Lists;
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.resources.Scopes;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+public class SnapshotDao implements Dao {
+
+ @CheckForNull
+ public SnapshotDto selectNullableById(DbSession session, long id) {
+ return mapper(session).selectByKey(id);
+ }
+
+ public SnapshotDto selectById(DbSession session, long id) {
+ SnapshotDto value = selectNullableById(session, id);
+ if (value == null) {
+ throw new IllegalArgumentException(String.format("Snapshot id does not exist: %d", id));
+ }
+ return value;
+ }
+
+ @CheckForNull
+ public SnapshotDto selectLastSnapshotByComponentId(DbSession session, long componentId) {
+ return mapper(session).selectLastSnapshot(componentId);
+ }
+
+ public List<SnapshotDto> selectSnapshotsByComponentId(DbSession session, long componentId) {
+ return mapper(session).selectSnapshotsByQuery(new SnapshotQuery().setComponentId(componentId));
+ }
+
+ public List<SnapshotDto> selectSnapshotsByQuery(DbSession session, SnapshotQuery query) {
+ return mapper(session).selectSnapshotsByQuery(query);
+ }
+
+ public List<SnapshotDto> selectPreviousVersionSnapshots(DbSession session, long componentId, String lastVersion) {
+ return mapper(session).selectPreviousVersionSnapshots(componentId, lastVersion);
+ }
+
+ public List<SnapshotDto> selectSnapshotAndChildrenOfProjectScope(DbSession session, long snapshotId) {
+ return mapper(session).selectSnapshotAndChildrenOfScope(snapshotId, Scopes.PROJECT);
+ }
+
+ public int updateSnapshotAndChildrenLastFlagAndStatus(DbSession session, SnapshotDto snapshot, boolean isLast, String status) {
+ Long rootId = snapshot.getId();
+ String path = Strings.nullToEmpty(snapshot.getPath()) + snapshot.getId() + ".%";
+ Long pathRootId = snapshot.getRootIdOrSelf();
+
+ return mapper(session).updateSnapshotAndChildrenLastFlagAndStatus(rootId, pathRootId, path, isLast, status);
+ }
+
+ public int updateSnapshotAndChildrenLastFlag(DbSession session, SnapshotDto snapshot, boolean isLast) {
+ Long rootId = snapshot.getId();
+ String path = Strings.nullToEmpty(snapshot.getPath()) + snapshot.getId() + ".%";
+ Long pathRootId = snapshot.getRootIdOrSelf();
+
+ return mapper(session).updateSnapshotAndChildrenLastFlag(rootId, pathRootId, path, isLast);
+ }
+
+ public static boolean isLast(SnapshotDto snapshotTested, @Nullable SnapshotDto previousLastSnapshot) {
+ return previousLastSnapshot == null || previousLastSnapshot.getCreatedAt() < snapshotTested.getCreatedAt();
+ }
+
+ public SnapshotDto insert(DbSession session, SnapshotDto item) {
+ mapper(session).insert(item);
+ return item;
+ }
+
+ public void insert(DbSession session, Collection<SnapshotDto> items) {
+ for (SnapshotDto item : items) {
+ insert(session, item);
+ }
+ }
+
+ public void insert(DbSession session, SnapshotDto item, SnapshotDto... others) {
+ insert(session, Lists.asList(item, others));
+ }
+
+ private SnapshotMapper mapper(DbSession session) {
+ return session.getMapper(SnapshotMapper.class);
+ }
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDao.java b/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDao.java
new file mode 100644
index 00000000000..d805044aae6
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/compute/AnalysisReportDao.java
@@ -0,0 +1,107 @@
+/*
+ * 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.db.compute;
+
+import com.google.common.annotations.VisibleForTesting;
+import org.sonar.api.utils.System2;
+import org.sonar.db.compute.AnalysisReportDto;
+import org.sonar.db.compute.AnalysisReportMapper;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+import javax.annotation.CheckForNull;
+
+import java.util.List;
+
+import static org.sonar.db.compute.AnalysisReportDto.Status.PENDING;
+import static org.sonar.db.compute.AnalysisReportDto.Status.WORKING;
+
+public class AnalysisReportDao implements Dao {
+
+ private System2 system2;
+
+ public AnalysisReportDao(System2 system2) {
+ this.system2 = system2;
+ }
+
+ /**
+ * Update all rows with: STATUS='PENDING', STARTED_AT=NULL, UPDATED_AT={now}
+ */
+ public void resetAllToPendingStatus(DbSession session) {
+ mapper(session).resetAllToPendingStatus(system2.now());
+ }
+
+ public void truncate(DbSession session) {
+ mapper(session).truncate();
+ }
+
+ public List<AnalysisReportDto> selectByProjectKey(DbSession session, String projectKey) {
+ return mapper(session).selectByProjectKey(projectKey);
+ }
+
+ @VisibleForTesting
+ AnalysisReportDto selectById(DbSession session, long id) {
+ return mapper(session).selectById(id);
+ }
+
+ @CheckForNull
+ public AnalysisReportDto pop(DbSession session) {
+ List<Long> reportIds = mapper(session).selectAvailables(PENDING, WORKING);
+ if (reportIds.isEmpty()) {
+ return null;
+ }
+
+ long reportId = reportIds.get(0);
+ return tryToPop(session, reportId);
+ }
+
+ @VisibleForTesting
+ AnalysisReportDto tryToPop(DbSession session, long reportId) {
+ AnalysisReportMapper mapper = mapper(session);
+ int nbOfReportBooked = mapper.updateWithBookingReport(reportId, system2.now(), PENDING, WORKING);
+ if (nbOfReportBooked == 0) {
+ return null;
+ }
+
+ AnalysisReportDto result = mapper.selectById(reportId);
+ session.commit();
+ return result;
+ }
+
+ public List<AnalysisReportDto> selectAll(DbSession session) {
+ return mapper(session).selectAll();
+ }
+
+ public AnalysisReportDto insert(DbSession session, AnalysisReportDto report) {
+ report.setCreatedAt(system2.now());
+ report.setUpdatedAt(system2.now());
+ mapper(session).insert(report);
+ return report;
+ }
+
+ public void delete(DbSession session, long id) {
+ mapper(session).delete(id);
+ }
+
+ private AnalysisReportMapper mapper(DbSession session) {
+ return session.getMapper(AnalysisReportMapper.class);
+ }
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java
index 8463da58cfa..c29f495047e 100644
--- a/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/dashboard/ActiveDashboardDao.java
@@ -22,11 +22,9 @@ package org.sonar.db.dashboard;
import java.util.List;
import javax.annotation.Nullable;
import org.apache.ibatis.session.SqlSession;
-import org.sonar.api.server.ServerSide;
import org.sonar.db.Dao;
import org.sonar.db.MyBatis;
-@ServerSide
public class ActiveDashboardDao implements Dao {
private MyBatis mybatis;
diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java
index 40b151e7ec9..4462c1c24c8 100644
--- a/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/dashboard/DashboardDao.java
@@ -19,8 +19,11 @@
*/
package org.sonar.db.dashboard;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.apache.ibatis.session.SqlSession;
import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
public class DashboardDao implements Dao {
@@ -62,4 +65,21 @@ public class DashboardDao implements Dao {
}
}
+ @CheckForNull
+ public DashboardDto getNullableByKey(DbSession session, Long key) {
+ return mapper(session).selectById(key);
+ }
+
+ /**
+ * Get dashboard if allowed : shared or owned by logged-in user
+ * @param userId id of logged-in user, null if anonymous
+ */
+ @CheckForNull
+ public DashboardDto getAllowedByKey(DbSession session, Long key, @Nullable Long userId) {
+ return mapper(session).selectAllowedById(key, userId != null ? userId : -1L);
+ }
+
+ private DashboardMapper mapper(DbSession session) {
+ return session.getMapper(DashboardMapper.class);
+ }
}
diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDao.java
new file mode 100644
index 00000000000..dec981655e0
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetDao.java
@@ -0,0 +1,76 @@
+/*
+ * 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.db.dashboard;
+
+import java.util.Collection;
+import org.sonar.db.dashboard.WidgetDto;
+import org.sonar.db.dashboard.WidgetMapper;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+import org.sonar.db.MyBatis;
+
+public class WidgetDao implements Dao {
+
+ private MyBatis myBatis;
+
+ public WidgetDao(MyBatis myBatis) {
+ this.myBatis = myBatis;
+ }
+
+ public WidgetDto getNullableByKey(Long widgetId) {
+ DbSession session = myBatis.openSession(false);
+ try {
+ return getNullableByKey(session, widgetId);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public WidgetDto getNullableByKey(DbSession session, Long widgetId) {
+ return mapper(session).selectById(widgetId);
+ }
+
+ public WidgetDto update(WidgetDto item) {
+ DbSession session = myBatis.openSession(false);
+ try {
+ return update(session, item);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public WidgetDto update(DbSession session, WidgetDto item) {
+ mapper(session).update(item);
+ return item;
+ }
+
+ public Collection<WidgetDto> findByDashboard(DbSession session, long dashboardKey) {
+ return mapper(session).selectByDashboard(dashboardKey);
+ }
+
+ public Collection<WidgetDto> findAll(DbSession session) {
+ return mapper(session).selectAll();
+ }
+
+ private WidgetMapper mapper(DbSession session) {
+ return session.getMapper(WidgetMapper.class);
+ }
+
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDao.java b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDao.java
new file mode 100644
index 00000000000..0102d3338a0
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/dashboard/WidgetPropertyDao.java
@@ -0,0 +1,90 @@
+/*
+ * 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.db.dashboard;
+
+import com.google.common.base.Function;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import org.sonar.db.Dao;
+import org.sonar.db.DaoUtils;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.db.DbSession;
+import org.sonar.db.MyBatis;
+
+public class WidgetPropertyDao implements Dao {
+
+ private final MyBatis myBatis;
+
+ public WidgetPropertyDao(MyBatis myBatis) {
+ this.myBatis = myBatis;
+ }
+
+ public WidgetPropertyDto insert(WidgetPropertyDto item) {
+ DbSession session = myBatis.openSession(false);
+ try {
+ return insert(session, item);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public WidgetPropertyDto insert(DbSession session, WidgetPropertyDto item) {
+ mapper(session).insert(item);
+ return item;
+ }
+
+ public void insert(DbSession session, Collection<WidgetPropertyDto> items) {
+ for (WidgetPropertyDto item : items) {
+ insert(session, item);
+ }
+ }
+
+ public WidgetPropertyDto getNullableByKey(Long propertyId) {
+ DbSession session = myBatis.openSession(false);
+ try {
+ return getNullableByKey(session, propertyId);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public WidgetPropertyDto getNullableByKey(DbSession session, Long propertyId) {
+ return mapper(session).selectById(propertyId);
+ }
+
+ public Collection<WidgetPropertyDto> findByDashboard(DbSession session, long dashboardKey) {
+ return mapper(session).selectByDashboard(dashboardKey);
+ }
+
+ public void deleteByWidgetIds(final DbSession session, List<Long> widgetIdsWithPropertiesToDelete) {
+ DatabaseUtils.executeLargeInputs(widgetIdsWithPropertiesToDelete, new Function<List<Long>, List<Void>>() {
+ @Override
+ public List<Void> apply(List<Long> input) {
+ mapper(session).deleteByWidgetIds(input);
+ return Arrays.asList();
+ }
+ });
+ }
+
+ private WidgetPropertyMapper mapper(DbSession session) {
+ return session.getMapper(WidgetPropertyMapper.class);
+ }
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java
index 25690f35569..94d7ef81c73 100644
--- a/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/duplication/DuplicationDao.java
@@ -22,10 +22,11 @@ package org.sonar.db.duplication;
import java.util.Collection;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
-public class DuplicationDao {
+public class DuplicationDao implements Dao {
private final MyBatis mybatis;
diff --git a/sonar-db/src/main/java/org/sonar/batch/index/ResourceCopy.java b/sonar-db/src/main/java/org/sonar/db/event/EventDao.java
index 6a3ccd83029..0f58097ab35 100644
--- a/sonar-db/src/main/java/org/sonar/batch/index/ResourceCopy.java
+++ b/sonar-db/src/main/java/org/sonar/db/event/EventDao.java
@@ -17,13 +17,25 @@
* 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.batch.index;
-/**
- * Used by views !!
- */
-public interface ResourceCopy {
+package org.sonar.db.event;
+
+import java.util.List;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+public class EventDao implements Dao {
+
+ public List<EventDto> selectByComponentUuid(DbSession session, String componentUuid) {
+ return session.getMapper(EventMapper.class).selectByComponentUuid(componentUuid);
+ }
+
+ public void insert(DbSession session, EventDto dto) {
+ session.getMapper(EventMapper.class).insert(dto);
+ }
- int getCopyResourceId();
+ public void delete(DbSession session, Long id) {
+ session.getMapper(EventMapper.class).delete(id);
+ }
}
diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java
index bb63a3c9b90..5c061ad2407 100644
--- a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanDao.java
@@ -25,13 +25,11 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
-import org.sonar.api.server.ServerSide;
import org.sonar.db.Dao;
import org.sonar.db.MyBatis;
import static com.google.common.collect.Lists.newArrayList;
-@ServerSide
public class ActionPlanDao implements Dao {
private final MyBatis mybatis;
diff --git a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java
index dfd4192922b..4d653374b5c 100644
--- a/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/issue/ActionPlanStatsDao.java
@@ -22,18 +22,18 @@ package org.sonar.db.issue;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.api.utils.System2;
+import org.sonar.db.AbstractDao;
import org.sonar.db.MyBatis;
-public class ActionPlanStatsDao {
+public class ActionPlanStatsDao extends AbstractDao {
- private final MyBatis mybatis;
-
- public ActionPlanStatsDao(MyBatis mybatis) {
- this.mybatis = mybatis;
+ public ActionPlanStatsDao(MyBatis myBatis, System2 system2) {
+ super(myBatis, system2);
}
public List<ActionPlanStatsDto> findByProjectId(Long projectId) {
- SqlSession session = mybatis.openSession(false);
+ SqlSession session = myBatis().openSession(false);
try {
return session.getMapper(ActionPlanStatsMapper.class).findByProjectId(projectId);
} finally {
diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java
index edc89f9c267..cecd0fe0f08 100644
--- a/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueDao.java
@@ -20,12 +20,16 @@
package org.sonar.db.issue;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.CheckForNull;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
-public class IssueDao {
+public class IssueDao implements Dao {
private final MyBatis mybatis;
@@ -43,7 +47,48 @@ public class IssueDao {
}
}
- protected IssueMapper mapper(DbSession session) {
+ @CheckForNull
+ public IssueDto selectNullableByKey(DbSession session, String key) {
+ return mapper(session).selectByKey(key);
+ }
+
+ public IssueDto selectByKey(DbSession session, String key) {
+ IssueDto issue = selectNullableByKey(session, key);
+ if (issue == null) {
+ throw new IllegalArgumentException(String.format("Issue key '%s' does not exist", key));
+ }
+ return issue;
+ }
+
+ public List<IssueDto> findByActionPlan(DbSession session, String actionPlan) {
+ return mapper(session).selectByActionPlan(actionPlan);
+ }
+
+ public List<IssueDto> selectByKeys(DbSession session, List<String> keys) {
+ return mapper(session).selectByKeys(keys);
+ }
+
+ public Set<String> selectComponentUuidsOfOpenIssuesForProjectUuid(DbSession session, String projectUuid) {
+ return mapper(session).selectComponentUuidsOfOpenIssuesForProjectUuid(projectUuid);
+ }
+
+ public void insert(DbSession session, IssueDto dto) {
+ mapper(session).insert(dto);
+ }
+
+ public void insert(DbSession session, IssueDto dto, IssueDto... others) {
+ IssueMapper mapper = mapper(session);
+ mapper.insert(dto);
+ for (IssueDto other : others) {
+ mapper.insert(other);
+ }
+ }
+
+ public void update(DbSession session, IssueDto dto) {
+ mapper(session).update(dto);
+ }
+
+ private IssueMapper mapper(DbSession session) {
return session.getMapper(IssueMapper.class);
}
diff --git a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java
index f9de1a19963..7f1f06ce324 100644
--- a/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/issue/IssueFilterFavouriteDao.java
@@ -22,9 +22,10 @@ package org.sonar.db.issue;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.db.Dao;
import org.sonar.db.MyBatis;
-public class IssueFilterFavouriteDao {
+public class IssueFilterFavouriteDao implements Dao {
private final MyBatis mybatis;
diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java
new file mode 100644
index 00000000000..ff4b710d9ca
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureDao.java
@@ -0,0 +1,87 @@
+/*
+ * 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.db.measure;
+
+import com.google.common.base.Function;
+import com.google.common.collect.Lists;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import javax.annotation.CheckForNull;
+import org.sonar.db.Dao;
+import org.sonar.db.DaoUtils;
+import org.sonar.db.DatabaseUtils;
+import org.sonar.db.DbSession;
+import org.sonar.db.component.SnapshotDto;
+
+public class MeasureDao implements Dao {
+
+ public boolean existsByKey(DbSession session, String componentKey, String metricKey) {
+ return mapper(session).countByComponentAndMetric(componentKey, metricKey) > 0;
+ }
+
+ @CheckForNull
+ public MeasureDto findByComponentKeyAndMetricKey(DbSession session, String componentKey, String metricKey) {
+ return mapper(session).selectByComponentAndMetric(componentKey, metricKey);
+ }
+
+ public List<MeasureDto> findByComponentKeyAndMetricKeys(final DbSession session, final String componentKey, List<String> metricKeys) {
+ return DatabaseUtils.executeLargeInputs(metricKeys, new Function<List<String>, List<MeasureDto>>() {
+ @Override
+ public List<MeasureDto> apply(List<String> keys) {
+ return mapper(session).selectByComponentAndMetrics(componentKey, keys);
+ }
+ });
+ }
+
+ public List<PastMeasureDto> selectByComponentUuidAndProjectSnapshotIdAndMetricIds(final DbSession session, final String componentUuid, final long projectSnapshotId,
+ Set<Integer> metricIds) {
+ return DatabaseUtils.executeLargeInputs(metricIds, new Function<List<Integer>, List<PastMeasureDto>>() {
+ @Override
+ public List<PastMeasureDto> apply(List<Integer> ids) {
+ return mapper(session).selectByComponentUuidAndProjectSnapshotIdAndStatusAndMetricIds(componentUuid, projectSnapshotId, ids,
+ SnapshotDto.STATUS_PROCESSED);
+ }
+ });
+ }
+
+ public void insert(DbSession session, MeasureDto measureDto) {
+ mapper(session).insert(measureDto);
+ }
+
+ public void insert(DbSession session, Collection<MeasureDto> items) {
+ for (MeasureDto item : items) {
+ insert(session, item);
+ }
+ }
+
+ public void insert(DbSession session, MeasureDto item, MeasureDto... others) {
+ insert(session, Lists.asList(item, others));
+ }
+
+ public List<String> selectMetricKeysForSnapshot(DbSession session, long snapshotId) {
+ return mapper(session).selectMetricKeysForSnapshot(snapshotId);
+ }
+
+ private MeasureMapper mapper(DbSession session) {
+ return session.getMapper(MeasureMapper.class);
+ }
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java
index 50d0bad2f53..8b5981caa45 100644
--- a/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/measure/MeasureFilterDao.java
@@ -20,9 +20,10 @@
package org.sonar.db.measure;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.db.Dao;
import org.sonar.db.MyBatis;
-public class MeasureFilterDao {
+public class MeasureFilterDao implements Dao {
private MyBatis mybatis;
public MeasureFilterDao(MyBatis mybatis) {
diff --git a/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java
index b82ba01dd09..6fc69f7818e 100644
--- a/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/notification/NotificationQueueDao.java
@@ -23,10 +23,11 @@ package org.sonar.db.notification;
import java.util.Collections;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.db.Dao;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
-public class NotificationQueueDao {
+public class NotificationQueueDao implements Dao {
private final MyBatis mybatis;
diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java
index e6a1508e222..e18bdbbcb57 100644
--- a/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionDao.java
@@ -27,13 +27,12 @@ import javax.annotation.Nullable;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.sonar.api.security.DefaultGroups;
-import org.sonar.api.server.ServerSide;
+import org.sonar.db.Dao;
import org.sonar.db.MyBatis;
import static com.google.common.collect.Maps.newHashMap;
-@ServerSide
-public class PermissionDao {
+public class PermissionDao implements Dao {
private static final String QUERY_PARAMETER = "query";
private static final String COMPONENT_ID_PARAMETER = "componentId";
diff --git a/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java b/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java
index cb1a63adbe3..c69532dc8ea 100644
--- a/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/property/PropertiesDao.java
@@ -36,6 +36,7 @@ import org.apache.ibatis.session.SqlSession;
import org.sonar.api.resources.Scopes;
import org.sonar.db.Dao;
import org.sonar.db.DaoUtils;
+import org.sonar.db.DatabaseUtils;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
@@ -83,7 +84,7 @@ public class PropertiesDao implements Dao {
String sql = "SELECT count(*) FROM properties pp " +
"left outer join projects pj on pp.resource_id = pj.id " +
"where pp.user_id is not null and (pp.resource_id is null or pj.uuid=?) " +
- "and (" + DaoUtils.repeatCondition("pp.prop_key like ?", dispatcherKeys.size(), "or") + ")";
+ "and (" + DatabaseUtils.repeatCondition("pp.prop_key like ?", dispatcherKeys.size(), "or") + ")";
try {
pstmt = connection.prepareStatement(sql);
pstmt.setString(1, projectUuid);
diff --git a/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java b/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java
index a06767ab51c..f4ddf2478b6 100644
--- a/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/purge/PurgeDao.java
@@ -48,19 +48,17 @@ public class PurgeDao implements Dao {
private final MyBatis mybatis;
private final ResourceDao resourceDao;
private final System2 system2;
- private final PurgeProfiler profiler;
- public PurgeDao(MyBatis mybatis, ResourceDao resourceDao, PurgeProfiler profiler, System2 system2) {
+ public PurgeDao(MyBatis mybatis, ResourceDao resourceDao, System2 system2) {
this.mybatis = mybatis;
this.resourceDao = resourceDao;
- this.profiler = profiler;
this.system2 = system2;
}
- public PurgeDao purge(PurgeConfiguration conf, PurgeListener purgeListener) {
+ public PurgeDao purge(PurgeConfiguration conf, PurgeListener listener, PurgeProfiler profiler) {
DbSession session = mybatis.openSession(true);
try {
- purge(session, conf, purgeListener);
+ purge(session, conf, listener, profiler);
session.commit();
} finally {
MyBatis.closeQuietly(session);
@@ -68,7 +66,7 @@ public class PurgeDao implements Dao {
return this;
}
- public void purge(DbSession session, PurgeConfiguration conf, PurgeListener purgeListener) {
+ public void purge(DbSession session, PurgeConfiguration conf, PurgeListener listener, PurgeProfiler profiler) {
PurgeMapper mapper = session.getMapper(PurgeMapper.class);
PurgeCommands commands = new PurgeCommands(session, mapper, profiler);
List<ResourceDto> projects = getProjects(conf.rootProjectIdUuid().getId(), session);
@@ -78,7 +76,7 @@ public class PurgeDao implements Dao {
purge(project, conf.scopesWithoutHistoricalData(), commands);
}
for (ResourceDto project : projects) {
- disableOrphanResources(project, session, mapper, purgeListener);
+ disableOrphanResources(project, session, mapper, listener);
}
deleteOldClosedIssues(conf, mapper);
}
@@ -171,16 +169,16 @@ public class PurgeDao implements Dao {
return result;
}
- public PurgeDao deleteResourceTree(IdUuidPair rootIdUuid) {
+ public PurgeDao deleteResourceTree(IdUuidPair rootIdUuid, PurgeProfiler profiler) {
DbSession session = mybatis.openSession(true);
try {
- return deleteResourceTree(session, rootIdUuid);
+ return deleteResourceTree(session, rootIdUuid, profiler);
} finally {
MyBatis.closeQuietly(session);
}
}
- public PurgeDao deleteResourceTree(DbSession session, IdUuidPair rootIdUuid) {
+ public PurgeDao deleteResourceTree(DbSession session, IdUuidPair rootIdUuid, PurgeProfiler profiler) {
deleteProject(rootIdUuid, mapper(session), new PurgeCommands(session, profiler));
deleteFileSources(rootIdUuid.getUuid(), new PurgeCommands(session, profiler));
return this;
@@ -209,17 +207,17 @@ public class PurgeDao implements Dao {
mapper.resolveResourceIssuesNotAlreadyResolved(componentIdUuid.getUuid(), system2.now());
}
- public PurgeDao deleteSnapshots(PurgeSnapshotQuery query) {
+ public PurgeDao deleteSnapshots(PurgeSnapshotQuery query, PurgeProfiler profiler) {
final DbSession session = mybatis.openSession(true);
try {
- return deleteSnapshots(query, session);
+ return deleteSnapshots(query, session, profiler);
} finally {
MyBatis.closeQuietly(session);
}
}
- public PurgeDao deleteSnapshots(PurgeSnapshotQuery query, final DbSession session) {
+ public PurgeDao deleteSnapshots(PurgeSnapshotQuery query, DbSession session, PurgeProfiler profiler) {
new PurgeCommands(session, profiler).deleteSnapshots(query);
return this;
}
diff --git a/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java b/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java
index ac7bad54d1a..35c03578122 100644
--- a/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java
+++ b/sonar-db/src/main/java/org/sonar/db/purge/period/DefaultPeriodCleaner.java
@@ -29,6 +29,7 @@ import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.db.DbSession;
import org.sonar.db.purge.PurgeDao;
+import org.sonar.db.purge.PurgeProfiler;
import org.sonar.db.purge.PurgeSnapshotQuery;
import org.sonar.db.purge.PurgeableSnapshotDto;
@@ -36,10 +37,12 @@ import org.sonar.db.purge.PurgeableSnapshotDto;
public class DefaultPeriodCleaner {
private static final Logger LOG = Loggers.get(DefaultPeriodCleaner.class);
- private PurgeDao purgeDao;
+ private final PurgeDao purgeDao;
+ private final PurgeProfiler profiler;
- public DefaultPeriodCleaner(PurgeDao purgeDao) {
+ public DefaultPeriodCleaner(PurgeDao purgeDao, PurgeProfiler profiler) {
this.purgeDao = purgeDao;
+ this.profiler = profiler;
}
public void clean(DbSession session, long projectId, Settings settings) {
@@ -58,8 +61,8 @@ public class DefaultPeriodCleaner {
private void delete(List<PurgeableSnapshotDto> snapshots, DbSession session) {
for (PurgeableSnapshotDto snapshot : snapshots) {
LOG.debug("<- Delete snapshot: {} [{}]", DateUtils.formatDateTime(snapshot.getDate()), snapshot.getSnapshotId());
- purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()), session);
- purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setId(snapshot.getSnapshotId()), session);
+ purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setRootSnapshotId(snapshot.getSnapshotId()), session, profiler);
+ purgeDao.deleteSnapshots(PurgeSnapshotQuery.create().setId(snapshot.getSnapshotId()), session, profiler);
}
}
diff --git a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java b/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java
deleted file mode 100644
index 24efe187dd7..00000000000
--- a/sonar-db/src/main/java/org/sonar/db/qualityprofile/ActiveRuleDao.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.db.qualityprofile;
-
-import java.util.List;
-import org.apache.ibatis.session.SqlSession;
-import org.sonar.api.server.ServerSide;
-import org.sonar.db.DbSession;
-import org.sonar.db.MyBatis;
-
-/**
- * @deprecated use the ActiveRuleDao class defined in sonar-server
- */
-@Deprecated
-@ServerSide
-public class ActiveRuleDao {
-
- private final MyBatis mybatis;
-
- public ActiveRuleDao(MyBatis mybatis) {
- this.mybatis = mybatis;
- }
-
- public void insert(ActiveRuleDto dto, SqlSession session) {
- session.getMapper(ActiveRuleMapper.class).insert(dto);
- }
-
- public List<ActiveRuleDto> selectByProfileKey(String profileKey) {
- DbSession session = mybatis.openSession(false);
- try {
- return session.getMapper(ActiveRuleMapper.class).selectByProfileKey(profileKey);
- } finally {
- session.close();
- }
- }
-
- public void insert(ActiveRuleParamDto dto, SqlSession session) {
- session.getMapper(ActiveRuleMapper.class).insertParameter(dto);
- }
-
- public List<ActiveRuleParamDto> selectParamsByProfileKey(String profileKey) {
- DbSession session = mybatis.openSession(false);
- try {
- return session.getMapper(ActiveRuleMapper.class).selectParamsByProfileKey(profileKey);
- } finally {
- session.close();
- }
- }
-}
diff --git a/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java b/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java
index 25236bc2bcb..8991c688db6 100644
--- a/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/rule/RuleDao.java
@@ -21,13 +21,14 @@ package org.sonar.db.rule;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
+import org.sonar.db.Dao;
import org.sonar.db.MyBatis;
/**
* @deprecated in 4.4 moved to org.sonar.server.rule.db.RuleDao.
*/
@Deprecated
-public class RuleDao {
+public class RuleDao implements Dao {
private MyBatis mybatis;
diff --git a/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java
index c34a9b89542..59c89c738b1 100644
--- a/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/semaphore/SemaphoreDao.java
@@ -24,15 +24,13 @@ import javax.annotation.CheckForNull;
import org.apache.ibatis.session.SqlSession;
import org.sonar.api.utils.Semaphores;
import org.sonar.api.utils.System2;
+import org.sonar.db.Dao;
import org.sonar.db.MyBatis;
import static com.google.common.base.Preconditions.checkArgument;
import static org.sonar.api.utils.DateUtils.longToDate;
-/**
- * @since 3.4
- */
-public class SemaphoreDao {
+public class SemaphoreDao implements Dao {
private static final String SEMAPHORE_NAME_MUST_NOT_BE_EMPTY = "Semaphore name must not be empty";
private final MyBatis mybatis;
diff --git a/sonar-db/src/main/java/org/sonar/db/source/FileSourceDao.java b/sonar-db/src/main/java/org/sonar/db/source/FileSourceDao.java
new file mode 100644
index 00000000000..6aeb7d0742b
--- /dev/null
+++ b/sonar-db/src/main/java/org/sonar/db/source/FileSourceDao.java
@@ -0,0 +1,146 @@
+/*
+ * 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.db.source;
+
+import com.google.common.base.Function;
+import com.google.common.base.Splitter;
+import java.io.Reader;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import javax.annotation.CheckForNull;
+import org.apache.commons.dbutils.DbUtils;
+import org.apache.commons.io.IOUtils;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+import org.sonar.db.MyBatis;
+import org.sonar.db.source.FileSourceDto.Type;
+
+public class FileSourceDao implements Dao {
+
+ private static final Splitter END_OF_LINE_SPLITTER = Splitter.on('\n');
+ private final MyBatis mybatis;
+
+ public FileSourceDao(MyBatis myBatis) {
+ this.mybatis = myBatis;
+ }
+
+ @CheckForNull
+ public FileSourceDto selectSource(String fileUuid) {
+ DbSession session = mybatis.openSession(false);
+ try {
+ return mapper(session).select(fileUuid, Type.SOURCE);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @CheckForNull
+ public FileSourceDto selectTest(String fileUuid) {
+ DbSession session = mybatis.openSession(false);
+ try {
+ return mapper(session).select(fileUuid, Type.TEST);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ @CheckForNull
+ public List<String> selectLineHashes(DbSession dbSession, String fileUuid) {
+ Connection connection = dbSession.getConnection();
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ try {
+ pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type=?");
+ pstmt.setString(1, fileUuid);
+ pstmt.setString(2, Type.SOURCE);
+ rs = pstmt.executeQuery();
+ if (rs.next()) {
+ return END_OF_LINE_SPLITTER.splitToList(rs.getString(1));
+ }
+ return null;
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to read FILE_SOURCES.LINE_HASHES of file " + fileUuid, e);
+ } finally {
+ DbUtils.closeQuietly(connection, pstmt, rs);
+ }
+ }
+
+ public <T> void readLineHashesStream(DbSession dbSession, String fileUuid, Function<Reader, T> function) {
+ Connection connection = dbSession.getConnection();
+ PreparedStatement pstmt = null;
+ ResultSet rs = null;
+ Reader reader = null;
+ try {
+ pstmt = connection.prepareStatement("SELECT line_hashes FROM file_sources WHERE file_uuid=? AND data_type=?");
+ pstmt.setString(1, fileUuid);
+ pstmt.setString(2, Type.SOURCE);
+ rs = pstmt.executeQuery();
+ if (rs.next()) {
+ reader = rs.getCharacterStream(1);
+ function.apply(reader);
+ }
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to read FILE_SOURCES.LINE_HASHES of file " + fileUuid, e);
+ } finally {
+ IOUtils.closeQuietly(reader);
+ DbUtils.closeQuietly(connection, pstmt, rs);
+ }
+ }
+
+ public void insert(FileSourceDto dto) {
+ DbSession session = mybatis.openSession(false);
+ try {
+ insert(session, dto);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void insert(DbSession session, FileSourceDto dto) {
+ mapper(session).insert(dto);
+ }
+
+ public void update(FileSourceDto dto) {
+ DbSession session = mybatis.openSession(false);
+ try {
+ update(session, dto);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void update(DbSession session, FileSourceDto dto) {
+ mapper(session).update(dto);
+ }
+
+ public void updateDateWhenUpdatedDateIsZero(DbSession session, String projectUuid, long updateDate) {
+ mapper(session).updateDateWhenUpdatedDateIsZero(projectUuid, updateDate);
+ }
+
+ private FileSourceMapper mapper(DbSession session) {
+ return session.getMapper(FileSourceMapper.class);
+ }
+}
diff --git a/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java b/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java
index 5837964ce82..56a4eb312fc 100644
--- a/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/user/AuthorDao.java
@@ -27,6 +27,7 @@ import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.sonar.db.Dao;
import org.sonar.db.DaoUtils;
+import org.sonar.db.DatabaseUtils;
import org.sonar.db.MyBatis;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ResourceDao;
@@ -112,7 +113,7 @@ public class AuthorDao implements Dao {
}
public List<String> selectScmAccountsByDeveloperUuids(final SqlSession session, Collection<String> developerUuids) {
- return DaoUtils.executeLargeInputs(developerUuids, new Function<List<String>, List<String>>() {
+ return DatabaseUtils.executeLargeInputs(developerUuids, new Function<List<String>, List<String>>() {
@Override
public List<String> apply(List<String> partition) {
return session.getMapper(AuthorMapper.class).selectScmAccountsByDeveloperUuids(partition);
diff --git a/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java b/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java
index 2a386c1d2b7..c4c8a118dce 100644
--- a/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/user/AuthorizationDao.java
@@ -30,6 +30,7 @@ import org.apache.ibatis.session.SqlSession;
import org.sonar.api.server.ServerSide;
import org.sonar.db.Dao;
import org.sonar.db.DaoUtils;
+import org.sonar.db.DatabaseUtils;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
@@ -49,7 +50,7 @@ public class AuthorizationDao implements Dao {
if (componentIds.isEmpty()) {
return Collections.emptySet();
}
- return DaoUtils.executeLargeInputs(componentIds, new Function<List<Long>, List<Long>>() {
+ return DatabaseUtils.executeLargeInputs(componentIds, new Function<List<Long>, List<Long>>() {
@Override
public List<Long> apply(List<Long> partition) {
if (userId == null) {
diff --git a/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java
index a62609259b8..e27e6fe5d98 100644
--- a/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/user/GroupMembershipDao.java
@@ -34,6 +34,7 @@ import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.session.SqlSession;
import org.sonar.db.Dao;
import org.sonar.db.DaoUtils;
+import org.sonar.db.DatabaseUtils;
import org.sonar.db.DbSession;
import org.sonar.db.MyBatis;
@@ -77,7 +78,7 @@ public class GroupMembershipDao implements Dao {
public Map<String, Integer> countUsersByGroups(final DbSession session, Collection<Long> groupIds) {
final Map<String, Integer> result = Maps.newHashMap();
- DaoUtils.executeLargeInputs(groupIds, new Function<List<Long>, List<GroupUserCount>>() {
+ DatabaseUtils.executeLargeInputs(groupIds, new Function<List<Long>, List<GroupUserCount>>() {
@Override
public List<GroupUserCount> apply(@Nonnull List<Long> input) {
List<GroupUserCount> userCounts = mapper(session).countUsersByGroup(input);
@@ -93,7 +94,7 @@ public class GroupMembershipDao implements Dao {
public Multimap<String, String> selectGroupsByLogins(final DbSession session, Collection<String> logins) {
final Multimap<String, String> result = ArrayListMultimap.create();
- DaoUtils.executeLargeInputs(logins, new Function<List<String>, List<LoginGroup>>() {
+ DatabaseUtils.executeLargeInputs(logins, new Function<List<String>, List<LoginGroup>>() {
@Override
public List<LoginGroup> apply(@Nonnull List<String> input) {
List<LoginGroup> groupMemberships = mapper(session).selectGroupsByLogins(input);
diff --git a/sonar-db/src/main/java/org/sonar/core/issue/db/package-info.java b/sonar-db/src/main/java/org/sonar/db/user/UserGroupDao.java
index 55dc4912649..2c5a8665ee6 100644
--- a/sonar-db/src/main/java/org/sonar/core/issue/db/package-info.java
+++ b/sonar-db/src/main/java/org/sonar/db/user/UserGroupDao.java
@@ -17,8 +17,28 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-@ParametersAreNonnullByDefault
-package org.sonar.core.issue.db;
-import javax.annotation.ParametersAreNonnullByDefault;
+package org.sonar.db.user;
+import org.sonar.db.Dao;
+import org.sonar.db.DbSession;
+
+public class UserGroupDao implements Dao {
+
+ public UserGroupDto insert(DbSession session, UserGroupDto dto) {
+ mapper(session).insert(dto);
+ return dto;
+ }
+
+ public void delete(DbSession session, UserGroupDto dto) {
+ mapper(session).delete(dto);
+ }
+
+ public void deleteMembersByGroupId(DbSession session, long groupId) {
+ mapper(session).deleteMembersByGroup(groupId);
+ }
+
+ protected UserGroupMapper mapper(DbSession session) {
+ return session.getMapper(UserGroupMapper.class);
+ }
+}
diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ComponentIndexMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ComponentIndexMapper.xml
deleted file mode 100644
index 2a308781795..00000000000
--- a/sonar-db/src/main/resources/org/sonar/db/component/ComponentIndexMapper.xml
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="org.sonar.db.component.ComponentIndexMapper">
-
- <select id="selectProjectIdsFromQueryAndViewOrSubViewUuid" parameterType="map" resultType="long">
- SELECT r.resource_id FROM resource_index r
- INNER JOIN projects copy ON copy.copy_resource_id = r.resource_id
- <where>
- AND copy.module_uuid_path LIKE #{viewUuidQuery}
- AND r.kee LIKE #{query}
- </where>
- ORDER BY r.name_size
- </select>
-
-</mapper>
-
diff --git a/sonar-db/src/main/resources/org/sonar/db/component/ResourceIndexerMapper.xml b/sonar-db/src/main/resources/org/sonar/db/component/ResourceIndexerMapper.xml
index 82afc7fa85d..b9a10673e3c 100644
--- a/sonar-db/src/main/resources/org/sonar/db/component/ResourceIndexerMapper.xml
+++ b/sonar-db/src/main/resources/org/sonar/db/component/ResourceIndexerMapper.xml
@@ -3,6 +3,16 @@
<mapper namespace="org.sonar.db.component.ResourceIndexerMapper">
+ <select id="selectProjectIdsFromQueryAndViewOrSubViewUuid" parameterType="map" resultType="long">
+ SELECT r.resource_id FROM resource_index r
+ INNER JOIN projects copy ON copy.copy_resource_id = r.resource_id
+ <where>
+ AND copy.module_uuid_path LIKE #{viewUuidQuery}
+ AND r.kee LIKE #{query}
+ </where>
+ ORDER BY r.name_size
+ </select>
+
<!--
The column PROJECTS.ROOT_ID is not exact on multi-modules projects. The root id must
be loaded from the table SNAPSHOTS
diff --git a/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java b/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java
index 24987271dfb..fc7c4b1ef80 100644
--- a/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/DaoUtilsTest.java
@@ -19,67 +19,14 @@
*/
package org.sonar.db;
-import com.google.common.base.Function;
-import com.google.common.collect.Iterables;
-import java.util.Collections;
-import java.util.List;
import org.junit.Test;
-import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.fail;
public class DaoUtilsTest {
@Test
public void list_all_dao_classes() {
- List<Class> daoClasses = DaoUtils.getDaoClasses();
-
- assertThat(daoClasses).isNotEmpty();
- }
-
- @Test
- public void repeatCondition() {
- assertThat(DaoUtils.repeatCondition("uuid=?", 1, "or")).isEqualTo("uuid=?");
- assertThat(DaoUtils.repeatCondition("uuid=?", 3, "or")).isEqualTo("uuid=? or uuid=? or uuid=?");
- }
-
- @Test
- public void execute_large_inputs() {
- List<Integer> inputs = newArrayList();
- List<String> expectedOutputs = newArrayList();
- for (int i = 0; i < 2010; i++) {
- inputs.add(i);
- expectedOutputs.add(Integer.toString(i));
- }
-
- List<String> outputs = DaoUtils.executeLargeInputs(inputs, new Function<List<Integer>, List<String>>() {
- @Override
- public List<String> apply(List<Integer> input) {
- // Check that each partition is only done on 1000 elements max
- assertThat(input.size()).isLessThanOrEqualTo(1000);
- return newArrayList(Iterables.transform(input, new Function<Integer, String>() {
- @Override
- public String apply(Integer input) {
- return Integer.toString(input);
- }
- }));
- }
- });
-
- assertThat(outputs).isEqualTo(expectedOutputs);
- }
-
- @Test
- public void execute_large_inputs_on_empty_list() {
- List<String> outputs = DaoUtils.executeLargeInputs(Collections.<Integer>emptyList(), new Function<List<Integer>, List<String>>() {
- @Override
- public List<String> apply(List<Integer> input) {
- fail("No partition should be made on empty list");
- return Collections.emptyList();
- }
- });
-
- assertThat(outputs).isEmpty();
+ assertThat(DaoUtils.getDaoClasses()).isNotEmpty();
}
}
diff --git a/sonar-db/src/test/java/org/sonar/db/DatabaseCheckerTest.java b/sonar-db/src/test/java/org/sonar/db/DatabaseCheckerTest.java
new file mode 100644
index 00000000000..2902ac122f9
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/DatabaseCheckerTest.java
@@ -0,0 +1,114 @@
+/*
+ * 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.db;
+
+import java.sql.SQLException;
+import org.apache.commons.lang.StringUtils;
+import org.junit.Test;
+import org.mockito.Mockito;
+import org.sonar.api.utils.MessageException;
+import org.sonar.db.dialect.Dialect;
+import org.sonar.db.dialect.H2;
+import org.sonar.db.dialect.MySql;
+import org.sonar.db.dialect.Oracle;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DatabaseCheckerTest {
+
+ @Test
+ public void requires_oracle_driver_11_2() throws Exception {
+ Database db = mockDb(new Oracle(), "11.2.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+ // no error
+
+ db = mockDb(new Oracle(), "11.2.1", "11.3.1");
+ new DatabaseChecker(db).start();
+ // no error
+
+ db = mockDb(new Oracle(), "11.2.1", "12.0.2");
+ new DatabaseChecker(db).start();
+ // no error
+
+ db = mockDb(new Oracle(), "11.2.1", "11.1.0.2");
+ try {
+ new DatabaseChecker(db).start();
+ fail();
+ } catch (MessageException e) {
+ assertThat(e).hasMessage("Unsupported Oracle JDBC driver version: 11.1.0.2. Minimal required version is 11.2.");
+ }
+ }
+
+ @Test
+ public void requires_oracle_11g_or_greater() throws Exception {
+ // oracle 11.0 is ok
+ Database db = mockDb(new Oracle(), "11.0.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 11.1 is ok
+ db = mockDb(new Oracle(), "11.1.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 11.2 is ok
+ db = mockDb(new Oracle(), "11.2.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 12 is ok
+ db = mockDb(new Oracle(), "12.0.1", "11.2.0.0.1");
+ new DatabaseChecker(db).start();
+
+ // oracle 10 is not supported
+ db = mockDb(new Oracle(), "10.2.1", "11.2.0.0.1");
+ try {
+ new DatabaseChecker(db).start();
+ fail();
+ } catch (MessageException e) {
+ assertThat(e).hasMessage("Unsupported Oracle version: 10.2.1. Minimal required version is 11.");
+ }
+ }
+
+ @Test
+ public void log_warning_if_h2() throws Exception {
+ Database db = mockDb(new H2(), "13.4", "13.4");
+ DatabaseChecker checker = new DatabaseChecker(db);
+ checker.start();
+ checker.stop();
+ // TODO test log
+ }
+
+ @Test
+ public void do_not_fail_if_mysql() throws Exception {
+ Database db = mockDb(new MySql(), "5.7", "5.7");
+ new DatabaseChecker(db).start();
+ // no error
+ }
+
+ private Database mockDb(Dialect dialect, String dbVersion, String driverVersion) throws SQLException {
+ Database db = mock(Database.class, Mockito.RETURNS_DEEP_STUBS);
+ when(db.getDialect()).thenReturn(dialect);
+ when(db.getDataSource().getConnection().getMetaData().getDatabaseMajorVersion()).thenReturn(Integer.parseInt(StringUtils.substringBefore(dbVersion, ".")));
+ when(db.getDataSource().getConnection().getMetaData().getDatabaseProductVersion()).thenReturn(dbVersion);
+ when(db.getDataSource().getConnection().getMetaData().getDriverVersion()).thenReturn(driverVersion);
+ return db;
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java b/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java
index 933e931ac03..1b6acbb3eb2 100644
--- a/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/DatabaseUtilsTest.java
@@ -19,15 +19,21 @@
*/
package org.sonar.db;
+import com.google.common.base.Function;
+import com.google.common.collect.Iterables;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
+import java.util.Collections;
+import java.util.List;
import org.junit.Test;
import org.sonar.db.dialect.Oracle;
+import static com.google.common.collect.Lists.newArrayList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
@@ -142,4 +148,49 @@ public class DatabaseUtilsTest extends AbstractDaoTestCase {
}
return sql;
}
+
+ @Test
+ public void repeatCondition() {
+ assertThat(DatabaseUtils.repeatCondition("uuid=?", 1, "or")).isEqualTo("uuid=?");
+ assertThat(DatabaseUtils.repeatCondition("uuid=?", 3, "or")).isEqualTo("uuid=? or uuid=? or uuid=?");
+ }
+
+ @Test
+ public void execute_large_inputs() {
+ List<Integer> inputs = newArrayList();
+ List<String> expectedOutputs = newArrayList();
+ for (int i = 0; i < 2010; i++) {
+ inputs.add(i);
+ expectedOutputs.add(Integer.toString(i));
+ }
+
+ List<String> outputs = DatabaseUtils.executeLargeInputs(inputs, new Function<List<Integer>, List<String>>() {
+ @Override
+ public List<String> apply(List<Integer> input) {
+ // Check that each partition is only done on 1000 elements max
+ assertThat(input.size()).isLessThanOrEqualTo(1000);
+ return newArrayList(Iterables.transform(input, new Function<Integer, String>() {
+ @Override
+ public String apply(Integer input) {
+ return Integer.toString(input);
+ }
+ }));
+ }
+ });
+
+ assertThat(outputs).isEqualTo(expectedOutputs);
+ }
+
+ @Test
+ public void execute_large_inputs_on_empty_list() {
+ List<String> outputs = DatabaseUtils.executeLargeInputs(Collections.<Integer>emptyList(), new Function<List<Integer>, List<String>>() {
+ @Override
+ public List<String> apply(List<Integer> input) {
+ fail("No partition should be made on empty list");
+ return Collections.emptyList();
+ }
+ });
+
+ assertThat(outputs).isEmpty();
+ }
}
diff --git a/sonar-db/src/test/java/org/sonar/db/DbTester.java b/sonar-db/src/test/java/org/sonar/db/DbTester.java
index ba428c5cbe8..dfa4e9cfef0 100644
--- a/sonar-db/src/test/java/org/sonar/db/DbTester.java
+++ b/sonar-db/src/test/java/org/sonar/db/DbTester.java
@@ -20,14 +20,8 @@
package org.sonar.db;
import com.google.common.base.Preconditions;
-import com.google.common.collect.Maps;
-import java.io.File;
-import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
-import java.net.HttpURLConnection;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.PreparedStatement;
@@ -36,19 +30,13 @@ import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
-import java.util.Properties;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.dbutils.QueryRunner;
-import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
-import org.apache.commons.lang.text.StrSubstitutor;
import org.dbunit.Assertion;
-import org.dbunit.DataSourceDatabaseTester;
import org.dbunit.DatabaseUnitException;
-import org.dbunit.IDatabaseTester;
import org.dbunit.assertion.DiffCollectingFailureHandler;
import org.dbunit.assertion.Difference;
import org.dbunit.database.DatabaseConfig;
@@ -61,13 +49,10 @@ import org.dbunit.dataset.filter.DefaultColumnFilter;
import org.dbunit.dataset.xml.FlatXmlDataSet;
import org.dbunit.ext.mssql.InsertIdentityOperation;
import org.dbunit.operation.DatabaseOperation;
-import org.junit.AssumptionViolatedException;
+import org.junit.After;
import org.junit.rules.ExternalResource;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.config.Settings;
-import org.sonar.db.deprecated.NullQueue;
-import org.sonar.db.dialect.Dialect;
+import org.picocontainer.containers.TransientPicoContainer;
+import org.sonar.api.utils.System2;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
@@ -78,96 +63,77 @@ import static org.junit.Assert.fail;
* This class should be call using @ClassRule in order to create the schema once (ft @Rule is used
* the schema will be recreated before each test).
* Data will be truncated each time you call prepareDbUnit().
- * <p/>
+ * <p>
* File using {@link DbTester} must be annotated with {@link org.sonar.test.DbTests} so
* that they can be executed on all supported DBs (Oracle, MySQL, ...).
*/
public class DbTester extends ExternalResource {
- private static final Logger LOG = LoggerFactory.getLogger(DbTester.class);
+ private final System2 system2;
+ private final TestDb db;
+ private DbClient2 client;
+ private DbSession session = null;
- private Database db;
- private DatabaseCommands commands;
- private IDatabaseTester tester;
- private MyBatis myBatis;
- private String schemaPath = null;
-
- public DbTester schema(Class baseClass, String filename) {
- String path = StringUtils.replaceChars(baseClass.getCanonicalName(), '.', '/');
- schemaPath = path + "/" + filename;
- return this;
+ @Deprecated
+ public DbTester() {
+ this.system2 = System2.INSTANCE;
+ this.db = TestDb.create(null);
}
- @Override
- protected void before() throws Throwable {
- Settings settings = new Settings().setProperties(Maps.fromProperties(System.getProperties()));
- if (settings.hasKey("orchestrator.configUrl")) {
- loadOrchestratorSettings(settings);
- }
- String login = settings.getString("sonar.jdbc.username");
- for (String key : settings.getKeysStartingWith("sonar.jdbc")) {
- LOG.info(key + ": " + settings.getString(key));
- }
- String dialect = settings.getString("sonar.jdbc.dialect");
- if (dialect != null && !"h2".equals(dialect)) {
- db = new DefaultDatabase(settings);
- } else {
- db = new H2Database("h2Tests" + DigestUtils.md5Hex(StringUtils.defaultString(schemaPath)), schemaPath == null);
- }
- db.start();
- if (schemaPath != null) {
- // will fail if not H2
- if (db.getDialect().getId().equals("h2")) {
- ((H2Database) db).executeScript(schemaPath);
- } else {
- db.stop();
- throw new AssumptionViolatedException("Test disabled because it supports only H2");
- }
- }
- LOG.info("Test Database: " + db);
-
- commands = DatabaseCommands.forDialect(db.getDialect());
- tester = new DataSourceDatabaseTester(db.getDataSource(), commands.useLoginAsSchema() ? login : null);
-
- myBatis = new MyBatis(db, new NullQueue());
- myBatis.start();
+ private DbTester(System2 system2, @Nullable String schemaPath) {
+ this.system2 = system2;
+ this.db = TestDb.create(schemaPath);
+ }
- truncateTables();
+ public static DbTester create(System2 system2) {
+ return new DbTester(system2, null);
}
- public void truncateTables() {
- try {
- commands.truncateDatabase(db.getDataSource());
- } catch (SQLException e) {
- throw new IllegalStateException("Fail to truncate db tables", e);
- }
+ public static DbTester createForSchema(System2 system2, Class testClass, String filename) {
+ String path = StringUtils.replaceChars(testClass.getCanonicalName(), '.', '/');
+ String schemaPath = path + "/" + filename;
+ return new DbTester(system2, schemaPath);
}
@Override
- protected void after() {
- db.stop();
- db = null;
- myBatis = null;
+ protected void before() throws Throwable {
+ truncateTables();
}
- public Database database() {
- return db;
+ @After
+ public void closeSession() throws Exception {
+ if (session != null) {
+ MyBatis.closeQuietly(session);
+ }
}
- public Dialect dialect() {
- return db.getDialect();
+ public DbSession getSession() {
+ if (session == null) {
+ session = db.getMyBatis().openSession(false);
+ }
+ return session;
}
- public MyBatis myBatis() {
- return myBatis;
+ public void truncateTables() {
+ db.truncateTables();
}
- public Connection openConnection() throws SQLException {
- return db.getDataSource().getConnection();
+ public DbClient2 getDbClient() {
+ if (client == null) {
+ TransientPicoContainer ioc = new TransientPicoContainer();
+ ioc.addComponent(db.getMyBatis());
+ ioc.addComponent(system2);
+ for (Class daoClass : DaoUtils.getDaoClasses()) {
+ ioc.addComponent(daoClass);
+ }
+ List<Dao> daos = ioc.getComponents(Dao.class);
+ client = new DbClient2(db.getMyBatis(), daos.toArray(new Dao[daos.size()]));
+ }
+ return client;
}
public void executeUpdateSql(String sql) {
- try (Connection connection = openConnection()) {
+ try (Connection connection = db.getDatabase().getDataSource().getConnection()) {
new QueryRunner().update(connection, sql);
} catch (Exception e) {
throw new IllegalStateException("Fail to execute sql: " + sql);
@@ -191,7 +157,7 @@ public class DbTester extends ExternalResource {
Preconditions.checkArgument(StringUtils.contains(sql, "count("),
"Parameter must be a SQL request containing 'count(x)' function. Got " + sql);
try (
- Connection connection = openConnection();
+ Connection connection = db.getDatabase().getDataSource().getConnection();
PreparedStatement stmt = connection.prepareStatement(sql);
ResultSet rs = stmt.executeQuery()) {
if (rs.next()) {
@@ -206,7 +172,7 @@ public class DbTester extends ExternalResource {
public List<Map<String, Object>> select(String selectSql) {
try (
- Connection connection = openConnection();
+ Connection connection = db.getDatabase().getDataSource().getConnection();
PreparedStatement stmt = connection.prepareStatement(selectSql);
ResultSet rs = stmt.executeQuery()) {
return getHashMap(rs);
@@ -259,8 +225,7 @@ public class DbTester extends ExternalResource {
public void prepareDbUnit(Class testClass, String... testNames) {
InputStream[] streams = new InputStream[testNames.length];
try {
- // Purge previous data
- commands.truncateDatabase(db.getDataSource());
+ db.truncateTables();
for (int i = 0; i < testNames.length; i++) {
String path = "/" + testClass.getName().replace('.', '/') + "/" + testNames[i];
@@ -271,7 +236,7 @@ public class DbTester extends ExternalResource {
}
prepareDbUnit(streams);
- commands.resetPrimaryKeys(db.getDataSource());
+ db.getCommands().resetPrimaryKeys(db.getDatabase().getDataSource());
} catch (SQLException e) {
throw translateException("Could not setup DBUnit data", e);
} finally {
@@ -288,9 +253,9 @@ public class DbTester extends ExternalResource {
for (int i = 0; i < dataSetStream.length; i++) {
dataSets[i] = dbUnitDataSet(dataSetStream[i]);
}
- tester.setDataSet(new CompositeDataSet(dataSets));
+ db.getDbUnitTester().setDataSet(new CompositeDataSet(dataSets));
connection = dbUnitConnection();
- new InsertIdentityOperation(DatabaseOperation.INSERT).execute(connection, tester.getDataSet());
+ new InsertIdentityOperation(DatabaseOperation.INSERT).execute(connection, db.getDbUnitTester().getDataSet());
} catch (Exception e) {
throw translateException("Could not setup DBUnit data", e);
} finally {
@@ -339,7 +304,7 @@ public class DbTester extends ExternalResource {
}
public void assertColumnDefinition(String table, String column, int expectedType, @Nullable Integer expectedSize) {
- try (Connection connection = openConnection();
+ try (Connection connection = db.getDatabase().getDataSource().getConnection();
PreparedStatement stmt = connection.prepareStatement("select * from " + table);
ResultSet res = stmt.executeQuery()) {
Integer columnIndex = getColumnIndex(res, column);
@@ -389,8 +354,8 @@ public class DbTester extends ExternalResource {
private IDatabaseConnection dbUnitConnection() {
try {
- IDatabaseConnection connection = tester.getConnection();
- connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, commands.getDbUnitFactory());
+ IDatabaseConnection connection = db.getDbUnitTester().getConnection();
+ connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, db.getDbUnitFactory());
return connection;
} catch (Exception e) {
throw translateException("Error while getting connection", e);
@@ -413,36 +378,6 @@ public class DbTester extends ExternalResource {
return runtimeException;
}
- private void loadOrchestratorSettings(Settings settings) throws URISyntaxException, IOException {
- String url = settings.getString("orchestrator.configUrl");
- URI uri = new URI(url);
- InputStream input = null;
- try {
- if (url.startsWith("file:")) {
- File file = new File(uri);
- input = FileUtils.openInputStream(file);
- } else {
- HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
- int responseCode = connection.getResponseCode();
- if (responseCode >= 400) {
- throw new IllegalStateException("Fail to request: " + uri + ". Status code=" + responseCode);
- }
-
- input = connection.getInputStream();
-
- }
- Properties props = new Properties();
- props.load(input);
- settings.addProperties(props);
- for (Map.Entry<String, String> entry : settings.getProperties().entrySet()) {
- String interpolatedValue = StrSubstitutor.replace(entry.getValue(), System.getenv(), "${", "}");
- settings.setProperty(entry.getKey(), interpolatedValue);
- }
- } finally {
- IOUtils.closeQuietly(input);
- }
- }
-
private static void doClobFree(Clob clob) throws SQLException {
try {
clob.free();
@@ -450,4 +385,19 @@ public class DbTester extends ExternalResource {
// JTS driver do not implement free() as it's using JDBC 3.0
}
}
+
+ @Deprecated
+ public MyBatis myBatis() {
+ return db.getMyBatis();
+ }
+
+ @Deprecated
+ public Connection openConnection() throws Exception {
+ return db.getDatabase().getDataSource().getConnection();
+ }
+
+ @Deprecated
+ public Database database() {
+ return db.getDatabase();
+ }
}
diff --git a/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java b/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java
index 194346fe0a0..87922b13faf 100644
--- a/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/MyBatisTest.java
@@ -63,7 +63,7 @@ public class MyBatisTest {
MyBatis myBatis = new MyBatis(database, queue);
myBatis.start();
- SqlSession session = myBatis.openBatchSession();
+ SqlSession session = myBatis.openSession(false);
try {
assertThat(session.getConnection(), notNullValue());
assertThat(session.getMapper(RuleMapper.class), notNullValue());
diff --git a/sonar-db/src/test/java/org/sonar/db/ResultSetIteratorTest.java b/sonar-db/src/test/java/org/sonar/db/ResultSetIteratorTest.java
new file mode 100644
index 00000000000..970f9090fd1
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/ResultSetIteratorTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.db;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.NoSuchElementException;
+import org.apache.commons.dbutils.DbUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.fail;
+
+@Category(DbTests.class)
+public class ResultSetIteratorTest {
+
+ @ClassRule
+ public static DbTester dbTester = DbTester.createForSchema(System2.INSTANCE, ResultSetIteratorTest.class, "schema.sql");
+
+ Connection connection = null;
+
+ @Before
+ public void setUp() throws Exception {
+ connection = dbTester.openConnection();
+ }
+
+ @After
+ public void tearDown() {
+ DbUtils.closeQuietly(connection);
+ }
+
+ @Test
+ public void create_iterator_from_statement() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "feed.xml");
+
+ PreparedStatement stmt = connection.prepareStatement("select * from issues order by id");
+ FirstIntColumnIterator iterator = new FirstIntColumnIterator(stmt);
+
+ assertThat(iterator.hasNext()).isTrue();
+
+ // calling multiple times hasNext() is ok
+ assertThat(iterator.hasNext()).isTrue();
+
+ assertThat(iterator.next()).isEqualTo(10);
+ assertThat(iterator.hasNext()).isTrue();
+ assertThat(iterator.next()).isEqualTo(20);
+
+ // call next() without calling hasNext()
+ assertThat(iterator.next()).isEqualTo(30);
+ assertThat(iterator.hasNext()).isFalse();
+
+ try {
+ iterator.next();
+ fail();
+ } catch (NoSuchElementException e) {
+ // ok
+ }
+
+ iterator.close();
+ // statement is closed by ResultSetIterator
+ assertThat(stmt.isClosed()).isTrue();
+ }
+
+ @Test
+ public void iterate_empty_list() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "feed.xml");
+
+ PreparedStatement stmt = connection.prepareStatement("select * from issues where id < 0");
+ FirstIntColumnIterator iterator = new FirstIntColumnIterator(stmt);
+
+ assertThat(iterator.hasNext()).isFalse();
+ }
+
+ @Test
+ public void create_iterator_from_result_set() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "feed.xml");
+
+ PreparedStatement stmt = connection.prepareStatement("select * from issues order by id");
+ ResultSet rs = stmt.executeQuery();
+ FirstIntColumnIterator iterator = new FirstIntColumnIterator(rs);
+
+ assertThat(iterator.next()).isEqualTo(10);
+ assertThat(iterator.next()).isEqualTo(20);
+ assertThat(iterator.next()).isEqualTo(30);
+
+ iterator.close();
+ assertThat(rs.isClosed()).isTrue();
+ stmt.close();
+ }
+
+ @Test
+ public void remove_row_is_not_supported() throws Exception {
+ PreparedStatement stmt = connection.prepareStatement("select * from issues order by id");
+ FirstIntColumnIterator iterator = new FirstIntColumnIterator(stmt);
+
+ try {
+ iterator.remove();
+ fail();
+ } catch (UnsupportedOperationException ok) {
+ // ok
+ }
+
+ iterator.close();
+ }
+
+ @Test
+ public void fail_to_read_row() throws Exception {
+ dbTester.prepareDbUnit(getClass(), "feed.xml");
+
+ PreparedStatement stmt = connection.prepareStatement("select * from issues order by id");
+ FailIterator iterator = new FailIterator(stmt);
+
+ assertThat(iterator.hasNext()).isTrue();
+ try {
+ iterator.next();
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e.getCause()).isInstanceOf(SQLException.class);
+ }
+ iterator.close();
+ }
+
+ private static class FirstIntColumnIterator extends ResultSetIterator<Integer> {
+
+ public FirstIntColumnIterator(PreparedStatement stmt) throws SQLException {
+ super(stmt);
+ }
+
+ public FirstIntColumnIterator(ResultSet rs) {
+ super(rs);
+ }
+
+ @Override
+ protected Integer read(ResultSet rs) throws SQLException {
+ return rs.getInt(1);
+ }
+ }
+
+ private static class FailIterator extends ResultSetIterator<Integer> {
+
+ public FailIterator(PreparedStatement stmt) throws SQLException {
+ super(stmt);
+ }
+
+ @Override
+ protected Integer read(ResultSet rs) throws SQLException {
+ // column does not exist
+ return rs.getInt(1234);
+ }
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/TestDb.java b/sonar-db/src/test/java/org/sonar/db/TestDb.java
new file mode 100644
index 00000000000..715ea17af6d
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/TestDb.java
@@ -0,0 +1,175 @@
+/*
+ * 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.db;
+
+import com.google.common.collect.Maps;
+import java.io.File;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URI;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.Properties;
+import javax.annotation.Nullable;
+import org.apache.commons.codec.digest.DigestUtils;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.text.StrSubstitutor;
+import org.dbunit.DataSourceDatabaseTester;
+import org.dbunit.IDatabaseTester;
+import org.dbunit.dataset.datatype.IDataTypeFactory;
+import org.junit.AssumptionViolatedException;
+import org.sonar.api.config.Settings;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.db.deprecated.NullQueue;
+
+/**
+ * This class should be call using @ClassRule in order to create the schema once (ft @Rule is used
+ * the schema will be recreated before each test).
+ * Data will be truncated each time you call prepareDbUnit().
+ * <p/>
+ * File using {@link TestDb} must be annotated with {@link org.sonar.test.DbTests} so
+ * that they can be executed on all supported DBs (Oracle, MySQL, ...).
+ */
+class TestDb {
+
+ private static TestDb DEFAULT;
+
+ private static final Logger LOG = Loggers.get(TestDb.class);
+
+ private Database db;
+ private DatabaseCommands commands;
+ private IDatabaseTester tester;
+ private MyBatis myBatis;
+
+ private TestDb(@Nullable String schemaPath) {
+ if (db == null) {
+ Settings settings = new Settings().setProperties(Maps.fromProperties(System.getProperties()));
+ if (settings.hasKey("orchestrator.configUrl")) {
+ loadOrchestratorSettings(settings);
+ }
+ String login = settings.getString("sonar.jdbc.username");
+ for (String key : settings.getKeysStartingWith("sonar.jdbc")) {
+ LOG.info(key + ": " + settings.getString(key));
+ }
+ String dialect = settings.getString("sonar.jdbc.dialect");
+ if (dialect != null && !"h2".equals(dialect)) {
+ db = new DefaultDatabase(settings);
+ } else {
+ db = new H2Database("h2Tests" + DigestUtils.md5Hex(StringUtils.defaultString(schemaPath)), schemaPath == null);
+ }
+ db.start();
+ if (schemaPath != null) {
+ // will fail if not H2
+ if (db.getDialect().getId().equals("h2")) {
+ ((H2Database) db).executeScript(schemaPath);
+ } else {
+ db.stop();
+ throw new AssumptionViolatedException("Test disabled because it supports only H2");
+ }
+ }
+ LOG.info("Test Database: " + db);
+
+ commands = DatabaseCommands.forDialect(db.getDialect());
+ tester = new DataSourceDatabaseTester(db.getDataSource(), commands.useLoginAsSchema() ? login : null);
+
+ myBatis = new MyBatis(db, new NullQueue());
+ myBatis.start();
+ }
+ }
+
+ void truncateTables() {
+ try {
+ commands.truncateDatabase(db.getDataSource());
+ } catch (SQLException e) {
+ throw new IllegalStateException("Fail to truncate db tables", e);
+ }
+ }
+
+ static TestDb create(@Nullable String schemaPath) {
+ if (schemaPath == null) {
+ if (DEFAULT == null) {
+ DEFAULT = new TestDb(null);
+ }
+ return DEFAULT;
+ }
+ return new TestDb(schemaPath);
+ }
+
+ void stop() {
+ db.stop();
+ db = null;
+ myBatis = null;
+ }
+
+ Database getDatabase() {
+ return db;
+ }
+
+ DatabaseCommands getCommands() {
+ return commands;
+ }
+
+ MyBatis getMyBatis() {
+ return myBatis;
+ }
+
+ IDatabaseTester getDbUnitTester() {
+ return tester;
+ }
+
+ IDataTypeFactory getDbUnitFactory() {
+ return commands.getDbUnitFactory();
+ }
+
+ private void loadOrchestratorSettings(Settings settings) {
+ String url = settings.getString("orchestrator.configUrl");
+ InputStream input = null;
+ try {
+ URI uri = new URI(url);
+ if (url.startsWith("file:")) {
+ File file = new File(uri);
+ input = FileUtils.openInputStream(file);
+ } else {
+ HttpURLConnection connection = (HttpURLConnection) uri.toURL().openConnection();
+ int responseCode = connection.getResponseCode();
+ if (responseCode >= 400) {
+ throw new IllegalStateException("Fail to request: " + uri + ". Status code=" + responseCode);
+ }
+
+ input = connection.getInputStream();
+
+ }
+ Properties props = new Properties();
+ props.load(input);
+ settings.addProperties(props);
+ for (Map.Entry<String, String> entry : settings.getProperties().entrySet()) {
+ String interpolatedValue = StrSubstitutor.replace(entry.getValue(), System.getenv(), "${", "}");
+ settings.setProperty(entry.getKey(), interpolatedValue);
+ }
+ } catch (Exception e) {
+ throw new IllegalStateException(e);
+ } finally {
+ IOUtils.closeQuietly(input);
+ }
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/activity/ActivityDaoTest.java b/sonar-db/src/test/java/org/sonar/db/activity/ActivityDaoTest.java
new file mode 100644
index 00000000000..c2135f6e3ac
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/activity/ActivityDaoTest.java
@@ -0,0 +1,59 @@
+/*
+ * 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.db.activity;
+
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+@Category(DbTests.class)
+public class ActivityDaoTest {
+
+ System2 system = mock(System2.class);
+
+ @Rule
+ public DbTester dbTester = DbTester.create(system);
+
+ ActivityDao sut = dbTester.getDbClient().activityDao();
+
+ @Test
+ public void insert() {
+ when(system.now()).thenReturn(1_500_000_000_000L);
+ ActivityDto dto = new ActivityDto()
+ .setKey("UUID_1").setAction("THE_ACTION").setType("THE_TYPE")
+ .setAuthor("THE_AUTHOR").setData("THE_DATA");
+ sut.insert(dto);
+
+ Map<String, Object> map = dbTester.selectFirst("select created_at as \"createdAt\", log_action as \"action\", data_field as \"data\" from activities where log_key='UUID_1'");
+ assertThat(map.get("action")).isEqualTo("THE_ACTION");
+ // not possible to check exact date yet. dbTester#selectFirst() uses ResultSet#getObject(), which returns
+ // non-JDBC interface in Oracle driver.
+ assertThat(map.get("createdAt")).isNotNull();
+ assertThat(map.get("data")).isEqualTo("THE_DATA");
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java
new file mode 100644
index 00000000000..931d4f0c508
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/component/ComponentLinkDaoTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.db.component;
+
+import java.util.List;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class ComponentLinkDaoTest {
+
+ @ClassRule
+ public static DbTester dbTester = DbTester.create(System2.INSTANCE);
+
+ ComponentLinkDao dao = dbTester.getDbClient().componentLinkDao();
+
+ @Test
+ public void select_by_component_uuid() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+ List<ComponentLinkDto> links = dao.selectByComponentUuid(dbTester.getSession(), "ABCD");
+ assertThat(links).hasSize(2);
+
+ links = dao.selectByComponentUuid(dbTester.getSession(), "BCDE");
+ assertThat(links).hasSize(1);
+
+ ComponentLinkDto link = links.get(0);
+ assertThat(link.getId()).isEqualTo(3L);
+ assertThat(link.getComponentUuid()).isEqualTo("BCDE");
+ assertThat(link.getType()).isEqualTo("homepage");
+ assertThat(link.getName()).isEqualTo("Home");
+ assertThat(link.getHref()).isEqualTo("http://www.struts.org");
+ }
+
+ @Test
+ public void insert() {
+ dbTester.prepareDbUnit(getClass(), "empty.xml");
+
+ dao.insert(dbTester.getSession(), new ComponentLinkDto()
+ .setComponentUuid("ABCD")
+ .setType("homepage")
+ .setName("Home")
+ .setHref("http://www.sonarqube.org")
+ );
+ dbTester.getSession().commit();
+
+ dbTester.assertDbUnit(getClass(), "insert-result.xml", new String[] {"id"}, "project_links");
+ }
+
+ @Test
+ public void update() {
+ dbTester.prepareDbUnit(getClass(), "update.xml");
+
+ dao.update(dbTester.getSession(), new ComponentLinkDto()
+ .setId(1L)
+ .setComponentUuid("ABCD")
+ .setType("homepage")
+ .setName("Home")
+ .setHref("http://www.sonarqube.org")
+ );
+ dbTester.getSession().commit();
+
+ dbTester.assertDbUnit(getClass(), "update-result.xml", "project_links");
+ }
+
+ @Test
+ public void delete() {
+ dbTester.prepareDbUnit(getClass(), "delete.xml");
+
+ dao.delete(dbTester.getSession(), 1L);
+ dbTester.getSession().commit();
+
+ assertThat(dbTester.countRowsOfTable("project_links")).isEqualTo(0);
+ }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java
index 90329d5842b..deb992be365 100644
--- a/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/component/ResourceIndexerDaoTest.java
@@ -22,14 +22,15 @@ package org.sonar.db.component;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
-import org.hamcrest.core.Is;
import org.junit.Before;
import org.junit.Test;
import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.utils.System2;
import org.sonar.db.AbstractDaoTestCase;
+import org.sonar.db.DbSession;
-import static org.hamcrest.Matchers.greaterThan;
-import static org.junit.Assert.assertThat;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
public class ResourceIndexerDaoTest extends AbstractDaoTestCase {
@@ -37,7 +38,7 @@ public class ResourceIndexerDaoTest extends AbstractDaoTestCase {
@Before
public void createDao() {
- dao = new ResourceIndexerDao(getMyBatis());
+ dao = new ResourceIndexerDao(getMyBatis(), mock(System2.class));
}
@Test
@@ -88,17 +89,17 @@ public class ResourceIndexerDaoTest extends AbstractDaoTestCase {
// project
rs = connection.createStatement().executeQuery("select count(resource_id) from resource_index where resource_id=1");
rs.next();
- assertThat(rs.getInt(1), greaterThan(0));
+ assertThat(rs.getInt(1)).isGreaterThan(0);
// directory
rs = connection.createStatement().executeQuery("select count(resource_id) from resource_index where resource_id=2");
rs.next();
- assertThat(rs.getInt(1), Is.is(0));
+ assertThat(rs.getInt(1)).isEqualTo(0);
// file
rs = connection.createStatement().executeQuery("select count(resource_id) from resource_index where resource_id=3");
rs.next();
- assertThat(rs.getInt(1), greaterThan(0));
+ assertThat(rs.getInt(1)).isGreaterThan(0);
} finally {
if (null != rs) {
rs.close();
@@ -150,4 +151,16 @@ public class ResourceIndexerDaoTest extends AbstractDaoTestCase {
checkTables("shouldNotReindexUnchangedResource", new String[] {"id"}, "resource_index");
}
+
+ @Test
+ public void select_project_ids_from_query_and_view_or_sub_view_uuid() {
+ setupData("select_project_ids_from_query_and_view_or_sub_view_uuid");
+ String viewUuid = "EFGH";
+
+ DbSession session = getMyBatis().openSession(false);
+ assertThat(dao.selectProjectIdsFromQueryAndViewOrSubViewUuid(session, "project", viewUuid)).containsOnly(1L, 2L);
+ assertThat(dao.selectProjectIdsFromQueryAndViewOrSubViewUuid(session, "one", viewUuid)).containsOnly(1L);
+ assertThat(dao.selectProjectIdsFromQueryAndViewOrSubViewUuid(session, "two", viewUuid)).containsOnly(2L);
+ assertThat(dao.selectProjectIdsFromQueryAndViewOrSubViewUuid(session, "unknown", viewUuid)).isEmpty();
+ }
}
diff --git a/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java
new file mode 100644
index 00000000000..21ec3e349a9
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/component/SnapshotDaoTest.java
@@ -0,0 +1,305 @@
+/*
+ * 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.db.component;
+
+import java.util.Date;
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.api.utils.DateUtils;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.db.component.SnapshotQuery.SORT_FIELD.BY_DATE;
+import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.ASC;
+import static org.sonar.db.component.SnapshotQuery.SORT_ORDER.DESC;
+
+@Category(DbTests.class)
+public class SnapshotDaoTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ DbSession session;
+
+ SnapshotDao sut;
+
+ @Before
+ public void createDao() {
+ session = db.myBatis().openSession(false);
+ sut = new SnapshotDao();
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void get_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ SnapshotDto result = sut.selectNullableById(session, 3L);
+ assertThat(result).isNotNull();
+ assertThat(result.getId()).isEqualTo(3L);
+ assertThat(result.getComponentId()).isEqualTo(3L);
+ assertThat(result.getRootProjectId()).isEqualTo(1L);
+ assertThat(result.getParentId()).isEqualTo(2L);
+ assertThat(result.getRootId()).isEqualTo(1L);
+ assertThat(result.getStatus()).isEqualTo("P");
+ assertThat(result.getLast()).isTrue();
+ assertThat(result.getPurgeStatus()).isEqualTo(1);
+ assertThat(result.getDepth()).isEqualTo(1);
+ assertThat(result.getScope()).isEqualTo("DIR");
+ assertThat(result.getQualifier()).isEqualTo("PAC");
+ assertThat(result.getVersion()).isEqualTo("2.1-SNAPSHOT");
+ assertThat(result.getPath()).isEqualTo("1.2.");
+
+ assertThat(result.getPeriodMode(1)).isEqualTo("days1");
+ assertThat(result.getPeriodModeParameter(1)).isEqualTo("30");
+ assertThat(result.getPeriodDate(1)).isEqualTo(1316815200000L);
+ assertThat(result.getPeriodMode(2)).isEqualTo("days2");
+ assertThat(result.getPeriodModeParameter(2)).isEqualTo("31");
+ assertThat(result.getPeriodDate(2)).isEqualTo(1316901600000L);
+ assertThat(result.getPeriodMode(3)).isEqualTo("days3");
+ assertThat(result.getPeriodModeParameter(3)).isEqualTo("32");
+ assertThat(result.getPeriodDate(3)).isEqualTo(1316988000000L);
+ assertThat(result.getPeriodMode(4)).isEqualTo("days4");
+ assertThat(result.getPeriodModeParameter(4)).isEqualTo("33");
+ assertThat(result.getPeriodDate(4)).isEqualTo(1317074400000L);
+ assertThat(result.getPeriodMode(5)).isEqualTo("days5");
+ assertThat(result.getPeriodModeParameter(5)).isEqualTo("34");
+ assertThat(result.getPeriodDate(5)).isEqualTo(1317160800000L);
+
+ assertThat(result.getCreatedAt()).isEqualTo(1228172400000L);
+ assertThat(result.getBuildDate()).isEqualTo(1317247200000L);
+
+ assertThat(sut.selectNullableById(session, 999L)).isNull();
+ }
+
+ @Test
+ public void lastSnapshot_returns_null_when_no_last_snapshot() {
+ SnapshotDto snapshot = sut.selectLastSnapshotByComponentId(session, 123L);
+
+ assertThat(snapshot).isNull();
+ }
+
+ @Test
+ public void lastSnapshot_from_one_resource() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+
+ SnapshotDto snapshot = sut.selectLastSnapshotByComponentId(session, 2L);
+
+ assertThat(snapshot).isNotNull();
+ assertThat(snapshot.getId()).isEqualTo(4L);
+ }
+
+ @Test
+ public void lastSnapshot_from_one_resource_without_last_is_null() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+
+ SnapshotDto snapshot = sut.selectLastSnapshotByComponentId(session, 5L);
+
+ assertThat(snapshot).isNull();
+ }
+
+ @Test
+ public void snapshot_and_child_retrieved() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+
+ List<SnapshotDto> snapshots = sut.selectSnapshotAndChildrenOfProjectScope(session, 1L);
+
+ assertThat(snapshots).isNotEmpty();
+ assertThat(snapshots).extracting("id").containsOnly(1L, 6L);
+ }
+
+ @Test
+ public void select_snapshots_by_component_id() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+
+ List<SnapshotDto> snapshots = sut.selectSnapshotsByComponentId(session, 1L);
+
+ assertThat(snapshots).hasSize(3);
+ }
+
+ @Test
+ public void select_snapshots_by_query() {
+ db.prepareDbUnit(getClass(), "select_snapshots_by_query.xml");
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery())).hasSize(6);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L))).hasSize(3);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setVersion("2.2-SNAPSHOT"))).extracting("id").containsOnly(3L);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setIsLast(true))).extracting("id").containsOnly(1L);
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setIsLast(false))).extracting("id").containsOnly(2L, 3L);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setCreatedAfter(1228172400002L))).extracting("id").containsOnly(2L, 3L);
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setCreatedBefore(1228172400002L))).extracting("id").containsOnly(1L);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(2L).setStatus("P"))).hasSize(1);
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(2L).setStatus("U"))).hasSize(1);
+
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setSort(BY_DATE, ASC)).get(0).getId()).isEqualTo(1L);
+ assertThat(sut.selectSnapshotsByQuery(session, new SnapshotQuery().setComponentId(1L).setSort(BY_DATE, DESC)).get(0).getId()).isEqualTo(3L);
+ }
+
+ @Test
+ public void select_previous_version_snapshots() throws Exception {
+ db.prepareDbUnit(getClass(), "select_previous_version_snapshots.xml");
+
+ List<SnapshotDto> snapshots = sut.selectPreviousVersionSnapshots(session, 1L, "1.2-SNAPSHOT");
+ assertThat(snapshots).hasSize(2);
+
+ SnapshotDto firstSnapshot = snapshots.get(0);
+ assertThat(firstSnapshot.getVersion()).isEqualTo("1.1");
+
+ // All snapshots are returned on an unknown version
+ assertThat(sut.selectPreviousVersionSnapshots(session, 1L, "UNKNOWN")).hasSize(3);
+ }
+
+ @Test
+ public void insert() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ SnapshotDto dto = defaultSnapshot().setCreatedAt(1403042400000L);
+
+ sut.insert(session, dto);
+ session.commit();
+
+ assertThat(dto.getId()).isNotNull();
+ db.assertDbUnit(getClass(), "insert-result.xml", new String[] {"id"}, "snapshots");
+ }
+
+ @Test
+ public void insert_snapshots() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ sut.insert(session,
+ new SnapshotDto().setComponentId(1L).setLast(false),
+ new SnapshotDto().setComponentId(2L).setLast(false));
+ session.commit();
+
+ assertThat(db.countRowsOfTable("snapshots")).isEqualTo(2);
+ }
+
+ @Test
+ public void set_snapshot_and_children_to_false_and_status_processed() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+ SnapshotDto snapshot = defaultSnapshot().setId(1L);
+
+ sut.updateSnapshotAndChildrenLastFlagAndStatus(session, snapshot, false, SnapshotDto.STATUS_PROCESSED);
+ session.commit();
+
+ List<SnapshotDto> snapshots = sut.selectSnapshotAndChildrenOfProjectScope(session, 1L);
+ assertThat(snapshots).hasSize(2);
+ assertThat(snapshots).extracting("id").containsOnly(1L, 6L);
+ assertThat(snapshots).extracting("last").containsOnly(false);
+ assertThat(snapshots).extracting("status").containsOnly(SnapshotDto.STATUS_PROCESSED);
+ }
+
+ @Test
+ public void set_snapshot_and_children_isLast_flag_to_false() {
+ db.prepareDbUnit(getClass(), "snapshots.xml");
+ SnapshotDto snapshot = defaultSnapshot().setId(1L);
+
+ sut.updateSnapshotAndChildrenLastFlag(session, snapshot, false);
+ session.commit();
+
+ List<SnapshotDto> snapshots = sut.selectSnapshotAndChildrenOfProjectScope(session, 1L);
+ assertThat(snapshots).hasSize(2);
+ assertThat(snapshots).extracting("id").containsOnly(1L, 6L);
+ assertThat(snapshots).extracting("last").containsOnly(false);
+ }
+
+ @Test
+ public void is_last_snapshot_when_no_previous_snapshot() {
+ SnapshotDto snapshot = defaultSnapshot();
+
+ boolean isLast = SnapshotDao.isLast(snapshot, null);
+
+ assertThat(isLast).isTrue();
+ }
+
+ @Test
+ public void is_last_snapshot_when_previous_snapshot_is_older() {
+ Date today = new Date();
+ Date yesterday = DateUtils.addDays(today, -1);
+
+ SnapshotDto snapshot = defaultSnapshot().setCreatedAt(today.getTime());
+ SnapshotDto previousLastSnapshot = defaultSnapshot().setCreatedAt(yesterday.getTime());
+
+ boolean isLast = SnapshotDao.isLast(snapshot, previousLastSnapshot);
+
+ assertThat(isLast).isTrue();
+ }
+
+ @Test
+ public void is_not_last_snapshot_when_previous_snapshot_is_newer() {
+ Date today = new Date();
+ Date yesterday = DateUtils.addDays(today, -1);
+
+ SnapshotDto snapshot = defaultSnapshot().setCreatedAt(yesterday.getTime());
+ SnapshotDto previousLastSnapshot = defaultSnapshot().setCreatedAt(today.getTime());
+
+ boolean isLast = SnapshotDao.isLast(snapshot, previousLastSnapshot);
+
+ assertThat(isLast).isFalse();
+ }
+
+ private static SnapshotDto defaultSnapshot() {
+ return new SnapshotDto()
+ .setComponentId(3L)
+ .setRootProjectId(1L)
+ .setParentId(2L)
+ .setRootId(1L)
+ .setStatus("P")
+ .setLast(true)
+ .setPurgeStatus(1)
+ .setDepth(1)
+ .setScope("DIR")
+ .setQualifier("PAC")
+ .setVersion("2.1-SNAPSHOT")
+ .setPath("1.2.")
+ .setPeriodMode(1, "days1")
+ .setPeriodMode(2, "days2")
+ .setPeriodMode(3, "days3")
+ .setPeriodMode(4, "days4")
+ .setPeriodMode(5, "days5")
+ .setPeriodParam(1, "30")
+ .setPeriodParam(2, "31")
+ .setPeriodParam(3, "32")
+ .setPeriodParam(4, "33")
+ .setPeriodParam(5, "34")
+ .setPeriodDate(1, 1_500_000_000_001L)
+ .setPeriodDate(2, 1_500_000_000_002L)
+ .setPeriodDate(3, 1_500_000_000_003L)
+ .setPeriodDate(4, 1_500_000_000_004L)
+ .setPeriodDate(5, 1_500_000_000_005L)
+ .setBuildDate(1_500_000_000_006L);
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/compute/AnalysisReportDaoTest.java b/sonar-db/src/test/java/org/sonar/db/compute/AnalysisReportDaoTest.java
new file mode 100644
index 00000000000..17bb66813b7
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/compute/AnalysisReportDaoTest.java
@@ -0,0 +1,212 @@
+/*
+ * 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.db.compute;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.utils.System2;
+import org.sonar.db.compute.AnalysisReportDao;
+import org.sonar.db.compute.AnalysisReportDto;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.MyBatis;
+import org.sonar.test.DbTests;
+
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.db.compute.AnalysisReportDto.Status.PENDING;
+import static org.sonar.db.compute.AnalysisReportDto.Status.WORKING;
+
+@Category(DbTests.class)
+public class AnalysisReportDaoTest {
+
+ private static final String DEFAULT_PROJECT_KEY = "123456789-987654321";
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ AnalysisReportDao sut;
+ DbSession session;
+ System2 system2;
+
+ @Before
+ public void before() {
+ this.session = db.myBatis().openSession(false);
+ this.system2 = mock(System2.class);
+ this.sut = new AnalysisReportDao(system2);
+
+ when(system2.now()).thenReturn(1_500_000_000_000L);
+ }
+
+ @After
+ public void after() {
+ MyBatis.closeQuietly(session);
+ }
+
+ @Test
+ public void insert_multiple_reports() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ AnalysisReportDto report1 = new AnalysisReportDto().setProjectKey("ProjectKey1").setProjectName("Project 1").setUuid("UUID_1").setStatus(PENDING);
+ AnalysisReportDto report2 = new AnalysisReportDto().setProjectKey("ProjectKey2").setProjectName("Project 2").setUuid("UUID_2").setStatus(PENDING);
+
+ sut.insert(session, report1);
+ sut.insert(session, report2);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "insert-result.xml", "analysis_reports");
+ }
+
+ @Test
+ public void resetAllToPendingStatus() {
+ db.prepareDbUnit(getClass(), "update-all-to-status-pending.xml");
+
+ sut.resetAllToPendingStatus(session);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "update-all-to-status-pending-result.xml", "analysis_reports");
+ }
+
+ @Test
+ public void truncate() {
+ db.prepareDbUnit(getClass(), "any-analysis-reports.xml");
+
+ sut.truncate(session);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "truncate-result.xml", "analysis_reports");
+ }
+
+ @Test
+ public void find_one_report_by_project_key() {
+ db.prepareDbUnit(getClass(), "select.xml");
+
+ final String projectKey = "123456789-987654321";
+ List<AnalysisReportDto> reports = sut.selectByProjectKey(session, projectKey);
+ AnalysisReportDto report = reports.get(0);
+
+ assertThat(reports).hasSize(1);
+ assertThat(report.getProjectKey()).isEqualTo(projectKey);
+ assertThat(report.getProjectName()).isEqualTo("Project 1");
+ assertThat(report.getStatus()).isEqualTo(AnalysisReportDto.Status.WORKING);
+ assertThat(report.getId()).isEqualTo(1);
+ }
+
+ @Test
+ public void find_several_reports_by_project_key() {
+ db.prepareDbUnit(getClass(), "select.xml");
+
+ final String projectKey = "987654321-123456789";
+ List<AnalysisReportDto> reports = sut.selectByProjectKey(session, projectKey);
+
+ assertThat(reports).hasSize(2);
+ }
+
+ @Test
+ public void pop_oldest_pending() {
+ db.prepareDbUnit(getClass(), "pop_oldest_pending.xml");
+
+ AnalysisReportDto nextAvailableReport = sut.pop(session);
+
+ assertThat(nextAvailableReport.getId()).isEqualTo(3);
+ assertThat(nextAvailableReport.getProjectKey()).isEqualTo("P2");
+ }
+
+ @Test
+ public void pop_null_if_no_pending_reports() {
+ db.prepareDbUnit(getClass(), "pop_null_if_no_pending_reports.xml");
+
+ AnalysisReportDto nextAvailableReport = sut.pop(session);
+
+ assertThat(nextAvailableReport).isNull();
+ }
+
+ @Test
+ public void getById_maps_all_the_fields_except_the_data() {
+ db.prepareDbUnit(getClass(), "one_analysis_report.xml");
+
+ AnalysisReportDto report = sut.selectById(session, 1L);
+
+ assertThat(report.getProjectKey()).isEqualTo(DEFAULT_PROJECT_KEY);
+ assertThat(report.getCreatedAt()).isEqualTo(1_500_000_000_001L);
+ assertThat(report.getUpdatedAt()).isEqualTo(1_500_000_000_002L);
+ assertThat(report.getStartedAt()).isEqualTo(1_500_000_000_003L);
+ assertThat(report.getFinishedAt()).isEqualTo(1_500_000_000_004L);
+ assertThat(report.getStatus()).isEqualTo(WORKING);
+ }
+
+ @Test
+ public void getById_returns_null_when_id_not_found() {
+ db.prepareDbUnit(getClass(), "select.xml");
+
+ AnalysisReportDto report = sut.selectById(session, 4L);
+
+ assertThat(report).isNull();
+ }
+
+ @Test
+ public void delete_one_analysis_report() {
+ db.prepareDbUnit(getClass(), "one_analysis_report.xml");
+
+ sut.delete(session, 1);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "truncate-result.xml", "analysis_reports");
+ }
+
+ @Test
+ public void findAll_one_analysis_report() {
+ db.prepareDbUnit(getClass(), "one_analysis_report.xml");
+
+ List<AnalysisReportDto> reports = sut.selectAll(session);
+
+ assertThat(reports).hasSize(1);
+ }
+
+ @Test
+ public void findAll_empty_table() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ List<AnalysisReportDto> reports = sut.selectAll(session);
+
+ assertThat(reports).isEmpty();
+ }
+
+ @Test
+ public void findAll_three_analysis_reports() {
+ db.prepareDbUnit(getClass(), "three_analysis_reports.xml");
+
+ List<AnalysisReportDto> reports = sut.selectAll(session);
+
+ assertThat(reports).hasSize(3);
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java b/sonar-db/src/test/java/org/sonar/db/dashboard/WidgetDaoTest.java
index 7c3eeaa1d08..aa5afd5af14 100644
--- a/sonar-db/src/test/java/org/sonar/db/qualityprofile/ActiveRuleDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/dashboard/WidgetDaoTest.java
@@ -17,55 +17,53 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+package org.sonar.db.dashboard;
-package org.sonar.db.qualityprofile;
-
-import java.util.List;
+import java.util.Collection;
+import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.sonar.db.AbstractDaoTestCase;
+import org.junit.experimental.categories.Category;
import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.MyBatis;
+import org.sonar.test.DbTests;
import static org.assertj.core.api.Assertions.assertThat;
-public class ActiveRuleDaoTest extends AbstractDaoTestCase {
+@Category(DbTests.class)
+public class WidgetDaoTest {
- ActiveRuleDao dao;
+ WidgetDao dao;
- @Before
- public void before() {
- dao = new ActiveRuleDao(getMyBatis());
- }
+ @Rule
+ public DbTester dbTester = new DbTester();
- @Test
- public void select_by_profile() {
- setupData("shared");
+ private DbSession session;
- List<ActiveRuleDto> result = dao.selectByProfileKey("parent");
- assertThat(result).hasSize(2);
+ @Before
+ public void setUp() {
+ dao = new WidgetDao(dbTester.myBatis());
+ session = dbTester.myBatis().openSession(false);
}
- @Test
- public void insert_parameter() {
- setupData("empty");
-
- DbSession session = getMyBatis().openSession(false);
- ActiveRuleParamDto dto = new ActiveRuleParamDto()
- .setActiveRuleId(1)
- .setRulesParameterId(1)
- .setKey("max")
- .setValue("20");
- dao.insert(dto, session);
- session.commit();
- session.close();
-
- checkTables("insert_parameter", "active_rule_parameters");
+ @After
+ public void tearDown() {
+ MyBatis.closeQuietly(session);
}
@Test
- public void select_params_by_profile_id() {
- setupData("shared");
+ public void should_select_all() {
+ dbTester.prepareDbUnit(this.getClass(), "before.xml");
+ session.commit();
- assertThat(dao.selectParamsByProfileKey("child")).hasSize(2);
+ Collection<WidgetDto> widgets = dao.findAll(session);
+ assertThat(widgets).hasSize(5);
+ for (WidgetDto widget : widgets) {
+ assertThat(widget.getId()).isNotNull();
+ assertThat(widget.getName()).isNotNull();
+ assertThat(widget.getDescription()).isNotNull();
+ }
}
}
diff --git a/sonar-db/src/test/java/org/sonar/db/event/EventDaoTest.java b/sonar-db/src/test/java/org/sonar/db/event/EventDaoTest.java
new file mode 100644
index 00000000000..4915c0e2291
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/event/EventDaoTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.db.event;
+
+import java.util.List;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class EventDaoTest {
+
+ @ClassRule
+ public static DbTester dbTester = new DbTester();
+
+ DbSession session;
+
+ EventDao dao;
+
+ @Before
+ public void setup() {
+ dbTester.truncateTables();
+ session = dbTester.myBatis().openSession(false);
+ dao = new EventDao();
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void select_by_component_uuid() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+ List<EventDto> dtos = dao.selectByComponentUuid(session, "ABCD");
+ assertThat(dtos).hasSize(3);
+
+ dtos = dao.selectByComponentUuid(session, "BCDE");
+ assertThat(dtos).hasSize(1);
+
+ EventDto dto = dtos.get(0);
+ assertThat(dto.getId()).isEqualTo(4L);
+ assertThat(dto.getComponentUuid()).isEqualTo("BCDE");
+ assertThat(dto.getSnapshotId()).isEqualTo(1000L);
+ assertThat(dto.getName()).isEqualTo("1.0");
+ assertThat(dto.getCategory()).isEqualTo("Version");
+ assertThat(dto.getDescription()).isEqualTo("Version 1.0");
+ assertThat(dto.getData()).isEqualTo("some data");
+ assertThat(dto.getDate()).isEqualTo(1413407091086L);
+ assertThat(dto.getCreatedAt()).isEqualTo(1225630680000L);
+ }
+
+ @Test
+ public void return_different_categories() {
+ dbTester.prepareDbUnit(getClass(), "shared.xml");
+
+ List<EventDto> dtos = dao.selectByComponentUuid(session, "ABCD");
+ assertThat(dtos).extracting("category").containsOnly(EventDto.CATEGORY_ALERT, EventDto.CATEGORY_PROFILE, EventDto.CATEGORY_VERSION);
+ }
+
+ @Test
+ public void insert() {
+ dbTester.prepareDbUnit(getClass(), "empty.xml");
+
+ dao.insert(session, new EventDto()
+ .setName("1.0")
+ .setCategory(EventDto.CATEGORY_VERSION)
+ .setDescription("Version 1.0")
+ .setData("some data")
+ .setDate(1413407091086L)
+ .setComponentUuid("ABCD")
+ .setSnapshotId(1000L)
+ .setCreatedAt(1225630680000L)
+ );
+ session.commit();
+
+ dbTester.assertDbUnit(getClass(), "insert-result.xml", new String[] {"id"}, "events");
+ }
+
+ @Test
+ public void delete() {
+ dbTester.prepareDbUnit(getClass(), "delete.xml");
+
+ dao.delete(session, 1L);
+ session.commit();
+
+ assertThat(dbTester.countRowsOfTable("events")).isEqualTo(0);
+ }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java
index a70e1a3d08e..9a083137952 100644
--- a/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/issue/ActionPlanStatsDaoTest.java
@@ -21,24 +21,23 @@
package org.sonar.db.issue;
import java.util.Collection;
-import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
-import org.sonar.db.AbstractDaoTestCase;
+import org.sonar.api.utils.System2;
+import org.sonar.db.DbTester;
import static org.assertj.core.api.Assertions.assertThat;
-public class ActionPlanStatsDaoTest extends AbstractDaoTestCase {
+public class ActionPlanStatsDaoTest {
- ActionPlanStatsDao dao;
+ @Rule
+ public DbTester dbTester = DbTester.create(System2.INSTANCE);
- @Before
- public void createDao() {
- dao = new ActionPlanStatsDao(getMyBatis());
- }
+ ActionPlanStatsDao dao = dbTester.getDbClient().getActionPlanStatsDao();
@Test
public void should_find_by_project() {
- setupData("shared", "should_find_by_project");
+ dbTester.prepareDbUnit(getClass(), "shared.xml", "should_find_by_project.xml");
Collection<ActionPlanStatsDto> result = dao.findByProjectId(1l);
assertThat(result).isNotEmpty();
diff --git a/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java b/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java
index 24f556df1e6..dc64f45d05d 100644
--- a/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/issue/IssueDaoTest.java
@@ -20,12 +20,17 @@
package org.sonar.db.issue;
+import java.util.Arrays;
+import java.util.List;
import org.apache.ibatis.executor.result.DefaultResultHandler;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.rule.RuleKey;
import org.sonar.db.AbstractDaoTestCase;
import org.sonar.db.DbSession;
+import org.sonar.db.component.ComponentDto;
+import org.sonar.db.rule.RuleTesting;
import static org.assertj.core.api.Assertions.assertThat;
@@ -91,4 +96,116 @@ public class IssueDaoTest extends AbstractDaoTestCase {
assertThat(issue.getComponentKey()).isNotNull();
assertThat(issue.getProjectKey()).isNull();
}
+
+ @Test
+ public void get_by_key() {
+ setupData("shared", "get_by_key");
+
+ IssueDto issue = dao.selectByKey(session, "ABCDE");
+ assertThat(issue.getKee()).isEqualTo("ABCDE");
+ assertThat(issue.getId()).isEqualTo(100L);
+ assertThat(issue.getComponentUuid()).isEqualTo("CDEF");
+ assertThat(issue.getProjectUuid()).isEqualTo("ABCD");
+ 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()).isEqualTo(1400000000000L);
+ assertThat(issue.getUpdatedAt()).isEqualTo(1450000000000L);
+ assertThat(issue.getRuleRepo()).isEqualTo("squid");
+ assertThat(issue.getRule()).isEqualTo("AvoidCycle");
+ assertThat(issue.getComponentKey()).isEqualTo("Action.java");
+ assertThat(issue.getProjectKey()).isEqualTo("struts");
+ }
+
+ @Test
+ public void get_by_keys() {
+ setupData("shared", "get_by_key");
+
+ List<IssueDto> issues = dao.selectByKeys(session, Arrays.asList("ABCDE"));
+ assertThat(issues).hasSize(1);
+ }
+
+ @Test
+ public void find_by_action_plan() {
+ setupData("shared", "find_by_action_plan");
+
+ List<IssueDto> issues = dao.findByActionPlan(session, "AP-1");
+ assertThat(issues).hasSize(1);
+
+ IssueDto issue = issues.get(0);
+ assertThat(issue.getKee()).isEqualTo("ABCDE");
+ assertThat(issue.getActionPlanKey()).isEqualTo("AP-1");
+ assertThat(issue.getComponentUuid()).isEqualTo("CDEF");
+ assertThat(issue.getProjectUuid()).isEqualTo("ABCD");
+ 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
+ public void insert() {
+ IssueDto dto = new IssueDto();
+ dto.setComponent(new ComponentDto().setKey("struts:Action").setId(123L).setUuid("component-uuid"));
+ dto.setProject(new ComponentDto().setKey("struts").setId(100L).setUuid("project-uuid"));
+ dto.setRule(RuleTesting.newDto(RuleKey.of("squid", "S001")).setId(200));
+ dto.setKee("ABCDE");
+ dto.setLine(500);
+ dto.setEffortToFix(3.14);
+ dto.setDebt(10L);
+ dto.setResolution("FIXED");
+ dto.setStatus("RESOLVED");
+ dto.setSeverity("BLOCKER");
+ dto.setReporter("emmerik");
+ dto.setAuthorLogin("morgan");
+ dto.setAssignee("karadoc");
+ dto.setActionPlanKey("current_sprint");
+ dto.setIssueAttributes("JIRA=FOO-1234");
+ dto.setChecksum("123456789");
+ dto.setMessage("the message");
+
+ dto.setIssueCreationTime(1_500_000_000_000L);
+ dto.setIssueUpdateTime(1_500_000_000_001L);
+ dto.setIssueCloseTime(1_500_000_000_002L);
+ dto.setCreatedAt(1_400_000_000_000L);
+ dto.setUpdatedAt(1_450_000_000_000L);
+
+ dao.insert(session, dto);
+ session.commit();
+
+ checkTables("insert", new String[] {"id"}, "issues");
+ }
}
diff --git a/sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java b/sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java
new file mode 100644
index 00000000000..9621d6aa945
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/measure/MeasureDaoTest.java
@@ -0,0 +1,333 @@
+/*
+ * 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.db.measure;
+
+import com.google.common.base.Function;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.db.measure.MeasureDao;
+import org.sonar.db.measure.MeasureDto;
+import org.sonar.db.measure.PastMeasureDto;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Category(DbTests.class)
+public class MeasureDaoTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ DbSession session;
+ MeasureDao sut;
+
+ @Before
+ public void setUp() {
+ db.truncateTables();
+ session = db.myBatis().openSession(false);
+ sut = new MeasureDao();
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void get_value_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ MeasureDto result = sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "ncloc");
+ assertThat(result.getId()).isEqualTo(22);
+ assertThat(result.getValue()).isEqualTo(10d);
+ assertThat(result.getData()).isNull();
+ assertThat(result.getVariation(1)).isEqualTo(1d);
+ assertThat(result.getVariation(2)).isEqualTo(2d);
+ assertThat(result.getVariation(3)).isEqualTo(3d);
+ assertThat(result.getVariation(4)).isEqualTo(4d);
+ assertThat(result.getVariation(5)).isEqualTo(-5d);
+ assertThat(result.getAlertStatus()).isEqualTo("OK");
+ assertThat(result.getAlertText()).isEqualTo("Green");
+ }
+
+ @Test
+ // TODO the string must be longer than 4000 char to be persisted in the data field
+ public void get_data_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ MeasureDto result = sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "authors_by_line");
+ assertThat(result.getId()).isEqualTo(20);
+ assertThat(result.getData()).isEqualTo("0123456789012345678901234567890123456789");
+ }
+
+ @Test
+ public void get_text_value_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ MeasureDto result = sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "coverage_line_hits_data");
+ assertThat(result.getId()).isEqualTo(21);
+ assertThat(result.getData()).isEqualTo("36=1;37=1;38=1;39=1;43=1;48=1;53=1");
+ }
+
+ @Test
+ public void find_by_component_key_and_metrics() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ List<MeasureDto> results = sut.findByComponentKeyAndMetricKeys(session, "org.struts:struts-core:src/org/struts/RequestContext.java",
+ newArrayList("ncloc", "authors_by_line"));
+ assertThat(results).hasSize(2);
+
+ results = sut.findByComponentKeyAndMetricKeys(session, "org.struts:struts-core:src/org/struts/RequestContext.java", newArrayList("ncloc"));
+ assertThat(results).hasSize(1);
+
+ MeasureDto result = results.get(0);
+ assertThat(result.getId()).isEqualTo(22);
+ assertThat(result.getValue()).isEqualTo(10d);
+ assertThat(result.getComponentKey()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java");
+ assertThat(result.getMetricKey()).isEqualTo("ncloc");
+ assertThat(result.getVariation(1)).isEqualTo(1d);
+ assertThat(result.getVariation(2)).isEqualTo(2d);
+ assertThat(result.getVariation(3)).isEqualTo(3d);
+ assertThat(result.getVariation(4)).isEqualTo(4d);
+ assertThat(result.getVariation(5)).isEqualTo(-5d);
+ }
+
+ @Test
+ public void find_by_component_key_and_metric() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ MeasureDto result = sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "ncloc");
+ assertThat(result.getId()).isEqualTo(22);
+ assertThat(result.getValue()).isEqualTo(10d);
+ assertThat(result.getMetricKey()).isEqualTo("ncloc");
+ assertThat(result.getComponentKey()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java");
+ assertThat(result.getVariation(1)).isEqualTo(1d);
+ assertThat(result.getVariation(2)).isEqualTo(2d);
+ assertThat(result.getVariation(3)).isEqualTo(3d);
+ assertThat(result.getVariation(4)).isEqualTo(4d);
+ assertThat(result.getVariation(5)).isEqualTo(-5d);
+
+ assertThat(sut.findByComponentKeyAndMetricKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "unknown")).isNull();
+ }
+
+ @Test
+ public void exists_by_key() {
+ db.prepareDbUnit(getClass(), "shared.xml");
+
+ assertThat(sut.existsByKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "ncloc")).isTrue();
+ assertThat(sut.existsByKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java", "unknown")).isFalse();
+ }
+
+ @Test
+ public void select_past_measures_by_component_uuid_and_root_snapshot_id_and_metric_keys() {
+ db.prepareDbUnit(getClass(), "past_measures.xml");
+
+ List<PastMeasureDto> fileMeasures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "CDEF", 1000L, ImmutableSet.of(1, 2));
+ assertThat(fileMeasures).hasSize(2);
+
+ PastMeasureDto fileMeasure1 = fileMeasures.get(0);
+ assertThat(fileMeasure1.getValue()).isEqualTo(5d);
+ assertThat(fileMeasure1.getMetricId()).isEqualTo(1);
+ assertThat(fileMeasure1.getRuleId()).isNull();
+ assertThat(fileMeasure1.getCharacteristicId()).isNull();
+ assertThat(fileMeasure1.getPersonId()).isNull();
+
+ PastMeasureDto fileMeasure2 = fileMeasures.get(1);
+ assertThat(fileMeasure2.getValue()).isEqualTo(60d);
+ assertThat(fileMeasure2.getMetricId()).isEqualTo(2);
+
+ List<PastMeasureDto> projectMeasures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "ABCD", 1000L, ImmutableSet.of(1, 2));
+ assertThat(projectMeasures).hasSize(2);
+
+ PastMeasureDto projectMeasure1 = projectMeasures.get(0);
+ assertThat(projectMeasure1.getValue()).isEqualTo(60d);
+ assertThat(projectMeasure1.getMetricId()).isEqualTo(1);
+
+ PastMeasureDto projectMeasure2 = projectMeasures.get(1);
+ assertThat(projectMeasure2.getValue()).isEqualTo(80d);
+ assertThat(projectMeasure2.getMetricId()).isEqualTo(2);
+
+ assertThat(sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "UNKNOWN", 1000L, ImmutableSet.of(1, 2))).isEmpty();
+ assertThat(sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "CDEF", 987654L, ImmutableSet.of(1, 2))).isEmpty();
+ assertThat(sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "CDEF", 1000L, ImmutableSet.of(123, 456))).isEmpty();
+ }
+
+ @Test
+ public void select_past_measures_on_rule_by_component_uuid_and_root_snapshot_id_and_metric_keys() {
+ db.prepareDbUnit(getClass(), "past_measures_with_rule_id.xml");
+
+ List<PastMeasureDto> measures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "ABCD", 1000L, ImmutableSet.of(1));
+ assertThat(measures).hasSize(3);
+
+ Map<Long, PastMeasureDto> pastMeasuresById = pastMeasuresById(measures);
+
+ PastMeasureDto measure1 = pastMeasuresById.get(1L);
+ assertThat(measure1.getValue()).isEqualTo(60d);
+ assertThat(measure1.getMetricId()).isEqualTo(1);
+ assertThat(measure1.getRuleId()).isNull();
+ assertThat(measure1.getCharacteristicId()).isNull();
+ assertThat(measure1.getPersonId()).isNull();
+
+ PastMeasureDto measure2 = pastMeasuresById.get(2L);
+ assertThat(measure2.getValue()).isEqualTo(20d);
+ assertThat(measure2.getMetricId()).isEqualTo(1);
+ assertThat(measure2.getRuleId()).isEqualTo(30);
+ assertThat(measure2.getCharacteristicId()).isNull();
+ assertThat(measure2.getPersonId()).isNull();
+
+ PastMeasureDto measure3 = pastMeasuresById.get(3L);
+ assertThat(measure3.getValue()).isEqualTo(40d);
+ assertThat(measure3.getMetricId()).isEqualTo(1);
+ assertThat(measure3.getRuleId()).isEqualTo(31);
+ assertThat(measure3.getCharacteristicId()).isNull();
+ assertThat(measure3.getPersonId()).isNull();
+ }
+
+ @Test
+ public void select_past_measures_on_characteristic_by_component_uuid_and_root_snapshot_id_and_metric_keys() {
+ db.prepareDbUnit(getClass(), "past_measures_with_characteristic_id.xml");
+
+ List<PastMeasureDto> measures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "ABCD", 1000L, ImmutableSet.of(1));
+ assertThat(measures).hasSize(3);
+
+ Map<Long, PastMeasureDto> pastMeasuresById = pastMeasuresById(measures);
+
+ PastMeasureDto measure1 = pastMeasuresById.get(1L);
+ assertThat(measure1.getValue()).isEqualTo(60d);
+ assertThat(measure1.getMetricId()).isEqualTo(1);
+ assertThat(measure1.getRuleId()).isNull();
+ assertThat(measure1.getCharacteristicId()).isNull();
+ assertThat(measure1.getPersonId()).isNull();
+
+ PastMeasureDto measure2 = pastMeasuresById.get(2L);
+ assertThat(measure2.getValue()).isEqualTo(20d);
+ assertThat(measure2.getMetricId()).isEqualTo(1);
+ assertThat(measure2.getRuleId()).isNull();
+ assertThat(measure2.getCharacteristicId()).isEqualTo(10);
+ assertThat(measure2.getPersonId()).isNull();
+
+ PastMeasureDto measure3 = pastMeasuresById.get(3L);
+ assertThat(measure3.getValue()).isEqualTo(40d);
+ assertThat(measure3.getMetricId()).isEqualTo(1);
+ assertThat(measure3.getRuleId()).isNull();
+ assertThat(measure3.getCharacteristicId()).isEqualTo(11);
+ assertThat(measure3.getPersonId()).isNull();
+ }
+
+ @Test
+ public void select_past_measures_on_person_by_component_uuid_and_root_snapshot_id_and_metric_keys() {
+ db.prepareDbUnit(getClass(), "past_measures_with_person_id.xml");
+
+ List<PastMeasureDto> measures = sut.selectByComponentUuidAndProjectSnapshotIdAndMetricIds(session, "ABCD", 1000L, ImmutableSet.of(1));
+ assertThat(measures).hasSize(3);
+
+ Map<Long, PastMeasureDto> pastMeasuresById = pastMeasuresById(measures);
+
+ PastMeasureDto measure1 = pastMeasuresById.get(1L);
+ assertThat(measure1.getValue()).isEqualTo(60d);
+ assertThat(measure1.getMetricId()).isEqualTo(1);
+ assertThat(measure1.getRuleId()).isNull();
+ assertThat(measure1.getCharacteristicId()).isNull();
+ assertThat(measure1.getPersonId()).isNull();
+
+ PastMeasureDto measure2 = pastMeasuresById.get(2L);
+ assertThat(measure2.getValue()).isEqualTo(20d);
+ assertThat(measure2.getMetricId()).isEqualTo(1);
+ assertThat(measure2.getRuleId()).isNull();
+ assertThat(measure2.getCharacteristicId()).isNull();
+ assertThat(measure2.getPersonId()).isEqualTo(20);
+
+ PastMeasureDto measure3 = pastMeasuresById.get(3L);
+ assertThat(measure3.getValue()).isEqualTo(40d);
+ assertThat(measure3.getMetricId()).isEqualTo(1);
+ assertThat(measure3.getRuleId()).isNull();
+ assertThat(measure3.getCharacteristicId()).isNull();
+ assertThat(measure3.getPersonId()).isEqualTo(21);
+ }
+
+ @Test
+ public void insert() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ sut.insert(session, new MeasureDto()
+ .setSnapshotId(2L)
+ .setMetricId(3)
+ .setCharacteristicId(4)
+ .setPersonId(23)
+ .setRuleId(5)
+ .setComponentId(6L)
+ .setValue(2.0d)
+ .setData("measure-value")
+ .setVariation(1, 1.0d)
+ .setVariation(2, 2.0d)
+ .setVariation(3, 3.0d)
+ .setVariation(4, 4.0d)
+ .setVariation(5, 5.0d)
+ .setAlertStatus("alert")
+ .setAlertText("alert-text")
+ .setDescription("measure-description")
+ );
+ session.commit();
+
+ db.assertDbUnit(getClass(), "insert-result.xml", new String[] {"id"}, "project_measures");
+ }
+
+ @Test
+ public void insert_measures() {
+ db.prepareDbUnit(getClass(), "empty.xml");
+
+ sut.insert(session, new MeasureDto()
+ .setSnapshotId(2L)
+ .setMetricId(3)
+ .setComponentId(6L)
+ .setValue(2.0d),
+ new MeasureDto()
+ .setSnapshotId(3L)
+ .setMetricId(4)
+ .setComponentId(6L)
+ .setValue(4.0d)
+ );
+ session.commit();
+
+ assertThat(db.countRowsOfTable("project_measures")).isEqualTo(2);
+ }
+
+ private static Map<Long, PastMeasureDto> pastMeasuresById(List<PastMeasureDto> pastMeasures) {
+ return FluentIterable.from(pastMeasures).uniqueIndex(new Function<PastMeasureDto, Long>() {
+ @Nullable
+ @Override
+ public Long apply(PastMeasureDto input) {
+ return input.getId();
+ }
+ });
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java b/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
index 592e42b406e..11aa33abc18 100644
--- a/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/purge/PurgeDaoTest.java
@@ -55,7 +55,7 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
when(system2.now()).thenReturn(1450000000000L);
dbSession = getMyBatis().openSession(false);
- sut = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis(), system2), new PurgeProfiler(), system2);
+ sut = new PurgeDao(getMyBatis(), new ResourceDao(getMyBatis(), system2), system2);
}
@After
@@ -66,14 +66,14 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
@Test
public void shouldDeleteAbortedBuilds() {
setupData("shouldDeleteAbortedBuilds");
- sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("shouldDeleteAbortedBuilds", "snapshots");
}
@Test
public void should_purge_project() {
setupData("shouldPurgeProject");
- sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("shouldPurgeProject", "projects", "snapshots");
}
@@ -88,28 +88,28 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
@Test
public void delete_file_sources_of_disabled_resources() {
setupData("delete_file_sources_of_disabled_resources");
- sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("delete_file_sources_of_disabled_resources", "file_sources");
}
@Test
public void shouldDeleteHistoricalDataOfDirectoriesAndFiles() {
setupData("shouldDeleteHistoricalDataOfDirectoriesAndFiles");
- sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30), PurgeListener.EMPTY);
+ sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[] {Scopes.DIRECTORY, Scopes.FILE}, 30), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("shouldDeleteHistoricalDataOfDirectoriesAndFiles", "projects", "snapshots");
}
@Test
public void disable_resources_without_last_snapshot() {
setupData("disable_resources_without_last_snapshot");
- sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(system2), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("disable_resources_without_last_snapshot", new String[] {"issue_close_date", "issue_update_date"}, "projects", "snapshots", "issues");
}
@Test
public void shouldDeleteSnapshots() {
setupData("shouldDeleteSnapshots");
- sut.deleteSnapshots(PurgeSnapshotQuery.create().setIslast(false).setResourceId(1L));
+ sut.deleteSnapshots(PurgeSnapshotQuery.create().setIslast(false).setResourceId(1L), new PurgeProfiler());
checkTables("shouldDeleteSnapshots", "snapshots");
}
@@ -130,21 +130,21 @@ public class PurgeDaoTest extends AbstractDaoTestCase {
@Test
public void should_delete_project_and_associated_data() {
setupData("shouldDeleteProject");
- sut.deleteResourceTree(new IdUuidPair(1L, "A"));
+ sut.deleteResourceTree(new IdUuidPair(1L, "A"), new PurgeProfiler());
assertEmptyTables("projects", "snapshots", "action_plans", "issues", "issue_changes", "file_sources");
}
@Test
public void should_delete_old_closed_issues() {
setupData("should_delete_old_closed_issues");
- sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY);
+ sut.purge(newConfigurationWith30Days(), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("should_delete_old_closed_issues", "issues", "issue_changes");
}
@Test
public void should_delete_all_closed_issues() {
setupData("should_delete_all_closed_issues");
- sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 0), PurgeListener.EMPTY);
+ sut.purge(new PurgeConfiguration(new IdUuidPair(1L, "1"), new String[0], 0), PurgeListener.EMPTY, new PurgeProfiler());
checkTables("should_delete_all_closed_issues", "issues", "issue_changes");
}
diff --git a/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java b/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java
index 1aa9d8aebcb..857b58ed48a 100644
--- a/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java
+++ b/sonar-db/src/test/java/org/sonar/db/purge/period/DefaultPeriodCleanerTest.java
@@ -30,9 +30,11 @@ import org.mockito.stubbing.Answer;
import org.sonar.api.utils.System2;
import org.sonar.db.DbSession;
import org.sonar.db.purge.PurgeDao;
+import org.sonar.db.purge.PurgeProfiler;
import org.sonar.db.purge.PurgeSnapshotQuery;
import org.sonar.db.purge.PurgeableSnapshotDto;
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.anyListOf;
import static org.mockito.Mockito.argThat;
import static org.mockito.Mockito.eq;
@@ -52,13 +54,13 @@ public class DefaultPeriodCleanerTest {
Filter filter1 = newLazyFilter();
Filter filter2 = newLazyFilter();
- DefaultPeriodCleaner cleaner = new DefaultPeriodCleaner(dao);
+ DefaultPeriodCleaner cleaner = new DefaultPeriodCleaner(dao, new PurgeProfiler());
cleaner.doClean(123L, Arrays.asList(filter1, filter2), session);
verify(filter1).log();
verify(filter2).log();
- verify(dao, times(2)).deleteSnapshots(argThat(newRootSnapshotQuery()), eq(session));
- verify(dao, times(2)).deleteSnapshots(argThat(newSnapshotIdQuery()), eq(session));
+ verify(dao, times(2)).deleteSnapshots(argThat(newRootSnapshotQuery()), eq(session), any(PurgeProfiler.class));
+ verify(dao, times(2)).deleteSnapshots(argThat(newSnapshotIdQuery()), eq(session), any(PurgeProfiler.class));
}
private BaseMatcher<PurgeSnapshotQuery> newRootSnapshotQuery() {
diff --git a/sonar-db/src/test/java/org/sonar/db/rule/RuleTesting.java b/sonar-db/src/test/java/org/sonar/db/rule/RuleTesting.java
new file mode 100644
index 00000000000..1b744886d6f
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/rule/RuleTesting.java
@@ -0,0 +1,105 @@
+/*
+ * 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.db.rule;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+import org.sonar.db.rule.RuleDto.Format;
+
+/**
+ * Utility class for tests involving rules
+ */
+public class RuleTesting {
+
+ public static final RuleKey XOO_X1 = RuleKey.of("xoo", "x1");
+ public static final RuleKey XOO_X2 = RuleKey.of("xoo", "x2");
+ public static final RuleKey XOO_X3 = RuleKey.of("xoo", "x3");
+
+ private RuleTesting() {
+ // only static helpers
+ }
+
+ public static RuleDto newXooX1() {
+ return newDto(XOO_X1).setLanguage("xoo");
+ }
+
+ public static RuleDto newXooX2() {
+ return newDto(XOO_X2).setLanguage("xoo");
+ }
+
+ public static RuleDto newXooX3() {
+ return newDto(XOO_X3).setLanguage("xoo");
+ }
+
+ /**
+ * Full RuleDto used to feed database with fake data. Tests must not rely on the
+ * field contents declared here. They should override the fields they need to test,
+ * for example:
+ * <pre>
+ * ruleDao.insert(dbSession, RuleTesting.newDto(key).setStatus(RuleStatus.BETA));
+ * </pre>
+ */
+ public static RuleDto newDto(RuleKey ruleKey) {
+ return new RuleDto()
+ .setRuleKey(ruleKey.rule())
+ .setRepositoryKey(ruleKey.repository())
+ .setName("Rule " + ruleKey.rule())
+ .setDescription("Description " + ruleKey.rule())
+ .setDescriptionFormat(Format.HTML)
+ .setStatus(RuleStatus.READY)
+ .setConfigKey("InternalKey" + ruleKey.rule())
+ .setSeverity(Severity.INFO)
+ .setIsTemplate(false)
+ .setTags(ImmutableSet.of("tag1", "tag2"))
+ .setSystemTags(ImmutableSet.of("systag1", "systag2"))
+ .setLanguage("js")
+ .setRemediationFunction("LINEAR")
+ .setDefaultRemediationFunction("LINEAR_OFFSET")
+ .setRemediationCoefficient("1h")
+ .setDefaultRemediationCoefficient("5d")
+ .setRemediationOffset("5min")
+ .setDefaultRemediationOffset("10h")
+ .setEffortToFixDescription(ruleKey.repository() + "." + ruleKey.rule() + ".effortToFix");
+ }
+
+ public static RuleDto newTemplateRule(RuleKey ruleKey) {
+ return newDto(ruleKey)
+ .setIsTemplate(true);
+ }
+
+ public static RuleDto newCustomRule(RuleDto templateRule) {
+ Preconditions.checkNotNull(templateRule.getId(), "The template rule need to be persisted before creating this custom rule.");
+ return newDto(RuleKey.of(templateRule.getRepositoryKey(), templateRule.getRuleKey() + "_" + System.currentTimeMillis()))
+ .setLanguage(templateRule.getLanguage())
+ .setTemplateId(templateRule.getId());
+ }
+
+ public static RuleDto newManualRule(String manualKey) {
+ return new RuleDto().setRuleKey(manualKey)
+ .setName("Name " + manualKey)
+ .setRepositoryKey(RuleKey.MANUAL_REPOSITORY_KEY)
+ .setDescription("Description " + manualKey)
+ .setStatus(RuleStatus.READY);
+ }
+
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/source/FileSourceDaoTest.java b/sonar-db/src/test/java/org/sonar/db/source/FileSourceDaoTest.java
new file mode 100644
index 00000000000..09d7fbcff1b
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/source/FileSourceDaoTest.java
@@ -0,0 +1,175 @@
+/*
+ * 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.db.source;
+
+import com.google.common.base.Function;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Reader;
+import org.apache.commons.io.IOUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.db.AbstractDaoTestCase;
+import org.sonar.db.DbSession;
+import org.sonar.db.source.FileSourceDto.Type;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class FileSourceDaoTest extends AbstractDaoTestCase {
+
+ DbSession session;
+
+ FileSourceDao sut;
+
+ @Before
+ public void setUpTestData() {
+ session = getMyBatis().openSession(false);
+ sut = new FileSourceDao(getMyBatis());
+ }
+
+ @After
+ public void tearDown() {
+ session.close();
+ }
+
+ @Test
+ public void select() {
+ setupData("shared");
+
+ FileSourceDto fileSourceDto = sut.selectSource("FILE1_UUID");
+
+ assertThat(fileSourceDto.getBinaryData()).isNotEmpty();
+ assertThat(fileSourceDto.getDataHash()).isEqualTo("hash");
+ assertThat(fileSourceDto.getProjectUuid()).isEqualTo("PRJ_UUID");
+ assertThat(fileSourceDto.getFileUuid()).isEqualTo("FILE1_UUID");
+ assertThat(fileSourceDto.getCreatedAt()).isEqualTo(1500000000000L);
+ assertThat(fileSourceDto.getUpdatedAt()).isEqualTo(1500000000000L);
+ assertThat(fileSourceDto.getDataType()).isEqualTo(Type.SOURCE);
+ }
+
+ @Test
+ public void select_line_hashes() {
+ setupData("shared");
+
+ ReaderToStringFunction fn = new ReaderToStringFunction();
+ sut.readLineHashesStream(session, "FILE1_UUID", fn);
+
+ assertThat(fn.result).isEqualTo("ABC\\nDEF\\nGHI");
+ }
+
+ @Test
+ public void no_line_hashes_on_unknown_file() {
+ setupData("shared");
+
+ ReaderToStringFunction fn = new ReaderToStringFunction();
+ sut.readLineHashesStream(session, "unknown", fn);
+
+ assertThat(fn.result).isNull();
+ }
+
+ @Test
+ public void no_line_hashes_when_only_test_data() {
+ setupData("no_line_hashes_when_only_test_data");
+
+ ReaderToStringFunction fn = new ReaderToStringFunction();
+ sut.readLineHashesStream(session, "FILE1_UUID", fn);
+
+ assertThat(fn.result).isNull();
+ }
+
+ @Test
+ public void insert() {
+ setupData("shared");
+
+ sut.insert(new FileSourceDto()
+ .setProjectUuid("PRJ_UUID")
+ .setFileUuid("FILE2_UUID")
+ .setBinaryData("FILE2_BINARY_DATA".getBytes())
+ .setDataHash("FILE2_DATA_HASH")
+ .setLineHashes("LINE1_HASH\\nLINE2_HASH")
+ .setSrcHash("FILE2_HASH")
+ .setDataType(Type.SOURCE)
+ .setCreatedAt(1500000000000L)
+ .setUpdatedAt(1500000000001L));
+
+ checkTable("insert", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at", "data_type");
+ }
+
+ @Test
+ public void update() {
+ setupData("shared");
+
+ sut.update(new FileSourceDto()
+ .setId(101L)
+ .setProjectUuid("PRJ_UUID")
+ .setFileUuid("FILE1_UUID")
+ .setBinaryData("updated data".getBytes())
+ .setDataHash("NEW_DATA_HASH")
+ .setSrcHash("NEW_FILE_HASH")
+ .setLineHashes("NEW_LINE_HASHES")
+ .setDataType(Type.SOURCE)
+ .setUpdatedAt(1500000000002L));
+
+ checkTable("update", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at", "data_type");
+ }
+
+ @Test
+ public void update_date_when_updated_date_is_zero() {
+ setupData("update_date_when_updated_date_is_zero");
+
+ sut.updateDateWhenUpdatedDateIsZero(session, "ABCD", 1500000000002L);
+ session.commit();
+
+ checkTable("update_date_when_updated_date_is_zero", "file_sources", "project_uuid", "file_uuid", "data_hash", "line_hashes", "src_hash", "created_at", "updated_at",
+ "data_type");
+ }
+
+ private static class ReaderToStringFunction implements Function<Reader, String> {
+
+ String result = null;
+
+ @Override
+ public String apply(Reader input) {
+ try {
+ result = IOUtils.toString(input);
+ return IOUtils.toString(input);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private static class InputStreamToStringFunction implements Function<InputStream, String> {
+
+ String result = null;
+
+ @Override
+ public String apply(InputStream input) {
+ try {
+ result = IOUtils.toString(input);
+ return IOUtils.toString(input);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/db/user/UserGroupDaoTest.java b/sonar-db/src/test/java/org/sonar/db/user/UserGroupDaoTest.java
new file mode 100644
index 00000000000..ff1c8cfecef
--- /dev/null
+++ b/sonar-db/src/test/java/org/sonar/db/user/UserGroupDaoTest.java
@@ -0,0 +1,69 @@
+/*
+ * 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.db.user;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.test.DbTests;
+
+@Category(DbTests.class)
+public class UserGroupDaoTest {
+
+ @ClassRule
+ public static DbTester db = new DbTester();
+
+ private UserGroupDao dao;
+ private DbSession session;
+
+ @Before
+ public void before() {
+ db.truncateTables();
+ this.session = db.myBatis().openSession(false);
+ this.dao = new UserGroupDao();
+ }
+
+ @After
+ public void after() {
+ this.session.close();
+ }
+
+ @Test
+ public void insert() {
+ UserGroupDto userGroupDto = new UserGroupDto().setUserId(1L).setGroupId(2L);
+ dao.insert(session, userGroupDto);
+ session.commit();
+
+ db.assertDbUnit(getClass(), "insert-result.xml", "groups_users");
+ }
+
+ @Test
+ public void delete_members_by_group_id() {
+ db.prepareDbUnit(getClass(), "delete_members_by_group_id.xml");
+ dao.deleteMembersByGroupId(session, 1L);
+ session.commit();
+ db.assertDbUnit(getClass(), "delete_members_by_group_id-result.xml", "groups_users");
+ }
+}
diff --git a/sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java b/sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java
deleted file mode 100644
index d4743f578cc..00000000000
--- a/sonar-db/src/test/java/org/sonar/jpa/test/AbstractDbUnitTestCase.java
+++ /dev/null
@@ -1,229 +0,0 @@
-/*
- * 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.jpa.test;
-
-import java.io.InputStream;
-import java.sql.SQLException;
-import org.apache.commons.io.IOUtils;
-import org.apache.ibatis.session.SqlSession;
-import org.dbunit.Assertion;
-import org.dbunit.DataSourceDatabaseTester;
-import org.dbunit.DatabaseUnitException;
-import org.dbunit.IDatabaseTester;
-import org.dbunit.database.DatabaseConfig;
-import org.dbunit.database.IDatabaseConnection;
-import org.dbunit.dataset.CompositeDataSet;
-import org.dbunit.dataset.IDataSet;
-import org.dbunit.dataset.ITable;
-import org.dbunit.dataset.ReplacementDataSet;
-import org.dbunit.dataset.filter.DefaultColumnFilter;
-import org.dbunit.dataset.xml.FlatXmlDataSet;
-import org.dbunit.ext.mssql.InsertIdentityOperation;
-import org.dbunit.operation.DatabaseOperation;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.sonar.db.Database;
-import org.sonar.db.DatabaseCommands;
-import org.sonar.db.H2Database;
-import org.sonar.db.MyBatis;
-import org.sonar.db.deprecated.NullQueue;
-import org.sonar.db.version.DatabaseVersion;
-import org.sonar.db.version.SchemaMigrationMapper;
-
-import static org.junit.Assert.fail;
-
-/**
- * @deprecated this class does not support non-H2 databases
- */
-@Deprecated
-public abstract class AbstractDbUnitTestCase {
- private static Database database;
- private static MyBatis myBatis;
- private static DatabaseCommands databaseCommands;
- private IDatabaseTester databaseTester;
-
- @BeforeClass
- public static void startDatabase() throws SQLException {
- if (database == null) {
- database = new H2Database("sonarHibernate", true);
- database.start();
-
- databaseCommands = DatabaseCommands.forDialect(database.getDialect());
-
- myBatis = new MyBatis(database, new NullQueue());
- myBatis.start();
- try (SqlSession session = myBatis.openSession(false)) {
- session.getMapper(SchemaMigrationMapper.class).insert(String.valueOf(DatabaseVersion.LAST_VERSION));
- session.commit();
- }
- }
- }
-
- @Before
- public void startDbUnit() throws Exception {
- databaseCommands.truncateDatabase(database.getDataSource());
- databaseTester = new DataSourceDatabaseTester(database.getDataSource());
- }
-
- protected MyBatis getMyBatis() {
- return myBatis;
- }
-
- protected Database getDatabase() {
- return database;
- }
-
- protected void setupData(String... testNames) {
- InputStream[] streams = new InputStream[testNames.length];
- try {
- for (int i = 0; i < testNames.length; i++) {
- String className = getClass().getName();
- className = String.format("/%s/%s.xml", className.replace(".", "/"), testNames[i]);
- streams[i] = getClass().getResourceAsStream(className);
- if (streams[i] == null) {
- throw new RuntimeException("Test not found :" + className);
- }
- }
-
- setupData(streams);
- databaseCommands.resetPrimaryKeys(database.getDataSource());
- } catch (SQLException e) {
- throw translateException("Could not setup DBUnit data", e);
- } finally {
- for (InputStream stream : streams) {
- IOUtils.closeQuietly(stream);
- }
- }
- }
-
- private void setupData(InputStream... dataSetStream) {
- IDatabaseConnection connection = null;
- try {
- IDataSet[] dataSets = new IDataSet[dataSetStream.length];
- for (int i = 0; i < dataSetStream.length; i++) {
- dataSets[i] = getData(dataSetStream[i]);
- }
- databaseTester.setDataSet(new CompositeDataSet(dataSets));
-
- connection = createConnection();
-
- new InsertIdentityOperation(DatabaseOperation.INSERT).execute(connection, databaseTester.getDataSet());
- } catch (Exception e) {
- throw translateException("Could not setup DBUnit data", e);
- } finally {
- closeQuietly(connection);
- }
- }
-
- private void closeQuietly(IDatabaseConnection connection) {
- try {
- if (connection != null) {
- connection.close();
- }
- } catch (SQLException ignored) {
-
- }
- }
-
- protected void checkTables(String testName, String... tables) {
- checkTables(testName, new String[0], tables);
- }
-
- protected void checkTables(String testName, String[] excludedColumnNames, String... tables) {
- IDatabaseConnection connection = null;
- try {
- connection = createConnection();
-
- IDataSet dataSet = connection.createDataSet();
- IDataSet expectedDataSet = getExpectedData(testName);
- for (String table : tables) {
- ITable filteredTable = DefaultColumnFilter.excludedColumnsTable(dataSet.getTable(table), excludedColumnNames);
- ITable filteredExpectedTable = DefaultColumnFilter.excludedColumnsTable(expectedDataSet.getTable(table), excludedColumnNames);
- Assertion.assertEquals(filteredExpectedTable, filteredTable);
- }
- } catch (DatabaseUnitException e) {
- fail(e.getMessage());
- } catch (SQLException e) {
- throw translateException("Error while checking results", e);
- } finally {
- closeQuietly(connection);
- }
- }
-
- protected void checkTable(String testName, String table, String... columns) {
- IDatabaseConnection connection = null;
- try {
- connection = createConnection();
-
- IDataSet dataSet = connection.createDataSet();
- IDataSet expectedDataSet = getExpectedData(testName);
- ITable filteredTable = DefaultColumnFilter.includedColumnsTable(dataSet.getTable(table), columns);
- ITable filteredExpectedTable = DefaultColumnFilter.includedColumnsTable(expectedDataSet.getTable(table), columns);
- Assertion.assertEquals(filteredExpectedTable, filteredTable);
-
- } catch (DatabaseUnitException e) {
- fail(e.getMessage());
- } catch (SQLException e) {
- throw translateException("Error while checking results", e);
- } finally {
- closeQuietly(connection);
- }
- }
-
- private IDatabaseConnection createConnection() {
- try {
- IDatabaseConnection connection = databaseTester.getConnection();
- connection.getConfig().setProperty(DatabaseConfig.PROPERTY_DATATYPE_FACTORY, databaseCommands.getDbUnitFactory());
- return connection;
- } catch (Exception e) {
- throw translateException("Error while getting connection", e);
- }
- }
-
- private IDataSet getExpectedData(String testName) {
- String className = getClass().getName();
- className = String.format("/%s/%s-result.xml", className.replace('.', '/'), testName);
-
- InputStream in = getClass().getResourceAsStream(className);
- try {
- return getData(in);
- } finally {
- IOUtils.closeQuietly(in);
- }
- }
-
- private IDataSet getData(InputStream stream) {
- try {
- ReplacementDataSet dataSet = new ReplacementDataSet(new FlatXmlDataSet(stream));
- dataSet.addReplacementObject("[null]", null);
- dataSet.addReplacementObject("[false]", Boolean.FALSE);
- dataSet.addReplacementObject("[true]", Boolean.TRUE);
- return dataSet;
- } catch (Exception e) {
- throw translateException("Could not read the dataset stream", e);
- }
- }
-
- private static RuntimeException translateException(String msg, Exception cause) {
- RuntimeException runtimeException = new RuntimeException(String.format("%s: [%s] %s", msg, cause.getClass().getName(), cause.getMessage()));
- runtimeException.setStackTrace(cause.getStackTrace());
- return runtimeException;
- }
-}
diff --git a/sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml b/sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml
deleted file mode 100644
index 64c38fb55ea..00000000000
--- a/sonar-db/src/test/resources/org/sonar/api/database/configuration/DatabaseConfigurationTest/some-properties.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<dataset>
-
- <properties prop_key="key1" resource_id="[null]" text_value="value1" user_id="[null]"/>
- <properties prop_key="key2" resource_id="[null]" text_value="value2" user_id="[null]"/>
-
-</dataset> \ No newline at end of file
diff --git a/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/feed.xml b/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/feed.xml
new file mode 100644
index 00000000000..e76d538413e
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/feed.xml
@@ -0,0 +1,5 @@
+<dataset>
+ <issues id="10" kee="AB" />
+ <issues id="20" kee="CD" />
+ <issues id="30" kee="EF" />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/schema.sql b/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/schema.sql
new file mode 100644
index 00000000000..333bb0e193e
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/ResultSetIteratorTest/schema.sql
@@ -0,0 +1,4 @@
+CREATE TABLE "ISSUES" (
+ "ID" INTEGER NOT NULL GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1),
+ "KEE" VARCHAR(200) NOT NULL
+);
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml
new file mode 100644
index 00000000000..8b89e7223ec
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/delete.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml
index 871dedcb5e9..871dedcb5e9 100644
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/empty.xml
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/empty.xml
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml
new file mode 100644
index 00000000000..8b89e7223ec
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/insert-result.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml
new file mode 100644
index 00000000000..33e9449d1dd
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/shared.xml
@@ -0,0 +1,7 @@
+<dataset>
+
+ <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
+ <project_links id="2" component_uuid="ABCD" link_type="scm" name="Sources" href="https://github.com/SonarSource/sonar"/>
+ <project_links id="3" component_uuid="BCDE" link_type="homepage" name="Home" href="http://www.struts.org"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml
new file mode 100644
index 00000000000..8b89e7223ec
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update-result.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <project_links id="1" component_uuid="ABCD" link_type="homepage" name="Home" href="http://www.sonarqube.org"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml
new file mode 100644
index 00000000000..6b80fc9d01c
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ComponentLinkDaoTest/update.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <project_links id="1" component_uuid="BCDE" link_type="ci" name="CI" href="github"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/select_project_ids_from_query_and_view_or_sub_view_uuid.xml b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/select_project_ids_from_query_and_view_or_sub_view_uuid.xml
new file mode 100644
index 00000000000..aff69473ce1
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/ResourceIndexerDaoTest/select_project_ids_from_query_and_view_or_sub_view_uuid.xml
@@ -0,0 +1,32 @@
+<dataset>
+
+ <!-- Real projects -->
+ <projects id="1" uuid="ABCD" project_uuid="ABCD" module_uuid_path=".ABCD." copy_resource_id="[null]" name="Project One" qualifier="TRK" scope="PRJ"/>
+ <projects id="2" uuid="BCDE" project_uuid="BCDE" module_uuid_path=".BCDE." copy_resource_id="[null]" name="Project Two" qualifier="TRK" scope="PRJ"/>
+
+ <!-- Copy projects -->
+ <projects id="3" uuid="CDEF" project_uuid="EFGH" module_uuid_path=".EFGH." copy_resource_id="1" name="Copy Project One" qualifier="TRK" scope="FIL"/>
+ <projects id="4" uuid="DEFG" project_uuid="EFGH" module_uuid_path=".EFGH." copy_resource_id="2" name="Copy Project One" qualifier="TRK" scope="FIL"/>
+
+ <!-- View containing all projects -->
+ <projects id="5" uuid="EFGH" project_uuid="EFGH" module_uuid_path=".EFGH." copy_resource_id="[null]" name="All projects" qualifier="VW" scope="PRJ"/>
+
+ <resource_index id="1" kee="project one" resource_id="1" root_project_id="1" position="0" name_size="11" qualifier="TRK"/>
+ <resource_index id="2" kee="roject one" resource_id="1" root_project_id="1" position="1" name_size="11" qualifier="TRK"/>
+ <resource_index id="3" kee="oject one" resource_id="1" root_project_id="1" position="2" name_size="11" qualifier="TRK"/>
+ <resource_index id="4" kee="ject one" resource_id="1" root_project_id="1" position="3" name_size="11" qualifier="TRK"/>
+ <resource_index id="5" kee="ect one" resource_id="1" root_project_id="1" position="4" name_size="11" qualifier="TRK"/>
+ <resource_index id="6" kee="ct one" resource_id="1" root_project_id="1" position="5" name_size="11" qualifier="TRK"/>
+ <resource_index id="7" kee="t one" resource_id="1" root_project_id="1" position="6" name_size="11" qualifier="TRK"/>
+ <resource_index id="8" kee=" one" resource_id="1" root_project_id="1" position="7" name_size="11" qualifier="TRK"/>
+ <resource_index id="9" kee="one" resource_id="1" root_project_id="1" position="8" name_size="11" qualifier="TRK"/>
+ <resource_index id="10" kee="project two" resource_id="2" root_project_id="2" position="0" name_size="11" qualifier="TRK"/>
+ <resource_index id="11" kee="roject two" resource_id="2" root_project_id="2" position="1" name_size="11" qualifier="TRK"/>
+ <resource_index id="12" kee="oject two" resource_id="2" root_project_id="2" position="2" name_size="11" qualifier="TRK"/>
+ <resource_index id="13" kee="ject two" resource_id="2" root_project_id="2" position="3" name_size="11" qualifier="TRK"/>
+ <resource_index id="14" kee="ect two" resource_id="2" root_project_id="2" position="4" name_size="11" qualifier="TRK"/>
+ <resource_index id="15" kee="ct two" resource_id="2" root_project_id="2" position="5" name_size="11" qualifier="TRK"/>
+ <resource_index id="16" kee="t two" resource_id="2" root_project_id="2" position="6" name_size="11" qualifier="TRK"/>
+ <resource_index id="17" kee="two" resource_id="2" root_project_id="2" position="7" name_size="11" qualifier="TRK"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/empty.xml
new file mode 100644
index 00000000000..871dedcb5e9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/empty.xml
@@ -0,0 +1,3 @@
+<dataset>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/insert-result.xml
new file mode 100644
index 00000000000..a138d68b188
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/insert-result.xml
@@ -0,0 +1,13 @@
+<dataset>
+
+ <snapshots id="1" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1500000000001"
+ period2_mode="days2" period2_param="31" period2_date="1500000000002"
+ period3_mode="days3" period3_param="32" period3_date="1500000000003"
+ period4_mode="days4" period4_param="33" period4_date="1500000000004"
+ period5_mode="days5" period5_param="34" period5_date="1500000000005"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1403042400000" build_date="1500000000006"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/modules.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/modules.xml
new file mode 100644
index 00000000000..9ba70bee6f4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/modules.xml
@@ -0,0 +1,90 @@
+<dataset>
+
+ <!-- root project -->
+ <projects id="1" root_id="[null]" scope="PRJ" qualifier="TRK" kee="org.struts:struts" name="Struts"
+ uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path="."
+ description="the description" long_name="Apache Struts"
+ enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="[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="1228222680000" build_date="1228222680000"
+ version="[null]" path=""/>
+ <snapshots id="10" 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="1228136280000" build_date="1228136280000"
+ version="[null]" path=""/>
+
+ <!-- module -->
+ <projects id="2" root_id="1" kee="org.struts:struts-core" name="Struts Core"
+ uuid="EFGH" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD."
+ scope="PRJ" qualifier="BRC" long_name="Struts Core"
+ description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+ <snapshots id="2" project_id="2" parent_snapshot_id="1" root_project_id="1" root_snapshot_id="1"
+ 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="BRC" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path="1."/>
+
+ <!-- sub module -->
+ <projects id="3" root_id="1" kee="org.struts:struts-data" name="Struts Data"
+ uuid="FGHI" project_uuid="ABCD" module_uuid="EFGH" module_uuid_path=".ABCD.EFGH."
+ scope="PRJ" qualifier="BRC" long_name="Struts Data"
+ description="[null]" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" authorization_updated_at="[null]" />
+ <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ 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="BRC" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path="1.2."/>
+
+ <!-- directory -->
+ <projects long_name="org.struts" id="4" scope="DIR" qualifier="DIR" kee="org.struts:struts-core:src/org/struts"
+ uuid="GHIJ" project_uuid="ABCD" module_uuid="FGHI" module_uuid_path=".ABCD.EFGH.FGHI."
+ name="src/org/struts" root_id="3"
+ description="[null]"
+ enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="src/org/struts" authorization_updated_at="[null]" />
+ <snapshots id="4" project_id="4" parent_snapshot_id="3" root_project_id="1" root_snapshot_id="1"
+ 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="DIR" qualifier="PAC" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path="1.2.3."/>
+
+ <!-- file -->
+ <projects long_name="org.struts.RequestContext" id="5" scope="FIL" qualifier="FIL" kee="org.struts:struts-core:src/org/struts/RequestContext.java"
+ uuid="HIJK" project_uuid="ABCD" module_uuid="FGHI" module_uuid_path=".ABCD.EFGH.FGHI."
+ name="RequestContext.java" root_id="3"
+ description="[null]"
+ enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]" path="src/org/struts/RequestContext.java" authorization_updated_at="[null]" />
+
+ <snapshots id="5" project_id="5" parent_snapshot_id="4" root_project_id="1" root_snapshot_id="1"
+ 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="FIL" qualifier="CLA" created_at="1228222680000" build_date="1228222680000"
+ version="[null]" path="1.2.3.4."/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_previous_version_snapshots.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_previous_version_snapshots.xml
new file mode 100644
index 00000000000..3f56960cd92
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_previous_version_snapshots.xml
@@ -0,0 +1,48 @@
+<dataset>
+
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD"
+ description="[null]"
+ enabled="[true]" language="java" copy_resource_id="[null]" person_id="[null]"/>
+
+ <!-- version 1.0 -->
+ <snapshots id="1000" 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]"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225630680000" build_date="1225630680000" version="1.0" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- version 1.1 -->
+ <snapshots id="1001" 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]"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225803480000" build_date="1225803480000" version="1.1" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- version 1.2-SNAPSHOT -->
+ <snapshots id="1002" 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]"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225976280000" build_date="1225976280000" version="1.2-SNAPSHOT" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- version 1.2-SNAPSHOT, current analysis -->
+ <snapshots id="1003" 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]"
+ project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1226235480000" build_date="1226235480000" version="1.2-SNAPSHOT" path=""
+ status="U" islast="[true]" depth="0"/>
+
+ <events id="1" name="1.0" component_uuid="ABCD" snapshot_id="1000" category="Version" event_date="1225630680000" created_at="1225630680000" description="" event_data="[null]"/>
+ <events id="2" name="Foo" component_uuid="ABCD" snapshot_id="1000" category="Other" event_date="1225717080000" created_at="1225717080000" description="" event_data="[null]"/>
+ <events id="3" name="1.1" component_uuid="ABCD" snapshot_id="1001" category="Version" event_date="1225803480000" created_at="1225803480000" description="" event_data="[null]"/>
+ <events id="4" name="Bar" component_uuid="ABCD" snapshot_id="1001" category="Other" event_date="1225889880000" created_at="1225889880000" description="" event_data="[null]"/>
+ <events id="5" name="Uhh" component_uuid="ABCD" snapshot_id="1002" category="Other" event_date="1226062680000" created_at="1226062680000" description="" event_data="[null]"/>
+ <events id="6" name="1.2-SNAPSHOT" component_uuid="ABCD" snapshot_id="1003" category="Version" event_date="1226235480000" created_at="1226235480000" description=""
+ event_data="[null]"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_snapshots_by_query.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_snapshots_by_query.xml
new file mode 100644
index 00000000000..1f32010f385
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/select_snapshots_by_query.xml
@@ -0,0 +1,64 @@
+<dataset>
+
+ <!-- PROJECT_ID = 1 -->
+ <snapshots id="1" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="PRJ" qualifier="PAC" created_at="1228172400001" build_date="1317247200000"
+ version="2.0-SNAPSHOT" path="1.2."/>
+ <snapshots id="2" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400002" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+ <snapshots id="3" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400003" build_date="1317247200000"
+ version="2.2-SNAPSHOT" path="1.2."/>
+
+ <!-- PROJECT_ID = 2 -->
+ <snapshots id="4" project_id="2" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+ <!-- Unprocessed snapshot -->
+ <snapshots id="5" project_id="2" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="U" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+ <!-- PROJECT_ID = 3 - no last snapshot -->
+ <snapshots id="6" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/shared.xml
new file mode 100644
index 00000000000..a52b271da32
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/shared.xml
@@ -0,0 +1,13 @@
+<dataset>
+
+ <snapshots id="3" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/snapshots.xml b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/snapshots.xml
new file mode 100644
index 00000000000..4c18e257396
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/component/SnapshotDaoTest/snapshots.xml
@@ -0,0 +1,65 @@
+<dataset>
+
+ <!-- PROJECT_ID = 1 -->
+ <snapshots id="1" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="PRJ" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+ <snapshots id="2" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+ <snapshots id="3" project_id="1" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+
+ <!-- PROJECT_ID = 2 -->
+ <snapshots id="4" project_id="2" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+ <!-- PROJECT_ID = 3 - no last snapshot -->
+ <snapshots id="5" project_id="3" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="3"
+ status="P" islast="[false]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="DIR" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+
+ <!-- Child of snapshot id=1 -->
+ <snapshots id="6" project_id="55" parent_snapshot_id="2" root_project_id="1" root_snapshot_id="1"
+ status="P" islast="[true]" purge_status="1"
+ period1_mode="days1" period1_param="30" period1_date="1316815200000"
+ period2_mode="days2" period2_param="31" period2_date="1316901600000"
+ period3_mode="days3" period3_param="32" period3_date="1316988000000"
+ period4_mode="days4" period4_param="33" period4_date="1317074400000"
+ period5_mode="days5" period5_param="34" period5_date="1317160800000"
+ depth="1" scope="PRJ" qualifier="PAC" created_at="1228172400000" build_date="1317247200000"
+ version="2.1-SNAPSHOT" path="1.2."/>
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/any-analysis-reports.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/any-analysis-reports.xml
new file mode 100644
index 00000000000..dba17d047a4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/any-analysis-reports.xml
@@ -0,0 +1,26 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ uuid="REPORT_1"
+ project_key="123456789-987654321"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411509600000"
+ />
+ <analysis_reports
+ id="2"
+ uuid="REPORT_2"
+ project_key="123456789-987654321"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="3"
+ uuid="REPORT_3"
+ project_key="123456789-987654321"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml
new file mode 100644
index 00000000000..ae28befd603
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/book_available_report_analysis_while_having_one_working_on_another_project.xml
@@ -0,0 +1,18 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="123456789-987654321"
+ uuid="REPORT_1"
+ report_status="PENDING"
+ created_at="1411509600000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="987654321-123456789"
+ uuid="REPORT_2"
+ report_status="WORKING"
+ created_at="1411423200000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/empty.xml
new file mode 100644
index 00000000000..871dedcb5e9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/empty.xml
@@ -0,0 +1,3 @@
+<dataset>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/insert-result.xml
new file mode 100644
index 00000000000..d25e3641ce9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/insert-result.xml
@@ -0,0 +1,24 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="ProjectKey1"
+ project_name="Project 1"
+ uuid="UUID_1"
+ report_status="PENDING"
+ started_at="[null]"
+ finished_at="[null]"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="ProjectKey2"
+ project_name="Project 2"
+ uuid="UUID_2"
+ report_status="PENDING"
+ started_at="[null]"
+ finished_at="[null]"
+ created_at="1500000000000"
+ updated_at="1500000000000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/one_analysis_report.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/one_analysis_report.xml
new file mode 100644
index 00000000000..c38ac125e00
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/one_analysis_report.xml
@@ -0,0 +1,12 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="123456789-987654321"
+ uuid="REPORT_1"
+ report_status="WORKING"
+ created_at="1500000000001"
+ updated_at="1500000000002"
+ started_at="1500000000003"
+ finished_at="1500000000004"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml
new file mode 100644
index 00000000000..82f93e9fec5
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_null_if_no_pending_reports.xml
@@ -0,0 +1,27 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="111111111-987654321"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411682400000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="123456789-987654321"
+ uuid="UUID_2"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411682400000"
+ />
+ <!-- not select as the previous report which is working is on the same project -->
+ <analysis_reports
+ id="3"
+ project_key="123456789-987654321"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411596000000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_oldest_pending.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_oldest_pending.xml
new file mode 100644
index 00000000000..972fde88fd7
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/pop_oldest_pending.xml
@@ -0,0 +1,37 @@
+<dataset>
+ <!-- WORKING -->
+ <analysis_reports
+ id="1"
+ project_key="P1"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411682400000"
+ />
+
+ <!-- PENDING on P1, which is already being WORKING-->
+ <analysis_reports
+ id="2"
+ project_key="P1"
+ uuid="UUID_2"
+ report_status="PENDING"
+ created_at="1411509600000"
+ updated_at="1411682400000"
+ />
+ <analysis_reports
+ id="3"
+ project_key="P2"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411596000000"
+ updated_at="1411682400000"
+ />
+ <analysis_reports
+ id="4"
+ project_key="P2"
+ uuid="UUID_4"
+ report_status="PENDING"
+ created_at="1420066800000"
+ updated_at="1420066800000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/select.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/select.xml
new file mode 100644
index 00000000000..de9d5b9f330
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/select.xml
@@ -0,0 +1,29 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="123456789-987654321"
+ project_name="Project 1"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="987654321-123456789"
+ project_name="Project 2"
+ uuid="UUID_2"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="3"
+ project_key="987654321-123456789"
+ project_name="Project 2"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/three_analysis_reports.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/three_analysis_reports.xml
new file mode 100644
index 00000000000..c1e3284f108
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/three_analysis_reports.xml
@@ -0,0 +1,26 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="123456789-987654321"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="2"
+ project_key="987654321-123456789"
+ uuid="UUID_2"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411596000000"
+ />
+ <analysis_reports
+ id="3"
+ project_key="987654321-123456789"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1411682400000"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/truncate-result.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/truncate-result.xml
new file mode 100644
index 00000000000..e573e0c5b06
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/truncate-result.xml
@@ -0,0 +1,3 @@
+<dataset>
+ <analysis_reports/>
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending-result.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending-result.xml
new file mode 100644
index 00000000000..16fb8dc0895
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending-result.xml
@@ -0,0 +1,36 @@
+<dataset>
+ <!-- all rows are PENDING, updated_at is now, started_at is null -->
+ <analysis_reports
+ id="1"
+ project_key="P1"
+ project_name="Project1"
+ uuid="UUID_1"
+ report_status="PENDING"
+ created_at="1411509600000"
+ updated_at="1500000000000"
+ started_at="[null]"
+ finished_at="[null]"
+ />
+ <analysis_reports
+ id="2"
+ project_key="P2"
+ project_name="Project2"
+ uuid="UUID_2"
+ report_status="PENDING"
+ created_at="1411596000000"
+ updated_at="1500000000000"
+ started_at="[null]"
+ finished_at="[null]"
+ />
+ <analysis_reports
+ id="3"
+ project_key="P1"
+ project_name="Project1"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1500000000000"
+ started_at="[null]"
+ finished_at="[null]"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending.xml b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending.xml
new file mode 100644
index 00000000000..a630cb4ec4b
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/update-all-to-status-pending.xml
@@ -0,0 +1,35 @@
+<dataset>
+ <analysis_reports
+ id="1"
+ project_key="P1"
+ project_name="Project1"
+ uuid="UUID_1"
+ report_status="WORKING"
+ created_at="1411509600000"
+ updated_at="1411509600000"
+ started_at="1411509600000"
+ finished_at="[null]"
+ />
+ <analysis_reports
+ id="2"
+ project_key="P2"
+ project_name="Project2"
+ uuid="UUID_2"
+ report_status="WORKING"
+ created_at="1411596000000"
+ updated_at="1411596000000"
+ started_at="1411509600000"
+ finished_at="[null]"
+ />
+ <analysis_reports
+ id="3"
+ project_key="P1"
+ project_name="Project1"
+ uuid="UUID_3"
+ report_status="PENDING"
+ created_at="1411682400000"
+ updated_at="1411682400000"
+ started_at="[null]"
+ finished_at="[null]"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/zip.zip b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/zip.zip
new file mode 100644
index 00000000000..a540bc5b5ca
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/compute/AnalysisReportDaoTest/zip.zip
Binary files differ
diff --git a/sonar-db/src/test/resources/org/sonar/db/dashboard/WidgetDaoTest/before.xml b/sonar-db/src/test/resources/org/sonar/db/dashboard/WidgetDaoTest/before.xml
new file mode 100644
index 00000000000..a942341e3d4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/dashboard/WidgetDaoTest/before.xml
@@ -0,0 +1,18 @@
+<dataset>
+
+ <widgets id="1" dashboard_id="1" widget_key="polop" name="Polop" description="Palap"
+ column_index="1" row_index="1" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+ <widgets id="2" dashboard_id="1" widget_key="false_positive_reviews" name="Polop" description="Palap"
+ column_index="1" row_index="2" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+ <widgets id="3" dashboard_id="1" widget_key="my_reviews" name="Polop" description="Palap"
+ column_index="1" row_index="3" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+ <widgets id="4" dashboard_id="1" widget_key="reviews_per_developer" name="Polop" description="Palap"
+ column_index="1" row_index="4" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+ <widgets id="5" dashboard_id="1" widget_key="unresolved_issues_statuses" name="Polop" description="Palap"
+ column_index="1" row_index="5" configured="[true]" created_at="[null]" updated_at="[null]" resource_id="[null]"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/delete.xml b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/delete.xml
new file mode 100644
index 00000000000..c22a68ed8e0
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/delete.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <events id="1" name="1.0" category="Version" description="Version 1.0" event_data="some data" event_date="1225630680000"
+ component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/empty.xml
new file mode 100644
index 00000000000..871dedcb5e9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/empty.xml
@@ -0,0 +1,3 @@
+<dataset>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/insert-result.xml
new file mode 100644
index 00000000000..27a2a24e080
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/insert-result.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <events id="1" name="1.0" category="Version" description="Version 1.0" event_data="some data" event_date="1413407091086"
+ component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/shared.xml
new file mode 100644
index 00000000000..0002deec3c2
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/event/EventDaoTest/shared.xml
@@ -0,0 +1,13 @@
+<dataset>
+
+ <events id="1" name="1.0" category="Version" description="Version 1.0" event_data="some data" event_date="1413407091086"
+ component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+ <events id="2" name="Red (was Orange)" category="Alert" description="Critical issues variation > 0 since previous version (1.0 - 2015 Feb 09), Open issues > 0"
+ event_data="[null]" event_date="1413407091086" component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+ <events id="3" name="Changes in 'Default' (Java)" category="Profile" description="Version 1.0" event_data="from=2014-10-12T08:36:25+0000;key=java-default;to=2014-10-12T10:36:25+0000"
+ event_date="1413407091086" component_uuid="ABCD" snapshot_id="1000" created_at="1225630680000" />
+
+ <events id="4" name="1.0" category="Version" description="Version 1.0" event_data="some data" event_date="1413407091086"
+ component_uuid="BCDE" snapshot_id="1000" created_at="1225630680000" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_by_action_plan.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_by_action_plan.xml
new file mode 100644
index 00000000000..a052d421f66
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/find_by_action_plan.xml
@@ -0,0 +1,29 @@
+<dataset>
+
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="CDEF"
+ project_uuid="ABCD"
+ 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"
+ action_plan_key="AP-1"
+ author_login="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="1366063200000"
+ issue_update_date="1366063200000"
+ issue_close_date="1366063200000"
+ created_at="1400000000000"
+ updated_at="1400000000000"
+ />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/get_by_key.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/get_by_key.xml
new file mode 100644
index 00000000000..154a7a67883
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/get_by_key.xml
@@ -0,0 +1,28 @@
+<dataset>
+
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="CDEF"
+ project_uuid="ABCD"
+ 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="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ issue_creation_date="1366063200000"
+ issue_update_date="1366063200000"
+ issue_close_date="1366063200000"
+ created_at="1400000000000"
+ updated_at="1450000000000"
+ />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/insert-result.xml
new file mode 100644
index 00000000000..fc1543cb2b9
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/insert-result.xml
@@ -0,0 +1,29 @@
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="component-uuid"
+ project_uuid="project-uuid"
+ rule_id="200"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="the message"
+ line="500"
+ effort_to_fix="3.14"
+ technical_debt="10"
+ status="RESOLVED"
+ resolution="FIXED"
+ checksum="123456789"
+ reporter="emmerik"
+ author_login="morgan"
+ assignee="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ tags="[null]"
+ issue_creation_date="1500000000000"
+ issue_update_date="1500000000001"
+ issue_close_date="1500000000002"
+ created_at="1400000000000"
+ updated_at="1450000000000"
+ action_plan_key="current_sprint"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update-result.xml
new file mode 100644
index 00000000000..d5959c63659
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update-result.xml
@@ -0,0 +1,29 @@
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="123"
+ project_uuid="101"
+ rule_id="200"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="the message"
+ line="500"
+ effort_to_fix="3.14"
+ technical_debt="10"
+ status="RESOLVED"
+ resolution="FIXED"
+ checksum="123456789"
+ reporter="emmerik"
+ author_login="morgan"
+ assignee="karadoc"
+ issue_attributes="JIRA=FOO-1234"
+ tags="[null]"
+ issue_creation_date="1368828000000"
+ issue_update_date="1368914400000"
+ issue_close_date="1369000800000"
+ created_at="1400000000000"
+ updated_at="1450000000000"
+ action_plan_key="current_sprint"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update.xml b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update.xml
new file mode 100644
index 00000000000..9c41f1922cc
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/issue/IssueDaoTest/update.xml
@@ -0,0 +1,28 @@
+<dataset>
+ <issues
+ id="100"
+ kee="ABCDE"
+ component_uuid="123"
+ project_uuid="100"
+ rule_id="200"
+ severity="INFO"
+ manual_severity="[false]"
+ message="old"
+ line="[null]"
+ effort_to_fix="[null]"
+ technical_debt="[null]"
+ status="OPEN"
+ resolution="[null]"
+ checksum="[null]"
+ reporter="[null]"
+ author_login="[null]"
+ assignee="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="[null]"
+ issue_update_date="[null]"
+ issue_close_date="[null]"
+ created_at="1400000000000"
+ updated_at="1400000000000"
+ action_plan_key="[null]"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/empty.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/empty.xml
new file mode 100644
index 00000000000..dda18829567
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/empty.xml
@@ -0,0 +1,3 @@
+<dataset>
+ <project_measures/>
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml
new file mode 100644
index 00000000000..26c55c5d3c4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/insert-result.xml
@@ -0,0 +1,27 @@
+<dataset>
+ <project_measures
+ id="1"
+ snapshot_id="2"
+ metric_id="3"
+ characteristic_id="4"
+ rule_id="5"
+ project_id="6"
+ person_id="23"
+ value="2.0"
+ text_value="measure-value"
+ tendency="[null]"
+ rule_priority="[null]"
+ measure_date="[null]"
+ measure_data="[null]"
+ variation_value_1="1.0"
+ variation_value_2="2.0"
+ variation_value_3="3.0"
+ variation_value_4="4.0"
+ variation_value_5="5.0"
+ alert_status="alert"
+ alert_text="alert-text"
+ url="[null]"
+ description="measure-description"
+ rules_category_id="[null]"
+ />
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures.xml
new file mode 100644
index 00000000000..1a9eaecf522
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures.xml
@@ -0,0 +1,59 @@
+<dataset>
+
+ <metrics id="1" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" enabled="[true]"/>
+
+ <metrics id="2" name="coverage" VAL_TYPE="INT" enabled="[true]"/>
+
+
+ <rules tags="[null]" system_tags="[null]" id="30" name="Check Header" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.header.HeaderCheck"
+ plugin_config_key="Checker/Treewalker/HeaderCheck" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <rules tags="[null]" system_tags="[null]" id="31" name="Equals Avoid Null" plugin_rule_key="com.puppycrawl.tools.checkstyle.checks.coding.EqualsAvoidNullCheck"
+ plugin_config_key="Checker/TreeWalker/EqualsAvoidNull" plugin_name="checkstyle" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <!-- project -->
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+ <!-- package -->
+ <projects long_name="[null]" id="2" scope="DIR" qualifier="PAC" kee="project:org.foo" name="org.foo"
+ root_id="1" uuid="BCDE" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+ <!-- file -->
+ <projects long_name="org.foo.Bar" id="3" scope="FIL" qualifier="CLA" kee="project:org.foo.Bar"
+ name="Bar" root_id="[null]" uuid="CDEF" project_uuid="ABCD" module_uuid="ABCD" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+
+ <!-- snapshots -->
+ <snapshots id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="[false]" depth="0"/>
+ <snapshots id="1001" project_id="2" parent_snapshot_id="1000" root_project_id="1" root_snapshot_id="1000"
+ scope="DIR" qualifier="PAC" created_at="1225544280000" build_date="1225544280000" version="[null]" path="1000."
+ status="P" islast="[false]" depth="1"/>
+ <snapshots id="1002" project_id="3" parent_snapshot_id="1001" root_project_id="1" root_snapshot_id="1000"
+ scope="FIL" qualifier="CLA" created_at="1225544280000" build_date="1225544280000" version="[null]" path="1000.1001."
+ status="P" islast="[false]" depth="2"/>
+
+
+ <!-- project measures -->
+ <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="2" VALUE="80" METRIC_ID="2" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <!-- package measures -->
+ <project_measures id="3" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1001" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="4" VALUE="70" METRIC_ID="2" SNAPSHOT_ID="1001" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <!-- file measures -->
+ <project_measures id="5" VALUE="5" METRIC_ID="1" SNAPSHOT_ID="1002" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="6" VALUE="60" METRIC_ID="2" SNAPSHOT_ID="1002" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_characteristic_id.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_characteristic_id.xml
new file mode 100644
index 00000000000..7e06f10c94c
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_characteristic_id.xml
@@ -0,0 +1,28 @@
+<dataset>
+
+ <metrics id="1" name="sqale_index" VAL_TYPE="WORK_DUR" DESCRIPTION="[null]" short_name="" enabled="[true]"/>
+
+ <!-- Root characteristic -->
+ <characteristics id="10" kee="PORTABILITY" name="Portability" parent_id="[null]" characteristic_order="1" enabled="[true]" created_at="2013-11-20" updated_at="2013-11-22"/>
+
+ <!-- Characteristic -->
+ <characteristics id="11" kee="COMPILER_RELATED_PORTABILITY" name="Compiler related portability" parent_id="10" characteristic_order="[null]" enabled="[true]"
+ created_at="2013-11-20" updated_at="2013-11-22"/>
+
+ <!-- project -->
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD." enabled="[true]"/>
+
+ <!-- snapshots -->
+ <snapshots id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- project measures -->
+ <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="[null]"/>
+
+ <project_measures id="2" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="10"/>
+
+ <project_measures id="3" VALUE="40" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="11"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml
new file mode 100644
index 00000000000..47a1c6933e4
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_person_id.xml
@@ -0,0 +1,22 @@
+<dataset>
+
+ <metrics delete_historical_data="[null]" id="1" name="sqale_index" VAL_TYPE="INT" DESCRIPTION="[null]" enabled="[true]"/>
+
+ <!-- project -->
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+ <!-- snapshots -->
+ <snapshots id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- project measures -->
+ <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" person_id="[null]"/>
+
+ <project_measures id="2" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" person_id="20"/>
+
+ <project_measures id="3" VALUE="40" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" person_id="21"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_rule_id.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_rule_id.xml
new file mode 100644
index 00000000000..b6ccf49fca2
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/past_measures_with_rule_id.xml
@@ -0,0 +1,32 @@
+<dataset>
+
+ <metrics delete_historical_data="[null]" id="1" name="minor_violations" VAL_TYPE="INT" DESCRIPTION="[null]" enabled="[true]"/>
+
+ <rules tags="[null]" system_tags="[null]" id="30" name="Classes that override clone should be Cloneable and call super.clone()"
+ plugin_rule_key="S1182"
+ plugin_config_key="S1182" plugin_name="squid" description="[null]" priority="4" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <rules tags="[null]" system_tags="[null]" id="31" name="Overriding methods should do more than simply call the same method in the super class"
+ plugin_rule_key="S1185"
+ plugin_config_key="S1185" plugin_name="squid" description="[null]" priority="1" status="READY"
+ is_template="[false]" template_id="[null]"/>
+
+ <!-- project -->
+ <projects long_name="[null]" id="1" scope="PRJ" qualifier="TRK" kee="project" name="project"
+ root_id="[null]" uuid="ABCD" project_uuid="ABCD" module_uuid="[null]" module_uuid_path=".ABCD."
+ enabled="[true]"/>
+
+ <!-- snapshots -->
+ <snapshots id="1000" project_id="1" parent_snapshot_id="[null]" root_project_id="1" root_snapshot_id="[null]"
+ scope="PRJ" qualifier="TRK" created_at="1225544280000" build_date="1225544280000" version="[null]" path=""
+ status="P" islast="[false]" depth="0"/>
+
+ <!-- project measures -->
+ <project_measures id="1" VALUE="60" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="[null]" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="2" VALUE="20" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="30" characteristic_id="[null]" person_id="[null]"/>
+
+ <project_measures id="3" VALUE="40" METRIC_ID="1" SNAPSHOT_ID="1000" RULE_ID="31" characteristic_id="[null]" person_id="[null]"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/shared.xml
new file mode 100644
index 00000000000..c27311c8d38
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/measure/MeasureDaoTest/shared.xml
@@ -0,0 +1,21 @@
+<dataset>
+
+ <metrics id="10" name="authors_by_line"/>
+ <metrics id="11" name="coverage_line_hits_data"/>
+ <metrics id="12" name="ncloc"/>
+
+ <projects id="1" kee="org.struts:struts-core:src/org/struts/RequestContext.java" enabled="[true]"/>
+
+ <snapshots id="5" project_id="1" islast="[true]" />
+
+ <project_measures id="20" snapshot_id="5" metric_id="10" value="[null]" text_value="0123456789012345678901234567890123456789" measure_data="[null]"
+ variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
+ alert_status="[null]" alert_text="[null]" />
+ <project_measures id="21" snapshot_id="5" metric_id="11" value="[null]" text_value="36=1;37=1;38=1;39=1;43=1;48=1;53=1" measure_data="[null]"
+ variation_value_1="[null]" variation_value_2="[null]" variation_value_3="[null]" variation_value_4="[null]" variation_value_5="[null]"
+ alert_status="[null]" alert_text="[null]" />
+ <project_measures id="22" snapshot_id="5" metric_id="12" value="10" text_value="[null]" measure_data="[null]"
+ variation_value_1="1" variation_value_2="2" variation_value_3="3" variation_value_4="4" variation_value_5="-5"
+ alert_status="OK" alert_text="Green"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml
deleted file mode 100644
index 2283bba7d52..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete-result.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<dataset>
-
- <!--<active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2" inheritance="INHERITED"-->
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml
deleted file mode 100644
index 617cd7e08b0..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_profile-result.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <!--<active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0" inheritance="[null]"-->
-
- <!--<active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" inheritance="[null]"-->
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml
deleted file mode 100644
index a06288e57b6..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_from_rule-result.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <!--<active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1" inheritance="[null]"/>-->
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml
deleted file mode 100644
index 900eb2c2874..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameter-result.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <!--<active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>-->
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml
deleted file mode 100644
index b8aba08833d..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters-result.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <!--<active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>-->
- <!--<active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>-->
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml
deleted file mode 100644
index d1bbff5912e..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id-result.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <!-- Parent of Active rule 1 -->
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <!--<active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>-->
- <!--<active_rule_parameters id="4" active_rule_id="3" rules_parameter_id="2" rules_parameter_key="format" value="text"/>-->
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml
deleted file mode 100644
index 47c6ceeac24..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/delete_parameters_from_profile_id.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <!-- Parent of Active rule 1 -->
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
- <active_rule_parameters id="4" active_rule_id="3" rules_parameter_id="2" rules_parameter_key="format" value="text"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml
deleted file mode 100644
index 574cbabdd56..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert-result.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml
deleted file mode 100644
index ed2e17d48d3..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/insert_parameter-result.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-<dataset>
-
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml
deleted file mode 100644
index b6d5461c10d..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/shared.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="2"
- inheritance="INHERITED"/>
-
- <!-- Parent of Active rule 1 -->
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
- <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
-
- <rules_profiles id="1" name="Child" language="java" parent_kee="parent" kee="child" is_default="[false]"/>
-
- <rules_profiles id="2" name="Parent" language="java" parent_kee="[null]" kee="parent" is_default="[false]"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml
deleted file mode 100644
index 30111d636a7..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update-result.xml
+++ /dev/null
@@ -1,12 +0,0 @@
-<dataset>
-
- <active_rules created_at="[null]" updated_at="[null]" id="1" profile_id="1" rule_id="10" failure_level="4"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="2" profile_id="2" rule_id="10" failure_level="0"
- inheritance="[null]"/>
-
- <active_rules created_at="[null]" updated_at="[null]" id="3" profile_id="2" rule_id="11" failure_level="1"
- inheritance="[null]"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml b/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml
deleted file mode 100644
index 289da2f39f2..00000000000
--- a/sonar-db/src/test/resources/org/sonar/db/qualityprofile/ActiveRuleDaoTest/update_parameter-result.xml
+++ /dev/null
@@ -1,8 +0,0 @@
-<dataset>
-
- <active_rule_parameters id="1" active_rule_id="2" rules_parameter_id="3" rules_parameter_key="newMax" value="30"/>
- <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
-
- <active_rule_parameters id="3" active_rule_id="2" rules_parameter_id="1" rules_parameter_key="max" value="15"/>
-
-</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/insert-result.xml
new file mode 100644
index 00000000000..4f347782dca
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/insert-result.xml
@@ -0,0 +1,17 @@
+<dataset>
+
+ <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash"
+ line_hashes="ABC\nDEF\nGHI"
+ src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000" data_type="SOURCE" />
+
+
+ <file_sources id="102" project_uuid="PRJ_UUID" file_uuid="FILE2_UUID"
+ binary_data="[ignore]"
+ data_hash="FILE2_DATA_HASH"
+ line_hashes="LINE1_HASH\nLINE2_HASH"
+ src_hash="FILE2_HASH"
+ created_at="1500000000000" updated_at="1500000000001" data_type="SOURCE" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/no_line_hashes_when_only_test_data.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/no_line_hashes_when_only_test_data.xml
new file mode 100644
index 00000000000..010394a156e
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/no_line_hashes_when_only_test_data.xml
@@ -0,0 +1,9 @@
+<dataset>
+
+ <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="[null]"
+ line_hashes="[null]"
+ src_hash="[null]"
+ created_at="1500000000000" updated_at="1500000000000" data_type="TEST" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/shared.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/shared.xml
new file mode 100644
index 00000000000..5187ca217af
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/shared.xml
@@ -0,0 +1,9 @@
+<dataset>
+
+ <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash"
+ line_hashes="ABC\nDEF\nGHI"
+ src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000" data_type="SOURCE" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update-result.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update-result.xml
new file mode 100644
index 00000000000..8dbe32d946d
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update-result.xml
@@ -0,0 +1,11 @@
+<dataset>
+
+ <file_sources id="101" project_uuid="PRJ_UUID" file_uuid="FILE1_UUID"
+ binary_data="[ignore]"
+ data_hash="NEW_DATA_HASH"
+ line_hashes="NEW_LINE_HASHES"
+ src_hash="NEW_FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000002" data_type="SOURCE" />
+
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml
new file mode 100644
index 00000000000..1ba1fe63a55
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero-result.xml
@@ -0,0 +1,18 @@
+<dataset>
+
+ <!-- Updated -->
+ <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000002" data_type="SOURCE" />
+
+ <!-- Not updated because updated_at is not null -->
+ <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000" data_type="SOURCE" />
+
+ <!-- Not updated because on another project -->
+ <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0" data_type="SOURCE" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml
new file mode 100644
index 00000000000..77a1f85b06a
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/source/FileSourceDaoTest/update_date_when_updated_date_is_zero.xml
@@ -0,0 +1,16 @@
+<dataset>
+
+ <!-- Only this source should be updated -->
+ <file_sources id="101" project_uuid="ABCD" file_uuid="FILE1_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0" data_type="SOURCE" />
+
+ <file_sources id="102" project_uuid="ABCD" file_uuid="FILE2_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="1500000000000" data_type="SOURCE" />
+
+ <file_sources id="103" project_uuid="BCDE" file_uuid="FILE3_UUID"
+ binary_data="abcde" data_hash="hash" line_hashes="ABC\nDEF\nGHI" src_hash="FILE_HASH"
+ created_at="1500000000000" updated_at="0" data_type="SOURCE" />
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id-result.xml
new file mode 100644
index 00000000000..edac414e636
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id-result.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <groups_users user_id="1" group_id="2"/>
+ <groups_users user_id="2" group_id="2"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id.xml
new file mode 100644
index 00000000000..2430e53dd8e
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/delete_members_by_group_id.xml
@@ -0,0 +1,8 @@
+<dataset>
+
+ <groups_users user_id="1" group_id="1"/>
+ <groups_users user_id="2" group_id="1"/>
+ <groups_users user_id="1" group_id="2"/>
+ <groups_users user_id="2" group_id="2"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/insert-result.xml b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/insert-result.xml
new file mode 100644
index 00000000000..2e5bb1ada57
--- /dev/null
+++ b/sonar-db/src/test/resources/org/sonar/db/user/UserGroupDaoTest/insert-result.xml
@@ -0,0 +1,5 @@
+<dataset>
+
+ <groups_users user_id="1" group_id="2"/>
+
+</dataset>
diff --git a/sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml b/sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml
deleted file mode 100644
index aeb851beb8e..00000000000
--- a/sonar-db/src/test/resources/org/sonar/jpa/dao/ProfilesDaoTest/shouldGetProfiles.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<dataset>
-
- <rules_profiles id="1" name="profile one" language="java" is_default="[false]"/>
- <rules_profiles id="2" name="profile two" language="java" is_default="[false]"/>
- <rules_profiles id="3" name="profile three" language="plsql" is_default="[false]"/>
-
-</dataset> \ No newline at end of file