|
1 | 1 | use crate::argconv::*; |
2 | 2 | use crate::batch::CassBatch; |
3 | 3 | use crate::cass_error::*; |
4 | | -use crate::cass_types::{get_column_type, CassDataType, MapDataType, UDTDataType}; |
| 4 | +use crate::cass_types::{CassDataType, MapDataType, UDTDataType}; |
5 | 5 | use crate::cluster::build_session_builder; |
6 | 6 | use crate::cluster::CassCluster; |
7 | 7 | use crate::exec_profile::{CassExecProfile, ExecProfileName, PerStatementExecProfile}; |
@@ -214,11 +214,12 @@ pub unsafe extern "C" fn cass_session_execute_batch( |
214 | 214 | match query_res { |
215 | 215 | Ok(_result) => Ok(CassResultValue::QueryResult(Arc::new(CassResult { |
216 | 216 | rows: None, |
217 | | - metadata: Arc::new(CassResultData { |
218 | | - paging_state_response: PagingStateResponse::NoMorePages, |
219 | | - col_specs: vec![], |
220 | | - tracing_id: None, |
221 | | - }), |
| 217 | + metadata: Arc::new(CassResultData::from_result_payload( |
| 218 | + PagingStateResponse::NoMorePages, |
| 219 | + vec![], |
| 220 | + None, |
| 221 | + None, |
| 222 | + )), |
222 | 223 | }))), |
223 | 224 | Err(err) => Ok(CassResultValue::QueryError(Arc::new(err))), |
224 | 225 | } |
@@ -285,40 +286,77 @@ pub unsafe extern "C" fn cass_session_execute( |
285 | 286 | .set_execution_profile_handle(handle), |
286 | 287 | } |
287 | 288 |
|
288 | | - let query_res: Result<(QueryResult, PagingStateResponse), QueryError> = match statement { |
| 289 | + // Creating a type alias here to fix clippy lints. |
| 290 | + // I want this type to be explicit, so future developers can understand |
| 291 | + // what's going on here (and why we include some weird Option of data types). |
| 292 | + type QueryRes = Result< |
| 293 | + ( |
| 294 | + QueryResult, |
| 295 | + PagingStateResponse, |
| 296 | + // We unfortunately have to retrieve the metadata here. |
| 297 | + // Since `query.qery` is consumed, we cannot match the statement |
| 298 | + // after execution, to retrieve the cached metadata in case |
| 299 | + // of prepared statements. |
| 300 | + Option<Arc<Vec<Arc<CassDataType>>>>, |
| 301 | + ), |
| 302 | + QueryError, |
| 303 | + >; |
| 304 | + let query_res: QueryRes = match statement { |
289 | 305 | Statement::Simple(query) => { |
| 306 | + // We don't store result metadta for Queries - return None. |
| 307 | + let maybe_result_col_data_types = None; |
| 308 | + |
290 | 309 | if paging_enabled { |
291 | 310 | session |
292 | 311 | .query_single_page(query.query, bound_values, paging_state) |
293 | 312 | .await |
| 313 | + .map(|(qr, psr)| (qr, psr, maybe_result_col_data_types)) |
294 | 314 | } else { |
295 | 315 | session |
296 | 316 | .query_unpaged(query.query, bound_values) |
297 | 317 | .await |
298 | | - .map(|result| (result, PagingStateResponse::NoMorePages)) |
| 318 | + .map(|result| { |
| 319 | + ( |
| 320 | + result, |
| 321 | + PagingStateResponse::NoMorePages, |
| 322 | + maybe_result_col_data_types, |
| 323 | + ) |
| 324 | + }) |
299 | 325 | } |
300 | 326 | } |
301 | 327 | Statement::Prepared(prepared) => { |
| 328 | + // Clone vector of the Arc<CassDataType>, so we don't do additional allocations when constructing |
| 329 | + // CassDataTypes in `CassResultData::from_result_payload`. |
| 330 | + let maybe_result_col_data_types = Some(prepared.result_col_data_types.clone()); |
| 331 | + |
302 | 332 | if paging_enabled { |
303 | 333 | session |
304 | 334 | .execute_single_page(&prepared.statement, bound_values, paging_state) |
305 | 335 | .await |
| 336 | + .map(|(qr, psr)| (qr, psr, maybe_result_col_data_types)) |
306 | 337 | } else { |
307 | 338 | session |
308 | 339 | .execute_unpaged(&prepared.statement, bound_values) |
309 | 340 | .await |
310 | | - .map(|result| (result, PagingStateResponse::NoMorePages)) |
| 341 | + .map(|result| { |
| 342 | + ( |
| 343 | + result, |
| 344 | + PagingStateResponse::NoMorePages, |
| 345 | + maybe_result_col_data_types, |
| 346 | + ) |
| 347 | + }) |
311 | 348 | } |
312 | 349 | } |
313 | 350 | }; |
314 | 351 |
|
315 | 352 | match query_res { |
316 | | - Ok((result, paging_state_response)) => { |
317 | | - let metadata = Arc::new(CassResultData { |
| 353 | + Ok((result, paging_state_response, maybe_col_data_types)) => { |
| 354 | + let metadata = Arc::new(CassResultData::from_result_payload( |
318 | 355 | paging_state_response, |
319 | | - col_specs: result.col_specs().to_vec(), |
320 | | - tracing_id: result.tracing_id, |
321 | | - }); |
| 356 | + result.col_specs().to_vec(), |
| 357 | + maybe_col_data_types, |
| 358 | + result.tracing_id, |
| 359 | + )); |
322 | 360 | let cass_rows = create_cass_rows_from_rows(result.rows, &metadata); |
323 | 361 | let cass_result = Arc::new(CassResult { |
324 | 362 | rows: cass_rows, |
@@ -358,9 +396,9 @@ fn create_cass_rows_from_rows( |
358 | 396 | fn create_cass_row_columns(row: Row, metadata: &Arc<CassResultData>) -> Vec<CassValue> { |
359 | 397 | row.columns |
360 | 398 | .into_iter() |
361 | | - .zip(metadata.col_specs.iter()) |
362 | | - .map(|(val, col)| { |
363 | | - let column_type = Arc::new(get_column_type(&col.typ)); |
| 399 | + .zip(metadata.col_data_types.iter()) |
| 400 | + .map(|(val, col_data_type)| { |
| 401 | + let column_type = Arc::clone(col_data_type); |
364 | 402 | CassValue { |
365 | 403 | value: val.map(|col_val| get_column_value(col_val, &column_type)), |
366 | 404 | value_type: column_type, |
|
0 commit comments