diff --git a/.travis.yml b/.travis.yml index cc4b9f0..3998fec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ env: - ORACLE_HOME=/u01/app/oracle/product/11.2.0/xe - ORACLE_SID=XE - ORACLE_DOWNLOAD_DIR=$HOME/.traviscache + - DATABASE_NAME=XE services: - postgresql @@ -24,12 +25,15 @@ before_script: docker pull microsoft/mssql-server-linux:2017-latest; docker run -e 'ACCEPT_EULA=Y' -e 'SA_PASSWORD=' -p 1433:1433 -d microsoft/mssql-server-linux:2017-latest; fi + - echo "CREATE USER travis_test IDENTIFIED BY travis_test;" | "$ORACLE_HOME/bin/sqlplus" -L -S / AS SYSDBA || travis_terminate 1; + - echo "grant CREATE SESSION, ALTER SESSION, CREATE DATABASE LINK, CREATE MATERIALIZED VIEW, CREATE PROCEDURE, CREATE PUBLIC SYNONYM, CREATE ROLE, CREATE SEQUENCE, CREATE SYNONYM, CREATE TABLE, CREATE TRIGGER, CREATE TYPE, CREATE VIEW, UNLIMITED TABLESPACE to travis_test;" | "$ORACLE_HOME/bin/sqlplus" -L -S / AS SYSDBA || travis_terminate 1; + script: - docker ps -a - mvn -B -pl '!test' clean install || travis_terminate 1; - mvn -B -pl test clean test '-DjdbcUrl1=jdbc:postgresql:test_db' '-DjdbcUrl2=jdbc:mariadb://127.0.0.1:3306/test_db?user=root' '-DjdbcUrl3=jdbc:sqlserver://localhost:1433;databaseName=master;username=sa;password=;' || travis_terminate 1; - - mvn -B -pl test clean test --settings .travis-settings.xml -P oracle '-DjdbcUrl=derby' || travis_terminate 1; # todo: change jdbcUrl to actual oracle datasource + - mvn -B -pl test clean test --settings .travis-settings.xml -P oracle '-DjdbcUrl=jdbc:oracle:thin:travis_test/travis_test@127.0.0.1:1521/xe' || travis_terminate 1; - mvn -B -pl test clean test -P unnest '-DjdbcUrl=hsqldb' || travis_terminate 1; matrix: @@ -42,7 +46,7 @@ matrix: script: - mvn -B -pl '!test' clean install || travis_terminate 1; - mvn -B -pl test clean test '-DjdbcUrl1=jdbc:postgresql:test_db' '-DjdbcUrl2=jdbc:mariadb://127.0.0.1:3306/test_db?user=root' || travis_terminate 1; - - mvn -B -pl test clean test --settings .travis-settings.xml -P oracle '-DjdbcUrl=derby' || travis_terminate 1; # todo: change jdbcUrl to actual oracle datasource + - mvn -B -pl test clean test --settings .travis-settings.xml -P oracle '-DjdbcUrl=jdbc:oracle:thin:travis_test/travis_test@127.0.0.1:1521/xe' || travis_terminate 1; - mvn -B -pl test clean test -P unnest '-DjdbcUrl=hsqldb' || travis_terminate 1; jdk: openjdk6 - env: JDK='OpenJDK 7' diff --git a/test/pom.xml b/test/pom.xml index a5e1851..f6a62a2 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -30,6 +30,11 @@ junit test + + com.mchange + c3p0 + 0.9.5.2 + org.apache.derby derby diff --git a/test/src/main/java/com/moparisthebest/jdbc/codegen/QueryMapperQmDao.java b/test/src/main/java/com/moparisthebest/jdbc/codegen/QueryMapperQmDao.java index b847fac..3564da2 100644 --- a/test/src/main/java/com/moparisthebest/jdbc/codegen/QueryMapperQmDao.java +++ b/test/src/main/java/com/moparisthebest/jdbc/codegen/QueryMapperQmDao.java @@ -54,7 +54,7 @@ public class QueryMapperQmDao implements QmDao { public static final String selectStrVal = "SELECT str_val FROM val WHERE val_no = ?"; private static final Collection> noArrayInListSupport; - private static final Class hsqlConnection; + public static final Class hsqlConnection, oracleConnection, mssqlConnection; static { Collection> no = new ArrayList>(); @@ -64,6 +64,7 @@ public class QueryMapperQmDao implements QmDao { , "org.sqlite.jdbc3.JDBC3Connection" , "org.mariadb.jdbc.MariaDbConnection" , "com.microsoft.sqlserver.jdbc.SQLServerConnection" + , "oracle.jdbc.driver.PhysicalConnection" // does not support ArrayInList but *does* support OracleArrayInList // h2 doesn't support this with java6 either... /*IFJAVA6_START , "org.h2.jdbc.JdbcConnection" @@ -75,15 +76,29 @@ public class QueryMapperQmDao implements QmDao { // ignore } noArrayInListSupport = Collections.unmodifiableCollection(no); - Class hsql = null; - try { - hsql = Class.forName("org.hsqldb.jdbc.JDBCConnection"); - } catch(Exception e) { - // ignore - } - hsqlConnection = hsql; + hsqlConnection = classForName("org.hsqldb.jdbc.JDBCConnection"); + oracleConnection = classForName("oracle.jdbc.driver.PhysicalConnection"); + mssqlConnection = classForName("com.microsoft.sqlserver.jdbc.SQLServerConnection"); } + private static Class classForName(final String className) { + try { + return Class.forName(className); + } catch(Exception e) { + return null; + } + } + + public static boolean isWrapperFor(final Connection conn, final Class connectionClass) { + if(connectionClass == null) + return false; + try { + return conn.isWrapperFor(connectionClass); + } catch(Exception e) { + return false; + } + } + public static boolean supportsArrayInList(final Connection conn) { for(final Class connectionClass : noArrayInListSupport) { try { @@ -100,13 +115,10 @@ public class QueryMapperQmDao implements QmDao { public static InList getBestInList(final Connection conn) { if(supportsArrayInList(conn)) return ArrayInList.instance(); - if(hsqlConnection != null) - try { - if(conn.isWrapperFor(hsqlConnection)) - return UnNestArrayInList.instance(); - } catch (SQLException e) { - // ignore - } + if(isWrapperFor(conn, hsqlConnection)) + return UnNestArrayInList.instance(); + if(isWrapperFor(conn, oracleConnection)) + return OracleArrayInList.instance(); // works for everything return BindInList.instance(); } diff --git a/test/src/test/java/com/moparisthebest/jdbc/QueryMapperTest.java b/test/src/test/java/com/moparisthebest/jdbc/QueryMapperTest.java index fb5179e..4f43d98 100644 --- a/test/src/test/java/com/moparisthebest/jdbc/QueryMapperTest.java +++ b/test/src/test/java/com/moparisthebest/jdbc/QueryMapperTest.java @@ -1,5 +1,6 @@ package com.moparisthebest.jdbc; +import com.mchange.v2.c3p0.DataSources; import com.moparisthebest.jdbc.codegen.JdbcMapperFactory; import com.moparisthebest.jdbc.codegen.QmDao; import com.moparisthebest.jdbc.codegen.QueryMapperQmDao; @@ -10,6 +11,7 @@ import org.junit.*; import org.junit.runner.RunWith; import org.junit.runners.Parameterized; +import javax.sql.DataSource; import java.sql.Connection; import java.sql.DriverManager; import java.sql.SQLException; @@ -21,7 +23,7 @@ import java.util.stream.Stream; //IFJAVA8_END import static com.moparisthebest.jdbc.TryClose.tryClose; -import static com.moparisthebest.jdbc.codegen.QueryMapperQmDao.supportsArrayInList; +import static com.moparisthebest.jdbc.codegen.QueryMapperQmDao.*; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; @@ -68,6 +70,7 @@ public class QueryMapperTest { public static final Boss reverseSetBoss3 = new ReverseSetBoss(fieldBoss3); public static final Collection jdbcUrls; + public static final Map dataSources = new HashMap(); static { final Collection jUrls = new ArrayList(); @@ -105,6 +108,16 @@ public class QueryMapperTest { // ignore, any real errors will be caught during test running } IFJAVA6_END*/ + for(final String jUrl : jdbcUrls) { + // oracle randomly fails without using a datasource... + // https://dba.stackexchange.com/questions/110819/oracle-intermittently-throws-ora-12516-tnslistener-could-not-find-available-h + if(jUrl.startsWith("jdbc:oracle")) + try { + dataSources.put(jUrl, DataSources.pooledDataSource(DataSources.unpooledDataSource(jUrl))); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } } public static void insertPerson(final QueryMapper qm, final Person person) throws SQLException { @@ -115,16 +128,9 @@ public class QueryMapperTest { return getConnection(jdbcUrls.iterator().next()); } - public static boolean isWrapperFor(final Connection conn, final String className) { - try { - return conn.isWrapperFor(Class.forName(className)); - } catch(Exception e) { - return false; - } - } - public static Connection getConnection(final String url) throws SQLException { - final Connection conn = DriverManager.getConnection(url); + final DataSource ds = dataSources.get(url); + final Connection conn = ds != null ? ds.getConnection() : DriverManager.getConnection(url); QueryMapper qm = null; try { qm = new QueryMapper(conn); @@ -134,7 +140,12 @@ public class QueryMapperTest { } catch(Exception e) { // ignore, means the database hasn't been set up yet } - if(isWrapperFor(conn, "com.microsoft.sqlserver.jdbc.SQLServerConnection")) { + if(isWrapperFor(conn, oracleConnection)) { + // OracleArrayInList support requires types created + qm.executeUpdate("create or replace TYPE \"ARRAY_NUM_TYPE\" is table of number"); + qm.executeUpdate("create or replace TYPE \"ARRAY_STR_TYPE\" is table of varchar2(32767)"); + } + if(isWrapperFor(conn, mssqlConnection)) { // mssql doesn't support inserting into TIMESTAMP qm.executeUpdate("CREATE TABLE person (person_no NUMERIC, first_name VARCHAR(40), last_name VARCHAR(40), birth_date DATETIME)"); } else {