Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
3f89f99
feat(bigquery-jdbc): implement parameter setters in PreparedStatement
Neenu1995 Jul 16, 2026
6a9191d
address commets
Neenu1995 Jul 16, 2026
defb44a
feat(bigquery-jdbc): implement PreparedStatement ParameterMetaData an…
Neenu1995 Jul 16, 2026
12348a6
add date/time handling in setObject
Neenu1995 Jul 16, 2026
1e293fb
fix(jdbc): clone Calendar parameter in date/time setters to prevent m…
Neenu1995 Jul 16, 2026
5e3e7d0
fix short conversion
Neenu1995 Jul 16, 2026
7611ee7
Merge branch 'ps-part1-setters' into ps-part2-metadata
Neenu1995 Jul 16, 2026
b3ca772
feat(jdbc): support dynamic parameter modes (IN/OUT/INOUT) in BigQuer…
Neenu1995 Jul 17, 2026
15ff74a
Merge branch 'main' into ps-part2-metadata
Neenu1995 Jul 17, 2026
9b2bcc9
Merge branch 'ps-part2-metadata' of github.com:googleapis/google-clou…
Neenu1995 Jul 17, 2026
6ea936b
feat(bigquery-jdbc): centralize Calendar date time conversion helpers…
Neenu1995 Jul 17, 2026
cfe22a7
refactor(bigquery-jdbc): remove legacy Calendar conversion wrappers f…
Neenu1995 Jul 17, 2026
a6d0246
test(bigquery-jdbc): relocate testCalendarConversions from BigQueryPa…
Neenu1995 Jul 17, 2026
be03443
fix(bigquery-jdbc): fix closing brace syntax error in BigQueryParamet…
Neenu1995 Jul 17, 2026
d576642
perf(bigquery-jdbc): optimize Calendar date/time conversions using ja…
Neenu1995 Jul 17, 2026
4c177b3
lint
Neenu1995 Jul 17, 2026
bd0f6e4
fix(bigquery-jdbc): update getSafeCalendar and convertTimeWithCalenda…
Neenu1995 Jul 17, 2026
00db9bd
fix(bigquery-jdbc): refine temporal timezone coercion for Calendar ge…
Neenu1995 Jul 17, 2026
ffa1ed3
defensive getSafeCalendar
Neenu1995 Jul 17, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.util.AbstractMap.SimpleEntry;
import java.util.Map;

Expand Down Expand Up @@ -117,11 +123,15 @@ static StandardSQLTypeName classToType(Class type)
return StandardSQLTypeName.FLOAT64;
} else if (BigDecimal.class.isAssignableFrom(type)) {
return StandardSQLTypeName.NUMERIC;
} else if (Date.class.isAssignableFrom(type)) {
} else if (Date.class.isAssignableFrom(type) || LocalDate.class.isAssignableFrom(type)) {
return StandardSQLTypeName.DATE;
} else if (Timestamp.class.isAssignableFrom(type)) {
} else if (Timestamp.class.isAssignableFrom(type)
|| LocalDateTime.class.isAssignableFrom(type)
|| OffsetDateTime.class.isAssignableFrom(type)
|| Instant.class.isAssignableFrom(type)
|| ZonedDateTime.class.isAssignableFrom(type)) {
return StandardSQLTypeName.TIMESTAMP;
} else if (Time.class.isAssignableFrom(type)) {
} else if (Time.class.isAssignableFrom(type) || LocalTime.class.isAssignableFrom(type)) {
return StandardSQLTypeName.TIME;
} else if (JsonObject.class.isAssignableFrom(type)) {
return StandardSQLTypeName.JSON;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* Copyright 2026 Google LLC
*
* 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
*
* https://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.google.cloud.bigquery.jdbc;

import com.google.cloud.bigquery.StandardSQLTypeName;
import com.google.cloud.bigquery.exception.BigQueryJdbcException;
import java.sql.ParameterMetaData;
import java.sql.SQLException;
import java.sql.Types;

/** ParameterMetaData implementation for BigQuery JDBC PreparedStatement parameters. */
class BigQueryParameterMetaData implements ParameterMetaData {
private final int parameterCount;
private final BigQueryParameterHandler parameterHandler;

BigQueryParameterMetaData(int parameterCount, BigQueryParameterHandler parameterHandler) {
this.parameterCount = parameterCount;
this.parameterHandler = parameterHandler;
}

private void checkValidIndex(int param) throws SQLException {
if (param < 1 || param > this.parameterCount) {
throw new BigQueryJdbcException("Invalid parameter index: " + param);
}
}

@Override
public int getParameterCount() {
return this.parameterCount;
}

@Override
public int isNullable(int param) throws SQLException {
checkValidIndex(param);
return parameterNullable;
}

@Override
public boolean isSigned(int param) throws SQLException {
int type = getParameterType(param);
return type == Types.SMALLINT
|| type == Types.TINYINT
|| type == Types.INTEGER
|| type == Types.BIGINT
|| type == Types.FLOAT
|| type == Types.DOUBLE
|| type == Types.DECIMAL
|| type == Types.NUMERIC;
}

@Override
public int getPrecision(int param) throws SQLException {
checkValidIndex(param);
StandardSQLTypeName sqlType = getStandardSQLTypeName(param);
if (sqlType != null) {
BigQueryJdbcTypeMappings.ColumnTypeInfo typeInfo =
BigQueryJdbcTypeMappings.STANDARD_TYPE_INFO.get(sqlType);
if (typeInfo != null && typeInfo.columnSize != null) {
return typeInfo.columnSize;
}
}
return 0;
}

@Override
public int getScale(int param) throws SQLException {
checkValidIndex(param);
StandardSQLTypeName sqlType = getStandardSQLTypeName(param);
if (sqlType != null) {
BigQueryJdbcTypeMappings.ColumnTypeInfo typeInfo =
BigQueryJdbcTypeMappings.STANDARD_TYPE_INFO.get(sqlType);
if (typeInfo != null && typeInfo.decimalDigits != null) {
return typeInfo.decimalDigits;
}
}
return 0;
}

@Override
public int getParameterType(int param) throws SQLException {
checkValidIndex(param);
StandardSQLTypeName sqlType = getStandardSQLTypeName(param);
if (sqlType != null) {
Integer jdbcType = BigQueryJdbcTypeMappings.standardSQLToJavaSqlTypesMapping.get(sqlType);
if (jdbcType != null) {
return jdbcType;
}
}
return Types.OTHER;
}

@Override
public String getParameterTypeName(int param) throws SQLException {
checkValidIndex(param);
StandardSQLTypeName sqlType = getStandardSQLTypeName(param);
return sqlType != null ? sqlType.name() : "UNKNOWN";
}

@Override
public String getParameterClassName(int param) throws SQLException {
checkValidIndex(param);
StandardSQLTypeName sqlType = getStandardSQLTypeName(param);
if (sqlType != null) {
Class<?> clazz = BigQueryJdbcTypeMappings.standardSQLToJavaTypeMapping.get(sqlType);
if (clazz != null) {
return clazz.getName();
}
}
Class<?> boundType = this.parameterHandler.getType(param);
if (boundType != null) {
return boundType.getName();
}
return Object.class.getName();
Comment thread
Neenu1995 marked this conversation as resolved.
}

@Override
public int getParameterMode(int param) throws SQLException {
checkValidIndex(param);
if (this.parameterHandler != null) {
BigQueryParameterHandler.BigQueryStatementParameterType paramType =
this.parameterHandler.getParameterType(param);
if (paramType == BigQueryParameterHandler.BigQueryStatementParameterType.OUT) {
return parameterModeOut;
} else if (paramType == BigQueryParameterHandler.BigQueryStatementParameterType.INOUT) {
return parameterModeInOut;
}
}
return parameterModeIn;
}

private StandardSQLTypeName getStandardSQLTypeName(int param) {
if (this.parameterHandler != null) {
StandardSQLTypeName sqlType = this.parameterHandler.getSqlType(param);
if (sqlType != null) {
return sqlType;
}
Class<?> javaType = this.parameterHandler.getType(param);
if (javaType != null) {
try {
return BigQueryJdbcTypeMappings.classToType(javaType);
} catch (SQLException ignored) {
// fall back to default
}
}
}
return null;
}

@Override
public <T> T unwrap(Class<T> iface) throws SQLException {
if (iface.isInstance(this)) {
return iface.cast(this);
}
throw new BigQueryJdbcException("Cannot unwrap to " + iface.getName());
}

@Override
public boolean isWrapperFor(Class<?> iface) throws SQLException {
return iface != null && iface.isInstance(this);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
Expand All @@ -70,7 +76,7 @@ class BigQueryPreparedStatement extends BigQueryStatement implements PreparedSta
protected int parameterCount = 0;
protected String currentQuery;
private Queue<ArrayList<BigQueryJdbcParameter>> batchParameters = new LinkedList<>();
private Schema insertSchema = null;
Schema insertSchema = null;
private TableName insertTableName = null;

BigQueryPreparedStatement(BigQueryConnection connection, String query) {
Expand Down Expand Up @@ -230,6 +236,30 @@ public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQ
setNull(parameterIndex, targetSqlType);
return;
}
if (x instanceof LocalDate) {
setDate(parameterIndex, Date.valueOf((LocalDate) x));
return;
}
if (x instanceof LocalTime) {
setTime(parameterIndex, Time.valueOf((LocalTime) x));
return;
}
if (x instanceof LocalDateTime) {
setTimestamp(parameterIndex, Timestamp.valueOf((LocalDateTime) x));
return;
}
if (x instanceof OffsetDateTime) {
setTimestamp(parameterIndex, Timestamp.from(((OffsetDateTime) x).toInstant()));
return;
}
if (x instanceof Instant) {
setTimestamp(parameterIndex, Timestamp.from((Instant) x));
return;
}
if (x instanceof ZonedDateTime) {
setTimestamp(parameterIndex, Timestamp.from(((ZonedDateTime) x).toInstant()));
return;
}
Class<?> javaType = BigQueryJdbcTypeMappings.getJavaType(targetSqlType);
this.parameterHandler.setParameter(parameterIndex, x, javaType);
}
Expand All @@ -241,6 +271,30 @@ public void setObject(int parameterIndex, Object x) throws SQLException {
setNull(parameterIndex, Types.NULL);
return;
}
if (x instanceof LocalDate) {
setDate(parameterIndex, Date.valueOf((LocalDate) x));
return;
}
if (x instanceof LocalTime) {
setTime(parameterIndex, Time.valueOf((LocalTime) x));
return;
}
if (x instanceof LocalDateTime) {
setTimestamp(parameterIndex, Timestamp.valueOf((LocalDateTime) x));
return;
}
if (x instanceof OffsetDateTime) {
setTimestamp(parameterIndex, Timestamp.from(((OffsetDateTime) x).toInstant()));
return;
}
if (x instanceof Instant) {
setTimestamp(parameterIndex, Timestamp.from((Instant) x));
return;
}
if (x instanceof ZonedDateTime) {
setTimestamp(parameterIndex, Timestamp.from(((ZonedDateTime) x).toInstant()));
return;
}
this.parameterHandler.setParameter(parameterIndex, x, x.getClass());
}

Expand Down Expand Up @@ -470,24 +524,42 @@ public void setArray(int parameterIndex, Array x) throws SQLException {
}

@Override
public ResultSetMetaData getMetaData() {
// TODO(neenu) :IMPLEMENT metadata
public ResultSetMetaData getMetaData() throws SQLException {
checkClosed();
if (this.insertSchema != null) {
return BigQueryResultSetMetadata.of(this.insertSchema.getFields(), this);
}
return null;
}

@Override
public void setDate(int parameterIndex, Date x, Calendar cal) {
// TODO :NOT IMPLEMENTED
public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException {
checkClosed();
if (x == null) {
setNull(parameterIndex, Types.DATE);
return;
}
setDate(parameterIndex, BigQueryTypeCoercionUtility.convertDateWithCalendar(x, cal));
}

@Override
public void setTime(int parameterIndex, Time x, Calendar cal) {
// TODO :NOT IMPLEMENTED
public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException {
checkClosed();
if (x == null) {
setNull(parameterIndex, Types.TIME);
return;
}
setTime(parameterIndex, BigQueryTypeCoercionUtility.convertTimeWithCalendar(x, cal));
}

@Override
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) {
// TODO :NOT IMPLEMENTED
public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException {
checkClosed();
if (x == null) {
setNull(parameterIndex, Types.TIMESTAMP);
return;
}
setTimestamp(parameterIndex, BigQueryTypeCoercionUtility.convertTimestampWithCalendar(x, cal));
}

@Override
Expand All @@ -501,9 +573,9 @@ public void setURL(int parameterIndex, URL x) throws SQLException {
}

@Override
public ParameterMetaData getParameterMetaData() {
// TODO(neenu) :IMPLEMENT
return null;
public ParameterMetaData getParameterMetaData() throws SQLException {
checkClosed();
return new BigQueryParameterMetaData(this.parameterCount, this.parameterHandler);
}

@Override
Expand Down
Loading
Loading