pub fn query<'a, T: SupportedTuple<'a>>(
    clauses: Vec<Clause<'a>>,
    triples: &[Triple<'a>],
) -> Result<(Vec<T>, Query<T>, HashMap<&'a str, usize>), Box<dyn Error>> {
    // Build clauses.
    let time = std::time::Instant::now();
    let mut relations = Vec::with_capacity(clauses.len());
    let mut variables = HashMap::new();

    for clause in clauses {
        let relation = match clause {
            Clause::Assign(name, mut expr) => {
                let mut bitset = Bitset::new();

                expr.assign_variables(&mut variables, &mut bitset);

                let name_idx = variables.find_index_or_insert(name.clone());

                if bitset.has(name_idx) {
                    return Err(format!("name {:?} has already been assigned", name).into());
                }

                BuiltClause::Assign(name_idx, bitset, expr)
            }
            Clause::Triple(patterns) => {
                let mut bitset = None;
                let mut relation = Vec::new();

                for triple in triples {
                    let mut tuple = SmallVec::<[Option<Val<'a>>; 3]>::with_capacity(3);
                    let mut tuple_bitset = Bitset::new();
                    let mut is_match = true;

                    for (val, pat) in triple.iter().zip(&patterns) {
                        match (val, pat) {
                            (Val::Num(actual), Pat::EqNum(expected)) if actual == expected => {
                                // Match.
                            }
                            (Val::Str(actual), Pat::EqStr(expected)) if actual == expected => {
                                // Match.
                            }
                            (Val::Bool(actual), Pat::EqBool(expected)) if actual == expected => {
                                // Match.
                            }
                            (val, Pat::Var(var)) => {
                                // Assign to variable.
                                let index = variables.find_index_or_insert(var.clone());

                                if tuple.len() <= index {
                                    tuple.resize_with(index, || None);
                                    tuple.push(Some(val.clone()));
                                } else {
                                    tuple[index] = Some(val.clone());
                                }

                                tuple_bitset.on(index);
                            }
                            _ => {
                                is_match = false;

                                break;
                            }
                        }
                    }

                    if is_match {
                        if bitset.is_none() {
                            bitset = Some(tuple_bitset);
                        }

                        relation.push(tuple.into_iter().collect());
                    }
                }

                let bitset = if let Some(bitset) = bitset {
                    bitset
                } else {
                    continue;
                };

                BuiltClause::Triples(relation, bitset)
            }
            Clause::Where(mut expr) => {
                let mut bitset = Bitset::new();

                expr.assign_variables(&mut variables, &mut bitset);

                BuiltClause::Where(expr, bitset)
            }
        };

        relations.push(relation);
    }

    let query_prepare = time.elapsed();

    // Build query.
    let time = std::time::Instant::now();
    let query = Query::new::<BuiltClause<T>, _, _>(relations.iter())?;
    let query_create = time.elapsed();

    // Run query.
    let time = std::time::Instant::now();
    let results = query.run(relations, crate::Hash::new())?.collect();
    let query_results = time.elapsed();

    eprintln!("query times: prepare: {:?}, create: {:?}, run: {:?}", query_prepare, query_create, query_results);

    Ok((results, query, variables))
}
/// Runs a query built on the given clauses using the given triples.
Runs a query built on the given clauses using the given triples.
Runs a query built on the given clauses using the given triples .
pub fn query<'a, T: SupportedTuple<'a>>(
    clauses: Vec<Clause<'a>>,
    triples: &[Triple<'a>],
) -> Result<(Vec<T>, Query<T>, HashMap<&'a str, usize>), Box<dyn Error>> {
    // Build clauses.
    let time = std::time::Instant::now();
    let mut relations = Vec::with_capacity(clauses.len());
    let mut variables = HashMap::new();
    for clause in clauses {
        let relation = match clause {
            Clause::Assign(name, mut expr) => {
                let mut bitset = Bitset::new();
                expr.assign_variables(&mut variables, &mut bitset);
                let name_idx = variables.find_index_or_insert(name.clone());
                if bitset.has(name_idx) {
                    return Err(format!("name {:?} has already been assigned", name).into());
                }
                BuiltClause::Assign(name_idx, bitset, expr)
            }
            Clause::Triple(patterns) => {
                let mut bitset = None;
                let mut relation = Vec::new();
                for triple in triples {
                    let mut tuple = SmallVec::<[Option<Val<'a>>; 3]>::with_capacity(3);
                    let mut tuple_bitset = Bitset::new();
                    let mut is_match = true;
                    for (val, pat) in triple.iter().zip(&patterns) {
                        match (val, pat) {
                            (Val::Num(actual), Pat::EqNum(expected)) if actual == expected => {
                                // Match.
                            }
                            (Val::Str(actual), Pat::EqStr(expected)) if actual == expected => {
                                // Match.
                            }
                            (Val::Bool(actual), Pat::EqBool(expected)) if actual == expected => {
                                // Match.
                            }
                            (val, Pat::Var(var)) => {
                                // Assign to variable.
                                let index = variables.find_index_or_insert(var.clone());
                                if tuple.len() <= index {
                                    tuple.resize_with(index, || None);
                                    tuple.push(Some(val.clone()));
                                } else {
                                    tuple[index] = Some(val.clone());
                                }
                                tuple_bitset.on(index);
                            }
                            _ => {
                                is_match = false;
                                break;
                            }
                        }
                    }
                    if is_match {
                        if bitset.is_none() {
                            bitset = Some(tuple_bitset);
                        }
                        relation.push(tuple.into_iter().collect());
                    }
                }
                let bitset = if let Some(bitset) = bitset {
                    bitset
                } else {
                    continue;
                };
                BuiltClause::Triples(relation, bitset)
            }
            Clause::Where(mut expr) => {
                let mut bitset = Bitset::new();
                expr.assign_variables(&mut variables, &mut bitset);
                BuiltClause::Where(expr, bitset)
            }
        };
        relations.push(relation);
    }
    let query_prepare = time.elapsed();
    // Build query.
    let time = std::time::Instant::now();
    let query = Query::new::<BuiltClause<T>, _, _>(relations.iter())?;
    let query_create = time.elapsed();
    // Run query.
    let time = std::time::Instant::now();
    let results = query.run(relations, crate::Hash::new())?.collect();
    let query_results = time.elapsed();
    eprintln!("query times: prepare: {:?}, create: {:?}, run: {:?}", query_prepare, query_create, query_results);
    Ok((results, query, variables))
}
pub fn query < ' a , T : SupportedTuple < ' a > > ( clauses : Vec < Clause < ' a > > , triples : & [ Triple < ' a > ] , ) -> Result < ( Vec < T > , Query < T > , HashMap < & ' a str , usize > ) , Box < dyn Error > > { // Build clauses. let time = std :: time :: Instant :: now ( ) ; let mut relations = Vec :: with_capacity ( clauses . len ( ) ) ; let mut variables = HashMap :: new ( ) ; for clause in clauses { let relation = match clause { Clause :: Assign ( name , mut expr ) => { let mut bitset = Bitset :: new ( ) ; expr . assign_variables ( & mut variables , & mut bitset ) ; let name_idx = variables . find_index_or_insert ( name . clone ( ) ) ; if bitset . has ( name_idx ) { return Err ( format ! ( " " name ) . into ( ) ) ; } BuiltClause :: Assign ( name_idx , bitset , expr ) } Clause :: Triple ( patterns ) => { let mut bitset = None ; let mut relation = Vec :: new ( ) ; for triple in triples { let mut tuple = SmallVec :: < [ Option < Val < ' a > > ; 3 ] > :: with_capacity ( 3 ) ; let mut tuple_bitset = Bitset :: new ( ) ; let mut is_match = true ; for ( val , pat ) in triple . iter ( ) . zip ( & patterns ) { match ( val , pat ) { ( Val :: Num ( actual ) , Pat :: EqNum ( expected ) ) if actual == expected => { // Match. } ( Val :: Str ( actual ) , Pat :: EqStr ( expected ) ) if actual == expected => { // Match. } ( Val :: Bool ( actual ) , Pat :: EqBool ( expected ) ) if actual == expected => { // Match. } ( val , Pat :: Var ( var ) ) => { // Assign to variable. let index = variables . find_index_or_insert ( var . clone ( ) ) ; if tuple . len ( ) <= index { tuple . resize_with ( index , | | None ) ; tuple . push ( Some ( val . clone ( ) ) ) ; } else { tuple [ index ] = Some ( val . clone ( ) ) ; } tuple_bitset . on ( index ) ; } _ => { is_match = false ; break ; } } } if is_match { if bitset . is_none ( ) { bitset = Some ( tuple_bitset ) ; } relation . push ( tuple . into_iter ( ) . collect ( ) ) ; } } let bitset = if let Some ( bitset ) = bitset { bitset } else { continue ; } ; BuiltClause :: Triples ( relation , bitset ) } Clause :: Where ( mut expr ) => { let mut bitset = Bitset :: new ( ) ; expr . assign_variables ( & mut variables , & mut bitset ) ; BuiltClause :: Where ( expr , bitset ) } } ; relations . push ( relation ) ; } let query_prepare = time . elapsed ( ) ; // Build query. let time = std :: time :: Instant :: now ( ) ; let query = Query :: new :: < BuiltClause < T > , _ , _ > ( relations . iter ( ) ) ? ; let query_create = time . elapsed ( ) ; // Run query. let time = std :: time :: Instant :: now ( ) ; let results = query . run ( relations , crate :: Hash :: new ( ) ) ? . collect ( ) ; let query_results = time . elapsed ( ) ; eprintln ! ( " " query_prepare query_create query_results ) ; Ok ( ( results , query , variables ) ) }
Runs a query built on the given clauses using the given triples.
Runs a query built on the given clauses using the given triples .
clauses
Vec<Clause<'a>>
triples
&[Triple<'a>]
clauses
Vec<Clause<'a>>
triples
&[Triple<'a>]