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
9 changes: 6 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,11 @@ Flags:
--jq-input-mode="eager" How query rows are passed to jq (json/yaml
only): eager (full ResultSet), lazy (JQValue
root).
--param=PARAM,... [name]=[type or literal]; legacy [name]:[...]
also accepted
--param=PARAM One [name]=[type or literal] assignment.
Repeat the flag for more parameters. Legacy
[name]:[...] is accepted. Commas stay inside
the value; one flag is not split into several
assignments.
--param-file=STRING YAML or JSON file of query parameters (name
to type/literal string)
--log-grpc gRPC logging: --log-grpc means payload;
Expand Down Expand Up @@ -256,7 +259,7 @@ $ execspansql ${DATABASE_ID} --query-mode=PROFILE --discard-results \
Many Cloud Spanner clients don't support parameter.
Without modifications, query which have parameters are impossible to execute and query whose parameters' types are `STRUCT` or `ARRAY` are impossible to show query plans.

execspansql supports query parameters via repeated `--param name=value` flags (legacy `name:value` is also accepted) or a `--param-file` (YAML or JSON). When both are given, `--param` overrides entries from the file.
execspansql supports query parameters via repeated `--param name=value` flags (legacy `name:value` is also accepted) or a `--param-file` (YAML or JSON). Each `--param` is one assignment: a comma inside an ARRAY, STRUCT, or string literal is kept. The former shorthand `--param=n=1,m=2` is not split into two parameters; pass `--param=n=1 --param=m=2` instead. When both a file and flags are given, `--param` overrides entries from the file.

#### PLAN with complex typed parameters

Expand Down
2 changes: 1 addition & 1 deletion main.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ type opts struct {
JqRawOutput bool `name:"raw-output" short:"r" help:"(--raw-output of jq)"`
JqFromFile string `name:"filter-file" xor:"filter" help:"(--from-file of jq)"`
JqInputMode string `name:"jq-input-mode" enum:"eager,lazy" default:"eager" help:"How query rows are passed to jq (json/yaml only): eager (full ResultSet), lazy (JQValue root)."`
ParamFlags []string `name:"param" help:"[name]=[type or literal]; legacy [name]:[...] also accepted"`
ParamFlags []string `name:"param" sep:"none" help:"One [name]=[type or literal] assignment. Repeat the flag for more parameters. Legacy [name]:[...] is accepted. Commas stay inside the value; one flag is not split into several assignments."`
ParamFile string `name:"param-file" help:"YAML or JSON file of query parameters (name to type/literal string)"`
LogGrpc logGrpcFlag `name:"log-grpc" enum:"off,metadata,payload" default:"off" help:"gRPC logging: --log-grpc means payload; use --log-grpc=off|metadata|payload to select a mode (payload may include request and response payloads)"`
TraceProject string `name:"experimental-trace-project" xor:"trace" help:"Export traces to Cloud Trace in the given project."`
Expand Down
41 changes: 41 additions & 0 deletions param_cli_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package main

import (
"strings"
"testing"
)

func TestParamFlagKeepsCommasThroughCLI(t *testing.T) {
values := []string{
`arr=[1, 2]`,
`s='a,b'`,
`x=STRUCT<a INT64,b STRING>(1,'two')`,
}
args := []string{"db", "--project=p", "--instance=i", "--sql=SELECT @arr"}
for _, value := range values {
args = append(args, "--param="+value)
}
o, err := processFlags(args)
if err != nil {
t.Fatal(err)
}
if strings.Join(o.ParamFlags, "\n") != strings.Join(values, "\n") {
t.Fatalf("ParamFlags = %#v, want one entry per flag", o.ParamFlags)
}
if _, err := prepareCommand(o); err != nil {
t.Fatalf("prepareCommand: %v", err)
}
}

func TestParamFlagDoesNotSplitCommaSeparatedAssignments(t *testing.T) {
o, err := processFlags([]string{
"db", "--project=p", "--instance=i", "--sql=SELECT @n, @m",
"--param=n=1,m=2",
})
if err != nil {
t.Fatal(err)
}
if len(o.ParamFlags) != 1 || o.ParamFlags[0] != "n=1,m=2" {
t.Fatalf("ParamFlags = %#v, want a single unsplit assignment", o.ParamFlags)
}
}
Loading