Skip to content

Commit b06ee14

Browse files
feat(compiler): Parse query parameter metadata from comments (#2850)
* feat(compiler): Parse query parameter metadata from comments * update comment stripping, fix a test * parse `@param` name correctly * add a test for metadata param parsing * use a word scanner for flag and param comment line parsing * forgot that I partially cleaned comments already * slightly more useful metadata test output * drop unnecessary metadata test cases * walk back changes, implement comment cleaning in source package * cleanup * simplify diff * ensure at least one test case for parsing @whatever without a leading space
1 parent 0cfadb0 commit b06ee14

File tree

15 files changed

+228
-71
lines changed

15 files changed

+228
-71
lines changed

internal/cmd/shim.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -209,13 +209,13 @@ func pluginQueries(r *compiler.Result) []*plugin.Query {
209209
}
210210
}
211211
out = append(out, &plugin.Query{
212-
Name: q.Name,
213-
Cmd: q.Cmd,
212+
Name: q.Metadata.Name,
213+
Cmd: q.Metadata.Cmd,
214214
Text: q.SQL,
215-
Comments: q.Comments,
215+
Comments: q.Metadata.Comments,
216216
Columns: columns,
217217
Params: params,
218-
Filename: q.Filename,
218+
Filename: q.Metadata.Filename,
219219
InsertIntoTable: iit,
220220
})
221221
}

internal/cmd/vet.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ func (c *checker) checkSQL(ctx context.Context, s config.SQL) error {
545545
req := codeGenRequest(result, combo)
546546
cfg := vetConfig(req)
547547
for i, query := range req.Queries {
548-
if result.Queries[i].Flags[QueryFlagSqlcVetDisable] {
548+
if result.Queries[i].Metadata.Flags[QueryFlagSqlcVetDisable] {
549549
if debug.Active {
550550
log.Printf("Skipping vet rules for query: %s\n", query.Name)
551551
}

internal/compiler/compile.go

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ import (
88
"path/filepath"
99
"strings"
1010

11-
"github.com/sqlc-dev/sqlc/internal/metadata"
1211
"github.com/sqlc-dev/sqlc/internal/migrations"
1312
"github.com/sqlc-dev/sqlc/internal/multierr"
1413
"github.com/sqlc-dev/sqlc/internal/opts"
14+
"github.com/sqlc-dev/sqlc/internal/source"
1515
"github.com/sqlc-dev/sqlc/internal/sql/ast"
1616
"github.com/sqlc-dev/sqlc/internal/sql/sqlerr"
1717
"github.com/sqlc-dev/sqlc/internal/sql/sqlpath"
@@ -20,7 +20,7 @@ import (
2020
// TODO: Rename this interface Engine
2121
type Parser interface {
2222
Parse(io.Reader) ([]ast.Statement, error)
23-
CommentSyntax() metadata.CommentSyntax
23+
CommentSyntax() source.CommentSyntax
2424
IsReservedKeyword(string) bool
2525
}
2626

@@ -90,14 +90,15 @@ func (c *Compiler) parseQueries(o opts.Parser) (*Result, error) {
9090
merr.Add(filename, src, loc, err)
9191
continue
9292
}
93-
if query.Name != "" {
94-
if _, exists := set[query.Name]; exists {
95-
merr.Add(filename, src, stmt.Raw.Pos(), fmt.Errorf("duplicate query name: %s", query.Name))
93+
queryName := query.Metadata.Name
94+
if queryName != "" {
95+
if _, exists := set[queryName]; exists {
96+
merr.Add(filename, src, stmt.Raw.Pos(), fmt.Errorf("duplicate query name: %s", queryName))
9697
continue
9798
}
98-
set[query.Name] = struct{}{}
99+
set[queryName] = struct{}{}
99100
}
100-
query.Filename = filepath.Base(filename)
101+
query.Metadata.Filename = filepath.Base(filename)
101102
if query != nil {
102103
q = append(q, query)
103104
}

internal/compiler/parse.go

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,31 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
4343
return nil, errors.New("missing semicolon at end of file")
4444
}
4545

46-
name, cmd, err := metadata.ParseQueryNameAndType(strings.TrimSpace(rawSQL), c.parser.CommentSyntax())
46+
name, cmd, err := metadata.ParseQueryNameAndType(rawSQL, metadata.CommentSyntax(c.parser.CommentSyntax()))
4747
if err != nil {
4848
return nil, err
4949
}
50+
5051
if err := validate.Cmd(raw.Stmt, name, cmd); err != nil {
5152
return nil, err
5253
}
5354

55+
md := metadata.Metadata{
56+
Name: name,
57+
Cmd: cmd,
58+
}
59+
60+
// TODO eventually can use this for name and type/cmd parsing too
61+
cleanedComments, err := source.CleanedComments(rawSQL, c.parser.CommentSyntax())
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
md.Params, md.Flags, err = metadata.ParseParamsAndFlags(cleanedComments)
67+
if err != nil {
68+
return nil, err
69+
}
70+
5471
var anlys *analysis
5572
if c.analyzer != nil {
5673
// TODO: Handle panics
@@ -90,17 +107,11 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query,
90107
return nil, err
91108
}
92109

93-
flags, err := metadata.ParseQueryFlags(comments)
94-
if err != nil {
95-
return nil, err
96-
}
110+
md.Comments = comments
97111

98112
return &Query{
99113
RawStmt: raw,
100-
Cmd: cmd,
101-
Comments: comments,
102-
Name: name,
103-
Flags: flags,
114+
Metadata: md,
104115
Params: anlys.Parameters,
105116
Columns: anlys.Columns,
106117
SQL: trimmed,

internal/compiler/query.go

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

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

@@ -41,15 +42,9 @@ type Column struct {
4142

4243
type Query struct {
4344
SQL string
44-
Name string
45-
Cmd string // TODO: Pick a better name. One of: one, many, exec, execrows, copyFrom
46-
Flags map[string]bool
45+
Metadata metadata.Metadata
4746
Columns []*Column
4847
Params []Parameter
49-
Comments []string
50-
51-
// XXX: Hack
52-
Filename string
5348

5449
// Needed for CopyFrom
5550
InsertIntoTable *ast.TableName

internal/endtoend/testdata/comment_syntax/mysql/go/query.sql.go

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

internal/endtoend/testdata/invalid_queries_foo/pgx/v4/stderr.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# package querytest
2-
query.sql:1:1: invalid query comment: -- name: ListFoos
2+
query.sql:1:1: missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: -- name: ListFoos
33
query.sql:5:1: invalid query comment: -- name: ListFoos :one :many
44
query.sql:8:1: invalid query type: :two
55
query.sql:11:1: query "DeleteFoo" specifies parameter ":one" without containing a RETURNING clause

internal/endtoend/testdata/invalid_queries_foo/pgx/v5/stderr.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# package querytest
2-
query.sql:1:1: invalid query comment: -- name: ListFoos
2+
query.sql:1:1: missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: -- name: ListFoos
33
query.sql:5:1: invalid query comment: -- name: ListFoos :one :many
44
query.sql:8:1: invalid query type: :two
55
query.sql:11:1: query "DeleteFoo" specifies parameter ":one" without containing a RETURNING clause

internal/endtoend/testdata/invalid_queries_foo/stdlib/stderr.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# package querytest
2-
query.sql:1:1: invalid query comment: -- name: ListFoos
2+
query.sql:1:1: missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: -- name: ListFoos
33
query.sql:5:1: invalid query comment: -- name: ListFoos :one :many
44
query.sql:8:1: invalid query type: :two
55
query.sql:11:1: query "DeleteFoo" specifies parameter ":one" without containing a RETURNING clause

internal/engine/dolphin/parse.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import (
1010
"github.com/pingcap/tidb/parser"
1111
_ "github.com/pingcap/tidb/parser/test_driver"
1212

13-
"github.com/sqlc-dev/sqlc/internal/metadata"
13+
"github.com/sqlc-dev/sqlc/internal/source"
1414
"github.com/sqlc-dev/sqlc/internal/sql/ast"
1515
"github.com/sqlc-dev/sqlc/internal/sql/sqlerr"
1616
)
@@ -86,8 +86,8 @@ func (p *Parser) Parse(r io.Reader) ([]ast.Statement, error) {
8686
}
8787

8888
// https://dev.mysql.com/doc/refman/8.0/en/comments.html
89-
func (p *Parser) CommentSyntax() metadata.CommentSyntax {
90-
return metadata.CommentSyntax{
89+
func (p *Parser) CommentSyntax() source.CommentSyntax {
90+
return source.CommentSyntax{
9191
Dash: true,
9292
SlashStar: true,
9393
Hash: true,

0 commit comments

Comments
 (0)