Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cli typing #1253

Closed
wants to merge 7 commits into from
Closed
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
145 changes: 145 additions & 0 deletions cmd/kwil-cli/cmds/call-action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package cmds

import (
"context"
"encoding/json"
"fmt"

"github.com/kwilteam/kwil-db/app/shared/display"
"github.com/kwilteam/kwil-db/cmd/kwil-cli/client"
"github.com/kwilteam/kwil-db/cmd/kwil-cli/config"
clientType "github.com/kwilteam/kwil-db/core/client/types"
"github.com/kwilteam/kwil-db/core/types"
"github.com/spf13/cobra"
)

var (
callActionLong = `TODO: fill me out`

callActionExample = `TODO: fill me out`
)

func callActionCmd() *cobra.Command {
var namespace string
var namedParams []string
var gwAuth, rpcAuth, logs bool

cmd := &cobra.Command{
Use: "call-action",
Short: "Call a view action",
Long: callActionLong,
Example: callActionExample,
RunE: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return display.PrintErr(cmd, fmt.Errorf("no action provided"))
}

tblConf, err := getTableConfig(cmd)
if err != nil {
return display.PrintErr(cmd, err)
}

// positional parameters
var params []any
for _, p := range args[1:] {
_, param, err := parseTypedParam(p)
if err != nil {
return display.PrintErr(cmd, err)
}

params = append(params, param)
}

var dialFlags uint8
if gwAuth {
// if calling kgw, then not only do we need a private key, but we also need to authenticate
dialFlags = client.UsingGateway
}
if rpcAuth {
// if calling a kwil node, then we need to authenticate
dialFlags = dialFlags | client.AuthenticatedCalls
}
if dialFlags == 0 {
// if neither of the above, private key is not required
dialFlags = client.WithoutPrivateKey
}

return client.DialClient(cmd.Context(), cmd, dialFlags, func(ctx context.Context, cl clientType.Client, conf *config.KwilCliConfig) error {
// if named params are specified, we need to query the action to find their positions
if len(namedParams) > 0 {
paramList, err := GetParamList(ctx, cl.Query, namespace, args[0])
if err != nil {
return display.PrintErr(cmd, err)
}

_, values, pos, err := getNamedParams(paramList, namedParams)
if err != nil {
return display.PrintErr(cmd, err)
}
// there is a case where an action has 3 parameters, but only 2 are specified positionally,
// with the 3rd being specified as a named parameter. In this case, we need to ensure that the
// length of params is the same as the length of actionParams
for i, p := range pos {
if p >= len(params) {
params = append(params, make([]any, p-len(params)+1)...)
}

params[p] = values[i]
}
}

res, err := cl.Call(ctx, namespace, args[0], params)
if err != nil {
return display.PrintErr(cmd, err)
}

return display.PrintCmd(cmd, &respCall{Data: res, PrintLogs: logs, tableConf: tblConf})
})
},
}

cmd.Flags().StringVarP(&namespace, "namespace", "n", "", "namespace to execute the action in")
cmd.Flags().StringArrayVarP(&namedParams, "param", "p", nil, "named parameters that will override any positional parameters")
cmd.Flags().BoolVar(&rpcAuth, "rpc-auth", false, "signals that the call is being made to a kwil node and should be authenticated with the private key")
cmd.Flags().BoolVar(&gwAuth, "gateway-auth", false, "signals that the call is being made to a gateway and should be authenticated with the private key")
cmd.Flags().BoolVar(&logs, "logs", false, "result will include logs from notices raised during the call")
bindTableOutputFlags(cmd)

return cmd
}

type respCall struct {
Data *types.CallResult
PrintLogs bool
tableConf *tableConfig
}

func (r *respCall) MarshalJSON() ([]byte, error) {
if !r.PrintLogs {
return json.Marshal(r.Data.QueryResult) // this is for backwards compatibility
}

bts, err := json.Marshal(r.Data)
if err != nil {
return nil, err
}

return bts, nil
}

func (r *respCall) MarshalText() (text []byte, err error) {
if !r.PrintLogs {
return recordsToTable(r.Data.QueryResult.ExportToStringMap(), r.tableConf), nil
}

bts := recordsToTable(r.Data.QueryResult.ExportToStringMap(), r.tableConf)

if len(r.Data.Logs) > 0 {
bts = append(bts, []byte("\n\nLogs:")...)
for _, log := range r.Data.Logs {
bts = append(bts, []byte("\n "+log)...)
}
}

return bts, nil
}
58 changes: 58 additions & 0 deletions cmd/kwil-cli/cmds/common/tx.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package common

import (
"context"
"time"

"github.com/kwilteam/kwil-db/app/shared/display"
client "github.com/kwilteam/kwil-db/core/client/types"
"github.com/kwilteam/kwil-db/core/types"
"github.com/spf13/cobra"
)

// BindTxFlags binds the flags for a transaction.
// It should be used with commands that author transactions.
func BindTxFlags(cmd *cobra.Command) {
cmd.Flags().Int64P("nonce", "N", -1, "nonce override (-1 means request from server)")
cmd.Flags().Bool("sync", false, "synchronous broadcast (wait for it to be included in a block)")
}

type TxFlags struct {
NonceOverride int64
SyncBroadcast bool
}

func GetTxFlags(cmd *cobra.Command) (*TxFlags, error) {
nonce, err := cmd.Flags().GetInt64("nonce")
if err != nil {
return nil, err
}
sync, err := cmd.Flags().GetBool("sync")
if err != nil {
return nil, err
}

return &TxFlags{
NonceOverride: nonce,
SyncBroadcast: sync,
}, nil
}

// DisplayTxResult takes a tx hash and decides whether to wait for it and print the tx result,
// or just print the tx hash. It will display the result of the transaction.
func DisplayTxResult(ctx context.Context, client1 client.Client, txHash types.Hash, cmd *cobra.Command) error {
txFlags, err := GetTxFlags(cmd)
if err != nil {
return display.PrintErr(cmd, err)
}

if len(txHash) > 0 && txFlags.SyncBroadcast {
time.Sleep(500 * time.Millisecond) // otherwise it says not found at first
resp, err := client1.TxQuery(ctx, txHash)
if err != nil {
return display.PrintErr(cmd, err)
}
return display.PrintCmd(cmd, display.NewTxHashAndExecResponse(resp))
}
return display.PrintCmd(cmd, display.RespTxHash(txHash))
}
11 changes: 6 additions & 5 deletions cmd/kwil-cli/cmds/database/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,12 @@ func batchCmd() *cobra.Command {
var inputValueMappings []string // these override the csv column mappings

cmd := &cobra.Command{
Use: "batch <procedure_or_action>",
Short: "Batch execute an action using inputs from a CSV file.",
Long: batchLong,
Example: batchExample,
Args: cobra.NoArgs,
Use: "batch <procedure_or_action>",
Short: "Batch execute an action using inputs from a CSV file.",
Long: batchLong,
Example: batchExample,
Deprecated: `Use "kwil-cli exec-action" instead.`,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return client.DialClient(cmd.Context(), cmd, 0, func(ctx context.Context, cl clientType.Client, conf *config.KwilCliConfig) error {
dbid, _, err := getSelectedNamespace(cmd)
Expand Down
9 changes: 5 additions & 4 deletions cmd/kwil-cli/cmds/database/call.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,11 @@ func callCmd() *cobra.Command {
var gwAuth, logs bool

cmd := &cobra.Command{
Use: "call <procedure_or_action> <parameter_1:value_1> <parameter_2:value_2> ...",
Short: "Call a 'view' action, returning the result.",
Long: callLong,
Example: callExample,
Use: "call <procedure_or_action> <parameter_1:value_1> <parameter_2:value_2> ...",
Short: "Call a 'view' action, returning the result.",
Long: callLong,
Example: callExample,
Deprecated: `Use "kwil-cli call-action" instead.`,
RunE: func(cmd *cobra.Command, args []string) error {
// AuthenticatedCalls specifies that the call should be authenticated with the private key
// if the call is made to the Kwild node with private mode enabled. Else, no authentication is required.
Expand Down
9 changes: 5 additions & 4 deletions cmd/kwil-cli/cmds/database/execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ func executeCmd() *cobra.Command {
var sqlFilepath string

cmd := &cobra.Command{
Use: "execute --sql <sql_stmt> <parameter_1:value_1> <parameter_2:value_2> ...",
Short: "Execute SQL or an action against a database.",
Long: executeLong,
Example: executeExample,
Use: "execute --sql <sql_stmt> <parameter_1:value_1> <parameter_2:value_2> ...",
Short: "Execute SQL or an action against a database.",
Long: executeLong,
Example: executeExample,
Deprecated: `Use "kwil-cli exec-action" or "kwil-cli exec-sql" instead.`,
RunE: func(cmd *cobra.Command, args []string) error {
return client.DialClient(cmd.Context(), cmd, 0, func(ctx context.Context, cl clientType.Client, conf *config.KwilCliConfig) error {
/*
Expand Down
9 changes: 5 additions & 4 deletions cmd/kwil-cli/cmds/database/query.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,11 @@ kwil-cli database query "SELECT * FROM users WHERE age > 25" --name mydb --owner
func queryCmd() *cobra.Command {
fmtConf := tableConfig{}
cmd := &cobra.Command{
Use: `query <select_statement>`,
Short: "Query a database using an ad-hoc SQL SELECT statement.",
Long: queryLong,
Example: queryExample,
Use: `query <select_statement>`,
Short: "Query a database using an ad-hoc SQL SELECT statement.",
Long: queryLong,
Example: queryExample,
Deprecated: `Use "kwil-cli query" instead.`,
RunE: func(cmd *cobra.Command, args []string) error {
return client.DialClient(cmd.Context(), cmd, client.WithoutPrivateKey,
func(ctx context.Context, client clientType.Client, conf *config.KwilCliConfig) error {
Expand Down
Loading