Skip to content

Commit

Permalink
Merge pull request #329 from stephenafamo/queries
Browse files Browse the repository at this point in the history
Groundwork for code generation for queries
  • Loading branch information
stephenafamo authored Dec 15, 2024
2 parents 0ce1a29 + b4b263c commit 1da2c27
Show file tree
Hide file tree
Showing 25 changed files with 175 additions and 29 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added

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

### Changed

- Updated error constant generation to employ specific error types for making error matching easier. (thanks @mbezhanov)
Expand Down
5 changes: 5 additions & 0 deletions gen/bobgen-helpers/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ func Version() string {
type Templates struct {
Models []fs.FS
Factory []fs.FS
Queries []fs.FS
}

func DefaultOutputs(destination, pkgname string, noFactory bool, templates *Templates) []*gen.Output {
Expand All @@ -57,6 +58,10 @@ func DefaultOutputs(destination, pkgname string, noFactory bool, templates *Temp
PkgName: pkgname,
Templates: append(templates.Models, gen.ModelTemplates),
},
{
Key: "queries",
Templates: append(templates.Queries, gen.QueriesTemplates),
},
}

if !noFactory {
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-mysql/driver/exclude-tables.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -2339,6 +2339,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": [
{
"Type": "TypeMonstersEnumNullable",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "github.com/go-sql-driver/mysql"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "github.com/go-sql-driver/mysql"
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-mysql/driver/include-exclude-tables.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "github.com/go-sql-driver/mysql"
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-mysql/driver/include-tables.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "github.com/go-sql-driver/mysql"
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-mysql/driver/mysql.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -2490,6 +2490,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": [
{
"Type": "TypeMonstersEnumNullable",
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-psql/driver/exclude-tables.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -4578,6 +4578,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": [
{
"Type": "UnicodeEnum",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": [
{
"Type": "UnicodeEnum",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": [
{
"Type": "UnicodeEnum",
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-psql/driver/include-exclude-tables.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": [
{
"Type": "UnicodeEnum",
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-psql/driver/include-tables.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": [
{
"Type": "UnicodeEnum",
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-psql/driver/psql.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -4743,6 +4743,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": [
{
"Type": "UnicodeEnum",
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-sqlite/driver/exclude-tables.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -3093,6 +3093,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "modernc.org/sqlite"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "modernc.org/sqlite"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "modernc.org/sqlite"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "modernc.org/sqlite"
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-sqlite/driver/include-tables.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "modernc.org/sqlite"
Expand Down
1 change: 1 addition & 0 deletions gen/bobgen-sqlite/driver/sqlite.golden.json
Original file line number Diff line number Diff line change
Expand Up @@ -3403,6 +3403,7 @@
"comment": ""
}
],
"query_folders": null,
"enums": null,
"extra_info": null,
"driver_name": "modernc.org/sqlite"
Expand Down
7 changes: 4 additions & 3 deletions gen/drivers/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ type Types map[string]Type

// DBInfo is the database's table data and dialect.
type DBInfo[DBExtra, ConstraintExtra, IndexExtra any] struct {
Tables []Table[ConstraintExtra, IndexExtra] `json:"tables"`
Enums []Enum `json:"enums"`
ExtraInfo DBExtra `json:"extra_info"`
Tables Tables[ConstraintExtra, IndexExtra] `json:"tables"`
QueryFolders []QueryFolder `json:"query_folders"`
Enums []Enum `json:"enums"`
ExtraInfo DBExtra `json:"extra_info"`
// DriverName is the module name of the underlying `database/sql` driver
DriverName string `json:"driver_name"`
}
Expand Down
53 changes: 53 additions & 0 deletions gen/drivers/query.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package drivers

type QueryFolder struct {
Path string
Files []QueryFile
}

type QueryFile struct {
Path string
Queries []Query
}

type Query struct {
Name string `yaml:"name"`
SQL string `yaml:"raw"`
RowName string `yaml:"row_name"`
GenerateRow bool `yaml:"generate_row"`

Columns []QueryArg `yaml:"columns"`
Args []QueryArg `yaml:"args"`
}

type QueryArg struct {
Name string `yaml:"name"`
Nullable bool `yaml:"nullable"`
TypeName string `yaml:"type"`
Refs []Ref `yaml:"refs"`
}

type Ref struct {
Key string `yaml:"key"`
Column string `yaml:"column"`
}

type db interface {
GetColumn(key string, col string) Column
}

func (c QueryArg) Type(db db) string {
if len(c.Refs) == 0 {
return c.TypeName
}

ref := db.GetColumn(c.Refs[0].Key, c.Refs[0].Column).Type

for _, r := range c.Refs[1:] {
if ref != db.GetColumn(r.Key, r.Column).Type {
return c.TypeName
}
}

return ref
}
78 changes: 58 additions & 20 deletions gen/gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ func Run[T, C, I any](ctx context.Context, s *State[C], driver drivers.Interface
data := &TemplateData[T, C, I]{
Dialect: driver.Dialect(),
Tables: dbInfo.Tables,
QueryFolders: dbInfo.QueryFolders,
Enums: dbInfo.Enums,
ExtraInfo: dbInfo.ExtraInfo,
Aliases: s.Config.Aliases,
Expand Down Expand Up @@ -162,17 +163,14 @@ func generate[T, C, I any](s *State[C], data *TemplateData[T, C, I], goVersion s
templateHeaderByteBuffer := &bytes.Buffer{}

for _, o := range s.Outputs {
if len(o.Templates) == 0 {
continue
}

if _, ok := knownKeys[o.Key]; ok {
return fmt.Errorf("Duplicate output key: %q", o.Key)
}
knownKeys[o.Key] = struct{}{}

// set the package name for this output
data.PkgName = o.PkgName
if len(o.Templates) == 0 {
continue
}

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

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

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

if err := generateSingletonOutput(o, data, goVersion, s.Config.NoTests); err != nil {
return fmt.Errorf("singleton template output: %w", err)
if !yield(struct{}{}) {
return
}
}
}
}

dirExtMap := groupTemplates(o.tableTemplates)
for range iterator {
// set the package name for this output
data.PkgName = o.PkgName

if err := o.initOutFolders(s.Config.Wipe); err != nil {
return fmt.Errorf("unable to initialize the output folders: %w", err)
}

// assign reusable scratch buffers to provided Output
o.templateByteBuffer = templateByteBuffer
o.templateHeaderByteBuffer = templateHeaderByteBuffer

if err := generateSingletonOutput(o, data, goVersion, s.Config.NoTests); err != nil {
return fmt.Errorf("singleton template output: %w", err)
}

dirExtMap := groupTemplates(o.tableTemplates)

for _, table := range data.Tables {
data.Table = table

// Generate the regular templates
if err := generateOutput(o, dirExtMap, o.tableTemplates, data, goVersion, s.Config.NoTests); err != nil {
return fmt.Errorf("unable to generate output: %w", err)
}
}

if len(data.QueryFolder.Files) == 0 {
continue
}

dirExtMap = groupTemplates(o.queryTemplates)
for _, file := range data.QueryFolder.Files {
data.QueryFile = file

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

// Generate the regular templates
if err := generateOutput(o, dirExtMap, data, goVersion, s.Config.NoTests); err != nil {
return fmt.Errorf("unable to generate output: %w", err)
if err := generateOutput(o, dirExtMap, o.queryTemplates, data, goVersion, s.Config.NoTests); err != nil {
return fmt.Errorf("unable to generate output: %w", err)
}
}
}
}
Expand Down
Loading

0 comments on commit 1da2c27

Please sign in to comment.