Skip to content

Commit 9c16a4f

Browse files
committed
Support :many key=group_id to return a map instead of a slice
issue #2353
1 parent 3a2aad4 commit 9c16a4f

File tree

8 files changed

+148
-4
lines changed

8 files changed

+148
-4
lines changed

internal/codegen/golang/query.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,8 @@ type Query struct {
200200
SourceName string
201201
Ret QueryValue
202202
Arg QueryValue
203+
ManyKey string // Taken from CmdParams.ManyKey, the map-key for :many. If empty a slice should be returned.
204+
ManyKeyType string // The Go type of ManyKey
203205
// Used for :copyfrom
204206
Table *plugin.Identifier
205207
}
@@ -219,3 +221,23 @@ func (q Query) TableIdentifier() string {
219221
}
220222
return "[]string{" + strings.Join(escapedNames, ", ") + "}"
221223
}
224+
225+
func (v Query) DefineRetTypeMultiple() string {
226+
if v.ManyKey != "" {
227+
return "map[" + v.ManyKeyType + "]" + v.Ret.DefineType()
228+
}
229+
return "[]" + v.Ret.DefineType()
230+
}
231+
232+
func (v Query) HasManyKey() bool {
233+
return v.ManyKey != ""
234+
}
235+
236+
func (v Query) ManyKeyField() string {
237+
for _, f := range v.Ret.Struct.Fields {
238+
if f.DBName == v.ManyKey {
239+
return v.Ret.Name + "." + f.Name
240+
}
241+
}
242+
panic("couldn't find :many-key in struct fields")
243+
}

internal/codegen/golang/result.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,9 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error)
247247
}
248248

249249
if len(query.Columns) == 1 && query.Columns[0].EmbedTable == nil {
250+
if query.CmdParams.ManyKey != "" {
251+
return nil, fmt.Errorf(":many key=%s query %s has only one column", query.CmdParams.ManyKey, query.Name)
252+
}
250253
c := query.Columns[0]
251254
name := columnName(c, 0)
252255
if c.IsFuncCall {
@@ -305,6 +308,18 @@ func buildQueries(req *plugin.CodeGenRequest, structs []Struct) ([]Query, error)
305308
SQLDriver: sqlpkg,
306309
EmitPointer: req.Settings.Go.EmitResultStructPointers,
307310
}
311+
if query.CmdParams.GetManyKey() != "" {
312+
gq.ManyKey = query.CmdParams.GetManyKey()
313+
for _, c := range gs.Fields {
314+
if c.DBName == gq.ManyKey {
315+
gq.ManyKeyType = c.Type
316+
break
317+
}
318+
}
319+
if gq.ManyKeyType == "" {
320+
return nil, fmt.Errorf("can not find key column %q in query %s", gq.ManyKey, gq.MethodName)
321+
}
322+
}
308323
}
309324

310325
qs = append(qs, gq)

internal/codegen/golang/templates/stdlib/queryCode.tmpl

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,27 @@ func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}
3535
{{if eq .Cmd ":many"}}
3636
{{range .Comments}}//{{.}}
3737
{{end -}}
38-
func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) ([]{{.Ret.DefineType}}, error) {
38+
func (q *Queries) {{.MethodName}}(ctx context.Context, {{ dbarg }} {{.Arg.Pair}}) ({{.DefineRetTypeMultiple}}, error) {
3939
{{- template "queryCodeStdExec" . }}
4040
if err != nil {
4141
return nil, err
4242
}
4343
defer rows.Close()
44-
{{- if $.EmitEmptySlices}}
45-
items := []{{.Ret.DefineType}}{}
44+
{{- if (or $.EmitEmptySlices .HasManyKey)}}
45+
items := {{.DefineRetTypeMultiple}}{}
4646
{{else}}
47-
var items []{{.Ret.DefineType}}
47+
var items {{.DefineRetTypeMultiple}}
4848
{{end -}}
4949
for rows.Next() {
5050
var {{.Ret.Name}} {{.Ret.Type}}
5151
if err := rows.Scan({{.Ret.Scan}}); err != nil {
5252
return nil, err
5353
}
54+
{{- if .HasManyKey}}
55+
items[{{.ManyKeyField}}] = {{.Ret.ReturnName}}
56+
{{else}}
5457
items = append(items, {{.Ret.ReturnName}})
58+
{{end -}}
5559
}
5660
if err := rows.Close(); err != nil {
5761
return nil, err

internal/endtoend/testdata/manykey/stdlib/go/db.go

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/manykey/stdlib/go/models.go

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/endtoend/testdata/manykey/stdlib/go/query.sql.go

Lines changed: 42 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CREATE TABLE foo (
2+
group_id INT NOT NULL,
3+
score INT NOT NULL
4+
);
5+
6+
-- name: SelectScoreSums :many key=group_id
7+
SELECT group_id, SUM(score) FROM foo GROUP BY group_id;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"version": "1",
3+
"packages": [
4+
{
5+
"path": "go",
6+
"name": "querytest",
7+
"schema": "query.sql",
8+
"queries": "query.sql"
9+
}
10+
]
11+
}

0 commit comments

Comments
 (0)