From 7342e90d136081c7b4a8780f0ef0fb4401301ac3 Mon Sep 17 00:00:00 2001 From: David Gageot Date: Fri, 26 Oct 2012 16:36:13 +0200 Subject: SONAR-3895 Remove Local Mode and fix Dry Run on postgresql --- .../org/sonar/core/persistence/DbTemplate.java | 60 +++++-------- .../core/persistence/DryRunDatabaseFactory.java | 100 +++++++++++++++++++++ .../core/persistence/LocalDatabaseFactory.java | 99 -------------------- .../persistence/DryRunDatabaseFactoryTest.java | 82 +++++++++++++++++ .../core/persistence/LocalDatabaseFactoryTest.java | 82 ----------------- .../should_create_database.xml | 11 +++ .../should_create_database.xml | 7 -- 7 files changed, 216 insertions(+), 225 deletions(-) create mode 100644 sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java delete mode 100644 sonar-core/src/main/java/org/sonar/core/persistence/LocalDatabaseFactory.java create mode 100644 sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java delete mode 100644 sonar-core/src/test/java/org/sonar/core/persistence/LocalDatabaseFactoryTest.java create mode 100644 sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml delete mode 100644 sonar-core/src/test/resources/org/sonar/core/persistence/LocalDatabaseFactoryTest/should_create_database.xml (limited to 'sonar-core/src') diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java b/sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java index 9dec7ff067f..bca98d80f8e 100644 --- a/sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java @@ -40,8 +40,6 @@ public class DbTemplate implements ServerComponent { public DbTemplate copyTable(DataSource source, DataSource dest, String table, String query) { LOG.info("Copy table " + table); - int colCount = getColumnCount(source, table); - truncate(dest, table); Connection sourceConnection = null; @@ -49,29 +47,35 @@ public class DbTemplate implements ServerComponent { ResultSet sourceResultSet = null; Connection destConnection = null; ResultSet destResultSet = null; + PreparedStatement destStatement = null; try { sourceConnection = source.getConnection(); sourceStatement = sourceConnection.createStatement(); sourceResultSet = sourceStatement.executeQuery(query); - destConnection = dest.getConnection(); - destConnection.setAutoCommit(false); + if (sourceResultSet.next()) { + int colCount = sourceResultSet.getMetaData().getColumnCount(); - PreparedStatement destStatement = destConnection.prepareStatement("INSERT INTO " + table + " VALUES(" + StringUtils.repeat("?", ",", colCount) + ")"); - while (sourceResultSet.next()) { - for (int col = 1; col <= colCount; col++) { - Object value = sourceResultSet.getObject(col); - destStatement.setObject(col, value); - } - destStatement.addBatch(); - } + destConnection = dest.getConnection(); + destConnection.setAutoCommit(false); - destStatement.executeBatch(); - destConnection.commit(); - destStatement.close(); + destStatement = destConnection.prepareStatement("INSERT INTO " + table + " VALUES(" + StringUtils.repeat("?", ",", colCount) + ")"); + do { + for (int col = 1; col <= colCount; col++) { + Object value = sourceResultSet.getObject(col); + destStatement.setObject(col, value); + } + destStatement.addBatch(); + } while (sourceResultSet.next()); + + destStatement.executeBatch(); + destConnection.commit(); + } } catch (SQLException e) { + LOG.error("Fail to copy table " + table, e); throw new SonarException("Fail to copy table " + table, e); } finally { + DatabaseUtils.closeQuietly(destStatement); DatabaseUtils.closeQuietly(destResultSet); DatabaseUtils.closeQuietly(destConnection); DatabaseUtils.closeQuietly(sourceResultSet); @@ -82,28 +86,7 @@ public class DbTemplate implements ServerComponent { return this; } - public int getColumnCount(DataSource dataSource, String table) { - Connection connection = null; - ResultSet metaData = null; - try { - connection = dataSource.getConnection(); - metaData = connection.getMetaData().getColumns(null, null, table, null); - - int nbColumns = 0; - while (metaData.next()) { - nbColumns++; - } - - return nbColumns; - } catch (SQLException e) { - throw new SonarException("Fail to get column count for table " + table, e); - } finally { - DatabaseUtils.closeQuietly(metaData); - DatabaseUtils.closeQuietly(connection); - } - } - - public int getRowCount(BasicDataSource dataSource, String table) { + public int getRowCount(DataSource dataSource, String table) { Connection connection = null; Statement statement = null; ResultSet resultSet = null; @@ -114,6 +97,7 @@ public class DbTemplate implements ServerComponent { return resultSet.next() ? resultSet.getInt(1) : 0; } catch (SQLException e) { + LOG.error("Fail to get row count for table " + table, e); throw new SonarException("Fail to get row count for table " + table, e); } finally { DatabaseUtils.closeQuietly(resultSet); @@ -130,6 +114,7 @@ public class DbTemplate implements ServerComponent { statement = connection.createStatement(); statement.executeUpdate("TRUNCATE TABLE " + table); } catch (SQLException e) { + LOG.error("Fail to truncate table " + table, e); throw new SonarException("Fail to truncate table " + table, e); } finally { DatabaseUtils.closeQuietly(statement); @@ -154,6 +139,7 @@ public class DbTemplate implements ServerComponent { connection = dataSource.getConnection(); DdlUtils.createSchema(connection, dialect); } catch (SQLException e) { + LOG.error("Fail to createSchema local database schema", e); throw new SonarException("Fail to createSchema local database schema", e); } finally { DatabaseUtils.closeQuietly(connection); diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java b/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java new file mode 100644 index 00000000000..156db8ab830 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java @@ -0,0 +1,100 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.core.persistence; + +import com.google.common.io.Files; +import org.apache.commons.dbcp.BasicDataSource; +import org.sonar.api.ServerComponent; +import org.sonar.api.platform.ServerFileSystem; +import org.sonar.api.utils.SonarException; + +import javax.sql.DataSource; + +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; + +public class DryRunDatabaseFactory implements ServerComponent { + private static final String DIALECT = "h2"; + private static final String DRIVER = "org.h2.Driver"; + private static final String URL = "jdbc:h2:"; + private static final String USER = "sonar"; + private static final String PASSWORD = "sonar"; + + private final Database database; + private final ServerFileSystem serverFileSystem; + + public DryRunDatabaseFactory(Database database, ServerFileSystem serverFileSystem) { + this.database = database; + this.serverFileSystem = serverFileSystem; + } + + public byte[] createDatabaseForDryRun(int resourceId) { + String name = serverFileSystem.getTempDir().getAbsolutePath() + "db-" + System.nanoTime(); + + try { + BasicDataSource destination = create(DIALECT, DRIVER, USER, PASSWORD, URL + name); + copy(database.getDataSource(), destination, resourceId); + close(destination); + + return dbFileContent(name); + } catch (SQLException e) { + throw new SonarException("Unable to create database for dry run", e); + } + } + + private void copy(DataSource source, DataSource dest, int resourceId) { + new DbTemplate() + .copyTable(source, dest, "PROPERTIES", + "SELECT * FROM PROPERTIES WHERE (((USER_ID IS NULL) AND (RESOURCE_ID IS NULL)) OR (RESOURCE_ID='" + resourceId + + "')) AND NOT (PROP_KEY LIKE '%.secured')") + .copyTable(source, dest, "RULES_PROFILES", "SELECT * FROM RULES_PROFILES") + .copyTable(source, dest, "RULES", "SELECT * FROM RULES") + .copyTable(source, dest, "RULES_PARAMETERS", "SELECT * FROM RULES_PARAMETERS") + .copyTable(source, dest, "ACTIVE_RULES", "SELECT * FROM ACTIVE_RULES") + .copyTable(source, dest, "ACTIVE_RULE_PARAMETERS", "SELECT * FROM ACTIVE_RULE_PARAMETERS") + .copyTable(source, dest, "METRICS", "SELECT * FROM METRICS") + .copyTable(source, dest, "CHARACTERISTICS", "SELECT * FROM CHARACTERISTICS") + .copyTable(source, dest, "CHARACTERISTIC_PROPERTIES", "SELECT * FROM CHARACTERISTIC_PROPERTIES") + .copyTable(source, dest, "CHARACTERISTIC_EDGES", "SELECT * FROM CHARACTERISTIC_EDGES") + .copyTable(source, dest, "QUALITY_MODELS", "SELECT * FROM QUALITY_MODELS"); + } + + private BasicDataSource create(String dialect, String driver, String user, String password, String url) { + BasicDataSource dataSource = new DbTemplate().dataSource(driver, user, password, url); + new DbTemplate().createSchema(dataSource, dialect); + return dataSource; + } + + private void close(BasicDataSource dest) throws SQLException { + dest.close(); + } + + private byte[] dbFileContent(String name) { + try { + File dbFile = new File(name + ".h2.db"); + byte[] content = Files.toByteArray(dbFile); + dbFile.delete(); + return content; + } catch (IOException e) { + throw new SonarException("Unable to read h2 database file", e); + } + } +} diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/LocalDatabaseFactory.java b/sonar-core/src/main/java/org/sonar/core/persistence/LocalDatabaseFactory.java deleted file mode 100644 index edebb896eef..00000000000 --- a/sonar-core/src/main/java/org/sonar/core/persistence/LocalDatabaseFactory.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.core.persistence; - -import com.google.common.io.Files; -import org.apache.commons.dbcp.BasicDataSource; -import org.sonar.api.ServerComponent; -import org.sonar.api.platform.ServerFileSystem; -import org.sonar.api.utils.SonarException; - -import javax.sql.DataSource; - -import java.io.File; -import java.io.IOException; -import java.sql.SQLException; - -public class LocalDatabaseFactory implements ServerComponent { - private static final String DIALECT = "h2"; - private static final String DRIVER = "org.h2.Driver"; - private static final String URL = "jdbc:h2:"; - private static final String USER = "sonar"; - private static final String PASSWORD = "sonar"; - - private final Database database; - private final ServerFileSystem serverFileSystem; - - public LocalDatabaseFactory(Database database, ServerFileSystem serverFileSystem) { - this.database = database; - this.serverFileSystem = serverFileSystem; - } - - public byte[] createDatabaseForLocalMode(int resourceId) { - String name = serverFileSystem.getTempDir().getAbsolutePath() + "db-" + System.nanoTime(); - - try { - BasicDataSource destination = create(DIALECT, DRIVER, USER, PASSWORD, URL + name); - copy(database.getDataSource(), destination, resourceId); - close(destination); - - return dbFileContent(name); - } catch (SQLException e) { - throw new SonarException("Unable to create database for local mode", e); - } - } - - private void copy(DataSource source, DataSource dest, int resourceId) { - new DbTemplate() - .copyTable(source, dest, "PROPERTIES", - "SELECT * FROM PROPERTIES WHERE (((USER_ID IS NULL) AND (RESOURCE_ID IS NULL)) OR (RESOURCE_ID='" + resourceId + "')) AND NOT (PROP_KEY LIKE '%.secured')") - .copyTable(source, dest, "RULES_PROFILES", "SELECT * FROM RULES_PROFILES") - .copyTable(source, dest, "RULES", "SELECT * FROM RULES") - .copyTable(source, dest, "RULES_PARAMETERS", "SELECT * FROM RULES_PARAMETERS") - .copyTable(source, dest, "ACTIVE_RULES", "SELECT * FROM ACTIVE_RULES") - .copyTable(source, dest, "ACTIVE_RULE_PARAMETERS", "SELECT * FROM ACTIVE_RULE_PARAMETERS") - .copyTable(source, dest, "METRICS", "SELECT * FROM METRICS") - .copyTable(source, dest, "CHARACTERISTICS", "SELECT * FROM CHARACTERISTICS") - .copyTable(source, dest, "CHARACTERISTIC_PROPERTIES", "SELECT * FROM CHARACTERISTIC_PROPERTIES") - .copyTable(source, dest, "CHARACTERISTIC_EDGES", "SELECT * FROM CHARACTERISTIC_EDGES") - .copyTable(source, dest, "QUALITY_MODELS", "SELECT * FROM QUALITY_MODELS"); - } - - private BasicDataSource create(String dialect, String driver, String user, String password, String url) { - BasicDataSource dataSource = new DbTemplate().dataSource(driver, user, password, url); - new DbTemplate().createSchema(dataSource, dialect); - return dataSource; - } - - private void close(BasicDataSource dest) throws SQLException { - dest.close(); - } - - private byte[] dbFileContent(String name) { - try { - File dbFile = new File(name + ".h2.db"); - byte[] content = Files.toByteArray(dbFile); - dbFile.delete(); - return content; - } catch (IOException e) { - throw new SonarException("Unable to read h2 database file", e); - } - } -} diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java new file mode 100644 index 00000000000..b44340a1fc5 --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java @@ -0,0 +1,82 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.core.persistence; + +import com.google.common.io.Files; +import org.apache.commons.dbcp.BasicDataSource; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.platform.ServerFileSystem; + +import java.io.File; +import java.io.IOException; +import java.sql.SQLException; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase { + private DryRunDatabaseFactory localDatabaseFactory; + + private ServerFileSystem serverFileSystem = mock(ServerFileSystem.class); + private BasicDataSource dataSource; + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Before + public void setUp() { + localDatabaseFactory = new DryRunDatabaseFactory(getDatabase(), serverFileSystem); + } + + @After + public void closeDatabase() throws SQLException { + if (dataSource != null) { + dataSource.close(); + } + } + + @Test + public void should_create_database() throws IOException, SQLException { + setupData("should_create_database"); + + when(serverFileSystem.getTempDir()).thenReturn(temporaryFolder.getRoot()); + + byte[] database = localDatabaseFactory.createDatabaseForDryRun(1); + dataSource = createDatabase(database); + + assertThat(rowCount("PROPERTIES")).isEqualTo(2); + assertThat(rowCount("PROJECTS")).isZero(); + } + + private BasicDataSource createDatabase(byte[] db) throws IOException { + File file = temporaryFolder.newFile("db.h2.db"); + Files.write(db, file); + return new DbTemplate().dataSource("org.h2.Driver", "sonar", "sonar", "jdbc:h2:" + file.getAbsolutePath().replaceAll(".h2.db", "")); + } + + private int rowCount(String table) { + return new DbTemplate().getRowCount(dataSource, table); + } +} diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/LocalDatabaseFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/LocalDatabaseFactoryTest.java deleted file mode 100644 index 3eb0d75c300..00000000000 --- a/sonar-core/src/test/java/org/sonar/core/persistence/LocalDatabaseFactoryTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Sonar, open source software quality management tool. - * Copyright (C) 2008-2012 SonarSource - * mailto:contact AT sonarsource DOT com - * - * Sonar 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. - * - * Sonar 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 Sonar; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 - */ -package org.sonar.core.persistence; - -import com.google.common.io.Files; -import org.apache.commons.dbcp.BasicDataSource; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.platform.ServerFileSystem; - -import java.io.File; -import java.io.IOException; -import java.sql.SQLException; - -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class LocalDatabaseFactoryTest extends AbstractDaoTestCase { - private LocalDatabaseFactory localDatabaseFactory; - - private ServerFileSystem serverFileSystem = mock(ServerFileSystem.class); - private BasicDataSource dataSource; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @Before - public void setUp() { - localDatabaseFactory = new LocalDatabaseFactory(getDatabase(), serverFileSystem); - } - - @After - public void closeDatabase() throws SQLException { - if (dataSource != null) { - dataSource.close(); - } - } - - @Test - public void should_create_database() throws IOException { - setupData("should_create_database"); - - when(serverFileSystem.getTempDir()).thenReturn(temporaryFolder.getRoot()); - - byte[] database = localDatabaseFactory.createDatabaseForLocalMode(1); - dataSource = createDatabase(database); - - assertThat(rowCount("PROPERTIES")).isEqualTo(2); - assertThat(rowCount("PROJECTS")).isZero(); - } - - private BasicDataSource createDatabase(byte[] db) throws IOException { - File file = temporaryFolder.newFile("db.h2.db"); - Files.write(db, file); - return new DbTemplate().dataSource("org.h2.Driver", "sonar", "sonar", "jdbc:h2:" + file.getAbsolutePath().replaceAll(".h2.db", "")); - } - - private int rowCount(String table) { - return new DbTemplate().getRowCount(dataSource, table); - } -} diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml new file mode 100644 index 00000000000..0e266518906 --- /dev/null +++ b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml @@ -0,0 +1,11 @@ + + + + + + + + + + \ No newline at end of file diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/LocalDatabaseFactoryTest/should_create_database.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/LocalDatabaseFactoryTest/should_create_database.xml deleted file mode 100644 index 30343973116..00000000000 --- a/sonar-core/src/test/resources/org/sonar/core/persistence/LocalDatabaseFactoryTest/should_create_database.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file -- cgit v1.2.3