Skip to content

Commit 2a36974

Browse files
committed
Add support for any type in vectors
Also: fix test in SqlTimestampCodecTest and prepare version 4.15.0
1 parent 1387275 commit 2a36974

File tree

8 files changed

+39
-31
lines changed

8 files changed

+39
-31
lines changed

Diff for: CHANGELOG.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to
55
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7-
## [Unreleased]
7+
## [4.15.0] - 2025-04-20
88
### Added
99
- Add support for the following special CQL commands in `CassandraStatement`:
1010
- `SOURCE <filename>`
@@ -13,6 +13,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
1313
set on a pre-existing connection.
1414
### Changed
1515
- Update Java Driver for Apache Cassandra® to version 4.19.0.
16+
- Allow any type in `vector` since it's now supported by the Java Driver for Apache Cassandra® (see the
17+
[related issue](https://datastax-oss.atlassian.net/browse/JAVA-3143)).
1618
- Update Apache Commons IO to version 2.19.0.
1719
- Update Jackson dependencies to version 2.18.3.
1820
- Update Semver4j to version 5.6.0.

Diff for: README.md

+16
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,22 @@ public class HelloCassandra {
137137
}
138138
```
139139

140+
Alternatively, you can also obtain a connection using a `CassandraDataSource` instance:
141+
```java
142+
public class HelloCassandra {
143+
public static void main(final String[] args) {
144+
final List<ContactPoint> contactPoints = Arrays.asList(
145+
ContactPoint.of("host1", 9042),
146+
ContactPoint.of("host2", 9042),
147+
ContactPoint.of("host3", 9042));
148+
final CassandraDataSource dataSource = new CassandraDataSource(contactPoints, "keyspace");
149+
dataSource.setLocalDataCenter("DC1");
150+
// Use setters on dataSource instance to specify additional properties of the connection.
151+
final Connection connection = dataSource.getConnection();
152+
}
153+
}
154+
```
155+
140156
For further details about configuration and usage of the driver, please refer to the
141157
[full documentation](https://github.com/ing-bank/cassandra-jdbc-wrapper/wiki/Documentation).
142158

Diff for: src/main/java/com/ing/data/cassandra/jdbc/CassandraPreparedStatement.java

+1-7
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,6 @@
8989
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.TOO_MANY_QUERIES;
9090
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.UNSUPPORTED_CONVERSION_TO_JSON;
9191
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.UNSUPPORTED_JDBC_TYPE;
92-
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.VECTOR_ELEMENTS_NOT_NUMBERS;
9392
import static com.ing.data.cassandra.jdbc.utils.JsonUtil.getObjectMapper;
9493
import static com.ing.data.cassandra.jdbc.utils.WarningConstants.INVALID_ARRAY_IMPLEMENTATION;
9594
import static com.ing.data.cassandra.jdbc.utils.WarningConstants.PREPARED_STATEMENT_CLOSING_FAILED;
@@ -711,12 +710,7 @@ public final void setObject(final int parameterIndex, final Object x, final int
711710
(DefaultVectorType) getBoundStatementVariableDefinitions().get(parameterIndex - 1).getType();
712711
final Class<?> itemsClass = DataTypeEnum.fromCqlTypeName(vectorType.getElementType()
713712
.asCql(false, false)).javaType;
714-
if (Number.class.isAssignableFrom(itemsClass)) {
715-
this.boundStatement = this.boundStatement.setVector(parameterIndex - 1, vector,
716-
itemsClass.asSubclass(Number.class));
717-
} else {
718-
throw new SQLException(VECTOR_ELEMENTS_NOT_NUMBERS);
719-
}
713+
this.boundStatement = this.boundStatement.setVector(parameterIndex - 1, vector, itemsClass);
720714
} else if (x instanceof java.net.InetAddress) {
721715
this.boundStatement = this.boundStatement.setInetAddress(parameterIndex - 1, (InetAddress) x);
722716
} else if (List.class.isAssignableFrom(x.getClass())) {

Diff for: src/main/java/com/ing/data/cassandra/jdbc/CassandraResultSet.java

+2-11
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@
107107
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.UNSUPPORTED_JSON_TYPE_CONVERSION;
108108
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.UNSUPPORTED_TYPE_CONVERSION;
109109
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.VALID_LABELS;
110-
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.VECTOR_ELEMENTS_NOT_NUMBERS;
111110
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.WAS_CLOSED_RS;
112111
import static com.ing.data.cassandra.jdbc.utils.JsonUtil.getObjectMapper;
113112
import static com.ing.data.cassandra.jdbc.utils.UdtUtil.udtValueUsingFormattedContents;
@@ -1537,11 +1536,7 @@ public CqlVector<?> getVector(final int columnIndex) throws SQLException {
15371536
final VectorType vectorType = (VectorType) getCqlDataType(columnIndex);
15381537
final Class<?> elementClass = Class.forName(fromDataType(vectorType.getElementType()).asJavaClass()
15391538
.getCanonicalName());
1540-
if (Number.class.isAssignableFrom(elementClass)) {
1541-
return this.currentRow.getVector(columnIndex - 1, elementClass.asSubclass(Number.class));
1542-
} else {
1543-
throw new SQLException(VECTOR_ELEMENTS_NOT_NUMBERS);
1544-
}
1539+
return this.currentRow.getVector(columnIndex - 1, elementClass);
15451540
} catch (ClassNotFoundException e) {
15461541
LOG.warn(GET_VECTOR_FAILED, e);
15471542
}
@@ -1555,11 +1550,7 @@ public CqlVector<?> getVector(final String columnLabel) throws SQLException {
15551550
final VectorType vectorType = (VectorType) getCqlDataType(columnLabel);
15561551
final Class<?> elementClass = Class.forName(fromDataType(vectorType.getElementType()).asJavaClass()
15571552
.getCanonicalName());
1558-
if (Number.class.isAssignableFrom(elementClass)) {
1559-
return this.currentRow.getVector(columnLabel, elementClass.asSubclass(Number.class));
1560-
} else {
1561-
throw new SQLException(VECTOR_ELEMENTS_NOT_NUMBERS);
1562-
}
1553+
return this.currentRow.getVector(columnLabel, elementClass);
15631554
} catch (ClassNotFoundException e) {
15641555
LOG.warn(GET_VECTOR_FAILED, e);
15651556
}

Diff for: src/main/java/com/ing/data/cassandra/jdbc/utils/ErrorConstants.java

-6
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,6 @@ public final class ErrorConstants {
267267
*/
268268
public static final String SSL_CONFIG_FAILED = "Unable to configure SSL: %s.";
269269

270-
/**
271-
* Error message used in any SQL exception thrown when the method {@link CassandraResultSet#getVector(int)} or
272-
* {@link CassandraResultSet#getVector(String)} is invoked on a column containing an invalid CQL vector.
273-
*/
274-
public static final String VECTOR_ELEMENTS_NOT_NUMBERS = "Vector elements are not numbers.";
275-
276270
/**
277271
* Error message used in any SQL exception thrown when the target JDBC type specified in the method
278272
* {@link CassandraPreparedStatement#setObject(int, Object, int)} and its variants is not supported.

Diff for: src/test/java/com/ing/data/cassandra/jdbc/VectorsUnitTest.java

+10-4
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,12 @@ static void finalizeSetUpTests() throws Exception {
4242
void givenVectorInsertStatement_whenExecute_insertExpectedValues() throws Exception {
4343
final Statement statement = sqlConnection.createStatement();
4444

45-
final String insert = "INSERT INTO vectors_test (keyValue, intsVector, floatsVector) "
46-
+ "VALUES(1, [4, 6, 8], [2.1, 3.7, 9.0, 5.5]);";
45+
final String insert = "INSERT INTO vectors_test (keyValue, intsVector, floatsVector, asciiVector) "
46+
+ "VALUES(1, [4, 6, 8], [2.1, 3.7, 9.0, 5.5], ['abc', 'def', 'ghi']);";
4747
statement.executeUpdate(insert);
4848

49-
final ResultSet resultSet = statement.executeQuery("SELECT * FROM vectors_test WHERE keyValue = 1;");
49+
final ResultSet resultSet = statement.executeQuery(
50+
"SELECT keyValue, intsVector, floatsVector, asciiVector FROM vectors_test WHERE keyValue = 1;");
5051
resultSet.next();
5152

5253
assertThat(resultSet, is(instanceOf(CassandraResultSet.class)));
@@ -57,12 +58,17 @@ void givenVectorInsertStatement_whenExecute_insertExpectedValues() throws Except
5758
assertEquals(4, intsVector.get(0));
5859
assertEquals(6, intsVector.get(1));
5960
assertEquals(8, intsVector.get(2));
60-
final CqlVector<?> floatsVector = ((CassandraResultSet) resultSet).getVector(2);
61+
final CqlVector<?> floatsVector = ((CassandraResultSet) resultSet).getVector(3);
6162
assertEquals(4, floatsVector.size());
6263
assertEquals(2.1f, floatsVector.get(0));
6364
assertEquals(3.7f, floatsVector.get(1));
6465
assertEquals(9.0f, floatsVector.get(2));
6566
assertEquals(5.5f, floatsVector.get(3));
67+
final CqlVector<?> asciiVector = ((CassandraResultSet) resultSet).getVector("asciiVector");
68+
assertEquals(3, asciiVector.size());
69+
assertEquals("abc", asciiVector.get(0));
70+
assertEquals("def", asciiVector.get(1));
71+
assertEquals("ghi", asciiVector.get(2));
6672

6773
statement.close();
6874
}

Diff for: src/test/java/com/ing/data/cassandra/jdbc/codec/SqlTimestampCodecTest.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,16 @@
1616
import com.datastax.oss.driver.api.core.ProtocolVersion;
1717
import com.datastax.oss.driver.api.core.type.DataTypes;
1818
import com.datastax.oss.driver.api.core.type.reflect.GenericType;
19+
import com.datastax.oss.driver.internal.core.type.codec.TimestampCodec;
1920
import com.datastax.oss.driver.internal.core.util.Strings;
2021
import org.apache.commons.lang3.StringUtils;
2122
import org.junit.jupiter.api.Test;
2223

2324
import java.nio.ByteBuffer;
2425
import java.sql.Timestamp;
2526
import java.time.Instant;
27+
import java.time.ZoneId;
28+
import java.time.format.DateTimeFormatter;
2629
import java.time.temporal.ChronoUnit;
2730

2831
import static com.ing.data.cassandra.jdbc.codec.SqlTimestampCodec.DEFAULT_TIMESTAMP_FORMAT;
@@ -82,7 +85,8 @@ void givenNullOrEmptyValue_whenParse_returnNull() {
8285

8386
@Test
8487
void givenNonNullValue_whenParse_returnExpectedValue() {
85-
assertEquals(NOW_SQL_TS, sut.parse(Strings.quote(String.valueOf(NOW_SQL_TS))));
88+
final String formattedTimestamp = DEFAULT_TIMESTAMP_FORMAT.format(NOW_INSTANT.atZone(ZoneId.systemDefault()));
89+
assertEquals(NOW_SQL_TS, sut.parse(Strings.quote(formattedTimestamp)));
8690
}
8791

8892
@Test

Diff for: src/test/resources/initEmbeddedCassandra.cql

+2-1
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,8 @@ USE test_keyspace_vect;
309309
CREATE TABLE vectors_test (
310310
keyValue int PRIMARY KEY,
311311
intsVector vector<int, 3>,
312-
floatsVector vector<float, 4>);
312+
floatsVector vector<float, 4>,
313+
asciiVector vector<ascii, 3>);
313314

314315
CREATE TABLE IF NOT EXISTS pet_supply_vectors (
315316
product_id TEXT PRIMARY KEY,

0 commit comments

Comments
 (0)