Skip to content

Commit 1b09bb2

Browse files
authored
feat: simplify function call parse (#18386)
* perf: simplify function call parse * test: add deep function call on `test_expr`
1 parent a8b79f1 commit 1b09bb2

File tree

4 files changed

+864
-50
lines changed

4 files changed

+864
-50
lines changed

src/query/ast/benches/bench.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ fn main() {
1818

1919
// bench fastest │ slowest │ median │ mean │ samples │ iters
2020
// ╰─ dummy │ │ │ │ │
21-
// ├─ deep_function_call 732.9 ms │ 732.9 ms │ 732.9 ms │ 732.9 ms │ 1 │ 1
22-
// ├─ deep_query 319.4 µs │ 515.6 µs │ 333.4 µs │ 335.3 µs │ 100 │ 100
23-
// ├─ large_query 1.998 ms │ 2.177 ms │ 2.032 ms │ 2.038 ms │ 100 │ 100
24-
// ├─ large_statement 1.952 ms │ 2.079 ms │ 2.016 ms │ 2.011 ms │ 100 │ 100
25-
// ╰─ wide_expr 620.4 µs │ 783.7 µs │ 646 µs │ 646.4 µs │ 100 │ 100
21+
// ├─ deep_function_call 1.238 ms │ 1.781 ms │ 1.355 ms │ 1.353 ms │ 100 │ 100
22+
// ├─ deep_query 285.6 µs │ 434.6 µs │ 306.8 µs │ 307 µs │ 100 │ 100
23+
// ├─ large_query 1.739 ms │ 1.893 ms │ 1.795 ms │ 1.801 ms │ 100 │ 100
24+
// ├─ large_statement 1.745 ms │ 1.885 ms │ 1.807 ms │ 1.806 ms │ 100 │ 100
25+
// ╰─ wide_expr 562 µs │ 651.9 µs │ 588.2 µs │ 590.5 µs │ 100 │ 100
2626

2727
#[divan::bench_group(max_time = 0.5)]
2828
mod dummy {
@@ -65,7 +65,7 @@ mod dummy {
6565

6666
#[divan::bench]
6767
fn deep_function_call() {
68-
let case = r#"ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN(RADIANS(CASE WHEN MOD(EXTRACT(SECOND FROM CURRENT_TIMESTAMP), 2) = 0 THEN 45.6789 ELSE 30.1234 END - IFNULL(NULLIF((SELECT 37.7749), 0), 15.4321))), 2) + POW(SIN(RADIANS((SELECT -122.4194) / 2)), 2) * COS(RADIANS(LEAST(60, GREATEST(20, (SELECT 25.5))))))) * (1000 + (RAND() * 500 - 250)), 2)"#;
68+
let case = r#"json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert('{}'::variant, 'email_address', 'gokul', true), 'home_phone', 12345, true), 'mobile_phone', 345678, true), 'race_code', 'M', true), 'race_desc', 'm', true), 'marital_status_code', 'y', true), 'marital_status_desc', 'yu', true), 'prefix', 'hj', true), 'first_name', 'g', true), 'last_name', 'p', true), 'deceased_date', '2085-05-07', true), 'birth_date', '6789', true), 'middle_name', '89', true), 'middle_initial', '0789', true), 'gender_code', '56789', true), 'gender_desc', 'm', true), 'home_phone_line_type', 'uyt', true), 'mobile_phone_line_type', 4, true)"#;
6969
let tokens = tokenize_sql(case).unwrap();
7070
let expr = parse_expr(&tokens, Dialect::PostgreSQL).unwrap();
7171
divan::black_box(expr);

src/query/ast/src/parser/expr.rs

Lines changed: 99 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2236,62 +2236,117 @@ pub fn function_call(i: Input) -> IResult<ExprElement> {
22362236
window: Option<WindowDesc>,
22372237
},
22382238
}
2239-
let function_call_with_lambda_body = map(
2239+
let function_call_body = map_res(
22402240
rule! {
2241-
"(" ~ #subexpr(0) ~ "," ~ #lambda_params ~ "->" ~ #subexpr(0) ~ ")"
2242-
},
2243-
|(_, arg, _, params, _, expr, _)| FunctionCallSuffix::Lambda {
2244-
arg,
2245-
params,
2246-
expr: Box::new(expr),
2247-
},
2248-
);
2249-
let function_call_with_within_group_window_body = map(
2250-
rule! {
2251-
"(" ~ DISTINCT? ~ #comma_separated_list0(subexpr(0))? ~ ")"
2241+
"(" ~ DISTINCT? ~ #subexpr(0)? ~ ","? ~ (#lambda_params ~ "->" ~ #subexpr(0))? ~ #comma_separated_list1(subexpr(0))? ~ ")"
2242+
~ ("(" ~ DISTINCT? ~ #comma_separated_list0(subexpr(0))? ~ ")")?
22522243
~ #within_group?
22532244
~ #window_function?
22542245
},
2255-
|(_, opt_distinct, opt_args, _, order_by, window)| match (order_by, window) {
2256-
(Some(order_by), window) => FunctionCallSuffix::WithInGroupWindow {
2257-
distinct: opt_distinct.is_some(),
2258-
args: opt_args.unwrap_or_default(),
2246+
|(
2247+
_,
2248+
opt_distinct_0,
2249+
first_param,
2250+
_,
2251+
opt_lambda,
2252+
params_0,
2253+
_,
2254+
params_1,
2255+
order_by,
2256+
window,
2257+
)| {
2258+
match (
2259+
first_param,
2260+
opt_lambda,
2261+
opt_distinct_0,
2262+
params_0,
2263+
params_1,
22592264
order_by,
22602265
window,
2261-
},
2262-
(None, Some(window)) => FunctionCallSuffix::Window {
2263-
distinct: opt_distinct.is_some(),
2264-
args: opt_args.unwrap_or_default(),
2265-
window,
2266-
},
2267-
(None, None) => FunctionCallSuffix::Simple {
2268-
distinct: opt_distinct.is_some(),
2269-
args: opt_args.unwrap_or_default(),
2270-
},
2271-
},
2272-
);
2273-
let function_call_with_params_window_body = map(
2274-
rule! {
2275-
"(" ~ #comma_separated_list1(subexpr(0)) ~ ")"
2276-
~ "(" ~ DISTINCT? ~ #comma_separated_list0(subexpr(0))? ~ ")"
2277-
~ #window_function?
2278-
},
2279-
|(_, params, _, _, opt_distinct, opt_args, _, window)| FunctionCallSuffix::ParamsWindow {
2280-
distinct: opt_distinct.is_some(),
2281-
params,
2282-
args: opt_args.unwrap_or_default(),
2283-
window,
2266+
) {
2267+
(
2268+
Some(first_param),
2269+
Some((lambda_params, _, arg_1)),
2270+
None,
2271+
None,
2272+
None,
2273+
None,
2274+
None,
2275+
) => Ok(FunctionCallSuffix::Lambda {
2276+
arg: first_param,
2277+
params: lambda_params,
2278+
expr: Box::new(arg_1),
2279+
}),
2280+
(
2281+
Some(first_param),
2282+
None,
2283+
None,
2284+
params_0,
2285+
Some((_, opt_distinct_1, params_1, _)),
2286+
None,
2287+
window,
2288+
) => {
2289+
let params = params_0
2290+
.map(|mut params| {
2291+
params.insert(0, first_param.clone());
2292+
params
2293+
})
2294+
.unwrap_or_else(|| vec![first_param]);
2295+
2296+
Ok(FunctionCallSuffix::ParamsWindow {
2297+
distinct: opt_distinct_1.is_some(),
2298+
params,
2299+
args: params_1.unwrap_or_default(),
2300+
window,
2301+
})
2302+
}
2303+
(first_param, None, opt_distinct, params, None, Some(order_by), window) => {
2304+
let mut args = params.unwrap_or_default();
2305+
if let Some(first_param) = first_param {
2306+
args.insert(0, first_param)
2307+
}
2308+
2309+
Ok(FunctionCallSuffix::WithInGroupWindow {
2310+
distinct: opt_distinct.is_some(),
2311+
args,
2312+
order_by,
2313+
window,
2314+
})
2315+
}
2316+
(first_param, None, opt_distinct, params, None, None, Some(window)) => {
2317+
let mut args = params.unwrap_or_default();
2318+
if let Some(first_param) = first_param {
2319+
args.insert(0, first_param)
2320+
}
2321+
2322+
Ok(FunctionCallSuffix::Window {
2323+
distinct: opt_distinct.is_some(),
2324+
args,
2325+
window,
2326+
})
2327+
}
2328+
(first_param, None, opt_distinct, params, None, None, None) => {
2329+
let mut args = params.unwrap_or_default();
2330+
if let Some(first_param) = first_param {
2331+
args.insert(0, first_param)
2332+
}
2333+
2334+
Ok(FunctionCallSuffix::Simple {
2335+
distinct: opt_distinct.is_some(),
2336+
args,
2337+
})
2338+
}
2339+
_ => Err(nom::Err::Error(ErrorKind::Other(
2340+
"Unsupported function format",
2341+
))),
2342+
}
22842343
},
22852344
);
22862345

22872346
map(
22882347
rule!(
22892348
#function_name
2290-
~ (
2291-
#function_call_with_lambda_body : "`function(..., x -> ...)`"
2292-
| #function_call_with_params_window_body : "`function(...)(...) OVER ([ PARTITION BY <expr>, ... ] [ ORDER BY <expr>, ... ] [ <window frame> ])`"
2293-
| #function_call_with_within_group_window_body : "`function(...) [ WITHIN GROUP ( ORDER BY <expr>, ... ) ] [ OVER ([ PARTITION BY <expr>, ... ] [ ORDER BY <expr>, ... ] [ <window frame> ]) ]`"
2294-
)
2349+
~ #function_call_body : "`function(... [ , x -> ... ] ) [ (...) ] [ WITHIN GROUP ( ORDER BY <expr>, ... ) ] [ OVER ([ PARTITION BY <expr>, ... ] [ ORDER BY <expr>, ... ] [ <window frame> ]) ]`"
22952350
),
22962351
|(name, suffix)| match suffix {
22972352
FunctionCallSuffix::Simple { distinct, args } => ExprElement::FunctionCall {

src/query/ast/tests/it/parser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1348,6 +1348,7 @@ fn test_expr() {
13481348
r#"MAP_TRANSFORM_VALUES({1:10,2:20,3:30}, (k, v) -> v + 1)"#,
13491349
r#"INTERVAL '1 YEAR'"#,
13501350
r#"(?, ?)"#,
1351+
r#"json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert(json_object_insert('{}'::variant, 'email_address', 'gokul', true), 'home_phone', 12345, true), 'mobile_phone', 345678, true), 'race_code', 'M', true), 'race_desc', 'm', true), 'marital_status_code', 'y', true), 'marital_status_desc', 'yu', true), 'prefix', 'hj', true), 'first_name', 'g', true), 'last_name', 'p', true), 'deceased_date', '2085-05-07', true), 'birth_date', '6789', true), 'middle_name', '89', true), 'middle_initial', '0789', true), 'gender_code', '56789', true), 'gender_desc', 'm', true)"#,
13511352
];
13521353

13531354
for case in cases {

0 commit comments

Comments
 (0)