Skip to content

Commit eb81daa

Browse files
committed
validator: implement index_create test case
The commit adds four tests in index_create testcase. Two for global indexes and two for local indexes, with or without additional filtering columns. The test constains index creation and simple query for the index. The query test for global index with filtering columns is disabled, because it is failing. SCYLLADB-635 bug is prepared to fix it.
1 parent 1fb30fb commit eb81daa

File tree

3 files changed

+210
-1
lines changed

3 files changed

+210
-1
lines changed

crates/validator-vector-store/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ license.workspace = true
99

1010
[dependencies]
1111
async-backtrace.workspace = true
12+
httpclient.workspace = true
1213
scylla.workspace = true
1314
scylla-proxy.workspace = true
1415
tap.workspace = true
1516
tokio.workspace = true
1617
tracing.workspace = true
1718
vector-search-validator-tests.workspace = true
1819
vector-store.workspace = true
19-
httpclient.workspace = true
Lines changed: 207 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,207 @@
1+
/*
2+
* Copyright 2026-present ScyllaDB
3+
* SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0
4+
*/
5+
6+
use async_backtrace::framed;
7+
use httpclient::HttpClient;
8+
use scylla::client::session::Session;
9+
use std::sync::Arc;
10+
use tracing::info;
11+
use vector_search_validator_tests::common::CreateIndexQuery;
12+
use vector_search_validator_tests::common::DEFAULT_TEST_TIMEOUT;
13+
use vector_search_validator_tests::*;
14+
use vector_store::IndexInfo;
15+
use vector_store::KeyspaceName;
16+
use vector_store::TableName;
17+
18+
#[framed]
19+
pub(crate) async fn new() -> TestCase {
20+
let timeout = DEFAULT_TEST_TIMEOUT;
21+
TestCase::empty()
22+
.with_init(timeout, common::init)
23+
.with_cleanup(timeout, common::cleanup)
24+
.with_test(
25+
"global_index_without_filtering_columns",
26+
timeout,
27+
global_index_without_filtering_columns,
28+
)
29+
.with_test(
30+
"global_index_with_filtering_columns",
31+
timeout,
32+
global_index_with_filtering_columns,
33+
)
34+
.with_test(
35+
"local_index_without_filtering_columns",
36+
timeout,
37+
local_index_without_filtering_columns,
38+
)
39+
.with_test(
40+
"local_index_with_filtering_columns",
41+
timeout,
42+
local_index_with_filtering_columns,
43+
)
44+
}
45+
46+
#[framed]
47+
async fn init_keyspace_table(
48+
actors: &TestActors,
49+
) -> (Arc<Session>, Vec<HttpClient>, KeyspaceName, TableName) {
50+
let (session, clients) = common::prepare_connection(actors).await;
51+
52+
info!("Creating keyspace and table");
53+
let keyspace = common::create_keyspace(&session).await;
54+
let table = common::create_table(
55+
&session,
56+
"pk INT, ck INT, v VECTOR<FLOAT, 3>, f INT, PRIMARY KEY(pk, ck)",
57+
None,
58+
)
59+
.await;
60+
61+
const DATASET_SIZE: i32 = 100;
62+
const CK_OFFSET: i32 = 1000;
63+
const F_OFFSET: i32 = 2000;
64+
65+
info!("Insert some vectors into the table");
66+
for i in 0..DATASET_SIZE {
67+
session
68+
.query_unpaged(
69+
format!("INSERT INTO {table} (pk, ck, f, v) VALUES (?, ?, ?, ?)"),
70+
(i, i + CK_OFFSET, i + F_OFFSET, &vec![i as f32; 3]),
71+
)
72+
.await
73+
.expect("failed to insert data");
74+
}
75+
(session, clients, keyspace, table)
76+
}
77+
78+
#[framed]
79+
async fn cleanup_keyspace(actors: &TestActors, keyspace: &KeyspaceName) {
80+
let (session, _clients) = common::prepare_connection(actors).await;
81+
82+
info!("Dropping keyspace");
83+
session
84+
.query_unpaged(format!("DROP KEYSPACE {keyspace}"), ())
85+
.await
86+
.expect("failed to drop a keyspace");
87+
}
88+
89+
#[framed]
90+
async fn wait_for_index(clients: &[HttpClient], index: &IndexInfo) {
91+
info!("Wait for the index to be created");
92+
for client in clients {
93+
common::wait_for_index(client, index).await;
94+
}
95+
}
96+
97+
#[framed]
98+
async fn global_index_without_filtering_columns(actors: TestActors) {
99+
info!("started");
100+
101+
let (session, clients, keyspace, table) = init_keyspace_table(&actors).await;
102+
103+
info!("Create an index");
104+
let index = common::create_index(CreateIndexQuery::new(&session, &clients, &table, "v")).await;
105+
106+
wait_for_index(&clients, &index).await;
107+
108+
info!("Query the index");
109+
let results = common::get_query_results(
110+
format!("SELECT pk FROM {table} ORDER BY v ANN OF [0.0, 0.0, 0.0] LIMIT 10"),
111+
&session,
112+
)
113+
.await;
114+
let rows = results.rows::<(i32,)>().expect("failed to get rows");
115+
assert_eq!(rows.rows_remaining(), 10);
116+
117+
cleanup_keyspace(&actors, &keyspace).await;
118+
119+
info!("finished");
120+
}
121+
122+
#[framed]
123+
async fn global_index_with_filtering_columns(actors: TestActors) {
124+
info!("started");
125+
126+
let (session, clients, keyspace, table) = init_keyspace_table(&actors).await;
127+
128+
info!("Create an index");
129+
let index = common::create_index(
130+
CreateIndexQuery::new(&session, &clients, &table, "v").filter_columns(["f"]),
131+
)
132+
.await;
133+
134+
wait_for_index(&clients, &index).await;
135+
136+
// TODO: Re-enable this test after SCYLLADB-635 is solved.
137+
// info!("Query the index");
138+
// let results = common::get_query_results(
139+
// format!("SELECT pk FROM {table} ORDER BY v ANN OF [0.0, 0.0, 0.0] LIMIT 10"),
140+
// &session,
141+
// )
142+
// .await;
143+
// let rows = results.rows::<(i32,)>().expect("failed to get rows");
144+
// assert_eq!(rows.rows_remaining(), 10);
145+
146+
cleanup_keyspace(&actors, &keyspace).await;
147+
148+
info!("finished");
149+
}
150+
151+
#[framed]
152+
async fn local_index_without_filtering_columns(actors: TestActors) {
153+
info!("started");
154+
155+
let (session, clients, keyspace, table) = init_keyspace_table(&actors).await;
156+
157+
info!("Create an index");
158+
let index = common::create_index(
159+
CreateIndexQuery::new(&session, &clients, &table, "v").partition_columns(["pk"]),
160+
)
161+
.await;
162+
163+
wait_for_index(&clients, &index).await;
164+
165+
info!("Query the index");
166+
let results = common::get_query_results(
167+
format!("SELECT pk FROM {table} ORDER BY v ANN OF [0.0, 0.0, 0.0] LIMIT 10"),
168+
&session,
169+
)
170+
.await;
171+
let rows = results.rows::<(i32,)>().expect("failed to get rows");
172+
assert_eq!(rows.rows_remaining(), 10);
173+
174+
cleanup_keyspace(&actors, &keyspace).await;
175+
176+
info!("finished");
177+
}
178+
179+
#[framed]
180+
async fn local_index_with_filtering_columns(actors: TestActors) {
181+
info!("started");
182+
183+
let (session, clients, keyspace, table) = init_keyspace_table(&actors).await;
184+
185+
info!("Create an index");
186+
let index = common::create_index(
187+
CreateIndexQuery::new(&session, &clients, &table, "v")
188+
.partition_columns(["pk"])
189+
.filter_columns(["f"]),
190+
)
191+
.await;
192+
193+
wait_for_index(&clients, &index).await;
194+
195+
info!("Query the index");
196+
let results = common::get_query_results(
197+
format!("SELECT pk FROM {table} ORDER BY v ANN OF [0.0, 0.0, 0.0] LIMIT 10"),
198+
&session,
199+
)
200+
.await;
201+
let rows = results.rows::<(i32,)>().expect("failed to get rows");
202+
assert_eq!(rows.rows_remaining(), 10);
203+
204+
cleanup_keyspace(&actors, &keyspace).await;
205+
206+
info!("finished");
207+
}

crates/validator-vector-store/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ mod crud;
99
mod db_timeout;
1010
mod full_scan;
1111
mod high_availability;
12+
mod index_create;
1213
mod index_status;
1314
mod quantization_and_rescoring;
1415
mod reconnect;
@@ -28,6 +29,7 @@ pub async fn test_cases() -> impl Iterator<Item = (String, TestCase)> {
2829
("full_scan", full_scan::new().await),
2930
("high_availability", high_availability::new().await),
3031
("index_status", index_status::new().await),
32+
("index_create", index_create::new().await),
3133
("reconnect", reconnect::new().await),
3234
("serde", serde::new().await),
3335
("similarity_function", similarity_functions::new().await),

0 commit comments

Comments
 (0)