diff --git a/examples/authors/sqlc.json b/examples/authors/sqlc.json index 303e2b03a3..29ceb3ef2d 100644 --- a/examples/authors/sqlc.json +++ b/examples/authors/sqlc.json @@ -5,6 +5,9 @@ "schema": "postgresql/schema.sql", "queries": "postgresql/query.sql", "engine": "postgresql", + "database": { + "url": "'postgresql://%s:%s@%s:%s/%s'.format([env.PG_USER, env.PG_PASSWORD, env.PG_HOST, env.PG_PORT, env.PG_DATABASE])" + }, "gen": { "go": { "package": "authors", diff --git a/go.mod b/go.mod index d0fe96e0b4..2cec9d1909 100644 --- a/go.mod +++ b/go.mod @@ -8,9 +8,11 @@ require ( github.com/cubicdaiya/gonp v1.0.4 github.com/davecgh/go-spew v1.1.1 github.com/go-sql-driver/mysql v1.7.1 + github.com/google/cel-go v0.16.0 github.com/google/go-cmp v0.5.9 github.com/jackc/pgconn v1.14.0 github.com/jackc/pgx/v4 v4.18.1 + github.com/jackc/pgx/v5 v5.4.1 github.com/jinzhu/inflection v1.0.0 github.com/lib/pq v1.10.9 github.com/mattn/go-sqlite3 v1.14.17 @@ -24,6 +26,11 @@ require ( gopkg.in/yaml.v3 v3.0.1 ) +require ( + github.com/rogpeppe/go-internal v1.10.0 // indirect + github.com/stoewer/go-strcase v1.2.0 // indirect +) + require ( github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect github.com/golang/protobuf v1.5.3 // indirect @@ -42,10 +49,10 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.7.0 // indirect go.uber.org/zap v1.19.1 // indirect - golang.org/x/crypto v0.6.0 // indirect + golang.org/x/crypto v0.9.0 // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect - golang.org/x/net v0.9.0 // indirect - golang.org/x/sys v0.7.0 // indirect + golang.org/x/net v0.10.0 // indirect + golang.org/x/sys v0.8.0 // indirect golang.org/x/text v0.9.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect diff --git a/go.sum b/go.sum index f4811cefa9..5926d85c7e 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,8 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/cel-go v0.16.0 h1:DG9YQ8nFCFXAs/FDDwBxmL1tpKNrdlGUM9U3537bX/Y= +github.com/google/cel-go v0.16.0/go.mod h1:HXZKzB0LXqer5lHHgfWAnlYwJaQBDKMjxjulNQzhwhY= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= @@ -90,6 +92,8 @@ github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQ github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= github.com/jackc/pgx/v4 v4.18.1 h1:YP7G1KABtKpB5IHrO9vYwSrCOhs7p3uqhvhhQBptya0= github.com/jackc/pgx/v4 v4.18.1/go.mod h1:FydWkUyadDmdNH/mHnGob881GawxeEm7TcMCzkb+qQE= +github.com/jackc/pgx/v5 v5.4.1 h1:oKfB/FhuVtit1bBM3zNRRsZ925ZkMN3HXL+LgLUM9lE= +github.com/jackc/pgx/v5 v5.4.1/go.mod h1:q6iHT8uDNXWiFNOlRqJzBTaSH3+2xCXkokxHZC5qWFY= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -100,6 +104,7 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= @@ -117,7 +122,6 @@ github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/pganalyze/pg_query_go/v4 v4.2.1 h1:id/vuyIQccb9f6Yx3pzH5l4QYrxE3v6/m8RPlgMrprc= github.com/pganalyze/pg_query_go/v4 v4.2.1/go.mod h1:aEkDNOXNM5j0YGzaAapwJ7LB3dLNj+bvbWcLv1hOVqA= github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= @@ -137,6 +141,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qq github.com/riza-io/grpc-go v0.2.0 h1:2HxQKFVE7VuYstcJ8zqpN84VnAoJ4dCL6YFhJewNcHQ= github.com/riza-io/grpc-go v0.2.0/go.mod h1:2bDvR9KkKC3KhtlSHfR3dAXjUMT86kg4UfWFyVGWqi8= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= @@ -151,6 +157,8 @@ github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stoewer/go-strcase v1.2.0 h1:Z2iHWqGXH00XYgqDmNgQbIBxf3wrNq0F3feEy0ainaU= +github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -201,8 +209,9 @@ golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWP golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= +golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= +golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -218,8 +227,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= -golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -242,8 +251,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -291,7 +300,7 @@ google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index 3e6c363908..762e42a677 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -44,6 +44,7 @@ func Do(args []string, stdin io.Reader, stdout io.Writer, stderr io.Writer) int rootCmd.AddCommand(initCmd) rootCmd.AddCommand(versionCmd) rootCmd.AddCommand(uploadCmd) + rootCmd.AddCommand(NewCmdVet()) rootCmd.SetArgs(args) rootCmd.SetIn(stdin) diff --git a/internal/cmd/vet.go b/internal/cmd/vet.go new file mode 100644 index 0000000000..5a6c86126e --- /dev/null +++ b/internal/cmd/vet.go @@ -0,0 +1,310 @@ +package cmd + +import ( + "context" + "errors" + "fmt" + "io" + "os" + "path/filepath" + "runtime/trace" + "strings" + "time" + + "github.com/google/cel-go/cel" + "github.com/google/cel-go/ext" + "github.com/jackc/pgx/v5" + "github.com/spf13/cobra" + + "github.com/kyleconroy/sqlc/internal/config" + "github.com/kyleconroy/sqlc/internal/debug" + "github.com/kyleconroy/sqlc/internal/opts" + "github.com/kyleconroy/sqlc/internal/plugin" + "github.com/kyleconroy/sqlc/internal/sql/ast" +) + +var ErrFailedChecks = errors.New("failed checks") + +func NewCmdVet() *cobra.Command { + return &cobra.Command{ + Use: "vet", + Short: "Vet examines queries", + RunE: func(cmd *cobra.Command, args []string) error { + defer trace.StartRegion(cmd.Context(), "vet").End() + stderr := cmd.ErrOrStderr() + dir, name := getConfigPath(stderr, cmd.Flag("file")) + if err := Vet(cmd.Context(), ParseEnv(cmd), dir, name, stderr); err != nil { + if !errors.Is(err, ErrFailedChecks) { + fmt.Fprintf(stderr, "%s\n", err) + } + os.Exit(1) + } + return nil + }, + } +} + +func Vet(ctx context.Context, e Env, dir, filename string, stderr io.Writer) error { + configPath, conf, err := readConfig(stderr, dir, filename) + if err != nil { + return err + } + + base := filepath.Base(configPath) + if err := config.Validate(conf); err != nil { + fmt.Fprintf(stderr, "error validating %s: %s\n", base, err) + return err + } + + if err := e.Validate(conf); err != nil { + fmt.Fprintf(stderr, "error validating %s: %s\n", base, err) + return err + } + + env, err := cel.NewEnv( + cel.StdLib(), + ext.Strings(ext.StringsVersion(1)), + cel.Types( + &plugin.VetConfig{}, + &plugin.VetQuery{}, + ), + cel.Variable("query", + cel.ObjectType("plugin.VetQuery"), + ), + cel.Variable("config", + cel.ObjectType("plugin.VetConfig"), + ), + ) + if err != nil { + return fmt.Errorf("new env: %s", err) + } + + checks := map[string]cel.Program{} + msgs := map[string]string{} + + for _, c := range conf.Rules { + if c.Name == "" { + return fmt.Errorf("checks require a name") + } + if _, found := checks[c.Name]; found { + return fmt.Errorf("type-check error: a check with the name '%s' already exists", c.Name) + } + if c.Rule == "" { + return fmt.Errorf("type-check error: %s is empty", c.Name) + } + ast, issues := env.Compile(c.Rule) + if issues != nil && issues.Err() != nil { + return fmt.Errorf("type-check error: %s %s", c.Name, issues.Err()) + } + prg, err := env.Program(ast) + if err != nil { + return fmt.Errorf("program construction error: %s %s", c.Name, err) + } + checks[c.Name] = prg + msgs[c.Name] = c.Msg + } + + dbenv, err := cel.NewEnv( + cel.StdLib(), + ext.Strings(ext.StringsVersion(1)), + cel.Variable("env", + cel.MapType(cel.StringType, cel.StringType), + ), + ) + if err != nil { + return fmt.Errorf("new dbenv; %s", err) + } + + c := checker{ + Checks: checks, + Conf: conf, + Dbenv: dbenv, + Dir: dir, + Env: env, + Envmap: map[string]string{}, + Msgs: msgs, + Stderr: stderr, + } + errored := false + for _, sql := range conf.SQL { + if err := c.checkSQL(ctx, sql); err != nil { + if !errors.Is(err, ErrFailedChecks) { + fmt.Fprintf(stderr, "%s\n", err) + } + errored = true + } + } + if errored { + return ErrFailedChecks + } + return nil +} + +type checker struct { + Checks map[string]cel.Program + Conf *config.Config + Dbenv *cel.Env + Dir string + Env *cel.Env + Envmap map[string]string + Msgs map[string]string + Stderr io.Writer +} + +// Determine if a query can be prepared based on the engine and the statement +// type. +func prepareable(sql config.SQL, raw *ast.RawStmt) bool { + if sql.Engine == config.EnginePostgreSQL { + // TOOD: Add support for MERGE and VALUES stmts + switch raw.Stmt.(type) { + case *ast.DeleteStmt: + return true + case *ast.InsertStmt: + return true + case *ast.SelectStmt: + return true + case *ast.UpdateStmt: + return true + default: + return false + } + } + return false +} + +func (c *checker) checkSQL(ctx context.Context, sql config.SQL) error { + // TODO: Create a separate function for this logic so we can + combo := config.Combine(*c.Conf, sql) + + // TODO: This feels like a hack that will bite us later + joined := make([]string, 0, len(sql.Schema)) + for _, s := range sql.Schema { + joined = append(joined, filepath.Join(c.Dir, s)) + } + sql.Schema = joined + + joined = make([]string, 0, len(sql.Queries)) + for _, q := range sql.Queries { + joined = append(joined, filepath.Join(c.Dir, q)) + } + sql.Queries = joined + + var name string + parseOpts := opts.Parser{ + Debug: debug.Debug, + } + + result, failed := parse(ctx, name, c.Dir, sql, combo, parseOpts, c.Stderr) + if failed { + return ErrFailedChecks + } + + // TODO: Add MySQL support + var pgconn *pgx.Conn + if sql.Engine == config.EnginePostgreSQL && sql.Database != nil { + ast, issues := c.Dbenv.Compile(sql.Database.URL) + if issues != nil && issues.Err() != nil { + return fmt.Errorf("type-check error: database url %s", issues.Err()) + } + prg, err := c.Dbenv.Program(ast) + if err != nil { + return fmt.Errorf("program construction error: database url %s", err) + } + // Populate the environment variable map if it is empty + if len(c.Envmap) == 0 { + for _, e := range os.Environ() { + k, v, _ := strings.Cut(e, "=") + c.Envmap[k] = v + } + } + out, _, err := prg.Eval(map[string]any{ + "env": c.Envmap, + }) + if err != nil { + return fmt.Errorf("expression error: %s", err) + } + dburl, ok := out.Value().(string) + if !ok { + return fmt.Errorf("expression returned non-string value: %v", out.Value()) + } + fmt.Println("URL", dburl) + conn, err := pgx.Connect(ctx, dburl) + if err != nil { + return fmt.Errorf("database: connection error: %s", err) + } + defer conn.Close(ctx) + pgconn = conn + } + + errored := false + req := codeGenRequest(result, combo) + cfg := vetConfig(req) + for i, query := range req.Queries { + original := result.Queries[i] + if pgconn != nil && prepareable(sql, original.RawStmt) { + name := fmt.Sprintf("sqlc_vet_%d_%d", time.Now().Unix(), i) + _, err := pgconn.Prepare(ctx, name, query.Text) + if err != nil { + fmt.Fprintf(c.Stderr, "%s: error preparing %s: %s\n", query.Filename, query.Name, err) + errored = true + continue + } + } + q := vetQuery(query) + for _, name := range sql.Rules { + prg, ok := c.Checks[name] + if !ok { + return fmt.Errorf("type-check error: a check with the name '%s' does not exist", name) + } + out, _, err := prg.Eval(map[string]any{ + "query": q, + "config": cfg, + }) + if err != nil { + return err + } + tripped, ok := out.Value().(bool) + if !ok { + return fmt.Errorf("expression returned non-bool value: %v", out.Value()) + } + if tripped { + // TODO: Get line numbers in the output + msg := c.Msgs[name] + if msg == "" { + fmt.Fprintf(c.Stderr, "%s: %s: %s\n", query.Filename, q.Name, name) + } else { + fmt.Fprintf(c.Stderr, "%s: %s: %s: %s\n", query.Filename, q.Name, name, msg) + } + errored = true + } + } + } + if errored { + return ErrFailedChecks + } + return nil +} + +func vetConfig(req *plugin.CodeGenRequest) *plugin.VetConfig { + return &plugin.VetConfig{ + Version: req.Settings.Version, + Engine: req.Settings.Engine, + Schema: req.Settings.Schema, + Queries: req.Settings.Queries, + } +} + +func vetQuery(q *plugin.Query) *plugin.VetQuery { + var params []*plugin.VetParameter + for _, p := range q.Params { + params = append(params, &plugin.VetParameter{ + Number: p.Number, + }) + } + return &plugin.VetQuery{ + Sql: q.Text, + Name: q.Name, + Cmd: strings.TrimPrefix(":", q.Cmd), + Params: params, + } +} diff --git a/internal/compiler/parse.go b/internal/compiler/parse.go index 9ac5cc855a..b108acc492 100644 --- a/internal/compiler/parse.go +++ b/internal/compiler/parse.go @@ -126,6 +126,7 @@ func (c *Compiler) parseQuery(stmt ast.Node, src string, o opts.Parser) (*Query, return nil, err } return &Query{ + RawStmt: raw, Cmd: cmd, Comments: comments, Name: name, diff --git a/internal/compiler/query.go b/internal/compiler/query.go index c3e754cc04..e77f555dbd 100644 --- a/internal/compiler/query.go +++ b/internal/compiler/query.go @@ -51,6 +51,9 @@ type Query struct { // Needed for CopyFrom InsertIntoTable *ast.TableName + + // Needed for vet + RawStmt *ast.RawStmt } type Parameter struct { diff --git a/internal/config/config.go b/internal/config/config.go index ba7035cbbc..1d7df3111e 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -4,7 +4,6 @@ import ( "bytes" "encoding/json" "errors" - "fmt" "io" "gopkg.in/yaml.v3" @@ -62,12 +61,17 @@ type Config struct { SQL []SQL `json:"sql" yaml:"sql"` Gen Gen `json:"overrides,omitempty" yaml:"overrides"` Plugins []Plugin `json:"plugins" yaml:"plugins"` + Rules []Rule `json:"rules" yaml:"rules"` } type Project struct { ID string `json:"id" yaml:"id"` } +type Database struct { + URL string `json:"url" yaml:"url"` +} + type Cloud struct { Organization string `json:"organization" yaml:"organization"` Project string `json:"project" yaml:"project"` @@ -85,6 +89,12 @@ type Plugin struct { } `json:"wasm" yaml:"wasm"` } +type Rule struct { + Name string `json:"name" yaml:"name"` + Rule string `json:"rule" yaml:"rule"` + Msg string `json:"message" yaml:"message"` +} + type Gen struct { Go *GenGo `json:"go,omitempty" yaml:"go"` } @@ -98,10 +108,12 @@ type SQL struct { Engine Engine `json:"engine,omitempty" yaml:"engine"` Schema Paths `json:"schema" yaml:"schema"` Queries Paths `json:"queries" yaml:"queries"` + Database *Database `json:"database" yaml:"database"` StrictFunctionChecks bool `json:"strict_function_checks" yaml:"strict_function_checks"` StrictOrderBy *bool `json:"strict_order_by" yaml:"strict_order_by"` Gen SQLGen `json:"gen" yaml:"gen"` Codegen []Codegen `json:"codegen" yaml:"codegen"` + Rules []string `json:"rules" yaml:"rules"` } // TODO: Figure out a better name for this @@ -196,19 +208,6 @@ func ParseConfig(rd io.Reader) (Config, error) { } } -func Validate(c *Config) error { - for _, sql := range c.SQL { - sqlGo := sql.Gen.Go - if sqlGo == nil { - continue - } - if sqlGo.EmitMethodsWithDBArgument && sqlGo.EmitPreparedQueries { - return fmt.Errorf("invalid config: emit_methods_with_db_argument and emit_prepared_queries settings are mutually exclusive") - } - } - return nil -} - type CombinedSettings struct { Global Config Package SQL diff --git a/internal/config/validate.go b/internal/config/validate.go new file mode 100644 index 0000000000..4810a32eb3 --- /dev/null +++ b/internal/config/validate.go @@ -0,0 +1,21 @@ +package config + +import "fmt" + +func Validate(c *Config) error { + for _, sql := range c.SQL { + sqlGo := sql.Gen.Go + if sqlGo == nil { + continue + } + if sqlGo.EmitMethodsWithDBArgument && sqlGo.EmitPreparedQueries { + return fmt.Errorf("invalid config: emit_methods_with_db_argument and emit_prepared_queries settings are mutually exclusive") + } + if sql.Database != nil { + if sql.Database.URL == "" { + return fmt.Errorf("invalid config: database must have a non-empty URL") + } + } + } + return nil +} diff --git a/internal/endtoend/endtoend_test.go b/internal/endtoend/endtoend_test.go index 6f7e888ed7..3893193728 100644 --- a/internal/endtoend/endtoend_test.go +++ b/internal/endtoend/endtoend_test.go @@ -123,6 +123,8 @@ func TestReplay(t *testing.T) { if err == nil { cmpDirectory(t, path, output) } + case "vet": + err = cmd.Vet(ctx, env, path, "", &stderr) default: t.Fatalf("unknown command") } diff --git a/internal/endtoend/testdata/vet_failures/exec.json b/internal/endtoend/testdata/vet_failures/exec.json new file mode 100644 index 0000000000..07753636ee --- /dev/null +++ b/internal/endtoend/testdata/vet_failures/exec.json @@ -0,0 +1,3 @@ +{ + "command": "vet" +} diff --git a/internal/endtoend/testdata/vet_failures/query.sql b/internal/endtoend/testdata/vet_failures/query.sql new file mode 100644 index 0000000000..718f3395c0 --- /dev/null +++ b/internal/endtoend/testdata/vet_failures/query.sql @@ -0,0 +1,25 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); + +-- name: GetAuthor :one +SELECT * FROM authors +WHERE id = $1 LIMIT 1; + +-- name: ListAuthors :many +SELECT * FROM authors +ORDER BY name; + +-- name: CreateAuthor :one +INSERT INTO authors ( + name, bio +) VALUES ( + $1, $2 +) +RETURNING *; + +-- name: DeleteAuthor :exec +DELETE FROM authors +WHERE id = $1; diff --git a/internal/endtoend/testdata/vet_failures/schema.sql b/internal/endtoend/testdata/vet_failures/schema.sql new file mode 100644 index 0000000000..b4fad78497 --- /dev/null +++ b/internal/endtoend/testdata/vet_failures/schema.sql @@ -0,0 +1,5 @@ +CREATE TABLE authors ( + id BIGSERIAL PRIMARY KEY, + name text NOT NULL, + bio text +); diff --git a/internal/endtoend/testdata/vet_failures/sqlc.yaml b/internal/endtoend/testdata/vet_failures/sqlc.yaml new file mode 100644 index 0000000000..10d5246f8b --- /dev/null +++ b/internal/endtoend/testdata/vet_failures/sqlc.yaml @@ -0,0 +1,31 @@ +version: 2 +sql: + - schema: "query.sql" + queries: "query.sql" + engine: "postgresql" + gen: + go: + package: "authors" + out: "db" + rules: + - no-pg + - no-delete + - only-one-param + - no-exec +rules: + - name: no-pg + message: "invalid engine: postgresql" + rule: | + config.engine == "postgresql" + - name: no-delete + message: "don't use delete statements" + rule: | + query.sql.contains("DELETE") + - name: only-one-param + message: "too many parameters" + rule: | + query.params.size() > 1 + - name: no-exec + message: "don't use exec" + rule: | + query.cmd == "exec" diff --git a/internal/endtoend/testdata/vet_failures/stderr.txt b/internal/endtoend/testdata/vet_failures/stderr.txt new file mode 100644 index 0000000000..3e5eeb6a52 --- /dev/null +++ b/internal/endtoend/testdata/vet_failures/stderr.txt @@ -0,0 +1,6 @@ +query.sql: GetAuthor: no-pg: invalid engine: postgresql +query.sql: ListAuthors: no-pg: invalid engine: postgresql +query.sql: CreateAuthor: no-pg: invalid engine: postgresql +query.sql: CreateAuthor: only-one-param: too many parameters +query.sql: DeleteAuthor: no-pg: invalid engine: postgresql +query.sql: DeleteAuthor: no-delete: don't use delete statements diff --git a/internal/endtoend/vet_test.go b/internal/endtoend/vet_test.go new file mode 100644 index 0000000000..071c5642c0 --- /dev/null +++ b/internal/endtoend/vet_test.go @@ -0,0 +1,45 @@ +//go:build examples +// +build examples + +package main + +import ( + "bytes" + "context" + "os" + "path/filepath" + "testing" + + "github.com/kyleconroy/sqlc/internal/cmd" +) + +func TestExamplesVet(t *testing.T) { + t.Parallel() + ctx := context.Background() + + examples, err := filepath.Abs(filepath.Join("..", "..", "examples")) + if err != nil { + t.Fatal(err) + } + + files, err := os.ReadDir(examples) + if err != nil { + t.Fatal(err) + } + + for _, replay := range files { + if !replay.IsDir() { + continue + } + tc := replay.Name() + t.Run(tc, func(t *testing.T) { + t.Parallel() + path := filepath.Join(examples, tc) + var stderr bytes.Buffer + err := cmd.Vet(ctx, cmd.Env{}, path, "", &stderr) + if err != nil { + t.Fatalf("sqlc vet failed: %s %s", err, stderr.String()) + } + }) + } +} diff --git a/internal/plugin/codegen.pb.go b/internal/plugin/codegen.pb.go index 03f16037b4..12003c9ba8 100644 --- a/internal/plugin/codegen.pb.go +++ b/internal/plugin/codegen.pb.go @@ -1593,6 +1593,195 @@ func (x *CodeGenResponse) GetFiles() []*File { return nil } +type VetParameter struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Number int32 `protobuf:"varint,1,opt,name=number,proto3" json:"number,omitempty"` +} + +func (x *VetParameter) Reset() { + *x = VetParameter{} + if protoimpl.UnsafeEnabled { + mi := &file_plugin_codegen_proto_msgTypes[18] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VetParameter) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VetParameter) ProtoMessage() {} + +func (x *VetParameter) ProtoReflect() protoreflect.Message { + mi := &file_plugin_codegen_proto_msgTypes[18] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VetParameter.ProtoReflect.Descriptor instead. +func (*VetParameter) Descriptor() ([]byte, []int) { + return file_plugin_codegen_proto_rawDescGZIP(), []int{18} +} + +func (x *VetParameter) GetNumber() int32 { + if x != nil { + return x.Number + } + return 0 +} + +type VetConfig struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + Engine string `protobuf:"bytes,2,opt,name=engine,proto3" json:"engine,omitempty"` + Schema []string `protobuf:"bytes,3,rep,name=schema,proto3" json:"schema,omitempty"` + Queries []string `protobuf:"bytes,4,rep,name=queries,proto3" json:"queries,omitempty"` +} + +func (x *VetConfig) Reset() { + *x = VetConfig{} + if protoimpl.UnsafeEnabled { + mi := &file_plugin_codegen_proto_msgTypes[19] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VetConfig) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VetConfig) ProtoMessage() {} + +func (x *VetConfig) ProtoReflect() protoreflect.Message { + mi := &file_plugin_codegen_proto_msgTypes[19] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VetConfig.ProtoReflect.Descriptor instead. +func (*VetConfig) Descriptor() ([]byte, []int) { + return file_plugin_codegen_proto_rawDescGZIP(), []int{19} +} + +func (x *VetConfig) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + +func (x *VetConfig) GetEngine() string { + if x != nil { + return x.Engine + } + return "" +} + +func (x *VetConfig) GetSchema() []string { + if x != nil { + return x.Schema + } + return nil +} + +func (x *VetConfig) GetQueries() []string { + if x != nil { + return x.Queries + } + return nil +} + +type VetQuery struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Sql string `protobuf:"bytes,1,opt,name=sql,proto3" json:"sql,omitempty"` + Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` + Cmd string `protobuf:"bytes,3,opt,name=cmd,proto3" json:"cmd,omitempty"` + Params []*VetParameter `protobuf:"bytes,4,rep,name=params,json=parameters,proto3" json:"params,omitempty"` +} + +func (x *VetQuery) Reset() { + *x = VetQuery{} + if protoimpl.UnsafeEnabled { + mi := &file_plugin_codegen_proto_msgTypes[20] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *VetQuery) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*VetQuery) ProtoMessage() {} + +func (x *VetQuery) ProtoReflect() protoreflect.Message { + mi := &file_plugin_codegen_proto_msgTypes[20] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use VetQuery.ProtoReflect.Descriptor instead. +func (*VetQuery) Descriptor() ([]byte, []int) { + return file_plugin_codegen_proto_rawDescGZIP(), []int{20} +} + +func (x *VetQuery) GetSql() string { + if x != nil { + return x.Sql + } + return "" +} + +func (x *VetQuery) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *VetQuery) GetCmd() string { + if x != nil { + return x.Cmd + } + return "" +} + +func (x *VetQuery) GetParams() []*VetParameter { + if x != nil { + return x.Params + } + return nil +} + var File_plugin_codegen_proto protoreflect.FileDescriptor var file_plugin_codegen_proto_rawDesc = []byte{ @@ -1867,16 +2056,33 @@ var file_plugin_codegen_proto_rawDesc = []byte{ 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x35, 0x0a, 0x0f, 0x43, 0x6f, 0x64, 0x65, 0x47, 0x65, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x22, 0x0a, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x6c, 0x75, 0x67, - 0x69, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x42, 0x7e, - 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x42, 0x0c, 0x43, 0x6f, - 0x64, 0x65, 0x67, 0x65, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2a, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x79, 0x6c, 0x65, 0x63, 0x6f, 0x6e, - 0x72, 0x6f, 0x79, 0x2f, 0x73, 0x71, 0x6c, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, - 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0xca, 0x02, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, - 0xe2, 0x02, 0x12, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x6e, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x52, 0x05, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x26, + 0x0a, 0x0c, 0x56, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x12, 0x16, + 0x0a, 0x06, 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, + 0x6e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x22, 0x6f, 0x0a, 0x09, 0x56, 0x65, 0x74, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x0a, + 0x06, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, + 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x73, 0x63, 0x68, 0x65, 0x6d, 0x61, 0x12, 0x18, 0x0a, + 0x07, 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, + 0x71, 0x75, 0x65, 0x72, 0x69, 0x65, 0x73, 0x22, 0x74, 0x0a, 0x08, 0x56, 0x65, 0x74, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x71, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x03, 0x73, 0x71, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x63, 0x6d, 0x64, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x63, 0x6d, 0x64, 0x12, 0x30, 0x0a, 0x06, 0x70, + 0x61, 0x72, 0x61, 0x6d, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x70, 0x6c, + 0x75, 0x67, 0x69, 0x6e, 0x2e, 0x56, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, + 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x42, 0x7e, 0x0a, + 0x0a, 0x63, 0x6f, 0x6d, 0x2e, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x42, 0x0c, 0x43, 0x6f, 0x64, + 0x65, 0x67, 0x65, 0x6e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x2a, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6b, 0x79, 0x6c, 0x65, 0x63, 0x6f, 0x6e, 0x72, + 0x6f, 0x79, 0x2f, 0x73, 0x71, 0x6c, 0x63, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, + 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0xa2, 0x02, 0x03, 0x50, 0x58, 0x58, 0xaa, 0x02, 0x06, + 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0xca, 0x02, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0xe2, + 0x02, 0x12, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x06, 0x50, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x62, 0x06, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -1891,7 +2097,7 @@ func file_plugin_codegen_proto_rawDescGZIP() []byte { return file_plugin_codegen_proto_rawDescData } -var file_plugin_codegen_proto_msgTypes = make([]protoimpl.MessageInfo, 20) +var file_plugin_codegen_proto_msgTypes = make([]protoimpl.MessageInfo, 23) var file_plugin_codegen_proto_goTypes = []interface{}{ (*File)(nil), // 0: plugin.File (*Override)(nil), // 1: plugin.Override @@ -1911,14 +2117,17 @@ var file_plugin_codegen_proto_goTypes = []interface{}{ (*Parameter)(nil), // 15: plugin.Parameter (*CodeGenRequest)(nil), // 16: plugin.CodeGenRequest (*CodeGenResponse)(nil), // 17: plugin.CodeGenResponse - nil, // 18: plugin.ParsedGoType.StructTagsEntry - nil, // 19: plugin.Settings.RenameEntry + (*VetParameter)(nil), // 18: plugin.VetParameter + (*VetConfig)(nil), // 19: plugin.VetConfig + (*VetQuery)(nil), // 20: plugin.VetQuery + nil, // 21: plugin.ParsedGoType.StructTagsEntry + nil, // 22: plugin.Settings.RenameEntry } var file_plugin_codegen_proto_depIdxs = []int32{ 12, // 0: plugin.Override.table:type_name -> plugin.Identifier 2, // 1: plugin.Override.go_type:type_name -> plugin.ParsedGoType - 18, // 2: plugin.ParsedGoType.struct_tags:type_name -> plugin.ParsedGoType.StructTagsEntry - 19, // 3: plugin.Settings.rename:type_name -> plugin.Settings.RenameEntry + 21, // 2: plugin.ParsedGoType.struct_tags:type_name -> plugin.ParsedGoType.StructTagsEntry + 22, // 3: plugin.Settings.rename:type_name -> plugin.Settings.RenameEntry 1, // 4: plugin.Settings.overrides:type_name -> plugin.Override 4, // 5: plugin.Settings.codegen:type_name -> plugin.Codegen 5, // 6: plugin.Settings.go:type_name -> plugin.GoCode @@ -1940,11 +2149,12 @@ var file_plugin_codegen_proto_depIdxs = []int32{ 7, // 22: plugin.CodeGenRequest.catalog:type_name -> plugin.Catalog 14, // 23: plugin.CodeGenRequest.queries:type_name -> plugin.Query 0, // 24: plugin.CodeGenResponse.files:type_name -> plugin.File - 25, // [25:25] is the sub-list for method output_type - 25, // [25:25] is the sub-list for method input_type - 25, // [25:25] is the sub-list for extension type_name - 25, // [25:25] is the sub-list for extension extendee - 0, // [0:25] is the sub-list for field type_name + 18, // 25: plugin.VetQuery.params:type_name -> plugin.VetParameter + 26, // [26:26] is the sub-list for method output_type + 26, // [26:26] is the sub-list for method input_type + 26, // [26:26] is the sub-list for extension type_name + 26, // [26:26] is the sub-list for extension extendee + 0, // [0:26] is the sub-list for field type_name } func init() { file_plugin_codegen_proto_init() } @@ -2169,6 +2379,42 @@ func file_plugin_codegen_proto_init() { return nil } } + file_plugin_codegen_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VetParameter); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_plugin_codegen_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VetConfig); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_plugin_codegen_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*VetQuery); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } file_plugin_codegen_proto_msgTypes[5].OneofWrappers = []interface{}{} type x struct{} @@ -2177,7 +2423,7 @@ func file_plugin_codegen_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_plugin_codegen_proto_rawDesc, NumEnums: 0, - NumMessages: 20, + NumMessages: 23, NumExtensions: 0, NumServices: 0, }, diff --git a/internal/plugin/codegen_vtproto.pb.go b/internal/plugin/codegen_vtproto.pb.go index c2728bf8d5..d4f35041f2 100644 --- a/internal/plugin/codegen_vtproto.pb.go +++ b/internal/plugin/codegen_vtproto.pb.go @@ -539,6 +539,80 @@ func (m *CodeGenResponse) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *VetParameter) CloneVT() *VetParameter { + if m == nil { + return (*VetParameter)(nil) + } + r := &VetParameter{ + Number: m.Number, + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *VetParameter) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *VetConfig) CloneVT() *VetConfig { + if m == nil { + return (*VetConfig)(nil) + } + r := &VetConfig{ + Version: m.Version, + Engine: m.Engine, + } + if rhs := m.Schema; rhs != nil { + tmpContainer := make([]string, len(rhs)) + copy(tmpContainer, rhs) + r.Schema = tmpContainer + } + if rhs := m.Queries; rhs != nil { + tmpContainer := make([]string, len(rhs)) + copy(tmpContainer, rhs) + r.Queries = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *VetConfig) CloneMessageVT() proto.Message { + return m.CloneVT() +} + +func (m *VetQuery) CloneVT() *VetQuery { + if m == nil { + return (*VetQuery)(nil) + } + r := &VetQuery{ + Sql: m.Sql, + Name: m.Name, + Cmd: m.Cmd, + } + if rhs := m.Params; rhs != nil { + tmpContainer := make([]*VetParameter, len(rhs)) + for k, v := range rhs { + tmpContainer[k] = v.CloneVT() + } + r.Params = tmpContainer + } + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *VetQuery) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (this *File) EqualVT(that *File) bool { if this == that { return true @@ -1339,6 +1413,107 @@ func (this *CodeGenResponse) EqualMessageVT(thatMsg proto.Message) bool { } return this.EqualVT(that) } +func (this *VetParameter) EqualVT(that *VetParameter) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Number != that.Number { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *VetParameter) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*VetParameter) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *VetConfig) EqualVT(that *VetConfig) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Version != that.Version { + return false + } + if this.Engine != that.Engine { + return false + } + if len(this.Schema) != len(that.Schema) { + return false + } + for i, vx := range this.Schema { + vy := that.Schema[i] + if vx != vy { + return false + } + } + if len(this.Queries) != len(that.Queries) { + return false + } + for i, vx := range this.Queries { + vy := that.Queries[i] + if vx != vy { + return false + } + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *VetConfig) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*VetConfig) + if !ok { + return false + } + return this.EqualVT(that) +} +func (this *VetQuery) EqualVT(that *VetQuery) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Sql != that.Sql { + return false + } + if this.Name != that.Name { + return false + } + if this.Cmd != that.Cmd { + return false + } + if len(this.Params) != len(that.Params) { + return false + } + for i, vx := range this.Params { + vy := that.Params[i] + if p, q := vx, vy; p != q { + if p == nil { + p = &VetParameter{} + } + if q == nil { + q = &VetParameter{} + } + if !p.EqualVT(q) { + return false + } + } + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *VetQuery) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*VetQuery) + if !ok { + return false + } + return this.EqualVT(that) +} func (m *File) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -2904,36 +3079,25 @@ func (m *CodeGenResponse) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } -func encodeVarint(dAtA []byte, offset int, v uint64) int { - offset -= sov(v) - base := offset - for v >= 1<<7 { - dAtA[offset] = uint8(v&0x7f | 0x80) - v >>= 7 - offset++ - } - dAtA[offset] = uint8(v) - return base -} -func (m *File) MarshalVTStrict() (dAtA []byte, err error) { +func (m *VetParameter) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil } size := m.SizeVT() dAtA = make([]byte, size) - n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) if err != nil { return nil, err } return dAtA[:n], nil } -func (m *File) MarshalToVTStrict(dAtA []byte) (int, error) { +func (m *VetParameter) MarshalToVT(dAtA []byte) (int, error) { size := m.SizeVT() - return m.MarshalToSizedBufferVTStrict(dAtA[:size]) + return m.MarshalToSizedBufferVT(dAtA[:size]) } -func (m *File) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { +func (m *VetParameter) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { return 0, nil } @@ -2945,42 +3109,33 @@ func (m *File) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if len(m.Contents) > 0 { - i -= len(m.Contents) - copy(dAtA[i:], m.Contents) - i = encodeVarint(dAtA, i, uint64(len(m.Contents))) - i-- - dAtA[i] = 0x12 - } - if len(m.Name) > 0 { - i -= len(m.Name) - copy(dAtA[i:], m.Name) - i = encodeVarint(dAtA, i, uint64(len(m.Name))) + if m.Number != 0 { + i = encodeVarint(dAtA, i, uint64(m.Number)) i-- - dAtA[i] = 0xa + dAtA[i] = 0x8 } return len(dAtA) - i, nil } -func (m *Override) MarshalVTStrict() (dAtA []byte, err error) { +func (m *VetConfig) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil } size := m.SizeVT() dAtA = make([]byte, size) - n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) if err != nil { return nil, err } return dAtA[:n], nil } -func (m *Override) MarshalToVTStrict(dAtA []byte) (int, error) { +func (m *VetConfig) MarshalToVT(dAtA []byte) (int, error) { size := m.SizeVT() - return m.MarshalToSizedBufferVTStrict(dAtA[:size]) + return m.MarshalToSizedBufferVT(dAtA[:size]) } -func (m *Override) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { +func (m *VetConfig) MarshalToSizedBufferVT(dAtA []byte) (int, error) { if m == nil { return 0, nil } @@ -2992,54 +3147,243 @@ func (m *Override) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { i -= len(m.unknownFields) copy(dAtA[i:], m.unknownFields) } - if m.Unsigned { - i-- - if m.Unsigned { - dAtA[i] = 1 - } else { - dAtA[i] = 0 + if len(m.Queries) > 0 { + for iNdEx := len(m.Queries) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Queries[iNdEx]) + copy(dAtA[i:], m.Queries[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.Queries[iNdEx]))) + i-- + dAtA[i] = 0x22 } - i-- - dAtA[i] = 0x58 } - if m.GoType != nil { - size, err := m.GoType.MarshalToSizedBufferVTStrict(dAtA[:i]) - if err != nil { - return 0, err + if len(m.Schema) > 0 { + for iNdEx := len(m.Schema) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Schema[iNdEx]) + copy(dAtA[i:], m.Schema[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.Schema[iNdEx]))) + i-- + dAtA[i] = 0x1a } - i -= size - i = encodeVarint(dAtA, i, uint64(size)) - i-- - dAtA[i] = 0x52 } - if len(m.ColumnName) > 0 { - i -= len(m.ColumnName) - copy(dAtA[i:], m.ColumnName) - i = encodeVarint(dAtA, i, uint64(len(m.ColumnName))) + if len(m.Engine) > 0 { + i -= len(m.Engine) + copy(dAtA[i:], m.Engine) + i = encodeVarint(dAtA, i, uint64(len(m.Engine))) i-- - dAtA[i] = 0x42 + dAtA[i] = 0x12 } - if m.Table != nil { - size, err := m.Table.MarshalToSizedBufferVTStrict(dAtA[:i]) - if err != nil { - return 0, err - } - i -= size - i = encodeVarint(dAtA, i, uint64(size)) + if len(m.Version) > 0 { + i -= len(m.Version) + copy(dAtA[i:], m.Version) + i = encodeVarint(dAtA, i, uint64(len(m.Version))) i-- - dAtA[i] = 0x3a + dAtA[i] = 0xa } - if len(m.Column) > 0 { - i -= len(m.Column) - copy(dAtA[i:], m.Column) - i = encodeVarint(dAtA, i, uint64(len(m.Column))) - i-- - dAtA[i] = 0x32 + return len(dAtA) - i, nil +} + +func (m *VetQuery) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil } - if m.Nullable { - i-- - if m.Nullable { - dAtA[i] = 1 + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VetQuery) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *VetQuery) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Params) > 0 { + for iNdEx := len(m.Params) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Params[iNdEx].MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Cmd) > 0 { + i -= len(m.Cmd) + copy(dAtA[i:], m.Cmd) + i = encodeVarint(dAtA, i, uint64(len(m.Cmd))) + i-- + dAtA[i] = 0x1a + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x12 + } + if len(m.Sql) > 0 { + i -= len(m.Sql) + copy(dAtA[i:], m.Sql) + i = encodeVarint(dAtA, i, uint64(len(m.Sql))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func encodeVarint(dAtA []byte, offset int, v uint64) int { + offset -= sov(v) + base := offset + for v >= 1<<7 { + dAtA[offset] = uint8(v&0x7f | 0x80) + v >>= 7 + offset++ + } + dAtA[offset] = uint8(v) + return base +} +func (m *File) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *File) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *File) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Contents) > 0 { + i -= len(m.Contents) + copy(dAtA[i:], m.Contents) + i = encodeVarint(dAtA, i, uint64(len(m.Contents))) + i-- + dAtA[i] = 0x12 + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *Override) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *Override) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *Override) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Unsigned { + i-- + if m.Unsigned { + dAtA[i] = 1 + } else { + dAtA[i] = 0 + } + i-- + dAtA[i] = 0x58 + } + if m.GoType != nil { + size, err := m.GoType.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x52 + } + if len(m.ColumnName) > 0 { + i -= len(m.ColumnName) + copy(dAtA[i:], m.ColumnName) + i = encodeVarint(dAtA, i, uint64(len(m.ColumnName))) + i-- + dAtA[i] = 0x42 + } + if m.Table != nil { + size, err := m.Table.MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x3a + } + if len(m.Column) > 0 { + i -= len(m.Column) + copy(dAtA[i:], m.Column) + i = encodeVarint(dAtA, i, uint64(len(m.Column))) + i-- + dAtA[i] = 0x32 + } + if m.Nullable { + i-- + if m.Nullable { + dAtA[i] = 1 } else { dAtA[i] = 0 } @@ -4480,52 +4824,221 @@ func (m *CodeGenResponse) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) return len(dAtA) - i, nil } -func (m *File) SizeVT() (n int) { +func (m *VetParameter) MarshalVTStrict() (dAtA []byte, err error) { if m == nil { - return 0 - } - var l int - _ = l - l = len(m.Name) - if l > 0 { - n += 1 + l + sov(uint64(l)) + return nil, nil } - l = len(m.Contents) - if l > 0 { - n += 1 + l + sov(uint64(l)) + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err } - n += len(m.unknownFields) - return n + return dAtA[:n], nil } -func (m *Override) SizeVT() (n int) { +func (m *VetParameter) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *VetParameter) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { if m == nil { - return 0 + return 0, nil } + i := len(dAtA) + _ = i var l int _ = l - l = len(m.CodeType) - if l > 0 { - n += 1 + l + sov(uint64(l)) - } - l = len(m.DbType) - if l > 0 { - n += 1 + l + sov(uint64(l)) + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) } - if m.Nullable { - n += 2 + if m.Number != 0 { + i = encodeVarint(dAtA, i, uint64(m.Number)) + i-- + dAtA[i] = 0x8 } - l = len(m.Column) - if l > 0 { - n += 1 + l + sov(uint64(l)) + return len(dAtA) - i, nil +} + +func (m *VetConfig) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil } - if m.Table != nil { - l = m.Table.SizeVT() - n += 1 + l + sov(uint64(l)) + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err } - l = len(m.ColumnName) - if l > 0 { - n += 1 + l + sov(uint64(l)) + return dAtA[:n], nil +} + +func (m *VetConfig) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *VetConfig) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Queries) > 0 { + for iNdEx := len(m.Queries) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Queries[iNdEx]) + copy(dAtA[i:], m.Queries[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.Queries[iNdEx]))) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Schema) > 0 { + for iNdEx := len(m.Schema) - 1; iNdEx >= 0; iNdEx-- { + i -= len(m.Schema[iNdEx]) + copy(dAtA[i:], m.Schema[iNdEx]) + i = encodeVarint(dAtA, i, uint64(len(m.Schema[iNdEx]))) + i-- + dAtA[i] = 0x1a + } + } + if len(m.Engine) > 0 { + i -= len(m.Engine) + copy(dAtA[i:], m.Engine) + i = encodeVarint(dAtA, i, uint64(len(m.Engine))) + i-- + dAtA[i] = 0x12 + } + if len(m.Version) > 0 { + i -= len(m.Version) + copy(dAtA[i:], m.Version) + i = encodeVarint(dAtA, i, uint64(len(m.Version))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *VetQuery) MarshalVTStrict() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVTStrict(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *VetQuery) MarshalToVTStrict(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVTStrict(dAtA[:size]) +} + +func (m *VetQuery) MarshalToSizedBufferVTStrict(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if len(m.Params) > 0 { + for iNdEx := len(m.Params) - 1; iNdEx >= 0; iNdEx-- { + size, err := m.Params[iNdEx].MarshalToSizedBufferVTStrict(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = encodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x22 + } + } + if len(m.Cmd) > 0 { + i -= len(m.Cmd) + copy(dAtA[i:], m.Cmd) + i = encodeVarint(dAtA, i, uint64(len(m.Cmd))) + i-- + dAtA[i] = 0x1a + } + if len(m.Name) > 0 { + i -= len(m.Name) + copy(dAtA[i:], m.Name) + i = encodeVarint(dAtA, i, uint64(len(m.Name))) + i-- + dAtA[i] = 0x12 + } + if len(m.Sql) > 0 { + i -= len(m.Sql) + copy(dAtA[i:], m.Sql) + i = encodeVarint(dAtA, i, uint64(len(m.Sql))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + +func (m *File) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Name) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Contents) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + n += len(m.unknownFields) + return n +} + +func (m *Override) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.CodeType) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.DbType) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Nullable { + n += 2 + } + l = len(m.Column) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if m.Table != nil { + l = m.Table.SizeVT() + n += 1 + l + sov(uint64(l)) + } + l = len(m.ColumnName) + if l > 0 { + n += 1 + l + sov(uint64(l)) } if m.GoType != nil { l = m.GoType.SizeVT() @@ -5103,6 +5616,77 @@ func (m *CodeGenResponse) SizeVT() (n int) { return n } +func (m *VetParameter) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Number != 0 { + n += 1 + sov(uint64(m.Number)) + } + n += len(m.unknownFields) + return n +} + +func (m *VetConfig) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Version) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Engine) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if len(m.Schema) > 0 { + for _, s := range m.Schema { + l = len(s) + n += 1 + l + sov(uint64(l)) + } + } + if len(m.Queries) > 0 { + for _, s := range m.Queries { + l = len(s) + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + +func (m *VetQuery) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Sql) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Name) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + l = len(m.Cmd) + if l > 0 { + n += 1 + l + sov(uint64(l)) + } + if len(m.Params) > 0 { + for _, e := range m.Params { + l = e.SizeVT() + n += 1 + l + sov(uint64(l)) + } + } + n += len(m.unknownFields) + return n +} + func sov(x uint64) (n int) { return (bits.Len64(x|1) + 6) / 7 } @@ -9425,6 +10009,436 @@ func (m *CodeGenResponse) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *VetParameter) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VetParameter: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VetParameter: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Number", wireType) + } + m.Number = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Number |= int32(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VetConfig) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VetConfig: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VetConfig: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Version", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Version = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Engine", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Engine = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Schema", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Schema = append(m.Schema, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Queries", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Queries = append(m.Queries, string(dAtA[iNdEx:postIndex])) + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} +func (m *VetQuery) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: VetQuery: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: VetQuery: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Sql", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Sql = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Name = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Cmd", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Cmd = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 4: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Params", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Params = append(m.Params, &VetParameter{}) + if err := m.Params[len(m.Params)-1].UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + default: + iNdEx = preIndex + skippy, err := skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func skip(dAtA []byte) (n int, err error) { l := len(dAtA) diff --git a/protos/plugin/codegen.proto b/protos/plugin/codegen.proto index cd4d4a040e..accecef017 100644 --- a/protos/plugin/codegen.proto +++ b/protos/plugin/codegen.proto @@ -205,3 +205,24 @@ message CodeGenResponse { repeated File files = 1 [json_name="files"]; } + +message VetParameter +{ + int32 number = 1 [json_name="number"]; +} + +message VetConfig +{ + string version = 1 [json_name="version"]; + string engine = 2 [json_name="engine"]; + repeated string schema = 3 [json_name="schema"]; + repeated string queries = 4 [json_name="queries"]; +} + +message VetQuery +{ + string sql = 1 [json_name="sql"]; + string name = 2 [json_name="name"]; + string cmd = 3 [json_name="cmd"]; + repeated VetParameter params = 4 [json_name="parameters"]; +} \ No newline at end of file