diff --git a/docs/generated/sql/functions.md b/docs/generated/sql/functions.md index 17664eac7b70..5cbedb9784a6 100644 --- a/docs/generated/sql/functions.md +++ b/docs/generated/sql/functions.md @@ -3018,7 +3018,7 @@ may increase either contention or retry errors, or both.

Immutable crdb_internal.assignment_cast(val: anyelement, type: anyelement) → anyelement

This function is used internally to perform assignment casts during mutations.

Stable -crdb_internal.check_consistency(stats_only: bool, start_key: bytes, end_key: bytes) → tuple{int AS range_id, bytes AS start_key, string AS start_key_pretty, string AS status, string AS detail}

Runs a consistency check on ranges touching the specified key range. an empty start or end key is treated as the minimum and maximum possible, respectively. stats_only should only be set to false when targeting a small number of ranges to avoid overloading the cluster. Each returned row contains the range ID, the status (a roachpb.CheckConsistencyResponse_Status), and verbose detail.

+crdb_internal.check_consistency(stats_only: bool, start_key: bytes, end_key: bytes) → tuple{int AS range_id, bytes AS start_key, string AS start_key_pretty, string AS status, string AS detail, interval AS duration}

Runs a consistency check on ranges touching the specified key range. an empty start or end key is treated as the minimum and maximum possible, respectively. stats_only should only be set to false when targeting a small number of ranges to avoid overloading the cluster. Each returned row contains the range ID, the status (a roachpb.CheckConsistencyResponse_Status), and verbose detail.

Example usage: SELECT * FROM crdb_internal.check_consistency(true, ‘\x02’, ‘\x04’)

Volatile diff --git a/pkg/sql/sem/builtins/fixed_oids.go b/pkg/sql/sem/builtins/fixed_oids.go index 84c7a2bac85d..b07f58e27771 100644 --- a/pkg/sql/sem/builtins/fixed_oids.go +++ b/pkg/sql/sem/builtins/fixed_oids.go @@ -370,7 +370,7 @@ var builtinOidsBySignature = map[string]oid.Oid{ `crdb_internal.active_version() -> jsonb`: 1296, `crdb_internal.approximate_timestamp(timestamp: decimal) -> timestamp`: 1298, `crdb_internal.assignment_cast(val: anyelement, type: anyelement) -> anyelement`: 1341, - `crdb_internal.check_consistency(stats_only: bool, start_key: bytes, end_key: bytes) -> tuple{int AS range_id, bytes AS start_key, string AS start_key_pretty, string AS status, string AS detail}`: 347, + `crdb_internal.check_consistency(stats_only: bool, start_key: bytes, end_key: bytes) -> tuple{int AS range_id, bytes AS start_key, string AS start_key_pretty, string AS status, string AS detail, interval AS duration}`: 347, `crdb_internal.check_password_hash_format(password: bytes) -> string`: 1376, `crdb_internal.cluster_id() -> uuid`: 1299, `crdb_internal.cluster_name() -> string`: 1301, diff --git a/pkg/sql/sem/builtins/generator_builtins.go b/pkg/sql/sem/builtins/generator_builtins.go index 39e46869f314..6ecb00c66b3e 100644 --- a/pkg/sql/sem/builtins/generator_builtins.go +++ b/pkg/sql/sem/builtins/generator_builtins.go @@ -35,6 +35,7 @@ import ( "github.com/cockroachdb/cockroach/pkg/util/errorutil" "github.com/cockroachdb/cockroach/pkg/util/json" "github.com/cockroachdb/cockroach/pkg/util/mon" + "github.com/cockroachdb/cockroach/pkg/util/timeutil" "github.com/cockroachdb/cockroach/pkg/util/tracing" "github.com/cockroachdb/cockroach/pkg/util/tracing/tracingpb" "github.com/cockroachdb/errors" @@ -1837,6 +1838,7 @@ type checkConsistencyGenerator struct { // row and moves it to curRow. When empty, consumes from 'descs' to produce // more rows. remainingRows []roachpb.CheckConsistencyResponse_Result + curDuration time.Duration curRow roachpb.CheckConsistencyResponse_Result } @@ -1889,8 +1891,8 @@ func makeCheckConsistencyGenerator( } var checkConsistencyGeneratorType = types.MakeLabeledTuple( - []*types.T{types.Int, types.Bytes, types.String, types.String, types.String}, - []string{"range_id", "start_key", "start_key_pretty", "status", "detail"}, + []*types.T{types.Int, types.Bytes, types.String, types.String, types.String, types.Interval}, + []string{"range_id", "start_key", "start_key_pretty", "status", "detail", "duration"}, ) // ResolvedType is part of the tree.ValueGenerator interface. @@ -1929,6 +1931,7 @@ func (c *checkConsistencyGenerator) Start(ctx context.Context, _ *kv.Txn) error // Next is part of the tree.ValueGenerator interface. func (c *checkConsistencyGenerator) Next(ctx context.Context) (bool, error) { + tBegin := timeutil.Now() if len(c.remainingRows) == 0 { if len(c.descs) == 0 { return false, nil @@ -1954,9 +1957,13 @@ func (c *checkConsistencyGenerator) Next(ctx context.Context) (bool, error) { }, } } else { + // NB: this could have more than one entry, if a range split in the + // meantime. c.remainingRows = resp.Result } } + + c.curDuration = timeutil.Since(tBegin) c.curRow = c.remainingRows[0] c.remainingRows = c.remainingRows[1:] return true, nil @@ -1964,12 +1971,18 @@ func (c *checkConsistencyGenerator) Next(ctx context.Context) (bool, error) { // Values is part of the tree.ValueGenerator interface. func (c *checkConsistencyGenerator) Values() (tree.Datums, error) { + intervalMeta := types.IntervalTypeMetadata{ + DurationField: types.IntervalDurationField{ + DurationType: types.IntervalDurationType_MILLISECOND, + }, + } return tree.Datums{ tree.NewDInt(tree.DInt(c.curRow.RangeID)), tree.NewDBytes(tree.DBytes(c.curRow.StartKey)), tree.NewDString(roachpb.Key(c.curRow.StartKey).String()), tree.NewDString(c.curRow.Status.String()), tree.NewDString(c.curRow.Detail), + tree.NewDInterval(duration.MakeDuration(c.curDuration.Nanoseconds(), 0 /* days */, 0 /* months */), intervalMeta), }, nil }