Skip to content

Commit 01284ad

Browse files
authored
Merge pull request #151802 from cockroachdb/blathers/backport-release-25.3-151787
release-25.3: fingerprintutils: select database and tables with aost if specified
2 parents 72d6ff3 + 6211772 commit 01284ad

File tree

2 files changed

+61
-8
lines changed

2 files changed

+61
-8
lines changed

pkg/testutils/fingerprintutils/fingerprint.go

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ type FingerprintOption struct {
2222
StartTime hlc.Timestamp
2323
}
2424

25+
func (f FingerprintOption) AOSTCmd() string {
26+
if f.AOST.IsEmpty() {
27+
return ""
28+
}
29+
return fmt.Sprintf("AS OF SYSTEM TIME '%s'", f.AOST.AsOfSystemTime())
30+
}
31+
2532
func AOST(aost hlc.Timestamp) func(*FingerprintOption) {
2633
return func(opt *FingerprintOption) {
2734
opt.AOST = aost
@@ -69,10 +76,7 @@ func FingerprintTable(
6976
return 0, err
7077
}
7178

72-
aostCmd := ""
73-
if !opts.AOST.IsEmpty() {
74-
aostCmd = fmt.Sprintf("AS OF SYSTEM TIME '%s'", opts.AOST.AsOfSystemTime())
75-
}
79+
aostCmd := opts.AOSTCmd()
7680

7781
cmd := fmt.Sprintf(`SELECT * FROM crdb_internal.fingerprint(crdb_internal.table_span(%d),true) %s`, tableID, aostCmd)
7882

@@ -115,12 +119,18 @@ func FingerprintTables(
115119
func FingerprintDatabase(
116120
ctx context.Context, db *gosql.DB, dbName string, optFuncs ...func(*FingerprintOption),
117121
) (map[string]int64, error) {
122+
opts, err := getOpts(optFuncs...)
123+
if err != nil {
124+
return nil, err
125+
}
126+
aostCmd := opts.AOSTCmd()
127+
118128
var databaseID int
119-
row := db.QueryRowContext(ctx, `SELECT id FROM system.namespace WHERE name = $1`, dbName)
129+
row := db.QueryRowContext(ctx, fmt.Sprintf(`SELECT id FROM system.namespace %s WHERE name = $1`, aostCmd), dbName)
120130
if err := row.Scan(&databaseID); err != nil {
121131
return nil, errors.New("could not get database descriptor id")
122132
}
123-
rows, err := db.QueryContext(ctx, `SELECT id, name FROM system.namespace where "parentID" = $1`, databaseID)
133+
rows, err := db.QueryContext(ctx, fmt.Sprintf(`SELECT id, name FROM system.namespace %s where "parentID" = $1`, aostCmd), databaseID)
124134
if err != nil {
125135
return nil, errors.New("could not get database table name and tableIDs")
126136
}
@@ -158,9 +168,12 @@ func FingerprintDatabase(
158168
func FingerprintAllDatabases(
159169
ctx context.Context, db *gosql.DB, includeSystemDB bool, optFuncs ...func(*FingerprintOption),
160170
) (map[string]map[string]int64, error) {
161-
171+
opts, err := getOpts(optFuncs...)
172+
if err != nil {
173+
return nil, err
174+
}
162175
dbNames := make([]string, 0)
163-
rows, err := db.QueryContext(ctx, `SELECT database_name FROM [SHOW DATABASES]`)
176+
rows, err := db.QueryContext(ctx, fmt.Sprintf(`select name from system.namespace %s where "parentID"=0`, opts.AOSTCmd()))
164177
if err != nil {
165178
return nil, errors.Wrap(err, "could not get database names")
166179
}

pkg/testutils/fingerprintutils/fingerprint_test.go

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/cockroachdb/cockroach/pkg/testutils/testcluster"
1717
"github.com/cockroachdb/cockroach/pkg/util/hlc"
1818
"github.com/cockroachdb/cockroach/pkg/util/leaktest"
19+
"github.com/cockroachdb/cockroach/pkg/util/randutil"
1920
"github.com/cockroachdb/cockroach/pkg/util/timeutil"
2021
"github.com/stretchr/testify/require"
2122
)
@@ -73,3 +74,42 @@ func TestFingerprintUtility(t *testing.T) {
7374
_, err = fingerprintutils.FingerprintDatabase(ctx, db, "d1", fingerprintutils.Stripped(), fingerprintutils.RevisionHistory())
7475
require.ErrorContains(t, err, "cannot specify stripped and revision history")
7576
}
77+
78+
// TestFingerprintAllDatabasesWithAOST tests that FingerprintAllDatabases works
79+
// correctly when using AOST (As Of System Time) even when the target
80+
// database/tables are deleted after the AOST timestamp.
81+
func TestFingerprintAllDatabasesWithAOST(t *testing.T) {
82+
defer leaktest.AfterTest(t)()
83+
84+
ctx := context.Background()
85+
tc := testcluster.StartTestCluster(t, 1, base.TestClusterArgs{})
86+
defer tc.Stopper().Stop(ctx)
87+
db := tc.ServerConn(0)
88+
sql := sqlutils.MakeSQLRunner(db)
89+
90+
rng, _ := randutil.NewTestRand()
91+
92+
sql.Exec(t, `CREATE DATABASE test_aost`)
93+
sql.Exec(t, `CREATE TABLE test_aost.table_to_delete (id INT PRIMARY KEY, data STRING)`)
94+
sql.Exec(t, `INSERT INTO test_aost.table_to_delete VALUES (1, 'test_data')`)
95+
96+
aostTimestamp := hlc.Timestamp{WallTime: timeutil.Now().UnixNano()}
97+
98+
sql.Exec(t, `DROP TABLE test_aost.table_to_delete`)
99+
if rng.Intn(2) == 0 {
100+
sql.Exec(t, `DROP DATABASE test_aost`)
101+
}
102+
103+
// FingerprintAllDatabases with AOST should still work and find the deleted table
104+
fingerprintsAOST, err := fingerprintutils.FingerprintAllDatabases(ctx, db, false,
105+
fingerprintutils.AOST(aostTimestamp))
106+
require.NoError(t, err)
107+
108+
testAostFingerprints, exists := fingerprintsAOST["test_aost"]
109+
require.True(t, exists, "test_aost database should be found in fingerprints")
110+
111+
// Verify that the deleted table is found in the AOST fingerprint
112+
tableFingerprint, exists := testAostFingerprints["table_to_delete"]
113+
require.True(t, exists, "table_to_delete should be found in AOST fingerprints")
114+
require.NotZero(t, tableFingerprint, "fingerprint should be non-zero")
115+
}

0 commit comments

Comments
 (0)