Skip to content

Commit ff349b0

Browse files
authored
Add version to configuration file (#116)
* Add required version number to configuration file `sqlc generate` now errors in the following cases: - The required version number is empty or not equal to "1" - There are zero packages configured - An unknown key exists in the configuration file
1 parent 5454832 commit ff349b0

6 files changed

Lines changed: 138 additions & 28 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,7 @@ in the directory where the `sqlc` command is run.
269269

270270
```json
271271
{
272+
"version": "1",
272273
"packages": [
273274
{
274275
"name": "db",

internal/cmd/cmd.go

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"bytes"
45
"encoding/json"
56
"fmt"
67
"io"
@@ -74,14 +75,29 @@ var initCmd = &cobra.Command{
7475
if _, err := os.Stat("sqlc.json"); !os.IsNotExist(err) {
7576
return nil
7677
}
77-
blob, err := json.MarshalIndent(dinosql.GenerateSettings{}, " ", "")
78+
blob, err := json.MarshalIndent(dinosql.GenerateSettings{Version: "1"}, "", " ")
7879
if err != nil {
7980
return err
8081
}
8182
return ioutil.WriteFile("sqlc.json", blob, 0644)
8283
},
8384
}
8485

86+
const errMessageNoVersion = `The configuration file must have a version number.
87+
Set the version to 1 at the top of sqlc.json:
88+
89+
{
90+
"version": "1"
91+
...
92+
}
93+
`
94+
95+
const errMessageUnknownVersion = `The configuration file has an invalid version number.
96+
The only supported version is "1".
97+
`
98+
99+
const errMessageNoPackages = `No packages are configured`
100+
85101
var genCmd = &cobra.Command{
86102
Use: "generate",
87103
Short: "Generate Go code from SQL",
@@ -92,19 +108,17 @@ var genCmd = &cobra.Command{
92108
os.Exit(1)
93109
}
94110

95-
var settings dinosql.GenerateSettings
96-
if err := json.Unmarshal(blob, &settings); err != nil {
97-
switch err.(type) {
98-
// TODO: Provide better error messages for sqlc.json parsing
99-
// case *json.SyntaxError:
100-
// case *json.InvalidUnmarshalError:
101-
// case *json.UnmarshalFieldError:
102-
// case *json.UnmarshalTypeError:
103-
// case *json.UnsupportedTypeError:
104-
// case *json.UnsupportedValueError:
105-
default:
106-
fmt.Fprintf(os.Stderr, "error parsing sqlc.json: %s\n", err)
111+
settings, err := dinosql.ParseConfig(bytes.NewReader(blob))
112+
if err != nil {
113+
switch err {
114+
case dinosql.ErrMissingVersion:
115+
fmt.Fprintf(os.Stderr, errMessageNoVersion)
116+
case dinosql.ErrUnknownVersion:
117+
fmt.Fprintf(os.Stderr, errMessageUnknownVersion)
118+
case dinosql.ErrNoPackages:
119+
fmt.Fprintf(os.Stderr, errMessageNoPackages)
107120
}
121+
fmt.Fprintf(os.Stderr, "error parsing sqlc.json: %s\n", err)
108122
os.Exit(1)
109123
}
110124

internal/dinosql/config.go

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
package dinosql
2+
3+
import (
4+
"encoding/json"
5+
"errors"
6+
"io"
7+
)
8+
9+
type PackageSettings struct {
10+
Name string `json:"name"`
11+
Path string `json:"path"`
12+
Schema string `json:"schema"`
13+
Queries string `json:"queries"`
14+
EmitPreparedQueries bool `json:"emit_prepared_queries"`
15+
EmitJSONTags bool `json:"emit_json_tags"`
16+
}
17+
18+
type GenerateSettings struct {
19+
Version string `json:"version"`
20+
Packages []PackageSettings `json:"packages"`
21+
Overrides []TypeOverride `json:"overrides,omitempty"`
22+
Rename map[string]string `json:"rename,omitempty"`
23+
}
24+
25+
var ErrMissingVersion = errors.New("no version number")
26+
var ErrUnknownVersion = errors.New("invalid version number")
27+
var ErrNoPackages = errors.New("no packages")
28+
29+
func ParseConfig(rd io.Reader) (GenerateSettings, error) {
30+
dec := json.NewDecoder(rd)
31+
dec.DisallowUnknownFields()
32+
var config GenerateSettings
33+
if err := dec.Decode(&config); err != nil {
34+
return config, err
35+
}
36+
if config.Version == "" {
37+
return config, ErrMissingVersion
38+
}
39+
if config.Version != "1" {
40+
return config, ErrUnknownVersion
41+
}
42+
if len(config.Packages) == 0 {
43+
return config, ErrNoPackages
44+
}
45+
return config, nil
46+
}

internal/dinosql/config_test.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package dinosql
2+
3+
import (
4+
"strings"
5+
"testing"
6+
7+
"github.com/google/go-cmp/cmp"
8+
)
9+
10+
const missingVersion = `{
11+
}`
12+
13+
const missingPackages = `{
14+
"version": "1"
15+
}`
16+
17+
const unknownVersion = `{
18+
"version": "foo"
19+
}`
20+
21+
const unknownFields = `{
22+
"foo": "bar"
23+
}`
24+
25+
func TestBadConfigs(t *testing.T) {
26+
for _, test := range []struct {
27+
name string
28+
err string
29+
json string
30+
}{
31+
{
32+
"missing version",
33+
"no version number",
34+
missingVersion,
35+
},
36+
{
37+
"missing packages",
38+
"no packages",
39+
missingPackages,
40+
},
41+
{
42+
"unknown version",
43+
"invalid version number",
44+
unknownVersion,
45+
},
46+
{
47+
"unknown fields",
48+
"json: unknown field \"foo\"",
49+
unknownFields,
50+
},
51+
} {
52+
tt := test
53+
t.Run(tt.name, func(t *testing.T) {
54+
_, err := ParseConfig(strings.NewReader(tt.json))
55+
if err == nil {
56+
t.Fatalf("expected err; got nil")
57+
}
58+
if diff := cmp.Diff(err.Error(), tt.err); diff != "" {
59+
t.Errorf("differed (-want +got):\n%s", diff)
60+
}
61+
})
62+
}
63+
}

internal/dinosql/parser.go

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -997,18 +997,3 @@ type TypeOverride struct {
997997
GoType string `json:"go_type"`
998998
Null bool `json:"null"`
999999
}
1000-
1001-
type PackageSettings struct {
1002-
Name string `json:"name"`
1003-
Path string `json:"path"`
1004-
Schema string `json:"schema"`
1005-
Queries string `json:"queries"`
1006-
EmitPreparedQueries bool `json:"emit_prepared_queries"`
1007-
EmitJSONTags bool `json:"emit_json_tags"`
1008-
}
1009-
1010-
type GenerateSettings struct {
1011-
Packages []PackageSettings `json:"packages"`
1012-
Overrides []TypeOverride `json:"overrides"`
1013-
Rename map[string]string `json:"rename"`
1014-
}

internal/dinosql/testdata/ondeck/sqlc.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"version": "1",
23
"packages": [
34
{
45
"name": "ondeck",

0 commit comments

Comments
 (0)