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  }