diff --git a/.github/ISSUE_TEMPLATE/BUG_REPORT.yml b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml new file mode 100644 index 0000000000..de1c8d208f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/BUG_REPORT.yml @@ -0,0 +1,82 @@ +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.10.0 + - 1.9.0 + - 1.8.0 + - Other + validations: + required: true + - 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: 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: 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 of code are you generating? + multiple: true + options: + - Go + - Python + - Kotlin diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4f568a5008..455bf2fb73 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,12 +34,9 @@ jobs: - uses: actions/setup-go@v2 with: - go-version: '1.16' + 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 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 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. 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" 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/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 } 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/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/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 `_ 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 88% rename from docs/tutorials/getting-started.md rename to docs/tutorials/getting-started-postgresql.md index 4cb2c2fc88..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. @@ -25,7 +26,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 ( @@ -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`. 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= 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) } 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/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 6aca91bd0c..2c38a3c48e 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,39 @@ 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 - } +var pgtypeTypes = map[string]struct{}{ + "pgtype.CIDR": {}, + "pgtype.Daterange": {}, + "pgtype.Inet": {}, + "pgtype.Int4range": {}, + "pgtype.Int8range": {}, + "pgtype.JSON": {}, + "pgtype.JSONB": {}, + "pgtype.Hstore": {}, + "pgtype.Macaddr": {}, + "pgtype.Numeric": {}, + "pgtype.Numrange": {}, + "pgtype.Tsrange": {}, + "pgtype.Tstzrange": {}, +} + +var pqtypeTypes = map[string]struct{}{ + "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{}) { + 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,14 +174,27 @@ func (i *importer) interfaceImports() fileImports { } } } + for typeName, pkg := range stdlibTypes { if uses(typeName) { std[pkg] = struct{}{} } } + 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 i.Settings.Overrides { + for _, o := range settings.Overrides { if o.GoBasicType || o.GoTypeName == "" { continue } @@ -202,9 +209,13 @@ 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 { + for _, o := range settings.Overrides { if o.GoBasicType || o.GoTypeName == "" { continue } @@ -215,76 +226,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{}{} - } - - 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} @@ -298,7 +285,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() { @@ -328,7 +315,7 @@ func (i *importer) queryImports(filename string) fileImports { } } return false - } + }) sliceScan := func() bool { for _, q := range gq { @@ -362,76 +349,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{}{} - } - - // 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) } diff --git a/internal/codegen/golang/postgresql_type.go b/internal/codegen/golang/postgresql_type.go index 1e893626df..2a46c24e30 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": @@ -57,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. // @@ -72,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" @@ -103,13 +132,40 @@ 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" + 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 @@ -128,6 +184,48 @@ 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 "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/datatype/pgx/go/models.go b/internal/endtoend/testdata/datatype/pgx/go/models.go index 0527cfff54..4786115b66 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 @@ -76,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/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/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 0527cfff54..38993fea43 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 @@ -76,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/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/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 +); 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 fd0ed966a2..999f37b360 100644 --- a/internal/endtoend/testdata/go.mod +++ b/internal/endtoend/testdata/go.mod @@ -4,12 +4,13 @@ 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 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 6b2aed8537..efdad878f2 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= @@ -108,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/hstore/pgx/go/db.go similarity index 96% rename from internal/endtoend/testdata/macaddr/pgx/go/db.go rename to internal/endtoend/testdata/hstore/pgx/go/db.go index 4559f50a4f..95557215a5 100644 --- a/internal/endtoend/testdata/macaddr/pgx/go/db.go +++ b/internal/endtoend/testdata/hstore/pgx/go/db.go @@ -1,6 +1,6 @@ // Code generated by sqlc. DO NOT EDIT. -package querytest +package hstore import ( "context" 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/ipaddr/pgx/sqlc.json b/internal/endtoend/testdata/hstore/pgx/sqlc.json similarity index 61% rename from internal/endtoend/testdata/ipaddr/pgx/sqlc.json rename to internal/endtoend/testdata/hstore/pgx/sqlc.json index 9403bd0279..66b4ca8872 100644 --- a/internal/endtoend/testdata/ipaddr/pgx/sqlc.json +++ b/internal/endtoend/testdata/hstore/pgx/sqlc.json @@ -5,9 +5,9 @@ "path": "go", "engine": "postgresql", "sql_package": "pgx/v4", - "name": "querytest", - "schema": "query.sql", - "queries": "query.sql" + "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" + } + ] +} diff --git a/internal/endtoend/testdata/ipaddr/pgx/go/db.go b/internal/endtoend/testdata/ipaddr/pgx/go/db.go deleted file mode 100644 index 4559f50a4f..0000000000 --- a/internal/endtoend/testdata/ipaddr/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/ipaddr/pgx/go/models.go b/internal/endtoend/testdata/ipaddr/pgx/go/models.go deleted file mode 100644 index c9b78920d4..0000000000 --- a/internal/endtoend/testdata/ipaddr/pgx/go/models.go +++ /dev/null @@ -1,13 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -import ( - "net" -) - -type Foo struct { - Bar bool - Inet net.IP - Cidr net.IP -} diff --git a/internal/endtoend/testdata/ipaddr/pgx/go/query.sql.go b/internal/endtoend/testdata/ipaddr/pgx/go/query.sql.go deleted file mode 100644 index cb2cda6b98..0000000000 --- a/internal/endtoend/testdata/ipaddr/pgx/go/query.sql.go +++ /dev/null @@ -1,32 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// source: query.sql - -package querytest - -import ( - "context" -) - -const get = `-- name: Get :many -SELECT bar, "inet", "cidr" 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.Inet, &i.Cidr); 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/ipaddr/pgx/query.sql b/internal/endtoend/testdata/ipaddr/pgx/query.sql deleted file mode 100644 index 11b6b5c820..0000000000 --- a/internal/endtoend/testdata/ipaddr/pgx/query.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE foo (bar bool not null, "inet" inet not null, "cidr" cidr not null); - --- name: Get :many -SELECT bar, "inet", "cidr" FROM foo LIMIT $1; diff --git a/internal/endtoend/testdata/ipaddr/stdlib/go/models.go b/internal/endtoend/testdata/ipaddr/stdlib/go/models.go deleted file mode 100644 index c9b78920d4..0000000000 --- a/internal/endtoend/testdata/ipaddr/stdlib/go/models.go +++ /dev/null @@ -1,13 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. - -package querytest - -import ( - "net" -) - -type Foo struct { - Bar bool - Inet net.IP - Cidr net.IP -} diff --git a/internal/endtoend/testdata/ipaddr/stdlib/go/query.sql.go b/internal/endtoend/testdata/ipaddr/stdlib/go/query.sql.go deleted file mode 100644 index 1bdc311a36..0000000000 --- a/internal/endtoend/testdata/ipaddr/stdlib/go/query.sql.go +++ /dev/null @@ -1,35 +0,0 @@ -// Code generated by sqlc. DO NOT EDIT. -// source: query.sql - -package querytest - -import ( - "context" -) - -const get = `-- name: Get :many -SELECT bar, "inet", "cidr" 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.Inet, &i.Cidr); 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/ipaddr/stdlib/query.sql b/internal/endtoend/testdata/ipaddr/stdlib/query.sql deleted file mode 100644 index 11b6b5c820..0000000000 --- a/internal/endtoend/testdata/ipaddr/stdlib/query.sql +++ /dev/null @@ -1,4 +0,0 @@ -CREATE TABLE foo (bar bool not null, "inet" inet not null, "cidr" cidr not null); - --- name: Get :many -SELECT bar, "inet", "cidr" FROM foo LIMIT $1; 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) { 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/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/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/ipaddr/stdlib/go/db.go b/internal/endtoend/testdata/pattern_matching/mysql/go/db.go similarity index 100% rename from internal/endtoend/testdata/ipaddr/stdlib/go/db.go rename to internal/endtoend/testdata/pattern_matching/mysql/go/db.go diff --git a/internal/endtoend/testdata/macaddr/pgx/go/models.go b/internal/endtoend/testdata/pattern_matching/mysql/go/models.go similarity index 55% rename from internal/endtoend/testdata/macaddr/pgx/go/models.go rename to internal/endtoend/testdata/pattern_matching/mysql/go/models.go index 0681470ceb..bef773dc9a 100644 --- a/internal/endtoend/testdata/macaddr/pgx/go/models.go +++ b/internal/endtoend/testdata/pattern_matching/mysql/go/models.go @@ -3,10 +3,9 @@ package querytest import ( - "net" + "database/sql" ) -type Foo struct { - Bar bool - Addr net.HardwareAddr +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/macaddr/stdlib/sqlc.json b/internal/endtoend/testdata/pattern_matching/mysql/sqlc.json similarity index 86% rename from internal/endtoend/testdata/macaddr/stdlib/sqlc.json rename to internal/endtoend/testdata/pattern_matching/mysql/sqlc.json index ac7c2ed829..0657f4db83 100644 --- a/internal/endtoend/testdata/macaddr/stdlib/sqlc.json +++ b/internal/endtoend/testdata/pattern_matching/mysql/sqlc.json @@ -2,6 +2,7 @@ "version": "1", "packages": [ { + "engine": "mysql", "path": "go", "name": "querytest", "schema": "query.sql", diff --git a/internal/endtoend/testdata/macaddr/stdlib/go/db.go b/internal/endtoend/testdata/pattern_matching/postgresql/go/db.go similarity index 100% rename from internal/endtoend/testdata/macaddr/stdlib/go/db.go rename to internal/endtoend/testdata/pattern_matching/postgresql/go/db.go diff --git a/internal/endtoend/testdata/macaddr/stdlib/go/models.go b/internal/endtoend/testdata/pattern_matching/postgresql/go/models.go similarity index 55% rename from internal/endtoend/testdata/macaddr/stdlib/go/models.go rename to internal/endtoend/testdata/pattern_matching/postgresql/go/models.go index 0681470ceb..bef773dc9a 100644 --- a/internal/endtoend/testdata/macaddr/stdlib/go/models.go +++ b/internal/endtoend/testdata/pattern_matching/postgresql/go/models.go @@ -3,10 +3,9 @@ package querytest import ( - "net" + "database/sql" ) -type Foo struct { - Bar bool - Addr net.HardwareAddr +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/macaddr/pgx/sqlc.json b/internal/endtoend/testdata/pattern_matching/postgresql/sqlc.json similarity index 85% rename from internal/endtoend/testdata/macaddr/pgx/sqlc.json rename to internal/endtoend/testdata/pattern_matching/postgresql/sqlc.json index 9403bd0279..de427d069f 100644 --- a/internal/endtoend/testdata/macaddr/pgx/sqlc.json +++ b/internal/endtoend/testdata/pattern_matching/postgresql/sqlc.json @@ -2,9 +2,8 @@ "version": "1", "packages": [ { - "path": "go", "engine": "postgresql", - "sql_package": "pgx/v4", + "path": "go", "name": "querytest", "schema": "query.sql", "queries": "query.sql" 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_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/ipaddr/stdlib/sqlc.json b/internal/endtoend/testdata/types_uuid/postgresql/stdlib/sqlc.json similarity index 100% rename from internal/endtoend/testdata/ipaddr/stdlib/sqlc.json rename to internal/endtoend/testdata/types_uuid/postgresql/stdlib/sqlc.json 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 { 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 {