Skip to content

Commit

Permalink
Refactor QueryRequest and QueryResponse
Browse files Browse the repository at this point in the history
- Add better javadoc and snippet to QueryResponse
- Use primitive boolean for jobComplete
- Add test for NPE in QueryRequestTests
- Add QueryRequest and QueryResponse to SerializationTest
  • Loading branch information
mziccard committed Dec 14, 2015
1 parent 20d4841 commit 903d3c6
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@
/**
* Google Cloud BigQuery Query Request. This class can be used to run a BigQuery SQL query and
* return results if the query completes within a specified timeout. The query results are saved to
* a temporary table that is deleted approximately 24 hours after the query is run. Query is run
* a temporary table that is deleted approximately 24 hours after the query is run. The query is run
* through a BigQuery Job whose identity can be accessed via {@link QueryResponse#job()}.
*
* @see <a href="https://cloud.google.com/bigquery/docs/reference/v2/jobs/query">Query</a>
* @see <a href="https://cloud.google.com/bigquery/query-reference">Query Reference</a>
*/
public class QueryRequest implements Serializable {

Expand Down Expand Up @@ -57,7 +58,7 @@ private Builder() {}
* Sets the BigQuery query to be executed.
*/
public Builder query(String query) {
this.query = query;
this.query = checkNotNull(query);
return this;
}

Expand All @@ -84,19 +85,18 @@ public Builder defaultDataset(DatasetId defaultDataset) {
* Sets how long to wait for the query to complete, in milliseconds, before the request times
* out and returns. Note that this is only a timeout for the request, not the query. If the
* query takes longer to run than the timeout value, the call returns without any results and
* with the {@link QueryResponse#jobComplete()} set to {@code false}. You can call
* {@link BigQuery#getQueryResults(JobId, BigQuery.QueryResultsOption...)} to wait for the query
* to complete and read the results. The default value is 10000 milliseconds (10 seconds).
* with the {@link QueryResponse#jobComplete()} set to {@code false}. If not set, a wait time of
* 10000 milliseconds (10 seconds) is used.
*/
public Builder maxWaitTime(Long maxWaitTime) {
this.maxWaitTime = maxWaitTime;
return this;
}

/**
* Sets whether the query has to be dry run or not. If set, the query is not executed: if the
* query is valid statistics are returned on how many bytes would be processed, if the query is
* invalid an error is returned.
* Sets whether the query has to be dry run or not. If set, the query is not executed. Tf the
* query is valid statistics are returned on how many bytes would be processed. If the query is
* invalid an error is returned. If not set the query is executed.
*/
public Builder dryRun(Boolean dryRun) {
this.dryRun = dryRun;
Expand All @@ -105,7 +105,8 @@ public Builder dryRun(Boolean dryRun) {

/**
* Sets whether to look for the result in the query cache. The query cache is a best-effort
* cache that will be flushed whenever tables in the query are modified.
* cache that will be flushed whenever tables in the query are modified. If not specified the
* query cache is used.
*
* @see <a href="https://cloud.google.com/bigquery/querying-data#querycaching">Query Caching</a>
*/
Expand All @@ -120,7 +121,7 @@ public QueryRequest build() {
}

private QueryRequest(Builder builder) {
query = checkNotNull(builder.query);
query = builder.query;
maxResults = builder.maxResults;
defaultDataset = builder.defaultDataset;
maxWaitTime = builder.maxWaitTime;
Expand Down Expand Up @@ -155,24 +156,26 @@ public DatasetId defaultDataset() {
* query takes longer to run than the timeout value, the call returns without any results and
* with the {@link QueryResponse#jobComplete()} set to {@code false}. You can call
* {@link BigQuery#getQueryResults(JobId, BigQuery.QueryResultsOption...)} to wait for the query
* to complete and read the results. The default value is 10000 milliseconds (10 seconds).
* to complete and read the results. If not set, a wait time of 10000 milliseconds (10 seconds)
* is used.
*/
public Long maxWaitTime() {
return maxWaitTime;
}

/**
* Returns whether the query has to be dry run or not. If set, the query is not executed: if the
* query is valid statistics are returned on how many bytes would be processed, if the query is
* invalid an error is returned.
* Returns whether the query has to be dry run or not. If set, the query is not executed. If the
* query is valid statistics are returned on how many bytes would be processed. If the query is
* invalid an error is returned. If not set the query is executed.
*/
public Boolean dryRun() {
return dryRun;
}

/**
* Returns whether to look for the result in the query cache. The query cache is a best-effort
* cache that will be flushed whenever tables in the query are modified.
* cache that will be flushed whenever tables in the query are modified. If not specified the
* query cache is used.
*
* @see <a href="https://cloud.google.com/bigquery/querying-data#querycaching">Query Caching</a>
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,21 @@
/**
* Google Cloud BigQuery Query Response. This class contains the results of a Query Job or of a
* Query Request.
*
* <p>Example usage of a query response:
* <pre> {@code
* QueryResponse response = bigquery.query(request);
* while (!response.jobComplete()) {
* response = bigquery.getQueryResults(response.job());
* Thread.sleep(1000);
* }
* List<BigQueryError> executionErrors = response.executionErrors();
* Page<List<FieldValue>> rows = response.rows();
* }</pre>
*
* @see <a href="https://cloud.google.com/bigquery/docs/reference/v2/jobs/getQueryResults">Get Query
* Results</a>
* @see <a href="https://cloud.google.com/bigquery/docs/reference/v2/jobs/query">Query</a>
*/
public class QueryResponse implements Serializable {

Expand All @@ -37,8 +52,8 @@ public class QueryResponse implements Serializable {
private final Long totalRows;
private final Page<List<FieldValue>> rows;
private final Long totalBytesProcessed;
private final Boolean jobComplete;
private final List<BigQueryError> errors;
private final boolean jobComplete;
private final List<BigQueryError> executionErrors;
private final Boolean cacheHit;

static final class Builder {
Expand All @@ -49,8 +64,8 @@ static final class Builder {
private Long totalRows;
private Page<List<FieldValue>> rows;
private Long totalBytesProcessed;
private Boolean jobComplete;
private List<BigQueryError> errors;
private boolean jobComplete;
private List<BigQueryError> executionErrors;
private Boolean cacheHit;

private Builder() {}
Expand Down Expand Up @@ -85,13 +100,13 @@ Builder totalBytesProcessed(Long totalBytesProcessed) {
return this;
}

Builder jobComplete(Boolean jobComplete) {
Builder jobComplete(boolean jobComplete) {
this.jobComplete = jobComplete;
return this;
}

Builder errors(List<BigQueryError> errors) {
this.errors = errors;
Builder executionErrors(List<BigQueryError> executionErrors) {
this.executionErrors = executionErrors;
return this;
}

Expand All @@ -113,7 +128,7 @@ private QueryResponse(Builder builder) {
this.rows = builder.rows;
this.totalBytesProcessed = builder.totalBytesProcessed;
this.jobComplete = builder.jobComplete;
this.errors = builder.errors;
this.executionErrors = builder.executionErrors;
this.cacheHit = builder.cacheHit;
}

Expand All @@ -125,7 +140,7 @@ public String etag() {
}

/**
* Returns the schema of the results when the query completed successfully. Returns {@code null}
* Returns the schema of the results if the query completed successfully. Returns {@code null}
* otherwise.
*/
public Schema schema() {
Expand Down Expand Up @@ -158,27 +173,30 @@ public Page<List<FieldValue>> rows() {
}

/**
* Returns the total number of bytes processed for the query.
* Returns the total number of bytes processed for the query. If this query was a dry run, this is
* the number of bytes that would be processed if the query were run. Returns {@code null}
* if the query did not complete.
*/
public Long totalBytesProcessed() {
return totalBytesProcessed;
}

/**
* Returns whether the job running the query has completed or not. If {@link #rows()} and
* {@link #totalRows()} are present, this method will always return {@code true}. If this method
* returns {@code false}, {@link #totalRows()} will not be available.
* {@link #totalRows()} are not {@code null}, this method will always return {@code true}. If this
* method returns {@code false} {@link #totalRows()} and {@link #rows()} return {@code null}. This
* method can be used to check if query execution completed and results are available.
*/
public Boolean jobComplete() {
public boolean jobComplete() {
return jobComplete;
}

/**
* Returns errors and warnings encountered during the running of the job, if any. Errors here do
* not necessarily mean that the job has completed or was unsuccessful.
*/
public List<BigQueryError> errors() {
return errors;
public List<BigQueryError> executionErrors() {
return executionErrors;
}

/**
Expand All @@ -198,7 +216,7 @@ public String toString() {
.add("totalRows", totalRows)
.add("schema", schema)
.add("totalBytesProcessed", totalBytesProcessed)
.add("errors", errors)
.add("executionErrors", executionErrors)
.add("cacheHit", cacheHit)
.toString();
}
Expand All @@ -217,17 +235,17 @@ public boolean equals(Object obj) {
return false;
}
QueryResponse response = (QueryResponse) obj;
return Objects.equals(schema, response.schema)
return jobComplete == jobComplete
&& Objects.equals(schema, response.schema)
&& Objects.equals(job, response.job)
&& Objects.equals(totalRows, response.totalRows)
&& Objects.equals(rows, response.rows)
&& Objects.equals(totalBytesProcessed, response.totalBytesProcessed)
&& Objects.equals(jobComplete, response.jobComplete)
&& Objects.equals(errors, response.errors)
&& Objects.equals(executionErrors, response.executionErrors)
&& Objects.equals(cacheHit, response.cacheHit);
}

static Builder builder() {
return new Builder();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class QueryRequestTest {

Expand All @@ -37,6 +39,9 @@ public class QueryRequestTest {
.maxWaitTime(MAX_WAIT_TIME)
.build();

@Rule
public ExpectedException thrown = ExpectedException.none();

@Test
public void testToBuilder() {
compareQueryRequest(QUERY_REQUEST, QUERY_REQUEST.toBuilder().build());
Expand All @@ -62,6 +67,8 @@ public void testBuilder() {
assertEquals(DRY_RUN, QUERY_REQUEST.dryRun());
assertEquals(MAX_RESULTS, QUERY_REQUEST.maxResults());
assertEquals(MAX_WAIT_TIME, QUERY_REQUEST.maxWaitTime());
thrown.expect(NullPointerException.class);
QueryRequest.builder(null);
}

@Test
Expand All @@ -73,6 +80,8 @@ public void testOf() {
assertNull(request.dryRun());
assertNull(request.maxResults());
assertNull(request.maxWaitTime());
thrown.expect(NullPointerException.class);
QueryRequest.of(null);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public Page<List<FieldValue>> nextPage() {
}
};
private static final Page<List<FieldValue>> ROWS =
new PageImpl<List<FieldValue>>(FETCHER, "cursor", ImmutableList.<List<FieldValue>>of());
new PageImpl<>(FETCHER, "cursor", ImmutableList.<List<FieldValue>>of());
private static final Long TOTAL_BYTES_PROCESSED = 4200L;
private static final Boolean JOB_COMPLETE = true;
private static final List<BigQueryError> ERRORS = ImmutableList.of(
Expand All @@ -62,7 +62,7 @@ public Page<List<FieldValue>> nextPage() {
.rows(ROWS)
.totalBytesProcessed(TOTAL_BYTES_PROCESSED)
.jobComplete(JOB_COMPLETE)
.errors(ERRORS)
.executionErrors(ERRORS)
.cacheHit(CACHE_HIT)
.build();

Expand All @@ -73,9 +73,9 @@ public void testBuilder() {
assertEquals(JOB_ID, QUERY_RESPONSE.job());
assertEquals(TOTAL_ROWS, QUERY_RESPONSE.totalRows());
assertEquals(ROWS, QUERY_RESPONSE.rows());
assertEquals(TOTAL_BYTES_PROCESSED, QUERY_RESPONSE.totalBytesProcessed());
assertEquals(TOTAL_BYTES_PROCESSED, (Long) QUERY_RESPONSE.totalBytesProcessed());
assertEquals(JOB_COMPLETE, QUERY_RESPONSE.jobComplete());
assertEquals(ERRORS, QUERY_RESPONSE.errors());
assertEquals(ERRORS, QUERY_RESPONSE.executionErrors());
assertEquals(CACHE_HIT, QUERY_RESPONSE.cacheHit());
}

Expand All @@ -89,7 +89,7 @@ public void testBuilderIncomplete() {
assertNull(queryResponse.rows());
assertNull(queryResponse.totalBytesProcessed());
assertEquals(false, queryResponse.jobComplete());
assertNull(queryResponse.errors());
assertNull(queryResponse.executionErrors());
assertNull(queryResponse.cacheHit());
}

Expand All @@ -107,7 +107,7 @@ private void compareQueryResponse(QueryResponse expected, QueryResponse value) {
assertEquals(expected.rows(), value.rows());
assertEquals(expected.totalBytesProcessed(), value.totalBytesProcessed());
assertEquals(expected.jobComplete(), value.jobComplete());
assertEquals(expected.errors(), value.errors());
assertEquals(expected.executionErrors(), value.executionErrors());
assertEquals(expected.cacheHit(), value.cacheHit());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,19 @@ public class SerializationTest {
private static final InsertAllResponse INSERT_ALL_RESPONSE = new InsertAllResponse(ERRORS_MAP);
private static final FieldValue FIELD_VALUE =
new FieldValue(FieldValue.Attribute.PRIMITIVE, "value");
private static final QueryRequest QUERY_REQUEST = QueryRequest.builder("query")
.useQueryCache(true)
.defaultDataset(DATASET_ID)
.dryRun(false)
.maxResults(42L)
.maxWaitTime(10L)
.build();
private static final QueryResponse QUERY_RESPONSE = QueryResponse.builder()
.etag(ETAG)
.schema(TABLE_SCHEMA)
.job(JOB_ID)
.totalRows(1L)
.build();

@Test
public void testServiceOptions() throws Exception {
Expand All @@ -212,7 +225,7 @@ public void testModelAndRequests() throws Exception {
TABLE_SCHEMA, TABLE_INFO, VIEW_INFO, EXTERNAL_TABLE_INFO, INLINE_FUNCTION, URI_FUNCTION,
JOB_STATISTICS, EXTRACT_STATISTICS, LOAD_STATISTICS, QUERY_STATISTICS, BIGQUERY_ERROR,
JOB_STATUS, JOB_ID, COPY_JOB, EXTRACT_JOB, LOAD_JOB, QUERY_JOB, INSERT_ALL_REQUEST,
INSERT_ALL_RESPONSE, FIELD_VALUE};
INSERT_ALL_RESPONSE, FIELD_VALUE, QUERY_REQUEST, QUERY_RESPONSE};
for (Serializable obj : objects) {
Object copy = serializeAndDeserialize(obj);
assertEquals(obj, obj);
Expand Down

0 comments on commit 903d3c6

Please sign in to comment.