Compare commits
10 commits
4e06d7c21b
...
844b288a18
Author | SHA1 | Date | |
---|---|---|---|
844b288a18 | |||
ffd0b831f9 | |||
9166a5d6db | |||
210f1fa3fd | |||
f7fd2df016 | |||
07b20d8188 | |||
0dd8138237 | |||
6c064531ab | |||
c2b05476f2 | |||
8a92b3f45c |
26 changed files with 274 additions and 277 deletions
|
@ -15,10 +15,10 @@ ext {
|
||||||
description = 'JDBC connection pool and utilities'
|
description = 'JDBC connection pool and utilities'
|
||||||
inceptionYear = '2018'
|
inceptionYear = '2018'
|
||||||
url = 'https://xbib.org/' + user + '/' + name
|
url = 'https://xbib.org/' + user + '/' + name
|
||||||
scmUrl = 'https://xbib.org/' + user + '/' + name
|
scmUrl = url
|
||||||
scmConnection = 'scm:git:git://xbib.org/' + user + '/' + name + '.git'
|
scmConnection = 'scm:git:git://xbib.org/' + user + '/' + name + '.git'
|
||||||
scmDeveloperConnection = 'scm:git:ssh://forgejo@xbib.org:' + user + '/' + name + '.git'
|
scmDeveloperConnection = 'scm:git:ssh://forgejo@xbib.org:' + user + '/' + name + '.git'
|
||||||
issueManagementSystem = 'Github'
|
issueManagementSystem = 'Forgejo'
|
||||||
issueManagementUrl = ext.scmUrl + '/issues'
|
issueManagementUrl = ext.scmUrl + '/issues'
|
||||||
licenseName = 'The Apache License, Version 2.0'
|
licenseName = 'The Apache License, Version 2.0'
|
||||||
licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
licenseUrl = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
group = org.xbib
|
group = org.xbib
|
||||||
name = database
|
name = database
|
||||||
version = 2.0.2
|
version = 2.2.0
|
||||||
|
|
||||||
org.gradle.warning.mode = ALL
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ jar {
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
options.fork = true
|
options.fork = true
|
||||||
options.forkOptions.jvmArgs += ['-Duser.language=en','-Duser.country=US']
|
options.forkOptions.jvmArgs += ['-Duser.language=en','-Duser.country=US']
|
||||||
options.compilerArgs << '-Xlint:all'
|
options.compilerArgs << '-Xlint:all,-exports'
|
||||||
options.encoding = 'UTF-8'
|
options.encoding = 'UTF-8'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ if (project.hasProperty('forgeJoToken')) {
|
||||||
publishing {
|
publishing {
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
url 'https://xbib.org/api/packages/joerg/maven'
|
url project.property('forgeJoUrl')
|
||||||
credentials(HttpHeaderCredentials) {
|
credentials(HttpHeaderCredentials) {
|
||||||
name = "Authorization"
|
name = "Authorization"
|
||||||
value = "token ${project.property('forgeJoToken')}"
|
value = "token ${project.property('forgeJoToken')}"
|
||||||
|
|
|
@ -1,27 +0,0 @@
|
||||||
apply plugin: 'ivy-publish'
|
|
||||||
|
|
||||||
publishing {
|
|
||||||
repositories {
|
|
||||||
ivy {
|
|
||||||
url = "https://xbib.org/repo"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
publications {
|
|
||||||
ivy(IvyPublication) {
|
|
||||||
from components.java
|
|
||||||
descriptor {
|
|
||||||
license {
|
|
||||||
name = 'The Apache License, Version 2.0'
|
|
||||||
url = 'http://www.apache.org/licenses/LICENSE-2.0.txt'
|
|
||||||
}
|
|
||||||
author {
|
|
||||||
name = 'Jörg Prante'
|
|
||||||
url = 'http://example.com/users/jane'
|
|
||||||
}
|
|
||||||
descriptor.description {
|
|
||||||
text = rootProject.ext.description
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,7 +19,7 @@ publishing {
|
||||||
id = 'jprante'
|
id = 'jprante'
|
||||||
name = 'Jörg Prante'
|
name = 'Jörg Prante'
|
||||||
email = 'joergprante@gmail.com'
|
email = 'joergprante@gmail.com'
|
||||||
url = 'https://github.com/jprante'
|
url = 'https://xbib.org/joerg'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scm {
|
scm {
|
||||||
|
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-all.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|
20
gradlew.bat
vendored
20
gradlew.bat
vendored
|
@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if %ERRORLEVEL% equ 0 goto execute
|
if %ERRORLEVEL% equ 0 goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto execute
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
|
||||||
echo.
|
echo. 1>&2
|
||||||
echo Please set the JAVA_HOME variable in your environment to match the
|
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
|
||||||
echo location of your Java installation.
|
echo location of your Java installation. 1>&2
|
||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
|
|
|
@ -118,7 +118,8 @@ public class Pool implements BagStateListener {
|
||||||
*
|
*
|
||||||
* @param config the config
|
* @param config the config
|
||||||
*/
|
*/
|
||||||
public Pool(PoolConfig config) throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
public Pool(PoolConfig config) throws ClassNotFoundException,
|
||||||
|
NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
|
||||||
config.validate();
|
config.validate();
|
||||||
this.config = config;
|
this.config = config;
|
||||||
logger.log(Level.INFO, () -> "starting new pool: " + config.getPoolName());
|
logger.log(Level.INFO, () -> "starting new pool: " + config.getPoolName());
|
||||||
|
@ -146,16 +147,26 @@ public class Pool implements BagStateListener {
|
||||||
checkFailFast(initializationTimeout);
|
checkFailFast(initializationTimeout);
|
||||||
}
|
}
|
||||||
ThreadFactory threadFactory = config.getThreadFactory();
|
ThreadFactory threadFactory = config.getThreadFactory();
|
||||||
|
ClassLoader contextClassLoader = config.getContextClassLoader();
|
||||||
int maxPoolSize = config.getMaximumPoolSize();
|
int maxPoolSize = config.getMaximumPoolSize();
|
||||||
LinkedBlockingQueue<Runnable> addConnectionQueue = new LinkedBlockingQueue<>(maxPoolSize);
|
LinkedBlockingQueue<Runnable> addConnectionQueue = new LinkedBlockingQueue<>(maxPoolSize);
|
||||||
this.addConnectionQueueReadOnlyView = Collections.unmodifiableCollection(addConnectionQueue);
|
this.addConnectionQueueReadOnlyView = Collections.unmodifiableCollection(addConnectionQueue);
|
||||||
this.addConnectionExecutor = createThreadPoolExecutor(addConnectionQueue, poolName + " connection adder", threadFactory, new ThreadPoolExecutor.DiscardOldestPolicy());
|
this.addConnectionExecutor = createThreadPoolExecutor(addConnectionQueue,
|
||||||
this.closeConnectionExecutor = createThreadPoolExecutor(maxPoolSize, poolName + " connection closer", threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
|
poolName + " connection adder",
|
||||||
|
threadFactory,
|
||||||
|
contextClassLoader,
|
||||||
|
new ThreadPoolExecutor.DiscardOldestPolicy());
|
||||||
|
this.closeConnectionExecutor = createThreadPoolExecutor(maxPoolSize,
|
||||||
|
poolName + " connection closer",
|
||||||
|
threadFactory,
|
||||||
|
contextClassLoader,
|
||||||
|
new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
this.leakTaskFactory = new ProxyLeakTaskFactory(config.getLeakDetectionThreshold(), houseKeepingExecutorService);
|
this.leakTaskFactory = new ProxyLeakTaskFactory(config.getLeakDetectionThreshold(), houseKeepingExecutorService);
|
||||||
this.houseKeeperTask = houseKeepingExecutorService.scheduleWithFixedDelay(new HouseKeeper(this), 100L, config.getHousekeepingPeriodMs(), TimeUnit.MILLISECONDS);
|
this.houseKeeperTask = houseKeepingExecutorService.scheduleWithFixedDelay(new HouseKeeper(this), 100L, config.getHousekeepingPeriodMs(), TimeUnit.MILLISECONDS);
|
||||||
if (Boolean.getBoolean("org.xbib.jdbc.connection.pool.blockUntilFilled") && config.getInitializationFailTimeout() > 1) {
|
if (Boolean.getBoolean("org.xbib.jdbc.connection.pool.blockUntilFilled") && config.getInitializationFailTimeout() > 1) {
|
||||||
addConnectionExecutor.setCorePoolSize(Math.min(16, Runtime.getRuntime().availableProcessors()));
|
int procs = Math.min(16, Runtime.getRuntime().availableProcessors());
|
||||||
addConnectionExecutor.setMaximumPoolSize(Math.min(16, Runtime.getRuntime().availableProcessors()));
|
addConnectionExecutor.setCorePoolSize(procs);
|
||||||
|
addConnectionExecutor.setMaximumPoolSize(procs);
|
||||||
final long startTime = ClockSource.currentTime();
|
final long startTime = ClockSource.currentTime();
|
||||||
while (ClockSource.elapsedMillis(startTime) < config.getInitializationFailTimeout() && getTotalConnections() < config.getMinimumIdle()) {
|
while (ClockSource.elapsedMillis(startTime) < config.getInitializationFailTimeout() && getTotalConnections() < config.getMinimumIdle()) {
|
||||||
quietlySleep(TimeUnit.MILLISECONDS.toMillis(100));
|
quietlySleep(TimeUnit.MILLISECONDS.toMillis(100));
|
||||||
|
@ -303,8 +314,11 @@ public class Pool implements BagStateListener {
|
||||||
addConnectionExecutor.awaitTermination(getLoginTimeout(), TimeUnit.SECONDS);
|
addConnectionExecutor.awaitTermination(getLoginTimeout(), TimeUnit.SECONDS);
|
||||||
destroyHouseKeepingExecutorService();
|
destroyHouseKeepingExecutorService();
|
||||||
bag.close();
|
bag.close();
|
||||||
final ExecutorService assassinExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(), poolName + " connection assassinator",
|
final ExecutorService assassinExecutor = createThreadPoolExecutor(config.getMaximumPoolSize(),
|
||||||
config.getThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());
|
poolName + " connection assassinator",
|
||||||
|
config.getThreadFactory(),
|
||||||
|
config.getContextClassLoader(),
|
||||||
|
new ThreadPoolExecutor.CallerRunsPolicy());
|
||||||
try {
|
try {
|
||||||
final long start = ClockSource.currentTime();
|
final long start = ClockSource.currentTime();
|
||||||
do {
|
do {
|
||||||
|
@ -413,6 +427,7 @@ public class Pool implements BagStateListener {
|
||||||
if (ds == null) {
|
if (ds == null) {
|
||||||
String dsClassName = config.getDataSourceClassName();
|
String dsClassName = config.getDataSourceClassName();
|
||||||
if (dsClassName != null) {
|
if (dsClassName != null) {
|
||||||
|
// we must use the system class loader
|
||||||
Class<?> clazz = Class.forName(dsClassName, true, ClassLoader.getSystemClassLoader());
|
Class<?> clazz = Class.forName(dsClassName, true, ClassLoader.getSystemClassLoader());
|
||||||
ds = (DataSource) clazz.getDeclaredConstructor().newInstance();
|
ds = (DataSource) clazz.getDeclaredConstructor().newInstance();
|
||||||
} else if (url != null) {
|
} else if (url != null) {
|
||||||
|
@ -814,7 +829,8 @@ public class Pool implements BagStateListener {
|
||||||
private ScheduledExecutorService initializeHouseKeepingExecutorService() {
|
private ScheduledExecutorService initializeHouseKeepingExecutorService() {
|
||||||
if (config.getScheduledExecutor() == null) {
|
if (config.getScheduledExecutor() == null) {
|
||||||
ThreadFactory threadFactory = Optional.ofNullable(config.getThreadFactory()).orElseGet(() ->
|
ThreadFactory threadFactory = Optional.ofNullable(config.getThreadFactory()).orElseGet(() ->
|
||||||
new DefaultThreadFactory(poolName + "-housekeeper", true));
|
new DefaultThreadFactory(poolName + "-housekeeper",
|
||||||
|
Thread.currentThread().getContextClassLoader(), true));
|
||||||
ScheduledThreadPoolExecutor executor =
|
ScheduledThreadPoolExecutor executor =
|
||||||
new ScheduledThreadPoolExecutor(1, threadFactory,
|
new ScheduledThreadPoolExecutor(1, threadFactory,
|
||||||
new ThreadPoolExecutor.DiscardPolicy());
|
new ThreadPoolExecutor.DiscardPolicy());
|
||||||
|
@ -867,16 +883,18 @@ public class Pool implements BagStateListener {
|
||||||
*
|
*
|
||||||
* @param queueSize the queue size
|
* @param queueSize the queue size
|
||||||
* @param threadName the thread name
|
* @param threadName the thread name
|
||||||
* @param threadFactory an optional ThreadFactory
|
* @param threadFactory an optional ThreadFactory, if null, a DefaultThreadFactory will be used
|
||||||
|
* @param contextClassLoader the context class loader if the thread factory is null
|
||||||
* @param policy the RejectedExecutionHandler policy
|
* @param policy the RejectedExecutionHandler policy
|
||||||
* @return a ThreadPoolExecutor
|
* @return a ThreadPoolExecutor
|
||||||
*/
|
*/
|
||||||
private ThreadPoolExecutor createThreadPoolExecutor(int queueSize,
|
private ThreadPoolExecutor createThreadPoolExecutor(int queueSize,
|
||||||
String threadName,
|
String threadName,
|
||||||
ThreadFactory threadFactory,
|
ThreadFactory threadFactory,
|
||||||
|
ClassLoader contextClassLoader,
|
||||||
RejectedExecutionHandler policy) {
|
RejectedExecutionHandler policy) {
|
||||||
if (threadFactory == null) {
|
if (threadFactory == null) {
|
||||||
threadFactory = new DefaultThreadFactory(threadName, true);
|
threadFactory = new DefaultThreadFactory(threadName, contextClassLoader, true);
|
||||||
}
|
}
|
||||||
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(queueSize);
|
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<>(queueSize);
|
||||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1,
|
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1,
|
||||||
|
@ -897,9 +915,10 @@ public class Pool implements BagStateListener {
|
||||||
private ThreadPoolExecutor createThreadPoolExecutor(BlockingQueue<Runnable> queue,
|
private ThreadPoolExecutor createThreadPoolExecutor(BlockingQueue<Runnable> queue,
|
||||||
String threadName,
|
String threadName,
|
||||||
ThreadFactory threadFactory,
|
ThreadFactory threadFactory,
|
||||||
|
ClassLoader contextClassLoader,
|
||||||
RejectedExecutionHandler policy) {
|
RejectedExecutionHandler policy) {
|
||||||
if (threadFactory == null) {
|
if (threadFactory == null) {
|
||||||
threadFactory = new DefaultThreadFactory(threadName, true);
|
threadFactory = new DefaultThreadFactory(threadName, contextClassLoader, true);
|
||||||
}
|
}
|
||||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1,
|
ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1,
|
||||||
5, TimeUnit.SECONDS, queue, threadFactory, policy);
|
5, TimeUnit.SECONDS, queue, threadFactory, policy);
|
||||||
|
@ -975,7 +994,7 @@ public class Pool implements BagStateListener {
|
||||||
*
|
*
|
||||||
* @return true if we should create a connection, false if the need has disappeared
|
* @return true if we should create a connection, false if the need has disappeared
|
||||||
*/
|
*/
|
||||||
synchronized boolean shouldCreateAnotherConnection() {
|
public synchronized boolean shouldCreateAnotherConnection() {
|
||||||
return getTotalConnections() < config.getMaximumPoolSize() &&
|
return getTotalConnections() < config.getMaximumPoolSize() &&
|
||||||
(bag.getWaitingThreadCount() > 0 || getIdleConnections() < config.getMinimumIdle());
|
(bag.getWaitingThreadCount() > 0 || getIdleConnections() < config.getMinimumIdle());
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.xbib.jdbc.connection.pool;
|
package org.xbib.jdbc.connection.pool;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
|
@ -74,6 +75,8 @@ public class PoolConfig {
|
||||||
|
|
||||||
private ThreadFactory threadFactory;
|
private ThreadFactory threadFactory;
|
||||||
|
|
||||||
|
private ClassLoader contextClassLoader;
|
||||||
|
|
||||||
private ScheduledExecutorService scheduledExecutor;
|
private ScheduledExecutorService scheduledExecutor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -297,15 +300,6 @@ public class PoolConfig {
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the name of the JDBC {@link DataSource} class used to create Connections.
|
|
||||||
*
|
|
||||||
* @return the fully qualified name of the JDBC {@link DataSource} class
|
|
||||||
*/
|
|
||||||
public String getDataSourceClassName() {
|
|
||||||
return dataSourceClassName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the fully qualified class name of the JDBC {@link DataSource} that will be used create Connections.
|
* Set the fully qualified class name of the JDBC {@link DataSource} that will be used create Connections.
|
||||||
*
|
*
|
||||||
|
@ -315,6 +309,15 @@ public class PoolConfig {
|
||||||
this.dataSourceClassName = className;
|
this.dataSourceClassName = className;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the JDBC {@link DataSource} class used to create Connections.
|
||||||
|
*
|
||||||
|
* @return the fully qualified name of the JDBC {@link DataSource} class
|
||||||
|
*/
|
||||||
|
public String getDataSourceClassName() {
|
||||||
|
return dataSourceClassName;
|
||||||
|
}
|
||||||
|
|
||||||
public Properties getProperties() {
|
public Properties getProperties() {
|
||||||
return properties;
|
return properties;
|
||||||
}
|
}
|
||||||
|
@ -324,23 +327,47 @@ public class PoolConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDriverClassName(String driverClassName) {
|
public void setDriverClassName(String driverClassName) {
|
||||||
Class<?> driverClass = attemptFromContextLoader(driverClassName);
|
Class<?> driverClass = null;
|
||||||
|
ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
if (threadContextClassLoader != null) {
|
||||||
try {
|
try {
|
||||||
if (driverClass == null) {
|
driverClass = threadContextClassLoader.loadClass(driverClassName);
|
||||||
driverClass = this.getClass().getClassLoader().loadClass(driverClassName);
|
if (driverClass != null) {
|
||||||
logger.log(Level.FINE, () -> "driver class found in the PoolConfig class classloader: " + driverClassName + " " + this.getClass().getClassLoader());
|
logger.log(Level.FINE, () -> "driver class found in thread context class loader:" + driverClassName);
|
||||||
}
|
}
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
logger.log(Level.SEVERE, "failed to load driver class from PoolConfig class classloader: " + driverClassName + " " + this.getClass().getClassLoader());
|
logger.log(Level.FINE, () -> "failed to load driver class from thread context class loader" + driverClassName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (driverClass == null) {
|
||||||
|
driverClass = getClass().getClassLoader().loadClass(driverClassName);
|
||||||
|
if (driverClass != null) {
|
||||||
|
logger.log(Level.FINE, () -> "driver class found in the class classloader: " + driverClassName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
logger.log(Level.FINE, () -> "failed to load driver class from class classloader: " + driverClassName);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
if (driverClass == null) {
|
||||||
|
driverClass = ClassLoader.getSystemClassLoader().loadClass(driverClassName);
|
||||||
|
if (driverClass != null) {
|
||||||
|
logger.log(Level.FINE, () -> "driver class found in the system class classloader: " + driverClassName);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
logger.log(Level.SEVERE, () -> "failed to load driver class from system class classloader: " + driverClassName);
|
||||||
}
|
}
|
||||||
if (driverClass == null) {
|
if (driverClass == null) {
|
||||||
throw new RuntimeException("failed to load driver class " + driverClassName + " in either of PoolConfig class loader or Thread context classloader");
|
throw new IllegalStateException("failed to load driver class " + driverClassName);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
driverClass.getConstructor().newInstance();
|
driverClass.getConstructor().newInstance();
|
||||||
this.driverClassName = driverClassName;
|
this.driverClassName = driverClassName;
|
||||||
} catch (Exception e) {
|
} catch (InstantiationException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
|
||||||
throw new RuntimeException("Failed to instantiate class " + driverClassName, e);
|
throw new IllegalStateException("failed to instantiate class " + driverClassName, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -549,15 +576,6 @@ public class PoolConfig {
|
||||||
return housekeepingPeriodMs;
|
return housekeepingPeriodMs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the thread factory used to create threads.
|
|
||||||
*
|
|
||||||
* @return the thread factory (may be null, in which case the default thread factory is used)
|
|
||||||
*/
|
|
||||||
public ThreadFactory getThreadFactory() {
|
|
||||||
return threadFactory;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the thread factory to be used to create threads.
|
* Set the thread factory to be used to create threads.
|
||||||
*
|
*
|
||||||
|
@ -567,20 +585,21 @@ public class PoolConfig {
|
||||||
this.threadFactory = threadFactory;
|
this.threadFactory = threadFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> attemptFromContextLoader(String driverClassName) {
|
/**
|
||||||
ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
* Get the thread factory used to create threads.
|
||||||
if (threadContextClassLoader != null) {
|
*
|
||||||
try {
|
* @return the thread factory (may be null, in which case the default thread factory is used)
|
||||||
Class<?> driverClass = threadContextClassLoader.loadClass(driverClassName);
|
*/
|
||||||
logger.log(Level.FINE, "Driver class found in Thread context class loader:" +
|
public ThreadFactory getThreadFactory() {
|
||||||
driverClassName + " " + threadContextClassLoader);
|
return threadFactory;
|
||||||
return driverClass;
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
logger.log(Level.FINE, "Driver class not found in Thread context class loader, trying classloader: " +
|
|
||||||
driverClassName + " " + threadContextClassLoader + " " + this.getClass().getClassLoader());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setContextClassLoader(ClassLoader contextClassLoader) {
|
||||||
|
this.contextClassLoader = contextClassLoader;
|
||||||
}
|
}
|
||||||
return null;
|
|
||||||
|
public ClassLoader getContextClassLoader() {
|
||||||
|
return contextClassLoader != null ? contextClassLoader : Thread.currentThread().getContextClassLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("StatementWithEmptyBody")
|
@SuppressWarnings("StatementWithEmptyBody")
|
||||||
|
|
|
@ -31,7 +31,8 @@ public class PoolEntryCreator implements Callable<Boolean> {
|
||||||
final PoolEntry poolEntry = pool.createPoolEntry();
|
final PoolEntry poolEntry = pool.createPoolEntry();
|
||||||
if (poolEntry != null) {
|
if (poolEntry != null) {
|
||||||
pool.bag.add(poolEntry);
|
pool.bag.add(poolEntry);
|
||||||
logger.log(Level.FINE, () -> MessageFormat.format("{0}: added connection {1} ", pool.poolName, poolEntry.getConnection()));
|
logger.log(Level.FINE, () -> MessageFormat.format("{0}: added connection {1} ",
|
||||||
|
pool.poolName, poolEntry.getConnection()));
|
||||||
if (loggingPrefix != null) {
|
if (loggingPrefix != null) {
|
||||||
pool.logPoolState(loggingPrefix);
|
pool.logPoolState(loggingPrefix);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,15 @@ public class DefaultThreadFactory implements ThreadFactory {
|
||||||
|
|
||||||
private final String threadName;
|
private final String threadName;
|
||||||
|
|
||||||
|
private final ClassLoader contextClassLoader;
|
||||||
|
|
||||||
private final boolean daemon;
|
private final boolean daemon;
|
||||||
|
|
||||||
public DefaultThreadFactory(String threadName, boolean daemon) {
|
public DefaultThreadFactory(String threadName,
|
||||||
|
ClassLoader contextClassLoader,
|
||||||
|
boolean daemon) {
|
||||||
this.threadName = threadName;
|
this.threadName = threadName;
|
||||||
|
this.contextClassLoader = contextClassLoader;
|
||||||
this.daemon = daemon;
|
this.daemon = daemon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +22,7 @@ public class DefaultThreadFactory implements ThreadFactory {
|
||||||
public Thread newThread(Runnable r) {
|
public Thread newThread(Runnable r) {
|
||||||
Thread thread = new Thread(r, threadName);
|
Thread thread = new Thread(r, threadName);
|
||||||
thread.setDaemon(daemon);
|
thread.setDaemon(daemon);
|
||||||
|
thread.setContextClassLoader(contextClassLoader);
|
||||||
return thread;
|
return thread;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,24 +17,36 @@ public class DriverDataSource implements DataSource {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(DriverDataSource.class.getName());
|
private static final Logger logger = Logger.getLogger(DriverDataSource.class.getName());
|
||||||
|
|
||||||
|
static {
|
||||||
|
DriverManager.setLogWriter(new PrintWriter(new LoggingOutputStream(logger)));
|
||||||
|
DriverManager.drivers().forEach(d -> logger.log(Level.INFO, "found driver " + d));
|
||||||
|
}
|
||||||
|
|
||||||
private static final String PASSWORD = "password";
|
private static final String PASSWORD = "password";
|
||||||
|
|
||||||
private static final String USER = "user";
|
private static final String USER = "user";
|
||||||
|
|
||||||
private static final String AUTOCOMMIT = "autocommit";
|
private static final String AUTOCOMMIT = "autocommit";
|
||||||
|
|
||||||
private String jdbcUrl;
|
|
||||||
|
|
||||||
private final Properties driverProperties;
|
private final Properties driverProperties;
|
||||||
|
|
||||||
|
private String jdbcUrl;
|
||||||
|
|
||||||
private Driver driver;
|
private Driver driver;
|
||||||
|
|
||||||
public DriverDataSource(String jdbcUrl, String driverClassName, Properties properties, String username, String password) {
|
public DriverDataSource(String jdbcUrl,
|
||||||
|
String driverClassName,
|
||||||
|
Properties properties,
|
||||||
|
String username,
|
||||||
|
String password) {
|
||||||
this.jdbcUrl = jdbcUrl;
|
this.jdbcUrl = jdbcUrl;
|
||||||
this.driverProperties = new Properties();
|
this.driverProperties = new Properties();
|
||||||
for (Entry<Object, Object> entry : properties.entrySet()) {
|
for (Entry<Object, Object> entry : properties.entrySet()) {
|
||||||
driverProperties.setProperty(entry.getKey().toString(), entry.getValue().toString());
|
driverProperties.setProperty(entry.getKey().toString(), entry.getValue().toString());
|
||||||
}
|
}
|
||||||
|
if (jdbcUrl != null) {
|
||||||
|
logger.log(Level.INFO, () -> "DriverManager looking for JDBC URL " + jdbcUrl);
|
||||||
|
}
|
||||||
if (username != null) {
|
if (username != null) {
|
||||||
setUser(username);
|
setUser(username);
|
||||||
}
|
}
|
||||||
|
@ -51,25 +63,25 @@ public class DriverDataSource implements DataSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (driver == null) {
|
if (driver == null) {
|
||||||
logger.warning("Registered driver with driverClassName was not found, trying direct instantiation: " + driverClassName);
|
logger.log(Level.WARNING, "Registered driver with driverClassName was not found, trying direct instantiation: " + driverClassName);
|
||||||
Class<?> driverClass = null;
|
Class<?> driverClass = null;
|
||||||
ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
ClassLoader threadContextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||||
try {
|
try {
|
||||||
if (threadContextClassLoader != null) {
|
if (threadContextClassLoader != null) {
|
||||||
try {
|
try {
|
||||||
driverClass = threadContextClassLoader.loadClass(driverClassName);
|
driverClass = threadContextClassLoader.loadClass(driverClassName);
|
||||||
logger.fine("Driver class found in Thread context class loader: " + driverClassName + " " + threadContextClassLoader);
|
logger.log(Level.FINE, "Driver class found in Thread context class loader: " + driverClassName + " " + threadContextClassLoader);
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
logger.fine("Driver class not found in Thread context class loader, trying classloader: " +
|
logger.log(Level.FINE, "Driver class not found in Thread context class loader, trying classloader: " +
|
||||||
driverClassName + " " + threadContextClassLoader + " " + this.getClass().getClassLoader());
|
driverClassName + " " + threadContextClassLoader + " " + this.getClass().getClassLoader());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (driverClass == null) {
|
if (driverClass == null) {
|
||||||
driverClass = this.getClass().getClassLoader().loadClass(driverClassName);
|
driverClass = this.getClass().getClassLoader().loadClass(driverClassName);
|
||||||
logger.fine("Driver class found in the PoolConfig class classloader:" + driverClassName + " " + this.getClass().getClassLoader());
|
logger.log(Level.FINE, "Driver class found in the PoolConfig class classloader:" + driverClassName + " " + this.getClass().getClassLoader());
|
||||||
}
|
}
|
||||||
} catch (ClassNotFoundException e) {
|
} catch (ClassNotFoundException e) {
|
||||||
logger.fine("Failed to load driver class from PoolConfig class classloader: " + driverClassName + " " + this.getClass().getClassLoader());
|
logger.log(Level.FINE, "Failed to load driver class from PoolConfig class classloader: " + driverClassName + " " + this.getClass().getClassLoader());
|
||||||
}
|
}
|
||||||
if (driverClass != null) {
|
if (driverClass != null) {
|
||||||
try {
|
try {
|
||||||
|
@ -80,18 +92,19 @@ public class DriverDataSource implements DataSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (driver == null && jdbcUrl != null) {
|
||||||
final String sanitizedUrl = jdbcUrl.replaceAll("([?&;][^&#;=]*[pP]assword=)[^&#;]*", "$1<masked>");
|
final String sanitizedUrl = jdbcUrl.replaceAll("([?&;][^&#;=]*[pP]assword=)[^&#;]*", "$1<masked>");
|
||||||
try {
|
try {
|
||||||
if (driver == null) {
|
|
||||||
driver = DriverManager.getDriver(jdbcUrl);
|
driver = DriverManager.getDriver(jdbcUrl);
|
||||||
logger.fine("Loaded driver with class name for jdbcUrl " + driver.getClass().getName() + " " + sanitizedUrl);
|
logger.log(Level.FINE, "Loaded driver with class name for jdbcUrl " + driver.getClass().getName() + " " + sanitizedUrl);
|
||||||
} else if (!driver.acceptsURL(jdbcUrl)) {
|
if (!driver.acceptsURL(sanitizedUrl)) {
|
||||||
throw new RuntimeException("Driver " + driverClassName + " claims to not accept jdbcUrl " + sanitizedUrl);
|
throw new RuntimeException("Driver " + driverClassName + " claims to not accept jdbcUrl " + sanitizedUrl);
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new RuntimeException("Failed to get driver instance for jdbcUrl " + sanitizedUrl, e);
|
throw new RuntimeException("Failed to get driver instance for jdbcUrl " + sanitizedUrl, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Connection getConnection() throws SQLException {
|
public Connection getConnection() throws SQLException {
|
||||||
|
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.xbib.jdbc.connection.pool.util;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class LoggingOutputStream extends ByteArrayOutputStream {
|
||||||
|
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
public LoggingOutputStream(Logger logger) {
|
||||||
|
super();
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flush() throws IOException {
|
||||||
|
super.flush();
|
||||||
|
String s = new String(buf, 0, count);
|
||||||
|
if (!s.isEmpty()) {
|
||||||
|
logger.log(Level.FINE, s);
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
|
@ -17,8 +17,10 @@ public class HouseKeeperCleanupTest {
|
||||||
private ScheduledThreadPoolExecutor executor;
|
private ScheduledThreadPoolExecutor executor;
|
||||||
|
|
||||||
@BeforeEach
|
@BeforeEach
|
||||||
public void before() throws Exception {
|
public void before() {
|
||||||
ThreadFactory threadFactory = new DefaultThreadFactory("global-housekeeper", true);
|
ThreadFactory threadFactory = new DefaultThreadFactory("global-housekeeper",
|
||||||
|
Thread.currentThread().getContextClassLoader(),
|
||||||
|
true);
|
||||||
executor = new ScheduledThreadPoolExecutor(1, threadFactory,
|
executor = new ScheduledThreadPoolExecutor(1, threadFactory,
|
||||||
new ThreadPoolExecutor.DiscardPolicy());
|
new ThreadPoolExecutor.DiscardPolicy());
|
||||||
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
|
executor.setExecuteExistingDelayedTasksAfterShutdownPolicy(false);
|
||||||
|
|
|
@ -27,7 +27,6 @@ public class MariaDBTest extends CommonTest {
|
||||||
static MariaDBContainer<?> mariaDBContainer;
|
static MariaDBContainer<?> mariaDBContainer;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// mariadb 10.3.6
|
|
||||||
mariaDBContainer = new MariaDBContainer<>("mariadb")
|
mariaDBContainer = new MariaDBContainer<>("mariadb")
|
||||||
.withDatabaseName("testDB")
|
.withDatabaseName("testDB")
|
||||||
.withUsername("testUser")
|
.withUsername("testUser")
|
||||||
|
@ -45,7 +44,7 @@ public class MariaDBTest extends CommonTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) throws Exception {
|
protected DatabaseProvider createDatabaseProvider(OptionsOverride options) {
|
||||||
Config config = ConfigSupplier.of()
|
Config config = ConfigSupplier.of()
|
||||||
.property("database.url", mariaDBContainer.getJdbcUrl())
|
.property("database.url", mariaDBContainer.getJdbcUrl())
|
||||||
.property("database.user", "testUser")
|
.property("database.user", "testUser")
|
||||||
|
@ -95,12 +94,14 @@ public class MariaDBTest extends CommonTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("MariaDB temporarily disabled")
|
@Disabled("MariaDB temporarily disabled")
|
||||||
|
@Test
|
||||||
@Override
|
@Override
|
||||||
public void intervals() {
|
public void intervals() {
|
||||||
super.intervals();
|
super.intervals();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Disabled("MariaDB temporarily disabled")
|
@Disabled("MariaDB temporarily disabled")
|
||||||
|
@Test
|
||||||
@Override
|
@Override
|
||||||
public void metadataColumnTypes() {
|
public void metadataColumnTypes() {
|
||||||
super.metadataColumnTypes();
|
super.metadataColumnTypes();
|
||||||
|
@ -251,5 +252,4 @@ public class MariaDBTest extends CommonTest {
|
||||||
+ " str_varchar, str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date from dbtest2 order by 1")
|
+ " str_varchar, str_fixed, str_lob, bin_blob, boolean_flag, date_millis, local_date from dbtest2 order by 1")
|
||||||
.queryMany(SqlArgs::readRow));
|
.queryMany(SqlArgs::readRow));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@ import org.xbib.jdbc.query.OptionsOverride;
|
||||||
import org.xbib.jdbc.query.Schema;
|
import org.xbib.jdbc.query.Schema;
|
||||||
import org.xbib.jdbc.test.CommonTest;
|
import org.xbib.jdbc.test.CommonTest;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exercise Database functionality with a real Oracle database.
|
* Exercise Database functionality with a real Oracle database.
|
||||||
*/
|
*/
|
||||||
|
@ -78,4 +81,16 @@ public class OracleTest extends CommonTest {
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTableExists() {
|
||||||
|
db.dropTableQuietly("dbtest");
|
||||||
|
new Schema().addTable("dbtest").addColumn("pk").primaryKey().schema().execute(db);
|
||||||
|
assertTrue(db.tableExists("dbtest"));
|
||||||
|
db.dropTableQuietly("dbtest");
|
||||||
|
assertFalse(db.tableExists("dbtest"));
|
||||||
|
db.ddl("create table \"dbtest\" (pk varchar(1))").execute();
|
||||||
|
assertTrue(db.tableExists("dbtest"));
|
||||||
|
db.dropTableQuietly("dbtest");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.xbib.jdbc.postgresql.Postgresql;
|
||||||
module org.xbib.jdbc.postgresql {
|
module org.xbib.jdbc.postgresql {
|
||||||
requires org.xbib.jdbc.query;
|
requires org.xbib.jdbc.query;
|
||||||
requires java.sql;
|
requires java.sql;
|
||||||
requires org.postgresql.jdbc;
|
requires org.postgresql.jdbc; // automatic module
|
||||||
uses Flavor;
|
uses Flavor;
|
||||||
exports org.xbib.jdbc.postgresql;
|
exports org.xbib.jdbc.postgresql;
|
||||||
provides Flavor with Postgresql;
|
provides Flavor with Postgresql;
|
||||||
|
|
|
@ -35,6 +35,7 @@ public class Listener implements Runnable {
|
||||||
while (true) {
|
while (true) {
|
||||||
try (Statement stmt = connection.createStatement();
|
try (Statement stmt = connection.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery("SELECT 1")) {
|
ResultSet rs = stmt.executeQuery("SELECT 1")) {
|
||||||
|
//
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
errorConsumer.accept(e);
|
errorConsumer.accept(e);
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,7 +102,7 @@ public class DatabaseImpl implements Database {
|
||||||
@Override
|
@Override
|
||||||
public void commitNow() {
|
public void commitNow() {
|
||||||
if (options.ignoreTransactionControl()) {
|
if (options.ignoreTransactionControl()) {
|
||||||
logger.fine("Ignoring call to commitNow()");
|
logger.log(Level.FINE, "Ignoring call to commitNow()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!options.allowTransactionControl()) {
|
if (!options.allowTransactionControl()) {
|
||||||
|
@ -118,7 +118,7 @@ public class DatabaseImpl implements Database {
|
||||||
@Override
|
@Override
|
||||||
public void rollbackNow() {
|
public void rollbackNow() {
|
||||||
if (options.ignoreTransactionControl()) {
|
if (options.ignoreTransactionControl()) {
|
||||||
logger.fine("Ignoring call to rollbackNow()");
|
logger.log(Level.FINE, "Ignoring call to rollbackNow()");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!options.allowTransactionControl()) {
|
if (!options.allowTransactionControl()) {
|
||||||
|
@ -200,14 +200,24 @@ public class DatabaseImpl implements Database {
|
||||||
public boolean tableExists(String tableName, String schemaName) throws DatabaseException {
|
public boolean tableExists(String tableName, String schemaName) throws DatabaseException {
|
||||||
if (tableName != null && connection != null) {
|
if (tableName != null && connection != null) {
|
||||||
try {
|
try {
|
||||||
|
// schema based check
|
||||||
DatabaseMetaData metadata = connection.getMetaData();
|
DatabaseMetaData metadata = connection.getMetaData();
|
||||||
String normalizedTable = flavor().normalizeTableName(tableName);
|
String normalizedTable = flavor().normalizeTableName(tableName);
|
||||||
ResultSet resultSet = metadata.getTables(connection.getCatalog(), schemaName, normalizedTable, new String[]{"TABLE", "VIEW"});
|
try (ResultSet resultSet = metadata.getTables(connection.getCatalog(), schemaName, normalizedTable, new String[]{"TABLE", "VIEW"})) {
|
||||||
while (resultSet.next()) {
|
while (resultSet.next()) {
|
||||||
if (normalizedTable.equals(resultSet.getString("TABLE_NAME"))) {
|
if (normalizedTable.equals(resultSet.getString("TABLE_NAME"))) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// otherwise, do a simple check
|
||||||
|
try (ResultSet resultSet = metadata.getTables(null, null, tableName, null) ) {
|
||||||
|
while (resultSet.next()) {
|
||||||
|
if (tableName.equals(resultSet.getString("TABLE_NAME"))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (SQLException exc) {
|
} catch (SQLException exc) {
|
||||||
throw new DatabaseException("Unable to look up table " + tableName
|
throw new DatabaseException("Unable to look up table " + tableName
|
||||||
+ " in schema " + schemaName + " : " + exc.getMessage(),
|
+ " in schema " + schemaName + " : " + exc.getMessage(),
|
||||||
|
@ -455,19 +465,14 @@ public class DatabaseImpl implements Database {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
params.forEach((k, v) -> {
|
params.forEach((k, v) -> {
|
||||||
if (v instanceof String) {
|
switch (v) {
|
||||||
sql.argString(k, (String) v);
|
case String s -> sql.argString(k, s);
|
||||||
} else if (v instanceof Integer) {
|
case Integer i -> sql.argInteger(k, i);
|
||||||
sql.argInteger(k, (Integer) v);
|
case Long l -> sql.argLong(k, l);
|
||||||
} else if (v instanceof Long) {
|
case Boolean b -> sql.argBoolean(k, b);
|
||||||
sql.argLong(k, (Long) v);
|
case LocalDate localDate -> sql.argLocalDate(k, localDate);
|
||||||
} else if (v instanceof Boolean) {
|
case LocalDateTime localDateTime -> sql.argLocalDateTime(k, localDateTime);
|
||||||
sql.argBoolean(k, (Boolean) v);
|
case null, default ->
|
||||||
} else if (v instanceof LocalDate) {
|
|
||||||
sql.argLocalDate(k, (LocalDate) v);
|
|
||||||
} else if (v instanceof LocalDateTime) {
|
|
||||||
sql.argLocalDateTime(k, (LocalDateTime) v);
|
|
||||||
} else {
|
|
||||||
throw new DatabaseException("unknown type for param: " + (v != null ? v.getClass() : "null"));
|
throw new DatabaseException("unknown type for param: " + (v != null ? v.getClass() : "null"));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -478,22 +483,15 @@ public class DatabaseImpl implements Database {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
params.forEach((k, v) -> {
|
params.forEach((k, v) -> {
|
||||||
if (v instanceof String) {
|
switch (v) {
|
||||||
sql.argString(k, (String) v);
|
case String s -> sql.argString(k, s);
|
||||||
} else if (v instanceof Integer) {
|
case Integer i -> sql.argInteger(k, i);
|
||||||
sql.argInteger(k, (Integer) v);
|
case Long l -> sql.argLong(k, l);
|
||||||
} else if (v instanceof Long) {
|
case Boolean b -> sql.argBoolean(k, b);
|
||||||
sql.argLong(k, (Long) v);
|
case LocalDate localDate -> sql.argLocalDate(k, localDate);
|
||||||
} else if (v instanceof Boolean) {
|
case LocalDateTime localDateTime -> sql.argLocalDateTime(k, localDateTime);
|
||||||
sql.argBoolean(k, (Boolean) v);
|
case null -> sql.argNull(k);
|
||||||
} else if (v instanceof LocalDate) {
|
default -> throw new DatabaseException("unknown type for param: " + v.getClass());
|
||||||
sql.argLocalDate(k, (LocalDate) v);
|
|
||||||
} else if (v instanceof LocalDateTime) {
|
|
||||||
sql.argLocalDateTime(k, (LocalDateTime) v);
|
|
||||||
} else if (v == null) {
|
|
||||||
sql.argNull(k);
|
|
||||||
} else {
|
|
||||||
throw new DatabaseException("unknown type for param: " + v.getClass());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -503,22 +501,15 @@ public class DatabaseImpl implements Database {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
params.forEach((k, v) -> {
|
params.forEach((k, v) -> {
|
||||||
if (v instanceof String) {
|
switch (v) {
|
||||||
sql.argString(k, (String) v);
|
case String s -> sql.argString(k, s);
|
||||||
} else if (v instanceof Integer) {
|
case Integer i -> sql.argInteger(k, i);
|
||||||
sql.argInteger(k, (Integer) v);
|
case Long l -> sql.argLong(k, l);
|
||||||
} else if (v instanceof Long) {
|
case Boolean b -> sql.argBoolean(k, b);
|
||||||
sql.argLong(k, (Long) v);
|
case LocalDate localDate -> sql.argLocalDate(k, localDate);
|
||||||
} else if (v instanceof Boolean) {
|
case LocalDateTime localDateTime -> sql.argLocalDateTime(k, localDateTime);
|
||||||
sql.argBoolean(k, (Boolean) v);
|
case null -> sql.argNull(k);
|
||||||
} else if (v instanceof LocalDate) {
|
default -> throw new DatabaseException("unknown type for param: " + v.getClass());
|
||||||
sql.argLocalDate(k, (LocalDate) v);
|
|
||||||
} else if (v instanceof LocalDateTime) {
|
|
||||||
sql.argLocalDateTime(k, (LocalDateTime) v);
|
|
||||||
} else if (v == null) {
|
|
||||||
sql.argNull(k);
|
|
||||||
} else {
|
|
||||||
throw new DatabaseException("unknown type for param: " + v.getClass());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -559,7 +550,10 @@ public class DatabaseImpl implements Database {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void consumeQueue(String table, String channel, int limit, Consumer<String> consumer) throws SQLException {
|
public void consumeQueue(String table,
|
||||||
|
String channel,
|
||||||
|
int limit,
|
||||||
|
Consumer<String> consumer) throws SQLException {
|
||||||
List<Long> consumedKeys = new ArrayList<>();
|
List<Long> consumedKeys = new ArrayList<>();
|
||||||
try {
|
try {
|
||||||
connection.setAutoCommit(false);
|
connection.setAutoCommit(false);
|
||||||
|
@ -572,13 +566,12 @@ public class DatabaseImpl implements Database {
|
||||||
consumer.accept(resultSet.getString("data"));
|
consumer.accept(resultSet.getString("data"));
|
||||||
}
|
}
|
||||||
succeedInQueue(connection, table, key);
|
succeedInQueue(connection, table, key);
|
||||||
} catch (QueueException e) {
|
} catch (Exception e) {
|
||||||
connection.rollback();
|
connection.rollback();
|
||||||
failInQueue(connection, table, key);
|
failInQueue(connection, table, key);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
connection.commit();
|
connection.commit();
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|
|
@ -5,13 +5,10 @@ import org.xbib.jdbc.connection.pool.PoolDataSource;
|
||||||
import org.xbib.jdbc.query.util.Metric;
|
import org.xbib.jdbc.query.util.Metric;
|
||||||
|
|
||||||
import javax.sql.DataSource;
|
import javax.sql.DataSource;
|
||||||
import java.io.Closeable;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.DriverManager;
|
import java.sql.DriverManager;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
@ -23,7 +20,7 @@ import java.util.logging.Logger;
|
||||||
* of this laziness, the underlying resources require explicit cleanup by calling either
|
* of this laziness, the underlying resources require explicit cleanup by calling either
|
||||||
* commitAndClose() or rollbackAndClose().
|
* commitAndClose() or rollbackAndClose().
|
||||||
*/
|
*/
|
||||||
public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
public final class DatabaseProvider implements Supplier<Database> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(DatabaseProvider.class.getName());
|
private static final Logger logger = Logger.getLogger(DatabaseProvider.class.getName());
|
||||||
|
|
||||||
|
@ -47,7 +44,7 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
return new DatabaseProviderBuilderImpl(ds, () -> {
|
return new DatabaseProviderBuilderImpl(ds, () -> {
|
||||||
try {
|
try {
|
||||||
if (ds == null) {
|
if (ds == null) {
|
||||||
throw new NullPointerException();
|
throw new IllegalArgumentException("data source must not be null");
|
||||||
}
|
}
|
||||||
return ds.getConnection();
|
return ds.getConnection();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
@ -170,7 +167,7 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
try {
|
try {
|
||||||
code.run(this);
|
code.run(this);
|
||||||
complete = true;
|
complete = true;
|
||||||
} catch (ThreadDeath | DatabaseException t) {
|
} catch (DatabaseException t) {
|
||||||
throw t;
|
throw t;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new DatabaseException("Error during transaction", t);
|
throw new DatabaseException("Error during transaction", t);
|
||||||
|
@ -188,7 +185,7 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
try {
|
try {
|
||||||
code.run(this);
|
code.run(this);
|
||||||
complete = true;
|
complete = true;
|
||||||
} catch (ThreadDeath | DatabaseException t) {
|
} catch (DatabaseException t) {
|
||||||
throw t;
|
throw t;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new DatabaseException("Error during transaction", t);
|
throw new DatabaseException("Error during transaction", t);
|
||||||
|
@ -207,7 +204,7 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
try {
|
try {
|
||||||
result = code.run(this);
|
result = code.run(this);
|
||||||
complete = true;
|
complete = true;
|
||||||
} catch (ThreadDeath | DatabaseException t) {
|
} catch (DatabaseException t) {
|
||||||
throw t;
|
throw t;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new DatabaseException("Error during transaction", t);
|
throw new DatabaseException("Error during transaction", t);
|
||||||
|
@ -227,7 +224,7 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
try {
|
try {
|
||||||
result = code.run(this);
|
result = code.run(this);
|
||||||
complete = true;
|
complete = true;
|
||||||
} catch (ThreadDeath | DatabaseException t) {
|
} catch (DatabaseException t) {
|
||||||
throw t;
|
throw t;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new DatabaseException("Error during transaction", t);
|
throw new DatabaseException("Error during transaction", t);
|
||||||
|
@ -249,7 +246,7 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
try {
|
try {
|
||||||
code.run(this, tx);
|
code.run(this, tx);
|
||||||
complete = true;
|
complete = true;
|
||||||
} catch (ThreadDeath | DatabaseException t) {
|
} catch (DatabaseException t) {
|
||||||
throw t;
|
throw t;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new DatabaseException("Error during transaction", t);
|
throw new DatabaseException("Error during transaction", t);
|
||||||
|
@ -270,7 +267,7 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
try {
|
try {
|
||||||
code.run(this, tx);
|
code.run(this, tx);
|
||||||
complete = true;
|
complete = true;
|
||||||
} catch (ThreadDeath | DatabaseException t) {
|
} catch (DatabaseException t) {
|
||||||
throw t;
|
throw t;
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
throw new DatabaseException("Error during transaction", t);
|
throw new DatabaseException("Error during transaction", t);
|
||||||
|
@ -287,9 +284,6 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
if (database != null) {
|
if (database != null) {
|
||||||
return database;
|
return database;
|
||||||
}
|
}
|
||||||
if (builder.isClosed()) {
|
|
||||||
throw new DatabaseException("Called get() on a DatabaseProvider after close()");
|
|
||||||
}
|
|
||||||
Metric metric = new Metric(logger.isLoggable(Level.FINE));
|
Metric metric = new Metric(logger.isLoggable(Level.FINE));
|
||||||
try {
|
try {
|
||||||
connection = builder.connectionProvider.get();
|
connection = builder.connectionProvider.get();
|
||||||
|
@ -299,7 +293,7 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
// Don't try to be clever about clearing it conditionally.
|
// Don't try to be clever about clearing it conditionally.
|
||||||
if (!builder.options.flavor().isAutoCommitOnly()) {
|
if (!builder.options.flavor().isAutoCommitOnly()) {
|
||||||
connection.setAutoCommit(false);
|
connection.setAutoCommit(false);
|
||||||
metric.checkpoint("setAutoCommit");
|
metric.checkpoint("setAutoCommit false");
|
||||||
}
|
}
|
||||||
} catch (SQLException e) {
|
} catch (SQLException e) {
|
||||||
throw new DatabaseException("Unable to set autoCommit for the connection", e);
|
throw new DatabaseException("Unable to set autoCommit for the connection", e);
|
||||||
|
@ -393,8 +387,7 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void close() {
|
||||||
public void close() throws IOException {
|
|
||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
try {
|
try {
|
||||||
connection.close();
|
connection.close();
|
||||||
|
@ -404,26 +397,22 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
}
|
}
|
||||||
connection = null;
|
connection = null;
|
||||||
database = null;
|
database = null;
|
||||||
builder.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DatabaseProviderBuilderImpl implements DatabaseProviderBuilder, Closeable {
|
private static class DatabaseProviderBuilderImpl implements DatabaseProviderBuilder {
|
||||||
|
|
||||||
private DataSource dataSource;
|
private final DataSource dataSource;
|
||||||
|
|
||||||
private final Supplier<Connection> connectionProvider;
|
private final Supplier<Connection> connectionProvider;
|
||||||
|
|
||||||
private final Options options;
|
private final Options options;
|
||||||
|
|
||||||
private final AtomicBoolean closed;
|
|
||||||
|
|
||||||
private DatabaseProviderBuilderImpl(DataSource dataSource,
|
private DatabaseProviderBuilderImpl(DataSource dataSource,
|
||||||
Supplier<Connection> connectionProvider,
|
Supplier<Connection> connectionProvider,
|
||||||
Options options) {
|
Options options) {
|
||||||
this.dataSource = dataSource;
|
this.dataSource = dataSource;
|
||||||
this.connectionProvider = connectionProvider;
|
this.connectionProvider = connectionProvider;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
this.closed = new AtomicBoolean(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -511,20 +500,5 @@ public final class DatabaseProvider implements Supplier<Database>, Closeable {
|
||||||
this.build().transact(tx);
|
this.build().transact(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void close() throws IOException {
|
|
||||||
if (closed.compareAndSet(false, true)) {
|
|
||||||
if (dataSource != null) {
|
|
||||||
if (dataSource instanceof Closeable) {
|
|
||||||
((Closeable) dataSource).close();
|
|
||||||
}
|
|
||||||
dataSource = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isClosed() {
|
|
||||||
return closed.get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +0,0 @@
|
||||||
package org.xbib.jdbc.query;
|
|
||||||
|
|
||||||
public class QueueException extends DatabaseException {
|
|
||||||
|
|
||||||
public QueueException(String message, Throwable cause) {
|
|
||||||
super(message, cause);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,6 +1,5 @@
|
||||||
package org.xbib.jdbc.query;
|
package org.xbib.jdbc.query;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -15,10 +14,6 @@ public class Table extends ArrayList<List<Object>> implements List<List<Object>>
|
||||||
|
|
||||||
private String search;
|
private String search;
|
||||||
|
|
||||||
private LocalDateTime from;
|
|
||||||
|
|
||||||
private LocalDateTime to;
|
|
||||||
|
|
||||||
private Integer offset;
|
private Integer offset;
|
||||||
|
|
||||||
private Integer size;
|
private Integer size;
|
||||||
|
@ -29,11 +24,12 @@ public class Table extends ArrayList<List<Object>> implements List<List<Object>>
|
||||||
|
|
||||||
private String groupByClause;
|
private String groupByClause;
|
||||||
|
|
||||||
private final List<Map.Entry<String, Boolean>> sort = new ArrayList<>();
|
private final List<Map.Entry<String, Boolean>> sort;
|
||||||
|
|
||||||
private long total;
|
private long total;
|
||||||
|
|
||||||
public Table() {
|
public Table() {
|
||||||
|
this.sort = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStatement(String statement) {
|
public void setStatement(String statement) {
|
||||||
|
@ -60,22 +56,6 @@ public class Table extends ArrayList<List<Object>> implements List<List<Object>>
|
||||||
return search;
|
return search;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFromDate(LocalDateTime from) {
|
|
||||||
this.from = from;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalDateTime getFromDate() {
|
|
||||||
return from;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setToDate(LocalDateTime to) {
|
|
||||||
this.to = to;
|
|
||||||
}
|
|
||||||
|
|
||||||
public LocalDateTime getToDate() {
|
|
||||||
return to;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setOffset(Integer offset) {
|
public void setOffset(Integer offset) {
|
||||||
this.offset = offset;
|
this.offset = offset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,13 +18,8 @@ import java.util.logging.Logger;
|
||||||
* to prevent SQL injection or any other bad things.
|
* to prevent SQL injection or any other bad things.
|
||||||
*/
|
*/
|
||||||
public class DebugSql {
|
public class DebugSql {
|
||||||
public static final String PARAM_SQL_SEPARATOR = "\tParamSql:\t";
|
|
||||||
|
|
||||||
public static String printDebugOnlySqlString(String sql, Object[] args, Options options) {
|
public static final String PARAM_SQL_SEPARATOR = "\tParamSql:\t";
|
||||||
StringBuilder buf = new StringBuilder();
|
|
||||||
printSql(buf, sql, args, false, true, options);
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void printSql(StringBuilder buf, String sql, Object[] args, Options options) {
|
public static void printSql(StringBuilder buf, String sql, Object[] args, Options options) {
|
||||||
printSql(buf, sql, args, true, options.isLogParameters(), options);
|
printSql(buf, sql, args, true, options.isLogParameters(), options);
|
||||||
|
@ -65,8 +60,7 @@ public class DebugSql {
|
||||||
for (int i = 0; i < argsToPrint.length; i++) {
|
for (int i = 0; i < argsToPrint.length; i++) {
|
||||||
buf.append(removeTabs(sqlParts[i]));
|
buf.append(removeTabs(sqlParts[i]));
|
||||||
Object argToPrint = argsToPrint[i];
|
Object argToPrint = argsToPrint[i];
|
||||||
if (argToPrint instanceof String) {
|
if (argToPrint instanceof String argToPrintString) {
|
||||||
String argToPrintString = (String) argToPrint;
|
|
||||||
int maxLength = options.maxStringLengthParam();
|
int maxLength = options.maxStringLengthParam();
|
||||||
if (argToPrintString.length() > maxLength && maxLength > 0) {
|
if (argToPrintString.length() > maxLength && maxLength > 0) {
|
||||||
buf.append("'").append(argToPrintString, 0, maxLength).append("...'");
|
buf.append("'").append(argToPrintString, 0, maxLength).append("...'");
|
||||||
|
@ -77,16 +71,12 @@ public class DebugSql {
|
||||||
}
|
}
|
||||||
} else if (argToPrint instanceof SqlNull || argToPrint == null) {
|
} else if (argToPrint instanceof SqlNull || argToPrint == null) {
|
||||||
buf.append("null");
|
buf.append("null");
|
||||||
} else if (argToPrint instanceof java.sql.Timestamp) {
|
} else if (argToPrint instanceof java.sql.Timestamp timestamp) {
|
||||||
java.sql.Timestamp timestamp = (java.sql.Timestamp) argToPrint;
|
|
||||||
LocalDateTime localDateTime = timestamp.toLocalDateTime();
|
LocalDateTime localDateTime = timestamp.toLocalDateTime();
|
||||||
buf.append(localDateTime.toString());
|
buf.append(localDateTime.toString());
|
||||||
//buf.append(options.flavor().dateAsSqlFunction((Timestamp) argToPrint, options.calendarForTimestamps()));
|
} else if (argToPrint instanceof java.sql.Date date) {
|
||||||
} else if (argToPrint instanceof java.sql.Date) {
|
|
||||||
java.sql.Date date = (java.sql.Date) argToPrint;
|
|
||||||
LocalDate localDate = date.toLocalDate();
|
LocalDate localDate = date.toLocalDate();
|
||||||
buf.append(localDate.toString());
|
buf.append(localDate.toString());
|
||||||
//buf.append(options.flavor().localDateAsSqlFunction((java.sql.Date) argToPrint));
|
|
||||||
} else if (argToPrint instanceof Number) {
|
} else if (argToPrint instanceof Number) {
|
||||||
buf.append(argToPrint);
|
buf.append(argToPrint);
|
||||||
} else if (argToPrint instanceof Boolean) {
|
} else if (argToPrint instanceof Boolean) {
|
||||||
|
@ -144,25 +134,22 @@ public class DebugSql {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void logSuccess(String sqlType, Logger log, Metric metric, String sql, Object[] args, Options options) {
|
public static void logSuccess(String sqlType, Logger log, Metric metric, String sql, Object[] args, Options options) {
|
||||||
if (log.isLoggable(Level.FINE)) {
|
if (log.isLoggable(Level.FINEST)) {
|
||||||
String msg = logMiddle('\t', sqlType, metric, null, sql, args, options);
|
log.log(Level.FINEST, () -> logMiddle('\t', sqlType, metric, null, sql, args, options));
|
||||||
log.fine(msg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void logWarning(String sqlType, Logger log, Metric metric, String errorCode, String sql, Object[] args,
|
public static void logWarning(String sqlType, Logger log, Metric metric, String errorCode, String sql, Object[] args,
|
||||||
Options options, Throwable t) {
|
Options options, Throwable t) {
|
||||||
if (log.isLoggable(Level.WARNING)) {
|
if (log.isLoggable(Level.WARNING)) {
|
||||||
String msg = logMiddle(' ', sqlType, metric, errorCode, sql, args, options);
|
log.log(Level.WARNING, logMiddle(' ', sqlType, metric, errorCode, sql, args, options), t);
|
||||||
log.log(Level.WARNING, msg, t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void logError(String sqlType, Logger log, Metric metric, String errorCode, String sql, Object[] args,
|
public static void logError(String sqlType, Logger log, Metric metric, String errorCode, String sql, Object[] args,
|
||||||
Options options, Throwable t) {
|
Options options, Throwable t) {
|
||||||
if (log.isLoggable(Level.SEVERE)) {
|
if (log.isLoggable(Level.SEVERE)) {
|
||||||
String msg = logMiddle(' ', sqlType, metric, errorCode, sql, args, options);
|
log.log(Level.SEVERE, logMiddle(' ', sqlType, metric, errorCode, sql, args, options), t);
|
||||||
log.log(Level.SEVERE, msg, t);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,26 +1,23 @@
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
versionCatalogs {
|
versionCatalogs {
|
||||||
libs {
|
libs {
|
||||||
version('gradle', '8.5')
|
version('gradle', '8.7')
|
||||||
library('mariadb', 'org.mariadb.jdbc', 'mariadb-java-client').version('3.1.3')
|
library('mariadb', 'org.mariadb.jdbc', 'mariadb-java-client').version('3.4.1')
|
||||||
library('oracle', 'com.oracle.database.jdbc','ojdbc11').version('23.2.0.0')
|
library('oracle', 'com.oracle.database.jdbc', 'ojdbc11').version('23.4.0.24.05')
|
||||||
library('postgresql', 'org.postgresql', 'postgresql').version('42.6.0')
|
library('postgresql', 'org.postgresql', 'postgresql').version('42.7.3')
|
||||||
}
|
}
|
||||||
testLibs {
|
testLibs {
|
||||||
version('junit', '5.10.1')
|
version('junit', '5.10.2')
|
||||||
version('testcontainers', '1.19.1')
|
version('testcontainers', '1.20.0')
|
||||||
library('junit-jupiter-api', 'org.junit.jupiter', 'junit-jupiter-api').versionRef('junit')
|
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-params', 'org.junit.jupiter', 'junit-jupiter-params').versionRef('junit')
|
||||||
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
library('junit-jupiter-engine', 'org.junit.jupiter', 'junit-jupiter-engine').versionRef('junit')
|
||||||
library('junit-jupiter-platform-launcher', 'org.junit.platform', 'junit-platform-launcher').version('1.10.1')
|
library('junit-jupiter-platform-launcher', 'org.junit.platform', 'junit-platform-launcher').version('1.10.1')
|
||||||
library('hamcrest', 'org.hamcrest', 'hamcrest-library').version('2.2')
|
library('hamcrest', 'org.hamcrest', 'hamcrest-library').version('2.2')
|
||||||
library('junit4', 'junit', 'junit').version('4.13.2')
|
library('junit4', 'junit', 'junit').version('4.13.2')
|
||||||
library('derby', 'org.apache.derby', 'derby').version('10.16.1.1')
|
library('derby', 'org.apache.derby', 'derby').version('10.17.1.0')
|
||||||
library('hsqldb', 'org.hsqldb', 'hsqldb').version('2.7.1')
|
library('hsqldb', 'org.hsqldb', 'hsqldb').version('2.7.3')
|
||||||
library('h2', 'com.h2database', 'h2').version('2.1.214')
|
library('h2', 'com.h2database', 'h2').version('2.3.230')
|
||||||
library('mariadb', 'org.mariadb.jdbc', 'mariadb-java-client').version('3.1.3')
|
|
||||||
library('oracle', 'com.oracle.database.jdbc','ojdbc11').version('23.2.0.0')
|
|
||||||
library('postgresql', 'org.postgresql', 'postgresql').version('42.6.0')
|
|
||||||
library('mockito-core', 'org.mockito', 'mockito-core').version('5.3.1')
|
library('mockito-core', 'org.mockito', 'mockito-core').version('5.3.1')
|
||||||
library('testcontainers', 'org.testcontainers', 'testcontainers').versionRef('testcontainers')
|
library('testcontainers', 'org.testcontainers', 'testcontainers').versionRef('testcontainers')
|
||||||
library('testcontainers-junit-jupiter', 'org.testcontainers', 'junit-jupiter').versionRef('testcontainers')
|
library('testcontainers-junit-jupiter', 'org.testcontainers', 'junit-jupiter').versionRef('testcontainers')
|
||||||
|
@ -32,6 +29,7 @@ dependencyResolutionManagement {
|
||||||
}
|
}
|
||||||
|
|
||||||
include 'jdbc-connection-pool'
|
include 'jdbc-connection-pool'
|
||||||
|
include 'jdbc-pool'
|
||||||
include 'jdbc-query'
|
include 'jdbc-query'
|
||||||
include 'jdbc-test'
|
include 'jdbc-test'
|
||||||
include 'jdbc-mariadb'
|
include 'jdbc-mariadb'
|
||||||
|
|
Loading…
Reference in a new issue