From 4584ef2ebfa6ac87ccab12cf051e31471084668f Mon Sep 17 00:00:00 2001 From: stephwang Date: Fri, 17 Sep 2021 15:12:38 -0400 Subject: [PATCH] update BigQueryResultSet to return wrapped ResultSet update javadoc Removing getInt from AbstractJdbcResultSet Removing getInt from AbstractJdbcResultSet Implemented getInt Added getResultSet method, removed unimplemented methods Wrapped ResultSet Implementation and exposed getResultSet method Modified executeSelect to Return BigQueryDryRunResult Modified executeSelect to Return BigQueryDryRunResult Modified executeSelect to Return BigQueryDryRunResult update javadoc --- .../cloud/bigquery/AbstractJdbcResultSet.java | 5 - .../cloud/bigquery/BigQueryResultSet.java | 12 +- .../cloud/bigquery/BigQueryResultSetImpl.java | 230 ++++++++++-------- .../com/google/cloud/bigquery/Connection.java | 9 +- .../google/cloud/bigquery/ConnectionImpl.java | 21 +- 5 files changed, 135 insertions(+), 142 deletions(-) diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/AbstractJdbcResultSet.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/AbstractJdbcResultSet.java index 4456317f2..256bbecf8 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/AbstractJdbcResultSet.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/AbstractJdbcResultSet.java @@ -932,11 +932,6 @@ public short getShort(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException(); } - @Override - public int getInt(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException(); - } - @Override public byte[] getBytes(String columnLabel) throws SQLException { throw new SQLFeatureNotSupportedException(); diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryResultSet.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryResultSet.java index 7a3277c3a..e66c8d7a8 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryResultSet.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryResultSet.java @@ -16,7 +16,7 @@ package com.google.cloud.bigquery; -import java.sql.SQLException; +import java.sql.ResultSet; public interface BigQueryResultSet { @@ -29,12 +29,6 @@ public interface BigQueryResultSet { */ long getTotalRows(); - /** Returns the next row. Null if there is no more rows left. */ - // ResultSet getNext(); - - /*Advances the result set to the next row, returning false if no such row exists. Potentially blocking operation*/ - boolean next() throws SQLException; - - /*Returns the value of a String field if the field exists, otherwise returns null*/ - String getString(String fieldName) throws SQLException; + /*Returns the The underlying ResultSet Implementation*/ + ResultSet getResultSet(); } diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryResultSetImpl.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryResultSetImpl.java index faaacd835..b91ed424c 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryResultSetImpl.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/BigQueryResultSetImpl.java @@ -18,28 +18,26 @@ import com.google.api.services.bigquery.model.TableRow; import java.math.BigDecimal; -import java.sql.*; -import java.util.Map; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Timestamp; import java.util.concurrent.BlockingQueue; // TODO: This implementation deals with the JSON response. We can have respective implementations -public class BigQueryResultSetImpl extends AbstractJdbcResultSet - implements BigQueryResultSet { +public class BigQueryResultSetImpl implements BigQueryResultSet { private final Schema schema; private final long totalRows; - // private final ResultSet nextRow; - private final Map nameType; // TODO: Remove - private final BlockingQueue buffer; // TableRow + private final BlockingQueue buffer; private T cursor; + private ResultSetWrapper underlyingResultSet = null; // TODO : Implement a wrapper/struct like spanner - public BigQueryResultSetImpl( - Schema schema, long totalRows, Map nameType, BlockingQueue buffer) { + public BigQueryResultSetImpl(Schema schema, long totalRows, BlockingQueue buffer) { this.schema = schema; this.totalRows = totalRows; - this.nameType = nameType; this.buffer = buffer; + this.underlyingResultSet = new ResultSetWrapper(); } @Override @@ -52,123 +50,139 @@ public long getTotalRows() { return totalRows; } - /* @Override - public ResultSet getNext() { - return null; - }*/ - @Override - /*Advances the result set to the next row, returning false if no such row exists. Potentially blocking operation*/ - public boolean next() throws SQLException { - if (buffer.peek() == null) { // producer has no more rows left. - return false; - } - try { - cursor = buffer.take(); // advance the cursor,Potentially blocking operation - } catch (InterruptedException e) { - throw new SQLException("No rows left"); - } - - return true; + public ResultSet getResultSet() { + return underlyingResultSet; } - @Override - public Object getObject(String fieldName) throws SQLException { - if (cursor instanceof TableRow) { - TableRow currentRow = (TableRow) cursor; - if (currentRow == null) { + private class ResultSetWrapper extends AbstractJdbcResultSet { + @Override + /*Advances the result set to the next row, returning false if no such row exists. Potentially blocking operation*/ + public boolean next() throws SQLException { + if (buffer.peek() == null) { // producer has no more rows left. + return false; + } + try { + cursor = buffer.take(); // advance the cursor,Potentially blocking operation + } catch (InterruptedException e) { throw new SQLException("No rows left"); } - return currentRow.get(fieldName); + + return true; } - // TODO: Add similar clauses for Apache Arrow - return null; - } - @Override - public String getString(String fieldName) throws SQLException { - Object value = getObject(fieldName); - if (value == null) { - throw new SQLException("fieldName can't be null"); - } else if (!(value instanceof String)) { - throw new SQLException("value not in instance of String"); - } else { - return (String) value; + @Override + public Object getObject(String fieldName) throws SQLException { + if (cursor instanceof TableRow) { + TableRow currentRow = (TableRow) cursor; + if (currentRow == null) { + throw new SQLException("No rows left"); + } + return currentRow.get(fieldName); + } + // TODO: Add similar clauses for Apache Arrow + return null; } - } - @Override - public long getLong(String fieldName) throws SQLException { - Object value = getObject(fieldName); - if (value == null) { - throw new SQLException("fieldName can't be null"); - } else if (!(value instanceof Long)) { - throw new SQLException("value not in instance of Long"); - } else { - return Long.parseLong(String.valueOf(value)); + @Override + public String getString(String fieldName) throws SQLException { + Object value = getObject(fieldName); + if (value == null) { + throw new SQLException("fieldName can't be null"); + } else if (!(value instanceof String)) { + throw new SQLException("value not in instance of String"); + } else { + return (String) value; + } } - } - @Override - public double getDouble(String fieldName) throws SQLException { - Object value = getObject(fieldName); - if (value == null) { - throw new SQLException("fieldName can't be null"); - } else if (!(value instanceof Double)) { - throw new SQLException("value not in instance of Double"); - } else { - return Double.parseDouble(String.valueOf(value)); + @Override + public long getLong(String fieldName) throws SQLException { + Object value = getObject(fieldName); + if (value == null) { + throw new SQLException("fieldName can't be null"); + } else if (!(value instanceof Long)) { + throw new SQLException("value not in instance of Long"); + } else { + return Long.parseLong(String.valueOf(value)); + } } - } - @Override - public BigDecimal getBigDecimal(String fieldName) throws SQLException { - Object value = getObject(fieldName); - if (value == null) { - throw new SQLException("fieldName can't be null"); - } else if (!(value instanceof Long - || value instanceof Double - || value instanceof BigDecimal - || value instanceof String)) { - throw new SQLException("value cannot be converted to BigDecimal"); - } else { - return new BigDecimal(String.valueOf(value)); + @Override + public double getDouble(String fieldName) throws SQLException { + Object value = getObject(fieldName); + if (value == null) { + throw new SQLException("fieldName can't be null"); + } else if (!(value instanceof Double)) { + throw new SQLException("value not in instance of Double"); + } else { + return Double.parseDouble(String.valueOf(value)); + } } - } - @Override - public boolean getBoolean(String fieldName) throws SQLException { - Object value = getObject(fieldName); - if (value == null) { - throw new SQLException("fieldName can't be null"); - } else if (!(value instanceof Boolean || (value instanceof String))) { - throw new SQLException("value not in instance of Boolean"); - } else { - return Boolean.parseBoolean(String.valueOf(value)); + @Override + public BigDecimal getBigDecimal(String fieldName) throws SQLException { + Object value = getObject(fieldName); + if (value == null) { + throw new SQLException("fieldName can't be null"); + } else if (!(value instanceof Long + || value instanceof Double + || value instanceof BigDecimal + || value instanceof String)) { + throw new SQLException("value cannot be converted to BigDecimal"); + } else { + return new BigDecimal(String.valueOf(value)); + } } - } - @Override - public byte getByte(String fieldName) throws SQLException { - Object value = getObject(fieldName); - if (value == null) { - throw new SQLException("fieldName can't be null"); - } else if (!(value instanceof Byte || (value instanceof String))) { - throw new SQLException("value not in instance of Boolean"); - } else { - return Byte.parseByte(String.valueOf(value)); + @Override + public boolean getBoolean(String fieldName) throws SQLException { + Object value = getObject(fieldName); + if (value == null) { + throw new SQLException("fieldName can't be null"); + } else if (!(value instanceof Boolean || (value instanceof String))) { + throw new SQLException("value not in instance of Boolean"); + } else { + return Boolean.parseBoolean(String.valueOf(value)); + } } - } - @Override - public Timestamp getTimestamp(String fieldName) throws SQLException { - Object value = getObject(fieldName); - if (value == null) { - throw new SQLException("fieldName can't be null"); - } else if (!(value instanceof Long || value instanceof Timestamp || value instanceof String)) { - throw new SQLException("value cannot be converted to Timestamp"); - } else { - return Timestamp.valueOf(String.valueOf(value)); + @Override + public byte getByte(String fieldName) throws SQLException { + Object value = getObject(fieldName); + if (value == null) { + throw new SQLException("fieldName can't be null"); + } else if (!(value instanceof Byte || (value instanceof String))) { + throw new SQLException("value not in instance of Boolean"); + } else { + return Byte.parseByte(String.valueOf(value)); + } + } + + @Override + public Timestamp getTimestamp(String fieldName) throws SQLException { + Object value = getObject(fieldName); + if (value == null) { + throw new SQLException("fieldName can't be null"); + } else if (!(value instanceof Long + || value instanceof Timestamp + || value instanceof String)) { + throw new SQLException("value cannot be converted to Timestamp"); + } else { + return Timestamp.valueOf(String.valueOf(value)); + } + } + + @Override + public int getInt(String fieldName) throws SQLException { + Object value = getObject(fieldName); + if (value == null) { + throw new SQLException("fieldName can't be null"); + } else if (!(value instanceof Integer || value instanceof String)) { + throw new SQLException("value cannot be converted to int"); + } else { + return Integer.parseInt(String.valueOf(value)); + } } } } diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Connection.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Connection.java index be6b62032..f254cadc0 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Connection.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/Connection.java @@ -17,7 +17,6 @@ package com.google.cloud.bigquery; import com.google.api.services.bigquery.model.QueryParameter; -import java.sql.ResultSet; import java.util.List; import java.util.Map; @@ -55,7 +54,8 @@ public interface Connection { * // .build(); * // Connection connection = bigquery.createConnection(connectionSettings); * String selectQuery = "SELECT corpus FROM `bigquery-public-data.samples.shakespeare` GROUP BY corpus;"; - * try (ResultSet rs = connection.executeSelect(selectQuery)) { + * try (BigQueryResultSet bqResultSet = connection.executeSelect(selectQuery)) { + * ResultSet rs = bqResultSet.getResultSet(); * while (rs.next()) { * System.out.printf("%s,", rs.getString("corpus")); * } @@ -69,7 +69,7 @@ public interface Connection { * @return a ResultSet that contains the data produced by the query * @exception BigQuerySQLException if a database access error occurs */ - ResultSet executeSelect(String sql) throws BigQuerySQLException; + BigQueryResultSet executeSelect(String sql) throws BigQuerySQLException; /** * Execute a SQL statement with query parameters that returns a single ResultSet @@ -86,6 +86,7 @@ public interface Connection { * @return a ResultSet that contains the data produced by the query * @exception BigQuerySQLException if a database access error occurs */ - ResultSet executeSelect(String sql, List parameters, Map labels) + BigQueryResultSet executeSelect( + String sql, List parameters, Map labels) throws BigQuerySQLException; } diff --git a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ConnectionImpl.java b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ConnectionImpl.java index 3f80c5c2d..b750f6485 100644 --- a/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ConnectionImpl.java +++ b/google-cloud-bigquery/src/main/java/com/google/cloud/bigquery/ConnectionImpl.java @@ -25,7 +25,6 @@ import com.google.common.base.Strings; import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; -import java.sql.ResultSet; import java.util.*; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; @@ -61,7 +60,7 @@ public BigQueryDryRunResult dryRun(String sql) throws BigQuerySQLException { } @Override - public ResultSet executeSelect(String sql) throws BigQuerySQLException { + public BigQueryResultSet executeSelect(String sql) throws BigQuerySQLException { // use jobs.query if all the properties of connectionSettings are supported if (isFastQuerySupported()) { String projectId = bigQueryOptions.getProjectId(); @@ -75,7 +74,7 @@ public ResultSet executeSelect(String sql) throws BigQuerySQLException { } @Override - public ResultSet executeSelect( + public BigQueryResultSet executeSelect( String sql, List parameters, Map labels) throws BigQuerySQLException { // use jobs.query if possible @@ -91,7 +90,7 @@ public ResultSet executeSelect( return null; // TODO getQueryResultsRpc(JobId.fromPb(queryJob.getJobReference())); } - private ResultSet queryRpc(final String projectId, final QueryRequest queryRequest) { + private BigQueryResultSet queryRpc(final String projectId, final QueryRequest queryRequest) { com.google.api.services.bigquery.model.QueryResponse results; try { results = @@ -127,17 +126,7 @@ private ResultSet queryRpc(final String projectId, final QueryRequest queryReque } } - // Get's field's name is to type mapping - private Map getFieldNameType(Schema schema) { - List fieldSchemas = schema.getFields().toPb(); - Map nameType = new HashMap<>(); - for (TableFieldSchema fieldSchema : fieldSchemas) { - nameType.put(fieldSchema.getName(), fieldSchema.getType()); - } - return nameType; - } - - private ResultSet processQueryResponseResults( + private BigQueryResultSet processQueryResponseResults( com.google.api.services.bigquery.model.QueryResponse results) { Schema schema; long numRows; @@ -162,7 +151,7 @@ private ResultSet processQueryResponseResults( // only 1 page of result if (results.getPageToken() == null) { - return new BigQueryResultSetImpl(schema, numRows, getFieldNameType(schema), buffer); + return new BigQueryResultSetImpl(schema, numRows, buffer); } // use tabledata.list or Read API to fetch subsequent pages of results long totalRows = results.getTotalRows().longValue();