Skip to content

Commit 56033d1

Browse files
committed
Add regression test for _iter typechecking
1 parent 3aab188 commit 56033d1

File tree

1 file changed

+71
-0
lines changed
  • scylla/tests/integration/session

1 file changed

+71
-0
lines changed

scylla/tests/integration/session/pager.rs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use std::sync::{
33
atomic::{AtomicBool, Ordering},
44
};
55

6+
use assert_matches::assert_matches;
67
use futures::{StreamExt as _, TryStreamExt as _};
8+
use scylla::errors::{NextPageError, NextRowError};
79
use scylla::{
810
client::execution_profile::ExecutionProfile,
911
policies::retry::{RequestInfo, RetryDecision, RetryPolicy, RetrySession},
@@ -149,3 +151,72 @@ async fn test_iter_methods_with_modification_statements() {
149151

150152
session.ddl(format!("DROP KEYSPACE {ks}")).await.unwrap();
151153
}
154+
155+
// Regression test for https://github.com/scylladb/scylla-rust-driver/issues/1448
156+
// PR with fix: https://github.com/scylladb/scylla-rust-driver/pull/1449
157+
#[tokio::test]
158+
async fn test_iter_methods_when_altering_table() {
159+
let session = create_new_session_builder().build().await.unwrap();
160+
let ks = unique_keyspace_name();
161+
162+
session.ddl(format!("CREATE KEYSPACE IF NOT EXISTS {ks} WITH REPLICATION = {{'class' : 'NetworkTopologyStrategy', 'replication_factor' : 1}}")).await.unwrap();
163+
session
164+
.ddl(format!(
165+
"CREATE TABLE IF NOT EXISTS {ks}.t (a int, b int, d int, primary key (a, b))"
166+
))
167+
.await
168+
.unwrap();
169+
170+
let insert_stmt = session
171+
.prepare(format!("INSERT INTO {ks}.t (a, b, d) VALUES (?, ?, ?)"))
172+
.await
173+
.unwrap();
174+
// First let's insert some data
175+
for a in 0..10 {
176+
for b in 0..10 {
177+
session
178+
.execute_unpaged(&insert_stmt, (a, b, 1337))
179+
.await
180+
.unwrap();
181+
}
182+
}
183+
184+
let mut select_stmt = session
185+
.prepare(format!("SELECT * FROM {ks}.t",))
186+
.await
187+
.unwrap();
188+
select_stmt.set_page_size(10);
189+
select_stmt.set_use_cached_result_metadata(false);
190+
let pager = session.execute_iter(select_stmt, &[]).await.unwrap();
191+
let mut stream = pager.rows_stream::<(i32, i32, Option<i32>)>().unwrap();
192+
193+
// Let's fetch a few pages, but not all.
194+
for _ in 0..50 {
195+
let _row = stream.next().await.unwrap().unwrap();
196+
}
197+
198+
session
199+
.query_unpaged(format!("ALTER TABLE {ks}.t ADD c text"), &())
200+
.await
201+
.unwrap();
202+
203+
// With the bug (typecheck only being done for first page), the code panics!
204+
// At some point, requests will return pages with new schema.
205+
// It contains new column, and the new schema was not type checked.
206+
// DeserializeRow::deserialize impl will panic because invariants that should
207+
// be enforced by type check are violated.
208+
let err = loop {
209+
match stream.next().await {
210+
None => panic!("No error. Expected typecheck error."),
211+
Some(Ok(_row)) => continue,
212+
Some(Err(e)) => break e,
213+
}
214+
};
215+
216+
assert_matches!(
217+
err,
218+
NextRowError::NextPageError(NextPageError::TypeCheckError(_))
219+
);
220+
221+
session.ddl(format!("DROP KEYSPACE {ks}")).await.unwrap();
222+
}

0 commit comments

Comments
 (0)