From f7f0b86993bdab674ec2ced2247b949bbbcb61a8 Mon Sep 17 00:00:00 2001 From: naisu <47899783+naisuuuu@users.noreply.github.com> Date: Sun, 15 Aug 2021 03:03:04 +0200 Subject: [PATCH 01/22] Fix typos in generated code sample (#1125) --- docs/howto/select.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/howto/select.md b/docs/howto/select.md index 962fd6a025..5f23435d74 100644 --- a/docs/howto/select.md +++ b/docs/howto/select.md @@ -175,9 +175,9 @@ type GetInfoForAuthorRow struct { BirthYear int } -func (q *Queries) GetBioForAuthor(ctx context.Context, id int) (GetBioForAuthor, error) { +func (q *Queries) GetInfoForAuthor(ctx context.Context, id int) (GetInfoForAuthorRow, error) { row := q.db.QueryRowContext(ctx, getInfoForAuthor, id) - var i GetBioForAuthor + var i GetInfoForAuthorRow err := row.Scan(&i.Bio, &i.BirthYear) return i, err } From 481f8927a840251f4964d238616fe4679ec669ba Mon Sep 17 00:00:00 2001 From: Robson Roberto Souza Peixoto <124390+robsonpeixoto@users.noreply.github.com> Date: Mon, 16 Aug 2021 01:08:38 -0300 Subject: [PATCH 02/22] Remove MYSQL_USER and MYSQL_PASSWORD from docker-compose.yaml (#1123) The right way to configure the *root* password is using the environment variable `MYSQL_ROOT_PASSWORD`. It also remove the `MYSQL_PASSWORD` because is only used the root user. From MySQL log: ``` 2021-08-13 20:28:55+00:00 [Note] [Entrypoint]: Switching to dedicated user 'mysql' 2021-08-13 20:28:55+00:00 [Note] [Entrypoint]: Entrypoint script for MySQL Server 8.0.26-1debian10 started. 2021-08-13 20:28:55+00:00 [ERROR] [Entrypoint]: MYSQL_USER="root", MYSQL_USER and MYSQL_PASSWORD are for configuring a regular user and cannot be used for the root user Remove MYSQL_USER="root" and use one of the following to control the root user password: - MYSQL_ROOT_PASSWORD - MYSQL_ALLOW_EMPTY_PASSWORD - MYSQL_RANDOM_ROOT_PASSWORD ``` Co-authored-by: Kyle Conroy --- docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index b4990c0225..75aae72d58 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -7,9 +7,7 @@ services: restart: always environment: MYSQL_DATABASE: dinotest - MYSQL_PASSWORD: mysecretpassword MYSQL_ROOT_PASSWORD: mysecretpassword - MYSQL_USER: root postgresql: image: "postgres:13" From 7f83322580c1d8cae69c2f0df70305ec1109b90d Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Aug 2021 08:08:47 -0700 Subject: [PATCH 03/22] build(deps): bump golang from 1.16.7 to 1.17.0 (#1129) Bumps golang from 1.16.7 to 1.17.0. --- updated-dependencies: - dependency-name: golang dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 028758cd65..69310d80fe 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # STEP 1: Build sqlc -FROM golang:1.16.7 AS builder +FROM golang:1.17.0 AS builder COPY . /workspace WORKDIR /workspace From 312ef9e97fd3314bb7bff5ac8bd6b86edfbf3d99 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Tue, 17 Aug 2021 08:17:46 -0700 Subject: [PATCH 04/22] ci: Upgrade Go to 1.17 (#1130) --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f568a5008..da8cb27b1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,7 +34,7 @@ jobs: - uses: actions/setup-go@v2 with: - go-version: '1.16' + go-version: '1.17' - run: go build ./... working-directory: internal/endtoend/testdata From 5785f2388a15d7513ac06fc286bc33e9b0a659bf Mon Sep 17 00:00:00 2001 From: LLLeon Date: Wed, 18 Aug 2021 12:46:37 +0800 Subject: [PATCH 05/22] Update getting-started.md (#1133) --- docs/tutorials/getting-started.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/getting-started.md b/docs/tutorials/getting-started.md index 4cb2c2fc88..f1d3605b21 100644 --- a/docs/tutorials/getting-started.md +++ b/docs/tutorials/getting-started.md @@ -25,7 +25,7 @@ packages: ``` sqlc needs to know your database schema and queries. In the same directory, -create a file named `schema.sql` with the fullowing contents: +create a file named `schema.sql` with the following contents: ```sql CREATE TABLE authors ( From bed10652d3365a85aba5472e048d16403b39f6ac Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Tue, 17 Aug 2021 22:21:35 -0700 Subject: [PATCH 06/22] Add RStudio to list of sponsors (#1131) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e601ab0936..7a641da020 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,7 @@ companies: - [Meter](https://meter.com) - [ngrok](https://ngrok.com) +- [RStudio](https://www.rstudio.com/) If you use sqlc at your company, please consider [becoming a sponsor](https://github.com/sponsors/kyleconroy) today. From b36e368ade282663c55592da19e5ca9a17422e8c Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Wed, 18 Aug 2021 08:51:29 -0700 Subject: [PATCH 07/22] endtoend: Run `go test` in CI (#1134) * endtoend: Run `go test` in CI * Re-order some steps --- .github/workflows/ci.yml | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index da8cb27b1b..455bf2fb73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,10 +36,7 @@ jobs: with: go-version: '1.17' - - run: go build ./... - working-directory: internal/endtoend/testdata - - - name: Test sqlc + - name: test ./... run: go test --tags=examples ./... env: PG_USER: postgres @@ -52,3 +49,10 @@ jobs: MYSQL_PORT: ${{ job.services.mysql.ports['3306'] }} MYSQL_ROOT_PASSWORD: mysecretpassword + - name: build internal/endtoend + run: go build ./... + working-directory: internal/endtoend/testdata + + - name: test internal/endtoend + run: go test ./... + working-directory: internal/endtoend/testdata From d0cf1e5f890730e4511cd2ddd31d4d9d6d84676f Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Wed, 18 Aug 2021 21:56:19 -0700 Subject: [PATCH 08/22] golang: Output NullUUID when necessary (#1137) * golang: Output NullUUID when necessary * Upgrade to the latest version of google/uuid * Make sure that overrides continue to work --- internal/codegen/golang/imports.go | 12 +++++ internal/codegen/golang/postgresql_type.go | 5 +- internal/endtoend/testdata/go.mod | 2 +- internal/endtoend/testdata/go.sum | 2 + .../pgx/go/db.go | 0 .../pgx/go/models.go | 0 .../pgx/go/query.sql.go | 0 .../pgx/query.sql | 0 .../pgx/sqlc.json | 0 .../stdlib/go/db.go | 0 .../stdlib/go/models.go | 0 .../stdlib/go/query.sql.go | 0 .../stdlib/query.sql | 0 .../stdlib/sqlc.json | 0 .../types_uuid/postgresql/stdlib/go/db.go | 29 +++++++++++ .../types_uuid/postgresql/stdlib/go/models.go | 15 ++++++ .../postgresql/stdlib/go/query.sql.go | 48 +++++++++++++++++++ .../types_uuid/postgresql/stdlib/query.sql | 11 +++++ .../types_uuid/postgresql/stdlib/sqlc.json | 11 +++++ 19 files changed, 133 insertions(+), 2 deletions(-) rename internal/endtoend/testdata/{ipaddr => types_network_address}/pgx/go/db.go (100%) rename internal/endtoend/testdata/{ipaddr => types_network_address}/pgx/go/models.go (100%) rename internal/endtoend/testdata/{ipaddr => types_network_address}/pgx/go/query.sql.go (100%) rename internal/endtoend/testdata/{ipaddr => types_network_address}/pgx/query.sql (100%) rename internal/endtoend/testdata/{ipaddr => types_network_address}/pgx/sqlc.json (100%) rename internal/endtoend/testdata/{ipaddr => types_network_address}/stdlib/go/db.go (100%) rename internal/endtoend/testdata/{ipaddr => types_network_address}/stdlib/go/models.go (100%) rename internal/endtoend/testdata/{ipaddr => types_network_address}/stdlib/go/query.sql.go (100%) rename internal/endtoend/testdata/{ipaddr => types_network_address}/stdlib/query.sql (100%) rename internal/endtoend/testdata/{ipaddr => types_network_address}/stdlib/sqlc.json (100%) create mode 100644 internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/db.go create mode 100644 internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/models.go create mode 100644 internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/query.sql.go create mode 100644 internal/endtoend/testdata/types_uuid/postgresql/stdlib/query.sql create mode 100644 internal/endtoend/testdata/types_uuid/postgresql/stdlib/sqlc.json diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 6aca91bd0c..4fe6e20512 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -202,6 +202,10 @@ func (i *importer) interfaceImports() fileImports { if uses("uuid.UUID") && !overrideUUID { pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} } + _, overrideNullUUID := overrideTypes["uuid.NullUUID"] + if uses("uuid.NullUUID") && !overrideNullUUID { + pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} + } // Custom imports for _, o := range i.Settings.Overrides { @@ -263,6 +267,10 @@ func (i *importer) modelImports() fileImports { if i.usesType("uuid.UUID") && !overrideUUID { pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} } + _, overrideNullUUID := overrideTypes["uuid.NullUUID"] + if i.usesType("uuid.NullUUID") && !overrideNullUUID { + pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} + } for _, o := range i.Settings.Overrides { if o.GoBasicType || o.GoTypeName == "" { @@ -408,6 +416,10 @@ func (i *importer) queryImports(filename string) fileImports { if uses("uuid.UUID") && !overrideUUID { pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} } + _, overrideNullUUID := overrideTypes["uuid.NullUUID"] + if uses("uuid.NullUUID") && !overrideNullUUID { + pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} + } // Custom imports for _, o := range i.Settings.Overrides { diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go index 1e893626df..42b4be0da0 100644 --- a/internal/codegen/golang/postgresql_type.go +++ b/internal/codegen/golang/postgresql_type.go @@ -103,7 +103,10 @@ func postgresType(r *compiler.Result, col *compiler.Column, settings config.Comb return "sql.NullString" case "uuid": - return "uuid.UUID" + if notNull { + return "uuid.UUID" + } + return "uuid.NullUUID" case "inet", "cidr": return "net.IP" diff --git a/internal/endtoend/testdata/go.mod b/internal/endtoend/testdata/go.mod index fd0ed966a2..3304264df2 100644 --- a/internal/endtoend/testdata/go.mod +++ b/internal/endtoend/testdata/go.mod @@ -4,7 +4,7 @@ go 1.16 require ( github.com/gofrs/uuid v4.0.0+incompatible - github.com/google/uuid v1.2.0 + github.com/google/uuid v1.3.0 github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853 github.com/jackc/pgtype v1.6.2 github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904 diff --git a/internal/endtoend/testdata/go.sum b/internal/endtoend/testdata/go.sum index 6b2aed8537..5398eca4f4 100644 --- a/internal/endtoend/testdata/go.sum +++ b/internal/endtoend/testdata/go.sum @@ -16,6 +16,8 @@ github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRx github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.2.0 h1:qJYtXnJRWmpe7m/3XlyhrsLrEURqHRM2kxzoxXqyUDs= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= diff --git a/internal/endtoend/testdata/ipaddr/pgx/go/db.go b/internal/endtoend/testdata/types_network_address/pgx/go/db.go similarity index 100% rename from internal/endtoend/testdata/ipaddr/pgx/go/db.go rename to internal/endtoend/testdata/types_network_address/pgx/go/db.go diff --git a/internal/endtoend/testdata/ipaddr/pgx/go/models.go b/internal/endtoend/testdata/types_network_address/pgx/go/models.go similarity index 100% rename from internal/endtoend/testdata/ipaddr/pgx/go/models.go rename to internal/endtoend/testdata/types_network_address/pgx/go/models.go diff --git a/internal/endtoend/testdata/ipaddr/pgx/go/query.sql.go b/internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go similarity index 100% rename from internal/endtoend/testdata/ipaddr/pgx/go/query.sql.go rename to internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go diff --git a/internal/endtoend/testdata/ipaddr/pgx/query.sql b/internal/endtoend/testdata/types_network_address/pgx/query.sql similarity index 100% rename from internal/endtoend/testdata/ipaddr/pgx/query.sql rename to internal/endtoend/testdata/types_network_address/pgx/query.sql diff --git a/internal/endtoend/testdata/ipaddr/pgx/sqlc.json b/internal/endtoend/testdata/types_network_address/pgx/sqlc.json similarity index 100% rename from internal/endtoend/testdata/ipaddr/pgx/sqlc.json rename to internal/endtoend/testdata/types_network_address/pgx/sqlc.json diff --git a/internal/endtoend/testdata/ipaddr/stdlib/go/db.go b/internal/endtoend/testdata/types_network_address/stdlib/go/db.go similarity index 100% rename from internal/endtoend/testdata/ipaddr/stdlib/go/db.go rename to internal/endtoend/testdata/types_network_address/stdlib/go/db.go diff --git a/internal/endtoend/testdata/ipaddr/stdlib/go/models.go b/internal/endtoend/testdata/types_network_address/stdlib/go/models.go similarity index 100% rename from internal/endtoend/testdata/ipaddr/stdlib/go/models.go rename to internal/endtoend/testdata/types_network_address/stdlib/go/models.go diff --git a/internal/endtoend/testdata/ipaddr/stdlib/go/query.sql.go b/internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go similarity index 100% rename from internal/endtoend/testdata/ipaddr/stdlib/go/query.sql.go rename to internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go diff --git a/internal/endtoend/testdata/ipaddr/stdlib/query.sql b/internal/endtoend/testdata/types_network_address/stdlib/query.sql similarity index 100% rename from internal/endtoend/testdata/ipaddr/stdlib/query.sql rename to internal/endtoend/testdata/types_network_address/stdlib/query.sql diff --git a/internal/endtoend/testdata/ipaddr/stdlib/sqlc.json b/internal/endtoend/testdata/types_network_address/stdlib/sqlc.json similarity index 100% rename from internal/endtoend/testdata/ipaddr/stdlib/sqlc.json rename to internal/endtoend/testdata/types_network_address/stdlib/sqlc.json diff --git a/internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/db.go b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/db.go new file mode 100644 index 0000000000..6a99519302 --- /dev/null +++ b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/db.go @@ -0,0 +1,29 @@ +// Code generated by sqlc. DO NOT EDIT. + +package querytest + +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/types_uuid/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/models.go new file mode 100644 index 0000000000..c3076fad07 --- /dev/null +++ b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. + +package querytest + +import ( + "database/sql" + + "github.com/google/uuid" +) + +type Foo struct { + Description sql.NullString + Bar uuid.NullUUID + Baz uuid.UUID +} diff --git a/internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/query.sql.go new file mode 100644 index 0000000000..2077b769b8 --- /dev/null +++ b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/go/query.sql.go @@ -0,0 +1,48 @@ +// Code generated by sqlc. DO NOT EDIT. +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/google/uuid" +) + +const find = `-- name: Find :one +SELECT bar FROM foo WHERE baz = $1 +` + +func (q *Queries) Find(ctx context.Context, baz uuid.UUID) (uuid.NullUUID, error) { + row := q.db.QueryRowContext(ctx, find, baz) + var bar uuid.NullUUID + err := row.Scan(&bar) + return bar, err +} + +const list = `-- name: List :many +SELECT description, bar, baz FROM foo +` + +func (q *Queries) List(ctx context.Context) ([]Foo, error) { + rows, err := q.db.QueryContext(ctx, list) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Foo + for rows.Next() { + var i Foo + if err := rows.Scan(&i.Description, &i.Bar, &i.Baz); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/types_uuid/postgresql/stdlib/query.sql b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..74ab78a3d1 --- /dev/null +++ b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/query.sql @@ -0,0 +1,11 @@ +CREATE TABLE foo ( + description text, + bar uuid, + baz uuid not null +); + +-- name: List :many +SELECT * FROM foo; + +-- name: Find :one +SELECT bar FROM foo WHERE baz = $1; diff --git a/internal/endtoend/testdata/types_uuid/postgresql/stdlib/sqlc.json b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/sqlc.json new file mode 100644 index 0000000000..ac7c2ed829 --- /dev/null +++ b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/sqlc.json @@ -0,0 +1,11 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "name": "querytest", + "schema": "query.sql", + "queries": "query.sql" + } + ] +} From 060884d475fd08b50d5863a2ca5bdf1a02099769 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Fri, 20 Aug 2021 18:53:24 -0700 Subject: [PATCH 09/22] codegen/golang: Consolidate import logic (#1139) * codegen/golang: Consolidate import logic Refactor import logic into a two shared functions instead of three confusing call sites. --- internal/codegen/golang/go_type.go | 2 +- internal/codegen/golang/imports.go | 204 ++++++----------------------- 2 files changed, 41 insertions(+), 165 deletions(-) diff --git a/internal/codegen/golang/go_type.go b/internal/codegen/golang/go_type.go index 11c4f96dbd..3050cae3da 100644 --- a/internal/codegen/golang/go_type.go +++ b/internal/codegen/golang/go_type.go @@ -6,7 +6,7 @@ import ( ) func goType(r *compiler.Result, col *compiler.Column, settings config.CombinedSettings) string { - // package overrides have a higher precedence + // Check if the column's type has been overridden for _, oride := range settings.Overrides { if oride.GoTypeName == "" { continue diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 4fe6e20512..6a5dfd55d4 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -76,17 +76,6 @@ func (i *importer) usesType(typ string) bool { return false } -func (i *importer) usesArrays() bool { - for _, strct := range i.Structs { - for _, f := range strct.Fields { - if strings.HasPrefix(f.Type, "[]") { - return true - } - } - } - return false -} - func (i *importer) Imports(filename string) [][]ImportSpec { dbFileName := "db.go" if i.Settings.Go.OutputDBFileName != "" { @@ -143,34 +132,16 @@ var stdlibTypes = map[string]string{ "net.HardwareAddr": "net", } -func (i *importer) interfaceImports() fileImports { - uses := func(name string) bool { - for _, q := range i.Queries { - if q.hasRetType() { - if strings.HasPrefix(q.Ret.Type(), name) { - return true - } - } - if !q.Arg.isEmpty() { - if strings.HasPrefix(q.Arg.Type(), name) { - return true - } - } - } - return false - } +func buildImports(settings config.CombinedSettings, queries []Query, uses func(string) bool) (map[string]struct{}, map[ImportSpec]struct{}) { + pkg := make(map[ImportSpec]struct{}) + std := make(map[string]struct{}) - std := map[string]struct{}{ - "context": {}, - } if uses("sql.Null") { std["database/sql"] = struct{}{} } - pkg := make(map[ImportSpec]struct{}) - - sqlpkg := SQLPackageFromString(i.Settings.Go.SQLPackage) - for _, q := range i.Queries { + sqlpkg := SQLPackageFromString(settings.Go.SQLPackage) + for _, q := range queries { if q.Cmd == metadata.CmdExecResult { switch sqlpkg { case SQLPackagePGX: @@ -180,6 +151,7 @@ func (i *importer) interfaceImports() fileImports { } } } + for typeName, pkg := range stdlibTypes { if uses(typeName) { std[pkg] = struct{}{} @@ -187,7 +159,7 @@ func (i *importer) interfaceImports() fileImports { } overrideTypes := map[string]string{} - for _, o := range i.Settings.Overrides { + for _, o := range settings.Overrides { if o.GoBasicType || o.GoTypeName == "" { continue } @@ -208,7 +180,7 @@ func (i *importer) interfaceImports() fileImports { } // Custom imports - for _, o := range i.Settings.Overrides { + for _, o := range settings.Overrides { if o.GoBasicType || o.GoTypeName == "" { continue } @@ -219,80 +191,52 @@ func (i *importer) interfaceImports() fileImports { } } - pkgs := make([]ImportSpec, 0, len(pkg)) - for spec := range pkg { - pkgs = append(pkgs, spec) - } + return std, pkg +} - stds := make([]ImportSpec, 0, len(std)) - for path := range std { - stds = append(stds, ImportSpec{Path: path}) - } +func (i *importer) interfaceImports() fileImports { + std, pkg := buildImports(i.Settings, i.Queries, func(name string) bool { + for _, q := range i.Queries { + if q.hasRetType() { + if strings.HasPrefix(q.Ret.Type(), name) { + return true + } + } + if !q.Arg.isEmpty() { + if strings.HasPrefix(q.Arg.Type(), name) { + return true + } + } + } + return false + }) - sort.Slice(stds, func(i, j int) bool { return stds[i].Path < stds[j].Path }) - sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].Path < pkgs[j].Path }) - return fileImports{stds, pkgs} + std["context"] = struct{}{} + + return sortedImports(std, pkg) } func (i *importer) modelImports() fileImports { - std := make(map[string]struct{}) - if i.usesType("sql.Null") { - std["database/sql"] = struct{}{} - } - for typeName, pkg := range stdlibTypes { - if i.usesType(typeName) { - std[pkg] = struct{}{} - } - } + std, pkg := buildImports(i.Settings, nil, func(prefix string) bool { + return i.usesType(prefix) + }) + if len(i.Enums) > 0 { std["fmt"] = struct{}{} } - // Custom imports - pkg := make(map[ImportSpec]struct{}) - overrideTypes := map[string]string{} - for _, o := range i.Settings.Overrides { - if o.GoBasicType || o.GoTypeName == "" { - continue - } - overrideTypes[o.GoTypeName] = o.GoImportPath - } - - _, overrideNullTime := overrideTypes["pq.NullTime"] - if i.usesType("pq.NullTime") && !overrideNullTime { - pkg[ImportSpec{Path: "github.com/lib/pq"}] = struct{}{} - } - - _, overrideUUID := overrideTypes["uuid.UUID"] - if i.usesType("uuid.UUID") && !overrideUUID { - pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} - } - _, overrideNullUUID := overrideTypes["uuid.NullUUID"] - if i.usesType("uuid.NullUUID") && !overrideNullUUID { - pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} - } - - for _, o := range i.Settings.Overrides { - if o.GoBasicType || o.GoTypeName == "" { - continue - } - _, alreadyImported := std[o.GoImportPath] - hasPackageAlias := o.GoPackage != "" - if (!alreadyImported || hasPackageAlias) && i.usesType(o.GoTypeName) { - pkg[ImportSpec{Path: o.GoImportPath, ID: o.GoPackage}] = struct{}{} - } - } + return sortedImports(std, pkg) +} +func sortedImports(std map[string]struct{}, pkg map[ImportSpec]struct{}) fileImports { pkgs := make([]ImportSpec, 0, len(pkg)) for spec := range pkg { pkgs = append(pkgs, spec) } - stds := make([]ImportSpec, 0, len(std)) for path := range std { stds = append(stds, ImportSpec{Path: path}) } - sort.Slice(stds, func(i, j int) bool { return stds[i].Path < stds[j].Path }) sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].Path < pkgs[j].Path }) return fileImports{stds, pkgs} @@ -306,7 +250,7 @@ func (i *importer) queryImports(filename string) fileImports { } } - uses := func(name string) bool { + std, pkg := buildImports(i.Settings, gq, func(name string) bool { for _, q := range gq { if q.hasRetType() { if q.Ret.EmitStruct() { @@ -336,7 +280,7 @@ func (i *importer) queryImports(filename string) fileImports { } } return false - } + }) sliceScan := func() bool { for _, q := range gq { @@ -370,80 +314,12 @@ func (i *importer) queryImports(filename string) fileImports { return false } - pkg := make(map[ImportSpec]struct{}) - std := map[string]struct{}{ - "context": {}, - } - if uses("sql.Null") { - std["database/sql"] = struct{}{} - } + std["context"] = struct{}{} sqlpkg := SQLPackageFromString(i.Settings.Go.SQLPackage) - - for _, q := range gq { - if q.Cmd == metadata.CmdExecResult { - switch sqlpkg { - case SQLPackagePGX: - pkg[ImportSpec{Path: "github.com/jackc/pgconn"}] = struct{}{} - default: - std["database/sql"] = struct{}{} - } - } - } - for typeName, pkg := range stdlibTypes { - if uses(typeName) { - std[pkg] = struct{}{} - } - } - - overrideTypes := map[string]string{} - for _, o := range i.Settings.Overrides { - if o.GoBasicType || o.GoTypeName == "" { - continue - } - overrideTypes[o.GoTypeName] = o.GoImportPath - } - if sliceScan() && sqlpkg != SQLPackagePGX { pkg[ImportSpec{Path: "github.com/lib/pq"}] = struct{}{} } - _, overrideNullTime := overrideTypes["pq.NullTime"] - if uses("pq.NullTime") && !overrideNullTime { - pkg[ImportSpec{Path: "github.com/lib/pq"}] = struct{}{} - } - _, overrideUUID := overrideTypes["uuid.UUID"] - if uses("uuid.UUID") && !overrideUUID { - pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} - } - _, overrideNullUUID := overrideTypes["uuid.NullUUID"] - if uses("uuid.NullUUID") && !overrideNullUUID { - pkg[ImportSpec{Path: "github.com/google/uuid"}] = struct{}{} - } - - // Custom imports - for _, o := range i.Settings.Overrides { - if o.GoBasicType || o.GoTypeName == "" { - continue - } - _, alreadyImported := std[o.GoImportPath] - hasPackageAlias := o.GoPackage != "" - if (!alreadyImported || hasPackageAlias) && uses(o.GoTypeName) { - pkg[ImportSpec{Path: o.GoImportPath, ID: o.GoPackage}] = struct{}{} - } - } - - pkgs := make([]ImportSpec, 0, len(pkg)) - for spec := range pkg { - pkgs = append(pkgs, spec) - } - - stds := make([]ImportSpec, 0, len(std)) - for path := range std { - stds = append(stds, ImportSpec{Path: path}) - } - - sort.Slice(stds, func(i, j int) bool { return stds[i].Path < stds[j].Path }) - sort.Slice(pkgs, func(i, j int) bool { return pkgs[i].Path < pkgs[j].Path }) - return fileImports{stds, pkgs} + return sortedImports(std, pkg) } From ca0f3de4f5aa99d035f9f6c0de933c887e6f54b0 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sat, 21 Aug 2021 16:41:39 -0700 Subject: [PATCH 10/22] codgen/golang: Use p[gq]type for network address types (#1142) * codgen/golang: pgtype for network address types * codgen/golang: Use pqtype for lib/pq --- internal/codegen/golang/driver.go | 18 ++++ internal/codegen/golang/imports.go | 24 +++++ internal/codegen/golang/postgresql_type.go | 31 ++++++- .../{posgresql => postgresql}/pgx/go/db.go | 0 .../pgx/go/models.go | 0 .../pgx/go/query.sql.go | 5 +- .../{posgresql => postgresql}/pgx/query.sql | 0 .../{posgresql => postgresql}/pgx/schema.sql | 0 .../{posgresql => postgresql}/pgx/sqlc.json | 0 .../{posgresql => postgresql}/stdlib/go/db.go | 0 .../stdlib/go/models.go | 0 .../stdlib/go/query.sql.go | 5 +- .../stdlib/query.sql | 0 .../stdlib/schema.sql | 0 .../stdlib/sqlc.json | 0 internal/endtoend/testdata/go.mod | 1 + internal/endtoend/testdata/go.sum | 2 + .../endtoend/testdata/macaddr/pgx/go/db.go | 30 ------- .../testdata/macaddr/pgx/go/models.go | 12 --- .../testdata/macaddr/pgx/go/query.sql.go | 57 ------------ .../endtoend/testdata/macaddr/pgx/query.sql | 7 -- .../endtoend/testdata/macaddr/pgx/sqlc.json | 13 --- .../endtoend/testdata/macaddr/stdlib/go/db.go | 29 ------ .../testdata/macaddr/stdlib/go/models.go | 12 --- .../testdata/macaddr/stdlib/go/query.sql.go | 63 ------------- .../testdata/macaddr/stdlib/query.sql | 7 -- .../testdata/macaddr/stdlib/sqlc.json | 11 --- .../types_network_address/pgx/go/models.go | 14 ++- .../types_network_address/pgx/go/query.sql.go | 87 ++++++++++++++++-- .../types_network_address/pgx/query.sql | 31 ++++++- .../types_network_address/stdlib/go/models.go | 14 ++- .../stdlib/go/query.sql.go | 90 +++++++++++++++++-- .../types_network_address/stdlib/query.sql | 31 ++++++- 33 files changed, 322 insertions(+), 272 deletions(-) create mode 100644 internal/codegen/golang/driver.go rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/pgx/go/db.go (100%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/pgx/go/models.go (100%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/pgx/go/query.sql.go (96%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/pgx/query.sql (100%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/pgx/schema.sql (100%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/pgx/sqlc.json (100%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/stdlib/go/db.go (100%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/stdlib/go/models.go (100%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/stdlib/go/query.sql.go (96%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/stdlib/query.sql (100%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/stdlib/schema.sql (100%) rename internal/endtoend/testdata/func_return/{posgresql => postgresql}/stdlib/sqlc.json (100%) delete mode 100644 internal/endtoend/testdata/macaddr/pgx/go/db.go delete mode 100644 internal/endtoend/testdata/macaddr/pgx/go/models.go delete mode 100644 internal/endtoend/testdata/macaddr/pgx/go/query.sql.go delete mode 100644 internal/endtoend/testdata/macaddr/pgx/query.sql delete mode 100644 internal/endtoend/testdata/macaddr/pgx/sqlc.json delete mode 100644 internal/endtoend/testdata/macaddr/stdlib/go/db.go delete mode 100644 internal/endtoend/testdata/macaddr/stdlib/go/models.go delete mode 100644 internal/endtoend/testdata/macaddr/stdlib/go/query.sql.go delete mode 100644 internal/endtoend/testdata/macaddr/stdlib/query.sql delete mode 100644 internal/endtoend/testdata/macaddr/stdlib/sqlc.json diff --git a/internal/codegen/golang/driver.go b/internal/codegen/golang/driver.go new file mode 100644 index 0000000000..de2e201b8c --- /dev/null +++ b/internal/codegen/golang/driver.go @@ -0,0 +1,18 @@ +package golang + +import "github.com/kyleconroy/sqlc/internal/config" + +type SQLDriver int + +const ( + SQLDriverPGXV4 SQLDriver = iota + SQLDriverLibPQ +) + +func parseDriver(settings config.CombinedSettings) SQLDriver { + if settings.Go.SQLPackage == "pgx/v4" { + return SQLDriverPGXV4 + } else { + return SQLDriverLibPQ + } +} diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 6a5dfd55d4..0f6dca633e 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -132,6 +132,18 @@ var stdlibTypes = map[string]string{ "net.HardwareAddr": "net", } +var pgtypeTypes = map[string]struct{}{ + "pgtype.CIDR": {}, + "pgtype.Inet": {}, + "pgtype.Macaddr": {}, +} + +var pqtypeTypes = map[string]struct{}{ + "pqtype.CIDR": {}, + "pqtype.Inet": {}, + "pqtype.Macaddr": {}, +} + func buildImports(settings config.CombinedSettings, queries []Query, uses func(string) bool) (map[string]struct{}, map[ImportSpec]struct{}) { pkg := make(map[ImportSpec]struct{}) std := make(map[string]struct{}) @@ -158,6 +170,18 @@ func buildImports(settings config.CombinedSettings, queries []Query, uses func(s } } + for typeName, _ := range pgtypeTypes { + if uses(typeName) { + pkg[ImportSpec{Path: "github.com/jackc/pgtype"}] = struct{}{} + } + } + + for typeName, _ := range pqtypeTypes { + if uses(typeName) { + pkg[ImportSpec{Path: "github.com/tabbed/pqtype"}] = struct{}{} + } + } + overrideTypes := map[string]string{} for _, o := range settings.Overrides { if o.GoBasicType || o.GoTypeName == "" { diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go index 42b4be0da0..c5e0d7fde0 100644 --- a/internal/codegen/golang/postgresql_type.go +++ b/internal/codegen/golang/postgresql_type.go @@ -12,6 +12,7 @@ import ( func postgresType(r *compiler.Result, col *compiler.Column, settings config.CombinedSettings) string { columnType := col.DataType notNull := col.NotNull || col.IsArray + driver := parseDriver(settings) switch columnType { case "serial", "serial4", "pg_catalog.serial4": @@ -108,11 +109,35 @@ func postgresType(r *compiler.Result, col *compiler.Column, settings config.Comb } return "uuid.NullUUID" - case "inet", "cidr": - return "net.IP" + case "inet": + switch driver { + case SQLDriverPGXV4: + return "pgtype.Inet" + case SQLDriverLibPQ: + return "pqtype.Inet" + default: + return "interface{}" + } + + case "cidr": + switch driver { + case SQLDriverPGXV4: + return "pgtype.CIDR" + case SQLDriverLibPQ: + return "pqtype.CIDR" + default: + return "interface{}" + } case "macaddr", "macaddr8": - return "net.HardwareAddr" + switch driver { + case SQLDriverPGXV4: + return "pgtype.Macaddr" + case SQLDriverLibPQ: + return "pqtype.Macaddr" + default: + return "interface{}" + } case "ltree", "lquery", "ltxtquery": // This module implements a data type ltree for representing labels diff --git a/internal/endtoend/testdata/func_return/posgresql/pgx/go/db.go b/internal/endtoend/testdata/func_return/postgresql/pgx/go/db.go similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/pgx/go/db.go rename to internal/endtoend/testdata/func_return/postgresql/pgx/go/db.go diff --git a/internal/endtoend/testdata/func_return/posgresql/pgx/go/models.go b/internal/endtoend/testdata/func_return/postgresql/pgx/go/models.go similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/pgx/go/models.go rename to internal/endtoend/testdata/func_return/postgresql/pgx/go/models.go diff --git a/internal/endtoend/testdata/func_return/posgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/func_return/postgresql/pgx/go/query.sql.go similarity index 96% rename from internal/endtoend/testdata/func_return/posgresql/pgx/go/query.sql.go rename to internal/endtoend/testdata/func_return/postgresql/pgx/go/query.sql.go index b8775974a0..44d4b34f13 100644 --- a/internal/endtoend/testdata/func_return/posgresql/pgx/go/query.sql.go +++ b/internal/endtoend/testdata/func_return/postgresql/pgx/go/query.sql.go @@ -5,7 +5,8 @@ package querytest import ( "context" - "net" + + "github.com/jackc/pgtype" ) const generateSeries = `-- name: GenerateSeries :many @@ -15,7 +16,7 @@ LIMIT 1 ` type GenerateSeriesParams struct { - Column1 net.IP + Column1 pgtype.Inet Column2 int32 } diff --git a/internal/endtoend/testdata/func_return/posgresql/pgx/query.sql b/internal/endtoend/testdata/func_return/postgresql/pgx/query.sql similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/pgx/query.sql rename to internal/endtoend/testdata/func_return/postgresql/pgx/query.sql diff --git a/internal/endtoend/testdata/func_return/posgresql/pgx/schema.sql b/internal/endtoend/testdata/func_return/postgresql/pgx/schema.sql similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/pgx/schema.sql rename to internal/endtoend/testdata/func_return/postgresql/pgx/schema.sql diff --git a/internal/endtoend/testdata/func_return/posgresql/pgx/sqlc.json b/internal/endtoend/testdata/func_return/postgresql/pgx/sqlc.json similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/pgx/sqlc.json rename to internal/endtoend/testdata/func_return/postgresql/pgx/sqlc.json diff --git a/internal/endtoend/testdata/func_return/posgresql/stdlib/go/db.go b/internal/endtoend/testdata/func_return/postgresql/stdlib/go/db.go similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/stdlib/go/db.go rename to internal/endtoend/testdata/func_return/postgresql/stdlib/go/db.go diff --git a/internal/endtoend/testdata/func_return/posgresql/stdlib/go/models.go b/internal/endtoend/testdata/func_return/postgresql/stdlib/go/models.go similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/stdlib/go/models.go rename to internal/endtoend/testdata/func_return/postgresql/stdlib/go/models.go diff --git a/internal/endtoend/testdata/func_return/posgresql/stdlib/go/query.sql.go b/internal/endtoend/testdata/func_return/postgresql/stdlib/go/query.sql.go similarity index 96% rename from internal/endtoend/testdata/func_return/posgresql/stdlib/go/query.sql.go rename to internal/endtoend/testdata/func_return/postgresql/stdlib/go/query.sql.go index 990f335916..fb51f3daea 100644 --- a/internal/endtoend/testdata/func_return/posgresql/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/func_return/postgresql/stdlib/go/query.sql.go @@ -5,7 +5,8 @@ package querytest import ( "context" - "net" + + "github.com/tabbed/pqtype" ) const generateSeries = `-- name: GenerateSeries :many @@ -15,7 +16,7 @@ LIMIT 1 ` type GenerateSeriesParams struct { - Column1 net.IP + Column1 pqtype.Inet Column2 int32 } diff --git a/internal/endtoend/testdata/func_return/posgresql/stdlib/query.sql b/internal/endtoend/testdata/func_return/postgresql/stdlib/query.sql similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/stdlib/query.sql rename to internal/endtoend/testdata/func_return/postgresql/stdlib/query.sql diff --git a/internal/endtoend/testdata/func_return/posgresql/stdlib/schema.sql b/internal/endtoend/testdata/func_return/postgresql/stdlib/schema.sql similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/stdlib/schema.sql rename to internal/endtoend/testdata/func_return/postgresql/stdlib/schema.sql diff --git a/internal/endtoend/testdata/func_return/posgresql/stdlib/sqlc.json b/internal/endtoend/testdata/func_return/postgresql/stdlib/sqlc.json similarity index 100% rename from internal/endtoend/testdata/func_return/posgresql/stdlib/sqlc.json rename to internal/endtoend/testdata/func_return/postgresql/stdlib/sqlc.json diff --git a/internal/endtoend/testdata/go.mod b/internal/endtoend/testdata/go.mod index 3304264df2..999f37b360 100644 --- a/internal/endtoend/testdata/go.mod +++ b/internal/endtoend/testdata/go.mod @@ -10,6 +10,7 @@ require ( github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904 github.com/kyleconroy/sqlc-testdata v0.0.0-20200512000015-15313bc43553 github.com/lib/pq v1.9.0 + github.com/tabbed/pqtype v0.1.0 // indirect github.com/volatiletech/null/v8 v8.1.2 gopkg.in/guregu/null.v4 v4.0.0 ) diff --git a/internal/endtoend/testdata/go.sum b/internal/endtoend/testdata/go.sum index 5398eca4f4..efdad878f2 100644 --- a/internal/endtoend/testdata/go.sum +++ b/internal/endtoend/testdata/go.sum @@ -110,6 +110,8 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/tabbed/pqtype v0.1.0 h1:14Up99XVLn1feoYN6yOe6lKcF7159EJ5JqUXntkeFeI= +github.com/tabbed/pqtype v0.1.0/go.mod h1:HLt2kLJPcUhODQkYn3mJkMHXVsuv3Z2n5NZEeKXL0Uk= github.com/volatiletech/inflect v0.0.1 h1:2a6FcMQyhmPZcLa+uet3VJ8gLn/9svWhJxJYwvE8KsU= github.com/volatiletech/inflect v0.0.1/go.mod h1:IBti31tG6phkHitLlr5j7shC5SOo//x0AjDzaJU1PLA= github.com/volatiletech/null/v8 v8.1.2 h1:kiTiX1PpwvuugKwfvUNX/SU/5A2KGZMXfGD0DUHdKEI= diff --git a/internal/endtoend/testdata/macaddr/pgx/go/db.go b/internal/endtoend/testdata/macaddr/pgx/go/db.go deleted file mode 100644 index 4559f50a4f..0000000000 --- a/internal/endtoend/testdata/macaddr/pgx/go/db.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -import ( - "context" - - "github.com/jackc/pgconn" - "github.com/jackc/pgx/v4" -) - -type DBTX interface { - Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) - Query(context.Context, string, ...interface{}) (pgx.Rows, error) - QueryRow(context.Context, string, ...interface{}) pgx.Row -} - -func New(db DBTX) *Queries { - return &Queries{db: db} -} - -type Queries struct { - db DBTX -} - -func (q *Queries) WithTx(tx pgx.Tx) *Queries { - return &Queries{ - db: tx, - } -} diff --git a/internal/endtoend/testdata/macaddr/pgx/go/models.go b/internal/endtoend/testdata/macaddr/pgx/go/models.go deleted file mode 100644 index 0681470ceb..0000000000 --- a/internal/endtoend/testdata/macaddr/pgx/go/models.go +++ /dev/null @@ -1,12 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -import ( - "net" -) - -type Foo struct { - Bar bool - Addr net.HardwareAddr -} diff --git a/internal/endtoend/testdata/macaddr/pgx/go/query.sql.go b/internal/endtoend/testdata/macaddr/pgx/go/query.sql.go deleted file mode 100644 index ad30e94bee..0000000000 --- a/internal/endtoend/testdata/macaddr/pgx/go/query.sql.go +++ /dev/null @@ -1,57 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// source: query.sql - -package querytest - -import ( - "context" - "net" -) - -const get = `-- name: Get :many -SELECT bar, addr FROM foo LIMIT $1 -` - -func (q *Queries) Get(ctx context.Context, limit int32) ([]Foo, error) { - rows, err := q.db.Query(ctx, get, limit) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Foo - for rows.Next() { - var i Foo - if err := rows.Scan(&i.Bar, &i.Addr); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getAddr = `-- name: GetAddr :many -SELECT addr FROM foo LIMIT $1 -` - -func (q *Queries) GetAddr(ctx context.Context, limit int32) ([]net.HardwareAddr, error) { - rows, err := q.db.Query(ctx, getAddr, limit) - if err != nil { - return nil, err - } - defer rows.Close() - var items []net.HardwareAddr - for rows.Next() { - var addr net.HardwareAddr - if err := rows.Scan(&addr); err != nil { - return nil, err - } - items = append(items, addr) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} diff --git a/internal/endtoend/testdata/macaddr/pgx/query.sql b/internal/endtoend/testdata/macaddr/pgx/query.sql deleted file mode 100644 index 4b0fa2203e..0000000000 --- a/internal/endtoend/testdata/macaddr/pgx/query.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE foo (bar bool not null, addr macaddr not null); - --- name: Get :many -SELECT bar, addr FROM foo LIMIT $1; - --- name: GetAddr :many -SELECT addr FROM foo LIMIT $1; diff --git a/internal/endtoend/testdata/macaddr/pgx/sqlc.json b/internal/endtoend/testdata/macaddr/pgx/sqlc.json deleted file mode 100644 index 9403bd0279..0000000000 --- a/internal/endtoend/testdata/macaddr/pgx/sqlc.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": "1", - "packages": [ - { - "path": "go", - "engine": "postgresql", - "sql_package": "pgx/v4", - "name": "querytest", - "schema": "query.sql", - "queries": "query.sql" - } - ] -} diff --git a/internal/endtoend/testdata/macaddr/stdlib/go/db.go b/internal/endtoend/testdata/macaddr/stdlib/go/db.go deleted file mode 100644 index 6a99519302..0000000000 --- a/internal/endtoend/testdata/macaddr/stdlib/go/db.go +++ /dev/null @@ -1,29 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -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/macaddr/stdlib/go/models.go b/internal/endtoend/testdata/macaddr/stdlib/go/models.go deleted file mode 100644 index 0681470ceb..0000000000 --- a/internal/endtoend/testdata/macaddr/stdlib/go/models.go +++ /dev/null @@ -1,12 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -import ( - "net" -) - -type Foo struct { - Bar bool - Addr net.HardwareAddr -} diff --git a/internal/endtoend/testdata/macaddr/stdlib/go/query.sql.go b/internal/endtoend/testdata/macaddr/stdlib/go/query.sql.go deleted file mode 100644 index ce14bdd56d..0000000000 --- a/internal/endtoend/testdata/macaddr/stdlib/go/query.sql.go +++ /dev/null @@ -1,63 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// source: query.sql - -package querytest - -import ( - "context" - "net" -) - -const get = `-- name: Get :many -SELECT bar, addr FROM foo LIMIT $1 -` - -func (q *Queries) Get(ctx context.Context, limit int32) ([]Foo, error) { - rows, err := q.db.QueryContext(ctx, get, limit) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Foo - for rows.Next() { - var i Foo - if err := rows.Scan(&i.Bar, &i.Addr); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const getAddr = `-- name: GetAddr :many -SELECT addr FROM foo LIMIT $1 -` - -func (q *Queries) GetAddr(ctx context.Context, limit int32) ([]net.HardwareAddr, error) { - rows, err := q.db.QueryContext(ctx, getAddr, limit) - if err != nil { - return nil, err - } - defer rows.Close() - var items []net.HardwareAddr - for rows.Next() { - var addr net.HardwareAddr - if err := rows.Scan(&addr); err != nil { - return nil, err - } - items = append(items, addr) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} diff --git a/internal/endtoend/testdata/macaddr/stdlib/query.sql b/internal/endtoend/testdata/macaddr/stdlib/query.sql deleted file mode 100644 index 4b0fa2203e..0000000000 --- a/internal/endtoend/testdata/macaddr/stdlib/query.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE foo (bar bool not null, addr macaddr not null); - --- name: Get :many -SELECT bar, addr FROM foo LIMIT $1; - --- name: GetAddr :many -SELECT addr FROM foo LIMIT $1; diff --git a/internal/endtoend/testdata/macaddr/stdlib/sqlc.json b/internal/endtoend/testdata/macaddr/stdlib/sqlc.json deleted file mode 100644 index ac7c2ed829..0000000000 --- a/internal/endtoend/testdata/macaddr/stdlib/sqlc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "1", - "packages": [ - { - "path": "go", - "name": "querytest", - "schema": "query.sql", - "queries": "query.sql" - } - ] -} diff --git a/internal/endtoend/testdata/types_network_address/pgx/go/models.go b/internal/endtoend/testdata/types_network_address/pgx/go/models.go index c9b78920d4..16e1c6001c 100644 --- a/internal/endtoend/testdata/types_network_address/pgx/go/models.go +++ b/internal/endtoend/testdata/types_network_address/pgx/go/models.go @@ -3,11 +3,17 @@ package querytest import ( - "net" + "github.com/jackc/pgtype" ) +type Bar struct { + Addr pgtype.Macaddr + NullableAddr pgtype.Macaddr +} + type Foo struct { - Bar bool - Inet net.IP - Cidr net.IP + PresentIp pgtype.Inet + NullableIp pgtype.Inet + PresentCidr pgtype.CIDR + NullableCidr pgtype.CIDR } diff --git a/internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go b/internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go index cb2cda6b98..bd6d214a4e 100644 --- a/internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go +++ b/internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go @@ -5,14 +5,86 @@ package querytest import ( "context" + + "github.com/jackc/pgtype" ) -const get = `-- name: Get :many -SELECT bar, "inet", "cidr" FROM foo LIMIT $1 +const findBarByAddr = `-- name: FindBarByAddr :one +SELECT addr, nullable_addr FROM bar +WHERE addr = $1 +` + +func (q *Queries) FindBarByAddr(ctx context.Context, addr pgtype.Macaddr) (Bar, error) { + row := q.db.QueryRow(ctx, findBarByAddr, addr) + var i Bar + err := row.Scan(&i.Addr, &i.NullableAddr) + return i, err +} + +const findFooByCIDR = `-- name: FindFooByCIDR :one +SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo +WHERE present_cidr = $1 +` + +func (q *Queries) FindFooByCIDR(ctx context.Context, presentCidr pgtype.CIDR) (Foo, error) { + row := q.db.QueryRow(ctx, findFooByCIDR, presentCidr) + var i Foo + err := row.Scan( + &i.PresentIp, + &i.NullableIp, + &i.PresentCidr, + &i.NullableCidr, + ) + return i, err +} + +const findFooByIP = `-- name: FindFooByIP :one +SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo +WHERE present_ip = $1 +` + +func (q *Queries) FindFooByIP(ctx context.Context, presentIp pgtype.Inet) (Foo, error) { + row := q.db.QueryRow(ctx, findFooByIP, presentIp) + var i Foo + err := row.Scan( + &i.PresentIp, + &i.NullableIp, + &i.PresentCidr, + &i.NullableCidr, + ) + return i, err +} + +const listBar = `-- name: ListBar :many +SELECT addr, nullable_addr FROM bar +` + +func (q *Queries) ListBar(ctx context.Context) ([]Bar, error) { + rows, err := q.db.Query(ctx, listBar) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Bar + for rows.Next() { + var i Bar + if err := rows.Scan(&i.Addr, &i.NullableAddr); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listFoo = `-- name: ListFoo :many +SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo ` -func (q *Queries) Get(ctx context.Context, limit int32) ([]Foo, error) { - rows, err := q.db.Query(ctx, get, limit) +func (q *Queries) ListFoo(ctx context.Context) ([]Foo, error) { + rows, err := q.db.Query(ctx, listFoo) if err != nil { return nil, err } @@ -20,7 +92,12 @@ func (q *Queries) Get(ctx context.Context, limit int32) ([]Foo, error) { var items []Foo for rows.Next() { var i Foo - if err := rows.Scan(&i.Bar, &i.Inet, &i.Cidr); err != nil { + if err := rows.Scan( + &i.PresentIp, + &i.NullableIp, + &i.PresentCidr, + &i.NullableCidr, + ); err != nil { return nil, err } items = append(items, i) diff --git a/internal/endtoend/testdata/types_network_address/pgx/query.sql b/internal/endtoend/testdata/types_network_address/pgx/query.sql index 11b6b5c820..b1576896a6 100644 --- a/internal/endtoend/testdata/types_network_address/pgx/query.sql +++ b/internal/endtoend/testdata/types_network_address/pgx/query.sql @@ -1,4 +1,29 @@ -CREATE TABLE foo (bar bool not null, "inet" inet not null, "cidr" cidr not null); +CREATE TABLE foo ( + present_ip inet not null, + nullable_ip inet, + present_cidr cidr not null, + nullable_cidr cidr +); --- name: Get :many -SELECT bar, "inet", "cidr" FROM foo LIMIT $1; +CREATE TABLE bar ( + addr macaddr not null, + nullable_addr macaddr +); + +-- name: ListFoo :many +SELECT * FROM foo; + +-- name: FindFooByIP :one +SELECT * FROM foo +WHERE present_ip = $1; + +-- name: FindFooByCIDR :one +SELECT * FROM foo +WHERE present_cidr = $1; + +-- name: ListBar :many +SELECT * FROM bar; + +-- name: FindBarByAddr :one +SELECT * FROM bar +WHERE addr = $1; diff --git a/internal/endtoend/testdata/types_network_address/stdlib/go/models.go b/internal/endtoend/testdata/types_network_address/stdlib/go/models.go index c9b78920d4..4c295838dc 100644 --- a/internal/endtoend/testdata/types_network_address/stdlib/go/models.go +++ b/internal/endtoend/testdata/types_network_address/stdlib/go/models.go @@ -3,11 +3,17 @@ package querytest import ( - "net" + "github.com/tabbed/pqtype" ) +type Bar struct { + Addr pqtype.Macaddr + NullableAddr pqtype.Macaddr +} + type Foo struct { - Bar bool - Inet net.IP - Cidr net.IP + PresentIp pqtype.Inet + NullableIp pqtype.Inet + PresentCidr pqtype.CIDR + NullableCidr pqtype.CIDR } diff --git a/internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go b/internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go index 1bdc311a36..26d1313f6f 100644 --- a/internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go +++ b/internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go @@ -5,14 +5,89 @@ package querytest import ( "context" + + "github.com/tabbed/pqtype" ) -const get = `-- name: Get :many -SELECT bar, "inet", "cidr" FROM foo LIMIT $1 +const findBarByAddr = `-- name: FindBarByAddr :one +SELECT addr, nullable_addr FROM bar +WHERE addr = $1 +` + +func (q *Queries) FindBarByAddr(ctx context.Context, addr pqtype.Macaddr) (Bar, error) { + row := q.db.QueryRowContext(ctx, findBarByAddr, addr) + var i Bar + err := row.Scan(&i.Addr, &i.NullableAddr) + return i, err +} + +const findFooByCIDR = `-- name: FindFooByCIDR :one +SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo +WHERE present_cidr = $1 +` + +func (q *Queries) FindFooByCIDR(ctx context.Context, presentCidr pqtype.CIDR) (Foo, error) { + row := q.db.QueryRowContext(ctx, findFooByCIDR, presentCidr) + var i Foo + err := row.Scan( + &i.PresentIp, + &i.NullableIp, + &i.PresentCidr, + &i.NullableCidr, + ) + return i, err +} + +const findFooByIP = `-- name: FindFooByIP :one +SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo +WHERE present_ip = $1 +` + +func (q *Queries) FindFooByIP(ctx context.Context, presentIp pqtype.Inet) (Foo, error) { + row := q.db.QueryRowContext(ctx, findFooByIP, presentIp) + var i Foo + err := row.Scan( + &i.PresentIp, + &i.NullableIp, + &i.PresentCidr, + &i.NullableCidr, + ) + return i, err +} + +const listBar = `-- name: ListBar :many +SELECT addr, nullable_addr FROM bar +` + +func (q *Queries) ListBar(ctx context.Context) ([]Bar, error) { + rows, err := q.db.QueryContext(ctx, listBar) + if err != nil { + return nil, err + } + defer rows.Close() + var items []Bar + for rows.Next() { + var i Bar + if err := rows.Scan(&i.Addr, &i.NullableAddr); err != nil { + return nil, err + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listFoo = `-- name: ListFoo :many +SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo ` -func (q *Queries) Get(ctx context.Context, limit int32) ([]Foo, error) { - rows, err := q.db.QueryContext(ctx, get, limit) +func (q *Queries) ListFoo(ctx context.Context) ([]Foo, error) { + rows, err := q.db.QueryContext(ctx, listFoo) if err != nil { return nil, err } @@ -20,7 +95,12 @@ func (q *Queries) Get(ctx context.Context, limit int32) ([]Foo, error) { var items []Foo for rows.Next() { var i Foo - if err := rows.Scan(&i.Bar, &i.Inet, &i.Cidr); err != nil { + if err := rows.Scan( + &i.PresentIp, + &i.NullableIp, + &i.PresentCidr, + &i.NullableCidr, + ); err != nil { return nil, err } items = append(items, i) diff --git a/internal/endtoend/testdata/types_network_address/stdlib/query.sql b/internal/endtoend/testdata/types_network_address/stdlib/query.sql index 11b6b5c820..b1576896a6 100644 --- a/internal/endtoend/testdata/types_network_address/stdlib/query.sql +++ b/internal/endtoend/testdata/types_network_address/stdlib/query.sql @@ -1,4 +1,29 @@ -CREATE TABLE foo (bar bool not null, "inet" inet not null, "cidr" cidr not null); +CREATE TABLE foo ( + present_ip inet not null, + nullable_ip inet, + present_cidr cidr not null, + nullable_cidr cidr +); --- name: Get :many -SELECT bar, "inet", "cidr" FROM foo LIMIT $1; +CREATE TABLE bar ( + addr macaddr not null, + nullable_addr macaddr +); + +-- name: ListFoo :many +SELECT * FROM foo; + +-- name: FindFooByIP :one +SELECT * FROM foo +WHERE present_ip = $1; + +-- name: FindFooByCIDR :one +SELECT * FROM foo +WHERE present_cidr = $1; + +-- name: ListBar :many +SELECT * FROM bar; + +-- name: FindBarByAddr :one +SELECT * FROM bar +WHERE addr = $1; From 31143391cd4c8fa566154f72f0eb2327dbd7903c Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sun, 22 Aug 2021 21:23:41 -0700 Subject: [PATCH 11/22] When using pgx, map numeric types to pgtype.Numeric (#1143) * endtoend: Consolidate test cases * codegen/golang: numeric -> pgtype.Numeric for pgx Fix the regenration script to always pass the `experimental` flag. --- internal/codegen/golang/imports.go | 1 + internal/codegen/golang/postgresql_type.go | 3 + .../testdata/datatype/pgx/go/models.go | 22 +++- .../testdata/datatype/pgx/sql/net-types.sql | 13 ++ .../testdata/datatype/stdlib/go/models.go | 14 +++ .../datatype/stdlib/sql/net-types.sql | 13 ++ .../postgresql/pgx/go/models.go | 4 +- .../postgresql/pgx/go/query.sql.go | 6 +- .../postgresql/pgx/go/query.sql.go | 8 +- .../types_network_address/pgx/go/db.go | 30 ----- .../types_network_address/pgx/go/models.go | 19 --- .../types_network_address/pgx/go/query.sql.go | 109 ----------------- .../types_network_address/pgx/query.sql | 29 ----- .../types_network_address/pgx/sqlc.json | 13 -- .../types_network_address/stdlib/go/db.go | 29 ----- .../types_network_address/stdlib/go/models.go | 19 --- .../stdlib/go/query.sql.go | 115 ------------------ .../types_network_address/stdlib/query.sql | 29 ----- .../types_network_address/stdlib/sqlc.json | 11 -- scripts/regenerate/main.go | 2 +- 20 files changed, 75 insertions(+), 414 deletions(-) create mode 100644 internal/endtoend/testdata/datatype/pgx/sql/net-types.sql create mode 100644 internal/endtoend/testdata/datatype/stdlib/sql/net-types.sql delete mode 100644 internal/endtoend/testdata/types_network_address/pgx/go/db.go delete mode 100644 internal/endtoend/testdata/types_network_address/pgx/go/models.go delete mode 100644 internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go delete mode 100644 internal/endtoend/testdata/types_network_address/pgx/query.sql delete mode 100644 internal/endtoend/testdata/types_network_address/pgx/sqlc.json delete mode 100644 internal/endtoend/testdata/types_network_address/stdlib/go/db.go delete mode 100644 internal/endtoend/testdata/types_network_address/stdlib/go/models.go delete mode 100644 internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go delete mode 100644 internal/endtoend/testdata/types_network_address/stdlib/query.sql delete mode 100644 internal/endtoend/testdata/types_network_address/stdlib/sqlc.json diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 0f6dca633e..e40bddd779 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -136,6 +136,7 @@ var pgtypeTypes = map[string]struct{}{ "pgtype.CIDR": {}, "pgtype.Inet": {}, "pgtype.Macaddr": {}, + "pgtype.Numeric": {}, } var pqtypeTypes = map[string]struct{}{ diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go index c5e0d7fde0..b55386b3fd 100644 --- a/internal/codegen/golang/postgresql_type.go +++ b/internal/codegen/golang/postgresql_type.go @@ -58,6 +58,9 @@ func postgresType(r *compiler.Result, col *compiler.Column, settings config.Comb return "sql.NullFloat64" // TODO: Change to sql.NullFloat32 after updating the go.mod file case "numeric", "pg_catalog.numeric", "money": + if driver == SQLDriverPGXV4 { + return "pgtype.Numeric" + } // Since the Go standard library does not have a decimal type, lib/pq // returns numerics as strings. // diff --git a/internal/endtoend/testdata/datatype/pgx/go/models.go b/internal/endtoend/testdata/datatype/pgx/go/models.go index 0527cfff54..3877de48c1 100644 --- a/internal/endtoend/testdata/datatype/pgx/go/models.go +++ b/internal/endtoend/testdata/datatype/pgx/go/models.go @@ -5,6 +5,8 @@ package datatype import ( "database/sql" "time" + + "github.com/jackc/pgtype" ) type DtCharacter struct { @@ -45,12 +47,24 @@ type DtDatetimeNotNull struct { H time.Time } +type DtNetType struct { + A pgtype.Inet + B pgtype.CIDR + C pgtype.Macaddr +} + +type DtNetTypesNotNull struct { + A pgtype.Inet + B pgtype.CIDR + C pgtype.Macaddr +} + type DtNumeric struct { A int16 B sql.NullInt32 C sql.NullInt64 - D sql.NullString - E sql.NullString + D pgtype.Numeric + E pgtype.Numeric F sql.NullFloat64 G sql.NullFloat64 H int16 @@ -65,8 +79,8 @@ type DtNumericNotNull struct { A int16 B int32 C int64 - D string - E string + D pgtype.Numeric + E pgtype.Numeric F float32 G float64 H int16 diff --git a/internal/endtoend/testdata/datatype/pgx/sql/net-types.sql b/internal/endtoend/testdata/datatype/pgx/sql/net-types.sql new file mode 100644 index 0000000000..6239b6f9f6 --- /dev/null +++ b/internal/endtoend/testdata/datatype/pgx/sql/net-types.sql @@ -0,0 +1,13 @@ +-- Network Address Types +-- https://www.postgresql.org/docs/current/datatype-net-types.html +CREATE TABLE dt_net_types ( + a inet, + b cidr, + c macaddr +); + +CREATE TABLE dt_net_types_not_null ( + a inet NOT NULL, + b cidr NOT NULL, + c macaddr NOT NULL +); diff --git a/internal/endtoend/testdata/datatype/stdlib/go/models.go b/internal/endtoend/testdata/datatype/stdlib/go/models.go index 0527cfff54..5068324852 100644 --- a/internal/endtoend/testdata/datatype/stdlib/go/models.go +++ b/internal/endtoend/testdata/datatype/stdlib/go/models.go @@ -5,6 +5,8 @@ package datatype import ( "database/sql" "time" + + "github.com/tabbed/pqtype" ) type DtCharacter struct { @@ -45,6 +47,18 @@ type DtDatetimeNotNull struct { H time.Time } +type DtNetType struct { + A pqtype.Inet + B pqtype.CIDR + C pqtype.Macaddr +} + +type DtNetTypesNotNull struct { + A pqtype.Inet + B pqtype.CIDR + C pqtype.Macaddr +} + type DtNumeric struct { A int16 B sql.NullInt32 diff --git a/internal/endtoend/testdata/datatype/stdlib/sql/net-types.sql b/internal/endtoend/testdata/datatype/stdlib/sql/net-types.sql new file mode 100644 index 0000000000..6239b6f9f6 --- /dev/null +++ b/internal/endtoend/testdata/datatype/stdlib/sql/net-types.sql @@ -0,0 +1,13 @@ +-- Network Address Types +-- https://www.postgresql.org/docs/current/datatype-net-types.html +CREATE TABLE dt_net_types ( + a inet, + b cidr, + c macaddr +); + +CREATE TABLE dt_net_types_not_null ( + a inet NOT NULL, + b cidr NOT NULL, + c macaddr NOT NULL +); diff --git a/internal/endtoend/testdata/params_location/postgresql/pgx/go/models.go b/internal/endtoend/testdata/params_location/postgresql/pgx/go/models.go index 2a3630d6b8..465cd087e7 100644 --- a/internal/endtoend/testdata/params_location/postgresql/pgx/go/models.go +++ b/internal/endtoend/testdata/params_location/postgresql/pgx/go/models.go @@ -4,11 +4,13 @@ package querytest import ( "database/sql" + + "github.com/jackc/pgtype" ) type Order struct { ID int32 - Price string + Price pgtype.Numeric UserID int32 } diff --git a/internal/endtoend/testdata/params_location/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/params_location/postgresql/pgx/go/query.sql.go index 63de450bcb..ba01fa1e28 100644 --- a/internal/endtoend/testdata/params_location/postgresql/pgx/go/query.sql.go +++ b/internal/endtoend/testdata/params_location/postgresql/pgx/go/query.sql.go @@ -6,6 +6,8 @@ package querytest import ( "context" "database/sql" + + "github.com/jackc/pgtype" ) const getUserByID = `-- name: GetUserByID :one @@ -82,10 +84,10 @@ WHERE orders.price > $1 type ListUserOrdersRow struct { ID sql.NullInt32 FirstName sql.NullString - Price string + Price pgtype.Numeric } -func (q *Queries) ListUserOrders(ctx context.Context, minPrice string) ([]ListUserOrdersRow, error) { +func (q *Queries) ListUserOrders(ctx context.Context, minPrice pgtype.Numeric) ([]ListUserOrdersRow, error) { rows, err := q.db.Query(ctx, listUserOrders, minPrice) if err != nil { return nil, err diff --git a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/go/query.sql.go index 337ba15b5e..575f2dd596 100644 --- a/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/go/query.sql.go +++ b/internal/endtoend/testdata/pg_generate_series/postgresql/pgx/go/query.sql.go @@ -6,6 +6,8 @@ package querytest import ( "context" "time" + + "github.com/jackc/pgtype" ) const generateSeries = `-- name: GenerateSeries :many @@ -17,15 +19,15 @@ type GenerateSeriesParams struct { Column2 time.Time `json:"column_2"` } -func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]string, error) { +func (q *Queries) GenerateSeries(ctx context.Context, arg GenerateSeriesParams) ([]pgtype.Numeric, error) { rows, err := q.db.Query(ctx, generateSeries, arg.Column1, arg.Column2) if err != nil { return nil, err } defer rows.Close() - var items []string + var items []pgtype.Numeric for rows.Next() { - var generate_series string + var generate_series pgtype.Numeric if err := rows.Scan(&generate_series); err != nil { return nil, err } diff --git a/internal/endtoend/testdata/types_network_address/pgx/go/db.go b/internal/endtoend/testdata/types_network_address/pgx/go/db.go deleted file mode 100644 index 4559f50a4f..0000000000 --- a/internal/endtoend/testdata/types_network_address/pgx/go/db.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -import ( - "context" - - "github.com/jackc/pgconn" - "github.com/jackc/pgx/v4" -) - -type DBTX interface { - Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) - Query(context.Context, string, ...interface{}) (pgx.Rows, error) - QueryRow(context.Context, string, ...interface{}) pgx.Row -} - -func New(db DBTX) *Queries { - return &Queries{db: db} -} - -type Queries struct { - db DBTX -} - -func (q *Queries) WithTx(tx pgx.Tx) *Queries { - return &Queries{ - db: tx, - } -} diff --git a/internal/endtoend/testdata/types_network_address/pgx/go/models.go b/internal/endtoend/testdata/types_network_address/pgx/go/models.go deleted file mode 100644 index 16e1c6001c..0000000000 --- a/internal/endtoend/testdata/types_network_address/pgx/go/models.go +++ /dev/null @@ -1,19 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -import ( - "github.com/jackc/pgtype" -) - -type Bar struct { - Addr pgtype.Macaddr - NullableAddr pgtype.Macaddr -} - -type Foo struct { - PresentIp pgtype.Inet - NullableIp pgtype.Inet - PresentCidr pgtype.CIDR - NullableCidr pgtype.CIDR -} diff --git a/internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go b/internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go deleted file mode 100644 index bd6d214a4e..0000000000 --- a/internal/endtoend/testdata/types_network_address/pgx/go/query.sql.go +++ /dev/null @@ -1,109 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// source: query.sql - -package querytest - -import ( - "context" - - "github.com/jackc/pgtype" -) - -const findBarByAddr = `-- name: FindBarByAddr :one -SELECT addr, nullable_addr FROM bar -WHERE addr = $1 -` - -func (q *Queries) FindBarByAddr(ctx context.Context, addr pgtype.Macaddr) (Bar, error) { - row := q.db.QueryRow(ctx, findBarByAddr, addr) - var i Bar - err := row.Scan(&i.Addr, &i.NullableAddr) - return i, err -} - -const findFooByCIDR = `-- name: FindFooByCIDR :one -SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo -WHERE present_cidr = $1 -` - -func (q *Queries) FindFooByCIDR(ctx context.Context, presentCidr pgtype.CIDR) (Foo, error) { - row := q.db.QueryRow(ctx, findFooByCIDR, presentCidr) - var i Foo - err := row.Scan( - &i.PresentIp, - &i.NullableIp, - &i.PresentCidr, - &i.NullableCidr, - ) - return i, err -} - -const findFooByIP = `-- name: FindFooByIP :one -SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo -WHERE present_ip = $1 -` - -func (q *Queries) FindFooByIP(ctx context.Context, presentIp pgtype.Inet) (Foo, error) { - row := q.db.QueryRow(ctx, findFooByIP, presentIp) - var i Foo - err := row.Scan( - &i.PresentIp, - &i.NullableIp, - &i.PresentCidr, - &i.NullableCidr, - ) - return i, err -} - -const listBar = `-- name: ListBar :many -SELECT addr, nullable_addr FROM bar -` - -func (q *Queries) ListBar(ctx context.Context) ([]Bar, error) { - rows, err := q.db.Query(ctx, listBar) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Bar - for rows.Next() { - var i Bar - if err := rows.Scan(&i.Addr, &i.NullableAddr); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const listFoo = `-- name: ListFoo :many -SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo -` - -func (q *Queries) ListFoo(ctx context.Context) ([]Foo, error) { - rows, err := q.db.Query(ctx, listFoo) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Foo - for rows.Next() { - var i Foo - if err := rows.Scan( - &i.PresentIp, - &i.NullableIp, - &i.PresentCidr, - &i.NullableCidr, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} diff --git a/internal/endtoend/testdata/types_network_address/pgx/query.sql b/internal/endtoend/testdata/types_network_address/pgx/query.sql deleted file mode 100644 index b1576896a6..0000000000 --- a/internal/endtoend/testdata/types_network_address/pgx/query.sql +++ /dev/null @@ -1,29 +0,0 @@ -CREATE TABLE foo ( - present_ip inet not null, - nullable_ip inet, - present_cidr cidr not null, - nullable_cidr cidr -); - -CREATE TABLE bar ( - addr macaddr not null, - nullable_addr macaddr -); - --- name: ListFoo :many -SELECT * FROM foo; - --- name: FindFooByIP :one -SELECT * FROM foo -WHERE present_ip = $1; - --- name: FindFooByCIDR :one -SELECT * FROM foo -WHERE present_cidr = $1; - --- name: ListBar :many -SELECT * FROM bar; - --- name: FindBarByAddr :one -SELECT * FROM bar -WHERE addr = $1; diff --git a/internal/endtoend/testdata/types_network_address/pgx/sqlc.json b/internal/endtoend/testdata/types_network_address/pgx/sqlc.json deleted file mode 100644 index 9403bd0279..0000000000 --- a/internal/endtoend/testdata/types_network_address/pgx/sqlc.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "version": "1", - "packages": [ - { - "path": "go", - "engine": "postgresql", - "sql_package": "pgx/v4", - "name": "querytest", - "schema": "query.sql", - "queries": "query.sql" - } - ] -} diff --git a/internal/endtoend/testdata/types_network_address/stdlib/go/db.go b/internal/endtoend/testdata/types_network_address/stdlib/go/db.go deleted file mode 100644 index 6a99519302..0000000000 --- a/internal/endtoend/testdata/types_network_address/stdlib/go/db.go +++ /dev/null @@ -1,29 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -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/types_network_address/stdlib/go/models.go b/internal/endtoend/testdata/types_network_address/stdlib/go/models.go deleted file mode 100644 index 4c295838dc..0000000000 --- a/internal/endtoend/testdata/types_network_address/stdlib/go/models.go +++ /dev/null @@ -1,19 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -import ( - "github.com/tabbed/pqtype" -) - -type Bar struct { - Addr pqtype.Macaddr - NullableAddr pqtype.Macaddr -} - -type Foo struct { - PresentIp pqtype.Inet - NullableIp pqtype.Inet - PresentCidr pqtype.CIDR - NullableCidr pqtype.CIDR -} diff --git a/internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go b/internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go deleted file mode 100644 index 26d1313f6f..0000000000 --- a/internal/endtoend/testdata/types_network_address/stdlib/go/query.sql.go +++ /dev/null @@ -1,115 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// source: query.sql - -package querytest - -import ( - "context" - - "github.com/tabbed/pqtype" -) - -const findBarByAddr = `-- name: FindBarByAddr :one -SELECT addr, nullable_addr FROM bar -WHERE addr = $1 -` - -func (q *Queries) FindBarByAddr(ctx context.Context, addr pqtype.Macaddr) (Bar, error) { - row := q.db.QueryRowContext(ctx, findBarByAddr, addr) - var i Bar - err := row.Scan(&i.Addr, &i.NullableAddr) - return i, err -} - -const findFooByCIDR = `-- name: FindFooByCIDR :one -SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo -WHERE present_cidr = $1 -` - -func (q *Queries) FindFooByCIDR(ctx context.Context, presentCidr pqtype.CIDR) (Foo, error) { - row := q.db.QueryRowContext(ctx, findFooByCIDR, presentCidr) - var i Foo - err := row.Scan( - &i.PresentIp, - &i.NullableIp, - &i.PresentCidr, - &i.NullableCidr, - ) - return i, err -} - -const findFooByIP = `-- name: FindFooByIP :one -SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo -WHERE present_ip = $1 -` - -func (q *Queries) FindFooByIP(ctx context.Context, presentIp pqtype.Inet) (Foo, error) { - row := q.db.QueryRowContext(ctx, findFooByIP, presentIp) - var i Foo - err := row.Scan( - &i.PresentIp, - &i.NullableIp, - &i.PresentCidr, - &i.NullableCidr, - ) - return i, err -} - -const listBar = `-- name: ListBar :many -SELECT addr, nullable_addr FROM bar -` - -func (q *Queries) ListBar(ctx context.Context) ([]Bar, error) { - rows, err := q.db.QueryContext(ctx, listBar) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Bar - for rows.Next() { - var i Bar - if err := rows.Scan(&i.Addr, &i.NullableAddr); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} - -const listFoo = `-- name: ListFoo :many -SELECT present_ip, nullable_ip, present_cidr, nullable_cidr FROM foo -` - -func (q *Queries) ListFoo(ctx context.Context) ([]Foo, error) { - rows, err := q.db.QueryContext(ctx, listFoo) - if err != nil { - return nil, err - } - defer rows.Close() - var items []Foo - for rows.Next() { - var i Foo - if err := rows.Scan( - &i.PresentIp, - &i.NullableIp, - &i.PresentCidr, - &i.NullableCidr, - ); err != nil { - return nil, err - } - items = append(items, i) - } - if err := rows.Close(); err != nil { - return nil, err - } - if err := rows.Err(); err != nil { - return nil, err - } - return items, nil -} diff --git a/internal/endtoend/testdata/types_network_address/stdlib/query.sql b/internal/endtoend/testdata/types_network_address/stdlib/query.sql deleted file mode 100644 index b1576896a6..0000000000 --- a/internal/endtoend/testdata/types_network_address/stdlib/query.sql +++ /dev/null @@ -1,29 +0,0 @@ -CREATE TABLE foo ( - present_ip inet not null, - nullable_ip inet, - present_cidr cidr not null, - nullable_cidr cidr -); - -CREATE TABLE bar ( - addr macaddr not null, - nullable_addr macaddr -); - --- name: ListFoo :many -SELECT * FROM foo; - --- name: FindFooByIP :one -SELECT * FROM foo -WHERE present_ip = $1; - --- name: FindFooByCIDR :one -SELECT * FROM foo -WHERE present_cidr = $1; - --- name: ListBar :many -SELECT * FROM bar; - --- name: FindBarByAddr :one -SELECT * FROM bar -WHERE addr = $1; diff --git a/internal/endtoend/testdata/types_network_address/stdlib/sqlc.json b/internal/endtoend/testdata/types_network_address/stdlib/sqlc.json deleted file mode 100644 index ac7c2ed829..0000000000 --- a/internal/endtoend/testdata/types_network_address/stdlib/sqlc.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "1", - "packages": [ - { - "path": "go", - "name": "querytest", - "schema": "query.sql", - "queries": "query.sql" - } - ] -} diff --git a/scripts/regenerate/main.go b/scripts/regenerate/main.go index bfc951d338..d48dc63ab7 100644 --- a/scripts/regenerate/main.go +++ b/scripts/regenerate/main.go @@ -19,7 +19,7 @@ func regenerate(dir string) error { } if strings.HasSuffix(path, "sqlc.json") || strings.HasSuffix(path, "sqlc.yaml") { cwd := filepath.Dir(path) - cmd := exec.Command("sqlc-dev", "generate") + cmd := exec.Command("sqlc-dev", "generate", "--experimental") cmd.Dir = cwd failed := cmd.Run() if _, err := os.Stat(filepath.Join(cwd, "stderr.txt")); os.IsNotExist(err) && failed != nil { From 2143e467fd50bc381390c6795b7dcffb74a4b7a3 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Mon, 23 Aug 2021 09:17:39 -0700 Subject: [PATCH 12/22] Handle null PostgreSQL JSON values (#1145) * codegen/golang: Handle NULL JSON values lib/pq: For nullable values, use pqtype.NullRawMessage pgx/v4: Always use pgtype.JSON[B] * endtoend: Update test cases --- internal/codegen/golang/imports.go | 9 ++++-- internal/codegen/golang/postgresql_type.go | 29 +++++++++++++++++-- .../testdata/json/postgresql/pgx/go/models.go | 10 +++---- .../json/postgresql/stdlib/go/models.go | 6 ++-- .../json_build/postgresql/pgx/go/query.sql.go | 23 ++++++++------- 5 files changed, 54 insertions(+), 23 deletions(-) diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index e40bddd779..6074d4fff6 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -135,14 +135,17 @@ var stdlibTypes = map[string]string{ var pgtypeTypes = map[string]struct{}{ "pgtype.CIDR": {}, "pgtype.Inet": {}, + "pgtype.JSON": {}, + "pgtype.JSONB": {}, "pgtype.Macaddr": {}, "pgtype.Numeric": {}, } var pqtypeTypes = map[string]struct{}{ - "pqtype.CIDR": {}, - "pqtype.Inet": {}, - "pqtype.Macaddr": {}, + "pqtype.CIDR": {}, + "pqtype.Inet": {}, + "pqtype.Macaddr": {}, + "pqtype.NullRawMessage": {}, } func buildImports(settings config.CombinedSettings, queries []Query, uses func(string) bool) (map[string]struct{}, map[ImportSpec]struct{}) { diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go index b55386b3fd..d3d51e7da8 100644 --- a/internal/codegen/golang/postgresql_type.go +++ b/internal/codegen/golang/postgresql_type.go @@ -76,8 +76,33 @@ func postgresType(r *compiler.Result, col *compiler.Column, settings config.Comb } return "sql.NullBool" - case "json", "jsonb": - return "json.RawMessage" + case "json": + switch driver { + case SQLDriverPGXV4: + return "pgtype.JSON" + case SQLDriverLibPQ: + if notNull { + return "json.RawMessage" + } else { + return "pqtype.NullRawMessage" + } + default: + return "interface{}" + } + + case "jsonb": + switch driver { + case SQLDriverPGXV4: + return "pgtype.JSONB" + case SQLDriverLibPQ: + if notNull { + return "json.RawMessage" + } else { + return "pqtype.NullRawMessage" + } + default: + return "interface{}" + } case "bytea", "blob", "pg_catalog.bytea": return "[]byte" diff --git a/internal/endtoend/testdata/json/postgresql/pgx/go/models.go b/internal/endtoend/testdata/json/postgresql/pgx/go/models.go index bac200d0ea..f7f823d320 100644 --- a/internal/endtoend/testdata/json/postgresql/pgx/go/models.go +++ b/internal/endtoend/testdata/json/postgresql/pgx/go/models.go @@ -3,12 +3,12 @@ package querytest import ( - "encoding/json" + "github.com/jackc/pgtype" ) type Foo struct { - A json.RawMessage - B json.RawMessage - C json.RawMessage - D json.RawMessage + A pgtype.JSON + B pgtype.JSONB + C pgtype.JSON + D pgtype.JSONB } diff --git a/internal/endtoend/testdata/json/postgresql/stdlib/go/models.go b/internal/endtoend/testdata/json/postgresql/stdlib/go/models.go index bac200d0ea..6e0646f271 100644 --- a/internal/endtoend/testdata/json/postgresql/stdlib/go/models.go +++ b/internal/endtoend/testdata/json/postgresql/stdlib/go/models.go @@ -4,11 +4,13 @@ package querytest import ( "encoding/json" + + "github.com/tabbed/pqtype" ) type Foo struct { A json.RawMessage B json.RawMessage - C json.RawMessage - D json.RawMessage + C pqtype.NullRawMessage + D pqtype.NullRawMessage } diff --git a/internal/endtoend/testdata/json_build/postgresql/pgx/go/query.sql.go b/internal/endtoend/testdata/json_build/postgresql/pgx/go/query.sql.go index cf023bfcb1..5f789c6f7d 100644 --- a/internal/endtoend/testdata/json_build/postgresql/pgx/go/query.sql.go +++ b/internal/endtoend/testdata/json_build/postgresql/pgx/go/query.sql.go @@ -5,7 +5,8 @@ package querytest import ( "context" - "encoding/json" + + "github.com/jackc/pgtype" ) const selectJSONBuildArray = `-- name: SelectJSONBuildArray :one @@ -18,11 +19,11 @@ SELECT ` type SelectJSONBuildArrayRow struct { - JsonBuildArray json.RawMessage - JsonBuildArray_2 json.RawMessage - JsonBuildArray_3 json.RawMessage - JsonBuildArray_4 json.RawMessage - JsonBuildArray_5 json.RawMessage + JsonBuildArray pgtype.JSON + JsonBuildArray_2 pgtype.JSON + JsonBuildArray_3 pgtype.JSON + JsonBuildArray_4 pgtype.JSON + JsonBuildArray_5 pgtype.JSON } func (q *Queries) SelectJSONBuildArray(ctx context.Context) (SelectJSONBuildArrayRow, error) { @@ -48,11 +49,11 @@ SELECT ` type SelectJSONBuildObjectRow struct { - JsonBuildObject json.RawMessage - JsonBuildObject_2 json.RawMessage - JsonBuildObject_3 json.RawMessage - JsonBuildObject_4 json.RawMessage - JsonBuildObject_5 json.RawMessage + JsonBuildObject pgtype.JSON + JsonBuildObject_2 pgtype.JSON + JsonBuildObject_3 pgtype.JSON + JsonBuildObject_4 pgtype.JSON + JsonBuildObject_5 pgtype.JSON } func (q *Queries) SelectJSONBuildObject(ctx context.Context) (SelectJSONBuildObjectRow, error) { From 71d9c4bf3b7d28dd709286b8806575d815ae7656 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Mon, 23 Aug 2021 22:05:59 -0700 Subject: [PATCH 13/22] codegen/golang: Add pgx support for range types (#1146) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * codegen/golang: Add pgx support for range types Support all six built-in range types: * int4range — Range of integer * int8range — Range of bigint * numrange — Range of numeric * tsrange — Range of timestamp without time zone * tstzrange — Range of timestamp with time zone * daterange — Range of date * Checkout for imports --- internal/codegen/golang/imports.go | 18 ++++++---- internal/codegen/golang/postgresql_type.go | 36 +++++++++++++++++++ .../testdata/datatype/pgx/go/models.go | 18 ++++++++++ .../testdata/datatype/pgx/sql/rangetypes.sql | 19 ++++++++++ .../testdata/datatype/stdlib/go/models.go | 18 ++++++++++ .../datatype/stdlib/sql/rangetypes.sql | 19 ++++++++++ 6 files changed, 122 insertions(+), 6 deletions(-) create mode 100644 internal/endtoend/testdata/datatype/pgx/sql/rangetypes.sql create mode 100644 internal/endtoend/testdata/datatype/stdlib/sql/rangetypes.sql diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 6074d4fff6..7a2c4a254a 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -133,12 +133,18 @@ var stdlibTypes = map[string]string{ } var pgtypeTypes = map[string]struct{}{ - "pgtype.CIDR": {}, - "pgtype.Inet": {}, - "pgtype.JSON": {}, - "pgtype.JSONB": {}, - "pgtype.Macaddr": {}, - "pgtype.Numeric": {}, + "pgtype.CIDR": {}, + "pgtype.Daterange": {}, + "pgtype.Inet": {}, + "pgtype.Int4range": {}, + "pgtype.Int8range": {}, + "pgtype.JSON": {}, + "pgtype.JSONB": {}, + "pgtype.Macaddr": {}, + "pgtype.Numeric": {}, + "pgtype.Numrange": {}, + "pgtype.Tsrange": {}, + "pgtype.Tstzrange": {}, } var pqtypeTypes = map[string]struct{}{ diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go index d3d51e7da8..130bad8961 100644 --- a/internal/codegen/golang/postgresql_type.go +++ b/internal/codegen/golang/postgresql_type.go @@ -184,6 +184,42 @@ func postgresType(r *compiler.Result, col *compiler.Column, settings config.Comb } return "sql.NullInt64" + case "daterange": + if driver == SQLDriverPGXV4 { + return "pgtype.Daterange" + } + return "interface{}" + + case "tsrange": + if driver == SQLDriverPGXV4 { + return "pgtype.Tsrange" + } + return "interface{}" + + case "tstzrange": + if driver == SQLDriverPGXV4 { + return "pgtype.Tstzrange" + } + return "interface{}" + + case "numrange": + if driver == SQLDriverPGXV4 { + return "pgtype.Numrange" + } + return "interface{}" + + case "int4range": + if driver == SQLDriverPGXV4 { + return "pgtype.Int4range" + } + return "interface{}" + + case "int8range": + if driver == SQLDriverPGXV4 { + return "pgtype.Int8range" + } + return "interface{}" + case "void": // A void value can only be scanned into an empty interface. return "interface{}" diff --git a/internal/endtoend/testdata/datatype/pgx/go/models.go b/internal/endtoend/testdata/datatype/pgx/go/models.go index 3877de48c1..4786115b66 100644 --- a/internal/endtoend/testdata/datatype/pgx/go/models.go +++ b/internal/endtoend/testdata/datatype/pgx/go/models.go @@ -90,3 +90,21 @@ type DtNumericNotNull struct { L int32 M int64 } + +type DtRange struct { + A pgtype.Int4range + B pgtype.Int8range + C pgtype.Numrange + D pgtype.Tsrange + E pgtype.Tstzrange + F pgtype.Daterange +} + +type DtRangeNotNull struct { + A pgtype.Int4range + B pgtype.Int8range + C pgtype.Numrange + D pgtype.Tsrange + E pgtype.Tstzrange + F pgtype.Daterange +} diff --git a/internal/endtoend/testdata/datatype/pgx/sql/rangetypes.sql b/internal/endtoend/testdata/datatype/pgx/sql/rangetypes.sql new file mode 100644 index 0000000000..7e61b658a5 --- /dev/null +++ b/internal/endtoend/testdata/datatype/pgx/sql/rangetypes.sql @@ -0,0 +1,19 @@ +-- Range Types +-- https://www.postgresql.org/docs/current/rangetypes.html +CREATE TABLE dt_range ( + a int4range, + b int8range, + c numrange, + d tsrange, + e tstzrange, + f daterange +); + +CREATE TABLE dt_range_not_null ( + a int4range NOT NULL, + b int8range NOT NULL, + c numrange NOT NULL, + d tsrange NOT NULL, + e tstzrange NOT NULL, + f daterange NOT NULL +); diff --git a/internal/endtoend/testdata/datatype/stdlib/go/models.go b/internal/endtoend/testdata/datatype/stdlib/go/models.go index 5068324852..38993fea43 100644 --- a/internal/endtoend/testdata/datatype/stdlib/go/models.go +++ b/internal/endtoend/testdata/datatype/stdlib/go/models.go @@ -90,3 +90,21 @@ type DtNumericNotNull struct { L int32 M int64 } + +type DtRange struct { + A interface{} + B interface{} + C interface{} + D interface{} + E interface{} + F interface{} +} + +type DtRangeNotNull struct { + A interface{} + B interface{} + C interface{} + D interface{} + E interface{} + F interface{} +} diff --git a/internal/endtoend/testdata/datatype/stdlib/sql/rangetypes.sql b/internal/endtoend/testdata/datatype/stdlib/sql/rangetypes.sql new file mode 100644 index 0000000000..7e61b658a5 --- /dev/null +++ b/internal/endtoend/testdata/datatype/stdlib/sql/rangetypes.sql @@ -0,0 +1,19 @@ +-- Range Types +-- https://www.postgresql.org/docs/current/rangetypes.html +CREATE TABLE dt_range ( + a int4range, + b int8range, + c numrange, + d tsrange, + e tstzrange, + f daterange +); + +CREATE TABLE dt_range_not_null ( + a int4range NOT NULL, + b int8range NOT NULL, + c numrange NOT NULL, + d tsrange NOT NULL, + e tstzrange NOT NULL, + f daterange NOT NULL +); From a096ecc710cd13ee2a89dd60830e3e39022fafb0 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sat, 28 Aug 2021 11:28:21 -0700 Subject: [PATCH 14/22] First attempt at a template for bugs (#1151) * First attempt at a template for bugs * Add SQL schema and queries * Add input field for playground link --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 76 +++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/BUG_REPORT.yml diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml new file mode 100644 index 0000000000..b137f6a9af --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -0,0 +1,76 @@ +name: Bug Report +description: File a bug report +labels: [bug, triage] +body: + - type: textarea + id: what-happened + attributes: + label: What happened? + description: Also tell us, what did you expect to happen? + placeholder: Tell us what you see! + value: "A bug happened!" + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant log output + description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. + render: shell + - type: textarea + id: schema + attributes: + label: Database schema + description: Please include definitions for the relevant database tables. This will be automatically formatted as SQL, so no need for backticks. + render: sql + - type: textarea + id: queries + attributes: + label: SQL queries + description: Please include the SQL queries causing issues. This will be automatically formatted as SQL, so no need for backticks. + render: sql + - type: input + id: playground + attributes: + label: Playground URL + description: "Link to a reproduction of the issue on the sqlc playground" + placeholder: "https://play.sqlc.dev/" + - type: dropdown + id: version + attributes: + label: Version + description: What version of sqlc are you running? + multiple: false + options: + - 1.9.0 + - 1.8.0 + - 1.7.0 + - Other + validations: + required: true + - type: dropdown + id: os + attributes: + label: What operating system are you using? + multiple: true + options: + - Linux + - Windows + - macOS + - type: dropdown + id: engines + attributes: + label: What database engines are you using? + multiple: true + options: + - PostgreSQL + - MySQL + - type: dropdown + id: languages + attributes: + label: What type code are you generating? + multiple: true + options: + - Go + - Python + - Kotlin From f5ff015c2f58959a1115d10ee9e44c653cdf0309 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sat, 28 Aug 2021 11:48:48 -0700 Subject: [PATCH 15/22] Re-order form, add configuration file section (#1153) --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 32 ++++++++++++++++----------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index b137f6a9af..c727cc2f20 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -2,6 +2,19 @@ name: Bug Report description: File a bug report labels: [bug, triage] body: + - type: dropdown + id: version + attributes: + label: Version + description: What version of sqlc are you running? If you don't know, run `sqlc version`. + multiple: false + options: + - 1.9.0 + - 1.8.0 + - 1.7.0 + - Other + validations: + required: true - type: textarea id: what-happened attributes: @@ -29,25 +42,18 @@ body: label: SQL queries description: Please include the SQL queries causing issues. This will be automatically formatted as SQL, so no need for backticks. render: sql + - type: textarea + id: config + attributes: + label: Configuration + description: Please include the sqlc.yaml or sqlc.json file you using in your project. This will be automatically formatted, so no need for backticks. + render: yaml - type: input id: playground attributes: label: Playground URL description: "Link to a reproduction of the issue on the sqlc playground" placeholder: "https://play.sqlc.dev/" - - type: dropdown - id: version - attributes: - label: Version - description: What version of sqlc are you running? - multiple: false - options: - - 1.9.0 - - 1.8.0 - - 1.7.0 - - Other - validations: - required: true - type: dropdown id: os attributes: From 7d347222341df0ce99d2c93d1f0c9997e611d68a Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sat, 28 Aug 2021 11:49:42 -0700 Subject: [PATCH 16/22] Update BUG_REPORT.yml --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index c727cc2f20..2f26e76335 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -74,7 +74,7 @@ body: - type: dropdown id: languages attributes: - label: What type code are you generating? + label: What type of code are you generating? multiple: true options: - Go From 14631c8b81994ba9b038ae12c6441f8d7ba81002 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Sat, 28 Aug 2021 18:23:41 -0700 Subject: [PATCH 17/22] codegen/golang: Use pgtype for hstore when using pgx (#1156) --- internal/codegen/golang/imports.go | 1 + internal/codegen/golang/postgresql_type.go | 6 ++ .../endtoend/testdata/hstore/pgx/go/db.go | 30 +++++++++ .../testdata/hstore/pgx/go/hstore.sql.go | 58 +++++++++++++++++ .../endtoend/testdata/hstore/pgx/go/models.go | 12 ++++ .../endtoend/testdata/hstore/pgx/hstore.sql | 12 ++++ .../endtoend/testdata/hstore/pgx/sqlc.json | 13 ++++ .../endtoend/testdata/hstore/stdlib/go/db.go | 29 +++++++++ .../testdata/hstore/stdlib/go/hstore.sql.go | 62 +++++++++++++++++++ .../testdata/hstore/stdlib/go/models.go | 10 +++ .../testdata/hstore/stdlib/hstore.sql | 12 ++++ .../endtoend/testdata/hstore/stdlib/sqlc.json | 11 ++++ 12 files changed, 256 insertions(+) create mode 100644 internal/endtoend/testdata/hstore/pgx/go/db.go create mode 100644 internal/endtoend/testdata/hstore/pgx/go/hstore.sql.go create mode 100644 internal/endtoend/testdata/hstore/pgx/go/models.go create mode 100644 internal/endtoend/testdata/hstore/pgx/hstore.sql create mode 100644 internal/endtoend/testdata/hstore/pgx/sqlc.json create mode 100644 internal/endtoend/testdata/hstore/stdlib/go/db.go create mode 100644 internal/endtoend/testdata/hstore/stdlib/go/hstore.sql.go create mode 100644 internal/endtoend/testdata/hstore/stdlib/go/models.go create mode 100644 internal/endtoend/testdata/hstore/stdlib/hstore.sql create mode 100644 internal/endtoend/testdata/hstore/stdlib/sqlc.json diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 7a2c4a254a..2c38a3c48e 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -140,6 +140,7 @@ var pgtypeTypes = map[string]struct{}{ "pgtype.Int8range": {}, "pgtype.JSON": {}, "pgtype.JSONB": {}, + "pgtype.Hstore": {}, "pgtype.Macaddr": {}, "pgtype.Numeric": {}, "pgtype.Numrange": {}, diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go index 130bad8961..2a46c24e30 100644 --- a/internal/codegen/golang/postgresql_type.go +++ b/internal/codegen/golang/postgresql_type.go @@ -220,6 +220,12 @@ func postgresType(r *compiler.Result, col *compiler.Column, settings config.Comb } return "interface{}" + case "hstore": + if driver == SQLDriverPGXV4 { + return "pgtype.Hstore" + } + return "interface{}" + case "void": // A void value can only be scanned into an empty interface. return "interface{}" diff --git a/internal/endtoend/testdata/hstore/pgx/go/db.go b/internal/endtoend/testdata/hstore/pgx/go/db.go new file mode 100644 index 0000000000..95557215a5 --- /dev/null +++ b/internal/endtoend/testdata/hstore/pgx/go/db.go @@ -0,0 +1,30 @@ +// Code generated by sqlc. DO NOT EDIT. + +package hstore + +import ( + "context" + + "github.com/jackc/pgconn" + "github.com/jackc/pgx/v4" +) + +type DBTX interface { + Exec(context.Context, string, ...interface{}) (pgconn.CommandTag, error) + Query(context.Context, string, ...interface{}) (pgx.Rows, error) + QueryRow(context.Context, string, ...interface{}) pgx.Row +} + +func New(db DBTX) *Queries { + return &Queries{db: db} +} + +type Queries struct { + db DBTX +} + +func (q *Queries) WithTx(tx pgx.Tx) *Queries { + return &Queries{ + db: tx, + } +} diff --git a/internal/endtoend/testdata/hstore/pgx/go/hstore.sql.go b/internal/endtoend/testdata/hstore/pgx/go/hstore.sql.go new file mode 100644 index 0000000000..65a2eb71f5 --- /dev/null +++ b/internal/endtoend/testdata/hstore/pgx/go/hstore.sql.go @@ -0,0 +1,58 @@ +// Code generated by sqlc. DO NOT EDIT. +// source: hstore.sql + +package hstore + +import ( + "context" + + "github.com/jackc/pgtype" +) + +const listBar = `-- name: ListBar :many +SELECT bar FROM foo +` + +func (q *Queries) ListBar(ctx context.Context) ([]pgtype.Hstore, error) { + rows, err := q.db.Query(ctx, listBar) + if err != nil { + return nil, err + } + defer rows.Close() + var items []pgtype.Hstore + for rows.Next() { + var bar pgtype.Hstore + if err := rows.Scan(&bar); err != nil { + return nil, err + } + items = append(items, bar) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listBaz = `-- name: ListBaz :many +SELECT baz FROM foo +` + +func (q *Queries) ListBaz(ctx context.Context) ([]pgtype.Hstore, error) { + rows, err := q.db.Query(ctx, listBaz) + if err != nil { + return nil, err + } + defer rows.Close() + var items []pgtype.Hstore + for rows.Next() { + var baz pgtype.Hstore + if err := rows.Scan(&baz); err != nil { + return nil, err + } + items = append(items, baz) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/hstore/pgx/go/models.go b/internal/endtoend/testdata/hstore/pgx/go/models.go new file mode 100644 index 0000000000..de9de5838d --- /dev/null +++ b/internal/endtoend/testdata/hstore/pgx/go/models.go @@ -0,0 +1,12 @@ +// Code generated by sqlc. DO NOT EDIT. + +package hstore + +import ( + "github.com/jackc/pgtype" +) + +type Foo struct { + Bar pgtype.Hstore + Baz pgtype.Hstore +} diff --git a/internal/endtoend/testdata/hstore/pgx/hstore.sql b/internal/endtoend/testdata/hstore/pgx/hstore.sql new file mode 100644 index 0000000000..ff91ac0291 --- /dev/null +++ b/internal/endtoend/testdata/hstore/pgx/hstore.sql @@ -0,0 +1,12 @@ +CREATE TABLE foo ( + bar hstore NOT NULL, + baz hstore +); + +-- name: ListBar :many +SELECT bar FROM foo; + +-- name: ListBaz :many +SELECT baz FROM foo; + + diff --git a/internal/endtoend/testdata/hstore/pgx/sqlc.json b/internal/endtoend/testdata/hstore/pgx/sqlc.json new file mode 100644 index 0000000000..66b4ca8872 --- /dev/null +++ b/internal/endtoend/testdata/hstore/pgx/sqlc.json @@ -0,0 +1,13 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "engine": "postgresql", + "sql_package": "pgx/v4", + "name": "hstore", + "schema": "hstore.sql", + "queries": "hstore.sql" + } + ] +} diff --git a/internal/endtoend/testdata/hstore/stdlib/go/db.go b/internal/endtoend/testdata/hstore/stdlib/go/db.go new file mode 100644 index 0000000000..34ea6ddfb7 --- /dev/null +++ b/internal/endtoend/testdata/hstore/stdlib/go/db.go @@ -0,0 +1,29 @@ +// Code generated by sqlc. DO NOT EDIT. + +package hstore + +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/hstore/stdlib/go/hstore.sql.go b/internal/endtoend/testdata/hstore/stdlib/go/hstore.sql.go new file mode 100644 index 0000000000..84afdb5c0c --- /dev/null +++ b/internal/endtoend/testdata/hstore/stdlib/go/hstore.sql.go @@ -0,0 +1,62 @@ +// Code generated by sqlc. DO NOT EDIT. +// source: hstore.sql + +package hstore + +import ( + "context" +) + +const listBar = `-- name: ListBar :many +SELECT bar FROM foo +` + +func (q *Queries) ListBar(ctx context.Context) ([]interface{}, error) { + rows, err := q.db.QueryContext(ctx, listBar) + if err != nil { + return nil, err + } + defer rows.Close() + var items []interface{} + for rows.Next() { + var bar interface{} + if err := rows.Scan(&bar); err != nil { + return nil, err + } + items = append(items, bar) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const listBaz = `-- name: ListBaz :many +SELECT baz FROM foo +` + +func (q *Queries) ListBaz(ctx context.Context) ([]interface{}, error) { + rows, err := q.db.QueryContext(ctx, listBaz) + if err != nil { + return nil, err + } + defer rows.Close() + var items []interface{} + for rows.Next() { + var baz interface{} + if err := rows.Scan(&baz); err != nil { + return nil, err + } + items = append(items, baz) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/hstore/stdlib/go/models.go b/internal/endtoend/testdata/hstore/stdlib/go/models.go new file mode 100644 index 0000000000..3dea5999cd --- /dev/null +++ b/internal/endtoend/testdata/hstore/stdlib/go/models.go @@ -0,0 +1,10 @@ +// Code generated by sqlc. DO NOT EDIT. + +package hstore + +import () + +type Foo struct { + Bar interface{} + Baz interface{} +} diff --git a/internal/endtoend/testdata/hstore/stdlib/hstore.sql b/internal/endtoend/testdata/hstore/stdlib/hstore.sql new file mode 100644 index 0000000000..ff91ac0291 --- /dev/null +++ b/internal/endtoend/testdata/hstore/stdlib/hstore.sql @@ -0,0 +1,12 @@ +CREATE TABLE foo ( + bar hstore NOT NULL, + baz hstore +); + +-- name: ListBar :many +SELECT bar FROM foo; + +-- name: ListBaz :many +SELECT baz FROM foo; + + diff --git a/internal/endtoend/testdata/hstore/stdlib/sqlc.json b/internal/endtoend/testdata/hstore/stdlib/sqlc.json new file mode 100644 index 0000000000..d218312403 --- /dev/null +++ b/internal/endtoend/testdata/hstore/stdlib/sqlc.json @@ -0,0 +1,11 @@ +{ + "version": "1", + "packages": [ + { + "path": "go", + "name": "hstore", + "schema": "hstore.sql", + "queries": "hstore.sql" + } + ] +} From cc6fe67fa4627c494f509f70f951f25f0b21b948 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 3 Sep 2021 20:09:35 -0700 Subject: [PATCH 18/22] build(deps): bump github.com/lib/pq from 1.10.2 to 1.10.3 (#1160) --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 43bca08501..5bece99fa2 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/jackc/pgx/v4 v4.13.0 github.com/jinzhu/inflection v1.0.0 github.com/kr/pretty v0.2.1 // indirect - github.com/lib/pq v1.10.2 + github.com/lib/pq v1.10.3 github.com/pganalyze/pg_query_go/v2 v2.0.5 github.com/pingcap/parser v0.0.0-20201024025010-3b2fb4b41d73 github.com/spf13/cobra v1.2.1 diff --git a/go.sum b/go.sum index ae4ebdf12f..33add28121 100644 --- a/go.sum +++ b/go.sum @@ -255,8 +255,9 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= +github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= +github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= From 014312953d0b5db02c328f4c5153578ea6412788 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Fri, 3 Sep 2021 21:42:42 -0700 Subject: [PATCH 19/22] docs: Fix invalid language support table (#1161) --- docs/reference/language-support.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/reference/language-support.rst b/docs/reference/language-support.rst index de55489d6e..70801ef42b 100644 --- a/docs/reference/language-support.rst +++ b/docs/reference/language-support.rst @@ -1,21 +1,21 @@ Database and Language Support ############################# -======== ====== ========== +======== ============ ============ Language MySQL PostgreSQL --------- ------ ---------- +======== ============ ============ Go Stable Stable Kotlin Beta Beta Python Experimental Experimental -======== ============ ========== +======== ============ ============ -Planned Language Support +Future Language Support ************************ - `C# `_ - `TypeScript `_ -Planned Database Support +Future Database Support ************************ - `SQLite `_ From e178fddf51600a8d22031573d034723220c01115 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Mon, 6 Sep 2021 20:04:22 -0700 Subject: [PATCH 20/22] engine/mysql: Add support for LIKE (#1162) --- .../testdata/pattern_matching/mysql/go/db.go | 29 +++++++++++++++ .../pattern_matching/mysql/go/models.go | 11 ++++++ .../pattern_matching/mysql/go/query.sql.go | 36 +++++++++++++++++++ .../testdata/pattern_matching/mysql/query.sql | 4 +++ .../testdata/pattern_matching/mysql/sqlc.json | 12 +++++++ .../pattern_matching/postgresql/go/db.go | 29 +++++++++++++++ .../pattern_matching/postgresql/go/models.go | 11 ++++++ .../postgresql/go/query.sql.go | 36 +++++++++++++++++++ .../pattern_matching/postgresql/query.sql | 4 +++ .../pattern_matching/postgresql/sqlc.json | 12 +++++++ internal/engine/dolphin/convert.go | 11 +++++- 11 files changed, 194 insertions(+), 1 deletion(-) create mode 100644 internal/endtoend/testdata/pattern_matching/mysql/go/db.go create mode 100644 internal/endtoend/testdata/pattern_matching/mysql/go/models.go create mode 100644 internal/endtoend/testdata/pattern_matching/mysql/go/query.sql.go create mode 100644 internal/endtoend/testdata/pattern_matching/mysql/query.sql create mode 100644 internal/endtoend/testdata/pattern_matching/mysql/sqlc.json create mode 100644 internal/endtoend/testdata/pattern_matching/postgresql/go/db.go create mode 100644 internal/endtoend/testdata/pattern_matching/postgresql/go/models.go create mode 100644 internal/endtoend/testdata/pattern_matching/postgresql/go/query.sql.go create mode 100644 internal/endtoend/testdata/pattern_matching/postgresql/query.sql create mode 100644 internal/endtoend/testdata/pattern_matching/postgresql/sqlc.json diff --git a/internal/endtoend/testdata/pattern_matching/mysql/go/db.go b/internal/endtoend/testdata/pattern_matching/mysql/go/db.go new file mode 100644 index 0000000000..6a99519302 --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/mysql/go/db.go @@ -0,0 +1,29 @@ +// Code generated by sqlc. DO NOT EDIT. + +package querytest + +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/pattern_matching/mysql/go/models.go b/internal/endtoend/testdata/pattern_matching/mysql/go/models.go new file mode 100644 index 0000000000..bef773dc9a --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/mysql/go/models.go @@ -0,0 +1,11 @@ +// Code generated by sqlc. DO NOT EDIT. + +package querytest + +import ( + "database/sql" +) + +type Pet struct { + Name sql.NullString +} diff --git a/internal/endtoend/testdata/pattern_matching/mysql/go/query.sql.go b/internal/endtoend/testdata/pattern_matching/mysql/go/query.sql.go new file mode 100644 index 0000000000..a1b3f7b76e --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/mysql/go/query.sql.go @@ -0,0 +1,36 @@ +// Code generated by sqlc. DO NOT EDIT. +// source: query.sql + +package querytest + +import ( + "context" + "database/sql" +) + +const petsByName = `-- name: PetsByName :many +SELECT name FROM pet WHERE name LIKE ? +` + +func (q *Queries) PetsByName(ctx context.Context, name sql.NullString) ([]sql.NullString, error) { + rows, err := q.db.QueryContext(ctx, petsByName, name) + if err != nil { + return nil, err + } + defer rows.Close() + var items []sql.NullString + for rows.Next() { + var name sql.NullString + if err := rows.Scan(&name); err != nil { + return nil, err + } + items = append(items, name) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/pattern_matching/mysql/query.sql b/internal/endtoend/testdata/pattern_matching/mysql/query.sql new file mode 100644 index 0000000000..57bbcd0287 --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/mysql/query.sql @@ -0,0 +1,4 @@ +CREATE TABLE pet (name text); + +-- name: PetsByName :many +SELECT * FROM pet WHERE name LIKE ?; diff --git a/internal/endtoend/testdata/pattern_matching/mysql/sqlc.json b/internal/endtoend/testdata/pattern_matching/mysql/sqlc.json new file mode 100644 index 0000000000..0657f4db83 --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/mysql/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "engine": "mysql", + "path": "go", + "name": "querytest", + "schema": "query.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/endtoend/testdata/pattern_matching/postgresql/go/db.go b/internal/endtoend/testdata/pattern_matching/postgresql/go/db.go new file mode 100644 index 0000000000..6a99519302 --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/postgresql/go/db.go @@ -0,0 +1,29 @@ +// Code generated by sqlc. DO NOT EDIT. + +package querytest + +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/pattern_matching/postgresql/go/models.go b/internal/endtoend/testdata/pattern_matching/postgresql/go/models.go new file mode 100644 index 0000000000..bef773dc9a --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/postgresql/go/models.go @@ -0,0 +1,11 @@ +// Code generated by sqlc. DO NOT EDIT. + +package querytest + +import ( + "database/sql" +) + +type Pet struct { + Name sql.NullString +} diff --git a/internal/endtoend/testdata/pattern_matching/postgresql/go/query.sql.go b/internal/endtoend/testdata/pattern_matching/postgresql/go/query.sql.go new file mode 100644 index 0000000000..10e2e2c3ff --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/postgresql/go/query.sql.go @@ -0,0 +1,36 @@ +// Code generated by sqlc. DO NOT EDIT. +// source: query.sql + +package querytest + +import ( + "context" + "database/sql" +) + +const petsByName = `-- name: PetsByName :many +SELECT name FROM pet WHERE name LIKE $1 +` + +func (q *Queries) PetsByName(ctx context.Context, name sql.NullString) ([]sql.NullString, error) { + rows, err := q.db.QueryContext(ctx, petsByName, name) + if err != nil { + return nil, err + } + defer rows.Close() + var items []sql.NullString + for rows.Next() { + var name sql.NullString + if err := rows.Scan(&name); err != nil { + return nil, err + } + items = append(items, name) + } + if err := rows.Close(); err != nil { + return nil, err + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} diff --git a/internal/endtoend/testdata/pattern_matching/postgresql/query.sql b/internal/endtoend/testdata/pattern_matching/postgresql/query.sql new file mode 100644 index 0000000000..083695e5f2 --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/postgresql/query.sql @@ -0,0 +1,4 @@ +CREATE TABLE pet (name text); + +-- name: PetsByName :many +SELECT * FROM pet WHERE name LIKE $1; diff --git a/internal/endtoend/testdata/pattern_matching/postgresql/sqlc.json b/internal/endtoend/testdata/pattern_matching/postgresql/sqlc.json new file mode 100644 index 0000000000..de427d069f --- /dev/null +++ b/internal/endtoend/testdata/pattern_matching/postgresql/sqlc.json @@ -0,0 +1,12 @@ +{ + "version": "1", + "packages": [ + { + "engine": "postgresql", + "path": "go", + "name": "querytest", + "schema": "query.sql", + "queries": "query.sql" + } + ] +} diff --git a/internal/engine/dolphin/convert.go b/internal/engine/dolphin/convert.go index 94d9c1b8f9..e27752cfd0 100644 --- a/internal/engine/dolphin/convert.go +++ b/internal/engine/dolphin/convert.go @@ -880,7 +880,16 @@ func (c *cc) convertPatternInExpr(n *pcast.PatternInExpr) ast.Node { } func (c *cc) convertPatternLikeExpr(n *pcast.PatternLikeExpr) ast.Node { - return todo(n) + return &ast.A_Expr{ + Kind: ast.A_Expr_Kind(9), + Name: &ast.List{ + Items: []ast.Node{ + &ast.String{Str: "~~"}, + }, + }, + Lexpr: c.convert(n.Expr), + Rexpr: c.convert(n.Pattern), + } } func (c *cc) convertPatternRegexpExpr(n *pcast.PatternRegexpExpr) ast.Node { From 32bb0ad3165e216b5445753d7a89b4499fadcd25 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Mon, 6 Sep 2021 21:33:41 -0700 Subject: [PATCH 21/22] docs: Add a getting started guide for MySQL (#1163) --- docs/index.rst | 3 +- docs/tutorials/getting-started-mysql.md | 155 ++++++++++++++++++ ...arted.md => getting-started-postgresql.md} | 14 +- 3 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 docs/tutorials/getting-started-mysql.md rename docs/tutorials/{getting-started.md => getting-started-postgresql.md} (90%) diff --git a/docs/index.rst b/docs/index.rst index be4af64b42..0386a8175f 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -32,7 +32,8 @@ code ever again. :caption: Tutorials :hidden: - tutorials/getting-started.md + tutorials/getting-started-mysql.md + tutorials/getting-started-postgresql.md .. toctree:: :maxdepth: 2 diff --git a/docs/tutorials/getting-started-mysql.md b/docs/tutorials/getting-started-mysql.md new file mode 100644 index 0000000000..fdb112d1c7 --- /dev/null +++ b/docs/tutorials/getting-started-mysql.md @@ -0,0 +1,155 @@ +# Getting started with MySQL + +This tutorial assumes that the latest version of sqlc is +[installed](../overview/install.html) and ready to use. + +Create a new directory called `sqlc-tutorial` and open it up. + +Initialize a new Go module named `tutorial.sql.dev/app` + +```shell +go mod init tutorial.sqlc.dev/app +``` + +sqlc looks for either a `sqlc.yaml` or `sqlc.json` file in the current +directory. In our new directory, create a file named `sqlc.yaml` with the +following contents: + +```yaml +version: 1 +packages: + - path: "tutorial" + name: "tutorial" + engine: "mysql" + schema: "schema.sql" + queries: "query.sql" +``` + +sqlc needs to know your database schema and queries. In the same directory, +create a file named `schema.sql` with the following contents: + +```sql +CREATE TABLE authors ( + id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, + name text NOT NULL, + bio text +); +``` + +Next, create a `query.sql` file with the following four queries: + +```sql +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = ? LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :execresult +INSERT INTO authors ( + name, bio +) VALUES ( + ?, ? +); + +-- name: DeleteAuthor :exec +DELETE FROM authors +WHERE id = ?; +``` + +You are now ready to generate code. Run the `generate` command. You shouldn't see any errors or output. + +```shell +sqlc generate +``` + +You should now have a `db` package containing three files. + +``` +├── go.mod +├── query.sql +├── schema.sql +├── sqlc.yaml +└── tutorial + ├── db.go + ├── models.go + └── query.sql.go +``` + +You can use your newly generated queries in `app.go`. + +```go +package main + +import ( + "context" + "database/sql" + "log" + "reflect" + + "tutorial.sqlc.dev/app/tutorial" + + _ "github.com/go-sql-driver/mysql" +) + +func run() error { + ctx := context.Background() + + db, err := sql.Open("mysql", "user:password@/dbname") + if err != nil { + return err + } + + queries := tutorial.New(db) + + // list all authors + authors, err := queries.ListAuthors(ctx) + if err != nil { + return err + } + log.Println(authors) + + // create an author + result, err := queries.CreateAuthor(ctx, tutorial.CreateAuthorParams{ + Name: "Brian Kernighan", + Bio: sql.NullString{String: "Co-author of The C Programming Language and The Go Programming Language", Valid: true}, + }) + if err != nil { + return err + } + + insertedAuthorID, err := result.LastInsertId() + if err != nil { + return err + } + log.Println(insertedAuthorID) + + // get the author we just inserted + fetchedAuthor, err := queries.GetAuthor(ctx, insertedAuthorID) + if err != nil { + return err + } + + // prints true + log.Println(reflect.DeepEqual(insertedAuthorID, fetchedAuthor.ID)) + return nil +} + +func main() { + if err := run(); err != nil { + log.Fatal(err) + } +} +``` + +Before the code will compile, you'll need to add the Go MySQL driver. + +``` +go get github.com/go-sql-driver/mysql +go build ./... +``` + +To make that possible, sqlc generates readable, **idiomatic** Go code that you +otherwise would have had to write yourself. Take a look in `tutorial/query.sql.go`. diff --git a/docs/tutorials/getting-started.md b/docs/tutorials/getting-started-postgresql.md similarity index 90% rename from docs/tutorials/getting-started.md rename to docs/tutorials/getting-started-postgresql.md index f1d3605b21..8e4a7bf188 100644 --- a/docs/tutorials/getting-started.md +++ b/docs/tutorials/getting-started-postgresql.md @@ -1,6 +1,7 @@ -# Getting started +# Getting started with PostgreSQL -This tutorial assumes that the latest version of sqlc is installed and ready to use. +This tutorial assumes that the latest version of sqlc is +[installed](../overview/install.html) and ready to use. Create a new directory called `sqlc-tutorial` and open it up. @@ -90,6 +91,8 @@ import ( "reflect" "tutorial.sqlc.dev/app/tutorial" + + _ "github.com/lib/pq" ) func run() error { @@ -137,5 +140,12 @@ func main() { } ``` +Before the code will compile, you'll need to add the Go PostgreSQL driver. + +``` +go get github.com/lib/pq +go build ./... +``` + To make that possible, sqlc generates readable, **idiomatic** Go code that you otherwise would have had to write yourself. Take a look in `tutorial/query.sql.go`. From ebd3b59ac687bbb073b62a025c5a03bfe749a387 Mon Sep 17 00:00:00 2001 From: Kyle Conroy Date: Tue, 7 Sep 2021 08:48:02 -0700 Subject: [PATCH 22/22] cmd/sqlc: Bump version to v1.10.0 (#1165) --- .github/ISSUE_TEMPLATE/BUG_REPORT.yml | 2 +- docs/conf.py | 2 +- docs/overview/install.md | 8 ++++---- internal/cmd/cmd.go | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml index 2f26e76335..de1c8d208f 100644 --- a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -9,9 +9,9 @@ body: description: What version of sqlc are you running? If you don't know, run `sqlc version`. multiple: false options: + - 1.10.0 - 1.9.0 - 1.8.0 - - 1.7.0 - Other validations: required: true diff --git a/docs/conf.py b/docs/conf.py index b0786b3443..b9821d54d0 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -22,7 +22,7 @@ author = 'Kyle Conroy' # The full version, including alpha/beta/rc tags -release = '1.9.0' +release = '1.10.0' # -- General configuration --------------------------------------------------- diff --git a/docs/overview/install.md b/docs/overview/install.md index ac02bc8a48..424225bbb5 100644 --- a/docs/overview/install.md +++ b/docs/overview/install.md @@ -34,8 +34,8 @@ docker run --rm -v $(pwd):/src -w /src kjconroy/sqlc generate ## Downloads -Get pre-built binaries for *v1.9.0*: +Get pre-built binaries for *v1.10.0*: -- [Linux](https://github.com/kyleconroy/sqlc/releases/download/v1.9.0/sqlc_1.9.0_linux_amd64.tar.gz) -- [macOS](https://github.com/kyleconroy/sqlc/releases/download/v1.9.0/sqlc_1.9.0_darwin_amd64.zip) -- [Windows (MySQL only)](https://github.com/kyleconroy/sqlc/releases/download/v1.9.0/sqlc_1.9.0_windows_amd64.zip) +- [Linux](https://github.com/kyleconroy/sqlc/releases/download/v1.10.0/sqlc_1.10.0_linux_amd64.tar.gz) +- [macOS](https://github.com/kyleconroy/sqlc/releases/download/v1.10.0/sqlc_1.10.0_darwin_amd64.zip) +- [Windows (MySQL only)](https://github.com/kyleconroy/sqlc/releases/download/v1.10.0/sqlc_1.10.0_windows_amd64.zip) diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 816f2ce56c..eda6b0fd68 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -50,7 +50,7 @@ var versionCmd = &cobra.Command{ if version == "" { // When no version is set, return the next bug fix version // after the most recent tag - fmt.Printf("%s\n", "v1.9.0") + fmt.Printf("%s\n", "v1.10.0") } else { fmt.Printf("%s\n", version) }