@@ -25,15 +25,19 @@ import (
2525 "github.com/cockroachdb/cockroach/pkg/sql/vecindex/cspann/testutils"
2626 "github.com/cockroachdb/cockroach/pkg/sql/vecindex/vecencoding"
2727 "github.com/cockroachdb/cockroach/pkg/testutils/serverutils"
28+ "github.com/cockroachdb/cockroach/pkg/testutils/skip"
2829 "github.com/cockroachdb/cockroach/pkg/testutils/sqlutils"
30+ "github.com/cockroachdb/cockroach/pkg/testutils/testcluster"
2931 "github.com/cockroachdb/cockroach/pkg/util/leaktest"
3032 "github.com/cockroachdb/cockroach/pkg/util/log"
33+ "github.com/cockroachdb/cockroach/pkg/util/randutil"
3134 "github.com/cockroachdb/cockroach/pkg/util/vector"
35+ "github.com/stretchr/testify/require"
3236)
3337
34- // TestVecindexConcurrency builds an index on multiple goroutines, with
38+ // TestVecIndexConcurrency builds an index on multiple goroutines, with
3539// background splits and merges enabled.
36- func TestVecindexConcurrency (t * testing.T ) {
40+ func TestVecIndexConcurrency (t * testing.T ) {
3741 defer leaktest .AfterTest (t )()
3842 defer log .Scope (t ).Close (t )
3943
@@ -143,6 +147,77 @@ func TestVecindexConcurrency(t *testing.T) {
143147 logProgress ()
144148}
145149
150+ // TestVecIndexStandbyReader builds an index on a source tenant and verifies
151+ // that a PCR standby reader can read the index, but doesn't attempt to initiate
152+ // fixups.
153+ func TestVecIndexStandbyReader (t * testing.T ) {
154+ defer leaktest .AfterTest (t )()
155+ defer log .Scope (t ).Close (t )
156+
157+ skip .UnderDuress (t , "slow test" )
158+
159+ rnd , seed := randutil .NewTestRand ()
160+ t .Logf ("random seed: %v" , seed )
161+
162+ ctx := context .Background ()
163+ tc := serverutils .StartCluster (t , 3 , /* numNodes */
164+ base.TestClusterArgs {
165+ ReplicationMode : base .ReplicationManual ,
166+ ServerArgs : base.TestServerArgs {
167+ DefaultTestTenant : base .TestControlsTenantsExplicitly ,
168+ },
169+ })
170+ defer tc .Stopper ().Stop (ctx )
171+ ts := tc .Server (0 )
172+
173+ _ , srcDB , err := ts .TenantController ().StartSharedProcessTenant (ctx ,
174+ base.TestSharedProcessTenantArgs {
175+ TenantID : serverutils .TestTenantID (),
176+ TenantName : "src" ,
177+ UseDatabase : "defaultdb" ,
178+ },
179+ )
180+ require .NoError (t , err )
181+ dstTenant , dstDB , err := ts .TenantController ().StartSharedProcessTenant (ctx ,
182+ base.TestSharedProcessTenantArgs {
183+ TenantID : serverutils .TestTenantID2 (),
184+ TenantName : "dst" ,
185+ UseDatabase : "defaultdb" ,
186+ },
187+ )
188+ require .NoError (t , err )
189+
190+ srcRunner := sqlutils .MakeSQLRunner (srcDB )
191+ dstRunner := sqlutils .MakeSQLRunner (dstDB )
192+
193+ // Enable vector indexes.
194+ srcRunner .Exec (t , `SET CLUSTER SETTING feature.vector_index.enabled = true` )
195+
196+ // Construct the table.
197+ srcRunner .Exec (t , "CREATE TABLE t (id INT PRIMARY KEY, v VECTOR(512), VECTOR INDEX foo (v))" )
198+
199+ // Load features and build the index.
200+ const batchSize = 10
201+ const numBatches = 100
202+ vectors := testutils .LoadFeatures (t , batchSize * numBatches )
203+ for i := 0 ; i < numBatches ; i ++ {
204+ insertVectors (t , srcRunner , i * batchSize , vectors .Slice (i * batchSize , batchSize ))
205+ }
206+
207+ // Wait for the standby reader to catch up.
208+ asOf := testcluster .WaitForStandbyTenantReplication (t , ctx , ts .Clock (), dstTenant )
209+
210+ const queryTemplate = `SELECT * FROM t@foo %s ORDER BY v <-> '%s' LIMIT 3`
211+ asOfClause := fmt .Sprintf ("AS OF SYSTEM TIME %s" , asOf .AsOfSystemTime ())
212+ for range 10 {
213+ // Select a random vector from the set and run an ANN query against both
214+ // tenants. The query results should be identical.
215+ vec := vectors .At (rnd .Intn (vectors .Count )).String ()
216+ expected := srcRunner .QueryStr (t , fmt .Sprintf (queryTemplate , asOfClause , vec ))
217+ dstRunner .CheckQueryResults (t , fmt .Sprintf (queryTemplate , "" , vec ), expected )
218+ }
219+ }
220+
146221// Insert block of vectors within the scope of a transaction.
147222func insertVectors (t * testing.T , runner * sqlutils.SQLRunner , startId int , vectors vector.Set ) {
148223 var valuesClause strings.Builder
@@ -161,8 +236,8 @@ func insertVectors(t *testing.T, runner *sqlutils.SQLRunner, startId int, vector
161236 runner .Exec (t , query , args ... )
162237}
163238
164- // TestVecindexDeletion tests that rows can be properly deleted from a vector index.
165- func TestVecindexDeletion (t * testing.T ) {
239+ // TestVecIndexDeletion tests that rows can be properly deleted from a vector index.
240+ func TestVecIndexDeletion (t * testing.T ) {
166241 defer leaktest .AfterTest (t )()
167242 defer log .Scope (t ).Close (t )
168243
0 commit comments