Skip to content

Commit 3a811ac

Browse files
committed
refactor results transformations
1 parent 08019ce commit 3a811ac

File tree

4 files changed

+164
-192
lines changed

4 files changed

+164
-192
lines changed

packages/cubejs-backend-native/src/node_export.rs

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@ use cubeorchestrator::cubestore_message_parser::CubeStoreResult;
3636
use cubesql::{telemetry::ReportingLogger, CubeError};
3737

3838
use cubeorchestrator::cubestore_result_transform::{
39-
get_final_cubestore_result, get_final_cubestore_result_array, get_final_cubestore_result_multi,
40-
transform_data,
41-
};
42-
use cubeorchestrator::types::{
43-
RequestResultArray, RequestResultData, RequestResultDataMulti, TransformDataRequest,
39+
get_final_cubestore_result_array, RequestResultArray, RequestResultData,
40+
RequestResultDataMulti, TransformedData,
4441
};
42+
use cubeorchestrator::transport::TransformDataRequest;
4543
use neon::prelude::*;
4644
use neon::types::buffer::TypedArray;
4745

@@ -567,20 +565,7 @@ fn transform_query_data(mut cx: FunctionContext) -> JsResult<JsPromise> {
567565
Err(err) => return Err(anyhow::Error::from(err)),
568566
};
569567

570-
let alias_to_member_name_map = &request_data.alias_to_member_name_map;
571-
let annotation = &request_data.annotation;
572-
let query = &request_data.query;
573-
let query_type = &request_data.query_type.unwrap_or_default();
574-
let res_type = &request_data.res_type;
575-
576-
let transformed = transform_data(
577-
alias_to_member_name_map,
578-
annotation,
579-
&cube_store_result,
580-
query,
581-
query_type,
582-
res_type.clone(),
583-
)?;
568+
let transformed = TransformedData::transform(&request_data, &cube_store_result)?;
584569

585570
match serde_json::to_string(&transformed) {
586571
Ok(json) => Ok(json),
@@ -622,11 +607,7 @@ fn final_cubestore_result(mut cx: FunctionContext) -> JsResult<JsPromise> {
622607
Err(err) => return Err(anyhow::Error::from(err)),
623608
};
624609

625-
get_final_cubestore_result(
626-
&transform_request_data,
627-
&cube_store_result,
628-
&mut result_data,
629-
)?;
610+
result_data.prepare_results(&transform_request_data, &cube_store_result)?;
630611

631612
match serde_json::to_string(&result_data) {
632613
Ok(json) => Ok(json),
@@ -783,11 +764,7 @@ fn final_cubestore_result_multi(mut cx: FunctionContext) -> JsResult<JsPromise>
783764
Err(err) => return Err(anyhow::Error::from(err)),
784765
};
785766

786-
get_final_cubestore_result_multi(
787-
&transform_requests,
788-
&cube_store_results,
789-
&mut result_data,
790-
)?;
767+
result_data.prepare_results(&transform_requests, &cube_store_results)?;
791768

792769
match serde_json::to_string(&result_data) {
793770
Ok(json) => Ok(json),

rust/cubeorchestrator/src/cubestore_result_transform.rs

Lines changed: 157 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
use crate::{
22
cubestore_message_parser::CubeStoreResult,
3-
types::{
4-
ConfigItem, MembersMap, NormalizedQuery, QueryTimeDimension, QueryType, RequestResultData,
5-
RequestResultDataMulti, ResultType, TransformDataRequest, TransformedData,
6-
BLENDING_QUERY_KEY_PREFIX, BLENDING_QUERY_RES_SEPARATOR, COMPARE_DATE_RANGE_FIELD,
7-
COMPARE_DATE_RANGE_SEPARATOR, MEMBER_SEPARATOR,
3+
transport::{
4+
ConfigItem, MembersMap, NormalizedQuery, QueryTimeDimension, QueryType, ResultType,
5+
TransformDataRequest, BLENDING_QUERY_KEY_PREFIX, BLENDING_QUERY_RES_SEPARATOR,
6+
COMPARE_DATE_RANGE_FIELD, COMPARE_DATE_RANGE_SEPARATOR, MEMBER_SEPARATOR,
87
},
98
};
109
use anyhow::{bail, Context, Result};
1110
use chrono::{DateTime, SecondsFormat};
1211
use itertools::multizip;
12+
use serde::{Deserialize, Serialize};
13+
use serde_json::Value;
1314
use std::{
1415
collections::{HashMap, HashSet},
1516
sync::Arc,
@@ -284,63 +285,6 @@ pub fn get_vanilla_row(
284285
Ok(row)
285286
}
286287

287-
/// Transforms queried data array to the output format.
288-
pub fn transform_data(
289-
alias_to_member_name_map: &HashMap<String, String>,
290-
annotation: &HashMap<String, ConfigItem>,
291-
data: &CubeStoreResult,
292-
query: &NormalizedQuery,
293-
query_type: &QueryType,
294-
res_type: Option<ResultType>,
295-
) -> Result<TransformedData> {
296-
let members_to_alias_map = get_members(
297-
query_type,
298-
query,
299-
data,
300-
alias_to_member_name_map,
301-
annotation,
302-
)?;
303-
let members: Vec<String> = members_to_alias_map.keys().cloned().collect();
304-
305-
match res_type {
306-
Some(ResultType::Compact) => {
307-
let dataset: Vec<_> = data
308-
.rows
309-
.iter()
310-
.map(|row| {
311-
get_compact_row(
312-
&members_to_alias_map,
313-
annotation,
314-
query_type,
315-
&members,
316-
query.time_dimensions.as_ref(),
317-
row,
318-
&data.columns_pos,
319-
)
320-
})
321-
.collect::<Result<Vec<_>>>()?;
322-
Ok(TransformedData::Compact { members, dataset })
323-
}
324-
_ => {
325-
let dataset: Vec<_> = data
326-
.rows
327-
.iter()
328-
.map(|row| {
329-
get_vanilla_row(
330-
alias_to_member_name_map,
331-
annotation,
332-
query_type,
333-
query,
334-
row,
335-
&data.columns_pos,
336-
)
337-
})
338-
.collect::<Result<Vec<_>>>()?;
339-
Ok(TransformedData::Vanilla(dataset))
340-
}
341-
}
342-
}
343-
344288
/// Helper to get a list if unique granularities from normalized queries
345289
pub fn get_query_granularities(queries: &[&NormalizedQuery]) -> Vec<String> {
346290
queries
@@ -414,31 +358,6 @@ pub fn get_pivot_query(
414358
Ok(pivot_query)
415359
}
416360

417-
pub fn get_final_cubestore_result(
418-
request_data: &TransformDataRequest,
419-
cube_store_result: &CubeStoreResult,
420-
result_data: &mut RequestResultData,
421-
) -> Result<()> {
422-
let alias_to_member_name_map = &request_data.alias_to_member_name_map;
423-
let annotation = &request_data.annotation;
424-
let query = &request_data.query;
425-
let query_type = &request_data.query_type.clone().unwrap_or_default();
426-
let res_type = &request_data.res_type;
427-
428-
let transformed = transform_data(
429-
alias_to_member_name_map,
430-
annotation,
431-
cube_store_result,
432-
query,
433-
query_type,
434-
res_type.clone(),
435-
)?;
436-
437-
result_data.data = Some(transformed);
438-
439-
Ok(())
440-
}
441-
442361
pub fn get_final_cubestore_result_array(
443362
transform_requests: &[TransformDataRequest],
444363
cube_store_results: &[Arc<CubeStoreResult>],
@@ -449,35 +368,164 @@ pub fn get_final_cubestore_result_array(
449368
cube_store_results.iter(),
450369
result_data.iter_mut(),
451370
)) {
452-
get_final_cubestore_result(transform_data, cube_store_result, result)?;
371+
result.prepare_results(transform_data, cube_store_result)?;
453372
}
454373

455374
Ok(())
456375
}
457376

458-
pub fn get_final_cubestore_result_multi(
459-
request_data: &[TransformDataRequest],
460-
cube_store_result: &[Arc<CubeStoreResult>],
461-
result_data: &mut RequestResultDataMulti,
462-
) -> Result<()> {
463-
for (transform_data, cube_store_result, result) in multizip((
464-
request_data.iter(),
465-
cube_store_result.iter(),
466-
result_data.results.iter_mut(),
467-
)) {
468-
get_final_cubestore_result(transform_data, cube_store_result, result)?;
377+
#[derive(Debug, Clone, Serialize, Deserialize)]
378+
#[serde(untagged)]
379+
pub enum TransformedData {
380+
Compact {
381+
members: Vec<String>,
382+
dataset: Vec<Vec<String>>,
383+
},
384+
Vanilla(Vec<HashMap<String, String>>),
385+
}
386+
387+
impl TransformedData {
388+
/// Transforms queried data array to the output format.
389+
pub fn transform(
390+
request_data: &TransformDataRequest,
391+
cube_store_result: &CubeStoreResult,
392+
) -> Result<Self> {
393+
let alias_to_member_name_map = &request_data.alias_to_member_name_map;
394+
let annotation = &request_data.annotation;
395+
let query = &request_data.query;
396+
let query_type = &request_data.query_type.clone().unwrap_or_default();
397+
let res_type = request_data.res_type.clone();
398+
399+
let members_to_alias_map = get_members(
400+
&query_type,
401+
query,
402+
cube_store_result,
403+
alias_to_member_name_map,
404+
annotation,
405+
)?;
406+
let members: Vec<String> = members_to_alias_map.keys().cloned().collect();
407+
408+
match res_type {
409+
Some(ResultType::Compact) => {
410+
let dataset: Vec<_> = cube_store_result
411+
.rows
412+
.iter()
413+
.map(|row| {
414+
get_compact_row(
415+
&members_to_alias_map,
416+
annotation,
417+
&query_type,
418+
&members,
419+
query.time_dimensions.as_ref(),
420+
row,
421+
&cube_store_result.columns_pos,
422+
)
423+
})
424+
.collect::<Result<Vec<_>>>()?;
425+
Ok(TransformedData::Compact { members, dataset })
426+
}
427+
_ => {
428+
let dataset: Vec<_> = cube_store_result
429+
.rows
430+
.iter()
431+
.map(|row| {
432+
get_vanilla_row(
433+
alias_to_member_name_map,
434+
annotation,
435+
&query_type,
436+
query,
437+
row,
438+
&cube_store_result.columns_pos,
439+
)
440+
})
441+
.collect::<Result<Vec<_>>>()?;
442+
Ok(TransformedData::Vanilla(dataset))
443+
}
444+
}
469445
}
446+
}
470447

471-
let normalized_queries = result_data
472-
.results
473-
.iter()
474-
.map(|result| &result.query)
475-
.collect::<Vec<_>>();
448+
#[derive(Debug, Clone, Serialize, Deserialize)]
449+
pub struct RequestResultDataMulti {
450+
#[serde(rename = "queryType")]
451+
pub query_type: QueryType,
452+
pub results: Vec<RequestResultData>,
453+
#[serde(rename = "pivotQuery")]
454+
pub pivot_query: Option<NormalizedQuery>,
455+
#[serde(rename = "slowQuery")]
456+
pub slow_query: bool,
457+
}
476458

477-
result_data.pivot_query = Option::from(get_pivot_query(
478-
&result_data.query_type,
479-
&normalized_queries,
480-
)?);
459+
impl RequestResultDataMulti {
460+
/// Processes multiple results and populates the final `RequestResultDataMulti` structure
461+
/// which is sent to the client.
462+
pub fn prepare_results(
463+
&mut self,
464+
request_data: &[TransformDataRequest],
465+
cube_store_result: &[Arc<CubeStoreResult>],
466+
) -> Result<()> {
467+
for (transform_data, cube_store_result, result) in multizip((
468+
request_data.iter(),
469+
cube_store_result.iter(),
470+
self.results.iter_mut(),
471+
)) {
472+
result.prepare_results(transform_data, cube_store_result)?;
473+
}
481474

482-
Ok(())
475+
let normalized_queries = self
476+
.results
477+
.iter()
478+
.map(|result| &result.query)
479+
.collect::<Vec<_>>();
480+
481+
self.pivot_query = Some(get_pivot_query(&self.query_type, &normalized_queries)?);
482+
483+
Ok(())
484+
}
485+
}
486+
487+
#[derive(Debug, Clone, Serialize, Deserialize)]
488+
pub struct RequestResultData {
489+
pub query: NormalizedQuery,
490+
#[serde(rename = "lastRefreshTime")]
491+
pub last_refresh_time: Option<String>,
492+
#[serde(rename = "refreshKeyValues")]
493+
pub refresh_key_values: Option<Value>,
494+
#[serde(rename = "usedPreAggregations")]
495+
pub used_pre_aggregations: Option<Value>,
496+
#[serde(rename = "transformedQuery")]
497+
pub transformed_query: Option<Value>,
498+
#[serde(rename = "requestId")]
499+
pub request_id: Option<String>,
500+
pub annotation: HashMap<String, HashMap<String, ConfigItem>>,
501+
#[serde(rename = "dataSource")]
502+
pub data_source: String,
503+
#[serde(rename = "dbType")]
504+
pub db_type: String,
505+
#[serde(rename = "extDbType")]
506+
pub ext_db_type: Option<String>,
507+
pub external: bool,
508+
#[serde(rename = "slowQuery")]
509+
pub slow_query: bool,
510+
pub total: Option<u64>,
511+
pub data: Option<TransformedData>,
512+
}
513+
514+
impl RequestResultData {
515+
/// Populates the `RequestResultData` structure with the transformed Query result.
516+
pub fn prepare_results(
517+
&mut self,
518+
request_data: &TransformDataRequest,
519+
cube_store_result: &CubeStoreResult,
520+
) -> Result<()> {
521+
let transformed = TransformedData::transform(request_data, cube_store_result)?;
522+
self.data = Some(transformed);
523+
524+
Ok(())
525+
}
526+
}
527+
528+
#[derive(Debug, Clone, Serialize, Deserialize)]
529+
pub struct RequestResultArray {
530+
pub results: Vec<RequestResultData>,
483531
}

rust/cubeorchestrator/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
pub mod cubestore_message_parser;
22
pub mod cubestore_result_transform;
3-
pub mod types;
3+
pub mod transport;

0 commit comments

Comments
 (0)