diff --git a/cmd/ormat/command/build.go b/cmd/ormat/command/build.go index c678807..20be542 100644 --- a/cmd/ormat/command/build.go +++ b/cmd/ormat/command/build.go @@ -2,10 +2,8 @@ package command import ( "context" - "fmt" "log/slog" "os" - "strings" "ariga.io/atlas/sql/schema" "github.com/spf13/cobra" @@ -30,15 +28,13 @@ func newBuildCmd() *buildCmd { getSchema := func() ens.Schemaer { innerParseFromFile := func(filename string) (ens.Schemaer, error) { - var d driver.Driver - content, err := os.ReadFile(filename) if err != nil { return nil, err } - d, ok := driver.LoadDriver(root.Schema) - if !ok { - return nil, fmt.Errorf("unsupported schema, only support [%v]", strings.Join(driver.DriverNames(), ", ")) + d, err := driver.LoadDriver(root.Schema) + if err != nil { + return nil, err } return d.InspectSchema(context.Background(), &driver.InspectOption{ URL: "", diff --git a/cmd/ormat/command/helper.go b/cmd/ormat/command/helper.go index b7c459b..9dc4261 100644 --- a/cmd/ormat/command/helper.go +++ b/cmd/ormat/command/helper.go @@ -1,7 +1,6 @@ package command import ( - "fmt" "net/url" "os" "path" @@ -16,9 +15,9 @@ func LoadDriver(URL string) (driver.Driver, error) { if err != nil { return nil, err } - d, ok := driver.LoadDriver(u.Scheme) - if !ok { - return nil, fmt.Errorf("unsupported schema, only support [%v]", strings.Join(driver.DriverNames(), ", ")) + d, err := driver.LoadDriver(u.Scheme) + if err != nil { + return nil, err } return d, nil } diff --git a/cmd/ormat/command/helper_config.go b/cmd/ormat/command/helper_config.go index 26ed2ef..0d61b06 100644 --- a/cmd/ormat/command/helper_config.go +++ b/cmd/ormat/command/helper_config.go @@ -28,7 +28,4 @@ func InitFlagSetForConfig(s *pflag.FlagSet, cc *Config) { s.StringVar(&cc.Package, "package", "", "package name") s.StringToStringVar(&cc.Options, "options", nil, "options key value") s.BoolVarP(&cc.DisableDocComment, "disableDocComment", "d", false, "禁用文档注释") - - s.BoolVar(&cc.EnableGogo, "enableGogo", false, "使能用 gogo proto (仅输出 proto 有效)") - s.BoolVar(&cc.EnableSea, "enableSea", false, "使能用 seaql (仅输出 proto 有效)") } diff --git a/cmd/ormat/command/proto.go b/cmd/ormat/command/proto.go new file mode 100644 index 0000000..daf7329 --- /dev/null +++ b/cmd/ormat/command/proto.go @@ -0,0 +1,143 @@ +package command + +import ( + "context" + "errors" + "fmt" + "log/slog" + "os" + + "ariga.io/atlas/sql/schema" + "github.com/spf13/cobra" + "github.com/things-go/ens/driver" + "github.com/things-go/ens/proto" +) + +type protoOpt struct { + // sql file + InputFile []string + Schema string + // database url + Url string + Tables []string + Exclude []string + + // output directory + OutputDir string + + // codegen + PackageName string // required, proto 包名 + Options map[string]string // required, proto option + DisableDocComment bool // 禁用doc注释 + DisableBool bool // 禁用bool,使用int32 + DisableTimestamp bool // 禁用google.protobuf.Timestamp,使用int64 +} + +type protoCmd struct { + cmd *cobra.Command + protoOpt +} + +func newProtoCmd() *protoCmd { + root := &protoCmd{} + + protoSchema := func() (*proto.Schema, error) { + if root.Url != "" { + d, err := LoadDriver(root.Url) + if err != nil { + return nil, err + } + return d.InspectProto(context.Background(), &driver.InspectOption{ + URL: root.Url, + InspectOptions: schema.InspectOptions{ + Mode: schema.InspectTables, + Tables: root.Tables, + Exclude: root.Exclude, + }, + }) + } + if len(root.InputFile) > 0 { + d, err := driver.LoadDriver(root.Schema) + if err != nil { + return nil, err + } + schemas := &proto.Schema{ + Name: "", + Messages: make([]*proto.Message, 0, 128), + } + for _, filename := range root.InputFile { + tmpSchema, err := func() (*proto.Schema, error) { + content, err := os.ReadFile(filename) + if err != nil { + return nil, err + } + return d.InspectProto(context.Background(), &driver.InspectOption{ + URL: "", + Data: string(content), + InspectOptions: schema.InspectOptions{}, + }) + }() + if err != nil { + slog.Warn("🧐 parse failed !!!", slog.String("file", filename), slog.Any("error", err)) + continue + } + schemas.Messages = append(schemas.Messages, tmpSchema.Messages...) + } + return schemas, nil + } + return nil, errors.New("at least one of [url input] is required") + } + + cmd := &cobra.Command{ + Use: "proto", + Short: "Generate proto from database", + Example: "ormat proto", + RunE: func(*cobra.Command, []string) error { + sc, err := protoSchema() + if err != nil { + return err + } + for _, msg := range sc.Messages { + codegen := &proto.CodeGen{ + Messages: []*proto.Message{msg}, + ByName: "ormat", + Version: version, + PackageName: root.PackageName, + Options: root.Options, + DisableDocComment: root.DisableDocComment, + DisableBool: root.DisableBool, + DisableTimestamp: root.DisableTimestamp, + } + data := codegen.Gen().Bytes() + filename := joinFilename(root.OutputDir, msg.TableName, ".proto") + err := WriteFile(filename, data) + if err != nil { + return fmt.Errorf("%v: %w", msg.TableName, err) + } + slog.Info("👉 " + filename) + } + return nil + }, + } + + cmd.Flags().StringSliceVarP(&root.InputFile, "input", "i", nil, "input file") + cmd.Flags().StringVarP(&root.Schema, "schema", "s", "file+mysql", "parser file driver, [file+mysql,file+tidb](仅input时有效)") + + // database url + cmd.Flags().StringVarP(&root.Url, "url", "u", "", "mysql://root:123456@127.0.0.1:3306/test") + cmd.Flags().StringSliceVarP(&root.Tables, "table", "t", nil, "only out custom table(仅url时有效)") + cmd.Flags().StringSliceVarP(&root.Exclude, "exclude", "e", nil, "exclude table pattern(仅url时有效)") + + cmd.Flags().StringVarP(&root.OutputDir, "out", "o", "./mapper", "out directory") + + cmd.Flags().StringVar(&root.PackageName, "package", "mapper", "proto package name") + cmd.Flags().StringToStringVar(&root.Options, "options", nil, "proto options key/value") + cmd.Flags().BoolVar(&root.DisableDocComment, "disableDocComment", false, "禁用文档注释") + cmd.Flags().BoolVar(&root.DisableBool, "disableBool", false, "禁用bool,使用int32") + cmd.Flags().BoolVar(&root.DisableTimestamp, "disableTimestamp", false, "禁用google.protobuf.Timestamp,使用int64") + + cmd.MarkFlagsOneRequired("url", "input") + + root.cmd = cmd + return root +} diff --git a/cmd/ormat/command/root.go b/cmd/ormat/command/root.go index 04d4a8c..3fbcda6 100644 --- a/cmd/ormat/command/root.go +++ b/cmd/ormat/command/root.go @@ -40,7 +40,7 @@ func NewRootCmd() *RootCmd { newSqlCmd().cmd, newBuildCmd().cmd, newGenCmd().cmd, - newUpgradeCmd().cmd, + newProtoCmd().cmd, ) root.cmd = cmd return root diff --git a/cmd/ormat/command/upgrade.go b/cmd/ormat/command/upgrade.go deleted file mode 100644 index 110765f..0000000 --- a/cmd/ormat/command/upgrade.go +++ /dev/null @@ -1,188 +0,0 @@ -package command - -import ( - "context" - "fmt" - "log/slog" - "net/http" - "os" - "runtime" - "strings" - "time" - - "github.com/google/go-github/v58/github" - "github.com/kierdavis/ansi" - "github.com/spf13/cobra" - "github.com/tj/go-update" - "github.com/tj/go-update/progress" - "golang.org/x/oauth2" -) - -type upgradeCmd struct { - cmd *cobra.Command -} - -func newUpgradeCmd() *upgradeCmd { - root := &upgradeCmd{} - cmd := &cobra.Command{ - Use: "upgrade", - Short: "Upgrade ormat", - Long: "Upgrade ormat by providing a version. If no version is provided, upgrade to the latest.", - SilenceUsage: true, - RunE: func(cmd *cobra.Command, args []string) error { - ansi.HideCursor() - defer ansi.ShowCursor() - - m := &manager{ - Manager: &update.Manager{ - Command: "ormat", - Store: &githubStore{ - Owner: "things-go", - Repo: "ens", - Version: version, - Client: NewGithubClient(os.Getenv("GITHUB_TOKEN")), - }, - }, - } - - var err error - var r *update.Release - var a *update.Asset - r, err = m.GetNewerReleases(args...) - if err != nil { - return err - } - if r == nil { - slog.Info("No upgrades") - return nil - } - // find the tarball for this system - arch := runtime.GOARCH - if runtime.GOARCH == "amd64" { - arch = "x86_64" - } - if runtime.GOOS == "windows" { - a = r.FindZip(runtime.GOOS, arch) - } else { - a = r.FindTarball(runtime.GOOS, arch) - } - if a == nil { - slog.Info("No upgrade for your system") - return nil - } - slog.Info("Downloading release: " + r.Version) - tmpPath, err := a.DownloadProxy(progress.Reader) - if err != nil { - return fmt.Errorf("Download failed: %s", err) - } - slog.Info("Downloaded release to " + tmpPath) - - // install it - if err := m.Install(tmpPath); err != nil { - return fmt.Errorf("install failed, %s", err) - } - slog.Info("Upgraded to " + r.Version) - return nil - }, - } - root.cmd = cmd - return root -} - -type manager struct { - *update.Manager -} - -// GetNewerReleases returns the specified release or latest or releases newer than Version, or nil. -func (m *manager) GetNewerReleases(version ...string) (*update.Release, error) { - if len(version) > 0 && version[0] != "" { - return m.GetRelease(version[0]) - } - // fetch the new releases - releases, err := m.LatestReleases() - if err != nil { - return nil, fmt.Errorf("error fetching releases: %s", err) - } - // no updates - if len(releases) == 0 { - slog.Debug("No upgrades") - return nil, nil - } - - // latest release - return releases[0], nil -} - -type githubStore struct { - Owner string - Repo string - Version string - *github.Client -} - -func NewGithubClient(accessToken string) *github.Client { - var tc *http.Client - - if accessToken != "" { - tc = oauth2.NewClient(context.Background(), oauth2.StaticTokenSource(&oauth2.Token{ - AccessToken: accessToken, - })) - } - return github.NewClient(tc) -} - -// GetRelease returns the specified release or ErrNotFound. -func (s *githubStore) GetRelease(version string) (*update.Release, error) { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - r, res, err := s.Client.Repositories.GetReleaseByTag(ctx, s.Owner, s.Repo, version) - if err != nil { - return nil, err - } - if res.StatusCode == 404 { - return nil, update.ErrNotFound - } - return intoUpdateRelease(r), nil -} - -// LatestReleases returns releases newer, or nil. -func (s *githubStore) LatestReleases() ([]*update.Release, error) { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - - releases, _, err := s.Client.Repositories.ListReleases(ctx, s.Owner, s.Repo, nil) - if err != nil { - return nil, err - } - - latest := make([]*update.Release, 0, len(releases)) - for _, r := range releases { - tag := r.GetTagName() - - if tag == s.Version || tag == strings.TrimPrefix(s.Version, "v") { - break - } - latest = append(latest, intoUpdateRelease(r)) - } - return latest, nil -} - -// intoUpdateRelease returns a Release. -func intoUpdateRelease(r *github.RepositoryRelease) *update.Release { - assets := make([]*update.Asset, 0, len(r.Assets)) - for _, v := range r.Assets { - assets = append(assets, &update.Asset{ - Name: v.GetName(), - Size: v.GetSize(), - URL: v.GetBrowserDownloadURL(), - Downloads: v.GetDownloadCount(), - }) - } - return &update.Release{ - Version: r.GetTagName(), - Notes: r.GetBody(), - PublishedAt: r.GetPublishedAt().Time, - URL: r.GetURL(), - Assets: assets, - } -} diff --git a/cmd/ormat/go.mod b/cmd/ormat/go.mod index 013a60e..d1fbe18 100644 --- a/cmd/ormat/go.mod +++ b/cmd/ormat/go.mod @@ -5,14 +5,10 @@ go 1.22 replace github.com/things-go/ens => ../.. require ( - ariga.io/atlas v0.21.1 - github.com/google/go-github/v58 v58.0.0 - github.com/kierdavis/ansi v0.0.0-20180105022324-90d93b0fcae2 + ariga.io/atlas v0.22.0 github.com/spf13/cobra v1.8.0 github.com/spf13/pflag v1.0.5 github.com/things-go/ens v0.3.1 - github.com/tj/go-update v2.2.5-0.20200519121640-62b4b798fd68+incompatible - golang.org/x/oauth2 v0.18.0 gorm.io/driver/sqlite v1.5.5 gorm.io/gorm v1.25.10 ) @@ -20,37 +16,23 @@ require ( require ( filippo.io/edwards25519 v1.1.0 // indirect github.com/agext/levenshtein v1.2.3 // indirect - github.com/apex/log v1.9.0 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect - github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect - github.com/c4milo/unpackit v0.0.0-20170704181138-4ed373e9ef1c // indirect github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect - github.com/dsnet/compress v0.0.1 // indirect github.com/go-openapi/inflect v0.21.0 // indirect github.com/go-sql-driver/mysql v1.8.1 // indirect - github.com/golang/protobuf v1.5.4 // indirect github.com/google/go-cmp v0.6.0 // indirect - github.com/google/go-querystring v1.1.0 // indirect - github.com/gosuri/uilive v0.0.4 // indirect - github.com/gosuri/uiprogress v0.0.1 // indirect github.com/hashicorp/hcl/v2 v2.20.1 // indirect - github.com/hooklift/assert v0.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgx/v5 v5.5.4 // indirect github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/now v1.1.5 // indirect - github.com/klauspost/compress v1.17.7 // indirect - github.com/klauspost/pgzip v1.2.6 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-sqlite3 v1.14.22 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/pingcap/errors v0.11.5-0.20221009092201-b66cddb77c32 // indirect - github.com/pingcap/failpoint v0.0.0-20220801062533-2eaa32854a6c // indirect + github.com/pingcap/failpoint v0.0.0-20240412033321-fd0796e60f86 // indirect github.com/pingcap/log v1.1.1-0.20230317032135-a0d097d16e22 // indirect github.com/pingcap/tidb/parser v0.0.0-20231013125129-93a834a6bf8d // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/ulikunitz/xz v0.5.11 // indirect github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 // indirect github.com/zclconf/go-cty v1.14.4 // indirect go.uber.org/atomic v1.11.0 // indirect @@ -58,11 +40,9 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/mod v0.17.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - golang.org/x/tools v0.20.0 // indirect - google.golang.org/appengine v1.6.8 // indirect - google.golang.org/protobuf v1.33.0 // indirect + golang.org/x/text v0.15.0 // indirect + golang.org/x/tools v0.21.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gorm.io/datatypes v1.2.0 // indirect gorm.io/driver/mysql v1.5.6 // indirect diff --git a/cmd/ormat/go.sum b/cmd/ormat/go.sum index 2179b2e..7067cf9 100644 --- a/cmd/ormat/go.sum +++ b/cmd/ormat/go.sum @@ -1,5 +1,5 @@ -ariga.io/atlas v0.21.1 h1:Eg9XYhKTH3UHoqP7tKMWFV+Z5JnpVOJCgO3MHrUtKmk= -ariga.io/atlas v0.21.1/go.mod h1:VPlcXdd4w2KqKnH54yEZcry79UAhpaWaxEsmn5JRNoE= +ariga.io/atlas v0.22.0 h1:AUO32g7J3wMFWwhix4X7PlRbOxzQk12udYej6Xnf4xg= +ariga.io/atlas v0.22.0/go.mod h1:VPlcXdd4w2KqKnH54yEZcry79UAhpaWaxEsmn5JRNoE= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -7,32 +7,15 @@ github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20O github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo= github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= -github.com/apex/log v1.9.0 h1:FHtw/xuaM8AgmvDDTI9fiwoAL25Sq2cxojnZICUU8l0= -github.com/apex/log v1.9.0/go.mod h1:m82fZlWIuiWzWP04XCTXmnX0xRkYYbCdYn8jbJeLBEA= -github.com/apex/logs v1.0.0/go.mod h1:XzxuLZ5myVHDy9SAmYpamKKRNApGj54PfYLcFrXqDwo= -github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy8kCu4PNA+aP7WUV72eXWJeP9/r3/K9aLE= -github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= -github.com/aws/aws-sdk-go v1.20.6/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaqKnf+7Qs6GbEPfd4iMOitWzXJx8= -github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8/go.mod h1:spo1JLcs67NmW1aVLEgtA8Yy1elc+X8y5SRW1sFW4Og= -github.com/c4milo/unpackit v0.0.0-20170704181138-4ed373e9ef1c h1:aprLqMn7gSPT+vdDSl+/E6NLEuArwD/J7IWd8bJt5lQ= -github.com/c4milo/unpackit v0.0.0-20170704181138-4ed373e9ef1c/go.mod h1:Ie6SubJv/NTO9Q0UBH0QCl3Ve50lu9hjbi5YJUw03TE= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso= github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548/go.mod h1:e6NPNENfs9mPDVNRekM7lKScauxd5kXTr1Mfyig6TDM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= -github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= -github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-openapi/inflect v0.21.0 h1:FoBjBTQEcbg2cJUWX6uwL9OyIW8eqc9k4KhN4lfbeYk= github.com/go-openapi/inflect v0.21.0/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw= github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= @@ -44,30 +27,10 @@ github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0kt github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EOqtpKwwwHI= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github/v58 v58.0.0 h1:Una7GGERlF/37XfkPwpzYJe0Vp4dt2k1kCjlxwjIvzw= -github.com/google/go-github/v58 v58.0.0/go.mod h1:k4hxDKEfoWpSqFlc8LTpGd9fu2KrV1YAa6Hi6FmDNY4= -github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= -github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= -github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gosuri/uilive v0.0.4 h1:hUEBpQDj8D8jXgtCdBu7sWsy5sbW/5GhuO8KBwJ2jyY= -github.com/gosuri/uilive v0.0.4/go.mod h1:V/epo5LjjlDE5RJUcqx8dbw+zc93y5Ya3yg8tfZ74VI= -github.com/gosuri/uiprogress v0.0.1 h1:0kpv/XY/qTmFWl/SkaJykZXrBBzwwadmW8fRb7RJSxw= -github.com/gosuri/uiprogress v0.0.1/go.mod h1:C1RTYn4Sc7iEyf6j8ft5dyoZ4212h8G1ol9QQluh5+0= github.com/hashicorp/hcl/v2 v2.20.1 h1:M6hgdyz7HYt1UN9e61j+qKJBqR3orTWbI1HKBJEdxtc= github.com/hashicorp/hcl/v2 v2.20.1/go.mod h1:TZDqQ4kNKCbh1iJp99FdPiUaVDDUPivbqxZulxDYqL4= -github.com/hooklift/assert v0.1.0 h1:UZzFxx5dSb9aBtvMHTtnPuvFnBvcEhHTPb9+0+jpEjs= -github.com/hooklift/assert v0.1.0/go.mod h1:pfexfvIHnKCdjh6CkkIZv5ic6dQ6aU2jhKghBlXuwwY= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -84,61 +47,34 @@ github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/ github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= -github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= -github.com/kierdavis/ansi v0.0.0-20180105022324-90d93b0fcae2 h1:2+IYapTz9szRWaC5dFYHV08KNZbQCalXxUKTjJxqt1Q= -github.com/kierdavis/ansi v0.0.0-20180105022324-90d93b0fcae2/go.mod h1:6KRKajh4tzbIPkvCp13swt0c9/lxruYdjz89vuDf3dk= -github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= -github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg= -github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= -github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= -github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= -github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= -github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= -github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.3/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= github.com/microsoft/go-mssqldb v0.17.0/go.mod h1:OkoNGhGEs8EZqchVTtochlXruEhEOaO4S0d2sB5aeGQ= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/pingcap/errors v0.11.0/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pingcap/errors v0.11.5-0.20221009092201-b66cddb77c32 h1:m5ZsBa5o/0CkzZXfXLaThzKuR85SnHHetqBCpzQ30h8= github.com/pingcap/errors v0.11.5-0.20221009092201-b66cddb77c32/go.mod h1:X2r9ueLEUZgtx2cIogM0v4Zj5uvvzhuuiu7Pn8HzMPg= -github.com/pingcap/failpoint v0.0.0-20220801062533-2eaa32854a6c h1:CgbKAHto5CQgWM9fSBIvaxsJHuGP0uM74HXtv3MyyGQ= -github.com/pingcap/failpoint v0.0.0-20220801062533-2eaa32854a6c/go.mod h1:4qGtCB0QK0wBzKtFEGDhxXnSnbQApw1gc9siScUl8ew= +github.com/pingcap/failpoint v0.0.0-20240412033321-fd0796e60f86 h1:3uFyQWvFeByY1OhhmXNP0nYbTXfAv3VRLByp26n1Ppc= +github.com/pingcap/failpoint v0.0.0-20240412033321-fd0796e60f86/go.mod h1:cv98q58yGEqg4gkB3e8n2+8MEW4fo3kPTz6EoQBMG4o= github.com/pingcap/log v1.1.1-0.20230317032135-a0d097d16e22 h1:2SOzvGvE8beiC1Y4g9Onkvu6UmuBBOeWRGQEjJaT/JY= github.com/pingcap/log v1.1.1-0.20230317032135-a0d097d16e22/go.mod h1:DWQW5jICDR7UJh4HtxXSM20Churx4CQL0fwL/SoOSA4= github.com/pingcap/tidb/parser v0.0.0-20231013125129-93a834a6bf8d h1:EHXDxa7eq8vWc2T8cwstlr3A48dx4TvMsCh5Y7z2VZ8= github.com/pingcap/tidb/parser v0.0.0-20231013125129-93a834a6bf8d/go.mod h1:cwq4bKUlftpWuznB+rqNwbN0xy6/i5SL/nYvEKeJn4s= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= -github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= -github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -146,22 +82,9 @@ github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tj/assert v0.0.0-20171129193455-018094318fb0/go.mod h1:mZ9/Rh9oLWpLLDRpvE+3b7gP/C2YyLFYxNmcLnPTMe0= -github.com/tj/assert v0.0.3 h1:Df/BlaZ20mq6kuai7f5z2TvPFiwC3xaWJSDQNiIS3Rk= -github.com/tj/assert v0.0.3/go.mod h1:Ne6X72Q+TB1AteidzQncjw9PabbMp4PBMZ1k+vd1Pvk= -github.com/tj/go-buffer v1.1.0/go.mod h1:iyiJpfFcR2B9sXu7KvjbT9fpM4mOelRSDTbntVj52Uc= -github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0= -github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao= -github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4= -github.com/tj/go-update v2.2.5-0.20200519121640-62b4b798fd68+incompatible h1:guTq1YxwB8XSILkI9q4IrOmrCOS6Hc1L3hmOhi4Swcs= -github.com/tj/go-update v2.2.5-0.20200519121640-62b4b798fd68+incompatible/go.mod h1:waFwwyiAhGey2e+dNoYQ/iLhIcFqhCW7zL/+vDU1WLo= -github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= -github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8= -github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 h1:zzrxE1FKn5ryBNl9eKOeqQ58Y/Qpo3Q9QNxKHX5uzzQ= github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2/go.mod h1:hzfGeIUDq/j97IG+FhNqkowIyEcD88LrW6fyU3K3WqY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -185,77 +108,73 @@ go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/oauth2 v0.18.0 h1:09qnuIAgzdx1XplqJvW6CQqMCtGZykZWcXzPMPUusvI= -golang.org/x/oauth2 v0.18.0/go.mod h1:Wf7knwG0MPoWIMMBgFlEaSUDaKskp0dCfrlJRJXbBi8= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= -golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 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= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= -golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= -golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.20.0 h1:hz/CVckiOxybQvFw6h7b/q80NTr9IUQb4s1IIzW7KNY= -golang.org/x/tools v0.20.0/go.mod h1:WvitBU7JJf6A4jOdg4S1tviW9bhUxkgeCui/0JHctQg= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= +golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM= -google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= -google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/driver/driver.go b/driver/driver.go index 8422608..6bd85fa 100644 --- a/driver/driver.go +++ b/driver/driver.go @@ -2,10 +2,13 @@ package driver import ( "context" + "fmt" + "strings" "sync" "ariga.io/atlas/sql/schema" "github.com/things-go/ens" + "github.com/things-go/ens/proto" ) const ( @@ -18,6 +21,7 @@ var drivers sync.Map type Driver interface { InspectSchema(context.Context, *InspectOption) (*ens.MixinSchema, error) + InspectProto(context.Context, *InspectOption) (*proto.Schema, error) } func RegisterDriver(name string, d Driver) { @@ -27,12 +31,12 @@ func RegisterDriver(name string, d Driver) { drivers.Store(name, d) } -func LoadDriver(name string) (Driver, bool) { +func LoadDriver(name string) (Driver, error) { d, ok := drivers.Load(name) if !ok { - return nil, false + return nil, fmt.Errorf("unsupported schema, only support [%v]", strings.Join(DriverNames(), ", ")) } - return d.(Driver), true + return d.(Driver), nil } func DriverNames() []string { diff --git a/driver/mysql/def_utils.go b/driver/mysql/def_utils.go index 5d023e2..f474d6f 100644 --- a/driver/mysql/def_utils.go +++ b/driver/mysql/def_utils.go @@ -5,6 +5,8 @@ import ( "ariga.io/atlas/sql/schema" "github.com/things-go/ens" "github.com/things-go/ens/internal/sqlx" + "github.com/things-go/ens/proto" + "google.golang.org/protobuf/reflect/protoreflect" ) func autoIncrement(attrs []schema.Attr) bool { @@ -47,3 +49,35 @@ func IntoMixinEntity(tb *schema.Table) ens.MixinEntity { SetIndexes(indexers...). SetForeignKeys(fkers...) } + +func IntoProto(tb *schema.Table) *proto.Message { + // * columns + fields := make([]*proto.MessageField, 0, len(tb.Columns)) + for _, col := range tb.Columns { + goType := intoGoType(col.Type.Raw) + k, n := goType.Type.IntoProtoKind() + cardinality := protoreflect.Required + if col.Type.Null { + cardinality = protoreflect.Optional + } + annotations := make([]string, 0, 8) + if k == protoreflect.Int64Kind || k == protoreflect.Uint64Kind { + annotations = append(annotations, `(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { type: [ INTEGER ] }`) + } + fields = append(fields, &proto.MessageField{ + Cardinality: cardinality, + Type: k, + TypeName: n, + Name: col.Name, + ColumnName: col.Name, + Comment: sqlx.MustComment(col.Attrs), + Annotations: annotations, + }) + } + return &proto.Message{ + Name: tb.Name, + TableName: tb.Name, + Comment: sqlx.MustComment(tb.Attrs), + Fields: fields, + } +} diff --git a/driver/mysql/mysql.go b/driver/mysql/mysql.go index 5741131..bbb7cfe 100644 --- a/driver/mysql/mysql.go +++ b/driver/mysql/mysql.go @@ -3,12 +3,15 @@ package mysql import ( "context" - _ "ariga.io/atlas/sql/mysql" - _ "github.com/go-sql-driver/mysql" - + "ariga.io/atlas/sql/schema" "ariga.io/atlas/sql/sqlclient" + "github.com/things-go/ens" "github.com/things-go/ens/driver" + "github.com/things-go/ens/proto" + + _ "ariga.io/atlas/sql/mysql" + _ "github.com/go-sql-driver/mysql" ) var _ driver.Driver = (*MySQL)(nil) @@ -16,11 +19,7 @@ var _ driver.Driver = (*MySQL)(nil) type MySQL struct{} func (self *MySQL) InspectSchema(ctx context.Context, arg *driver.InspectOption) (*ens.MixinSchema, error) { - client, err := sqlclient.Open(ctx, arg.URL) - if err != nil { - return nil, err - } - schemaes, err := client.InspectSchema(ctx, "", &arg.InspectOptions) + schemaes, err := self.inspectSchema(ctx, arg) if err != nil { return nil, err } @@ -33,3 +32,26 @@ func (self *MySQL) InspectSchema(ctx context.Context, arg *driver.InspectOption) Entities: entities, }, nil } + +func (self *MySQL) InspectProto(ctx context.Context, arg *driver.InspectOption) (*proto.Schema, error) { + schemaes, err := self.inspectSchema(ctx, arg) + if err != nil { + return nil, err + } + messages := make([]*proto.Message, 0, len(schemaes.Tables)) + for _, tb := range schemaes.Tables { + messages = append(messages, IntoProto(tb)) + } + return &proto.Schema{ + Name: schemaes.Name, + Messages: messages, + }, nil +} + +func (self *MySQL) inspectSchema(ctx context.Context, arg *driver.InspectOption) (*schema.Schema, error) { + client, err := sqlclient.Open(ctx, arg.URL) + if err != nil { + return nil, err + } + return client.InspectSchema(ctx, "", &arg.InspectOptions) +} diff --git a/driver/mysql/mysql_test.go b/driver/mysql/mysql_test.go deleted file mode 100644 index 4792de4..0000000 --- a/driver/mysql/mysql_test.go +++ /dev/null @@ -1,18 +0,0 @@ -package mysql - -// func TestXXX(t *testing.T) { -// id := schema.NewColumn("id"). -// SetType(&schema.IntegerType{T: mysql.TypeBigInt}). -// AddAttrs(&mysql.AutoIncrement{}). -// SetComment("主键") -// gender := schema.NewColumn("gender"). -// SetType(&schema.BoolType{T: "tinyint(1)"}). -// SetComment("性别"). -// SetDefault(&schema.Literal{V: "0"}) - -// tb := schema.NewTable("dict"). -// SetComment("字典"). -// SetPrimaryKey(schema.NewPrimaryKey(id, gender)). -// AddColumns(id, gender) - -// } diff --git a/driver/mysql/sql.go b/driver/mysql/sql.go index 2e5065a..c56b051 100644 --- a/driver/mysql/sql.go +++ b/driver/mysql/sql.go @@ -12,6 +12,7 @@ import ( "github.com/things-go/ens" "github.com/things-go/ens/driver" "github.com/things-go/ens/internal/sqlx" + "github.com/things-go/ens/proto" "github.com/xwb1989/sqlparser" ) @@ -20,7 +21,30 @@ var _ driver.Driver = (*SQL)(nil) type SQL struct{} // InspectSchema implements driver.Driver. -func (self *SQL) InspectSchema(_ context.Context, arg *driver.InspectOption) (*ens.MixinSchema, error) { +func (self *SQL) InspectSchema(ctx context.Context, arg *driver.InspectOption) (*ens.MixinSchema, error) { + table, err := self.inspectSchema(ctx, arg) + if err != nil { + return nil, err + } + return &ens.MixinSchema{ + Name: "", + Entities: []ens.MixinEntity{IntoMixinEntity(table)}, + }, nil +} + +// InspectSchema implements driver.Driver. +func (self *SQL) InspectProto(ctx context.Context, arg *driver.InspectOption) (*proto.Schema, error) { + table, err := self.inspectSchema(ctx, arg) + if err != nil { + return nil, err + } + return &proto.Schema{ + Name: "", + Messages: []*proto.Message{IntoProto(table)}, + }, nil +} + +func (self *SQL) inspectSchema(_ context.Context, arg *driver.InspectOption) (*schema.Table, error) { statement, err := sqlparser.Parse(arg.Data) if err != nil { return nil, err @@ -33,14 +57,7 @@ func (self *SQL) InspectSchema(_ context.Context, arg *driver.InspectOption) (*e if stmt.TableSpec == nil { return nil, errors.New("未解析到任何字段") } - table, err := parseSqlTable(stmt) - if err != nil { - return nil, err - } - return &ens.MixinSchema{ - Name: "", - Entities: []ens.MixinEntity{IntoMixinEntity(table)}, - }, nil + return parseSqlTable(stmt) default: return nil, errors.New("不是DDL语句") } diff --git a/driver/mysql/sql_tidb.go b/driver/mysql/sql_tidb.go index fe7840f..1a810e4 100644 --- a/driver/mysql/sql_tidb.go +++ b/driver/mysql/sql_tidb.go @@ -8,6 +8,7 @@ import ( "github.com/things-go/ens" "github.com/things-go/ens/driver" "github.com/things-go/ens/internal/sqlx" + "github.com/things-go/ens/proto" "ariga.io/atlas/sql/mysql" "ariga.io/atlas/sql/schema" @@ -47,6 +48,32 @@ func (self *SQLTidb) InspectSchema(_ context.Context, arg *driver.InspectOption) }, nil } +// InspectSchema implements driver.Driver. +func (self *SQLTidb) InspectProto(_ context.Context, arg *driver.InspectOption) (*proto.Schema, error) { + pr := parser.New() + stmts, _, err := pr.ParseSQL(arg.Data) + if err != nil { + return nil, err + } + + messages := make([]*proto.Message, 0, len(stmts)) + for _, stmt := range stmts { + createStmt, ok := stmt.(*ast.CreateTableStmt) + if !ok { + continue + } + table, err := parserCreateTableStmtTable(createStmt) + if err != nil { + return nil, err + } + messages = append(messages, IntoProto(table)) + } + return &proto.Schema{ + Name: "", + Messages: messages, + }, nil +} + func parserCreateTableStmtTable(stmt *ast.CreateTableStmt) (*schema.Table, error) { table := schema.NewTable(stmt.Table.Name.L) diff --git a/entity_builder.go b/entity_builder.go index 01337be..584a470 100644 --- a/entity_builder.go +++ b/entity_builder.go @@ -53,17 +53,13 @@ func (self *EntityBuilder) Fields() []Fielder { return self.field func (self *EntityBuilder) Indexes() []Indexer { return self.indexes } func (self *EntityBuilder) ForeignKeys() []ForeignKeyer { return self.foreignKeys } func (self *EntityBuilder) Build(opt *Option) *EntityDescriptor { - enableGogo, enableSea := false, false - if opt != nil { - enableGogo, enableSea = opt.EnableGogo, opt.EnableSea - } fielders := self.Fields() fields := make([]*FieldDescriptor, 0, len(fielders)) protoMessages := make([]*ProtoMessage, 0, len(fielders)) for _, fb := range fielders { field := fb.Build(opt) fields = append(fields, field) - protoMessages = append(protoMessages, field.buildProtoMessage(enableGogo, enableSea)) + protoMessages = append(protoMessages, field.buildProtoMessage()) } indexers := self.Indexes() indexes := make([]*IndexDescriptor, 0, len(indexers)) diff --git a/field.go b/field.go index 1802c8c..b8189d6 100644 --- a/field.go +++ b/field.go @@ -1,5 +1,3 @@ -//go:generate go run internal/gen.go - package ens import ( diff --git a/field_protobuf.go b/field_protobuf.go index aa28a6f..7d61796 100644 --- a/field_protobuf.go +++ b/field_protobuf.go @@ -1,7 +1,6 @@ package ens import ( - "fmt" "strings" "github.com/things-go/ens/matcher" @@ -10,40 +9,31 @@ import ( type ProtoMessage struct { DataType string // 数据类型 Name string // 名称 + Optional bool // 是否可选 Comment string // 注释 Annotations []string // 注解 } -func (field *FieldDescriptor) buildProtoMessage(enableGogo, enableSea bool) *ProtoMessage { +func (field *FieldDescriptor) buildProtoMessage() *ProtoMessage { dataType := field.Type.Type.IntoProtoDataType() annotations := make([]string, 0, 16) if field.Type.Type == TypeInt64 || field.Type.Type == TypeUint64 { annotations = append(annotations, `(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { type: [ INTEGER ] }`) } else if field.Type.IsTime() { - if enableGogo { - annotations = append(annotations, `(gogoproto.stdtime) = true`, `(gogoproto.nullable) = false`) - } else { - dataType = "int64" - annotations = append(annotations, `(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { type: [ INTEGER ] }`) - } + dataType = "int64" + annotations = append(annotations, `(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { type: [ INTEGER ] }`) } comment := strings.TrimSuffix(matcher.TrimEnumValue(field.Comment), ",") if comment != "" { comment = "// " + comment } - if field.Column != nil && enableSea { - l := fmt.Sprintf(`// #[seaql(type="%s")]`, field.Column.Definition()) - if comment != "" { - comment = comment + "\n" + l - } else { - comment = l - } - } + return &ProtoMessage{ DataType: dataType, Name: field.Name, + Optional: field.Optional, Comment: comment, Annotations: annotations, } diff --git a/go.mod b/go.mod index 090a182..808221a 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/pingcap/tidb/parser v0.0.0-20231013125129-93a834a6bf8d github.com/xwb1989/sqlparser v0.0.0-20180606152119-120387863bf2 golang.org/x/tools v0.21.0 + google.golang.org/protobuf v1.34.1 gorm.io/datatypes v1.2.0 gorm.io/gorm v1.25.10 gorm.io/plugin/soft_delete v1.2.1 diff --git a/go.sum b/go.sum index e480b70..bba1398 100644 --- a/go.sum +++ b/go.sum @@ -153,6 +153,8 @@ golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58 golang.org/x/tools v0.21.0 h1:qc0xYgIbsSDt9EyWz05J5wfa7LOVW0YTLOXrqdLAWIw= golang.org/x/tools v0.21.0/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 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-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/go_type.go b/go_type.go index de6663b..1189b6c 100644 --- a/go_type.go +++ b/go_type.go @@ -2,9 +2,10 @@ package ens import ( "reflect" + "slices" "strings" - "github.com/things-go/ens/utils" + "google.golang.org/protobuf/reflect/protoreflect" ) var typeNames = [...]string{ @@ -100,6 +101,46 @@ func (t Type) IsValid() bool { return t > TypeInvalid && t < endTypes } +func (t Type) IntoProtoKind() (k protoreflect.Kind, n string) { + switch t { + case TypeBool: + k = protoreflect.BoolKind + n = k.String() + + case TypeInt8, TypeInt16, TypeInt32, TypeInt: + k = protoreflect.Int32Kind + n = k.String() + case TypeInt64: + k = protoreflect.Int64Kind + n = k.String() + case TypeUint8, TypeUint16, TypeUint32, TypeUint: + k = protoreflect.Uint32Kind + n = k.String() + case TypeUint64: + k = protoreflect.Uint64Kind + n = k.String() + case TypeFloat32: + k = protoreflect.FloatKind + n = k.String() + case TypeFloat64: + k = protoreflect.DoubleKind + n = k.String() + case TypeDecimal, TypeString, TypeEnum, TypeJSON, TypeUUID, TypeOther: + k = protoreflect.StringKind + n = k.String() + case TypeBytes: + k = protoreflect.BytesKind + n = k.String() + case TypeTime: + k = protoreflect.MessageKind + n = "google.protobuf.Timestamp" + default: + k = protoreflect.StringKind + n = k.String() + } + return k, n +} + func (t Type) IntoProtoDataType() string { dataType := "" switch t { @@ -168,7 +209,7 @@ func newGoType(t Type, tt reflect.Type) *GoType { Ident: tt.String(), PkgPath: tv.PkgPath(), PkgQualifier: PkgQualifier(tv.String()), - Nullable: utils.Contains([]reflect.Kind{reflect.Slice, reflect.Ptr, reflect.Map}, tt.Kind()), + Nullable: slices.Contains([]reflect.Kind{reflect.Slice, reflect.Ptr, reflect.Map}, tt.Kind()), } } diff --git a/option.go b/option.go index 05ec17c..d4618a2 100644 --- a/option.go +++ b/option.go @@ -7,6 +7,4 @@ type Option struct { DisableNullToPoint bool `yaml:"disableNullToPoint" json:"disableNullToPoint"` // 禁用字段为null时输出指针类型,将输出为sql.Nullxx EnableForeignKey bool `yaml:"enableForeignKey" json:"enableForeignKey"` // 输出外键 Tags map[string]string `yaml:"tags" json:"tags"` // tags标签列表, support smallCamelCase, camelCase, snakeCase, kebab - EnableGogo bool `yaml:"enableGogo" json:"enableGogo"` // 使能用 gogo (仅输出 proto 有效) - EnableSea bool `yaml:"enableSea" json:"enableSea"` // 使能用 seaql (仅输出 proto 有效)} } diff --git a/proto/codegen.go b/proto/codegen.go new file mode 100644 index 0000000..0bed676 --- /dev/null +++ b/proto/codegen.go @@ -0,0 +1,154 @@ +package proto + +import ( + "bytes" + "fmt" + "strings" + + "github.com/things-go/ens/utils" + "golang.org/x/tools/imports" + "google.golang.org/protobuf/reflect/protoreflect" +) + +type CodeGen struct { + buf bytes.Buffer + Messages []*Message // required, proto Message + ByName string // required, 生成名称 + Version string // required, 生成版本 + PackageName string // required, proto 包名 + Options map[string]string // required, proto option + DisableDocComment bool // 禁用doc注释 + DisableBool bool // 禁用bool,使用int32 + DisableTimestamp bool // 禁用google.protobuf.Timestamp,使用int64 +} + +// Bytes returns the CodeBuf's buffer. +func (g *CodeGen) Bytes() []byte { + return g.buf.Bytes() +} + +// FormatSource return formats and adjusts imports contents of the CodeGen's buffer. +func (g *CodeGen) FormatSource() ([]byte, error) { + data := g.buf.Bytes() + if len(data) == 0 { + return data, nil + } + // return format.Source(data) + return imports.Process("", data, nil) +} + +// Write appends the contents of p to the buffer, +func (g *CodeGen) Write(b []byte) (n int, err error) { + return g.buf.Write(b) +} + +// Print formats using the default formats for its operands and writes to the generated output. +// Spaces are added between operands when neither is a string. +// It returns the number of bytes written and any write error encountered. +func (g *CodeGen) Print(a ...any) (n int, err error) { + return fmt.Fprint(&g.buf, a...) +} + +// Printf formats according to a format specifier for its operands and writes to the generated output. +// It returns the number of bytes written and any write error encountered. +func (g *CodeGen) Printf(format string, a ...any) (n int, err error) { + return fmt.Fprintf(&g.buf, format, a...) +} + +// Fprintln formats using the default formats to the generated output. +// Spaces are always added between operands and a newline is appended. +// It returns the number of bytes written and any write error encountered. +func (g *CodeGen) Println(a ...any) (n int, err error) { + return fmt.Fprintln(&g.buf, a...) +} + +func (g *CodeGen) Gen() *CodeGen { + if !g.DisableDocComment { + g.Printf("// Code generated by %s. DO NOT EDIT.\n", g.ByName) + g.Printf("// version: %s\n", g.Version) + g.Println() + } + g.Println(`syntax = "proto3";`) + g.Println() + g.Printf("package %s;\n", g.PackageName) + g.Println() + + if len(g.Options) > 0 { + for k, v := range g.Options { + g.Printf("option %s = \"%s\";\n", k, v) + } + g.Println() + } + + if g.needGoogleProtobufTimestamp(g.Messages) { + g.Println(`import "google/protobuf/timestamp.proto";`) + } + if g.needOpenapiv2Annotation(g.Messages) { + g.Println(`import "protoc-gen-openapiv2/options/annotations.proto";`) + } + g.Println() + + for _, et := range g.Messages { + structName := utils.CamelCase(et.Name) + + g.Printf("// %s %s\n", structName, strings.ReplaceAll(strings.TrimSpace(et.Comment), "\n", "\n// ")) + g.Printf("message %s {\n", structName) + for i, m := range et.Fields { + if m.Comment != "" { + g.Printf("// %s\n", m.Comment) + } + typeName := g.toTypeName(m) + annotation := "" + if len(m.Annotations) > 0 { + annotation = fmt.Sprintf(" [%s]", strings.Join(m.Annotations, ", ")) + } + seq := i + 1 + if m.Cardinality == protoreflect.Required { + g.Printf("%s %s = %d%s;\n", typeName, m.Name, seq, annotation) + } else { + g.Printf("%s %s %s = %d%s;\n", m.Cardinality.String(), typeName, m.Name, seq, annotation) + } + } + g.Println("}") + } + return g +} + +func (g *CodeGen) toTypeName(m *MessageField) string { + switch { + case g.DisableBool && m.Type == protoreflect.BoolKind: + return protoreflect.Int32Kind.String() + case m.Type == protoreflect.MessageKind && m.TypeName == "google.protobuf.Timestamp": + if g.DisableTimestamp { + m.Annotations = append(m.Annotations, `(grpc.gateway.protoc_gen_openapiv2.options.openapiv2_field) = { type: [ INTEGER ] }`) + return protoreflect.Int64Kind.String() + } else { + return m.TypeName + } + default: + return m.Type.String() + } +} + +func (g *CodeGen) needOpenapiv2Annotation(messages []*Message) bool { + for _, msg := range messages { + for _, v := range msg.Fields { + if v.Type == protoreflect.Int64Kind || + g.DisableTimestamp && v.Type == protoreflect.MessageKind && v.TypeName == "google.protobuf.Timestamp" { + return true + } + } + } + return false +} + +func (g *CodeGen) needGoogleProtobufTimestamp(messages []*Message) bool { + for _, msg := range messages { + for _, v := range msg.Fields { + if !g.DisableTimestamp && v.Type == protoreflect.MessageKind && v.TypeName == "google.protobuf.Timestamp" { + return true + } + } + } + return false +} diff --git a/proto/proto.go b/proto/proto.go new file mode 100644 index 0000000..2eb1869 --- /dev/null +++ b/proto/proto.go @@ -0,0 +1,25 @@ +package proto + +import "google.golang.org/protobuf/reflect/protoreflect" + +type MessageField struct { + Cardinality protoreflect.Cardinality // optional, required, or repeated + Type protoreflect.Kind // 类型 + TypeName string // 类型名称 + Name string // 名称, snake or small camel case + ColumnName string // 列名, snake case + Comment string // 注释 + Annotations []string // 注解 +} + +type Message struct { + Name string // 名称, camel case + TableName string // 表名, snake name + Comment string // 注释 + Fields []*MessageField // 字段 +} + +type Schema struct { + Name string + Messages []*Message +} diff --git a/rapier/codegen.go b/rapier/codegen.go new file mode 100644 index 0000000..40a272b --- /dev/null +++ b/rapier/codegen.go @@ -0,0 +1,235 @@ +package rapier + +import ( + "bytes" + "fmt" + "strings" + + "github.com/things-go/ens" + "golang.org/x/tools/imports" +) + +type CodeGen struct { + buf bytes.Buffer + Structs []*Struct // required + PackageName string // required + ModelImportPath string // required + ByName string + Version string + DisableDocComment bool +} + +// Bytes returns the CodeBuf's buffer. +func (g *CodeGen) Bytes() []byte { + return g.buf.Bytes() +} + +// FormatSource return formats and adjusts imports contents of the CodeGen's buffer. +func (g *CodeGen) FormatSource() ([]byte, error) { + data := g.buf.Bytes() + if len(data) == 0 { + return data, nil + } + // return format.Source(data) + return imports.Process("", data, nil) +} + +// Write appends the contents of p to the buffer, +func (g *CodeGen) Write(b []byte) (n int, err error) { + return g.buf.Write(b) +} + +// Print formats using the default formats for its operands and writes to the generated output. +// Spaces are added between operands when neither is a string. +// It returns the number of bytes written and any write error encountered. +func (g *CodeGen) Print(a ...any) (n int, err error) { + return fmt.Fprint(&g.buf, a...) +} + +// Printf formats according to a format specifier for its operands and writes to the generated output. +// It returns the number of bytes written and any write error encountered. +func (g *CodeGen) Printf(format string, a ...any) (n int, err error) { + return fmt.Fprintf(&g.buf, format, a...) +} + +// Fprintln formats using the default formats to the generated output. +// Spaces are always added between operands and a newline is appended. +// It returns the number of bytes written and any write error encountered. +func (g *CodeGen) Println(a ...any) (n int, err error) { + return fmt.Fprintln(&g.buf, a...) +} + +func (g *CodeGen) Get() *CodeGen { + pkgQualifierPrefix := "" + if p := ens.PkgName(g.ModelImportPath); p != "" { + pkgQualifierPrefix = p + "." + } + if !g.DisableDocComment { + g.Printf("// Code generated by %s. DO NOT EDIT.\n", g.ByName) + g.Printf("// version: %s\n", g.Version) + g.Println() + } + g.Printf("package %s\n", g.PackageName) + g.Println() + + //* import + g.Println("import (") + if pkgQualifierPrefix != "" { + g.Printf("\"%s\"\n", g.ModelImportPath) + g.Println() + } + g.Println(`rapier "github.com/thinkgos/gorm-rapier"`) + g.Println(`"gorm.io/gorm"`) + g.Println(")") + + //* struct + for _, et := range g.Structs { + structGoName := et.GoName + tableName := et.TableName + + varRefNative := fmt.Sprintf(`ref_%s_Native`, structGoName) + funcInnerNew := fmt.Sprintf(`new_%s`, structGoName) + { //* var field + g.Printf("var %s = New_%s(\"%s\")\n", varRefNative, structGoName, tableName) + g.Println() + } + + typeNative := fmt.Sprintf("%s_Native", structGoName) + //* type + { + g.Printf("type %s struct {\n", typeNative) + g.Println("refAlias string") + g.Println("refTableName string") + g.Println("ALL rapier.Asterisk") + for _, field := range et.Fields { + g.Printf("%s rapier.%s\n", field.GoName, field.Type.String()) + } + g.Println("}") + g.Println() + } + //* function new_xxx + { + g.Printf("func %s(tableName, alias string) *%s {\n", funcInnerNew, typeNative) + g.Printf("return &%s {\n", typeNative) + g.Println("refAlias: alias,") + g.Println("refTableName: tableName,") + g.Println("ALL: rapier.NewAsterisk(alias),") + for _, field := range et.Fields { + g.Printf("%s: rapier.New%s(alias, \"%s\"),\n", field.GoName, field.Type.String(), field.ColumnName) + } + g.Println("}") + g.Println("}") + g.Println() + } + //* function Ref_xxx + { + g.Printf("// Ref_%s model with TableName `%s`.\n", structGoName, tableName) + g.Println("// NOTE: Don't modify any public field!!!") + g.Printf("func Ref_%s() *%s {\n", structGoName, typeNative) + g.Printf("return %s\n", varRefNative) + g.Println("}") + g.Println() + } + //* function New_xxxx + { + g.Printf("// New_%s new instance.\n", structGoName) + g.Println("// NOTE: Don't modify any public field!!!") + g.Printf("func New_%s(tableName string) *%s {\n", structGoName, typeNative) + g.Printf("return %s(tableName, tableName)\n", funcInnerNew) + g.Println("}") + g.Println() + } + //* method As + { + g.Println("// As alias") + g.Printf("func (x *%[1]s) As(alias string) *%[1]s {\n", typeNative) + g.Printf("return %s(x.refTableName, alias)\n", funcInnerNew) + g.Println("}") + g.Println() + } + //* method Ref_Alias + { + g.Printf("// Ref_Alias hold alias name when call %[1]s_Native.As that you defined.\n", structGoName) + g.Printf("func (x *%s) Ref_Alias() string {\n", typeNative) + g.Println("return x.refAlias") + g.Println("}") + g.Println() + } + // impl TableName interface + { + //* method TableName + g.Printf("// TableName hold table name when call New_%[1]s that you defined.\n", structGoName) + g.Printf("func (x *%s) TableName() string {\n", typeNative) + g.Println("return x.refTableName") + g.Println("}") + g.Println() + } + + //* method New_Executor + { + modelName := pkgQualifierPrefix + structGoName + g.Println("// New_Executor new entity executor which suggest use only once.") + g.Printf("func (*%s) New_Executor(db *gorm.DB) *rapier.Executor[%s] {\n", typeNative, modelName) + g.Printf("return rapier.NewExecutor[%s](db)\n", modelName) + g.Println("}") + g.Println() + } + //* method Select_Expr + { + g.Println("// Select_Expr select model fields") + g.Printf("func (x *%s) Select_Expr() []rapier.Expr {\n", typeNative) + g.Println("return []rapier.Expr{") + for _, field := range et.Fields { + g.Printf("x.%s,\n", field.GoName) + } + g.Println("}") + g.Println("}") + g.Println() + } + + //* method Select_VariantExpr + { + g.Println("// Select_VariantExpr select model fields, but time.Time field convert to timestamp(int64).") + g.Printf("func (x *%s) Select_VariantExpr(prefixes ...string) []rapier.Expr {\n", typeNative) + g.Println("if len(prefixes) > 0 && prefixes[0] != \"\" {") + g.Println("return []rapier.Expr{") + for _, field := range et.Fields { + g.Println(genRapier_SelectVariantExprField(field, true)) + } + g.Println("}") + g.Println("} else {") + g.Println("return []rapier.Expr{") + for _, field := range et.Fields { + g.Println(genRapier_SelectVariantExprField(field, false)) + } + g.Println("}") + g.Println("}") + g.Println("}") + g.Println() + } + } + return g +} + +func genRapier_SelectVariantExprField(field *StructField, hasPrefix bool) string { + goName := field.GoName + + b := &strings.Builder{} + b.Grow(64) + b.WriteString("x.") + b.WriteString(goName) + if field.Type == Time { + b.WriteString(".UnixTimestamp()") + if field.Nullable { + b.WriteString(".IfNull(0)") + } + if !hasPrefix { + fmt.Fprintf(b, ".As(x.%s.ColumnName())", goName) + } + } + if hasPrefix { + fmt.Fprintf(b, ".As(x.%s.FieldName(prefixes...))", goName) + } + b.WriteString(",") + return b.String() +} diff --git a/rapier/rapier.go b/rapier/rapier.go new file mode 100644 index 0000000..401fe37 --- /dev/null +++ b/rapier/rapier.go @@ -0,0 +1,43 @@ +//go:generate stringer -type Type +package rapier + +type Type int + +const ( + Field Type = iota + Bool + Int8 + Int16 + Int32 + Int64 + Int + Uint8 + Uint16 + Uint32 + Uint64 + Uint + Float32 + Float64 + String + Enum + Decimal + Bytes + Time + endType + + JSON = Field + UUID = Field +) + +type StructField struct { + Type Type + GoName string + Nullable bool + ColumnName string +} + +type Struct struct { + GoName string + TableName string + Fields []*StructField +} diff --git a/rapier/type_string.go b/rapier/type_string.go new file mode 100644 index 0000000..f376880 --- /dev/null +++ b/rapier/type_string.go @@ -0,0 +1,42 @@ +// Code generated by "stringer -type Type"; DO NOT EDIT. + +package rapier + +import "strconv" + +func _() { + // An "invalid array index" compiler error signifies that the constant values have changed. + // Re-run the stringer command to generate them again. + var x [1]struct{} + _ = x[Field-0] + _ = x[Bool-1] + _ = x[Int8-2] + _ = x[Int16-3] + _ = x[Int32-4] + _ = x[Int64-5] + _ = x[Int-6] + _ = x[Uint8-7] + _ = x[Uint16-8] + _ = x[Uint32-9] + _ = x[Uint64-10] + _ = x[Uint-11] + _ = x[Float32-12] + _ = x[Float64-13] + _ = x[String-14] + _ = x[Enum-15] + _ = x[Decimal-16] + _ = x[Bytes-17] + _ = x[Time-18] + _ = x[endType-19] +} + +const _Type_name = "FieldBoolInt8Int16Int32Int64IntUint8Uint16Uint32Uint64UintFloat32Float64StringEnumDecimalBytesTimeendType" + +var _Type_index = [...]uint8{0, 5, 9, 13, 18, 23, 28, 31, 36, 42, 48, 54, 58, 65, 72, 78, 82, 89, 94, 98, 105} + +func (i Type) String() string { + if i < 0 || i >= Type(len(_Type_index)-1) { + return "Type(" + strconv.FormatInt(int64(i), 10) + ")" + } + return _Type_name[_Type_index[i]:_Type_index[i+1]] +} diff --git a/tag.go b/tag.go index 461d3a5..3eb31e3 100644 --- a/tag.go +++ b/tag.go @@ -10,7 +10,7 @@ const ( ) func TagName(kind, name string) string { - vv := "" + vv := name switch kind { case TagSmallCamelCase: vv = utils.SmallCamelCase(name) diff --git a/utils/utils.go b/utils/utils.go index 28503d8..0add22d 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -25,13 +25,3 @@ func GetPkgName(path string) string { } return pkgName } - -// Contains reports whether v is present in s. -func Contains[S ~[]E, E comparable](s S, v E) bool { - for i := range s { - if v == s[i] { - return true - } - } - return false -}