Skip to content

Commit

Permalink
Implement \watch command
Browse files Browse the repository at this point in the history
  • Loading branch information
nineinchnick committed Apr 1, 2021
1 parent 35afc3a commit 56dc9d5
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 3 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -564,13 +564,14 @@ Type "help" for help.
(not connected)=> \?
General
\q quit usql
\copyright show usql usage and distribution terms
\drivers display information about available database drivers
\g [FILE] or ; execute query (and send results to file or |pipe)
\gexec execute query and execute each value of the result
\g [FILE] or ; execute query (and send results to file or |pipe)
\gset [PREFIX] execute query and store results in usql variables
\gx as \g, but forces expanded output mode
\q quit usql
\watch [SEC] execute query every SEC seconds
Help
\? [commands] show help on backslash commands
Expand Down
1 change: 1 addition & 0 deletions drivers/completer/completer.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,7 @@ func NewDefaultCompleter(r metadata.Reader) func(db metadata.DB) readline.AutoCo
`\timing`,
`\unset`,
`\w`,
`\watch`,
`\x`,
`\Z`,
},
Expand Down
30 changes: 30 additions & 0 deletions handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,8 @@ func (h *Handler) Execute(ctx context.Context, w io.Writer, res metacmd.Result,
}
f := h.execOnly
switch res.Exec {
case metacmd.ExecWatch:
f = h.execWatch
case metacmd.ExecSet:
f = h.execSet
case metacmd.ExecExec:
Expand Down Expand Up @@ -766,6 +768,34 @@ func (h *Handler) execOnly(ctx context.Context, w io.Writer, prefix, qstr string
return f(ctx, w, prefix, qstr, execParams)
}

// execWatch repeatedly executes a query against the database.
func (h *Handler) execWatch(ctx context.Context, w io.Writer, prefix, qstr string, qtyp bool, execParams map[string]string) error {
sec := 2
if a, ok := execParams["interval"]; ok {
var err error
sec, err = strconv.Atoi(a)
if err != nil {
return text.ErrInvalidValue
}
}
for {
fmt.Fprintf(w, "%s (every %ds)\n", time.Now().Format(time.RFC1123), sec)
err := h.execOnly(ctx, w, prefix, qstr, qtyp, execParams)
if err != nil {
return err
}
watchCtx, cancel := context.WithTimeout(ctx, time.Duration(sec)*time.Second)
<-watchCtx.Done()
cancel()
if err := watchCtx.Err(); err != nil && !errors.Is(err, context.DeadlineExceeded) {
if errors.Is(err, context.Canceled) {
return nil
}
return err
}
}
}

// execSet executes a SQL query, setting all returned columns as variables.
func (h *Handler) execSet(ctx context.Context, w io.Writer, prefix, qstr string, _ bool, execParams map[string]string) error {
// query
Expand Down
8 changes: 8 additions & 0 deletions metacmd/cmds.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ func init() {
"gset": "execute query and store results in " + text.CommandName + " variables,[PREFIX]",
"gx": `as \g, but forces expanded output mode,`,
"crosstabview": "execute query and display results in crosstab,[COLUMNS]",
"watch": "execute query every SEC seconds,[SEC]",
},
Process: func(p *Params) error {
p.Result.Exec = ExecOnly
Expand Down Expand Up @@ -210,6 +211,13 @@ func init() {
break
}
}
case "watch":
p.Result.Exec = ExecWatch
params, err := p.GetAll(true)
if err != nil {
return err
}
p.Result.ParseExecParams(params, "interval")
}
return nil
},
Expand Down
5 changes: 4 additions & 1 deletion metacmd/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,8 @@ const (
ExecExec
// ExecCrosstab indicates execution using crosstabview (\crosstabview).
ExecCrosstab
// ExecWatch indicates repeated execution with a fixed time interval.
ExecWatch
)

// Result is the result of metacmd execution.
Expand All @@ -102,7 +104,8 @@ type Result struct {
Exec ExecType
// ExecParams are accompanying parameters for execution. For ExecPipe, it
// will contain the key pipe with a filename and/or a command. For ExecSet
// it will contain the variable prefix.
// it will contain the variable prefix. For ExecWatch, it will contain
// the time interval value.
ExecParams map[string]string
// Crosstab are the crosstab column parameters.
Crosstab []string
Expand Down

0 comments on commit 56dc9d5

Please sign in to comment.