Skip to content

Commit 9ade53d

Browse files
authored
Merge branch 'main' into dev (#9)
2 parents 69514bb + 7f99d7b commit 9ade53d

Some content is hidden

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

41 files changed

+4476
-1208
lines changed

.github/workflows/rust.yml

+8
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,14 @@ jobs:
3737
uses: ./.github/actions/setup-builder
3838
- run: cargo clippy --all-targets --all-features -- -D warnings
3939

40+
benchmark-lint:
41+
runs-on: ubuntu-latest
42+
steps:
43+
- uses: actions/checkout@v4
44+
- name: Setup Rust Toolchain
45+
uses: ./.github/actions/setup-builder
46+
- run: cd sqlparser_bench && cargo clippy --all-targets --all-features -- -D warnings
47+
4048
compile:
4149
runs-on: ubuntu-latest
4250
steps:

Cargo.toml

+4-1
Original file line numberDiff line numberDiff line change
@@ -37,15 +37,18 @@ name = "sqlparser"
3737
path = "src/lib.rs"
3838

3939
[features]
40-
default = ["std"]
40+
default = ["std", "recursive-protection"]
4141
std = []
42+
recursive-protection = ["std", "recursive"]
4243
# Enable JSON output in the `cli` example:
4344
json_example = ["serde_json", "serde"]
4445
visitor = ["sqlparser_derive"]
4546

4647
[dependencies]
4748
bigdecimal = { version = "0.4.1", features = ["serde"], optional = true }
4849
log = "0.4"
50+
recursive = { version = "0.1.1", optional = true}
51+
4952
serde = { version = "1.0", features = ["derive"], optional = true }
5053
# serde_json is only used in examples/cli, but we have to put it outside
5154
# of dev-dependencies because of

README.md

+6-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ The following optional [crate features](https://doc.rust-lang.org/cargo/referen
7171

7272
* `serde`: Adds [Serde](https://serde.rs/) support by implementing `Serialize` and `Deserialize` for all AST nodes.
7373
* `visitor`: Adds a `Visitor` capable of recursively walking the AST tree.
74-
74+
* `recursive-protection` (enabled by default), uses [recursive](https://docs.rs/recursive/latest/recursive/) for stack overflow protection.
7575

7676
## Syntax vs Semantics
7777

@@ -248,11 +248,14 @@ You can run them with:
248248
```
249249
git checkout main
250250
cd sqlparser_bench
251-
cargo bench
251+
cargo bench -- --save-baseline main
252252
git checkout <your branch>
253-
cargo bench
253+
cargo bench -- --baseline main
254254
```
255255

256+
By adding the `--save-baseline main` and `--baseline main` you can track the
257+
progress of your improvements as you continue working on the feature branch.
258+
256259
## Licensing
257260

258261
All code in this repository is licensed under the [Apache Software License 2.0](LICENSE.txt).

derive/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,10 @@ fn derive_visit(input: proc_macro::TokenStream, visit_type: &VisitType) -> proc_
7878

7979
let expanded = quote! {
8080
// The generated impl.
81+
// Note that it uses [`recursive::recursive`] to protect from stack overflow.
82+
// See tests in https://github.com/apache/datafusion-sqlparser-rs/pull/1522/ for more info.
8183
impl #impl_generics sqlparser::ast::#visit_trait for #name #ty_generics #where_clause {
84+
#[cfg_attr(feature = "recursive-protection", recursive::recursive)]
8285
fn visit<V: sqlparser::ast::#visitor_trait>(
8386
&#modifier self,
8487
visitor: &mut V

sqlparser_bench/README.md

+23-1
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,26 @@
1717
under the License.
1818
-->
1919

20-
Benchmarks for sqlparser. See [the main README](../README.md) for more information.
20+
Benchmarks for sqlparser. See [the main README](../README.md) for more information.
21+
22+
Note: this is in a separate, non workspace crate to avoid adding a dependency
23+
on `criterion` to the main crate (which complicates testing without std).
24+
25+
# Running Benchmarks
26+
27+
```shell
28+
cargo bench --bench sqlparser_bench
29+
```
30+
31+
# Profiling
32+
33+
Note you can generate a [flamegraph] using the following command:
34+
35+
```shell
36+
cargo flamegraph --bench sqlparser_bench
37+
```
38+
39+
[flamegraph]: https://crates.io/crates/flamegraph
40+
41+
Here is an example flamegraph:
42+
![flamegraph](img/flamegraph.svg)

sqlparser_bench/benches/sqlparser_bench.rs

+39
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,45 @@ fn basic_queries(c: &mut Criterion) {
4242
group.bench_function("sqlparser::with_select", |b| {
4343
b.iter(|| Parser::parse_sql(&dialect, with_query).unwrap());
4444
});
45+
46+
let large_statement = {
47+
let expressions = (0..1000)
48+
.map(|n| format!("FN_{}(COL_{})", n, n))
49+
.collect::<Vec<_>>()
50+
.join(", ");
51+
let tables = (0..1000)
52+
.map(|n| format!("TABLE_{}", n))
53+
.collect::<Vec<_>>()
54+
.join(" JOIN ");
55+
let where_condition = (0..1000)
56+
.map(|n| format!("COL_{} = {}", n, n))
57+
.collect::<Vec<_>>()
58+
.join(" OR ");
59+
let order_condition = (0..1000)
60+
.map(|n| format!("COL_{} DESC", n))
61+
.collect::<Vec<_>>()
62+
.join(", ");
63+
64+
format!(
65+
"SELECT {} FROM {} WHERE {} ORDER BY {}",
66+
expressions, tables, where_condition, order_condition
67+
)
68+
};
69+
70+
group.bench_function("parse_large_statement", |b| {
71+
b.iter(|| Parser::parse_sql(&dialect, criterion::black_box(large_statement.as_str())));
72+
});
73+
74+
let large_statement = Parser::parse_sql(&dialect, large_statement.as_str())
75+
.unwrap()
76+
.pop()
77+
.unwrap();
78+
79+
group.bench_function("format_large_statement", |b| {
80+
b.iter(|| {
81+
let _formatted_query = large_statement.to_string();
82+
});
83+
});
4584
}
4685

4786
criterion_group!(benches, basic_queries);

0 commit comments

Comments
 (0)