Skip to content

Commit 6ceb473

Browse files
authored
Define code generation interface via Protocol Buffers (#1406)
* Define CodeGenRequest and CodeGenResponse via `proto/plugin/codegen.proto` * Move pattern matching to another package
1 parent 45bd150 commit 6ceb473

File tree

12 files changed

+2458
-441
lines changed

12 files changed

+2458
-441
lines changed

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ sqlc-pg-gen:
2121
start:
2222
docker-compose up -d
2323

24+
fmt:
25+
go fmt ./...
26+
2427
psql:
2528
PGPASSWORD=mysecretpassword psql --host=127.0.0.1 --port=5432 --username=postgres dinotest
2629

internal/cmd/generate.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/kyleconroy/sqlc/internal/debug"
2020
"github.com/kyleconroy/sqlc/internal/multierr"
2121
"github.com/kyleconroy/sqlc/internal/opts"
22+
"github.com/kyleconroy/sqlc/internal/plugin"
2223
)
2324

2425
const errMessageNoVersion = `The configuration file must have a version number.
@@ -187,6 +188,7 @@ func Generate(ctx context.Context, e Env, dir, filename string, stderr io.Writer
187188
region = trace.StartRegion(ctx, "codegen")
188189
}
189190
var files map[string]string
191+
var resp *plugin.CodeGenResponse
190192
var out string
191193
switch {
192194
case sql.Gen.Go != nil:
@@ -197,14 +199,21 @@ func Generate(ctx context.Context, e Env, dir, filename string, stderr io.Writer
197199
files, err = kotlin.Generate(result, combo)
198200
case sql.Gen.Python != nil:
199201
out = combo.Python.Out
200-
files, err = python.Generate(result, combo)
202+
resp, err = python.Generate(codeGenRequest(result, combo))
201203
default:
202204
panic("missing language backend")
203205
}
204206
if region != nil {
205207
region.End()
206208
}
207209

210+
if resp != nil {
211+
files = map[string]string{}
212+
for _, file := range resp.Files {
213+
files[file.Name] = string(file.Contents)
214+
}
215+
}
216+
208217
if err != nil {
209218
fmt.Fprintf(stderr, "# package %s\n", name)
210219
fmt.Fprintf(stderr, "error generating code: %s\n", err)

internal/cmd/shim.go

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
package cmd
2+
3+
import (
4+
"strings"
5+
6+
"github.com/kyleconroy/sqlc/internal/compiler"
7+
"github.com/kyleconroy/sqlc/internal/config"
8+
"github.com/kyleconroy/sqlc/internal/plugin"
9+
"github.com/kyleconroy/sqlc/internal/sql/catalog"
10+
)
11+
12+
func pluginOverride(o config.Override) *plugin.Override {
13+
var column string
14+
var table plugin.Identifier
15+
16+
if o.Column != "" {
17+
colParts := strings.Split(o.Column, ".")
18+
switch len(colParts) {
19+
case 2:
20+
table.Schema = "public"
21+
table.Name = colParts[0]
22+
column = colParts[1]
23+
case 3:
24+
table.Schema = colParts[0]
25+
table.Name = colParts[1]
26+
column = colParts[2]
27+
case 4:
28+
table.Catalog = colParts[0]
29+
table.Schema = colParts[1]
30+
table.Name = colParts[2]
31+
column = colParts[3]
32+
}
33+
}
34+
return &plugin.Override{
35+
CodeType: "", // FIXME
36+
DbType: o.DBType,
37+
Nullable: o.Nullable,
38+
Column: o.Column,
39+
ColumnName: column,
40+
Table: &table,
41+
PythonType: pluginPythonType(o.PythonType),
42+
}
43+
}
44+
45+
func pluginSettings(cs config.CombinedSettings) *plugin.Settings {
46+
var over []*plugin.Override
47+
for _, o := range cs.Overrides {
48+
over = append(over, pluginOverride(o))
49+
}
50+
return &plugin.Settings{
51+
Version: cs.Global.Version,
52+
Engine: string(cs.Package.Engine),
53+
Schema: []string(cs.Package.Schema),
54+
Queries: []string(cs.Package.Queries),
55+
Overrides: over,
56+
Rename: cs.Rename,
57+
Python: pluginPythonCode(cs.Python),
58+
}
59+
}
60+
61+
func pluginPythonCode(s config.SQLPython) *plugin.PythonCode {
62+
return &plugin.PythonCode{
63+
Out: s.Out,
64+
Package: s.Package,
65+
EmitExactTableNames: s.EmitExactTableNames,
66+
EmitSyncQuerier: s.EmitSyncQuerier,
67+
EmitAsyncQuerier: s.EmitAsyncQuerier,
68+
}
69+
}
70+
71+
func pluginPythonType(pt config.PythonType) *plugin.PythonType {
72+
return &plugin.PythonType{
73+
Module: pt.Module,
74+
Name: pt.Name,
75+
}
76+
}
77+
78+
func pluginCatalog(c *catalog.Catalog) *plugin.Catalog {
79+
var schemas []*plugin.Schema
80+
for _, s := range c.Schemas {
81+
var enums []*plugin.Enum
82+
for _, typ := range s.Types {
83+
enum, ok := typ.(*catalog.Enum)
84+
if !ok {
85+
continue
86+
}
87+
enums = append(enums, &plugin.Enum{
88+
Name: enum.Name,
89+
Comment: enum.Comment,
90+
Vals: enum.Vals,
91+
})
92+
}
93+
var tables []*plugin.Table
94+
for _, t := range s.Tables {
95+
var columns []*plugin.Column
96+
for _, c := range t.Columns {
97+
l := -1
98+
if c.Length != nil {
99+
l = *c.Length
100+
}
101+
columns = append(columns, &plugin.Column{
102+
Name: c.Name,
103+
Type: &plugin.Identifier{
104+
Catalog: c.Type.Catalog,
105+
Schema: c.Type.Schema,
106+
Name: c.Type.Name,
107+
},
108+
Comment: c.Comment,
109+
NotNull: c.IsNotNull,
110+
IsArray: c.IsArray,
111+
Length: int32(l),
112+
Table: &plugin.Identifier{
113+
Catalog: t.Rel.Catalog,
114+
Schema: t.Rel.Schema,
115+
Name: t.Rel.Name,
116+
},
117+
})
118+
}
119+
tables = append(tables, &plugin.Table{
120+
Rel: &plugin.Identifier{
121+
Catalog: t.Rel.Catalog,
122+
Schema: t.Rel.Schema,
123+
Name: t.Rel.Name,
124+
},
125+
Columns: columns,
126+
Comment: t.Comment,
127+
})
128+
}
129+
schemas = append(schemas, &plugin.Schema{
130+
Comment: s.Comment,
131+
Name: s.Name,
132+
Tables: tables,
133+
Enums: enums,
134+
})
135+
}
136+
return &plugin.Catalog{
137+
Name: c.Name,
138+
DefaultSchema: c.DefaultSchema,
139+
Comment: c.Comment,
140+
Schemas: schemas,
141+
}
142+
}
143+
144+
func pluginQueries(r *compiler.Result) []*plugin.Query {
145+
var out []*plugin.Query
146+
for _, q := range r.Queries {
147+
var params []*plugin.Parameter
148+
var columns []*plugin.Column
149+
for _, c := range q.Columns {
150+
columns = append(columns, pluginQueryColumn(c))
151+
}
152+
for _, p := range q.Params {
153+
params = append(params, pluginQueryParam(p))
154+
}
155+
out = append(out, &plugin.Query{
156+
Name: q.Name,
157+
Cmd: q.Cmd,
158+
Text: q.SQL,
159+
Comments: q.Comments,
160+
Columns: columns,
161+
Params: params,
162+
Filename: q.Filename,
163+
})
164+
}
165+
return out
166+
}
167+
168+
func pluginQueryColumn(c *compiler.Column) *plugin.Column {
169+
l := -1
170+
if c.Length != nil {
171+
l = *c.Length
172+
}
173+
out := &plugin.Column{
174+
Name: c.Name,
175+
Comment: c.Comment,
176+
NotNull: c.NotNull,
177+
IsArray: c.IsArray,
178+
Length: int32(l),
179+
}
180+
181+
if c.Type != nil {
182+
out.Type = &plugin.Identifier{
183+
Catalog: c.Type.Catalog,
184+
Schema: c.Type.Schema,
185+
Name: c.Type.Name,
186+
}
187+
} else {
188+
out.Type = &plugin.Identifier{
189+
Name: c.DataType,
190+
}
191+
}
192+
193+
if c.Table != nil {
194+
out.Table = &plugin.Identifier{
195+
Catalog: c.Table.Catalog,
196+
Schema: c.Table.Schema,
197+
Name: c.Table.Name,
198+
}
199+
}
200+
201+
return out
202+
}
203+
204+
func pluginQueryParam(p compiler.Parameter) *plugin.Parameter {
205+
return &plugin.Parameter{
206+
Number: int32(p.Number),
207+
Column: pluginQueryColumn(p.Column),
208+
}
209+
}
210+
211+
func codeGenRequest(r *compiler.Result, settings config.CombinedSettings) *plugin.CodeGenRequest {
212+
return &plugin.CodeGenRequest{
213+
Settings: pluginSettings(settings),
214+
Catalog: pluginCatalog(r.Catalog),
215+
Queries: pluginQueries(r),
216+
}
217+
}

0 commit comments

Comments
 (0)