snapshot of https://github.com/sqlc-dev/sqlc.git (main, 2026-09-16; blobs > 131072B omitted)
Some checks failed
kotlin / test (push) Has been skipped
python / test (push) Has been skipped
typescript / test (push) Has been skipped
go / build darwin/amd64 (push) Has been cancelled
go / build linux/amd64 (push) Has been cancelled
go / build windows/amd64 (push) Has been cancelled
go / build darwin/arm64 (push) Has been cancelled
go / build linux/arm64 (push) Has been cancelled
go / build windows/arm64 (push) Has been cancelled
go / test (push) Has been cancelled
go / vuln_check (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-16 02:17:34 +05:00
commit 0f4df23290
7340 changed files with 238743 additions and 0 deletions

172
internal/metadata/meta.go Normal file
View File

@@ -0,0 +1,172 @@
package metadata
import (
"bufio"
"fmt"
"github.com/sqlc-dev/sqlc/internal/constants"
"strings"
"unicode"
"github.com/sqlc-dev/sqlc/internal/source"
)
type CommentSyntax source.CommentSyntax
type Metadata struct {
Name string
Cmd string
Comments []string
Params map[string]string
Flags map[string]bool
// RuleSkiplist contains the names of rules to disable vetting for.
// If the map is empty, but the disable vet flag is specified, then all rules are ignored.
RuleSkiplist map[string]struct{}
Filename string
}
const (
CmdExec = ":exec"
CmdExecResult = ":execresult"
CmdExecRows = ":execrows"
CmdExecLastId = ":execlastid"
CmdMany = ":many"
CmdOne = ":one"
CmdCopyFrom = ":copyfrom"
CmdBatchExec = ":batchexec"
CmdBatchMany = ":batchmany"
CmdBatchOne = ":batchone"
)
// A query name must be a valid Go identifier
//
// https://golang.org/ref/spec#Identifiers
func validateQueryName(name string) error {
if len(name) == 0 {
return fmt.Errorf("invalid query name: %q", name)
}
for i, c := range name {
isLetter := unicode.IsLetter(c) || c == '_'
isDigit := unicode.IsDigit(c)
if i == 0 && !isLetter {
return fmt.Errorf("invalid query name %q", name)
} else if !(isLetter || isDigit) {
return fmt.Errorf("invalid query name %q", name)
}
}
return nil
}
func ParseQueryNameAndType(t string, commentStyle CommentSyntax) (string, string, error) {
for line := range strings.SplitSeq(t, "\n") {
var prefix string
if strings.HasPrefix(line, "--") {
if !commentStyle.Dash {
continue
}
prefix = "--"
}
if strings.HasPrefix(line, "/*") {
if !commentStyle.SlashStar {
continue
}
prefix = "/*"
}
if strings.HasPrefix(line, "#") {
if !commentStyle.Hash {
continue
}
prefix = "#"
}
if prefix == "" {
continue
}
rest := line[len(prefix):]
if !strings.HasPrefix(strings.TrimSpace(rest), "name") {
continue
}
if !strings.Contains(rest, ":") {
continue
}
if !strings.HasPrefix(rest, " name: ") {
return "", "", fmt.Errorf("invalid metadata: %s", line)
}
part := strings.Split(strings.TrimSpace(line), " ")
if prefix == "/*" {
part = part[:len(part)-1] // removes the trailing "*/" element
}
if len(part) == 3 {
return "", "", fmt.Errorf("missing query type [':one', ':many', ':exec', ':execrows', ':execlastid', ':execresult', ':copyfrom', 'batchexec', 'batchmany', 'batchone']: %s", line)
}
if len(part) != 4 {
return "", "", fmt.Errorf("invalid query comment: %s", line)
}
queryName := part[2]
queryType := strings.TrimSpace(part[3])
switch queryType {
case CmdOne, CmdMany, CmdExec, CmdExecResult, CmdExecRows, CmdExecLastId, CmdCopyFrom, CmdBatchExec, CmdBatchMany, CmdBatchOne:
default:
return "", "", fmt.Errorf("invalid query type: %s", queryType)
}
if err := validateQueryName(queryName); err != nil {
return "", "", err
}
return queryName, queryType, nil
}
return "", "", nil
}
// ParseCommentFlags processes the comments provided with queries to determine the metadata params, flags and rules to skip.
// All flags in query comments are prefixed with `@`, e.g. @param, @@sqlc-vet-disable.
func ParseCommentFlags(comments []string) (map[string]string, map[string]bool, map[string]struct{}, error) {
params := make(map[string]string)
flags := make(map[string]bool)
ruleSkiplist := make(map[string]struct{})
for _, line := range comments {
s := bufio.NewScanner(strings.NewReader(line))
s.Split(bufio.ScanWords)
s.Scan()
token := s.Text()
if !strings.HasPrefix(token, "@") {
continue
}
switch token {
case constants.QueryFlagParam:
s.Scan()
name := s.Text()
var rest []string
for s.Scan() {
paramToken := s.Text()
rest = append(rest, paramToken)
}
params[name] = strings.Join(rest, " ")
case constants.QueryFlagSqlcVetDisable:
flags[token] = true
// Vet rules can all be disabled in the same line or split across lines .i.e.
// /* @sqlc-vet-disable sqlc/db-prepare delete-without-where */
// is equivalent to:
// /* @sqlc-vet-disable sqlc/db-prepare */
// /* @sqlc-vet-disable delete-without-where */
for s.Scan() {
ruleSkiplist[s.Text()] = struct{}{}
}
default:
flags[token] = true
}
if s.Err() != nil {
return params, flags, ruleSkiplist, s.Err()
}
}
return params, flags, ruleSkiplist, nil
}

View File

@@ -0,0 +1,182 @@
package metadata
import (
"testing"
)
func TestParseQueryNameAndType(t *testing.T) {
for _, query := range []string{
`-- name: CreateFoo, :one`,
`-- name: 9Foo_, :one`,
`-- name: CreateFoo :two`,
`-- name: CreateFoo`,
`-- name: CreateFoo :one something`,
`-- name: `,
`--name: CreateFoo :one`,
`--name CreateFoo :one`,
`--name: CreateFoo :two`,
"-- name:CreateFoo",
`--name:CreateFoo :two`,
} {
if _, _, err := ParseQueryNameAndType(query, CommentSyntax{Dash: true}); err == nil {
t.Errorf("expected invalid metadata: %q", query)
}
}
for _, query := range []string{
`-- some comment`,
`-- name comment`,
`--name comment`,
} {
if _, _, err := ParseQueryNameAndType(query, CommentSyntax{Dash: true}); err != nil {
t.Errorf("expected valid comment: %q", query)
}
}
for query, cs := range map[string]CommentSyntax{
`-- name: CreateFoo :one`: {Dash: true},
`# name: CreateFoo :one`: {Hash: true},
`/* name: CreateFoo :one */`: {SlashStar: true},
} {
queryName, queryCmd, err := ParseQueryNameAndType(query, cs)
if err != nil {
t.Errorf("expected valid metadata: %q", query)
}
if queryName != "CreateFoo" {
t.Errorf("incorrect queryName parsed: (%q) %q", queryName, query)
}
if queryCmd != CmdOne {
t.Errorf("incorrect queryCmd parsed: (%q) %q", queryCmd, query)
}
}
}
func TestParseQueryParams(t *testing.T) {
for _, comments := range [][]string{
{
" name: CreateFoo :one",
" @param foo_id UUID",
},
{
" name: CreateFoo :one ",
" @param foo_id UUID ",
},
{
" name: CreateFoo :one",
"@param foo_id UUID",
" invalid",
},
{
" name: CreateFoo :one",
" @invalid",
" @param foo_id UUID",
},
{
" name: GetFoos :many ",
" @param foo_id UUID ",
" @param @invalid UUID ",
},
} {
params, _, _, err := ParseCommentFlags(comments)
if err != nil {
t.Errorf("expected comments to parse, got err: %s", err)
}
pt, ok := params["foo_id"]
if !ok {
t.Errorf("expected param not found")
}
if pt != "UUID" {
t.Error("unexpected param metadata:", pt)
}
_, ok = params["invalid"]
if ok {
t.Errorf("unexpected param found")
}
}
}
func TestParseQueryFlags(t *testing.T) {
for _, comments := range [][]string{
{
" name: CreateFoo :one",
" @flag-foo",
},
{
" name: CreateFoo :one ",
"@flag-foo ",
},
{
" name: CreateFoo :one",
" @flag-foo @flag-bar",
},
{
" name: GetFoos :many",
" @param @flag-bar UUID",
" @flag-foo",
},
{
" name: GetFoos :many",
" @flag-foo",
" @param @flag-bar UUID",
},
} {
_, flags, _, err := ParseCommentFlags(comments)
if err != nil {
t.Errorf("expected comments to parse, got err: %s", err)
}
if !flags["@flag-foo"] {
t.Errorf("expected flag not found")
}
if flags["@flag-bar"] {
t.Errorf("unexpected flag found")
}
}
}
func TestParseQueryRuleSkiplist(t *testing.T) {
for _, comments := range [][]string{
{
" name: CreateFoo :one",
" @sqlc-vet-disable sqlc/db-prepare delete-without-where ",
},
{
" name: CreateFoo :one ",
" @sqlc-vet-disable sqlc/db-prepare ",
" @sqlc-vet-disable delete-without-where ",
},
{
" name: CreateFoo :one",
" @sqlc-vet-disable sqlc/db-prepare ",
" update-without where",
" @sqlc-vet-disable delete-without-where ",
},
} {
_, flags, ruleSkiplist, err := ParseCommentFlags(comments)
if err != nil {
t.Errorf("expected comments to parse, got err: %s", err)
}
if !flags["@sqlc-vet-disable"] {
t.Errorf("expected @sqlc-vet-disable flag not found")
}
if _, ok := ruleSkiplist["sqlc/db-prepare"]; !ok {
t.Errorf("expected rule not found in skiplist")
}
if _, ok := ruleSkiplist["delete-without-where"]; !ok {
t.Errorf("expected rule not found in skiplist")
}
if _, ok := ruleSkiplist["update-without-where"]; ok {
t.Errorf("unexpected rule found in skiplist")
}
}
}