Skip to content

Commit c5f3105

Browse files
committed
feat: adding support for pgx/v4
1 parent 560acee commit c5f3105

6 files changed

Lines changed: 157 additions & 110 deletions

File tree

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ packages:
278278
queries: "./sql/query/"
279279
schema: "./sql/schema/"
280280
engine: "postgresql"
281+
sql_library: "pgx/v4"
281282
emit_json_tags: true
282283
emit_prepared_queries: true
283284
emit_interface: false
@@ -296,6 +297,8 @@ Each package document has the following keys:
296297
- Directory of SQL migrations or path to single SQL file; or a list of paths
297298
- `engine`:
298299
- Either `postgresql` or `mysql`. Defaults to `postgresql`. MySQL support is experimental
300+
- `sql_library`:
301+
- Either `pgx/v4` or empty, which defaults to using the `database/sql` package
299302
- `emit_json_tags`:
300303
- If true, add JSON tags to generated structs. Defaults to `false`.
301304
- `emit_prepared_queries`:

examples/booktest/mysql/db_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func TestBooks(t *testing.T) {
5454
AuthorID: int32(authorID),
5555
Isbn: "2",
5656
Title: "the second book",
57-
BookType: BooksBookTypeFICTION ,
57+
BookType: BooksBookTypeFICTION,
5858
Yr: 2016,
5959
Available: now,
6060
Tags: "cool,unique",

internal/codegen/golang/gen.go

Lines changed: 140 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,44 @@ import (
3535
{{end}}
3636
3737
{{define "dbCode"}}
38+
39+
{{if eq .SQLLibrary "pgx/v4"}}
40+
41+
type DBTX interface {
42+
Query(ctx context.Context, sql string, args ...interface{}) (pgx.Rows, error)
43+
QueryRow(ctx context.Context, sql string, args ...interface{}) pgx.Row
44+
Exec(ctx context.Context, sql string, arguments ...interface{}) (pgconn.CommandTag, error)
45+
Close()
46+
}
47+
48+
func New(db DBTX) *Queries {
49+
return &Queries{db: db}
50+
}
51+
52+
func (q *Queries) Close() error {
53+
q.db.Close()
54+
return nil
55+
}
56+
57+
func (q *Queries) exec(ctx context.Context, query string, args ...interface{}) (pgconn.CommandTag, error) {
58+
return q.db.Exec(ctx, query, args...)
59+
60+
}
61+
62+
func (q *Queries) query(ctx context.Context, query string, args ...interface{}) (pgx.Rows, error) {
63+
return q.db.Query(ctx, query, args...)
64+
}
65+
66+
func (q *Queries) queryRow(ctx context.Context, query string, args ...interface{}) pgx.Row {
67+
return q.db.QueryRow(ctx, query, args...)
68+
}
69+
70+
type Queries struct {
71+
db DBTX
72+
}
73+
74+
{{else}}
75+
3876
type DBTX interface {
3977
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
4078
PrepareContext(context.Context, string) (*sql.Stmt, error)
@@ -130,6 +168,8 @@ func (q *Queries) WithTx(tx *sql.Tx) *Queries {
130168
}
131169
}
132170
{{end}}
171+
{{end}}
172+
133173
134174
{{define "interfaceFile"}}// Code generated by sqlc. DO NOT EDIT.
135175
@@ -235,128 +275,121 @@ import (
235275
{{end}}
236276
237277
{{define "queryCode"}}
238-
{{range .GoQueries}}
239-
{{if $.OutputQuery .SourceName}}
240-
const {{.ConstantName}} = {{$.Q}}-- name: {{.MethodName}} {{.Cmd}}
241-
{{escape .SQL}}
242-
{{$.Q}}
243-
244-
{{if .Arg.EmitStruct}}
245-
type {{.Arg.Type}} struct { {{- range .Arg.Struct.Fields}}
246-
{{.Name}} {{.Type}} {{if or ($.EmitJSONTags) ($.EmitDBTags)}}{{$.Q}}{{.Tag}}{{$.Q}}{{end}}
247-
{{- end}}
248-
}
249-
{{end}}
250-
251-
{{if .Ret.EmitStruct}}
252-
type {{.Ret.Type}} struct { {{- range .Ret.Struct.Fields}}
253-
{{.Name}} {{.Type}} {{if or ($.EmitJSONTags) ($.EmitDBTags)}}{{$.Q}}{{.Tag}}{{$.Q}}{{end}}
254-
{{- end}}
255-
}
256-
{{end}}
257-
258-
{{if eq .Cmd ":one"}}
259-
{{range .Comments}}//{{.}}
260-
{{end -}}
261-
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ({{.Ret.Type}}, error) {
262-
{{- if $.EmitPreparedQueries}}
263-
row := q.queryRow(ctx, q.{{.FieldName}}, {{.ConstantName}}, {{.Arg.Params}})
264-
{{- else}}
265-
row := q.db.QueryRowContext(ctx, {{.ConstantName}}, {{.Arg.Params}})
266-
{{- end}}
267-
var {{.Ret.Name}} {{.Ret.Type}}
268-
err := row.Scan({{.Ret.Scan}})
269-
return {{.Ret.Name}}, err
270-
}
271-
{{end}}
272278
273-
{{if eq .Cmd ":many"}}
274-
{{range .Comments}}//{{.}}
275-
{{end -}}
276-
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ([]{{.Ret.Type}}, error) {
277-
{{- if $.EmitPreparedQueries}}
278-
rows, err := q.query(ctx, q.{{.FieldName}}, {{.ConstantName}}, {{.Arg.Params}})
279-
{{- else}}
280-
rows, err := q.db.QueryContext(ctx, {{.ConstantName}}, {{.Arg.Params}})
281-
{{- end}}
282-
if err != nil {
283-
return nil, err
279+
{{if eq .SQLLibrary "pgx/v4a"}}
280+
281+
{{else}}
282+
{{range .GoQueries}}
283+
{{if $.OutputQuery .SourceName}}
284+
const {{.ConstantName}} = {{$.Q}}-- name: {{.MethodName}} {{.Cmd}}
285+
{{escape .SQL}}
286+
{{$.Q}}
287+
288+
{{if .Arg.EmitStruct}}
289+
type {{.Arg.Type}} struct { {{- range .Arg.Struct.Fields}}
290+
{{.Name}} {{.Type}} {{if or ($.EmitJSONTags) ($.EmitDBTags)}}{{$.Q}}{{.Tag}}{{$.Q}}{{end}}
291+
{{- end}}
292+
}
293+
{{end}}
294+
295+
{{if .Ret.EmitStruct}}
296+
type {{.Ret.Type}} struct { {{- range .Ret.Struct.Fields}}
297+
{{.Name}} {{.Type}} {{if or ($.EmitJSONTags) ($.EmitDBTags)}}{{$.Q}}{{.Tag}}{{$.Q}}{{end}}
298+
{{- end}}
284299
}
285-
defer rows.Close()
286-
{{- if $.EmitEmptySlices}}
287-
items := []{{.Ret.Type}}{}
288-
{{else}}
289-
var items []{{.Ret.Type}}
300+
{{end}}
301+
302+
{{if eq .Cmd ":one"}}
303+
{{range .Comments}}//{{.}}
290304
{{end -}}
291-
for rows.Next() {
305+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ({{.Ret.Type}}, error) {
306+
row := q.db.QueryRow(ctx, {{.ConstantName}}, {{.Arg.Params}})
292307
var {{.Ret.Name}} {{.Ret.Type}}
293-
if err := rows.Scan({{.Ret.Scan}}); err != nil {
308+
err := row.Scan({{.Ret.Scan}})
309+
return {{.Ret.Name}}, err
310+
}
311+
{{end}}
312+
313+
{{if eq .Cmd ":many"}}
314+
{{range .Comments}}//{{.}}
315+
{{end -}}
316+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) ([]{{.Ret.Type}}, error) {
317+
rows, err := q.db.Query(ctx, {{.ConstantName}}, {{.Arg.Params}})
318+
if err != nil {
294319
return nil, err
295320
}
296-
items = append(items, {{.Ret.Name}})
321+
defer rows.Close()
322+
{{- if $.EmitEmptySlices}}
323+
items := []{{.Ret.Type}}{}
324+
{{else}}
325+
var items []{{.Ret.Type}}
326+
{{end -}}
327+
for rows.Next() {
328+
var {{.Ret.Name}} {{.Ret.Type}}
329+
if err := rows.Scan({{.Ret.Scan}}); err != nil {
330+
return nil, err
331+
}
332+
items = append(items, {{.Ret.Name}})
333+
}
334+
rows.Close()
335+
if err := rows.Err(); err != nil {
336+
return nil, err
337+
}
338+
return items, nil
297339
}
298-
if err := rows.Close(); err != nil {
299-
return nil, err
340+
{{end}}
341+
342+
{{if eq .Cmd ":exec"}}
343+
{{range .Comments}}//{{.}}
344+
{{end -}}
345+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) error {
346+
_, err := q.db.Exec(ctx, {{.ConstantName}}, {{.Arg.Params}})
347+
return err
300348
}
301-
if err := rows.Err(); err != nil {
302-
return nil, err
349+
{{end}}
350+
351+
{{if eq .Cmd ":execrows"}}
352+
{{range .Comments}}//{{.}}
353+
{{end -}}
354+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (int64, error) {
355+
{{- if $.EmitPreparedQueries}}
356+
result, err := q.exec(ctx, q.{{.FieldName}}, {{.ConstantName}}, {{.Arg.Params}})
357+
{{- else}}
358+
result, err := q.db.ExecContext(ctx, {{.ConstantName}}, {{.Arg.Params}})
359+
{{- end}}
360+
if err != nil {
361+
return 0, err
362+
}
363+
return result.RowsAffected()
303364
}
304-
return items, nil
305-
}
306-
{{end}}
307-
308-
{{if eq .Cmd ":exec"}}
309-
{{range .Comments}}//{{.}}
310-
{{end -}}
311-
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) error {
312-
{{- if $.EmitPreparedQueries}}
313-
_, err := q.exec(ctx, q.{{.FieldName}}, {{.ConstantName}}, {{.Arg.Params}})
314-
{{- else}}
315-
_, err := q.db.ExecContext(ctx, {{.ConstantName}}, {{.Arg.Params}})
316-
{{- end}}
317-
return err
318-
}
319-
{{end}}
320-
321-
{{if eq .Cmd ":execrows"}}
322-
{{range .Comments}}//{{.}}
323-
{{end -}}
324-
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (int64, error) {
325-
{{- if $.EmitPreparedQueries}}
326-
result, err := q.exec(ctx, q.{{.FieldName}}, {{.ConstantName}}, {{.Arg.Params}})
327-
{{- else}}
328-
result, err := q.db.ExecContext(ctx, {{.ConstantName}}, {{.Arg.Params}})
329-
{{- end}}
330-
if err != nil {
331-
return 0, err
365+
{{end}}
366+
367+
{{if eq .Cmd ":execresult"}}
368+
{{range .Comments}}//{{.}}
369+
{{end -}}
370+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (sql.Result, error) {
371+
{{- if $.EmitPreparedQueries}}
372+
return q.exec(ctx, q.{{.FieldName}}, {{.ConstantName}}, {{.Arg.Params}})
373+
{{- else}}
374+
return q.db.ExecContext(ctx, {{.ConstantName}}, {{.Arg.Params}})
375+
{{- end}}
332376
}
333-
return result.RowsAffected()
334-
}
377+
{{end}}
378+
{{end}}
379+
{{end}}
335380
{{end}}
336381
337-
{{if eq .Cmd ":execresult"}}
338-
{{range .Comments}}//{{.}}
339-
{{end -}}
340-
func (q *Queries) {{.MethodName}}(ctx context.Context, {{.Arg.Pair}}) (sql.Result, error) {
341-
{{- if $.EmitPreparedQueries}}
342-
return q.exec(ctx, q.{{.FieldName}}, {{.ConstantName}}, {{.Arg.Params}})
343-
{{- else}}
344-
return q.db.ExecContext(ctx, {{.ConstantName}}, {{.Arg.Params}})
345-
{{- end}}
346-
}
347-
{{end}}
348-
{{end}}
349-
{{end}}
350382
{{end}}
351383
`
352384

353385
type tmplCtx struct {
354-
Q string
355-
Package string
356-
Enums []Enum
357-
Structs []Struct
358-
GoQueries []Query
359-
Settings config.Config
386+
Q string
387+
Package string
388+
SQLLibrary string
389+
Enums []Enum
390+
Structs []Struct
391+
GoQueries []Query
392+
Settings config.Config
360393

361394
// TODO: Race conditions
362395
SourceName string
@@ -404,6 +437,7 @@ func generate(settings config.CombinedSettings, enums []Enum, structs []Struct,
404437
EmitDBTags: golang.EmitDBTags,
405438
EmitPreparedQueries: golang.EmitPreparedQueries,
406439
EmitEmptySlices: golang.EmitEmptySlices,
440+
SQLLibrary: golang.SQLLibrary,
407441
Q: "`",
408442
Package: golang.Package,
409443
GoQueries: queries,

internal/codegen/golang/imports.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,17 @@ func (i *importer) Imports(filename string) [][]ImportSpec {
103103
func (i *importer) dbImports() fileImports {
104104
std := []ImportSpec{
105105
{Path: "context"},
106-
{Path: "database/sql"},
107106
}
108-
if i.Settings.Go.EmitPreparedQueries {
109-
std = append(std, ImportSpec{Path: "fmt"})
107+
108+
switch i.Settings.Go.SQLLibrary {
109+
case "pgx/v4":
110+
std = append(std, ImportSpec{Path: "github.com/jackc/pgconn"})
111+
std = append(std, ImportSpec{Path: "github.com/jackc/pgx/v4"})
112+
default:
113+
if i.Settings.Go.EmitPreparedQueries {
114+
std = append(std, ImportSpec{Path: "fmt"})
115+
}
116+
std = append(std, ImportSpec{Path: "database/sql"})
110117
}
111118
return fileImports{Std: std}
112119
}

internal/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ type SQLGo struct {
115115
EmitPreparedQueries bool `json:"emit_prepared_queries" yaml:"emit_prepared_queries"`
116116
EmitExactTableNames bool `json:"emit_exact_table_names,omitempty" yaml:"emit_exact_table_names"`
117117
EmitEmptySlices bool `json:"emit_empty_slices,omitempty" yaml:"emit_empty_slices"`
118+
SQLLibrary string `json:"sql_library,omitempty" yaml:"sql_library"`
118119
Package string `json:"package" yaml:"package"`
119120
Out string `json:"out" yaml:"out"`
120121
Overrides []Override `json:"overrides,omitempty" yaml:"overrides"`

internal/config/v_one.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type v1PackageSettings struct {
2121
Path string `json:"path" yaml:"path"`
2222
Schema Paths `json:"schema" yaml:"schema"`
2323
Queries Paths `json:"queries" yaml:"queries"`
24+
SQLLibrary string `json:"sql_library" yaml:"sql_library"`
2425
EmitInterface bool `json:"emit_interface" yaml:"emit_interface"`
2526
EmitJSONTags bool `json:"emit_json_tags" yaml:"emit_json_tags"`
2627
EmitDBTags bool `json:"emit_db_tags" yaml:"emit_db_tags"`
@@ -109,6 +110,7 @@ func (c *V1GenerateSettings) Translate() Config {
109110
EmitPreparedQueries: pkg.EmitPreparedQueries,
110111
EmitExactTableNames: pkg.EmitExactTableNames,
111112
EmitEmptySlices: pkg.EmitEmptySlices,
113+
SQLLibrary: pkg.SQLLibrary,
112114
Package: pkg.Name,
113115
Out: pkg.Path,
114116
Overrides: pkg.Overrides,

0 commit comments

Comments
 (0)