Skip to content

Commit 92b4af4

Browse files
craig[bot]bghal
andcommitted
Merge #153727
153727: sql: implement show inspect errors r=bghal a=bghal Adds the implementation for `SHOW INSPECT ERRORS` which reads from the `system.inspect_errors` table. This command is used to review the results of the data consistency validation jobs spun up by `INSPECT`. Part of: #148287 Epic: CRDB-30356 Release note: None Co-authored-by: Brendan Gerrity <[email protected]>
2 parents ac68bca + 9b1f81d commit 92b4af4

File tree

10 files changed

+233
-42
lines changed

10 files changed

+233
-42
lines changed

pkg/sql/catalog/bootstrap/testdata/testdata

Lines changed: 4 additions & 4 deletions
Large diffs are not rendered by default.

pkg/sql/catalog/catprivilege/system.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ var (
2727
catconstants.StatementActivityTableName,
2828
catconstants.TransactionActivityTableName,
2929
catconstants.PreparedTransactionsTableName,
30-
catconstants.InspectErrorsTableName,
3130
}
3231

3332
readWriteSystemTables = []catconstants.SystemTableName{
@@ -83,6 +82,7 @@ var (
8382
catconstants.TransactionDiagnosticsRequestsTableName,
8483
catconstants.TransactionDiagnosticsTableName,
8584
catconstants.StatementHintsTableName,
85+
catconstants.InspectErrorsTableName,
8686
}
8787

8888
readWriteSystemSequences = []catconstants.SystemTableName{

pkg/sql/catalog/systemschema_test/testdata/bootstrap_system

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.

pkg/sql/catalog/systemschema_test/testdata/bootstrap_tenant

Lines changed: 3 additions & 3 deletions
Large diffs are not rendered by default.

pkg/sql/delegate/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ go_library(
6262
"//pkg/sql/privilege",
6363
"//pkg/sql/roleoption",
6464
"//pkg/sql/sem/catconstants",
65+
"//pkg/sql/sem/catid",
6566
"//pkg/sql/sem/eval",
6667
"//pkg/sql/sem/tree",
6768
"//pkg/sql/sessiondatapb",

pkg/sql/delegate/show_inspect_errors.go

Lines changed: 65 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,15 @@
66
package delegate
77

88
import (
9+
"fmt"
910
"strings"
1011

12+
"github.com/cockroachdb/cockroach/pkg/clusterversion"
13+
"github.com/cockroachdb/cockroach/pkg/jobs"
14+
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
15+
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
1116
"github.com/cockroachdb/cockroach/pkg/sql/privilege"
17+
"github.com/cockroachdb/cockroach/pkg/sql/sem/catid"
1218
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
1319
"github.com/cockroachdb/cockroach/pkg/sql/sqltelemetry"
1420
"github.com/cockroachdb/cockroach/pkg/sql/syntheticprivilege"
@@ -17,21 +23,78 @@ import (
1723
func (d *delegator) delegateShowInspectErrors(n *tree.ShowInspectErrors) (tree.Statement, error) {
1824
sqltelemetry.IncrementShowCounter(sqltelemetry.InspectErrors)
1925

26+
if !d.evalCtx.Settings.Version.IsActive(d.ctx, clusterversion.V25_4) {
27+
return nil, pgerror.Newf(pgcode.FeatureNotSupported, "SHOW INSPECT ERRORS requires the cluster to be upgraded to v25.4")
28+
}
29+
2030
if err := d.catalog.CheckPrivilege(d.ctx, syntheticprivilege.GlobalPrivilegeObject,
2131
d.catalog.GetCurrentUser(), privilege.INSPECT); err != nil {
2232
return nil, err
2333
}
2434

35+
var tableID = catid.InvalidDescID
2536
if n.TableName != nil {
26-
_, _, err := d.catalog.ResolveDataSource(d.ctx, resolveFlags, n.TableName)
37+
resolvedTableID, err := d.evalCtx.Planner.ResolveTableName(d.ctx, n.TableName)
2738
if err != nil {
2839
return nil, err
2940
}
3041

42+
tableID = catid.DescID(resolvedTableID)
3143
}
3244

3345
var query strings.Builder
34-
query.WriteString("SELECT * FROM system.inspect_errors")
46+
47+
query.WriteString(`WITH
48+
inspect_jobs AS (
49+
SELECT id
50+
FROM crdb_internal.system_jobs
51+
WHERE job_type = 'INSPECT'
52+
`)
53+
if n.JobID == nil {
54+
query.WriteString(fmt.Sprintf(` AND status IN ('%s', '%s', '%s', '%s')`,
55+
jobs.StateFailed, jobs.StateSucceeded, jobs.StateCanceled, jobs.StateRevertFailed)) // in terminal state
56+
} else {
57+
query.WriteString(fmt.Sprintf(" AND id = %d", *n.JobID))
58+
}
59+
60+
// TODO(148287): query the inspect job payload to figure out if a job touches a particular table or database ID
61+
// If a table was specified, only consider jobs that reported errors on it.
62+
// If a job ID was specified, only consider that job. The records from the
63+
// most recent completed job that satisfies those criteria is used.
64+
query.WriteString(`),
65+
job_id AS (
66+
SELECT max(inspect_jobs.id) as id
67+
FROM inspect_jobs
68+
JOIN crdb_internal.cluster_inspect_errors ie ON inspect_jobs.id = ie.job_id
69+
WHERE 1=1
70+
`)
71+
if tableID != catid.InvalidDescID {
72+
query.WriteString(fmt.Sprintf(" AND ie.id = %d", tableID))
73+
}
74+
if n.JobID != nil {
75+
query.WriteString(fmt.Sprintf(" AND ie.job_id = %d", *n.JobID))
76+
}
77+
78+
query.WriteString(`)
79+
SELECT
80+
ie.error_type,
81+
COALESCE(t.database_name, '<unknown>') AS database_name,
82+
COALESCE(t.schema_name, '<unknown>') AS schema_name,
83+
COALESCE(t.object_name, '<unknown>') AS table_name,
84+
primary_key,
85+
ie.job_id,
86+
to_char(aost, 'YYYY-MM-DD HH24:MI:SS.US') as aost`)
87+
if n.WithDetails {
88+
query.WriteString(", jsonb_pretty(ie.details) as details")
89+
}
90+
query.WriteString(`
91+
FROM crdb_internal.cluster_inspect_errors ie
92+
LEFT JOIN crdb_internal.fully_qualified_names t ON ie.id = t.object_id
93+
WHERE ie.job_id IN (SELECT id FROM job_id)`)
94+
if tableID != catid.InvalidDescID {
95+
query.WriteString(fmt.Sprintf(" AND ie.id = %d", tableID))
96+
}
97+
query.WriteString(` ORDER BY ie.error_type, ie.error_id`)
3598

3699
return d.parse(query.String())
37100
}

pkg/sql/inspect_node.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ package sql
88
import (
99
"context"
1010

11+
"github.com/cockroachdb/cockroach/pkg/clusterversion"
12+
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgcode"
13+
"github.com/cockroachdb/cockroach/pkg/sql/pgwire/pgerror"
1114
"github.com/cockroachdb/cockroach/pkg/sql/privilege"
1215
"github.com/cockroachdb/cockroach/pkg/sql/sem/tree"
1316
"github.com/cockroachdb/cockroach/pkg/util/errorutil/unimplemented"
@@ -23,6 +26,14 @@ type inspectNode struct {
2326
// Inspect checks the database.
2427
// Privileges: INSPECT.
2528
func (p *planner) Inspect(ctx context.Context, n *tree.Inspect) (planNode, error) {
29+
if !p.extendedEvalCtx.Settings.Version.IsActive(ctx, clusterversion.V25_4) {
30+
return nil, pgerror.Newf(pgcode.FeatureNotSupported, "SHOW INSPECT ERRORS requires the cluster to be upgraded to v25.4")
31+
}
32+
33+
if err := p.CheckGlobalPrivilegeOrRoleOption(ctx, privilege.INSPECT); err != nil {
34+
return nil, err
35+
}
36+
2637
switch n.Typ {
2738
case tree.InspectTable:
2839
tableName := n.Table.ToTableName()
@@ -39,10 +50,6 @@ func (p *planner) Inspect(ctx context.Context, n *tree.Inspect) (planNode, error
3950
return nil, errors.AssertionFailedf("unexpected INSPECT type received, got: %v", n.Typ)
4051
}
4152

42-
if err := p.CheckGlobalPrivilegeOrRoleOption(ctx, privilege.INSPECT); err != nil {
43-
return nil, err
44-
}
45-
4653
return &inspectNode{n: n}, nil
4754
}
4855

pkg/sql/logictest/testdata/logic_test/inspect

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,24 +57,33 @@ subtest end
5757
# inspect and scrub are converging so for now tests on INSPECT live here
5858
subtest inspect
5959

60+
onlyif config local-mixed-25.2 local-mixed-25.3
61+
statement error pq: SHOW INSPECT ERRORS requires the cluster to be upgraded to v25.4
62+
SHOW INSPECT ERRORS
63+
6064
statement ok
6165
CREATE TABLE foo (c1 INT);
6266

67+
skipif config local-mixed-25.2 local-mixed-25.3
6368
statement error INSPECT TABLE requires the enable_inspect_command setting to be enabled
6469
INSPECT TABLE foo;
6570

71+
skipif config local-mixed-25.2 local-mixed-25.3
6672
statement error INSPECT DATABASE requires the enable_inspect_command setting to be enabled
6773
INSPECT DATABASE test;
6874

6975
statement ok
7076
SET enable_inspect_command = true;
7177

78+
skipif config local-mixed-25.2 local-mixed-25.3
7279
statement ok
7380
INSPECT TABLE foo;
7481

82+
skipif config local-mixed-25.2 local-mixed-25.3
7583
statement ok
7684
INSPECT TABLE foo WITH OPTIONS INDEX (bar.public.biz);
7785

86+
skipif config local-mixed-25.2 local-mixed-25.3
7887
statement ok
7988
INSPECT TABLE foo AS OF SYSTEM TIME 1 WITH OPTIONS INDEX (bar,biz);
8089

@@ -84,9 +93,11 @@ CREATE USER testuser2;
8493

8594
user testuser2
8695

96+
skipif config local-mixed-25.2 local-mixed-25.3
8797
statement error pq: user testuser2 does not have INSPECT privilege
8898
INSPECT TABLE foo;
8999

100+
skipif config local-mixed-25.2 local-mixed-25.3
90101
statement error pq: user testuser2 does not have INSPECT privilege
91102
INSPECT DATABASE test;
92103

@@ -100,9 +111,11 @@ user testuser2
100111
statement ok
101112
SET enable_inspect_command = true;
102113

114+
skipif config local-mixed-25.2 local-mixed-25.3
103115
statement ok
104116
INSPECT TABLE foo;
105117

118+
skipif config local-mixed-25.2 local-mixed-25.3
106119
statement ok
107120
INSPECT DATABASE test;
108121

Lines changed: 121 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,142 @@
1+
onlyif config local-mixed-25.2 local-mixed-25.3
2+
statement error pq: SHOW INSPECT ERRORS requires the cluster to be upgraded to v25.4
3+
SHOW INSPECT ERRORS
4+
15
user testuser
26

3-
skipif config local-mixed-25.2
4-
skipif config local-mixed-25.3
7+
skipif config local-mixed-25.2 local-mixed-25.3
58
statement error pq: user testuser does not have INSPECT system privilege
69
SHOW INSPECT ERRORS
710

811
user root
912

10-
skipif config local-mixed-25.2
11-
skipif config local-mixed-25.3
13+
statement ok
14+
GRANT SYSTEM INSPECT TO testuser;
15+
16+
skipif config local-mixed-25.2 local-mixed-25.3
1217
statement error relation "bad_table" does not exist
1318
SHOW INSPECT ERRORS FOR TABLE bad_table
1419

1520
statement ok
16-
CREATE TABLE foo (a INT)
21+
CREATE TABLE foo (a INT);
22+
CREATE TABLE bar (b INT);
23+
24+
let $foo_table_id
25+
SELECT 'foo'::regclass::oid
26+
27+
let $bar_table_id
28+
SELECT 'bar'::regclass::oid
29+
30+
let $database_id
31+
SELECT id FROM system.namespace WHERE name = current_database() AND "parentID" = 0
32+
33+
let $schema_id
34+
SELECT current_schema()::regnamespace::oid
35+
36+
let $aost
37+
SELECT '2025-09-23-11:02:14-04:00'::timestamp
38+
39+
# the job_info insert addresses the `crdb_internal.system_jobs` inner join
40+
statement ok
41+
INSERT INTO system.jobs (id, owner, status, job_type)
42+
VALUES (555, 'testuser', 'failed', 'INSPECT');
43+
INSERT INTO system.job_info (job_id, info_key)
44+
VALUES (555, 'legacy_payload');
1745

18-
skipif config local-mixed-25.2
19-
skipif config local-mixed-25.3
46+
skipif config local-mixed-25.2 local-mixed-25.3
2047
statement ok
21-
SHOW INSPECT ERRORS
48+
INSERT INTO system.inspect_errors (job_id, error_type, aost, database_id, schema_id, id, details)
49+
VALUES
50+
(555, '555_foo', '$aost', $database_id, $schema_id, $foo_table_id, '{"detail":"555\"foo"}'),
51+
(555, '555_bar', '$aost', $database_id, $schema_id, $bar_table_id, '{"detail":"555\"bar"}');
2252

23-
skipif config local-mixed-25.2
24-
skipif config local-mixed-25.3
2553
statement ok
26-
SHOW INSPECT ERRORS WITH DETAILS
54+
INSERT INTO system.jobs (id, owner, status, job_type)
55+
VALUES (666, 'testuser', 'failed', 'INSPECT');
56+
INSERT INTO system.job_info (job_id, info_key)
57+
VALUES (666, 'legacy_payload');
2758

28-
skipif config local-mixed-25.2
29-
skipif config local-mixed-25.3
59+
skipif config local-mixed-25.2 local-mixed-25.3
3060
statement ok
31-
SHOW INSPECT ERRORS FOR JOB 666
61+
INSERT INTO system.inspect_errors (job_id, error_type, aost, database_id, schema_id, id, details)
62+
VALUES (666, '666_foo', '$aost', $database_id, $schema_id, $foo_table_id, '{"detail1":"\u2603 666_foo_1","detail2":"\n666_foo_2"}');
3263

33-
skipif config local-mixed-25.2
34-
skipif config local-mixed-25.3
3564
statement ok
36-
SHOW INSPECT ERRORS FOR TABLE foo
65+
INSERT INTO system.jobs (id, owner, status, job_type)
66+
VALUES (777, 'testuser', 'running', 'INSPECT');
67+
INSERT INTO system.job_info (job_id, info_key)
68+
VALUES (777, 'legacy_payload');
3769

38-
skipif config local-mixed-25.2
39-
skipif config local-mixed-25.3
70+
skipif config local-mixed-25.2 local-mixed-25.3
4071
statement ok
41-
SHOW INSPECT ERRORS FOR TABLE foo FOR JOB 666 WITH DETAILS
72+
INSERT INTO system.inspect_errors (job_id, error_type, aost, database_id, schema_id, id, details)
73+
VALUES (777, '777_foo', '$aost', $database_id, $schema_id, $foo_table_id, '{"detail":"777 foo"}');
74+
75+
user testuser
76+
77+
# no options should show most records from the recent completed job
78+
skipif config local-mixed-25.2 local-mixed-25.3
79+
query TTTTTIT colnames
80+
SHOW INSPECT ERRORS
81+
----
82+
error_type database_name schema_name table_name primary_key job_id aost
83+
666_foo test public foo NULL 666 2025-09-23 04:00:00.000000
84+
85+
skipif config local-mixed-25.2 local-mixed-25.3
86+
query TTTTTITT colnames
87+
SHOW INSPECT ERRORS WITH DETAILS
88+
----
89+
error_type database_name schema_name table_name primary_key job_id aost details
90+
666_foo test public foo NULL 666 2025-09-23 04:00:00.000000 {
91+
"detail1": "☃ 666_foo_1",
92+
"detail2": "\n666_foo_2"
93+
}
94+
95+
# specifying a job shows results regardless of status
96+
skipif config local-mixed-25.2 local-mixed-25.3
97+
query TTTTTIT
98+
SHOW INSPECT ERRORS FOR JOB 777
99+
----
100+
777_foo test public foo NULL 777 2025-09-23 04:00:00.000000
101+
102+
skipif config local-mixed-25.2 local-mixed-25.3
103+
query TTTTTIT nosort
104+
SHOW INSPECT ERRORS FOR JOB 555
105+
----
106+
555_bar test public bar NULL 555 2025-09-23 04:00:00.000000
107+
555_foo test public foo NULL 555 2025-09-23 04:00:00.000000
108+
109+
# query by table shows records from the most recent completed job that reported errors on that table
110+
skipif config local-mixed-25.2 local-mixed-25.3
111+
query TTTTTIT
112+
SHOW INSPECT ERRORS FOR TABLE foo
113+
----
114+
666_foo test public foo NULL 666 2025-09-23 04:00:00.000000
115+
116+
# and query by table only shows records for that given table
117+
skipif config local-mixed-25.2 local-mixed-25.3
118+
query TTTTTIT
119+
SHOW INSPECT ERRORS FOR TABLE bar
120+
----
121+
555_bar test public bar NULL 555 2025-09-23 04:00:00.000000
122+
123+
skipif config local-mixed-25.2 local-mixed-25.3
124+
query TTTTTIT
125+
SHOW INSPECT ERRORS FOR TABLE public.bar
126+
----
127+
555_bar test public bar NULL 555 2025-09-23 04:00:00.000000
128+
129+
skipif config local-mixed-25.2 local-mixed-25.3
130+
query TTTTTIT
131+
SHOW INSPECT ERRORS FOR TABLE test.public.bar
132+
----
133+
555_bar test public bar NULL 555 2025-09-23 04:00:00.000000
134+
135+
skipif config local-mixed-25.2 local-mixed-25.3
136+
query TTTTTITT colnames
137+
SHOW INSPECT ERRORS FOR TABLE foo FOR JOB 555 WITH DETAILS
138+
----
139+
error_type database_name schema_name table_name primary_key job_id aost details
140+
555_foo test public foo NULL 555 2025-09-23 04:00:00.000000 {
141+
"detail": "555\"foo"
142+
}

0 commit comments

Comments
 (0)