Skip to content

Commit

Permalink
Implement additional getters in CassandraResultSet
Browse files Browse the repository at this point in the history
see changelog for details
  • Loading branch information
maximevw committed Nov 5, 2023
1 parent 9c2efd3 commit 675e10f
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 59 deletions.
16 changes: 10 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## Unreleased
### Changed
- Deprecate the parameter `version` (CQL version) in JDBC URL because this one is purely informational and has no
effect. This will be removed in the next release.
### Added
- Handle additional types and conversions in the methods `CassandraPreparedStatement.setObject()`:
- JDBC types `BLOB`, `CLOB`, `NCLOB` and Java types `java.sql.Blob`, `java.sql.Clob`, and `java.sql.NClob` handled as
- JDBC types `BLOB`, `CLOB`, `NCLOB` and Java types `java.sql.Blob`, `java.sql.Clob`, and `java.sql.NClob` handled as
arrays of bytes (CQL type `blob`)
- JDBC types `LONGVARCHAR`, `NCHAR`, `NVARCHAR`, `LONGNVARCHAR` and `DATALINK` and Java type `java.net.URL` handled
- JDBC types `LONGVARCHAR`, `NCHAR`, `NVARCHAR`, `LONGNVARCHAR` and `DATALINK` and Java type `java.net.URL` handled
as string (CQL types `text`, `varchar` and `ascii`)
- JDBC type `TIME_WITH_TIMEZONE` and Java types `java.time.OffsetTime` and `java.time.LocalTime` handled as
- JDBC type `TIME_WITH_TIMEZONE` and Java types `java.time.OffsetTime` and `java.time.LocalTime` handled as
`LocalTime` (CQL type `time`)
- JDBC type `TIMESTAMP_WITH_TIMEZONE` and Java types `java.util.OffsetDateTime`, `java.time.LocalDateTime`,
`java.util.Date` and `java.util.Calendar` handled as `Instant` (CQL type `timestamp`)
- Java type `java.time.LocalDate` (CQL type `date`)
- JDBC type `BIT` handled as boolean (CQL type `boolean`)
- JDBC type `NUMERIC` handled as `BigDecimal` (CQL type `decimal`)
- JDBC type `REAL` handled as float number (CQL type `float`)
- Handle `java.util.Calendar` in the methods `CassandraResultSet.getObject(int | String, Class)`.
- Implement the following methods in `CassandraResultSet`: `getAsciiStream(int | String)`,
`getCharacterStream(int | String)`, `getClob(int | String)`, `getNClob(int | String)`.
### Changed
- Deprecate the parameter `version` (CQL version) in JDBC URL because this one is purely informational and has no
effect. This will be removed in the next release.
- Update Apache Commons IO to version 2.15.0.
- Update Jackson dependencies to version 2.15.3.
- Use Apache Cassandra® 5.0 image to run tests.
Expand Down
24 changes: 22 additions & 2 deletions src/main/java/com/ing/data/cassandra/jdbc/AbstractResultSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ boolean isCqlType(final String columnLabel, @Nonnull final DataTypeEnum type) {
*/
abstract DataType getCqlDataType(String columnLabel);

public boolean absolute(final int row) throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public void cancelRowUpdates() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}
Expand All @@ -97,6 +101,10 @@ public void deleteRow() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public boolean first() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public Array getArray(final int columnIndex) throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}
Expand Down Expand Up @@ -165,11 +173,11 @@ public Object getObject(final String columnLabel, final Map<String, Class<?>> ma
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public <T> T getObject(final String columnLabel, final Class<T> type) throws SQLException {
public <T> T getObject(final int columnIndex, final Class<T> type) throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public <T> T getObject(final int columnIndex, final Class<T> type) throws SQLException {
public <T> T getObject(final String columnLabel, final Class<T> type) throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

Expand Down Expand Up @@ -201,6 +209,10 @@ public void insertRow() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public boolean last() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public void moveToCurrentRow() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}
Expand All @@ -209,10 +221,18 @@ public void moveToInsertRow() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public boolean previous() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public void refreshRow() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public boolean relative(final int arg0) throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

public boolean rowDeleted() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,11 +203,6 @@ DataType getCqlDataType(final String columnLabel) {
return this.currentRow.getColumnDefinitions().getType(columnLabel);
}

@Override
public boolean absolute(final int row) throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

@Override
public void afterLast() throws SQLException {
if (this.resultSetType == TYPE_FORWARD_ONLY) {
Expand Down Expand Up @@ -290,11 +285,6 @@ public int findColumn(final String columnLabel) throws SQLException {
throw new SQLSyntaxErrorException(String.format(VALID_LABELS, columnLabel));
}

@Override
public boolean first() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

@Override
public BigDecimal getBigDecimal(final int columnIndex) throws SQLException {
checkIndex(columnIndex);
Expand Down Expand Up @@ -1015,11 +1005,6 @@ public boolean isLast() throws SQLException {
return !this.rowsIterator.hasNext();
}

@Override
public boolean last() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

@Override
public synchronized boolean next() {
if (hasMoreRows()) {
Expand All @@ -1034,16 +1019,6 @@ public synchronized boolean next() {
return false;
}

@Override
public boolean previous() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

@Override
public boolean relative(final int arg0) throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

@Override
public boolean wasNull() {
return this.wasNull;
Expand Down
131 changes: 105 additions & 26 deletions src/main/java/com/ing/data/cassandra/jdbc/CassandraResultSet.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,24 @@
import com.ing.data.cassandra.jdbc.types.DataTypeEnum;
import com.ing.data.cassandra.jdbc.types.TypesMap;
import org.apache.commons.collections4.IteratorUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.ByteArrayInputStream;
import java.io.CharArrayReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
Expand All @@ -71,6 +76,7 @@
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
Expand All @@ -79,7 +85,6 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean;

Expand All @@ -94,6 +99,7 @@
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.MUST_BE_POSITIVE;
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.NOT_SUPPORTED;
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.NO_INTERFACE;
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.UNABLE_TO_READ_VALUE;
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.UNSUPPORTED_JSON_TYPE_CONVERSION;
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.UNSUPPORTED_TYPE_CONVERSION;
import static com.ing.data.cassandra.jdbc.utils.ErrorConstants.VALID_LABELS;
Expand Down Expand Up @@ -272,11 +278,6 @@ DataType getCqlDataType(final String columnLabel) {
return this.currentRow.getColumnDefinitions().get(columnLabel).getType();
}

@Override
public boolean absolute(final int row) throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

@Override
public void afterLast() throws SQLException {
if (this.resultSetType == TYPE_FORWARD_ONLY) {
Expand Down Expand Up @@ -355,8 +356,25 @@ public int findColumn(final String columnLabel) throws SQLException {
}

@Override
public boolean first() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
public InputStream getAsciiStream(final int columnIndex) throws SQLException {
checkIndex(columnIndex);
final String s = this.currentRow.getString(columnIndex - 1);
if (s != null) {
return new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
} else {
return null;
}
}

@Override
public InputStream getAsciiStream(final String columnLabel) throws SQLException {
checkName(columnLabel);
final String s = this.currentRow.getString(columnLabel);
if (s != null) {
return new ByteArrayInputStream(s.getBytes(StandardCharsets.US_ASCII));
} else {
return null;
}
}

@Override
Expand Down Expand Up @@ -505,6 +523,70 @@ public byte[] getBytes(final String columnLabel) throws SQLException {
return null;
}

@Override
public Reader getCharacterStream(final int columnIndex) throws SQLException {
checkIndex(columnIndex);
final byte[] byteArray = this.getBytes(columnIndex);
if (byteArray != null) {
final InputStream inputStream = new ByteArrayInputStream(byteArray);
try {
return new CharArrayReader(IOUtils.toCharArray(inputStream, StandardCharsets.UTF_8));
} catch (final IOException e) {
throw new SQLException(String.format(UNABLE_TO_READ_VALUE, Reader.class.getSimpleName()), e);
}
} else {
return null;
}
}

@Override
public Reader getCharacterStream(final String columnLabel) throws SQLException {
checkName(columnLabel);
final byte[] byteArray = this.getBytes(columnLabel);
if (byteArray != null) {
final InputStream inputStream = new ByteArrayInputStream(byteArray);
try {
return new CharArrayReader(IOUtils.toCharArray(inputStream, StandardCharsets.UTF_8));
} catch (final IOException e) {
throw new SQLException(String.format(UNABLE_TO_READ_VALUE, Reader.class.getSimpleName()), e);
}
} else {
return null;
}
}

@Override
public Clob getClob(final int columnIndex) throws SQLException {
checkIndex(columnIndex);
final byte[] byteArray = getBytes(columnIndex);
if (byteArray != null) {
final InputStream inputStream = new ByteArrayInputStream(byteArray);
try {
return new javax.sql.rowset.serial.SerialClob(IOUtils.toCharArray(inputStream, StandardCharsets.UTF_8));
} catch (final IOException e) {
throw new SQLException(String.format(UNABLE_TO_READ_VALUE, Clob.class.getSimpleName()), e);
}
} else {
return null;
}
}

@Override
public Clob getClob(final String columnLabel) throws SQLException {
checkName(columnLabel);
final byte[] byteArray = getBytes(columnLabel);
if (byteArray != null) {
final InputStream inputStream = new ByteArrayInputStream(byteArray);
try {
return new javax.sql.rowset.serial.SerialClob(IOUtils.toCharArray(inputStream, StandardCharsets.UTF_8));
} catch (final IOException e) {
throw new SQLException(String.format(UNABLE_TO_READ_VALUE, Clob.class.getSimpleName()), e);
}
} else {
return null;
}
}

@Override
public int getConcurrency() throws SQLException {
checkNotClosed();
Expand Down Expand Up @@ -757,6 +839,16 @@ public ResultSetMetaData getMetaData() {
return this.metadata;
}

@Override
public NClob getNClob(final int columnIndex) throws SQLException {
return (NClob) getClob(columnIndex);
}

@Override
public NClob getNClob(final String columnLabel) throws SQLException {
return (NClob) getClob(columnLabel);
}

@Override
public Object getObject(final int columnIndex) throws SQLException {
checkIndex(columnIndex);
Expand Down Expand Up @@ -1065,16 +1157,18 @@ public <T> T getObject(final int columnIndex, final Class<T> type) throws SQLExc
returnValue = getTimestamp(columnIndex);
} else if (type == LocalDate.class) {
returnValue = getLocalDate(columnIndex);
} else if (type == LocalDateTime.class || type == LocalTime.class) {
final Timestamp timestamp = getTimestamp(columnIndex, Calendar.getInstance(TimeZone.getTimeZone("UTC")));
} else if (type == LocalDateTime.class || type == LocalTime.class || type == Calendar.class) {
final Timestamp timestamp = getTimestamp(columnIndex, Calendar.getInstance());
if (timestamp == null) {
returnValue = null;
} else {
final LocalDateTime ldt = LocalDateTime.ofInstant(timestamp.toInstant(), ZoneId.of("UTC"));
if (type == java.time.LocalDateTime.class) {
returnValue = ldt;
} else {
} else if (type == java.time.LocalTime.class) {
returnValue = ldt.toLocalTime();
} else {
returnValue = new Calendar.Builder().setInstant(ldt.toEpochSecond(ZoneOffset.UTC)).build();
}
}
} else if (type == java.time.OffsetDateTime.class) {
Expand Down Expand Up @@ -1463,11 +1557,6 @@ public boolean isLast() throws SQLException {
return !this.rowsIterator.hasNext();
}

@Override
public boolean last() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

@Override
public synchronized boolean next() {
if (hasMoreRows()) {
Expand All @@ -1482,16 +1571,6 @@ public synchronized boolean next() {
return false;
}

@Override
public boolean previous() throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

@Override
public boolean relative(final int arg0) throws SQLException {
throw new SQLFeatureNotSupportedException(NOT_SUPPORTED);
}

/**
* Gets whether a column was a null value.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,12 @@ public final class ErrorConstants {
*/
public static final String UNSUPPORTED_TYPE_CONVERSION = "Conversion to type %s not supported.";

/**
* Error message used in any SQL exception thrown when the conversion to a specific type in a getter method of
* {@link CassandraResultSet} failed.
*/
public static final String UNABLE_TO_READ_VALUE = "Unable to read value as %s.";

/**
* Error message used in any SQL exception thrown when the conversion to the specified type in the methods
* {@link CassandraResultSet#getObjectFromJson(int, Class)},
Expand Down
Loading

0 comments on commit 675e10f

Please sign in to comment.