Hacktoberfest 2026: los issues que los mantenedores marcaron para octubre, abiertos y aptos para principiantes. Explorar issues de Hacktoberfest

[jdbc-v2] User-Agent wraps detected frameworks in double parentheses: ((apache.spark))

Abierto Apto para principiantes
#3,214 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
2/5
Tiempo estimado
1-3 horas
Aptitud para principiantes
70/100
Tipo de issue
Error
Claridad
Bien especificado
Estado de actividad
Activo
Stack tecnológico
java
Área
database

Línea de trabajo

La doble agrupación proviene de dos lugares en jdbc-v2: Driver.FrameworksDetection.getFrameworksDetected() en jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java envuelve cada nombre entre paréntesis, y ConnectionImpl en jdbc-v2 vuelve a envolver el resultado unido. Elimina el envoltorio por nombre solo en la copia de jdbc-v2, dejando DriverV1.FrameworksDetection en jdbc-v1 sin cambios. Está terminado cuando un stack que contiene org.apache.spark produce un único grupo como (apache.spark), y un stack sin framework sigue sin producir ningún grupo. Una prueba en un paquete org.apache.spark debe restablecer primero el campo estático frameworksDetected.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

bug jdbc-v2

Description

When jdbc-v2 detects a framework on the call stack (apache.spark, apache.flink, apache.nifi), it adds the framework names to the User-Agent header inside two levels of parentheses:

jdbc-v2/0.12.0-rc1-SNAPSHOT ((apache.spark)) clickhouse-java-v2/0.12.0-rc1-SNAPSHOT (Linux; jvm:17.0.20.1) Apache-HttpClient/5.6.4

With two frameworks on the stack, each name gets its own inner group:

jdbc-v2/0.12.0-rc1-SNAPSHOT ((apache.flink); (apache.spark)) clickhouse-java-v2/0.12.0-rc1-SNAPSHOT (Linux; jvm:17.0.20.1) Apache-HttpClient/5.6.4

Nested comments are valid HTTP (RFC 9110), so requests do not fail. But the header is read by tools that parse system.query_log.http_user_agent (see #2775), and a single comment group is the shape that the rest of the header uses.

Root cause

Two places add parentheses:

  1. Driver.FrameworksDetection.getFrameworksDetected() wraps each name: inferredFrameworks.add(String.format("(%s)", framework)), then joins with "; ".
    https://github.com/ClickHouse/clickhouse-java/blob/5392b642e5ca0375a77b8cc0f15b29b97a8f772f/jdbc-v2/src/main/java/com/clickhouse/jdbc/Driver.java#L50-L55
  2. ConnectionImpl wraps the result again: clientName += " (" + detectedFrameworks + ")".
    https://github.com/ClickHouse/clickhouse-java/blob/5392b642e5ca0375a77b8cc0f15b29b97a8f772f/jdbc-v2/src/main/java/com/clickhouse/jdbc/ConnectionImpl.java#L101-L107

FrameworksDetection is the same code as DriverV1.FrameworksDetection in jdbc-v1. jdbc-v1 appends the result directly to the product name, with no outer group, so there the inner parentheses are the only group:
https://github.com/ClickHouse/clickhouse-java/blob/5392b642e5ca0375a77b8cc0f15b29b97a8f772f/clickhouse-jdbc/src/main/java/com/clickhouse/jdbc/internal/ClickHouseConnectionImpl.java#L287-L291
jdbc-v2 kept the per-name parentheses and added an outer group, so the names are wrapped twice.

Suggested fix

In jdbc-v2 only, remove one level. For example, add the plain name in Driver.FrameworksDetection (inferredFrameworks.add(framework)) and keep the outer group in ConnectionImpl. Result:

  • one framework: jdbc-v2/<v> (apache.spark) clickhouse-java-v2/<v> ...
  • two frameworks: jdbc-v2/<v> (apache.flink; apache.spark) clickhouse-java-v2/<v> ...

Cases that must not change:

  • No framework on the stack: no group (today: jdbc-v2/<v> clickhouse-java-v2/<v> ...).
  • jdbc-v1 (DriverV1.FrameworksDetection): it has no outer group, so it needs its per-name parentheses.

A unit test can call Driver.FrameworksDetection.getFrameworksDetected() from a class in an org.apache.spark.* package. The result is cached in a static field, so the test must reset FrameworksDetection.frameworksDetected (package-private) first.

Related: #3213 (open) changes the client-v2 part of the header to the standard format for #3202. It does not change the jdbc-v2 framework group and says this is a separate issue. A maintainer could also decide to move the frameworks into the new client_metadata key/value pairs. That changes the jdbc-v2 output and needs a key name, so it is a design decision, not part of this bug.

Steps to reproduce
  1. Put a class in a package whose name contains apache.spark (for example org.apache.spark.repro) and open a jdbc-v2 connection from it.
  2. Run a query that has a unique marker, then SYSTEM FLUSH LOGS.
  3. Read http_user_agent for that query from system.query_log.
Error Log or Exception StackTrace

No exception. Observed http_user_agent values (one JVM per row, because detection result is cached per JVM):

[spark on stack]                    jdbc-v2/0.12.0-rc1-SNAPSHOT ((apache.spark)) clickhouse-java-v2/0.12.0-rc1-SNAPSHOT (Linux; jvm:17.0.20.1) Apache-HttpClient/5.6.4
[spark, client_name=my-app/1.0]     my-app/1.0 jdbc-v2/0.12.0-rc1-SNAPSHOT ((apache.spark)) clickhouse-java-v2/0.12.0-rc1-SNAPSHOT (Linux; jvm:17.0.20.1) Apache-HttpClient/5.6.4
[spark -> flink on stack]           jdbc-v2/0.12.0-rc1-SNAPSHOT ((apache.flink); (apache.spark)) clickhouse-java-v2/0.12.0-rc1-SNAPSHOT (Linux; jvm:17.0.20.1) Apache-HttpClient/5.6.4
[no framework on stack]             jdbc-v2/0.12.0-rc1-SNAPSHOT clickhouse-java-v2/0.12.0-rc1-SNAPSHOT (Linux; jvm:17.0.20.1) Apache-HttpClient/5.6.4
Expected Behaviour

One comment group with the framework names:

jdbc-v2/0.12.0-rc1-SNAPSHOT (apache.spark) clickhouse-java-v2/0.12.0-rc1-SNAPSHOT ...
jdbc-v2/0.12.0-rc1-SNAPSHOT (apache.flink; apache.spark) clickhouse-java-v2/0.12.0-rc1-SNAPSHOT ...
Code Example
package org.apache.spark.repro;   // "apache.spark" in the stack trace triggers detection

import java.sql.*;
import java.util.*;

public class SparkApp {
    public static void main(String[] args) throws Exception {
        Properties p = new Properties();
        p.setProperty("user", "default");
        p.setProperty("password", "<password>");
        String marker = "ua_probe_" + UUID.randomUUID().toString().replace("-", "");
        try (Connection c = new com.clickhouse.jdbc.Driver().connect("jdbc:clickhouse://localhost:8123/default", p);
             Statement s = c.createStatement()) {
            s.executeQuery("SELECT '" + marker + "'").close();
            s.execute("SYSTEM FLUSH LOGS");
            try (ResultSet rs = s.executeQuery("SELECT http_user_agent FROM system.query_log"
                    + " WHERE type = 'QueryFinish' AND query LIKE '%" + marker + "%'"
                    + " AND query NOT LIKE '%query_log%' LIMIT 1")) {
                rs.next();
                System.out.println(rs.getString(1));
                // prints: jdbc-v2/<v> ((apache.spark)) clickhouse-java-v2/<v> (...)
            }
        }
    }
}

For the two-framework case, call the same code from a class in org.apache.flink.repro that SparkApp calls.

Configuration
Client Configuration
// defaults; framework detection is enabled by default
Environment
  • Cloud
  • Client version: jdbc-v2 0.12.0-rc1-SNAPSHOT, built from main at 5392b642e5ca0375a77b8cc0f15b29b97a8f772f
  • Language version: Java 17.0.20.1
  • OS: Linux
ClickHouse Server
  • ClickHouse Server version: 26.9.1.1629
  • ClickHouse Server non-default settings, if any: none relevant
  • CREATE TABLE statements for tables involved: none (SELECT '<marker>' only)

Found by automated analysis (Polyglot AI) while working on #3202. Verified by running the code above against a live ClickHouse server, not only by reading the code.

Lenguaje dominante
Java
Estrellas
1.6k
Forks
640
Merge medio
1 d 13 h
PR fusionados (30 d)
41

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de ClickHouse/clickhouse-java

Todos los issues de ClickHouse/clickhouse-java

Issues similares

Más issues de Java

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.