/* * This file is a component of thundr, a software library from 3wks. * Read more: http://www.3wks.com.au/thundr * Copyright (C) 2013 3wks, <thundr@3wks.com.au> * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.threewks.thundr.bigquery; import java.io.IOException; import java.util.ArrayList; import java.util.List; import com.google.api.services.bigquery.Bigquery; import com.google.api.services.bigquery.Bigquery.Jobs.Insert; import com.google.api.services.bigquery.model.GetQueryResultsResponse; import com.google.api.services.bigquery.model.Job; import com.google.api.services.bigquery.model.JobConfiguration; import com.google.api.services.bigquery.model.JobConfigurationQuery; import com.google.api.services.bigquery.model.JobReference; import com.google.api.services.bigquery.model.QueryRequest; import com.google.api.services.bigquery.model.QueryResponse; import com.google.api.services.bigquery.model.TableCell; import com.google.api.services.bigquery.model.TableFieldSchema; import com.google.api.services.bigquery.model.TableRow; import com.google.api.services.bigquery.model.TableSchema; import com.threewks.thundr.logger.Logger; public class BigQueryPullServiceImpl implements BigQueryPullService { private Bigquery bigQuery; private String projectId; public BigQueryPullServiceImpl(Bigquery bigQuery, String bigQueryProjectId) { this.bigQuery = bigQuery; this.projectId = bigQueryProjectId; } @Override public List<List<String>> query(String query, boolean includeColumnNames) throws IOException { Logger.debug("Running query %s", query); QueryRequest queryRequest = new QueryRequest().setQuery(query); QueryResponse response = bigQuery.jobs().query(projectId, queryRequest).execute(); if (response.getJobComplete()) { JobReference jobReference = response.getJobReference(); if (jobReference != null) { Logger.debug("Successfully ran query for job id %s", jobReference.getJobId()); } } return buildQueryResults(response.getSchema(), response.getRows(), includeColumnNames); } @Override public String queryAsync(String query) throws IOException { Job job = new Job(); JobConfiguration config = new JobConfiguration(); JobConfigurationQuery queryConfig = new JobConfigurationQuery(); config.setQuery(queryConfig); job.setConfiguration(config); queryConfig.setQuery(query); Insert insert = bigQuery.jobs().insert(projectId, job); insert.setProjectId(projectId); JobReference jobReference = insert.execute().getJobReference(); Logger.debug("Submitted job %s to BigQuery", jobReference.getJobId()); return jobReference.getJobId(); } @Override public String getJobStatus(String jobId) throws IOException { Job job = bigQuery.jobs().get(projectId, jobId).execute(); return job.getStatus().getState(); } @Override public List<List<String>> getAsyncQueryResults(String jobId, boolean includeColumnNames) throws IOException { Job job = bigQuery.jobs().get(projectId, jobId).execute(); String state = job.getStatus().getState(); if (state.equals("DONE")) { GetQueryResultsResponse response = bigQuery.jobs().getQueryResults(projectId, job.getJobReference().getJobId()).execute(); TableSchema schema = response.getSchema(); List<TableRow> rows = response.getRows(); return buildQueryResults(schema, rows, includeColumnNames); } // job is not done yet, return null return null; } /** * Build a list of results. * * @param schema the table schema for the results. * @param rows the rows of results. * @param includeColumnNames a boolean indicating whether the column names should be included in the results or not. * @return the results as a list of list of strings. */ private List<List<String>> buildQueryResults(TableSchema schema, List<TableRow> rows, boolean includeColumnNames) { List<List<String>> results = new ArrayList<List<String>>(); if (includeColumnNames) { results.add(getColumnNames(schema)); } results.addAll(getResultData(rows)); return results; } /** * Get a list of the column names from a {@link TableSchema}. * * @param schema the table schema to extract the column names from. * @return a list of strings. */ private List<String> getColumnNames(TableSchema schema) { List<TableFieldSchema> tableFieldSchema = schema.getFields(); List<String> columnNames = new ArrayList<String>(); for (TableFieldSchema fieldSchema : tableFieldSchema) { columnNames.add(fieldSchema.getName()); } return columnNames; } /** * Extract the result data from a list of {@link TableRow} objects. * * @param rows a list of table rows to extract the result data from. * @return a list of rows (represented as lists of strings). */ private List<List<String>> getResultData(List<TableRow> rows) { List<List<String>> results = new ArrayList<List<String>>(); if (rows != null) { for (TableRow tableRow : rows) { List<String> row = new ArrayList<String>(); List<TableCell> fields = tableRow.getF(); for (TableCell cell : fields) { row.add((String) cell.getV()); } results.add(row); } } return results; } }