Skip to content

Commit 05ab019

Browse files
committed
implemented type cast for parametrized types and added check for valid target types
1 parent d42b67a commit 05ab019

File tree

3 files changed

+87
-11
lines changed

3 files changed

+87
-11
lines changed

jdbc-v2/src/main/java/com/clickhouse/jdbc/PreparedStatementImpl.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
import java.sql.Statement;
4141
import java.sql.Time;
4242
import java.sql.Timestamp;
43-
import java.sql.Types;
4443
import java.time.Instant;
4544
import java.time.LocalDate;
4645
import java.time.LocalDateTime;
@@ -931,6 +930,9 @@ private ClickHouseDataType sqlType2ClickHouseDataType(SQLType type) throws SQLEx
931930
clickHouseDataType = JdbcUtils.SQL_TO_CLICKHOUSE_TYPE_MAP.get(type);
932931
} else if (type instanceof ClickHouseDataType) {
933932
clickHouseDataType = (ClickHouseDataType) type;
933+
if (JdbcUtils.INVALID_TARGET_TYPES.contains(clickHouseDataType)) {
934+
throw new SQLException("Type " + clickHouseDataType + " cannot be used as target type here because requires additional parameters and API doesn't have a way to pass them. ");
935+
}
934936
}
935937

936938
if (clickHouseDataType == null) {
@@ -944,6 +946,12 @@ private String encodeObject(Object x, ClickHouseDataType clickHouseDataType, Int
944946
String encodedObject = encodeObject(x);
945947
if (clickHouseDataType != null) {
946948
encodedObject += "::" + clickHouseDataType.name();
949+
if (clickHouseDataType.hasParameter()) {
950+
if (scaleOrLength == null) {
951+
throw new SQLException("Target type " + clickHouseDataType + " requires a parameter");
952+
}
953+
encodedObject += "(" + scaleOrLength + ")";
954+
}
947955
}
948956
return encodedObject;
949957
}

jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/JdbcUtils.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,11 @@
2424
import java.time.temporal.TemporalAccessor;
2525
import java.util.ArrayList;
2626
import java.util.Collections;
27+
import java.util.EnumSet;
2728
import java.util.HashMap;
2829
import java.util.List;
2930
import java.util.Map;
31+
import java.util.Set;
3032
import java.util.TreeMap;
3133
import java.util.stream.Collectors;
3234

@@ -124,6 +126,9 @@ private static Map<SQLType, Class<?>> generateClassMap() {
124126
return ImmutableMap.copyOf(map);
125127
}
126128

129+
public static final Set<ClickHouseDataType> INVALID_TARGET_TYPES = EnumSet.of(ClickHouseDataType.Nested, ClickHouseDataType.Enum8, ClickHouseDataType.Enum16, ClickHouseDataType.Enum,
130+
ClickHouseDataType.Tuple, ClickHouseDataType.Map, ClickHouseDataType.Nothing, ClickHouseDataType.Nullable, ClickHouseDataType.Variant);
131+
127132
public static final Map<ClickHouseDataType, Class<?>> DATA_TYPE_CLASS_MAP = getDataTypeClassMap();
128133
private static Map<ClickHouseDataType, Class<?>> getDataTypeClassMap() {
129134
Map<ClickHouseDataType, Class<?>> map = new HashMap<>();

jdbc-v2/src/test/java/com/clickhouse/jdbc/PreparedStatementTest.java

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,23 @@
44
import com.clickhouse.data.ClickHouseVersion;
55
import com.clickhouse.data.Tuple;
66
import com.clickhouse.jdbc.internal.DriverProperties;
7+
import com.clickhouse.jdbc.internal.JdbcUtils;
78
import org.apache.commons.lang3.RandomStringUtils;
8-
import org.testcontainers.shaded.com.fasterxml.jackson.databind.deser.std.UUIDDeserializer;
99
import org.testng.Assert;
1010
import org.testng.annotations.DataProvider;
11-
import org.testng.annotations.Ignore;
1211
import org.testng.annotations.Test;
1312

1413
import java.io.ByteArrayInputStream;
1514
import java.io.InputStreamReader;
1615
import java.sql.Array;
1716
import java.sql.Connection;
1817
import java.sql.Date;
18+
import java.sql.JDBCType;
1919
import java.sql.PreparedStatement;
2020
import java.sql.ResultSet;
2121
import java.sql.ResultSetMetaData;
2222
import java.sql.SQLException;
23+
import java.sql.SQLType;
2324
import java.sql.Statement;
2425
import java.sql.Timestamp;
2526
import java.sql.Types;
@@ -1260,22 +1261,84 @@ public void testWithInClause() throws Exception {
12601261
}
12611262
}
12621263

1264+
@Test(groups = {"integration"}, dataProvider = "testTypeCastsDP")
1265+
public void testTypeCastsWithoutArgument(Object value, SQLType targetType, ClickHouseDataType expectedType) throws Exception {
1266+
try (Connection conn = getJdbcConnection()) {
1267+
try (PreparedStatement stmt = conn.prepareStatement("select ?, toTypeName(?)")) {
1268+
stmt.setObject(1, value, targetType);
1269+
stmt.setObject(2, value, targetType);
1270+
1271+
try (ResultSet rs = stmt.executeQuery()) {
1272+
rs.next();
1273+
assertEquals(rs.getString(2), expectedType.getName());
1274+
switch (expectedType) {
1275+
case IPv4:
1276+
assertEquals(rs.getString(1), "/" + value);
1277+
break;
1278+
case IPv6:
1279+
// do not check
1280+
break;
1281+
default:
1282+
assertEquals(rs.getString(1), String.valueOf(value));
1283+
}
1284+
}
1285+
}
1286+
}
1287+
}
1288+
1289+
@DataProvider(name = "testTypeCastsDP")
1290+
public static Object[][] testTypeCastsDP() {
1291+
return new Object[][] {
1292+
{100, ClickHouseDataType.Int8, ClickHouseDataType.Int8},
1293+
{100L, ClickHouseDataType.Int16, ClickHouseDataType.Int16},
1294+
{100L, ClickHouseDataType.Int32, ClickHouseDataType.Int32},
1295+
{100L, ClickHouseDataType.Int64, ClickHouseDataType.Int64},
1296+
{100L, ClickHouseDataType.UInt8, ClickHouseDataType.UInt8},
1297+
{100L, ClickHouseDataType.UInt16, ClickHouseDataType.UInt16},
1298+
{100L, ClickHouseDataType.UInt32, ClickHouseDataType.UInt32},
1299+
{100L, ClickHouseDataType.UInt64, ClickHouseDataType.UInt64},
1300+
{"ed0c77a3-2e4b-4954-98ee-22a4fdad9565", ClickHouseDataType.UUID, ClickHouseDataType.UUID},
1301+
{"::ffff:127.0.0.1", ClickHouseDataType.IPv6, ClickHouseDataType.IPv6},
1302+
{"116.253.40.133", ClickHouseDataType.IPv4, ClickHouseDataType.IPv4},
1303+
};
1304+
}
1305+
12631306
@Test(groups = {"integration"})
1264-
public void testTypeCasts() throws Exception {
1307+
public void testTypesInvalidForCast() throws Exception {
12651308
try (Connection conn = getJdbcConnection()) {
12661309
try (PreparedStatement stmt = conn.prepareStatement("select ?, toTypeName(?)")) {
1267-
stmt.setObject(1, 100, ClickHouseDataType.Int8);
1268-
stmt.setObject(2, 100, ClickHouseDataType.Int8);
1310+
for (ClickHouseDataType type : JdbcUtils.INVALID_TARGET_TYPES) {
1311+
expectThrows(SQLException.class, ()->stmt.setObject(1, "", type));
1312+
}
1313+
}
1314+
}
1315+
}
12691316

1270-
try (ResultSet rs = stmt.executeQuery()) {
1271-
rs.next();
1272-
assertEquals(rs.getInt(1), 100);
1273-
assertEquals(rs.getString(2), ClickHouseDataType.Int8.getName());
1274-
}
1317+
@Test(groups = {"integration"}, dataProvider = "testTypeCastWithScaleOrLengthDP")
1318+
public void testTypeCastWithScaleOrLength(Object value, SQLType targetType, Integer scaleOrLength, String expectedValue,
1319+
String expectedType) throws Exception {
1320+
try (Connection conn = getJdbcConnection()) {
1321+
try (PreparedStatement stmt = conn.prepareStatement("select ?, toTypeName(?)")) {
1322+
stmt.setObject(1, value, targetType, scaleOrLength);
1323+
stmt.setObject(2, value, targetType, scaleOrLength);
1324+
try (ResultSet rs = stmt.executeQuery()) {
1325+
rs.next();
1326+
assertEquals(rs.getString(1), expectedValue);
1327+
assertEquals(rs.getString(2), expectedType);
1328+
}
12751329
}
12761330
}
12771331
}
12781332

1333+
@DataProvider(name = "testTypeCastWithScaleOrLengthDP")
1334+
public static Object[][] testTypeCastWithScaleOrLengthDP() {
1335+
return new Object[][] {
1336+
{0.123456789, ClickHouseDataType.Decimal64, 3, "0.123", "Decimal(18, 3)"},
1337+
{"hello", ClickHouseDataType.FixedString, 5, "hello", "FixedString(5)"},
1338+
{"2017-10-02 10:20:30.333333", ClickHouseDataType.DateTime64, 3, "2017-10-02T10:20:30.333", "DateTime64(3)"}
1339+
};
1340+
}
1341+
12791342
@Test(groups = {"integration"})
12801343
public void testCheckOfParametersAreSet() throws Exception {
12811344
try (Connection conn = getJdbcConnection()) {

0 commit comments

Comments
 (0)