- Notifications
You must be signed in to change notification settings - Fork995
Add ClickHouse Engine Support to sqlc#4220
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Open
mgilbir wants to merge13 commits intosqlc-dev:mainChoose a base branch frommgilbir:add-clickhouse-support
base:main
Could not load branches
Branch not found:{{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline, and old review comments may become outdated.
Uh oh!
There was an error while loading.Please reload this page.
Open
Changes from1 commit
Commits
Show all changes
13 commits Select commitHold shift + click to select a range
f30b317 Add ClickHouse engine: parser, converter, and catalog
mgilbir7960b17 Add ClickHouse engine unit tests
mgilbir5112bab Register ClickHouse engine in compiler
mgilbire817d54 Add ClickHouse type mapping for Go code generation
mgilbird426a16 Add ClickHouse code generation templates
mgilbir14e9917 Add JOIN USING support and refactor output column handling
mgilbircec1ed9 Add ClickHouse test database adapters
mgilbir15d203a Add ClickHouse documentation and example project
mgilbircc9759f Add ClickHouse example project generated code
mgilbircfdb3ff Add end-to-end test for JOIN...USING syntax
mgilbird7965d6 Add end-to-end tests for ClickHouse core SQL features
mgilbir01638c9 Add end-to-end tests for ClickHouse advanced SQL features
mgilbir00ce8b7 Add end-to-end tests for ClickHouse types and functions
mgilbirFile filter
Filter by extension
Conversations
Failed to load comments.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Jump to file
Failed to load files.
Loading
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
Add JOIN USING support and refactor output column handling
Implement JOIN...USING clause support for ClickHouse and PostgreSQL.Refactor output_columns.go for improved type resolution.Add comprehensive tests for output columns and type resolution.Update quote character handling and catalog interface.
- Loading branch information
Uh oh!
There was an error while loading.Please reload this page.
commit14e9917e306f423d196ab04b1f8c7e1ef0c7c3ee
There are no files selected for viewing
196 changes: 196 additions & 0 deletionsinternal/compiler/clickhouse_join_test.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,196 @@ | ||
| package compiler | ||
| import ( | ||
| "strings" | ||
| "testing" | ||
| "github.com/sqlc-dev/sqlc/internal/config" | ||
| "github.com/sqlc-dev/sqlc/internal/engine/clickhouse" | ||
| "github.com/sqlc-dev/sqlc/internal/sql/ast" | ||
| ) | ||
| // TestClickHouseJoinColumnResolution tests that column names are properly resolved | ||
| // in JOIN queries now that JoinExpr is correctly converted | ||
| func TestClickHouseJoinColumnResolution(t *testing.T) { | ||
| parser := clickhouse.NewParser() | ||
| cat := clickhouse.NewCatalog() | ||
| // Create database and tables | ||
| schemaSQL := `CREATE DATABASE IF NOT EXISTS test_db; | ||
| CREATE TABLE test_db.users ( | ||
| id UInt32, | ||
| name String, | ||
| email String | ||
| ); | ||
| CREATE TABLE test_db.posts ( | ||
| id UInt32, | ||
| user_id UInt32, | ||
| title String, | ||
| content String | ||
| )` | ||
| stmts, err := parser.Parse(strings.NewReader(schemaSQL)) | ||
| if err != nil { | ||
| t.Fatalf("Parse schema failed: %v", err) | ||
| } | ||
| for _, stmt := range stmts { | ||
| if err := cat.Update(stmt, nil); err != nil { | ||
| t.Fatalf("Update catalog failed: %v", err) | ||
| } | ||
| } | ||
| // Create compiler | ||
| conf := config.SQL{ | ||
| Engine: config.EngineClickHouse, | ||
| } | ||
| combo := config.CombinedSettings{ | ||
| Global: config.Config{}, | ||
| } | ||
| c, err := NewCompiler(conf, combo) | ||
| if err != nil { | ||
| t.Fatalf("Failed to create compiler: %v", err) | ||
| } | ||
| // Replace catalog | ||
| c.catalog = cat | ||
| // Parse a JOIN query | ||
| querySQL := "SELECT u.id, u.name, p.id as post_id, p.title FROM test_db.users u LEFT JOIN test_db.posts p ON u.id = p.user_id WHERE u.id = 1" | ||
| queryStmts, err := parser.Parse(strings.NewReader(querySQL)) | ||
| if err != nil { | ||
| t.Fatalf("Parse query failed: %v", err) | ||
| } | ||
| if len(queryStmts) == 0 { | ||
| t.Fatal("No queries parsed") | ||
| } | ||
| selectStmt := queryStmts[0].Raw.Stmt | ||
| if selectStmt == nil { | ||
| t.Fatal("Select statement is nil") | ||
| } | ||
| selectAst, ok := selectStmt.(*ast.SelectStmt) | ||
| if !ok { | ||
| t.Fatalf("Expected SelectStmt, got %T", selectStmt) | ||
| } | ||
| // Build query catalog and get output columns | ||
| qc, err := c.buildQueryCatalog(c.catalog, selectAst, nil) | ||
| if err != nil { | ||
| t.Fatalf("Failed to build query catalog: %v", err) | ||
| } | ||
| cols, err := c.outputColumns(qc, selectAst) | ||
| if err != nil { | ||
| t.Fatalf("Failed to get output columns: %v", err) | ||
| } | ||
| if len(cols) != 4 { | ||
| t.Errorf("Expected 4 columns, got %d", len(cols)) | ||
| } | ||
| expectedNames := []string{"id", "name", "post_id", "title"} | ||
| for i, expected := range expectedNames { | ||
| if i < len(cols) { | ||
| if cols[i].Name != expected { | ||
| t.Errorf("Column %d: expected name %q, got %q", i, expected, cols[i].Name) | ||
| } | ||
| } | ||
| } | ||
| } | ||
| // TestClickHouseLeftJoinNullability tests that LEFT JOIN correctly marks right-side columns as nullable | ||
| // In ClickHouse, columns are non-nullable by default unless wrapped in Nullable(T) | ||
| func TestClickHouseLeftJoinNullability(t *testing.T) { | ||
| parser := clickhouse.NewParser() | ||
| cat := clickhouse.NewCatalog() | ||
| schemaSQL := `CREATE TABLE orders ( | ||
| order_id UInt32, | ||
| customer_name String, | ||
| amount Float64, | ||
| created_at DateTime | ||
| ); | ||
| CREATE TABLE shipments ( | ||
| shipment_id UInt32, | ||
| order_id UInt32, | ||
| address String, | ||
| shipped_at DateTime | ||
| )` | ||
| stmts, err := parser.Parse(strings.NewReader(schemaSQL)) | ||
| if err != nil { | ||
| t.Fatalf("Parse schema failed: %v", err) | ||
| } | ||
| for _, stmt := range stmts { | ||
| if err := cat.Update(stmt, nil); err != nil { | ||
| t.Fatalf("Update catalog failed: %v", err) | ||
| } | ||
| } | ||
| conf := config.SQL{ | ||
| Engine: config.EngineClickHouse, | ||
| } | ||
| combo := config.CombinedSettings{ | ||
| Global: config.Config{}, | ||
| } | ||
| c, err := NewCompiler(conf, combo) | ||
| if err != nil { | ||
| t.Fatalf("Failed to create compiler: %v", err) | ||
| } | ||
| c.catalog = cat | ||
| querySQL := "SELECT o.order_id, o.customer_name, o.amount, o.created_at, s.shipment_id, s.address, s.shipped_at FROM orders o LEFT JOIN shipments s ON o.order_id = s.order_id ORDER BY o.created_at DESC" | ||
| queryStmts, err := parser.Parse(strings.NewReader(querySQL)) | ||
| if err != nil { | ||
| t.Fatalf("Parse query failed: %v", err) | ||
| } | ||
| selectAst := queryStmts[0].Raw.Stmt.(*ast.SelectStmt) | ||
| qc, err := c.buildQueryCatalog(c.catalog, selectAst, nil) | ||
| if err != nil { | ||
| t.Fatalf("Failed to build query catalog: %v", err) | ||
| } | ||
| cols, err := c.outputColumns(qc, selectAst) | ||
| if err != nil { | ||
| t.Fatalf("Failed to get output columns: %v", err) | ||
| } | ||
| if len(cols) != 7 { | ||
| t.Errorf("Expected 7 columns, got %d", len(cols)) | ||
| } | ||
| // Left table columns should be non-nullable | ||
| leftTableNonNull := map[string]bool{ | ||
| "order_id": true, | ||
| "customer_name": true, | ||
| "amount": true, | ||
| "created_at": true, | ||
| } | ||
| // Right table columns should be nullable (because of LEFT JOIN) | ||
| rightTableNullable := map[string]bool{ | ||
| "shipment_id": true, | ||
| "address": true, | ||
| "shipped_at": true, | ||
| } | ||
| for _, col := range cols { | ||
| if expected, ok := leftTableNonNull[col.Name]; ok { | ||
| if col.NotNull != expected { | ||
| t.Errorf("Column %q: expected NotNull=%v, got %v", col.Name, expected, col.NotNull) | ||
| } | ||
| } | ||
| if expected, ok := rightTableNullable[col.Name]; ok { | ||
| if col.NotNull == expected { | ||
| t.Errorf("Column %q: expected NotNull=%v, got %v", col.Name, !expected, col.NotNull) | ||
| } | ||
| } | ||
| } | ||
| } |
20 changes: 18 additions & 2 deletionsinternal/compiler/expand.go
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.Learn more about bidirectional Unicode characters
Oops, something went wrong.
Uh oh!
There was an error while loading.Please reload this page.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.