Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add derive based AST visitor #765

Merged
merged 10 commits into from Dec 28, 2022
Merged

Conversation

tustvold
Copy link
Contributor

Reimplements #758 but using a proc-macro.

One issue is that currently this will not dispatch to visit_table_name for statements where the ObjectType is parameterised, this is Drop, ShowCreate, Comment. We could theoretically add a skip_if option down the line, but I wanted to keep things simple for now.

@alamb
Copy link
Collaborator

alamb commented Dec 15, 2022

Thanks @tustvold -- I will check this one out carefully, but probably not until tomorrow

@alamb
Copy link
Collaborator

alamb commented Dec 16, 2022

Thank you -- I plan to review this carefully later today

Copy link
Collaborator

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you @tustvold -- I just had a chance to go through this code in more detail 👍

I think it works well for the usecase of visiting parts

I also spent some time comparing it to the approach in #601 and I had a queston:

How hard do you think it would be to add the following features (in the future):

  1. A Rewriter / mutator for performing SQL rewrites in addition to visiting,
  2. A previsit() and postvisit() to specify the order in which children were visted (DFS or BFS)?
  3. Additional "visit" methods (e.g. if I wanted to visit all Idents)? Could this be done in the proc macro itself? It seems like Drive proposed in Add an AST visitor #601 can do so.

I think 3. would be particularly compelling for other users of this crate in the near term.

cc @lovasoa -- I wonder if you have thoughts on this API

cc @AugustoFKL for your guidance

name = "sqlparser_derive"
description = "proc macro for sqlparser"
version = "0.1.0"
authors = ["Andy Grove <andygrove73@gmail.com>"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 maybe this should be something different. I will think about a more appropriate author -- maybe sqlparser-rs contributors 🤔

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TBH I'm not sure as well. Theoretically I'd say that the owner/creator should be the author, but since this is an expansion, not sure whether put both of you or just the @tustvold

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is ok as is

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed it to "sqlparser authors" in #775

@@ -32,6 +33,7 @@ serde = { version = "1.0", features = ["derive"], optional = true }
# of dev-dependencies because of
# https://github.com/rust-lang/cargo/issues/1596
serde_json = { version = "1.0", optional = true }
sqlparser_derive = { version = "0.1", path = "derive", optional = true }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to myself: if we merge this PR I think we should document this feature flag -- it seems documentation is missing for the existing feature flags

Copy link
Collaborator

@alamb alamb Dec 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs in #774 #776


## Visit

This crate contains a procedural macro that can automatically derive implementations of the `Visit` trait
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note to self -- this should have a doc link back to the sqlparser crate

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in #779

derive/src/lib.rs Show resolved Hide resolved
@@ -337,6 +341,7 @@ fn format_datetime_precision_and_tz(
/// guarantee compatibility with the input query we must maintain its exact information.
#[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit))]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a big fan of this method as a way to minimize maintenance burden on new contributions

I picked a random struct and removed the #[cfg_attr(feature = "visitor", derive(Visit))] to see what would happen if it was forgotten

I think the error is fairly clear 👍

   Compiling sqlparser v0.28.0 (/Users/alamb/Software/sqlparser-rs)
error[E0277]: the trait bound `ast::Password: visitor::Visit` is not satisfied
    --> src/ast/mod.rs:1262:9
     |
1262 |         password: Option<Password>,
     |         ^^^^^^^^ the trait `visitor::Visit` is not implemented for `ast::Password`
     |
     = help: the following other types implement trait `visitor::Visit`:
               Box<T>
               CommentObject
               CreateTableBuilder
               Keyword
               Option<T>
               String
               Vec<T>
               ast::Action
             and 120 others
note: required for `Option<ast::Password>` to implement `visitor::Visit`
    --> src/ast/visitor.rs:21:16
     |
21   | impl<T: Visit> Visit for Option<T> {
     |                ^^^^^     ^^^^^^^^^

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's also making it easier to keep up with the merge conflicts 😆

pub trait Visitor {
type Break;

/// Invoked for any tables, virtual or otherwise that appear in the AST
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we please rename this to visit_relation (which is a more general term for table / view / CTE, etc)?

@@ -2,6 +2,7 @@
# will have compiled files and executables
/target/
/sqlparser_bench/target/
/derive/target/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also note to self

I tested using

cargo test --all --features=visitor

We need to add this feature to the CI tests

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, that explains the poor coverage I guess

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I verified that the CI does run with --all-features: https://github.com/sqlparser-rs/sqlparser-rs/actions/runs/3794845435/jobs/6453351547

run: cargo test --all-features

@coveralls
Copy link

coveralls commented Dec 18, 2022

Pull Request Test Coverage Report for Build 3794824925

  • 0 of 74 (0.0%) changed or added relevant lines in 3 files are covered.
  • 305 unchanged lines in 1 file lost coverage.
  • Overall coverage decreased (-0.4%) to 85.985%

Changes Missing Coverage Covered Lines Changed/Added Lines %
src/lib.rs 0 1 0.0%
derive/src/lib.rs 0 27 0.0%
src/ast/visitor.rs 0 46 0.0%
Files with Coverage Reduction New Missed Lines %
src/lib.rs 305 10.05%
Totals Coverage Status
Change from base Build 3794463597: -0.4%
Covered Lines: 13007
Relevant Lines: 15127

💛 - Coveralls

@tustvold
Copy link
Contributor Author

Additional "visit" methods (e.g. if I wanted to visit all Idents)? Could this be done in the proc macro itself? It seems like Drive proposed in #601 can do so.

Very easy, it would simply be a case of adding the method to the Visitor and then potentially annotating a couple of fields and/or structs with visit(with = "my_amazing_visit_method")

A previsit() and postvisit() to specify the order in which children were visted (DFS or BFS)?

Currently the code implements previsit, it would be relatively straightforward to add an additional annotation to support post visit.

A Rewriter / mutator for performing SQL rewrites in addition to visiting,

You could definitely apply the same broad approach to this problem, but without having a good idea as to what the API might look like, or what the precise use-case would be, I'm not sure how easy this would be in practice. I suspect rewriting SQL AST directly would be relatively non-trivial to do correctly, not to mention verbose, with a far better approach to first lower to some sort of logical/intermediate representation.

@tustvold tustvold requested a review from alamb December 22, 2022 09:25
@lovasoa
Copy link
Contributor

lovasoa commented Dec 22, 2022

I would love this to be merged!

This re-implements the entire derive-visitor crate inside sqlparser-rs, as opposed to my approach in #601 that just added it as a dependency. But I would still be very happy if this were merged and we finally had a way to visit sql statements !

Copy link
Contributor

@AugustoFKL AugustoFKL left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tustvold any reasons why the coverage is so small?

Copy link
Collaborator

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should do it.

I'll plan to resolve outstanding conflicts and then add additional documentation / tests as a follow on PR.

Thank you @tustvold @AugustoFKL and @lovasoa

name = "sqlparser_derive"
description = "proc macro for sqlparser"
version = "0.1.0"
authors = ["Andy Grove <andygrove73@gmail.com>"]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is ok as is

@alamb alamb merged commit dec3c2b into sqlparser-rs:main Dec 28, 2022
@alamb
Copy link
Collaborator

alamb commented Dec 28, 2022

Thanks again all!

@alamb
Copy link
Collaborator

alamb commented Dec 28, 2022

Improved Docs: #778

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants