Closed Saisimon closed 5 years ago
How to deal with if byte[]' size > 1?
The ResultSetUtil#convertByteArrayValue method references to MySQL JDBC driver 5.1 version, it just checks first of byte array.In 8.0 version, it changes to byte array -> long -> boolean, you can find the implement in here, I’m not sure which way is better, what do you think? BTW, this method has only been verified in the MySQL database, I don't have an environment for other databases.
For other database it is a problem, could you verify for other database too?
OK. I'll verify it, when I have time.
Because the pr #2607 is not sure for all databases of jdbc, it is a risk here, so may I revert this pr until this issue solve totally?
it`s ok
ok, revert it and hope you solve totally later.
@terrymanu this issue should assigns to @tuohai666 , because #2467 causes this issue.
If you can't fix, just unassign this issue from you.
As we know, MySQL does not have built-in Boolean type. However, it uses TINYINT(1) instead. To make it more convenient, MySQL provides BOOLEAN or BOOL as the synonym of TINYINT(1) . In MySQL, zero is considered as false, and non-zero value is considered as true.
Convert BIT to Boolean is abuse, BIT is for binary value, not boolean value. I suggest that you change the column type from BIT to TINYINT.
Convert BIT to Boolean is abuse, BIT is for binary value, not boolean value. I suggest that you change the column type from BIT to TINYINT.
change to TINYINT(1) also throws java.lang.ClassCastException: [B cannot be cast to java.lang.Boolean change to TINYINT(2) throws org.apache.shardingsphere.core.exception.ShardingException: Unsupported data type:boolean
Get it. Can you help to test whether this change works?
If there's no problem, you can submit a pull request instead of the previous one. This change will not lead to side effect.
Compilation failure.
case "boolean":
return 0 != number.longValue()
it only fixes the case of tinyint(2).
Sorry, codes should like this:
case "boolean":
return 0 != number.byteValue()
Don't need no support tinyint(2), only support tinyint(1).
no fix, because mysql driver treats tinyint(1) as bit type, the value always returns a byte array, never jumps to convertNumberValue method.
The previous pull requst convert byte[] to boolean, but have been reverted. Are there any other solutions? What do you think? If the value can't converted in sharding-jdbc finally, you may convert it in your service codes without getBoolean().
It was restored because it only works with mysql and sql server and does not support postgresql. In postgresql, 116 is true and the other numbers are false. I think there are two ways to solve this problem:
But both ways will make a lot of changes.
In my opinion, the purpose of JDBC
is resolve different databases's compatibility. so ResultSet
defined some method like getBytes()
, getBoolean()
and etc to help us get object with expected java type.
ShardingSphere
work on dataSource, and defined ResultSet
too, like ShardingResultSet
and EncryptResultSet
. but ShardingSphere
use database column type in place of expected java type.
There are some codes in StreamQueryResult
, we can see getValue()
do nothing with final Class<?> type
.
@Override
public Object getValue(final int columnIndex, final Class<?> type) throws SQLException {
return decrypt(columnIndex, QueryResultUtil.getValue(resultSet, columnIndex));
}
And in QueryResultUtil
, getValueByColumnType()
get database column type from resultSet. metaData
and use it for getXXX()
selection.
public static Object getValueByColumnType(final ResultSet resultSet, final int columnIndex) throws SQLException {
ResultSetMetaData metaData = resultSet.getMetaData();
switch (metaData.getColumnType(columnIndex)) {
case Types.BIT:
return resultSet.getBytes(columnIndex);
case Types.BOOLEAN:
return resultSet.getBoolean(columnIndex);
case Types.TINYINT:
return resultSet.getByte(columnIndex);
...
}
}
Usually it's okay, but when we use mysql and call some special methods such as getBoolean()
, our expected java type is boolean, database column type is not boolean.
so I think we should pass on the expected java type, and use it for getXXX()
selection.
Can I send a PR ?
@Saisimon Do you want to have a try to resolve this problem completely?
It was restored because it only works with mysql and sql server and does not support postgresql. In postgresql, 116 is true and the other numbers are false. I think there are two ways to solve this problem:
- QueryResultUtil#getValueByColumnType() adds a convertType class param, which is converted directly to the correct field type here.
- Provide different conversion methods according to different databases.
But both ways will make a lot of changes.
OK
Bug Report
For English only, other languages will not accept.
Before report a bug, make sure you have:
Please pay attention on issues you submitted, because we maybe need more details. If no response more than 7 days and we cannot reproduce it on current information, we will close it.
Please answer these questions before submitting your issue. Thanks!
Which version of ShardingSphere did you use?
4.0.0-RC2-SNAPSHOT,4.0.0-RC1 version work well
Which project did you use? Sharding-JDBC or Sharding-Proxy?
Sharding-JDBC
Expected behavior
Work well
Actual behavior
throw java.lang.ClassCastException: [B cannot be cast to java.lang.Boolean
Reason analyze (If you can)
MySQL column type is BIT, MergeResultSet value is an byte array, can not convert to boolean.
Steps to reproduce the behavior, such as: SQL to execute, sharding rule configuration, when exception occur etc.
pom.xml
application.yml
Demo.java
DemoRepository.java
DemoApplication.java
Log
Example codes for reproduce this issue (such as a github link).