Skip to content

Commit 1f06d8a

Browse files
authored
refactor(query): rewrite function call expr to cast expr (#17669)
* rewrite_function_to_cast * test * update * fmt_with_options * fix * check_function score * x * Revert "x" This reverts commit 507642037d9a20df2e2a098534090b1e0f33829a. * cast_scalar * num string Signed-off-by: coldWater <[email protected]> * update Signed-off-by: coldWater <[email protected]> * fix Signed-off-by: coldWater <[email protected]> * fix Signed-off-by: coldWater <[email protected]> * fix Signed-off-by: coldWater <[email protected]> * fix Signed-off-by: coldWater <[email protected]> * fix * x * fix * rewrite * bloom * expr size * fix * fix --------- Signed-off-by: coldWater <[email protected]>
1 parent b7e71a5 commit 1f06d8a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+19113
-2176
lines changed

src/query/expression/src/expression.rs

Lines changed: 279 additions & 115 deletions
Large diffs are not rendered by default.

src/query/expression/src/filter/select_expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl SelectExprBuilder {
137137
.can_reorder(can_reorder)
138138
}
139139
"not" => {
140-
self.not_function = Some((id.clone(), function.clone()));
140+
self.not_function = Some((*id.clone(), function.clone()));
141141
let result = self.build_select_expr(&args[0], not ^ true);
142142
if result.can_push_down_not {
143143
result
@@ -255,7 +255,7 @@ impl SelectExprBuilder {
255255
let (id, function) = self.not_function.as_ref().unwrap();
256256
Expr::FunctionCall {
257257
span: None,
258-
id: id.clone(),
258+
id: Box::new(id.clone()),
259259
function: function.clone(),
260260
generics: vec![],
261261
args: vec![expr.clone()],

src/query/expression/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#![feature(trait_upcasting)]
4343
#![feature(alloc_layout_extra)]
4444
#![feature(debug_closure_helpers)]
45+
#![feature(never_type)]
4546

4647
#[allow(dead_code)]
4748
mod block;

src/query/expression/src/type_check.rs

Lines changed: 114 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15+
use std::borrow::Cow;
1516
use std::collections::HashMap;
1617
use std::fmt::Write;
1718

@@ -31,10 +32,11 @@ use crate::types::decimal::MAX_DECIMAL256_PRECISION;
3132
use crate::types::DataType;
3233
use crate::types::DecimalDataType;
3334
use crate::types::Number;
34-
use crate::types::NumberScalar;
35+
use crate::visit_expr;
3536
use crate::AutoCastRules;
3637
use crate::ColumnIndex;
3738
use crate::ConstantFolder;
39+
use crate::ExprVisitor;
3840
use crate::FunctionContext;
3941
use crate::Scalar;
4042

@@ -150,7 +152,7 @@ pub fn check_cast<Index: ColumnIndex>(
150152
is_try: bool,
151153
expr: Expr<Index>,
152154
dest_type: &DataType,
153-
fn_registry: &FunctionRegistry,
155+
_: &FunctionRegistry,
154156
) -> Result<Expr<Index>> {
155157
let wrapped_dest_type = if is_try {
156158
wrap_nullable_for_try_cast(span, dest_type)?
@@ -168,26 +170,6 @@ pub fn check_cast<Index: ColumnIndex>(
168170
dest_type: wrapped_dest_type,
169171
})
170172
} else {
171-
// fast path to eval function for cast
172-
if let Some(cast_fn) = get_simple_cast_function(is_try, expr.data_type(), dest_type) {
173-
let params = if let DataType::Decimal(ty) = dest_type {
174-
vec![
175-
Scalar::Number(NumberScalar::Int64(ty.precision() as _)),
176-
Scalar::Number(NumberScalar::Int64(ty.scale() as _)),
177-
]
178-
} else {
179-
vec![]
180-
};
181-
182-
if let Ok(cast_expr) =
183-
check_function(span, &cast_fn, &params, &[expr.clone()], fn_registry)
184-
{
185-
if cast_expr.data_type() == &wrapped_dest_type {
186-
return Ok(cast_expr);
187-
}
188-
}
189-
}
190-
191173
if !can_cast_to(expr.data_type(), dest_type) {
192174
return Err(ErrorCode::BadArguments(format!(
193175
"unable to cast type `{}` to type `{}`",
@@ -301,7 +283,7 @@ pub fn check_function<Index: ColumnIndex>(
301283
let return_type = function.signature.return_type.clone();
302284
return Ok(Expr::FunctionCall {
303285
span,
304-
id,
286+
id: Box::new(id),
305287
function,
306288
generics: vec![],
307289
args: args.to_vec(),
@@ -312,22 +294,52 @@ pub fn check_function<Index: ColumnIndex>(
312294
let auto_cast_rules = fn_registry.get_auto_cast_rules(name);
313295

314296
let mut fail_reasons = Vec::with_capacity(candidates.len());
315-
for (id, func) in &candidates {
297+
let mut checked_candidates = vec![];
298+
let args_not_const = args
299+
.iter()
300+
.map(Expr::contains_column_ref)
301+
.collect::<Vec<_>>();
302+
let need_sort = candidates.len() > 1 && args_not_const.iter().any(|contain| !*contain);
303+
for (seq, (id, func)) in candidates.iter().enumerate() {
316304
match try_check_function(args, &func.signature, auto_cast_rules, fn_registry) {
317-
Ok((checked_args, return_type, generics)) => {
318-
return Ok(Expr::FunctionCall {
305+
Ok((args, return_type, generics)) => {
306+
let score = if need_sort {
307+
args.iter()
308+
.zip(args_not_const.iter().copied())
309+
.map(|(expr, not_const)| {
310+
// smaller score win
311+
if not_const && expr.is_cast() {
312+
1
313+
} else {
314+
0
315+
}
316+
})
317+
.sum::<usize>()
318+
} else {
319+
0
320+
};
321+
let expr = Expr::FunctionCall {
319322
span,
320-
id: id.clone(),
323+
id: Box::new(id.clone()),
321324
function: func.clone(),
322325
generics,
323-
args: checked_args,
326+
args,
324327
return_type,
325-
});
328+
};
329+
if !need_sort {
330+
return Ok(expr);
331+
}
332+
checked_candidates.push((expr, score, seq));
326333
}
327334
Err(err) => fail_reasons.push(err),
328335
}
329336
}
330337

338+
if !checked_candidates.is_empty() {
339+
checked_candidates.sort_by_key(|(_, score, seq)| std::cmp::Reverse((*score, *seq)));
340+
return Ok(checked_candidates.pop().unwrap().0);
341+
}
342+
331343
let mut msg = if params.is_empty() {
332344
format!(
333345
"no function matches signature `{name}({})`, you might need to add explicit type casts.",
@@ -783,6 +795,78 @@ pub const ALL_SIMPLE_CAST_FUNCTIONS: &[&str] = &[
783795
"parse_json",
784796
];
785797

786-
pub fn is_simple_cast_function(name: &str) -> bool {
798+
fn is_simple_cast_function(name: &str) -> bool {
787799
ALL_SIMPLE_CAST_FUNCTIONS.contains(&name)
788800
}
801+
802+
pub fn rewrite_function_to_cast<Index: ColumnIndex>(expr: Expr<Index>) -> Expr<Index> {
803+
match visit_expr(&expr, &mut RewriteCast).unwrap() {
804+
None => expr,
805+
Some(expr) => expr,
806+
}
807+
}
808+
809+
struct RewriteCast;
810+
811+
impl<Index: ColumnIndex> ExprVisitor<Index> for RewriteCast {
812+
type Error = !;
813+
814+
fn enter_function_call(
815+
&mut self,
816+
expr: &Expr<Index>,
817+
) -> std::result::Result<Option<Expr<Index>>, Self::Error> {
818+
let expr = match Self::visit_function_call(expr, self)? {
819+
Some(expr) => Cow::Owned(expr),
820+
None => Cow::Borrowed(expr),
821+
};
822+
let Expr::FunctionCall {
823+
span,
824+
function,
825+
generics,
826+
args,
827+
return_type,
828+
..
829+
} = expr.as_ref()
830+
else {
831+
unreachable!();
832+
};
833+
if !generics.is_empty() || args.len() != 1 {
834+
return match expr {
835+
Cow::Borrowed(_) => Ok(None),
836+
Cow::Owned(expr) => Ok(Some(expr)),
837+
};
838+
}
839+
if function.signature.name == "parse_json" {
840+
return Ok(Some(Expr::Cast {
841+
span: *span,
842+
is_try: false,
843+
expr: Box::new(args.first().unwrap().clone()),
844+
dest_type: return_type.clone(),
845+
}));
846+
}
847+
let func_name = format!(
848+
"to_{}",
849+
return_type.remove_nullable().to_string().to_lowercase()
850+
);
851+
if function.signature.name == func_name {
852+
return Ok(Some(Expr::Cast {
853+
span: *span,
854+
is_try: false,
855+
expr: Box::new(args.first().unwrap().clone()),
856+
dest_type: return_type.clone(),
857+
}));
858+
};
859+
if function.signature.name == format!("try_{func_name}") {
860+
return Ok(Some(Expr::Cast {
861+
span: *span,
862+
is_try: true,
863+
expr: Box::new(args.first().unwrap().clone()),
864+
dest_type: return_type.clone(),
865+
}));
866+
}
867+
match expr {
868+
Cow::Borrowed(_) => Ok(None),
869+
Cow::Owned(expr) => Ok(Some(expr)),
870+
}
871+
}
872+
}

0 commit comments

Comments
 (0)