Issue Details (XML | Word | Printable)

Key: JDBC-270
Type: Bug Bug
Status: Open Open
Priority: Minor Minor
Assignee: Roman Rokytskyy
Reporter: Sebastian Bösl
Votes: 1
Watchers: 1
Operations

If you were logged in you would be able to see more operations.
Jaybird JCA/JDBC Driver

FBClob doesn't implement length() method

Created: 23/Aug/12 07:55 AM   Updated: 21/Feb/17 12:07 PM
Component/s: JDBC driver
Affects Version/s: Jaybird 2.2
Fix Version/s: None


 Description  « Hide
Hibernate 4.1 uses the FBClob.length() method when reading Clobs from the database, in the current version of Jaybird the method throws a FBDriverNotCapableException which Hibernate can't handle.

I've fixed the problem by implementing the method as follows (though I don't know if it's 100% correct:
public long length() throws SQLException {
String encoding = getWrappedBlob().gdsHelper.getJavaEncoding();
if (encoding != null) {
float bytePerChar = Charset.forName(encoding).newDecoder().averageCharsPerByte();
return (long)(getWrappedBlob().length() * bytePerChar);
}
return getWrappedBlob().length();
}

 All   Comments   Change History   Subversion Commits      Sort Order: Ascending order - Click to sort in descending order
Roman Rokytskyy added a comment - 23/Aug/12 09:02 AM
It is correct re. how to call the underlying FBBlob instance, but the result you get will not be precise - the average chars per byte won't work with UTF-8. That is the reason why I did not implement the method.

Sebastian Bösl added a comment - 23/Aug/12 09:19 AM
I see.
For the purpose of hibernate it's not necessary to be precise since the value is only used as a hint for the buffer size, so even a constant value would have worked for me.
The reason I opened this issue was that I would prefer an official solution for the sake of future updates.
So if the issue will be handled in the 2.3 version I won't mind if you close this ticket

Mark Rotteveel added a comment - 25/Aug/12 07:31 AM
JDBC does not require this method to be implemented: http://docs.oracle.com/javase/7/docs/api/java/sql/Clob.html#length() :
SQLFeatureNotSupportedException - if the JDBC driver does not support this method. FBDriverNotCapableException extends SQLFeatureNotSupportedException (in the Java 6 and 7 version of Jaybird).

Maybe there are other drivers out there that do the same, so maybe it is wise to handle the exception generically

Pablo León added a comment - 20/Feb/17 01:57 PM
This is also causing problems with Mybatis 3.4.x (3.3.x and previous where working ok):

Error querying database. Cause: org.apache.ibatis.executor.result.ResultMapException: Error attempting to get column 'DIRECCION' from result set. Cause: org.firebirdsql.jdbc.FBDriverNotCapableException: Cannot determine length for CLOB

Mark Rotteveel added a comment - 21/Feb/17 12:07 PM
Unfortunately it is impossible to do this correctly with UTF8 (without reading the entire blob). And as this is an optional JDBC method, you'll need to ask MyBatis if they really need this method.

More curiously though, Jaybird handles a BLOB SUB_TYPE TEXT primarily as a longvarchar, and java.sql.Clob is actually just supported as a fallback; however according to https://github.com/mybatis/mybatis-3/blob/master/src/main/java/org/apache/ibatis/type/TypeHandlerRegistry.java#L91 the LONGVARCHAR handling is mapped to ClobTypeHandler, instead of the StringTypeHandler or maybe the ClobReaderTypeHandler.

The ClobTypeHandler (https://github.com/mybatis/mybatis-3/blob/master/src/main/java/org/apache/ibatis/type/ClobTypeHandler.java) obtains a string using:

  public String getNullableResult(ResultSet rs, int columnIndex)
      throws SQLException {
    String value = "";
    Clob clob = rs.getClob(columnIndex);
    if (clob != null) {
      int size = (int) clob.length();
      value = clob.getSubString(1, size);
    }
    return value;
}

The workaround is to configure an alternative type handler (eg the StringTypeHandler).