spotify/dbeam

Handling of unsigned int fields in MySQL

robwil opened this issue · 3 comments

I think the computeMapping function does not properly handle unsigned int fields in MySQL. It winds up calling .getInt(..) on a value that may be greater than the int max due to having unsigned only values in it.

https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-type-conversions.html seems to suggest that GetColumnClassName rather than GetColumnTypeName will return the correct type (long instead of int) for these cases, but I have not been able to confirm that.

Example error:

java.sql.SQLDataException: Value '2190526558' is outside of valid range for type java.lang.Integer 
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:114) 
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:97) 
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:89) 
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:63) 
com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:73) 
com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:92) 
com.mysql.cj.jdbc.result.ResultSetImpl.getObject(ResultSetImpl.java:1382) 
com.mysql.cj.jdbc.result.ResultSetImpl.getInt(ResultSetImpl.java:786) 
com.spotify.dbeam.avro.JdbcAvroRecord.lambda$computeMapping$3(JdbcAvroRecord.java:96)

Just noting a workaround if anyone else has this problem, you can define a VIEW that does a CAST(field AS UNSIGNED INTEGER) as field which will cause MySQL to return it as a BIGINT, which will be properly treated as a Long by DBeam.

@robwil What is a native MySQL column type in your case? I assume [int unsigned].

@rulle-io yes, exactly. The MySQL column type is int unsigned. In the CREATE TABLE, it shows as int(10) unsigned to be exact.