From da3c16de153ce0e709c91b97d9ac1b95a1d7baba Mon Sep 17 00:00:00 2001 From: Kenneth Shaw Date: Mon, 10 Jun 2024 11:48:00 +0700 Subject: [PATCH] Rough in \chart command --- handler/handler.go | 12 +++++++++--- metacmd/cmds.go | 3 +++ metacmd/types.go | 2 ++ run.go | 26 ++++++++++++-------------- 4 files changed, 26 insertions(+), 17 deletions(-) diff --git a/handler/handler.go b/handler/handler.go index d65e940e29e..6c12e9baa6f 100644 --- a/handler/handler.go +++ b/handler/handler.go @@ -429,6 +429,8 @@ func (h *Handler) Execute(ctx context.Context, w io.Writer, opt metacmd.Option, f = h.doExecSet case metacmd.ExecWatch: f = h.doExecWatch + case metacmd.ExecChart: + f = h.doExecChart } if err = drivers.WrapErr(h.u.Driver, f(ctx, w, opt, prefix, sqlstr, qtyp, bind)); err != nil { if forceTrans { @@ -1031,6 +1033,11 @@ func (h *Handler) doExecWatch(ctx context.Context, w io.Writer, opt metacmd.Opti } } +// doExecChart executes a single query against the database, displaying its output as a chart. +func (h *Handler) doExecChart(ctx context.Context, w io.Writer, opt metacmd.Option, prefix, sqlstr string, qtyp bool, bind []interface{}) error { + return nil +} + // doExecSingle executes a single query against the database based on its query type. func (h *Handler) doExecSingle(ctx context.Context, w io.Writer, opt metacmd.Option, prefix, sqlstr string, qtyp bool, bind []interface{}) error { // exec or query @@ -1158,12 +1165,11 @@ func (h *Handler) doQuery(ctx context.Context, w io.Writer, opt metacmd.Option, case drivers.UseColumnTypes(h.u): extra = append(extra, tblfmt.WithUseColumnTypes(true)) } - // wrap query with crosstab resultSet := tblfmt.ResultSet(rows) + // wrap query with crosstab if opt.Exec == metacmd.ExecCrosstab { var err error - resultSet, err = tblfmt.NewCrosstabView(rows, append(extra, tblfmt.WithParams(opt.Crosstab...))...) - if err != nil { + if resultSet, err = tblfmt.NewCrosstabView(rows, append(extra, tblfmt.WithParams(opt.Crosstab...))...); err != nil { return err } extra = nil diff --git a/metacmd/cmds.go b/metacmd/cmds.go index c00784a679c..825b0ea5191 100644 --- a/metacmd/cmds.go +++ b/metacmd/cmds.go @@ -249,6 +249,7 @@ func init() { {"gexec", "", "execute query and execute each value of the result"}, {"gset", "[PREFIX]", "execute query and store results in " + text.CommandName + " variables"}, {"crosstabview", "[(OPTIONS)] [COLUMNS]", "execute query and display results in crosstab"}, + {"chart", "CHART [(OPTIONS)]", "execute query and display results as a chart"}, {"watch", "[(OPTIONS)] [DURATION]", "execute query every specified interval"}, }, Process: func(p *Params) error { @@ -295,6 +296,8 @@ func init() { break } } + case "chart": + p.Option.Exec = ExecChart case "watch": p.Option.Exec = ExecWatch p.Option.Watch = 2 * time.Second diff --git a/metacmd/types.go b/metacmd/types.go index e356e1ed94b..2b7d3b1ab79 100644 --- a/metacmd/types.go +++ b/metacmd/types.go @@ -99,6 +99,8 @@ const ( ExecExec // ExecCrosstab indicates execution using crosstabview (\crosstabview). ExecCrosstab + // ExecChart indicates execution using chart (\chart). + ExecChart // ExecWatch indicates repeated execution with a fixed time interval. ExecWatch ) diff --git a/run.go b/run.go index e9d6cecdd08..3e8eb8c3d36 100644 --- a/run.go +++ b/run.go @@ -237,21 +237,19 @@ func Run(ctx context.Context, args *Args, connections map[string]interface{}, in cygwin := isatty.IsCygwinTerminal(os.Stdout.Fd()) && isatty.IsCygwinTerminal(os.Stdin.Fd()) forceNonInteractive := len(args.CommandOrFiles) != 0 - /* - // enable term graphics - if !forceNonInteractive && interactive && !cygwin { - // NOTE: this is done here and not in the env.init() package, because - // NOTE: we need to determine if it is interactive first, otherwise it - // NOTE: could mess up the non-interactive output with control characters - var typ string - if s, _ := env.Getenv(text.CommandUpper()+"_TERM_GRAPHICS", "TERM_GRAPHICS"); s != "" { - typ = s - } - if err := env.Set("TERM_GRAPHICS", typ); err != nil { - return err - } + // enable term graphics + if !forceNonInteractive && interactive && !cygwin { + // NOTE: this is done here and not in the env.init() package, because + // NOTE: we need to determine if it is interactive first, otherwise it + // NOTE: could mess up the non-interactive output with control characters + var typ string + if s, _ := env.Getenv(text.CommandUpper()+"_TERM_GRAPHICS", "TERM_GRAPHICS"); s != "" { + typ = s } - */ + if err := env.Set("TERM_GRAPHICS", typ); err != nil { + return err + } + } // configured named connections for name, v := range connections {