Skip to content

bug: Insert and select Double INF value cause error #16213

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

Closed
1 of 2 tasks
hantmac opened this issue Aug 8, 2024 · 4 comments · Fixed by #16258
Closed
1 of 2 tasks

bug: Insert and select Double INF value cause error #16213

hantmac opened this issue Aug 8, 2024 · 4 comments · Fixed by #16258
Assignees
Labels
C-bug Category: something isn't working

Comments

@hantmac
Copy link
Member

hantmac commented Aug 8, 2024

Search before asking

  • 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!
@hantmac hantmac added the C-bug Category: something isn't working label Aug 8, 2024
@dqhl76
Copy link
Collaborator

dqhl76 commented Aug 13, 2024

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)

@sundy-li
Copy link
Member

serde-rs/json#202

@sundy-li
Copy link
Member

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

@dqhl76
Copy link
Collaborator

dqhl76 commented Aug 15, 2024

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

image

I think OrderedFloat just use f64's serialize and deserialize method

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants