Skip to content

Commit d426a16

Browse files
committed
Add ClickHouse code generation templates
Templates for generating Go database code: - Database interface template - Interface declarations - Query function implementations - Import resolution tests
1 parent e817d54 commit d426a16

5 files changed

Lines changed: 249 additions & 0 deletions

File tree

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package golang
2+
3+
import (
4+
"testing"
5+
6+
"github.com/sqlc-dev/sqlc/internal/codegen/golang/opts"
7+
)
8+
9+
func TestClickHouseDriver_NotPGX(t *testing.T) {
10+
driver := opts.SQLDriver(opts.SQLDriverClickHouseV2)
11+
if driver.IsPGX() {
12+
t.Error("ClickHouse driver should not identify as PGX")
13+
}
14+
}
15+
16+
func TestClickHouseDriver_IsClickHouse(t *testing.T) {
17+
driver := opts.SQLDriver(opts.SQLDriverClickHouseV2)
18+
if !driver.IsClickHouse() {
19+
t.Error("ClickHouse driver should identify as ClickHouse")
20+
}
21+
}
22+
23+
func TestStandardDriver_NotClickHouse(t *testing.T) {
24+
driver := opts.SQLDriver(opts.SQLDriverLibPQ)
25+
if driver.IsClickHouse() {
26+
t.Error("Standard driver should not identify as ClickHouse")
27+
}
28+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{{define "dbCodeTemplateClickHouse"}}
2+
3+
type DBTX interface {
4+
Exec(ctx context.Context, query string, args ...any) error
5+
Query(ctx context.Context, query string, args ...any) (driver.Rows, error)
6+
QueryRow(ctx context.Context, query string, args ...any) driver.Row
7+
{{- if .UsesBatch }}
8+
PrepareBatch(ctx context.Context, query string) (driver.Batch, error)
9+
{{- end }}
10+
}
11+
12+
{{ if .EmitMethodsWithDBArgument}}
13+
func New() *Queries {
14+
return &Queries{}
15+
{{- else -}}
16+
func New(db DBTX) *Queries {
17+
return &Queries{db: db}
18+
{{- end}}
19+
}
20+
21+
type Queries struct {
22+
{{if not .EmitMethodsWithDBArgument}}
23+
db DBTX
24+
{{end}}
25+
}
26+
27+
{{if not .EmitMethodsWithDBArgument}}
28+
func (q *Queries) WithTx(tx driver.Conn) *Queries {
29+
return &Queries{
30+
db: tx,
31+
}
32+
}
33+
{{end}}
34+
{{end}}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{{define "interfaceCodeClickHouse"}}
2+
type Querier interface { {{- range .GoQueries}}
3+
{{- if ne (hasPrefix .Cmd ":batch") true}}
4+
{{range .Comments}}//{{.}}
5+
{{end -}}
6+
{{- if $.EmitMethodsWithDBArgument -}}
7+
{{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) ({{.Ret.EmitResultType}}, error)
8+
{{- else -}}
9+
{{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ({{.Ret.EmitResultType}}, error)
10+
{{- end -}}
11+
{{- end}}
12+
{{- end}}
13+
}
14+
15+
var _ Querier = (*Queries)(nil)
16+
{{end}}
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
{{define "queryCodeClickHouse"}}
2+
{{range .GoQueries}}
3+
{{if $.OutputQuery .SourceName}}
4+
{{if and (ne .Cmd ":copyfrom") (ne (hasPrefix .Cmd ":batch") true)}}
5+
const {{.ConstantName}} = {{$.Q}}-- name: {{.MethodName}} {{.Cmd}}
6+
{{escape .SQL}}
7+
{{$.Q}}
8+
{{end}}
9+
10+
{{if ne (hasPrefix .Cmd ":batch") true}}
11+
{{if .Arg.EmitStruct}}
12+
type {{.Arg.Type}} struct { {{- range .Arg.Struct.Fields}}
13+
{{.Name}} {{.Type}} {{if .Tag}}{{$.Q}}{{.Tag}}{{$.Q}}{{end}}
14+
{{- end}}
15+
}
16+
{{end}}
17+
18+
{{if .Ret.EmitStruct}}
19+
type {{.Ret.Type}} struct { {{- range .Ret.Struct.Fields}}
20+
{{.Name}} {{.Type}} {{if .Tag}}{{$.Q}}{{.Tag}}{{$.Q}}{{end}}
21+
{{- end}}
22+
}
23+
{{end}}
24+
{{end}}
25+
26+
{{if eq .Cmd ":one"}}
27+
{{range .Comments}}//{{.}}
28+
{{end -}}
29+
{{- if $.EmitMethodsWithDBArgument -}}
30+
func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) ({{.Ret.DefineType}}, error) {
31+
row := db.QueryRow(ctx, {{.ConstantName}}, {{.Arg.Params}})
32+
{{- else -}}
33+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ({{.Ret.DefineType}}, error) {
34+
row := q.db.QueryRow(ctx, {{.ConstantName}}, {{.Arg.Params}})
35+
{{- end}}
36+
{{- if or (ne .Arg.Pair .Ret.Pair) (ne .Arg.DefineType .Ret.DefineType) }}
37+
var {{.Ret.Name}} {{.Ret.Type}}
38+
{{- end}}
39+
err := row.Scan({{.Ret.Scan}})
40+
{{- if $.WrapErrors}}
41+
if err != nil {
42+
err = fmt.Errorf("query {{.MethodName}}: %w", err)
43+
}
44+
{{- end}}
45+
return {{.Ret.ReturnName}}, err
46+
}
47+
{{end}}
48+
49+
{{if eq .Cmd ":many"}}
50+
{{range .Comments}}//{{.}}
51+
{{end -}}
52+
{{- if $.EmitMethodsWithDBArgument -}}
53+
func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) ([]{{.Ret.DefineType}}, error) {
54+
rows, err := db.Query(ctx, {{.ConstantName}}, {{.Arg.Params}})
55+
{{- else -}}
56+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ([]{{.Ret.DefineType}}, error) {
57+
rows, err := q.db.Query(ctx, {{.ConstantName}}, {{.Arg.Params}})
58+
{{- end}}
59+
if err != nil {
60+
return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}}
61+
}
62+
defer rows.Close()
63+
{{- if $.EmitEmptySlices}}
64+
items := []{{.Ret.DefineType}}{}
65+
{{else}}
66+
var items []{{.Ret.DefineType}}
67+
{{end -}}
68+
for rows.Next() {
69+
var {{.Ret.Name}} {{.Ret.Type}}
70+
if err := rows.Scan({{.Ret.Scan}}); err != nil {
71+
return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}}
72+
}
73+
items = append(items, {{.Ret.ReturnName}})
74+
}
75+
if err := rows.Err(); err != nil {
76+
return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}}
77+
}
78+
return items, nil
79+
}
80+
{{end}}
81+
82+
{{if eq .Cmd ":exec"}}
83+
{{range .Comments}}//{{.}}
84+
{{end -}}
85+
{{- if $.EmitMethodsWithDBArgument -}}
86+
func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) error {
87+
err := db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}})
88+
{{- else -}}
89+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) error {
90+
err := q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}})
91+
{{- end}}
92+
{{- if $.WrapErrors}}
93+
if err != nil {
94+
return fmt.Errorf("exec {{.MethodName}}: %w", err)
95+
}
96+
{{- end}}
97+
return err
98+
}
99+
{{end}}
100+
101+
{{if eq .Cmd ":execrows"}}
102+
{{range .Comments}}//{{.}}
103+
{{end -}}
104+
{{- if $.EmitMethodsWithDBArgument -}}
105+
func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) (int64, error) {
106+
// ClickHouse doesn't support RowsAffected, returning error
107+
return 0, fmt.Errorf(":execrows not supported by ClickHouse driver")
108+
}
109+
{{- else -}}
110+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (int64, error) {
111+
// ClickHouse doesn't support RowsAffected, returning error
112+
return 0, fmt.Errorf(":execrows not supported by ClickHouse driver")
113+
}
114+
{{- end}}
115+
{{end}}
116+
117+
{{if eq .Cmd ":execlastid"}}
118+
{{range .Comments}}//{{.}}
119+
{{end -}}
120+
{{- if $.EmitMethodsWithDBArgument -}}
121+
func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) (int64, error) {
122+
// ClickHouse doesn't support LastInsertId, returning error
123+
return 0, fmt.Errorf(":execlastid not supported by ClickHouse driver")
124+
}
125+
{{- else -}}
126+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (int64, error) {
127+
// ClickHouse doesn't support LastInsertId, returning error
128+
return 0, fmt.Errorf(":execlastid not supported by ClickHouse driver")
129+
}
130+
{{- end}}
131+
{{end}}
132+
133+
{{if eq .Cmd ":execresult"}}
134+
{{range .Comments}}//{{.}}
135+
{{end -}}
136+
{{- if $.EmitMethodsWithDBArgument -}}
137+
func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) error {
138+
{{- if $.WrapErrors}}
139+
err := db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}})
140+
if err != nil {
141+
return fmt.Errorf("exec {{.MethodName}}: %w", err)
142+
}
143+
return nil
144+
{{- else}}
145+
return db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}})
146+
{{- end}}
147+
}
148+
{{- else -}}
149+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) error {
150+
{{- if $.WrapErrors}}
151+
err := q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}})
152+
if err != nil {
153+
return fmt.Errorf("exec {{.MethodName}}: %w", err)
154+
}
155+
return nil
156+
{{- else}}
157+
return q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}})
158+
{{- end}}
159+
}
160+
{{- end}}
161+
{{end}}
162+
163+
{{end}}
164+
{{end}}
165+
{{end}}

internal/codegen/golang/templates/template.tmpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import (
2525

2626
{{if .SQLDriver.IsPGX }}
2727
{{- template "dbCodeTemplatePgx" .}}
28+
{{else if .SQLDriver.IsClickHouse }}
29+
{{- template "dbCodeTemplateClickHouse" .}}
2830
{{else}}
2931
{{- template "dbCodeTemplateStd" .}}
3032
{{end}}
@@ -57,6 +59,8 @@ import (
5759
{{define "interfaceCode"}}
5860
{{if .SQLDriver.IsPGX }}
5961
{{- template "interfaceCodePgx" .}}
62+
{{else if .SQLDriver.IsClickHouse }}
63+
{{- template "interfaceCodeClickHouse" .}}
6064
{{else}}
6165
{{- template "interfaceCodeStd" .}}
6266
{{end}}
@@ -188,6 +192,8 @@ import (
188192
{{define "queryCode"}}
189193
{{if .SQLDriver.IsPGX }}
190194
{{- template "queryCodePgx" .}}
195+
{{else if .SQLDriver.IsClickHouse }}
196+
{{- template "queryCodeClickHouse" .}}
191197
{{else}}
192198
{{- template "queryCodeStd" .}}
193199
{{end}}

0 commit comments

Comments
 (0)