From c1c275bd29ce15672f96ef90b8b5b82de78a7c70 Mon Sep 17 00:00:00 2001 From: Dmitry Gridnev <33265875+FlymeDllVa@users.noreply.github.com> Date: Thu, 23 Feb 2023 20:03:47 +0300 Subject: [PATCH] fix: pgx closed batch return pointer if need #1959 (#1960) --- .../golang/templates/pgx/batchCode.tmpl | 2 +- .../{ => mysql}/go/db.go | 0 .../{ => mysql}/go/models.go | 0 .../{ => mysql}/go/querier.go | 0 .../{ => mysql}/go/query.sql.go | 0 .../{ => mysql}/query.sql | 0 .../{ => mysql}/sqlc.json | 0 .../postgresql/pgx/v4/go/batch.go | 68 +++++++++++++++++ .../postgresql/pgx/v4/go/db.go | 33 ++++++++ .../postgresql/pgx/v4/go/models.go | 14 ++++ .../postgresql/pgx/v4/go/query.sql.go | 75 ++++++++++++++++++ .../postgresql/pgx/v4/query.sql | 16 ++++ .../postgresql/pgx/v4/sqlc.json | 19 +++++ .../postgresql/pgx/v5/go/batch.go | 68 +++++++++++++++++ .../postgresql/pgx/v5/go/db.go | 33 ++++++++ .../postgresql/pgx/v5/go/models.go | 14 ++++ .../postgresql/pgx/v5/go/query.sql.go | 76 +++++++++++++++++++ .../postgresql/pgx/v5/query.sql | 16 ++++ .../postgresql/pgx/v5/sqlc.json | 19 +++++ 19 files changed, 452 insertions(+), 1 deletion(-) rename internal/endtoend/testdata/emit_result_and_params_struct_pointers/{ => mysql}/go/db.go (100%) rename internal/endtoend/testdata/emit_result_and_params_struct_pointers/{ => mysql}/go/models.go (100%) rename internal/endtoend/testdata/emit_result_and_params_struct_pointers/{ => mysql}/go/querier.go (100%) rename internal/endtoend/testdata/emit_result_and_params_struct_pointers/{ => mysql}/go/query.sql.go (100%) rename internal/endtoend/testdata/emit_result_and_params_struct_pointers/{ => mysql}/query.sql (100%) rename internal/endtoend/testdata/emit_result_and_params_struct_pointers/{ => mysql}/sqlc.json (100%) create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/batch.go create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/db.go create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/models.go create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/query.sql.go create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/query.sql create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/sqlc.json create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/batch.go create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/db.go create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/models.go create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/query.sql.go create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/query.sql create mode 100644 internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/sqlc.json diff --git a/internal/codegen/golang/templates/pgx/batchCode.tmpl b/internal/codegen/golang/templates/pgx/batchCode.tmpl index 9603696cd9..42b7e0face 100644 --- a/internal/codegen/golang/templates/pgx/batchCode.tmpl +++ b/internal/codegen/golang/templates/pgx/batchCode.tmpl @@ -107,7 +107,7 @@ func (b *{{.MethodName}}BatchResults) QueryRow(f func(int, {{.Ret.DefineType}}, var {{.Ret.Name}} {{.Ret.Type}} if b.closed { if f != nil { - f(t, {{.Ret.Name}}, errors.New("batch already closed")) + f(t, {{if .Ret.IsPointer}}nil{{else}}{{.Ret.Name}}{{end}}, errors.New("batch already closed")) } continue } diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/go/db.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/go/db.go similarity index 100% rename from internal/endtoend/testdata/emit_result_and_params_struct_pointers/go/db.go rename to internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/go/db.go diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/go/models.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/go/models.go similarity index 100% rename from internal/endtoend/testdata/emit_result_and_params_struct_pointers/go/models.go rename to internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/go/models.go diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/go/querier.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/go/querier.go similarity index 100% rename from internal/endtoend/testdata/emit_result_and_params_struct_pointers/go/querier.go rename to internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/go/querier.go diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/go/query.sql.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/go/query.sql.go similarity index 100% rename from internal/endtoend/testdata/emit_result_and_params_struct_pointers/go/query.sql.go rename to internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/go/query.sql.go diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/query.sql b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/query.sql similarity index 100% rename from internal/endtoend/testdata/emit_result_and_params_struct_pointers/query.sql rename to internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/query.sql diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/sqlc.json b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/sqlc.json similarity index 100% rename from internal/endtoend/testdata/emit_result_and_params_struct_pointers/sqlc.json rename to internal/endtoend/testdata/emit_result_and_params_struct_pointers/mysql/sqlc.json diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/batch.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/batch.go new file mode 100644 index 0000000000..7e4e20e40f --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/batch.go @@ -0,0 +1,68 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 +// source: batch.go + +package querytest + +import ( + "context" + "database/sql" + "errors" + + "github.com/jackc/pgx/v4" +) + +const insertValues = `-- name: InsertValues :batchone +INSERT INTO foo (a, b) +VALUES ($1, $2) +ON CONFLICT DO NOTHING +RETURNING a, b +` + +type InsertValuesBatchResults struct { + br pgx.BatchResults + tot int + closed bool +} + +type InsertValuesParams struct { + A sql.NullInt32 + B sql.NullInt32 +} + +func (q *Queries) InsertValues(ctx context.Context, arg []*InsertValuesParams) *InsertValuesBatchResults { + batch := &pgx.Batch{} + for _, a := range arg { + vals := []interface{}{ + a.A, + a.B, + } + batch.Queue(insertValues, vals...) + } + br := q.db.SendBatch(ctx, batch) + return &InsertValuesBatchResults{br, len(arg), false} +} + +func (b *InsertValuesBatchResults) QueryRow(f func(int, *Foo, error)) { + defer b.br.Close() + for t := 0; t < b.tot; t++ { + var i Foo + if b.closed { + if f != nil { + f(t, nil, errors.New("batch already closed")) + } + continue + } + row := b.br.QueryRow() + err := row.Scan(&i.A, &i.B) + if f != nil { + f(t, &i, err) + } + } +} + +func (b *InsertValuesBatchResults) Close() error { + b.closed = true + return b.br.Close() +} diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/db.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/db.go new file mode 100644 index 0000000000..f5ba3be7f8 --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/db.go @@ -0,0 +1,33 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 + +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 + SendBatch(context.Context, *pgx.Batch) pgx.BatchResults +} + +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/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/models.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/models.go new file mode 100644 index 0000000000..84d5d33d93 --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/models.go @@ -0,0 +1,14 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 + +package querytest + +import ( + "database/sql" +) + +type Foo struct { + A sql.NullInt32 + B sql.NullInt32 +} diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/query.sql.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/query.sql.go new file mode 100644 index 0000000000..99356b3997 --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/go/query.sql.go @@ -0,0 +1,75 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 +// source: query.sql + +package querytest + +import ( + "context" + "database/sql" +) + +const getAll = `-- name: GetAll :many +SELECT a, b FROM foo +` + +func (q *Queries) GetAll(ctx context.Context) ([]*Foo, error) { + rows, err := q.db.Query(ctx, getAll) + if err != nil { + return nil, err + } + defer rows.Close() + var items []*Foo + for rows.Next() { + var i Foo + if err := rows.Scan(&i.A, &i.B); err != nil { + return nil, err + } + items = append(items, &i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getAllAByB = `-- name: GetAllAByB :many +SELECT a FROM foo WHERE b = ? +` + +func (q *Queries) GetAllAByB(ctx context.Context, b sql.NullInt32) ([]sql.NullInt32, error) { + rows, err := q.db.Query(ctx, getAllAByB, b) + if err != nil { + return nil, err + } + defer rows.Close() + var items []sql.NullInt32 + for rows.Next() { + var a sql.NullInt32 + if err := rows.Scan(&a); err != nil { + return nil, err + } + items = append(items, a) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getOne = `-- name: GetOne :one +SELECT a, b FROM foo WHERE a = ? AND b = ? LIMIT 1 +` + +type GetOneParams struct { + A sql.NullInt32 + B sql.NullInt32 +} + +func (q *Queries) GetOne(ctx context.Context, arg *GetOneParams) (*Foo, error) { + row := q.db.QueryRow(ctx, getOne, arg.A, arg.B) + var i Foo + err := row.Scan(&i.A, &i.B) + return &i, err +} diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/query.sql b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/query.sql new file mode 100644 index 0000000000..7fc9b6b946 --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/query.sql @@ -0,0 +1,16 @@ +CREATE TABLE foo (a integer, b integer); + +-- name: InsertValues :batchone +INSERT INTO foo (a, b) +VALUES ($1, $2) +ON CONFLICT DO NOTHING +RETURNING *; + +-- name: GetOne :one +SELECT * FROM foo WHERE a = ? AND b = ? LIMIT 1; + +-- name: GetAll :many +SELECT * FROM foo; + +-- name: GetAllAByB :many +SELECT a FROM foo WHERE b = ?; diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/sqlc.json b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/sqlc.json new file mode 100644 index 0000000000..3ce648806d --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v4/sqlc.json @@ -0,0 +1,19 @@ +{ + "version": "2", + "sql": [ + { + "engine": "postgresql", + "schema": "query.sql", + "queries": "query.sql", + "gen": { + "go": { + "package": "querytest", + "sql_package": "pgx/v4", + "out": "go", + "emit_result_struct_pointers": true, + "emit_params_struct_pointers": true + } + } + } + ] +} diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/batch.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/batch.go new file mode 100644 index 0000000000..1b4a713582 --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/batch.go @@ -0,0 +1,68 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 +// source: batch.go + +package querytest + +import ( + "context" + "errors" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgtype" +) + +const insertValues = `-- name: InsertValues :batchone +INSERT INTO foo (a, b) +VALUES ($1, $2) +ON CONFLICT DO NOTHING +RETURNING a, b +` + +type InsertValuesBatchResults struct { + br pgx.BatchResults + tot int + closed bool +} + +type InsertValuesParams struct { + A pgtype.Int4 + B pgtype.Int4 +} + +func (q *Queries) InsertValues(ctx context.Context, arg []*InsertValuesParams) *InsertValuesBatchResults { + batch := &pgx.Batch{} + for _, a := range arg { + vals := []interface{}{ + a.A, + a.B, + } + batch.Queue(insertValues, vals...) + } + br := q.db.SendBatch(ctx, batch) + return &InsertValuesBatchResults{br, len(arg), false} +} + +func (b *InsertValuesBatchResults) QueryRow(f func(int, *Foo, error)) { + defer b.br.Close() + for t := 0; t < b.tot; t++ { + var i Foo + if b.closed { + if f != nil { + f(t, nil, errors.New("batch already closed")) + } + continue + } + row := b.br.QueryRow() + err := row.Scan(&i.A, &i.B) + if f != nil { + f(t, &i, err) + } + } +} + +func (b *InsertValuesBatchResults) Close() error { + b.closed = true + return b.br.Close() +} diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/db.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/db.go new file mode 100644 index 0000000000..08e71d89dc --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/db.go @@ -0,0 +1,33 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5" + "github.com/jackc/pgx/v5/pgconn" +) + +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 + SendBatch(context.Context, *pgx.Batch) pgx.BatchResults +} + +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/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/models.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/models.go new file mode 100644 index 0000000000..517c8704fb --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/models.go @@ -0,0 +1,14 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 + +package querytest + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Foo struct { + A pgtype.Int4 + B pgtype.Int4 +} diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/query.sql.go b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/query.sql.go new file mode 100644 index 0000000000..0dc08bebc5 --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/go/query.sql.go @@ -0,0 +1,76 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.17.2 +// source: query.sql + +package querytest + +import ( + "context" + + "github.com/jackc/pgx/v5/pgtype" +) + +const getAll = `-- name: GetAll :many +SELECT a, b FROM foo +` + +func (q *Queries) GetAll(ctx context.Context) ([]*Foo, error) { + rows, err := q.db.Query(ctx, getAll) + if err != nil { + return nil, err + } + defer rows.Close() + var items []*Foo + for rows.Next() { + var i Foo + if err := rows.Scan(&i.A, &i.B); err != nil { + return nil, err + } + items = append(items, &i) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getAllAByB = `-- name: GetAllAByB :many +SELECT a FROM foo WHERE b = ? +` + +func (q *Queries) GetAllAByB(ctx context.Context, b pgtype.Int4) ([]pgtype.Int4, error) { + rows, err := q.db.Query(ctx, getAllAByB, b) + if err != nil { + return nil, err + } + defer rows.Close() + var items []pgtype.Int4 + for rows.Next() { + var a pgtype.Int4 + if err := rows.Scan(&a); err != nil { + return nil, err + } + items = append(items, a) + } + if err := rows.Err(); err != nil { + return nil, err + } + return items, nil +} + +const getOne = `-- name: GetOne :one +SELECT a, b FROM foo WHERE a = ? AND b = ? LIMIT 1 +` + +type GetOneParams struct { + A pgtype.Int4 + B pgtype.Int4 +} + +func (q *Queries) GetOne(ctx context.Context, arg *GetOneParams) (*Foo, error) { + row := q.db.QueryRow(ctx, getOne, arg.A, arg.B) + var i Foo + err := row.Scan(&i.A, &i.B) + return &i, err +} diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/query.sql b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/query.sql new file mode 100644 index 0000000000..7fc9b6b946 --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/query.sql @@ -0,0 +1,16 @@ +CREATE TABLE foo (a integer, b integer); + +-- name: InsertValues :batchone +INSERT INTO foo (a, b) +VALUES ($1, $2) +ON CONFLICT DO NOTHING +RETURNING *; + +-- name: GetOne :one +SELECT * FROM foo WHERE a = ? AND b = ? LIMIT 1; + +-- name: GetAll :many +SELECT * FROM foo; + +-- name: GetAllAByB :many +SELECT a FROM foo WHERE b = ?; diff --git a/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/sqlc.json b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/sqlc.json new file mode 100644 index 0000000000..693beafd11 --- /dev/null +++ b/internal/endtoend/testdata/emit_result_and_params_struct_pointers/postgresql/pgx/v5/sqlc.json @@ -0,0 +1,19 @@ +{ + "version": "2", + "sql": [ + { + "engine": "postgresql", + "schema": "query.sql", + "queries": "query.sql", + "gen": { + "go": { + "package": "querytest", + "sql_package": "pgx/v5", + "out": "go", + "emit_result_struct_pointers": true, + "emit_params_struct_pointers": true + } + } + } + ] +}