From 9740bdd5424bc5fc6e15a8a140d157c5d20a0e10 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sat, 25 Jan 2020 11:33:33 -0700 Subject: [PATCH 1/4] Factor out generate guts --- internal/cmd/cmd.go | 113 ++-------------------------------- internal/cmd/generate.go | 127 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 132 insertions(+), 108 deletions(-) create mode 100644 internal/cmd/generate.go diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index d589c3446b..487deb07ef 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -1,7 +1,6 @@ package cmd import ( - "bytes" "encoding/json" "fmt" "io" @@ -11,7 +10,6 @@ import ( "path/filepath" "github.com/kyleconroy/sqlc/internal/dinosql" - "github.com/kyleconroy/sqlc/internal/mysql" "github.com/davecgh/go-spew/spew" pg "github.com/lfittl/pg_query_go" @@ -84,127 +82,26 @@ var initCmd = &cobra.Command{ }, } -const errMessageNoVersion = `The configuration file must have a version number. -Set the version to 1 at the top of sqlc.json: - -{ - "version": "1" - ... -} -` - -const errMessageUnknownVersion = `The configuration file has an invalid version number. -The only supported version is "1". -` - -const errMessageNoPackages = `No packages are configured` - var genCmd = &cobra.Command{ Use: "generate", Short: "Generate Go code from SQL", Run: func(cmd *cobra.Command, args []string) { - blob, err := ioutil.ReadFile("sqlc.json") + stderr := cmd.ErrOrStderr() + dir, err := os.Getwd() if err != nil { - fmt.Fprintln(os.Stderr, "error parsing sqlc.json: file does not exist") + fmt.Fprintln(stderr, "error parsing sqlc.json: file does not exist") os.Exit(1) } - settings, err := dinosql.ParseConfig(bytes.NewReader(blob)) + output, err := Generate(dir, stderr) if err != nil { - switch err { - case dinosql.ErrMissingVersion: - fmt.Fprintf(os.Stderr, errMessageNoVersion) - case dinosql.ErrUnknownVersion: - fmt.Fprintf(os.Stderr, errMessageUnknownVersion) - case dinosql.ErrNoPackages: - fmt.Fprintf(os.Stderr, errMessageNoPackages) - } - fmt.Fprintf(os.Stderr, "error parsing sqlc.json: %s\n", err) - os.Exit(1) - } - - var errored bool - - output := map[string]string{} - - for _, pkg := range settings.Packages { - name := pkg.Name - combo := dinosql.Combine(settings, pkg) - var result dinosql.Generateable - - switch pkg.Engine { - - case dinosql.EngineMySQL: - // Experimental MySQL support - q, err := mysql.GeneratePkg(name, pkg.Schema, pkg.Queries, combo) - if err != nil { - fmt.Fprintf(os.Stderr, "# package %s\n", name) - if parserErr, ok := err.(*dinosql.ParserErr); ok { - for _, fileErr := range parserErr.Errs { - fmt.Fprintf(os.Stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err) - } - } else { - fmt.Fprintf(os.Stderr, "error parsing schema: %s\n", err) - } - errored = true - continue - } - result = q - - case dinosql.EnginePostgreSQL: - c, err := dinosql.ParseCatalog(pkg.Schema) - if err != nil { - fmt.Fprintf(os.Stderr, "# package %s\n", name) - if parserErr, ok := err.(*dinosql.ParserErr); ok { - for _, fileErr := range parserErr.Errs { - fmt.Fprintf(os.Stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err) - } - } else { - fmt.Fprintf(os.Stderr, "error parsing schema: %s\n", err) - } - errored = true - continue - } - - q, err := dinosql.ParseQueries(c, pkg) - if err != nil { - fmt.Fprintf(os.Stderr, "# package %s\n", name) - if parserErr, ok := err.(*dinosql.ParserErr); ok { - for _, fileErr := range parserErr.Errs { - fmt.Fprintf(os.Stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err) - } - } else { - fmt.Fprintf(os.Stderr, "error parsing queries: %s\n", err) - } - errored = true - continue - } - result = q - - } - - files, err := dinosql.Generate(result, combo) - if err != nil { - fmt.Fprintf(os.Stderr, "# package %s\n", name) - fmt.Fprintf(os.Stderr, "error generating code: %s\n", err) - errored = true - continue - } - - for n, source := range files { - filename := filepath.Join(pkg.Path, n) - output[filename] = source - } - } - - if errored { os.Exit(1) } for filename, source := range output { os.MkdirAll(filepath.Dir(filename), 0755) if err := ioutil.WriteFile(filename, []byte(source), 0644); err != nil { - fmt.Fprintf(os.Stderr, "%s: %s\n", filename, err) + fmt.Fprintf(stderr, "%s: %s\n", filename, err) os.Exit(1) } } diff --git a/internal/cmd/generate.go b/internal/cmd/generate.go new file mode 100644 index 0000000000..ba3f07907d --- /dev/null +++ b/internal/cmd/generate.go @@ -0,0 +1,127 @@ +package cmd + +import ( + "bytes" + "fmt" + "io" + "io/ioutil" + "path/filepath" + + "github.com/kyleconroy/sqlc/internal/dinosql" + "github.com/kyleconroy/sqlc/internal/mysql" +) + +const errMessageNoVersion = `The configuration file must have a version number. +Set the version to 1 at the top of sqlc.json: + +{ + "version": "1" + ... +} +` + +const errMessageUnknownVersion = `The configuration file has an invalid version number. +The only supported version is "1". +` + +const errMessageNoPackages = `No packages are configured` + +func Generate(dir string, stderr io.Writer) (map[string]string, error) { + blob, err := ioutil.ReadFile(filepath.Join(dir, "sqlc.json")) + if err != nil { + fmt.Fprintln(stderr, "error parsing sqlc.json: file does not exist") + return nil, err + } + + settings, err := dinosql.ParseConfig(bytes.NewReader(blob)) + if err != nil { + switch err { + case dinosql.ErrMissingVersion: + fmt.Fprintf(stderr, errMessageNoVersion) + case dinosql.ErrUnknownVersion: + fmt.Fprintf(stderr, errMessageUnknownVersion) + case dinosql.ErrNoPackages: + fmt.Fprintf(stderr, errMessageNoPackages) + } + fmt.Fprintf(stderr, "error parsing sqlc.json: %s\n", err) + return nil, err + } + + output := map[string]string{} + errored := false + + for _, pkg := range settings.Packages { + name := pkg.Name + combo := dinosql.Combine(settings, pkg) + var result dinosql.Generateable + + switch pkg.Engine { + + case dinosql.EngineMySQL: + // Experimental MySQL support + q, err := mysql.GeneratePkg(name, pkg.Schema, pkg.Queries, combo) + if err != nil { + fmt.Fprintf(stderr, "# package %s\n", name) + if parserErr, ok := err.(*dinosql.ParserErr); ok { + for _, fileErr := range parserErr.Errs { + fmt.Fprintf(stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err) + } + } else { + fmt.Fprintf(stderr, "error parsing schema: %s\n", err) + } + errored = true + continue + } + result = q + + case dinosql.EnginePostgreSQL: + c, err := dinosql.ParseCatalog(pkg.Schema) + if err != nil { + fmt.Fprintf(stderr, "# package %s\n", name) + if parserErr, ok := err.(*dinosql.ParserErr); ok { + for _, fileErr := range parserErr.Errs { + fmt.Fprintf(stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err) + } + } else { + fmt.Fprintf(stderr, "error parsing schema: %s\n", err) + } + errored = true + continue + } + + q, err := dinosql.ParseQueries(c, pkg) + if err != nil { + fmt.Fprintf(stderr, "# package %s\n", name) + if parserErr, ok := err.(*dinosql.ParserErr); ok { + for _, fileErr := range parserErr.Errs { + fmt.Fprintf(stderr, "%s:%d:%d: %s\n", fileErr.Filename, fileErr.Line, fileErr.Column, fileErr.Err) + } + } else { + fmt.Fprintf(stderr, "error parsing queries: %s\n", err) + } + errored = true + continue + } + result = q + + } + + files, err := dinosql.Generate(result, combo) + if err != nil { + fmt.Fprintf(stderr, "# package %s\n", name) + fmt.Fprintf(stderr, "error generating code: %s\n", err) + errored = true + continue + } + + for n, source := range files { + filename := filepath.Join(pkg.Path, n) + output[filename] = source + } + } + + if errored { + return nil, fmt.Errorf("errored") + } + return output, nil +} From 6c4cc94fc2c0612586ef2fcf0e947e245bbd3323 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sat, 25 Jan 2020 12:00:53 -0700 Subject: [PATCH 2/4] Redo the end-to-end test --- internal/cmd/generate.go | 6 +- internal/endtoend/endtoend_test.go | 90 ++++++++++-------------------- 2 files changed, 35 insertions(+), 61 deletions(-) diff --git a/internal/cmd/generate.go b/internal/cmd/generate.go index ba3f07907d..da4cfa8c4b 100644 --- a/internal/cmd/generate.go +++ b/internal/cmd/generate.go @@ -55,6 +55,10 @@ func Generate(dir string, stderr io.Writer) (map[string]string, error) { combo := dinosql.Combine(settings, pkg) var result dinosql.Generateable + // TODO: This feels like a hack that will bite us later + pkg.Schema = filepath.Join(dir, pkg.Schema) + pkg.Queries = filepath.Join(dir, pkg.Queries) + switch pkg.Engine { case dinosql.EngineMySQL: @@ -115,7 +119,7 @@ func Generate(dir string, stderr io.Writer) (map[string]string, error) { } for n, source := range files { - filename := filepath.Join(pkg.Path, n) + filename := filepath.Join(dir, pkg.Path, n) output[filename] = source } } diff --git a/internal/endtoend/endtoend_test.go b/internal/endtoend/endtoend_test.go index fe1e446621..dce352692a 100644 --- a/internal/endtoend/endtoend_test.go +++ b/internal/endtoend/endtoend_test.go @@ -1,7 +1,7 @@ package main import ( - "fmt" + "bytes" "io/ioutil" "os" "path/filepath" @@ -9,83 +9,50 @@ import ( "testing" "github.com/google/go-cmp/cmp" - "github.com/kyleconroy/sqlc/internal/dinosql" - "github.com/kyleconroy/sqlc/internal/mysql" + "github.com/kyleconroy/sqlc/internal/cmd" ) func TestCodeGeneration(t *testing.T) { // Change to the top-level directory of the project - os.Chdir(filepath.Join("..", "..", "examples")) + examples, _ := filepath.Abs(filepath.Join("..", "..", "examples")) + var stderr bytes.Buffer - rd, err := os.Open("sqlc.json") + output, err := cmd.Generate(examples, &stderr) if err != nil { - t.Fatal(err) - } - - conf, err := dinosql.ParseConfig(rd) - if err != nil { - t.Fatal(err) - } - - for _, p := range conf.Packages { - pkg := p - t.Run(pkg.Name, func(t *testing.T) { - combo := dinosql.Combine(conf, pkg) - var result dinosql.Generateable - switch pkg.Engine { - case dinosql.EngineMySQL: - q, err := mysql.GeneratePkg(pkg.Name, pkg.Schema, pkg.Queries, combo) - if err != nil { - t.Fatal(err) - } - result = q - case dinosql.EnginePostgreSQL: - c, err := dinosql.ParseCatalog(pkg.Schema) - if err != nil { - fmt.Printf("%#v\n", err) - t.Fatal(err) - } - q, err := dinosql.ParseQueries(c, pkg) - if err != nil { - t.Fatal(err) - } - result = q - } - output, err := dinosql.Generate(result, combo) - if err != nil { - t.Fatal(err) - } - cmpDirectory(t, pkg.Path, output) - }) + t.Fatalf("%s", stderr.String()) } + cmpDirectory(t, examples, output) } func cmpDirectory(t *testing.T, dir string, actual map[string]string) { - t.Helper() - - files, err := ioutil.ReadDir(dir) - if err != nil { - t.Fatalf("error reading dir %s: %s", dir, err) - } - expected := map[string]string{} - - for _, file := range files { + var ff = func(path string, file os.FileInfo, err error) error { + if err != nil { + return err + } if file.IsDir() { - continue + return nil } - if !strings.HasSuffix(file.Name(), ".go") { - continue + if !strings.HasSuffix(path, ".go") { + return nil } - if strings.HasSuffix(file.Name(), "_test.go") { - continue + if strings.HasSuffix(path, "_test.go") { + return nil } - blob, err := ioutil.ReadFile(filepath.Join(dir, file.Name())) + blob, err := ioutil.ReadFile(path) if err != nil { - t.Fatal(err) + return err } - expected[file.Name()] = string(blob) + expected[path] = string(blob) + return nil + } + if err := filepath.Walk(dir, ff); err != nil { + t.Fatal(err) + } + + if len(expected) == 0 { + t.Fatalf("expected output is empty: %s", expected) } if !cmp.Equal(expected, actual) { @@ -99,5 +66,8 @@ func cmpDirectory(t *testing.T, dir string, actual map[string]string) { t.Errorf("%s differed (-want +got):\n%s", name, diff) } } + for name, _ := range actual { + t.Log(name) + } } } From 51f46997695b5355628008c3c590bab412900a56 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sat, 25 Jan 2020 18:09:13 -0700 Subject: [PATCH 3/4] intenral/endtoend: Port gen_test to new test setup The existing tests in `gen_test` were unit tests that tested internal APIs. Port these tests to integration tests, encompassing an entire run of sqlc itself. --- internal/dinosql/gen_test.go | 183 ------------------ internal/endtoend/endtoend_test.go | 48 +++-- internal/endtoend/testdata/datatype/go/db.go | 29 +++ .../endtoend/testdata/datatype/go/models.go | 72 +++++++ .../testdata/datatype/sql/character.sql | 17 ++ .../testdata/datatype/sql/datetime.sql | 23 +++ .../testdata/datatype/sql/numeric.sql | 29 +++ .../endtoend/testdata/datatype/sql/query.sql | 1 + internal/endtoend/testdata/datatype/sqlc.json | 9 + internal/endtoend/testdata/enums/go/db.go | 29 +++ internal/endtoend/testdata/enums/go/models.go | 22 +++ internal/endtoend/testdata/enums/sql/enum.sql | 11 ++ .../endtoend/testdata/enums/sql/query.sql | 1 + internal/endtoend/testdata/enums/sqlc.json | 9 + internal/endtoend/testdata/overrides/go/db.go | 29 +++ .../endtoend/testdata/overrides/go/models.go | 17 ++ .../endtoend/testdata/overrides/sql/query.sql | 1 + .../testdata/overrides/sql/schema.sql | 8 + .../endtoend/testdata/overrides/sqlc.json | 21 ++ 19 files changed, 364 insertions(+), 195 deletions(-) delete mode 100644 internal/dinosql/gen_test.go create mode 100644 internal/endtoend/testdata/datatype/go/db.go create mode 100644 internal/endtoend/testdata/datatype/go/models.go create mode 100644 internal/endtoend/testdata/datatype/sql/character.sql create mode 100644 internal/endtoend/testdata/datatype/sql/datetime.sql create mode 100644 internal/endtoend/testdata/datatype/sql/numeric.sql create mode 100644 internal/endtoend/testdata/datatype/sql/query.sql create mode 100644 internal/endtoend/testdata/datatype/sqlc.json create mode 100644 internal/endtoend/testdata/enums/go/db.go create mode 100644 internal/endtoend/testdata/enums/go/models.go create mode 100644 internal/endtoend/testdata/enums/sql/enum.sql create mode 100644 internal/endtoend/testdata/enums/sql/query.sql create mode 100644 internal/endtoend/testdata/enums/sqlc.json create mode 100644 internal/endtoend/testdata/overrides/go/db.go create mode 100644 internal/endtoend/testdata/overrides/go/models.go create mode 100644 internal/endtoend/testdata/overrides/sql/query.sql create mode 100644 internal/endtoend/testdata/overrides/sql/schema.sql create mode 100644 internal/endtoend/testdata/overrides/sqlc.json diff --git a/internal/dinosql/gen_test.go b/internal/dinosql/gen_test.go deleted file mode 100644 index 0da8627ac7..0000000000 --- a/internal/dinosql/gen_test.go +++ /dev/null @@ -1,183 +0,0 @@ -package dinosql - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/kyleconroy/sqlc/internal/pg" -) - -func TestColumnsToStruct(t *testing.T) { - cols := []pg.Column{ - { - Name: "other", - DataType: "text", - NotNull: true, - }, - { - Name: "count", - DataType: "bigint", - NotNull: true, - }, - { - Name: "count", - DataType: "bigint", - NotNull: true, - }, - { - Name: "tags", - DataType: "text", - NotNull: true, - IsArray: true, - }, - { - Name: "byte_seq", - DataType: "bytea", - NotNull: true, - }, - { - Name: "retyped", - DataType: "text", - NotNull: true, - }, - { - Name: "languages", - DataType: "text", - IsArray: true, - }, - } - - // all of the columns are on the 'foo' table - for i := range cols { - cols[i].Table = pg.FQN{Schema: "public", Rel: "foo"} - } - - // set up column-based override test - o := Override{ - GoType: "example.com/pkg.CustomType", - Column: "foo.retyped", - } - o.Parse() - - // set up column-based array override test - oa := Override{ - GoType: "github.com/lib/pq.StringArray", - Column: "foo.languages", - } - oa.Parse() - - r := Result{} - settings := Combine(GenerateSettings{Overrides: []Override{o, oa}}, PackageSettings{}) - actual := r.columnsToStruct("Foo", cols, settings) - expected := &GoStruct{ - Name: "Foo", - Fields: []GoField{ - {Name: "Other", Type: "string", Tags: map[string]string{"json:": "other"}}, - {Name: "Count", Type: "int64", Tags: map[string]string{"json:": "count"}}, - {Name: "Count_2", Type: "int64", Tags: map[string]string{"json:": "count_2"}}, - {Name: "Tags", Type: "[]string", Tags: map[string]string{"json:": "tags"}}, - {Name: "ByteSeq", Type: "[]byte", Tags: map[string]string{"json:": "byte_seq"}}, - {Name: "Retyped", Type: "pkg.CustomType", Tags: map[string]string{"json:": "retyped"}}, - {Name: "Languages", Type: "pq.StringArray", Tags: map[string]string{"json:": "languages"}}, - }, - } - if diff := cmp.Diff(expected, actual); diff != "" { - t.Errorf("struct mismatch: \n%s", diff) - } -} - -func TestInnerType(t *testing.T) { - r := Result{} - types := map[string]string{ - // Numeric Types - // https://www.postgresql.org/docs/current/datatype-numeric.html - "integer": "int32", - "int": "int32", - "pg_catalog.int4": "int32", - "pg_catalog.numeric": "string", - - // Character Types - // https://www.postgresql.org/docs/current/datatype-character.html - "string": "string", - - // Date/Time Types - // https://www.postgresql.org/docs/current/datatype-datetime.html - "date": "time.Time", - "pg_catalog.time": "time.Time", - "pg_catalog.timetz": "time.Time", - "pg_catalog.timestamp": "time.Time", - "pg_catalog.timestamptz": "time.Time", - "timestamptz": "time.Time", - } - settings := Combine(GenerateSettings{}, PackageSettings{}) - for k, v := range types { - dbType := k - goType := v - t.Run(k+"-"+v, func(t *testing.T) { - col := pg.Column{DataType: dbType, NotNull: true} - if goType != r.goType(col, settings) { - t.Errorf("expected Go type for %s to be %s, not %s", dbType, goType, r.goType(col, settings)) - } - }) - } -} - -func TestNullInnerType(t *testing.T) { - r := Result{} - types := map[string]string{ - // Numeric Types - // https://www.postgresql.org/docs/current/datatype-numeric.html - "integer": "sql.NullInt32", - "int": "sql.NullInt32", - "pg_catalog.int4": "sql.NullInt32", - "pg_catalog.numeric": "sql.NullString", - - // Character Types - // https://www.postgresql.org/docs/current/datatype-character.html - "string": "sql.NullString", - - // Date/Time Types - // https://www.postgresql.org/docs/current/datatype-datetime.html - "date": "sql.NullTime", - "pg_catalog.time": "sql.NullTime", - "pg_catalog.timetz": "sql.NullTime", - "pg_catalog.timestamp": "sql.NullTime", - "pg_catalog.timestamptz": "sql.NullTime", - "timestamptz": "sql.NullTime", - } - settings := Combine(GenerateSettings{}, PackageSettings{}) - for k, v := range types { - dbType := k - goType := v - t.Run(k+"-"+v, func(t *testing.T) { - col := pg.Column{DataType: dbType, NotNull: false} - if goType != r.goType(col, settings) { - t.Errorf("expected Go type for %s to be %s, not %s", dbType, goType, r.goType(col, settings)) - } - }) - } -} - -func TestEnumValueName(t *testing.T) { - values := map[string]string{ - // Valid separators - "foo-bar": "FooBar", - "foo_bar": "FooBar", - "foo:bar": "FooBar", - "foo/bar": "FooBar", - // Strip unknown characters - "foo@bar": "Foobar", - "foo+bar": "Foobar", - "foo!bar": "Foobar", - } - for k, v := range values { - input := k - expected := v - t.Run(k+"-"+v, func(t *testing.T) { - actual := enumValueName(k) - if actual != expected { - t.Errorf("expected name for %s to be %s, not %s", input, expected, actual) - } - }) - } -} diff --git a/internal/endtoend/endtoend_test.go b/internal/endtoend/endtoend_test.go index dce352692a..ac69188b04 100644 --- a/internal/endtoend/endtoend_test.go +++ b/internal/endtoend/endtoend_test.go @@ -12,8 +12,9 @@ import ( "github.com/kyleconroy/sqlc/internal/cmd" ) -func TestCodeGeneration(t *testing.T) { - // Change to the top-level directory of the project +func TestExamples(t *testing.T) { + t.Parallel() + examples, _ := filepath.Abs(filepath.Join("..", "..", "examples")) var stderr bytes.Buffer @@ -25,6 +26,29 @@ func TestCodeGeneration(t *testing.T) { cmpDirectory(t, examples, output) } +func TestReplay(t *testing.T) { + t.Parallel() + + files, err := ioutil.ReadDir("testdata") + if err != nil { + t.Fatal(err) + } + + for _, replay := range files { + tc := replay.Name() + t.Run(tc, func(t *testing.T) { + t.Parallel() + path, _ := filepath.Abs(filepath.Join("testdata", tc)) + var stderr bytes.Buffer + output, err := cmd.Generate(path, &stderr) + if err != nil { + t.Fatalf("%s", stderr.String()) + } + cmpDirectory(t, path, output) + }) + } +} + func cmpDirectory(t *testing.T, dir string, actual map[string]string) { expected := map[string]string{} var ff = func(path string, file os.FileInfo, err error) error { @@ -58,16 +82,16 @@ func cmpDirectory(t *testing.T, dir string, actual map[string]string) { if !cmp.Equal(expected, actual) { t.Errorf("%s contents differ", dir) for name, contents := range expected { - if actual[name] == "" { - t.Errorf("%s is empty", name) - continue - } - if diff := cmp.Diff(contents, actual[name]); diff != "" { - t.Errorf("%s differed (-want +got):\n%s", name, diff) - } - } - for name, _ := range actual { - t.Log(name) + name := name + tn := strings.Replace(name, dir+"/", "", -1) + t.Run(tn, func(t *testing.T) { + if actual[name] == "" { + t.Fatalf("%s is empty", name) + } + if diff := cmp.Diff(contents, actual[name]); diff != "" { + t.Errorf("%s differed (-want +got):\n%s", name, diff) + } + }) } } } diff --git a/internal/endtoend/testdata/datatype/go/db.go b/internal/endtoend/testdata/datatype/go/db.go new file mode 100644 index 0000000000..1558a525e9 --- /dev/null +++ b/internal/endtoend/testdata/datatype/go/db.go @@ -0,0 +1,29 @@ +// Code generated by sqlc. DO NOT EDIT. + +package datatype + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/datatype/go/models.go b/internal/endtoend/testdata/datatype/go/models.go new file mode 100644 index 0000000000..ef28d2b855 --- /dev/null +++ b/internal/endtoend/testdata/datatype/go/models.go @@ -0,0 +1,72 @@ +// Code generated by sqlc. DO NOT EDIT. + +package datatype + +import ( + "database/sql" + "time" +) + +type DtCharacter struct { + A sql.NullString + B sql.NullString + C sql.NullString + D sql.NullString + E sql.NullString +} + +type DtCharacterNotNull struct { + A string + B string + C string + D string + E string +} + +type DtDatetime struct { + A sql.NullTime + B sql.NullTime + C sql.NullTime + D sql.NullTime + E sql.NullTime + F sql.NullTime + G sql.NullTime + H sql.NullTime +} + +type DtDatetimeNotNull struct { + A time.Time + B time.Time + C time.Time + D time.Time + E time.Time + F time.Time + G time.Time + H time.Time +} + +type DtNumeric struct { + A int16 + B sql.NullInt32 + C sql.NullInt64 + D sql.NullString + E sql.NullString + F sql.NullFloat64 + G sql.NullFloat64 + H int16 + I sql.NullInt32 + J sql.NullInt64 +} + +type DtNumericNotNull struct { + A int16 + B int32 + C int64 + D string + E string + F float32 + G float64 + H int16 + I int32 + J int64 +} diff --git a/internal/endtoend/testdata/datatype/sql/character.sql b/internal/endtoend/testdata/datatype/sql/character.sql new file mode 100644 index 0000000000..e3f41dac81 --- /dev/null +++ b/internal/endtoend/testdata/datatype/sql/character.sql @@ -0,0 +1,17 @@ +-- Character Types +-- https://www.postgresql.org/docs/current/datatype-character.html +CREATE TABLE dt_character ( + a text, + b character varying(32), + c varchar(32), + d character(32), + e char(32) +); + +CREATE TABLE dt_character_not_null ( + a text NOT NULL, + b character varying(32) NOT NULL, + c varchar(32) NOT NULL, + d character(32) NOT NULL, + e char(32) NOT NULL +); diff --git a/internal/endtoend/testdata/datatype/sql/datetime.sql b/internal/endtoend/testdata/datatype/sql/datetime.sql new file mode 100644 index 0000000000..5e6bcf033f --- /dev/null +++ b/internal/endtoend/testdata/datatype/sql/datetime.sql @@ -0,0 +1,23 @@ +-- Date/Time Types +-- https://www.postgresql.org/docs/current/datatype-datetime.html +CREATE TABLE dt_datetime ( + a DATE, + b TIME, + c TIME WITHOUT TIME ZONE, + d TIME WITH TIME ZONE, + e TIMESTAMP, + f TIMESTAMP WITHOUT TIME ZONE, + g TIMESTAMP WITH TIME ZONE, + h timestamptz +); + +CREATE TABLE dt_datetime_not_null ( + a DATE NOT NULL, + b TIME NOT NULL, + c TIME WITHOUT TIME ZONE NOT NULL, + d TIME WITH TIME ZONE NOT NULL, + e TIMESTAMP NOT NULL, + f TIMESTAMP WITHOUT TIME ZONE NOT NULL, + g TIMESTAMP WITH TIME ZONE NOT NULL, + h timestamptz NOT NULL +); diff --git a/internal/endtoend/testdata/datatype/sql/numeric.sql b/internal/endtoend/testdata/datatype/sql/numeric.sql new file mode 100644 index 0000000000..45980fa004 --- /dev/null +++ b/internal/endtoend/testdata/datatype/sql/numeric.sql @@ -0,0 +1,29 @@ +-- Numeric Types +-- https://www.postgresql.org/docs/current/datatype-numeric.html +CREATE TABLE dt_numeric ( + -- TODO: this maps incorrectly to int16, not NullInt16 + a smallint, + b integer, + c bigint, + d decimal, + e numeric, + f real, + g double precision, + -- TODO: this maps incorrectly to int16, not NullInt16 + h smallserial, + i serial, + j bigserial +); + +CREATE TABLE dt_numeric_not_null ( + a smallint NOT NULL, + b integer NOT NULL, + c bigint NOT NULL, + d decimal NOT NULL, + e numeric NOT NULL, + f real NOT NULL, + g double precision NOT NULL, + h smallserial NOT NULL, + i serial NOT NULL, + j bigserial NOT NULL +); diff --git a/internal/endtoend/testdata/datatype/sql/query.sql b/internal/endtoend/testdata/datatype/sql/query.sql new file mode 100644 index 0000000000..e0ac49d1ec --- /dev/null +++ b/internal/endtoend/testdata/datatype/sql/query.sql @@ -0,0 +1 @@ +SELECT 1; diff --git a/internal/endtoend/testdata/datatype/sqlc.json b/internal/endtoend/testdata/datatype/sqlc.json new file mode 100644 index 0000000000..790422948d --- /dev/null +++ b/internal/endtoend/testdata/datatype/sqlc.json @@ -0,0 +1,9 @@ +{ + "version": "1", + "packages": [{ + "path": "go", + "name": "datatype", + "schema": "sql/", + "queries": "sql/" + }] +} diff --git a/internal/endtoend/testdata/enums/go/db.go b/internal/endtoend/testdata/enums/go/db.go new file mode 100644 index 0000000000..6b476d86a6 --- /dev/null +++ b/internal/endtoend/testdata/enums/go/db.go @@ -0,0 +1,29 @@ +// Code generated by sqlc. DO NOT EDIT. + +package enum + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/enums/go/models.go b/internal/endtoend/testdata/enums/go/models.go new file mode 100644 index 0000000000..3ee85ce37d --- /dev/null +++ b/internal/endtoend/testdata/enums/go/models.go @@ -0,0 +1,22 @@ +// Code generated by sqlc. DO NOT EDIT. + +package enum + +import () + +type Foobar string + +const ( + FoobarFooA Foobar = "foo-a" + FoobarFooB Foobar = "foo_b" + FoobarFooC Foobar = "foo:c" + FoobarFooD Foobar = "foo/d" + FoobarFooe Foobar = "foo@e" + FoobarFoof Foobar = "foo+f" + FoobarFoog Foobar = "foo!g" +) + +func (e *Foobar) Scan(src interface{}) error { + *e = Foobar(src.([]byte)) + return nil +} diff --git a/internal/endtoend/testdata/enums/sql/enum.sql b/internal/endtoend/testdata/enums/sql/enum.sql new file mode 100644 index 0000000000..3d5f715c3b --- /dev/null +++ b/internal/endtoend/testdata/enums/sql/enum.sql @@ -0,0 +1,11 @@ +CREATE TYPE foobar AS ENUM ( + -- Valid separators + 'foo-a', + 'foo_b', + 'foo:c', + 'foo/d', + -- Strip unknown characters + 'foo@e', + 'foo+f', + 'foo!g' +); diff --git a/internal/endtoend/testdata/enums/sql/query.sql b/internal/endtoend/testdata/enums/sql/query.sql new file mode 100644 index 0000000000..e0ac49d1ec --- /dev/null +++ b/internal/endtoend/testdata/enums/sql/query.sql @@ -0,0 +1 @@ +SELECT 1; diff --git a/internal/endtoend/testdata/enums/sqlc.json b/internal/endtoend/testdata/enums/sqlc.json new file mode 100644 index 0000000000..9e4a4bfa02 --- /dev/null +++ b/internal/endtoend/testdata/enums/sqlc.json @@ -0,0 +1,9 @@ +{ + "version": "1", + "packages": [{ + "path": "go", + "name": "enum", + "schema": "sql/", + "queries": "sql/" + }] +} diff --git a/internal/endtoend/testdata/overrides/go/db.go b/internal/endtoend/testdata/overrides/go/db.go new file mode 100644 index 0000000000..6f21c94ed1 --- /dev/null +++ b/internal/endtoend/testdata/overrides/go/db.go @@ -0,0 +1,29 @@ +// Code generated by sqlc. DO NOT EDIT. + +package override + +import ( + "context" + "database/sql" +) + +type DBTX interface { + ExecContext(context.Context, string, ...interface{}) (sql.Result, error) + PrepareContext(context.Context, string) (*sql.Stmt, error) + QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error) + QueryRowContext(context.Context, string, ...interface{}) *sql.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx *sql.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/overrides/go/models.go b/internal/endtoend/testdata/overrides/go/models.go new file mode 100644 index 0000000000..fb93846885 --- /dev/null +++ b/internal/endtoend/testdata/overrides/go/models.go @@ -0,0 +1,17 @@ +// Code generated by sqlc. DO NOT EDIT. + +package override + +import ( + "example.com/pkg" + "github.com/lib/pq" +) + +type Foo struct { + Other string + Total int64 + Tags []string + ByteSeq []byte + Retyped pkg.CustomType + Langs pq.StringArray +} diff --git a/internal/endtoend/testdata/overrides/sql/query.sql b/internal/endtoend/testdata/overrides/sql/query.sql new file mode 100644 index 0000000000..e0ac49d1ec --- /dev/null +++ b/internal/endtoend/testdata/overrides/sql/query.sql @@ -0,0 +1 @@ +SELECT 1; diff --git a/internal/endtoend/testdata/overrides/sql/schema.sql b/internal/endtoend/testdata/overrides/sql/schema.sql new file mode 100644 index 0000000000..fc3a13e53d --- /dev/null +++ b/internal/endtoend/testdata/overrides/sql/schema.sql @@ -0,0 +1,8 @@ +CREATE TABLE foo ( + other text NOT NULL, + total bigint NOT NULL, + tags text[] NOT NULL, + byte_seq bytea NOT NULL, + retyped text NOT NULL, + langs text[] +); diff --git a/internal/endtoend/testdata/overrides/sqlc.json b/internal/endtoend/testdata/overrides/sqlc.json new file mode 100644 index 0000000000..3fdb0650c9 --- /dev/null +++ b/internal/endtoend/testdata/overrides/sqlc.json @@ -0,0 +1,21 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "name": "override", + "schema": "sql/", + "queries": "sql/", + "overrides": [ + { + "go_type": "example.com/pkg.CustomType", + "column": "foo.retyped" + }, + { + "go_type": "github.com/lib/pq.StringArray", + "column": "foo.langs" + } + ] + } + ] +} From bba3874ea00335aa82d109c621b55973c97ce0de Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sat, 25 Jan 2020 18:17:57 -0700 Subject: [PATCH 4/4] Fix whitespace --- internal/endtoend/testdata/enums/sql/enum.sql | 8 ++++---- internal/endtoend/testdata/overrides/sqlc.json | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/endtoend/testdata/enums/sql/enum.sql b/internal/endtoend/testdata/enums/sql/enum.sql index 3d5f715c3b..f1de033807 100644 --- a/internal/endtoend/testdata/enums/sql/enum.sql +++ b/internal/endtoend/testdata/enums/sql/enum.sql @@ -1,11 +1,11 @@ CREATE TYPE foobar AS ENUM ( - -- Valid separators + -- Valid separators 'foo-a', 'foo_b', 'foo:c', 'foo/d', - -- Strip unknown characters + -- Strip unknown characters 'foo@e', - 'foo+f', - 'foo!g' + 'foo+f', + 'foo!g' ); diff --git a/internal/endtoend/testdata/overrides/sqlc.json b/internal/endtoend/testdata/overrides/sqlc.json index 3fdb0650c9..f98bb706b7 100644 --- a/internal/endtoend/testdata/overrides/sqlc.json +++ b/internal/endtoend/testdata/overrides/sqlc.json @@ -8,13 +8,13 @@ "queries": "sql/", "overrides": [ { - "go_type": "example.com/pkg.CustomType", - "column": "foo.retyped" - }, - { + "go_type": "example.com/pkg.CustomType", + "column": "foo.retyped" + }, + { "go_type": "github.com/lib/pq.StringArray", - "column": "foo.langs" - } + "column": "foo.langs" + } ] } ]