Skip to content

Commit d018aaa

Browse files
committed
Include query name and command in parse output
Each parsed statement now reports its sqlc query name and command, extracted from the "-- name:" annotation using the dialect's comment syntax. The fields are omitted for statements without an annotation (e.g. schema DDL). The statement AST is nested under an "ast" key.
1 parent 3715ae6 commit d018aaa

1 file changed

Lines changed: 54 additions & 13 deletions

File tree

internal/cmd/parse.go

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,44 @@ import (
55
"fmt"
66
"io"
77
"os"
8+
"strings"
89

910
"github.com/spf13/cobra"
1011

1112
"github.com/sqlc-dev/sqlc/internal/engine/clickhouse"
1213
"github.com/sqlc-dev/sqlc/internal/engine/dolphin"
1314
"github.com/sqlc-dev/sqlc/internal/engine/postgresql"
1415
"github.com/sqlc-dev/sqlc/internal/engine/sqlite"
16+
"github.com/sqlc-dev/sqlc/internal/metadata"
17+
"github.com/sqlc-dev/sqlc/internal/source"
1518
"github.com/sqlc-dev/sqlc/internal/sql/ast"
1619
)
1720

21+
// dialectParser is the subset of the engine parsers that the parse command
22+
// needs: parsing SQL into statements and reporting the dialect's comment syntax
23+
// (used to extract the sqlc query name and command).
24+
type dialectParser interface {
25+
Parse(io.Reader) ([]ast.Statement, error)
26+
CommentSyntax() source.CommentSyntax
27+
}
28+
29+
// parsedStatement is the JSON representation of a single parsed statement. The
30+
// name and cmd are extracted from the sqlc query annotation (e.g.
31+
// "-- name: GetAuthor :one") and are omitted when the statement has none.
32+
type parsedStatement struct {
33+
Name string `json:"name,omitempty"`
34+
Cmd string `json:"cmd,omitempty"`
35+
AST *ast.RawStmt `json:"ast"`
36+
}
37+
1838
var parseCmd = &cobra.Command{
1939
Use: "parse [file]",
2040
Short: "Parse SQL and output the AST as JSON",
2141
Long: `Parse SQL from a file or stdin and output the abstract syntax tree as JSON.
2242
43+
Each statement is reported with its sqlc query name and command (when the
44+
statement carries a "-- name:" annotation) alongside the AST.
45+
2346
Examples:
2447
# Parse a SQL file with PostgreSQL dialect
2548
sqlc parse --dialect postgresql schema.sql
@@ -63,38 +86,56 @@ Examples:
6386
input = cmd.InOrStdin()
6487
}
6588

66-
// Parse SQL based on dialect
67-
var stmts []ast.Statement
89+
// Select the parser for the requested dialect
90+
var parser dialectParser
6891
switch dialect {
6992
case "postgresql", "postgres", "pg":
70-
parser := postgresql.NewParser()
71-
stmts, err = parser.Parse(input)
93+
parser = postgresql.NewParser()
7294
case "mysql":
73-
parser := dolphin.NewParser()
74-
stmts, err = parser.Parse(input)
95+
parser = dolphin.NewParser()
7596
case "sqlite":
76-
parser := sqlite.NewParser()
77-
stmts, err = parser.Parse(input)
97+
parser = sqlite.NewParser()
7898
case "clickhouse":
79-
parser := clickhouse.NewParser()
80-
stmts, err = parser.Parse(input)
99+
parser = clickhouse.NewParser()
81100
default:
82101
return fmt.Errorf("unsupported dialect: %s (use postgresql, mysql, sqlite, or clickhouse)", dialect)
83102
}
103+
104+
// Read the full source so each statement's name and command can be
105+
// extracted from its annotation comment.
106+
src, err := io.ReadAll(input)
107+
if err != nil {
108+
return fmt.Errorf("failed to read input: %w", err)
109+
}
110+
111+
stmts, err := parser.Parse(strings.NewReader(string(src)))
84112
if err != nil {
85113
return fmt.Errorf("parse error: %w", err)
86114
}
87115

116+
commentSyntax := metadata.CommentSyntax(parser.CommentSyntax())
117+
88118
// Output the AST as a single JSON document
89-
raws := make([]*ast.RawStmt, 0, len(stmts))
119+
out := make([]parsedStatement, 0, len(stmts))
90120
for _, stmt := range stmts {
91-
raws = append(raws, stmt.Raw)
121+
ps := parsedStatement{AST: stmt.Raw}
122+
rawSQL, err := source.Pluck(string(src), stmt.Raw.StmtLocation, stmt.Raw.StmtLen)
123+
if err != nil {
124+
return fmt.Errorf("failed to read statement source: %w", err)
125+
}
126+
name, cmd, err := metadata.ParseQueryNameAndType(rawSQL, commentSyntax)
127+
if err != nil {
128+
return fmt.Errorf("failed to parse query annotation: %w", err)
129+
}
130+
ps.Name = name
131+
ps.Cmd = cmd
132+
out = append(out, ps)
92133
}
93134

94135
stdout := cmd.OutOrStdout()
95136
encoder := json.NewEncoder(stdout)
96137
encoder.SetIndent("", " ")
97-
if err := encoder.Encode(raws); err != nil {
138+
if err := encoder.Encode(out); err != nil {
98139
return fmt.Errorf("failed to encode AST: %w", err)
99140
}
100141

0 commit comments

Comments
 (0)