Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FBClob doesn't implement length() method [JDBC270] #317

Closed
firebird-automations opened this issue Aug 23, 2012 · 6 comments
Closed

FBClob doesn't implement length() method [JDBC270] #317

firebird-automations opened this issue Aug 23, 2012 · 6 comments

Comments

@firebird-automations
Copy link

Submitted by: Sebastian Bösl (sboesl)

Assigned to: Roman Rokytskyy (rrokytskyy)

Votes: 1

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();
}

@firebird-automations
Copy link
Author

Commented by: Roman Rokytskyy (rrokytskyy)

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.

@firebird-automations
Copy link
Author

Commented by: Sebastian Bösl (sboesl)

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

@firebird-automations
Copy link
Author

Commented by: @mrotteveel

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

@firebird-automations
Copy link
Author

Commented by: Pablo León (palevi)

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

@firebird-automations
Copy link
Author

Commented by: @mrotteveel

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).

@firebird-automations
Copy link
Author

Modified by: @mrotteveel

status: Open [ 1 ] => Closed [ 6 ]

resolution: Won't Fix [ 2 ]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant