multisql/executor/query/select/join/
execute.rs1use {
2 super::{JoinError, JoinMethod, JoinPlan, JoinType},
3 crate::{
4 recipe::{Ingredient, MetaRecipe, Method, PlannedRecipe, Recipe},
5 types::{ColumnInfo, Row},
6 Glue, IndexFilter, Result, Value,
7 },
8};
9
10#[derive(Debug)]
11pub struct JoinExecute {
12 pub database: Option<String>,
13 pub table: String,
14 pub method: JoinMethod,
15 pub join_type: JoinType,
16 pub widths: (usize, usize),
17 pub index_filter: Option<IndexFilter>,
18}
19
20impl JoinExecute {
21 pub fn new(
22 plan: JoinPlan,
23 plane_columns: &[ColumnInfo],
24 index_filter: Option<IndexFilter>,
25 ) -> Result<Self> {
26 let JoinPlan {
27 database,
28 table,
29 join_type,
30 constraint,
31 columns,
32 ..
33 } = plan;
34 let widths = (plane_columns.len(), columns.len());
35 let method = decide_method(constraint, columns, plane_columns)?;
36 Ok(Self {
37 database,
38 table,
39 method,
40 join_type,
41 widths,
42 index_filter,
43 })
44 }
45 pub fn set_first_table(&mut self) {
46 self.method = JoinMethod::FirstTable;
47 }
48 pub async fn execute<'a>(self, glue: &Glue, plane_rows: Vec<Row>) -> Result<Vec<Row>> {
49 let rows = glue
50 .get_rows(&self.table, &self.database, &self.index_filter)
51 .await?;
52 self.method.run(
53 &self.join_type,
54 self.widths.0,
55 self.widths.1,
56 plane_rows,
57 rows,
58 )
59 }
60}
61
62fn decide_method(
63 constraint: MetaRecipe,
64 self_columns: Vec<ColumnInfo>,
65 plane_columns: &[ColumnInfo],
66) -> Result<JoinMethod> {
67 Ok(match &constraint.recipe {
68 Recipe::Ingredient(Ingredient::Value(Value::Bool(true))) => JoinMethod::All,
69 Recipe::Method(method) => match **method {
70 Method::BinaryOperation(
71 operator,
72 Recipe::Ingredient(Ingredient::Column(index_l)),
73 Recipe::Ingredient(Ingredient::Column(index_r)),
74 ) if operator == Value::eq => {
75 let column_l = constraint
77 .meta
78 .objects
79 .get(index_l)
80 .ok_or(JoinError::Unreachable)?
81 .as_ref()
82 .ok_or(JoinError::Unreachable)?;
83 let column_r = constraint
84 .meta
85 .objects
86 .get(index_r)
87 .ok_or(JoinError::Unreachable)?
88 .as_ref()
89 .ok_or(JoinError::Unreachable)?;
90
91 let (self_index, plane_index) = if let Some(self_index) =
92 self_columns.iter().position(|column| column == column_l)
93 {
94 let plane_index = plane_columns
95 .iter()
96 .position(|column| column == column_r)
97 .ok_or(JoinError::Unreachable)?;
98 (self_index, plane_index)
99 } else {
100 let self_index = self_columns
101 .iter()
102 .position(|column| column == column_r)
103 .ok_or(JoinError::Unreachable)?;
104 let plane_index = plane_columns
105 .iter()
106 .position(|column| column == column_l)
107 .ok_or(JoinError::Unreachable)?;
108 (self_index, plane_index)
109 };
110
111 JoinMethod::ColumnEqColumn {
112 plane_trust_ordered: false,
113 plane_index,
114 self_trust_ordered: false,
115 self_index,
116 }
117 }
118 _ => JoinMethod::General(PlannedRecipe::new(constraint.clone(), plane_columns)?),
122 },
123 _ => JoinMethod::Ignore,
124 })
125}