1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use std::{
    collections::HashMap,
    sync::{Arc, RwLock},
};

use futures::{executor::block_on, future};
use versatile_data::{Order, RowSet};

use crate::{Database, Search};

#[derive(Clone, Debug)]
pub struct SearchResult {
    collection_id: i32,
    rows: RowSet,
    join: HashMap<String, HashMap<u32, SearchResult>>,
}
impl SearchResult {
    pub fn new(
        collection_id: i32,
        rows: RowSet,
        join: HashMap<String, HashMap<u32, SearchResult>>,
    ) -> Self {
        Self {
            collection_id,
            rows,
            join,
        }
    }
    pub fn collection_id(&self) -> i32 {
        self.collection_id
    }
    pub fn rows(&self) -> &RowSet {
        &self.rows
    }
    pub fn join(&self) -> &HashMap<String, HashMap<u32, SearchResult>> {
        &self.join
    }

    pub fn sort(&self, database: &Database, orders: &[Order]) -> Vec<u32> {
        database.collection(self.collection_id).map_or(vec![], |c| {
            if orders.len() > 0 {
                c.data.sort(&self.rows, &orders)
            } else {
                self.rows.iter().map(|&x| x).collect()
            }
        })
    }
}

impl Search {
    pub fn get_result(&self) -> Arc<RwLock<Option<SearchResult>>> {
        Arc::clone(&self.result)
    }

    pub fn result(&mut self, database: &Database) -> Arc<RwLock<Option<SearchResult>>> {
        if let Some(collection) = database.collection(self.collection_id) {
            let rows = if self.conditions.len() > 0 {
                block_on(async {
                    let mut fs = self
                        .conditions
                        .iter()
                        .map(|c| c.result(collection, &database.relation))
                        .collect();
                    let (ret, _index, remaining) = future::select_all(fs).await;
                    let mut rows = ret;
                    fs = remaining;
                    while !fs.is_empty() {
                        let (ret, _index, remaining) = future::select_all(fs).await;
                        rows = rows.intersection(&ret).map(|&x| x).collect();
                        fs = remaining;
                    }
                    rows
                })
            } else {
                collection.data.all()
            };

            let join_result = block_on(async {
                let mut join_result = HashMap::new();
                let mut fs: Vec<_> = self
                    .join
                    .iter()
                    .map(|(name, join)| {
                        Box::pin(async {
                            (
                                name.to_owned(),
                                join.result(database, self.collection_id, &rows),
                            )
                        })
                    })
                    .collect();
                while !fs.is_empty() {
                    let (ret, _index, remaining) = future::select_all(fs).await;
                    join_result.insert(ret.0, ret.1.await);
                    fs = remaining;
                }
                join_result
            });
            *self.result.write().unwrap() = Some(SearchResult {
                collection_id: self.collection_id,
                rows,
                join: join_result,
            });
        }
        Arc::clone(&self.result)
    }
}