File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -18977,3 +18977,30 @@ fn parse_non_pg_dialects_keep_xml_names_as_regular_identifiers() {
1897718977 let dialects = all_dialects_except(|d| d.supports_xml_expressions());
1897818978 dialects.verified_only_select("SELECT xml FROM t");
1897918979}
18980+
18981+ /// Regression test for the 2^N parse-time blowup in `parse_compound_expr` on
18982+ /// inputs like `IF a0.a1...aN.#`. The parse is run on a worker thread and the
18983+ /// main thread asserts that it reports back within a generous timeout. Post-fix
18984+ /// the parser returns `Err` in well under a millisecond, so the timeout is a
18985+ /// hang guard, not a perf threshold.
18986+ #[test]
18987+ fn parse_compound_chain_no_exponential_blowup() {
18988+ use std::sync::mpsc;
18989+ use std::thread;
18990+ use std::time::Duration;
18991+
18992+ let chain: String = (0..30)
18993+ .map(|i| format!("a{i}"))
18994+ .collect::<Vec<_>>()
18995+ .join(".");
18996+ let sql = format!("IF {chain}.#");
18997+
18998+ let (tx, rx) = mpsc::channel();
18999+ thread::spawn(move || {
19000+ let _ = Parser::parse_sql(&GenericDialect {}, &sql);
19001+ let _ = tx.send(());
19002+ });
19003+
19004+ rx.recv_timeout(Duration::from_secs(5))
19005+ .expect("parser should reject this quickly, not loop exponentially");
19006+ }
You can’t perform that action at this time.
0 commit comments