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
use std::collections::HashMap;

use futures::future;
use versatile_data::RowSet;

use crate::{CollectionRow, Database};

#[derive(Clone, Debug)]
pub struct Join {
    collection_id: i32,
    conditions: Vec<JoinCondition>,
}
impl Join {
    pub fn new(collection_id: i32, conditions: Vec<JoinCondition>) -> Self {
        Self {
            collection_id,
            conditions,
        }
    }

    fn result_row(
        &self,
        database: &Database,
        parent_collection_id: i32,
        parent_row: &u32,
    ) -> Vec<CollectionRow> {
        let parent_row = *parent_row;
        let mut result = vec![];
        for condition in &self.conditions {
            match condition {
                JoinCondition::Depend { key } => {
                    result.extend(
                        database
                            .relation
                            .read()
                            .unwrap()
                            .pends(key, &CollectionRow::new(parent_collection_id, parent_row))
                            .iter()
                            .filter(|r| r.collection_id() == self.collection_id)
                            .cloned()
                            .collect::<Vec<_>>(),
                    );
                }
            }
        }
        result
    }

    pub async fn result(
        &self,
        database: &Database,
        parent_collection_id: i32,
        parent_rows: &RowSet,
    ) -> HashMap<u32, Vec<CollectionRow>> {
        let mut r = HashMap::new();

        let mut fs: Vec<_> = parent_rows
            .iter()
            .map(|parent_row| {
                Box::pin(async {
                    (
                        *parent_row,
                        self.result_row(database, parent_collection_id, parent_row),
                    )
                })
            })
            .collect();
        while !fs.is_empty() {
            let (ret, _index, remaining) = future::select_all(fs).await;
            r.insert(ret.0, ret.1);
            fs = remaining;
        }
        r
    }
}

#[derive(Clone, Debug)]
pub enum JoinCondition {
    Depend { key: Option<String> },
}