Skip to content

Commit befae56

Browse files
author
Nico Verwer
committed
do not hang when database connection is not available
1 parent 4fa7494 commit befae56

File tree

1 file changed

+211
-9
lines changed
  • extensions/modules/sql/src/main/java/org/exist/xquery/modules/sql

1 file changed

+211
-9
lines changed

extensions/modules/sql/src/main/java/org/exist/xquery/modules/sql/SQLModule.java

Lines changed: 211 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,35 @@
3737
import org.apache.logging.log4j.LogManager;
3838
import org.apache.logging.log4j.Logger;
3939

40-
import org.exist.dom.QName;
4140
import org.exist.xquery.*;
4241

42+
import java.sql.Array;
43+
import java.sql.Blob;
44+
import java.sql.CallableStatement;
45+
import java.sql.Clob;
4346
import java.sql.Connection;
47+
import java.sql.DatabaseMetaData;
48+
import java.sql.NClob;
49+
import java.sql.PreparedStatement;
50+
import java.sql.SQLClientInfoException;
4451
import java.sql.SQLException;
45-
52+
import java.sql.SQLWarning;
53+
import java.sql.SQLXML;
54+
import java.sql.Savepoint;
55+
import java.sql.Statement;
56+
import java.sql.Struct;
57+
import java.util.Date;
4658
import java.util.List;
4759
import java.util.Map;
4860
import java.util.Map.Entry;
4961
import java.util.Properties;
5062
import java.util.concurrent.ConcurrentHashMap;
63+
import java.util.concurrent.Executor;
5164
import java.util.regex.Matcher;
5265
import java.util.regex.Pattern;
5366

5467
import org.exist.xquery.modules.ModuleUtils;
5568
import org.exist.xquery.modules.ModuleUtils.ContextMapEntryModifier;
56-
import org.exist.xquery.value.FunctionParameterSequenceType;
57-
import org.exist.xquery.value.FunctionReturnSequenceType;
58-
5969
import javax.annotation.Nullable;
6070

6171
import static org.exist.xquery.FunctionDSL.functionDefs;
@@ -86,6 +96,7 @@ public class SQLModule extends AbstractInternalModule {
8696
public final static String PREPARED_STATEMENTS_CONTEXTVAR = "_eXist_sql_prepared_statements";
8797

8898
private static final Map<String, HikariDataSource> CONNECTION_POOLS = new ConcurrentHashMap<>();
99+
private static final Map<String, Date> NO_CONNECTION_POOLS = new ConcurrentHashMap<>();
89100
private static final Pattern POOL_NAME_PATTERN = Pattern.compile("(pool\\.[0-9]+)\\.name");
90101

91102
public SQLModule(final Map<String, List<?>> parameters) {
@@ -105,7 +116,8 @@ public SQLModule(final Map<String, List<?>> parameters) {
105116
final String poolId = poolNameMatcher.group(1);
106117
final String poolName = parameter.getValue().get(0).toString();
107118
if (poolName != null && !poolName.isEmpty()) {
108-
if (!CONNECTION_POOLS.containsKey(poolName)) {
119+
boolean connectionFailure = NO_CONNECTION_POOLS.size() > 0;
120+
if (!CONNECTION_POOLS.containsKey(poolName) && !connectionFailure) {
109121

110122
final Properties poolProperties = new Properties();;
111123
poolProperties.setProperty("poolName", poolName);
@@ -121,9 +133,18 @@ public SQLModule(final Map<String, List<?>> parameters) {
121133
}
122134
}
123135

124-
final HikariConfig hikariConfig = new HikariConfig(poolProperties);
125-
final HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
126-
CONNECTION_POOLS.put(poolName, hikariDataSource);
136+
try {
137+
final HikariConfig hikariConfig = new HikariConfig(poolProperties);
138+
final HikariDataSource hikariDataSource = new HikariDataSource(hikariConfig);
139+
CONNECTION_POOLS.put(poolName, hikariDataSource);
140+
} catch (Exception ex) {
141+
connectionFailure = true;
142+
}
143+
}
144+
if (connectionFailure && !NO_CONNECTION_POOLS.containsKey(poolName)) {
145+
LOG.warn("No database connection for "+poolName+" could be made. Also not for "+String.join(", ", NO_CONNECTION_POOLS.keySet()));
146+
CONNECTION_POOLS.put(poolName, new NoConnectionHikariDataSource());
147+
NO_CONNECTION_POOLS.put(poolName, new Date());
127148
}
128149
}
129150
}
@@ -291,4 +312,185 @@ public void modifyEntry(final Entry<Long, PreparedStatementWithSQL> entry) {
291312
}
292313
});
293314
}
315+
316+
class NoConnectionHikariDataSource extends HikariDataSource {
317+
@Override
318+
public Connection getConnection() throws SQLException
319+
{
320+
return new Connection() {
321+
322+
@Override
323+
public <T> T unwrap(Class<T> iface) throws SQLException { return null; }
324+
325+
@Override
326+
public boolean isWrapperFor(Class<?> iface) throws SQLException { return false; }
327+
328+
@Override
329+
public Statement createStatement() throws SQLException { return null; }
330+
331+
@Override
332+
public PreparedStatement prepareStatement(String sql) throws SQLException { return null; }
333+
334+
@Override
335+
public CallableStatement prepareCall(String sql) throws SQLException { return null; }
336+
337+
@Override
338+
public String nativeSQL(String sql) throws SQLException { return null; }
339+
340+
@Override
341+
public void setAutoCommit(boolean autoCommit) throws SQLException {}
342+
343+
@Override
344+
public boolean getAutoCommit() throws SQLException { return false; }
345+
346+
@Override
347+
public void commit() throws SQLException {}
348+
349+
@Override
350+
public void rollback() throws SQLException {}
351+
352+
@Override
353+
public void close() throws SQLException {}
354+
355+
@Override
356+
public boolean isClosed() throws SQLException { return false; }
357+
358+
@Override
359+
public DatabaseMetaData getMetaData() throws SQLException { return null; }
360+
361+
@Override
362+
public void setReadOnly(boolean readOnly) throws SQLException {}
363+
364+
@Override
365+
public boolean isReadOnly() throws SQLException { return false; }
366+
367+
@Override
368+
public void setCatalog(String catalog) throws SQLException {}
369+
370+
@Override
371+
public String getCatalog() throws SQLException { return null; }
372+
373+
@Override
374+
public void setTransactionIsolation(int level) throws SQLException {}
375+
376+
@Override
377+
public int getTransactionIsolation() throws SQLException { return 0;}
378+
379+
@Override
380+
public SQLWarning getWarnings() throws SQLException { return null; }
381+
382+
@Override
383+
public void clearWarnings() throws SQLException {}
384+
385+
@Override
386+
public Statement createStatement(int resultSetType, int resultSetConcurrency)
387+
throws SQLException { return null; }
388+
389+
@Override
390+
public PreparedStatement prepareStatement(String sql, int resultSetType,
391+
int resultSetConcurrency) throws SQLException { return null; }
392+
393+
@Override
394+
public CallableStatement prepareCall(String sql, int resultSetType,
395+
int resultSetConcurrency) throws SQLException { return null; }
396+
397+
@Override
398+
public Map<String, Class<?>> getTypeMap() throws SQLException { return null; }
399+
400+
@Override
401+
public void setTypeMap(Map<String, Class<?>> map) throws SQLException {}
402+
403+
@Override
404+
public void setHoldability(int holdability) throws SQLException {}
405+
406+
@Override
407+
public int getHoldability() throws SQLException { return 0; }
408+
409+
@Override
410+
public Savepoint setSavepoint() throws SQLException { return null; }
411+
412+
@Override
413+
public Savepoint setSavepoint(String name) throws SQLException { return null; }
414+
415+
@Override
416+
public void rollback(Savepoint savepoint) throws SQLException {}
417+
418+
@Override
419+
public void releaseSavepoint(Savepoint savepoint) throws SQLException {}
420+
421+
@Override
422+
public Statement createStatement(int resultSetType, int resultSetConcurrency,
423+
int resultSetHoldability) throws SQLException { return null; }
424+
425+
@Override
426+
public PreparedStatement prepareStatement(String sql, int resultSetType,
427+
int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
428+
429+
@Override
430+
public CallableStatement prepareCall(String sql, int resultSetType,
431+
int resultSetConcurrency, int resultSetHoldability) throws SQLException { return null; }
432+
433+
@Override
434+
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
435+
throws SQLException { return null; }
436+
437+
@Override
438+
public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
439+
throws SQLException { return null; }
440+
441+
@Override
442+
public PreparedStatement prepareStatement(String sql, String[] columnNames)
443+
throws SQLException { return null; }
444+
445+
@Override
446+
public Clob createClob() throws SQLException { return null; }
447+
448+
@Override
449+
public Blob createBlob() throws SQLException { return null; }
450+
451+
@Override
452+
public NClob createNClob() throws SQLException { return null; }
453+
454+
@Override
455+
public SQLXML createSQLXML() throws SQLException { return null; }
456+
457+
@Override
458+
public boolean isValid(int timeout) throws SQLException { return false; }
459+
460+
@Override
461+
public void setClientInfo(String name, String value) throws SQLClientInfoException {}
462+
463+
@Override
464+
public void setClientInfo(Properties properties) throws SQLClientInfoException {}
465+
466+
@Override
467+
public String getClientInfo(String name) throws SQLException { return null; }
468+
469+
@Override
470+
public Properties getClientInfo() throws SQLException { return null; }
471+
472+
@Override
473+
public Array createArrayOf(String typeName, Object[] elements) throws SQLException { return null; }
474+
475+
@Override
476+
public Struct createStruct(String typeName, Object[] attributes) throws SQLException { return null; }
477+
478+
@Override
479+
public void setSchema(String schema) throws SQLException {}
480+
481+
@Override
482+
public String getSchema() throws SQLException { return null; }
483+
484+
@Override
485+
public void abort(Executor executor) throws SQLException {}
486+
487+
@Override
488+
public void setNetworkTimeout(Executor executor, int milliseconds)
489+
throws SQLException {}
490+
491+
@Override
492+
public int getNetworkTimeout() throws SQLException { return 0; }
493+
};
494+
}
495+
}
294496
}

0 commit comments

Comments
 (0)