risingwave_frontend/binder/relation/
join.rs1use risingwave_pb::plan_common::JoinType;
16use risingwave_sqlparser::ast::{
17 BinaryOperator, Expr, Ident, JoinConstraint, JoinOperator, TableFactor, TableWithJoins, Value,
18};
19
20use crate::binder::bind_context::BindContext;
21use crate::binder::statement::RewriteExprsRecursive;
22use crate::binder::{Binder, COLUMN_GROUP_PREFIX, Clause, Relation};
23use crate::error::{ErrorCode, Result};
24use crate::expr::{ExprImpl, ScopeId};
25
26#[derive(Debug, Clone)]
27pub struct BoundJoin {
28 pub join_type: JoinType,
29 pub left: Relation,
30 pub right: Relation,
31 pub cond: ExprImpl,
32 pub left_scope: ScopeId,
35}
36
37impl RewriteExprsRecursive for BoundJoin {
38 fn rewrite_exprs_recursive(&mut self, rewriter: &mut impl crate::expr::ExprRewriter) {
39 self.left.rewrite_exprs_recursive(rewriter);
40 self.right.rewrite_exprs_recursive(rewriter);
41 self.cond = rewriter.rewrite_expr(self.cond.take());
42 }
43}
44
45impl Binder {
46 pub(crate) fn bind_vec_table_with_joins(
47 &mut self,
48 from: &[TableWithJoins],
49 ) -> Result<Option<Relation>> {
50 let mut from_iter = from.iter();
51 let first = match from_iter.next() {
52 Some(t) => t,
53 None => return Ok(None),
54 };
55 self.push_lateral_context();
56 let mut root = self.bind_table_with_joins(first)?;
57 self.pop_and_merge_lateral_context()?;
58 for t in from_iter {
59 self.push_lateral_context();
60 let right = self.bind_table_with_joins(t)?;
61 self.pop_and_merge_lateral_context()?;
62
63 let left_scope = self.context.scope;
64 root = if Self::requires_apply(&right, left_scope) {
65 Relation::Apply(Box::new(BoundJoin {
66 join_type: JoinType::Inner,
67 left: root,
68 right,
69 cond: ExprImpl::literal_bool(true),
70 left_scope,
71 }))
72 } else {
73 Relation::Join(Box::new(BoundJoin {
74 join_type: JoinType::Inner,
75 left: root,
76 right,
77 cond: ExprImpl::literal_bool(true),
78 left_scope,
79 }))
80 }
81 }
82 Ok(Some(root))
83 }
84
85 fn requires_apply(relation: &Relation, left_scope: ScopeId) -> bool {
86 matches!(relation, Relation::Subquery(subquery) if subquery.lateral)
87 || matches!(relation, Relation::TableFunction { .. })
88 || relation.is_correlated_by_scope(left_scope)
89 }
90
91 pub(crate) fn bind_table_with_joins(&mut self, table: &TableWithJoins) -> Result<Relation> {
92 let mut root = self.bind_table_factor(&table.relation)?;
93 for join in &table.joins {
94 let (constraint, join_type) = match &join.join_operator {
95 JoinOperator::Inner(constraint) => (constraint, JoinType::Inner),
96 JoinOperator::LeftOuter(constraint) => (constraint, JoinType::LeftOuter),
97 JoinOperator::RightOuter(constraint) => (constraint, JoinType::RightOuter),
98 JoinOperator::FullOuter(constraint) => (constraint, JoinType::FullOuter),
99 JoinOperator::CrossJoin => (&JoinConstraint::None, JoinType::Inner),
101 JoinOperator::AsOfInner(constraint) => (constraint, JoinType::AsofInner),
102 JoinOperator::AsOfLeft(constraint) => (constraint, JoinType::AsofLeftOuter),
103 };
104 let right: Relation;
105 let cond: ExprImpl;
106 if matches!(
107 constraint.clone(),
108 JoinConstraint::Using(_) | JoinConstraint::Natural
109 ) {
110 let option_rel: Option<Relation>;
111 (cond, option_rel) =
112 self.bind_join_constraint(constraint, Some(&join.relation), join_type)?;
113 right = option_rel.unwrap();
114 } else {
115 right = self.bind_table_factor(&join.relation)?;
116 (cond, _) = self.bind_join_constraint(constraint, None, join_type)?;
117 }
118
119 let left_scope = self.context.scope;
120 root = if Self::requires_apply(&right, left_scope) {
121 match join_type {
122 JoinType::Inner | JoinType::LeftOuter => {}
123 _ => {
124 return Err(ErrorCode::InvalidInputSyntax("The combining JOIN type must be INNER or LEFT for a LATERAL reference.".to_owned())
125 .into());
126 }
127 }
128
129 Relation::Apply(Box::new(BoundJoin {
130 join_type,
131 left: root,
132 right,
133 cond,
134 left_scope,
135 }))
136 } else {
137 Relation::Join(Box::new(BoundJoin {
138 join_type,
139 left: root,
140 right,
141 cond,
142 left_scope,
143 }))
144 };
145 }
146
147 Ok(root)
148 }
149
150 fn bind_join_constraint(
151 &mut self,
152 constraint: &JoinConstraint,
153 table_factor: Option<&TableFactor>,
154 join_type: JoinType,
155 ) -> Result<(ExprImpl, Option<Relation>)> {
156 Ok(match constraint {
157 JoinConstraint::None => (ExprImpl::literal_bool(true), None),
158 c @ JoinConstraint::Natural | c @ JoinConstraint::Using(_) => {
159 let old_context = self.context.clone();
161 let l_len = old_context.columns.len();
162 self.push_lateral_context();
164 let table_factor = table_factor.unwrap();
165 let relation = self.bind_table_factor(table_factor)?;
166
167 let using_columns = match c {
168 JoinConstraint::Natural => None,
169 JoinConstraint::Using(cols) => {
170 for col in cols {
172 if !old_context.indices_of.contains_key(&col.real_value()) {
173 return Err(ErrorCode::ItemNotFound(format!("column \"{}\" specified in USING clause does not exist in left table", col.real_value())).into());
174 }
175 if !self.context.indices_of.contains_key(&col.real_value()) {
176 return Err(ErrorCode::ItemNotFound(format!("column \"{}\" specified in USING clause does not exist in right table", col.real_value())).into());
177 }
178 }
179 Some(cols)
180 }
181 _ => unreachable!(),
182 };
183
184 let mut columns = self
185 .context
186 .indices_of
187 .iter()
188 .filter(|(_, idxs)| idxs.iter().all(|i| !self.context.columns[*i].is_hidden))
189 .map(|(s, idxes)| (Ident::from_real_value(s), idxes))
190 .collect::<Vec<_>>();
191 columns.sort_by_key(|a| a.0.real_value());
192
193 let mut col_indices = Vec::new();
194 let mut binary_expr = Expr::Value(Value::Boolean(true));
195
196 for (column, indices_r) in columns {
198 if let Some(cols) = &using_columns
202 && !cols.contains(&column)
203 {
204 continue;
205 }
206 let indices_l = match old_context.get_unqualified_indices(&column.real_value())
207 {
208 Err(e) => {
209 if let ErrorCode::ItemNotFound(_) = e {
210 continue;
211 } else {
212 return Err(e.into());
213 }
214 }
215 Ok(idxs) => idxs,
216 };
217 col_indices.push((indices_l[0], indices_r[0] + l_len));
219 let left_expr = Self::get_identifier_from_indices(
220 &old_context,
221 &indices_l,
222 column.clone(),
223 )?;
224 let right_expr = Self::get_identifier_from_indices(
225 &self.context,
226 indices_r,
227 column.clone(),
228 )?;
229 binary_expr = Expr::BinaryOp {
230 left: Box::new(binary_expr),
231 op: BinaryOperator::And,
232 right: Box::new(Expr::BinaryOp {
233 left: Box::new(left_expr),
234 op: BinaryOperator::Eq,
235 right: Box::new(right_expr),
236 }),
237 }
238 }
239 self.pop_and_merge_lateral_context()?;
240 let expr = self.bind_expr(&binary_expr)?;
243 for (l, r) in col_indices {
244 let non_nullable = match join_type {
245 JoinType::LeftOuter | JoinType::Inner => Some(l),
246 JoinType::RightOuter => Some(r),
247 JoinType::FullOuter => None,
248 _ => unreachable!(),
249 };
250 self.context.add_natural_columns(l, r, non_nullable);
251 }
252 (expr, Some(relation))
253 }
254 JoinConstraint::On(expr) => {
255 let clause = self.context.clause;
256 self.context.clause = Some(Clause::JoinOn);
257 let bound_expr: ExprImpl = self
258 .bind_expr(expr)
259 .and_then(|expr| expr.enforce_bool_clause("JOIN ON"))?;
260 self.context.clause = clause;
261 (bound_expr, None)
262 }
263 })
264 }
265
266 fn get_identifier_from_indices(
267 context: &BindContext,
268 indices: &[usize],
269 column: Ident,
270 ) -> Result<Expr> {
271 if indices.len() == 1 {
272 let right_table = context.columns[indices[0]].table_name.as_ref();
273 Ok(Expr::CompoundIdentifier(vec![
274 Ident::from_real_value(right_table),
275 column,
276 ]))
277 } else if let Some(group_id) = context.column_group_context.mapping.get(&indices[0]) {
278 Ok(Expr::CompoundIdentifier(vec![
279 Ident::from_real_value(&format!("{COLUMN_GROUP_PREFIX}{}", group_id)),
280 column,
281 ]))
282 } else {
283 Err(
284 ErrorCode::InternalError(format!("Ambiguous column name: {}", column.real_value()))
285 .into(),
286 )
287 }
288 }
289}