Skip to content

Commit 1d592cd

Browse files
committed
fix(bigquery-jdbc: implement JDBC wrapper interface methods
1 parent dcc2a68 commit 1d592cd

11 files changed

Lines changed: 157 additions & 49 deletions

File tree

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryBaseResultSet.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,4 +674,17 @@ public Time getTime(String columnLabel, Calendar cal) throws SQLException {
674674
public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {
675675
return getTimestamp(getColumnIndex(columnLabel), cal);
676676
}
677+
678+
@Override
679+
public <T> T unwrap(Class<T> iface) throws SQLException {
680+
if (iface.isInstance(this)) {
681+
return iface.cast(this);
682+
}
683+
throw new SQLException("Cannot unwrap to " + iface.getName());
684+
}
685+
686+
@Override
687+
public boolean isWrapperFor(Class<?> iface) throws SQLException {
688+
return iface != null && iface.isInstance(this);
689+
}
677690
}

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryConnection.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1220,4 +1220,17 @@ private boolean checkIsReadOnlyTokenUsed(Map<String, String> authProps) {
12201220
}
12211221
return false;
12221222
}
1223+
1224+
@Override
1225+
public <T> T unwrap(Class<T> iface) throws SQLException {
1226+
if (iface.isInstance(this)) {
1227+
return iface.cast(this);
1228+
}
1229+
throw new SQLException("Cannot unwrap to " + iface.getName());
1230+
}
1231+
1232+
@Override
1233+
public boolean isWrapperFor(Class<?> iface) throws SQLException {
1234+
return iface != null && iface.isInstance(this);
1235+
}
12231236
}

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryNoOpsConnection.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,6 @@ public String nativeSQL(String sql) throws SQLException {
4747
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
4848
}
4949

50-
@Override
51-
public <T> T unwrap(Class<T> iface) throws SQLException {
52-
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
53-
}
54-
55-
@Override
56-
public boolean isWrapperFor(Class<?> iface) {
57-
return false;
58-
}
59-
6050
@Override
6151
public boolean isReadOnly() {
6252
return false;

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryNoOpsResultSet.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -655,16 +655,6 @@ public void updateNClob(String columnLabel, Reader reader) throws SQLException {
655655
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
656656
}
657657

658-
@Override
659-
public <T> T unwrap(Class<T> iface) throws SQLException {
660-
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
661-
}
662-
663-
@Override
664-
public boolean isWrapperFor(Class<?> iface) throws SQLException {
665-
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
666-
}
667-
668658
@Override
669659
public SQLWarning getWarnings() throws SQLException {
670660
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryNoOpsStatement.java

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,6 @@ abstract class BigQueryNoOpsStatement implements Statement {
2727

2828
@Override
2929
public void setCursorName(String name) throws SQLException {
30-
// TODO: ResultSet Concurrency is read only(Not updatable)
31-
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
32-
}
33-
34-
@Override
35-
public <T> T unwrap(Class<T> iface) throws SQLException {
36-
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
37-
}
38-
39-
@Override
40-
public boolean isWrapperFor(Class<?> iface) throws SQLException {
4130
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
4231
}
4332

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryStatement.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1573,20 +1573,6 @@ private boolean getMoreResultsImpl(int current) throws SQLException {
15731573
}
15741574
}
15751575

1576-
@Override
1577-
public boolean isWrapperFor(Class<?> iface) {
1578-
return iface.isInstance(this);
1579-
}
1580-
1581-
@Override
1582-
public <T> T unwrap(Class<T> iface) throws SQLException {
1583-
if (!isWrapperFor(iface)) {
1584-
throw new BigQueryJdbcException(
1585-
String.format("Unable to cast Statement to %s class.", iface.getName()));
1586-
}
1587-
return (T) this;
1588-
}
1589-
15901576
@Override
15911577
public int getResultSetHoldability() {
15921578
return ResultSet.CLOSE_CURSORS_AT_COMMIT;
@@ -1617,6 +1603,19 @@ public boolean isCloseOnCompletion() {
16171603
return this.closeOnCompletion;
16181604
}
16191605

1606+
@Override
1607+
public <T> T unwrap(Class<T> iface) throws SQLException {
1608+
if (iface.isInstance(this)) {
1609+
return iface.cast(this);
1610+
}
1611+
throw new SQLException("Cannot unwrap to " + iface.getName());
1612+
}
1613+
1614+
@Override
1615+
public boolean isWrapperFor(Class<?> iface) throws SQLException {
1616+
return iface != null && iface.isInstance(this);
1617+
}
1618+
16201619
protected void logQueryExecutionStart(String sql) {
16211620
if (sql == null) {
16221621
return;

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/DataSource.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1368,13 +1368,16 @@ public Logger getParentLogger() {
13681368
}
13691369

13701370
@Override
1371-
public <T> T unwrap(Class<T> iface) {
1372-
return null;
1371+
public <T> T unwrap(Class<T> iface) throws SQLException {
1372+
if (iface.isInstance(this)) {
1373+
return iface.cast(this);
1374+
}
1375+
throw new SQLException("Cannot unwrap to " + iface.getName());
13731376
}
13741377

13751378
@Override
1376-
public boolean isWrapperFor(Class<?> iface) {
1377-
return false;
1379+
public boolean isWrapperFor(Class<?> iface) throws SQLException {
1380+
return iface != null && iface.isInstance(this);
13781381
}
13791382

13801383
private static void validateNonNegative(long val, String propertyName) {

java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryBaseResultSetTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818

1919
import static com.google.common.truth.Truth.assertThat;
2020
import static org.junit.jupiter.api.Assertions.assertFalse;
21+
import static org.junit.jupiter.api.Assertions.assertSame;
22+
import static org.junit.jupiter.api.Assertions.assertThrows;
23+
import static org.junit.jupiter.api.Assertions.assertTrue;
2124
import static org.mockito.ArgumentMatchers.any;
2225
import static org.mockito.Mockito.CALLS_REAL_METHODS;
2326
import static org.mockito.Mockito.doReturn;
@@ -28,6 +31,7 @@
2831
import com.google.cloud.bigquery.JobId;
2932
import com.google.cloud.bigquery.JobStatistics.QueryStatistics;
3033
import java.lang.reflect.Field;
34+
import java.sql.SQLException;
3135
import org.junit.jupiter.api.BeforeEach;
3236
import org.junit.jupiter.api.Test;
3337

@@ -101,4 +105,22 @@ public void testGetQueryStatistics_no_job() {
101105
doReturn(job).when(bigQuery).getJob(any(JobId.class));
102106
assertThat(resultSet.getQueryStatistics()).isNull();
103107
}
108+
109+
@Test
110+
public void testWrapperMethods() throws SQLException {
111+
assertTrue(resultSet.isWrapperFor(java.sql.ResultSet.class));
112+
assertTrue(resultSet.isWrapperFor(BigQueryBaseResultSet.class));
113+
assertFalse(resultSet.isWrapperFor(java.sql.Statement.class));
114+
assertFalse(resultSet.isWrapperFor(null));
115+
116+
Object unwrappedRs = resultSet.unwrap(java.sql.ResultSet.class);
117+
assertSame(unwrappedRs, resultSet);
118+
119+
Object unwrappedImpl = resultSet.unwrap(BigQueryBaseResultSet.class);
120+
assertSame(unwrappedImpl, resultSet);
121+
122+
SQLException e =
123+
assertThrows(SQLException.class, () -> resultSet.unwrap(java.sql.Statement.class));
124+
assertTrue(e.getMessage().contains("Cannot unwrap to java.sql.Statement"));
125+
}
104126
}

java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryConnectionTest.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import static org.junit.jupiter.api.Assertions.assertFalse;
2121
import static org.junit.jupiter.api.Assertions.assertNotNull;
2222
import static org.junit.jupiter.api.Assertions.assertNull;
23+
import static org.junit.jupiter.api.Assertions.assertSame;
24+
import static org.junit.jupiter.api.Assertions.assertThrows;
2325
import static org.junit.jupiter.api.Assertions.assertTrue;
2426

2527
import com.google.api.gax.grpc.InstantiatingGrpcChannelProvider;
@@ -496,4 +498,24 @@ public void testConnectionPropertiesLoggingAndMasking() throws IOException, SQLE
496498
rootLogger.setLevel(originalLevel);
497499
}
498500
}
501+
502+
@Test
503+
public void testWrapperMethods() throws Exception {
504+
try (BigQueryConnection connection = new BigQueryConnection(BASE_URL)) {
505+
assertTrue(connection.isWrapperFor(java.sql.Connection.class));
506+
assertTrue(connection.isWrapperFor(BigQueryConnection.class));
507+
assertFalse(connection.isWrapperFor(java.sql.Statement.class));
508+
assertFalse(connection.isWrapperFor(null));
509+
510+
Object unwrappedConn = connection.unwrap(java.sql.Connection.class);
511+
assertSame(unwrappedConn, connection);
512+
513+
Object unwrappedImpl = connection.unwrap(BigQueryConnection.class);
514+
assertSame(unwrappedImpl, connection);
515+
516+
SQLException e =
517+
assertThrows(SQLException.class, () -> connection.unwrap(java.sql.Statement.class));
518+
assertTrue(e.getMessage().contains("Cannot unwrap to java.sql.Statement"));
519+
}
520+
}
499521
}

java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryStatementTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static com.google.cloud.bigquery.jdbc.utils.ArrowUtilities.serializeSchema;
2020
import static com.google.common.truth.Truth.assertThat;
2121
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
import static org.junit.jupiter.api.Assertions.assertFalse;
2223
import static org.junit.jupiter.api.Assertions.assertTrue;
2324
import static org.junit.jupiter.api.Assertions.fail;
2425
import static org.mockito.ArgumentMatchers.any;
@@ -669,4 +670,23 @@ public void testUseReadAPI_ZeroPageSizeDivisionByZeroSafeguard() throws SQLExcep
669670
boolean useReadApi = statement.useReadAPI(tableResult);
670671
assertThat(useReadApi).isTrue(); // ratio = 500 / 1 = 500 > 2 -> true
671672
}
673+
674+
@Test
675+
public void testWrapperMethods() throws SQLException {
676+
assertTrue(bigQueryStatement.isWrapperFor(java.sql.Statement.class));
677+
assertTrue(bigQueryStatement.isWrapperFor(BigQueryStatement.class));
678+
assertFalse(bigQueryStatement.isWrapperFor(java.sql.Connection.class));
679+
assertFalse(bigQueryStatement.isWrapperFor(null));
680+
681+
Object unwrappedStmt = bigQueryStatement.unwrap(java.sql.Statement.class);
682+
org.junit.jupiter.api.Assertions.assertSame(unwrappedStmt, bigQueryStatement);
683+
684+
Object unwrappedImpl = bigQueryStatement.unwrap(BigQueryStatement.class);
685+
org.junit.jupiter.api.Assertions.assertSame(unwrappedImpl, bigQueryStatement);
686+
687+
SQLException e =
688+
org.junit.jupiter.api.Assertions.assertThrows(
689+
SQLException.class, () -> bigQueryStatement.unwrap(java.sql.Connection.class));
690+
assertTrue(e.getMessage().contains("Cannot unwrap to java.sql.Connection"));
691+
}
672692
}

0 commit comments

Comments
 (0)