func parseOthersFlagsForRunContext(ctx *cli.Context, ctxRun *action.Context) error { if ctx.IsSet("format") { format := ctx.String("format") subformat := "" //TODO: refactor it! if strings.Contains(format, "raw:") { subformat = format[len("raw:"):] format = "raw" } if strings.Contains(format, "table:") { subformat = format[len("table:"):] format = "table" } if strings.Contains(format, "json:") { subformat = format[len("json:"):] format = "json" } if strings.Contains(format, "xml:") { subformat = format[len("xml:"):] format = "xml" } switch format { case "table", "raw", "json", "xml": ctxRun.Set("format", format) ctxRun.Set("subformat", subformat) break default: return fmt.Errorf("Unknown format:%s", format) } } else { ctxRun.Set("format", "raw") } if ctx.IsSet("timeout") { ctxRun.Set("timeout", ctx.Int("timeout")) } if ctx.IsSet("commit") { ctxRun.Set("commit", ctx.Bool("commit")) } return nil }
//SelectBefore trigger before for select action func SelectBefore(dbs []db.Database, ctx *action.Context) error { // Prepare data in ctx.datasets logger.Trace.Println("SelectBefore") format := ctx.Get("format") subformat := ctx.GetDef("subformat", "").(string) datasets := dataset.NewColllection() chanHdr := make(chanHeader) chandata := make(chanData) chanDone := make(chan bool) ctx.Set("chanheader", chanHdr) ctx.Set("chandata", chandata) ctx.Set("chandone", chanDone) ctx.Set("datasets", datasets) line := 0 go func() { for { select { case hdr := <-chanHdr: ds := datasets.GetOrCreateDataset(hdr.Code) ds.AddColumns(hdr.Columns...) case cudata := <-chandata: line++ ds := datasets.GetOrCreateDataset(cudata.Code) ds.Append(cudata.Data) if format == "raw" { fmt.Println(formatRaw(subformat, ds.RowsCount(), line, ds.GetColumnsNames(), cudata.Data)) } case <-chanDone: logger.Trace.Println("SelectBefore do done") return } } }() return nil }
//Run concrete action for all databases func Run(dbs []db.Database, sql *sqlcommand.SQLCommand, act action.Actioner, ctx *action.Context, pget parametergetter.ParameterGetter) (*action.Context, error) { logger.Trace.Println("rdb run") defer logger.Trace.Println("rdb run done") ctx.Set("params", pget) ctx.Set("silent", pget.GetDef(parametergetter.Silent, false).(bool)) ctx.Snap.Start() colParams, err := parameters.GetInstance().All() if err != nil { return nil, err } ctx.Set("Params", colParams.Get()) for _, d := range dbs { err := runItem(d, sql, act, ctx, pget) if err != nil { logger.Error.Println(err) //todo: в общий список ошибок } } wg.Wait() ctx.Snap.Done(nil) return ctx, nil }
func runItem(d db.Database, s *sqlcommand.SQLCommand, doaction action.Actioner, ctx *action.Context, pget parametergetter.ParameterGetter) error { logger.Trace.Println("runItem") defer logger.Trace.Println(d.Code, "runItem done") if s != nil { logger.Trace.Println(d.Code, s.Script) } wg.Add(1) ctx.IncInt("exec", 1) params := ctx.Get("Params").([]parameters.Parameter) go func() { timeout := ctx.GetDef("timeout", 0).(int) defer wg.Done() var ( ctxExec context.Context cancel context.CancelFunc ) ch := make(chan bool) if timeout > 0 { ctxExec, cancel = context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) } else { ctxExec, cancel = context.WithCancel(context.Background()) } defer cancel() localCtx := action.NewContext() go func() { defer func() { ch <- true close(ch) }() ctx.Set("context"+d.Code, localCtx) ctx.Set("iscancel", ch) localCtx.Snap.Start() localCtx.Set("success", false) connectionString, e := paramsreplace.Replace(d.ConnectionString, params) if e != nil { ctx.IncInt("failed", 1) logger.Error.Println(e) return } logger.Debug.Println(d.Code, "Connection string:", connectionString) connection, err := rdb.Open(d.Engine, connectionString) if err != nil { ctx.IncInt("failed", 1) logger.Error.Println(d.Code, err) return } defer func() { if err := connection.Close(); err != nil { panic(err) } else { logger.Trace.Printf("%s disconnected", d.Code) } }() err = doaction(d, connection, s, ctx) if err != nil { if err.Error() != "cancel" { ctx.IncInt("failed", 1) localCtx.Snap.Done(err) logger.Error.Println(d.Code, err) if !ctx.GetDef("silent", false).(bool) { fmt.Fprintf(os.Stdout, "%s: %s\n", d.Code, strings.Replace(err.Error(), "\n", " ", -1)) } } return } localCtx.Set("success", true) ctx.IncInt("success", 1) localCtx.Snap.Done(nil) runtime.Gosched() }() select { case <-ch: logger.Trace.Println("operation done w/o timeout") return case <-ctxExec.Done(): err := ctxExec.Err() logger.Trace.Printf("operation done: %s\n", err) ctx.IncInt("failed", 1) localCtx.Snap.Done(err) logger.Error.Println(d.Code, err) // ch <- true return } }() return nil }
func doOutputTable(dbs []db.Database, ctx *action.Context) error { datasets := ctx.Get("datasets").(*dataset.CollectionDataset) table := fmttab.New("", fmttab.BorderThin, nil) table.AddColumn("_CODE_", 10, fmttab.AlignLeft) ctx.Set("table", table) for _, col := range datasets.GetUniqueColumnsNames() { table.AddColumn(col, 15, fmttab.AlignLeft) } for _, ds := range datasets.GetDatasets() { for _, row := range ds.Rows { table.AppendData(row.GetDataMap()) } } pget := ctx.Get("params").(parametergetter.ParameterGetter) if pget.GetDef(parametergetter.AutoFitWidthColumns, true).(bool) { //todo: move into fmttab cols := table.Columns.ColumnsVisible() for c, col := range cols { max := utf8.RuneCountInString(col.Name) for i := 0; i < len(table.Data); i++ { val, ok := table.Data[i][col.Name] if ok && val != nil { fval := fmt.Sprintf("%v", val) l := utf8.RuneCountInString(fval) if l > max { max = l } } } if max != 0 { cols[c].Width = max } } } switch pget.GetDef(parametergetter.BorderTable, "").(string) { case "Thin": table.SetBorder(fmttab.BorderThin) case "Double": table.SetBorder(fmttab.BorderDouble) case "None": table.SetBorder(fmttab.BorderNone) case "Simple": table.SetBorder(fmttab.BorderSimple) } tabex.SetTableSubFormat(table, ctx.GetDef("subformat", "").(string)) if pget.GetDef(parametergetter.Fit, true).(bool) { if e := termbox.Init(); e != nil { return e } tw, _ := termbox.Size() table.AutoSize(true, tw) termbox.Close() } if _, err := table.WriteTo(os.Stdout); err != nil { return err } return nil }