ClickHouse: `Display` implementation converts types to uppercase, causing `UNKNOWN_TYPE` errors

Abierto
#2,153 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
35/100
Tipo de issue
Error
Claridad
Bastante claro
Estado de actividad
Estancado
Stack tecnológico
clickhouse, rust
Área
databases

Línea de trabajo

Comienza inspeccionando la implementación de DataType Display y los tipos AST enumerados en el issue, incluidos Statement, Query, Expr, ColumnDef y los nodos relacionados. Traza cómo la serialización llega a los tipos de datos anidados y, después, evalúa la API to_sql propuesta, consciente del dialecto, a través de toda la jerarquía. Se considera terminado cuando el ejemplo de ClickHouse hace round-trip con tipos PascalCase y el comportamiento existente de Display sigue siendo compatible hacia atrás.

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

Descripción

Problem

ClickHouse data types are case-sensitive and require PascalCase (e.g., String, Int32, Nullable). However, the sqlparser-rs library's Display implementation for DataType converts certain types to uppercase, causing UNKNOWN_TYPE errors when round-tripping SQL through ClickHouse.

Example

use sqlparser::dialect::ClickHouseDialect;
use sqlparser::parser::Parser;

let sql = "CREATE TABLE t (col Nullable(String))";
let dialect = ClickHouseDialect {};
let ast = Parser::parse_sql(&dialect, sql).unwrap();

// Round-trip: parse and convert back to string
let regenerated = ast[0].to_string();
// Result: "CREATE TABLE t (col Nullable(STRING))"
//                                       ^^^^^^ uppercase!

When this regenerated SQL is executed against ClickHouse, it fails with:

Code: 47. DB::Exception: Unknown type STRING. (UNKNOWN_TYPE)

Affected Types

Type Current Output ClickHouse Requires
DataType::Int8 INT8 Int8
DataType::Int64 INT64 Int64
DataType::Float64 FLOAT64 Float64
DataType::String STRING String
DataType::Bool BOOL Bool
DataType::Date DATE Date
DataType::Datetime DATETIME DateTime

Types already correct (PascalCase):

  • Int16, Int32, Int128, Int256
  • UInt8, UInt16, UInt32, UInt64, UInt128, UInt256
  • Float32
  • Nullable, LowCardinality, Array, Map, Tuple, Nested

Root Cause

The Display trait implementation for DataType uses uppercase for type names (e.g., write!(f, "STRING")), which is standard for most SQL dialects but incorrect for ClickHouse.

The challenge is that Display doesn't have access to dialect context, so it can't conditionally format based on the active dialect.

The Problem with Display

Most users serialize SQL by calling Display on top-level AST types:

let ast = Parser::parse_sql(&dialect, sql).unwrap();
let regenerated = ast[0].to_string();  // Uses Display on Statement
// or
let regenerated = format!("{}", query);  // Uses Display on Query

The Display trait signature doesn't allow passing context:

fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result

Proposed Solution

To solve this, we need dialect-aware serialization throughout the AST hierarchy:

Add to_sql(&dyn Dialect) to all AST types

  • Add to_sql(&dyn Dialect) -> String method to Statement, Query, Expr, ColumnDef, and other AST types
  • Each type's implementation calls to_sql() on its children, propagating the dialect
  • Keep existing Display implementations unchanged for backwards compatibility
// Example usage after fix:
let ast = Parser::parse_sql(&dialect, sql).unwrap();
let regenerated = ast[0].to_sql(&dialect);  // Correct PascalCase for ClickHouse
Implementation Scope

The affected types include (non-exhaustive):

  • Statement (top-level)
  • Query, SetExpr, Select
  • Expr (especially Cast, TryCast, SafeCast)
  • ColumnDef, ColumnOption
  • TableConstraint
  • AlterTableOperation
  • FunctionArg, FunctionArgExpr

This is a significant change but provides the cleanest API and maintains backwards compatibility.

Workarounds

Currently, users must post-process the SQL string output to fix casing. See 514-labs/moosestack#3152 for an example regex-based workaround.

References

Lenguaje dominante
Rust
Estrellas
3.5k
Forks
774
Merge medio
3 d 4 h
PR fusionados (30 d)
19

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

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 apache/datafusion-sqlparser-rs

Todos los issues de apache/datafusion-sqlparser-rs

Issues similares

Más issues de Rust

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.