fn build_join_indexes(
    left: &JoinHashMap,
    right: &RecordBatch,
    join_type: &JoinType,
    right_on: &HashSet<String>,
) -> Result<Vec<(JoinIndex, RightIndex)>> {
    let keys_values = right_on
        .iter()
        .map(|name| Ok(col(name).evaluate(right)?.into_array(right.num_rows())))
        .collect::<Result<Vec<_>>>()?;

    let mut key = Vec::with_capacity(keys_values.len());

    match join_type {
        JoinType::Inner => {
            let mut indexes = Vec::new(); // unknown a prior size

            // Visit all of the right rows
            for row in 0..right.num_rows() {
                // Get the key and find it in the build index
                create_key(&keys_values, row, &mut key)?;
                let left_indexes = left.get(&key);

                // for every item on the left and right with this key, add the respective pair
                left_indexes.unwrap_or(&vec![]).iter().for_each(|x| {
                    // on an inner join, left and right indices are present
                    indexes.push((Some(*x), Some(row)));
                })
            }
            Ok(indexes)
        }
        JoinType::Left => {
            let mut indexes = Vec::new(); // unknown a prior size

            // Keep track of which item is visited in the build input
            // TODO: this can be stored more efficiently with a marker
            let mut is_visited = HashSet::new();

            // First visit all of the rows
            for row in 0..right.num_rows() {
                create_key(&keys_values, row, &mut key)?;
                let left_indexes = left.get(&key);

                if let Some(indices) = left_indexes {
                    is_visited.insert(key.clone());

                    indices.iter().for_each(|x| {
                        indexes.push((Some(*x), Some(row)));
                    })
                };
            }
            // Add the remaining left rows to the result set with None on the right side
            for (key, indices) in left {
                if !is_visited.contains(key) {
                    indices.iter().for_each(|x| {
                        indexes.push((Some(*x), None));
                    });
                }
            }

            Ok(indexes)
        }
        JoinType::Right => {
            let mut indexes = Vec::new(); // unknown a prior size
            for row in 0..right.num_rows() {
                create_key(&keys_values, row, &mut key)?;

                let left_indices = left.get(&key);

                match left_indices {
                    Some(indices) => {
                        indices.iter().for_each(|x| {
                            indexes.push((Some(*x), Some(row)));
                        });
                    }
                    None => {
                        // when no match, add the row with None for the left side
                        indexes.push((None, Some(row)));
                    }
                }
            }
            Ok(indexes)
        }
    }
}
/// returns a vector with (index from left, index from right).
/// The size of this vector corresponds to the total size of a joined batch
// For a join on column A:
// left       right
//     batch 1
// A B         A D
// ---------------
// 1 a         3 6
// 2 b         1 2
// 3 c         2 4
//     batch 2
// A B         A D
// ---------------
// 1 a         5 10
// 2 b         2 2
// 4 d         1 1
// indices (batch, batch_row)
// left       right
// (0, 2)     (0, 0)
// (0, 0)     (0, 1)
// (0, 1)     (0, 2)
// (1, 0)     (0, 1)
// (1, 1)     (0, 2)
// (0, 1)     (1, 1)
// (0, 0)     (1, 2)
// (1, 1)     (1, 1)
// (1, 0)     (1, 2)
returns a vector with (index from left, index from right).
The size of this vector corresponds to the total size of a joined batch
For a join on column A:
left       right
batch 1
A B         A D




returns a vector with ( index from left index from right ) . The size of this vector corresponds to the total size of a joined batch For a join on column A : left right batch 1 A B A D
fn build_join_indexes(
    left: &JoinHashMap,
    right: &RecordBatch,
    join_type: &JoinType,
    right_on: &HashSet<String>,
) -> Result<Vec<(JoinIndex, RightIndex)>> {
    let keys_values = right_on
        .iter()
        .map(|name| Ok(col(name).evaluate(right)?.into_array(right.num_rows())))
        .collect::<Result<Vec<_>>>()?;
    let mut key = Vec::with_capacity(keys_values.len());
    match join_type {
        JoinType::Inner => {
            let mut indexes = Vec::new(); // unknown a prior size
            // Visit all of the right rows
            for row in 0..right.num_rows() {
                // Get the key and find it in the build index
                create_key(&keys_values, row, &mut key)?;
                let left_indexes = left.get(&key);
                // for every item on the left and right with this key, add the respective pair
                left_indexes.unwrap_or(&vec![]).iter().for_each(|x| {
                    // on an inner join, left and right indices are present
                    indexes.push((Some(*x), Some(row)));
                })
            }
            Ok(indexes)
        }
        JoinType::Left => {
            let mut indexes = Vec::new(); // unknown a prior size
            // Keep track of which item is visited in the build input
            // TODO: this can be stored more efficiently with a marker
            let mut is_visited = HashSet::new();
            // First visit all of the rows
            for row in 0..right.num_rows() {
                create_key(&keys_values, row, &mut key)?;
                let left_indexes = left.get(&key);
                if let Some(indices) = left_indexes {
                    is_visited.insert(key.clone());
                    indices.iter().for_each(|x| {
                        indexes.push((Some(*x), Some(row)));
                    })
                };
            }
            // Add the remaining left rows to the result set with None on the right side
            for (key, indices) in left {
                if !is_visited.contains(key) {
                    indices.iter().for_each(|x| {
                        indexes.push((Some(*x), None));
                    });
                }
            }
            Ok(indexes)
        }
        JoinType::Right => {
            let mut indexes = Vec::new(); // unknown a prior size
            for row in 0..right.num_rows() {
                create_key(&keys_values, row, &mut key)?;
                let left_indices = left.get(&key);
                match left_indices {
                    Some(indices) => {
                        indices.iter().for_each(|x| {
                            indexes.push((Some(*x), Some(row)));
                        });
                    }
                    None => {
                        // when no match, add the row with None for the left side
                        indexes.push((None, Some(row)));
                    }
                }
            }
            Ok(indexes)
        }
    }
}
fn build_join_indexes ( left : & JoinHashMap , right : & RecordBatch , join_type : & JoinType , right_on : & HashSet < String > , ) -> Result < Vec < ( JoinIndex , RightIndex ) > > { let keys_values = right_on . iter ( ) . map ( | name | Ok ( col ( name ) . evaluate ( right ) ? . into_array ( right . num_rows ( ) ) ) ) . collect :: < Result < Vec < _ > > > ( ) ? ; let mut key = Vec :: with_capacity ( keys_values . len ( ) ) ; match join_type { JoinType :: Inner => { let mut indexes = Vec :: new ( ) ; // unknown a prior size // Visit all of the right rows for row in 0 .. right . num_rows ( ) { // Get the key and find it in the build index create_key ( & keys_values , row , & mut key ) ? ; let left_indexes = left . get ( & key ) ; // for every item on the left and right with this key, add the respective pair left_indexes . unwrap_or ( & vec ! [ ] ) . iter ( ) . for_each ( | x | { // on an inner join, left and right indices are present indexes . push ( ( Some ( * x ) , Some ( row ) ) ) ; } ) } Ok ( indexes ) } JoinType :: Left => { let mut indexes = Vec :: new ( ) ; // unknown a prior size // Keep track of which item is visited in the build input // TODO: this can be stored more efficiently with a marker let mut is_visited = HashSet :: new ( ) ; // First visit all of the rows for row in 0 .. right . num_rows ( ) { create_key ( & keys_values , row , & mut key ) ? ; let left_indexes = left . get ( & key ) ; if let Some ( indices ) = left_indexes { is_visited . insert ( key . clone ( ) ) ; indices . iter ( ) . for_each ( | x | { indexes . push ( ( Some ( * x ) , Some ( row ) ) ) ; } ) } ; } // Add the remaining left rows to the result set with None on the right side for ( key , indices ) in left { if ! is_visited . contains ( key ) { indices . iter ( ) . for_each ( | x | { indexes . push ( ( Some ( * x ) , None ) ) ; } ) ; } } Ok ( indexes ) } JoinType :: Right => { let mut indexes = Vec :: new ( ) ; // unknown a prior size for row in 0 .. right . num_rows ( ) { create_key ( & keys_values , row , & mut key ) ? ; let left_indices = left . get ( & key ) ; match left_indices { Some ( indices ) => { indices . iter ( ) . for_each ( | x | { indexes . push ( ( Some ( * x ) , Some ( row ) ) ) ; } ) ; } None => { // when no match, add the row with None for the left side indexes . push ( ( None , Some ( row ) ) ) ; } } } Ok ( indexes ) } } }
returns a vector with (index from left, index from right).
returns a vector with ( index from left index from right ) .
left
&JoinHashMap
right
&RecordBatch
join_type
&JoinType
right_on
&HashSet<String>
left
&JoinHashMap
right
&RecordBatch
join_type
&JoinType
right_on
&HashSet<String>