001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 004 * mailto:contact AT sonarsource DOT com 005 * 006 * Sonar is free software; you can redistribute it and/or 007 * modify it under the terms of the GNU Lesser General Public 008 * License as published by the Free Software Foundation; either 009 * version 3 of the License, or (at your option) any later version. 010 * 011 * Sonar is distributed in the hope that it will be useful, 012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 014 * Lesser General Public License for more details. 015 * 016 * You should have received a copy of the GNU Lesser General Public 017 * License along with Sonar; if not, write to the Free Software 018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 019 */ 020 package org.sonar.api.batch; 021 022 import org.sonar.api.database.DatabaseSession; 023 import org.sonar.api.database.model.*; 024 025 import java.util.List; 026 import javax.persistence.Query; 027 028 /** 029 * @since 1.10 030 */ 031 public abstract class AbstractPurge implements Purge { 032 033 private static final int MAX_IN_ELEMENTS = 950; 034 035 private int sqlInPageSize = MAX_IN_ELEMENTS; 036 private DatabaseSession session; 037 038 public AbstractPurge(DatabaseSession session) { 039 this.session = session; 040 } 041 042 protected DatabaseSession getSession() { 043 return session; 044 } 045 046 /** 047 * Delete SNAPSHOTS and all dependent tables (MEASURES, ...) 048 */ 049 protected void deleteSnapshotData(List<Integer> snapshotIds) { 050 deleteMeasuresBySnapshotId(snapshotIds); 051 deleteSources(snapshotIds); 052 deleteViolations(snapshotIds); 053 deleteSnapshots(snapshotIds); 054 } 055 056 /** 057 * Delete all measures, including MEASURE_DATA 058 */ 059 protected void deleteMeasuresBySnapshotId(List<Integer> snapshotIds) { 060 executeQuery(snapshotIds, "delete from " + MeasureData.class.getSimpleName() + " m where m.snapshotId in (:ids)"); 061 executeQuery(snapshotIds, "delete from " + MeasureModel.class.getSimpleName() + " m where m.snapshotId in (:ids)"); 062 } 063 064 /** 065 * Delete all measures, including MEASURE_DATA 066 */ 067 protected void deleteMeasuresById(List<Integer> measureIds) { 068 executeQuery(measureIds, "delete from " + MeasureData.class.getSimpleName() + " m where m.measure.id in (:ids)"); 069 executeQuery(measureIds, "delete from " + MeasureModel.class.getSimpleName() + " m where m.id in (:ids)"); 070 } 071 072 /** 073 * Delete SNAPSHOT_SOURCES table 074 */ 075 protected void deleteSources(List<Integer> snapshotIds) { 076 executeQuery(snapshotIds, "delete from " + SnapshotSource.class.getSimpleName() + " e where e.snapshotId in (:ids)"); 077 } 078 079 /** 080 * Delete violations (RULE_FAILURES table) 081 */ 082 protected void deleteViolations(List<Integer> snapshotIds) { 083 executeQuery(snapshotIds, "delete from " + RuleFailureModel.class.getSimpleName() + " e where e.snapshotId in (:ids)"); 084 } 085 086 /** 087 * Delete SNAPSHOTS table 088 */ 089 protected void deleteSnapshots(List<Integer> snapshotIds) { 090 executeQuery(snapshotIds, "delete from " + Snapshot.class.getSimpleName() + " s where s.id in (:ids)"); 091 } 092 093 094 /** 095 * Paginate execution of SQL requests to avoid exceeding size of rollback segment 096 */ 097 protected void executeQuery(List<Integer> ids, String hql) { 098 if (ids == null || ids.isEmpty()) { 099 return; 100 } 101 102 int index = 0; 103 while (index < ids.size()) { 104 Query query = session.createQuery(hql); 105 List<Integer> paginedSids = ids.subList(index, Math.min(ids.size(), index + sqlInPageSize)); 106 query.setParameter("ids", paginedSids); 107 query.executeUpdate(); 108 index += sqlInPageSize; 109 session.commit(); 110 } 111 } 112 }