diff --git a/cmd/explain.go b/cmd/explain.go index 8dc0b1b..ad6a9c7 100644 --- a/cmd/explain.go +++ b/cmd/explain.go @@ -228,9 +228,9 @@ var explainCmd = &cobra.Command{ return err } - list, err := service.Explains(ctx, []string{sql}, expOpt, fiOpt) + exp, err := service.Explain(ctx, sql, expOpt, fiOpt) if err == nil { - view.RenderExplains(list, false) + view.RenderExplain(exp, false) } return err }() diff --git a/cmd/root.go b/cmd/root.go index c753302..2ecb519 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -39,7 +39,7 @@ to quickly create a Cobra application.`, Run: func(cmd *cobra.Command, args []string) { versionFlag, err := cmd.Flags().GetBool("version") if err == nil && versionFlag { - fmt.Println("1.0.1") + fmt.Println("1.0.2") } }, } @@ -61,5 +61,5 @@ func init() { // Cobra also supports local flags, which will only run // when this action is called directly. - rootCmd.Flags().BoolP("version", "", true, "version") + rootCmd.Flags().BoolP("version", "v", true, "version") } diff --git a/service/explain.go b/service/explain.go index b88a59e..79a9d59 100644 --- a/service/explain.go +++ b/service/explain.go @@ -17,7 +17,7 @@ func ExplainChannels( exCh := make(chan *model.ExplainInfo) errCh := make(chan error) - option.TableMap = GetTableDBMap(ctx) // TODO: ここでやるべき? + option.TableMap = GetTableDBMap(ctx) go func() { defer func() { @@ -51,27 +51,31 @@ func ExplainChannels( return exCh, errCh } -// Explains execute explain queries -func Explains( +// Explain execute explain query +func Explain( ctx context.Context, - queries []string, + query string, option *model.ExplainOption, fi *model.ExplainFilter, -) ([]*model.ExplainInfo, error) { - infos := make([]*model.ExplainInfo, 0) +) (*model.ExplainInfo, error) { + expIno := new(model.ExplainInfo) - option.TableMap = GetTableDBMap(ctx) // TODO: ここでやるべき? + option.TableMap = GetTableDBMap(ctx) if err := openAdditonal(ctx, GetDBInfo(ctx)); err != nil { - return infos, err + return expIno, err } - infos, err := exeExplains(ctx, queries, option) + exp, err := exeExplainOne(ctx, query, option) if err != nil { - return infos, err + return expIno, err } - return filterResults(infos, fi), nil + if !getAdditionalFlgInFilterResult(exp, fi) { + return expIno, nil + } + + return exp, nil } func openAdditonal(ctx context.Context, dbi *model.DBInfo) error { @@ -86,69 +90,45 @@ func openAdditonal(ctx context.Context, dbi *model.DBInfo) error { return nil } -func exeExplains( - ctx context.Context, queries []string, option *model.ExplainOption, -) ([]*model.ExplainInfo, error) { - - list := []*model.ExplainInfo{} +func exeExplainOne( + ctx context.Context, query string, option *model.ExplainOption, +) (*model.ExplainInfo, error) { - queryMap := map[string]*model.SQLInfo{} + expInfo := new(model.ExplainInfo) - for _, q := range queries { - // SQL Parse - info, err := getSQLInfo(ctx, q) - if err != nil { - if option.NoError { - if ErrCode(err) == int(SQLParseError) { - continue - } - } + // SQL Parse + info, err := getSQLInfo(ctx, query) + if err != nil { + if !option.NoError || ErrCode(err) != int(SQLParseError) { return nil, err } - if info.Table == "" { - continue - } - - // uniqフラグ指定の場合、重複SQLの除外 - if _, ok := queryMap[info.PrepareSQL]; ok && option.Uniq { - continue - } - queryMap[info.PrepareSQL] = info - - if option.UseTableMap { - for _, db := range option.TableMap[info.Table] { - // Explain実行 - expInfo, err := exeExplain(ctx, db, q, info.PrepareSQL) - if err != nil { - if option.NoError { - if ErrCode(err) == int(ExeExplainError) { - continue - } - } - return nil, err - } + } + if info.Table == "" { + return expInfo, nil + } - list = append(list, expInfo) - } - } else { + if option.UseTableMap { + for _, db := range option.TableMap[info.Table] { // Explain実行 - db := option.DB - expInfo, err := exeExplain(ctx, db, q, info.PrepareSQL) + expInfo, err = exeExplain(ctx, db, query, info.PrepareSQL) if err != nil { - if option.NoError { - if ErrCode(err) == int(ExeExplainError) { - continue - } + if !option.NoError || ErrCode(err) != int(ExeExplainError) { + return nil, err } + } + } + } else { + // Explain実行 + db := option.DB + expInfo, err = exeExplain(ctx, db, query, info.PrepareSQL) + if err != nil { + if !option.NoError || ErrCode(err) != int(ExeExplainError) { return nil, err } - - list = append(list, expInfo) } - } - return list, nil + return expInfo, nil } func exeExplainChannels( @@ -241,26 +221,11 @@ func exeExplain(ctx context.Context, db, sql, prepareSQL string) (*model.Explain }, nil } -func filterResults(infos []*model.ExplainInfo, fi *model.ExplainFilter) []*model.ExplainInfo { - +func getAdditionalFlgInFilterResult(info *model.ExplainInfo, fi *model.ExplainFilter) bool { if fi == (&model.ExplainFilter{}) { - return infos + return true } - list := make([]*model.ExplainInfo, 0, len(infos)) - - for _, info := range infos { - - if !getAdditionalFlgInFilterResult(info, fi) { - continue - } - list = append(list, info) - } - - return list -} - -func getAdditionalFlgInFilterResult(info *model.ExplainInfo, fi *model.ExplainFilter) bool { add := true for i, exp := range info.Values { diff --git a/view/render.go b/view/render.go index e44fd90..4d734e3 100644 --- a/view/render.go +++ b/view/render.go @@ -30,17 +30,13 @@ var optionHeader []string = []string{ "value", } -// RenderExplains render expl results -func RenderExplains(infos []*model.ExplainInfo, isParseEnable bool) { - - for _, info := range infos { - RenderExplain(info, isParseEnable) - } -} - // RenderExplain render expl result func RenderExplain(info *model.ExplainInfo, isParseEnable bool) { + if info == nil || len(info.Values) == 0 { + return + } + headerDatas := make([][]string, 0, 3) headerDatas = append(headerDatas, []string{"DataBase:", info.DataBase}) if isParseEnable {