Skip to content

Commit

Permalink
Issue #117: Handle groups rows elemenations in case group by don't cr…
Browse files Browse the repository at this point in the history
…eate extra groups
  • Loading branch information
AmrDeveloper committed Sep 11, 2024
1 parent afd9872 commit a195cf4
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 16 deletions.
15 changes: 9 additions & 6 deletions crates/gitql-engine/src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ fn evaluate_select_query(
let hidden_selections_map = query.hidden_selections;
let hidden_selections = hidden_selections_map.values().flatten().cloned().collect();
let mut statements_map = query.statements;
let has_group_by_statement = statements_map.contains_key("group");

for gql_command in FIXED_LOGICAL_PLAN {
if statements_map.contains_key(gql_command) {
Expand All @@ -96,6 +97,7 @@ fn evaluate_select_query(
&mut gitql_object,
&mut alias_table,
&hidden_selections_map,
has_group_by_statement,
)?;

// If the main group is empty, no need to perform other statements
Expand All @@ -121,19 +123,21 @@ fn evaluate_select_query(
&mut gitql_object,
&mut alias_table,
&hidden_selections_map,
has_group_by_statement,
)?;
}
}
}
}

// Remove Hidden Selection from the rows after executing the query plan
let number_of_groups = gitql_object.groups.len();
let group: &mut Group = &mut gitql_object.groups[0];
remove_hidden_selected(&mut gitql_object.titles, group, &hidden_selections);

// If there are many groups that mean group by is executed before.
// must merge each group into only one element
if gitql_object.len() > 1 {
if number_of_groups > 1 {
for group in gitql_object.groups.iter_mut() {
if group.len() > 1 {
group.rows.drain(1..);
Expand All @@ -142,14 +146,12 @@ fn evaluate_select_query(
}
// If it a single group but it select only aggregations function,
// should return only first element in the group
else if gitql_object.len() == 1
else if number_of_groups == 1
&& !query.has_group_by_statement
&& query.has_aggregation_function
&& group.len() > 1
{
let group: &mut Group = &mut gitql_object.groups[0];
if group.len() > 1 {
group.rows.drain(1..);
}
group.rows.drain(1..);
}

// Into statement must be executed last after flatted and remove hidden selections
Expand All @@ -162,6 +164,7 @@ fn evaluate_select_query(
&mut gitql_object,
&mut alias_table,
&hidden_selections_map,
has_group_by_statement,
)?;

return Ok(EvaluationResult::SelectedInfo);
Expand Down
25 changes: 15 additions & 10 deletions crates/gitql-engine/src/engine_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub fn execute_statement(
gitql_object: &mut GitQLObject,
alias_table: &mut HashMap<String, String>,
hidden_selection: &HashMap<String, Vec<String>>,
has_group_by_statement: bool,
) -> Result<(), String> {
match statement.kind() {
Do => {
Expand Down Expand Up @@ -106,7 +107,13 @@ pub fn execute_statement(
.as_any()
.downcast_ref::<AggregationsStatement>()
.unwrap();
execute_aggregation_function_statement(env, statement, gitql_object, alias_table)
execute_aggregation_function_statement(
env,
statement,
gitql_object,
alias_table,
has_group_by_statement,
)
}
Into => {
let statement = statement.as_any().downcast_ref::<IntoStatement>().unwrap();
Expand Down Expand Up @@ -450,13 +457,13 @@ fn execute_group_by_statement(
e.insert(next_group_index);
next_group_index += 1;
gitql_object.groups.push(Group { rows: vec![object] });
continue;
}

// If there is an existing group for this value, append current object to it
else {
let index = *groups_map.get(&values_hash).unwrap();
let target_group = &mut gitql_object.groups[index];
target_group.rows.push(object);
}
let index = *groups_map.get(&values_hash).unwrap();
let target_group = &mut gitql_object.groups[index];
target_group.rows.push(object);
}

Ok(())
Expand All @@ -467,16 +474,14 @@ fn execute_aggregation_function_statement(
statement: &AggregationsStatement,
gitql_object: &mut GitQLObject,
alias_table: &HashMap<String, String>,
is_query_has_group_by: bool,
) -> Result<(), String> {
// Make sure you have at least one aggregation function to calculate
let aggregations_map = &statement.aggregations;
if aggregations_map.is_empty() {
return Ok(());
}

// Used to determine if group by statement is executed before or not
let groups_count = gitql_object.len();

// We should run aggregation function for each group
for group in &mut gitql_object.groups {
// No need to apply all aggregation if there is no selected elements
Expand Down Expand Up @@ -559,7 +564,7 @@ fn execute_aggregation_function_statement(

// In case of group by statement is executed
// Remove all elements expect the first one
if groups_count > 1 {
if is_query_has_group_by {
group.rows.drain(1..);
}
}
Expand Down

0 comments on commit a195cf4

Please sign in to comment.