callicles opened a new pull request, #2154:
URL: https://github.com/apache/datafusion-sqlparser-rs/pull/2154

   ## feat: Add dialect-aware SQL serialization with `ToSql` trait for 
ClickHouse PascalCase types
   
   ### Summary
   
   This PR introduces a new `ToSql` trait that enables dialect-aware SQL 
serialization, specifically addressing ClickHouse's requirement for PascalCase 
type names (e.g., `String`, `Int64`, `Nullable(String)`) instead of the 
standard uppercase convention (`STRING`, `INT64`).
   
   **Related Issue:** 
https://github.com/apache/datafusion-sqlparser-rs/issues/2153
   
   ### Problem
   
   ClickHouse is case-sensitive for data type names and requires PascalCase. 
When using `sqlparser-rs` to parse and regenerate SQL:
   
   ```rust
   let sql = "CREATE TABLE t (col String)";
   let ast = Parser::parse_sql(&dialect, sql)?;
   let regenerated = format!("{}", ast[0]);  // Produces "CREATE TABLE t (col 
STRING)"
   ```
   
   The regenerated SQL fails with `UNKNOWN_TYPE` errors when executed against 
ClickHouse because `STRING` is not recognized—only `String` is valid.
   
   ### Solution
   
   Introduce a `ToSql` trait that accepts dialect context:
   
   ```rust
   pub trait ToSql {
       fn to_sql(&self, dialect: &dyn Dialect) -> String;
       fn write_sql(&self, f: &mut dyn Write, dialect: &dyn Dialect) -> 
fmt::Result;
   }
   ```
   
   Usage:
   ```rust
   use sqlparser::ast::ToSql;
   
   let sql = "CREATE TABLE t (col String)";
   let ast = Parser::parse_sql(&ClickHouseDialect {}, sql)?;
   let regenerated = ast[0].to_sql(&ClickHouseDialect {});
   // Produces: "CREATE TABLE t (col String)" ✓
   ```
   
   ### Design Decisions
   
   1. **Coexistence with `Display`**: The existing `Display` trait continues to 
work unchanged (uppercase types). `ToSql` is opt-in for users who need 
dialect-aware formatting.
   
   2. **`impl_to_sql_display!` macro**: Types without `DataType` fields 
delegate to their `Display` implementation via macro, avoiding code duplication.
   
   3. **Recursive propagation**: Types containing `DataType` fields implement 
`write_sql` explicitly, calling `write_sql` on nested types to propagate 
dialect context through the AST.
   
   4. **`requires_pascalcase_types()` dialect method**: A new method on the 
`Dialect` trait that returns `true` for ClickHouse.
   
   ### Changes
   
   | File | Description |
   |------|-------------|
   | `src/ast/to_sql.rs` | New module with `ToSql` trait, 
`impl_to_sql_display!` macro, and helpers |
   | `src/ast/data_type.rs` | `ToSql` impl for `DataType` with PascalCase 
formatting |
   | `src/ast/mod.rs` | `ToSql` impls for `Expr`, `Statement`, `Function`, 
window types, etc. |
   | `src/ast/ddl.rs` | `ToSql` impls for `CreateTable`, `AlterTable`, 
`ColumnDef`, etc. |
   | `src/ast/query.rs` | `ToSql` impls for `Query`, `Select`, `TableFactor`, 
etc. |
   | `src/dialect/mod.rs` | Add `requires_pascalcase_types()` to `Dialect` 
trait |
   | `src/dialect/clickhouse.rs` | Override `requires_pascalcase_types()` to 
return `true` |
   | `tests/sqlparser_clickhouse.rs` | Comprehensive tests including round-trip 
verification |
   
   ### Coverage
   
   `ToSql` is implemented for all major AST types users are likely to serialize:
   
   - **Statements**: `Statement`, `Query`, `Select`, `CreateTable`, 
`AlterTable`, `CreateView`, `CreateFunction`, `Declare`, `Prepare`
   - **Expressions**: `Expr` (all variants including `Cast`, `Case`, 
`BinaryOp`, `Function`, etc.)
   - **Types**: `DataType`, `ColumnDef`, `ViewColumnDef`, `StructField`, 
`UnionField`
   - **Query components**: `TableFactor`, `Join`, `OrderByExpr`, `WindowSpec`, 
`Cte`, `With`
   - **Functions**: `Function`, `FunctionArg`, `FunctionArguments`, window 
functions
   
   ### Testing
   
   Added 8 new tests covering:
   - Basic `DataType` PascalCase formatting
   - `CREATE TABLE` with nested types (`Nullable`, `Array`, `Map`)
   - `ALTER TABLE` operations
   - `SELECT` with `CAST` expressions
   - Complex expressions (`CASE`, nested `CAST`)
   - `CREATE VIEW` statements
   - **Round-trip test**: parse → `to_sql` → parse → verify equivalence
   
   ```
   test result: ok. 55 passed; 0 failed (ClickHouse tests)
   ```
   
   ### Migration Guide
   
   If you currently use `Display` and need dialect-aware formatting:
   
   ```rust
   // Before
   let sql = format!("{}", statement);
   
   // After
   use sqlparser::ast::ToSql;
   let sql = statement.to_sql(&dialect);
   ```
   
   ### Breaking Changes
   
   None. This is a purely additive change. Existing code using `Display` 
continues to work unchanged.
   
   Disclaimer: This was worked on with AI


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to