1use super::*;
2
3impl<'host, H: SubqueryHost + ?Sized> SubqueryExecutor<'host, H> {
4 pub(super) fn convert_all_any_to_expression(
12 &self,
13 all_any: &AllAnyExpression,
14 values: Vec<radixdb_core::Value>,
15 ) -> Result<Expression> {
16 use radixdb_sql::ast::AllAnyType;
17
18 let op = all_any.operator.as_str();
19
20 if values.is_empty() {
22 return match all_any.all_any_type {
23 AllAnyType::All => {
24 Ok(Expression::BooleanLiteral(BooleanLiteral {
26 token: dummy_token("TRUE", TokenType::Keyword),
27 value: true,
28 }))
29 }
30 AllAnyType::Any => {
31 Ok(Expression::BooleanLiteral(BooleanLiteral {
33 token: dummy_token("FALSE", TokenType::Keyword),
34 value: false,
35 }))
36 }
37 };
38 }
39
40 let value_exprs: Vec<Expression> = values.iter().map(value_to_expression).collect();
42
43 if op == "=" && matches!(all_any.all_any_type, AllAnyType::Any) {
45 return Ok(Expression::In(InExpression {
46 token: all_any.token.clone(),
47 left: all_any.left.clone(),
48 right: Box::new(Expression::ExpressionList(Box::new(ExpressionList {
49 token: dummy_token("(", TokenType::Punctuator),
50 expressions: value_exprs,
51 }))),
52 not: false,
53 }));
54 }
55
56 if (op == "<>" || op == "!=") && matches!(all_any.all_any_type, AllAnyType::All) {
58 return Ok(Expression::In(InExpression {
59 token: all_any.token.clone(),
60 left: all_any.left.clone(),
61 right: Box::new(Expression::ExpressionList(Box::new(ExpressionList {
62 token: dummy_token("(", TokenType::Punctuator),
63 expressions: value_exprs,
64 }))),
65 not: true,
66 }));
67 }
68
69 let logical_op = match all_any.all_any_type {
72 AllAnyType::All => "AND",
73 AllAnyType::Any => "OR",
74 };
75
76 let mut result_expr: Option<Expression> = None;
78
79 for value_expr in value_exprs {
80 let comparison = Expression::Infix(InfixExpression::new(
81 all_any.token.clone(),
82 all_any.left.clone(),
83 op.to_string(),
84 Box::new(value_expr),
85 ));
86
87 result_expr = Some(match result_expr {
88 None => comparison,
89 Some(prev) => Expression::Infix(InfixExpression::new(
90 all_any.token.clone(),
91 Box::new(prev),
92 logical_op.to_string(),
93 Box::new(comparison),
94 )),
95 });
96 }
97
98 Ok(result_expr.unwrap_or_else(|| {
99 Expression::BooleanLiteral(BooleanLiteral {
100 token: dummy_token("TRUE", TokenType::Keyword),
101 value: true,
102 })
103 }))
104 }
105
106 pub(super) fn execute_scalar_subquery(
110 &self,
111 subquery: &SelectStatement,
112 ctx: &ExecutionContext,
113 ) -> Result<radixdb_core::Value> {
114 let is_non_correlated =
117 ctx.outer_row().is_none() && !Self::is_subquery_correlated(subquery);
118
119 let cache_key = if is_non_correlated {
121 let key = subquery.to_string();
122 if let Some(cached_value) = get_cached_scalar_subquery(&key) {
123 return Ok(cached_value);
124 }
125 Some(key)
126 } else {
127 None
128 };
129
130 if !is_non_correlated {
134 if let Some(value) = Self::try_lookup_batch_aggregate(subquery, ctx) {
136 return Ok(value);
137 }
138
139 if let Some(count) = self.try_execute_scalar_count_with_index(subquery, ctx)? {
141 return Ok(radixdb_core::Value::Integer(count));
142 }
143
144 if let Some(batch_cache) = self.try_execute_and_cache_batch_aggregate(subquery, ctx)? {
146 if let Some(value) = Self::try_lookup_batch_aggregate(subquery, ctx) {
147 return Ok(value);
148 }
149 if Self::is_count_expression(&subquery.columns[0]) {
150 return Ok(Value::Integer(0));
151 }
152 drop(batch_cache);
153 }
154 }
155
156 let subquery_ctx = ctx.with_incremented_query_depth();
158 let mut result = self.host.subquery_execute_select(subquery, &subquery_ctx)?;
159 if result.columns().len() != 1 {
160 return Err(Error::InvalidArgument(format!(
161 "scalar subquery must return exactly one column; got {}",
162 result.columns().len()
163 )));
164 }
165
166 if !result.next() {
168 if let Some(err) = result.last_error() {
170 return Err(err);
171 }
172 let null_value = radixdb_core::Value::null_unknown();
173 if let Some(key) = cache_key {
175 cache_scalar_subquery(
176 key,
177 extract_table_names_for_cache(subquery),
178 null_value.clone(),
179 );
180 }
181 return Ok(null_value);
182 }
183
184 let row = result.take_row();
185 let first_value = match row.take_first_value() {
187 Some(v) => v,
188 None => {
189 let null_value = radixdb_core::Value::null_unknown();
190 if let Some(key) = cache_key {
191 cache_scalar_subquery(
192 key,
193 extract_table_names_for_cache(subquery),
194 null_value.clone(),
195 );
196 }
197 return Ok(null_value);
198 }
199 };
200
201 if result.next() {
203 return Err(Error::Internal {
204 message: "scalar subquery returned more than one row".to_string(),
205 });
206 }
207 if let Some(err) = result.last_error() {
208 return Err(err);
209 }
210
211 if let Some(key) = cache_key {
213 cache_scalar_subquery(
214 key,
215 extract_table_names_for_cache(subquery),
216 first_value.clone(),
217 );
218 }
219
220 Ok(first_value)
221 }
222
223 pub(super) fn execute_in_subquery(
227 &self,
228 subquery: &SelectStatement,
229 ctx: &ExecutionContext,
230 ) -> Result<Vec<radixdb_core::Value>> {
231 let is_non_correlated =
234 ctx.outer_row().is_none() && !Self::is_subquery_correlated(subquery);
235
236 let cache_key = if is_non_correlated {
238 let key = subquery.to_string();
239 if let Some(cached_values) = get_cached_in_subquery(&key) {
240 return Ok(cached_values);
241 }
242 Some(key)
243 } else {
244 None
245 };
246
247 let subquery_ctx = ctx.with_incremented_query_depth();
249 let mut result = self.host.subquery_execute_select(subquery, &subquery_ctx)?;
250 if result.columns().len() != 1 {
251 return Err(Error::InvalidArgument(format!(
252 "IN/ANY/ALL subquery must return exactly one column; got {}",
253 result.columns().len()
254 )));
255 }
256
257 let mut values = Vec::new();
259 while result.next() {
260 let row = result.take_row();
261 if let Some(value) = row.take_first_value() {
263 values.push(value);
264 }
265 }
266 if let Some(err) = result.last_error() {
267 return Err(err);
268 }
269
270 if let Some(key) = cache_key {
272 cache_in_subquery(key, extract_table_names_for_cache(subquery), values.clone());
273 }
274
275 Ok(values)
276 }
277
278 pub(super) fn execute_in_subquery_rows(
280 &self,
281 subquery: &SelectStatement,
282 expected_width: usize,
283 ctx: &ExecutionContext,
284 ) -> Result<Vec<Vec<radixdb_core::Value>>> {
285 let subquery_ctx = ctx.with_incremented_query_depth();
287 let mut result = self.host.subquery_execute_select(subquery, &subquery_ctx)?;
288 if result.columns().len() != expected_width {
289 return Err(Error::InvalidArgument(format!(
290 "tuple IN width {} does not match subquery width {}",
291 expected_width,
292 result.columns().len()
293 )));
294 }
295
296 let mut rows = Vec::new();
298 while result.next() {
299 let row = result.take_row();
300 if !row.is_empty() {
301 rows.push(row.into_values());
303 }
304 }
305 if let Some(err) = result.last_error() {
306 return Err(err);
307 }
308
309 Ok(rows)
310 }
311
312 pub(super) fn has_subqueries(expr: &Expression) -> bool {
314 let mut found = false;
315 radixdb_sql::ast::walk_expression_tree(expr, &mut |expression| {
316 found |= matches!(
317 expression,
318 Expression::Exists(_) | Expression::ScalarSubquery(_) | Expression::AllAny(_)
319 );
320 });
321 found
322 }
323
324 pub(super) fn try_process_select_subqueries(
332 &self,
333 columns: &[Expression],
334 ctx: &ExecutionContext,
335 ) -> Result<Option<Vec<Expression>>> {
336 let mut result: Option<Vec<Expression>> = None;
337
338 for (i, col) in columns.iter().enumerate() {
339 if let Some(processed) = self.try_process_expression_subqueries(col, ctx)? {
340 let vec = result.get_or_insert_with(|| columns[..i].to_vec());
342 vec.push(processed);
343 } else if let Some(ref mut vec) = result {
344 vec.push(col.clone());
346 }
347 }
349
350 Ok(result)
351 }
352
353 pub(super) fn try_process_expression_subqueries(
358 &self,
359 expr: &Expression,
360 ctx: &ExecutionContext,
361 ) -> Result<Option<Expression>> {
362 if Self::has_subqueries(expr) {
363 return Ok(Some(self.process_where_subqueries(expr, ctx)?));
364 }
365 match expr {
366 Expression::ScalarSubquery(subquery) => {
367 let value = self.execute_scalar_subquery(&subquery.subquery, ctx)?;
369 Ok(Some(value_to_expression(&value)))
370 }
371
372 Expression::Exists(exists) => {
373 let exists_result = self.execute_exists_subquery(&exists.subquery, ctx)?;
375 Ok(Some(Expression::BooleanLiteral(BooleanLiteral {
376 token: dummy_token(
377 if exists_result { "TRUE" } else { "FALSE" },
378 TokenType::Keyword,
379 ),
380 value: exists_result,
381 })))
382 }
383
384 Expression::Aliased(aliased) => {
385 if let Some(processed) =
387 self.try_process_expression_subqueries(&aliased.expression, ctx)?
388 {
389 Ok(Some(Expression::Aliased(AliasedExpression {
390 token: aliased.token.clone(),
391 expression: Box::new(processed),
392 alias: aliased.alias.clone(),
393 })))
394 } else {
395 Ok(None)
396 }
397 }
398
399 Expression::Infix(infix) => {
400 let left = self.try_process_expression_subqueries(&infix.left, ctx)?;
402 let right = self.try_process_expression_subqueries(&infix.right, ctx)?;
403
404 if left.is_some() || right.is_some() {
405 Ok(Some(Expression::Infix(InfixExpression {
406 token: infix.token.clone(),
407 left: Box::new(left.unwrap_or_else(|| (*infix.left).clone())),
408 operator: infix.operator.clone(),
409 op_type: infix.op_type,
410 right: Box::new(right.unwrap_or_else(|| (*infix.right).clone())),
411 })))
412 } else {
413 Ok(None)
414 }
415 }
416
417 Expression::Prefix(prefix) => {
418 if let Some(processed) =
419 self.try_process_expression_subqueries(&prefix.right, ctx)?
420 {
421 Ok(Some(Expression::Prefix(PrefixExpression {
422 token: prefix.token.clone(),
423 operator: prefix.operator.clone(),
424 op_type: prefix.op_type,
425 right: Box::new(processed),
426 })))
427 } else {
428 Ok(None)
429 }
430 }
431
432 Expression::FunctionCall(func) => {
433 let mut any_changed = false;
435 let mut processed_args: Vec<Option<Expression>> =
436 Vec::with_capacity(func.arguments.len());
437
438 for arg in &func.arguments {
439 let processed = self.try_process_expression_subqueries(arg, ctx)?;
440 if processed.is_some() {
441 any_changed = true;
442 }
443 processed_args.push(processed);
444 }
445
446 if any_changed {
447 let final_args: Vec<Expression> = func
448 .arguments
449 .iter()
450 .zip(processed_args)
451 .map(|(orig, processed)| processed.unwrap_or_else(|| orig.clone()))
452 .collect();
453
454 Ok(Some(Expression::FunctionCall(Box::new(FunctionCall {
455 token: func.token.clone(),
456 function: func.function.clone(),
457 arguments: final_args,
458 is_distinct: func.is_distinct,
459 order_by: func.order_by.clone(),
460 filter: func.filter.clone(),
461 }))))
462 } else {
463 Ok(None)
464 }
465 }
466
467 Expression::Case(case) => {
468 let mut any_changed = false;
470
471 let processed_value = if let Some(ref value) = case.value {
473 let processed = self.try_process_expression_subqueries(value, ctx)?;
474 if processed.is_some() {
475 any_changed = true;
476 }
477 processed.map(Box::new)
478 } else {
479 None
480 };
481
482 let mut processed_whens: Vec<(Option<Expression>, Option<Expression>)> =
484 Vec::with_capacity(case.when_clauses.len());
485 for when in &case.when_clauses {
486 let cond = self.try_process_expression_subqueries(&when.condition, ctx)?;
487 let then = self.try_process_expression_subqueries(&when.then_result, ctx)?;
488 if cond.is_some() || then.is_some() {
489 any_changed = true;
490 }
491 processed_whens.push((cond, then));
492 }
493
494 let processed_else = if let Some(ref else_val) = case.else_value {
496 let processed = self.try_process_expression_subqueries(else_val, ctx)?;
497 if processed.is_some() {
498 any_changed = true;
499 }
500 processed.map(Box::new)
501 } else {
502 None
503 };
504
505 if any_changed {
506 let final_whens: Vec<WhenClause> = case
507 .when_clauses
508 .iter()
509 .zip(processed_whens)
510 .map(|(orig, (cond, then))| WhenClause {
511 token: orig.token.clone(),
512 condition: cond.unwrap_or_else(|| orig.condition.clone()),
513 then_result: then.unwrap_or_else(|| orig.then_result.clone()),
514 })
515 .collect();
516
517 Ok(Some(Expression::Case(Box::new(CaseExpression {
518 token: case.token.clone(),
519 value: processed_value.or_else(|| case.value.clone()),
520 when_clauses: final_whens,
521 else_value: processed_else.or_else(|| case.else_value.clone()),
522 }))))
523 } else {
524 Ok(None)
525 }
526 }
527
528 Expression::Cast(cast) => {
529 if let Some(processed) = self.try_process_expression_subqueries(&cast.expr, ctx)? {
531 Ok(Some(Expression::Cast(CastExpression {
532 token: cast.token.clone(),
533 expr: Box::new(processed),
534 type_name: cast.type_name.clone(),
535 })))
536 } else {
537 Ok(None)
538 }
539 }
540
541 Expression::AllAny(all_any) => {
542 let values = self.execute_in_subquery(&all_any.subquery, ctx)?;
544
545 Ok(Some(self.convert_all_any_to_expression(all_any, values)?))
547 }
548
549 _ => Ok(None),
551 }
552 }
553
554 pub(super) fn has_correlated_subqueries(expr: &Expression) -> bool {
562 let mut correlated = false;
563 radixdb_sql::ast::walk_expression_tree(expr, &mut |expression| {
564 if correlated {
565 return;
566 }
567 correlated = match expression {
568 Expression::Exists(exists) => Self::is_subquery_correlated(&exists.subquery),
569 Expression::ScalarSubquery(subquery) => {
570 Self::is_subquery_correlated(&subquery.subquery)
571 }
572 Expression::AllAny(all_any) => Self::is_subquery_correlated(&all_any.subquery),
573 _ => false,
574 };
575 });
576 correlated
577 }
578
579 pub(super) fn has_correlated_select_subqueries(columns: &[Expression]) -> bool {
581 columns.iter().any(Self::has_correlated_subqueries)
582 }
583
584 pub(super) fn process_correlated_expression(
587 &self,
588 expr: &Expression,
589 ctx: &ExecutionContext,
590 ) -> Result<Expression> {
591 if Self::has_subqueries(expr) {
592 return self.process_where_subqueries(expr, ctx);
593 }
594 match expr {
595 Expression::ScalarSubquery(subquery) => {
596 let value = self.execute_scalar_subquery(&subquery.subquery, ctx)?;
598 Ok(value_to_expression(&value))
599 }
600
601 Expression::Exists(exists) => {
602 let exists_result = self.execute_exists_subquery(&exists.subquery, ctx)?;
604 Ok(Expression::BooleanLiteral(BooleanLiteral {
605 token: dummy_token(
606 if exists_result { "TRUE" } else { "FALSE" },
607 TokenType::Keyword,
608 ),
609 value: exists_result,
610 }))
611 }
612
613 Expression::Aliased(aliased) => {
614 let processed = self.process_correlated_expression(&aliased.expression, ctx)?;
615 Ok(Expression::Aliased(AliasedExpression {
616 token: aliased.token.clone(),
617 expression: Box::new(processed),
618 alias: aliased.alias.clone(),
619 }))
620 }
621
622 Expression::Infix(infix) => {
623 let left = self.process_correlated_expression(&infix.left, ctx)?;
624 let right = self.process_correlated_expression(&infix.right, ctx)?;
625 Ok(Expression::Infix(InfixExpression {
626 token: infix.token.clone(),
627 left: Box::new(left),
628 operator: infix.operator.clone(),
629 op_type: infix.op_type,
630 right: Box::new(right),
631 }))
632 }
633
634 Expression::Prefix(prefix) => {
635 let right = self.process_correlated_expression(&prefix.right, ctx)?;
636 Ok(Expression::Prefix(PrefixExpression {
637 token: prefix.token.clone(),
638 operator: prefix.operator.clone(),
639 op_type: prefix.op_type,
640 right: Box::new(right),
641 }))
642 }
643
644 Expression::FunctionCall(func) => {
645 let processed_args: Result<Vec<Expression>> = func
646 .arguments
647 .iter()
648 .map(|arg| self.process_correlated_expression(arg, ctx))
649 .collect();
650
651 Ok(Expression::FunctionCall(Box::new(FunctionCall {
652 token: func.token.clone(),
653 function: func.function.clone(),
654 arguments: processed_args?,
655 is_distinct: func.is_distinct,
656 order_by: func.order_by.clone(),
657 filter: func.filter.clone(),
658 })))
659 }
660
661 Expression::In(in_expr) => {
662 let processed_left = self.process_correlated_expression(&in_expr.left, ctx)?;
663
664 if let Expression::ScalarSubquery(subquery) = in_expr.right.as_ref() {
665 let values = self.execute_in_subquery(&subquery.subquery, ctx)?;
667 let hash_set: ValueSet = values.into_iter().collect();
668
669 return Ok(Expression::InHashSet(InHashSetExpression {
670 token: in_expr.token.clone(),
671 column: Box::new(processed_left),
672 values: CompactArc::new(hash_set),
673 not: in_expr.not,
674 }));
675 }
676
677 let processed_right = self.process_correlated_expression(&in_expr.right, ctx)?;
678 Ok(Expression::In(InExpression {
679 token: in_expr.token.clone(),
680 left: Box::new(processed_left),
681 right: Box::new(processed_right),
682 not: in_expr.not,
683 }))
684 }
685
686 Expression::Between(between) => {
687 let processed_expr = self.process_correlated_expression(&between.expr, ctx)?;
688 let processed_lower = self.process_correlated_expression(&between.lower, ctx)?;
689 let processed_upper = self.process_correlated_expression(&between.upper, ctx)?;
690
691 Ok(Expression::Between(BetweenExpression {
692 token: between.token.clone(),
693 expr: Box::new(processed_expr),
694 not: between.not,
695 lower: Box::new(processed_lower),
696 upper: Box::new(processed_upper),
697 }))
698 }
699
700 Expression::Case(case) => {
701 let processed_value = if let Some(ref value) = case.value {
702 Some(Box::new(self.process_correlated_expression(value, ctx)?))
703 } else {
704 None
705 };
706
707 let processed_whens: Result<Vec<WhenClause>> = case
708 .when_clauses
709 .iter()
710 .map(|when| {
711 Ok(WhenClause {
712 token: when.token.clone(),
713 condition: self.process_correlated_expression(&when.condition, ctx)?,
714 then_result: self
715 .process_correlated_expression(&when.then_result, ctx)?,
716 })
717 })
718 .collect();
719
720 let processed_else = if let Some(ref else_val) = case.else_value {
721 Some(Box::new(self.process_correlated_expression(else_val, ctx)?))
722 } else {
723 None
724 };
725
726 Ok(Expression::Case(Box::new(CaseExpression {
727 token: case.token.clone(),
728 value: processed_value,
729 when_clauses: processed_whens?,
730 else_value: processed_else,
731 })))
732 }
733
734 Expression::Cast(cast) => {
735 let processed_expr = self.process_correlated_expression(&cast.expr, ctx)?;
736 Ok(Expression::Cast(CastExpression {
737 token: cast.token.clone(),
738 expr: Box::new(processed_expr),
739 type_name: cast.type_name.clone(),
740 }))
741 }
742
743 _ => Ok(expr.clone()),
745 }
746 }
747
748 pub(super) fn is_subquery_correlated(subquery: &SelectStatement) -> bool {
750 let subquery_tables = Self::collect_subquery_table_columns(subquery);
752 let mut correlated = false;
753 radixdb_sql::ast::walk_select_tree(subquery, &mut |expression| {
754 if correlated {
755 return;
756 }
757 match expression {
758 Expression::QualifiedIdentifier(qid) => {
759 correlated = !subquery_tables
760 .iter()
761 .any(|table| table.eq_ignore_ascii_case(&qid.qualifier.value_lower));
762 }
763 Expression::Identifier(_) => correlated = true,
767 _ => {}
768 }
769 });
770 correlated
771 }
772
773 pub(super) fn collect_subquery_table_columns(subquery: &SelectStatement) -> Vec<String> {
775 let mut tables = Vec::new();
776
777 if let Some(ref table_expr) = subquery.table_expr {
778 Self::collect_table_names_from_source(table_expr, &mut tables);
779 }
780
781 tables
782 }
783
784 pub(super) fn collect_table_names_from_source(source: &Expression, tables: &mut Vec<String>) {
786 match source {
787 Expression::TableSource(ts) => {
788 if let Some(ref alias) = ts.alias {
792 tables.push(alias.value_lower.to_string());
793 } else {
794 tables.push(ts.name.value_lower.to_string());
795 }
796 }
797 Expression::JoinSource(js) => {
798 Self::collect_table_names_from_source(&js.left, tables);
799 Self::collect_table_names_from_source(&js.right, tables);
800 }
801 Expression::SubquerySource(ss) => {
802 if let Some(ref alias) = ss.alias {
804 tables.push(alias.value_lower.to_string());
805 }
806 }
807 Expression::FunctionTableSource(fs) => {
808 if let Some(ref alias) = fs.alias {
809 tables.push(alias.value_lower.to_string());
810 } else {
811 tables.push(fs.function.value_lower.to_string());
812 }
813 }
814 _ => {}
815 }
816 }
817
818 #[allow(dead_code)]
828 pub(super) fn references_outer_columns(expr: &Expression, subquery_tables: &[String]) -> bool {
829 match expr {
830 Expression::Identifier(_id) => {
831 false
836 }
837 Expression::QualifiedIdentifier(qid) => {
838 let table_name = &qid.qualifier.value_lower;
840
841 !subquery_tables
844 .iter()
845 .any(|t| t.eq_ignore_ascii_case(table_name))
846 }
847 Expression::Infix(infix) => {
848 Self::references_outer_columns(&infix.left, subquery_tables)
849 || Self::references_outer_columns(&infix.right, subquery_tables)
850 }
851 Expression::Prefix(prefix) => {
852 Self::references_outer_columns(&prefix.right, subquery_tables)
853 }
854 Expression::FunctionCall(func) => func
855 .arguments
856 .iter()
857 .any(|arg| Self::references_outer_columns(arg, subquery_tables)),
858 Expression::In(in_expr) => {
859 Self::references_outer_columns(&in_expr.left, subquery_tables)
860 || Self::references_outer_columns(&in_expr.right, subquery_tables)
861 }
862 Expression::Between(between) => {
863 Self::references_outer_columns(&between.expr, subquery_tables)
864 || Self::references_outer_columns(&between.lower, subquery_tables)
865 || Self::references_outer_columns(&between.upper, subquery_tables)
866 }
867 Expression::Case(case) => {
868 if let Some(ref value) = case.value {
869 if Self::references_outer_columns(value, subquery_tables) {
870 return true;
871 }
872 }
873 for when in &case.when_clauses {
874 if Self::references_outer_columns(&when.condition, subquery_tables)
875 || Self::references_outer_columns(&when.then_result, subquery_tables)
876 {
877 return true;
878 }
879 }
880 if let Some(ref else_val) = case.else_value {
881 if Self::references_outer_columns(else_val, subquery_tables) {
882 return true;
883 }
884 }
885 false
886 }
887 Expression::Aliased(aliased) => {
888 Self::references_outer_columns(&aliased.expression, subquery_tables)
889 }
890 Expression::Cast(cast) => Self::references_outer_columns(&cast.expr, subquery_tables),
891 _ => false,
892 }
893 }
894
895 pub(super) fn process_correlated_where(
898 &self,
899 expr: &Expression,
900 ctx: &ExecutionContext,
901 ) -> Result<Expression> {
902 self.process_where_subqueries(expr, ctx)
907 }
908
909 pub fn try_extract_semi_join_info(
922 exists: &ExistsExpression,
923 is_negated: bool,
924 outer_tables: &[String],
925 ) -> Option<SemiJoinInfo> {
926 let subquery = &exists.subquery;
927
928 let (inner_table, inner_alias): (String, Option<String>) =
930 match subquery.table_expr.as_ref().map(|b| b.as_ref()) {
931 Some(Expression::TableSource(ts)) => {
932 let alias = ts.alias.as_ref().map(|a| a.value.to_string());
933 (ts.name.value.to_string(), alias)
934 }
935 _ => return None, };
937
938 let where_clause = subquery.where_clause.as_ref()?;
940
941 let inner_table_lower: String = inner_alias
943 .clone()
944 .unwrap_or_else(|| inner_table.to_lowercase());
945 let inner_tables = vec![inner_table_lower.to_lowercase()];
946
947 let extraction =
949 Self::extract_equality_correlation(where_clause, outer_tables, &inner_tables);
950 let (outer_col, outer_tbl, inner_col, remaining) = extraction?;
951
952 if let Some(ref rem) = remaining {
958 if Self::expression_references_outer_tables(rem.as_ref(), outer_tables, &inner_tables) {
959 return None;
960 }
961 convert_ast_to_storage_expr(rem.as_ref())?;
962 }
963
964 Some(SemiJoinInfo {
965 outer_column: outer_col,
966 outer_table: outer_tbl,
967 inner_column: inner_col,
968 inner_table,
969 inner_alias,
970 non_correlated_where: remaining,
971 is_negated,
972 })
973 }
974
975 pub(super) fn extract_equality_correlation(
984 expr: &Expression,
985 outer_tables: &[String],
986 inner_tables: &[String],
987 ) -> Option<CorrelationExtraction> {
988 match expr {
989 Expression::Infix(infix) if infix.operator == "=" => Self::try_extract_equality_pair(
991 &infix.left,
992 &infix.right,
993 outer_tables,
994 inner_tables,
995 )
996 .map(|(outer_col, outer_tbl, inner_col)| (outer_col, outer_tbl, inner_col, None)),
997
998 Expression::Infix(infix) if infix.operator.eq_ignore_ascii_case("AND") => {
1000 if let Some((outer_col, outer_tbl, inner_col, left_remaining)) =
1002 Self::extract_equality_correlation(&infix.left, outer_tables, inner_tables)
1003 {
1004 let remaining = Self::combine_and_predicates_arc(left_remaining, &infix.right);
1006 return Some((outer_col, outer_tbl, inner_col, remaining));
1007 }
1008
1009 if let Some((outer_col, outer_tbl, inner_col, right_remaining)) =
1011 Self::extract_equality_correlation(&infix.right, outer_tables, inner_tables)
1012 {
1013 let remaining = Self::combine_and_predicates_arc(right_remaining, &infix.left);
1015 return Some((outer_col, outer_tbl, inner_col, remaining));
1016 }
1017
1018 None
1019 }
1020
1021 _ => None,
1022 }
1023 }
1024
1025 pub(super) fn try_extract_equality_pair(
1028 left: &Expression,
1029 right: &Expression,
1030 outer_tables: &[String],
1031 inner_tables: &[String],
1032 ) -> Option<(String, Option<String>, String)> {
1033 if let (Some((outer_col, outer_tbl)), Some(inner_col)) = (
1035 Self::extract_outer_column(left, outer_tables, inner_tables),
1036 Self::extract_inner_column(right, inner_tables),
1037 ) {
1038 return Some((outer_col, outer_tbl, inner_col));
1039 }
1040
1041 if let (Some(inner_col), Some((outer_col, outer_tbl))) = (
1043 Self::extract_inner_column(left, inner_tables),
1044 Self::extract_outer_column(right, outer_tables, inner_tables),
1045 ) {
1046 return Some((outer_col, outer_tbl, inner_col));
1047 }
1048
1049 None
1050 }
1051
1052 pub(super) fn extract_outer_column(
1055 expr: &Expression,
1056 outer_tables: &[String],
1057 inner_tables: &[String],
1058 ) -> Option<(String, Option<String>)> {
1059 match expr {
1060 Expression::QualifiedIdentifier(qid) => {
1061 let table = qid.qualifier.value_lower.as_str();
1063 if outer_tables.iter().any(|t| t.eq_ignore_ascii_case(table))
1065 && !inner_tables.iter().any(|t| t.eq_ignore_ascii_case(table))
1066 {
1067 Some((
1068 qid.name.value.to_string(),
1069 Some(qid.qualifier.value.to_string()),
1070 ))
1071 } else {
1072 None
1073 }
1074 }
1075 _ => None,
1078 }
1079 }
1080
1081 pub(super) fn extract_inner_column(
1083 expr: &Expression,
1084 inner_tables: &[String],
1085 ) -> Option<String> {
1086 match expr {
1087 Expression::QualifiedIdentifier(qid) => {
1088 let table = qid.qualifier.value_lower.as_str();
1090 if inner_tables.iter().any(|t| t.eq_ignore_ascii_case(table)) {
1091 Some(qid.name.value.to_string())
1092 } else {
1093 None
1094 }
1095 }
1096 Expression::Identifier(id) => {
1097 Some(id.value.to_string())
1100 }
1101 _ => None,
1102 }
1103 }
1104
1105 pub(super) fn expression_references_outer_tables(
1108 expr: &Expression,
1109 outer_tables: &[String],
1110 inner_tables: &[String],
1111 ) -> bool {
1112 match expr {
1113 Expression::QualifiedIdentifier(qid) => {
1114 let table = &qid.qualifier.value_lower;
1116 outer_tables.iter().any(|t| t.eq_ignore_ascii_case(table))
1118 && !inner_tables.iter().any(|t| t.eq_ignore_ascii_case(table))
1119 }
1120 Expression::Infix(infix) => {
1121 Self::expression_references_outer_tables(&infix.left, outer_tables, inner_tables)
1122 || Self::expression_references_outer_tables(
1123 &infix.right,
1124 outer_tables,
1125 inner_tables,
1126 )
1127 }
1128 Expression::Prefix(prefix) => {
1129 Self::expression_references_outer_tables(&prefix.right, outer_tables, inner_tables)
1130 }
1131 Expression::FunctionCall(func) => func.arguments.iter().any(|arg| {
1132 Self::expression_references_outer_tables(arg, outer_tables, inner_tables)
1133 }),
1134 Expression::In(in_expr) => {
1135 Self::expression_references_outer_tables(&in_expr.left, outer_tables, inner_tables)
1136 || Self::expression_references_outer_tables(
1137 &in_expr.right,
1138 outer_tables,
1139 inner_tables,
1140 )
1141 }
1142 Expression::Between(between) => {
1143 Self::expression_references_outer_tables(&between.expr, outer_tables, inner_tables)
1144 || Self::expression_references_outer_tables(
1145 &between.lower,
1146 outer_tables,
1147 inner_tables,
1148 )
1149 || Self::expression_references_outer_tables(
1150 &between.upper,
1151 outer_tables,
1152 inner_tables,
1153 )
1154 }
1155 Expression::Case(case) => {
1156 case.value.as_ref().is_some_and(|op| {
1157 Self::expression_references_outer_tables(
1158 op.as_ref(),
1159 outer_tables,
1160 inner_tables,
1161 )
1162 }) || case.when_clauses.iter().any(|wc| {
1163 Self::expression_references_outer_tables(
1164 &wc.condition,
1165 outer_tables,
1166 inner_tables,
1167 ) || Self::expression_references_outer_tables(
1168 &wc.then_result,
1169 outer_tables,
1170 inner_tables,
1171 )
1172 }) || case.else_value.as_ref().is_some_and(|el| {
1173 Self::expression_references_outer_tables(
1174 el.as_ref(),
1175 outer_tables,
1176 inner_tables,
1177 )
1178 })
1179 }
1180 Expression::Exists(exists) => {
1185 Self::subquery_references_outer_tables(&exists.subquery, outer_tables, inner_tables)
1186 }
1187 Expression::ScalarSubquery(sq) => {
1188 Self::subquery_references_outer_tables(&sq.subquery, outer_tables, inner_tables)
1189 }
1190 Expression::AllAny(aa) => {
1191 Self::subquery_references_outer_tables(&aa.subquery, outer_tables, inner_tables)
1192 }
1193 _ => false,
1195 }
1196 }
1197
1198 pub(super) fn subquery_references_outer_tables(
1202 subquery: &SelectStatement,
1203 outer_tables: &[String],
1204 inner_tables: &[String],
1205 ) -> bool {
1206 if let Some(ref where_clause) = subquery.where_clause {
1207 let mut sub_tables: Vec<String> = inner_tables.to_vec();
1209 Self::collect_table_names_from_source_if_present(&subquery.table_expr, &mut sub_tables);
1210 if Self::expression_references_outer_tables(where_clause, outer_tables, &sub_tables) {
1212 return true;
1213 }
1214 }
1215 false
1216 }
1217
1218 pub(super) fn collect_table_names_from_source_if_present(
1220 table_expr: &Option<Box<Expression>>,
1221 tables: &mut Vec<String>,
1222 ) {
1223 if let Some(ref expr) = table_expr {
1224 Self::collect_table_names_from_source(expr.as_ref(), tables);
1225 }
1226 }
1227
1228 pub(super) fn combine_and_predicates_arc(
1231 left: Option<Arc<Expression>>,
1232 right: &Expression,
1233 ) -> Option<Arc<Expression>> {
1234 match left {
1235 None => Some(Arc::new(right.clone())),
1236 Some(l) => {
1237 let left_expr = Arc::try_unwrap(l).unwrap_or_else(|arc| (*arc).clone());
1239 Some(Arc::new(Expression::Infix(InfixExpression {
1240 token: dummy_token_clone(),
1241 left: Box::new(left_expr),
1242 operator: "AND".into(),
1243 op_type: InfixOperator::And,
1244 right: Box::new(right.clone()),
1245 })))
1246 }
1247 }
1248 }
1249}