Skip to content

{identifier:Type} pattern in SQL comment forces server-side mode, breaking @name substitution in same query #1828

@drowninginflowers

Description

@drowninginflowers

Summary

When a SQL query contains a {identifier:Type} pattern inside a -- comment, the driver switches the entire query to server-side query-settings mode. Any @name parameter in the actual SQL is then left unsubstituted and reaches ClickHouse as a bare @name token, producing error code 26.

The bug reproduces whether or not the identifier in the comment matches a named parameter.

Environment

  • clickhouse-go: v2.43.0
  • ClickHouse server: 26.2.5.45
  • Go: 1.25.0
  • Protocol: native TCP (port 9000)

Reproduction

package main

import (
	"context"
	"fmt"
	"os"

	"github.com/ClickHouse/clickhouse-go/v2"
)

func main() {
	opts, _ := clickhouse.ParseDSN(os.Getenv("CLICKHOUSE_DSN"))
	conn, _ := clickhouse.Open(opts)
	defer conn.Close()
	ctx := context.Background()

	run := func(label, query string, args ...any) {
		rows, err := conn.Query(ctx, query, args...)
		if err != nil {
			fmt.Printf("FAIL  %s\n      %v\n", label, err)
			return
		}
		rows.Close()
		fmt.Printf("PASS  %s\n", label)
	}

	// PASS: @name alone, no {x:T} anywhere in the SQL
	run("baseline",
		`SELECT number FROM numbers(@limit)`,
		clickhouse.Named("limit", uint32(5)),
	)

	// PASS: @name in a comment is fine when no {x:T} is present
	run("@name in comment, no {x:T}",
		"-- uses @limit\nSELECT number FROM numbers(@limit)",
		clickhouse.Named("limit", uint32(5)),
	)

	// FAIL: {x:T} in a comment — identifier matches a named param
	// Driver forces server-side mode; @limit in SQL is never substituted.
	run("{x:T} in comment, identifier matches param",
		"-- server-side equivalent: {limit:UInt32}\nSELECT number FROM numbers(@limit)",
		clickhouse.Named("limit", uint32(5)),
	)

	// FAIL: {x:T} in a comment — identifier does not match any param
	// Same failure regardless of whether the identifier is in the params map.
	run("{x:T} in comment, identifier not in params",
		"-- see {name:Type} style for expression positions\nSELECT number FROM numbers(@limit)",
		clickhouse.Named("limit", uint32(5)),
	)
}

Output:

PASS  baseline
PASS  @name in comment, no {x:T}
FAIL  {x:T} in comment, identifier matches param
      code: 26, message: Cannot parse quoted string: expected opening quote ''', got '5'
FAIL  {x:T} in comment, identifier not in params
      code: 26, message: Cannot parse quoted string: expected opening quote ''', got '5'

Expected behaviour

SQL comments should not be scanned for parameter patterns. {identifier:Type} inside a -- comment should have no effect on how @name parameters in the actual query are processed.

Actual behaviour

Any {identifier:Type} found in a -- comment forces the driver into server-side query-settings mode for the whole query. @name in the SQL is then passed through to ClickHouse unsubstituted, which rejects it (code 62 "Syntax error") or misinterprets the bound value (code 26 "Cannot parse quoted string") depending on the specific query structure.

Suggested fix

Strip or skip SQL comment regions before scanning for {identifier:Type} and @name patterns. Single-line (--) and block (/* */) comments should both be excluded from parameter scanning.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions