Google BigQuery, Exception thrown for null value in prepared statement

Viewed 449

We are trying to load data to google bigquery using Jdbc (Simba driver). When trying to insert a null value in a prepared statement, we are getting an exception. This works when it is not a prepared statement. For example, the code (with the connection Url hidden):

import java.sql.*;

public class Program {

    public static void main(String[] args) {
        Program program = new Program();
        try {
            program.doStatement();
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            program.doPreparedStatement();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

   

    public Program() {}

    public void doPreparedStatement() throws Exception {
         try(Connection connection = getConnection()) {
            
            PreparedStatement statement = connection.prepareStatement("INSERT INTO test1.my_table (CONTACT, COMPANY, ADDRESS, CITY, STATE, ZIP) VALUES (?,?,?,?,?,?)");
            statement.setString(1, "MyContact");
            statement.setString(2, "MyCompany");
            statement.setString(3, "MyAddress");
            statement.setString(4, "MyCity");
            statement.setString(5, "MyState");
            statement.setNull(6, Types.BIGINT);
            System.err.println("Executing prepared statement...");
           int count = statement.executeUpdate();
        }
        System.err.println(" done.");
    }

    public void doStatement() throws Exception {
        try(Connection connection = getConnection()) {
            String create_command = 
                "CREATE TABLE test1.my_table ( CONTACT STRING, COMPANY STRING, ADDRESS STRING, CITY STRING, STATE STRING, ZIP STRING )";
            Statement createStatement = connection.createStatement( );
            System.err.println("Create table.");
            createStatement.execute(create_command);
            System.err.println("Table created.");
            
            System.err.println("Executing statement...");
            Statement statement = connection.createStatement();
            int count = statement.executeUpdate("INSERT INTO test1.my_table (CONTACT, COMPANY, ADDRESS, CITY, STATE, ZIP) VALUES ('MyContact','MyCompany','MyAddress','MyCity','MyState',NULL)");
        }
        System.err.println(" done.");
    }

    private Connection getConnection() throws Exception
    {
        Connection connection = null;
        connection = DriverManager.getConnection(CONNECTION_URL);
        return connection;
    }


}

Produces the following output:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

Create table.

Table created.

Executing statement...

 done.

Executing prepared statement...

java.sql.SQLException: [Simba][BigQueryJDBCDriver](100032) Error executing query job. Message: Unparseable query parameter `` in type `TYPE_INT64`, Bad int64 value: null value: 'null'
        at com.simba.googlebigquery.googlebigquery.client.BQClient.insertJob(Unknown Source)
        at com.simba.googlebigquery.googlebigquery.client.BQClient.executeQuery(Unknown Source)
        at com.simba.googlebigquery.googlebigquery.dataengine.BQAbstractExecutor.execute(Unknown Source)
        at com.simba.googlebigquery.googlebigquery.dataengine.BQSQLExecutor.execute(Unknown Source)
        at com.simba.googlebigquery.jdbc.common.SPreparedStatement.executeWithParams(Unknown Source)
        at com.simba.googlebigquery.jdbc.common.SPreparedStatement.executeAnyUpdate(Unknown Source)
        at com.simba.googlebigquery.jdbc.common.SPreparedStatement.executeUpdate(Unknown Source)
        at Program.doPreparedStatement(Program.java:35)
Caused by: com.simba.googlebigquery.support.exceptions.GeneralException: [Simba][BigQueryJDBCDriver](100032) Error executing query job. Message: Unparseable query parameter `` in type `TYPE_INT64`, Bad int64 value: null value: 'null'
        ... 8 more
1 Answers

I've found this to work when adding BigQuery support to jOOQ (see e.g. #11841), for numeric types:

statement.setBigDecimal(6, null);

The BigDecimal type is the only numeric JDBC type that is not primitive. For other data types, use their respective setter if it is supported, or setString(6, null), if Simba still doesn't like NULL values for the respective type, including e.g.:

  • Boolean
  • Date
  • Time

If in doubt about any conversion problems (e.g. because Simba seems to bind BigDecimal as STRING, currently, at least in version 1.2.13.1016), make sure you cast the bind variable, e.g.:

CAST(? AS INT64)
Related