diff --git a/.classpath b/.classpath index 35edb50..c5c9f50 100644 --- a/.classpath +++ b/.classpath @@ -21,7 +21,8 @@ - + + diff --git a/lib/README b/lib/README index 9f12cb8..b9ab066 100644 --- a/lib/README +++ b/lib/README @@ -2,6 +2,7 @@ Description of used libraries: - commons-codec: digest tools - commons-lang: useful tools (StringUtils...) - hamcrest-core: required by junit +- hsqldb: SQL Database for unit test. - junit: unit tests API - log4j: log API - slf4j-api: facade log API diff --git a/lib/hsqldb-2.3.0.jar b/lib/hsqldb-2.3.0.jar new file mode 100644 index 0000000..de45eda Binary files /dev/null and b/lib/hsqldb-2.3.0.jar differ diff --git a/src/fr/devinsy/sikevadb/SQLSikevaDB.java b/src/fr/devinsy/sikevadb/SQLSikevaDB.java index 2ebb6df..238b477 100644 --- a/src/fr/devinsy/sikevadb/SQLSikevaDB.java +++ b/src/fr/devinsy/sikevadb/SQLSikevaDB.java @@ -15,6 +15,7 @@ */ package fr.devinsy.sikevadb; +import java.io.FileNotFoundException; import java.io.IOException; import java.sql.Connection; import java.sql.DriverManager; @@ -34,7 +35,6 @@ import org.joda.time.DateTime; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import fr.devinsy.util.FileTools; import fr.devinsy.util.StringList; /** @@ -75,7 +75,7 @@ public class SQLSikevaDB implements SikevaDB { throw new NullPointerException("url is null."); } else if (StringUtils.isBlank(login)) { throw new NullPointerException("login is null."); - } else if (StringUtils.isBlank(password)) { + } else if (password == null) { throw new NullPointerException("password is null"); } else { this.driverClassname = driverClassName; @@ -279,7 +279,7 @@ public class SQLSikevaDB implements SikevaDB { public void close(final Connection connection, final Statement statement, final ResultSet resultSet) { // - if ((connection != null) && (this.singleConnection != connection)) { + if ((connection != null) && (connection != this.singleConnection)) { try { connection.close(); } catch (SQLException exception) { @@ -583,26 +583,45 @@ public class SQLSikevaDB implements SikevaDB { * @throws SQLException */ public void createSchema() throws IOException, SQLException { - // - String createCommand = FileTools.load(SQLSikevaDB.class.getResource("/fr/devinsy/sikevadb/createSchema.sql")); - // Connection connection = null; - PreparedStatement statement = null; - ResultSet resultSet = null; + Statement statement = null; try { // connection = getConnection(); connection.setAutoCommit(true); + System.out.println("driver name =" + connection.getMetaData().getDriverName()); + System.out.println("driver version =" + connection.getMetaData().getDriverVersion()); + System.out.println("driver database name =" + connection.getMetaData().getDatabaseProductName()); + System.out.println("driver database version =" + connection.getMetaData().getDatabaseProductVersion()); + // - statement = connection.prepareStatement(createCommand); - statement.executeUpdate(); + StringList sqlCommands; + String databaseProductName = connection.getMetaData().getDatabaseProductName().split(" ")[0]; + logger.debug("[datatbaseProductName={}]", databaseProductName); + sqlCommands = SQLSikevaDBTools.loadSQLScript(SQLSikevaDB.class.getResource("/fr/devinsy/sikevadb/createTable-" + databaseProductName + ".sql")); - connection.commit(); + if (sqlCommands == null) { + throw new FileNotFoundException("SQL script creation not found for [" + databaseProductName + "]."); + } else { + // + for (String sql : sqlCommands) { + System.out.println("sql=[" + sql + "]"); + statement = connection.createStatement(); + statement.execute(sql); + } + + System.out.println("============================== APRÈS"); + + statement = connection.createStatement(); + statement.execute("delete from elements"); + + System.out.println("============================== APRÈS2"); + } } finally { - close(connection, statement, resultSet); + close(connection, statement, null); } } @@ -1172,7 +1191,7 @@ public class SQLSikevaDB implements SikevaDB { try { connection = getConnection(); connection.setAutoCommit(true); - statement = connection.prepareStatement("SELECT DISTINCT TOPKEY FROM elements WHERE ARCHIVE_DATE IS NULL ORDER BY CREATION_DATE ASC"); + statement = connection.prepareStatement("SELECT DISTINCT TOPKEY FROM elements WHERE ARCHIVE_DATE IS NULL"); resultSet = statement.executeQuery(); while (resultSet.next()) { @@ -1213,7 +1232,8 @@ public class SQLSikevaDB implements SikevaDB { try { connection = getConnection(); connection.setAutoCommit(true); - statement = connection.prepareStatement("SELECT DISTINCT SUBKEY FROM elements WHERE ARCHIVE_DATE IS NULL AND TOPKEY=? ORDER BY CREATION_DATE ASC"); + statement = connection + .prepareStatement("SELECT DISTINCT SUBKEY,CREATION_DATE FROM elements WHERE ARCHIVE_DATE IS NULL AND TOPKEY=? AND SUBKEY IS NOT NULL ORDER BY CREATION_DATE ASC"); statement.setString(1, key); resultSet = statement.executeQuery(); diff --git a/src/fr/devinsy/sikevadb/SQLSikevaDBTools.java b/src/fr/devinsy/sikevadb/SQLSikevaDBTools.java new file mode 100644 index 0000000..cb2988e --- /dev/null +++ b/src/fr/devinsy/sikevadb/SQLSikevaDBTools.java @@ -0,0 +1,106 @@ +/** + * Copyright (C) 2013 DEVINSY & Christian P. MOMON + * + * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE, Version 3, 29 June + * 2007; or any later version you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.gnu.org/licenses/lgpl-3.0.txt + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package fr.devinsy.sikevadb; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.StringReader; +import java.net.URL; + +import org.apache.commons.lang3.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import fr.devinsy.util.FileTools; +import fr.devinsy.util.StringList; + +/** + * + * + * @author Christian P. Momon + */ +public class SQLSikevaDBTools { + private static final Logger logger = LoggerFactory.getLogger(SQLSikevaDBTools.class); + + /** + * + * @param source + * @throws IOException + */ + public static StringList loadSQLScript(final URL source) throws IOException { + StringList result; + + String script = FileTools.load(source); + + result = splitSQLCommands(script); + + // + return result; + } + + /** + * + * @param source + * @throws IOException + */ + public static StringList splitSQLCommands(final String source) throws IOException { + StringList result; + + // + result = new StringList(); + + // + if (source != null) { + // + BufferedReader in = new BufferedReader(new StringReader(source)); + + boolean ended = false; + StringList sql = new StringList(); + while (!ended) { + String line = in.readLine(); + + if (line == null) { + ended = true; + } else { + if ((StringUtils.isNotBlank(line)) && (!line.startsWith("--"))) { + // + if (line.endsWith(";")) { + // + sql.append(line.substring(0, line.length() - 1)); + + // + result.add(sql.toString()); + + // + sql.clear(); + + } else { + // + sql.append(line).append(' '); + + } + } + } + } + + // + in.close(); + } + + // + return result; + } +} diff --git a/src/fr/devinsy/sikevadb/createTable-HSQL.sql b/src/fr/devinsy/sikevadb/createTable-HSQL.sql new file mode 100644 index 0000000..89acffa --- /dev/null +++ b/src/fr/devinsy/sikevadb/createTable-HSQL.sql @@ -0,0 +1,16 @@ +-- Specific file for HSQLDB due difference between MySQL yntax and HSQLDB syntax. +-- Warning: there is a convention about the file name. + +DROP TABLE IF EXISTS elements; +CREATE TABLE IF NOT EXISTS elements ( + `ID` INTEGER NOT NULL AUTO_INCREMENT, + `TOPKEY` varchar(255) NOT NULL, + `SUBKEY` varchar(255) DEFAULT NULL, + `VALUE` longtext, + `SIZE` INTEGER NOT NULL DEFAULT '0', + `DIGEST` varchar(255) NOT NULL, + `CREATION_DATE` datetime NOT NULL, + `EDITION_DATE` datetime NOT NULL, + `ARCHIVE_DATE` datetime DEFAULT NULL, + PRIMARY KEY (`ID`) +); diff --git a/src/fr/devinsy/sikevadb/createSchema.sql b/src/fr/devinsy/sikevadb/createTable-MySQL.sql similarity index 76% rename from src/fr/devinsy/sikevadb/createSchema.sql rename to src/fr/devinsy/sikevadb/createTable-MySQL.sql index ca10ce9..d534595 100644 --- a/src/fr/devinsy/sikevadb/createSchema.sql +++ b/src/fr/devinsy/sikevadb/createTable-MySQL.sql @@ -1,5 +1,7 @@ -SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; -SET time_zone = "+00:00"; +-- Warning: there is a convention about the file name. + +-- SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +-- SET time_zone = "+00:00"; -- -------------------------------------------------------- @@ -9,11 +11,11 @@ SET time_zone = "+00:00"; DROP TABLE IF EXISTS `elements`; CREATE TABLE IF NOT EXISTS `elements` ( - `ID` int(11) NOT NULL AUTO_INCREMENT, + `ID` INTEGER NOT NULL AUTO_INCREMENT, `TOPKEY` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `SUBKEY` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL, `VALUE` longtext COLLATE utf8_unicode_ci, - `SIZE` int(11) NOT NULL DEFAULT '0', + `SIZE` INTEGER NOT NULL DEFAULT '0', `DIGEST` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `CREATION_DATE` datetime NOT NULL, `EDITION_DATE` datetime NOT NULL, diff --git a/test/fr/devinsy/sikevadb/SQLSikevaDBTest.java b/test/fr/devinsy/sikevadb/SQLSikevaDBTest.java index 03c0323..445be49 100644 --- a/test/fr/devinsy/sikevadb/SQLSikevaDBTest.java +++ b/test/fr/devinsy/sikevadb/SQLSikevaDBTest.java @@ -1,5 +1,6 @@ package fr.devinsy.sikevadb; +import java.io.IOException; import java.sql.SQLException; import javax.naming.NamingException; @@ -10,9 +11,9 @@ import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Level; import org.apache.log4j.Logger; import org.joda.time.DateTime; -import org.junit.After; +import org.junit.AfterClass; import org.junit.Assert; -import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import fr.devinsy.util.StringList; @@ -22,36 +23,8 @@ import fr.devinsy.util.StringList; * @author Christian P. Momon */ public class SQLSikevaDBTest { - static protected org.apache.log4j.Logger logger = org.apache.log4j.Logger.getLogger(SQLSikevaDBTest.class); - private SQLSikevaDB database; - - /** - * - */ - @After - public void after() { - if (this.database != null) { - this.database.close(); - } - } - - /** - * @throws NamingException - * @throws SQLException - * @throws ClassNotFoundException - * @throws IllegalAccessException - * @throws InstantiationException - * - */ - @Before - public void before() throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException, NamingException { - BasicConfigurator.configure(); - Logger.getRootLogger().setLevel(Level.ERROR); - - // Add ?profileSQL=true to generate huge logs. - this.database = new SQLSikevaDB("com.mysql.jdbc.Driver", "jdbc:mysql://localhost:3306/sikevadb-test", "sikevadb-test", "12345678"); - this.database.open(); - } + private static org.slf4j.Logger logger = org.slf4j.LoggerFactory.getLogger(SQLSikevaDBTest.class); + private static SQLSikevaDB database; /** * @throws Exception @@ -183,7 +156,8 @@ public class SQLSikevaDBTest { Assert.assertEquals(5, keys.size()); Assert.assertTrue(keys.contains("alpha03")); - Assert.assertEquals(1, database.getSubkeys("alpha03").size()); + Assert.assertEquals(0, database.getSubkeys("alpha03").size()); + Assert.assertEquals(5, database.getSubkeys("alpha01").size()); // logger.debug("===== test done."); @@ -485,4 +459,39 @@ public class SQLSikevaDBTest { logger.debug("===== test done."); } + /** + * + */ + @AfterClass + public static void afterClass() { + if (database != null) { + database.close(); + } + } + + /** + * @throws NamingException + * @throws SQLException + * @throws ClassNotFoundException + * @throws IllegalAccessException + * @throws InstantiationException + * @throws IOException + * + */ + @BeforeClass + public static void beforeClass() throws InstantiationException, IllegalAccessException, ClassNotFoundException, SQLException, NamingException, IOException { + BasicConfigurator.configure(); + Logger.getRootLogger().setLevel(Level.ERROR); + + // Add ?profileSQL=true to generate huge logs. + + // database = new SQLSikevaDB("com.mysql.jdbc.Driver", + // "jdbc:mysql://localhost:3306/sikevadb-test", "sikevadb-test", + // "12345678"); + + database = new SQLSikevaDB("org.hsqldb.jdbcDriver", "jdbc:hsqldb:mem:sikevadb-unittest;sql.syntax_mys=true", "sa", ""); + database.open(); + database.createSchema(); + } + }