Skip to content

Commit e99d697

Browse files
authored
Merge pull request #1057 from wprzytula/new-deserialization-api
Introduce new deserialization API
2 parents dce9e9f + d4a222c commit e99d697

39 files changed

+1677
-1027
lines changed

examples/allocations.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use anyhow::Result;
2-
use scylla::{statement::prepared_statement::PreparedStatement, Session, SessionBuilder};
2+
use scylla::transport::session::Session;
3+
use scylla::{statement::prepared_statement::PreparedStatement, SessionBuilder};
34
use std::io::Write;
45
use std::sync::atomic::{AtomicUsize, Ordering};
56
use std::sync::Arc;

examples/basic.rs

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
use anyhow::Result;
2-
use futures::TryStreamExt;
3-
use scylla::macros::FromRow;
2+
use futures::StreamExt as _;
3+
use futures::TryStreamExt as _;
4+
use scylla::frame::response::result::Row;
45
use scylla::transport::session::Session;
6+
use scylla::DeserializeRow;
57
use scylla::SessionBuilder;
68
use std::env;
79

@@ -53,39 +55,38 @@ async fn main() -> Result<()> {
5355
let mut iter = session
5456
.query_iter("SELECT a, b, c FROM examples_ks.basic", &[])
5557
.await?
56-
.into_typed::<(i32, i32, String)>();
58+
.rows_stream::<(i32, i32, String)>()?;
5759
while let Some((a, b, c)) = iter.try_next().await? {
5860
println!("a, b, c: {}, {}, {}", a, b, c);
5961
}
6062

61-
// Or as custom structs that derive FromRow
62-
#[derive(Debug, FromRow)]
63+
// Or as custom structs that derive DeserializeRow
64+
#[allow(unused)]
65+
#[derive(Debug, DeserializeRow)]
6366
struct RowData {
64-
_a: i32,
65-
_b: Option<i32>,
66-
_c: String,
67+
a: i32,
68+
b: Option<i32>,
69+
c: String,
6770
}
6871

6972
let mut iter = session
7073
.query_iter("SELECT a, b, c FROM examples_ks.basic", &[])
7174
.await?
72-
.into_typed::<RowData>();
75+
.rows_stream::<RowData>()?;
7376
while let Some(row_data) = iter.try_next().await? {
7477
println!("row_data: {:?}", row_data);
7578
}
7679

7780
// Or simply as untyped rows
7881
let mut iter = session
7982
.query_iter("SELECT a, b, c FROM examples_ks.basic", &[])
80-
.await?;
81-
while let Some(row) = iter.try_next().await? {
83+
.await?
84+
.rows_stream::<Row>()?;
85+
while let Some(row) = iter.next().await.transpose()? {
8286
let a = row.columns[0].as_ref().unwrap().as_int().unwrap();
8387
let b = row.columns[1].as_ref().unwrap().as_int().unwrap();
8488
let c = row.columns[2].as_ref().unwrap().as_text().unwrap();
8589
println!("a, b, c: {}, {}, {}", a, b, c);
86-
87-
// Alternatively each row can be parsed individually
88-
// let (a2, b2, c2) = row.into_typed::<(i32, i32, String)>() ?;
8990
}
9091

9192
let metrics = session.get_metrics();

examples/compare-tokens.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ async fn main() -> Result<()> {
5151
(pk,),
5252
)
5353
.await?
54-
.single_row_typed::<(i64,)>()?;
54+
.into_rows_result()?
55+
.expect("Got not Rows result")
56+
.single_row()?;
5557
assert_eq!(t, qt);
5658
println!("token for {}: {}", pk, t);
5759
}

examples/cql-time-types.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
use anyhow::Result;
55
use chrono::{DateTime, NaiveDate, NaiveTime, Utc};
6-
use futures::{StreamExt, TryStreamExt};
6+
use futures::{StreamExt as _, TryStreamExt as _};
77
use scylla::frame::response::result::CqlValue;
88
use scylla::frame::value::{CqlDate, CqlTime, CqlTimestamp};
99
use scylla::transport::session::Session;
@@ -44,7 +44,7 @@ async fn main() -> Result<()> {
4444
let mut iter = session
4545
.query_iter("SELECT d from examples_ks.dates", &[])
4646
.await?
47-
.into_typed::<(NaiveDate,)>();
47+
.rows_stream::<(NaiveDate,)>()?;
4848
while let Some(row_result) = iter.next().await {
4949
let (read_date,): (NaiveDate,) = match row_result {
5050
Ok(read_date) => read_date,
@@ -66,7 +66,7 @@ async fn main() -> Result<()> {
6666
let mut iter = session
6767
.query_iter("SELECT d from examples_ks.dates", &[])
6868
.await?
69-
.into_typed::<(time::Date,)>();
69+
.rows_stream::<(time::Date,)>()?;
7070
while let Some(row_result) = iter.next().await {
7171
let (read_date,): (time::Date,) = match row_result {
7272
Ok(read_date) => read_date,
@@ -88,7 +88,7 @@ async fn main() -> Result<()> {
8888
let mut iter = session
8989
.query_iter("SELECT d from examples_ks.dates", &[])
9090
.await?
91-
.into_typed::<(CqlValue,)>();
91+
.rows_stream::<(CqlValue,)>()?;
9292
while let Some(row_result) = iter.next().await {
9393
let read_days: u32 = match row_result {
9494
Ok((CqlValue::Date(CqlDate(days)),)) => days,
@@ -124,7 +124,7 @@ async fn main() -> Result<()> {
124124
let mut iter = session
125125
.query_iter("SELECT d from examples_ks.times", &[])
126126
.await?
127-
.into_typed::<(NaiveTime,)>();
127+
.rows_stream::<(NaiveTime,)>()?;
128128
while let Some((read_time,)) = iter.try_next().await? {
129129
println!("Parsed a time into chrono::NaiveTime: {:?}", read_time);
130130
}
@@ -139,7 +139,7 @@ async fn main() -> Result<()> {
139139
let mut iter = session
140140
.query_iter("SELECT d from examples_ks.times", &[])
141141
.await?
142-
.into_typed::<(time::Time,)>();
142+
.rows_stream::<(time::Time,)>()?;
143143
while let Some((read_time,)) = iter.try_next().await? {
144144
println!("Parsed a time into time::Time: {:?}", read_time);
145145
}
@@ -154,7 +154,7 @@ async fn main() -> Result<()> {
154154
let mut iter = session
155155
.query_iter("SELECT d from examples_ks.times", &[])
156156
.await?
157-
.into_typed::<(CqlTime,)>();
157+
.rows_stream::<(CqlTime,)>()?;
158158
while let Some((read_time,)) = iter.try_next().await? {
159159
println!("Read a time as raw nanos: {:?}", read_time);
160160
}
@@ -185,7 +185,7 @@ async fn main() -> Result<()> {
185185
let mut iter = session
186186
.query_iter("SELECT d from examples_ks.timestamps", &[])
187187
.await?
188-
.into_typed::<(DateTime<Utc>,)>();
188+
.rows_stream::<(DateTime<Utc>,)>()?;
189189
while let Some((read_time,)) = iter.try_next().await? {
190190
println!(
191191
"Parsed a timestamp into chrono::DateTime<chrono::Utc>: {:?}",
@@ -206,7 +206,7 @@ async fn main() -> Result<()> {
206206
let mut iter = session
207207
.query_iter("SELECT d from examples_ks.timestamps", &[])
208208
.await?
209-
.into_typed::<(time::OffsetDateTime,)>();
209+
.rows_stream::<(time::OffsetDateTime,)>()?;
210210
while let Some((read_time,)) = iter.try_next().await? {
211211
println!(
212212
"Parsed a timestamp into time::OffsetDateTime: {:?}",
@@ -227,7 +227,7 @@ async fn main() -> Result<()> {
227227
let mut iter = session
228228
.query_iter("SELECT d from examples_ks.timestamps", &[])
229229
.await?
230-
.into_typed::<(CqlTimestamp,)>();
230+
.rows_stream::<(CqlTimestamp,)>()?;
231231
while let Some((read_time,)) = iter.try_next().await? {
232232
println!("Read a timestamp as raw millis: {:?}", read_time);
233233
}

examples/cqlsh-rs.rs

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@ use rustyline::completion::{Completer, Pair};
33
use rustyline::error::ReadlineError;
44
use rustyline::{CompletionType, Config, Context, Editor};
55
use rustyline_derive::{Helper, Highlighter, Hinter, Validator};
6+
use scylla::frame::response::result::Row;
7+
use scylla::transport::session::Session;
68
use scylla::transport::Compression;
7-
use scylla::{LegacyQueryResult, Session, SessionBuilder};
9+
use scylla::QueryRowsResult;
10+
use scylla::SessionBuilder;
811
use std::env;
912

1013
#[derive(Helper, Highlighter, Validator, Hinter)]
@@ -173,23 +176,24 @@ impl Completer for CqlHelper {
173176
}
174177
}
175178

176-
fn print_result(result: &LegacyQueryResult) {
177-
if result.rows.is_none() {
178-
println!("OK");
179-
return;
180-
}
181-
for row in result.rows.as_ref().unwrap() {
182-
for column in &row.columns {
183-
print!("|");
184-
print!(
185-
" {:16}",
186-
match column {
187-
None => "null".to_owned(),
188-
Some(value) => format!("{:?}", value),
189-
}
190-
);
179+
fn print_result(result: Option<&QueryRowsResult>) {
180+
if let Some(rows_result) = result {
181+
for row in rows_result.rows::<Row>().unwrap() {
182+
let row = row.unwrap();
183+
for column in &row.columns {
184+
print!("|");
185+
print!(
186+
" {:16}",
187+
match column {
188+
None => "null".to_owned(),
189+
Some(value) => format!("{:?}", value),
190+
}
191+
);
192+
}
193+
println!("|")
191194
}
192-
println!("|")
195+
} else {
196+
println!("OK");
193197
}
194198
}
195199

@@ -222,7 +226,10 @@ async fn main() -> Result<()> {
222226
let maybe_res = session.query_unpaged(line, &[]).await;
223227
match maybe_res {
224228
Err(err) => println!("Error: {}", err),
225-
Ok(res) => print_result(&res),
229+
Ok(res) => {
230+
let rows_res = res.into_rows_result()?;
231+
print_result(rows_res.as_ref())
232+
}
226233
}
227234
}
228235
Err(ReadlineError::Interrupted) => continue,

examples/custom_deserialization.rs

Lines changed: 24 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
use anyhow::Result;
2-
use scylla::cql_to_rust::{FromCqlVal, FromCqlValError};
3-
use scylla::frame::response::result::CqlValue;
4-
use scylla::macros::impl_from_cql_value_from_method;
5-
use scylla::{Session, SessionBuilder};
1+
use anyhow::{Context, Result};
2+
use scylla::deserialize::DeserializeValue;
3+
use scylla::frame::response::result::ColumnType;
4+
use scylla::transport::session::Session;
5+
use scylla::SessionBuilder;
66
use std::env;
77

88
#[tokio::main]
@@ -28,53 +28,38 @@ async fn main() -> Result<()> {
2828
)
2929
.await?;
3030

31-
// You can implement FromCqlVal for your own types
31+
// You can implement DeserializeValue for your own types
3232
#[derive(PartialEq, Eq, Debug)]
33-
struct MyType(String);
33+
struct MyType<'a>(&'a str);
3434

35-
impl FromCqlVal<CqlValue> for MyType {
36-
fn from_cql(cql_val: CqlValue) -> Result<Self, FromCqlValError> {
37-
Ok(Self(
38-
cql_val.into_string().ok_or(FromCqlValError::BadCqlType)?,
39-
))
35+
impl<'frame, 'metadata> DeserializeValue<'frame, 'metadata> for MyType<'frame> {
36+
fn type_check(
37+
typ: &scylla::frame::response::result::ColumnType,
38+
) -> std::result::Result<(), scylla::deserialize::TypeCheckError> {
39+
<&str as DeserializeValue<'frame, 'metadata>>::type_check(typ)
4040
}
41-
}
42-
43-
let (v,) = session
44-
.query_unpaged(
45-
"SELECT v FROM examples_ks.custom_deserialization WHERE pk = 1",
46-
(),
47-
)
48-
.await?
49-
.single_row_typed::<(MyType,)>()?;
50-
assert_eq!(v, MyType("asdf".to_owned()));
51-
52-
// If you defined an extension trait for CqlValue then you can use
53-
// the `impl_from_cql_value_from_method` macro to turn it into
54-
// a FromCqlValue impl
55-
#[derive(PartialEq, Eq, Debug)]
56-
struct MyOtherType(String);
5741

58-
trait CqlValueExt {
59-
fn into_my_other_type(self) -> Option<MyOtherType>;
60-
}
42+
fn deserialize(
43+
typ: &'metadata ColumnType<'metadata>,
44+
v: Option<scylla::deserialize::FrameSlice<'frame>>,
45+
) -> std::result::Result<Self, scylla::deserialize::DeserializationError> {
46+
let s = <&str as DeserializeValue<'frame, 'metadata>>::deserialize(typ, v)?;
6147

62-
impl CqlValueExt for CqlValue {
63-
fn into_my_other_type(self) -> Option<MyOtherType> {
64-
Some(MyOtherType(self.into_string()?))
48+
Ok(Self(s))
6549
}
6650
}
6751

68-
impl_from_cql_value_from_method!(MyOtherType, into_my_other_type);
69-
70-
let (v,) = session
52+
let rows_result = session
7153
.query_unpaged(
7254
"SELECT v FROM examples_ks.custom_deserialization WHERE pk = 1",
7355
(),
7456
)
7557
.await?
76-
.single_row_typed::<(MyOtherType,)>()?;
77-
assert_eq!(v, MyOtherType("asdf".to_owned()));
58+
.into_rows_result()?
59+
.context("Expected Result:Rows response, got a different Result response.")?;
60+
61+
let (v,) = rows_result.single_row::<(MyType,)>()?;
62+
assert_eq!(v, MyType("asdf"));
7863

7964
println!("Ok.");
8065

examples/get_by_name.rs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use anyhow::{anyhow, Result};
1+
use anyhow::{anyhow, Context as _, Result};
2+
use scylla::frame::response::result::Row;
23
use scylla::transport::session::Session;
34
use scylla::SessionBuilder;
45
use std::env;
@@ -35,18 +36,26 @@ async fn main() -> Result<()> {
3536
)
3637
.await?;
3738

38-
let query_result = session
39+
let rows_result = session
3940
.query_unpaged("SELECT pk, ck, value FROM examples_ks.get_by_name", &[])
40-
.await?;
41-
let (ck_idx, _) = query_result
42-
.get_column_spec("ck")
41+
.await?
42+
.into_rows_result()?
43+
.context("Response is not of Rows type")?;
44+
let col_specs = rows_result.column_specs();
45+
let (ck_idx, _) = col_specs
46+
.get_by_name("ck")
4347
.ok_or_else(|| anyhow!("No ck column found"))?;
44-
let (value_idx, _) = query_result
45-
.get_column_spec("value")
48+
let (value_idx, _) = col_specs
49+
.get_by_name("value")
4650
.ok_or_else(|| anyhow!("No value column found"))?;
51+
let rows = rows_result
52+
.rows::<Row>()
53+
.unwrap()
54+
.collect::<Result<Vec<_>, _>>()
55+
.unwrap();
4756
println!("ck | value");
4857
println!("---------------------");
49-
for row in query_result.rows.ok_or_else(|| anyhow!("no rows found"))? {
58+
for row in rows {
5059
println!("{:?} | {:?}", row.columns[ck_idx], row.columns[value_idx]);
5160
}
5261

examples/logging_log.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use anyhow::Result;
2-
use scylla::transport::session::Session;
3-
use scylla::SessionBuilder;
2+
use scylla::{Session, SessionBuilder};
43
use std::env;
54
use tracing::info;
65

examples/query_history.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! This example shows how to collect history of query execution.
22
33
use anyhow::Result;
4-
use futures::StreamExt;
4+
use futures::StreamExt as _;
5+
use scylla::frame::response::result::Row;
56
use scylla::history::{HistoryCollector, StructuredHistory};
67
use scylla::query::Query;
78
use scylla::transport::session::Session;
@@ -59,7 +60,10 @@ async fn main() -> Result<()> {
5960
let iter_history_listener = Arc::new(HistoryCollector::new());
6061
iter_query.set_history_listener(iter_history_listener.clone());
6162

62-
let mut rows_iterator = session.query_iter(iter_query, ()).await?;
63+
let mut rows_iterator = session
64+
.query_iter(iter_query, ())
65+
.await?
66+
.rows_stream::<Row>()?;
6367
while let Some(_row) = rows_iterator.next().await {
6468
// Receive rows...
6569
}

0 commit comments

Comments
 (0)