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: add support for multiple results to SQL statements #4081

Merged
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
1 change: 1 addition & 0 deletions GLOCKFILE
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ github.com/cockroachdb/c-lz4 c40aaae2fc50293eb8750b34632bc3efe813e23f
github.com/cockroachdb/c-protobuf 4feb192131ea08dfbd7253a00868ad69cbb61b81
github.com/cockroachdb/c-rocksdb c0124c907c74b579d9d3d48eb96471bef270bc25
github.com/cockroachdb/c-snappy 5c6d0932e0adaffce4bfca7bdf2ac37f79952ccf
github.com/cockroachdb/pq dd29f9a2c333350480bf658e7f99c4ffdc145830
github.com/cockroachdb/stress aa7690c22fd0abd6168ed0e6c361e4f4c5f7ab25
github.com/codahale/hdrhistogram e88be87d51429689cef99043a54150d733265cd7
github.com/coreos/etcd 410d32a9b14f6052a834a966a02950cde518d7ce
Expand Down
38 changes: 23 additions & 15 deletions cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -501,7 +501,7 @@ range_max_bytes: 67108864
// range_min_bytes: 8388608
// range_max_bytes: 67108864
//
// OK
// INSERT 1
// zone ls
// Object 100:
// replicas:
Expand All @@ -524,7 +524,7 @@ range_max_bytes: 67108864
// ttlseconds: 0
//
// zone rm 100
// OK
// DELETE 1
// zone ls
}

Expand All @@ -538,10 +538,11 @@ func Example_sql() {
c.RunWithArgs([]string{"sql", "-e", "select * from t.f"})
c.RunWithArgs([]string{"sql", "-e", "show databases"})
c.RunWithArgs([]string{"sql", "-e", "explain select 3"})
c.RunWithArgs([]string{"sql", "-e", "select 1; select 2"})

// Output:
// sql -e create database t; create table t.f (x int, y int); insert into t.f values (42, 69)
// OK
// INSERT 1
// sql -e select 3 select * from t.f
// 1 row
// 3
Expand All @@ -550,11 +551,11 @@ func Example_sql() {
// x y
// 42 69
// sql -e begin select 3 commit
// OK
// BEGIN
// 1 row
// 3
// 3
// OK
// COMMIT
// sql -e select * from t.f
// 1 row
// x y
Expand All @@ -568,6 +569,13 @@ func Example_sql() {
// 1 row
// Level Type Description
// 0 empty -
// sql -e select 1; select 2
// 1 row
// 1
// 1
// 1 row
// 2
// 2
}

func Example_sql_escape() {
Expand All @@ -586,21 +594,21 @@ func Example_sql_escape() {

// Output:
// sql -e create database t; create table t.t (s string, d string);
// OK
// CREATE TABLE
// sql -e insert into t.t values (e'foo', 'printable ASCII')
// OK
// INSERT 1
// sql -e insert into t.t values (e'foo\x0a', 'non-printable ASCII')
// OK
// INSERT 1
// sql -e insert into t.t values ('κόσμε', 'printable UTF8')
// OK
// INSERT 1
// sql -e insert into t.t values (e'\xc3\xb1', 'printable UTF8 using escapes')
// OK
// INSERT 1
// sql -e insert into t.t values (e'\x01', 'non-printable UTF8 string')
// OK
// INSERT 1
// sql -e insert into t.t values (e'\xdc\x88\x38\x35', 'UTF8 string with RTL char')
// OK
// INSERT 1
// sql -e insert into t.t values (e'\xc3\x28', 'non-UTF8 string')
// OK
// INSERT 1
// sql -e select * from t.t
// 7 rows
// s d
Expand Down Expand Up @@ -632,15 +640,15 @@ func Example_user() {
// +----------+
// +----------+
// user set foo --password=bar
// OK
// INSERT 1
// user ls
// +----------+
// | username |
// +----------+
// | foo |
// +----------+
// user rm foo
// OK
// DELETE 1
// user ls
// +----------+
// | username |
Expand Down
5 changes: 2 additions & 3 deletions cli/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,8 @@ subsequent positional argument on the command line may contain
one or more SQL statements, separated by semicolons. If an
error occurs in any statement, the command exits with a
non-zero status code and further statements are not
executed. Only the results of the first SQL statement in each
positional argument are printed on the standard output.`),

executed. The results of each SQL statement are printed on
the standard output.`),
"join": wrapText(`
A comma-separated list of addresses to use when a new node is joining
an existing cluster. For the first node in a cluster, --join should
Expand Down
4 changes: 2 additions & 2 deletions cli/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ func runLsNodes(cmd *cobra.Command, args []string) error {
})
}

printQueryOutput(os.Stdout, lsNodesColumnHeaders, rows)
printQueryOutput(os.Stdout, lsNodesColumnHeaders, rows, "")
return nil
}

Expand Down Expand Up @@ -128,7 +128,7 @@ func runStatusNode(cmd *cobra.Command, args []string) error {
return util.Errorf("expected no arguments or a single node ID")
}

printQueryOutput(os.Stdout, nodesColumnHeaders, nodeStatusesToRows(nodeStatuses))
printQueryOutput(os.Stdout, nodesColumnHeaders, nodeStatusesToRows(nodeStatuses), "")
return nil
}

Expand Down
47 changes: 25 additions & 22 deletions cli/sql.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ import (
"github.com/cockroachdb/cockroach/util/log"
"github.com/mattn/go-isatty"
"github.com/spf13/cobra"

"github.com/cockroachdb/pq"
)

const (
Expand Down Expand Up @@ -210,7 +212,7 @@ func runInteractive(conn *sqlConn) (exitErr error) {
readline.SetHistoryPath("")
}

if exitErr = runPrettyQuery(conn, os.Stdout, fullStmt); exitErr != nil {
if exitErr = runPrettyQuery(conn, os.Stdout, makeQuery(fullStmt)); exitErr != nil {
fmt.Fprintln(osStderr, exitErr)
}

Expand All @@ -225,30 +227,31 @@ func runInteractive(conn *sqlConn) (exitErr error) {
// on error.
func runStatements(conn *sqlConn, stmts []string) error {
for _, stmt := range stmts {
fullStmt := stmt + "\n"
cols, allRows, err := runQuery(conn, fullStmt)
if err != nil {
fmt.Fprintln(osStderr, err)
return err
}

if len(cols) == 0 {
// No result selected, inform the user.
fmt.Fprintln(os.Stdout, "OK")
} else {
// Some results selected, inform the user about how much data to expect.
noun := "rows"
if len(allRows) == 1 {
noun = "row"
q := makeQuery(stmt)
for {
cols, allRows, tag, err := runQuery(conn, q)
if err != nil {
if err == pq.ErrNoMoreResults {
break
}
fmt.Fprintln(osStderr, err)
os.Exit(1)
}

fmt.Fprintf(os.Stdout, "%d %s\n", len(allRows), noun)

// Then print the results themselves.
fmt.Fprintln(os.Stdout, strings.Join(cols, "\t"))
for _, row := range allRows {
fmt.Fprintln(os.Stdout, strings.Join(row, "\t"))
if len(cols) == 0 {
// No result selected, inform the user.
fmt.Fprintln(os.Stdout, tag)
} else {
// Some results selected, inform the user about how much data to expect.
fmt.Fprintf(os.Stdout, "%d row%s\n", len(allRows), pluralize(int64(len(allRows))))

// Then print the results themselves.
fmt.Fprintln(os.Stdout, strings.Join(cols, "\t"))
for _, row := range allRows {
fmt.Fprintln(os.Stdout, strings.Join(row, "\t"))
}
}
q = nextResult
}
}
return nil
Expand Down
Loading