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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use {
super::{JoinManual, JoinType},
crate::{
executor::{
fetch::fetch_columns,
types::{ColumnInfo, ComplexTableName},
MetaRecipe,
},
Context, JoinError, Result, StorageInner,
},
std::cmp::Ordering,
};
#[derive(Debug)]
pub struct JoinPlan {
pub database: String,
pub table: String,
pub columns: Vec<ColumnInfo>,
pub join_type: JoinType,
pub constraint: MetaRecipe,
pub needed_tables: Vec<usize>,
}
impl PartialEq for JoinPlan {
fn eq(&self, _other: &Self) -> bool {
false
}
}
impl Eq for JoinPlan {}
impl PartialOrd for JoinPlan {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.join_type.cmp(&other.join_type))
}
}
impl Ord for JoinPlan {
fn cmp(&self, other: &Self) -> Ordering {
self.join_type.cmp(&other.join_type)
}
}
impl JoinPlan {
pub async fn new<'a>(
join_manual: JoinManual,
storages: &Vec<(String, &mut StorageInner)>,
context: &Context,
) -> Result<Self> {
let JoinManual {
table,
constraint,
join_type,
} = join_manual;
let columns = get_columns(storages, table.clone(), context).await?;
let ComplexTableName {
database,
name: table,
..
} = table;
Ok(Self {
database,
table,
join_type,
columns,
constraint,
needed_tables: vec![],
})
}
pub fn calculate_needed_tables(&mut self, table_columns: &Vec<Vec<ColumnInfo>>) {
self.needed_tables = table_columns
.iter()
.enumerate()
.filter_map(|(index, columns)| {
if columns.iter().any(|table_column| {
self.constraint
.meta
.objects
.iter()
.any(|constraint_column| {
constraint_column
.as_ref()
.map(|constraint_column| table_column == constraint_column)
.unwrap_or(false)
})
}) {
Some(index)
} else {
None
}
})
.collect()
}
}
async fn get_columns(
storages: &Vec<(String, &mut StorageInner)>,
table: ComplexTableName,
context: &Context,
) -> Result<Vec<ColumnInfo>> {
if let Some((context_table_labels, ..)) = context.tables.get(&table.name) {
Ok(context_table_labels
.iter()
.map(|name| ColumnInfo {
table: table.clone(),
name: name.clone(),
index: None,
})
.collect::<Vec<ColumnInfo>>())
} else {
let storage = storages
.into_iter()
.find_map(|(name, storage)| {
if name == &table.database {
Some(&**storage)
} else {
None
}
})
.or(storages.get(0).map(|(_, storage)| &**storage))
.ok_or(JoinError::TableNotFound(table.clone()))?;
fetch_columns(storage, table).await
}
}