Skip to content

Commit e31f898

Browse files
committed
Run arbitraty sql
1 parent 6857dc1 commit e31f898

6 files changed

Lines changed: 360 additions & 27 deletions

File tree

cmd/query/helpers.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
package query
22

33
import (
4+
"errors"
45
"fmt"
56
"strconv"
7+
"time"
8+
9+
"github.com/duneanalytics/cli/output"
10+
"github.com/duneanalytics/duneapi-client-go/dune"
11+
"github.com/duneanalytics/duneapi-client-go/models"
12+
"github.com/spf13/cobra"
613
)
714

815
func parseQueryID(arg string) (int, error) {
@@ -12,3 +19,40 @@ func parseQueryID(arg string) (int, error) {
1219
}
1320
return id, nil
1421
}
22+
23+
func parsePerformance(cmd *cobra.Command) (string, error) {
24+
performance, _ := cmd.Flags().GetString("performance")
25+
if performance != "medium" && performance != "large" {
26+
return "", fmt.Errorf("invalid performance tier %q: must be \"medium\" or \"large\"", performance)
27+
}
28+
return performance, nil
29+
}
30+
31+
func waitAndDisplay(cmd *cobra.Command, exec dune.Execution) error {
32+
resp, err := exec.WaitGetResults(5*time.Second, 60)
33+
if err != nil {
34+
return err
35+
}
36+
37+
if resp.State != "QUERY_STATE_COMPLETED" {
38+
msg := fmt.Sprintf("query execution failed with state %s", resp.State)
39+
if resp.Error != nil {
40+
msg += fmt.Sprintf(": %s", resp.Error.Message)
41+
}
42+
return errors.New(msg)
43+
}
44+
45+
return output.DisplayResults(cmd, resp)
46+
}
47+
48+
func displayExecuteResponse(cmd *cobra.Command, resp *models.ExecuteResponse) error {
49+
w := cmd.OutOrStdout()
50+
switch output.FormatFromCmd(cmd) {
51+
case output.FormatJSON:
52+
return output.PrintJSON(w, resp)
53+
default:
54+
fmt.Fprintf(w, "Execution ID: %s\n", resp.ExecutionID)
55+
fmt.Fprintf(w, "State: %s\n", resp.State)
56+
return nil
57+
}
58+
}

cmd/query/query.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@ func NewQueryCmd() *cobra.Command {
1313
cmd.AddCommand(newUpdateCmd())
1414
cmd.AddCommand(newArchiveCmd())
1515
cmd.AddCommand(newRunCmd())
16+
cmd.AddCommand(newRunSQLCmd())
1617
return cmd
1718
}

cmd/query/run.go

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package query
33
import (
44
"fmt"
55
"strings"
6-
"time"
76

87
"github.com/duneanalytics/cli/cmdutil"
98
"github.com/duneanalytics/cli/output"
@@ -40,9 +39,9 @@ func runRun(cmd *cobra.Command, args []string) error {
4039
return err
4140
}
4241

43-
performance, _ := cmd.Flags().GetString("performance")
44-
if performance != "medium" && performance != "large" {
45-
return fmt.Errorf("invalid performance tier %q: must be \"medium\" or \"large\"", performance)
42+
performance, err := parsePerformance(cmd)
43+
if err != nil {
44+
return err
4645
}
4746

4847
req := models.ExecuteRequest{
@@ -68,15 +67,7 @@ func runNoWait(cmd *cobra.Command, req models.ExecuteRequest) error {
6867
return err
6968
}
7069

71-
w := cmd.OutOrStdout()
72-
switch output.FormatFromCmd(cmd) {
73-
case output.FormatJSON:
74-
return output.PrintJSON(w, resp)
75-
default:
76-
fmt.Fprintf(w, "Execution ID: %s\n", resp.ExecutionID)
77-
fmt.Fprintf(w, "State: %s\n", resp.State)
78-
return nil
79-
}
70+
return displayExecuteResponse(cmd, resp)
8071
}
8172

8273
func runWait(cmd *cobra.Command, req models.ExecuteRequest) error {
@@ -87,20 +78,7 @@ func runWait(cmd *cobra.Command, req models.ExecuteRequest) error {
8778
return err
8879
}
8980

90-
resp, err := exec.WaitGetResults(5*time.Second, 60)
91-
if err != nil {
92-
return err
93-
}
94-
95-
if resp.State != "QUERY_STATE_COMPLETED" {
96-
msg := fmt.Sprintf("query execution failed with state %s", resp.State)
97-
if resp.Error != nil {
98-
msg += fmt.Sprintf(": %s", resp.Error.Message)
99-
}
100-
return fmt.Errorf("%s", msg)
101-
}
102-
103-
return output.DisplayResults(cmd, resp)
81+
return waitAndDisplay(cmd, exec)
10482
}
10583

10684
func parseParams(raw []string) (map[string]any, error) {

cmd/query/run_sql.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package query
2+
3+
import (
4+
"github.com/duneanalytics/cli/cmdutil"
5+
"github.com/duneanalytics/cli/output"
6+
"github.com/duneanalytics/duneapi-client-go/models"
7+
"github.com/spf13/cobra"
8+
)
9+
10+
func newRunSQLCmd() *cobra.Command {
11+
cmd := &cobra.Command{
12+
Use: "run-sql",
13+
Short: "Execute raw SQL and display results",
14+
Args: cobra.NoArgs,
15+
RunE: runRunSQL,
16+
}
17+
18+
cmd.Flags().String("sql", "", "SQL query to execute (required)")
19+
_ = cmd.MarkFlagRequired("sql")
20+
cmd.Flags().StringArray("param", nil, "query parameter in key=value format (repeatable)")
21+
cmd.Flags().String("performance", "medium", `performance tier: "medium" or "large"`)
22+
cmd.Flags().Int("limit", 0, "maximum number of rows to display (0 = all)")
23+
cmd.Flags().Bool("no-wait", false, "submit execution and exit without waiting for results")
24+
output.AddFormatFlag(cmd, "text")
25+
26+
return cmd
27+
}
28+
29+
func runRunSQL(cmd *cobra.Command, _ []string) error {
30+
sql, _ := cmd.Flags().GetString("sql")
31+
32+
paramFlags, _ := cmd.Flags().GetStringArray("param")
33+
params, err := parseParams(paramFlags)
34+
if err != nil {
35+
return err
36+
}
37+
38+
performance, err := parsePerformance(cmd)
39+
if err != nil {
40+
return err
41+
}
42+
43+
req := models.ExecuteSQLRequest{
44+
SQL: sql,
45+
Performance: performance,
46+
}
47+
if len(params) > 0 {
48+
req.QueryParameters = params
49+
}
50+
51+
noWait, _ := cmd.Flags().GetBool("no-wait")
52+
if noWait {
53+
return runSQLNoWait(cmd, req)
54+
}
55+
return runSQLWait(cmd, req)
56+
}
57+
58+
func runSQLNoWait(cmd *cobra.Command, req models.ExecuteSQLRequest) error {
59+
client := cmdutil.ClientFromCmd(cmd)
60+
61+
resp, err := client.SQLExecute(req)
62+
if err != nil {
63+
return err
64+
}
65+
66+
return displayExecuteResponse(cmd, resp)
67+
}
68+
69+
func runSQLWait(cmd *cobra.Command, req models.ExecuteSQLRequest) error {
70+
client := cmdutil.ClientFromCmd(cmd)
71+
72+
exec, err := client.RunSQL(req)
73+
if err != nil {
74+
return err
75+
}
76+
77+
return waitAndDisplay(cmd, exec)
78+
}

0 commit comments

Comments
 (0)