factor out subprojects: oracle, postgresql, mariadb, fix pool tests
This commit is contained in:
parent
1409d0e42d
commit
ca784dc6cf
73 changed files with 2546 additions and 755 deletions
|
@ -6,13 +6,13 @@ java {
|
|||
}
|
||||
|
||||
compileJava {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
compileTestJava {
|
||||
sourceCompatibility = JavaVersion.VERSION_11
|
||||
targetCompatibility = JavaVersion.VERSION_11
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
jar {
|
||||
|
@ -35,7 +35,7 @@ artifacts {
|
|||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.compilerArgs << '-Xlint:all,-fallthrough'
|
||||
options.compilerArgs << '-Xlint:all,-fallthrough,-exports,-try'
|
||||
}
|
||||
|
||||
javadoc {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
module org.xbib.jdbc.connection.pool {
|
||||
requires java.logging;
|
||||
requires transitive java.sql;
|
||||
requires java.sql;
|
||||
exports org.xbib.jdbc.connection.pool;
|
||||
exports org.xbib.jdbc.connection.pool.util;
|
||||
}
|
||||
|
|
|
@ -16,14 +16,6 @@ public class PoolConfig {
|
|||
|
||||
private static final AtomicLong POOL_COUNTER = new AtomicLong();
|
||||
|
||||
private static final long CONNECTION_TIMEOUT = TimeUnit.SECONDS.toMillis(30);
|
||||
|
||||
private static final long VALIDATION_TIMEOUT = TimeUnit.SECONDS.toMillis(5);
|
||||
|
||||
private static final long IDLE_TIMEOUT = TimeUnit.MINUTES.toMillis(10);
|
||||
|
||||
private static final long MAX_LIFETIME = TimeUnit.MINUTES.toMillis(30);
|
||||
|
||||
private static final int DEFAULT_POOL_SIZE = 8;
|
||||
|
||||
private final Properties properties;
|
||||
|
@ -100,20 +92,28 @@ public class PoolConfig {
|
|||
this.properties = properties;
|
||||
this.minIdle = -1;
|
||||
this.maxPoolSize = -1;
|
||||
this.maxLifetime = MAX_LIFETIME;
|
||||
this.connectionTimeout = CONNECTION_TIMEOUT;
|
||||
this.validationTimeout = VALIDATION_TIMEOUT;
|
||||
this.idleTimeout = IDLE_TIMEOUT;
|
||||
this.maxLifetime = TimeUnit.MINUTES.toMillis(30);
|
||||
this.connectionTimeout = TimeUnit.SECONDS.toMillis(30);
|
||||
this.validationTimeout = TimeUnit.SECONDS.toMillis(5);
|
||||
this.idleTimeout = TimeUnit.MINUTES.toMillis(1);
|
||||
this.initializationFailTimeout = -1;
|
||||
this.isAutoCommit = true;
|
||||
this.isAutoCommit = true; // JDBC convention
|
||||
this.aliveBypassWindowMs = TimeUnit.MILLISECONDS.toMillis(500);
|
||||
this.housekeepingPeriodMs = TimeUnit.SECONDS.toMillis(30);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the JDBC URL.
|
||||
* @param url the JDBC url as string
|
||||
*/
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JDBC URL.
|
||||
* @return the JDBC URL as string
|
||||
*/
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
@ -450,15 +450,6 @@ public class PoolConfig {
|
|||
this.isIsolateInternalQueries = isolate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the Connections in the pool are in read-only mode.
|
||||
*
|
||||
* @return {@code true} if the Connections in the pool are read-only, {@code false} if not
|
||||
*/
|
||||
public boolean isReadOnly() {
|
||||
return isReadOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Connections to be added to the pool as read-only Connections.
|
||||
*
|
||||
|
@ -468,8 +459,13 @@ public class PoolConfig {
|
|||
this.isReadOnly = readOnly;
|
||||
}
|
||||
|
||||
public String getPoolName() {
|
||||
return poolName;
|
||||
/**
|
||||
* Determine whether the Connections in the pool are in read-only mode.
|
||||
*
|
||||
* @return {@code true} if the Connections in the pool are read-only, {@code false} if not
|
||||
*/
|
||||
public boolean isReadOnly() {
|
||||
return isReadOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -482,6 +478,10 @@ public class PoolConfig {
|
|||
this.poolName = poolName;
|
||||
}
|
||||
|
||||
public String getPoolName() {
|
||||
return poolName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ScheduledExecutorService used for housekeeping.
|
||||
*
|
||||
|
@ -628,26 +628,26 @@ public class PoolConfig {
|
|||
|
||||
private void validateNumerics() {
|
||||
if (maxLifetime != 0 && maxLifetime < TimeUnit.SECONDS.toMillis(30)) {
|
||||
logger.log(Level.WARNING, "maxLifetime is less than 30000ms, setting to default ms: " +
|
||||
poolName + " " + MAX_LIFETIME);
|
||||
maxLifetime = MAX_LIFETIME;
|
||||
logger.log(Level.WARNING, "maxLifetime is less than 30s, setting to default ms: " +
|
||||
poolName + " " + TimeUnit.SECONDS.toMillis(30));
|
||||
maxLifetime = TimeUnit.SECONDS.toMillis(30);
|
||||
}
|
||||
if (leakDetectionThreshold > 0) {
|
||||
if (leakDetectionThreshold < TimeUnit.SECONDS.toMillis(2) || (leakDetectionThreshold > maxLifetime && maxLifetime > 0)) {
|
||||
logger.log(Level.WARNING, "leakDetectionThreshold is less than 2000ms or more than maxLifetime, disabling it: " +
|
||||
logger.log(Level.WARNING, "leakDetectionThreshold is less than 2s or more than maxLifetime, disabling it: " +
|
||||
poolName);
|
||||
leakDetectionThreshold = 0;
|
||||
}
|
||||
}
|
||||
if (connectionTimeout < 250) {
|
||||
logger.log(Level.WARNING, "connectionTimeout is less than 250ms, setting to ms: " +
|
||||
poolName + " " + CONNECTION_TIMEOUT);
|
||||
connectionTimeout = CONNECTION_TIMEOUT;
|
||||
poolName + " " + TimeUnit.MILLISECONDS.toMillis(250));
|
||||
connectionTimeout = TimeUnit.MILLISECONDS.toMillis(250);
|
||||
}
|
||||
if (validationTimeout < 250) {
|
||||
logger.log(Level.WARNING, "validationTimeout is less than 250ms, setting to ms" +
|
||||
poolName + " " + VALIDATION_TIMEOUT);
|
||||
validationTimeout = VALIDATION_TIMEOUT;
|
||||
poolName + " " + TimeUnit.MILLISECONDS.toMillis(250));
|
||||
validationTimeout = TimeUnit.MILLISECONDS.toMillis(250);
|
||||
}
|
||||
if (maxPoolSize < 1) {
|
||||
maxPoolSize = DEFAULT_POOL_SIZE;
|
||||
|
@ -659,10 +659,10 @@ public class PoolConfig {
|
|||
logger.log(Level.WARNING, "idleTimeout is close to or more than maxLifetime, disabling it:" + poolName);
|
||||
idleTimeout = 0;
|
||||
} else if (idleTimeout != 0 && idleTimeout < TimeUnit.SECONDS.toMillis(10) && minIdle < maxPoolSize) {
|
||||
logger.log(Level.WARNING, "idleTimeout is less than 10000ms, setting to default ms: " +
|
||||
poolName + " " + IDLE_TIMEOUT);
|
||||
idleTimeout = IDLE_TIMEOUT;
|
||||
} else if (idleTimeout != IDLE_TIMEOUT && idleTimeout != 0 && minIdle == maxPoolSize) {
|
||||
logger.log(Level.WARNING, "idleTimeout is less than 10s, setting to default ms: " +
|
||||
poolName + " " + TimeUnit.SECONDS.toMillis(10));
|
||||
idleTimeout = TimeUnit.SECONDS.toMillis(10);
|
||||
} else if (idleTimeout != TimeUnit.SECONDS.toMillis(10) && idleTimeout != 0 && minIdle == maxPoolSize) {
|
||||
logger.log(Level.WARNING, "idleTimeout has been set but has no effect because the pool is operating as a fixed size pool: " + poolName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,9 +15,9 @@ import org.xbib.jdbc.connection.pool.PoolDataSource;
|
|||
public class ConcurrentCloseConnectionTest
|
||||
{
|
||||
@Test
|
||||
public void testConcurrentClose() throws Exception
|
||||
{
|
||||
public void testConcurrentClose() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setDataSourceClassName("org.xbib.io.pool.jdbc.mock.StubDataSource");
|
||||
try (PoolDataSource ds = new PoolDataSource(config);
|
||||
final Connection connection = ds.getConnection()) {
|
||||
|
|
|
@ -31,6 +31,7 @@ public class ConnectionCloseBlockingTest {
|
|||
@Test
|
||||
public void testConnectionCloseBlocking() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(1500);
|
||||
|
|
|
@ -63,6 +63,7 @@ public class ConnectionPoolSizeVsThreadsTest {
|
|||
LOGGER.info(MessageFormat.format("Starting test (minIdle={0}, maxPoolSize={1}, threadCount={2}, workTimeMs={3}, restTimeMs={4}, connectionAcquisitionTimeMs={5}, iterations={6}, postTestTimeMs={7})",
|
||||
minIdle, maxPoolSize, threadCount, workTimeMs, restTimeMs, connectionAcquisitionTimeMs, iterations, postTestTimeMs));
|
||||
final PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(minIdle);
|
||||
config.setMaximumPoolSize(maxPoolSize);
|
||||
config.setInitializationFailTimeout(Long.MAX_VALUE);
|
||||
|
|
|
@ -21,6 +21,7 @@ public class ConnectionRaceConditionTest {
|
|||
@Test
|
||||
public void testRaceCondition() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setInitializationFailTimeout(Long.MAX_VALUE);
|
||||
|
|
|
@ -20,9 +20,9 @@ public class ConnectionStateTest {
|
|||
Properties properties = new Properties();
|
||||
properties.put("user", "bar");
|
||||
properties.put("password", "secret");
|
||||
properties.put("url", "baf");
|
||||
properties.put("loginTimeout", "10");
|
||||
PoolConfig config = new PoolConfig(properties);
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setAutoCommit(true);
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
|
@ -41,6 +41,7 @@ public class ConnectionStateTest {
|
|||
public void testTransactionIsolation() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
PoolConfig config = new PoolConfig(properties);
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setTransactionIsolation("TRANSACTION_READ_COMMITTED");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
|
@ -58,6 +59,7 @@ public class ConnectionStateTest {
|
|||
@Test
|
||||
public void testIsolation() {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setDataSourceClassName("org.xbib.io.pool.jdbc.mock.StubDataSource");
|
||||
config.setTransactionIsolation("TRANSACTION_REPEATABLE_READ");
|
||||
config.validate();
|
||||
|
@ -68,6 +70,7 @@ public class ConnectionStateTest {
|
|||
@Test
|
||||
public void testReadOnly() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setCatalog("test");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
|
@ -85,6 +88,7 @@ public class ConnectionStateTest {
|
|||
@Test
|
||||
public void testCatalog() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setCatalog("test");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
|
@ -95,6 +99,7 @@ public class ConnectionStateTest {
|
|||
Connection unwrap = connection.unwrap(Connection.class);
|
||||
connection.setCatalog("other");
|
||||
connection.close();
|
||||
// after close, we can access unwrap
|
||||
assertEquals("test", unwrap.getCatalog());
|
||||
}
|
||||
}
|
||||
|
@ -103,6 +108,7 @@ public class ConnectionStateTest {
|
|||
@Test
|
||||
public void testCommitTracking() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setAutoCommit(false);
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
|
|
|
@ -34,6 +34,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testCreate() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
|
@ -69,6 +70,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testMaxLifetime() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(1500);
|
||||
|
@ -110,6 +112,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testMaxLifetime2() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(2500);
|
||||
|
@ -149,6 +152,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testDoubleClose() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(2500);
|
||||
|
@ -167,6 +171,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testEviction() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(5);
|
||||
config.setConnectionTimeout(2500);
|
||||
|
@ -184,11 +189,11 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testEviction2() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMaximumPoolSize(5);
|
||||
config.setConnectionTimeout(2500);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
config.setDataSourceClassName("org.xbib.io.pool.jdbc.mock.StubDataSource");
|
||||
//config.setExceptionOverrideClassName(OverrideHandler.class.getName());
|
||||
try (PoolDataSource ds = new PoolDataSource(config)) {
|
||||
Pool pool = ds.getPool();
|
||||
while (pool.getTotalConnections() < 5) {
|
||||
|
@ -214,6 +219,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testEviction3() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMaximumPoolSize(5);
|
||||
config.setConnectionTimeout(2500);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
|
@ -243,6 +249,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testEvictAllRefill() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(5);
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setConnectionTimeout(2500);
|
||||
|
@ -268,6 +275,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testBackfill() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(4);
|
||||
config.setConnectionTimeout(1000);
|
||||
|
@ -309,6 +317,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testMaximumPoolLimit() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(4);
|
||||
config.setConnectionTimeout(20000);
|
||||
|
@ -348,6 +357,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testOldDriver() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(2500);
|
||||
|
@ -375,6 +385,7 @@ public class ConnectionTest {
|
|||
StubDataSource stubDataSource = new StubDataSource();
|
||||
stubDataSource.setThrowException(new SQLException("Connection refused"));
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(2500);
|
||||
|
@ -394,6 +405,7 @@ public class ConnectionTest {
|
|||
StubDataSource stubDataSource = new StubDataSource();
|
||||
stubDataSource.setThrowException(new SQLException("Connection refused"));
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
config.setDataSource(stubDataSource);
|
||||
|
@ -420,6 +432,7 @@ public class ConnectionTest {
|
|||
}
|
||||
};
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(2);
|
||||
config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(3));
|
||||
|
@ -448,6 +461,7 @@ public class ConnectionTest {
|
|||
StubDataSourceWithErrorSwitch stubDataSource = new StubDataSourceWithErrorSwitch();
|
||||
stubDataSource.setErrorOnConnection(true);
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
config.setDataSource(stubDataSource);
|
||||
|
@ -465,6 +479,7 @@ public class ConnectionTest {
|
|||
public void testDataSourceRaisesErrorAfterInitializationTestQuery() throws Exception {
|
||||
StubDataSourceWithErrorSwitch stubDataSource = new StubDataSourceWithErrorSwitch();
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(2);
|
||||
config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(3));
|
||||
|
@ -486,6 +501,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testPopulationSlowAcquisition() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMaximumPoolSize(20);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
config.setDataSourceClassName("org.xbib.io.pool.jdbc.mock.StubDataSource");
|
||||
|
@ -515,6 +531,7 @@ public class ConnectionTest {
|
|||
@Test
|
||||
public void testMinimumIdleZero() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(5);
|
||||
config.setConnectionTimeout(1000L);
|
||||
|
@ -545,11 +562,4 @@ public class ConnectionTest {
|
|||
this.errorOnConnection = errorOnConnection;
|
||||
}
|
||||
}
|
||||
|
||||
/*public static class OverrideHandler implements SQLExceptionOverride {
|
||||
@java.lang.Override
|
||||
public Override adjudicate(SQLException sqlException) {
|
||||
return (sqlException.getSQLState().equals("08999")) ? Override.DO_NOT_EVICT : Override.CONTINUE_EVICT;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ public class ConnectionTimeoutRetryTest {
|
|||
@Test
|
||||
public void testConnectionRetries() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(2800);
|
||||
|
@ -46,6 +47,7 @@ public class ConnectionTimeoutRetryTest {
|
|||
@Test
|
||||
public void testConnectionRetries2() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(2800);
|
||||
|
@ -76,6 +78,7 @@ public class ConnectionTimeoutRetryTest {
|
|||
@Test
|
||||
public void testConnectionRetries3() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(2);
|
||||
config.setConnectionTimeout(2800);
|
||||
|
@ -114,6 +117,7 @@ public class ConnectionTimeoutRetryTest {
|
|||
@Test
|
||||
public void testConnectionRetries5() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(2);
|
||||
config.setConnectionTimeout(1000);
|
||||
|
@ -151,6 +155,7 @@ public class ConnectionTimeoutRetryTest {
|
|||
public void testConnectionIdleFill() throws Exception {
|
||||
StubConnection.slowCreate = false;
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(5);
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setConnectionTimeout(2000);
|
||||
|
|
|
@ -28,6 +28,7 @@ public class HouseKeeperCleanupTest {
|
|||
@Test
|
||||
public void testHouseKeeperCleanupWithCustomExecutor() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setInitializationFailTimeout(Long.MAX_VALUE);
|
||||
|
|
|
@ -12,6 +12,7 @@ public class IsolationTest {
|
|||
@Test
|
||||
public void testIsolation() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setIsolateInternalQueries(true);
|
||||
|
@ -31,6 +32,7 @@ public class IsolationTest {
|
|||
@Test
|
||||
public void testNonIsolation() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setIsolateInternalQueries(false);
|
||||
|
|
|
@ -25,10 +25,10 @@ public class JdbcDriverTest {
|
|||
@Test
|
||||
public void driverTest1() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.put("url", "jdbc:stub");
|
||||
properties.put("user", "bart");
|
||||
properties.put("password", "simpson");
|
||||
PoolConfig config = new PoolConfig(properties);
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
|
@ -46,8 +46,8 @@ public class JdbcDriverTest {
|
|||
@Test
|
||||
public void driverTest2() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.put("url", "jdbc:invalid");
|
||||
PoolConfig config = new PoolConfig(properties);
|
||||
config.setUrl("jdbc:invalid");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
|
|
|
@ -23,18 +23,17 @@ public class PoolTest {
|
|||
@BeforeAll
|
||||
static void setup() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.put("url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
|
||||
PoolConfig config = new PoolConfig(properties);
|
||||
config.setUrl("jdbc:h2:mem:test");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(2);
|
||||
config.setConnectionTestQuery("SELECT 1");
|
||||
config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
|
||||
try (PoolDataSource ds = new PoolDataSource(config);
|
||||
Connection conn = ds.getConnection();
|
||||
Statement stmt = conn.createStatement()) {
|
||||
stmt.executeUpdate("DROP TABLE IF EXISTS basic_pool_test");
|
||||
stmt.executeUpdate("CREATE TABLE basic_pool_test ("
|
||||
+ "id INTEGER NOT NULL IDENTITY PRIMARY KEY, "
|
||||
+ "id INTEGER PRIMARY KEY, "
|
||||
+ "timestamp TIMESTAMP, "
|
||||
+ "string VARCHAR(128), "
|
||||
+ "string_from_number NUMERIC "
|
||||
|
@ -45,12 +44,11 @@ public class PoolTest {
|
|||
@Test
|
||||
public void testIdleTimeout() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.put("url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
|
||||
PoolConfig config = new PoolConfig(properties);
|
||||
config.setUrl("jdbc:h2:mem:test");
|
||||
config.setMinimumIdle(5);
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setConnectionTestQuery("SELECT 1");
|
||||
config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
|
||||
System.setProperty("pool.jdbc.housekeeping.periodMs", "1000");
|
||||
try (PoolDataSource ds = new PoolDataSource(config)) {
|
||||
System.clearProperty("pool.jdbc.housekeeping.periodMs");
|
||||
|
@ -79,11 +77,10 @@ public class PoolTest {
|
|||
@Test
|
||||
public void testIdleTimeout2() throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.put("url", "jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
|
||||
PoolConfig config = new PoolConfig(properties);
|
||||
config.setUrl("jdbc:h2:mem:test");
|
||||
config.setMaximumPoolSize(50);
|
||||
config.setConnectionTestQuery("SELECT 1");
|
||||
config.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource");
|
||||
System.setProperty("pool.jdbc.housekeeping.periodMs", "1000");
|
||||
try (PoolDataSource ds = new PoolDataSource(config)) {
|
||||
System.clearProperty("pool.jdbc.housekeeping.periodMs");
|
||||
|
|
|
@ -3,32 +3,12 @@ package org.xbib.io.pool.jdbc;
|
|||
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
||||
import org.junit.jupiter.api.extension.ExtensionContext;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.ConsoleHandler;
|
||||
import java.util.logging.Handler;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.logging.SimpleFormatter;
|
||||
import org.xbib.jdbc.connection.pool.IsolationLevel;
|
||||
|
||||
public class PoolTestExtension implements BeforeAllCallback {
|
||||
|
||||
@Override
|
||||
public void beforeAll(ExtensionContext context) {
|
||||
//Level level = Level.INFO;
|
||||
Level level = Level.ALL;
|
||||
System.setProperty("java.util.logging.SimpleFormatter.format",
|
||||
"%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] %5$s %6$s%n");
|
||||
LogManager.getLogManager().reset();
|
||||
Logger rootLogger = LogManager.getLogManager().getLogger("");
|
||||
Handler handler = new ConsoleHandler();
|
||||
handler.setFormatter(new SimpleFormatter());
|
||||
rootLogger.addHandler(handler);
|
||||
rootLogger.setLevel(level);
|
||||
for (Handler h : rootLogger.getHandlers()) {
|
||||
handler.setFormatter(new SimpleFormatter());
|
||||
h.setLevel(level);
|
||||
}
|
||||
}
|
||||
|
||||
public static void quietlySleep(long millis) {
|
||||
|
|
|
@ -22,6 +22,7 @@ public class ProxiesTest {
|
|||
@Test
|
||||
public void testProxyCreation() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
|
@ -55,6 +56,7 @@ public class ProxiesTest {
|
|||
@Test
|
||||
public void testStatementProxy() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
|
@ -81,6 +83,7 @@ public class ProxiesTest {
|
|||
@Test
|
||||
public void testStatementExceptions() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTimeout(TimeUnit.SECONDS.toMillis(1));
|
||||
|
@ -168,6 +171,7 @@ public class ProxiesTest {
|
|||
@Test
|
||||
public void testOtherExceptions() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
|
|
|
@ -14,6 +14,7 @@ public class RampUpDownTest {
|
|||
@Test
|
||||
public void rampUpDownTest() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(5);
|
||||
config.setMaximumPoolSize(60);
|
||||
config.setInitializationFailTimeout(0);
|
||||
|
|
|
@ -29,6 +29,7 @@ public class SaturatedPoolTest830 {
|
|||
@Test
|
||||
public void saturatedPoolTest() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(5);
|
||||
config.setMaximumPoolSize(MAX_POOL_SIZE);
|
||||
config.setInitializationFailTimeout(Long.MAX_VALUE);
|
||||
|
|
|
@ -117,6 +117,7 @@ public class ShutdownTest {
|
|||
public void testShutdown4() throws Exception {
|
||||
StubConnection.slowCreate = true;
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(10);
|
||||
config.setMaximumPoolSize(10);
|
||||
config.setInitializationFailTimeout(Long.MAX_VALUE);
|
||||
|
@ -137,6 +138,7 @@ public class ShutdownTest {
|
|||
public void testShutdown5() throws Exception {
|
||||
assertSame( 0, StubConnection.count.get(), "StubConnection count not as expected");
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(5);
|
||||
config.setMaximumPoolSize(5);
|
||||
config.setInitializationFailTimeout(0);
|
||||
|
@ -158,6 +160,7 @@ public class ShutdownTest {
|
|||
@Test
|
||||
public void testAfterShutdown() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(0);
|
||||
config.setMaximumPoolSize(5);
|
||||
config.setInitializationFailTimeout(0);
|
||||
|
@ -177,6 +180,7 @@ public class ShutdownTest {
|
|||
@Test
|
||||
public void testShutdownDuringInit() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(5);
|
||||
config.setMaximumPoolSize(5);
|
||||
config.setConnectionTimeout(1000);
|
||||
|
@ -193,6 +197,7 @@ public class ShutdownTest {
|
|||
@Test
|
||||
public void testThreadedShutdown() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(5);
|
||||
config.setMaximumPoolSize(5);
|
||||
config.setConnectionTimeout(1000);
|
||||
|
|
|
@ -19,6 +19,7 @@ public class StatementTest {
|
|||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(2);
|
||||
config.setConnectionTestQuery("VALUES 1");
|
||||
|
|
|
@ -19,6 +19,7 @@ public class UnwrapTest {
|
|||
@Test
|
||||
public void testUnwrapConnection() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setInitializationFailTimeout(0);
|
||||
|
@ -37,6 +38,7 @@ public class UnwrapTest {
|
|||
@Test
|
||||
public void testUnwrapDataSource() throws Exception {
|
||||
PoolConfig config = new PoolConfig();
|
||||
config.setUrl("jdbc:stub");
|
||||
config.setMinimumIdle(1);
|
||||
config.setMaximumPoolSize(1);
|
||||
config.setInitializationFailTimeout(0);
|
||||
|
|
10
jdbc-connection-pool/src/test/resources/logging.properties
Normal file
10
jdbc-connection-pool/src/test/resources/logging.properties
Normal file
|
@ -0,0 +1,10 @@
|
|||
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
|
||||
.level=ALL
|
||||
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] %5$s %6$s%n
|
||||
java.util.logging.ConsoleHandler.level=ALL
|
||||
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.level=ALL
|
||||
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.pattern=build/database.log
|
||||
jdk.event.security.level=INFO
|
||||
javax.management.level=INFO
|
12
jdbc-mariadb/build.gradle
Normal file
12
jdbc-mariadb/build.gradle
Normal file
|
@ -0,0 +1,12 @@
|
|||
dependencies {
|
||||
api project(':jdbc-query')
|
||||
implementation libs.mariadb
|
||||
testImplementation project(':jdbc-test')
|
||||
testImplementation libs.testcontainers
|
||||
testImplementation libs.testcontainers.junit.jupiter
|
||||
testImplementation libs.testcontainers.mariadb
|
||||
}
|
||||
|
||||
test {
|
||||
systemProperty 'user.timezone', 'GMT'
|
||||
}
|
10
jdbc-mariadb/src/main/java/module-info.java
Normal file
10
jdbc-mariadb/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
import org.xbib.jdbc.query.Flavor;
|
||||
import org.xbib.jdbc.mariadb.MariaDB;
|
||||
|
||||
module org.xbib.jdbc.mariadb {
|
||||
requires org.xbib.jdbc.query;
|
||||
requires java.sql;
|
||||
uses Flavor;
|
||||
exports org.xbib.jdbc.mariadb;
|
||||
provides Flavor with MariaDB;
|
||||
}
|
|
@ -1,27 +1,33 @@
|
|||
package org.xbib.jdbc.query.flavor;
|
||||
package org.xbib.jdbc.mariadb;
|
||||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
public class MySQL implements Flavor {
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class MariaDB implements Flavor {
|
||||
|
||||
public MariaDB() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "mysql";
|
||||
return "mariadb";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(String url) {
|
||||
return url.startsWith("jdbc:mysql:");
|
||||
return url.startsWith("jdbc:mariadb:");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String driverClass() {
|
||||
return "com.mysql.jdbc.Driver";
|
||||
return "org.mariadb.jdbc.Driver";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNormalizedUpperCase() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -41,7 +47,12 @@ public class MySQL implements Flavor {
|
|||
|
||||
@Override
|
||||
public String typeFloat() {
|
||||
return "real";
|
||||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException {
|
||||
preparedStatement.setFloat(i, floatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -49,6 +60,11 @@ public class MySQL implements Flavor {
|
|||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException {
|
||||
preparedStatement.setDouble(i, doubleValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric(" + size + "," + precision + ")";
|
||||
|
@ -56,6 +72,9 @@ public class MySQL implements Flavor {
|
|||
|
||||
@Override
|
||||
public String typeStringVar(int length) {
|
||||
if (length == 16777215) {
|
||||
return "mediumtext";
|
||||
}
|
||||
return "varchar(" + length + ")";
|
||||
}
|
||||
|
||||
|
@ -66,17 +85,17 @@ public class MySQL implements Flavor {
|
|||
|
||||
@Override
|
||||
public String typeClob() {
|
||||
return "clob";
|
||||
return "mediumtext"; // mediumtext = varchar(16777215), longtext = varchar(0)
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBlob() {
|
||||
return "blob";
|
||||
return "mediumblob";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeLocalDateTime() {
|
||||
return "timestamp";
|
||||
return "datetime(3)";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -86,42 +105,32 @@ public class MySQL implements Flavor {
|
|||
|
||||
@Override
|
||||
public boolean useStringForClob() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useBytesForBlob() {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceNextVal(String sequenceName) {
|
||||
return "next value for " + sequenceName;
|
||||
return "next value for " + sequenceName + "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceSelectNextVal(String sequenceName) {
|
||||
return "values next value for " + sequenceName;
|
||||
return "select " + sequenceNextVal(sequenceName) + fromAny();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceDrop(String sequenceName) {
|
||||
return "drop sequence " + sequenceName + " restrict";
|
||||
public String sequenceDrop(String dbtestSeq) {
|
||||
return "drop sequence if exists " + dbtestSeq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tableDrop(String table) {
|
||||
return "drop table " + table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsInsertReturning() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceCacheClause(int nbrValuesToCache) {
|
||||
return "";
|
||||
return "drop table if exists " + table;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -131,22 +140,32 @@ public class MySQL implements Flavor {
|
|||
|
||||
@Override
|
||||
public String sequenceCycleClause(boolean cycle) {
|
||||
return cycle ? " cycle" : " no cycle";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dbTimeMillis() {
|
||||
return "current_timestamp";
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fromAny() {
|
||||
return " from sysibm.sysdummy1";
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsInsertReturning() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dbTimeMillis() {
|
||||
return "localtimestamp(3)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceCacheClause(int nbrValuesToCache) {
|
||||
return " cache " + nbrValuesToCache;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
return " as bigint";
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -156,22 +175,25 @@ public class MySQL implements Flavor {
|
|||
|
||||
@Override
|
||||
public String writeNextIntoQueue(String table) {
|
||||
throw new UnsupportedOperationException();
|
||||
return "insert into " + table
|
||||
+ " (channel, data, state, delay, modified) "
|
||||
+ "values (?, ?, null, 0, ?)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readNextFromQueue(String table) {
|
||||
throw new UnsupportedOperationException();
|
||||
return "select id, data from " + table +
|
||||
" where channel = ? and state is NULL and pushed_at <= (CAST (? as TIMESTAMP) - (INTERVAL '1 minute' * delay))" +
|
||||
" order by id asc limit 1 for update skip lock";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String succeedInQueue(String table) {
|
||||
throw new UnsupportedOperationException();
|
||||
return "update" + table + " set state = 'OK', modified = " + dbTimeMillis() + " where id = ?";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String failInQueue(String table) {
|
||||
throw new UnsupportedOperationException();
|
||||
return "update" + table + " set state = 'FAIL', modified = " + dbTimeMillis() + " where id = ?";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
org.xbib.jdbc.mariadb.MariaDB
|
|
@ -0,0 +1,108 @@
|
|||
package org.xbib.jdbc.mariadb.test;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.MariaDBContainer;
|
||||
import org.xbib.jdbc.query.Config;
|
||||
import org.xbib.jdbc.query.ConfigSupplier;
|
||||
import org.xbib.jdbc.query.DatabaseProvider;
|
||||
import org.xbib.jdbc.query.OptionsOverride;
|
||||
import org.xbib.jdbc.test.CommonTest;
|
||||
|
||||
public class MariaDBTest extends CommonTest {
|
||||
|
||||
static MariaDBContainer<?> mariaDBContainer;
|
||||
|
||||
static {
|
||||
mariaDBContainer = new MariaDBContainer<>("mariadb")
|
||||
.withDatabaseName("testDB")
|
||||
.withUsername("testUser")
|
||||
.withPassword("testPassword");
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void startContainer() {
|
||||
mariaDBContainer.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopContainer() {
|
||||
mariaDBContainer.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
||||
Config config = ConfigSupplier.of()
|
||||
.property("database.url", mariaDBContainer.getJdbcUrl())
|
||||
.property("database.user", "testUser")
|
||||
.property("database.password", "testPassword")
|
||||
.get();
|
||||
return DatabaseProvider.builder(config)
|
||||
.withSqlParameterLogging()
|
||||
.withSqlInExceptionMessages()
|
||||
.withOptions(options)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB prohibits NaN and Infinity")
|
||||
@Test
|
||||
public void argFloatNaN() {
|
||||
super.argFloatNaN();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB prohibits NaN and Infinity")
|
||||
@Test
|
||||
public void argFloatInfinity() {
|
||||
super.argFloatInfinity();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB prohibits NaN and Infinity")
|
||||
@Test
|
||||
public void argDoubleNaN() {
|
||||
super.argDoubleNaN();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB prohibits NaN and Infinity")
|
||||
@Test
|
||||
public void argDoubleInfinity() {
|
||||
super.argDoubleInfinity();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB prohibits NaN and Infinity")
|
||||
@Test
|
||||
public void argFloatNegativeZero() {
|
||||
super.argFloatNegativeZero();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB prohibits NaN and Infinity")
|
||||
@Test
|
||||
public void argDoubleNegativeZero() {
|
||||
super.argDoubleNegativeZero();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB temporarily disabled")
|
||||
@Override
|
||||
public void intervals() {
|
||||
super.intervals();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB temporarily disabled")
|
||||
@Override
|
||||
public void metadataColumnNames() {
|
||||
super.intervals();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB temporarily disabled")
|
||||
@Override
|
||||
public void metadataColumnTypes() {
|
||||
super.metadataColumnTypes();
|
||||
}
|
||||
|
||||
@Disabled("MariaDB temporarily disabled")
|
||||
@Override
|
||||
public void saveResultAsTable() {
|
||||
super.saveResultAsTable();
|
||||
}
|
||||
}
|
10
jdbc-mariadb/src/test/resources/logging.properties
Normal file
10
jdbc-mariadb/src/test/resources/logging.properties
Normal file
|
@ -0,0 +1,10 @@
|
|||
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
|
||||
.level=ALL
|
||||
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] %5$s %6$s%n
|
||||
java.util.logging.ConsoleHandler.level=ALL
|
||||
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.level=ALL
|
||||
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.pattern=build/database.log
|
||||
jdk.event.security.level=INFO
|
||||
javax.management.level=INFO
|
12
jdbc-oracle/build.gradle
Normal file
12
jdbc-oracle/build.gradle
Normal file
|
@ -0,0 +1,12 @@
|
|||
dependencies {
|
||||
api project(':jdbc-query')
|
||||
implementation libs.oracle
|
||||
testImplementation project(':jdbc-test')
|
||||
testImplementation libs.testcontainers
|
||||
testImplementation libs.testcontainers.junit.jupiter
|
||||
testImplementation libs.testcontainers.oracle.xe
|
||||
}
|
||||
|
||||
test {
|
||||
systemProperty 'user.timezone', 'GMT'
|
||||
}
|
12
jdbc-oracle/src/main/java/module-info.java
Normal file
12
jdbc-oracle/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,12 @@
|
|||
import org.xbib.jdbc.oracle.Oracle;
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
module org.xbib.jdbc.oracle {
|
||||
requires org.xbib.jdbc.query;
|
||||
requires org.xbib.jdbc.connection.pool;
|
||||
requires com.oracle.database.jdbc;
|
||||
requires java.sql;
|
||||
uses Flavor;
|
||||
exports org.xbib.jdbc.oracle;
|
||||
provides Flavor with Oracle;
|
||||
}
|
|
@ -1,9 +1,17 @@
|
|||
package org.xbib.jdbc.query.flavor;
|
||||
package org.xbib.jdbc.oracle;
|
||||
|
||||
import oracle.jdbc.OraclePreparedStatement;
|
||||
import org.xbib.jdbc.connection.pool.ProxyPreparedStatement;
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class Oracle implements Flavor {
|
||||
|
||||
public Oracle() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "oracle";
|
||||
|
@ -29,11 +37,31 @@ public class Oracle implements Flavor {
|
|||
return "binary_float";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException {
|
||||
if (preparedStatement instanceof ProxyPreparedStatement) {
|
||||
ProxyPreparedStatement proxyPreparedStatement = (ProxyPreparedStatement) preparedStatement;
|
||||
((OraclePreparedStatement) proxyPreparedStatement.getDelegate()).setBinaryFloat(i, floatValue);
|
||||
} else {
|
||||
((OraclePreparedStatement) preparedStatement).setBinaryFloat(i, floatValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeDouble() {
|
||||
return "binary_double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException {
|
||||
if (preparedStatement instanceof ProxyPreparedStatement) {
|
||||
ProxyPreparedStatement proxyPreparedStatement = (ProxyPreparedStatement) preparedStatement;
|
||||
((OraclePreparedStatement) proxyPreparedStatement.getDelegate()).setBinaryDouble(i, doubleValue);
|
||||
} else {
|
||||
((OraclePreparedStatement) preparedStatement).setBinaryDouble(i, doubleValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric(" + size + "," + precision + ")";
|
|
@ -0,0 +1 @@
|
|||
org.xbib.jdbc.oracle.Oracle
|
|
@ -0,0 +1,67 @@
|
|||
package org.xbib.jdbc.oracle.test;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.OracleContainer;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.xbib.jdbc.query.Config;
|
||||
import org.xbib.jdbc.query.ConfigSupplier;
|
||||
import org.xbib.jdbc.query.DatabaseProvider;
|
||||
import org.xbib.jdbc.query.OptionsOverride;
|
||||
import org.xbib.jdbc.test.CommonTest;
|
||||
|
||||
/**
|
||||
* Exercise Database functionality with a real Oracle database.
|
||||
*/
|
||||
@Testcontainers
|
||||
public class OracleTest extends CommonTest {
|
||||
|
||||
static OracleContainer oracleContainer;
|
||||
|
||||
static {
|
||||
oracleContainer = new OracleContainer("gvenzl/oracle-xe:21.3.0-slim")
|
||||
.withDatabaseName("testDB")
|
||||
.withUsername("testUser")
|
||||
.withPassword("testPassword")
|
||||
.withExposedPorts(1521)
|
||||
.withReuse(true);
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void startContainer() {
|
||||
oracleContainer.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopContainer() {
|
||||
oracleContainer.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
||||
Config config = ConfigSupplier.of()
|
||||
.property("database.url", oracleContainer.getJdbcUrl())
|
||||
.property("database.user", "testUser")
|
||||
.property("database.password", "testPassword")
|
||||
.get();
|
||||
return DatabaseProvider.builder(config)
|
||||
.withSqlParameterLogging()
|
||||
.withSqlInExceptionMessages()
|
||||
.withOptions(options)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Disabled("Current Oracle behavior is to convert -0f to 0f")
|
||||
@Test
|
||||
public void argFloatNegativeZero() {
|
||||
super.argFloatNegativeZero();
|
||||
}
|
||||
|
||||
@Disabled("Current Oracle behavior is to convert -0d to 0d")
|
||||
@Test
|
||||
public void argDoubleNegativeZero() {
|
||||
super.argDoubleNegativeZero();
|
||||
}
|
||||
}
|
10
jdbc-oracle/src/test/resources/logging.properties
Normal file
10
jdbc-oracle/src/test/resources/logging.properties
Normal file
|
@ -0,0 +1,10 @@
|
|||
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
|
||||
.level=ALL
|
||||
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] %5$s %6$s%n
|
||||
java.util.logging.ConsoleHandler.level=ALL
|
||||
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.level=ALL
|
||||
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.pattern=build/database.log
|
||||
jdk.event.security.level=INFO
|
||||
javax.management.level=INFO
|
12
jdbc-postgresql/build.gradle
Normal file
12
jdbc-postgresql/build.gradle
Normal file
|
@ -0,0 +1,12 @@
|
|||
dependencies {
|
||||
api project(':jdbc-query')
|
||||
implementation libs.postgresql
|
||||
testImplementation project(':jdbc-test')
|
||||
testImplementation libs.testcontainers
|
||||
testImplementation libs.testcontainers.junit.jupiter
|
||||
testImplementation libs.testcontainers.postgresql
|
||||
}
|
||||
|
||||
test {
|
||||
systemProperty 'user.timezone', 'GMT'
|
||||
}
|
10
jdbc-postgresql/src/main/java/module-info.java
Normal file
10
jdbc-postgresql/src/main/java/module-info.java
Normal file
|
@ -0,0 +1,10 @@
|
|||
import org.xbib.jdbc.query.Flavor;
|
||||
import org.xbib.jdbc.postgresql.Postgresql;
|
||||
|
||||
module org.xbib.jdbc.postgresql {
|
||||
requires org.xbib.jdbc.query;
|
||||
requires java.sql;
|
||||
uses Flavor;
|
||||
exports org.xbib.jdbc.postgresql;
|
||||
provides Flavor with Postgresql;
|
||||
}
|
|
@ -1,9 +1,15 @@
|
|||
package org.xbib.jdbc.query.flavor;
|
||||
package org.xbib.jdbc.postgresql;
|
||||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class Postgresql implements Flavor {
|
||||
|
||||
public Postgresql() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "postgresql";
|
||||
|
@ -44,11 +50,21 @@ public class Postgresql implements Flavor {
|
|||
return "real";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException {
|
||||
preparedStatement.setFloat(i, floatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeDouble() {
|
||||
return "double precision";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException {
|
||||
preparedStatement.setDouble(i, doubleValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric(" + size + "," + precision + ")";
|
|
@ -0,0 +1 @@
|
|||
org.xbib.jdbc.postgresql.Postgresql
|
|
@ -0,0 +1,71 @@
|
|||
package org.xbib.jdbc.postgresql.test;
|
||||
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.xbib.jdbc.query.Config;
|
||||
import org.xbib.jdbc.query.ConfigSupplier;
|
||||
import org.xbib.jdbc.query.DatabaseProvider;
|
||||
import org.xbib.jdbc.query.OptionsOverride;
|
||||
import org.xbib.jdbc.query.Schema;
|
||||
import org.xbib.jdbc.test.CommonTest;
|
||||
|
||||
/**
|
||||
* Exercise Database functionality with a real PostgreSQL database.
|
||||
*/
|
||||
public class PostgresqlTest extends CommonTest {
|
||||
|
||||
static PostgreSQLContainer<?> postgreSQLContainer;
|
||||
|
||||
static {
|
||||
postgreSQLContainer = new PostgreSQLContainer<>("postgres")
|
||||
.withDatabaseName("testDB")
|
||||
.withUsername("testUser")
|
||||
.withPassword("testPassword");
|
||||
}
|
||||
|
||||
@BeforeAll
|
||||
public static void startContainer() {
|
||||
postgreSQLContainer.start();
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void stopContainer() {
|
||||
postgreSQLContainer.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
||||
Config config = ConfigSupplier.of()
|
||||
.property("database.url", postgreSQLContainer.getJdbcUrl())
|
||||
.property("database.user", "testUser")
|
||||
.property("database.password", "testPassword")
|
||||
.get();
|
||||
return DatabaseProvider.builder(config)
|
||||
.withSqlParameterLogging()
|
||||
.withSqlInExceptionMessages()
|
||||
.withOptions(options)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* PostgreSQL seems to have different behavior in that is does not convert
|
||||
* column names to uppercase (it actually converts them to lowercase).
|
||||
* I haven't figured out how to smooth over this difference, since all databases
|
||||
* seem to respect the provided case when it is inside quotes, but don't provide
|
||||
* a way to tell whether a particular parameter was quoted.
|
||||
*/
|
||||
@Override
|
||||
@Test
|
||||
public void metadataColumnNames() {
|
||||
db.dropTableQuietly("dbtest");
|
||||
new Schema().addTable("dbtest").addColumn("pk").primaryKey().schema().execute(db);
|
||||
db.toSelect("select Pk, Pk as Foo, Pk as \"Foo\" from dbtest")
|
||||
.query(rs -> {
|
||||
Assertions.assertArrayEquals(new String[]{"pk", "foo", "Foo"}, rs.getColumnLabels());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
10
jdbc-postgresql/src/test/resources/logging.properties
Normal file
10
jdbc-postgresql/src/test/resources/logging.properties
Normal file
|
@ -0,0 +1,10 @@
|
|||
handlers=java.util.logging.FileHandler, java.util.logging.ConsoleHandler
|
||||
.level=ALL
|
||||
java.util.logging.SimpleFormatter.format=%1$tY-%1$tm-%1$td %1$tH:%1$tM:%1$tS.%1$tL %4$-7s [%3$s] %5$s %6$s%n
|
||||
java.util.logging.ConsoleHandler.level=ALL
|
||||
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.level=ALL
|
||||
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.pattern=build/database.log
|
||||
jdk.event.security.level=INFO
|
||||
javax.management.level=INFO
|
|
@ -4,5 +4,4 @@ dependencies {
|
|||
testImplementation libs.hsqldb
|
||||
testImplementation libs.testcontainers
|
||||
testImplementation libs.testcontainers.junit.jupiter
|
||||
testImplementation libs.testcontainers.oracle.xe
|
||||
}
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
import org.xbib.jdbc.query.Flavor;
|
||||
import org.xbib.jdbc.query.flavor.Derby;
|
||||
import org.xbib.jdbc.query.flavor.Hsql;
|
||||
import org.xbib.jdbc.query.flavor.Oracle;
|
||||
import org.xbib.jdbc.query.flavor.Postgresql;
|
||||
import org.xbib.jdbc.query.flavor.SqlServer;
|
||||
|
||||
module org.xbib.jdbc.query {
|
||||
uses Flavor;
|
||||
requires transitive org.xbib.jdbc.connection.pool;
|
||||
requires org.xbib.jdbc.connection.pool;
|
||||
requires java.sql;
|
||||
exports org.xbib.jdbc.query;
|
||||
provides Flavor with Derby, Hsql, Oracle, Postgresql, SqlServer;
|
||||
provides Flavor with Derby, Hsql, SqlServer;
|
||||
}
|
||||
|
|
|
@ -28,12 +28,12 @@ public interface ConfigSupplier extends Supplier<Config> {
|
|||
|
||||
ConfigSupplier custom(Function<String, String> keyValueLookup);
|
||||
|
||||
ConfigSupplier value(String key, String value);
|
||||
|
||||
ConfigSupplier systemProperties();
|
||||
ConfigSupplier property(String key, String value);
|
||||
|
||||
ConfigSupplier env();
|
||||
|
||||
ConfigSupplier systemProperties();
|
||||
|
||||
ConfigSupplier properties(Properties properties);
|
||||
|
||||
ConfigSupplier config(Config config);
|
||||
|
|
|
@ -47,7 +47,7 @@ public class ConfigSupplierImpl implements ConfigSupplier {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ConfigSupplier value(String key, String value) {
|
||||
public ConfigSupplier property(String key, String value) {
|
||||
return custom(k -> k.equals(key) ? value : null, "value(" + key + ")");
|
||||
}
|
||||
|
||||
|
|
|
@ -259,17 +259,17 @@ public class DatabaseImpl implements Database {
|
|||
}
|
||||
Duration duration = Duration.between(appDate, dbDate).abs();
|
||||
if (duration.getSeconds() > 3600) {
|
||||
throw new DatabaseException("App and db time are over an hour apart (check your timezones) app: "
|
||||
throw new DatabaseException("JDBC and database time are over an hour apart (check your timezones) app: "
|
||||
+ appDate + " db: "
|
||||
+ dbDate);
|
||||
}
|
||||
if (duration.getSeconds() * 1000 > millisToError) {
|
||||
throw new DatabaseException("App and db time over " + millisToError + " millis apart (check your clocks) app: "
|
||||
throw new DatabaseException("JDBC and database time over " + millisToError + " millis apart (check your clocks) app: "
|
||||
+ appDate + " db: "
|
||||
+ dbDate);
|
||||
}
|
||||
if (duration.getSeconds() * 1000 > millisToWarn) {
|
||||
logger.warning("App and db time are over " + millisToWarn + " millis apart (check your clocks) app: "
|
||||
logger.warning("JDBC and database time are over " + millisToWarn + " millis apart (check your clocks) app: "
|
||||
+ appDate + " db: "
|
||||
+ dbDate);
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import java.sql.Connection;
|
|||
import java.sql.DriverManager;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.logging.Level;
|
||||
|
@ -27,33 +28,20 @@ import java.util.logging.Logger;
|
|||
* of this laziness, the underlying resources require explicit cleanup by calling either
|
||||
* commitAndClose() or rollbackAndClose().
|
||||
*/
|
||||
public final class DatabaseProvider implements Supplier<Database> {
|
||||
public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||
|
||||
private static final Logger log = Logger.getLogger(DatabaseProvider.class.getName());
|
||||
|
||||
private static final AtomicInteger poolNameCounter = new AtomicInteger(1);
|
||||
|
||||
private final Options options;
|
||||
private final DatabaseProviderBuilderImpl builder;
|
||||
|
||||
private DatabaseProvider delegateTo = null;
|
||||
private Connection connection;
|
||||
|
||||
private Supplier<Connection> connectionProvider;
|
||||
private Database database;
|
||||
|
||||
private Connection connection = null;
|
||||
|
||||
private Database database = null;
|
||||
|
||||
private DatabaseProvider(Supplier<Connection> connectionProvider, Options options) {
|
||||
if (connectionProvider == null) {
|
||||
throw new IllegalArgumentException("connection provider cannot be null");
|
||||
}
|
||||
this.connectionProvider = connectionProvider;
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
private DatabaseProvider(DatabaseProvider delegateTo) {
|
||||
this.delegateTo = delegateTo;
|
||||
this.options = delegateTo.options;
|
||||
private DatabaseProvider(DatabaseProviderBuilderImpl builder) {
|
||||
this.builder = builder;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -75,15 +63,15 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
*
|
||||
* <p>A database pool will be created using jdbc-connection-pool.</p>
|
||||
*/
|
||||
public static Builder builder(Config config) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
public static DatabaseProviderBuilder builder(Config config) throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
|
||||
return builder(createDataSource(config), getFlavor(config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Use an externally configured DataSource and a Flavor.
|
||||
*/
|
||||
public static Builder builder(DataSource ds, Flavor flavor) {
|
||||
return new BuilderImpl(ds, () -> {
|
||||
public static DatabaseProviderBuilder builder(DataSource ds, Flavor flavor) {
|
||||
return new DatabaseProviderBuilderImpl(ds, () -> {
|
||||
try {
|
||||
return ds.getConnection();
|
||||
} catch (Exception e) {
|
||||
|
@ -97,7 +85,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* the JDBC standard DriverManager method. The url parameter will be inspected
|
||||
* to determine the Flavor for this database.
|
||||
*/
|
||||
public static Builder builder(String url) {
|
||||
public static DatabaseProviderBuilder builder(String url) {
|
||||
return builder(url, Flavor.fromJdbcUrl(url), null, null, null);
|
||||
}
|
||||
|
||||
|
@ -108,7 +96,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* @param flavor use this flavor rather than guessing based on the url
|
||||
*/
|
||||
|
||||
public static Builder builder(String url, Flavor flavor) {
|
||||
public static DatabaseProviderBuilder builder(String url, Flavor flavor) {
|
||||
return builder(url, flavor, null, null, null);
|
||||
}
|
||||
|
||||
|
@ -118,7 +106,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* to determine the Flavor for this database.
|
||||
*/
|
||||
|
||||
public static Builder builder(String url, Properties info) {
|
||||
public static DatabaseProviderBuilder builder(String url, Properties info) {
|
||||
return builder(url, Flavor.fromJdbcUrl(url), info, null, null);
|
||||
}
|
||||
|
||||
|
@ -129,7 +117,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* @param flavor use this flavor rather than guessing based on the url
|
||||
*/
|
||||
|
||||
public static Builder builder(String url, Flavor flavor, Properties info) {
|
||||
public static DatabaseProviderBuilder builder(String url, Flavor flavor, Properties info) {
|
||||
return builder(url, flavor, info, null, null);
|
||||
}
|
||||
|
||||
|
@ -139,7 +127,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* to determine the Flavor for this database.
|
||||
*/
|
||||
|
||||
public static Builder builder(String url, String user, String password) {
|
||||
public static DatabaseProviderBuilder builder(String url, String user, String password) {
|
||||
return builder(url, Flavor.fromJdbcUrl(url), null, user, password);
|
||||
}
|
||||
|
||||
|
@ -150,14 +138,14 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* @param flavor use this flavor rather than guessing based on the url
|
||||
*/
|
||||
|
||||
public static Builder builder(String url,
|
||||
public static DatabaseProviderBuilder builder(String url,
|
||||
Flavor flavor,
|
||||
String user,
|
||||
String password) {
|
||||
return builder(url, flavor, null, user, password);
|
||||
}
|
||||
|
||||
private static Builder builder(String url,
|
||||
private static DatabaseProviderBuilder builder(String url,
|
||||
Flavor flavor,
|
||||
Properties info,
|
||||
String user,
|
||||
|
@ -174,7 +162,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
}
|
||||
}
|
||||
return new BuilderImpl(null, () -> {
|
||||
return new DatabaseProviderBuilderImpl(null, () -> {
|
||||
try {
|
||||
if (info != null) {
|
||||
return DriverManager.getConnection(url, info);
|
||||
|
@ -206,7 +194,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* @param propertyFileName path to the properties file we will attempt to read
|
||||
* @throws DatabaseException if the property file could not be read for any reason
|
||||
*/
|
||||
public static Builder fromPropertyFile(String propertyFileName) {
|
||||
public static DatabaseProviderBuilder fromPropertyFile(String propertyFileName) {
|
||||
return fromPropertyFile(propertyFileName, Charset.defaultCharset().newDecoder());
|
||||
}
|
||||
|
||||
|
@ -228,7 +216,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* @param decoder character encoding to use when reading the property file
|
||||
* @throws DatabaseException if the property file could not be read for any reason
|
||||
*/
|
||||
public static Builder fromPropertyFile(String propertyFileName, CharsetDecoder decoder) {
|
||||
public static DatabaseProviderBuilder fromPropertyFile(String propertyFileName, CharsetDecoder decoder) {
|
||||
Properties properties = new Properties();
|
||||
if (propertyFileName != null && propertyFileName.length() > 0) {
|
||||
try (
|
||||
|
@ -265,7 +253,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* pass "my." as the prefix)
|
||||
* @throws DatabaseException if the property file could not be read for any reason
|
||||
*/
|
||||
public static Builder fromPropertyFile(String filename, String propertyPrefix) {
|
||||
public static DatabaseProviderBuilder fromPropertyFile(String filename, String propertyPrefix) {
|
||||
return fromPropertyFile(filename, propertyPrefix, Charset.defaultCharset().newDecoder());
|
||||
}
|
||||
|
||||
|
@ -291,7 +279,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* @param decoder character encoding to use when reading the property file
|
||||
* @throws DatabaseException if the property file could not be read for any reason
|
||||
*/
|
||||
public static Builder fromPropertyFile(String filename, String propertyPrefix, CharsetDecoder decoder) {
|
||||
public static DatabaseProviderBuilder fromPropertyFile(String filename, String propertyPrefix, CharsetDecoder decoder) {
|
||||
Properties properties = new Properties();
|
||||
if (filename != null && filename.length() > 0) {
|
||||
try (
|
||||
|
@ -323,7 +311,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* @param properties properties will be read from here
|
||||
* @throws DatabaseException if the property file could not be read for any reason
|
||||
*/
|
||||
public static Builder fromProperties(Properties properties) {
|
||||
public static DatabaseProviderBuilder fromProperties(Properties properties) {
|
||||
return fromProperties(properties, "", false);
|
||||
}
|
||||
|
||||
|
@ -348,7 +336,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* pass "my." as the prefix)
|
||||
* @throws DatabaseException if the property file could not be read for any reason
|
||||
*/
|
||||
public static Builder fromProperties(Properties properties, String propertyPrefix) {
|
||||
public static DatabaseProviderBuilder fromProperties(Properties properties, String propertyPrefix) {
|
||||
return fromProperties(properties, propertyPrefix, false);
|
||||
}
|
||||
|
||||
|
@ -374,7 +362,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* log entry will be entered, but it will attempt to proceed using
|
||||
* solely the system properties
|
||||
*/
|
||||
public static Builder fromPropertyFileOrSystemProperties(String filename) {
|
||||
public static DatabaseProviderBuilder fromPropertyFileOrSystemProperties(String filename) {
|
||||
return fromPropertyFileOrSystemProperties(filename, Charset.defaultCharset().newDecoder());
|
||||
}
|
||||
|
||||
|
@ -400,7 +388,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* solely the system properties
|
||||
* @param decoder character encoding to use when reading the property file
|
||||
*/
|
||||
public static Builder fromPropertyFileOrSystemProperties(String filename, CharsetDecoder decoder) {
|
||||
public static DatabaseProviderBuilder fromPropertyFileOrSystemProperties(String filename, CharsetDecoder decoder) {
|
||||
Properties properties = new Properties();
|
||||
if (filename != null && filename.length() > 0) {
|
||||
try (
|
||||
|
@ -441,7 +429,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* (exactly, so if you want to use "my.database.url" you must
|
||||
* pass "my." as the prefix)
|
||||
*/
|
||||
public static Builder fromPropertyFileOrSystemProperties(String filename, String propertyPrefix) {
|
||||
public static DatabaseProviderBuilder fromPropertyFileOrSystemProperties(String filename, String propertyPrefix) {
|
||||
return fromPropertyFileOrSystemProperties(filename, propertyPrefix, Charset.defaultCharset().newDecoder());
|
||||
}
|
||||
|
||||
|
@ -471,7 +459,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* pass "my." as the prefix)
|
||||
* @param decoder character encoding to use when reading the property file
|
||||
*/
|
||||
public static Builder fromPropertyFileOrSystemProperties(String filename, String propertyPrefix,
|
||||
public static DatabaseProviderBuilder fromPropertyFileOrSystemProperties(String filename, String propertyPrefix,
|
||||
CharsetDecoder decoder) {
|
||||
Properties properties = new Properties();
|
||||
if (filename != null && filename.length() > 0) {
|
||||
|
@ -502,7 +490,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* </pre>
|
||||
*/
|
||||
|
||||
public static Builder fromSystemProperties() {
|
||||
public static DatabaseProviderBuilder fromSystemProperties() {
|
||||
return fromProperties(null, "", true);
|
||||
}
|
||||
|
||||
|
@ -524,11 +512,11 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* dot if desired (e.g. "mydb." for properties like -Dmydb.database.url)
|
||||
*/
|
||||
|
||||
public static Builder fromSystemProperties(String propertyPrefix) {
|
||||
public static DatabaseProviderBuilder fromSystemProperties(String propertyPrefix) {
|
||||
return fromProperties(null, propertyPrefix, true);
|
||||
}
|
||||
|
||||
private static Builder fromProperties(Properties properties, String propertyPrefix, boolean useSystemProperties) {
|
||||
private static DatabaseProviderBuilder fromProperties(Properties properties, String propertyPrefix, boolean useSystemProperties) {
|
||||
if (propertyPrefix == null) {
|
||||
propertyPrefix = "";
|
||||
}
|
||||
|
@ -599,7 +587,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
}
|
||||
|
||||
public static DataSource createDataSource(Config config)
|
||||
private static DataSource createDataSource(Config config)
|
||||
throws ClassNotFoundException, InvocationTargetException, NoSuchMethodException, InstantiationException,
|
||||
IllegalAccessException {
|
||||
String url = config.getString("database.url");
|
||||
|
@ -621,7 +609,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
return new PoolDataSource(poolConfig);
|
||||
}
|
||||
|
||||
public static Flavor getFlavor(Config config) {
|
||||
private static Flavor getFlavor(Config config) {
|
||||
String url = config.getString("database.url");
|
||||
if (url == null) {
|
||||
throw new DatabaseException("You must provide database.url");
|
||||
|
@ -755,30 +743,27 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
|
||||
public Database get() {
|
||||
if (delegateTo != null) {
|
||||
return delegateTo.get();
|
||||
}
|
||||
if (database != null) {
|
||||
return database;
|
||||
}
|
||||
if (connectionProvider == null) {
|
||||
if (builder.isClosed()) {
|
||||
throw new DatabaseException("Called get() on a DatabaseProvider after close()");
|
||||
}
|
||||
Metric metric = new Metric(log.isLoggable(Level.FINE));
|
||||
try {
|
||||
connection = connectionProvider.get();
|
||||
connection = builder.connectionProvider.get();
|
||||
metric.checkpoint("getConn");
|
||||
try {
|
||||
// JDBC specifies that autoCommit is the default for all new connections.
|
||||
// Don't try to be clever about clearing it conditionally.
|
||||
if (!options.flavor().isAutoCommitOnly()) {
|
||||
if (!builder.options.flavor().isAutoCommitOnly()) {
|
||||
connection.setAutoCommit(false);
|
||||
metric.checkpoint("setAutoCommit");
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
throw new DatabaseException("Unable to set autoCommit for the connection", e);
|
||||
}
|
||||
database = new DatabaseImpl(connection, options);
|
||||
database = new DatabaseImpl(connection, builder.options);
|
||||
metric.checkpoint("dbInit");
|
||||
} catch (RuntimeException e) {
|
||||
metric.checkpoint("fail");
|
||||
|
@ -786,7 +771,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
} finally {
|
||||
metric.done();
|
||||
if (log.isLoggable(Level.FINE)) {
|
||||
StringBuilder buf = new StringBuilder("Get ").append(options.flavor()).append(" database: ");
|
||||
StringBuilder buf = new StringBuilder("Get ").append(builder.options.flavor()).append(" database: ");
|
||||
metric.printMessage(buf);
|
||||
log.fine(buf.toString());
|
||||
}
|
||||
|
@ -794,78 +779,10 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
return database;
|
||||
}
|
||||
|
||||
public Builder fakeBuilder() {
|
||||
return new Builder() {
|
||||
@Override
|
||||
public Builder withOptions(OptionsOverride optionsOverride) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder withSqlParameterLogging() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder withSqlInExceptionMessages() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder withDatePerAppOnly() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder withTransactionControl() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder withTransactionControlSilentlyIgnored() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder withConnectionAccess() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DatabaseProvider build() {
|
||||
return new DatabaseProvider(DatabaseProvider.this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transact(DbCode tx) {
|
||||
build().transact(tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T transactReturning(DbCodeTyped<T> tx) {
|
||||
return build().transactReturning(tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void transact(DbCodeTx tx) {
|
||||
build().transact(tx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
log.fine("Ignoring close call on fakeBuilder");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public void commit() {
|
||||
if (delegateTo != null) {
|
||||
log.fine("Ignoring commit() because this is a fake provider");
|
||||
return;
|
||||
}
|
||||
if (connection != null) {
|
||||
try {
|
||||
if (!options.flavor().isAutoCommitOnly()) {
|
||||
if (!builder.options.flavor().isAutoCommitOnly()) {
|
||||
connection.commit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -875,31 +792,22 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
|
||||
public void commitAndClose() {
|
||||
if (delegateTo != null) {
|
||||
log.fine("Ignoring commitAndClose() because this is a fake provider");
|
||||
return;
|
||||
}
|
||||
if (connection != null) {
|
||||
try {
|
||||
if (!options.flavor().isAutoCommitOnly()) {
|
||||
if (connection != null) {
|
||||
if (!builder.options.flavor().isAutoCommitOnly()) {
|
||||
connection.commit();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new DatabaseException("Unable to commit the transaction", e);
|
||||
}
|
||||
close();
|
||||
} catch (Exception e) {
|
||||
throw new DatabaseException("Unable to commit the transaction", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void rollback() {
|
||||
if (delegateTo != null) {
|
||||
log.fine("Ignoring rollback() because this is a fake provider");
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection != null) {
|
||||
try {
|
||||
if (!options.flavor().isAutoCommitOnly()) {
|
||||
if (!builder.options.flavor().isAutoCommitOnly()) {
|
||||
connection.rollback();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -909,24 +817,20 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
|
||||
public void rollbackAndClose() {
|
||||
if (delegateTo != null) {
|
||||
log.fine("Ignoring rollbackAndClose() because this is a fake provider");
|
||||
return;
|
||||
}
|
||||
|
||||
if (connection != null) {
|
||||
try {
|
||||
if (!options.flavor().isAutoCommitOnly()) {
|
||||
if (connection != null) {
|
||||
if (!builder.options.flavor().isAutoCommitOnly()) {
|
||||
connection.rollback();
|
||||
}
|
||||
}
|
||||
close();
|
||||
} catch (Exception e) {
|
||||
log.log(Level.SEVERE, "Unable to rollback the transaction", e);
|
||||
}
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
private void close() {
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (connection != null) {
|
||||
try {
|
||||
connection.close();
|
||||
|
@ -936,7 +840,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
connection = null;
|
||||
database = null;
|
||||
connectionProvider = null;
|
||||
builder.close();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -944,15 +848,15 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* the previous instance. This is intended to make it safe to pass builders
|
||||
* around without risk someone will reconfigure it.
|
||||
*/
|
||||
public interface Builder {
|
||||
public interface DatabaseProviderBuilder {
|
||||
|
||||
Builder withOptions(OptionsOverride options);
|
||||
DatabaseProviderBuilder withOptions(OptionsOverride options);
|
||||
|
||||
/**
|
||||
* Enable logging of parameter values along with the SQL.
|
||||
*/
|
||||
|
||||
Builder withSqlParameterLogging();
|
||||
DatabaseProviderBuilder withSqlParameterLogging();
|
||||
|
||||
/**
|
||||
* Include SQL in exception messages. This will also include parameters in the
|
||||
|
@ -961,7 +865,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* dependent on how the exception are caught and handled.
|
||||
*/
|
||||
|
||||
Builder withSqlInExceptionMessages();
|
||||
DatabaseProviderBuilder withSqlInExceptionMessages();
|
||||
|
||||
/**
|
||||
* Wherever argDateNowPerDb() is specified, use argDateNowPerApp() instead. This is
|
||||
|
@ -969,7 +873,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* own system clock that will be used for time travel.
|
||||
*/
|
||||
|
||||
Builder withDatePerAppOnly();
|
||||
DatabaseProviderBuilder withDatePerAppOnly();
|
||||
|
||||
/**
|
||||
* Allow provided Database instances to explicitly control transactions using the
|
||||
|
@ -977,14 +881,14 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* throw an exception.
|
||||
*/
|
||||
|
||||
Builder withTransactionControl();
|
||||
DatabaseProviderBuilder withTransactionControl();
|
||||
|
||||
/**
|
||||
* This can be useful when testing code, as it can pretend to use transactions,
|
||||
* while giving you control over whether it actually commits or rolls back.
|
||||
*/
|
||||
|
||||
Builder withTransactionControlSilentlyIgnored();
|
||||
DatabaseProviderBuilder withTransactionControlSilentlyIgnored();
|
||||
|
||||
/**
|
||||
* Allow direct access to the underlying database connection. Normally this is
|
||||
|
@ -992,7 +896,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
* legacy code that works with raw JDBC.
|
||||
*/
|
||||
|
||||
Builder withConnectionAccess();
|
||||
DatabaseProviderBuilder withConnectionAccess();
|
||||
|
||||
/**
|
||||
* WARNING: You should try to avoid using this method. If you use it more
|
||||
|
@ -1060,31 +964,35 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
*/
|
||||
void transact(DbCodeTx code);
|
||||
|
||||
void close() throws IOException;
|
||||
}
|
||||
|
||||
private static class BuilderImpl implements Builder {
|
||||
private static class DatabaseProviderBuilderImpl implements DatabaseProviderBuilder, Closeable {
|
||||
|
||||
private DataSource ds;
|
||||
private DataSource dataSource;
|
||||
|
||||
private final Supplier<Connection> connectionProvider;
|
||||
|
||||
private final Options options;
|
||||
|
||||
private BuilderImpl(DataSource ds, Supplier<Connection> connectionProvider, Options options) {
|
||||
this.ds = ds;
|
||||
private final AtomicBoolean closed;
|
||||
|
||||
private DatabaseProviderBuilderImpl(DataSource dataSource,
|
||||
Supplier<Connection> connectionProvider,
|
||||
Options options) {
|
||||
this.dataSource = dataSource;
|
||||
this.connectionProvider = connectionProvider;
|
||||
this.options = options;
|
||||
this.closed = new AtomicBoolean(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder withOptions(OptionsOverride options) {
|
||||
return new BuilderImpl(ds, connectionProvider, options.withParent(this.options));
|
||||
public DatabaseProviderBuilder withOptions(OptionsOverride options) {
|
||||
return new DatabaseProviderBuilderImpl(dataSource, connectionProvider, options.withParent(this.options));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder withSqlParameterLogging() {
|
||||
return new BuilderImpl(ds, connectionProvider, new OptionsOverride() {
|
||||
public DatabaseProviderBuilder withSqlParameterLogging() {
|
||||
return new DatabaseProviderBuilderImpl(dataSource, connectionProvider, new OptionsOverride() {
|
||||
@Override
|
||||
public boolean isLogParameters() {
|
||||
return true;
|
||||
|
@ -1093,8 +1001,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Builder withSqlInExceptionMessages() {
|
||||
return new BuilderImpl(ds, connectionProvider, new OptionsOverride() {
|
||||
public DatabaseProviderBuilder withSqlInExceptionMessages() {
|
||||
return new DatabaseProviderBuilderImpl(dataSource, connectionProvider, new OptionsOverride() {
|
||||
@Override
|
||||
public boolean isDetailedExceptions() {
|
||||
return true;
|
||||
|
@ -1103,8 +1011,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Builder withDatePerAppOnly() {
|
||||
return new BuilderImpl(ds, connectionProvider, new OptionsOverride() {
|
||||
public DatabaseProviderBuilder withDatePerAppOnly() {
|
||||
return new DatabaseProviderBuilderImpl(dataSource, connectionProvider, new OptionsOverride() {
|
||||
@Override
|
||||
public boolean useLocalDateTimeOnly() {
|
||||
return true;
|
||||
|
@ -1113,8 +1021,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Builder withTransactionControl() {
|
||||
return new BuilderImpl(ds, connectionProvider, new OptionsOverride() {
|
||||
public DatabaseProviderBuilder withTransactionControl() {
|
||||
return new DatabaseProviderBuilderImpl(dataSource, connectionProvider, new OptionsOverride() {
|
||||
@Override
|
||||
public boolean allowTransactionControl() {
|
||||
return true;
|
||||
|
@ -1123,8 +1031,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Builder withTransactionControlSilentlyIgnored() {
|
||||
return new BuilderImpl(ds, connectionProvider, new OptionsOverride() {
|
||||
public DatabaseProviderBuilder withTransactionControlSilentlyIgnored() {
|
||||
return new DatabaseProviderBuilderImpl(dataSource, connectionProvider, new OptionsOverride() {
|
||||
@Override
|
||||
public boolean ignoreTransactionControl() {
|
||||
return true;
|
||||
|
@ -1133,8 +1041,8 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public Builder withConnectionAccess() {
|
||||
return new BuilderImpl(ds, connectionProvider, new OptionsOverride() {
|
||||
public DatabaseProviderBuilder withConnectionAccess() {
|
||||
return new DatabaseProviderBuilderImpl(dataSource, connectionProvider, new OptionsOverride() {
|
||||
@Override
|
||||
public boolean allowConnectionAccess() {
|
||||
return true;
|
||||
|
@ -1144,7 +1052,7 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
|
||||
@Override
|
||||
public DatabaseProvider build() {
|
||||
return new DatabaseProvider(connectionProvider, options);
|
||||
return new DatabaseProvider(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1164,12 +1072,18 @@ public final class DatabaseProvider implements Supplier<Database> {
|
|||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
if (ds != null) {
|
||||
if (ds instanceof Closeable) {
|
||||
((Closeable) ds).close();
|
||||
if (closed.compareAndSet(false, true)) {
|
||||
if (dataSource != null) {
|
||||
if (dataSource instanceof Closeable) {
|
||||
((Closeable) dataSource).close();
|
||||
}
|
||||
ds = null;
|
||||
dataSource = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return closed.get();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package org.xbib.jdbc.query;
|
|||
import org.xbib.jdbc.query.util.DebugSql;
|
||||
import org.xbib.jdbc.query.util.Metric;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.Statement;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
@ -13,8 +13,6 @@ public class DdlImpl implements Ddl {
|
|||
|
||||
private static final Logger log = Logger.getLogger(Database.class.getName());
|
||||
|
||||
private static final Logger logQuiet = Logger.getLogger(Database.class.getName() + ".quiet");
|
||||
|
||||
private final Connection connection;
|
||||
|
||||
private final String sql;
|
||||
|
@ -28,15 +26,15 @@ public class DdlImpl implements Ddl {
|
|||
}
|
||||
|
||||
private void updateInternal(boolean quiet) {
|
||||
CallableStatement ps = null;
|
||||
PreparedStatement preparedStatement = null;
|
||||
Metric metric = new Metric(log.isLoggable(Level.FINE));
|
||||
boolean isSuccess = false;
|
||||
String errorCode = null;
|
||||
Exception logEx = null;
|
||||
try {
|
||||
ps = connection.prepareCall(sql);
|
||||
preparedStatement = connection.prepareStatement(sql);
|
||||
metric.checkpoint("prep");
|
||||
ps.execute();
|
||||
preparedStatement.execute();
|
||||
metric.checkpoint("exec");
|
||||
isSuccess = true;
|
||||
} catch (Exception e) {
|
||||
|
@ -44,15 +42,13 @@ public class DdlImpl implements Ddl {
|
|||
logEx = e;
|
||||
throw DatabaseException.wrap(DebugSql.exceptionMessage(sql, null, errorCode, options), e);
|
||||
} finally {
|
||||
close(ps);
|
||||
close(preparedStatement);
|
||||
metric.checkpoint("close");
|
||||
// PostgreSQL requires explicit commit since we are running with setAutoCommit(false)
|
||||
commit(connection);
|
||||
metric.done("commit");
|
||||
if (isSuccess) {
|
||||
DebugSql.logSuccess("DDL", log, metric, sql, null, options);
|
||||
} else if (quiet) {
|
||||
DebugSql.logWarning("DDL", logQuiet, metric, errorCode, sql, null, options, logEx);
|
||||
} else {
|
||||
DebugSql.logError("DDL", log, metric, errorCode, sql, null, options, logEx);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package org.xbib.jdbc.query;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
public interface Flavor {
|
||||
|
@ -24,8 +26,12 @@ public interface Flavor {
|
|||
|
||||
String typeFloat();
|
||||
|
||||
void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException;
|
||||
|
||||
String typeDouble();
|
||||
|
||||
void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException;
|
||||
|
||||
String typeBigDecimal(int size, int precision);
|
||||
|
||||
String typeStringVar(int length);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package org.xbib.jdbc.query;
|
||||
|
||||
import org.xbib.jdbc.query.flavor.Postgresql;
|
||||
import org.xbib.jdbc.query.flavor.Derby;
|
||||
|
||||
/**
|
||||
* Base class for selectively overriding another Options object.
|
||||
|
@ -18,10 +18,10 @@ public class OptionsOverride implements Options {
|
|||
}
|
||||
|
||||
/**
|
||||
* Defer to OptionsDefault for anything that is not specified, and use postgresql flavor.
|
||||
* Defer to OptionsDefault for anything that is not specified.
|
||||
*/
|
||||
public OptionsOverride() {
|
||||
parent = new OptionsDefault(new Postgresql());
|
||||
parent = new OptionsDefault(new Derby());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,8 +5,6 @@ import org.xbib.jdbc.query.Schema.Table.Column;
|
|||
import org.xbib.jdbc.query.Schema.Table.ForeignKey;
|
||||
import org.xbib.jdbc.query.Schema.Table.Index;
|
||||
import org.xbib.jdbc.query.Schema.Table.Unique;
|
||||
import org.xbib.jdbc.query.flavor.Oracle;
|
||||
import org.xbib.jdbc.query.flavor.Postgresql;
|
||||
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
|
@ -93,13 +91,14 @@ public class Schema {
|
|||
table.addColumn(names[i]).asLong();
|
||||
break;
|
||||
case Types.REAL:
|
||||
case 100: // Oracle proprietary it seems
|
||||
case 100: // Oracle "binary float"
|
||||
table.addColumn(names[i]).asFloat();
|
||||
break;
|
||||
case Types.DOUBLE:
|
||||
case 101: // Oracle proprietary it seems
|
||||
case 101: // Oracle "binary double"
|
||||
table.addColumn(names[i]).asDouble();
|
||||
break;
|
||||
case Types.DECIMAL:
|
||||
case Types.NUMERIC:
|
||||
int precision1 = metadata.getPrecision(i + 1);
|
||||
int scale = metadata.getScale(i + 1);
|
||||
|
@ -121,6 +120,7 @@ public class Schema {
|
|||
break;
|
||||
case Types.BINARY:
|
||||
case Types.VARBINARY:
|
||||
case Types.LONGVARBINARY:
|
||||
case Types.BLOB:
|
||||
table.addColumn(names[i]).asBlob();
|
||||
break;
|
||||
|
@ -128,14 +128,12 @@ public class Schema {
|
|||
case Types.NCLOB:
|
||||
table.addColumn(names[i]).asClob();
|
||||
break;
|
||||
|
||||
// The date type is used for a true date - no time info.
|
||||
// It must be checked before TimeStamp because sql dates are also
|
||||
// recognized as sql timestamp.
|
||||
case Types.DATE:
|
||||
table.addColumn(names[i]).asLocalDate();
|
||||
break;
|
||||
|
||||
// This is the type dates and times with time and time zone associated.
|
||||
// Note that Oracle dates are always really Timestamps.
|
||||
case Types.TIMESTAMP:
|
||||
|
@ -149,9 +147,9 @@ public class Schema {
|
|||
table.addColumn(names[i]).asLocalDateTime();
|
||||
}
|
||||
break;
|
||||
|
||||
case Types.NVARCHAR:
|
||||
case Types.VARCHAR:
|
||||
case Types.LONGVARCHAR:
|
||||
int precision = metadata.getPrecision(i + 1);
|
||||
if (precision >= 2147483647) {
|
||||
// Postgres seems to report clobs are varchar(2147483647)
|
||||
|
@ -160,8 +158,8 @@ public class Schema {
|
|||
table.addColumn(names[i]).asString(precision);
|
||||
}
|
||||
break;
|
||||
case Types.CHAR:
|
||||
case Types.NCHAR:
|
||||
case Types.CHAR:
|
||||
table.addColumn(names[i]).asStringFixed(metadata.getPrecision(i + 1));
|
||||
break;
|
||||
default:
|
||||
|
@ -184,12 +182,10 @@ public class Schema {
|
|||
|
||||
private String executeOrPrint(Database db, Flavor flavor) {
|
||||
validate();
|
||||
|
||||
if (flavor == null) {
|
||||
flavor = db.flavor();
|
||||
}
|
||||
StringBuilder script = new StringBuilder();
|
||||
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
for (Table table : tables) {
|
||||
Sql sql = new Sql();
|
||||
sql.append("create table ").append(table.name).append(" (\n");
|
||||
|
@ -228,10 +224,10 @@ public class Schema {
|
|||
sql.append(flavor.typeStringFixed(column.scale));
|
||||
break;
|
||||
case LocalDateTime:
|
||||
sql.append(flavor.typeLocalDateTime()); // Append a date with time
|
||||
sql.append(flavor.typeLocalDateTime());
|
||||
break;
|
||||
case LocalDate:
|
||||
sql.append(flavor.typeLocalDate()); // Append a true date - no time
|
||||
sql.append(flavor.typeLocalDate());
|
||||
break;
|
||||
case Clob:
|
||||
sql.append(flavor.typeClob());
|
||||
|
@ -244,7 +240,6 @@ public class Schema {
|
|||
sql.append(" not null");
|
||||
}
|
||||
}
|
||||
|
||||
if (table.primaryKey != null) {
|
||||
sql.append(",\n constraint ");
|
||||
sql.append(rpad(table.primaryKey.name, 30));
|
||||
|
@ -278,16 +273,16 @@ public class Schema {
|
|||
if (table.customClauses.containsKey(flavor)) {
|
||||
sql.append(" ").append(table.customClauses.get(flavor));
|
||||
}
|
||||
executeOrPrint(sql, db, script);
|
||||
executeOrPrint(sql, db, stringBuilder);
|
||||
sql = new Sql();
|
||||
if (flavor instanceof Oracle || flavor instanceof Postgresql) {
|
||||
if ("oracle".equals(flavor.getName()) || "postgresql".equals(flavor.getName())) {
|
||||
if (table.comment != null) {
|
||||
sql.append("comment on table ");
|
||||
sql.append(table.name);
|
||||
sql.append(" is \n'");
|
||||
sql.append(table.comment.replace("'", "''"));
|
||||
sql.append("'");
|
||||
executeOrPrint(sql, db, script);
|
||||
executeOrPrint(sql, db, stringBuilder);
|
||||
sql = new Sql();
|
||||
}
|
||||
for (Column c : table.columns) {
|
||||
|
@ -299,7 +294,7 @@ public class Schema {
|
|||
sql.append(" is \n'");
|
||||
sql.append(c.comment.replace("'", "''"));
|
||||
sql.append("'");
|
||||
executeOrPrint(sql, db, script);
|
||||
executeOrPrint(sql, db, stringBuilder);
|
||||
sql = new Sql();
|
||||
}
|
||||
}
|
||||
|
@ -322,7 +317,7 @@ public class Schema {
|
|||
if (fk.onDeleteCascade) {
|
||||
sql.append(" on delete cascade");
|
||||
}
|
||||
executeOrPrint(sql, db, script);
|
||||
executeOrPrint(sql, db, stringBuilder);
|
||||
}
|
||||
}
|
||||
for (Table table : tables) {
|
||||
|
@ -342,10 +337,9 @@ public class Schema {
|
|||
sql.append(name);
|
||||
}
|
||||
sql.listEnd(")");
|
||||
executeOrPrint(sql, db, script);
|
||||
executeOrPrint(sql, db, stringBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
for (Sequence sequence : sequences) {
|
||||
Sql sql = new Sql();
|
||||
sql.append("create sequence ");
|
||||
|
@ -362,11 +356,10 @@ public class Schema {
|
|||
sql.append(flavor.sequenceCacheClause(sequence.cache));
|
||||
sql.append(flavor.sequenceOrderClause(sequence.order));
|
||||
sql.append(flavor.sequenceCycleClause(sequence.cycle));
|
||||
executeOrPrint(sql, db, script);
|
||||
executeOrPrint(sql, db, stringBuilder);
|
||||
}
|
||||
|
||||
if (db == null) {
|
||||
return script.toString();
|
||||
return stringBuilder.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -865,12 +858,10 @@ public class Schema {
|
|||
return asType(ColumnType.StringFixed);
|
||||
}
|
||||
|
||||
// This type is for dates that have time associated
|
||||
public Column asLocalDateTime() {
|
||||
return asType(ColumnType.LocalDateTime);
|
||||
}
|
||||
|
||||
// This type is for true dates with no time associated
|
||||
public Column asLocalDate() {
|
||||
return asType(ColumnType.LocalDate);
|
||||
}
|
||||
|
|
|
@ -668,6 +668,7 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
case 101: // Oracle binary double
|
||||
args.argDouble(names[i], r.getDoubleOrNull());
|
||||
break;
|
||||
case Types.DECIMAL:
|
||||
case Types.NUMERIC:
|
||||
if (precision[i] <= 10 && scale[i] == 0) {
|
||||
args.argInteger(names[i], r.getIntegerOrNull());
|
||||
|
@ -703,6 +704,8 @@ public class SqlArgs implements SqlInsert.Apply, SqlUpdate.Apply, SqlSelect.Appl
|
|||
case Types.VARCHAR:
|
||||
case Types.CHAR:
|
||||
case Types.NCHAR:
|
||||
case Types.LONGVARCHAR:
|
||||
case Types.LONGNVARCHAR:
|
||||
if (precision[i] >= 2147483647) {
|
||||
// Postgres seems to report clobs are varchar(2147483647)
|
||||
args.argClobString(names[i], r.getClobStringOrNull());
|
||||
|
|
|
@ -33,7 +33,7 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
|
||||
private final Connection connection;
|
||||
|
||||
private final StatementAdaptor adaptor;
|
||||
private final StatementAdapter adaptor;
|
||||
|
||||
private final String sql;
|
||||
|
||||
|
@ -57,7 +57,7 @@ public class SqlInsertImpl implements SqlInsert {
|
|||
this.connection = connection;
|
||||
this.sql = sql;
|
||||
this.options = options;
|
||||
adaptor = new StatementAdaptor(options);
|
||||
adaptor = new StatementAdapter(options);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
|
||||
private final Connection connection;
|
||||
|
||||
private final StatementAdaptor adaptor;
|
||||
private final StatementAdapter adaptor;
|
||||
|
||||
private final Object cancelLock = new Object();
|
||||
|
||||
|
@ -52,7 +52,7 @@ public class SqlSelectImpl implements SqlSelect {
|
|||
this.connection = connection;
|
||||
this.sql = sql;
|
||||
this.options = options;
|
||||
adaptor = new StatementAdaptor(options);
|
||||
adaptor = new StatementAdapter(options);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public class SqlUpdateImpl implements SqlUpdate {
|
|||
|
||||
private final Connection connection;
|
||||
|
||||
private final StatementAdaptor adaptor;
|
||||
private final StatementAdapter adaptor;
|
||||
|
||||
private final String sql;
|
||||
|
||||
|
@ -47,7 +47,7 @@ public class SqlUpdateImpl implements SqlUpdate {
|
|||
this.connection = connection;
|
||||
this.sql = sql;
|
||||
this.options = options;
|
||||
adaptor = new StatementAdaptor(options);
|
||||
adaptor = new StatementAdapter(options);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -22,13 +22,13 @@ import java.util.stream.Collectors;
|
|||
/**
|
||||
* Deal with mapping parameters into prepared statements.
|
||||
*/
|
||||
public class StatementAdaptor {
|
||||
public class StatementAdapter {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(StatementAdaptor.class.getName());
|
||||
private static final Logger logger = Logger.getLogger(StatementAdapter.class.getName());
|
||||
|
||||
private final Options options;
|
||||
|
||||
public StatementAdaptor(Options options) {
|
||||
public StatementAdapter(Options options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
||||
|
@ -90,9 +90,9 @@ public class StatementAdaptor {
|
|||
ps.setBinaryStream(i + 1, (InputStream) parameter);
|
||||
}
|
||||
} else if (parameter instanceof Float) {
|
||||
ps.setFloat(i + 1, (Float) parameter);
|
||||
options.flavor().setFloat(ps, i + 1, (Float) parameter);
|
||||
} else if (parameter instanceof Double) {
|
||||
ps.setDouble(i + 1, (Double) parameter);
|
||||
options.flavor().setDouble(ps, i + 1, (Double) parameter);
|
||||
} else {
|
||||
ps.setObject(i + 1, parameter);
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
package org.xbib.jdbc.query;
|
||||
|
||||
import org.xbib.jdbc.query.flavor.Derby;
|
||||
import org.xbib.jdbc.query.flavor.Oracle;
|
||||
import org.xbib.jdbc.query.flavor.Postgresql;
|
||||
import org.xbib.jdbc.query.flavor.SqlServer;
|
||||
|
||||
import java.util.Objects;
|
||||
|
@ -21,7 +19,7 @@ public class When {
|
|||
}
|
||||
|
||||
public When oracle(String sql) {
|
||||
if (actualFlavor instanceof Oracle) {
|
||||
if ("oracle".equals(actualFlavor.getName())) {
|
||||
chosen = sql;
|
||||
}
|
||||
return this;
|
||||
|
@ -35,7 +33,7 @@ public class When {
|
|||
}
|
||||
|
||||
public When postgres(String sql) {
|
||||
if (actualFlavor instanceof Postgresql) {
|
||||
if ("postgresql".equals(actualFlavor.getName())) {
|
||||
chosen = sql;
|
||||
}
|
||||
return this;
|
||||
|
|
|
@ -1,177 +0,0 @@
|
|||
package org.xbib.jdbc.query.flavor;
|
||||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
public class BigQuery implements Flavor {
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return "bigQuery";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supports(String url) {
|
||||
return url.startsWith("jdbc:bigquery:");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String driverClass() {
|
||||
return "com.simba.googlebigquery.jdbc42.Driver";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNormalizedUpperCase() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeInteger() {
|
||||
return "int64";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBoolean() {
|
||||
// BigQuery has a native boolean type, but we're not trying to use it
|
||||
return "string";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeLong() {
|
||||
return "int64";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeFloat() {
|
||||
return "float64";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeDouble() {
|
||||
return "float64";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeStringVar(int length) {
|
||||
return "string";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeStringFixed(int length) {
|
||||
return "string";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeClob() {
|
||||
return "string";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBlob() {
|
||||
return "bytes";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeLocalDateTime() {
|
||||
return "datetime";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeLocalDate() {
|
||||
return "date";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useStringForClob() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useBytesForBlob() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceNextVal(String sequenceName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceSelectNextVal(String sequenceName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceDrop(String dbtestSeq) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tableDrop(String table) {
|
||||
return "drop table " + table;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsInsertReturning() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String dbTimeMillis() {
|
||||
return "current_timestamp()";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceCacheClause(int nbrValuesToCache) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOrderClause(boolean order) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceCycleClause(boolean cycle) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fromAny() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sequenceOptions() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAutoCommitOnly() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String writeNextIntoQueue(String table) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String readNextFromQueue(String table) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String succeedInQueue(String table) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String failInQueue(String table) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
|
@ -2,6 +2,9 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class Derby implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -44,11 +47,21 @@ public class Derby implements Flavor {
|
|||
return "real";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException {
|
||||
preparedStatement.setFloat(i, floatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeDouble() {
|
||||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException {
|
||||
preparedStatement.setDouble(i, doubleValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric(" + size + "," + precision + ")";
|
||||
|
|
|
@ -2,6 +2,9 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class H2 implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -44,11 +47,21 @@ public class H2 implements Flavor {
|
|||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException {
|
||||
preparedStatement.setFloat(i, floatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeDouble() {
|
||||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException {
|
||||
preparedStatement.setDouble(i, doubleValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric(" + size + "," + precision + ")";
|
||||
|
|
|
@ -2,6 +2,9 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class Hsql implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -44,11 +47,21 @@ public class Hsql implements Flavor {
|
|||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException {
|
||||
preparedStatement.setFloat(i, floatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeDouble() {
|
||||
return "double";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException {
|
||||
preparedStatement.setDouble(i, doubleValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric(" + size + "," + precision + ")";
|
||||
|
|
|
@ -2,6 +2,9 @@ package org.xbib.jdbc.query.flavor;
|
|||
|
||||
import org.xbib.jdbc.query.Flavor;
|
||||
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.SQLException;
|
||||
|
||||
public class SqlServer implements Flavor {
|
||||
|
||||
@Override
|
||||
|
@ -29,11 +32,21 @@ public class SqlServer implements Flavor {
|
|||
return "float(24)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFloat(PreparedStatement preparedStatement, int i, Float floatValue) throws SQLException {
|
||||
preparedStatement.setFloat(i, floatValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeDouble() {
|
||||
return "float(53)";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDouble(PreparedStatement preparedStatement, int i, Double doubleValue) throws SQLException {
|
||||
preparedStatement.setDouble(i, doubleValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String typeBigDecimal(int size, int precision) {
|
||||
return "numeric(" + size + "," + precision + ")";
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
org.xbib.jdbc.query.flavor.BigQuery
|
||||
org.xbib.jdbc.query.flavor.Derby
|
||||
org.xbib.jdbc.query.flavor.Hsql
|
||||
org.xbib.jdbc.query.flavor.H2
|
||||
org.xbib.jdbc.query.flavor.MySQL
|
||||
org.xbib.jdbc.query.flavor.Oracle
|
||||
org.xbib.jdbc.query.flavor.Postgresql
|
||||
org.xbib.jdbc.query.flavor.SqlServer
|
|
@ -15,7 +15,7 @@ import org.xbib.jdbc.query.RowsHandler;
|
|||
import org.xbib.jdbc.query.Schema;
|
||||
import org.xbib.jdbc.query.Sql;
|
||||
import org.xbib.jdbc.query.SqlArgs;
|
||||
import org.xbib.jdbc.query.StatementAdaptor;
|
||||
import org.xbib.jdbc.query.StatementAdapter;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
@ -59,7 +59,7 @@ public abstract class CommonTest {
|
|||
|
||||
final static String TEST_TABLE_NAME = "dbtest";
|
||||
|
||||
protected DatabaseProvider dbp;
|
||||
protected static DatabaseProvider dbp;
|
||||
|
||||
protected Database db;
|
||||
|
||||
|
@ -67,6 +67,8 @@ public abstract class CommonTest {
|
|||
|
||||
protected LocalDate localDateNow;
|
||||
|
||||
protected abstract DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception;
|
||||
|
||||
@BeforeEach
|
||||
public void setupJdbc() throws Exception {
|
||||
now = LocalDateTime.now().truncatedTo(ChronoUnit.MILLIS);
|
||||
|
@ -77,8 +79,6 @@ public abstract class CommonTest {
|
|||
db.dropTableQuietly(TEST_TABLE_NAME);
|
||||
}
|
||||
|
||||
protected abstract DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception;
|
||||
|
||||
@AfterEach
|
||||
public void closeJdbc() {
|
||||
if (dbp != null) {
|
||||
|
@ -92,12 +92,10 @@ public abstract class CommonTest {
|
|||
String lowercaseTable = TEST_TABLE_NAME.toLowerCase();
|
||||
testTableLookup(lowercaseTable);
|
||||
db.dropTableQuietly(lowercaseTable);
|
||||
|
||||
// Let's try creating a table with an upper case name and verify it works
|
||||
String uppercaseTable = TEST_TABLE_NAME.toUpperCase();
|
||||
testTableLookup(uppercaseTable);
|
||||
db.dropTableQuietly(uppercaseTable);
|
||||
|
||||
// Verify that null or empty name is handled gracefully
|
||||
assertFalse(db.tableExists(null));
|
||||
assertFalse(db.tableExists(""));
|
||||
|
@ -106,7 +104,6 @@ public abstract class CommonTest {
|
|||
private void testTableLookup(String tableName) {
|
||||
// Verify test table does not exist
|
||||
assertFalse(db.tableExists(tableName));
|
||||
|
||||
// Create and verify it exists.
|
||||
new Schema().addTable(tableName).addColumn("pk").primaryKey().schema().execute(db);
|
||||
assertTrue(db.tableExists(tableName));
|
||||
|
@ -1529,7 +1526,7 @@ public abstract class CommonTest {
|
|||
LocalDate lastStdDateSpring = LocalDate.of(2019, Month.MARCH, 9);
|
||||
LocalDate firstDSTDateSpring = LocalDate.of(2019, Month.MARCH, 10);
|
||||
// Verify that the original LocalDate matches the driver SQL LocalDate generated.
|
||||
StatementAdaptor adaptor = new StatementAdaptor(new OptionsDefault(db.flavor()));
|
||||
StatementAdapter adaptor = new StatementAdapter(new OptionsDefault(db.flavor()));
|
||||
assertEquals(lastStdDateSpring.toString(), adaptor.nullLocalDate(lastStdDateSpring).toString());
|
||||
assertEquals(firstDSTDateSpring.toString(), adaptor.nullLocalDate(firstDSTDateSpring).toString());
|
||||
}
|
||||
|
|
|
@ -120,7 +120,7 @@ public class ConfigTest {
|
|||
|
||||
@Test
|
||||
public void testStripPrefixConflict() {
|
||||
Config config = ConfigSupplier.of().value("a.foo", "a").value("foo", "bar").removePrefix("a.").get();
|
||||
Config config = ConfigSupplier.of().property("a.foo", "a").property("foo", "bar").removePrefix("a.").get();
|
||||
|
||||
assertEquals("bar", config.getString("foo"));
|
||||
}
|
||||
|
@ -138,12 +138,12 @@ public class ConfigTest {
|
|||
|
||||
@Test
|
||||
public void testTidyValues() {
|
||||
Config config = ConfigSupplier.of().value("foo", " a ").get();
|
||||
Config config = ConfigSupplier.of().property("foo", " a ").get();
|
||||
|
||||
// Strip whitespace
|
||||
assertEquals("a", config.getString("foo"));
|
||||
|
||||
config = ConfigSupplier.of().value("foo", " ").value("foo", "").value("foo", null).value("foo", "a").get();
|
||||
config = ConfigSupplier.of().property("foo", " ").property("foo", "").property("foo", null).property("foo", "a").get();
|
||||
|
||||
// Skip over the garbage ones
|
||||
assertEquals("a", config.getString("foo"));
|
||||
|
@ -152,35 +152,35 @@ public class ConfigTest {
|
|||
@Test
|
||||
public void testBoolean() {
|
||||
// Case insensitive, allow either true/false or yes/no
|
||||
Config config = ConfigSupplier.of().value("foo", "tRuE").get();
|
||||
Config config = ConfigSupplier.of().property("foo", "tRuE").get();
|
||||
|
||||
assertTrue(config.getBooleanOrFalse("foo"));
|
||||
assertTrue(config.getBooleanOrTrue("foo"));
|
||||
assertFalse(config.getBooleanOrFalse("unknown"));
|
||||
assertTrue(config.getBooleanOrTrue("unknown"));
|
||||
|
||||
config = ConfigSupplier.of().value("foo", "yEs").get();
|
||||
config = ConfigSupplier.of().property("foo", "yEs").get();
|
||||
|
||||
assertTrue(config.getBooleanOrFalse("foo"));
|
||||
assertTrue(config.getBooleanOrTrue("foo"));
|
||||
assertFalse(config.getBooleanOrFalse("unknown"));
|
||||
assertTrue(config.getBooleanOrTrue("unknown"));
|
||||
|
||||
config = ConfigSupplier.of().value("foo", "fAlSe").get();
|
||||
config = ConfigSupplier.of().property("foo", "fAlSe").get();
|
||||
|
||||
assertFalse(config.getBooleanOrFalse("foo"));
|
||||
assertFalse(config.getBooleanOrTrue("foo"));
|
||||
assertFalse(config.getBooleanOrFalse("unknown"));
|
||||
assertTrue(config.getBooleanOrTrue("unknown"));
|
||||
|
||||
config = ConfigSupplier.of().value("foo", "nO").get();
|
||||
config = ConfigSupplier.of().property("foo", "nO").get();
|
||||
|
||||
assertFalse(config.getBooleanOrFalse("foo"));
|
||||
assertFalse(config.getBooleanOrTrue("foo"));
|
||||
assertFalse(config.getBooleanOrFalse("unknown"));
|
||||
assertTrue(config.getBooleanOrTrue("unknown"));
|
||||
|
||||
config = ConfigSupplier.of().value("foo", "bad value").get();
|
||||
config = ConfigSupplier.of().property("foo", "bad value").get();
|
||||
|
||||
assertFalse(config.getBooleanOrFalse("foo"));
|
||||
assertTrue(config.getBooleanOrTrue("foo"));
|
||||
|
@ -190,7 +190,7 @@ public class ConfigTest {
|
|||
|
||||
@Test
|
||||
public void testInteger() {
|
||||
Config config = ConfigSupplier.of().value("good", "123").value("bad", "hi").get();
|
||||
Config config = ConfigSupplier.of().property("good", "123").property("bad", "hi").get();
|
||||
assertEquals(Integer.valueOf(123), config.getInteger("good"));
|
||||
assertNull(config.getInteger("bad"));
|
||||
assertNull(config.getInteger("missing"));
|
||||
|
@ -201,7 +201,7 @@ public class ConfigTest {
|
|||
|
||||
@Test
|
||||
public void testLong() {
|
||||
Config config = ConfigSupplier.of().value("good", "123").value("bad", "hi").get();
|
||||
Config config = ConfigSupplier.of().property("good", "123").property("bad", "hi").get();
|
||||
|
||||
assertEquals(Long.valueOf(123), config.getLong("good"));
|
||||
assertNull(config.getLong("bad"));
|
||||
|
@ -213,7 +213,7 @@ public class ConfigTest {
|
|||
|
||||
@Test
|
||||
public void testFloat() {
|
||||
Config config = ConfigSupplier.of().value("good", "123.45").value("bad", "hi").get();
|
||||
Config config = ConfigSupplier.of().property("good", "123.45").property("bad", "hi").get();
|
||||
|
||||
assertEquals(Float.valueOf(123.45f), config.getFloat("good"));
|
||||
assertNull(config.getFloat("bad"));
|
||||
|
@ -225,7 +225,7 @@ public class ConfigTest {
|
|||
|
||||
@Test
|
||||
public void testDouble() {
|
||||
Config config = ConfigSupplier.of().value("good", "123.45").value("bad", "hi").get();
|
||||
Config config = ConfigSupplier.of().property("good", "123.45").property("bad", "hi").get();
|
||||
|
||||
assertEquals(Double.valueOf(123.45), config.getDouble("good"));
|
||||
assertNull(config.getDouble("bad"));
|
||||
|
@ -237,7 +237,7 @@ public class ConfigTest {
|
|||
|
||||
@Test
|
||||
public void testBigDecimal() {
|
||||
Config config = ConfigSupplier.of().value("good", "123.45").value("bad", "hi").get();
|
||||
Config config = ConfigSupplier.of().property("good", "123.45").property("bad", "hi").get();
|
||||
|
||||
assertEquals(new BigDecimal("123.45"), config.getBigDecimal("good"));
|
||||
assertNull(config.getBigDecimal("bad"));
|
||||
|
|
|
@ -15,6 +15,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
|||
/**
|
||||
* Exercise Database functionality with a real database (Derby).
|
||||
*/
|
||||
@Disabled
|
||||
public class DerbyTest extends CommonTest {
|
||||
|
||||
private static final Logger logger = Logger.getLogger(DerbyTest.class.getName());
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
package org.xbib.jdbc.query.test;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.OracleContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.xbib.jdbc.query.DatabaseProvider;
|
||||
import org.xbib.jdbc.query.OptionsOverride;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Exercise Database functionality with a real Oracle database.
|
||||
*/
|
||||
@Disabled
|
||||
public class OracleTest extends CommonTest {
|
||||
|
||||
@Container
|
||||
public OracleContainer oracleContainer = new OracleContainer("");
|
||||
|
||||
@Override
|
||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
||||
Properties properties = new Properties();
|
||||
properties.load(new FileReader(System.getProperty("local.properties", "local.properties")));
|
||||
return DatabaseProvider.builder(
|
||||
properties.getProperty("database.url"),
|
||||
properties.getProperty("database.user"),
|
||||
properties.getProperty("database.password")
|
||||
).withSqlParameterLogging().withSqlInExceptionMessages().withOptions(options).build();
|
||||
}
|
||||
|
||||
@Disabled("Current Oracle behavior is to convert -0f to 0f")
|
||||
@Test
|
||||
public void argFloatNegativeZero() {
|
||||
super.argFloatNegativeZero();
|
||||
}
|
||||
|
||||
@Disabled("Current Oracle behavior is to convert -0d to 0d")
|
||||
@Test
|
||||
public void argDoubleNegativeZero() {
|
||||
super.argDoubleNegativeZero();
|
||||
}
|
||||
}
|
|
@ -1,52 +0,0 @@
|
|||
package org.xbib.jdbc.query.test;
|
||||
|
||||
import java.io.IOException;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.xbib.jdbc.query.DatabaseProvider;
|
||||
import org.xbib.jdbc.query.OptionsOverride;
|
||||
import org.xbib.jdbc.query.Schema;
|
||||
|
||||
import java.io.FileReader;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
|
||||
/**
|
||||
* Exercise Database functionality with a real PostgreSQL database.
|
||||
*/
|
||||
@Disabled
|
||||
public class PostgreSqlTest extends CommonTest {
|
||||
|
||||
@Override
|
||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws IOException {
|
||||
Properties properties = new Properties();
|
||||
properties.load(new FileReader(System.getProperty("local.properties", "local.properties")));
|
||||
return DatabaseProvider.builder(
|
||||
properties.getProperty("postgres.database.url"),
|
||||
properties.getProperty("postgres.database.user"),
|
||||
properties.getProperty("postgres.database.password")
|
||||
).withOptions(options).withSqlParameterLogging().withSqlInExceptionMessages().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* PostgreSQL seems to have different behavior in that is does not convert
|
||||
* column names to uppercase (it actually converts them to lowercase).
|
||||
* I haven't figured out how to smooth over this difference, since all databases
|
||||
* seem to respect the provided case when it is inside quotes, but don't provide
|
||||
* a way to tell whether a particular parameter was quoted.
|
||||
*/
|
||||
@Override
|
||||
@Test
|
||||
public void metadataColumnNames() {
|
||||
db.dropTableQuietly("dbtest");
|
||||
|
||||
new Schema().addTable("dbtest").addColumn("pk").primaryKey().schema().execute(db);
|
||||
|
||||
db.toSelect("select Pk, Pk as Foo, Pk as \"Foo\" from dbtest")
|
||||
.query(rs -> {
|
||||
assertArrayEquals(new String[]{"pk", "foo", "Foo"}, rs.getColumnLabels());
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
|
@ -12,7 +12,7 @@ public abstract class DerbyExample {
|
|||
// For subclasses to override
|
||||
}
|
||||
|
||||
void example(DatabaseProvider.Builder dbb, final String[] args) {
|
||||
void example(DatabaseProvider.DatabaseProviderBuilder dbb, final String[] args) {
|
||||
dbb.transact(db -> {
|
||||
example(db.get(), args);
|
||||
});
|
||||
|
|
|
@ -1,65 +0,0 @@
|
|||
package org.xbib.jdbc.query.test.example;
|
||||
|
||||
import org.xbib.jdbc.query.DatabaseException;
|
||||
import org.xbib.jdbc.query.DatabaseProvider;
|
||||
import org.xbib.jdbc.query.Schema;
|
||||
|
||||
/**
|
||||
* Demo of how to use the {@code DatabaseProvider.fakeBuilder()} to control
|
||||
* transactions for testing purposes.
|
||||
*/
|
||||
public class FakeBuilder extends DerbyExample {
|
||||
public static void main(String[] args) {
|
||||
new FakeBuilder().launch(args);
|
||||
}
|
||||
|
||||
void example(DatabaseProvider.Builder dbb, String[] args) {
|
||||
DatabaseProvider realDbp = null;
|
||||
|
||||
try {
|
||||
realDbp = dbb.build();
|
||||
|
||||
dbb.transact(db -> {
|
||||
// Drops in case we are running this multiple times
|
||||
db.get().dropTableQuietly("t");
|
||||
|
||||
// Create and populate a simple table
|
||||
new Schema().addTable("t").addColumn("pk").primaryKey().schema().execute(db.get());
|
||||
});
|
||||
|
||||
DatabaseProvider.Builder fakeBuilder = realDbp.fakeBuilder();
|
||||
|
||||
// Trying all three transact methods, just for completeness
|
||||
fakeBuilder.transact(db -> {
|
||||
db.get().toInsert("insert into t (pk) values (?)").argLong(1L).insert(1);
|
||||
});
|
||||
fakeBuilder.transact((db, tx) -> {
|
||||
db.get().toInsert("insert into t (pk) values (?)").argLong(2L).insert(1);
|
||||
});
|
||||
|
||||
fakeBuilder.transact(db -> {
|
||||
println("Rows before rollback: " + db.get().toSelect("select count(*) from t").queryLongOrZero());
|
||||
});
|
||||
|
||||
realDbp.rollbackAndClose();
|
||||
|
||||
// Can't use fakeBuilder after close
|
||||
try {
|
||||
fakeBuilder.transact(db -> {
|
||||
db.get().tableExists("foo");
|
||||
println("Eeek...shouldn't get here!");
|
||||
});
|
||||
} catch (DatabaseException e) {
|
||||
println("Correctly threw exception: " + e.getMessage());
|
||||
}
|
||||
|
||||
dbb.transact(db -> {
|
||||
println("Rows after rollback: " + db.get().toSelect("select count(*) from t").queryLongOrZero());
|
||||
});
|
||||
} finally {
|
||||
if (realDbp != null) {
|
||||
realDbp.rollbackAndClose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,5 +5,6 @@ java.util.logging.ConsoleHandler.level=ALL
|
|||
java.util.logging.ConsoleHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.level=ALL
|
||||
java.util.logging.FileHandler.formatter=java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.pattern=build/marc.log
|
||||
java.util.logging.FileHandler.pattern=build/database.log
|
||||
jdk.event.security.level=INFO
|
||||
javax.management.level=INFO
|
||||
|
|
5
jdbc-test/build.gradle
Normal file
5
jdbc-test/build.gradle
Normal file
|
@ -0,0 +1,5 @@
|
|||
dependencies {
|
||||
api project(":jdbc-query")
|
||||
implementation libs.junit.jupiter.api
|
||||
implementation libs.hamcrest
|
||||
}
|
1721
jdbc-test/src/main/java/org/xbib/jdbc/test/CommonTest.java
Normal file
1721
jdbc-test/src/main/java/org/xbib/jdbc/test/CommonTest.java
Normal file
File diff suppressed because it is too large
Load diff
|
@ -2,23 +2,32 @@ dependencyResolutionManagement {
|
|||
versionCatalogs {
|
||||
libs {
|
||||
version('gradle', '7.5.1')
|
||||
version('junit', '5.8.2')
|
||||
version('testcontainers', '1.17.3')
|
||||
version('junit', '5.9.1')
|
||||
version('testcontainers', '1.17.5')
|
||||
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
||||
library('junit-jupiter-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
||||
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
||||
library('hamcrest', 'org.hamcrest', 'hamcrest-library').version('2.2')
|
||||
library('junit4', 'junit', 'junit').version('4.13.2')
|
||||
library('derby', 'org.apache.derby', 'derby').version('10.15.2.0')
|
||||
library('derby', 'org.apache.derby', 'derby').version('10.16.1.1')
|
||||
library('hsqldb', 'org.hsqldb', 'hsqldb').version('2.7.1')
|
||||
library('h2', 'com.h2database', 'h2').version('1.4.200')
|
||||
library('h2', 'com.h2database', 'h2').version('2.1.214')
|
||||
library('mariadb', 'org.mariadb.jdbc', 'mariadb-java-client').version('3.0.8')
|
||||
library('oracle', 'com.oracle.database.jdbc','ojdbc11').version('21.7.0.0')
|
||||
library('postgresql', 'org.postgresql', 'postgresql').version('42.5.0')
|
||||
library('mockito-core', 'org.mockito', 'mockito-core').version('4.8.1')
|
||||
library('testcontainers', 'org.testcontainers', 'testcontainers').versionRef('testcontainers')
|
||||
library('testcontainers-junit-jupiter', 'org.testcontainers', 'junit-jupiter').versionRef('testcontainers')
|
||||
library('testcontainers-mariadb', 'org.testcontainers', 'mariadb').versionRef('testcontainers')
|
||||
library('testcontainers-oracle-xe', 'org.testcontainers', 'oracle-xe').versionRef('testcontainers')
|
||||
library('mockito-core', 'org.mockito', 'mockito-core').version('4.6.1')
|
||||
library('testcontainers-postgresql', 'org.testcontainers', 'postgresql').versionRef('testcontainers')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include 'jdbc-connection-pool'
|
||||
include 'jdbc-query'
|
||||
include 'jdbc-test'
|
||||
include 'jdbc-mariadb'
|
||||
include 'jdbc-oracle'
|
||||
include 'jdbc-postgresql'
|
||||
|
|
Loading…
Reference in a new issue