Skip to content

SQL containing WITH clause and WITH TOTALS fails with ClickHouseUnknownException #441

Description

@vinodkmrm

SQL containing the WITH clause (Common Table Expressions (CTE)) and WITH TOTAL clause fails, when looping through the result set. Call to ClickHouseResultSet.next() after reading the last row fails with ClickHouseUnknownException. Call to ClickHouseResultSet.getTotals() fails with "java.lang.IllegalStateException: Cannot get totals when totals are not being used." e.g

Bug is in ru.yandex.clickhouse.ClickHouseStatementImpl#extractWithTotals method. This method must check for sql staring with "WITH" or "SELECT". Right now it only checks for SQL starting with "SELECT", as show below -

  private boolean extractWithTotals(String sql) {
       if (Utils.startsWithIgnoreCase(sql, "select")) {
           String withoutStrings = Utils.retainUnquoted(sql, '\'');
           return withoutStrings.toLowerCase().contains(" with totals");
       }
       return false;
   }

Query :

WITH 2 AS factor
SELECT 
    number % 2 AS odd_even, 
    count(*) AS count, 
    sum(factor * number) AS output
FROM 
(
    SELECT number
    FROM system.numbers
    LIMIT 100
)
GROUP BY number % 2
    WITH TOTALS
 

Java Code :

       ClickHouseDataSource clickHouseDataSource = new ClickHouseDataSource(
                "jdbc:clickhouse://localhost:8123"
        );
        String sqlQueryWith = "WITH 2 AS factor\n" +
                "SELECT \n" +
                "    number % 2 AS odd_even, \n" +
                "    count(*) AS count, \n" +
                "    sum(factor * number) AS output\n" +
                "FROM \n" +
                "(\n" +
                "    SELECT number\n" +
                "    FROM system.numbers\n" +
                "    LIMIT 100\n" +
                ")\n" +
                "GROUP BY number % 2\n" +
                "    WITH TOTALS\n";

        try (ClickHouseConnection connection = clickHouseDataSource.getConnection()) {
            ClickHouseStatement statement = connection.createStatement();
            ResultSet rs = statement.executeQuery(sqlQueryWith);
            while (rs.next()) {
                System.out.println(format("odd_even %d, count : %d, output %d", rs.getInt("odd_even"),
                        rs.getInt("count"), rs.getInt("output")));
            }
            ((ClickHouseResultSet) rs).getTotals();
            System.out.println(format("Total odd_even %d, count : %d, output %d", rs.getInt("odd_even"),
                    rs.getInt("count"), rs.getInt("output")));

        }

Activity

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

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions