risingwave_frontend/expr/
expr_visitor.rsuse risingwave_common::util::recursive::{tracker, Recurse};
use super::{
AggCall, CorrelatedInputRef, ExprImpl, FunctionCall, FunctionCallWithLambda, InputRef, Literal,
Now, Parameter, Subquery, TableFunction, UserDefinedFunction, WindowFunction,
EXPR_DEPTH_THRESHOLD, EXPR_TOO_DEEP_NOTICE,
};
use crate::session::current::notice_to_user;
pub fn default_visit_expr<V: ExprVisitor + ?Sized>(visitor: &mut V, expr: &ExprImpl) {
tracker!().recurse(|t| {
if t.depth_reaches(EXPR_DEPTH_THRESHOLD) {
notice_to_user(EXPR_TOO_DEEP_NOTICE);
}
match expr {
ExprImpl::InputRef(inner) => visitor.visit_input_ref(inner),
ExprImpl::Literal(inner) => visitor.visit_literal(inner),
ExprImpl::FunctionCall(inner) => visitor.visit_function_call(inner),
ExprImpl::FunctionCallWithLambda(inner) => {
visitor.visit_function_call_with_lambda(inner)
}
ExprImpl::AggCall(inner) => visitor.visit_agg_call(inner),
ExprImpl::Subquery(inner) => visitor.visit_subquery(inner),
ExprImpl::CorrelatedInputRef(inner) => visitor.visit_correlated_input_ref(inner),
ExprImpl::TableFunction(inner) => visitor.visit_table_function(inner),
ExprImpl::WindowFunction(inner) => visitor.visit_window_function(inner),
ExprImpl::UserDefinedFunction(inner) => visitor.visit_user_defined_function(inner),
ExprImpl::Parameter(inner) => visitor.visit_parameter(inner),
ExprImpl::Now(inner) => visitor.visit_now(inner),
}
})
}
pub trait ExprVisitor {
fn visit_expr(&mut self, expr: &ExprImpl) {
default_visit_expr(self, expr)
}
fn visit_function_call(&mut self, func_call: &FunctionCall) {
func_call
.inputs()
.iter()
.for_each(|expr| self.visit_expr(expr));
}
fn visit_function_call_with_lambda(&mut self, func_call: &FunctionCallWithLambda) {
self.visit_function_call(func_call.base())
}
fn visit_agg_call(&mut self, agg_call: &AggCall) {
agg_call
.args()
.iter()
.for_each(|expr| self.visit_expr(expr));
agg_call.order_by().visit_expr(self);
agg_call.filter().visit_expr(self);
}
fn visit_parameter(&mut self, _: &Parameter) {}
fn visit_literal(&mut self, _: &Literal) {}
fn visit_input_ref(&mut self, _: &InputRef) {}
fn visit_subquery(&mut self, _: &Subquery) {}
fn visit_correlated_input_ref(&mut self, _: &CorrelatedInputRef) {}
fn visit_table_function(&mut self, func_call: &TableFunction) {
func_call.args.iter().for_each(|expr| self.visit_expr(expr));
}
fn visit_window_function(&mut self, func_call: &WindowFunction) {
func_call.args.iter().for_each(|expr| self.visit_expr(expr));
}
fn visit_user_defined_function(&mut self, func_call: &UserDefinedFunction) {
func_call.args.iter().for_each(|expr| self.visit_expr(expr));
}
fn visit_now(&mut self, _: &Now) {}
}