2121import static org .junit .jupiter .api .Assertions .assertNotNull ;
2222import static org .junit .jupiter .api .Assertions .assertNull ;
2323import static org .junit .jupiter .api .Assertions .assertThrows ;
24+ import static org .junit .jupiter .api .Assertions .assertTrue ;
2425import static org .mockito .Mockito .mock ;
26+ import static org .mockito .Mockito .when ;
2527
2628import com .google .cloud .bigquery .Field ;
29+ import com .google .cloud .bigquery .FieldList ;
30+ import com .google .cloud .bigquery .QueryJobConfiguration ;
2731import com .google .cloud .bigquery .Schema ;
2832import com .google .cloud .bigquery .StandardSQLTypeName ;
33+ import com .google .gson .Gson ;
34+ import com .google .gson .JsonNull ;
35+ import com .google .gson .JsonObject ;
2936import java .sql .Array ;
3037import java .sql .Date ;
3138import java .sql .ParameterMetaData ;
3845import java .time .LocalDate ;
3946import java .time .LocalDateTime ;
4047import java .time .LocalTime ;
48+ import java .util .ArrayList ;
4149import java .util .Calendar ;
4250import java .util .TimeZone ;
4351import org .junit .jupiter .api .BeforeEach ;
@@ -51,6 +59,7 @@ public class BigQueryPreparedStatementSettersTest {
5159 @ BeforeEach
5260 public void setUp () throws Exception {
5361 connection = mock (BigQueryConnection .class );
62+ when (connection .getQueryDialect ()).thenReturn ("SQL" );
5463 preparedStatement = new BigQueryPreparedStatement (connection , "SELECT ?, ?, ?, ?, ?" );
5564 }
5665
@@ -269,4 +278,51 @@ public void testSetObjectWithJavaTime() throws Exception {
269278 preparedStatement .setObject (4 , instant );
270279 assertEquals (Timestamp .class , preparedStatement .parameterHandler .getType (4 ));
271280 }
281+
282+ // Verifies standard DML QueryJobConfiguration creates positional parameters with null values when
283+ // setObject is called with null.
284+ @ Test
285+ public void testBatchJobConfigurationWithSetObjectNull () throws Exception {
286+ preparedStatement .setObject (1 , null );
287+ preparedStatement .setInt (2 , 42 );
288+ preparedStatement .setString (3 , "test" );
289+ preparedStatement .setDouble (4 , 3.14 );
290+ preparedStatement .setBoolean (5 , true );
291+ preparedStatement .addBatch ();
292+
293+ ArrayList <BigQueryJdbcParameter > batchParams =
294+ preparedStatement .parameterHandler .parametersList ;
295+ QueryJobConfiguration config = preparedStatement .getWriteBatchJobConfiguration (batchParams );
296+ assertNotNull (config );
297+ assertEquals (5 , config .getPositionalParameters ().size ());
298+ assertNull (config .getPositionalParameters ().get (0 ).getValue ());
299+ assertEquals (StandardSQLTypeName .STRING , config .getPositionalParameters ().get (0 ).getType ());
300+ }
301+
302+ // Verifies Storage Write API JSON row serialization maps null parameter values to
303+ // JsonNull.INSTANCE.
304+ @ Test
305+ public void testCreateJsonRowWithSetObjectNull () throws Exception {
306+ preparedStatement .setObject (1 , null );
307+ preparedStatement .setInt (2 , 42 );
308+ preparedStatement .setString (3 , "test" );
309+ preparedStatement .setDouble (4 , 3.14 );
310+ preparedStatement .setBoolean (5 , true );
311+
312+ FieldList fieldList =
313+ FieldList .of (
314+ Field .of ("col1" , StandardSQLTypeName .STRING ),
315+ Field .of ("col2" , StandardSQLTypeName .INT64 ),
316+ Field .of ("col3" , StandardSQLTypeName .STRING ),
317+ Field .of ("col4" , StandardSQLTypeName .FLOAT64 ),
318+ Field .of ("col5" , StandardSQLTypeName .BOOL ));
319+
320+ ArrayList <BigQueryJdbcParameter > params = preparedStatement .parameterHandler .parametersList ;
321+ JsonObject jsonRow = BigQueryPreparedStatement .createJsonRow (fieldList , params , new Gson ());
322+
323+ assertNotNull (jsonRow );
324+ assertEquals (JsonNull .INSTANCE , jsonRow .get ("col1" ));
325+ assertTrue (jsonRow .get ("col1" ).isJsonNull ());
326+ assertEquals ("42" , jsonRow .get ("col2" ).getAsString ());
327+ }
272328}
0 commit comments