diff --git a/docs/generated/sql/functions.md b/docs/generated/sql/functions.md index 4277a9bd7045..35fbc2ced206 100644 --- a/docs/generated/sql/functions.md +++ b/docs/generated/sql/functions.md @@ -3106,6 +3106,8 @@ may increase either contention or retry errors, or both.
crdb_internal.encode_key(table_id: int, index_id: int, row_tuple: anyelement) → bytes
Generate the key for a row on a particular table and index.
crdb_internal.fingerprint(span: bytes[], start_time: decimal, all_revisions: bool) → int
This function is used only by CockroachDB’s developers for testing purposes.
+crdb_internal.fingerprint(span: bytes[], start_time: timestamptz, all_revisions: bool) → int
This function is used only by CockroachDB’s developers for testing purposes.
crdb_internal.fingerprint(span: bytes[], stripped: bool) → int
This function is used only by CockroachDB’s developers for testing purposes.
diff --git a/pkg/ccl/streamingccl/replicationtestutils/testutils.go b/pkg/ccl/streamingccl/replicationtestutils/testutils.go index 9df6af3b71ba..70acdb3c5107 100644 --- a/pkg/ccl/streamingccl/replicationtestutils/testutils.go +++ b/pkg/ccl/streamingccl/replicationtestutils/testutils.go @@ -149,7 +149,8 @@ func (c *TenantStreamingClusters) RequireDestinationFingerprintAtTimestamp( func FingerprintTenantAtTimestampNoHistory( t sqlutils.Fataler, db *sqlutils.SQLRunner, tenantID uint64, timestamp string, ) string { - fingerprintQuery := fmt.Sprintf("SELECT * FROM crdb_internal.fingerprint(crdb_internal.tenant_span($1::INT), 0::TIMESTAMPTZ, false) AS OF SYSTEM TIME %s", timestamp) + fingerprintQuery := fmt.Sprintf("SELECT * FROM crdb_internal.fingerprint(crdb_internal."+ + "tenant_span($1::INT), 0::DECIMAL, false) AS OF SYSTEM TIME %s", timestamp) return db.QueryStr(t, fingerprintQuery, tenantID)[0][0] } diff --git a/pkg/cmd/roachtest/tests/cluster_to_cluster.go b/pkg/cmd/roachtest/tests/cluster_to_cluster.go index bcc4d5ff5164..fae0d042fd56 100644 --- a/pkg/cmd/roachtest/tests/cluster_to_cluster.go +++ b/pkg/cmd/roachtest/tests/cluster_to_cluster.go @@ -583,17 +583,12 @@ func (rd *replicationDriver) compareTenantFingerprintsAtTimestamp( rd.t.Status(fmt.Sprintf("comparing tenant fingerprints between start time %s and end time %s", startTime.UTC(), endTime.UTC())) - // TODO(adityamaru,lidorcarmel): Once we agree on the format and precision we - // display all user facing timestamps with, we should revisit how we format - // the start time to ensure we are fingerprinting from the most accurate lower - // bound. - microSecondRFC3339Format := "2006-01-02 15:04:05.999999" - startTimeStr := startTime.Format(microSecondRFC3339Format) + startTimeDecimal := hlc.Timestamp{WallTime: startTime.UnixNano()}.AsOfSystemTime() aost := hlc.Timestamp{WallTime: endTime.UnixNano()}.AsOfSystemTime() fingerprintQuery := fmt.Sprintf(` SELECT * -FROM crdb_internal.fingerprint(crdb_internal.tenant_span($1::INT), '%s'::TIMESTAMPTZ, true) -AS OF SYSTEM TIME '%s'`, startTimeStr, aost) +FROM crdb_internal.fingerprint(crdb_internal.tenant_span($1::INT), '%s'::DECIMAL, true) +AS OF SYSTEM TIME '%s'`, startTimeDecimal, aost) var srcFingerprint int64 fingerPrintMonitor := rd.newMonitor(ctx) diff --git a/pkg/sql/sem/builtins/builtins.go b/pkg/sql/sem/builtins/builtins.go index 24aa614b263e..d9dbe61598ed 100644 --- a/pkg/sql/sem/builtins/builtins.go +++ b/pkg/sql/sem/builtins/builtins.go @@ -7627,6 +7627,22 @@ expires until the statement bundle is collected`, Info: "This function is used only by CockroachDB's developers for testing purposes.", Volatility: volatility.Stable, }, + tree.Overload{ + Types: tree.ParamTypes{ + {Name: "span", Typ: types.BytesArray}, + {Name: "start_time", Typ: types.Decimal}, + {Name: "all_revisions", Typ: types.Bool}, + // NB: The function can be called with an AOST clause that will be used + // as the `end_time` when issuing the ExportRequests for the purposes of + // fingerprinting. + }, + ReturnType: tree.FixedReturnType(types.Int), + Fn: func(ctx context.Context, evalCtx *eval.Context, args tree.Datums) (tree.Datum, error) { + return verboseFingerprint(ctx, evalCtx, args) + }, + Info: "This function is used only by CockroachDB's developers for testing purposes.", + Volatility: volatility.Stable, + }, tree.Overload{ Types: tree.ParamTypes{ {Name: "span", Typ: types.BytesArray}, @@ -7638,17 +7654,7 @@ expires until the statement bundle is collected`, }, ReturnType: tree.FixedReturnType(types.Int), Fn: func(ctx context.Context, evalCtx *eval.Context, args tree.Datums) (tree.Datum, error) { - if len(args) != 3 { - return nil, errors.New("argument list must have three elements") - } - span, err := parseSpan(args[0]) - if err != nil { - return nil, err - } - startTime := tree.MustBeDTimestampTZ(args[1]).Time - startTimestamp := hlc.Timestamp{WallTime: startTime.UnixNano()} - allRevisions := bool(tree.MustBeDBool(args[2])) - return fingerprint(ctx, evalCtx, span, startTimestamp, allRevisions /* stripped */, false) + return verboseFingerprint(ctx, evalCtx, args) }, Info: "This function is used only by CockroachDB's developers for testing purposes.", Volatility: volatility.Stable, diff --git a/pkg/sql/sem/builtins/fingerprint_builtin_test.go b/pkg/sql/sem/builtins/fingerprint_builtin_test.go index 8928d103d35f..6f70e1fb3f01 100644 --- a/pkg/sql/sem/builtins/fingerprint_builtin_test.go +++ b/pkg/sql/sem/builtins/fingerprint_builtin_test.go @@ -21,7 +21,6 @@ import ( "github.com/cockroachdb/cockroach/pkg/kv/kvserver" "github.com/cockroachdb/cockroach/pkg/roachpb" "github.com/cockroachdb/cockroach/pkg/server" - "github.com/cockroachdb/cockroach/pkg/sql/sem/eval" "github.com/cockroachdb/cockroach/pkg/storage" "github.com/cockroachdb/cockroach/pkg/testutils/serverutils" "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils" @@ -89,10 +88,11 @@ func TestFingerprint(t *testing.T) { } fingerprint := func(t *testing.T, startKey, endKey string, startTime, endTime hlc.Timestamp, allRevisions bool) int64 { - decimal := eval.TimestampToDecimal(endTime) + aost := endTime.AsOfSystemTime() var fingerprint int64 - query := fmt.Sprintf(`SELECT * FROM crdb_internal.fingerprint(ARRAY[$1::BYTES, $2::BYTES], $3, $4) AS OF SYSTEM TIME %s`, decimal.String()) - require.NoError(t, sqlDB.QueryRow(query, roachpb.Key(startKey), roachpb.Key(endKey), startTime.GoTime(), allRevisions).Scan(&fingerprint)) + query := fmt.Sprintf(`SELECT * FROM crdb_internal.fingerprint(ARRAY[$1::BYTES, $2::BYTES],$3::DECIMAL, $4) AS OF SYSTEM TIME '%s'`, aost) + require.NoError(t, sqlDB.QueryRow(query, roachpb.Key(startKey), roachpb.Key(endKey), + startTime.AsOfSystemTime(), allRevisions).Scan(&fingerprint)) return fingerprint } diff --git a/pkg/sql/sem/builtins/fingerprint_builtins.go b/pkg/sql/sem/builtins/fingerprint_builtins.go index e50561be7058..c1611869541f 100644 --- a/pkg/sql/sem/builtins/fingerprint_builtins.go +++ b/pkg/sql/sem/builtins/fingerprint_builtins.go @@ -31,6 +31,33 @@ import ( "github.com/cockroachdb/errors" ) +func verboseFingerprint( + ctx context.Context, evalCtx *eval.Context, args tree.Datums, +) (tree.Datum, error) { + if len(args) != 3 { + return nil, errors.New("argument list must have three elements") + } + span, err := parseSpan(args[0]) + if err != nil { + return nil, err + } + + // The startTime can either be a timestampTZ or a decimal. + var startTimestamp hlc.Timestamp + if parsedDecimal, ok := tree.AsDDecimal(args[1]); ok { + startTimestamp, err = hlc.DecimalToHLC(&parsedDecimal.Decimal) + if err != nil { + return nil, err + } + } else { + startTime := tree.MustBeDTimestampTZ(args[1]).Time + startTimestamp = hlc.Timestamp{WallTime: startTime.UnixNano()} + } + + allRevisions := bool(tree.MustBeDBool(args[2])) + return fingerprint(ctx, evalCtx, span, startTimestamp, allRevisions /* stripped */, false) +} + func fingerprint( ctx context.Context, evalCtx *eval.Context, diff --git a/pkg/sql/sem/builtins/fixed_oids.go b/pkg/sql/sem/builtins/fixed_oids.go index f619f7cd50d5..9fa7fd84f7c1 100644 --- a/pkg/sql/sem/builtins/fixed_oids.go +++ b/pkg/sql/sem/builtins/fixed_oids.go @@ -2383,6 +2383,7 @@ var builtinOidsArray = []string{ 2410: `crdb_internal.pretty_value(raw_value: bytes) -> string`, 2411: `to_char(date: date, format: string) -> string`, 2412: `crdb_internal.unsafe_lock_replica(range_id: int, lock: bool) -> bool`, + 2413: `crdb_internal.fingerprint(span: bytes[], start_time: decimal, all_revisions: bool) -> int`, } var builtinOidsBySignature map[string]oid.Oid