From bda6aaf41e7ce7769332f68922d0192fd3097615 Mon Sep 17 00:00:00 2001 From: Nitish Tiwari Date: Mon, 13 Nov 2023 14:13:24 +0530 Subject: [PATCH] Fix issue with query where any query with 'where' clause panicked This PR fixes the nil pointer issue for queries containing where clause. Also fixes some help messages to be at par with other messages. Also update the goreleaser config to ensure 'v' is added in published release versions. --- .goreleaser.yml | 2 +- cmd/query.go | 6 ++--- cmd/role.go | 4 +-- cmd/tail.go | 2 +- pkg/model/query.go | 63 ++++++++++++++++++++++++++-------------------- 5 files changed, 43 insertions(+), 34 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index d3cfce4..2d6cf18 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -17,7 +17,7 @@ builds: - -trimpath - -tags=kqueue ldflags: - - -s -w -X main.Version={{ .Version }} -X main.Commit={{ .ShortCommit }} + - -s -w -X main.Version=v{{ .Version }} -X main.Commit={{ .ShortCommit }} archives: - format: tar.gz diff --git a/cmd/query.go b/cmd/query.go index 1a63a1a..665911e 100644 --- a/cmd/query.go +++ b/cmd/query.go @@ -46,7 +46,7 @@ var query = &cobra.Command{ Use: "query [query] [flags]", Example: " pb query \"select * from frontend\" --from=10m --to=now", Short: "Run SQL query on a log stream", - Long: "\nqRun SQL query on a log stream. Default output format is json. Use -i flag to open interactive table view.", + Long: "\nRun SQL query on a log stream. Default output format is json. Use -i flag to open interactive table view.", Args: cobra.MaximumNArgs(1), PreRunE: PreRunDefaultProfile, RunE: func(command *cobra.Command, args []string) error { @@ -72,7 +72,7 @@ var query = &cobra.Command{ start = defaultStart } - end, _ := command.Flags().GetString(endFlag) + end, err := command.Flags().GetString(endFlag) if err != nil { return err } @@ -80,7 +80,7 @@ var query = &cobra.Command{ end = defaultEnd } - interactive, _ := command.Flags().GetBool(interactiveFlag) + interactive, err := command.Flags().GetBool(interactiveFlag) if err != nil { return err } diff --git a/cmd/role.go b/cmd/role.go index 107701b..1e6b4ce 100644 --- a/cmd/role.go +++ b/cmd/role.go @@ -62,8 +62,8 @@ func (user *RoleData) Render() string { } var AddRoleCmd = &cobra.Command{ - Use: "upsert role-name", - Example: " pb role upsert ingestors", + Use: "add role-name", + Example: " pb role add ingestors", Short: "Add a new role", Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { diff --git a/cmd/tail.go b/cmd/tail.go index cc5e387..736629e 100644 --- a/cmd/tail.go +++ b/cmd/tail.go @@ -35,7 +35,7 @@ import ( var TailCmd = &cobra.Command{ Use: "tail stream-name", Example: " pb tail backend_logs", - Short: "tail a log stream", + Short: "Stream live events from a log stream", Args: cobra.ExactArgs(1), PreRunE: PreRunDefaultProfile, RunE: func(cmd *cobra.Command, args []string) error { diff --git a/pkg/model/query.go b/pkg/model/query.go index 5b40b77..3c0a7f0 100644 --- a/pkg/model/query.go +++ b/pkg/model/query.go @@ -25,7 +25,6 @@ import ( "os" "pb/pkg/config" "pb/pkg/iterator" - "regexp" "strings" "sync" "time" @@ -167,33 +166,31 @@ func createIteratorFromModel(m *QueryModel) *iterator.QueryIterator[QueryData, F startTime = startTime.Truncate(time.Minute) endTime = endTime.Truncate(time.Minute).Add(time.Minute) - regex := regexp.MustCompile(`^select\s+(?:\*|\w+(?:,\s*\w+)*)\s+from\s+(\w+)(?:\s+;)?$`) - matches := regex.FindStringSubmatch(m.query.Value()) - if matches == nil { - return nil + table := streamNameFromQuery(m.query.Value()) + if table != "" { + iter := iterator.NewQueryIterator( + startTime, endTime, + false, + func(t1, t2 time.Time) (QueryData, FetchResult) { + client := &http.Client{ + Timeout: time.Second * 50, + } + return fetchData(client, &m.profile, m.query.Value(), t1.UTC().Format(time.RFC3339), t2.UTC().Format(time.RFC3339)) + }, + func(t1, t2 time.Time) bool { + client := &http.Client{ + Timeout: time.Second * 50, + } + res, err := fetchData(client, &m.profile, "select count(*) as count from "+table, m.timeRange.StartValueUtc(), m.timeRange.EndValueUtc()) + if err == fetchErr { + return false + } + count := res.Records[0]["count"].(float64) + return count > 0 + }) + return &iter } - table := matches[1] - iter := iterator.NewQueryIterator( - startTime, endTime, - false, - func(t1, t2 time.Time) (QueryData, FetchResult) { - client := &http.Client{ - Timeout: time.Second * 50, - } - return fetchData(client, &m.profile, m.query.Value(), t1.UTC().Format(time.RFC3339), t2.UTC().Format(time.RFC3339)) - }, - func(t1, t2 time.Time) bool { - client := &http.Client{ - Timeout: time.Second * 50, - } - res, err := fetchData(client, &m.profile, "select count(*) as count from "+table, m.timeRange.StartValueUtc(), m.timeRange.EndValueUtc()) - if err == fetchErr { - return false - } - count := res.Records[0]["count"].(float64) - return count > 0 - }) - return &iter + return nil } func NewQueryModel(profile config.Profile, queryStr string, startTime, endTime time.Time) QueryModel { @@ -653,3 +650,15 @@ func countDigits(num int) int { numDigits := int(math.Log10(math.Abs(float64(num)))) + 1 return numDigits } + +func streamNameFromQuery(query string) string { + stream := "" + tokens := strings.Split(query, " ") + for i, token := range tokens { + if token == "from" { + stream = tokens[i+1] + break + } + } + return stream +}