From de8d4ebab0d6e5065291125b164c0048acd61fee Mon Sep 17 00:00:00 2001 From: Alexander Radzin Date: Wed, 17 Apr 2024 17:47:02 +0300 Subject: [PATCH] FIR-32021: implemented getBlob() and getClob() (#392) --- .../jdbc/resultset/FireboltResultSet.java | 38 +++++++++---------- .../jdbc/statement/FireboltStatement.java | 9 +++-- .../jdbc/resultset/FireboltResultSetTest.java | 25 ++++++++++-- 3 files changed, 44 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/firebolt/jdbc/resultset/FireboltResultSet.java b/src/main/java/com/firebolt/jdbc/resultset/FireboltResultSet.java index 4d7c5d735..2feada9e2 100644 --- a/src/main/java/com/firebolt/jdbc/resultset/FireboltResultSet.java +++ b/src/main/java/com/firebolt/jdbc/resultset/FireboltResultSet.java @@ -20,6 +20,8 @@ import lombok.CustomLog; import org.apache.commons.text.StringEscapeUtils; +import javax.sql.rowset.serial.SerialBlob; +import javax.sql.rowset.serial.SerialClob; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -50,6 +52,7 @@ import java.util.Calendar; import java.util.List; import java.util.Map; +import java.util.Optional; import java.util.TimeZone; import java.util.TreeMap; import java.util.stream.Collectors; @@ -681,9 +684,8 @@ public void setFetchDirection(int direction) throws SQLException { } @Override - @NotImplemented public int getFetchSize() throws SQLException { - throw new FireboltUnsupportedOperationException(); + return 0; // fetch size is not supported; 0 means unlimited like in PostgreSQL and MySQL } @Override @@ -1014,17 +1016,15 @@ public Ref getRef(int columnIndex) throws SQLException { } @Override - @NotImplemented - @ExcludeFromJacocoGeneratedReport public Blob getBlob(int columnIndex) throws SQLException { - throw new FireboltSQLFeatureNotSupportedException(); + byte[] bytes = getBytes(columnIndex); + return bytes == null ? null : new SerialBlob(bytes); } @Override - @NotImplemented - @ExcludeFromJacocoGeneratedReport public Clob getClob(int columnIndex) throws SQLException { - throw new FireboltSQLFeatureNotSupportedException(); + String str = getString(columnIndex); + return str == null ? null : new SerialClob(str.toCharArray()); } @Override @@ -1042,17 +1042,13 @@ public Ref getRef(String columnLabel) throws SQLException { } @Override - @NotImplemented - @ExcludeFromJacocoGeneratedReport public Blob getBlob(String columnLabel) throws SQLException { - throw new FireboltSQLFeatureNotSupportedException(); + return getBlob(findColumn(columnLabel)); } @Override - @NotImplemented - @ExcludeFromJacocoGeneratedReport public Clob getClob(String columnLabel) throws SQLException { - throw new FireboltSQLFeatureNotSupportedException(); + return getClob(findColumn(columnLabel)); } @Override @@ -1177,17 +1173,19 @@ public void updateNClob(String columnLabel, NClob nClob) throws SQLException { } @Override - @NotImplemented - @ExcludeFromJacocoGeneratedReport public NClob getNClob(int columnIndex) throws SQLException { - throw new FireboltSQLFeatureNotSupportedException(); + String str = getString(columnIndex); + class FireboltNClob extends SerialClob implements NClob { + public FireboltNClob(char[] ch) throws SQLException { + super(ch); + } + } + return str == null ? null : new FireboltNClob(str.toCharArray()); } @Override - @NotImplemented - @ExcludeFromJacocoGeneratedReport public NClob getNClob(String columnLabel) throws SQLException { - throw new FireboltSQLFeatureNotSupportedException(); + return getNClob(findColumn(columnLabel)); } @Override diff --git a/src/main/java/com/firebolt/jdbc/statement/FireboltStatement.java b/src/main/java/com/firebolt/jdbc/statement/FireboltStatement.java index fa775632f..be5b01382 100644 --- a/src/main/java/com/firebolt/jdbc/statement/FireboltStatement.java +++ b/src/main/java/com/firebolt/jdbc/statement/FireboltStatement.java @@ -5,6 +5,7 @@ import com.firebolt.jdbc.annotation.NotImplemented; import com.firebolt.jdbc.connection.FireboltConnection; import com.firebolt.jdbc.connection.settings.FireboltProperties; +import com.firebolt.jdbc.exception.ExceptionType; import com.firebolt.jdbc.exception.FireboltException; import com.firebolt.jdbc.exception.FireboltSQLFeatureNotSupportedException; import com.firebolt.jdbc.exception.FireboltUnsupportedOperationException; @@ -386,15 +387,15 @@ public int getFetchDirection() throws SQLException { } @Override - @ExcludeFromJacocoGeneratedReport public void setFetchDirection(int direction) throws SQLException { - // no-op + if (direction != ResultSet.FETCH_FORWARD) { + throw new FireboltException(ExceptionType.TYPE_NOT_SUPPORTED); + } } @Override - @NotImplemented public int getFetchSize() throws SQLException { - return 0; + return 0; // fetch size is not supported; 0 means unlimited like in PostgreSQL and MySQL } @Override diff --git a/src/test/java/com/firebolt/jdbc/resultset/FireboltResultSetTest.java b/src/test/java/com/firebolt/jdbc/resultset/FireboltResultSetTest.java index 2a95592a9..f1cc18584 100644 --- a/src/test/java/com/firebolt/jdbc/resultset/FireboltResultSetTest.java +++ b/src/test/java/com/firebolt/jdbc/resultset/FireboltResultSetTest.java @@ -22,6 +22,7 @@ import java.net.MalformedURLException; import java.net.URL; import java.sql.Array; +import java.sql.Clob; import java.sql.Date; import java.sql.ResultSet; import java.sql.ResultSetMetaData; @@ -212,8 +213,8 @@ void unsupported() throws SQLException { assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateRef("label", null)); assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateBlob(1, mock(java.sql.Blob.class))); assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateBlob("label", mock(java.sql.Blob.class))); - assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateClob(1, mock(java.sql.Clob.class))); - assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateClob("label", mock(java.sql.Clob.class))); + assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateClob(1, mock(Clob.class))); + assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateClob("label", mock(Clob.class))); assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateArray(1, mock(Array.class))); assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateArray("label", mock(Array.class))); assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.updateRowId(1, mock(RowId.class))); @@ -267,7 +268,7 @@ void unsupported() throws SQLException { void fetchSize() throws SQLException { inputStream = getInputStreamWithCommonResponseExample(); resultSet = new FireboltResultSet(inputStream, "any_name", "array_db", 65535); - assertThrows(SQLFeatureNotSupportedException.class, () -> resultSet.getFetchSize()); + assertEquals(0, resultSet.getFetchSize()); resultSet.setFetchSize(0); // ignored resultSet.setFetchSize(1); // ignored @@ -463,6 +464,14 @@ void shouldReturnString() throws SQLException { assertEquals(expected, resultSet.getObject(3, String.class)); assertEquals(expected, resultSet.getNString(3)); assertEquals(expected, resultSet.getNString("name")); + assertEquals(expected, getStringFromClob(resultSet.getClob(3))); + assertEquals(expected, getStringFromClob(resultSet.getClob("name"))); + assertEquals(expected, getStringFromClob(resultSet.getNClob(3))); + assertEquals(expected, getStringFromClob(resultSet.getNClob("name"))); + } + + private String getStringFromClob(Clob clob) throws SQLException { + return clob.getSubString(1, (int)clob.length()); } @Test @@ -485,7 +494,7 @@ void shouldReturnTypeForward() throws SQLException { } @Test - void shouldReturnBytes() throws SQLException { + void shouldReturnBytes() throws SQLException, IOException { inputStream = getInputStreamWithCommonResponseExample(); resultSet = new FireboltResultSet(inputStream, "any_name", "array_db", 65535); resultSet.next(); @@ -494,8 +503,11 @@ void shouldReturnBytes() throws SQLException { assertArrayEquals(expected, resultSet.getBytes("name")); assertArrayEquals(expected, resultSet.getObject(3, byte[].class)); assertArrayEquals(expected, resultSet.getObject("name", byte[].class)); + assertArrayEquals(expected, resultSet.getBlob(3).getBinaryStream().readAllBytes()); + assertArrayEquals(expected, resultSet.getBlob("name").getBinaryStream().readAllBytes()); resultSet.next(); assertNull(resultSet.getBytes(3)); + assertNull(resultSet.getBlob(3)); } @Test @@ -505,6 +517,7 @@ void shouldReturnNullWhenValueIsNull() throws SQLException { resultSet.next(); resultSet.next(); assertNull(resultSet.getBytes(3)); + assertNull(resultSet.getBlob(3)); } @Test @@ -535,6 +548,10 @@ void shouldReturnNullWhenValueStringIsNull() throws SQLException { assertNull(resultSet.getString("name")); assertNull(resultSet.getNString(3)); assertNull(resultSet.getNString("name")); + assertNull(resultSet.getClob(3)); + assertNull(resultSet.getClob("name")); + assertNull(resultSet.getNClob(3)); + assertNull(resultSet.getNClob("name")); } @Test