Skip to content

Commit 43152a2

Browse files
Bench: move compound-chain regression to sqlparser_bench
1 parent e191085 commit 43152a2

2 files changed

Lines changed: 32 additions & 25 deletions

File tree

sqlparser_bench/benches/sqlparser_bench.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,5 +152,36 @@ fn parse_many_identifiers(c: &mut Criterion) {
152152
group.finish();
153153
}
154154

155-
criterion_group!(benches, basic_queries, word_to_ident, parse_many_identifiers);
155+
/// Benchmark parsing pathological compound chains that previously caused 2^N
156+
/// work in `parse_compound_expr`. The input `IF a0.a1...aN.#` rejects at the
157+
/// trailing `#`, which used to force quadratic-or-worse backtracking through
158+
/// the chain.
159+
fn parse_compound_chain(c: &mut Criterion) {
160+
let mut group = c.benchmark_group("parse_compound_chain");
161+
let dialect = GenericDialect {};
162+
163+
for &n in &[10usize, 20, 30] {
164+
let chain = (0..n)
165+
.map(|i| format!("a{i}"))
166+
.collect::<Vec<_>>()
167+
.join(".");
168+
let sql = format!("IF {chain}.#");
169+
170+
group.bench_function(format!("chain_{n}"), |b| {
171+
b.iter(|| {
172+
let _ = Parser::parse_sql(&dialect, std::hint::black_box(&sql));
173+
});
174+
});
175+
}
176+
177+
group.finish();
178+
}
179+
180+
criterion_group!(
181+
benches,
182+
basic_queries,
183+
word_to_ident,
184+
parse_many_identifiers,
185+
parse_compound_chain
186+
);
156187
criterion_main!(benches);

tests/sqlparser_postgres.rs

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -9243,27 +9243,3 @@ fn parse_lock_table() {
92439243
}
92449244
}
92459245
}
9246-
9247-
/// `parse_compound_expr` used to do 2^N work on `IF a.b.c...x.#` because every
9248-
/// `.` re-entered `parse_subexpr` over the rest of the chain.
9249-
#[test]
9250-
fn parse_compound_chain_no_exponential_blowup() {
9251-
use std::sync::mpsc;
9252-
use std::thread;
9253-
use std::time::Duration;
9254-
9255-
let chain: String = (0..30)
9256-
.map(|i| format!("a{i}"))
9257-
.collect::<Vec<_>>()
9258-
.join(".");
9259-
let sql = format!("IF {chain}.#");
9260-
9261-
let (tx, rx) = mpsc::channel();
9262-
thread::spawn(move || {
9263-
let _ = sqlparser::parser::Parser::parse_sql(&PostgreSqlDialect {}, &sql);
9264-
let _ = tx.send(());
9265-
});
9266-
9267-
rx.recv_timeout(Duration::from_secs(5))
9268-
.expect("parser should reject this quickly, not loop exponentially");
9269-
}

0 commit comments

Comments
 (0)