From 5cf3bb5ddf01591d3bb9dc35770e86593ffcdb97 Mon Sep 17 00:00:00 2001 From: aiceflower Date: Sun, 12 Apr 2026 17:41:45 +0800 Subject: [PATCH 1/3] #AI COMMIT# fix: Add DB2 validation query support for JDBC engine connection pool - Add DB2-specific validation query "SELECT 1 FROM SYSIBM.SYSDUMMY1" - Same pattern as existing Oracle validation query handling - Fixes DB2 connection pool validation error when using datasource name Co-Authored-By: Claude Opus 4.6 --- .../linkis/manager/engineplugin/jdbc/ConnectionManager.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/ConnectionManager.java b/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/ConnectionManager.java index db1c2ce9c6..0f7ca01e58 100644 --- a/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/ConnectionManager.java +++ b/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/ConnectionManager.java @@ -205,6 +205,8 @@ protected DataSource buildDataSource(String dbUrl, Map propertie datasource.setUrl(dbUrl); if (dbUrl.toLowerCase().contains("oracle")) { datasource.setValidationQuery("SELECT 1 FROM DUAL"); + } else if (dbUrl.toLowerCase().contains("db2")) { + datasource.setValidationQuery("SELECT 1 FROM SYSIBM.SYSDUMMY1"); } datasource.setUsername(username); if (AESUtils.LINKIS_DATASOURCE_AES_SWITCH.getValue()) { @@ -248,6 +250,8 @@ private Connection getConnectionFromDataSource( } if (url.contains("oracle")) { ((DruidDataSource) dataSource).setValidationQuery("SELECT 1 FROM DUAL"); + } else if (url.contains("db2")) { + ((DruidDataSource) dataSource).setValidationQuery("SELECT 1 FROM SYSIBM.SYSDUMMY1"); } return dataSource.getConnection(); } From 40c7b808df7d6b0f588d492becdedaefab0d8532 Mon Sep 17 00:00:00 2001 From: aiceflower Date: Sun, 12 Apr 2026 17:42:01 +0800 Subject: [PATCH 2/3] #AI COMMIT# fix: Exclude conflicting jars from JDBC plugin assembly - Exclude Jetty jars to avoid version conflicts with public-module - Exclude SLF4J bindings to prevent multiple binding errors - Exclude Hadoop jars to use shared public-module versions These exclusions prevent class loading conflicts when JDBC engine starts and uses jars from both plugin lib and public-module. Co-Authored-By: Claude Opus 4.6 --- .../jdbc/src/main/assembly/distribution.xml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/linkis-engineconn-plugins/jdbc/src/main/assembly/distribution.xml b/linkis-engineconn-plugins/jdbc/src/main/assembly/distribution.xml index 8aadec99a3..0e745a9cfc 100644 --- a/linkis-engineconn-plugins/jdbc/src/main/assembly/distribution.xml +++ b/linkis-engineconn-plugins/jdbc/src/main/assembly/distribution.xml @@ -45,6 +45,15 @@ org.apache.hbase:hbase-shaded-protobuf:jar org.apache.hbase:hbase-shaded-miscellaneous:jar org.apache.hbase:hbase-protocol-shaded:jar + + org.eclipse.jetty:jetty-*:jar + org.eclipse.jetty:jetty-runner:jar + + org.apache.logging.log4j:log4j-slf4j-impl:jar + org.slf4j:slf4j-reload4j:jar + org.slf4j:slf4j-log4j12:jar + + org.apache.hadoop:hadoop-*:jar From a78dd7b6fc792ec055b2f4b3c643375d3466488c Mon Sep 17 00:00:00 2001 From: aiceflower Date: Sun, 12 Apr 2026 18:00:26 +0800 Subject: [PATCH 3/3] #AI COMMIT# refactor: Make validation query configurable for different database types - Add configuration parameter 'wds.linkis.jdbc.validation.query.mapping' - Default mapping: oracle:SELECT 1 FROM DUAL,db2:SELECT 1 FROM SYSIBM.SYSDUMMY1 - Remove hardcoded database-specific validation query logic - To add new database type, just update configuration, no code change needed Benefits: - Configuration-driven approach for extensibility - Easy to add support for new databases without modifying source code - Default values work for most common databases Usage example: Add to linkis-engineconn.properties: wds.linkis.jdbc.validation.query.mapping=oracle:SELECT 1 FROM DUAL,db2:SELECT 1 FROM SYSIBM.SYSDUMMY1,postgresql:SELECT 1 Co-Authored-By: Claude Opus 4.6 --- .../engineplugin/jdbc/ConnectionManager.java | 71 ++++++++++++++++--- .../jdbc/constant/JDBCEngineConnConstant.java | 6 ++ .../jdbc/conf/JDBCConfiguration.scala | 9 +++ 3 files changed, 78 insertions(+), 8 deletions(-) diff --git a/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/ConnectionManager.java b/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/ConnectionManager.java index 0f7ca01e58..2cbce3abee 100644 --- a/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/ConnectionManager.java +++ b/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/ConnectionManager.java @@ -57,6 +57,9 @@ public class ConnectionManager { private final Map dataSourceFactories; private final JDBCDataSourceConfigurations jdbcDataSourceConfigurations; + // Cache for validation query mapping parsed from configuration + private volatile Map validationQueryMapping = null; + private static volatile ConnectionManager connectionManager; // NOSONAR private ScheduledExecutorService scheduledExecutorService; private Integer kinitFailCount = 0; @@ -64,6 +67,54 @@ public class ConnectionManager { private ConnectionManager() { jdbcDataSourceConfigurations = new JDBCDataSourceConfigurations(); dataSourceFactories = new HashMap<>(); + initValidationQueryMapping(); + } + + /** + * Parse validation query mapping from configuration. Format: dbType1:query1,dbType2:query2,... + * Example: oracle:SELECT 1 FROM DUAL,db2:SELECT 1 FROM SYSIBM.SYSDUMMY1 + */ + private void initValidationQueryMapping() { + String mappingConfig = JDBCConfiguration$.MODULE$.JDBC_VALIDATION_QUERY_MAPPING(); + Map mapping = new HashMap<>(); + if (StringUtils.isNotBlank(mappingConfig)) { + String[] entries = mappingConfig.split(","); + for (String entry : entries) { + String[] parts = entry.split(":"); + if (parts.length == 2) { + String dbType = parts[0].trim().toLowerCase(); + String query = parts[1].trim(); + mapping.put(dbType, query); + LOG.info("Loaded validation query mapping: {} -> {}", dbType, query); + } + } + } + this.validationQueryMapping = mapping; + } + + /** + * Get validation query for a specific JDBC URL based on database type. Returns null if no + * specific mapping found (will use default "SELECT 1"). + * + * @param jdbcUrl the JDBC connection URL + * @return the validation query for this database type, or null if using default + */ + private String getValidationQueryFromUrl(String jdbcUrl) { + if (jdbcUrl == null || validationQueryMapping == null || validationQueryMapping.isEmpty()) { + return null; + } + String lowerUrl = jdbcUrl.toLowerCase(); + for (Map.Entry entry : validationQueryMapping.entrySet()) { + if (lowerUrl.contains(entry.getKey())) { + LOG.debug( + "Using validation query '{}' for database type '{}' from URL: {}", + entry.getValue(), + entry.getKey(), + jdbcUrl); + return entry.getValue(); + } + } + return null; } public static ConnectionManager getInstance() { @@ -203,11 +254,13 @@ protected DataSource buildDataSource(String dbUrl, Map propertie DruidDataSource datasource = new DruidDataSource(); LOG.info("Database connection address information(数据库连接地址信息)=" + dbUrl); datasource.setUrl(dbUrl); - if (dbUrl.toLowerCase().contains("oracle")) { - datasource.setValidationQuery("SELECT 1 FROM DUAL"); - } else if (dbUrl.toLowerCase().contains("db2")) { - datasource.setValidationQuery("SELECT 1 FROM SYSIBM.SYSDUMMY1"); + + // Set validation query based on database type from configuration + String dbSpecificValidationQuery = getValidationQueryFromUrl(dbUrl); + if (dbSpecificValidationQuery != null) { + datasource.setValidationQuery(dbSpecificValidationQuery); } + datasource.setUsername(username); if (AESUtils.LINKIS_DATASOURCE_AES_SWITCH.getValue()) { // decrypt @@ -248,11 +301,13 @@ private Connection getConnectionFromDataSource( } } } - if (url.contains("oracle")) { - ((DruidDataSource) dataSource).setValidationQuery("SELECT 1 FROM DUAL"); - } else if (url.contains("db2")) { - ((DruidDataSource) dataSource).setValidationQuery("SELECT 1 FROM SYSIBM.SYSDUMMY1"); + + // Set validation query based on database type from configuration + String dbSpecificValidationQuery = getValidationQueryFromUrl(url); + if (dbSpecificValidationQuery != null) { + ((DruidDataSource) dataSource).setValidationQuery(dbSpecificValidationQuery); } + return dataSource.getConnection(); } diff --git a/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/constant/JDBCEngineConnConstant.java b/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/constant/JDBCEngineConnConstant.java index 50e1c0e653..96b93c44a7 100644 --- a/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/constant/JDBCEngineConnConstant.java +++ b/linkis-engineconn-plugins/jdbc/src/main/java/org/apache/linkis/manager/engineplugin/jdbc/constant/JDBCEngineConnConstant.java @@ -57,6 +57,12 @@ private JDBCEngineConnConstant() {} public static final String JDBC_POOL_TEST_WHILE_IDLE = "wds.linkis.jdbc.pool.testWhileIdle"; public static final String JDBC_POOL_VALIDATION_QUERY = "wds.linkis.jdbc.pool.validationQuery"; public static final String JDBC_POOL_DEFAULT_VALIDATION_QUERY = "SELECT 1"; + + // Configuration for database-specific validation queries + // Format: dbType1:query1,dbType2:query2,... + // Example: oracle:SELECT 1 FROM DUAL,db2:SELECT 1 FROM SYSIBM.SYSDUMMY1,mysql:SELECT 1 + public static final String JDBC_VALIDATION_QUERY_MAPPING = + "wds.linkis.jdbc.validation.query.mapping"; public static final String JDBC_POOL_TIME_BETWEEN_MIN_EVIC_IDLE_MS = "wds.linkis.jdbc.pool.minEvictableIdleTimeMillis"; public static final String JDBC_POOL_TIME_BETWEEN_EVIC_RUNS_MS = diff --git a/linkis-engineconn-plugins/jdbc/src/main/scala/org/apache/linkis/manager/engineplugin/jdbc/conf/JDBCConfiguration.scala b/linkis-engineconn-plugins/jdbc/src/main/scala/org/apache/linkis/manager/engineplugin/jdbc/conf/JDBCConfiguration.scala index 2b70663ea8..ce1bb4d09a 100644 --- a/linkis-engineconn-plugins/jdbc/src/main/scala/org/apache/linkis/manager/engineplugin/jdbc/conf/JDBCConfiguration.scala +++ b/linkis-engineconn-plugins/jdbc/src/main/scala/org/apache/linkis/manager/engineplugin/jdbc/conf/JDBCConfiguration.scala @@ -43,4 +43,13 @@ object JDBCConfiguration { val SUPPORT_CONN_PARAM_EXECUTE_ENABLE: Boolean = CommonVars[Boolean]("linkis.support.conn.param.execute.enable", true).getValue + // Validation query mapping for different database types + // Format: dbType1:query1,dbType2:query2,... + // Default includes common databases that need non-standard validation queries + val JDBC_VALIDATION_QUERY_MAPPING: String = + CommonVars[String]( + "wds.linkis.jdbc.validation.query.mapping", + "oracle:SELECT 1 FROM DUAL,db2:SELECT 1 FROM SYSIBM.SYSDUMMY1" + ).getValue + }