From 3f89f992c2010ec8246f8eaa5fc15d9a4001eaea Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Thu, 16 Jul 2026 12:36:43 -0400 Subject: [PATCH 1/3] feat(bigquery-jdbc): implement parameter setters in PreparedStatement --- .../jdbc/BigQueryJdbcTypeMappings.java | 15 +-- .../jdbc/BigQueryPreparedStatement.java | 56 +++++--- .../BigQueryPreparedStatementSettersTest.java | 125 ++++++++++++++++++ .../bigquery/jdbc/it/ITBigQueryJDBCTest.java | 26 ++-- 4 files changed, 190 insertions(+), 32 deletions(-) create mode 100644 java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcTypeMappings.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcTypeMappings.java index 795d60436b83..35ac15aae3cf 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcTypeMappings.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcTypeMappings.java @@ -80,6 +80,8 @@ class BigQueryJdbcTypeMappings { ImmutableMap.ofEntries( entry(Types.BIGINT, Long.class), entry(Types.INTEGER, Integer.class), + entry(Types.SMALLINT, Long.class), + entry(Types.TINYINT, Long.class), entry(Types.BOOLEAN, Boolean.class), entry(Types.DOUBLE, Double.class), entry(Types.FLOAT, Float.class), @@ -94,7 +96,8 @@ class BigQueryJdbcTypeMappings { entry(Types.VARBINARY, byte[].class), entry(Types.STRUCT, Struct.class), entry(Types.BIT, Boolean.class), - entry(Types.ARRAY, Array.class)); + entry(Types.ARRAY, Array.class), + entry(Types.NULL, String.class)); static StandardSQLTypeName classToType(Class type) throws BigQueryJdbcSqlFeatureNotSupportedException { @@ -102,30 +105,24 @@ static StandardSQLTypeName classToType(Class type) return StandardSQLTypeName.BOOL; } else if (String.class.isAssignableFrom(type)) { return StandardSQLTypeName.STRING; - } else if (String.class.isAssignableFrom(type)) { - return StandardSQLTypeName.GEOGRAPHY; - } else if (String.class.isAssignableFrom(type)) { - return StandardSQLTypeName.DATETIME; } else if (Integer.class.isAssignableFrom(type)) { return StandardSQLTypeName.INT64; } else if (Long.class.isAssignableFrom(type)) { return StandardSQLTypeName.INT64; + } else if (Short.class.isAssignableFrom(type)) { + return StandardSQLTypeName.INT64; } else if (Double.class.isAssignableFrom(type)) { return StandardSQLTypeName.FLOAT64; } else if (Float.class.isAssignableFrom(type)) { return StandardSQLTypeName.FLOAT64; } else if (BigDecimal.class.isAssignableFrom(type)) { return StandardSQLTypeName.NUMERIC; - } else if (BigDecimal.class.isAssignableFrom(type)) { - return StandardSQLTypeName.BIGNUMERIC; } else if (Date.class.isAssignableFrom(type)) { return StandardSQLTypeName.DATE; } else if (Timestamp.class.isAssignableFrom(type)) { return StandardSQLTypeName.TIMESTAMP; } else if (Time.class.isAssignableFrom(type)) { return StandardSQLTypeName.TIME; - } else if (String.class.isAssignableFrom(type)) { - return StandardSQLTypeName.JSON; } else if (JsonObject.class.isAssignableFrom(type)) { return StandardSQLTypeName.JSON; } else if (Byte.class.isAssignableFrom(type)) { diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java index 7e62c7fd4f69..9a235e59d66c 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java @@ -55,6 +55,7 @@ import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; +import java.sql.Types; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -114,8 +115,15 @@ public void clearParameters() { } @Override - public void setNull(int parameterIndex, int sqlType) { - // TODO(neenu): implement null case + public void setNull(int parameterIndex, int sqlType) throws SQLException { + checkClosed(); + Class javaType; + try { + javaType = BigQueryJdbcTypeMappings.getJavaType(sqlType); + } catch (SQLException e) { + javaType = String.class; + } + this.parameterHandler.setParameter(parameterIndex, null, javaType); } @Override @@ -131,8 +139,9 @@ public void setByte(int parameterIndex, byte x) throws SQLException { } @Override - public void setShort(int parameterIndex, short x) { - // TODO(neenu): implement Bytes conversion. + public void setShort(int parameterIndex, short x) throws SQLException { + checkClosed(); + this.parameterHandler.setParameter(parameterIndex, (long) x, Long.class); } @Override @@ -172,8 +181,9 @@ public void setString(int parameterIndex, String x) throws SQLException { } @Override - public void setBytes(int parameterIndex, byte[] x) { - // TODO(neenu): implement Bytes conversion. + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + checkClosed(); + this.parameterHandler.setParameter(parameterIndex, x, byte[].class); } @Override @@ -218,11 +228,24 @@ public void setBinaryStream(int parameterIndex, InputStream x, int length) { } @Override - public void setObject(int parameterIndex, Object x, int targetSqlType) {} + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + checkClosed(); + if (x == null) { + setNull(parameterIndex, targetSqlType); + return; + } + Class javaType = BigQueryJdbcTypeMappings.getJavaType(targetSqlType); + this.parameterHandler.setParameter(parameterIndex, x, javaType); + } @Override - public void setObject(int parameterIndex, Object x) { - // TODO :NOT IMPLEMENTED + public void setObject(int parameterIndex, Object x) throws SQLException { + checkClosed(); + if (x == null) { + setNull(parameterIndex, Types.NULL); + return; + } + this.parameterHandler.setParameter(parameterIndex, x, x.getClass()); } @Override @@ -444,8 +467,9 @@ public void setClob(int parameterIndex, Clob x) { } @Override - public void setArray(int parameterIndex, Array x) { - // TODO(neenu) :IMPLEMENT ARRAY + public void setArray(int parameterIndex, Array x) throws SQLException { + checkClosed(); + this.parameterHandler.setParameter(parameterIndex, x, Array.class); } @Override @@ -470,8 +494,8 @@ public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) { } @Override - public void setNull(int parameterIndex, int sqlType, String typeName) { - // TODO :NOT IMPLEMENTED + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + setNull(parameterIndex, sqlType); } @Override @@ -526,8 +550,10 @@ public void setSQLXML(int parameterIndex, SQLXML xmlObject) { } @Override - public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) { - // TODO(neenu) : IMPLEMENT? + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) + throws SQLException { + checkClosed(); + setObject(parameterIndex, x, targetSqlType); } @Override diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java new file mode 100644 index 000000000000..edf0998c5965 --- /dev/null +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java @@ -0,0 +1,125 @@ +/* + * 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 static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.mockito.Mockito.mock; + +import com.google.cloud.bigquery.StandardSQLTypeName; +import java.sql.Array; +import java.sql.Types; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +public class BigQueryPreparedStatementSettersTest { + + private BigQueryConnection connection; + private BigQueryPreparedStatement preparedStatement; + + @BeforeEach + public void setUp() throws Exception { + connection = mock(BigQueryConnection.class); + preparedStatement = new BigQueryPreparedStatement(connection, "SELECT ?, ?, ?, ?, ?"); + } + + @Test + public void testSetNullWithSqlType() throws Exception { + preparedStatement.setNull(1, Types.VARCHAR); + assertNull(preparedStatement.parameterHandler.getParameter(1)); + assertEquals(String.class, preparedStatement.parameterHandler.getType(1)); + assertEquals(StandardSQLTypeName.STRING, preparedStatement.parameterHandler.getSqlType(1)); + + preparedStatement.setNull(2, Types.INTEGER); + assertNull(preparedStatement.parameterHandler.getParameter(2)); + assertEquals(Integer.class, preparedStatement.parameterHandler.getType(2)); + assertEquals(StandardSQLTypeName.INT64, preparedStatement.parameterHandler.getSqlType(2)); + + preparedStatement.setNull(3, Types.NULL); + assertNull(preparedStatement.parameterHandler.getParameter(3)); + assertEquals(String.class, preparedStatement.parameterHandler.getType(3)); + assertEquals(StandardSQLTypeName.STRING, preparedStatement.parameterHandler.getSqlType(3)); + } + + @Test + public void testSetNullWithTypeName() throws Exception { + preparedStatement.setNull(1, Types.VARCHAR, "VARCHAR"); + assertNull(preparedStatement.parameterHandler.getParameter(1)); + assertEquals(String.class, preparedStatement.parameterHandler.getType(1)); + assertEquals(StandardSQLTypeName.STRING, preparedStatement.parameterHandler.getSqlType(1)); + } + + @Test + public void testSetShort() throws Exception { + preparedStatement.setShort(1, (short) 42); + assertEquals(42L, preparedStatement.parameterHandler.getParameter(1)); + assertEquals(Long.class, preparedStatement.parameterHandler.getType(1)); + assertEquals(StandardSQLTypeName.INT64, preparedStatement.parameterHandler.getSqlType(1)); + } + + @Test + public void testSetBytes() throws Exception { + byte[] bytes = new byte[] {1, 2, 3, 4}; + preparedStatement.setBytes(1, bytes); + assertArrayEquals(bytes, (byte[]) preparedStatement.parameterHandler.getParameter(1)); + assertEquals(byte[].class, preparedStatement.parameterHandler.getType(1)); + assertEquals(StandardSQLTypeName.BYTES, preparedStatement.parameterHandler.getSqlType(1)); + } + + @Test + public void testSetObjectSingleArg() throws Exception { + preparedStatement.setObject(1, "hello"); + assertEquals("hello", preparedStatement.parameterHandler.getParameter(1)); + assertEquals(String.class, preparedStatement.parameterHandler.getType(1)); + assertEquals(StandardSQLTypeName.STRING, preparedStatement.parameterHandler.getSqlType(1)); + + preparedStatement.setObject(2, 100L); + assertEquals(100L, preparedStatement.parameterHandler.getParameter(2)); + assertEquals(Long.class, preparedStatement.parameterHandler.getType(2)); + assertEquals(StandardSQLTypeName.INT64, preparedStatement.parameterHandler.getSqlType(2)); + + preparedStatement.setObject(3, null); + assertNull(preparedStatement.parameterHandler.getParameter(3)); + assertEquals(String.class, preparedStatement.parameterHandler.getType(3)); + } + + @Test + public void testSetObjectWithTargetSqlType() throws Exception { + preparedStatement.setObject(1, 123, Types.INTEGER); + assertEquals(123, preparedStatement.parameterHandler.getParameter(1)); + assertEquals(Integer.class, preparedStatement.parameterHandler.getType(1)); + assertEquals(StandardSQLTypeName.INT64, preparedStatement.parameterHandler.getSqlType(1)); + + preparedStatement.setObject(2, null, Types.INTEGER); + assertNull(preparedStatement.parameterHandler.getParameter(2)); + assertEquals(Integer.class, preparedStatement.parameterHandler.getType(2)); + + preparedStatement.setObject(3, 456, Types.INTEGER, 0); + assertEquals(456, preparedStatement.parameterHandler.getParameter(3)); + assertEquals(Integer.class, preparedStatement.parameterHandler.getType(3)); + } + + @Test + public void testSetArray() throws Exception { + Array mockArray = mock(Array.class); + preparedStatement.setArray(1, mockArray); + assertEquals(mockArray, preparedStatement.parameterHandler.getParameter(1)); + assertEquals(Array.class, preparedStatement.parameterHandler.getType(1)); + assertEquals(StandardSQLTypeName.ARRAY, preparedStatement.parameterHandler.getSqlType(1)); + } +} diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBigQueryJDBCTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBigQueryJDBCTest.java index 47b0d0893f53..3fd1489c1afe 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBigQueryJDBCTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/it/ITBigQueryJDBCTest.java @@ -51,6 +51,7 @@ import java.sql.Statement; import java.sql.Time; import java.sql.Timestamp; +import java.sql.Types; import java.time.LocalTime; import java.util.Properties; import java.util.Random; @@ -984,11 +985,11 @@ public void testPreparedExecuteMethod() throws SQLException { String TABLE_NAME = "JDBC_PREPARED_EXECUTE_TABLE_" + randomNumber; String createQuery = String.format( - "CREATE OR REPLACE TABLE %s.%s (`StringField` STRING, `IntegerField` INTEGER);", + "CREATE OR REPLACE TABLE %s.%s (`StringField` STRING, `IntegerField` INTEGER, `ShortField` INT64, `BytesField` BYTES, `DoubleField` FLOAT64, `BooleanField` BOOL, `NullField` STRING);", DATASET, TABLE_NAME); String insertQuery = String.format( - "INSERT INTO %s.%s (StringField, IntegerField) VALUES (?,?), (?,?), (?,?), (?,?);", + "INSERT INTO %s.%s (StringField, IntegerField, ShortField, BytesField, DoubleField, BooleanField, NullField) VALUES (?,?,?,?,?,?,?), (?,?,?,?,?,?,?);", DATASET, TABLE_NAME); String updateQuery = String.format("UPDATE %s.%s SET StringField=? WHERE IntegerField=?", DATASET, TABLE_NAME); @@ -999,14 +1000,23 @@ public void testPreparedExecuteMethod() throws SQLException { assertFalse(createStatus); PreparedStatement insertStmt = bigQueryConnection.prepareStatement(insertQuery); + // Row 1: Testing setString, setInt, setShort, setBytes, setObject, setNull insertStmt.setString(1, "String1"); insertStmt.setInt(2, 111); - insertStmt.setString(3, "String2"); - insertStmt.setInt(4, 222); - insertStmt.setString(5, "String3"); - insertStmt.setInt(6, 333); - insertStmt.setString(7, "String4"); - insertStmt.setInt(8, 444); + insertStmt.setShort(3, (short) 12); + insertStmt.setBytes(4, new byte[] {0x1, 0x2}); + insertStmt.setObject(5, 3.14d); + insertStmt.setObject(6, true, Types.BOOLEAN); + insertStmt.setNull(7, Types.VARCHAR); + + // Row 2: Testing setString, setInt, setShort, setBytes, setObject, setNull with typeName + insertStmt.setString(8, "String2"); + insertStmt.setInt(9, 222); + insertStmt.setShort(10, (short) 34); + insertStmt.setBytes(11, new byte[] {0x3, 0x4}); + insertStmt.setObject(12, 6.28d); + insertStmt.setObject(13, false); + insertStmt.setNull(14, Types.VARCHAR, "STRING"); boolean insertStatus = insertStmt.execute(); assertFalse(insertStatus); From 6a9191d777b8e93ec19dd42906de474810b6e60d Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Thu, 16 Jul 2026 12:58:29 -0400 Subject: [PATCH 2/3] address commets --- .../jdbc/BigQueryJdbcTypeMappings.java | 6 +- .../jdbc/BigQueryPreparedStatement.java | 111 +++++++++--------- .../BigQueryPreparedStatementSettersTest.java | 26 +++- 3 files changed, 82 insertions(+), 61 deletions(-) diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcTypeMappings.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcTypeMappings.java index 35ac15aae3cf..648cf8fd4673 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcTypeMappings.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcTypeMappings.java @@ -80,8 +80,8 @@ class BigQueryJdbcTypeMappings { ImmutableMap.ofEntries( entry(Types.BIGINT, Long.class), entry(Types.INTEGER, Integer.class), - entry(Types.SMALLINT, Long.class), - entry(Types.TINYINT, Long.class), + entry(Types.SMALLINT, Short.class), + entry(Types.TINYINT, Byte.class), entry(Types.BOOLEAN, Boolean.class), entry(Types.DOUBLE, Double.class), entry(Types.FLOAT, Float.class), @@ -126,7 +126,7 @@ static StandardSQLTypeName classToType(Class type) } else if (JsonObject.class.isAssignableFrom(type)) { return StandardSQLTypeName.JSON; } else if (Byte.class.isAssignableFrom(type)) { - return StandardSQLTypeName.BYTES; + return StandardSQLTypeName.INT64; } else if (Array.class.isAssignableFrom(type)) { return StandardSQLTypeName.ARRAY; } else if (Struct.class.isAssignableFrom(type)) { diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java index 9a235e59d66c..12b450d044b1 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java @@ -27,6 +27,7 @@ import com.google.cloud.bigquery.TableId; import com.google.cloud.bigquery.exception.BigQueryJdbcException; import com.google.cloud.bigquery.exception.BigQueryJdbcRuntimeException; +import com.google.cloud.bigquery.exception.BigQueryJdbcSqlFeatureNotSupportedException; import com.google.cloud.bigquery.storage.v1.BatchCommitWriteStreamsRequest; import com.google.cloud.bigquery.storage.v1.BatchCommitWriteStreamsResponse; import com.google.cloud.bigquery.storage.v1.BigQueryWriteClient; @@ -117,12 +118,7 @@ public void clearParameters() { @Override public void setNull(int parameterIndex, int sqlType) throws SQLException { checkClosed(); - Class javaType; - try { - javaType = BigQueryJdbcTypeMappings.getJavaType(sqlType); - } catch (SQLException e) { - javaType = String.class; - } + Class javaType = BigQueryJdbcTypeMappings.getJavaType(sqlType); this.parameterHandler.setParameter(parameterIndex, null, javaType); } @@ -141,7 +137,7 @@ public void setByte(int parameterIndex, byte x) throws SQLException { @Override public void setShort(int parameterIndex, short x) throws SQLException { checkClosed(); - this.parameterHandler.setParameter(parameterIndex, (long) x, Long.class); + this.parameterHandler.setParameter(parameterIndex, x, Short.class); } @Override @@ -447,23 +443,24 @@ Boolean useWriteAPI() { } @Override - public void setCharacterStream(int parameterIndex, Reader reader, int length) { - // TODO :NOT IMPLEMENTED + public void setCharacterStream(int parameterIndex, Reader reader, int length) + throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setCharacterStream is not supported."); } @Override - public void setRef(int parameterIndex, Ref x) { - // TODO :NOT IMPLEMENTED + public void setRef(int parameterIndex, Ref x) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setRef is not supported."); } @Override - public void setBlob(int parameterIndex, Blob x) { - // TODO :NOT IMPLEMENTED + public void setBlob(int parameterIndex, Blob x) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setBlob is not supported."); } @Override - public void setClob(int parameterIndex, Clob x) { - // TODO :NOT IMPLEMENTED + public void setClob(int parameterIndex, Clob x) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setClob is not supported."); } @Override @@ -499,8 +496,8 @@ public void setNull(int parameterIndex, int sqlType, String typeName) throws SQL } @Override - public void setURL(int parameterIndex, URL x) { - // TODO :NOT IMPLEMENTED + public void setURL(int parameterIndex, URL x) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setURL is not supported."); } @Override @@ -510,45 +507,52 @@ public ParameterMetaData getParameterMetaData() { } @Override - public void setRowId(int parameterIndex, RowId x) { - // TODO :NOT IMPLEMENTED + public void setRowId(int parameterIndex, RowId x) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setRowId is not supported."); } @Override - public void setNString(int parameterIndex, String value) { - // TODO :NOT IMPLEMENTED + public void setNString(int parameterIndex, String value) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setNString is not supported."); } @Override - public void setNCharacterStream(int parameterIndex, Reader value, long length) { - // TODO :NOT IMPLEMENTED + public void setNCharacterStream(int parameterIndex, Reader value, long length) + throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setNCharacterStream is not supported."); } @Override - public void setNClob(int parameterIndex, NClob value) { - // TODO :NOT IMPLEMENTED + public void setNClob(int parameterIndex, NClob value) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setNClob is not supported."); } @Override - public void setClob(int parameterIndex, Reader reader, long length) { - // TODO :NOT IMPLEMENTED + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setClob is not supported."); } @Override - public void setBlob(int parameterIndex, InputStream inputStream, long length) { - // TODO :NOT IMPLEMENTED + public void setBlob(int parameterIndex, InputStream inputStream, long length) + throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setBlob is not supported."); } @Override - public void setNClob(int parameterIndex, Reader reader, long length) { - // TODO :NOT IMPLEMENTED + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setNClob is not supported."); } @Override - public void setSQLXML(int parameterIndex, SQLXML xmlObject) { - // TODO :NOT IMPLEMENTED + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setSQLXML is not supported."); } + /** + * Note: BigQuery handles numeric scale and precision dynamically for NUMERIC (DECIMAL) and + * BIGNUMERIC data types. The scaleOrLength parameter is ignored and delegates directly to {@link + * #setObject(int, Object, int)}. + */ @Override public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { @@ -557,52 +561,53 @@ public void setObject(int parameterIndex, Object x, int targetSqlType, int scale } @Override - public void setAsciiStream(int parameterIndex, InputStream x, long length) { - // TODO :NOT IMPLEMENTED + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setAsciiStream is not supported."); } @Override - public void setBinaryStream(int parameterIndex, InputStream x, long length) { - // TODO :NOT IMPLEMENTED + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setBinaryStream is not supported."); } @Override - public void setCharacterStream(int parameterIndex, Reader reader, long length) { - // TODO :NOT IMPLEMENTED + public void setCharacterStream(int parameterIndex, Reader reader, long length) + throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setCharacterStream is not supported."); } @Override - public void setAsciiStream(int parameterIndex, InputStream x) { - // TODO :NOT IMPLEMENTED + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setAsciiStream is not supported."); } @Override - public void setBinaryStream(int parameterIndex, InputStream x) { - // TODO :NOT IMPLEMENTED + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setBinaryStream is not supported."); } @Override - public void setCharacterStream(int parameterIndex, Reader reader) { - // TODO :NOT IMPLEMENTED + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setCharacterStream is not supported."); } @Override - public void setNCharacterStream(int parameterIndex, Reader value) { - // TODO :NOT IMPLEMENTED + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setNCharacterStream is not supported."); } @Override - public void setClob(int parameterIndex, Reader reader) { - // TODO :NOT IMPLEMENTED + public void setClob(int parameterIndex, Reader reader) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setClob is not supported."); } @Override - public void setBlob(int parameterIndex, InputStream inputStream) { - // TODO :NOT IMPLEMENTED + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setBlob is not supported."); } @Override - public void setNClob(int parameterIndex, Reader reader) { - // TODO :NOT IMPLEMENTED + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + throw new BigQueryJdbcSqlFeatureNotSupportedException("setNClob is not supported."); } } diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java index edf0998c5965..f9b07efabd90 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatementSettersTest.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.mock; import com.google.cloud.bigquery.StandardSQLTypeName; @@ -50,10 +51,20 @@ public void testSetNullWithSqlType() throws Exception { assertEquals(Integer.class, preparedStatement.parameterHandler.getType(2)); assertEquals(StandardSQLTypeName.INT64, preparedStatement.parameterHandler.getSqlType(2)); - preparedStatement.setNull(3, Types.NULL); + preparedStatement.setNull(3, Types.SMALLINT); assertNull(preparedStatement.parameterHandler.getParameter(3)); - assertEquals(String.class, preparedStatement.parameterHandler.getType(3)); - assertEquals(StandardSQLTypeName.STRING, preparedStatement.parameterHandler.getSqlType(3)); + assertEquals(Short.class, preparedStatement.parameterHandler.getType(3)); + assertEquals(StandardSQLTypeName.INT64, preparedStatement.parameterHandler.getSqlType(3)); + + preparedStatement.setNull(4, Types.TINYINT); + assertNull(preparedStatement.parameterHandler.getParameter(4)); + assertEquals(Byte.class, preparedStatement.parameterHandler.getType(4)); + assertEquals(StandardSQLTypeName.INT64, preparedStatement.parameterHandler.getSqlType(4)); + + preparedStatement.setNull(5, Types.NULL); + assertNull(preparedStatement.parameterHandler.getParameter(5)); + assertEquals(String.class, preparedStatement.parameterHandler.getType(5)); + assertEquals(StandardSQLTypeName.STRING, preparedStatement.parameterHandler.getSqlType(5)); } @Test @@ -64,11 +75,16 @@ public void testSetNullWithTypeName() throws Exception { assertEquals(StandardSQLTypeName.STRING, preparedStatement.parameterHandler.getSqlType(1)); } + @Test + public void testSetNullWithUnsupportedSqlTypeThrowsException() { + assertThrows(java.sql.SQLException.class, () -> preparedStatement.setNull(1, 99999)); + } + @Test public void testSetShort() throws Exception { preparedStatement.setShort(1, (short) 42); - assertEquals(42L, preparedStatement.parameterHandler.getParameter(1)); - assertEquals(Long.class, preparedStatement.parameterHandler.getType(1)); + assertEquals((short) 42, preparedStatement.parameterHandler.getParameter(1)); + assertEquals(Short.class, preparedStatement.parameterHandler.getType(1)); assertEquals(StandardSQLTypeName.INT64, preparedStatement.parameterHandler.getSqlType(1)); } From 5e3e7d059975df0bee3bbfaa221f6939760fb9eb Mon Sep 17 00:00:00 2001 From: Neenu1995 Date: Thu, 16 Jul 2026 14:10:28 -0400 Subject: [PATCH 3/3] fix short conversion --- .../bigquery/jdbc/BigQueryParameterHandler.java | 11 +++++++++++ .../jdbc/BigQueryParameterHandlerTest.java | 17 +++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandler.java b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandler.java index 9cb60177090c..026e68943cfc 100644 --- a/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandler.java +++ b/java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandler.java @@ -21,6 +21,7 @@ import com.google.cloud.bigquery.StandardSQLTypeName; import com.google.cloud.bigquery.exception.BigQueryJdbcException; import com.google.cloud.bigquery.exception.BigQueryJdbcSqlFeatureNotSupportedException; +import java.math.BigInteger; import java.sql.SQLException; import java.util.ArrayList; @@ -59,6 +60,16 @@ QueryJobConfiguration.Builder configureParameters( Object parameterValue = getParameter(i); StandardSQLTypeName sqlType = getSqlType(i); + if (parameterValue != null) { + if (sqlType == StandardSQLTypeName.INT64 + && (parameterValue instanceof Short + || parameterValue instanceof Byte + || parameterValue instanceof BigInteger)) { + parameterValue = ((Number) parameterValue).longValue(); + } else if (sqlType == StandardSQLTypeName.FLOAT64 && parameterValue instanceof Float) { + parameterValue = ((Number) parameterValue).doubleValue(); + } + } LOG.finest( "Parameter %s of type %s at index %s added to QueryJobConfiguration", parameterValue, sqlType, i); diff --git a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandlerTest.java b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandlerTest.java index 961c59ecf7b7..ab7fa7fb1c7a 100644 --- a/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandlerTest.java +++ b/java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandlerTest.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; +import com.google.cloud.bigquery.QueryJobConfiguration; import com.google.cloud.bigquery.StandardSQLTypeName; import com.google.cloud.bigquery.jdbc.BigQueryParameterHandler.BigQueryStatementParameterType; import org.junit.jupiter.api.Test; @@ -139,4 +140,20 @@ public void testGetSetParameterByIndex() throws Exception { assertEquals(String.class, paramHandler.getType(2)); assertEquals(StandardSQLTypeName.STRING, paramHandler.getSqlType(2)); } + + @Test + public void testConfigureParametersWidenNumericTypes() throws Exception { + BigQueryParameterHandler paramHandler = new BigQueryParameterHandler(3); + paramHandler.setParameter(1, (short) 5, Short.class); + paramHandler.setParameter(2, (byte) 10, Byte.class); + paramHandler.setParameter(3, 3.14f, Float.class); + + QueryJobConfiguration.Builder builder = QueryJobConfiguration.newBuilder("SELECT 1"); + paramHandler.configureParameters(builder); + + QueryJobConfiguration config = builder.build(); + assertEquals(3, config.getPositionalParameters().size()); + assertEquals("5", config.getPositionalParameters().get(0).getValue()); + assertEquals("10", config.getPositionalParameters().get(1).getValue()); + } }