From 1019343045bac10530f0a9dbedf483e56c151c1d Mon Sep 17 00:00:00 2001 From: Andrew Benton Date: Sat, 8 Mar 2025 23:21:35 -0800 Subject: [PATCH 1/4] feat(codegen/golang): add an option to wrap query errors that includes query name --- internal/codegen/golang/gen.go | 5 + internal/codegen/golang/imports.go | 4 + internal/codegen/golang/opts/options.go | 1 + .../golang/templates/pgx/queryCode.tmpl | 25 ++-- .../golang/templates/stdlib/queryCode.tmpl | 28 ++++- .../wrap_errors/postgresql/pgx/db/db.go | 32 +++++ .../wrap_errors/postgresql/pgx/db/models.go | 15 +++ .../postgresql/pgx/db/query.sql.go | 119 ++++++++++++++++++ .../wrap_errors/postgresql/pgx/query.sql | 31 +++++ .../wrap_errors/postgresql/pgx/schema.sql | 5 + .../wrap_errors/postgresql/pgx/sqlc.yaml | 11 ++ 11 files changed, 263 insertions(+), 13 deletions(-) create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/db.go create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/models.go create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/query.sql.go create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/pgx/query.sql create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/pgx/schema.sql create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/pgx/sqlc.yaml diff --git a/internal/codegen/golang/gen.go b/internal/codegen/golang/gen.go index 5b7977f500..ac91cc537f 100644 --- a/internal/codegen/golang/gen.go +++ b/internal/codegen/golang/gen.go @@ -41,6 +41,7 @@ type tmplCtx struct { UsesBatch bool OmitSqlcVersion bool BuildTags string + WrapErrors bool } func (t *tmplCtx) OutputQuery(sourceName string) bool { @@ -98,6 +99,9 @@ func (t *tmplCtx) codegenQueryRetval(q Query) (string, error) { case ":execrows", ":execlastid": return "result, err :=", nil case ":execresult": + if t.WrapErrors { + return "result, err :=", nil + } return "return", nil default: return "", fmt.Errorf("unhandled q.Cmd case %q", q.Cmd) @@ -187,6 +191,7 @@ func generate(req *plugin.GenerateRequest, options *opts.Options, enums []Enum, SqlcVersion: req.SqlcVersion, BuildTags: options.BuildTags, OmitSqlcVersion: options.OmitSqlcVersion, + WrapErrors: options.WrapErrors, } if tctx.UsesCopyFrom && !tctx.SQLDriver.IsPGX() && options.SqlDriver != opts.SQLDriverGoSQLDriverMySQL { diff --git a/internal/codegen/golang/imports.go b/internal/codegen/golang/imports.go index 9e7819e4b1..ccca4f603c 100644 --- a/internal/codegen/golang/imports.go +++ b/internal/codegen/golang/imports.go @@ -402,6 +402,10 @@ func (i *importer) queryImports(filename string) fileImports { pkg[ImportSpec{Path: "github.com/lib/pq"}] = struct{}{} } + if i.Options.WrapErrors { + std["fmt"] = struct{}{} + } + return sortedImports(std, pkg) } diff --git a/internal/codegen/golang/opts/options.go b/internal/codegen/golang/opts/options.go index 30a6c2246c..0d5d51c2dd 100644 --- a/internal/codegen/golang/opts/options.go +++ b/internal/codegen/golang/opts/options.go @@ -39,6 +39,7 @@ type Options struct { OutputCopyfromFileName string `json:"output_copyfrom_file_name,omitempty" yaml:"output_copyfrom_file_name"` OutputFilesSuffix string `json:"output_files_suffix,omitempty" yaml:"output_files_suffix"` InflectionExcludeTableNames []string `json:"inflection_exclude_table_names,omitempty" yaml:"inflection_exclude_table_names"` + WrapErrors bool `json:"wrap_errors,omitempty" yaml:"wrap_errors"` QueryParameterLimit *int32 `json:"query_parameter_limit,omitempty" yaml:"query_parameter_limit"` OmitSqlcVersion bool `json:"omit_sqlc_version,omitempty" yaml:"omit_sqlc_version"` OmitUnusedStructs bool `json:"omit_unused_structs,omitempty" yaml:"omit_unused_structs"` diff --git a/internal/codegen/golang/templates/pgx/queryCode.tmpl b/internal/codegen/golang/templates/pgx/queryCode.tmpl index 18de5db2ba..1dff82e3ea 100644 --- a/internal/codegen/golang/templates/pgx/queryCode.tmpl +++ b/internal/codegen/golang/templates/pgx/queryCode.tmpl @@ -37,6 +37,11 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ({{.Ret.De var {{.Ret.Name}} {{.Ret.Type}} {{- end}} err := row.Scan({{.Ret.Scan}}) + {{- if $.WrapErrors}} + if err != nil { + err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + } + {{- end}} return {{.Ret.ReturnName}}, err } {{end}} @@ -52,7 +57,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ([]{{.Ret. rows, err := q.db.Query(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} if err != nil { - return nil, err + return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } defer rows.Close() {{- if $.EmitEmptySlices}} @@ -63,12 +68,12 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ([]{{.Ret. for rows.Next() { var {{.Ret.Name}} {{.Ret.Type}} if err := rows.Scan({{.Ret.Scan}}); err != nil { - return nil, err + return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } items = append(items, {{.Ret.ReturnName}}) } if err := rows.Err(); err != nil { - return nil, err + return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } return items, nil } @@ -84,7 +89,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) e func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) error { _, err := q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} - return err + return {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } {{end}} @@ -99,7 +104,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (int64, er result, err := q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} if err != nil { - return 0, err + return 0, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } return result.RowsAffected(), nil } @@ -110,11 +115,17 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (int64, er {{end -}} {{- if $.EmitMethodsWithDBArgument -}} func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) (pgconn.CommandTag, error) { - return db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) + result, err := db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- else -}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (pgconn.CommandTag, error) { - return q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) + result, err := q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} + {{- if $.WrapErrors}} + if err != nil { + err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + } + {{- end}} + return result, err } {{end}} diff --git a/internal/codegen/golang/templates/stdlib/queryCode.tmpl b/internal/codegen/golang/templates/stdlib/queryCode.tmpl index cf56000ec6..1dffdea1f8 100644 --- a/internal/codegen/golang/templates/stdlib/queryCode.tmpl +++ b/internal/codegen/golang/templates/stdlib/queryCode.tmpl @@ -28,6 +28,11 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} var {{.Ret.Name}} {{.Ret.Type}} {{- end}} err := row.Scan({{.Ret.Scan}}) + {{- if $.WrapErrors}} + if err != nil { + err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + } + {{- end}} return {{.Ret.ReturnName}}, err } {{end}} @@ -38,7 +43,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) ([]{{.Ret.DefineType}}, error) { {{- template "queryCodeStdExec" . }} if err != nil { - return nil, err + return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } defer rows.Close() {{- if $.EmitEmptySlices}} @@ -49,15 +54,15 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} for rows.Next() { var {{.Ret.Name}} {{.Ret.Type}} if err := rows.Scan({{.Ret.Scan}}); err != nil { - return nil, err + return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } items = append(items, {{.Ret.ReturnName}}) } if err := rows.Close(); err != nil { - return nil, err + return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } if err := rows.Err(); err != nil { - return nil, err + return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } return items, nil } @@ -68,6 +73,11 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} {{end -}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) error { {{- template "queryCodeStdExec" . }} + {{- if $.WrapErrors}} + if err != nil { + err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + } + {{- end}} return err } {{end}} @@ -78,7 +88,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) (int64, error) { {{- template "queryCodeStdExec" . }} if err != nil { - return 0, err + return 0, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } return result.RowsAffected() } @@ -90,7 +100,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) (int64, error) { {{- template "queryCodeStdExec" . }} if err != nil { - return 0, err + return 0, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} } return result.LastInsertId() } @@ -101,6 +111,12 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} {{end -}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) (sql.Result, error) { {{- template "queryCodeStdExec" . }} + {{- if $.WrapErrors}} + if err != nil { + err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + } + return result, err + {{- end}} } {{end}} diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/db.go b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/db.go new file mode 100644 index 0000000000..e0426795e3 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/db.go @@ -0,0 +1,32 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package authors + +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 +} + +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/wrap_errors/postgresql/pgx/db/models.go b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/models.go new file mode 100644 index 0000000000..be12bfc336 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package authors + +import ( + "github.com/jackc/pgx/v5/pgtype" +) + +type Author struct { + ID int64 + Name string + Bio pgtype.Text +} diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/query.sql.go b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/query.sql.go new file mode 100644 index 0000000000..f32b9b8d36 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/query.sql.go @@ -0,0 +1,119 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 +// source: query.sql + +package authors + +import ( + "context" + "fmt" + + "github.com/jackc/pgx/v5/pgconn" + "github.com/jackc/pgx/v5/pgtype" +) + +const createAuthor = `-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +) +RETURNING id, name, bio +` + +type CreateAuthorParams struct { + Name string + Bio pgtype.Text +} + +func (q *Queries) CreateAuthor(ctx context.Context, arg CreateAuthorParams) (Author, error) { + row := q.db.QueryRow(ctx, createAuthor, arg.Name, arg.Bio) + var i Author + err := row.Scan(&i.ID, &i.Name, &i.Bio) + if err != nil { + err = fmt.Errorf("error executing query CreateAuthor: %w", err) + } + return i, err +} + +const deleteAuthorExec = `-- name: DeleteAuthorExec :exec +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExec(ctx context.Context, id int64) error { + _, err := q.db.Exec(ctx, deleteAuthorExec, id) + return fmt.Errorf("error executing query DeleteAuthorExec: %w", err) +} + +const deleteAuthorExecLastID = `-- name: DeleteAuthorExecLastID :execlastid +DELETE FROM authors +WHERE id = $1 +` + +const deleteAuthorExecResult = `-- name: DeleteAuthorExecResult :execresult +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExecResult(ctx context.Context, id int64) (pgconn.CommandTag, error) { + result, err := q.db.Exec(ctx, deleteAuthorExecResult, id) + if err != nil { + err = fmt.Errorf("error executing query DeleteAuthorExecResult: %w", err) + } + return result, err +} + +const deleteAuthorExecRows = `-- name: DeleteAuthorExecRows :execrows +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExecRows(ctx context.Context, id int64) (int64, error) { + result, err := q.db.Exec(ctx, deleteAuthorExecRows, id) + if err != nil { + return 0, fmt.Errorf("error executing query DeleteAuthorExecRows: %w", err) + } + return result.RowsAffected(), nil +} + +const getAuthor = `-- name: GetAuthor :one +SELECT id, name, bio FROM authors +WHERE id = $1 LIMIT 1 +` + +func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) { + row := q.db.QueryRow(ctx, getAuthor, id) + var i Author + err := row.Scan(&i.ID, &i.Name, &i.Bio) + if err != nil { + err = fmt.Errorf("error executing query GetAuthor: %w", err) + } + return i, err +} + +const listAuthors = `-- name: ListAuthors :many +SELECT id, name, bio FROM authors +ORDER BY name +` + +func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) { + rows, err := q.db.Query(ctx, listAuthors) + if err != nil { + return nil, fmt.Errorf("error executing query ListAuthors: %w", err) + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, fmt.Errorf("error executing query ListAuthors: %w", err) + } + items = append(items, i) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("error executing query ListAuthors: %w", err) + } + return items, nil +} diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/pgx/query.sql b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/query.sql new file mode 100644 index 0000000000..e0310a2257 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/query.sql @@ -0,0 +1,31 @@ +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +) +RETURNING *; + +-- name: DeleteAuthorExec :exec +DELETE FROM authors +WHERE id = $1; + +-- name: DeleteAuthorExecRows :execrows +DELETE FROM authors +WHERE id = $1; + +-- name: DeleteAuthorExecLastID :execlastid +DELETE FROM authors +WHERE id = $1; + +-- name: DeleteAuthorExecResult :execresult +DELETE FROM authors +WHERE id = $1; diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/pgx/schema.sql b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/schema.sql new file mode 100644 index 0000000000..b4fad78497 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/pgx/sqlc.yaml b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/sqlc.yaml new file mode 100644 index 0000000000..5a2adcda8e --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/sqlc.yaml @@ -0,0 +1,11 @@ +version: 2 +sql: + - schema: "schema.sql" + queries: "query.sql" + engine: "postgresql" + gen: + go: + package: "authors" + sql_package: "pgx/v5" + out: "db" + wrap_errors: true From f2200867c762fb45b62c11be5389d287c28870e5 Mon Sep 17 00:00:00 2001 From: Andrew Benton Date: Sat, 8 Mar 2025 23:47:19 -0800 Subject: [PATCH 2/4] use queryretval template func to avoid rewriting test output --- internal/codegen/golang/templates/pgx/queryCode.tmpl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/codegen/golang/templates/pgx/queryCode.tmpl b/internal/codegen/golang/templates/pgx/queryCode.tmpl index 1dff82e3ea..cef6ed3f8b 100644 --- a/internal/codegen/golang/templates/pgx/queryCode.tmpl +++ b/internal/codegen/golang/templates/pgx/queryCode.tmpl @@ -115,17 +115,17 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (int64, er {{end -}} {{- if $.EmitMethodsWithDBArgument -}} func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) (pgconn.CommandTag, error) { - result, err := db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) + {{queryRetval .}} db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- else -}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (pgconn.CommandTag, error) { - result, err := q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) + {{queryRetval .}} q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} {{- if $.WrapErrors}} if err != nil { err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) } - {{- end}} return result, err + {{- end}} } {{end}} From 37eb9aeb66104f2a0fbe03953ba7bdd4a3480d27 Mon Sep 17 00:00:00 2001 From: Andrew Benton Date: Sun, 9 Mar 2025 11:41:19 -0700 Subject: [PATCH 3/4] shorter error messages --- .../golang/templates/pgx/queryCode.tmpl | 14 +++++++------- .../golang/templates/stdlib/queryCode.tmpl | 18 +++++++++--------- .../wrap_errors/postgresql/pgx/db/query.sql.go | 16 ++++++++-------- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/internal/codegen/golang/templates/pgx/queryCode.tmpl b/internal/codegen/golang/templates/pgx/queryCode.tmpl index cef6ed3f8b..fb43db46aa 100644 --- a/internal/codegen/golang/templates/pgx/queryCode.tmpl +++ b/internal/codegen/golang/templates/pgx/queryCode.tmpl @@ -39,7 +39,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ({{.Ret.De err := row.Scan({{.Ret.Scan}}) {{- if $.WrapErrors}} if err != nil { - err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + err = fmt.Errorf("query {{.MethodName}}: %w", err) } {{- end}} return {{.Ret.ReturnName}}, err @@ -57,7 +57,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ([]{{.Ret. rows, err := q.db.Query(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} if err != nil { - return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } defer rows.Close() {{- if $.EmitEmptySlices}} @@ -68,12 +68,12 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ([]{{.Ret. for rows.Next() { var {{.Ret.Name}} {{.Ret.Type}} if err := rows.Scan({{.Ret.Scan}}); err != nil { - return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } items = append(items, {{.Ret.ReturnName}}) } if err := rows.Err(); err != nil { - return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } return items, nil } @@ -89,7 +89,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, db DBTX, {{.Arg.Pair}}) e func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) error { _, err := q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} - return {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } {{end}} @@ -104,7 +104,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (int64, er result, err := q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}}) {{- end}} if err != nil { - return 0, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return 0, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } return result.RowsAffected(), nil } @@ -122,7 +122,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (pgconn.Co {{- end}} {{- if $.WrapErrors}} if err != nil { - err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + err = fmt.Errorf("query {{.MethodName}}: %w", err) } return result, err {{- end}} diff --git a/internal/codegen/golang/templates/stdlib/queryCode.tmpl b/internal/codegen/golang/templates/stdlib/queryCode.tmpl index 1dffdea1f8..1e7f4e22a4 100644 --- a/internal/codegen/golang/templates/stdlib/queryCode.tmpl +++ b/internal/codegen/golang/templates/stdlib/queryCode.tmpl @@ -30,7 +30,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} err := row.Scan({{.Ret.Scan}}) {{- if $.WrapErrors}} if err != nil { - err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + err = fmt.Errorf("query {{.MethodName}}: %w", err) } {{- end}} return {{.Ret.ReturnName}}, err @@ -43,7 +43,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) ([]{{.Ret.DefineType}}, error) { {{- template "queryCodeStdExec" . }} if err != nil { - return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } defer rows.Close() {{- if $.EmitEmptySlices}} @@ -54,15 +54,15 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} for rows.Next() { var {{.Ret.Name}} {{.Ret.Type}} if err := rows.Scan({{.Ret.Scan}}); err != nil { - return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } items = append(items, {{.Ret.ReturnName}}) } if err := rows.Close(); err != nil { - return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } if err := rows.Err(); err != nil { - return nil, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return nil, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } return items, nil } @@ -75,7 +75,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} {{- template "queryCodeStdExec" . }} {{- if $.WrapErrors}} if err != nil { - err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + err = fmt.Errorf("query {{.MethodName}}: %w", err) } {{- end}} return err @@ -88,7 +88,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) (int64, error) { {{- template "queryCodeStdExec" . }} if err != nil { - return 0, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return 0, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } return result.RowsAffected() } @@ -100,7 +100,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) (int64, error) { {{- template "queryCodeStdExec" . }} if err != nil { - return 0, {{if $.WrapErrors}}fmt.Errorf("error executing query {{.MethodName}}: %w", err){{else}}err{{end}} + return 0, {{if $.WrapErrors}}fmt.Errorf("query {{.MethodName}}: %w", err){{else}}err{{end}} } return result.LastInsertId() } @@ -113,7 +113,7 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}} {{- template "queryCodeStdExec" . }} {{- if $.WrapErrors}} if err != nil { - err = fmt.Errorf("error executing query {{.MethodName}}: %w", err) + err = fmt.Errorf("query {{.MethodName}}: %w", err) } return result, err {{- end}} diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/query.sql.go b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/query.sql.go index f32b9b8d36..3da47fd614 100644 --- a/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/query.sql.go +++ b/internal/endtoend/testdata/wrap_errors/postgresql/pgx/db/query.sql.go @@ -32,7 +32,7 @@ func (q *Queries) CreateAuthor(ctx context.Context, arg CreateAuthorParams) (Aut var i Author err := row.Scan(&i.ID, &i.Name, &i.Bio) if err != nil { - err = fmt.Errorf("error executing query CreateAuthor: %w", err) + err = fmt.Errorf("query CreateAuthor: %w", err) } return i, err } @@ -44,7 +44,7 @@ WHERE id = $1 func (q *Queries) DeleteAuthorExec(ctx context.Context, id int64) error { _, err := q.db.Exec(ctx, deleteAuthorExec, id) - return fmt.Errorf("error executing query DeleteAuthorExec: %w", err) + return fmt.Errorf("query DeleteAuthorExec: %w", err) } const deleteAuthorExecLastID = `-- name: DeleteAuthorExecLastID :execlastid @@ -60,7 +60,7 @@ WHERE id = $1 func (q *Queries) DeleteAuthorExecResult(ctx context.Context, id int64) (pgconn.CommandTag, error) { result, err := q.db.Exec(ctx, deleteAuthorExecResult, id) if err != nil { - err = fmt.Errorf("error executing query DeleteAuthorExecResult: %w", err) + err = fmt.Errorf("query DeleteAuthorExecResult: %w", err) } return result, err } @@ -73,7 +73,7 @@ WHERE id = $1 func (q *Queries) DeleteAuthorExecRows(ctx context.Context, id int64) (int64, error) { result, err := q.db.Exec(ctx, deleteAuthorExecRows, id) if err != nil { - return 0, fmt.Errorf("error executing query DeleteAuthorExecRows: %w", err) + return 0, fmt.Errorf("query DeleteAuthorExecRows: %w", err) } return result.RowsAffected(), nil } @@ -88,7 +88,7 @@ func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) { var i Author err := row.Scan(&i.ID, &i.Name, &i.Bio) if err != nil { - err = fmt.Errorf("error executing query GetAuthor: %w", err) + err = fmt.Errorf("query GetAuthor: %w", err) } return i, err } @@ -101,19 +101,19 @@ ORDER BY name func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) { rows, err := q.db.Query(ctx, listAuthors) if err != nil { - return nil, fmt.Errorf("error executing query ListAuthors: %w", err) + return nil, fmt.Errorf("query ListAuthors: %w", err) } defer rows.Close() var items []Author for rows.Next() { var i Author if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { - return nil, fmt.Errorf("error executing query ListAuthors: %w", err) + return nil, fmt.Errorf("query ListAuthors: %w", err) } items = append(items, i) } if err := rows.Err(); err != nil { - return nil, fmt.Errorf("error executing query ListAuthors: %w", err) + return nil, fmt.Errorf("query ListAuthors: %w", err) } return items, nil } From 9aa551fac9135076ecc03dbd656694b474410314 Mon Sep 17 00:00:00 2001 From: Andrew Benton Date: Sun, 9 Mar 2025 11:54:17 -0700 Subject: [PATCH 4/4] add more tests --- .../testdata/wrap_errors/mysql/db/db.go | 31 +++++ .../testdata/wrap_errors/mysql/db/models.go | 15 ++ .../wrap_errors/mysql/db/query.sql.go | 123 ++++++++++++++++ .../testdata/wrap_errors/mysql/query.sql | 30 ++++ .../testdata/wrap_errors/mysql/schema.sql | 5 + .../testdata/wrap_errors/mysql/sqlc.yaml | 10 ++ .../wrap_errors/postgresql/stdlib/db/db.go | 31 +++++ .../postgresql/stdlib/db/models.go | 15 ++ .../postgresql/stdlib/db/query.sql.go | 131 ++++++++++++++++++ .../wrap_errors/postgresql/stdlib/query.sql | 31 +++++ .../wrap_errors/postgresql/stdlib/schema.sql | 5 + .../wrap_errors/postgresql/stdlib/sqlc.yaml | 10 ++ .../testdata/wrap_errors/sqlite/db/db.go | 31 +++++ .../testdata/wrap_errors/sqlite/db/models.go | 15 ++ .../wrap_errors/sqlite/db/query.sql.go | 128 +++++++++++++++++ .../testdata/wrap_errors/sqlite/query.sql | 30 ++++ .../testdata/wrap_errors/sqlite/schema.sql | 5 + .../testdata/wrap_errors/sqlite/sqlc.yaml | 10 ++ 18 files changed, 656 insertions(+) create mode 100644 internal/endtoend/testdata/wrap_errors/mysql/db/db.go create mode 100644 internal/endtoend/testdata/wrap_errors/mysql/db/models.go create mode 100644 internal/endtoend/testdata/wrap_errors/mysql/db/query.sql.go create mode 100644 internal/endtoend/testdata/wrap_errors/mysql/query.sql create mode 100644 internal/endtoend/testdata/wrap_errors/mysql/schema.sql create mode 100644 internal/endtoend/testdata/wrap_errors/mysql/sqlc.yaml create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/db.go create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/models.go create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/query.sql.go create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/stdlib/query.sql create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/stdlib/schema.sql create mode 100644 internal/endtoend/testdata/wrap_errors/postgresql/stdlib/sqlc.yaml create mode 100644 internal/endtoend/testdata/wrap_errors/sqlite/db/db.go create mode 100644 internal/endtoend/testdata/wrap_errors/sqlite/db/models.go create mode 100644 internal/endtoend/testdata/wrap_errors/sqlite/db/query.sql.go create mode 100644 internal/endtoend/testdata/wrap_errors/sqlite/query.sql create mode 100644 internal/endtoend/testdata/wrap_errors/sqlite/schema.sql create mode 100644 internal/endtoend/testdata/wrap_errors/sqlite/sqlc.yaml diff --git a/internal/endtoend/testdata/wrap_errors/mysql/db/db.go b/internal/endtoend/testdata/wrap_errors/mysql/db/db.go new file mode 100644 index 0000000000..583a45c80d --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/mysql/db/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package authors + +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/wrap_errors/mysql/db/models.go b/internal/endtoend/testdata/wrap_errors/mysql/db/models.go new file mode 100644 index 0000000000..7c18cda646 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/mysql/db/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package authors + +import ( + "database/sql" +) + +type Author struct { + ID int64 + Name string + Bio sql.NullString +} diff --git a/internal/endtoend/testdata/wrap_errors/mysql/db/query.sql.go b/internal/endtoend/testdata/wrap_errors/mysql/db/query.sql.go new file mode 100644 index 0000000000..a04ba62b32 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/mysql/db/query.sql.go @@ -0,0 +1,123 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 +// source: query.sql + +package authors + +import ( + "context" + "database/sql" + "fmt" +) + +const createAuthor = `-- name: CreateAuthor :execlastid +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +) +` + +func (q *Queries) CreateAuthor(ctx context.Context) (int64, error) { + result, err := q.db.ExecContext(ctx, createAuthor) + if err != nil { + return 0, fmt.Errorf("query CreateAuthor: %w", err) + } + return result.LastInsertId() +} + +const deleteAuthorExec = `-- name: DeleteAuthorExec :exec +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExec(ctx context.Context) error { + _, err := q.db.ExecContext(ctx, deleteAuthorExec) + if err != nil { + err = fmt.Errorf("query DeleteAuthorExec: %w", err) + } + return err +} + +const deleteAuthorExecLastID = `-- name: DeleteAuthorExecLastID :execlastid +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExecLastID(ctx context.Context) (int64, error) { + result, err := q.db.ExecContext(ctx, deleteAuthorExecLastID) + if err != nil { + return 0, fmt.Errorf("query DeleteAuthorExecLastID: %w", err) + } + return result.LastInsertId() +} + +const deleteAuthorExecResult = `-- name: DeleteAuthorExecResult :execresult +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExecResult(ctx context.Context) (sql.Result, error) { + result, err := q.db.ExecContext(ctx, deleteAuthorExecResult) + if err != nil { + err = fmt.Errorf("query DeleteAuthorExecResult: %w", err) + } + return result, err +} + +const deleteAuthorExecRows = `-- name: DeleteAuthorExecRows :execrows +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExecRows(ctx context.Context) (int64, error) { + result, err := q.db.ExecContext(ctx, deleteAuthorExecRows) + if err != nil { + return 0, fmt.Errorf("query DeleteAuthorExecRows: %w", err) + } + return result.RowsAffected() +} + +const getAuthor = `-- name: GetAuthor :one +SELECT id, name, bio FROM authors +WHERE id = $1 LIMIT 1 +` + +func (q *Queries) GetAuthor(ctx context.Context) (Author, error) { + row := q.db.QueryRowContext(ctx, getAuthor) + var i Author + err := row.Scan(&i.ID, &i.Name, &i.Bio) + if err != nil { + err = fmt.Errorf("query GetAuthor: %w", err) + } + return i, err +} + +const listAuthors = `-- name: ListAuthors :many +SELECT id, name, bio FROM authors +ORDER BY name +` + +func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthors) + if err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + return items, nil +} diff --git a/internal/endtoend/testdata/wrap_errors/mysql/query.sql b/internal/endtoend/testdata/wrap_errors/mysql/query.sql new file mode 100644 index 0000000000..3f9971d942 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/mysql/query.sql @@ -0,0 +1,30 @@ +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :execlastid +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +); + +-- name: DeleteAuthorExec :exec +DELETE FROM authors +WHERE id = $1; + +-- name: DeleteAuthorExecRows :execrows +DELETE FROM authors +WHERE id = $1; + +-- name: DeleteAuthorExecLastID :execlastid +DELETE FROM authors +WHERE id = $1; + +-- name: DeleteAuthorExecResult :execresult +DELETE FROM authors +WHERE id = $1; diff --git a/internal/endtoend/testdata/wrap_errors/mysql/schema.sql b/internal/endtoend/testdata/wrap_errors/mysql/schema.sql new file mode 100644 index 0000000000..8d65cdb7b5 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/mysql/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGINT PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/wrap_errors/mysql/sqlc.yaml b/internal/endtoend/testdata/wrap_errors/mysql/sqlc.yaml new file mode 100644 index 0000000000..5b3b1ddc10 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/mysql/sqlc.yaml @@ -0,0 +1,10 @@ +version: 2 +sql: + - schema: "schema.sql" + queries: "query.sql" + engine: "mysql" + gen: + go: + package: "authors" + out: "db" + wrap_errors: true diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/db.go b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/db.go new file mode 100644 index 0000000000..583a45c80d --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package authors + +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/wrap_errors/postgresql/stdlib/db/models.go b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/models.go new file mode 100644 index 0000000000..7c18cda646 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package authors + +import ( + "database/sql" +) + +type Author struct { + ID int64 + Name string + Bio sql.NullString +} diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/query.sql.go b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/query.sql.go new file mode 100644 index 0000000000..71d946ad4e --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/db/query.sql.go @@ -0,0 +1,131 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 +// source: query.sql + +package authors + +import ( + "context" + "database/sql" + "fmt" +) + +const createAuthor = `-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +) +RETURNING id, name, bio +` + +type CreateAuthorParams struct { + Name string + Bio sql.NullString +} + +func (q *Queries) CreateAuthor(ctx context.Context, arg CreateAuthorParams) (Author, error) { + row := q.db.QueryRowContext(ctx, createAuthor, arg.Name, arg.Bio) + var i Author + err := row.Scan(&i.ID, &i.Name, &i.Bio) + if err != nil { + err = fmt.Errorf("query CreateAuthor: %w", err) + } + return i, err +} + +const deleteAuthorExec = `-- name: DeleteAuthorExec :exec +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExec(ctx context.Context, id int64) error { + _, err := q.db.ExecContext(ctx, deleteAuthorExec, id) + if err != nil { + err = fmt.Errorf("query DeleteAuthorExec: %w", err) + } + return err +} + +const deleteAuthorExecLastID = `-- name: DeleteAuthorExecLastID :execlastid +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExecLastID(ctx context.Context, id int64) (int64, error) { + result, err := q.db.ExecContext(ctx, deleteAuthorExecLastID, id) + if err != nil { + return 0, fmt.Errorf("query DeleteAuthorExecLastID: %w", err) + } + return result.LastInsertId() +} + +const deleteAuthorExecResult = `-- name: DeleteAuthorExecResult :execresult +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExecResult(ctx context.Context, id int64) (sql.Result, error) { + result, err := q.db.ExecContext(ctx, deleteAuthorExecResult, id) + if err != nil { + err = fmt.Errorf("query DeleteAuthorExecResult: %w", err) + } + return result, err +} + +const deleteAuthorExecRows = `-- name: DeleteAuthorExecRows :execrows +DELETE FROM authors +WHERE id = $1 +` + +func (q *Queries) DeleteAuthorExecRows(ctx context.Context, id int64) (int64, error) { + result, err := q.db.ExecContext(ctx, deleteAuthorExecRows, id) + if err != nil { + return 0, fmt.Errorf("query DeleteAuthorExecRows: %w", err) + } + return result.RowsAffected() +} + +const getAuthor = `-- name: GetAuthor :one +SELECT id, name, bio FROM authors +WHERE id = $1 LIMIT 1 +` + +func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) { + row := q.db.QueryRowContext(ctx, getAuthor, id) + var i Author + err := row.Scan(&i.ID, &i.Name, &i.Bio) + if err != nil { + err = fmt.Errorf("query GetAuthor: %w", err) + } + return i, err +} + +const listAuthors = `-- name: ListAuthors :many +SELECT id, name, bio FROM authors +ORDER BY name +` + +func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthors) + if err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + return items, nil +} diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/query.sql b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/query.sql new file mode 100644 index 0000000000..e0310a2257 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/query.sql @@ -0,0 +1,31 @@ +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +) +RETURNING *; + +-- name: DeleteAuthorExec :exec +DELETE FROM authors +WHERE id = $1; + +-- name: DeleteAuthorExecRows :execrows +DELETE FROM authors +WHERE id = $1; + +-- name: DeleteAuthorExecLastID :execlastid +DELETE FROM authors +WHERE id = $1; + +-- name: DeleteAuthorExecResult :execresult +DELETE FROM authors +WHERE id = $1; diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/schema.sql b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/schema.sql new file mode 100644 index 0000000000..b4fad78497 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/sqlc.yaml b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/sqlc.yaml new file mode 100644 index 0000000000..6827bf778a --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/postgresql/stdlib/sqlc.yaml @@ -0,0 +1,10 @@ +version: 2 +sql: + - schema: "schema.sql" + queries: "query.sql" + engine: "postgresql" + gen: + go: + package: "authors" + out: "db" + wrap_errors: true diff --git a/internal/endtoend/testdata/wrap_errors/sqlite/db/db.go b/internal/endtoend/testdata/wrap_errors/sqlite/db/db.go new file mode 100644 index 0000000000..583a45c80d --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/sqlite/db/db.go @@ -0,0 +1,31 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package authors + +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/wrap_errors/sqlite/db/models.go b/internal/endtoend/testdata/wrap_errors/sqlite/db/models.go new file mode 100644 index 0000000000..7c18cda646 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/sqlite/db/models.go @@ -0,0 +1,15 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 + +package authors + +import ( + "database/sql" +) + +type Author struct { + ID int64 + Name string + Bio sql.NullString +} diff --git a/internal/endtoend/testdata/wrap_errors/sqlite/db/query.sql.go b/internal/endtoend/testdata/wrap_errors/sqlite/db/query.sql.go new file mode 100644 index 0000000000..cf3d7be9b0 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/sqlite/db/query.sql.go @@ -0,0 +1,128 @@ +// Code generated by sqlc. DO NOT EDIT. +// versions: +// sqlc v1.28.0 +// source: query.sql + +package authors + +import ( + "context" + "database/sql" + "fmt" +) + +const createAuthor = `-- name: CreateAuthor :execlastid +INSERT INTO authors ( + name, bio +) VALUES ( + ?1, ?2 +) +` + +type CreateAuthorParams struct { + Name string + Bio sql.NullString +} + +func (q *Queries) CreateAuthor(ctx context.Context, arg CreateAuthorParams) (int64, error) { + result, err := q.db.ExecContext(ctx, createAuthor, arg.Name, arg.Bio) + if err != nil { + return 0, fmt.Errorf("query CreateAuthor: %w", err) + } + return result.LastInsertId() +} + +const deleteAuthorExec = `-- name: DeleteAuthorExec :exec +DELETE FROM authors +WHERE id = ?1 +` + +func (q *Queries) DeleteAuthorExec(ctx context.Context, id int64) error { + _, err := q.db.ExecContext(ctx, deleteAuthorExec, id) + if err != nil { + err = fmt.Errorf("query DeleteAuthorExec: %w", err) + } + return err +} + +const deleteAuthorExecLastID = `-- name: DeleteAuthorExecLastID :execlastid +DELETE FROM authors +WHERE id = ?1 +` + +func (q *Queries) DeleteAuthorExecLastID(ctx context.Context, id int64) (int64, error) { + result, err := q.db.ExecContext(ctx, deleteAuthorExecLastID, id) + if err != nil { + return 0, fmt.Errorf("query DeleteAuthorExecLastID: %w", err) + } + return result.LastInsertId() +} + +const deleteAuthorExecResult = `-- name: DeleteAuthorExecResult :execresult +DELETE FROM authors +WHERE id = ?1 +` + +func (q *Queries) DeleteAuthorExecResult(ctx context.Context, id int64) (sql.Result, error) { + result, err := q.db.ExecContext(ctx, deleteAuthorExecResult, id) + if err != nil { + err = fmt.Errorf("query DeleteAuthorExecResult: %w", err) + } + return result, err +} + +const deleteAuthorExecRows = `-- name: DeleteAuthorExecRows :execrows +DELETE FROM authors +WHERE id = ?1 +` + +func (q *Queries) DeleteAuthorExecRows(ctx context.Context, id int64) (int64, error) { + result, err := q.db.ExecContext(ctx, deleteAuthorExecRows, id) + if err != nil { + return 0, fmt.Errorf("query DeleteAuthorExecRows: %w", err) + } + return result.RowsAffected() +} + +const getAuthor = `-- name: GetAuthor :one +SELECT id, name, bio FROM authors +WHERE id = ?1 LIMIT 1 +` + +func (q *Queries) GetAuthor(ctx context.Context, id int64) (Author, error) { + row := q.db.QueryRowContext(ctx, getAuthor, id) + var i Author + err := row.Scan(&i.ID, &i.Name, &i.Bio) + if err != nil { + err = fmt.Errorf("query GetAuthor: %w", err) + } + return i, err +} + +const listAuthors = `-- name: ListAuthors :many +SELECT id, name, bio FROM authors +ORDER BY name +` + +func (q *Queries) ListAuthors(ctx context.Context) ([]Author, error) { + rows, err := q.db.QueryContext(ctx, listAuthors) + if err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + defer rows.Close() + var items []Author + for rows.Next() { + var i Author + if err := rows.Scan(&i.ID, &i.Name, &i.Bio); err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + items = append(items, i) + } + if err := rows.Close(); err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + if err := rows.Err(); err != nil { + return nil, fmt.Errorf("query ListAuthors: %w", err) + } + return items, nil +} diff --git a/internal/endtoend/testdata/wrap_errors/sqlite/query.sql b/internal/endtoend/testdata/wrap_errors/sqlite/query.sql new file mode 100644 index 0000000000..2db6403c8b --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/sqlite/query.sql @@ -0,0 +1,30 @@ +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = ?1 LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :execlastid +INSERT INTO authors ( + name, bio +) VALUES ( + ?1, ?2 +); + +-- name: DeleteAuthorExec :exec +DELETE FROM authors +WHERE id = ?1; + +-- name: DeleteAuthorExecRows :execrows +DELETE FROM authors +WHERE id = ?1; + +-- name: DeleteAuthorExecLastID :execlastid +DELETE FROM authors +WHERE id = ?1; + +-- name: DeleteAuthorExecResult :execresult +DELETE FROM authors +WHERE id = ?1; diff --git a/internal/endtoend/testdata/wrap_errors/sqlite/schema.sql b/internal/endtoend/testdata/wrap_errors/sqlite/schema.sql new file mode 100644 index 0000000000..8d65cdb7b5 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/sqlite/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGINT PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/wrap_errors/sqlite/sqlc.yaml b/internal/endtoend/testdata/wrap_errors/sqlite/sqlc.yaml new file mode 100644 index 0000000000..de726297c7 --- /dev/null +++ b/internal/endtoend/testdata/wrap_errors/sqlite/sqlc.yaml @@ -0,0 +1,10 @@ +version: 2 +sql: + - schema: "schema.sql" + queries: "query.sql" + engine: "sqlite" + gen: + go: + package: "authors" + out: "db" + wrap_errors: true