diff --git a/.gitignore b/.gitignore index baccda415..d41369207 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # will have compiled files and executables /target/ /sqlparser_bench/target/ +/derive/target/ # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock diff --git a/Cargo.toml b/Cargo.toml index 2355f4646..a3376a673 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,7 @@ version = "0.28.0" authors = ["Andy Grove "] homepage = "https://github.com/sqlparser-rs/sqlparser-rs" documentation = "https://docs.rs/sqlparser/" -keywords = [ "ansi", "sql", "lexer", "parser" ] +keywords = ["ansi", "sql", "lexer", "parser"] repository = "https://github.com/sqlparser-rs/sqlparser-rs" license = "Apache-2.0" include = [ @@ -23,6 +23,7 @@ default = ["std"] std = [] # Enable JSON output in the `cli` example: json_example = ["serde_json", "serde"] +visitor = ["sqlparser_derive"] [dependencies] bigdecimal = { version = "0.3", features = ["serde"], optional = true } @@ -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 } [dev-dependencies] simple_logger = "4.0" diff --git a/derive/Cargo.toml b/derive/Cargo.toml new file mode 100644 index 000000000..221437a9e --- /dev/null +++ b/derive/Cargo.toml @@ -0,0 +1,23 @@ +[package] +name = "sqlparser_derive" +description = "proc macro for sqlparser" +version = "0.1.0" +authors = ["Andy Grove "] +homepage = "https://github.com/sqlparser-rs/sqlparser-rs" +documentation = "https://docs.rs/sqlparser/" +keywords = ["ansi", "sql", "lexer", "parser"] +repository = "https://github.com/sqlparser-rs/sqlparser-rs" +license = "Apache-2.0" +include = [ + "src/**/*.rs", + "Cargo.toml", +] +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +syn = "1.0" +proc-macro2 = "1.0" +quote = "1.0" diff --git a/derive/README.md b/derive/README.md new file mode 100644 index 000000000..e5ab87496 --- /dev/null +++ b/derive/README.md @@ -0,0 +1,79 @@ +# SQL Parser Derive Macro + +## Visit + +This crate contains a procedural macro that can automatically derive implementations of the `Visit` trait + +```rust +#[derive(Visit)] +struct Foo { + boolean: bool, + bar: Bar, +} + +#[derive(Visit)] +enum Bar { + A(), + B(String, bool), + C { named: i32 }, +} +``` + +Will generate code akin to + +```rust +impl Visit for Foo { + fn visit(&self, visitor: &mut V) -> ControlFlow { + self.boolean.visit(visitor)?; + self.bar.visit(visitor)?; + ControlFlow::Continue(()) + } +} + +impl Visit for Bar { + fn visit(&self, visitor: &mut V) -> ControlFlow { + match self { + Self::A() => {} + Self::B(_1, _2) => { + _1.visit(visitor)?; + _2.visit(visitor)?; + } + Self::C { named } => { + named.visit(visitor)?; + } + } + ControlFlow::Continue(()) + } +} +``` + +Additionally certain types may wish to call a corresponding method on visitor before recursing + +```rust +#[derive(Visit)] +#[visit(with = "visit_expr")] +enum Expr { + A(), + B(String, #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] ObjectName, bool), +} +``` + +Will generate + +```rust +impl Visit for Bar { + fn visit(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_expr(self)?; + match self { + Self::A() => {} + Self::B(_1, _2, _3) => { + _1.visit(visitor)?; + visitor.visit_relation(_3)?; + _2.visit(visitor)?; + _3.visit(visitor)?; + } + } + ControlFlow::Continue(()) + } +} +``` diff --git a/derive/src/lib.rs b/derive/src/lib.rs new file mode 100644 index 000000000..b211b767b --- /dev/null +++ b/derive/src/lib.rs @@ -0,0 +1,184 @@ +use proc_macro2::TokenStream; +use quote::{format_ident, quote, quote_spanned, ToTokens}; +use syn::spanned::Spanned; +use syn::{ + parse_macro_input, parse_quote, Attribute, Data, DeriveInput, Fields, GenericParam, Generics, + Ident, Index, Lit, Meta, MetaNameValue, NestedMeta, +}; + +/// Implementation of `[#derive(Visit)]` +#[proc_macro_derive(Visit, attributes(visit))] +pub fn derive_visit(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + // Parse the input tokens into a syntax tree. + let input = parse_macro_input!(input as DeriveInput); + let name = input.ident; + + let attributes = Attributes::parse(&input.attrs); + // Add a bound `T: HeapSize` to every type parameter T. + let generics = add_trait_bounds(input.generics); + let (impl_generics, ty_generics, where_clause) = generics.split_for_impl(); + + let (pre_visit, post_visit) = attributes.visit(quote!(self)); + let children = visit_children(&input.data); + + let expanded = quote! { + // The generated impl. + impl #impl_generics sqlparser::ast::Visit for #name #ty_generics #where_clause { + fn visit(&self, visitor: &mut V) -> ::std::ops::ControlFlow { + #pre_visit + #children + #post_visit + ::std::ops::ControlFlow::Continue(()) + } + } + }; + + proc_macro::TokenStream::from(expanded) +} + +/// Parses attributes that can be provided to this macro +/// +/// `#[visit(leaf, with = "visit_expr")]` +#[derive(Default)] +struct Attributes { + /// Content for the `with` attribute + with: Option, +} + +impl Attributes { + fn parse(attrs: &[Attribute]) -> Self { + let mut out = Self::default(); + for attr in attrs.iter().filter(|a| a.path.is_ident("visit")) { + let meta = attr.parse_meta().expect("visit attribute"); + match meta { + Meta::List(l) => { + for nested in &l.nested { + match nested { + NestedMeta::Meta(Meta::NameValue(v)) => out.parse_name_value(v), + _ => panic!("Expected #[visit(key = \"value\")]"), + } + } + } + _ => panic!("Expected #[visit(...)]"), + } + } + out + } + + /// Updates self with a name value attribute + fn parse_name_value(&mut self, v: &MetaNameValue) { + if v.path.is_ident("with") { + match &v.lit { + Lit::Str(s) => self.with = Some(format_ident!("{}", s.value(), span = s.span())), + _ => panic!("Expected a string value, got {}", v.lit.to_token_stream()), + } + return; + } + panic!("Unrecognised kv attribute {}", v.path.to_token_stream()) + } + + /// Returns the pre and post visit token streams + fn visit(&self, s: TokenStream) -> (Option, Option) { + let pre_visit = self.with.as_ref().map(|m| { + let m = format_ident!("pre_{}", m); + quote!(visitor.#m(#s)?;) + }); + let post_visit = self.with.as_ref().map(|m| { + let m = format_ident!("post_{}", m); + quote!(visitor.#m(#s)?;) + }); + (pre_visit, post_visit) + } +} + +// Add a bound `T: Visit` to every type parameter T. +fn add_trait_bounds(mut generics: Generics) -> Generics { + for param in &mut generics.params { + if let GenericParam::Type(ref mut type_param) = *param { + type_param.bounds.push(parse_quote!(sqlparser::ast::Visit)); + } + } + generics +} + +// Generate the body of the visit implementation for the given type +fn visit_children(data: &Data) -> TokenStream { + match data { + Data::Struct(data) => match &data.fields { + Fields::Named(fields) => { + let recurse = fields.named.iter().map(|f| { + let name = &f.ident; + let attributes = Attributes::parse(&f.attrs); + let (pre_visit, post_visit) = attributes.visit(quote!(&self.#name)); + quote_spanned!(f.span() => #pre_visit sqlparser::ast::Visit::visit(&self.#name, visitor)?; #post_visit) + }); + quote! { + #(#recurse)* + } + } + Fields::Unnamed(fields) => { + let recurse = fields.unnamed.iter().enumerate().map(|(i, f)| { + let index = Index::from(i); + let attributes = Attributes::parse(&f.attrs); + let (pre_visit, post_visit) = attributes.visit(quote!(&self.#index)); + quote_spanned!(f.span() => #pre_visit sqlparser::ast::Visit::visit(&self.#index, visitor)?; #post_visit) + }); + quote! { + #(#recurse)* + } + } + Fields::Unit => { + quote!() + } + }, + Data::Enum(data) => { + let statements = data.variants.iter().map(|v| { + let name = &v.ident; + match &v.fields { + Fields::Named(fields) => { + let names = fields.named.iter().map(|f| &f.ident); + let visit = fields.named.iter().map(|f| { + let name = &f.ident; + let attributes = Attributes::parse(&f.attrs); + let (pre_visit, post_visit) = attributes.visit(quote!(&#name)); + quote_spanned!(f.span() => #pre_visit sqlparser::ast::Visit::visit(#name, visitor)?; #post_visit) + }); + + quote!( + Self::#name { #(#names),* } => { + #(#visit)* + } + ) + } + Fields::Unnamed(fields) => { + let names = fields.unnamed.iter().enumerate().map(|(i, f)| format_ident!("_{}", i, span = f.span())); + let visit = fields.unnamed.iter().enumerate().map(|(i, f)| { + let name = format_ident!("_{}", i); + let attributes = Attributes::parse(&f.attrs); + let (pre_visit, post_visit) = attributes.visit(quote!(&#name)); + quote_spanned!(f.span() => #pre_visit sqlparser::ast::Visit::visit(#name, visitor)?; #post_visit) + }); + + quote! { + Self::#name ( #(#names),*) => { + #(#visit)* + } + } + } + Fields::Unit => { + quote! { + Self::#name => {} + } + } + } + }); + + quote! { + match self { + #(#statements),* + } + } + } + Data::Union(_) => unimplemented!(), + } +} diff --git a/src/ast/data_type.rs b/src/ast/data_type.rs index 1353eca90..af8320d8f 100644 --- a/src/ast/data_type.rs +++ b/src/ast/data_type.rs @@ -17,6 +17,9 @@ use core::fmt; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "visitor")] +use sqlparser_derive::Visit; + use crate::ast::ObjectName; use super::value::escape_single_quote_string; @@ -24,6 +27,7 @@ use super::value::escape_single_quote_string; /// SQL data types #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum DataType { /// Fixed-length character type e.g. CHARACTER(10) Character(Option), @@ -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))] pub enum TimezoneInfo { /// No information about time zone. E.g., TIMESTAMP None, @@ -384,6 +389,7 @@ impl fmt::Display for TimezoneInfo { /// [standard]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#exact-numeric-type #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ExactNumberInfo { /// No additional information e.g. `DECIMAL` None, @@ -414,6 +420,7 @@ impl fmt::Display for ExactNumberInfo { /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#character-length #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct CharacterLength { /// Default (if VARYING) or maximum (if not VARYING) length pub length: u64, @@ -436,6 +443,7 @@ impl fmt::Display for CharacterLength { /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#char-length-units #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum CharLengthUnits { /// CHARACTERS unit Characters, diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index f55760984..e5bee49ca 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -20,6 +20,9 @@ use core::fmt; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "visitor")] +use sqlparser_derive::Visit; + use crate::ast::value::escape_single_quote_string; use crate::ast::{display_comma_separated, display_separated, DataType, Expr, Ident, ObjectName}; use crate::tokenizer::Token; @@ -27,6 +30,7 @@ use crate::tokenizer::Token; /// An `ALTER TABLE` (`Statement::AlterTable`) operation #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum AlterTableOperation { /// `ADD ` AddConstraint(TableConstraint), @@ -96,6 +100,7 @@ pub enum AlterTableOperation { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum AlterIndexOperation { RenameIndex { index_name: ObjectName }, } @@ -219,6 +224,7 @@ impl fmt::Display for AlterIndexOperation { /// An `ALTER COLUMN` (`Statement::AlterTable`) operation #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum AlterColumnOperation { /// `SET NOT NULL` SetNotNull, @@ -262,6 +268,7 @@ impl fmt::Display for AlterColumnOperation { /// `ALTER TABLE ADD ` statement. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum TableConstraint { /// `[ CONSTRAINT ] { PRIMARY KEY | UNIQUE } ()` Unique { @@ -425,6 +432,7 @@ impl fmt::Display for TableConstraint { /// [1]: https://dev.mysql.com/doc/refman/8.0/en/create-table.html #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum KeyOrIndexDisplay { /// Nothing to display None, @@ -460,6 +468,7 @@ impl fmt::Display for KeyOrIndexDisplay { /// [3]: https://www.postgresql.org/docs/14/sql-createindex.html #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum IndexType { BTree, Hash, @@ -478,6 +487,7 @@ impl fmt::Display for IndexType { /// SQL column definition #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct ColumnDef { pub name: Ident, pub data_type: DataType, @@ -513,6 +523,7 @@ impl fmt::Display for ColumnDef { /// "column options," and we allow any column option to be named. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct ColumnOptionDef { pub name: Option, pub option: ColumnOption, @@ -528,6 +539,7 @@ impl fmt::Display for ColumnOptionDef { /// TABLE` statement. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ColumnOption { /// `NULL` Null, @@ -617,6 +629,7 @@ fn display_constraint_name(name: &'_ Option) -> impl fmt::Display + '_ { /// Used in foreign key constraints in `ON UPDATE` and `ON DELETE` options. #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ReferentialAction { Restrict, Cascade, diff --git a/src/ast/helpers/stmt_create_table.rs b/src/ast/helpers/stmt_create_table.rs index 97c567b83..403d91131 100644 --- a/src/ast/helpers/stmt_create_table.rs +++ b/src/ast/helpers/stmt_create_table.rs @@ -4,6 +4,9 @@ use alloc::{boxed::Box, format, string::String, vec, vec::Vec}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "visitor")] +use sqlparser_derive::Visit; + use crate::ast::{ ColumnDef, FileFormat, HiveDistributionStyle, HiveFormat, ObjectName, OnCommit, Query, SqlOption, Statement, TableConstraint, @@ -40,6 +43,7 @@ use crate::parser::ParserError; /// [1]: crate::ast::Statement::CreateTable #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct CreateTableBuilder { pub or_replace: bool, pub temporary: bool, diff --git a/src/ast/mod.rs b/src/ast/mod.rs index b497014dd..80dff8504 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -22,6 +22,9 @@ use core::fmt; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "visitor")] +use sqlparser_derive::Visit; + pub use self::data_type::{ CharLengthUnits, CharacterLength, DataType, ExactNumberInfo, TimezoneInfo, }; @@ -38,6 +41,9 @@ pub use self::query::{ }; pub use self::value::{escape_quoted_string, DateTimeField, TrimWhereField, Value}; +#[cfg(feature = "visitor")] +pub use visitor::*; + mod data_type; mod ddl; pub mod helpers; @@ -45,6 +51,9 @@ mod operator; mod query; mod value; +#[cfg(feature = "visitor")] +mod visitor; + struct DisplaySeparated<'a, T> where T: fmt::Display, @@ -85,6 +94,7 @@ where /// An identifier, decomposed into its value or character data and the quote style. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct Ident { /// The value of the identifier without quotes. pub value: String, @@ -145,6 +155,7 @@ impl fmt::Display for Ident { /// A name of a table, view, custom type, etc., possibly multi-part, i.e. db.schema.obj #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct ObjectName(pub Vec); impl fmt::Display for ObjectName { @@ -153,10 +164,11 @@ impl fmt::Display for ObjectName { } } -#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] /// Represents an Array Expression, either /// `ARRAY[..]`, or `[..]` +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct Array { /// The list of expressions between brackets pub elem: Vec, @@ -179,6 +191,7 @@ impl fmt::Display for Array { /// JsonOperator #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum JsonOperator { /// -> keeps the value as json Arrow, @@ -242,6 +255,7 @@ impl fmt::Display for JsonOperator { /// inappropriate type, like `WHERE 1` or `SELECT 1=1`, as necessary. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit), visit(with = "visit_expr"))] pub enum Expr { /// Identifier e.g. table name or column name Identifier(Ident), @@ -882,6 +896,7 @@ impl fmt::Display for Expr { /// A window specification (i.e. `OVER (PARTITION BY .. ORDER BY .. etc.)`) #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct WindowSpec { pub partition_by: Vec, pub order_by: Vec, @@ -927,6 +942,7 @@ impl fmt::Display for WindowSpec { /// reject invalid bounds like `ROWS UNBOUNDED FOLLOWING` before execution. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct WindowFrame { pub units: WindowFrameUnits, pub start_bound: WindowFrameBound, @@ -952,6 +968,7 @@ impl Default for WindowFrame { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum WindowFrameUnits { Rows, Range, @@ -971,6 +988,7 @@ impl fmt::Display for WindowFrameUnits { /// Specifies [WindowFrame]'s `start_bound` and `end_bound` #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum WindowFrameBound { /// `CURRENT ROW` CurrentRow, @@ -994,6 +1012,7 @@ impl fmt::Display for WindowFrameBound { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum AddDropSync { ADD, DROP, @@ -1012,6 +1031,7 @@ impl fmt::Display for AddDropSync { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ShowCreateObject { Event, Function, @@ -1036,6 +1056,7 @@ impl fmt::Display for ShowCreateObject { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum CommentObject { Column, Table, @@ -1052,6 +1073,7 @@ impl fmt::Display for CommentObject { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum Password { Password(Expr), NullPassword, @@ -1061,9 +1083,11 @@ pub enum Password { #[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit), visit(with = "visit_statement"))] pub enum Statement { /// Analyze (Hive) Analyze { + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, partitions: Option>, for_columns: bool, @@ -1074,11 +1098,13 @@ pub enum Statement { }, /// Truncate (Hive) Truncate { + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, partitions: Option>, }, /// Msck (Hive) Msck { + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, repair: bool, partition_action: Option, @@ -1092,6 +1118,7 @@ pub enum Statement { /// INTO - optional keyword into: bool, /// TABLE + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, /// COLUMNS columns: Vec, @@ -1119,6 +1146,7 @@ pub enum Statement { }, Copy { /// TABLE + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, /// COLUMNS columns: Vec, @@ -1181,6 +1209,7 @@ pub enum Statement { global: Option, if_not_exists: bool, /// Table name + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] name: ObjectName, /// Optional schema columns: Vec, @@ -1205,6 +1234,7 @@ pub enum Statement { }, /// SQLite's `CREATE VIRTUAL TABLE .. USING ()` CreateVirtualTable { + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] name: ObjectName, if_not_exists: bool, module_name: Ident, @@ -1214,6 +1244,7 @@ pub enum Statement { CreateIndex { /// index name name: ObjectName, + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, using: Option, columns: Vec, @@ -1247,6 +1278,7 @@ pub enum Statement { /// ALTER TABLE AlterTable { /// Table name + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] name: ObjectName, operation: AlterTableOperation, }, @@ -1383,6 +1415,7 @@ pub enum Statement { ShowColumns { extended: bool, full: bool, + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, filter: Option, }, @@ -1498,9 +1531,10 @@ pub enum Statement { /// EXPLAIN TABLE /// Note: this is a MySQL-specific statement. See ExplainTable { - // If true, query used the MySQL `DESCRIBE` alias for explain + /// If true, query used the MySQL `DESCRIBE` alias for explain describe_alias: bool, - // Table name + /// Table name + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, }, /// EXPLAIN / DESCRIBE for select_statement @@ -1534,19 +1568,22 @@ pub enum Statement { /// CACHE [ FLAG ] TABLE [ OPTIONS('K1' = 'V1', 'K2' = V2) ] [ AS ] [ ] /// Based on Spark SQL,see Cache { - // Table flag + /// Table flag table_flag: Option, - // Table name + /// Table name + + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, has_as: bool, - // Table confs + /// Table confs options: Vec, - // Cache table as a Query + /// Cache table as a Query query: Option, }, /// UNCACHE TABLE [ IF EXISTS ] UNCache { - // Table name + /// Table name + #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, if_exists: bool, }, @@ -2673,6 +2710,7 @@ impl fmt::Display for Statement { /// [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ] #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum SequenceOptions { IncrementBy(Expr, bool), MinValue(MinMaxValue), @@ -2737,6 +2775,7 @@ impl fmt::Display for SequenceOptions { /// [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ] #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum MinMaxValue { // clause is not specified Empty, @@ -2748,6 +2787,7 @@ pub enum MinMaxValue { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] #[non_exhaustive] pub enum OnInsert { /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead) @@ -2758,18 +2798,21 @@ pub enum OnInsert { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct OnConflict { pub conflict_target: Option, pub action: OnConflictAction, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ConflictTarget { Columns(Vec), OnConstraint(ObjectName), } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum OnConflictAction { DoNothing, DoUpdate(DoUpdate), @@ -2777,6 +2820,7 @@ pub enum OnConflictAction { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct DoUpdate { /// Column assignments pub assignments: Vec, @@ -2838,6 +2882,7 @@ impl fmt::Display for OnConflictAction { /// Privileges granted in a GRANT statement or revoked in a REVOKE statement. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum Privileges { /// All privileges applicable to the object type All { @@ -2874,6 +2919,7 @@ impl fmt::Display for Privileges { /// Specific direction for FETCH statement #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum FetchDirection { Count { limit: Value }, Next, @@ -2937,6 +2983,7 @@ impl fmt::Display for FetchDirection { /// A privilege on a database object (table, sequence, etc.). #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum Action { Connect, Create, @@ -2986,6 +3033,7 @@ impl fmt::Display for Action { /// Objects on which privileges are granted in a GRANT statement. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum GrantObjects { /// Grant privileges on `ALL SEQUENCES IN SCHEMA [, ...]` AllSequencesInSchema { schemas: Vec }, @@ -3032,6 +3080,7 @@ impl fmt::Display for GrantObjects { /// SQL assignment `foo = expr` as used in SQLUpdate #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct Assignment { pub id: Vec, pub value: Expr, @@ -3045,6 +3094,7 @@ impl fmt::Display for Assignment { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum FunctionArgExpr { Expr(Expr), /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`. @@ -3065,6 +3115,7 @@ impl fmt::Display for FunctionArgExpr { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum FunctionArg { Named { name: Ident, arg: FunctionArgExpr }, Unnamed(FunctionArgExpr), @@ -3081,6 +3132,7 @@ impl fmt::Display for FunctionArg { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum CloseCursor { All, Specific { name: Ident }, @@ -3098,6 +3150,7 @@ impl fmt::Display for CloseCursor { /// A function call #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct Function { pub name: ObjectName, pub args: Vec, @@ -3111,6 +3164,7 @@ pub struct Function { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum AnalyzeFormat { TEXT, GRAPHVIZ, @@ -3152,6 +3206,7 @@ impl fmt::Display for Function { /// External table's available file format #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum FileFormat { TEXTFILE, SEQUENCEFILE, @@ -3181,6 +3236,7 @@ impl fmt::Display for FileFormat { /// [ WITHIN GROUP (ORDER BY [, ...] ) ]` #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct ListAgg { pub distinct: bool, pub expr: Box, @@ -3218,6 +3274,7 @@ impl fmt::Display for ListAgg { /// The `ON OVERFLOW` clause of a LISTAGG invocation #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ListAggOnOverflow { /// `ON OVERFLOW ERROR` Error, @@ -3255,6 +3312,7 @@ impl fmt::Display for ListAggOnOverflow { /// ORDER BY position is defined differently for BigQuery, Postgres and Snowflake. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct ArrayAgg { pub distinct: bool, pub expr: Box, @@ -3291,6 +3349,7 @@ impl fmt::Display for ArrayAgg { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ObjectType { Table, View, @@ -3315,6 +3374,7 @@ impl fmt::Display for ObjectType { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum KillType { Connection, Query, @@ -3335,6 +3395,7 @@ impl fmt::Display for KillType { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum HiveDistributionStyle { PARTITIONED { columns: Vec, @@ -3354,14 +3415,15 @@ pub enum HiveDistributionStyle { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum HiveRowFormat { SERDE { class: String }, DELIMITED, } -#[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] #[allow(clippy::large_enum_variant)] pub enum HiveIOFormat { IOF { @@ -3375,6 +3437,7 @@ pub enum HiveIOFormat { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct HiveFormat { pub row_format: Option, pub storage: Option, @@ -3383,6 +3446,7 @@ pub struct HiveFormat { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct SqlOption { pub name: Ident, pub value: Value, @@ -3396,6 +3460,7 @@ impl fmt::Display for SqlOption { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum TransactionMode { AccessMode(TransactionAccessMode), IsolationLevel(TransactionIsolationLevel), @@ -3413,6 +3478,7 @@ impl fmt::Display for TransactionMode { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum TransactionAccessMode { ReadOnly, ReadWrite, @@ -3430,6 +3496,7 @@ impl fmt::Display for TransactionAccessMode { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum TransactionIsolationLevel { ReadUncommitted, ReadCommitted, @@ -3451,6 +3518,7 @@ impl fmt::Display for TransactionIsolationLevel { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ShowStatementFilter { Like(String), ILike(String), @@ -3473,6 +3541,7 @@ impl fmt::Display for ShowStatementFilter { /// https://sqlite.org/lang_conflict.html #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum SqliteOnConflict { Rollback, Abort, @@ -3496,6 +3565,7 @@ impl fmt::Display for SqliteOnConflict { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum CopyTarget { Stdin, Stdout, @@ -3527,6 +3597,7 @@ impl fmt::Display for CopyTarget { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum OnCommit { DeleteRows, PreserveRows, @@ -3538,6 +3609,7 @@ pub enum OnCommit { /// #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum CopyOption { /// FORMAT format_name Format(Ident), @@ -3591,6 +3663,7 @@ impl fmt::Display for CopyOption { /// #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum CopyLegacyOption { /// BINARY Binary, @@ -3619,6 +3692,7 @@ impl fmt::Display for CopyLegacyOption { /// #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum CopyLegacyCsvOption { /// HEADER Header, @@ -3650,6 +3724,7 @@ impl fmt::Display for CopyLegacyCsvOption { /// #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum MergeClause { MatchedUpdate { predicate: Option, @@ -3711,6 +3786,7 @@ impl fmt::Display for MergeClause { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum DiscardObject { ALL, PLANS, @@ -3732,6 +3808,7 @@ impl fmt::Display for DiscardObject { /// Optional context modifier for statements that can be or `LOCAL`, or `SESSION`. #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ContextModifier { /// No context defined. Each dialect defines the default in this scenario. None, @@ -3777,6 +3854,7 @@ impl fmt::Display for DropFunctionOption { /// Function describe in DROP FUNCTION. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct DropFunctionDesc { pub name: ObjectName, pub args: Option>, @@ -3795,6 +3873,7 @@ impl fmt::Display for DropFunctionDesc { /// Function argument in CREATE OR DROP FUNCTION. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct OperateFunctionArg { pub mode: Option, pub name: Option, @@ -3843,6 +3922,7 @@ impl fmt::Display for OperateFunctionArg { /// The mode of an argument in CREATE FUNCTION. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum ArgMode { In, Out, @@ -3862,6 +3942,7 @@ impl fmt::Display for ArgMode { /// These attributes inform the query optimizer about the behavior of the function. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum FunctionBehavior { Immutable, Stable, @@ -3880,6 +3961,7 @@ impl fmt::Display for FunctionBehavior { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum FunctionDefinition { SingleQuotedDef(String), DoubleDollarDef(String), @@ -3898,6 +3980,7 @@ impl fmt::Display for FunctionDefinition { /// Postgres: https://www.postgresql.org/docs/15/sql-createfunction.html #[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct CreateFunctionBody { /// LANGUAGE lang_name pub language: Option, @@ -3936,6 +4019,7 @@ impl fmt::Display for CreateFunctionBody { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum CreateFunctionUsing { Jar(String), File(String), @@ -3958,6 +4042,7 @@ impl fmt::Display for CreateFunctionUsing { /// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#schema-definition #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum SchemaName { /// Only schema name specified: ``. Simple(ObjectName), @@ -3988,6 +4073,7 @@ impl fmt::Display for SchemaName { /// [1]: https://dev.mysql.com/doc/refman/8.0/en/fulltext-search.html#function_match #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum SearchModifier { /// `IN NATURAL LANGUAGE MODE`. InNaturalLanguageMode, diff --git a/src/ast/operator.rs b/src/ast/operator.rs index f22839474..b8f371be3 100644 --- a/src/ast/operator.rs +++ b/src/ast/operator.rs @@ -14,14 +14,19 @@ use core::fmt; #[cfg(not(feature = "std"))] use alloc::{string::String, vec::Vec}; + #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "visitor")] +use sqlparser_derive::Visit; + use super::display_separated; /// Unary operators #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum UnaryOperator { Plus, Minus, @@ -59,6 +64,7 @@ impl fmt::Display for UnaryOperator { /// Binary operators #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum BinaryOperator { Plus, Minus, diff --git a/src/ast/query.rs b/src/ast/query.rs index 9d23b1ae7..7a009c2ed 100644 --- a/src/ast/query.rs +++ b/src/ast/query.rs @@ -16,12 +16,16 @@ use alloc::{boxed::Box, vec::Vec}; #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; +#[cfg(feature = "visitor")] +use sqlparser_derive::Visit; + use crate::ast::*; /// The most complete variant of a `SELECT` query expression, optionally /// including `WITH`, `UNION` / other set operations, and `ORDER BY`. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub struct Query { /// WITH (common table expressions, or CTEs) pub with: Option, @@ -69,6 +73,7 @@ impl fmt::Display for Query { #[allow(clippy::large_enum_variant)] #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit))] pub enum SetExpr { /// Restricted SELECT .. FROM .. HAVING (no ORDER BY or set operations) Select(Box