gitql_engine/
engine_join.rsuse std::collections::HashMap;
use gitql_ast::statement::Join;
use gitql_ast::statement::JoinKind;
use gitql_ast::statement::JoinOperand;
use gitql_ast::statement::TableSelection;
use gitql_core::environment::Environment;
use gitql_core::object::Row;
use gitql_core::values::base::Value;
use gitql_core::values::boolean::BoolValue;
use gitql_core::values::null::NullValue;
use crate::engine_evaluator::evaluate_expression;
#[inline(always)]
pub(crate) fn apply_join_operation(
    env: &mut Environment,
    all_rows: &mut Vec<Row>,
    joins: &Vec<Join>,
    tables_selections: &Vec<TableSelection>,
    selected_rows_per_table: &mut HashMap<String, Vec<Row>>,
    hidden_selection_per_table: &HashMap<String, usize>,
    titles: &[String],
) -> Result<(), String> {
    if joins.is_empty() {
        for table_selection in tables_selections {
            let table_rows = selected_rows_per_table
                .get_mut(&table_selection.table_name)
                .unwrap();
            all_rows.append(table_rows);
        }
        return Ok(());
    }
    let mut current_tables_rows: Vec<Row> = vec![];
    let mut all_rows_hidden_count = 0;
    for join in joins {
        let mut current_join_rows: Vec<Row> = vec![];
        let left_rows: &Vec<Row>;
        let left_hidden_count: usize;
        let right_rows: &Vec<Row>;
        let right_hidden_count: usize;
        match &join.operand {
            JoinOperand::OuterAndInner(outer, inner) => {
                left_hidden_count = *hidden_selection_per_table.get(outer).unwrap_or(&0);
                right_hidden_count = *hidden_selection_per_table.get(inner).unwrap_or(&0);
                all_rows_hidden_count += left_hidden_count + right_hidden_count;
                left_rows = selected_rows_per_table.get(outer).unwrap();
                right_rows = selected_rows_per_table.get(inner).unwrap();
            }
            JoinOperand::Inner(inner) => {
                left_hidden_count = all_rows_hidden_count;
                right_hidden_count = *hidden_selection_per_table.get(inner).unwrap_or(&0);
                all_rows_hidden_count += right_hidden_count;
                left_rows = ¤t_tables_rows;
                right_rows = selected_rows_per_table.get(inner).unwrap();
            }
        }
        if join.kind == JoinKind::Cross && (left_rows.is_empty() || right_rows.is_empty()) {
            continue;
        }
        for outer in left_rows {
            for inner in right_rows {
                let row_len = outer.values.len() + inner.values.len();
                let mut joined_row: Vec<Box<dyn Value>> = Vec::with_capacity(row_len);
                joined_row.append(&mut outer.values.clone());
                let inner_rows = inner.values.clone();
                let inner_hidden_values = &inner_rows[0..right_hidden_count];
                joined_row.splice(
                    left_hidden_count..left_hidden_count,
                    inner_hidden_values.to_vec(),
                );
                let inner_other_values = &inner_rows[right_hidden_count..];
                joined_row.extend_from_slice(inner_other_values);
                if let Some(predicate) = &join.predicate {
                    let predicate_value = evaluate_expression(env, predicate, titles, &joined_row)?;
                    if let Some(bool_value) = predicate_value.as_any().downcast_ref::<BoolValue>() {
                        if bool_value.value {
                            current_join_rows.push(Row { values: joined_row });
                            continue;
                        }
                    }
                    match join.kind {
                        JoinKind::Left => {
                            let mut left_joined_row: Vec<Box<dyn Value>> =
                                Vec::with_capacity(row_len);
                            left_joined_row.append(&mut outer.values.clone());
                            for _ in 0..inner.values.len() {
                                left_joined_row.push(Box::new(NullValue));
                            }
                        }
                        JoinKind::Right => {
                            let mut right_joined_row: Vec<Box<dyn Value>> =
                                Vec::with_capacity(row_len);
                            for _ in 0..outer.values.len() {
                                right_joined_row.push(Box::new(NullValue));
                            }
                            right_joined_row.append(&mut inner.values.clone());
                        }
                        _ => {}
                    }
                    continue;
                }
                current_join_rows.push(Row { values: joined_row });
            }
        }
        current_tables_rows.clear();
        current_tables_rows.append(&mut current_join_rows);
    }
    all_rows.append(&mut current_tables_rows);
    Ok(())
}