Skip to content
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor go codegen to plugin types #1460

Merged
merged 7 commits into from Mar 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion internal/cmd/generate.go
Expand Up @@ -193,7 +193,7 @@ func Generate(ctx context.Context, e Env, dir, filename string, stderr io.Writer
switch {
case sql.Gen.Go != nil:
out = combo.Go.Out
files, err = golang.Generate(result, combo)
resp, err = golang.Generate(codeGenRequest(result, combo))
case sql.Gen.Kotlin != nil:
out = combo.Kotlin.Out
resp, err = kotlin.Generate(codeGenRequest(result, combo))
Expand Down
103 changes: 79 additions & 24 deletions internal/cmd/shim.go
Expand Up @@ -39,6 +39,7 @@ func pluginOverride(o config.Override) *plugin.Override {
ColumnName: column,
Table: &table,
PythonType: pluginPythonType(o.PythonType),
GoType: pluginGoType(o),
}
}

Expand All @@ -56,6 +57,7 @@ func pluginSettings(cs config.CombinedSettings) *plugin.Settings {
Rename: cs.Rename,
Python: pluginPythonCode(cs.Python),
Kotlin: pluginKotlinCode(cs.Kotlin),
Go: pluginGoCode(cs.Go),
}
}

Expand All @@ -69,6 +71,42 @@ func pluginPythonCode(s config.SQLPython) *plugin.PythonCode {
}
}

func pluginGoCode(s config.SQLGo) *plugin.GoCode {
return &plugin.GoCode{
EmitInterface: s.EmitInterface,
EmitJsonTags: s.EmitJSONTags,
stephen marked this conversation as resolved.
Show resolved Hide resolved
EmitDbTags: s.EmitDBTags,
EmitPreparedQueries: s.EmitPreparedQueries,
EmitExactTableNames: s.EmitExactTableNames,
EmitEmptySlices: s.EmitEmptySlices,
EmitExportedQueries: s.EmitExportedQueries,
EmitResultStructPointers: s.EmitResultStructPointers,
EmitParamsStructPointers: s.EmitParamsStructPointers,
EmitMethodsWithDbArgument: s.EmitMethodsWithDBArgument,
JsonTagsCaseStyle: s.JSONTagsCaseStyle,
Package: s.Package,
Out: s.Out,
SqlPackage: s.SQLPackage,
OutputDbFileName: s.OutputDBFileName,
OutputModelsFileName: s.OutputModelsFileName,
OutputQuerierFileName: s.OutputQuerierFileName,
OutputFilesSuffix: s.OutputFilesSuffix,
}
}

func pluginGoType(o config.Override) *plugin.ParsedGoType {
// Note that there is a slight mismatch between this and the
// proto api. The GoType on the override is the unparsed type,
// which could be a qualified path or an object, as per
// https://docs.sqlc.dev/en/latest/reference/config.html#renaming-struct-fields
kyleconroy marked this conversation as resolved.
Show resolved Hide resolved
return &plugin.ParsedGoType{
ImportPath: o.GoImportPath,
Package: o.GoPackage,
TypeName: o.GoTypeName,
BasicType: o.GoBasicType,
}
}

func pluginPythonType(pt config.PythonType) *plugin.PythonType {
return &plugin.PythonType{
Module: pt.Module,
Expand All @@ -88,16 +126,21 @@ func pluginCatalog(c *catalog.Catalog) *plugin.Catalog {
var schemas []*plugin.Schema
for _, s := range c.Schemas {
var enums []*plugin.Enum
var cts []*plugin.CompositeType
for _, typ := range s.Types {
enum, ok := typ.(*catalog.Enum)
if !ok {
continue
switch typ := typ.(type) {
case *catalog.Enum:
enums = append(enums, &plugin.Enum{
Name: typ.Name,
Comment: typ.Comment,
Vals: typ.Vals,
})
case *catalog.CompositeType:
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i assume the proto has Enums instead of Types because it it hard to represent a Enum | CompositeType in proto. this could also be a oneof maybe

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're correct that oneof is the correct way to handle this type of polymorphism. You can see this in the Python AST proto file. For now I'm happy to keep these as two separate arrays.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah thanks, i missed the existing usage of oneof. i am happy to keep this as is or take a suggested refactor

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fine to keep this for now

cts = append(cts, &plugin.CompositeType{
Name: typ.Name,
Comment: typ.Comment,
})
}
enums = append(enums, &plugin.Enum{
Name: enum.Name,
Comment: enum.Comment,
Vals: enum.Vals,
})
}
var tables []*plugin.Table
for _, t := range s.Tables {
Expand Down Expand Up @@ -136,10 +179,11 @@ func pluginCatalog(c *catalog.Catalog) *plugin.Catalog {
})
}
schemas = append(schemas, &plugin.Schema{
Comment: s.Comment,
Name: s.Name,
Tables: tables,
Enums: enums,
Comment: s.Comment,
Name: s.Name,
Tables: tables,
Enums: enums,
CompositeTypes: cts,
})
}
return &plugin.Catalog{
Expand All @@ -161,14 +205,23 @@ func pluginQueries(r *compiler.Result) []*plugin.Query {
for _, p := range q.Params {
params = append(params, pluginQueryParam(p))
}
var iit *plugin.Identifier
if q.InsertIntoTable != nil {
iit = &plugin.Identifier{
stephen marked this conversation as resolved.
Show resolved Hide resolved
Catalog: q.InsertIntoTable.Catalog,
Schema: q.InsertIntoTable.Schema,
Name: q.InsertIntoTable.Name,
}
}
out = append(out, &plugin.Query{
Name: q.Name,
Cmd: q.Cmd,
Text: q.SQL,
Comments: q.Comments,
Columns: columns,
Params: params,
Filename: q.Filename,
Name: q.Name,
Cmd: q.Cmd,
Text: q.SQL,
Comments: q.Comments,
Columns: columns,
Params: params,
Filename: q.Filename,
InsertIntoTable: iit,
})
}
return out
Expand All @@ -180,11 +233,13 @@ func pluginQueryColumn(c *compiler.Column) *plugin.Column {
l = *c.Length
}
out := &plugin.Column{
Name: c.Name,
Comment: c.Comment,
NotNull: c.NotNull,
IsArray: c.IsArray,
Length: int32(l),
Name: c.Name,
Comment: c.Comment,
NotNull: c.NotNull,
IsArray: c.IsArray,
Length: int32(l),
IsNamedParam: c.IsNamedParam,
IsFuncCall: c.IsFuncCall,
}

if c.Type != nil {
Expand Down
13 changes: 6 additions & 7 deletions internal/codegen/golang/compat.go
@@ -1,17 +1,16 @@
package golang

import (
"github.com/kyleconroy/sqlc/internal/core"
"github.com/kyleconroy/sqlc/internal/sql/ast"
"github.com/kyleconroy/sqlc/internal/plugin"
)

func sameTableName(n *ast.TableName, f core.FQN, defaultSchema string) bool {
if n == nil {
func sameTableName(tableID, f *plugin.Identifier, defaultSchema string) bool {
if tableID == nil {
return false
}
schema := n.Schema
if n.Schema == "" {
schema := tableID.Schema
if tableID.Schema == "" {
schema = defaultSchema
}
return n.Catalog == f.Catalog && schema == f.Schema && n.Name == f.Rel
return tableID.Catalog == f.Catalog && schema == f.Schema && tableID.Name == f.Name
}
8 changes: 5 additions & 3 deletions internal/codegen/golang/driver.go
@@ -1,6 +1,8 @@
package golang

import "github.com/kyleconroy/sqlc/internal/config"
import (
"github.com/kyleconroy/sqlc/internal/plugin"
)

type SQLDriver int

Expand All @@ -9,8 +11,8 @@ const (
SQLDriverLibPQ
)

func parseDriver(settings config.CombinedSettings) SQLDriver {
if settings.Go.SQLPackage == "pgx/v4" {
func parseDriver(settings *plugin.Settings) SQLDriver {
if settings.Go.SqlPackage == "pgx/v4" {
return SQLDriverPGXV4
} else {
return SQLDriverLibPQ
Expand Down
6 changes: 3 additions & 3 deletions internal/codegen/golang/field.go
Expand Up @@ -5,7 +5,7 @@ import (
"sort"
"strings"

"github.com/kyleconroy/sqlc/internal/config"
"github.com/kyleconroy/sqlc/internal/plugin"
)

type Field struct {
Expand All @@ -28,8 +28,8 @@ func (gf Field) Tag() string {
return strings.Join(tags, " ")
}

func JSONTagName(name string, settings config.CombinedSettings) string {
style := settings.Go.JSONTagsCaseStyle
func JSONTagName(name string, settings *plugin.Settings) string {
style := settings.Go.JsonTagsCaseStyle
if style == "" || style == "none" {
return name
} else {
Expand Down
50 changes: 25 additions & 25 deletions internal/codegen/golang/gen.go
Expand Up @@ -10,25 +10,17 @@ import (
"text/template"

"github.com/kyleconroy/sqlc/internal/codegen"
"github.com/kyleconroy/sqlc/internal/compiler"
"github.com/kyleconroy/sqlc/internal/config"
"github.com/kyleconroy/sqlc/internal/metadata"
"github.com/kyleconroy/sqlc/internal/plugin"
)

type Generateable interface {
Structs(settings config.CombinedSettings) []Struct
GoQueries(settings config.CombinedSettings) []Query
Enums(settings config.CombinedSettings) []Enum
}

type tmplCtx struct {
Q string
Package string
SQLPackage SQLPackage
Enums []Enum
Structs []Struct
GoQueries []Query
Settings config.Config
stephen marked this conversation as resolved.
Show resolved Hide resolved

// TODO: Race conditions
SourceName string
Expand All @@ -47,19 +39,19 @@ func (t *tmplCtx) OutputQuery(sourceName string) bool {
return t.SourceName == sourceName
}

func Generate(r *compiler.Result, settings config.CombinedSettings) (map[string]string, error) {
enums := buildEnums(r, settings)
structs := buildStructs(r, settings)
queries, err := buildQueries(r, settings, structs)
func Generate(req *plugin.CodeGenRequest) (*plugin.CodeGenResponse, error) {
enums := buildEnums(req)
structs := buildStructs(req)
queries, err := buildQueries(req, structs)
if err != nil {
return nil, err
}
return generate(settings, enums, structs, queries)
return generate(req, enums, structs, queries)
}

func generate(settings config.CombinedSettings, enums []Enum, structs []Struct, queries []Query) (map[string]string, error) {
func generate(req *plugin.CodeGenRequest, enums []Enum, structs []Struct, queries []Query) (*plugin.CodeGenResponse, error) {
i := &importer{
Settings: settings,
Settings: req.Settings,
Queries: queries,
Enums: enums,
Structs: structs,
Expand All @@ -83,18 +75,17 @@ func generate(settings config.CombinedSettings, enums []Enum, structs []Struct,
),
)

golang := settings.Go
golang := req.Settings.Go
tctx := tmplCtx{
Settings: settings.Global,
EmitInterface: golang.EmitInterface,
EmitJSONTags: golang.EmitJSONTags,
EmitDBTags: golang.EmitDBTags,
EmitJSONTags: golang.EmitJsonTags,
EmitDBTags: golang.EmitDbTags,
EmitPreparedQueries: golang.EmitPreparedQueries,
EmitEmptySlices: golang.EmitEmptySlices,
EmitMethodsWithDBArgument: golang.EmitMethodsWithDBArgument,
EmitMethodsWithDBArgument: golang.EmitMethodsWithDbArgument,
UsesCopyFrom: usesCopyFrom(queries),
UsesBatch: usesBatch(queries),
SQLPackage: SQLPackageFromString(golang.SQLPackage),
SQLPackage: SQLPackageFromString(golang.SqlPackage),
Q: "`",
Package: golang.Package,
GoQueries: queries,
Expand Down Expand Up @@ -139,8 +130,8 @@ func generate(settings config.CombinedSettings, enums []Enum, structs []Struct,
}

dbFileName := "db.go"
if golang.OutputDBFileName != "" {
dbFileName = golang.OutputDBFileName
if golang.OutputDbFileName != "" {
dbFileName = golang.OutputDbFileName
}
modelsFileName := "models.go"
if golang.OutputModelsFileName != "" {
Expand Down Expand Up @@ -187,7 +178,16 @@ func generate(settings config.CombinedSettings, enums []Enum, structs []Struct,
return nil, err
}
}
return output, nil
resp := plugin.CodeGenResponse{}

for filename, code := range output {
resp.Files = append(resp.Files, &plugin.File{
Name: filename,
Contents: []byte(code),
})
}

return &resp, nil
}

func usesCopyFrom(queries []Query) bool {
Expand Down