Skip to content

Commit

Permalink
sql: enhance SHOW RANGES
Browse files Browse the repository at this point in the history
TLDR:
- hide broken columns from crdb_internal.ranges{,no_leases}
- use crdb_internal.index_spans, .table_spans instead
- rework SHOW RANGES.
  - select between "1 row per range" and "1 row per range/object intersection" using new syntax
  - fix representation of start/end key

(see text of release notes below for details)

To test this, use for example the following setup:

```
> -- Enable merge of adjacent ranges with same zone config.
> set cluster setting spanconfig.host_coalesce_adjacent.enabled = true;
> -- Table t has two indexes with some split points.
> create table t(x int primary key, y int);
> create index sec_idx on t(y);
> alter index t@primary split at values(3);
> alter index t@sec_idx split at values(3);
> -- Tables u and v share a range with t@sec_idx.
> create table u(x int);
> create table v(x int);
> -- Make some other tables with forced split points due to different
> -- zone configs.
> create schema otherschema;
> create table otherschema.w(x int);
> create table otherschema.z(x int);
> alter table otherschema.w configure zone using num_replicas = 5;
> alter table otherschema.z configure zone using num_replicas = 7;
```

Example output for `SHOW RANGES FROM DATABASE`:

```
> show ranges from database defaultdb; -- 1 row per range
> show ranges from current_catalog; -- implicit db from session

    start_key    |    end_key     | range_id | ...
-----------------+----------------+----------+----
  /Table/104     | /Table/104/1/3 |       56 | ...
  /Table/104/1/3 | /Table/104/2   |       57 | ...
  /Table/104/2   | /Table/104/2/3 |       55 | ...
  /Table/104/2/3 | /Table/108     |       58 | ...
  /Table/108     | /Table/109     |       59 | ...
  /Table/109     | /Max           |       60 | ...
```

New syntax: `WITH TABLES` / `WITH INDEXES`:

```
> show ranges from database defaultdb with tables; -- 1 row per range/table intersection

    start_key    |    end_key     | range_id | schema_name | table_name | table_start_key |    table_end_key     | ...
-----------------+----------------+----------+-------------+------------+-----------------+----------------------+----
  /Table/104     | /Table/104/1/3 |       56 | public      | t          | /Table/104      | /Table/105           | ...
  /Table/104/1/3 | /Table/104/2   |       57 | public      | t          | /Table/104      | /Table/105           | ...
  /Table/104/2   | /Table/104/2/3 |       55 | public      | t          | /Table/104      | /Table/105           | ...
  /Table/104/2/3 | /Table/108     |       58 | public      | t          | /Table/104      | /Table/105           | ...
  /Table/104/2/3 | /Table/108     |       58 | public      | u          | /Table/105      | /Table/106           | ...
  /Table/104/2/3 | /Table/108     |       58 | public      | v          | /Table/106      | /Table/107           | ...
  /Table/108     | /Table/109     |       59 | otherschema | w          | /Table/108      | /Table/109           | ...
  /Table/109     | /Max           |       60 | otherschema | z          | /Table/109      | /Table/109/PrefixEnd | ...
```

```
> show ranges from database defaultdb with indexes; -- 1 row per range/index intersection

    start_key    |    end_key     | range_id | schema_name | table_name | index_name | index_start_key | index_end_key | ...
-----------------+----------------+----------+-------------+------------+------------+-----------------+---------------+----
  /Table/104     | /Table/104/1/3 |       56 | public      | t          | t_pkey     | /Table/104/1    | /Table/104/2  | ...
  /Table/104/1/3 | /Table/104/2   |       57 | public      | t          | t_pkey     | /Table/104/1    | /Table/104/2  | ...
  /Table/104/2   | /Table/104/2/3 |       55 | public      | t          | sec_idx    | /Table/104/2    | /Table/104/3  | ...
  /Table/104/2/3 | /Table/108     |       58 | public      | t          | sec_idx    | /Table/104/2    | /Table/104/3  | ...
  /Table/104/2/3 | /Table/108     |       58 | public      | u          | u_pkey     | /Table/105/1    | /Table/105/2  | ...
  /Table/104/2/3 | /Table/108     |       58 | public      | v          | v_pkey     | /Table/106/1    | /Table/106/2  | ...
  /Table/108     | /Table/109     |       59 | otherschema | w          | w_pkey     | /Table/108/1    | /Table/108/2  | ...
  /Table/109     | /Max           |       60 | otherschema | z          | z_pkey     | /Table/109/1    | /Table/109/2  | ...
```

Example output for `SHOW RANGES FROM TABLE`:

```
> show ranges from table t;

   start_key   |      end_key       | range_id | ...
---------------+--------------------+----------+----
  …/<TableMin> | …/1/3              |       56 | ...
  …/1/3        | …/2                |       57 | ...
  …/2          | …/2/3              |       55 | ...
  …/2/3        | <after:/Table/108> |       58 | ...
```

```
> show ranges from table u;

         start_key        |      end_key       | range_id | ...
--------------------------+--------------------+----------+----
  <before:/Table/104/2/3> | <after:/Table/108> |       58 | ...
```

```
> show ranges from table otherschema.w;

  start_key    |  end_key     | range_id | ...
---------------+--------------+----------+----
  …/<TableMin> | …/<TableMax> |       59 | ...
```

New syntax: `SHOW RANGES FROM TABLE ... WITH INDEXES`:

```
> show ranges from table t with indexes;

  start_key    |      end_key       | range_id | index_name | index_start_key | index_end_key | ...
---------------+--------------------+----------+------------+-----------------+---------------+----
  …/<TableMin> | …/1/3              |       56 | t_pkey     | …/1             | …/2           | ...
  …/1/3        | …/<IndexMax>       |       57 | t_pkey     | …/1             | …/2           | ...
  …/<IndexMin> | …/2/3              |       55 | sec_idx    | …/2             | …/3           | ...
  …/2/3        | <after:/Table/108> |       58 | sec_idx    | …/2             | …/3           | ...
```

```
> show ranges from table u with indexes;

         start_key        |      end_key       | range_id | index_name | index_start_key | index_end_key | ...
--------------------------+--------------------+----------+------------+-----------------+---------------+----
  <before:/Table/104/2/3> | <after:/Table/108> |       58 | u_pkey     | …/1             | …/2           | ...
```

```
> show ranges from table otherschema.w with indexes;

  start_key    |  end_key     | range_id | index_name | index_start_key | index_end_key | ...
---------------+--------------+----------+------------+-----------------+---------------+----
  …/<TableMin> | …/<TableMax> |       59 | w_pkey     | …/1             | …/2           | ...
```

Example output for `SHOW RANGES FROM INDEX`:

```
> show ranges from index t@t_pkey;

  start_key    |  end_key     | range_id | ...
---------------+--------------+----------+----
  …/<TableMin> | …/3          |       56 | ...
  …/3          | …/<IndexMax> |       57 | ...
```

```
> show ranges from index t@sec_idx;

  start_key    |      end_key       | range_id | ...
---------------+--------------------+----------+----
  …/<IndexMin> | …/3                |       55 | ...
  …/3          | <after:/Table/108> |       58 | ...
```

```
> show ranges from index u@u_pkey;

         start_key        |      end_key       | range_id | ...
--------------------------+--------------------+----------+----
  <before:/Table/104/2/3> | <after:/Table/108> |       58 | ...
```

```
> show ranges from index otherschema.w@w_pkey;

  start_key    |  end_key     | range_id | ...
---------------+--------------+----------+----
  …/<TableMin> | …/<TableMax> |       59 | ...
```

See release notes below for details.

----

Release note (backward-incompatible change): CockroachDB now supports
sharing storage ranges across multiple indexes/tables. As a result,
there is no more guarantee that there is at most one SQL object (e.g.
table/index/sequence/materialized view) per storage range.

Therefore, the columns `table_id`, `database_name`, `schema_name`,
`table_name` and `index_name` in `crdb_internal.ranges` and
`.ranges_no_leases` have become nonsensical: a range cannot be
attributed to a single table/index any more.

As a result:

- The aforementioned columns in the `crdb_internal` virtual tables
  have been marked as hidden, and will now report NULL.

- `SHOW RANGES FROM DATABASE` continues to report one row per range,
  but stops returning the database / schema / table / index name.

- `SHOW RANGES FROM TABLE` continues to report one row per range,
  but stops returning the index name.

Summary:

| Statement                                          | Row identity                     | Before                     | After                            |
|----------------------------------------------------|----------------------------------|----------------------------|----------------------------------|
| `SHOW RANGES FROM DATABASE`                        | rangeID                          | Includes schema/table name | (NEW) No schema/table name       |
| `SHOW RANGES FROM TABLE`                           | rangeID                          | Includes index name        | (NEW) No index name              |
| `SHOW RANGES FROM INDEX`                           | rangeID                          | Includes index name        | Unchanged                        |
| `SHOW RANGES FROM DATABASE ... WITH TABLES` (NEW)  | rangeID, schema/table name       | N/A                        | Includes schema/table name       |
| `SHOW RANGES FROM DATABASE ... WITH INDEXES` (NEW) | rangeID, schema/table/index name | N/A                        | Includes schema/table/index name |
| `SHOW RANGES FROM TABLE ... WITH INDEXES` (NEW)    | rangeID, index name              | N/A                        | Includes index name              |

Release note (backward-incompatible change): The format of the
columns `start_key` and `end_key` for `SHOW RANGES FROM DATABASE`
and `SHOW RANGES FROM TABLE` have been extended to include which
table/index the key belong to. This is necessary because a range
can now contain data from more than one table/index.

Summary:

| Statement                                          | Start/end key column, before | Start/end key column, after           |
|----------------------------------------------------|------------------------------|---------------------------------------|
| `SHOW RANGES FROM DATABASE`                        | Truncates table/index IDs    | (NEW) Includes table/index ID         |
| `SHOW RANGES FROM TABLE`                           | Truncates table/index IDs    | (NEW) Includes table/index ID         |
| `SHOW RANGES FROM INDEX`                           | Truncates table/index IDs    | Unchanged                             |
| `SHOW RANGES FROM DATABASE ... WITH TABLES` (NEW)  | N/A                          | Includes table/index ID               |
| `SHOW RANGES FROM DATABASE ... WITH INDEXES` (NEW) | N/A                          | Includes table/index ID               |
| `SHOW RANGES FROM TABLE ... WITH INDEXES` (NEW)    | N/A                          | Truncates table ID, includes index ID |

Release note (backward-incompatible change): The format of
the columns `start_key` and `end_key` for `SHOW RANGE ... FOR ROW`
has been changed to stay consistent with the output of `SHOW RANGES
FROM INDEX`.

Release note (bug fix): In some cases the start/end key columns of the
output of `SHOW RANGES` was missing. This was corrected.

Release note (sql change): Two new virtual tables
`crdb_internal.index_spans` and `.table_spans` have been introduced,
which list the logical keyspace used by each index/table.

Release note (sql change): The following new statements are
introduced:

- `SHOW RANGES FROM CURRENT_CATALOG`: alias for `SHOW RANGES FROM
  DATABASE` on the session's current database.

- `SHOW RANGES FROM DATABASE ... WITH TABLES`
  Reports at least one row per table. It's possible for the same
  range ID to be repeated across multiple rows, when a range spans
  multiple tables.

- `SHOW RANGES FROM DATABASE ... WITH INDEXES`
  Reports at least one row per index. It's possible for the same
  range ID to be repeated across multiple rows, when a range spans
  multiple indexes.

- `SHOW RANGES FROM TABLE ... WITH INDEXES`
  Reports at least one row per index. It's possible for the same
  range ID to be repeated across multiple rows, when a range spans
  multiple indexes.

Under the hood, these statements are implemented by means of a join
between `crdb_internal.ranges` and
`crdb_internal.{index,table}_spans`.
  • Loading branch information
knz committed Dec 16, 2022
1 parent 5b23751 commit 47a4ca1
Show file tree
Hide file tree
Showing 63 changed files with 1,690 additions and 1,032 deletions.
10 changes: 8 additions & 2 deletions docs/generated/sql/bnf/show_ranges_stmt.bnf
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
show_ranges_stmt ::=
'SHOW' 'RANGES' 'FROM' 'TABLE' table_name
| 'SHOW' 'RANGES' 'FROM' 'INDEX' table_index_name
'SHOW' 'RANGES' 'FROM' 'INDEX' table_index_name
| 'SHOW' 'RANGES' 'FROM' 'TABLE' table_name
| 'SHOW' 'RANGES' 'FROM' 'TABLE' table_name 'WITH' 'INDEXES'
| 'SHOW' 'RANGES' 'FROM' 'DATABASE' database_name
| 'SHOW' 'RANGES' 'FROM' 'CURRENT_CATALOG'
| 'SHOW' 'RANGES' 'FROM' 'DATABASE' database_name 'WITH' 'TABLES'
| 'SHOW' 'RANGES' 'FROM' 'CURRENT_CATALOG' 'WITH' 'TABLES'
| 'SHOW' 'RANGES' 'FROM' 'DATABASE' database_name 'WITH' 'INDEXES'
| 'SHOW' 'RANGES' 'FROM' 'CURRENT_CATALOG' 'WITH' 'INDEXES'
10 changes: 8 additions & 2 deletions docs/generated/sql/bnf/stmt_block.bnf
Original file line number Diff line number Diff line change
Expand Up @@ -867,9 +867,15 @@ show_statements_stmt ::=
| 'SHOW' 'ALL' opt_cluster statements_or_queries

show_ranges_stmt ::=
'SHOW' 'RANGES' 'FROM' 'TABLE' table_name
| 'SHOW' 'RANGES' 'FROM' 'INDEX' table_index_name
'SHOW' 'RANGES' 'FROM' 'INDEX' table_index_name
| 'SHOW' 'RANGES' 'FROM' 'TABLE' table_name
| 'SHOW' 'RANGES' 'FROM' 'TABLE' table_name 'WITH' 'INDEXES'
| 'SHOW' 'RANGES' 'FROM' 'DATABASE' database_name
| 'SHOW' 'RANGES' 'FROM' 'CURRENT_CATALOG'
| 'SHOW' 'RANGES' 'FROM' 'DATABASE' database_name 'WITH' 'TABLES'
| 'SHOW' 'RANGES' 'FROM' 'CURRENT_CATALOG' 'WITH' 'TABLES'
| 'SHOW' 'RANGES' 'FROM' 'DATABASE' database_name 'WITH' 'INDEXES'
| 'SHOW' 'RANGES' 'FROM' 'CURRENT_CATALOG' 'WITH' 'INDEXES'

show_range_for_row_stmt ::=
'SHOW' 'RANGE' 'FROM' 'TABLE' table_name 'FOR' 'ROW' '(' expr_list ')'
Expand Down
2 changes: 2 additions & 0 deletions pkg/ccl/logictestccl/testdata/logic_test/crdb_internal_tenant
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ crdb_internal gossip_liveness table admin NULL NULL
crdb_internal gossip_network table admin NULL NULL
crdb_internal gossip_nodes table admin NULL NULL
crdb_internal index_columns table admin NULL NULL
crdb_internal index_spans table admin NULL NULL
crdb_internal index_usage_statistics table admin NULL NULL
crdb_internal invalid_objects table admin NULL NULL
crdb_internal jobs table admin NULL NULL
Expand Down Expand Up @@ -92,6 +93,7 @@ crdb_internal super_regions table admin NULL NULL
crdb_internal table_columns table admin NULL NULL
crdb_internal table_indexes table admin NULL NULL
crdb_internal table_row_statistics table admin NULL NULL
crdb_internal table_spans table admin NULL NULL
crdb_internal tables table admin NULL NULL
crdb_internal tenant_usage_details view admin NULL NULL
crdb_internal transaction_contention_events table admin NULL NULL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,29 +256,27 @@ statement ok
CREATE INDEX t_presplit_idx_member_id ON t_presplit (member_id) USING HASH WITH (bucket_count=8);

skipif config 3node-tenant
query TITTT colnames,retry
SELECT t.name, r.table_id, r.index_name, r.start_pretty, r.end_pretty
FROM crdb_internal.tables t
JOIN crdb_internal.ranges r ON t.table_id = r.table_id
WHERE t.name = 't_presplit'
AND t.state = 'PUBLIC'
AND r.split_enforced_until IS NOT NULL;
query TITTT colnames,retry,rowsort
SELECT table_name, table_id, index_name, start_key, end_key
FROM [SHOW RANGES FROM DATABASE test WITH INDEXES]
WHERE table_name = 't_presplit'
----
name table_id index_name start_pretty end_pretty
t_presplit 112 t_presplit_idx_member_id /Table/112/2 /Table/112/2/"new york"/0
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/0 /Table/112/2/"new york"/1
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/1 /Table/112/2/"new york"/2
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/2 /Table/112/2/"new york"/3
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/3 /Table/112/2/"new york"/4
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/4 /Table/112/2/"new york"/5
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/5 /Table/112/2/"new york"/6
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/6 /Table/112/2/"new york"/7
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/7 /Table/112/2/"seattle"/0
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/0 /Table/112/2/"seattle"/1
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/1 /Table/112/2/"seattle"/2
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/2 /Table/112/2/"seattle"/3
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/3 /Table/112/2/"seattle"/4
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/4 /Table/112/2/"seattle"/5
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/5 /Table/112/2/"seattle"/6
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/6 /Table/112/2/"seattle"/7
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/7 /Table/112/3/"new york"/0
table_name table_id index_name start_key end_key
t_presplit 112 t_presplit_pkey /Table/109/11/"seattle"/15 /Table/112/2
t_presplit 112 t_presplit_idx_member_id /Table/112/2 /Table/112/2/"new york"/0
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/0 /Table/112/2/"new york"/1
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/1 /Table/112/2/"new york"/2
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/2 /Table/112/2/"new york"/3
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/3 /Table/112/2/"new york"/4
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/4 /Table/112/2/"new york"/5
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/5 /Table/112/2/"new york"/6
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/6 /Table/112/2/"new york"/7
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"new york"/7 /Table/112/2/"seattle"/0
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/0 /Table/112/2/"seattle"/1
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/1 /Table/112/2/"seattle"/2
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/2 /Table/112/2/"seattle"/3
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/3 /Table/112/2/"seattle"/4
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/4 /Table/112/2/"seattle"/5
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/5 /Table/112/2/"seattle"/6
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/6 /Table/112/2/"seattle"/7
t_presplit 112 t_presplit_idx_member_id /Table/112/2/"seattle"/7 /Table/112/3/"new york"/0
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ ap-southeast-2 23
query TT
SELECT start_key, end_key FROM [SHOW RANGE FROM TABLE regional_by_row_table FOR ROW ('ap-southeast-2', 1)]
----
NULL NULL
<before:/Table/53> <after:/Table/110/5>

query TIIII
SELECT crdb_region, pk, pk2, a, b FROM regional_by_row_table
Expand Down Expand Up @@ -394,10 +394,10 @@ ALTER TABLE regional_by_row_table EXPERIMENTAL_RELOCATE VALUES (ARRAY[1], 'ap-so
query TTTI colnames,rowsort
SELECT start_key, end_key, replicas, lease_holder FROM [SHOW RANGES FROM INDEX regional_by_row_table@primary]
----
start_key end_key replicas lease_holder
NULL /"\x80"/0 {1} 1
/"\x80"/0 /"\xc0"/0 {4} 4
/"\xc0"/0 NULL {7} 7
start_key end_key replicas lease_holder
<before:/Table/53> …/"\x80"/0 {1} 1
/"\x80"/0 /"\xc0"/0 {4} 4
/"\xc0"/0 <after:/Table/110/5> {7} 7

statement ok
SET locality_optimized_partitioned_index_scan = false
Expand Down Expand Up @@ -642,10 +642,10 @@ ALTER TABLE child EXPERIMENTAL_RELOCATE VALUES (ARRAY[1], 'ap-southeast-2', 0),
query TTTI colnames,rowsort
SELECT start_key, end_key, replicas, lease_holder FROM [SHOW RANGES FROM INDEX child@primary]
----
start_key end_key replicas lease_holder
NULL /"\x80"/0 {1} 1
/"\x80"/0 /"\xc0"/0 {4} 4
/"\xc0"/0 NULL {7} 7
start_key end_key replicas lease_holder
<before:/Table/110/5> …/"\x80"/0 {1} 1
/"\x80"/0 /"\xc0"/0 {4} 4
/"\xc0"/0 <after:/Max> {7} 7

statement ok
SET locality_optimized_partitioned_index_scan = false
Expand Down
139 changes: 115 additions & 24 deletions pkg/sql/crdb_internal.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ import (
"github.com/cockroachdb/cockroach/pkg/sql/sem/builtins"
"github.com/cockroachdb/cockroach/pkg/sql/sem/builtins/builtinsregistry"
"github.com/cockroachdb/cockroach/pkg/sql/sem/catconstants"
"github.com/cockroachdb/cockroach/pkg/sql/sem/catid"
"github.com/cockroachdb/cockroach/pkg/sql/sem/eval"
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
"github.com/cockroachdb/cockroach/pkg/sql/sessiondata"
Expand Down Expand Up @@ -140,6 +141,7 @@ var crdbInternal = virtualSchema{
catconstants.CrdbInternalGossipNetworkTableID: crdbInternalGossipNetworkTable,
catconstants.CrdbInternalTransactionContentionEvents: crdbInternalTransactionContentionEventsTable,
catconstants.CrdbInternalIndexColumnsTableID: crdbInternalIndexColumnsTable,
catconstants.CrdbInternalIndexSpansTableID: crdbInternalIndexSpansTable,
catconstants.CrdbInternalIndexUsageStatisticsTableID: crdbInternalIndexUsageStatistics,
catconstants.CrdbInternalInflightTraceSpanTableID: crdbInternalInflightTraceSpanTable,
catconstants.CrdbInternalJobsTableID: crdbInternalJobsTable,
Expand All @@ -165,6 +167,7 @@ var crdbInternal = virtualSchema{
catconstants.CrdbInternalStmtStatsTableID: crdbInternalStmtStatsView,
catconstants.CrdbInternalTableColumnsTableID: crdbInternalTableColumnsTable,
catconstants.CrdbInternalTableIndexesTableID: crdbInternalTableIndexesTable,
catconstants.CrdbInternalTableSpansTableID: crdbInternalTableSpansTable,
catconstants.CrdbInternalTablesTableLastStatsID: crdbInternalTablesTableLastStats,
catconstants.CrdbInternalTablesTableID: crdbInternalTablesTable,
catconstants.CrdbInternalClusterTxnStatsTableID: crdbInternalClusterTxnStatsTable,
Expand Down Expand Up @@ -3533,11 +3536,11 @@ FROM crdb_internal.ranges_no_leases
{Name: "start_pretty", Typ: types.String},
{Name: "end_key", Typ: types.Bytes},
{Name: "end_pretty", Typ: types.String},
{Name: "table_id", Typ: types.Int},
{Name: "database_name", Typ: types.String},
{Name: "schema_name", Typ: types.String},
{Name: "table_name", Typ: types.String},
{Name: "index_name", Typ: types.String},
{Hidden: true, Name: "table_id", Typ: types.Int},
{Hidden: true, Name: "database_name", Typ: types.String},
{Hidden: true, Name: "schema_name", Typ: types.String},
{Hidden: true, Name: "table_name", Typ: types.String},
{Hidden: true, Name: "index_name", Typ: types.String},
{Name: "replicas", Typ: types.Int2Vector},
{Name: "replica_localities", Typ: types.StringArray},
{Name: "voting_replicas", Typ: types.Int2Vector},
Expand Down Expand Up @@ -3653,11 +3656,11 @@ CREATE TABLE crdb_internal.ranges_no_leases (
start_pretty STRING NOT NULL,
end_key BYTES NOT NULL,
end_pretty STRING NOT NULL,
table_id INT NOT NULL,
database_name STRING NOT NULL,
schema_name STRING NOT NULL,
table_name STRING NOT NULL,
index_name STRING NOT NULL,
table_id INT NOT VISIBLE,
database_name STRING NOT VISIBLE,
schema_name STRING NOT VISIBLE,
table_name STRING NOT VISIBLE,
index_name STRING NOT VISIBLE,
replicas INT[] NOT NULL,
replica_localities STRING[] NOT NULL,
voting_replicas INT[] NOT NULL,
Expand Down Expand Up @@ -3685,9 +3688,13 @@ CREATE TABLE crdb_internal.ranges_no_leases (
return p.CheckPrivilege(ctx, desc, privilege.ZONECONFIG) == nil
}

hasPermission, dbNames, tableNames, schemaNames, indexNames, schemaParents, parents :=
descriptorsByType(descs, privCheckerFunc)

hasPermission := false
for _, desc := range descs {
if privCheckerFunc(desc) {
hasPermission = true
break
}
}
// if the user has no ZONECONFIG privilege on any table/schema/database
if !hasPermission {
return nil, nil, pgerror.Newf(pgcode.InsufficientPrivilege, "only users with the ZONECONFIG privilege or the admin role can read crdb_internal.ranges_no_leases")
Expand Down Expand Up @@ -3763,11 +3770,6 @@ CREATE TABLE crdb_internal.ranges_no_leases (
}
}

tableID, dbName, schemaName, tableName, indexName := lookupNamesByKey(
p, rangeDesc.StartKey.AsRawKey(), dbNames, tableNames, schemaNames,
indexNames, schemaParents, parents,
)

splitEnforcedUntil := tree.DNull
if !rangeDesc.StickyBit.IsEmpty() {
splitEnforcedUntil = eval.TimestampToInexactDTimestamp(rangeDesc.StickyBit)
Expand All @@ -3779,11 +3781,11 @@ CREATE TABLE crdb_internal.ranges_no_leases (
tree.NewDString(keys.PrettyPrint(nil /* valDirs */, rangeDesc.StartKey.AsRawKey())),
tree.NewDBytes(tree.DBytes(rangeDesc.EndKey)),
tree.NewDString(keys.PrettyPrint(nil /* valDirs */, rangeDesc.EndKey.AsRawKey())),
tree.NewDInt(tree.DInt(tableID)),
tree.NewDString(dbName),
tree.NewDString(schemaName),
tree.NewDString(tableName),
tree.NewDString(indexName),
tree.DNull, // tableID
tree.DNull, // dbName
tree.DNull, // schemaName
tree.DNull, // tableName
tree.DNull, // indexName
votersAndNonVotersArr,
replicaLocalityArr,
votersArr,
Expand Down Expand Up @@ -6350,6 +6352,95 @@ CREATE TABLE crdb_internal.transaction_contention_events (
},
}

var crdbInternalIndexSpansTable = virtualSchemaTable{
comment: `key spans per table index`,
schema: `
CREATE TABLE crdb_internal.index_spans (
descriptor_id INT NOT NULL,
index_id INT NOT NULL,
start_key BYTES NOT NULL,
end_key BYTES NOT NULL,
INDEX(descriptor_id)
);`,
indexes: []virtualIndex{
{
populate: func(ctx context.Context, constraint tree.Datum, p *planner, db catalog.DatabaseDescriptor, addRow func(...tree.Datum) error) (matched bool, err error) {
descID := catid.DescID(tree.MustBeDInt(constraint))
table, err := p.LookupTableByID(ctx, descID)
if err != nil {
return false, err
}
return true, generateIndexSpans(ctx, p, table, addRow)
},
},
},
populate: func(ctx context.Context, p *planner, db catalog.DatabaseDescriptor, addRow func(...tree.Datum) error) error {
return forEachTableDescAll(ctx, p, db, hideVirtual,
func(_ catalog.DatabaseDescriptor, _ catalog.SchemaDescriptor, table catalog.TableDescriptor) error {
return generateIndexSpans(ctx, p, table, addRow)
})
},
}

func generateIndexSpans(
ctx context.Context, p *planner, table catalog.TableDescriptor, addRow func(...tree.Datum) error,
) error {
tabID := table.GetID()
return catalog.ForEachIndex(table, catalog.IndexOpts{}, func(idx catalog.Index) error {
indexID := idx.GetID()
start := roachpb.Key(rowenc.MakeIndexKeyPrefix(p.ExecCfg().Codec, tabID, indexID))
end := start.PrefixEnd()
return addRow(
tree.NewDInt(tree.DInt(tabID)),
tree.NewDInt(tree.DInt(indexID)),
tree.NewDBytes(tree.DBytes(start)),
tree.NewDBytes(tree.DBytes(end)),
)
})
}

var crdbInternalTableSpansTable = virtualSchemaTable{
comment: `key spans per SQL object`,
schema: `
CREATE TABLE crdb_internal.table_spans (
descriptor_id INT NOT NULL,
start_key BYTES NOT NULL,
end_key BYTES NOT NULL,
INDEX(descriptor_id)
);`,
indexes: []virtualIndex{
{
populate: func(ctx context.Context, constraint tree.Datum, p *planner, db catalog.DatabaseDescriptor, addRow func(...tree.Datum) error) (matched bool, err error) {
descID := catid.DescID(tree.MustBeDInt(constraint))
table, err := p.LookupTableByID(ctx, descID)
if err != nil {
return false, err
}
return true, generateTableSpan(ctx, p, table, addRow)
},
},
},
populate: func(ctx context.Context, p *planner, db catalog.DatabaseDescriptor, addRow func(...tree.Datum) error) error {
return forEachTableDescAll(ctx, p, db, hideVirtual,
func(_ catalog.DatabaseDescriptor, _ catalog.SchemaDescriptor, table catalog.TableDescriptor) error {
return generateTableSpan(ctx, p, table, addRow)
})
},
}

func generateTableSpan(
ctx context.Context, p *planner, table catalog.TableDescriptor, addRow func(...tree.Datum) error,
) error {
tabID := table.GetID()
start := p.ExecCfg().Codec.TablePrefix(uint32(tabID))
end := start.PrefixEnd()
return addRow(
tree.NewDInt(tree.DInt(tabID)),
tree.NewDBytes(tree.DBytes(start)),
tree.NewDBytes(tree.DBytes(end)),
)
}

// crdbInternalClusterLocksTable exposes the state of locks, as well as lock waiters,
// in range lock tables across the cluster.
var crdbInternalClusterLocksTable = virtualSchemaTable{
Expand All @@ -6360,7 +6451,7 @@ CREATE TABLE crdb_internal.cluster_locks (
range_id INT NOT NULL,
table_id INT NOT NULL,
database_name STRING NOT NULL,
schema_name STRING,
schema_name STRING NOT NULL,
table_name STRING NOT NULL,
index_name STRING,
lock_key BYTES NOT NULL,
Expand Down
12 changes: 10 additions & 2 deletions pkg/sql/delegate/show_range_for_row.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,16 @@ func (d *delegator) delegateShowRangeForRow(n *tree.ShowRangeForRow) (tree.State

const query = `
SELECT
CASE WHEN r.start_key < x'%[5]s' THEN NULL ELSE crdb_internal.pretty_key(r.start_key, 2) END AS start_key,
CASE WHEN r.end_key >= x'%[6]s' THEN NULL ELSE crdb_internal.pretty_key(r.end_key, 2) END AS end_key,
CASE
WHEN r.start_key = crdb_internal.table_span(%[1]d)[1] THEN '…/<TableMin>'
WHEN r.start_key < crdb_internal.table_span(%[1]d)[1] THEN '<before:'||crdb_internal.pretty_key(r.start_key,-1)||'>'
ELSE '…'||crdb_internal.pretty_key(r.start_key, 2)
END AS start_key,
CASE
WHEN r.end_key = crdb_internal.table_span(%[1]d)[2] THEN '…/<TableMax>'
WHEN r.end_key < crdb_internal.table_span(%[1]d)[2] THEN '<after:'||crdb_internal.pretty_key(r.end_key,-1)||'>'
ELSE '…'||crdb_internal.pretty_key(r.end_key, 2)
END AS end_key,
range_id,
lease_holder,
replica_localities[array_position(replicas, lease_holder)] as lease_holder_locality,
Expand Down
Loading

0 comments on commit 47a4ca1

Please sign in to comment.