Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion java-bigquery-jdbc/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ target-it/**
tools/**/*.class
tools/**/drivers/**
tools/**/logs/**
tools/**/*.jfr
tools/**/*.jfr

# Gemini/Jetski agent custom skills
.agents/
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package com.google.cloud.bigquery.jdbc;

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryError;
import com.google.cloud.bigquery.Field;
import com.google.cloud.bigquery.FieldList;
import com.google.cloud.bigquery.Job;
Expand All @@ -40,10 +41,12 @@
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.List;

public abstract class BigQueryBaseResultSet extends BigQueryNoOpsResultSet
implements BigQueryResultSet {
Expand All @@ -58,6 +61,10 @@ public abstract class BigQueryBaseResultSet extends BigQueryNoOpsResultSet
protected final boolean isNested;
protected boolean isClosed = false;
protected boolean wasNull = false;
private int fetchSize = -1;
private Job job;
private SQLWarning warnings;
private boolean warningsLoaded = false;
protected final BigQueryTypeCoercer bigQueryTypeCoercer = BigQueryTypeCoercionUtility.INSTANCE;

protected BigQueryBaseResultSet(
Expand All @@ -76,11 +83,12 @@ public QueryStatistics getQueryStatistics() {
if (queryStatistics != null) {
return queryStatistics;
}
if (jobId == null || bigQuery == null) {
return null;
Job activeJob = this.job;
if (activeJob == null && jobId != null && bigQuery != null) {
this.job = bigQuery.getJob(jobId);
activeJob = this.job;
}
Job job = bigQuery.getJob(jobId);
queryStatistics = job != null ? job.getStatistics() : null;
queryStatistics = activeJob != null ? activeJob.getStatistics() : null;
return queryStatistics;
}

Expand All @@ -92,6 +100,14 @@ public JobId getJobId() {
return jobId;
}

public void setJob(Job job) {
this.job = job;
}
Comment thread
Neenu1995 marked this conversation as resolved.
Comment thread
Neenu1995 marked this conversation as resolved.

public Job getJob() {
return job;
}

public void setQueryId(String queryId) {
this.queryId = queryId;
}
Expand Down Expand Up @@ -688,4 +704,89 @@ public <T> T unwrap(Class<T> iface) throws SQLException {
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return iface != null && iface.isInstance(this);
}

@Override
public int getFetchDirection() throws SQLException {
checkClosed();
// Fetch direction is restricted to forward-only.
return ResultSet.FETCH_FORWARD;
}

@Override
public void setFetchDirection(int direction) throws SQLException {
checkClosed();
// Restricts the fetch direction to FETCH_FORWARD. Other directions are not supported.
if (direction != ResultSet.FETCH_FORWARD) {
throw new SQLException("Only FETCH_FORWARD is supported");
}
}

@Override
public void setFetchSize(int rows) throws SQLException {
checkClosed();
if (rows < 0) {
throw new SQLException("Fetch size must be >= 0");
}
// This is a no-op placeholder for JDBC API compliance to prevent crashes in
// third-party client tools that call this automatically.
// The driver manages pagination internally under the hood.
this.fetchSize = rows;
}

@Override
public int getFetchSize() throws SQLException {
checkClosed();
// Returns the fetch size set on this ResultSet, or falls back to the statement's
// fetch size, defaulting to the internal row buffer size of 20000.
if (this.fetchSize != -1) {
Comment thread
Neenu1995 marked this conversation as resolved.
Outdated
return this.fetchSize;
}
if (statement != null) {
int statementFetchSize = statement.getFetchSize();
if (statementFetchSize > 0) {
return statementFetchSize;
}
}
return 20000;
Comment thread
Neenu1995 marked this conversation as resolved.
Outdated
}

@Override
public SQLWarning getWarnings() throws SQLException {
checkClosed();
// Dynamically fetches and chains non-fatal execution errors from the BigQuery Job
// as SQLWarning objects, using lazy-loading and local caching for performance.
if (warningsLoaded) {
return warnings;
}
Job activeJob = this.job;
if (activeJob == null && jobId != null && bigQuery != null) {
this.job = bigQuery.getJob(jobId);
activeJob = this.job;
}
if (activeJob != null
&& activeJob.getStatus() != null
&& activeJob.getStatus().getExecutionErrors() != null) {
List<BigQueryError> errors = activeJob.getStatus().getExecutionErrors();
SQLWarning chain = null;
for (BigQueryError error : errors) {
SQLWarning warning = new SQLWarning(error.getMessage(), error.getReason());
if (chain == null) {
chain = warning;
} else {
chain.setNextWarning(warning);
}
}
this.warnings = chain;
}
this.warningsLoaded = true;
return warnings;
}
Comment thread
Neenu1995 marked this conversation as resolved.

@Override
public void clearWarnings() throws SQLException {
checkClosed();
// Clears the cached warnings chain.
this.warnings = null;
this.warningsLoaded = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
import java.sql.ResultSet;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Time;
import java.sql.Timestamp;
Expand All @@ -42,21 +41,6 @@
/** NoOps Abstract base class for BigQuery JDBC ResultSet(s). */
abstract class BigQueryNoOpsResultSet implements ResultSet {

@Override
public int getFetchDirection() throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
}

@Override
public void setFetchSize(int rows) throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
}

@Override
public int getFetchSize() throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
}

@Override
public String getCursorName() throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
Expand Down Expand Up @@ -102,11 +86,6 @@ public boolean previous() throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
}

@Override
public void setFetchDirection(int direction) throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
}

@Override
public boolean rowUpdated() throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
Expand Down Expand Up @@ -655,16 +634,6 @@ public void updateNClob(String columnLabel, Reader reader) throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
}

@Override
public SQLWarning getWarnings() throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
}

@Override
public void clearWarnings() throws SQLException {
throw new BigQueryJdbcSqlFeatureNotSupportedException(METHOD_NOT_IMPLEMENTED);
}

void checkClosed() throws SQLException {
if (isClosed()) {
throw new BigQueryJdbcException("This " + getClass().getName() + " has been closed");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,7 @@ void runQuery(String query, QueryJobConfiguration jobConfiguration)
? getStatementType(jobConfiguration)
: ((QueryStatistics) executeResult.job.getStatistics()).getStatementType();
SqlType queryType = getQueryType(jobConfiguration, statementType);
handleQueryResult(query, executeResult.tableResult, queryType);
handleQueryResult(query, executeResult.tableResult, queryType, executeResult.job);
} catch (InterruptedException ex) {
throw new BigQueryJdbcRuntimeException("Interrupted during runQuery", ex);
} catch (BigQueryException ex) {
Expand Down Expand Up @@ -678,14 +678,22 @@ Job getNextJob() {

void handleQueryResult(String query, TableResult results, SqlType queryType)
throws SQLException, InterruptedException {
handleQueryResult(query, results, queryType, null);
}

void handleQueryResult(String query, TableResult results, SqlType queryType, Job job)
throws SQLException, InterruptedException {
LOG.finer("++enter++");
switch (queryType) {
case SELECT:
processQueryResponse(query, results);
if (this.currentResultSet instanceof BigQueryBaseResultSet) {
Comment thread
Neenu1995 marked this conversation as resolved.
Outdated
((BigQueryBaseResultSet) this.currentResultSet).setJob(job);
}
break;
case DML:
case DML_EXTRA:
QueryStatistics dmlStats = getQueryStatisticsFromJob(results);
QueryStatistics dmlStats = getQueryStatisticsFromJob(results, job);
Long dmlRowCount =
(dmlStats != null && dmlStats.getNumDmlAffectedRows() != null)
? dmlStats.getNumDmlAffectedRows()
Expand Down Expand Up @@ -717,13 +725,13 @@ void handleQueryResult(String query, TableResult results, SqlType queryType)
StatementType statementType =
((QueryStatistics) (currentJob.getStatistics())).getStatementType();
SqlType sqlType = getQueryType(currentJob.getConfiguration(), statementType);
handleQueryResult(query, currentJob.getQueryResults(), sqlType);
handleQueryResult(query, currentJob.getQueryResults(), sqlType, currentJob);
} catch (NullPointerException ex) {
throw new BigQueryJdbcException(ex);
}
break;
case EXPORT:
QueryStatistics exportStats = getQueryStatisticsFromJob(results);
QueryStatistics exportStats = getQueryStatisticsFromJob(results, job);
Long exportRowCount = 0L;
if (exportStats != null) {
QueryStatistics.ExportDataStats dataStats = exportStats.getExportDataStats();
Expand All @@ -745,10 +753,14 @@ void handleQueryResult(String query, TableResult results, SqlType queryType)
}
}

private QueryStatistics getQueryStatisticsFromJob(TableResult results) throws SQLException {
private QueryStatistics getQueryStatisticsFromJob(TableResult results, Job job)
throws SQLException {
try {
Job job = this.bigQuery.getJob(results.getJobId());
Job completedJob = (job != null) ? job.waitFor() : null;
Job activeJob = job;
if (activeJob == null) {
activeJob = this.bigQuery.getJob(results.getJobId());
}
Job completedJob = (activeJob != null) ? activeJob.waitFor() : null;
JobStatistics stats = (completedJob != null) ? completedJob.getStatistics() : null;
if (stats instanceof QueryStatistics) {
return (QueryStatistics) stats;
Expand Down Expand Up @@ -794,7 +806,6 @@ ArrowSchema getArrowSchema(ReadSession readSession) {
return readSession.getArrowSchema();
}

/** Uses Bigquery Storage Read API and returns the stream as ResultSet */
@InternalApi
ResultSet processArrowResultSet(TableResult results) throws SQLException {
LOG.finer("++enter++");
Expand Down Expand Up @@ -844,6 +855,7 @@ ResultSet processArrowResultSet(TableResult results) throws SQLException {
new BigQueryResultSetFinalizers.ArrowResultSetFinalizer(
arrowResultSet, referenceQueueArrowRs, populateBufferWorker));
arrowResultSet.setJobId(currentJobId);
arrowResultSet.setQueryId(results.getQueryId());
return arrowResultSet;

} catch (Exception ex) {
Expand Down Expand Up @@ -1561,7 +1573,7 @@ private boolean getMoreResultsImpl(int current) throws SQLException {
StatementType statementType =
((QueryStatistics) (currentJob.getStatistics())).getStatementType();
SqlType sqlType = getQueryType(currentJob.getConfiguration(), statementType);
handleQueryResult(this.scriptQuery, currentJob.getQueryResults(), sqlType);
handleQueryResult(this.scriptQuery, currentJob.getQueryResults(), sqlType, currentJob);

return sqlType == SqlType.SELECT;
} else {
Expand Down
Loading
Loading