Skip to content

Commit 3a2aad4

Browse files
committed
Allow for extra parameters to the queryType
Like `-- name: InsertMulti :exec multiple` and `-- name: Select :many key=group_id` issue #2353
1 parent 3e0fca0 commit 3a2aad4

File tree

11 files changed

+706
-143
lines changed

11 files changed

+706
-143
lines changed

internal/cmd/shim.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77
"github.com/kyleconroy/sqlc/internal/config"
88
"github.com/kyleconroy/sqlc/internal/config/convert"
99
"github.com/kyleconroy/sqlc/internal/info"
10+
"github.com/kyleconroy/sqlc/internal/metadata"
1011
"github.com/kyleconroy/sqlc/internal/plugin"
1112
"github.com/kyleconroy/sqlc/internal/sql/catalog"
1213
)
@@ -226,9 +227,18 @@ func pluginQueries(r *compiler.Result) []*plugin.Query {
226227
Name: q.InsertIntoTable.Name,
227228
}
228229
}
230+
var cmdParams *plugin.CmdParams
231+
if q.CmdParams != (metadata.CmdParams{}) {
232+
cmdParams = &plugin.CmdParams{
233+
ManyKey: q.CmdParams.ManyKey,
234+
InsertMultiple: q.CmdParams.InsertMultiple,
235+
NoInference: q.CmdParams.NoInference,
236+
}
237+
}
229238
out = append(out, &plugin.Query{
230239
Name: q.Name,
231240
Cmd: q.Cmd,
241+
CmdParams: cmdParams,
232242
Text: q.SQL,
233243
Comments: q.Comments,
234244
Columns: columns,

internal/compiler/parse.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
7070
if err := validate.In(c.catalog, raw); err != nil {
7171
return nil, err
7272
}
73-
name, cmd, err := metadata.Parse(strings.TrimSpace(rawSQL), c.parser.CommentSyntax())
73+
name, cmd, cmdParams, err := metadata.Parse(strings.TrimSpace(rawSQL), c.parser.CommentSyntax())
7474
if err != nil {
7575
return nil, err
7676
}
@@ -133,6 +133,7 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
133133
Columns: cols,
134134
SQL: trimmed,
135135
InsertIntoTable: table,
136+
CmdParams: cmdParams,
136137
}, nil
137138
}
138139

internal/compiler/query.go

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package compiler
22

33
import (
4+
"github.com/kyleconroy/sqlc/internal/metadata"
45
"github.com/kyleconroy/sqlc/internal/sql/ast"
56
)
67

@@ -39,12 +40,13 @@ type Column struct {
3940
}
4041

4142
type Query struct {
42-
SQL string
43-
Name string
44-
Cmd string // TODO: Pick a better name. One of: one, many, exec, execrows, copyFrom
45-
Columns []*Column
46-
Params []Parameter
47-
Comments []string
43+
SQL string
44+
Name string
45+
Cmd string // TODO: Pick a better name. One of: one, many, exec, execrows, copyFrom
46+
CmdParams metadata.CmdParams
47+
Columns []*Column
48+
Params []Parameter
49+
Comments []string
4850

4951
// XXX: Hack
5052
Filename string

internal/endtoend/testdata/codegen_json/gen/codegen.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62583,6 +62583,7 @@
6258362583
"text": "SELECT id, name, bio FROM authors\nWHERE id = $1 LIMIT 1",
6258462584
"name": "GetAuthor",
6258562585
"cmd": ":one",
62586+
"cmd_params": null,
6258662587
"columns": [
6258762588
{
6258862589
"name": "id",
@@ -62698,6 +62699,7 @@
6269862699
"text": "SELECT id, name, bio FROM authors\nORDER BY name",
6269962700
"name": "ListAuthors",
6270062701
"cmd": ":many",
62702+
"cmd_params": null,
6270162703
"columns": [
6270262704
{
6270362705
"name": "id",
@@ -62784,6 +62786,7 @@
6278462786
"text": "INSERT INTO authors (\n name, bio\n) VALUES (\n $1, $2\n)\nRETURNING id, name, bio",
6278562787
"name": "CreateAuthor",
6278662788
"cmd": ":one",
62789+
"cmd_params": null,
6278762790
"columns": [
6278862791
{
6278962792
"name": "id",
@@ -62931,6 +62934,7 @@
6293162934
"text": "DELETE FROM authors\nWHERE id = $1",
6293262935
"name": "DeleteAuthor",
6293362936
"cmd": ":exec",
62937+
"cmd_params": null,
6293462938
"columns": [],
6293562939
"params": [
6293662940
{

internal/endtoend/testdata/process_plugin_disabled/gen/codegen.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62583,6 +62583,7 @@
6258362583
"text": "SELECT id, name, bio FROM authors\nWHERE id = $1 LIMIT 1",
6258462584
"name": "GetAuthor",
6258562585
"cmd": ":one",
62586+
"cmd_params": null,
6258662587
"columns": [
6258762588
{
6258862589
"name": "id",
@@ -62698,6 +62699,7 @@
6269862699
"text": "SELECT id, name, bio FROM authors\nORDER BY name",
6269962700
"name": "ListAuthors",
6270062701
"cmd": ":many",
62702+
"cmd_params": null,
6270162703
"columns": [
6270262704
{
6270362705
"name": "id",
@@ -62784,6 +62786,7 @@
6278462786
"text": "INSERT INTO authors (\n name, bio\n) VALUES (\n $1, $2\n)\nRETURNING id, name, bio",
6278562787
"name": "CreateAuthor",
6278662788
"cmd": ":one",
62789+
"cmd_params": null,
6278762790
"columns": [
6278862791
{
6278962792
"name": "id",
@@ -62931,6 +62934,7 @@
6293162934
"text": "DELETE FROM authors\nWHERE id = $1",
6293262935
"name": "DeleteAuthor",
6293362936
"cmd": ":exec",
62937+
"cmd_params": null,
6293462938
"columns": [],
6293562939
"params": [
6293662940
{

internal/endtoend/testdata/process_plugin_sqlc_gen_json/gen/codegen.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62583,6 +62583,7 @@
6258362583
"text": "SELECT id, name, bio FROM authors\nWHERE id = $1 LIMIT 1",
6258462584
"name": "GetAuthor",
6258562585
"cmd": ":one",
62586+
"cmd_params": null,
6258662587
"columns": [
6258762588
{
6258862589
"name": "id",
@@ -62698,6 +62699,7 @@
6269862699
"text": "SELECT id, name, bio FROM authors\nORDER BY name",
6269962700
"name": "ListAuthors",
6270062701
"cmd": ":many",
62702+
"cmd_params": null,
6270162703
"columns": [
6270262704
{
6270362705
"name": "id",
@@ -62784,6 +62786,7 @@
6278462786
"text": "INSERT INTO authors (\n name, bio\n) VALUES (\n $1, $2\n)\nRETURNING id, name, bio",
6278562787
"name": "CreateAuthor",
6278662788
"cmd": ":one",
62789+
"cmd_params": null,
6278762790
"columns": [
6278862791
{
6278962792
"name": "id",
@@ -62931,6 +62934,7 @@
6293162934
"text": "DELETE FROM authors\nWHERE id = $1",
6293262935
"name": "DeleteAuthor",
6293362936
"cmd": ":exec",
62937+
"cmd_params": null,
6293462938
"columns": [],
6293562939
"params": [
6293662940
{

internal/metadata/meta.go

Lines changed: 42 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ const (
2525
CmdBatchOne = ":batchone"
2626
)
2727

28+
type CmdParams struct {
29+
ManyKey string
30+
InsertMultiple bool
31+
NoInference bool
32+
}
33+
2834
// A query name must be a valid Go identifier
2935
//
3036
// https://golang.org/ref/spec#Identifiers
@@ -44,7 +50,7 @@ func validateQueryName(name string) error {
4450
return nil
4551
}
4652

47-
func Parse(t string, commentStyle CommentSyntax) (string, string, error) {
53+
func Parse(t string, commentStyle CommentSyntax) (string, string, CmdParams, error) {
4854
for _, line := range strings.Split(t, "\n") {
4955
var prefix string
5056
if strings.HasPrefix(line, "--") {
@@ -76,30 +82,56 @@ func Parse(t string, commentStyle CommentSyntax) (string, string, error) {
7682
continue
7783
}
7884
if !strings.HasPrefix(rest, " name: ") {
79-
return "", "", fmt.Errorf("invalid metadata: %s", line)
85+
return "", "", CmdParams{}, fmt.Errorf("invalid metadata: %s", line)
8086
}
8187

8288
part := strings.Split(strings.TrimSpace(line), " ")
8389
if prefix == "/*" {
8490
part = part[:len(part)-1] // removes the trailing "*/" element
8591
}
8692
if len(part) == 2 {
87-
return "", "", fmt.Errorf("missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: %s", line)
88-
}
89-
if len(part) != 4 {
90-
return "", "", fmt.Errorf("invalid query comment: %s", line)
93+
return "", "", CmdParams{}, fmt.Errorf("missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: %s", line)
9194
}
9295
queryName := part[2]
9396
queryType := strings.TrimSpace(part[3])
9497
switch queryType {
9598
case CmdOne, CmdMany, CmdExec, CmdExecResult, CmdExecRows, CmdExecLastId, CmdCopyFrom, CmdBatchExec, CmdBatchMany, CmdBatchOne:
9699
default:
97-
return "", "", fmt.Errorf("invalid query type: %s", queryType)
100+
return "", "", CmdParams{}, fmt.Errorf("invalid query type: %s", queryType)
98101
}
99102
if err := validateQueryName(queryName); err != nil {
100-
return "", "", err
103+
return "", "", CmdParams{}, err
104+
}
105+
cmdParams, err := parseCmdParams(part[4:], queryType)
106+
if err != nil {
107+
return "", "", CmdParams{}, err
108+
}
109+
return queryName, queryType, cmdParams, nil
110+
}
111+
return "", "", CmdParams{}, nil
112+
}
113+
114+
func parseCmdParams(part []string, queryType string) (CmdParams, error) {
115+
var ret CmdParams
116+
for _, p := range part {
117+
if p == "multiple" {
118+
if queryType != CmdExec && queryType != CmdExecResult && queryType != CmdExecRows && queryType != CmdExecLastId {
119+
return ret, fmt.Errorf("query command parameter multiple is invalid for query type %s", queryType)
120+
}
121+
ret.InsertMultiple = true
122+
} else if p == "no-inference" {
123+
if queryType != CmdExec && queryType != CmdExecResult && queryType != CmdExecRows && queryType != CmdExecLastId {
124+
return ret, fmt.Errorf("query command parameter no-inference is invalid for query type %s", queryType)
125+
}
126+
ret.NoInference = true
127+
} else if strings.HasPrefix(p, "key=") {
128+
if queryType != CmdMany {
129+
return ret, fmt.Errorf("query command parameter %s is invalid for query type %s", p, queryType)
130+
}
131+
ret.ManyKey = strings.TrimPrefix(p, "key=")
132+
} else {
133+
return ret, fmt.Errorf("invalid query command parameter %q", p)
101134
}
102-
return queryName, queryType, nil
103135
}
104-
return "", "", nil
136+
return ret, nil
105137
}

internal/metadata/meta_test.go

Lines changed: 44 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package metadata
22

33
import "testing"
44

5-
func TestParseMetadata(t *testing.T) {
5+
func TestNonMetadata(t *testing.T) {
66

77
for _, query := range []string{
88
`-- name: CreateFoo, :one`,
@@ -17,7 +17,7 @@ func TestParseMetadata(t *testing.T) {
1717
"-- name:CreateFoo",
1818
`--name:CreateFoo :two`,
1919
} {
20-
if _, _, err := Parse(query, CommentSyntax{Dash: true}); err == nil {
20+
if _, _, _, err := Parse(query, CommentSyntax{Dash: true}); err == nil {
2121
t.Errorf("expected invalid metadata: %q", query)
2222
}
2323
}
@@ -27,21 +27,52 @@ func TestParseMetadata(t *testing.T) {
2727
`-- name comment`,
2828
`--name comment`,
2929
} {
30-
if _, _, err := Parse(query, CommentSyntax{Dash: true}); err != nil {
30+
if _, _, _, err := Parse(query, CommentSyntax{Dash: true}); err != nil {
3131
t.Errorf("expected valid comment: %q", query)
3232
}
3333
}
34+
}
3435

35-
query := `-- name: CreateFoo :one`
36-
queryName, queryType, err := Parse(query, CommentSyntax{Dash: true})
37-
if err != nil {
38-
t.Errorf("expected valid metadata: %q", query)
39-
}
40-
if queryName != "CreateFoo" {
41-
t.Errorf("incorrect queryName parsed: %q", query)
36+
func TestParse(t *testing.T) {
37+
tests := []struct {
38+
query string
39+
wantName string
40+
wantType string
41+
wantCmdParams CmdParams
42+
}{
43+
{
44+
query: "-- name: CreateFoo :one",
45+
wantName: "CreateFoo",
46+
wantType: CmdOne,
47+
},
48+
{
49+
query: "-- name: InsertMulti :exec multiple",
50+
wantName: "InsertMulti",
51+
wantType: CmdExec,
52+
wantCmdParams: CmdParams{InsertMultiple: true},
53+
},
54+
{
55+
query: "-- name: SelectKey :many key=group_id",
56+
wantName: "SelectKey",
57+
wantType: CmdMany,
58+
wantCmdParams: CmdParams{ManyKey: "group_id"},
59+
},
4260
}
43-
if queryType != CmdOne {
44-
t.Errorf("incorrect queryType parsed: %q", query)
61+
for _, tc := range tests {
62+
t.Run(tc.query, func(t *testing.T) {
63+
name, queryType, cmdParams, err := Parse(tc.query, CommentSyntax{Dash: true})
64+
if err != nil {
65+
t.Fatalf("Parse failed: %v", err)
66+
}
67+
if name != tc.wantName {
68+
t.Errorf("unexpected name: got %q; want %q", name, tc.wantName)
69+
}
70+
if queryType != tc.wantType {
71+
t.Errorf("unexpected queryType: got %q; want %q", queryType, tc.wantType)
72+
}
73+
if cmdParams != tc.wantCmdParams {
74+
t.Errorf("unexpected cmdParams: got %#v; want %#v", cmdParams, tc.wantCmdParams)
75+
}
76+
})
4577
}
46-
4778
}

0 commit comments

Comments
 (0)