All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.starschema.clouddb.jdbc.BQScrollableResultSet Maven / Gradle / Ivy

/**
 * Copyright (c) 2015, STARSCHEMA LTD. All rights reserved.
 *
 * 

Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * *

1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the * above copyright notice, this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * *

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *

This class implements the java.sql.Resultset interface */ package net.starschema.clouddb.jdbc; import com.google.api.client.util.Data; import com.google.api.services.bigquery.model.BiEngineReason; import com.google.api.services.bigquery.model.GetQueryResultsResponse; import com.google.api.services.bigquery.model.JobReference; import com.google.api.services.bigquery.model.TableCell; import com.google.api.services.bigquery.model.TableRow; import com.google.api.services.bigquery.model.TableSchema; import java.math.BigDecimal; import java.math.BigInteger; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.List; import javax.annotation.Nullable; /** * This class implements the java.sql.ResultSet interface its superclass is ScrollableResultset * * @author Attila Horváth */ public class BQScrollableResultSet extends ScrollableResultset implements java.sql.ResultSet { /** to set the maxFieldSize */ private int maxFieldSize = 0; /** This Reference is for storing the Reference for the Statement which created this Resultset */ private BQStatement Statementreference = null; /** The total number of bytes processed while creating this ResultSet */ private final @Nullable Long totalBytesProcessed; /** Whether the ResultSet came from BigQuery's cache */ private final @Nullable Boolean cacheHit; /** Specifies which mode of BI Engine acceleration was performed (if any). */ private final @Nullable String biEngineMode; /** * In case of DISABLED or PARTIAL bi_engine_mode, these contain the explanatory reasons as to why * BI Engine could not accelerate. In case the full query was accelerated, this field is not * populated. */ private final @Nullable List biEngineReasons; private final @Nullable JobReference jobReference; /** The BigQuery query ID; set if the query completed without a Job */ private final @Nullable String queryId; private TableSchema schema; /** * Constructor of BQResultset, that initializes all private variables * * @param bigQueryGetQueryResultResponse BigQueryGetQueryResultResponse from Bigquery * @param bqStatementRoot Reference of the Statement that creates this Resultset */ public BQScrollableResultSet( GetQueryResultsResponse bigQueryGetQueryResultResponse, BQStatementRoot bqStatementRoot) { this( bigQueryGetQueryResultResponse.getRows(), bqStatementRoot, bigQueryGetQueryResultResponse.getSchema(), bigQueryGetQueryResultResponse.getTotalBytesProcessed(), bigQueryGetQueryResultResponse.getCacheHit(), null, null, bigQueryGetQueryResultResponse.getJobReference(), null); BigInteger maxrow; try { maxrow = BigInteger.valueOf(bqStatementRoot.getMaxRows()); bigQueryGetQueryResultResponse.setTotalRows(maxrow); } catch (SQLException e) { } // Should not happen. } public BQScrollableResultSet( List rows, BQStatementRoot bqStatementRoot, TableSchema schema, @Nullable Long totalBytesProcessed, @Nullable Boolean cacheHit, @Nullable String biEngineMode, @Nullable List biEngineReasons, @Nullable JobReference jobReference, @Nullable String queryId) { logger.debug("Created Scrollable resultset TYPE_SCROLL_INSENSITIVE"); try { maxFieldSize = bqStatementRoot.getMaxFieldSize(); } catch (SQLException e) { // Should not happen. } if (rows != null) { this.RowsofResult = rows.toArray(); } if (bqStatementRoot instanceof BQStatement) { this.Statementreference = (BQStatement) bqStatementRoot; } this.schema = schema; this.totalBytesProcessed = totalBytesProcessed; this.cacheHit = cacheHit; this.biEngineMode = biEngineMode; this.biEngineReasons = biEngineReasons; this.jobReference = jobReference; this.queryId = queryId; } /** {@inheritDoc} */ @Override public int findColumn(String columnLabel) throws SQLException { return CommonResultSet.findColumn(columnLabel, getMetaData()); } /** {@inheritDoc} */ @Override public ResultSetMetaData getMetaData() throws SQLException { if (this.isClosed()) { throw new BQSQLException("This Resultset is Closed"); } return new BQResultsetMetaData(this.schema, this.Statementreference.connection.getProjectId()); } /** {@inheritDoc} */ @Override public Object getObject(int columnIndex) throws SQLException { // to make the logfiles smaller! // logger.debug("Function call getObject columnIndex is: " + String.valueOf(columnIndex)); this.closestrm(); if (this.isClosed()) { throw new BQSQLException("This Resultset is Closed"); } this.ThrowCursorNotValidExeption(); if (this.RowsofResult == null) { throw new BQSQLException("There are no rows in this Resultset"); } if (this.getMetaData().getColumnCount() < columnIndex || columnIndex < 1) { throw new BQSQLException("ColumnIndex is not valid"); } String Columntype = schema.getFields().get(columnIndex - 1).getType(); TableCell field = ((TableRow) this.RowsofResult[this.Cursor]).getF().get(columnIndex - 1); if (Data.isNull(field.getV())) { this.wasnull = true; return null; } else { String result = field.getV().toString(); this.wasnull = false; try { if (Columntype.equals("STRING")) { // removing the excess byte by the setmaxFiledSize if (maxFieldSize == 0 || maxFieldSize == Integer.MAX_VALUE) { return result; } else { try { // lets try to remove the excess bytes return result.substring(0, maxFieldSize); } catch (IndexOutOfBoundsException iout) { // we don't need to remove any excess byte return result; } } } if (Columntype.equals("FLOAT")) { return Float.parseFloat(result); } if (Columntype.equals("BOOLEAN")) { return Boolean.parseBoolean(result); } if (Columntype.equals("INTEGER")) { return Long.parseLong(result); } if (Columntype.equals("DATETIME")) { // A BigQuery DATETIME is essentially defined by its string representation; // the "clock-calendar parameters" comprising year, month, day, hour, minute, etc. // On the other hand, a [java.sql.Timestamp] object is defined as a global instant, // similar to BQ TIMESTAMP. It has a [toString] method that interprets that instant in the // system default time zone. Thus, in order to produce a [Timestamp] object whose // [toString] method has the correct result, we must adjust the value of the instant // according to the system default time zone (passing a null Calendar uses the system // default). return DateTimeUtils.parseDateTime(result, null); } if (Columntype.equals("TIMESTAMP")) { // A BigQuery TIMESTAMP is defined as a global instant in time, so when we create the // [java.sql.Timestamp] object to represent it, we must not make any time zone adjustment. return DateTimeUtils.parseTimestamp(result); } if (Columntype.equals("DATE")) { return DateTimeUtils.parseDate(result, null); } if (Columntype.equals("TIME")) { return DateTimeUtils.parseTime(result, null); } if (Columntype.equals("NUMERIC")) { return new BigDecimal(result); } throw new BQSQLException("Unsupported Type"); } catch (NumberFormatException e) { throw new BQSQLException(e); } } } /** {@inheritDoc} */ @Override public Statement getStatement() throws SQLException { return this.Statementreference; } @Override public T getObject(int columnIndex, Class type) throws SQLException { throw new BQSQLException("Not implemented."); } @Override public T getObject(String columnLabel, Class type) throws SQLException { throw new BQSQLException("Not implemented."); } /** {@inheritDoc} */ @Override public String getString(int columnIndex) throws SQLException { // to make the logfiles smaller! // logger.debug("Function call getString columnIndex is: " + String.valueOf(columnIndex)); this.closestrm(); this.ThrowCursorNotValidExeption(); if (this.isClosed()) { throw new BQSQLException("This Resultset is Closed"); } String result = ((TableRow) this.RowsofResult[this.Cursor]).getF().get(columnIndex - 1).getV().toString(); if (result == null) { this.wasnull = true; } else { this.wasnull = false; } // removing the excess byte by the setmaxFiledSize if (maxFieldSize == 0 || maxFieldSize == Integer.MAX_VALUE) { return result; } else { try { // lets try to remove the excess bytes return result.substring(0, maxFieldSize); } catch (IndexOutOfBoundsException iout) { // we don't need to remove any excess byte return result; } } } public @Nullable Long getTotalBytesProcessed() { return totalBytesProcessed; } public @Nullable Boolean getCacheHit() { return cacheHit; } public @Nullable String getBiEngineMode() { return biEngineMode; } public @Nullable List getBiEngineReasons() { return biEngineReasons; } public @Nullable String getJobId() { if (this.jobReference != null) { return this.jobReference.getJobId(); } else { return null; } } public @Nullable String getQueryId() { return queryId; } }