Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 64fedfa

Browse files
author
Alexander Radzin
authored
support of oracle blobs that cannot be retrieved by ResultSet.getStr… (#18)
support of oracle blobs that cannot be retrieved by ResultSet.getString()
1 parent 843d20a commit 64fedfa

6 files changed

Lines changed: 64 additions & 5 deletions

File tree

src/main/java/com/upsolver/datasources/jdbc/JDBCDataSource.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ public CompletionStage<LoadedData> getSample() {
232232
Connection connection = getConnection();
233233
var result = queryData(sampleMetadata, 100, connection);
234234
var rowReader =
235-
new RowReader(tableInfo, new ResultSetValuesGetter(tableInfo, result), sampleMetadata, connection, true);
235+
new RowReader(tableInfo, new ResultSetValuesGetter(tableInfo, result, queryDialect), sampleMetadata, connection, true);
236236
var inputStream = new ResultSetInputStream(new CsvRowConverter(tableInfo), rowReader, true);
237237
var loadedData = new LoadedData(inputStream, Instant.now());
238238
return CompletableFuture.completedFuture(loadedData);
@@ -462,7 +462,7 @@ private CompletionStage<Iterator<DataLoader<JDBCTaskMetadata>>> splitData(Result
462462

463463
// Value getter + Some of the code in RowReader are needed only because we insist on running a single query
464464
// and using a single result set for all ranges. If we allow query per window a lot of the code can be simplified.
465-
var valueGetter = new ResultSetValuesGetter(tableInfo, resultSet);
465+
var valueGetter = new ResultSetValuesGetter(tableInfo, resultSet, queryDialect);
466466

467467
for (int i = 0; i < wantedRanges.size(); i++) {
468468
final var isLast = i == wantedRanges.size() - 1;

src/main/java/com/upsolver/datasources/jdbc/ResultSetValuesGetter.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,30 @@
11
package com.upsolver.datasources.jdbc;
22

33
import com.upsolver.datasources.jdbc.metadata.TableInfo;
4+
import com.upsolver.datasources.jdbc.querybuilders.QueryDialect;
5+
import com.upsolver.datasources.jdbc.utils.ThrowingBiFunction;
46

57
import java.sql.ResultSet;
8+
import java.sql.ResultSetMetaData;
69
import java.sql.SQLException;
710
import java.sql.Timestamp;
11+
import java.util.ArrayList;
12+
import java.util.List;
813

914
class ResultSetValuesGetter implements AutoCloseable {
1015
private final TableInfo tableInfo;
1116
private final ResultSet underlying;
17+
private final List<ThrowingBiFunction<ResultSet, Integer, String, SQLException>> valueGetters;
1218

1319
private String[] nextValues = null;
1420
private long nextIncValue;
1521
private Timestamp nextTimestampValue;
1622
private boolean onNextValues = false;
1723

18-
ResultSetValuesGetter(TableInfo tableInfo, ResultSet underlying) {
24+
ResultSetValuesGetter(TableInfo tableInfo, ResultSet underlying, QueryDialect queryDialect) {
1925
this.tableInfo = tableInfo;
2026
this.underlying = underlying;
27+
valueGetters = initValueGetters(queryDialect);
2128
}
2229

2330
public boolean next() throws SQLException {
@@ -74,7 +81,7 @@ public String[] getValues() throws SQLException {
7481
} else {
7582
var result = new String[tableInfo.getColumnCount()];
7683
for (int i = 0; i < tableInfo.getColumnCount(); i++) {
77-
result[i] = underlying.getString(i + 1); // Column indices start at 1 (☉_☉)
84+
result[i] = valueGetters.get(i).apply(underlying, i + 1); // Column indices start at 1 (☉_☉)
7885
}
7986
return result;
8087
}
@@ -84,4 +91,18 @@ public String[] getValues() throws SQLException {
8491
public void close() throws Exception {
8592
underlying.close();
8693
}
94+
95+
private List<ThrowingBiFunction<ResultSet, Integer, String, SQLException>> initValueGetters(QueryDialect queryDialect) {
96+
try {
97+
ResultSetMetaData md = underlying.getMetaData();
98+
int n = md.getColumnCount();
99+
List<ThrowingBiFunction<ResultSet, Integer, String, SQLException>> valueGetters = new ArrayList<>();
100+
for (int i = 0; i < n; i++) {
101+
valueGetters.add(queryDialect.getStringValueGetter(md.getColumnType(i + 1)));
102+
}
103+
return valueGetters;
104+
} catch (SQLException e) {
105+
throw new RuntimeException("Error while retrieving table metadata", e);
106+
}
107+
}
87108
}

src/main/java/com/upsolver/datasources/jdbc/querybuilders/DefaultQueryDialect.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.upsolver.datasources.jdbc.metadata.SimpleSqlType;
55
import com.upsolver.datasources.jdbc.metadata.TableInfo;
66
import com.upsolver.datasources.jdbc.utils.NamedPreparedStatment;
7+
import com.upsolver.datasources.jdbc.utils.ThrowingBiFunction;
78
import org.slf4j.Logger;
89
import org.slf4j.LoggerFactory;
910

@@ -17,7 +18,9 @@
1718
import java.time.Instant;
1819
import java.util.Arrays;
1920
import java.util.Collection;
21+
import java.util.Collections;
2022
import java.util.HashSet;
23+
import java.util.Map;
2124

2225
public class DefaultQueryDialect implements QueryDialect {
2326
private static final Logger logger = LoggerFactory.getLogger(DefaultQueryDialect.class);
@@ -29,6 +32,17 @@ public class DefaultQueryDialect implements QueryDialect {
2932
JDBCType.TIMESTAMP_WITH_TIMEZONE
3033
));
3134

35+
private static final ThrowingBiFunction<ResultSet, Integer, String, SQLException> getString = ResultSet::getString;
36+
private final Map<Integer, ThrowingBiFunction<ResultSet, Integer, String, SQLException>> valueGetters;
37+
38+
public DefaultQueryDialect() {
39+
this(Collections.emptyMap());
40+
}
41+
42+
public DefaultQueryDialect(Map<Integer, ThrowingBiFunction<ResultSet, Integer, String, SQLException>> valueGetters) {
43+
this.valueGetters = valueGetters;
44+
}
45+
3246
@Override
3347
public long utcOffsetSeconds(Connection connection) throws SQLException {
3448
var rs = connection.prepareStatement("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP)").executeQuery();
@@ -245,4 +259,9 @@ public Connection getConnection(String url, java.util.Properties info) throws SQ
245259
public String getDriverClassName() {
246260
return null;
247261
}
262+
263+
@Override
264+
public ThrowingBiFunction<ResultSet, Integer, String, SQLException> getStringValueGetter(int sqlType) {
265+
return valueGetters.getOrDefault(sqlType, getString);
266+
}
248267
}

src/main/java/com/upsolver/datasources/jdbc/querybuilders/OracleQueryDialect.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
package com.upsolver.datasources.jdbc.querybuilders;
22

3+
import com.upsolver.datasources.jdbc.utils.ThrowingBiFunction;
34
import oracle.jdbc.OracleType;
45

6+
import java.math.BigInteger;
57
import java.sql.Connection;
68
import java.sql.JDBCType;
79
import java.sql.ResultSet;
810
import java.sql.SQLException;
911
import java.sql.SQLType;
12+
import java.sql.Types;
1013
import java.util.Arrays;
1114
import java.util.Collection;
15+
import java.util.Collections;
1216
import java.util.HashSet;
17+
import java.util.Map;
1318
import java.util.Optional;
1419

1520
public class OracleQueryDialect extends DefaultQueryDialect {
@@ -19,6 +24,13 @@ public class OracleQueryDialect extends DefaultQueryDialect {
1924
OracleType.TIMESTAMP_WITH_LOCAL_TIME_ZONE
2025
));
2126

27+
private static final ThrowingBiFunction<ResultSet, Integer, String, SQLException> blobAsString = (rs, i) -> Optional.ofNullable(rs.getBytes(i)).map(bytes -> new BigInteger(1, bytes).toString(16)).orElse(null);
28+
private static final Map<Integer, ThrowingBiFunction<ResultSet, Integer, String, SQLException>> blobValueGetters = Collections.singletonMap(Types.BLOB, blobAsString);
29+
30+
public OracleQueryDialect() {
31+
super(blobValueGetters);
32+
}
33+
2234
@Override
2335
public long utcOffsetSeconds(Connection connection) throws SQLException {
2436
var rs =

src/main/java/com/upsolver/datasources/jdbc/querybuilders/QueryDialect.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
import com.upsolver.datasources.jdbc.JDBCTaskMetadata;
44
import com.upsolver.datasources.jdbc.metadata.TableInfo;
55
import com.upsolver.datasources.jdbc.utils.NamedPreparedStatment;
6+
import com.upsolver.datasources.jdbc.utils.ThrowingBiFunction;
67

78
import java.sql.Connection;
8-
import java.sql.JDBCType;
99
import java.sql.PreparedStatement;
1010
import java.sql.ResultSet;
1111
import java.sql.SQLException;
@@ -70,4 +70,5 @@ NamedPreparedStatment queryFullTable(TableInfo tableInfo,
7070

7171
String getDriverClassName();
7272

73+
ThrowingBiFunction<ResultSet, Integer, String, SQLException> getStringValueGetter(int sqlType);
7374
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.upsolver.datasources.jdbc.utils;
2+
3+
@FunctionalInterface
4+
public interface ThrowingBiFunction<T, U, R, E extends Throwable> {
5+
R apply(T t, U u) throws E;
6+
}

0 commit comments

Comments
 (0)