diff --git a/docs/generated/sql/bnf/stmt_block.bnf b/docs/generated/sql/bnf/stmt_block.bnf index 4920c24c1cc4..d33119f6d231 100644 --- a/docs/generated/sql/bnf/stmt_block.bnf +++ b/docs/generated/sql/bnf/stmt_block.bnf @@ -472,8 +472,11 @@ show_grants_stmt ::= show_indexes_stmt ::= 'SHOW' 'INDEX' 'FROM' table_name + | 'SHOW' 'INDEX' 'FROM' 'DATABASE' database_name | 'SHOW' 'INDEXES' 'FROM' table_name + | 'SHOW' 'INDEXES' 'FROM' 'DATABASE' database_name | 'SHOW' 'KEYS' 'FROM' table_name + | 'SHOW' 'KEYS' 'FROM' 'DATABASE' database_name show_jobs_stmt ::= 'SHOW' opt_automatic 'JOBS' diff --git a/pkg/cli/cli_test.go b/pkg/cli/cli_test.go index 56fcf4f4cfc6..749ee70ec221 100644 --- a/pkg/cli/cli_test.go +++ b/pkg/cli/cli_test.go @@ -72,6 +72,7 @@ type cliTestParams struct { noServer bool storeSpecs []base.StoreSpec locality roachpb.Locality + addr string } func (c *cliTest) fail(err interface{}) { @@ -135,6 +136,7 @@ func newCLITest(params cliTestParams) cliTest { SSLCertsDir: c.certsDir, StoreSpecs: params.storeSpecs, Locality: params.locality, + Addr: params.addr, }) if err != nil { c.fail(err) @@ -370,7 +372,7 @@ func (c cliTest) runWithArgsUnredirected(origArgs []string) { args = append(args, "--insecure=false") args = append(args, fmt.Sprintf("--certs-dir=%s", c.certsDir)) } - args = append(args, fmt.Sprintf("--host=%s:%s", h, p)) + args = append(args, fmt.Sprintf("--host=%s", net.JoinHostPort(h, p))) } args = append(args, origArgs[1:]...) diff --git a/pkg/cli/start.go b/pkg/cli/start.go index ee7c9d35addb..c14785115373 100644 --- a/pkg/cli/start.go +++ b/pkg/cli/start.go @@ -1105,9 +1105,6 @@ func addrWithDefaultHost(addr string) (string, error) { if host == "" { host = "localhost" } - if strings.Contains(host, ":") { - host = "[" + host + "]" - } return net.JoinHostPort(host, port), nil } diff --git a/pkg/cli/start_test.go b/pkg/cli/start_test.go index eca38d6d1e4b..e32ea846e86c 100644 --- a/pkg/cli/start_test.go +++ b/pkg/cli/start_test.go @@ -174,3 +174,25 @@ func TestGCProfiles(t *testing.T) { sum -= len(data[:i]) } } + +func TestAddrWithDefaultHost(t *testing.T) { + defer leaktest.AfterTest(t)() + + testData := []struct { + inAddr string + outAddr string + }{ + {"localhost:123", "localhost:123"}, + {":123", "localhost:123"}, + {"[::1]:123", "[::1]:123"}, + } + + for _, test := range testData { + addr, err := addrWithDefaultHost(test.inAddr) + if err != nil { + t.Error(err) + } else if addr != test.outAddr { + t.Errorf("expected %q, got %q", test.outAddr, addr) + } + } +} diff --git a/pkg/sql/delegate/delegate.go b/pkg/sql/delegate/delegate.go index be6ace94bc44..da346eaece48 100644 --- a/pkg/sql/delegate/delegate.go +++ b/pkg/sql/delegate/delegate.go @@ -49,6 +49,9 @@ func TryDelegate( case *tree.ShowCreate: return d.delegateShowCreate(t) + case *tree.ShowDatabaseIndexes: + return d.delegateShowDatabaseIndexes(t) + case *tree.ShowIndexes: return d.delegateShowIndexes(t) diff --git a/pkg/sql/delegate/show_table.go b/pkg/sql/delegate/show_table.go index 5f992f377a65..ee64c9a9d213 100644 --- a/pkg/sql/delegate/show_table.go +++ b/pkg/sql/delegate/show_table.go @@ -34,6 +34,22 @@ func (d *delegator) delegateShowCreate(n *tree.ShowCreate) (tree.Statement, erro return d.showTableDetails(n.Name, showCreateQuery) } +func (d *delegator) delegateShowDatabaseIndexes( + n *tree.ShowDatabaseIndexes, +) (tree.Statement, error) { + const getAllIndexesQuery = ` + SELECT table_name, + index_name, + non_unique::BOOL, + seq_in_index, + column_name, + direction, + storing::BOOL, + implicit::BOOL + FROM %s.information_schema.statistics` + return parse(fmt.Sprintf(getAllIndexesQuery, n.Database.String())) +} + func (d *delegator) delegateShowIndexes(n *tree.ShowIndexes) (tree.Statement, error) { const getIndexesQuery = ` SELECT table_name, diff --git a/pkg/sql/logictest/testdata/logic_test/show_source b/pkg/sql/logictest/testdata/logic_test/show_source index 27980c50cf88..33ff9f78841f 100644 --- a/pkg/sql/logictest/testdata/logic_test/show_source +++ b/pkg/sql/logictest/testdata/logic_test/show_source @@ -331,3 +331,35 @@ code 42601 file sql/parser/show_syntax.go function RunShowSyntax detail source SQL: foo ^ + + +# Test the SHOW INDEXES FROM DATABSE COMMAND +statement ok +CREATE DATABASE showdbindexestest; + +statement ok +CREATE TABLE showdbindexestest.table1 (key1 INT PRIMARY KEY); + +statement ok +CREATE TABLE showdbindexestest.table2 (key2 INT PRIMARY KEY); + +query TTBITTBB +SHOW INDEXES FROM DATABASE showdbindexestest; +---- +table1 primary false 1 key1 ASC false false +table2 primary false 1 key2 ASC false false + +statement ok +CREATE DATABASE "$peci@l"; + +statement ok +CREATE TABLE "$peci@l".table1 (key1 INT PRIMARY KEY); + +statement ok +CREATE TABLE "$peci@l".table2 (key2 INT PRIMARY KEY); + +query TTBITTBB +SHOW INDEXES FROM DATABASE "$peci@l"; +---- +table1 primary false 1 key1 ASC false false +table2 primary false 1 key2 ASC false false diff --git a/pkg/sql/parser/parse_test.go b/pkg/sql/parser/parse_test.go index 4ade74df8ce0..ebe22ef9bcaa 100644 --- a/pkg/sql/parser/parse_test.go +++ b/pkg/sql/parser/parse_test.go @@ -410,6 +410,7 @@ func TestParse(t *testing.T) { {`SHOW INDEXES FROM a`}, {`EXPLAIN SHOW INDEXES FROM a`}, {`SHOW INDEXES FROM a.b.c`}, + {`SHOW INDEXES FROM DATABASE a`}, {`SHOW CONSTRAINTS FROM a`}, {`SHOW CONSTRAINTS FROM a.b.c`}, {`EXPLAIN SHOW CONSTRAINTS FROM a.b.c`}, diff --git a/pkg/sql/parser/sql.y b/pkg/sql/parser/sql.y index 1e7e4975897e..e713782accd1 100644 --- a/pkg/sql/parser/sql.y +++ b/pkg/sql/parser/sql.y @@ -3347,7 +3347,7 @@ show_grants_stmt: // %Help: SHOW INDEXES - list indexes // %Category: DDL -// %Text: SHOW INDEXES FROM +// %Text: SHOW INDEXES FROM { | DATABASE } // %SeeAlso: WEBDOCS/show-index.html show_indexes_stmt: SHOW INDEX FROM table_name @@ -3355,15 +3355,27 @@ show_indexes_stmt: $$.val = &tree.ShowIndexes{Table: $4.unresolvedObjectName()} } | SHOW INDEX error // SHOW HELP: SHOW INDEXES +| SHOW INDEX FROM DATABASE database_name + { + $$.val = &tree.ShowDatabaseIndexes{Database: tree.Name($5)} + } | SHOW INDEXES FROM table_name { $$.val = &tree.ShowIndexes{Table: $4.unresolvedObjectName()} } +| SHOW INDEXES FROM DATABASE database_name + { + $$.val = &tree.ShowDatabaseIndexes{Database: tree.Name($5)} + } | SHOW INDEXES error // SHOW HELP: SHOW INDEXES | SHOW KEYS FROM table_name { $$.val = &tree.ShowIndexes{Table: $4.unresolvedObjectName()} } +| SHOW KEYS FROM DATABASE database_name + { + $$.val = &tree.ShowDatabaseIndexes{Database: tree.Name($5)} + } | SHOW KEYS error // SHOW HELP: SHOW INDEXES // %Help: SHOW CONSTRAINTS - list constraints diff --git a/pkg/sql/sem/tree/show.go b/pkg/sql/sem/tree/show.go index 802df1afb6db..0dd40dade12f 100644 --- a/pkg/sql/sem/tree/show.go +++ b/pkg/sql/sem/tree/show.go @@ -155,6 +155,17 @@ func (node *ShowIndexes) Format(ctx *FmtCtx) { ctx.FormatNode(node.Table) } +// ShowDatabaseIndexes represents a SHOW INDEXES FROM DATABASE statement. +type ShowDatabaseIndexes struct { + Database Name +} + +// Format implements the NodeFormatter interface. +func (node *ShowDatabaseIndexes) Format(ctx *FmtCtx) { + ctx.WriteString("SHOW INDEXES FROM DATABASE ") + ctx.FormatNode(&node.Database) +} + // ShowQueries represents a SHOW QUERIES statement type ShowQueries struct { All bool diff --git a/pkg/sql/sem/tree/stmt.go b/pkg/sql/sem/tree/stmt.go index 96eeca4e076a..7f904a84461b 100644 --- a/pkg/sql/sem/tree/stmt.go +++ b/pkg/sql/sem/tree/stmt.go @@ -684,11 +684,17 @@ func (*ShowGrants) StatementType() StatementType { return Rows } // StatementTag returns a short string identifying the type of statement. func (*ShowGrants) StatementTag() string { return "SHOW GRANTS" } +// StatementType implements the Statement interface. +func (*ShowDatabaseIndexes) StatementType() StatementType { return Rows } + +// StatementTag returns a short string identifying the type of statement. +func (*ShowDatabaseIndexes) StatementTag() string { return "SHOW INDEXES FROM DATABASE" } + // StatementType implements the Statement interface. func (*ShowIndexes) StatementType() StatementType { return Rows } // StatementTag returns a short string identifying the type of statement. -func (*ShowIndexes) StatementTag() string { return "SHOW INDEXES" } +func (*ShowIndexes) StatementTag() string { return "SHOW INDEXES FROM TABLE" } // StatementType implements the Statement interface. func (*ShowQueries) StatementType() StatementType { return Rows } @@ -915,6 +921,7 @@ func (n *ShowColumns) String() string { return AsString(n) } func (n *ShowConstraints) String() string { return AsString(n) } func (n *ShowCreate) String() string { return AsString(n) } func (n *ShowDatabases) String() string { return AsString(n) } +func (n *ShowDatabaseIndexes) String() string { return AsString(n) } func (n *ShowGrants) String() string { return AsString(n) } func (n *ShowHistogram) String() string { return AsString(n) } func (n *ShowIndexes) String() string { return AsString(n) }