Skip to content

Add derive based AST visitor - #765

Merged
alamb merged 10 commits into
apache:mainfrom
tustvold:proc-macro-ast-visitor
Dec 28, 2022
Merged

Add derive based AST visitor#765
alamb merged 10 commits into
apache:mainfrom
tustvold:proc-macro-ast-visitor

Conversation

@tustvold

Copy link
Copy Markdown
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
Copy Markdown
Contributor

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

@alamb

Copy link
Copy Markdown
Contributor

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

@alambalamb left a comment

Copy link
Copy Markdown
Contributor

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 #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

Comment threadderive/Cargo.toml
name = "sqlparser_derive"
description = "proc macro for sqlparser"
version = "0.1.0"
authors = ["Andy Grove <andygrove73@gmail.com>"]

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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
Copy Markdown
Contributor

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
Copy Markdown
Contributor

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

Comment threadCargo.toml
# 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
Copy Markdown
Contributor

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

@alambalambDec 28, 2022

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Docs in #774#776

Comment threadderive/README.md

## Visit

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

Copy link
Copy Markdown
Contributor

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
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

in #779

Comment threadderive/src/lib.rs
Comment threadsrc/ast/data_type.rs
/// 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
Copy Markdown
Contributor

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
Copy Markdown
ContributorAuthor

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 😆

Comment threadsrc/ast/visitor.rs Outdated
pub trait Visitor {
type Break;

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

Copy link
Copy Markdown
Contributor

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)?

Comment thread.gitignore
# will have compiled files and executables
/target/
/sqlparser_bench/target/
/derive/target/

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@coveralls

coveralls commented Dec 18, 2022

Copy link
Copy Markdown

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 CoverageCovered LinesChanged/Added Lines%
src/lib.rs010.0%
derive/src/lib.rs0270.0%
src/ast/visitor.rs0460.0%
Files with Coverage ReductionNew Missed Lines%
src/lib.rs30510.05%
TotalsCoverage Status
Change from base Build 3794463597:-0.4%
Covered Lines:13007
Relevant Lines:15127

💛 - Coveralls

@tustvold

Copy link
Copy Markdown
ContributorAuthor

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 alambDecember 22, 2022 09:25
@lovasoa

lovasoa commented Dec 22, 2022

Copy link
Copy Markdown
Contributor

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 !

@AugustoFKLAugustoFKL left a comment

Copy link
Copy Markdown
Contributor

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?

@alambalamb left a comment

Copy link
Copy Markdown
Contributor

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

Comment threadderive/Cargo.toml
name = "sqlparser_derive"
description = "proc macro for sqlparser"
version = "0.1.0"
authors = ["Andy Grove <andygrove73@gmail.com>"]

Copy link
Copy Markdown
Contributor

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 apache:mainDec 28, 2022
@alamb

alamb commented Dec 28, 2022

Copy link
Copy Markdown
Contributor

Thanks again all!

@alamb

alamb commented Dec 28, 2022

Copy link
Copy Markdown
Contributor

Improved Docs: #778

This was referenced Dec 31, 2022
Sign up for freeto 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.

5 participants

@tustvold@alamb@coveralls@lovasoa@AugustoFKL