Skip to content

Commit d8213e0

Browse files
committed
result: extract constructor logic to query_result.rs
The logic will become much more complex once we bump to 0.15. It introduces additional nesting, thus I prefer to extract it to separate functions (since cass_session_execute) is already complex enough. I also moved the necessary utility functions to query_result module.
1 parent 97adf66 commit d8213e0

File tree

2 files changed

+165
-147
lines changed

2 files changed

+165
-147
lines changed

scylla-rust-wrapper/src/query_result.rs

Lines changed: 159 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ use crate::inet::CassInet;
77
use crate::metadata::{
88
CassColumnMeta, CassKeyspaceMeta, CassMaterializedViewMeta, CassSchemaMeta, CassTableMeta,
99
};
10+
use crate::query_result::Value::{CollectionValue, RegularValue};
1011
use crate::types::*;
1112
use crate::uuid::CassUuid;
12-
use scylla::frame::response::result::{ColumnSpec, CqlValue};
13+
use scylla::frame::response::result::{ColumnSpec, CqlValue, Row};
1314
use scylla::transport::PagingStateResponse;
15+
use scylla::QueryResult;
1416
use std::convert::TryInto;
1517
use std::os::raw::c_char;
1618
use std::sync::Arc;
@@ -23,6 +25,34 @@ pub struct CassResult {
2325
pub paging_state_response: PagingStateResponse,
2426
}
2527

28+
impl CassResult {
29+
/// It creates CassResult object based on the:
30+
/// - query result
31+
/// - paging state response
32+
/// - optional cached result metadata - it's provided for prepared statements
33+
pub fn from_result_payload(
34+
result: QueryResult,
35+
paging_state_response: PagingStateResponse,
36+
maybe_result_metadata: Option<Arc<CassResultMetadata>>,
37+
) -> Self {
38+
// maybe_result_metadata is:
39+
// - Some(_) for prepared statements
40+
// - None for unprepared statements
41+
let metadata = maybe_result_metadata
42+
.unwrap_or_else(|| Arc::new(CassResultMetadata::from_column_specs(result.col_specs())));
43+
let cass_rows = result
44+
.rows
45+
.map(|rows| create_cass_rows_from_rows(rows, &metadata));
46+
47+
CassResult {
48+
rows: cass_rows,
49+
metadata,
50+
tracing_id: result.tracing_id,
51+
paging_state_response,
52+
}
53+
}
54+
}
55+
2656
#[derive(Debug)]
2757
pub struct CassResultMetadata {
2858
pub col_specs: Vec<CassColumnSpec>,
@@ -51,6 +81,18 @@ pub struct CassRow {
5181
pub result_metadata: Arc<CassResultMetadata>,
5282
}
5383

84+
pub fn create_cass_rows_from_rows(
85+
rows: Vec<Row>,
86+
metadata: &Arc<CassResultMetadata>,
87+
) -> Vec<CassRow> {
88+
rows.into_iter()
89+
.map(|r| CassRow {
90+
columns: create_cass_row_columns(r, metadata),
91+
result_metadata: metadata.clone(),
92+
})
93+
.collect()
94+
}
95+
5496
pub enum Value {
5597
RegularValue(CqlValue),
5698
CollectionValue(Collection),
@@ -73,6 +115,120 @@ pub struct CassValue {
73115
pub value_type: Arc<CassDataType>,
74116
}
75117

118+
fn create_cass_row_columns(row: Row, metadata: &Arc<CassResultMetadata>) -> Vec<CassValue> {
119+
row.columns
120+
.into_iter()
121+
.zip(metadata.col_specs.iter())
122+
.map(|(val, col_spec)| {
123+
let column_type = Arc::clone(&col_spec.data_type);
124+
CassValue {
125+
value: val.map(|col_val| get_column_value(col_val, &column_type)),
126+
value_type: column_type,
127+
}
128+
})
129+
.collect()
130+
}
131+
132+
fn get_column_value(column: CqlValue, column_type: &Arc<CassDataType>) -> Value {
133+
match (column, column_type.as_ref()) {
134+
(
135+
CqlValue::List(list),
136+
CassDataType::List {
137+
typ: Some(list_type),
138+
..
139+
},
140+
) => CollectionValue(Collection::List(
141+
list.into_iter()
142+
.map(|val| CassValue {
143+
value_type: list_type.clone(),
144+
value: Some(get_column_value(val, list_type)),
145+
})
146+
.collect(),
147+
)),
148+
(
149+
CqlValue::Map(map),
150+
CassDataType::Map {
151+
typ: MapDataType::KeyAndValue(key_type, value_type),
152+
..
153+
},
154+
) => CollectionValue(Collection::Map(
155+
map.into_iter()
156+
.map(|(key, val)| {
157+
(
158+
CassValue {
159+
value_type: key_type.clone(),
160+
value: Some(get_column_value(key, key_type)),
161+
},
162+
CassValue {
163+
value_type: value_type.clone(),
164+
value: Some(get_column_value(val, value_type)),
165+
},
166+
)
167+
})
168+
.collect(),
169+
)),
170+
(
171+
CqlValue::Set(set),
172+
CassDataType::Set {
173+
typ: Some(set_type),
174+
..
175+
},
176+
) => CollectionValue(Collection::Set(
177+
set.into_iter()
178+
.map(|val| CassValue {
179+
value_type: set_type.clone(),
180+
value: Some(get_column_value(val, set_type)),
181+
})
182+
.collect(),
183+
)),
184+
(
185+
CqlValue::UserDefinedType {
186+
keyspace,
187+
type_name,
188+
fields,
189+
},
190+
CassDataType::UDT(udt_type),
191+
) => CollectionValue(Collection::UserDefinedType {
192+
keyspace,
193+
type_name,
194+
fields: fields
195+
.into_iter()
196+
.enumerate()
197+
.map(|(index, (name, val_opt))| {
198+
let udt_field_type_opt = udt_type.get_field_by_index(index);
199+
if let (Some(val), Some(udt_field_type)) = (val_opt, udt_field_type_opt) {
200+
return (
201+
name,
202+
Some(CassValue {
203+
value_type: udt_field_type.clone(),
204+
value: Some(get_column_value(val, udt_field_type)),
205+
}),
206+
);
207+
}
208+
(name, None)
209+
})
210+
.collect(),
211+
}),
212+
(CqlValue::Tuple(tuple), CassDataType::Tuple(tuple_types)) => {
213+
CollectionValue(Collection::Tuple(
214+
tuple
215+
.into_iter()
216+
.enumerate()
217+
.map(|(index, val_opt)| {
218+
val_opt
219+
.zip(tuple_types.get(index))
220+
.map(|(val, tuple_field_type)| CassValue {
221+
value_type: tuple_field_type.clone(),
222+
value: Some(get_column_value(val, tuple_field_type)),
223+
})
224+
})
225+
.collect(),
226+
))
227+
}
228+
(regular_value, _) => RegularValue(regular_value),
229+
}
230+
}
231+
76232
pub struct CassResultIterator {
77233
result: Arc<CassResult>,
78234
position: Option<usize>,
@@ -1392,11 +1548,11 @@ mod tests {
13921548
cass_result_column_data_type, cass_result_column_name, cass_result_first_row,
13931549
ptr_to_cstr_n, ptr_to_ref, size_t,
13941550
},
1395-
session::create_cass_rows_from_rows,
13961551
};
13971552

13981553
use super::{
1399-
cass_result_column_count, cass_result_column_type, CassResult, CassResultMetadata,
1554+
cass_result_column_count, cass_result_column_type, create_cass_rows_from_rows, CassResult,
1555+
CassResultMetadata,
14001556
};
14011557

14021558
fn col_spec(name: &'static str, typ: ColumnType<'static>) -> ColumnSpec<'static> {

scylla-rust-wrapper/src/session.rs

Lines changed: 6 additions & 144 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
11
use crate::argconv::*;
22
use crate::batch::CassBatch;
33
use crate::cass_error::*;
4-
use crate::cass_types::{CassDataType, MapDataType, UDTDataType};
4+
use crate::cass_types::{CassDataType, UDTDataType};
55
use crate::cluster::build_session_builder;
66
use crate::cluster::CassCluster;
77
use crate::exec_profile::{CassExecProfile, ExecProfileName, PerStatementExecProfile};
88
use crate::future::{CassFuture, CassFutureResult, CassResultValue};
99
use crate::metadata::create_table_metadata;
1010
use crate::metadata::{CassKeyspaceMeta, CassMaterializedViewMeta, CassSchemaMeta};
1111
use crate::prepared::CassPrepared;
12-
use crate::query_result::Value::{CollectionValue, RegularValue};
13-
use crate::query_result::{CassResult, CassResultMetadata, CassRow, CassValue, Collection, Value};
12+
use crate::query_result::{CassResult, CassResultMetadata};
1413
use crate::statement::CassStatement;
1514
use crate::statement::Statement;
1615
use crate::types::{cass_uint64_t, size_t};
1716
use crate::uuid::CassUuid;
18-
use scylla::frame::response::result::{CqlValue, Row};
1917
use scylla::frame::types::Consistency;
2018
use scylla::query::Query;
2119
use scylla::transport::errors::QueryError;
@@ -354,21 +352,11 @@ pub unsafe extern "C" fn cass_session_execute(
354352

355353
match query_res {
356354
Ok((result, paging_state_response, maybe_result_metadata)) => {
357-
// maybe_result_metadata is:
358-
// - Some(_) for prepared statements
359-
// - None for unprepared statements
360-
let metadata = maybe_result_metadata.unwrap_or_else(|| {
361-
Arc::new(CassResultMetadata::from_column_specs(result.col_specs()))
362-
});
363-
let cass_rows = result
364-
.rows
365-
.map(|rows| create_cass_rows_from_rows(rows, &metadata));
366-
let cass_result = Arc::new(CassResult {
367-
rows: cass_rows,
368-
metadata,
369-
tracing_id: result.tracing_id,
355+
let cass_result = Arc::new(CassResult::from_result_payload(
356+
result,
370357
paging_state_response,
371-
});
358+
maybe_result_metadata,
359+
));
372360

373361
Ok(CassResultValue::QueryResult(cass_result))
374362
}
@@ -384,132 +372,6 @@ pub unsafe extern "C" fn cass_session_execute(
384372
}
385373
}
386374

387-
pub(crate) fn create_cass_rows_from_rows(
388-
rows: Vec<Row>,
389-
metadata: &Arc<CassResultMetadata>,
390-
) -> Vec<CassRow> {
391-
rows.into_iter()
392-
.map(|r| CassRow {
393-
columns: create_cass_row_columns(r, metadata),
394-
result_metadata: metadata.clone(),
395-
})
396-
.collect()
397-
}
398-
399-
fn create_cass_row_columns(row: Row, metadata: &Arc<CassResultMetadata>) -> Vec<CassValue> {
400-
row.columns
401-
.into_iter()
402-
.zip(metadata.col_specs.iter())
403-
.map(|(val, col_spec)| {
404-
let column_type = Arc::clone(&col_spec.data_type);
405-
CassValue {
406-
value: val.map(|col_val| get_column_value(col_val, &column_type)),
407-
value_type: column_type,
408-
}
409-
})
410-
.collect()
411-
}
412-
413-
fn get_column_value(column: CqlValue, column_type: &Arc<CassDataType>) -> Value {
414-
match (column, column_type.as_ref()) {
415-
(
416-
CqlValue::List(list),
417-
CassDataType::List {
418-
typ: Some(list_type),
419-
..
420-
},
421-
) => CollectionValue(Collection::List(
422-
list.into_iter()
423-
.map(|val| CassValue {
424-
value_type: list_type.clone(),
425-
value: Some(get_column_value(val, list_type)),
426-
})
427-
.collect(),
428-
)),
429-
(
430-
CqlValue::Map(map),
431-
CassDataType::Map {
432-
typ: MapDataType::KeyAndValue(key_type, value_type),
433-
..
434-
},
435-
) => CollectionValue(Collection::Map(
436-
map.into_iter()
437-
.map(|(key, val)| {
438-
(
439-
CassValue {
440-
value_type: key_type.clone(),
441-
value: Some(get_column_value(key, key_type)),
442-
},
443-
CassValue {
444-
value_type: value_type.clone(),
445-
value: Some(get_column_value(val, value_type)),
446-
},
447-
)
448-
})
449-
.collect(),
450-
)),
451-
(
452-
CqlValue::Set(set),
453-
CassDataType::Set {
454-
typ: Some(set_type),
455-
..
456-
},
457-
) => CollectionValue(Collection::Set(
458-
set.into_iter()
459-
.map(|val| CassValue {
460-
value_type: set_type.clone(),
461-
value: Some(get_column_value(val, set_type)),
462-
})
463-
.collect(),
464-
)),
465-
(
466-
CqlValue::UserDefinedType {
467-
keyspace,
468-
type_name,
469-
fields,
470-
},
471-
CassDataType::UDT(udt_type),
472-
) => CollectionValue(Collection::UserDefinedType {
473-
keyspace,
474-
type_name,
475-
fields: fields
476-
.into_iter()
477-
.enumerate()
478-
.map(|(index, (name, val_opt))| {
479-
let udt_field_type_opt = udt_type.get_field_by_index(index);
480-
if let (Some(val), Some(udt_field_type)) = (val_opt, udt_field_type_opt) {
481-
return (
482-
name,
483-
Some(CassValue {
484-
value_type: udt_field_type.clone(),
485-
value: Some(get_column_value(val, udt_field_type)),
486-
}),
487-
);
488-
}
489-
(name, None)
490-
})
491-
.collect(),
492-
}),
493-
(CqlValue::Tuple(tuple), CassDataType::Tuple(tuple_types)) => {
494-
CollectionValue(Collection::Tuple(
495-
tuple
496-
.into_iter()
497-
.enumerate()
498-
.map(|(index, val_opt)| {
499-
val_opt
500-
.zip(tuple_types.get(index))
501-
.map(|(val, tuple_field_type)| CassValue {
502-
value_type: tuple_field_type.clone(),
503-
value: Some(get_column_value(val, tuple_field_type)),
504-
})
505-
})
506-
.collect(),
507-
))
508-
}
509-
(regular_value, _) => RegularValue(regular_value),
510-
}
511-
}
512-
513375
#[no_mangle]
514376
pub unsafe extern "C" fn cass_session_prepare_from_existing(
515377
cass_session: *mut CassSession,

0 commit comments

Comments
 (0)