Skip to content

Commit cc0f152

Browse files
committed
Fix #75: handle complex types in CassandraResultSet.getObject() methods
1 parent 80837fe commit cc0f152

File tree

3 files changed

+86
-6
lines changed

3 files changed

+86
-6
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1717
### Fixed
1818
- Do not try to register codecs again (if already done previously) on a pre-existing session to avoid warnings in logs.
1919
- Fix some logging in `SessionHolder` to not leak connection credentials.
20+
- Fix `CodecNotFoundException` when getting complex objects, e.g. collections of collections, from a result set (see
21+
issue [#75](https://github.com/ing-bank/cassandra-jdbc-wrapper/issues/75)).
2022

2123
## [4.13.1] - 2024-09-04
2224
### Fixed

src/main/java/com/ing/data/cassandra/jdbc/types/TypesMap.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,8 @@ public final class TypesMap {
6666
TYPES_MAP.put("org.apache.cassandra.db.marshal.inet", JdbcInetAddress.INSTANCE);
6767
TYPES_MAP.put("org.apache.cassandra.db.marshal.int", JdbcInt32.INSTANCE);
6868
TYPES_MAP.put("org.apache.cassandra.db.marshal.list", JdbcList.INSTANCE);
69-
TYPES_MAP.put("org.apache.cassandra.db.marshal.map", JdbcList.INSTANCE);
70-
TYPES_MAP.put("org.apache.cassandra.db.marshal.set", JdbcList.INSTANCE);
69+
TYPES_MAP.put("org.apache.cassandra.db.marshal.map", JdbcMap.INSTANCE);
70+
TYPES_MAP.put("org.apache.cassandra.db.marshal.set", JdbcSet.INSTANCE);
7171
TYPES_MAP.put("org.apache.cassandra.db.marshal.smallint", JdbcShort.INSTANCE);
7272
TYPES_MAP.put("org.apache.cassandra.db.marshal.text", JdbcUTF8.INSTANCE);
7373
TYPES_MAP.put("org.apache.cassandra.db.marshal.time", JdbcTime.INSTANCE);
@@ -95,8 +95,13 @@ private TypesMap() {
9595
public static AbstractJdbcType<?> getTypeForComparator(final String comparator) {
9696
// If not fully qualified, assume it's the short name for a built-in type.
9797
if (comparator != null && !comparator.contains(".")) {
98-
return TYPES_MAP.getOrDefault("org.apache.cassandra.db.marshal." + comparator.toLowerCase(),
99-
JdbcOther.INSTANCE);
98+
String cqlSimpleType = comparator.toLowerCase();
99+
// If the CQL type is a collection (map, list, set, ...), ignore the types of elements in the collection
100+
// to retrieve the corresponding JDBC type.
101+
if (cqlSimpleType.contains("<")) {
102+
cqlSimpleType = cqlSimpleType.substring(0, comparator.indexOf("<"));
103+
}
104+
return TYPES_MAP.getOrDefault("org.apache.cassandra.db.marshal." + cqlSimpleType, JdbcOther.INSTANCE);
100105
}
101106
return TYPES_MAP.getOrDefault(comparator, JdbcOther.INSTANCE);
102107
}

src/test/java/com/ing/data/cassandra/jdbc/JdbcRegressionUnitTest.java

+75-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
import com.datastax.oss.driver.api.core.data.UdtValue;
2020
import org.junit.jupiter.api.BeforeAll;
2121
import org.junit.jupiter.api.Test;
22-
import org.slf4j.Logger;
23-
import org.slf4j.LoggerFactory;
2422

2523
import java.io.ByteArrayInputStream;
2624
import java.math.BigDecimal;
@@ -51,6 +49,7 @@
5149
import java.util.UUID;
5250

5351
import static org.hamcrest.MatcherAssert.assertThat;
52+
import static org.hamcrest.Matchers.hasItem;
5453
import static org.hamcrest.Matchers.instanceOf;
5554
import static org.hamcrest.Matchers.is;
5655
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -1032,4 +1031,78 @@ void testIngIssue33() throws Exception {
10321031
stmt2.close();
10331032
stmt3.close();
10341033
}
1034+
1035+
@Test
1036+
@SuppressWarnings("unchecked")
1037+
void testIngIssue75() throws Exception {
1038+
final Statement stmt = sqlConnection.createStatement();
1039+
1040+
// Create the table with complex types.
1041+
final String createTableQuery = "CREATE TABLE t75 (id int PRIMARY KEY, "
1042+
+ "complex_type1 list<frozen<map<text, text>>>, "
1043+
+ "complex_type2 list<frozen<map<text, list<frozen<map<text, text>>>>>>, "
1044+
+ "complex_type3 set<frozen<map<text, set<bigint>>>>);";
1045+
stmt.execute(createTableQuery);
1046+
stmt.close();
1047+
1048+
// Insert data into the table.
1049+
final String insertQuery =
1050+
"INSERT INTO t75(id, complex_type1, complex_type2, complex_type3) values(?, ?, ?, ?);";
1051+
final PreparedStatement stmt2 = sqlConnection.prepareStatement(insertQuery);
1052+
stmt2.setObject(1, 1);
1053+
1054+
final Map<String, String> map = new HashMap<>();
1055+
map.put("a", "10");
1056+
map.put("b", "20");
1057+
final List<Map<String, String>> list = new ArrayList<>();
1058+
list.add(map);
1059+
stmt2.setObject(2, list);
1060+
1061+
final Map<String, List<Map<String, String>>> map2 = new HashMap<>();
1062+
map2.put("c", list);
1063+
final List<Map<String, List<Map<String, String>>>> list2 = new ArrayList<>();
1064+
list2.add(map2);
1065+
stmt2.setObject(3, list2);
1066+
1067+
final Map<String, Set<Long>> map3 = new HashMap<>();
1068+
final Set<Long> innerSet = new HashSet<>();
1069+
innerSet.add(10L);
1070+
innerSet.add(15L);
1071+
map3.put("d", innerSet);
1072+
final Set<Map<String, Set<Long>>> outerSet = new HashSet<>();
1073+
outerSet.add(map3);
1074+
stmt2.setObject(4, outerSet);
1075+
1076+
stmt2.execute();
1077+
stmt2.close();
1078+
1079+
final Statement stmt3 = sqlConnection.createStatement();
1080+
final CassandraResultSet result = (CassandraResultSet) stmt3.executeQuery("SELECT * FROM t75 WHERE id = 1;");
1081+
1082+
assertTrue(result.next());
1083+
assertEquals(1, result.getInt("id"));
1084+
1085+
final List<Map<String, String>> complexType1ValueAsList =
1086+
(List<Map<String, String>>) result.getList("complex_type1");
1087+
final List<Map<String, String>> complexType1ValueAsObject =
1088+
(List<Map<String, String>>) result.getObject("complex_type1");
1089+
assertThat(complexType1ValueAsList, hasItem(map));
1090+
assertThat(complexType1ValueAsObject, hasItem(map));
1091+
1092+
final List<Map<String, List<Map<String, String>>>> complexType2ValueAsList =
1093+
(List<Map<String, List<Map<String, String>>>>) result.getList("complex_type2");
1094+
final List<Map<String, List<Map<String, String>>>> complexType2ValueAsObject =
1095+
(List<Map<String, List<Map<String, String>>>>) result.getObject("complex_type2");
1096+
assertThat(complexType2ValueAsList, hasItem(map2));
1097+
assertThat(complexType2ValueAsObject, hasItem(map2));
1098+
1099+
final Set<Map<String, Set<Long>>> complexType3ValueAsSet =
1100+
(Set<Map<String, Set<Long>>>) result.getSet("complex_type3");
1101+
final Set<Map<String, Set<Long>>> complexType3ValueAsObject =
1102+
(Set<Map<String, Set<Long>>>) result.getObject("complex_type3");
1103+
assertThat(complexType3ValueAsSet, hasItem(map3));
1104+
assertThat(complexType3ValueAsObject, hasItem(map3));
1105+
1106+
stmt3.close();
1107+
}
10351108
}

0 commit comments

Comments
 (0)