This is an automated email from the ASF dual-hosted git repository.
Caideyipi pushed a commit to branch codex/jdbc-driver-info
in repository https://gitbox.apache.org/repos/asf/iotdb.git
The following commit(s) were added to refs/heads/codex/jdbc-driver-info by this
push:
new e180e1ffbaf Improve JDBC standard interface behavior
e180e1ffbaf is described below
commit e180e1ffbaf69d9e655fdd0e93f29ccf3232e7e7
Author: Caideyipi <[email protected]>
AuthorDate: Mon Jun 8 18:34:28 2026 +0800
Improve JDBC standard interface behavior
---
.../iotdb/jdbc/IoTDBAbstractDatabaseMetadata.java | 4 +-
.../org/apache/iotdb/jdbc/IoTDBConnection.java | 4 +-
.../org/apache/iotdb/jdbc/IoTDBDataSource.java | 64 +++++++++-------
.../apache/iotdb/jdbc/IoTDBDataSourceFactory.java | 11 ++-
.../org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java | 4 +-
.../apache/iotdb/jdbc/IoTDBPreparedStatement.java | 6 +-
.../org/apache/iotdb/jdbc/IoTDBResultMetadata.java | 4 +-
.../java/org/apache/iotdb/jdbc/IoTDBStatement.java | 4 +-
.../iotdb/jdbc/IoTDBTablePreparedStatement.java | 6 +-
.../org/apache/iotdb/jdbc/IoTDBURLException.java | 4 +
...oTDBURLException.java => JdbcWrapperUtils.java} | 17 ++++-
.../src/main/java/org/apache/iotdb/jdbc/Utils.java | 87 +++++++++++++++++++---
.../org/apache/iotdb/jdbc/IoTDBConnectionTest.java | 19 +++++
.../iotdb/jdbc/IoTDBDataSourceFactoryTest.java | 29 ++++++++
.../iotdb/jdbc/IoTDBDatabaseMetadataTest.java | 18 +++++
.../apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java | 7 ++
.../iotdb/jdbc/IoTDBPreparedStatementTest.java | 17 +++++
.../apache/iotdb/jdbc/IoTDBResultMetadataTest.java | 20 +++++
.../org/apache/iotdb/jdbc/IoTDBStatementTest.java | 21 ++++++
.../jdbc/IoTDBTablePreparedStatementTest.java | 19 +++++
.../test/java/org/apache/iotdb/jdbc/UtilsTest.java | 24 ++++++
21 files changed, 331 insertions(+), 58 deletions(-)
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBAbstractDatabaseMetadata.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBAbstractDatabaseMetadata.java
index 3928657b933..5ffaea704c9 100644
---
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBAbstractDatabaseMetadata.java
+++
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBAbstractDatabaseMetadata.java
@@ -2858,11 +2858,11 @@ public abstract class IoTDBAbstractDatabaseMetadata
implements DatabaseMetaData
@Override
public <T> T unwrap(Class<T> arg0) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ return JdbcWrapperUtils.unwrap(this, arg0);
}
@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
- throw new SQLException(METHOD_NOT_SUPPORTED_STRING);
+ return JdbcWrapperUtils.isWrapperFor(this, arg0);
}
}
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
index c0f239c2625..66d17d43d79 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBConnection.java
@@ -157,12 +157,12 @@ public class IoTDBConnection implements Connection {
@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
- throw new SQLException(JdbcMessages.NOT_SUPPORT_IS_WRAPPER_FOR);
+ return JdbcWrapperUtils.isWrapperFor(this, arg0);
}
@Override
public <T> T unwrap(Class<T> arg0) throws SQLException {
- throw new SQLException(JdbcMessages.NOT_SUPPORT_UNWRAP);
+ return JdbcWrapperUtils.unwrap(this, arg0);
}
@Override
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDataSource.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDataSource.java
index c3f880565a3..34645c78c49 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDataSource.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDataSource.java
@@ -40,6 +40,8 @@ public class IoTDBDataSource implements DataSource {
private String password;
private Properties properties;
private Integer port = 6667;
+ private PrintWriter logWriter;
+ private int loginTimeout;
public IoTDBDataSource() {
properties = new Properties();
@@ -91,45 +93,38 @@ public class IoTDBDataSource implements DataSource {
@Override
public Connection getConnection() throws SQLException {
- try {
- return new IoTDBConnection(url, properties);
- } catch (TTransportException e) {
- LOGGER.error(JdbcMessages.GET_CONNECTION_ERROR, e);
- }
- return null;
+ return createConnection((Properties) properties.clone());
}
@Override
public Connection getConnection(String username, String password) throws
SQLException {
- try {
- Properties newProp = new Properties();
- setProperty(newProp, Config.AUTH_USER, username);
- setProperty(newProp, Config.AUTH_PASSWORD, password);
- return new IoTDBConnection(url, newProp);
- } catch (TTransportException e) {
- LOGGER.error(JdbcMessages.GET_CONNECTION_ERROR, e);
- }
- return null;
+ Properties newProp = (Properties) properties.clone();
+ setProperty(newProp, Config.AUTH_USER, username);
+ setProperty(newProp, Config.AUTH_PASSWORD, password);
+ return createConnection(newProp);
}
@Override
public PrintWriter getLogWriter() {
- return null;
+ return logWriter;
}
@Override
public void setLogWriter(PrintWriter printWriter) {
- // Do nothing
+ this.logWriter = printWriter;
}
@Override
- public void setLoginTimeout(int i) {
- // Do nothing
+ public void setLoginTimeout(int i) throws SQLException {
+ if (i < 0) {
+ throw new SQLException("loginTimeout must be >= 0");
+ }
+ this.loginTimeout = i;
}
@Override
public int getLoginTimeout() {
- return 0;
+ return loginTimeout;
}
@Override
@@ -139,15 +134,34 @@ public class IoTDBDataSource implements DataSource {
@Override
public <T> T unwrap(Class<T> aClass) throws SQLException {
- if (isWrapperFor(aClass)) {
- return aClass.cast(this);
- }
- throw new SQLException(JdbcMessages.CANNOT_UNWRAP_TO + aClass);
+ return JdbcWrapperUtils.unwrap(this, aClass);
}
@Override
public boolean isWrapperFor(Class<?> aClass) {
- return aClass != null && aClass.isInstance(this);
+ return JdbcWrapperUtils.isWrapperFor(this, aClass);
+ }
+
+ private Connection createConnection(Properties connectionProperties) throws
SQLException {
+ applyLoginTimeout(connectionProperties);
+ try {
+ return new IoTDBConnection(url, connectionProperties);
+ } catch (TTransportException e) {
+ LOGGER.error(JdbcMessages.GET_CONNECTION_ERROR, e);
+ throw new SQLException(
+ "Connection Error, please check whether the network is available or
the server"
+ + " has started.",
+ e);
+ }
+ }
+
+ private void applyLoginTimeout(Properties connectionProperties) {
+ if (loginTimeout <= 0 ||
connectionProperties.containsKey(Config.NETWORK_TIMEOUT)) {
+ return;
+ }
+ long timeoutInMs = (long) loginTimeout * 1000;
+ connectionProperties.setProperty(
+ Config.NETWORK_TIMEOUT, String.valueOf(Math.min(timeoutInMs,
Integer.MAX_VALUE)));
}
private void setProperty(String key, String value) {
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDataSourceFactory.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDataSourceFactory.java
index f81245d16b8..228ad925af5 100644
---
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDataSourceFactory.java
+++
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBDataSourceFactory.java
@@ -29,6 +29,8 @@ import javax.sql.DataSource;
import javax.sql.XADataSource;
import java.sql.Driver;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
public class IoTDBDataSourceFactory implements DataSourceFactory {
@@ -67,13 +69,14 @@ public class IoTDBDataSourceFactory implements
DataSourceFactory {
}
@Override
- public ConnectionPoolDataSource createConnectionPoolDataSource(Properties
properties) {
- return null;
+ public ConnectionPoolDataSource createConnectionPoolDataSource(Properties
properties)
+ throws SQLException {
+ throw new
SQLFeatureNotSupportedException(JdbcMessages.METHOD_NOT_SUPPORTED);
}
@Override
- public XADataSource createXADataSource(Properties properties) {
- return null;
+ public XADataSource createXADataSource(Properties properties) throws
SQLException {
+ throw new
SQLFeatureNotSupportedException(JdbcMessages.METHOD_NOT_SUPPORTED);
}
@Override
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
index 3ea3c52320d..9ed67182ce8 100644
---
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
+++
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSet.java
@@ -182,12 +182,12 @@ public class IoTDBJDBCResultSet implements ResultSet {
@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return JdbcWrapperUtils.isWrapperFor(this, iface);
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return JdbcWrapperUtils.unwrap(this, iface);
}
@Override
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
index 80f6530c18a..647b74a9e1a 100644
---
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
+++
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBPreparedStatement.java
@@ -195,13 +195,13 @@ public class IoTDBPreparedStatement extends
IoTDBStatement implements PreparedSt
}
@Override
- public <T> T unwrap(Class<T> iface) {
- return null;
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return JdbcWrapperUtils.unwrap(this, iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) {
- return false;
+ return JdbcWrapperUtils.isWrapperFor(this, iface);
}
};
}
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java
index 59279d88465..4fba689c3e5 100644
---
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java
+++
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBResultMetadata.java
@@ -70,12 +70,12 @@ public class IoTDBResultMetadata implements
ResultSetMetaData {
@Override
public boolean isWrapperFor(Class<?> arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return JdbcWrapperUtils.isWrapperFor(this, arg0);
}
@Override
public <T> T unwrap(Class<T> arg0) throws SQLException {
- throw new SQLException(Constant.METHOD_NOT_SUPPORTED);
+ return JdbcWrapperUtils.unwrap(this, arg0);
}
@SuppressWarnings({
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
index 1c6ce8c0e9b..49818558b59 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBStatement.java
@@ -182,12 +182,12 @@ public class IoTDBStatement implements Statement {
@Override
public boolean isWrapperFor(Class<?> iface) {
- return false;
+ return JdbcWrapperUtils.isWrapperFor(this, iface);
}
@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
- throw new SQLException(JdbcMessages.CANNOT_UNWRAP_TO + iface);
+ return JdbcWrapperUtils.unwrap(this, iface);
}
@Override
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBTablePreparedStatement.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBTablePreparedStatement.java
index 674ec164691..79312bc5f84 100644
---
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBTablePreparedStatement.java
+++
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBTablePreparedStatement.java
@@ -322,13 +322,13 @@ public class IoTDBTablePreparedStatement extends
IoTDBStatement implements Prepa
}
@Override
- public <T> T unwrap(Class<T> iface) {
- return null;
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return JdbcWrapperUtils.unwrap(this, iface);
}
@Override
public boolean isWrapperFor(Class<?> iface) {
- return false;
+ return JdbcWrapperUtils.isWrapperFor(this, iface);
}
};
}
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBURLException.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBURLException.java
index 81b12077e8c..a704218eb46 100644
---
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBURLException.java
+++
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBURLException.java
@@ -28,4 +28,8 @@ public class IoTDBURLException extends SQLException {
public IoTDBURLException(String reason) {
super(reason);
}
+
+ public IoTDBURLException(String reason, Throwable cause) {
+ super(reason, cause);
+ }
}
diff --git
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBURLException.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/JdbcWrapperUtils.java
similarity index 65%
copy from
iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBURLException.java
copy to
iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/JdbcWrapperUtils.java
index 81b12077e8c..8f9148d0e1e 100644
---
a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/IoTDBURLException.java
+++
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/JdbcWrapperUtils.java
@@ -19,13 +19,22 @@
package org.apache.iotdb.jdbc;
+import org.apache.iotdb.jdbc.i18n.JdbcMessages;
+
import java.sql.SQLException;
-public class IoTDBURLException extends SQLException {
+final class JdbcWrapperUtils {
- private static final long serialVersionUID = -5071922897222027267L;
+ static boolean isWrapperFor(Object wrapper, Class<?> iface) {
+ return iface != null && iface.isInstance(wrapper);
+ }
- public IoTDBURLException(String reason) {
- super(reason);
+ static <T> T unwrap(Object wrapper, Class<T> iface) throws SQLException {
+ if (isWrapperFor(wrapper, iface)) {
+ return iface.cast(wrapper);
+ }
+ throw new SQLException(JdbcMessages.CANNOT_UNWRAP_TO + iface);
}
+
+ private JdbcWrapperUtils() {}
}
diff --git a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
index 39b72df9a59..873e01e7d21 100644
--- a/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
+++ b/iotdb-client/jdbc/src/main/java/org/apache/iotdb/jdbc/Utils.java
@@ -115,26 +115,25 @@ public class Utils {
}
if (properties.containsKey(Config.DEFAULT_BUFFER_CAPACITY)) {
params.setThriftDefaultBufferSize(
-
Integer.parseInt(properties.getProperty(Config.DEFAULT_BUFFER_CAPACITY)));
+ parseIntegerProperty(properties, Config.DEFAULT_BUFFER_CAPACITY));
}
if (properties.containsKey(Config.THRIFT_FRAME_MAX_SIZE)) {
- params.setThriftMaxFrameSize(
-
Integer.parseInt(properties.getProperty(Config.THRIFT_FRAME_MAX_SIZE)));
+ params.setThriftMaxFrameSize(parseIntegerProperty(properties,
Config.THRIFT_FRAME_MAX_SIZE));
}
if (properties.containsKey(Config.VERSION)) {
-
params.setVersion(Constant.Version.valueOf(properties.getProperty(Config.VERSION)));
+ params.setVersion(parseVersionProperty(properties));
}
if (properties.containsKey(Config.NETWORK_TIMEOUT)) {
-
params.setNetworkTimeout(Integer.parseInt(properties.getProperty(Config.NETWORK_TIMEOUT)));
+ params.setNetworkTimeout(parseIntegerProperty(properties,
Config.NETWORK_TIMEOUT));
}
if (properties.containsKey(Config.TIME_ZONE)) {
- params.setTimeZone(properties.getProperty(Config.TIME_ZONE));
+ params.setTimeZone(validateTimeZoneProperty(properties));
}
if (properties.containsKey(Config.CHARSET)) {
- params.setCharset(properties.getProperty(Config.CHARSET));
+ params.setCharset(validateCharsetProperty(properties));
}
if (properties.containsKey(Config.USE_SSL)) {
-
params.setUseSSL(Boolean.parseBoolean(properties.getProperty(Config.USE_SSL)));
+ params.setUseSSL(parseBooleanProperty(properties));
}
if (properties.containsKey(Config.TRUST_STORE)) {
params.setTrustStore(properties.getProperty(Config.TRUST_STORE));
@@ -143,7 +142,7 @@ public class Utils {
params.setTrustStorePwd(properties.getProperty(Config.TRUST_STORE_PWD));
}
if (properties.containsKey(Config.SQL_DIALECT)) {
- params.setSqlDialect(properties.getProperty(Config.SQL_DIALECT));
+ params.setSqlDialect(validateSqlDialectProperty(properties));
}
return params;
@@ -238,5 +237,75 @@ public class Utils {
return "true".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value);
}
+ private static int parseIntegerProperty(Properties properties, String key)
+ throws IoTDBURLException {
+ String value = getPropertyValue(properties, key);
+ try {
+ return Integer.parseInt(value);
+ } catch (NumberFormatException e) {
+ throw invalidPropertyValue(key, value, e);
+ }
+ }
+
+ private static Constant.Version parseVersionProperty(Properties properties)
+ throws IoTDBURLException {
+ String value = getPropertyValue(properties, Config.VERSION);
+ try {
+ return Constant.Version.valueOf(value);
+ } catch (IllegalArgumentException e) {
+ throw invalidPropertyValue(Config.VERSION, value, e);
+ }
+ }
+
+ private static boolean parseBooleanProperty(Properties properties) throws
IoTDBURLException {
+ String value = getPropertyValue(properties, Config.USE_SSL);
+ if (!isBoolean(value)) {
+ throw invalidPropertyValue(Config.USE_SSL, value, null);
+ }
+ return Boolean.parseBoolean(value);
+ }
+
+ private static String validateTimeZoneProperty(Properties properties) throws
IoTDBURLException {
+ String value = getPropertyValue(properties, Config.TIME_ZONE);
+ try {
+ ZoneId.of(value);
+ } catch (DateTimeException e) {
+ throw invalidPropertyValue(Config.TIME_ZONE, value, e);
+ }
+ return value;
+ }
+
+ private static String validateCharsetProperty(Properties properties) throws
IoTDBURLException {
+ String value = getPropertyValue(properties, Config.CHARSET);
+ try {
+ Charset.forName(value);
+ } catch (Exception e) {
+ throw invalidPropertyValue(Config.CHARSET, value, e);
+ }
+ return value;
+ }
+
+ private static String validateSqlDialectProperty(Properties properties)
throws IoTDBURLException {
+ String value = getPropertyValue(properties, Config.SQL_DIALECT);
+ if (!Constant.TREE.equals(value) && !Constant.TABLE.equals(value)) {
+ throw invalidPropertyValue(Config.SQL_DIALECT, value, null);
+ }
+ return value;
+ }
+
+ private static String getPropertyValue(Properties properties, String key)
+ throws IoTDBURLException {
+ String value = properties.getProperty(key);
+ if (value == null) {
+ throw invalidPropertyValue(key, null, null);
+ }
+ return value;
+ }
+
+ private static IoTDBURLException invalidPropertyValue(String key, String
value, Throwable cause) {
+ return new IoTDBURLException(
+ "Invalid value for JDBC connection property " + key + ": " + value,
cause);
+ }
+
private Utils() {}
}
diff --git
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
index 2919e51d265..b1668dda5b2 100644
---
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
+++
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBConnectionTest.java
@@ -34,6 +34,7 @@ import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.sql.Connection;
import java.sql.SQLClientInfoException;
import java.sql.SQLException;
import java.time.ZoneId;
@@ -41,7 +42,10 @@ import java.util.ArrayList;
import java.util.List;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@@ -119,4 +123,19 @@ public class IoTDBConnectionTest {
connection.setQueryTimeout(60);
Assert.assertEquals(60, connection.getQueryTimeout());
}
+
+ @Test
+ public void testWrapperMethods() throws SQLException {
+ assertTrue(connection.isWrapperFor(IoTDBConnection.class));
+ assertTrue(connection.isWrapperFor(Connection.class));
+ assertFalse(connection.isWrapperFor(String.class));
+ assertFalse(connection.isWrapperFor(null));
+ assertSame(connection, connection.unwrap(IoTDBConnection.class));
+ assertSame(connection, connection.unwrap(Connection.class));
+ }
+
+ @Test(expected = SQLException.class)
+ public void testUnwrapRejectsUnsupportedClass() throws SQLException {
+ connection.unwrap(String.class);
+ }
}
diff --git
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDataSourceFactoryTest.java
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDataSourceFactoryTest.java
index f4073b24003..b2f3ad4926f 100644
---
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDataSourceFactoryTest.java
+++
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDataSourceFactoryTest.java
@@ -24,6 +24,8 @@ import org.osgi.service.jdbc.DataSourceFactory;
import javax.sql.DataSource;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.util.Properties;
@@ -105,6 +107,33 @@ public class IoTDBDataSourceFactoryTest {
new IoTDBDataSource().getParentLogger();
}
+ @Test(expected = SQLFeatureNotSupportedException.class)
+ public void testConnectionPoolDataSourceIsUnsupported() throws SQLException {
+ new IoTDBDataSourceFactory().createConnectionPoolDataSource(null);
+ }
+
+ @Test(expected = SQLFeatureNotSupportedException.class)
+ public void testXADataSourceIsUnsupported() throws SQLException {
+ new IoTDBDataSourceFactory().createXADataSource(null);
+ }
+
+ @Test
+ public void testDataSourceStoresLogWriterAndLoginTimeout() throws
SQLException {
+ IoTDBDataSource dataSource = new IoTDBDataSource();
+ PrintWriter logWriter = new PrintWriter(new StringWriter());
+
+ dataSource.setLogWriter(logWriter);
+ dataSource.setLoginTimeout(10);
+
+ assertSame(logWriter, dataSource.getLogWriter());
+ assertEquals(10, dataSource.getLoginTimeout());
+ }
+
+ @Test(expected = SQLException.class)
+ public void testDataSourceRejectsNegativeLoginTimeout() throws SQLException {
+ new IoTDBDataSource().setLoginTimeout(-1);
+ }
+
@Test(expected = SQLException.class)
public void testDataSourceConnectionWithCredentialsThrowsInvalidUrl() throws
SQLException {
IoTDBDataSource dataSource = new IoTDBDataSource();
diff --git
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
index ab29a141399..804f3f89d6b 100644
---
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
+++
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBDatabaseMetadataTest.java
@@ -48,6 +48,9 @@ import java.util.List;
import java.util.Map;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@@ -86,6 +89,21 @@ public class IoTDBDatabaseMetadataTest {
Assert.assertEquals("PKTABLE_CAT",
resultSet.getMetaData().getColumnName(2));
}
+ @Test
+ public void testWrapperMethods() throws SQLException {
+ assertTrue(databaseMetaData.isWrapperFor(IoTDBDatabaseMetadata.class));
+ assertTrue(databaseMetaData.isWrapperFor(DatabaseMetaData.class));
+ assertFalse(databaseMetaData.isWrapperFor(String.class));
+ assertFalse(databaseMetaData.isWrapperFor(null));
+ assertSame(databaseMetaData,
databaseMetaData.unwrap(IoTDBDatabaseMetadata.class));
+ assertSame(databaseMetaData,
databaseMetaData.unwrap(DatabaseMetaData.class));
+ }
+
+ @Test(expected = SQLException.class)
+ public void testUnwrapRejectsUnsupportedClass() throws SQLException {
+ databaseMetaData.unwrap(String.class);
+ }
+
@Test
public void testGetBestRowIdentifier() throws SQLException {
ResultSet resultSet = databaseMetaData.getBestRowIdentifier(null, null,
null, 0, true);
diff --git
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java
index 3fb60b8760d..854709fddbb 100644
---
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java
+++
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBJDBCResultSetTest.java
@@ -201,6 +201,13 @@ public class IoTDBJDBCResultSetTest {
fetchResultsResp.hasResultSet = true; // at the first time to fetch
try (ResultSet resultSet = statement.getResultSet()) {
+ Assert.assertTrue(resultSet.isWrapperFor(IoTDBJDBCResultSet.class));
+ Assert.assertTrue(resultSet.isWrapperFor(ResultSet.class));
+ Assert.assertFalse(resultSet.isWrapperFor(String.class));
+ Assert.assertFalse(resultSet.isWrapperFor(null));
+ Assert.assertSame(resultSet, resultSet.unwrap(IoTDBJDBCResultSet.class));
+ Assert.assertSame(resultSet, resultSet.unwrap(ResultSet.class));
+
// check columnInfoMap
Assert.assertEquals(1, resultSet.findColumn("Time"));
Assert.assertEquals(2, resultSet.findColumn("root.vehicle.d0.s2"));
diff --git
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
index f80b8a83936..acc6b523b5e 100644
---
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
+++
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBPreparedStatementTest.java
@@ -31,6 +31,7 @@ import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
+import java.sql.ParameterMetaData;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
@@ -38,7 +39,9 @@ import java.time.ZoneId;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -81,6 +84,20 @@ public class IoTDBPreparedStatementTest {
argument.getValue().getStatement());
}
+ @SuppressWarnings("resource")
+ @Test
+ public void testParameterMetadataWrapperMethods() throws Exception {
+ IoTDBPreparedStatement ps =
+ new IoTDBPreparedStatement(connection, client, sessionId, "SELECT ?",
zoneId);
+ ParameterMetaData metadata = ps.getParameterMetaData();
+
+ assertTrue(metadata.isWrapperFor(ParameterMetaData.class));
+ assertFalse(metadata.isWrapperFor(String.class));
+ assertFalse(metadata.isWrapperFor(null));
+ assertSame(metadata, metadata.unwrap(ParameterMetaData.class));
+ assertThrows(SQLException.class, () -> metadata.unwrap(String.class));
+ }
+
@SuppressWarnings("resource")
@Test
public void unusedArgument() throws SQLException {
diff --git
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBResultMetadataTest.java
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBResultMetadataTest.java
index dc9869bddda..b9e5b3dfedb 100644
---
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBResultMetadataTest.java
+++
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBResultMetadataTest.java
@@ -23,6 +23,7 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
+import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
@@ -32,6 +33,7 @@ import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class IoTDBResultMetadataTest {
@@ -173,4 +175,22 @@ public class IoTDBResultMetadataTest {
assertEquals(metadata.getColumnType(i + 1), types[i - 1]);
}
}
+
+ @Test
+ public void testWrapperMethods() throws SQLException {
+ metadata = new IoTDBResultMetadata(false, null, "QUERY", null, null,
false);
+
+ assertTrue(metadata.isWrapperFor(IoTDBResultMetadata.class));
+ assertTrue(metadata.isWrapperFor(ResultSetMetaData.class));
+ assertFalse(metadata.isWrapperFor(String.class));
+ assertFalse(metadata.isWrapperFor(null));
+ assertSame(metadata, metadata.unwrap(IoTDBResultMetadata.class));
+ assertSame(metadata, metadata.unwrap(ResultSetMetaData.class));
+ }
+
+ @Test(expected = SQLException.class)
+ public void testUnwrapRejectsUnsupportedClass() throws SQLException {
+ metadata = new IoTDBResultMetadata(false, null, "QUERY", null, null,
false);
+ metadata.unwrap(String.class);
+ }
}
diff --git
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
index 5cfd5342e05..95973222498 100644
---
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
+++
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBStatementTest.java
@@ -33,9 +33,13 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.sql.SQLException;
+import java.sql.Statement;
import java.time.ZoneId;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;
@@ -106,4 +110,21 @@ public class IoTDBStatementTest {
statement.setQueryTimeout(100);
Assert.assertEquals(100, statement.getQueryTimeout());
}
+
+ @Test
+ public void testWrapperMethods() throws SQLException {
+ IoTDBStatement statement = new IoTDBStatement(connection, client,
sessionId, zoneID);
+
+ assertTrue(statement.isWrapperFor(IoTDBStatement.class));
+ assertTrue(statement.isWrapperFor(Statement.class));
+ assertFalse(statement.isWrapperFor(String.class));
+ assertFalse(statement.isWrapperFor(null));
+ assertSame(statement, statement.unwrap(IoTDBStatement.class));
+ assertSame(statement, statement.unwrap(Statement.class));
+ }
+
+ @Test(expected = SQLException.class)
+ public void testUnwrapRejectsUnsupportedClass() throws SQLException {
+ new IoTDBStatement(connection, client, sessionId,
zoneID).unwrap(String.class);
+ }
}
diff --git
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBTablePreparedStatementTest.java
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBTablePreparedStatementTest.java
index dd1c7ecbcb2..80aa9fa32af 100644
---
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBTablePreparedStatementTest.java
+++
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/IoTDBTablePreparedStatementTest.java
@@ -35,8 +35,13 @@ import org.mockito.MockitoAnnotations;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.sql.ParameterMetaData;
+import java.sql.SQLException;
import java.time.ZoneId;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.verify;
@@ -111,6 +116,20 @@ public class IoTDBTablePreparedStatementTest {
// ========== Table Model SQL Injection Prevention Tests ==========
+ @SuppressWarnings("resource")
+ @Test
+ public void testParameterMetadataWrapperMethods() throws Exception {
+ IoTDBTablePreparedStatement ps =
+ new IoTDBTablePreparedStatement(connection, client, sessionId, "SELECT
?", zoneId);
+ ParameterMetaData metadata = ps.getParameterMetaData();
+
+ assertTrue(metadata.isWrapperFor(ParameterMetaData.class));
+ assertFalse(metadata.isWrapperFor(String.class));
+ assertFalse(metadata.isWrapperFor(null));
+ assertSame(metadata, metadata.unwrap(ParameterMetaData.class));
+ assertThrows(SQLException.class, () -> metadata.unwrap(String.class));
+ }
+
@SuppressWarnings("resource")
@Test
public void testTableModelLoginInjectionWithComment() throws Exception {
diff --git
a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/UtilsTest.java
b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/UtilsTest.java
index e8241dd6aa2..9927d050cb9 100644
--- a/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/UtilsTest.java
+++ b/iotdb-client/jdbc/src/test/java/org/apache/iotdb/jdbc/UtilsTest.java
@@ -213,4 +213,28 @@ public class UtilsTest {
public void testParseUrlParamRejectsInvalidSqlDialectValue() throws
IoTDBURLException {
Utils.parseUrl("jdbc:iotdb://127.0.0.1:6667?sql_dialect=bad", new
Properties());
}
+
+ @Test
+ public void testParseUrlRejectsInvalidConnectionProperties() {
+ assertInvalidProperty(Config.DEFAULT_BUFFER_CAPACITY, "bad");
+ assertInvalidProperty(Config.THRIFT_FRAME_MAX_SIZE, "bad");
+ assertInvalidProperty(Config.VERSION, "bad");
+ assertInvalidProperty(Config.NETWORK_TIMEOUT, "bad");
+ assertInvalidProperty(Config.TIME_ZONE, "bad-time-zone");
+ assertInvalidProperty(Config.CHARSET, "bad-charset");
+ assertInvalidProperty(Config.USE_SSL, "bad");
+ assertInvalidProperty(Config.SQL_DIALECT, "bad");
+ }
+
+ private static void assertInvalidProperty(String key, String value) {
+ Properties properties = new Properties();
+ properties.setProperty(key, value);
+ try {
+ Utils.parseUrl("jdbc:iotdb://127.0.0.1:6667", properties);
+ } catch (IoTDBURLException e) {
+ assertTrue(e.getMessage().contains(key));
+ return;
+ }
+ fail("Expected IoTDBURLException for invalid property " + key);
+ }
}