Skip to content

Commit 94f7404

Browse files
authored
feat(bigquery-jdbc): implement parameter setters in PreparedStatement (#13792)
b/535194644 * **Parameter Setter Overloads (`BigQueryPreparedStatement.java`)**: * Implemented missing JDBC parameter setters: `setShort`, `setByte`, `setInt`, `setLong`, `setFloat`, `setDouble`, `setBigDecimal`, `setBoolean`, `setString`, `setBytes`, `setObject`, and `setNull`. * Delegates parameter binding to `BigQueryParameterHandler` with correct Java type metadata. * **Transport-Layer Value Widening (`BigQueryParameterHandler.java`)**: * Added value widening in `configureParameters(...)` when constructing `QueryParameterValue`: * Widens `Short`, `Byte`, and `BigInteger` $\rightarrow$ `Long` for `StandardSQLTypeName.INT64`. * Widens `Float` $\rightarrow$ `Double` for `StandardSQLTypeName.FLOAT64`. * Resolves runtime `IllegalArgumentException: Type INT64 incompatible with java.lang.Short` during query execution. * **JDBC Metadata Preservation (`BigQueryJdbcTypeMappings.java`)**: * Retained standard mappings (`Types.SMALLINT` $\rightarrow$ `java.lang.Short`, `Types.TINYINT` $\rightarrow$ `java.lang.Byte`). * Ensures `ParameterMetaData.getParameterClassName()` remains 100% compliant with JDBC standards.
1 parent acff1f2 commit 94f7404

6 files changed

Lines changed: 286 additions & 79 deletions

File tree

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryJdbcTypeMappings.java

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class BigQueryJdbcTypeMappings {
8080
ImmutableMap.ofEntries(
8181
entry(Types.BIGINT, Long.class),
8282
entry(Types.INTEGER, Integer.class),
83+
entry(Types.SMALLINT, Short.class),
84+
entry(Types.TINYINT, Byte.class),
8385
entry(Types.BOOLEAN, Boolean.class),
8486
entry(Types.DOUBLE, Double.class),
8587
entry(Types.FLOAT, Float.class),
@@ -94,42 +96,37 @@ class BigQueryJdbcTypeMappings {
9496
entry(Types.VARBINARY, byte[].class),
9597
entry(Types.STRUCT, Struct.class),
9698
entry(Types.BIT, Boolean.class),
97-
entry(Types.ARRAY, Array.class));
99+
entry(Types.ARRAY, Array.class),
100+
entry(Types.NULL, String.class));
98101

99102
static StandardSQLTypeName classToType(Class type)
100103
throws BigQueryJdbcSqlFeatureNotSupportedException {
101104
if (Boolean.class.isAssignableFrom(type)) {
102105
return StandardSQLTypeName.BOOL;
103106
} else if (String.class.isAssignableFrom(type)) {
104107
return StandardSQLTypeName.STRING;
105-
} else if (String.class.isAssignableFrom(type)) {
106-
return StandardSQLTypeName.GEOGRAPHY;
107-
} else if (String.class.isAssignableFrom(type)) {
108-
return StandardSQLTypeName.DATETIME;
109108
} else if (Integer.class.isAssignableFrom(type)) {
110109
return StandardSQLTypeName.INT64;
111110
} else if (Long.class.isAssignableFrom(type)) {
112111
return StandardSQLTypeName.INT64;
112+
} else if (Short.class.isAssignableFrom(type)) {
113+
return StandardSQLTypeName.INT64;
113114
} else if (Double.class.isAssignableFrom(type)) {
114115
return StandardSQLTypeName.FLOAT64;
115116
} else if (Float.class.isAssignableFrom(type)) {
116117
return StandardSQLTypeName.FLOAT64;
117118
} else if (BigDecimal.class.isAssignableFrom(type)) {
118119
return StandardSQLTypeName.NUMERIC;
119-
} else if (BigDecimal.class.isAssignableFrom(type)) {
120-
return StandardSQLTypeName.BIGNUMERIC;
121120
} else if (Date.class.isAssignableFrom(type)) {
122121
return StandardSQLTypeName.DATE;
123122
} else if (Timestamp.class.isAssignableFrom(type)) {
124123
return StandardSQLTypeName.TIMESTAMP;
125124
} else if (Time.class.isAssignableFrom(type)) {
126125
return StandardSQLTypeName.TIME;
127-
} else if (String.class.isAssignableFrom(type)) {
128-
return StandardSQLTypeName.JSON;
129126
} else if (JsonObject.class.isAssignableFrom(type)) {
130127
return StandardSQLTypeName.JSON;
131128
} else if (Byte.class.isAssignableFrom(type)) {
132-
return StandardSQLTypeName.BYTES;
129+
return StandardSQLTypeName.INT64;
133130
} else if (Array.class.isAssignableFrom(type)) {
134131
return StandardSQLTypeName.ARRAY;
135132
} else if (Struct.class.isAssignableFrom(type)) {

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandler.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.google.cloud.bigquery.StandardSQLTypeName;
2222
import com.google.cloud.bigquery.exception.BigQueryJdbcException;
2323
import com.google.cloud.bigquery.exception.BigQueryJdbcSqlFeatureNotSupportedException;
24+
import java.math.BigInteger;
2425
import java.sql.SQLException;
2526
import java.util.ArrayList;
2627

@@ -59,6 +60,16 @@ QueryJobConfiguration.Builder configureParameters(
5960

6061
Object parameterValue = getParameter(i);
6162
StandardSQLTypeName sqlType = getSqlType(i);
63+
if (parameterValue != null) {
64+
if (sqlType == StandardSQLTypeName.INT64
65+
&& (parameterValue instanceof Short
66+
|| parameterValue instanceof Byte
67+
|| parameterValue instanceof BigInteger)) {
68+
parameterValue = ((Number) parameterValue).longValue();
69+
} else if (sqlType == StandardSQLTypeName.FLOAT64 && parameterValue instanceof Float) {
70+
parameterValue = ((Number) parameterValue).doubleValue();
71+
}
72+
}
6273
LOG.finest(
6374
"Parameter %s of type %s at index %s added to QueryJobConfiguration",
6475
parameterValue, sqlType, i);

java-bigquery-jdbc/src/main/java/com/google/cloud/bigquery/jdbc/BigQueryPreparedStatement.java

Lines changed: 92 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.google.cloud.bigquery.TableId;
2828
import com.google.cloud.bigquery.exception.BigQueryJdbcException;
2929
import com.google.cloud.bigquery.exception.BigQueryJdbcRuntimeException;
30+
import com.google.cloud.bigquery.exception.BigQueryJdbcSqlFeatureNotSupportedException;
3031
import com.google.cloud.bigquery.storage.v1.BatchCommitWriteStreamsRequest;
3132
import com.google.cloud.bigquery.storage.v1.BatchCommitWriteStreamsResponse;
3233
import com.google.cloud.bigquery.storage.v1.BigQueryWriteClient;
@@ -55,6 +56,7 @@
5556
import java.sql.SQLXML;
5657
import java.sql.Time;
5758
import java.sql.Timestamp;
59+
import java.sql.Types;
5860
import java.util.ArrayList;
5961
import java.util.Arrays;
6062
import java.util.Calendar;
@@ -114,8 +116,10 @@ public void clearParameters() {
114116
}
115117

116118
@Override
117-
public void setNull(int parameterIndex, int sqlType) {
118-
// TODO(neenu): implement null case
119+
public void setNull(int parameterIndex, int sqlType) throws SQLException {
120+
checkClosed();
121+
Class<?> javaType = BigQueryJdbcTypeMappings.getJavaType(sqlType);
122+
this.parameterHandler.setParameter(parameterIndex, null, javaType);
119123
}
120124

121125
@Override
@@ -131,8 +135,9 @@ public void setByte(int parameterIndex, byte x) throws SQLException {
131135
}
132136

133137
@Override
134-
public void setShort(int parameterIndex, short x) {
135-
// TODO(neenu): implement Bytes conversion.
138+
public void setShort(int parameterIndex, short x) throws SQLException {
139+
checkClosed();
140+
this.parameterHandler.setParameter(parameterIndex, x, Short.class);
136141
}
137142

138143
@Override
@@ -172,8 +177,9 @@ public void setString(int parameterIndex, String x) throws SQLException {
172177
}
173178

174179
@Override
175-
public void setBytes(int parameterIndex, byte[] x) {
176-
// TODO(neenu): implement Bytes conversion.
180+
public void setBytes(int parameterIndex, byte[] x) throws SQLException {
181+
checkClosed();
182+
this.parameterHandler.setParameter(parameterIndex, x, byte[].class);
177183
}
178184

179185
@Override
@@ -218,11 +224,24 @@ public void setBinaryStream(int parameterIndex, InputStream x, int length) {
218224
}
219225

220226
@Override
221-
public void setObject(int parameterIndex, Object x, int targetSqlType) {}
227+
public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException {
228+
checkClosed();
229+
if (x == null) {
230+
setNull(parameterIndex, targetSqlType);
231+
return;
232+
}
233+
Class<?> javaType = BigQueryJdbcTypeMappings.getJavaType(targetSqlType);
234+
this.parameterHandler.setParameter(parameterIndex, x, javaType);
235+
}
222236

223237
@Override
224-
public void setObject(int parameterIndex, Object x) {
225-
// TODO :NOT IMPLEMENTED
238+
public void setObject(int parameterIndex, Object x) throws SQLException {
239+
checkClosed();
240+
if (x == null) {
241+
setNull(parameterIndex, Types.NULL);
242+
return;
243+
}
244+
this.parameterHandler.setParameter(parameterIndex, x, x.getClass());
226245
}
227246

228247
@Override
@@ -424,28 +443,30 @@ Boolean useWriteAPI() {
424443
}
425444

426445
@Override
427-
public void setCharacterStream(int parameterIndex, Reader reader, int length) {
428-
// TODO :NOT IMPLEMENTED
446+
public void setCharacterStream(int parameterIndex, Reader reader, int length)
447+
throws SQLException {
448+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setCharacterStream is not supported.");
429449
}
430450

431451
@Override
432-
public void setRef(int parameterIndex, Ref x) {
433-
// TODO :NOT IMPLEMENTED
452+
public void setRef(int parameterIndex, Ref x) throws SQLException {
453+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setRef is not supported.");
434454
}
435455

436456
@Override
437-
public void setBlob(int parameterIndex, Blob x) {
438-
// TODO :NOT IMPLEMENTED
457+
public void setBlob(int parameterIndex, Blob x) throws SQLException {
458+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setBlob is not supported.");
439459
}
440460

441461
@Override
442-
public void setClob(int parameterIndex, Clob x) {
443-
// TODO :NOT IMPLEMENTED
462+
public void setClob(int parameterIndex, Clob x) throws SQLException {
463+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setClob is not supported.");
444464
}
445465

446466
@Override
447-
public void setArray(int parameterIndex, Array x) {
448-
// TODO(neenu) :IMPLEMENT ARRAY
467+
public void setArray(int parameterIndex, Array x) throws SQLException {
468+
checkClosed();
469+
this.parameterHandler.setParameter(parameterIndex, x, Array.class);
449470
}
450471

451472
@Override
@@ -470,13 +491,13 @@ public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) {
470491
}
471492

472493
@Override
473-
public void setNull(int parameterIndex, int sqlType, String typeName) {
474-
// TODO :NOT IMPLEMENTED
494+
public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
495+
setNull(parameterIndex, sqlType);
475496
}
476497

477498
@Override
478-
public void setURL(int parameterIndex, URL x) {
479-
// TODO :NOT IMPLEMENTED
499+
public void setURL(int parameterIndex, URL x) throws SQLException {
500+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setURL is not supported.");
480501
}
481502

482503
@Override
@@ -486,97 +507,107 @@ public ParameterMetaData getParameterMetaData() {
486507
}
487508

488509
@Override
489-
public void setRowId(int parameterIndex, RowId x) {
490-
// TODO :NOT IMPLEMENTED
510+
public void setRowId(int parameterIndex, RowId x) throws SQLException {
511+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setRowId is not supported.");
491512
}
492513

493514
@Override
494-
public void setNString(int parameterIndex, String value) {
495-
// TODO :NOT IMPLEMENTED
515+
public void setNString(int parameterIndex, String value) throws SQLException {
516+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setNString is not supported.");
496517
}
497518

498519
@Override
499-
public void setNCharacterStream(int parameterIndex, Reader value, long length) {
500-
// TODO :NOT IMPLEMENTED
520+
public void setNCharacterStream(int parameterIndex, Reader value, long length)
521+
throws SQLException {
522+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setNCharacterStream is not supported.");
501523
}
502524

503525
@Override
504-
public void setNClob(int parameterIndex, NClob value) {
505-
// TODO :NOT IMPLEMENTED
526+
public void setNClob(int parameterIndex, NClob value) throws SQLException {
527+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setNClob is not supported.");
506528
}
507529

508530
@Override
509-
public void setClob(int parameterIndex, Reader reader, long length) {
510-
// TODO :NOT IMPLEMENTED
531+
public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
532+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setClob is not supported.");
511533
}
512534

513535
@Override
514-
public void setBlob(int parameterIndex, InputStream inputStream, long length) {
515-
// TODO :NOT IMPLEMENTED
536+
public void setBlob(int parameterIndex, InputStream inputStream, long length)
537+
throws SQLException {
538+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setBlob is not supported.");
516539
}
517540

518541
@Override
519-
public void setNClob(int parameterIndex, Reader reader, long length) {
520-
// TODO :NOT IMPLEMENTED
542+
public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
543+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setNClob is not supported.");
521544
}
522545

523546
@Override
524-
public void setSQLXML(int parameterIndex, SQLXML xmlObject) {
525-
// TODO :NOT IMPLEMENTED
547+
public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
548+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setSQLXML is not supported.");
526549
}
527550

551+
/**
552+
* Note: BigQuery handles numeric scale and precision dynamically for NUMERIC (DECIMAL) and
553+
* BIGNUMERIC data types. The scaleOrLength parameter is ignored and delegates directly to {@link
554+
* #setObject(int, Object, int)}.
555+
*/
528556
@Override
529-
public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) {
530-
// TODO(neenu) : IMPLEMENT?
557+
public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength)
558+
throws SQLException {
559+
checkClosed();
560+
setObject(parameterIndex, x, targetSqlType);
531561
}
532562

533563
@Override
534-
public void setAsciiStream(int parameterIndex, InputStream x, long length) {
535-
// TODO :NOT IMPLEMENTED
564+
public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
565+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setAsciiStream is not supported.");
536566
}
537567

538568
@Override
539-
public void setBinaryStream(int parameterIndex, InputStream x, long length) {
540-
// TODO :NOT IMPLEMENTED
569+
public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
570+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setBinaryStream is not supported.");
541571
}
542572

543573
@Override
544-
public void setCharacterStream(int parameterIndex, Reader reader, long length) {
545-
// TODO :NOT IMPLEMENTED
574+
public void setCharacterStream(int parameterIndex, Reader reader, long length)
575+
throws SQLException {
576+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setCharacterStream is not supported.");
546577
}
547578

548579
@Override
549-
public void setAsciiStream(int parameterIndex, InputStream x) {
550-
// TODO :NOT IMPLEMENTED
580+
public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
581+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setAsciiStream is not supported.");
551582
}
552583

553584
@Override
554-
public void setBinaryStream(int parameterIndex, InputStream x) {
555-
// TODO :NOT IMPLEMENTED
585+
public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
586+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setBinaryStream is not supported.");
556587
}
557588

558589
@Override
559-
public void setCharacterStream(int parameterIndex, Reader reader) {
560-
// TODO :NOT IMPLEMENTED
590+
public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
591+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setCharacterStream is not supported.");
561592
}
562593

563594
@Override
564-
public void setNCharacterStream(int parameterIndex, Reader value) {
565-
// TODO :NOT IMPLEMENTED
595+
public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException {
596+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setNCharacterStream is not supported.");
566597
}
567598

568599
@Override
569-
public void setClob(int parameterIndex, Reader reader) {
570-
// TODO :NOT IMPLEMENTED
600+
public void setClob(int parameterIndex, Reader reader) throws SQLException {
601+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setClob is not supported.");
571602
}
572603

573604
@Override
574-
public void setBlob(int parameterIndex, InputStream inputStream) {
575-
// TODO :NOT IMPLEMENTED
605+
public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
606+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setBlob is not supported.");
576607
}
577608

578609
@Override
579-
public void setNClob(int parameterIndex, Reader reader) {
580-
// TODO :NOT IMPLEMENTED
610+
public void setNClob(int parameterIndex, Reader reader) throws SQLException {
611+
throw new BigQueryJdbcSqlFeatureNotSupportedException("setNClob is not supported.");
581612
}
582613
}

java-bigquery-jdbc/src/test/java/com/google/cloud/bigquery/jdbc/BigQueryParameterHandlerTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static org.junit.jupiter.api.Assertions.assertEquals;
2020
import static org.junit.jupiter.api.Assertions.assertNotNull;
2121

22+
import com.google.cloud.bigquery.QueryJobConfiguration;
2223
import com.google.cloud.bigquery.StandardSQLTypeName;
2324
import com.google.cloud.bigquery.jdbc.BigQueryParameterHandler.BigQueryStatementParameterType;
2425
import org.junit.jupiter.api.Test;
@@ -139,4 +140,20 @@ public void testGetSetParameterByIndex() throws Exception {
139140
assertEquals(String.class, paramHandler.getType(2));
140141
assertEquals(StandardSQLTypeName.STRING, paramHandler.getSqlType(2));
141142
}
143+
144+
@Test
145+
public void testConfigureParametersWidenNumericTypes() throws Exception {
146+
BigQueryParameterHandler paramHandler = new BigQueryParameterHandler(3);
147+
paramHandler.setParameter(1, (short) 5, Short.class);
148+
paramHandler.setParameter(2, (byte) 10, Byte.class);
149+
paramHandler.setParameter(3, 3.14f, Float.class);
150+
151+
QueryJobConfiguration.Builder builder = QueryJobConfiguration.newBuilder("SELECT 1");
152+
paramHandler.configureParameters(builder);
153+
154+
QueryJobConfiguration config = builder.build();
155+
assertEquals(3, config.getPositionalParameters().size());
156+
assertEquals("5", config.getPositionalParameters().get(0).getValue());
157+
assertEquals("10", config.getPositionalParameters().get(1).getValue());
158+
}
142159
}

0 commit comments

Comments
 (0)