Skip to content

jdbc-v2: an insert whose values list holds a function call the ANTLR4 grammar cannot match is reported to use none, and is routed to the RowBinary writer #3027

Description

@polyglotAI-bot

Describe the bug

With an ANTLR4 parser backend selected (jdbc_sql_parser=ANTLR4 or ANTLR4_PARAMS_PARSER), the driver reports that an
INSERT ... VALUES list holds no function call while it does, when the values list contains a function call the bundled
ANTLR4 grammar cannot match. Function calls in a values list are reported by a listener callback on the parse tree
(insertParameterFuncExpr). A statement the grammar cannot match is still given a parse tree, completed by error
recovery, which skips the tokens the parser recovered on - the function call among them - so the callback never fires and
ParsedPreparedStatement.useFunction stays false.

With the beta RowBinary writer enabled (beta.row_binary_for_simple_insert=true) that flag is one of the conditions
ConnectionImpl#prepareStatement uses to decide whether an insert can be written with the RowBinary writer, which
requires a values list of parameter placeholders only. Such a statement is therefore routed to the RowBinary writer,
where the literal function-call column cannot be written.

The default JAVACC backend is not affected: it reports function usage from the SQL itself, not from a parse tree.

Steps to reproduce

Properties properties = new Properties();
properties.setProperty("beta.row_binary_for_simple_insert", "true");
properties.setProperty("jdbc_sql_parser", "ANTLR4"); // or ANTLR4_PARAMS_PARSER

try (Connection conn = DriverManager.getConnection(url, properties)) {
    try (Statement stmt = conn.createStatement()) {
        stmt.execute("CREATE TABLE t (v1 Int32, v2 String) Engine MergeTree ORDER BY ()");
    }
    // hex(x'AB') is valid ClickHouse; the bundled grammar has no hex string literal, so the
    // statement is parsed with errors and the function call is skipped by error recovery
    PreparedStatement ps = conn.prepareStatement("INSERT INTO t (v1, v2) VALUES (?, hex(x'AB'))");
    System.out.println(ps.getClass()); // WriterStatementImpl - the RowBinary writer
}

Expected behaviour

The statement holds a function call in its values list, so it must be given the generic parameter substitution path
(PreparedStatementImpl), as it is with INSERT INTO t (v1, v2) VALUES (?, now()) (a function call the grammar does
match) and with the JAVACC backend, and the row must be stored with v2 = 'AB'.

Actual behaviour

ParsedPreparedStatement.useFunction is false, and the statement is routed to the RowBinary writer
(WriterStatementImpl).

Code example

See above.

Error log

n/a

Configuration

Environment

  • Client version: 0.11.0-rc1 (main)
  • OS: Linux

ClickHouse server

  • ClickHouse Server version: 26.3

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions