Skip to content

Commit 03f8b59

Browse files
committed
Groundwork for code generation for queries
1 parent 0ce1a29 commit 03f8b59

25 files changed

+175
-29
lines changed

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
12+
- Added a new field `QueryFolders` to `gen/drivers.DBInfo` for drivers to be able to include information about parsed queries.
13+
- Added `gen/QueriesTemplates` which in the future will contain base templates for generating code for parsed qureries.
14+
- Added a `QueryTemplate` field to `bobgen_helpers.Templates` for drivers to include additional templates for queries.
15+
- Added a new reserved output key `queries`. This is handled specially for each query folder supplied by the driver.
16+
1017
### Changed
1118

1219
- Updated error constant generation to employ specific error types for making error matching easier. (thanks @mbezhanov)

gen/bobgen-helpers/helpers.go

+5
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ func Version() string {
3535
type Templates struct {
3636
Models []fs.FS
3737
Factory []fs.FS
38+
Queries []fs.FS
3839
}
3940

4041
func DefaultOutputs(destination, pkgname string, noFactory bool, templates *Templates) []*gen.Output {
@@ -57,6 +58,10 @@ func DefaultOutputs(destination, pkgname string, noFactory bool, templates *Temp
5758
PkgName: pkgname,
5859
Templates: append(templates.Models, gen.ModelTemplates),
5960
},
61+
{
62+
Key: "queries",
63+
Templates: append(templates.Queries, gen.QueriesTemplates),
64+
},
6065
}
6166

6267
if !noFactory {

gen/bobgen-mysql/driver/exclude-tables.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -2339,6 +2339,7 @@
23392339
"comment": ""
23402340
}
23412341
],
2342+
"query_folders": null,
23422343
"enums": [
23432344
{
23442345
"Type": "TypeMonstersEnumNullable",

gen/bobgen-mysql/driver/include-exclude-tables-mixed.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
"comment": ""
120120
}
121121
],
122+
"query_folders": null,
122123
"enums": null,
123124
"extra_info": null,
124125
"driver_name": "github.com/go-sql-driver/mysql"

gen/bobgen-mysql/driver/include-exclude-tables-regex.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
"comment": ""
120120
}
121121
],
122+
"query_folders": null,
122123
"enums": null,
123124
"extra_info": null,
124125
"driver_name": "github.com/go-sql-driver/mysql"

gen/bobgen-mysql/driver/include-exclude-tables.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"comment": ""
6161
}
6262
],
63+
"query_folders": null,
6364
"enums": null,
6465
"extra_info": null,
6566
"driver_name": "github.com/go-sql-driver/mysql"

gen/bobgen-mysql/driver/include-tables.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
"comment": ""
120120
}
121121
],
122+
"query_folders": null,
122123
"enums": null,
123124
"extra_info": null,
124125
"driver_name": "github.com/go-sql-driver/mysql"

gen/bobgen-mysql/driver/mysql.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -2490,6 +2490,7 @@
24902490
"comment": ""
24912491
}
24922492
],
2493+
"query_folders": null,
24932494
"enums": [
24942495
{
24952496
"Type": "TypeMonstersEnumNullable",

gen/bobgen-psql/driver/exclude-tables.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -4578,6 +4578,7 @@
45784578
"comment": ""
45794579
}
45804580
],
4581+
"query_folders": null,
45814582
"enums": [
45824583
{
45834584
"Type": "UnicodeEnum",

gen/bobgen-psql/driver/include-exclude-tables-mixed.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
"comment": ""
134134
}
135135
],
136+
"query_folders": null,
136137
"enums": [
137138
{
138139
"Type": "UnicodeEnum",

gen/bobgen-psql/driver/include-exclude-tables-regex.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
"comment": ""
134134
}
135135
],
136+
"query_folders": null,
136137
"enums": [
137138
{
138139
"Type": "UnicodeEnum",

gen/bobgen-psql/driver/include-exclude-tables.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@
6767
"comment": ""
6868
}
6969
],
70+
"query_folders": null,
7071
"enums": [
7172
{
7273
"Type": "UnicodeEnum",

gen/bobgen-psql/driver/include-tables.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
"comment": ""
134134
}
135135
],
136+
"query_folders": null,
136137
"enums": [
137138
{
138139
"Type": "UnicodeEnum",

gen/bobgen-psql/driver/psql.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -4743,6 +4743,7 @@
47434743
"comment": ""
47444744
}
47454745
],
4746+
"query_folders": null,
47464747
"enums": [
47474748
{
47484749
"Type": "UnicodeEnum",

gen/bobgen-sqlite/driver/exclude-tables.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -3093,6 +3093,7 @@
30933093
"comment": ""
30943094
}
30953095
],
3096+
"query_folders": [],
30963097
"enums": null,
30973098
"extra_info": null,
30983099
"driver_name": "modernc.org/sqlite"

gen/bobgen-sqlite/driver/include-exclude-tables-mixed.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@
245245
"comment": ""
246246
}
247247
],
248+
"query_folders": [],
248249
"enums": null,
249250
"extra_info": null,
250251
"driver_name": "modernc.org/sqlite"

gen/bobgen-sqlite/driver/include-exclude-tables-regex.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@
245245
"comment": ""
246246
}
247247
],
248+
"query_folders": [],
248249
"enums": null,
249250
"extra_info": null,
250251
"driver_name": "modernc.org/sqlite"

gen/bobgen-sqlite/driver/include-exclude-tables.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
"comment": ""
124124
}
125125
],
126+
"query_folders": [],
126127
"enums": null,
127128
"extra_info": null,
128129
"driver_name": "modernc.org/sqlite"

gen/bobgen-sqlite/driver/include-tables.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@
245245
"comment": ""
246246
}
247247
],
248+
"query_folders": [],
248249
"enums": null,
249250
"extra_info": null,
250251
"driver_name": "modernc.org/sqlite"

gen/bobgen-sqlite/driver/sqlite.golden.json

+1
Original file line numberDiff line numberDiff line change
@@ -3403,6 +3403,7 @@
34033403
"comment": ""
34043404
}
34053405
],
3406+
"query_folders": [],
34063407
"enums": null,
34073408
"extra_info": null,
34083409
"driver_name": "modernc.org/sqlite"

gen/drivers/interface.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -54,9 +54,10 @@ type Types map[string]Type
5454

5555
// DBInfo is the database's table data and dialect.
5656
type DBInfo[DBExtra, ConstraintExtra, IndexExtra any] struct {
57-
Tables []Table[ConstraintExtra, IndexExtra] `json:"tables"`
58-
Enums []Enum `json:"enums"`
59-
ExtraInfo DBExtra `json:"extra_info"`
57+
Tables Tables[ConstraintExtra, IndexExtra] `json:"tables"`
58+
QueryFolders []QueryFolder `json:"query_folders"`
59+
Enums []Enum `json:"enums"`
60+
ExtraInfo DBExtra `json:"extra_info"`
6061
// DriverName is the module name of the underlying `database/sql` driver
6162
DriverName string `json:"driver_name"`
6263
}

gen/drivers/query.go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package drivers
2+
3+
type QueryFolder struct {
4+
Path string
5+
Files []QueryFile
6+
}
7+
8+
type QueryFile struct {
9+
Path string
10+
Queries []Query
11+
}
12+
13+
type Query struct {
14+
Name string `yaml:"name"`
15+
SQL string `yaml:"raw"`
16+
RowName string `yaml:"row_name"`
17+
GenerateRow bool `yaml:"generate_row"`
18+
19+
Columns []QueryArg `yaml:"columns"`
20+
Args []QueryArg `yaml:"args"`
21+
}
22+
23+
type QueryArg struct {
24+
Name string `yaml:"name"`
25+
Nullable bool `yaml:"nullable"`
26+
TypeName string `yaml:"type"`
27+
Refs []Ref `yaml:"refs"`
28+
}
29+
30+
type Ref struct {
31+
Key string `yaml:"key"`
32+
Column string `yaml:"column"`
33+
}
34+
35+
type db interface {
36+
GetColumn(key string, col string) Column
37+
}
38+
39+
func (c QueryArg) Type(db db) string {
40+
if len(c.Refs) == 0 {
41+
return c.TypeName
42+
}
43+
44+
ref := db.GetColumn(c.Refs[0].Key, c.Refs[0].Column).Type
45+
46+
for _, r := range c.Refs[1:] {
47+
if ref != db.GetColumn(r.Key, r.Column).Type {
48+
return c.TypeName
49+
}
50+
}
51+
52+
return ref
53+
}

gen/gen.go

+58-20
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ func Run[T, C, I any](ctx context.Context, s *State[C], driver drivers.Interface
120120
data := &TemplateData[T, C, I]{
121121
Dialect: driver.Dialect(),
122122
Tables: dbInfo.Tables,
123+
QueryFolders: dbInfo.QueryFolders,
123124
Enums: dbInfo.Enums,
124125
ExtraInfo: dbInfo.ExtraInfo,
125126
Aliases: s.Config.Aliases,
@@ -162,17 +163,14 @@ func generate[T, C, I any](s *State[C], data *TemplateData[T, C, I], goVersion s
162163
templateHeaderByteBuffer := &bytes.Buffer{}
163164

164165
for _, o := range s.Outputs {
165-
if len(o.Templates) == 0 {
166-
continue
167-
}
168-
169166
if _, ok := knownKeys[o.Key]; ok {
170167
return fmt.Errorf("Duplicate output key: %q", o.Key)
171168
}
172169
knownKeys[o.Key] = struct{}{}
173170

174-
// set the package name for this output
175-
data.PkgName = o.PkgName
171+
if len(o.Templates) == 0 {
172+
continue
173+
}
176174

177175
if err := o.initTemplates(s.CustomTemplateFuncs); err != nil {
178176
return fmt.Errorf("unable to initialize templates: %w", err)
@@ -182,26 +180,66 @@ func generate[T, C, I any](s *State[C], data *TemplateData[T, C, I], goVersion s
182180
continue
183181
}
184182

185-
if err := o.initOutFolders(s.Config.Wipe); err != nil {
186-
return fmt.Errorf("unable to initialize the output folders: %w", err)
187-
}
183+
iterator := slices.Values([]struct{}{{}})
188184

189-
// assign reusable scratch buffers to provided Output
190-
o.templateByteBuffer = templateByteBuffer
191-
o.templateHeaderByteBuffer = templateHeaderByteBuffer
185+
if o.Key == "queries" {
186+
iterator = func(yield func(struct{}) bool) {
187+
for _, folder := range data.QueryFolders {
188+
o.PkgName = filepath.Base(folder.Path)
189+
o.OutFolder = folder.Path
190+
data.QueryFolder = folder
192191

193-
if err := generateSingletonOutput(o, data, goVersion, s.Config.NoTests); err != nil {
194-
return fmt.Errorf("singleton template output: %w", err)
192+
if !yield(struct{}{}) {
193+
return
194+
}
195+
}
196+
}
195197
}
196198

197-
dirExtMap := groupTemplates(o.tableTemplates)
199+
for range iterator {
200+
// set the package name for this output
201+
data.PkgName = o.PkgName
202+
203+
if err := o.initOutFolders(s.Config.Wipe); err != nil {
204+
return fmt.Errorf("unable to initialize the output folders: %w", err)
205+
}
206+
207+
// assign reusable scratch buffers to provided Output
208+
o.templateByteBuffer = templateByteBuffer
209+
o.templateHeaderByteBuffer = templateHeaderByteBuffer
210+
211+
if err := generateSingletonOutput(o, data, goVersion, s.Config.NoTests); err != nil {
212+
return fmt.Errorf("singleton template output: %w", err)
213+
}
214+
215+
dirExtMap := groupTemplates(o.tableTemplates)
216+
217+
for _, table := range data.Tables {
218+
data.Table = table
219+
220+
// Generate the regular templates
221+
if err := generateOutput(o, dirExtMap, o.tableTemplates, data, goVersion, s.Config.NoTests); err != nil {
222+
return fmt.Errorf("unable to generate output: %w", err)
223+
}
224+
}
225+
226+
if len(data.QueryFolder.Files) == 0 {
227+
continue
228+
}
229+
230+
dirExtMap = groupTemplates(o.queryTemplates)
231+
for _, file := range data.QueryFolder.Files {
232+
data.QueryFile = file
198233

199-
for _, table := range data.Tables {
200-
data.Table = table
234+
// We do this so that the name of the file is correct
235+
base := filepath.Base(file.Path)
236+
data.Table = drivers.Table[C, I]{
237+
Name: base[:len(base)-4],
238+
}
201239

202-
// Generate the regular templates
203-
if err := generateOutput(o, dirExtMap, data, goVersion, s.Config.NoTests); err != nil {
204-
return fmt.Errorf("unable to generate output: %w", err)
240+
if err := generateOutput(o, dirExtMap, o.queryTemplates, data, goVersion, s.Config.NoTests); err != nil {
241+
return fmt.Errorf("unable to generate output: %w", err)
242+
}
205243
}
206244
}
207245
}

0 commit comments

Comments
 (0)