databend
databend copied to clipboard
bug: Insert and select Double INF value cause error
Search before asking
- [X] I had searched in the issues and found no similar issues.
Version
Databend Query v1.2.598-nightly-812688f7b6(rust-1.81.0-nightly-2024-08-05T22:07:38.113740317Z)
What's Wrong?
Using java insert into the Double.POSITIVE_INFINITY value into table and get an error sometime when select from it.
How to Reproduce?
public void testWriteDouble() throws SQLException {
try (Connection connection = createConnection()) {
DatabendStatement statement = (DatabendStatement) connection.createStatement();
statement.execute("CREATE TABLE IF NOT EXISTS test_basic_driver.table_double (\n" +
" ID INT,\n" +
" Name VARCHAR(50),\n" +
" Age INT,\n" +
" City VARCHAR(50),\n" +
" Score DOUBLE\n" +
");");
Double infDouble = Double.POSITIVE_INFINITY;
String sql = "INSERT INTO test_basic_driver.table_double (ID, Name, Age, City, Score) values";
PreparedStatement prepareStatement = connection.prepareStatement(sql);
prepareStatement.setInt(1, 1);
prepareStatement.setString(2, "Alice");
prepareStatement.setInt(3, 25);
prepareStatement.setString(4, "Toronto");
prepareStatement.setDouble(5, infDouble);
prepareStatement.addBatch();
prepareStatement.executeBatch();
statement.execute("SELECT * FROM test_basic_driver.table_double");
ResultSet r = statement.getResultSet();
r.next();
Assert.assertEquals(r.getDouble(5), "Infinity");
} catch (SQLException throwables) {
throwables.printStackTrace();
}
}
The above code get error:
java.sql.SQLException: Error executing query: SQL: SELECT * FROM test_basic_driver.table_double Query failed: QueryErrors{code=1006, message=Cannot parse request for /actions/init_query_fragments, cause: Error("invalid type: null, expected f64", line: 1, column: 3444)} cause: null
at com.databend.jdbc.DatabendStatement.internalExecute(DatabendStatement.java:215)
at com.databend.jdbc.DatabendStatement.execute(DatabendStatement.java:154)
at com.databend.jdbc.TestBasicDriver.testWriteDouble(TestBasicDriver.java:200)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:566)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:104)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:645)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:851)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1177)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:129)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:112)
at org.testng.TestRunner.privateRun(TestRunner.java:756)
at org.testng.TestRunner.run(TestRunner.java:610)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:387)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:382)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:340)
at org.testng.SuiteRunner.run(SuiteRunner.java:289)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1293)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1218)
at org.testng.TestNG.runSuites(TestNG.java:1133)
at org.testng.TestNG.run(TestNG.java:1104)
at com.intellij.rt.testng.IDEARemoteTestNG.run(IDEARemoteTestNG.java:66)
at com.intellij.rt.testng.RemoteTestNGStarter.main(RemoteTestNGStarter.java:109)
Caused by: java.lang.RuntimeException: Query failed: QueryErrors{code=1006, message=Cannot parse request for /actions/init_query_fragments, cause: Error("invalid type: null, expected f64", line: 1, column: 3444)}
at com.databend.client.DatabendClientV1.executeInternal(DatabendClientV1.java:181)
at com.databend.client.DatabendClientV1.execute(DatabendClientV1.java:202)
at com.databend.client.DatabendClientV1.<init>(DatabendClientV1.java:91)
at com.databend.jdbc.DatabendConnection.startQuery(DatabendConnection.java:614)
at com.databend.jdbc.DatabendStatement.internalExecute(DatabendStatement.java:186)
which is QueryErrors{code=1006, message=Cannot parse request for /actions/init_query_fragments, cause: Error("invalid type: null, expected f64", line: 1, column: 3444)}
Are you willing to submit PR?
- [ ] Yes I am willing to submit a PR!
After investigating, I found that the likely root cause is that the fragment we sent has a field ColumnStatistics and min max field in ColumnStatistics could be f64::INFINITY.
However, f64::INFINITY cannot be correctly serialized and deserialized. When f64::INFINITY is serialized, it becomes 'null', and attempting to deserialize this results in an error: "invalid type: null, expected f64". Below is a minimal method to reproduce this issue:
#[derive(Debug, serde::Serialize, serde::Deserialize)]
struct Dummy{
test: f64
}
fn main(){
let dummy = Dummy{test: f64::INFINITY};
let serialized = serde_json::to_string(&dummy).unwrap();
let deserialized: Dummy = serde_json::from_str(&serialized).unwrap();
println!("{:?}",deserialized);
}
called `Result::unwrap()` on an `Err` value: Error("invalid type: null, expected f64", line: 1, column: 12)
https://github.com/serde-rs/json/issues/202
ColumnStatistics and min max field in ColumnStatistics could be f64::INFINITY.
We are using F64, which is type F64 = OrderedFloat<f64>;, so there is no f64 in ColumnStatistics
ColumnStatistics and min max field in ColumnStatistics could be f64::INFINITY.
We are using F64, which is
type F64 = OrderedFloat<f64>;, so there is no f64 in ColumnStatistics
I think OrderedFloat just use f64's serialize and deserialize method