Skip to content

Commit

Permalink
attempt to do a better job passing plugin-specific override information
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewmbenton committed Oct 27, 2023
1 parent 9c7d17d commit bcbe477
Show file tree
Hide file tree
Showing 8 changed files with 373 additions and 309 deletions.
26 changes: 25 additions & 1 deletion internal/cmd/shim.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package cmd

import (
"encoding/json"
"fmt"
"strings"

gopluginopts "github.com/sqlc-dev/sqlc/internal/codegen/golang/opts"
"github.com/sqlc-dev/sqlc/internal/compiler"
"github.com/sqlc-dev/sqlc/internal/config"
"github.com/sqlc-dev/sqlc/internal/config/convert"
Expand Down Expand Up @@ -34,18 +37,39 @@ func pluginOverride(r *compiler.Result, o config.Override) *plugin.Override {
}
}

var options []byte
var err error
if o.Options.IsZero() {
// Send go-specific override information to the go codegen plugin
options, err = json.Marshal(gopluginopts.OverrideOptions{
GoType: o.GoType,
GoStructTag: o.GoStructTag,
})
if err != nil {
panic(err) // TODO don't panic, return err
}
} else {
options, err = convert.YAMLtoJSON(o.Options)
if err != nil {
panic(err)
}

fmt.Printf(">>> %s", string(options))
}

return &plugin.Override{
CodeType: o.CodeType,
DbType: o.DBType,
Nullable: o.Nullable,
Unsigned: o.Unsigned,
Column: o.Column,
ColumnName: column,
Table: &table,
Options: options,
}
}

func pluginSettings(r *compiler.Result, cs config.CombinedSettings) *plugin.Settings {
// TODO only send overrides meant for this plugin
var over []*plugin.Override
for _, o := range cs.Overrides {
over = append(over, pluginOverride(r, o))
Expand Down
19 changes: 13 additions & 6 deletions internal/codegen/golang/opts/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,22 +49,29 @@ func ParseOpts(req *plugin.CodeGenRequest) (*Options, error) {
var options *Options
dec := json.NewDecoder(bytes.NewReader(req.PluginOptions))
dec.DisallowUnknownFields()
fmt.Printf("### %s", string(req.PluginOptions))
if err := dec.Decode(&options); err != nil {
return options, fmt.Errorf("unmarshalling options: %w", err)
}

for _, override := range req.Settings.Overrides {
var actualOverride Override
if err := json.Unmarshal(override.CodeType, &actualOverride); err != nil {
var overrideOpts OverrideOptions
if err := json.Unmarshal(override.Options, &overrideOpts); err != nil {
return options, err
}
if err := actualOverride.Parse(); err != nil {
parsedGoType, err := overrideOpts.GoType.Parse()
if err != nil {
return options, err
}
options.Overrides = append(options.Overrides, NewGoOverride(
parsedGoStructTags, err := overrideOpts.GoStructTag.Parse()
if err != nil {
return options, err
}
parsedGoType.StructTags = parsedGoStructTags
options.Overrides = append(options.Overrides, GoOverride{
override,
actualOverride,
))
parsedGoType,
})
}

// in sqlc config.Combine() the "package"-level overrides were appended to
Expand Down
9 changes: 9 additions & 0 deletions internal/codegen/golang/opts/override.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ type Override struct {

// Parsed form of GoStructTag, e.g. {"validate:", "required"}
GoStructTags map[string]string `json:"-"`

// For passing plugin-specific configuration
Plugin string `json:"plugin"` // Irrelevant here in the plugin context
Options OverrideOptions `json:"options"`
}

type OverrideOptions struct {
GoType GoType `json:"go_type"`
GoStructTag GoStructTag `json:"go_struct_tag"`
}

func (o *Override) Parse() (err error) {
Expand Down
44 changes: 0 additions & 44 deletions internal/config/go_type.go
Original file line number Diff line number Diff line change
@@ -1,45 +1 @@
package config

import (
"encoding/json"
)

type GoType struct {
Path string `json:"import" yaml:"import"`
Package string `json:"package" yaml:"package"`
Name string `json:"type" yaml:"type"`
Pointer bool `json:"pointer" yaml:"pointer"`
Slice bool `json:"slice" yaml:"slice"`
Spec string
BuiltIn bool
}

func (o *GoType) UnmarshalJSON(data []byte) error {
var spec string
if err := json.Unmarshal(data, &spec); err == nil {
*o = GoType{Spec: spec}
return nil
}
type alias GoType
var a alias
if err := json.Unmarshal(data, &a); err != nil {
return err
}
*o = GoType(a)
return nil
}

func (o *GoType) UnmarshalYAML(unmarshal func(interface{}) error) error {
var spec string
if err := unmarshal(&spec); err == nil {
*o = GoType{Spec: spec}
return nil
}
type alias GoType
var a alias
if err := unmarshal(&a); err != nil {
return err
}
*o = GoType(a)
return nil
}
30 changes: 17 additions & 13 deletions internal/config/override.go
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
package config

import (
"encoding/json"
"fmt"
"os"
"strings"

gopluginopts "github.com/sqlc-dev/sqlc/internal/codegen/golang/opts"
"github.com/sqlc-dev/sqlc/internal/pattern"
"gopkg.in/yaml.v3"
)

type Override struct {
// name of the golang type to use, e.g. `github.com/segmentio/ksuid.KSUID`
GoType GoType `json:"go_type" yaml:"go_type"`
GoType gopluginopts.GoType `json:"go_type" yaml:"go_type"`

// additional Go struct tags to add to this field, in raw Go struct tag form, e.g. `validate:"required" x:"y,z"`
// see https://github.com/sqlc-dev/sqlc/issues/534
GoStructTag string `json:"go_struct_tag" yaml:"go_struct_tag"`
GoStructTag gopluginopts.GoStructTag `json:"go_struct_tag" yaml:"go_struct_tag"`

// fully qualified name of the Go type, e.g. `github.com/segmentio/ksuid.KSUID`
DBType string `json:"db_type" yaml:"db_type"`
Expand All @@ -42,7 +43,17 @@ type Override struct {
TableRel *pattern.Match `json:"-"`

// For passing plugin-specific configuration
CodeType []byte `json:"-"`
Plugin string `json:"plugin,omitempty"`
Options yaml.Node `json:"options,omitempty"`
}

func (o Override) hasGoOptions() bool {
hasGoTypePath := o.GoType.Path != ""
hasGoTypePackage := o.GoType.Package != ""
hasGoTypeName := o.GoType.Name != ""
hasGoType := hasGoTypePath || hasGoTypePackage || hasGoTypeName
hasGoStructTag := o.GoStructTag != ""
return hasGoType || hasGoStructTag
}

func (o *Override) Parse() (err error) {
Expand All @@ -67,6 +78,8 @@ func (o *Override) Parse() (err error) {
return fmt.Errorf("Override specifying both `column` (%q) and `db_type` (%q) is not valid.", o.Column, o.DBType)
case o.Column == "" && o.DBType == "":
return fmt.Errorf("Override must specify one of either `column` or `db_type`")
case o.hasGoOptions() && !o.Options.IsZero():
return fmt.Errorf("Override can specify go_type/go_struct_tag or options but not both")
}

// validate Column
Expand Down Expand Up @@ -111,14 +124,5 @@ func (o *Override) Parse() (err error) {
}
}

// A simple way to get stuff into the Go codegen plugin so that
// we can just call Parse() again in there
codeType, err := json.Marshal(o)
if err != nil {
return err
}

o.CodeType = codeType

return nil
}
Loading

0 comments on commit bcbe477

Please sign in to comment.