Skip to content

Commit e8f92ef

Browse files
committed
prepared: reuse prepared statement's result metadata
1 parent 52b2b14 commit e8f92ef

File tree

4 files changed

+27
-24
lines changed

4 files changed

+27
-24
lines changed

scylla-rust-wrapper/src/cass_types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ pub enum MapDataType {
138138
KeyAndValue(Arc<CassDataType>, Arc<CassDataType>),
139139
}
140140

141+
#[derive(Debug)]
141142
pub struct CassColumnSpec {
142143
pub name: String,
143144
pub data_type: Arc<CassDataType>,

scylla-rust-wrapper/src/prepared.rs

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
argconv::*,
66
cass_error::CassError,
77
cass_types::{get_column_type, CassDataType},
8+
query_result::CassResultData,
89
statement::{CassStatement, Statement},
910
types::size_t,
1011
};
@@ -14,11 +15,10 @@ use scylla::prepared_statement::PreparedStatement;
1415
pub struct CassPrepared {
1516
// Data types of columns from PreparedMetadata.
1617
pub variable_col_data_types: Vec<Arc<CassDataType>>,
17-
// Data types of columns from ResultMetadata.
18-
//
19-
// Arc<CassDataType> -> to share each data type with other structs such as `CassValue`
20-
// Arc<Vec<...>> -> to share the whole vector with `CassResultData`.
21-
pub result_col_data_types: Arc<Vec<Arc<CassDataType>>>,
18+
19+
// Cached result metadata. Arc'ed since we want to share it
20+
// with result metadata after execution.
21+
pub result_metadata: Arc<CassResultData>,
2222
pub statement: PreparedStatement,
2323
}
2424

@@ -30,17 +30,13 @@ impl CassPrepared {
3030
.map(|col_spec| Arc::new(get_column_type(col_spec.typ())))
3131
.collect();
3232

33-
let result_col_data_types: Arc<Vec<Arc<CassDataType>>> = Arc::new(
34-
statement
35-
.get_result_set_col_specs()
36-
.iter()
37-
.map(|col_spec| Arc::new(get_column_type(col_spec.typ())))
38-
.collect(),
39-
);
33+
let result_metadata = Arc::new(CassResultData::from_column_specs(
34+
statement.get_result_set_col_specs(),
35+
));
4036

4137
Self {
4238
variable_col_data_types,
43-
result_col_data_types,
39+
result_metadata,
4440
statement,
4541
}
4642
}

scylla-rust-wrapper/src/query_result.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ pub struct CassResult {
2323
pub paging_state_response: PagingStateResponse,
2424
}
2525

26+
#[derive(Debug)]
2627
pub struct CassResultData {
2728
pub col_specs: Vec<CassColumnSpec>,
2829
}

scylla-rust-wrapper/src/session.rs

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -300,20 +300,20 @@ pub unsafe extern "C" fn cass_session_execute(
300300
// Since `query.query` is consumed, we cannot match the statement
301301
// after execution, to retrieve the cached metadata in case
302302
// of prepared statements.
303-
Option<Arc<Vec<Arc<CassDataType>>>>,
303+
Option<Arc<CassResultData>>,
304304
),
305305
QueryError,
306306
>;
307307
let query_res: QueryRes = match statement {
308308
Statement::Simple(query) => {
309309
// We don't store result metadata for Queries - return None.
310-
let maybe_result_col_data_types = None;
310+
let maybe_result_metadata = None;
311311

312312
if paging_enabled {
313313
session
314314
.query_single_page(query.query, bound_values, paging_state)
315315
.await
316-
.map(|(qr, psr)| (qr, psr, maybe_result_col_data_types))
316+
.map(|(qr, psr)| (qr, psr, maybe_result_metadata))
317317
} else {
318318
session
319319
.query_unpaged(query.query, bound_values)
@@ -322,21 +322,21 @@ pub unsafe extern "C" fn cass_session_execute(
322322
(
323323
result,
324324
PagingStateResponse::NoMorePages,
325-
maybe_result_col_data_types,
325+
maybe_result_metadata,
326326
)
327327
})
328328
}
329329
}
330330
Statement::Prepared(prepared) => {
331-
// Clone vector of the Arc<CassDataType>, so we don't do additional allocations when constructing
332-
// CassDataTypes in `CassResultData::from_result_payload`.
333-
let maybe_result_col_data_types = Some(prepared.result_col_data_types.clone());
331+
// Clone result metadata, so we don't need to construct it from scratch in
332+
// `CassResultData::from_column_specs` - it requires a lot of allocations for complex types.
333+
let maybe_result_metadata = Some(Arc::clone(&prepared.result_metadata));
334334

335335
if paging_enabled {
336336
session
337337
.execute_single_page(&prepared.statement, bound_values, paging_state)
338338
.await
339-
.map(|(qr, psr)| (qr, psr, maybe_result_col_data_types))
339+
.map(|(qr, psr)| (qr, psr, maybe_result_metadata))
340340
} else {
341341
session
342342
.execute_unpaged(&prepared.statement, bound_values)
@@ -345,16 +345,21 @@ pub unsafe extern "C" fn cass_session_execute(
345345
(
346346
result,
347347
PagingStateResponse::NoMorePages,
348-
maybe_result_col_data_types,
348+
maybe_result_metadata,
349349
)
350350
})
351351
}
352352
}
353353
};
354354

355355
match query_res {
356-
Ok((result, paging_state_response, _maybe_col_data_types)) => {
357-
let metadata = Arc::new(CassResultData::from_column_specs(result.col_specs()));
356+
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(CassResultData::from_column_specs(result.col_specs()))
362+
});
358363
let cass_rows = result
359364
.rows
360365
.map(|rows| create_cass_rows_from_rows(rows, &metadata));

0 commit comments

Comments
 (0)