Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,11 @@ pb sql save "SELECT * FROM backend WHERE status = 500" --name=server-errors
pb sql list
```

SQL queries without an explicit `LIMIT` return at most 500 rows. Add a SQL
`LIMIT` when you need more rows, including with `--output json`; JSON output
does not fetch additional pages. Interactive mode (`-i`) fetches 500-row
windows up to the SQL limit.

OTel fields with dots like `service.name` and `http.status_code` work directly in queries without manual quoting.

## PromQL Workflows
Expand Down
2 changes: 1 addition & 1 deletion cmd/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ func newAgentManifest() agentManifest {
{Command: "pb dataset info <dataset> -o json", Description: "Read dataset statistics and configuration", Scope: "server", Mutates: false, RequiresProfile: true},
{Command: "pb user list -o json", Description: "List users and their roles", Scope: "server", Mutates: false, RequiresProfile: true},
{Command: "pb role list -o json", Description: "List roles and privileges", Scope: "server", Mutates: false, RequiresProfile: true},
{Command: "pb sql run \"<SELECT query>\" --from <time> --to <time> -o json", Description: "Run a read-only SQL query", Scope: "server", Mutates: false, RequiresProfile: true, Constraints: []string{"Use SELECT-only SQL", "Never use --save-as because it creates a saved query"}},
{Command: "pb sql run \"<SELECT query>\" --from <time> --to <time> -o json", Description: "Run a read-only SQL query", Scope: "server", Mutates: false, RequiresProfile: true, Constraints: []string{"Use SELECT-only SQL", "Queries without a SQL LIMIT return at most 500 rows", "An explicit SQL LIMIT is not capped at 500 by pb; choose a reasonable limit to avoid large JSON responses", "Never use --save-as because it creates a saved query"}},
{Command: "pb sql list -o json", Description: "List saved SQL queries without opening the TUI", Scope: "server", Mutates: false, RequiresProfile: true},
{Command: "pb promql run \"<expression>\" --dataset <dataset> -o json", Description: "Run a PromQL query", Scope: "server", Mutates: false, RequiresProfile: true},
{Command: "pb promql labels <dataset> -o json", Description: "List PromQL label names", Scope: "server", Mutates: false, RequiresProfile: true},
Expand Down
9 changes: 7 additions & 2 deletions cmd/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
tea "github.com/charmbracelet/bubbletea"

"github.com/spf13/cobra"
"golang.org/x/term"
)

var (
Expand All @@ -54,7 +55,7 @@ var query = &cobra.Command{
Use: "run [query] [flags]",
Example: " pb sql run \"select * from frontend\" --from=10m --to=now\n pb sql run \"select * from frontend\" -i",
Short: "Run SQL query on a dataset",
Long: "\nRun SQL query on a dataset. Default output format is text.\nUse --output json for JSON output, or -i for interactive table view.",
Long: "\nRun SQL query on a dataset. Default output format is text.\nUse --output json for JSON output, or -i for interactive table view.\nQueries without a SQL LIMIT return at most 500 rows.\nExplicit limits are not capped at 500 by pb; choose a reasonable value.",
Args: cobra.MaximumNArgs(1),
SilenceUsage: true,
PreRunE: PreRunDefaultProfile,
Expand Down Expand Up @@ -180,9 +181,13 @@ func parseTimeStr(s string) (time.Time, error) {
return time.Time{}, fmt.Errorf("unrecognized time format %q (use: now, 10m, 2h, 1d, or RFC3339)", s)
}

// startSpinner prints an animated spinner to stderr while a fetch is in progress.
// startSpinner prints an animated spinner to stderr while a fetch is in progress and stderr is a terminal.
// Call the returned function to stop it and clear the line.
func startSpinner() func() {
if !term.IsTerminal(int(os.Stderr.Fd())) {
return func() {}
}

frames := []string{"|", "/", "-", "\\"}
done := make(chan struct{})
stopped := make(chan struct{})
Expand Down
Loading