github.com/cockroachdb/cockroach@v20.2.0-alpha.1+incompatible/pkg/sql/delegate/show_ranges.go (about) 1 // Copyright 2019 The Cockroach Authors. 2 // 3 // Use of this software is governed by the Business Source License 4 // included in the file licenses/BSL.txt. 5 // 6 // As of the Change Date specified in that file, in accordance with 7 // the Business Source License, use of this software will be governed 8 // by the Apache License, Version 2.0, included in the file 9 // licenses/APL.txt. 10 11 package delegate 12 13 import ( 14 "encoding/hex" 15 "fmt" 16 17 "github.com/cockroachdb/cockroach/pkg/sql/lex" 18 "github.com/cockroachdb/cockroach/pkg/sql/opt/cat" 19 "github.com/cockroachdb/cockroach/pkg/sql/privilege" 20 "github.com/cockroachdb/cockroach/pkg/sql/sem/tree" 21 "github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry" 22 "github.com/cockroachdb/errors" 23 ) 24 25 // delegateShowRanges implements the SHOW RANGES statement: 26 // SHOW RANGES FROM TABLE t 27 // SHOW RANGES FROM INDEX t@idx 28 // SHOW RANGES FROM DATABASE db 29 // 30 // These statements show the ranges corresponding to the given table or index, 31 // along with the list of replicas and the lease holder. 32 func (d *delegator) delegateShowRanges(n *tree.ShowRanges) (tree.Statement, error) { 33 sqltelemetry.IncrementShowCounter(sqltelemetry.Ranges) 34 if n.DatabaseName != "" { 35 const dbQuery = ` 36 SELECT 37 table_name, 38 CASE 39 WHEN crdb_internal.pretty_key(r.start_key, 2) = '' THEN NULL 40 ELSE crdb_internal.pretty_key(r.start_key, 2) 41 END AS start_key, 42 CASE 43 WHEN crdb_internal.pretty_key(r.end_key, 2) = '' THEN NULL 44 ELSE crdb_internal.pretty_key(r.end_key, 2) 45 END AS end_key, 46 range_id, 47 range_size / 1000000 as range_size_mb, 48 lease_holder, 49 gossip_nodes.locality as lease_holder_locality, 50 replicas, 51 replica_localities 52 FROM %[1]s.crdb_internal.ranges AS r 53 LEFT JOIN crdb_internal.gossip_nodes ON lease_holder = node_id 54 WHERE database_name=%[2]s 55 ORDER BY table_name, r.start_key 56 ` 57 // Note: n.DatabaseName.String() != string(n.DatabaseName) 58 return parse(fmt.Sprintf(dbQuery, n.DatabaseName.String(), lex.EscapeSQLString(string(n.DatabaseName)))) 59 } 60 61 idx, resName, err := cat.ResolveTableIndex( 62 d.ctx, d.catalog, cat.Flags{AvoidDescriptorCaches: true}, &n.TableOrIndex, 63 ) 64 if err != nil { 65 return nil, err 66 } 67 if err := d.catalog.CheckPrivilege(d.ctx, idx.Table(), privilege.SELECT); err != nil { 68 return nil, err 69 } 70 if idx.Table().IsVirtualTable() { 71 return nil, errors.New("SHOW RANGES may not be called on a virtual table") 72 } 73 74 span := idx.Span() 75 startKey := hex.EncodeToString([]byte(span.Key)) 76 endKey := hex.EncodeToString([]byte(span.EndKey)) 77 return parse(fmt.Sprintf(` 78 SELECT 79 CASE WHEN r.start_key <= x'%[1]s' THEN NULL ELSE crdb_internal.pretty_key(r.start_key, 2) END AS start_key, 80 CASE WHEN r.end_key >= x'%[2]s' THEN NULL ELSE crdb_internal.pretty_key(r.end_key, 2) END AS end_key, 81 range_id, 82 range_size / 1000000 as range_size_mb, 83 lease_holder, 84 gossip_nodes.locality as lease_holder_locality, 85 replicas, 86 replica_localities 87 FROM %[3]s.crdb_internal.ranges AS r 88 LEFT JOIN %[3]s.crdb_internal.gossip_nodes ON lease_holder = node_id 89 WHERE (r.start_key < x'%[2]s') 90 AND (r.end_key > x'%[1]s') ORDER BY r.start_key 91 `, 92 startKey, endKey, resName.CatalogName.String(), // note: CatalogName.String() != Catalog() 93 )) 94 }