diff --git a/.github/workflows/analysis.yml b/.github/workflows/analysis.yml
index 5a3909c77..cdd11fdf4 100644
--- a/.github/workflows/analysis.yml
+++ b/.github/workflows/analysis.yml
@@ -96,5 +96,5 @@ jobs:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
run: |
mvn --batch-mode -DclickhouseVersion=$PREFERRED_LTS_VERSION \
- -Panalysis verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar
+ -Panalysis org.sonarsource.scanner.maven:sonar-maven-plugin:sonar verify
continue-on-error: true
diff --git a/clickhouse-jdbc/pom.xml b/clickhouse-jdbc/pom.xml
index a2abcced9..f0fe220de 100644
--- a/clickhouse-jdbc/pom.xml
+++ b/clickhouse-jdbc/pom.xml
@@ -20,6 +20,7 @@
4.1.4
JDBC
4.2
+ ${project.basedir}/target/site/jacoco-aggregate/jacoco.xml
clickhouse-jdbc-bin
com.clickhouse.jdbc.Main
diff --git a/client-v2/pom.xml b/client-v2/pom.xml
index ee94812f9..fe8e10cc9 100644
--- a/client-v2/pom.xml
+++ b/client-v2/pom.xml
@@ -45,6 +45,7 @@
slf4j-api
${slf4j.version}
+
org.apache.httpcomponents.client5
httpclient5
diff --git a/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java b/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java
index f902ef521..8a1589532 100644
--- a/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java
+++ b/client-v2/src/main/java/com/clickhouse/client/api/metadata/TableSchema.java
@@ -4,10 +4,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
-import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
import java.util.List;
import java.util.Map;
diff --git a/jdbc-v2/pom.xml b/jdbc-v2/pom.xml
index 2adaded36..307612d6a 100644
--- a/jdbc-v2/pom.xml
+++ b/jdbc-v2/pom.xml
@@ -20,7 +20,6 @@
4.1.4
JDBC
4.2
-
${project.groupId}.shaded
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java
index a534b5556..18ec3006c 100644
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java
@@ -1,9 +1,11 @@
package com.clickhouse.jdbc;
import com.clickhouse.client.api.metadata.TableSchema;
-import com.clickhouse.data.ClickHouseColumn;
import com.clickhouse.data.Tuple;
import com.clickhouse.jdbc.internal.ExceptionUtils;
+import com.clickhouse.jdbc.internal.JdbcUtils;
+import com.clickhouse.jdbc.metadata.ParameterMetaDataImpl;
+import com.clickhouse.jdbc.metadata.ResultSetMetaDataImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -28,7 +30,6 @@
import java.sql.SQLFeatureNotSupportedException;
import java.sql.SQLType;
import java.sql.SQLXML;
-import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
@@ -45,6 +46,7 @@
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
@@ -64,9 +66,12 @@ public class PreparedStatementImpl extends StatementImpl implements PreparedStat
String [] valueSegments;
Object [] parameters;
String insertIntoSQL;
-
StatementType statementType;
+ private final ParameterMetaData parameterMetaData;
+
+ private ResultSetMetaData resultSetMetaData = null;
+
public PreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLException {
super(connection);
this.originalSql = sql.trim();
@@ -74,7 +79,7 @@ public PreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLEx
this.sqlSegments = splitStatement(originalSql);
this.statementType = parseStatementType(originalSql);
- if (statementType == StatementType.INSERT) {
+ if (this.statementType == StatementType.INSERT) {
insertIntoSQL = originalSql.substring(0, originalSql.indexOf("VALUES") + 6);
valueSegments = originalSql.substring(originalSql.indexOf("VALUES") + 6).split("\\?");
}
@@ -82,6 +87,7 @@ public PreparedStatementImpl(ConnectionImpl connection, String sql) throws SQLEx
//Create an array of objects to store the parameters
this.parameters = new Object[sqlSegments.length - 1];
this.defaultCalendar = connection.defaultCalendar;
+ this.parameterMetaData = new ParameterMetaDataImpl(this.parameters.length);
}
private String compileSql(String [] segments) {
@@ -303,7 +309,32 @@ public void setArray(int parameterIndex, Array x) throws SQLException {
@Override
public ResultSetMetaData getMetaData() throws SQLException {
checkClosed();
- return null;
+
+ if (resultSetMetaData == null && currentResultSet == null) {
+ // before execution
+ if (statementType == StatementType.SELECT) {
+ try {
+ // Replace '?' with NULL to make SQL valid for DESCRIBE
+ String sql = JdbcUtils.replaceQuestionMarks(originalSql, JdbcUtils.NULL);
+ TableSchema tSchema = connection.getClient().getTableSchemaFromQuery(sql);
+ resultSetMetaData = new ResultSetMetaDataImpl(tSchema.getColumns(),
+ connection.getSchema(), connection.getCatalog(),
+ tSchema.getTableName(), JdbcUtils.DATA_TYPE_CLASS_MAP);
+ } catch (Exception e) {
+ LOG.warn("Failed to get schema for statement '{}'", originalSql);
+ }
+ }
+
+ if (resultSetMetaData == null) {
+ resultSetMetaData = new ResultSetMetaDataImpl(Collections.emptyList(),
+ connection.getSchema(), connection.getCatalog(),
+ "", JdbcUtils.DATA_TYPE_CLASS_MAP);
+ }
+ } else if (currentResultSet != null) {
+ resultSetMetaData = currentResultSet.getMetaData();
+ }
+
+ return resultSetMetaData;
}
@Override
@@ -350,10 +381,18 @@ public void setURL(int parameterIndex, URL x) throws SQLException {
parameters[parameterIndex - 1] = encodeObject(x);
}
+ /**
+ * Returned metadata has only minimal information about parameters. Currently only their count.
+ * Current implementation do not parse SQL to detect type of each parameter.
+ *
+ * @see ParameterMetaDataImpl
+ * @return {@link ParameterMetaDataImpl}
+ * @throws SQLException if the statement is close
+ */
@Override
public ParameterMetaData getParameterMetaData() throws SQLException {
checkClosed();
- return null;
+ return parameterMetaData;
}
@Override
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java
index 41aa8c1fb..535f9a495 100644
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/ResultSetImpl.java
@@ -1,5 +1,17 @@
package com.clickhouse.jdbc;
+import com.clickhouse.client.api.data_formats.ClickHouseBinaryFormatReader;
+import com.clickhouse.client.api.metadata.TableSchema;
+import com.clickhouse.client.api.query.QueryResponse;
+import com.clickhouse.data.ClickHouseColumn;
+import com.clickhouse.data.ClickHouseDataType;
+import com.clickhouse.jdbc.internal.ExceptionUtils;
+import com.clickhouse.jdbc.internal.JdbcUtils;
+import com.clickhouse.jdbc.metadata.ResultSetMetaDataImpl;
+import com.clickhouse.jdbc.types.Array;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.Reader;
@@ -7,27 +19,31 @@
import java.math.BigDecimal;
import java.net.URL;
import java.nio.charset.StandardCharsets;
-import java.sql.*;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.NClob;
+import java.sql.Ref;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.RowId;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLType;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
import java.time.ZonedDateTime;
import java.util.Calendar;
-import java.util.GregorianCalendar;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
-import com.clickhouse.client.api.data_formats.ClickHouseBinaryFormatReader;
-import com.clickhouse.client.api.metadata.TableSchema;
-import com.clickhouse.client.api.query.QueryResponse;
-import com.clickhouse.data.ClickHouseColumn;
-import com.clickhouse.data.ClickHouseDataType;
-import com.clickhouse.jdbc.internal.ExceptionUtils;
-import com.clickhouse.jdbc.internal.JdbcUtils;
-import com.clickhouse.jdbc.types.Array;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
public class ResultSetImpl implements ResultSet, JdbcV2Wrapper {
private static final Logger log = LoggerFactory.getLogger(ResultSetImpl.class);
- private final ResultSetMetaData metaData;
+ private ResultSetMetaData metaData;
protected ClickHouseBinaryFormatReader reader;
private QueryResponse response;
private boolean closed;
@@ -39,7 +55,12 @@ public ResultSetImpl(StatementImpl parentStatement, QueryResponse response, Clic
this.parentStatement = parentStatement;
this.response = response;
this.reader = reader;
- this.metaData = new com.clickhouse.jdbc.metadata.ResultSetMetaData(this);
+ TableSchema tableMetadata = reader.getSchema();
+
+ // Result set contains columns from one database (there is a special table engine 'Merge' to do cross DB queries)
+ this.metaData = new ResultSetMetaDataImpl(tableMetadata
+ .getColumns(), response.getSettings().getDatabase(), "", tableMetadata.getTableName(),
+ JdbcUtils.DATA_TYPE_CLASS_MAP);
this.closed = false;
this.wasNull = false;
this.defaultCalendar = parentStatement.connection.defaultCalendar;
@@ -49,7 +70,7 @@ protected ResultSetImpl(ResultSetImpl resultSet) {
this.parentStatement = resultSet.parentStatement;
this.response = resultSet.response;
this.reader = resultSet.reader;
- this.metaData = new com.clickhouse.jdbc.metadata.ResultSetMetaData(this);
+ this.metaData = resultSet.metaData;
this.closed = false;
this.wasNull = false;
this.defaultCalendar = parentStatement.connection.defaultCalendar;
@@ -431,6 +452,10 @@ public ResultSetMetaData getMetaData() throws SQLException {
return metaData;
}
+ protected void setMetaData(ResultSetMetaDataImpl metaData) {
+ this.metaData = metaData;
+ }
+
@Override
public Object getObject(int columnIndex) throws SQLException {
return getObject(columnIndex, JdbcUtils.convertToJavaClass(getSchema().getColumnByIndex(columnIndex).getDataType()));
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java
index fe565514d..6fb43b69f 100644
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/StatementImpl.java
@@ -19,7 +19,6 @@
import java.sql.SQLWarning;
import java.sql.Statement;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
@@ -60,7 +59,7 @@ protected enum StatementType {
SELECT, INSERT, DELETE, UPDATE, CREATE, DROP, ALTER, TRUNCATE, USE, SHOW, DESCRIBE, EXPLAIN, SET, KILL, OTHER, INSERT_INTO_SELECT
}
- protected static StatementType parseStatementType(String sql) {
+ public static StatementType parseStatementType(String sql) {
if (sql == null) {
return StatementType.OTHER;
}
@@ -184,6 +183,7 @@ public ResultSetImpl executeQuery(String sql, QuerySettings settings) throws SQL
mergedSettings.setQueryId(lastQueryId);
}
LOG.debug("Query ID: {}", lastQueryId);
+ mergedSettings.setDatabase(connection.getSchema());
try {
lastSql = parseJdbcEscapeSyntax(sql);
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ClientInfoProperties.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ClientInfoProperties.java
index 3c6913b64..ada5139d6 100644
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ClientInfoProperties.java
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ClientInfoProperties.java
@@ -1,37 +1,37 @@
-package com.clickhouse.jdbc.internal;
-
-public enum ClientInfoProperties {
-
- APPLICATION_NAME("ApplicationName", 255, "", "Client application name."),
- ;
-
- private String key;
- private int maxValue;
-
- private String defaultValue;
-
- private String description;
-
- ClientInfoProperties(String key, int maxValue, String defaultValue, String description) {
- this.key = key;
- this.maxValue = maxValue;
- this.defaultValue = defaultValue;
- this.description = description;
- }
-
- public String getKey() {
- return key;
- }
-
- public int getMaxValue() {
- return maxValue;
- }
-
- public String getDefaultValue() {
- return defaultValue;
- }
-
- public String getDescription() {
- return description;
- }
-}
+package com.clickhouse.jdbc.internal;
+
+public enum ClientInfoProperties {
+
+ APPLICATION_NAME("ApplicationName", 255, "", "Client application name."),
+ ;
+
+ private String key;
+ private int maxValue;
+
+ private String defaultValue;
+
+ private String description;
+
+ ClientInfoProperties(String key, int maxValue, String defaultValue, String description) {
+ this.key = key;
+ this.maxValue = maxValue;
+ this.defaultValue = defaultValue;
+ this.description = description;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public int getMaxValue() {
+ return maxValue;
+ }
+
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+}
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/DriverProperties.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/DriverProperties.java
index cf7721eeb..c2d82f246 100644
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/DriverProperties.java
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/DriverProperties.java
@@ -1,53 +1,53 @@
-package com.clickhouse.jdbc.internal;
-
-import java.util.Collections;
-import java.util.List;
-
-/**
- * JDBC driver specific properties. Should not include any of ClientConfigProperties.
- * Processing logic should be the follows
- * 1. If property is among DriverProperties then Driver handles it specially and will not pass to a client
- * 2. If property is not among DriverProperties then it is passed to a client
- */
-public enum DriverProperties {
-
- IGNORE_UNSUPPORTED_VALUES("jdbc_ignore_unsupported_values", ""),
- SCHEMA_TERM("jdbc_schema_term", ""),
- /**
- * Indicates if driver should create a secure connection over SSL/TLS
- */
- SECURE_CONNECTION("ssl", "false"),
-
- /**
- * query settings to be passed along with query operation.
- * {@see com.clickhouse.client.api.query.QuerySettings}
- */
- DEFAULT_QUERY_SETTINGS("default_query_settings", null);
- private final String key;
-
- private final String defaultValue;
-
- private final List choices;
-
- DriverProperties(String key, String defaultValue) {
- this(key, defaultValue, Collections.emptyList());
- }
-
- DriverProperties(String key, String defaultValue, List choices) {
- this.key = key;
- this.defaultValue = defaultValue;
- this.choices = choices;
- }
-
- public String getKey() {
- return key;
- }
-
- public String getDefaultValue() {
- return defaultValue;
- }
-
- public List getChoices() {
- return choices;
- }
-}
+package com.clickhouse.jdbc.internal;
+
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * JDBC driver specific properties. Should not include any of ClientConfigProperties.
+ * Processing logic should be the follows
+ * 1. If property is among DriverProperties then Driver handles it specially and will not pass to a client
+ * 2. If property is not among DriverProperties then it is passed to a client
+ */
+public enum DriverProperties {
+
+ IGNORE_UNSUPPORTED_VALUES("jdbc_ignore_unsupported_values", ""),
+ SCHEMA_TERM("jdbc_schema_term", ""),
+ /**
+ * Indicates if driver should create a secure connection over SSL/TLS
+ */
+ SECURE_CONNECTION("ssl", "false"),
+
+ /**
+ * query settings to be passed along with query operation.
+ * {@see com.clickhouse.client.api.query.QuerySettings}
+ */
+ DEFAULT_QUERY_SETTINGS("default_query_settings", null);
+ private final String key;
+
+ private final String defaultValue;
+
+ private final List choices;
+
+ DriverProperties(String key, String defaultValue) {
+ this(key, defaultValue, Collections.emptyList());
+ }
+
+ DriverProperties(String key, String defaultValue, List choices) {
+ this.key = key;
+ this.defaultValue = defaultValue;
+ this.choices = choices;
+ }
+
+ public String getKey() {
+ return key;
+ }
+
+ public String getDefaultValue() {
+ return defaultValue;
+ }
+
+ public List getChoices() {
+ return choices;
+ }
+}
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java
index 01662a8fd..754803fc1 100644
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java
@@ -3,6 +3,7 @@
import com.clickhouse.client.api.data_formats.internal.BinaryStreamReader;
import com.clickhouse.data.ClickHouseDataType;
import com.clickhouse.jdbc.types.Array;
+import com.google.common.collect.ImmutableMap;
import java.net.Inet4Address;
import java.net.Inet6Address;
@@ -22,10 +23,12 @@
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
public class JdbcUtils {
//Define a map to store the mapping between ClickHouse data types and SQL data types
- private static final Map CLICKHOUSE_TO_SQL_TYPE_MAP = generateTypeMap();
+ public static final Map CLICKHOUSE_TO_SQL_TYPE_MAP = generateTypeMap();
public static final Map CLICKHOUSE_TYPE_NAME_TO_SQL_TYPE_MAP = Collections.unmodifiableMap(generateTypeMap().entrySet()
.stream().collect(
@@ -70,10 +73,10 @@ private static Map generateTypeMap() {
map.put(ClickHouseDataType.LineString, JDBCType.OTHER);
map.put(ClickHouseDataType.MultiPolygon, JDBCType.OTHER);
map.put(ClickHouseDataType.MultiLineString, JDBCType.OTHER);
- return map;
+ return ImmutableMap.copyOf(map);
}
- private static final Map> SQL_TYPE_TO_CLASS_MAP = generateClassMap();
+ public static final Map> SQL_TYPE_TO_CLASS_MAP = generateClassMap();
private static Map> generateClassMap() {
Map> map = new HashMap<>();
map.put(JDBCType.CHAR, String.class);
@@ -110,6 +113,16 @@ private static Map> generateClassMap() {
map.put(JDBCType.LONGNVARCHAR, String.class);
map.put(JDBCType.NCLOB, java.sql.NClob.class);
map.put(JDBCType.SQLXML, java.sql.SQLXML.class);
+ return ImmutableMap.copyOf(map);
+ }
+
+ public static final Map> DATA_TYPE_CLASS_MAP = getDataTypeClassMap();
+ private static Map> getDataTypeClassMap() {
+ Map> map = new HashMap<>();
+ for (Map.Entry e : CLICKHOUSE_TO_SQL_TYPE_MAP.entrySet()) {
+ map.put(e.getKey(), SQL_TYPE_TO_CLASS_MAP.get(e.getValue()));
+ }
+
return map;
}
@@ -122,7 +135,7 @@ public static SQLType convertToSqlType(ClickHouseDataType clickhouseType) {
}
public static Class> convertToJavaClass(ClickHouseDataType clickhouseType) {
- return SQL_TYPE_TO_CLASS_MAP.get(convertToSqlType(clickhouseType));
+ return DATA_TYPE_CLASS_MAP.get(clickhouseType);
}
public static List tokenizeSQL(String sql) {
@@ -271,4 +284,26 @@ public static String escapeQuotes(String str) {
.replace("'", "\\'")
.replace("\"", "\\\"");
}
+
+ public static final String NULL = "NULL";
+
+ private static final Pattern REPLACE_Q_MARK_PATTERN = Pattern.compile("(\"[^\"]*\"|`[^`]*`|'[^']*')|(\\?)");
+
+ public static String replaceQuestionMarks(String sql, String replacement) {
+ Matcher matcher = REPLACE_Q_MARK_PATTERN.matcher(sql);
+
+ StringBuilder result = new StringBuilder();
+
+ while (matcher.find()) {
+ if (matcher.group(1) != null) {
+ // Quoted string — keep as-is
+ matcher.appendReplacement(result, Matcher.quoteReplacement(matcher.group(1)));
+ } else if (matcher.group(2) != null) {
+ // Question mark outside quotes — replace it
+ matcher.appendReplacement(result, Matcher.quoteReplacement(replacement));
+ }
+ }
+ matcher.appendTail(result);
+ return result.toString();
+ }
}
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/MetadataResultSet.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/MetadataResultSet.java
index f3403c6a8..77ee23a4e 100644
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/MetadataResultSet.java
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/MetadataResultSet.java
@@ -3,6 +3,7 @@
import com.clickhouse.client.api.metadata.TableSchema;
import com.clickhouse.data.ClickHouseColumn;
import com.clickhouse.jdbc.ResultSetImpl;
+import com.clickhouse.jdbc.metadata.ResultSetMetaDataImpl;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
@@ -22,6 +23,9 @@ public class MetadataResultSet extends ResultSetImpl {
public MetadataResultSet(ResultSetImpl resultSet) throws SQLException {
super(resultSet);
this.overridingSchemaAdaptor = new OverridingSchemaAdaptor(resultSet.getSchema());
+ this.setMetaData(new ResultSetMetaDataImpl(overridingSchemaAdaptor.getColumns(),
+ overridingSchemaAdaptor.getDatabaseName(), "",
+ overridingSchemaAdaptor.getTableName(), JdbcUtils.DATA_TYPE_CLASS_MAP));
ResultSetMetaData metaData = getMetaData();
int count = metaData.getColumnCount();
cachedColumnLabels = new String[count];
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ParameterMetaData.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ParameterMetaData.java
deleted file mode 100644
index 912aaf501..000000000
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ParameterMetaData.java
+++ /dev/null
@@ -1,108 +0,0 @@
-package com.clickhouse.jdbc.metadata;
-
-import com.clickhouse.data.ClickHouseColumn;
-import com.clickhouse.jdbc.JdbcV2Wrapper;
-import com.clickhouse.jdbc.internal.JdbcUtils;
-import com.clickhouse.jdbc.internal.ExceptionUtils;
-
-import java.sql.SQLException;
-import java.util.List;
-
-public class ParameterMetaData implements java.sql.ParameterMetaData, JdbcV2Wrapper {
- private final List params;
-
- protected ParameterMetaData(List params) throws SQLException {
- if (params == null) {
- throw ExceptionUtils.toSqlState(new IllegalArgumentException("Parameters array cannot be null."));
- }
-
- this.params = params;
- }
-
- protected ClickHouseColumn getParam(int param) throws SQLException {
- if (param < 1 || param > params.size()) {
- throw new SQLException("Parameter index out of range: " + param, ExceptionUtils.SQL_STATE_CLIENT_ERROR);
- }
-
- return params.get(param - 1);
- }
-
- @Override
- public int getParameterCount() throws SQLException {
- try {
- return params.size();
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
- }
-
- @Override
- public int isNullable(int param) throws SQLException {
- try {
- return getParam(param).isNullable() ? parameterNullable : parameterNoNulls;
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
- }
-
- @Override
- public boolean isSigned(int param) throws SQLException {
- try{
- return getParam(param).getDataType().isSigned();
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
- }
-
- @Override
- public int getPrecision(int param) throws SQLException {
- try {
- return getParam(param).getPrecision();
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
- }
-
- @Override
- public int getScale(int param) throws SQLException {
- try {
- return getParam(param).getScale();
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
- }
-
- @Override
- public int getParameterType(int param) throws SQLException {
- //TODO: Should we implement .getSQLType()?
- try {
- return JdbcUtils.convertToSqlType(getParam(param).getDataType()).getVendorTypeNumber();
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
- }
-
- @Override
- public String getParameterTypeName(int param) throws SQLException {
- try {
- return getParam(param).getDataType().name();
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
- }
-
- @Override
- public String getParameterClassName(int param) throws SQLException {
- //TODO: Should we implement .getClassName()?
- try {
- return getParam(param).getDataType().getObjectClass().getName();
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
- }
-
- @Override
- public int getParameterMode(int param) throws SQLException {
- return parameterModeIn;
- }
-}
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ParameterMetaDataImpl.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ParameterMetaDataImpl.java
new file mode 100644
index 000000000..bca28e3ba
--- /dev/null
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ParameterMetaDataImpl.java
@@ -0,0 +1,132 @@
+package com.clickhouse.jdbc.metadata;
+
+import com.clickhouse.jdbc.JdbcV2Wrapper;
+
+import java.sql.ParameterMetaData;
+import java.sql.SQLException;
+import java.sql.Types;
+
+/**
+ * Implement ParameterMetaData interface and provides minimal information about parameters.
+ * This class will return only actual number of parameters.
+ * This class cannot be used to determine exact datatype for a parameter.
+ */
+public class ParameterMetaDataImpl implements ParameterMetaData, JdbcV2Wrapper {
+
+ private static final int FAIL_SAFE_PRECISION = 0;
+
+ private static final int FAIL_SAFE_SCALE = 0;
+
+ private final int paramCount;
+
+ public ParameterMetaDataImpl(int paramCount) {
+ this.paramCount = paramCount;
+ }
+
+ @Override
+ public int getParameterCount() {
+ return paramCount;
+ }
+
+ private void checkParamIndex(int index) throws SQLException {
+ if (index > paramCount || index < 1) {
+ throw new SQLException("Parameter index out of range. " + (paramCount == 0 ? "There are no parameters" : "[1," + paramCount + "]"));
+ }
+ }
+
+ /**
+ * Always returns {@code ParameterMetaData.parameterNullableUnknown}.
+ *
+ * @param param parameter index starting from 1
+ * @return ParameterMetaData.parameterNullableUnknown
+ */
+ @Override
+ public int isNullable(int param) throws SQLException {
+ checkParamIndex(param);
+ return ParameterMetaData.parameterNullableUnknown;
+ }
+
+ /**
+ * Always returns {@code false}.
+ *
+ * @param param parameter index starting from 1
+ * @return false
+ */
+ @Override
+ public boolean isSigned(int param) throws SQLException {
+ checkParamIndex(param);
+ return false;
+ }
+
+ /**
+ * Always returns 0.
+ *
+ * @param param parameter index starting from 1
+ * @return 0
+ */
+ @Override
+ public int getPrecision(int param) throws SQLException {
+ checkParamIndex(param);
+ return FAIL_SAFE_PRECISION;
+ }
+
+ /**
+ * Always returns 0.
+ *
+ * @param param parameter index starting from 1
+ * @return 0
+ */
+ @Override
+ public int getScale(int param) throws SQLException {
+ checkParamIndex(param);
+ return FAIL_SAFE_SCALE;
+ }
+
+ /**
+ * Always returns {@code Types.OTHER}.
+ *
+ * @param param parameter index starting from 1
+ * @return {@code Types.OTHER}
+ */
+ @Override
+ public int getParameterType(int param) throws SQLException {
+ checkParamIndex(param);
+ return Types.OTHER;
+ }
+
+ /**
+ * Always returns "UNKNOWN".
+ *
+ * @param param parameter index starting from 1
+ * @return String {@code "UNKNOWN"}
+ */
+ @Override
+ public String getParameterTypeName(int param) throws SQLException {
+ checkParamIndex(param);
+ return "UNKNOWN";
+ }
+
+ /**
+ * Always returns {@code Object.class.getName()}.
+ *
+ * @param param the first parameter is 1, the second is 2, ...
+ * @return String {@code Object.class.getName()}
+ */
+ @Override
+ public String getParameterClassName(int param) throws SQLException {
+ checkParamIndex(param);
+ return Object.class.getName();
+ }
+
+ /**
+ * Always return {@code java.sql.ParameterMetaData#parameterModeIn}.
+ *
+ * @param param parameter index starting from 1
+ * @return {@code java.sql.ParameterMetaData#parameterModeIn}
+ */
+ @Override
+ public int getParameterMode(int param) throws SQLException {
+ checkParamIndex(param);
+ return parameterModeIn;
+ }
+}
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImpl.java
similarity index 74%
rename from jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java
rename to jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImpl.java
index ab759c685..0de57b4b8 100644
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaData.java
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImpl.java
@@ -1,50 +1,67 @@
package com.clickhouse.jdbc.metadata;
-import java.sql.SQLException;
-
-import com.clickhouse.client.api.metadata.TableSchema;
import com.clickhouse.data.ClickHouseColumn;
+import com.clickhouse.data.ClickHouseDataType;
import com.clickhouse.jdbc.JdbcV2Wrapper;
-import com.clickhouse.jdbc.ResultSetImpl;
-import com.clickhouse.jdbc.internal.JdbcUtils;
import com.clickhouse.jdbc.internal.ExceptionUtils;
+import com.clickhouse.jdbc.internal.JdbcUtils;
+
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+
+public class ResultSetMetaDataImpl implements java.sql.ResultSetMetaData, JdbcV2Wrapper {
+
+ private final List columns;
-public class ResultSetMetaData implements java.sql.ResultSetMetaData, JdbcV2Wrapper {
- private final ResultSetImpl resultSet;
- public ResultSetMetaData(ResultSetImpl resultSet) {
- this.resultSet = resultSet;
+ private final String schema;
+
+ private final String catalog;
+
+ private final String tableName;
+
+ private final Map> typeClassMap;
+
+ public ResultSetMetaDataImpl(List columns, String schema, String catalog, String tableName,
+ Map> typeClassMap) {
+ this.columns = columns;
+ this.schema = schema;
+ this.catalog = catalog;
+ this.tableName = tableName;
+ this.typeClassMap = typeClassMap;
}
private ClickHouseColumn getColumn(int column) throws SQLException {
- if (column < 1 || column > getColumnCount()) {
+ try {
+ return columns.get(column - 1);
+ } catch (IndexOutOfBoundsException e) {
throw new SQLException("Column index out of range: " + column, ExceptionUtils.SQL_STATE_CLIENT_ERROR);
}
- return resultSet.getSchema().getColumns().get(column - 1);
}
@Override
public int getColumnCount() throws SQLException {
- try {
- TableSchema schema = resultSet.getSchema();
- return schema.getColumns().size();
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
+ return columns.size();
}
@Override
public boolean isAutoIncrement(int column) throws SQLException {
- return false;
+ return false; // no auto-incremental types
}
@Override
public boolean isCaseSensitive(int column) throws SQLException {
- return true;
+ try {
+ // TODO: should be in sync with DatabaseMetadata
+ return getColumn(column).getDataType().isCaseSensitive();
+ } catch (Exception e) {
+ throw ExceptionUtils.toSqlState(e);
+ }
}
@Override
public boolean isSearchable(int column) throws SQLException {
- return true;
+ return true; // all columns are considered as searchable
}
@Override
@@ -95,7 +112,7 @@ public String getColumnName(int column) throws SQLException {
@Override
public String getSchemaName(int column) throws SQLException {
- return "";
+ return schema;
}
@Override
@@ -118,16 +135,12 @@ public int getScale(int column) throws SQLException {
@Override
public String getTableName(int column) throws SQLException {
- try {
- return resultSet.getSchema().getTableName();
- } catch (Exception e) {
- throw ExceptionUtils.toSqlState(e);
- }
+ return tableName;
}
@Override
public String getCatalogName(int column) throws SQLException {
- return "";
+ return catalog;
}
@Override
@@ -165,6 +178,10 @@ public boolean isDefinitelyWritable(int column) throws SQLException {
@Override
public String getColumnClassName(int column) throws SQLException {
- return null;
+ try {
+ return typeClassMap.getOrDefault(getColumn(column).getDataType(), Object.class).getName();
+ } catch (Exception e) {
+ throw ExceptionUtils.toSqlState(e);
+ }
}
}
diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/types/Array.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/types/Array.java
index d2e06b2b6..e463a8fb5 100644
--- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/types/Array.java
+++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/types/Array.java
@@ -7,7 +7,6 @@
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
-import java.sql.Types;
import java.util.List;
import java.util.Map;
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java
index 9346edcd6..d8901dd22 100644
--- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java
+++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/ConnectionTest.java
@@ -1,15 +1,12 @@
package com.clickhouse.jdbc;
-import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.sql.*;
import java.util.Arrays;
import java.util.Base64;
-import java.util.List;
import java.util.Properties;
import java.util.Properties;
-import java.util.concurrent.TimeUnit;
import java.util.UUID;
import com.clickhouse.client.ClickHouseNode;
@@ -18,23 +15,17 @@
import com.clickhouse.client.api.Client;
import com.clickhouse.client.api.ClientConfigProperties;
import com.clickhouse.client.api.ServerException;
-import com.clickhouse.client.api.enums.Protocol;
import com.clickhouse.client.api.internal.ServerSettings;
-import com.clickhouse.client.api.query.GenericRecord;
-import com.clickhouse.client.api.query.QueryResponse;
import com.clickhouse.jdbc.internal.ClientInfoProperties;
import com.clickhouse.jdbc.internal.DriverProperties;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.client.WireMock;
import com.github.tomakehurst.wiremock.common.ConsoleNotifier;
import com.github.tomakehurst.wiremock.core.WireMockConfiguration;
-import org.apache.hc.core5.http.HttpStatus;
-import com.clickhouse.jdbc.internal.JdbcUtils;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
-import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.fail;
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcIntegrationTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcIntegrationTest.java
index af42aada7..6b80b9d55 100644
--- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcIntegrationTest.java
+++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/JdbcIntegrationTest.java
@@ -5,7 +5,6 @@
import com.clickhouse.client.BaseIntegrationTest;
import com.clickhouse.client.ClickHouseProtocol;
import com.clickhouse.client.api.ClientConfigProperties;
-import com.clickhouse.client.api.internal.ServerSettings;
import com.clickhouse.client.api.query.GenericRecord;
import com.clickhouse.logging.Logger;
import com.clickhouse.logging.LoggerFactory;
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java
index 7f3f61ce5..59e6bb084 100644
--- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java
+++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java
@@ -1,12 +1,13 @@
package com.clickhouse.jdbc;
import org.apache.commons.lang3.RandomStringUtils;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
import java.sql.Array;
import java.sql.Connection;
-import java.sql.JDBCType;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
@@ -23,6 +24,8 @@
import static org.testng.Assert.assertTrue;
+
+
public class PreparedStatementTest extends JdbcIntegrationTest {
@Test(groups = { "integration" })
@@ -321,6 +324,48 @@ void testInsert() throws Exception {
}
}
+ @Test(dataProvider = "testGetMetadataDataProvider")
+ void testGetMetadata(String sql, int colCountBeforeExecution, Object[] values,
+ int colCountAfterExecution) throws Exception {
+ String tableName = "test_get_metadata";
+ runQuery("CREATE TABLE IF NOT EXISTS " + tableName + " ( a1 String, b2 Float, b3 Float ) Engine=MergeTree ORDER BY ()");
+
+ try (Connection conn = getJdbcConnection();
+ PreparedStatement stmt = conn.prepareStatement(String.format(sql, tableName))) {
+ ResultSetMetaData metadataRs = stmt.getMetaData();
+ assertNotNull(metadataRs);
+ Assert.assertEquals(metadataRs.getColumnCount(), colCountBeforeExecution);
+
+ for (int i = 1; i <= metadataRs.getColumnCount(); i++) {
+ assertEquals(metadataRs.getSchemaName(i), stmt.getConnection().getSchema());
+ }
+
+ if (values != null) {
+ for (int i = 0; i < values.length; i++) {
+ stmt.setObject(i + 1, values[i]);
+ }
+ }
+
+ stmt.execute();
+ metadataRs = stmt.getMetaData();
+
+ assertNotNull(metadataRs);
+ assertEquals(metadataRs.getColumnCount(), colCountAfterExecution);
+ for (int i = 1; i <= metadataRs.getColumnCount(); i++) {
+ assertEquals(metadataRs.getSchemaName(i), stmt.getConnection().getSchema());
+ }
+ }
+ }
+
+ @DataProvider(name = "testGetMetadataDataProvider")
+ static Object[][] testGetMetadataDataProvider() {
+ return new Object[][] {
+ {"INSERT INTO `%s` VALUES (?, ?, ?)", 0, new Object[]{"test", 0.3, 0.4}, 0},
+ {"SELECT * FROM `%s`", 3, null, 3},
+ {"SHOW TABLES", 0, null, 1}
+ };
+ }
+
@Test(groups = { "integration" })
void testMetabaseBug01() throws Exception {
try (Connection conn = getJdbcConnection()) {
@@ -456,7 +501,10 @@ void testMetabaseBug01() throws Exception {
void testStatementSplit() throws Exception {
try (Connection conn = getJdbcConnection()) {
try (Statement stmt = conn.createStatement()) {
- stmt.execute("CREATE TABLE `with_complex_id` (`v?``1` Int32, \"v?\"\"2\" Int32,`v?\\`3` Int32, \"v?\\\"4\" Int32) ENGINE Memory;");
+ stmt.execute("CREATE TABLE IF NOT EXISTS `with_complex_id` (`v?``1` Int32, " +
+ "\"v?\"\"2\" Int32,`v?\\`3` Int32, \"v?\\\"4\" Int32) ENGINE MergeTree ORDER BY ();");
+ stmt.execute("CREATE TABLE IF NOT EXISTS `test_stmt_split2` (v1 Int32, v2 String) ENGINE MergeTree ORDER BY (); ");
+ stmt.execute("INSERT INTO `test_stmt_split2` VALUES (1, 'abc'), (2, '?'), (3, '?')");
}
String insertQuery = "-- line comment1 ?\n"
+ "# line comment2 ?\n"
@@ -489,6 +537,20 @@ void testStatementSplit() throws Exception {
assertEquals(rs.getString(7), "test string3 ?\\");
}
}
+
+ try (PreparedStatement stmt = conn.prepareStatement("SELECT v1 FROM `test_stmt_split2` WHERE v1 > ? AND v2 = '?'")) {
+ stmt.setInt(1, 2);
+ try (ResultSet rs = stmt.executeQuery()) {
+ int count = 0;
+ while (rs.next()) {
+ count++;
+ assertEquals(rs.getInt(1), 3);
+ }
+
+ Assert.assertEquals(count, 1);
+ }
+ }
+
}
}
}
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java
index 8b5cca1f9..7396f037c 100644
--- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java
+++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/StatementTest.java
@@ -1,9 +1,7 @@
package com.clickhouse.jdbc;
import com.clickhouse.client.api.ClientConfigProperties;
-import com.clickhouse.client.api.ClientException;
import com.clickhouse.client.api.query.GenericRecord;
-import com.clickhouse.client.api.query.QuerySettings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
@@ -21,13 +19,9 @@
import java.sql.Statement;
import java.time.LocalDate;
import java.util.Arrays;
-import java.util.GregorianCalendar;
import java.util.List;
import java.util.Properties;
-import java.util.TimeZone;
-import java.util.UUID;
import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicReference;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
@@ -35,7 +29,6 @@
import static org.testng.Assert.assertNull;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
public class StatementTest extends JdbcIntegrationTest {
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcConfigurationTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcConfigurationTest.java
index 125ce0f85..771fed914 100644
--- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcConfigurationTest.java
+++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcConfigurationTest.java
@@ -7,11 +7,8 @@
import java.sql.DriverPropertyInfo;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Map;
import java.util.Properties;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.testng.Assert.assertEquals;
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcUtilsTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcUtilsTest.java
index e83e3f30c..009bff49d 100644
--- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcUtilsTest.java
+++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/JdbcUtilsTest.java
@@ -1,5 +1,6 @@
package com.clickhouse.jdbc.internal;
+import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import java.util.List;
@@ -57,4 +58,20 @@ public void testEscapeQuotes() {
assertEquals(JdbcUtils.escapeQuotes(inStr[i]), outStr[i]);
}
}
+
+ @Test(dataProvider = "testReplaceQuestionMark_dataProvider")
+ public void testReplaceQuestionMark(String sql, String result) {
+ assertEquals(JdbcUtils.replaceQuestionMarks(sql, "NULL"), result);
+ }
+
+ @DataProvider(name = "testReplaceQuestionMark_dataProvider")
+ public static Object[][] testReplaceQuestionMark_dataProvider() {
+ return new Object[][] {
+ {"", ""},
+ {" ", " "},
+ {"SELECT * FROM t WHERE a = '?'", "SELECT * FROM t WHERE a = '?'"},
+ {"SELECT `v2?` FROM t WHERE `v1?` = ?", "SELECT `v2?` FROM t WHERE `v1?` = NULL"},
+ {"INSERT INTO \"t2?\" VALUES (?, ?, 'some_?', ?)", "INSERT INTO \"t2?\" VALUES (NULL, NULL, 'some_?', NULL)"}
+ };
+ }
}
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java
index fcd955c39..066792cd8 100644
--- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java
+++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/DatabaseMetaDataTest.java
@@ -1,7 +1,6 @@
package com.clickhouse.jdbc.metadata;
import com.clickhouse.client.ClickHouseServerForTest;
-import com.clickhouse.client.api.command.CommandResponse;
import com.clickhouse.data.ClickHouseDataType;
import com.clickhouse.data.ClickHouseVersion;
import com.clickhouse.jdbc.JdbcIntegrationTest;
@@ -9,7 +8,6 @@
import com.clickhouse.jdbc.internal.DriverProperties;
import com.clickhouse.jdbc.internal.JdbcUtils;
import org.testng.Assert;
-import org.testng.annotations.Ignore;
import org.testng.annotations.Test;
import java.sql.Connection;
@@ -19,10 +17,8 @@
import java.sql.DatabaseMetaData;
import java.util.Arrays;
import java.util.Collections;
-import java.util.HashSet;
import java.util.List;
import java.util.Properties;
-import java.util.Set;
import static org.testng.Assert.*;
@@ -173,7 +169,7 @@ public void testGetCatalogs() throws Exception {
DatabaseMetaData dbmd = conn.getMetaData();
ResultSet rs = dbmd.getCatalogs();
assertFalse(rs.next());
- ResultSetMetaDataTest.assertColumnNames(rs, "TABLE_CAT");
+ ResultSetMetaDataImplTest.assertColumnNames(rs, "TABLE_CAT");
}
}
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ParameterMetaDataImplTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ParameterMetaDataImplTest.java
new file mode 100644
index 000000000..d039c8b76
--- /dev/null
+++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ParameterMetaDataImplTest.java
@@ -0,0 +1,84 @@
+package com.clickhouse.jdbc.metadata;
+
+import org.testng.annotations.Test;
+
+import java.sql.SQLException;
+import java.sql.Types;
+
+import static org.testng.Assert.*;
+
+
+public class ParameterMetaDataImplTest {
+ @Test(groups = {"integration"})
+ public void testGetParameterCount() {
+ ParameterMetaDataImpl metaData = new ParameterMetaDataImpl(0);
+ assertEquals(metaData.getParameterCount(), 0);
+
+ metaData = new ParameterMetaDataImpl(1);
+ assertEquals(metaData.getParameterCount(), 1);
+ }
+
+ @Test(groups = {"integration"})
+ public void testIsNullable() throws SQLException {
+ ParameterMetaDataImpl metaData = new ParameterMetaDataImpl(1);
+ assertEquals(metaData.isNullable(1), ParameterMetaDataImpl.parameterNullableUnknown);
+
+ assertThrows(() -> metaData.isNullable(0));
+ assertThrows(() -> metaData.isNullable(2));
+ }
+
+ @Test(groups = {"integration"})
+ public void testIsSigned() throws SQLException {
+ ParameterMetaDataImpl metaData = new ParameterMetaDataImpl(1);
+ assertFalse(metaData.isSigned(1));
+
+ assertThrows(() -> metaData.isSigned(0));
+ assertThrows(() -> metaData.isSigned(2));
+ }
+
+ @Test(groups = {"integration"})
+ public void testGetPrecisionAndScale() throws SQLException {
+ ParameterMetaDataImpl metaData = new ParameterMetaDataImpl(1);
+ assertEquals(metaData.getPrecision(1), 0);
+ assertEquals(metaData.getScale(1), 0);
+
+ assertThrows(() -> metaData.getPrecision(0));
+ assertThrows(() -> metaData.getPrecision(2));
+ }
+
+ @Test(groups = {"integration"})
+ public void testGetParameterType() throws SQLException {
+ ParameterMetaDataImpl metaData = new ParameterMetaDataImpl(1);
+ assertEquals(metaData.getParameterType(1), Types.OTHER);
+
+ assertThrows(() -> metaData.getParameterType(0));
+ assertThrows(() -> metaData.getParameterType(2));
+ }
+
+ @Test(groups = {"integration"})
+ public void testGetParameterTypeName() throws SQLException {
+ ParameterMetaDataImpl metaData = new ParameterMetaDataImpl(1);
+ assertEquals(metaData.getParameterTypeName(1), "UNKNOWN");
+
+ assertThrows(() -> metaData.getParameterTypeName(0));
+ assertThrows(() -> metaData.getParameterTypeName(2));
+ }
+
+ @Test(groups = {"integration"})
+ public void testGetParameterClassName() throws SQLException {
+ ParameterMetaDataImpl metaData = new ParameterMetaDataImpl(1);
+ assertEquals(metaData.getParameterClassName(1), Object.class.getName());
+
+ assertThrows(() -> metaData.getParameterClassName(0));
+ assertThrows(() -> metaData.getParameterClassName(2));
+ }
+
+ @Test(groups = {"integration"})
+ public void testGetParameterMode() throws SQLException {
+ ParameterMetaDataImpl metaData = new ParameterMetaDataImpl(1);
+ assertEquals(metaData.getParameterMode(1), ParameterMetaDataImpl.parameterModeIn);
+
+ assertThrows(() -> metaData.getParameterMode(0));
+ assertThrows(() -> metaData.getParameterMode(2));
+ }
+}
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ParameterMetaDataTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ParameterMetaDataTest.java
deleted file mode 100644
index 0420650b6..000000000
--- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ParameterMetaDataTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package com.clickhouse.jdbc.metadata;
-
-import com.clickhouse.data.ClickHouseColumn;
-import com.clickhouse.data.ClickHouseDataType;
-import com.clickhouse.jdbc.JdbcIntegrationTest;
-import org.testng.annotations.Test;
-
-import java.sql.SQLException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertTrue;
-
-
-public class ParameterMetaDataTest extends JdbcIntegrationTest {
- @Test(groups = { "integration" })
- public void testGetParameterCount() throws SQLException {
- ParameterMetaData metaData = new ParameterMetaData(Collections.emptyList());
- assertEquals(metaData.getParameterCount(), 0);
-
- metaData = new ParameterMetaData(List.of(ClickHouseColumn.of("param1", ClickHouseDataType.Int32, false)));
- assertEquals(metaData.getParameterCount(), 1);
- }
-
- @Test(groups = { "integration" })
- public void testIsNullable() throws SQLException {
- ClickHouseColumn column = ClickHouseColumn.of("param1", ClickHouseDataType.Int32, true);
- ParameterMetaData metaData = new ParameterMetaData(Collections.singletonList(column));
- assertEquals(metaData.isNullable(1), ParameterMetaData.parameterNullable);
- }
-
- @Test(groups = { "integration" })
- public void testIsSigned() throws SQLException {
- ClickHouseColumn column = ClickHouseColumn.of("param1", ClickHouseDataType.Int32, false);
- ParameterMetaData metaData = new ParameterMetaData(Collections.singletonList(column));
- assertTrue(metaData.isSigned(1));
-
- column = ClickHouseColumn.of("param2", ClickHouseDataType.UInt32, false);
- metaData = new ParameterMetaData(Collections.singletonList(column));
- assertFalse(metaData.isSigned(1));
- }
-
- @Test(groups = { "integration" })
- public void testGetPrecisionAndScale() throws SQLException {
- ClickHouseColumn column = ClickHouseColumn.of("param1", ClickHouseDataType.Int32, false, 10, 5);
- ParameterMetaData metaData = new ParameterMetaData(Collections.singletonList(column));
- assertEquals(metaData.getPrecision(1), 10);
- assertEquals(metaData.getScale(1), 5);
- }
-
- @Test(groups = { "integration" })
- public void testGetParameterType() throws SQLException {
- ClickHouseColumn column = ClickHouseColumn.of("param1", ClickHouseDataType.Int32, false);
- ParameterMetaData metaData = new ParameterMetaData(Collections.singletonList(column));
- assertEquals(metaData.getParameterType(1), java.sql.Types.INTEGER);
- }
-
- @Test(groups = { "integration" })
- public void testGetParameterTypeName() throws SQLException {
- ClickHouseColumn column = ClickHouseColumn.of("param1", ClickHouseDataType.Int32, false);
- ParameterMetaData metaData = new ParameterMetaData(Collections.singletonList(column));
- assertEquals(metaData.getParameterTypeName(1), "Int32");
- }
-
- @Test(groups = { "integration" })
- public void testGetParameterClassName() throws SQLException {
- ClickHouseColumn column = ClickHouseColumn.of("param1", ClickHouseDataType.Int32, false);
- ParameterMetaData metaData = new ParameterMetaData(Collections.singletonList(column));
- assertEquals(metaData.getParameterClassName(1), "java.lang.Integer");
- }
-
- @Test(groups = { "integration" })
- public void testGetParameterMode() throws SQLException {
- ClickHouseColumn column = ClickHouseColumn.of("param1", ClickHouseDataType.Int32, false);
- ParameterMetaData metaData = new ParameterMetaData(Collections.singletonList(column));
- assertEquals(metaData.getParameterMode(1), ParameterMetaData.parameterModeIn);
- }
-}
diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImplTest.java
similarity index 85%
rename from jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataTest.java
rename to jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImplTest.java
index 0b6c989a6..c722e85d3 100644
--- a/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataTest.java
+++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/metadata/ResultSetMetaDataImplTest.java
@@ -3,24 +3,28 @@
import com.clickhouse.jdbc.JdbcIntegrationTest;
import org.testng.annotations.Test;
+import java.math.BigInteger;
import java.sql.Connection;
+import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.Statement;
import java.sql.Types;
import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertThrows;
import static org.testng.Assert.assertTrue;
-public class ResultSetMetaDataTest extends JdbcIntegrationTest {
+public class ResultSetMetaDataImplTest extends JdbcIntegrationTest {
@Test(groups = { "integration" })
public void testGetColumnCount() throws Exception {
try (Connection conn = getJdbcConnection()) {
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT 1 AS a, 2 AS b, 3 AS c");
ResultSetMetaData rsmd = rs.getMetaData();
- assertEquals(3, rsmd.getColumnCount());
+ assertEquals(rsmd.getColumnCount(), 3);
}
}
}
@@ -31,7 +35,7 @@ public void testGetColumnLabel() throws Exception {
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT 1 AS a");
ResultSetMetaData rsmd = rs.getMetaData();
- assertEquals("a", rsmd.getColumnLabel(1));
+ assertEquals(rsmd.getColumnLabel(1), "a");
}
}
}
@@ -42,7 +46,7 @@ public void testGetColumnName() throws Exception {
try (Statement stmt = conn.createStatement()) {
ResultSet rs = stmt.executeQuery("SELECT 1 AS a");
ResultSetMetaData rsmd = rs.getMetaData();
- assertEquals("a", rsmd.getColumnName(1));
+ assertEquals(rsmd.getColumnName(1), "a");
}
}
}
@@ -54,9 +58,21 @@ public void testGetColumnTypeIntegers() throws Exception {
ResultSet rs = stmt.executeQuery("SELECT toInt8(1), toInt16(1), toInt32(1), toInt64(1) AS a");
ResultSetMetaData rsmd = rs.getMetaData();
assertEquals(rsmd.getColumnType(1), Types.TINYINT);
+ assertEquals(rsmd.getColumnClassName(1), Integer.class.getName());
assertEquals(rsmd.getColumnType(2), Types.SMALLINT);
+ assertEquals(rsmd.getColumnClassName(2), Integer.class.getName());
assertEquals(rsmd.getColumnType(3), Types.INTEGER);
+ assertEquals(rsmd.getColumnClassName(3), Integer.class.getName());
assertEquals(rsmd.getColumnType(4), Types.BIGINT);
+ assertEquals(rsmd.getColumnClassName(4), Long.class.getName());
+
+ for (int i = 1; i <= rsmd.getColumnCount(); i++) {
+ assertTrue(rsmd.isCaseSensitive(i));
+ assertFalse(rsmd.isCurrency(i));
+ assertEquals(rsmd.isNullable(i), ResultSetMetaData.columnNoNulls);
+ assertTrue(rsmd.isSearchable(i));
+ assertTrue(rsmd.isSigned(i));
+ }
}
}
}
diff --git a/pom.xml b/pom.xml
index 7fae19284..8bb776012 100644
--- a/pom.xml
+++ b/pom.xml
@@ -159,7 +159,7 @@
**/*0*.java,**/data/*Value.java,**/data/array/*Value.java,**/stream/*Stream.java
jacoco
reuseReports
- target/site/jacoco-aggregate/jacoco.xml
+ ${project.basedir}/**/target/site/jacoco-aggregate/jacoco.xml
java
${maven.build.timestamp}
@@ -393,6 +393,16 @@
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ 2.43.0
+
+
+
+
+
+
kr.motd.maven
os-maven-plugin