You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@datafusion.apache.org by gi...@apache.org on 2025/10/10 14:08:46 UTC

(datafusion-sqlparser-rs) branch gh-readonly-queue/main/pr-2057-e7d42f3d1a3fb6a542b70d8bef945db2c67bcf06 created (now cc595cfd)

This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a change to branch gh-readonly-queue/main/pr-2057-e7d42f3d1a3fb6a542b70d8bef945db2c67bcf06
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git


      at cc595cfd Moving several struct variants out of `Statement` enum to allow for trait impls for specific sub-variants (#2057)

This branch includes the following new commits:

     new cc595cfd Moving several struct variants out of `Statement` enum to allow for trait impls for specific sub-variants (#2057)

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org


(datafusion-sqlparser-rs) 01/01: Moving several struct variants out of `Statement` enum to allow for trait impls for specific sub-variants (#2057)

Posted by gi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

github-bot pushed a commit to branch gh-readonly-queue/main/pr-2057-e7d42f3d1a3fb6a542b70d8bef945db2c67bcf06
in repository https://gitbox.apache.org/repos/asf/datafusion-sqlparser-rs.git

commit cc595cfd847f6e4b8edb6def67535e0a499b8845
Author: Luca Cappelletti <ca...@gmail.com>
AuthorDate: Fri Oct 10 16:08:20 2025 +0200

    Moving several struct variants out of `Statement` enum to allow for trait impls for specific sub-variants (#2057)
---
 src/ast/dcl.rs                | 113 ++++++-
 src/ast/ddl.rs                | 412 +++++++++++++++++++++++-
 src/ast/dml.rs                |  65 +++-
 src/ast/mod.rs                | 719 +++++++++---------------------------------
 src/ast/spans.rs              | 200 ++++++------
 src/parser/mod.rs             |  48 +--
 src/test_utils.rs             |  23 +-
 tests/sqlparser_bigquery.rs   |  12 +-
 tests/sqlparser_clickhouse.rs |  30 +-
 tests/sqlparser_common.rs     | 111 +++----
 tests/sqlparser_mssql.rs      |  10 +-
 tests/sqlparser_mysql.rs      |  38 +--
 tests/sqlparser_postgres.rs   | 193 +++++-------
 tests/sqlparser_snowflake.rs  |  10 +-
 tests/sqlparser_sqlite.rs     |  10 +-
 15 files changed, 1032 insertions(+), 962 deletions(-)

diff --git a/src/ast/dcl.rs b/src/ast/dcl.rs
index 07989407..d04875a7 100644
--- a/src/ast/dcl.rs
+++ b/src/ast/dcl.rs
@@ -28,8 +28,9 @@ use serde::{Deserialize, Serialize};
 #[cfg(feature = "visitor")]
 use sqlparser_derive::{Visit, VisitMut};
 
-use super::{display_comma_separated, Expr, Ident, Password};
+use super::{display_comma_separated, Expr, Ident, Password, Spanned};
 use crate::ast::{display_separated, ObjectName};
+use crate::tokenizer::Span;
 
 /// An option in `ROLE` statement.
 ///
@@ -252,3 +253,113 @@ impl fmt::Display for SecondaryRoles {
         }
     }
 }
+
+/// CREATE ROLE statement
+/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateRole {
+    pub names: Vec<ObjectName>,
+    pub if_not_exists: bool,
+    // Postgres
+    pub login: Option<bool>,
+    pub inherit: Option<bool>,
+    pub bypassrls: Option<bool>,
+    pub password: Option<Password>,
+    pub superuser: Option<bool>,
+    pub create_db: Option<bool>,
+    pub create_role: Option<bool>,
+    pub replication: Option<bool>,
+    pub connection_limit: Option<Expr>,
+    pub valid_until: Option<Expr>,
+    pub in_role: Vec<Ident>,
+    pub in_group: Vec<Ident>,
+    pub role: Vec<Ident>,
+    pub user: Vec<Ident>,
+    pub admin: Vec<Ident>,
+    // MSSQL
+    pub authorization_owner: Option<ObjectName>,
+}
+
+impl fmt::Display for CreateRole {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
+            if_not_exists = if self.if_not_exists { "IF NOT EXISTS " } else { "" },
+            names = display_separated(&self.names, ", "),
+            superuser = match self.superuser {
+                Some(true) => " SUPERUSER",
+                Some(false) => " NOSUPERUSER",
+                None => ""
+            },
+            create_db = match self.create_db {
+                Some(true) => " CREATEDB",
+                Some(false) => " NOCREATEDB",
+                None => ""
+            },
+            create_role = match self.create_role {
+                Some(true) => " CREATEROLE",
+                Some(false) => " NOCREATEROLE",
+                None => ""
+            },
+            inherit = match self.inherit {
+                Some(true) => " INHERIT",
+                Some(false) => " NOINHERIT",
+                None => ""
+            },
+            login = match self.login {
+                Some(true) => " LOGIN",
+                Some(false) => " NOLOGIN",
+                None => ""
+            },
+            replication = match self.replication {
+                Some(true) => " REPLICATION",
+                Some(false) => " NOREPLICATION",
+                None => ""
+            },
+            bypassrls = match self.bypassrls {
+                Some(true) => " BYPASSRLS",
+                Some(false) => " NOBYPASSRLS",
+                None => ""
+            }
+        )?;
+        if let Some(limit) = &self.connection_limit {
+            write!(f, " CONNECTION LIMIT {limit}")?;
+        }
+        match &self.password {
+            Some(Password::Password(pass)) => write!(f, " PASSWORD {pass}")?,
+            Some(Password::NullPassword) => write!(f, " PASSWORD NULL")?,
+            None => {}
+        };
+        if let Some(until) = &self.valid_until {
+            write!(f, " VALID UNTIL {until}")?;
+        }
+        if !self.in_role.is_empty() {
+            write!(f, " IN ROLE {}", display_comma_separated(&self.in_role))?;
+        }
+        if !self.in_group.is_empty() {
+            write!(f, " IN GROUP {}", display_comma_separated(&self.in_group))?;
+        }
+        if !self.role.is_empty() {
+            write!(f, " ROLE {}", display_comma_separated(&self.role))?;
+        }
+        if !self.user.is_empty() {
+            write!(f, " USER {}", display_comma_separated(&self.user))?;
+        }
+        if !self.admin.is_empty() {
+            write!(f, " ADMIN {}", display_comma_separated(&self.admin))?;
+        }
+        if let Some(owner) = &self.authorization_owner {
+            write!(f, " AUTHORIZATION {owner}")?;
+        }
+        Ok(())
+    }
+}
+
+impl Spanned for CreateRole {
+    fn span(&self) -> Span {
+        Span::empty()
+    }
+}
diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs
index c6ab7ad1..aafa8e64 100644
--- a/src/ast/ddl.rs
+++ b/src/ast/ddl.rs
@@ -19,7 +19,7 @@
 //! (commonly referred to as Data Definition Language, or DDL)
 
 #[cfg(not(feature = "std"))]
-use alloc::{boxed::Box, string::String, vec::Vec};
+use alloc::{boxed::Box, format, string::String, vec, vec::Vec};
 use core::fmt::{self, Display, Write};
 
 #[cfg(feature = "serde")]
@@ -30,15 +30,16 @@ use sqlparser_derive::{Visit, VisitMut};
 
 use crate::ast::value::escape_single_quote_string;
 use crate::ast::{
-    display_comma_separated, display_separated, table_constraints::TableConstraint, ArgMode,
-    CommentDef, ConditionalStatements, CreateFunctionBody, CreateFunctionUsing,
-    CreateTableLikeKind, CreateTableOptions, DataType, Expr, FileFormat, FunctionBehavior,
-    FunctionCalledOnNull, FunctionDeterminismSpecifier, FunctionParallel, HiveDistributionStyle,
-    HiveFormat, HiveIOFormat, HiveRowFormat, Ident, InitializeKind, MySQLColumnPosition,
-    ObjectName, OnCommit, OneOrManyWithParens, OperateFunctionArg, OrderByExpr, ProjectionSelect,
-    Query, RefreshModeKind, RowAccessPolicy, SequenceOptions, Spanned, SqlOption,
-    StorageSerializationPolicy, TableVersion, Tag, TriggerEvent, TriggerExecBody, TriggerObject,
-    TriggerPeriod, TriggerReferencing, Value, ValueWithSpan, WrappedCollection,
+    display_comma_separated, display_separated, ArgMode, AttachedToken, CommentDef,
+    ConditionalStatements, CreateFunctionBody, CreateFunctionUsing, CreateTableLikeKind,
+    CreateTableOptions, CreateViewParams, DataType, Expr, FileFormat, FunctionBehavior,
+    FunctionCalledOnNull, FunctionDesc, FunctionDeterminismSpecifier, FunctionParallel,
+    HiveDistributionStyle, HiveFormat, HiveIOFormat, HiveRowFormat, HiveSetLocation, Ident,
+    InitializeKind, MySQLColumnPosition, ObjectName, OnCommit, OneOrManyWithParens,
+    OperateFunctionArg, OrderByExpr, ProjectionSelect, Query, RefreshModeKind, RowAccessPolicy,
+    SequenceOptions, Spanned, SqlOption, StorageSerializationPolicy, TableConstraint, TableVersion,
+    Tag, TriggerEvent, TriggerExecBody, TriggerObject, TriggerPeriod, TriggerReferencing, Value,
+    ValueWithSpan, WrappedCollection,
 };
 use crate::display_utils::{DisplayCommaSeparated, Indent, NewLine, SpaceOrNewline};
 use crate::keywords::Keyword;
@@ -3138,3 +3139,394 @@ impl fmt::Display for DropTrigger {
         Ok(())
     }
 }
+
+/// A `TRUNCATE` statement.
+///
+/// ```sql
+/// TRUNCATE TABLE table_names [PARTITION (partitions)] [RESTART IDENTITY | CONTINUE IDENTITY] [CASCADE | RESTRICT] [ON CLUSTER cluster_name]
+/// ```
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Truncate {
+    /// Table names to truncate
+    pub table_names: Vec<super::TruncateTableTarget>,
+    /// Optional partition specification
+    pub partitions: Option<Vec<Expr>>,
+    /// TABLE - optional keyword
+    pub table: bool,
+    /// Postgres-specific option: [ RESTART IDENTITY | CONTINUE IDENTITY ]
+    pub identity: Option<super::TruncateIdentityOption>,
+    /// Postgres-specific option: [ CASCADE | RESTRICT ]
+    pub cascade: Option<super::CascadeOption>,
+    /// ClickHouse-specific option: [ ON CLUSTER cluster_name ]
+    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/truncate/)
+    pub on_cluster: Option<Ident>,
+}
+
+impl fmt::Display for Truncate {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        let table = if self.table { "TABLE " } else { "" };
+
+        write!(
+            f,
+            "TRUNCATE {table}{table_names}",
+            table_names = display_comma_separated(&self.table_names)
+        )?;
+
+        if let Some(identity) = &self.identity {
+            match identity {
+                super::TruncateIdentityOption::Restart => write!(f, " RESTART IDENTITY")?,
+                super::TruncateIdentityOption::Continue => write!(f, " CONTINUE IDENTITY")?,
+            }
+        }
+        if let Some(cascade) = &self.cascade {
+            match cascade {
+                super::CascadeOption::Cascade => write!(f, " CASCADE")?,
+                super::CascadeOption::Restrict => write!(f, " RESTRICT")?,
+            }
+        }
+
+        if let Some(ref parts) = &self.partitions {
+            if !parts.is_empty() {
+                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
+            }
+        }
+        if let Some(on_cluster) = &self.on_cluster {
+            write!(f, " ON CLUSTER {on_cluster}")?;
+        }
+        Ok(())
+    }
+}
+
+impl Spanned for Truncate {
+    fn span(&self) -> Span {
+        Span::union_iter(
+            self.table_names.iter().map(|i| i.name.span()).chain(
+                self.partitions
+                    .iter()
+                    .flat_map(|i| i.iter().map(|k| k.span())),
+            ),
+        )
+    }
+}
+
+/// An `MSCK` statement.
+///
+/// ```sql
+/// MSCK [REPAIR] TABLE table_name [ADD|DROP|SYNC PARTITIONS]
+/// ```
+/// MSCK (Hive) - MetaStore Check command
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Msck {
+    /// Table name to check
+    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
+    pub table_name: ObjectName,
+    /// Whether to repair the table
+    pub repair: bool,
+    /// Partition action (ADD, DROP, or SYNC)
+    pub partition_action: Option<super::AddDropSync>,
+}
+
+impl fmt::Display for Msck {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "MSCK {repair}TABLE {table}",
+            repair = if self.repair { "REPAIR " } else { "" },
+            table = self.table_name
+        )?;
+        if let Some(pa) = &self.partition_action {
+            write!(f, " {pa}")?;
+        }
+        Ok(())
+    }
+}
+
+impl Spanned for Msck {
+    fn span(&self) -> Span {
+        self.table_name.span()
+    }
+}
+
+/// CREATE VIEW statement.
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateView {
+    /// True if this is a `CREATE OR ALTER VIEW` statement
+    ///
+    /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql)
+    pub or_alter: bool,
+    pub or_replace: bool,
+    pub materialized: bool,
+    /// Snowflake: SECURE view modifier
+    /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
+    pub secure: bool,
+    /// View name
+    pub name: ObjectName,
+    /// If `if_not_exists` is true, this flag is set to true if the view name comes before the `IF NOT EXISTS` clause.
+    /// Example:
+    /// ```sql
+    /// CREATE VIEW myview IF NOT EXISTS AS SELECT 1`
+    ///  ```
+    /// Otherwise, the flag is set to false if the view name comes after the clause
+    /// Example:
+    /// ```sql
+    /// CREATE VIEW IF NOT EXISTS myview AS SELECT 1`
+    ///  ```
+    pub name_before_not_exists: bool,
+    pub columns: Vec<ViewColumnDef>,
+    pub query: Box<Query>,
+    pub options: CreateTableOptions,
+    pub cluster_by: Vec<Ident>,
+    /// Snowflake: Views can have comments in Snowflake.
+    /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
+    pub comment: Option<String>,
+    /// if true, has RedShift [`WITH NO SCHEMA BINDING`] clause <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html>
+    pub with_no_schema_binding: bool,
+    /// if true, has SQLite `IF NOT EXISTS` clause <https://www.sqlite.org/lang_createview.html>
+    pub if_not_exists: bool,
+    /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
+    pub temporary: bool,
+    /// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
+    /// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
+    pub to: Option<ObjectName>,
+    /// MySQL: Optional parameters for the view algorithm, definer, and security context
+    pub params: Option<CreateViewParams>,
+}
+
+impl fmt::Display for CreateView {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "CREATE {or_alter}{or_replace}",
+            or_alter = if self.or_alter { "OR ALTER " } else { "" },
+            or_replace = if self.or_replace { "OR REPLACE " } else { "" },
+        )?;
+        if let Some(ref params) = self.params {
+            params.fmt(f)?;
+        }
+        write!(
+            f,
+            "{secure}{materialized}{temporary}VIEW {if_not_and_name}{to}",
+            if_not_and_name = if self.if_not_exists {
+                if self.name_before_not_exists {
+                    format!("{} IF NOT EXISTS", self.name)
+                } else {
+                    format!("IF NOT EXISTS {}", self.name)
+                }
+            } else {
+                format!("{}", self.name)
+            },
+            secure = if self.secure { "SECURE " } else { "" },
+            materialized = if self.materialized {
+                "MATERIALIZED "
+            } else {
+                ""
+            },
+            temporary = if self.temporary { "TEMPORARY " } else { "" },
+            to = self
+                .to
+                .as_ref()
+                .map(|to| format!(" TO {to}"))
+                .unwrap_or_default()
+        )?;
+        if !self.columns.is_empty() {
+            write!(f, " ({})", display_comma_separated(&self.columns))?;
+        }
+        if matches!(self.options, CreateTableOptions::With(_)) {
+            write!(f, " {}", self.options)?;
+        }
+        if let Some(ref comment) = self.comment {
+            write!(f, " COMMENT = '{}'", escape_single_quote_string(comment))?;
+        }
+        if !self.cluster_by.is_empty() {
+            write!(
+                f,
+                " CLUSTER BY ({})",
+                display_comma_separated(&self.cluster_by)
+            )?;
+        }
+        if matches!(self.options, CreateTableOptions::Options(_)) {
+            write!(f, " {}", self.options)?;
+        }
+        f.write_str(" AS")?;
+        SpaceOrNewline.fmt(f)?;
+        self.query.fmt(f)?;
+        if self.with_no_schema_binding {
+            write!(f, " WITH NO SCHEMA BINDING")?;
+        }
+        Ok(())
+    }
+}
+
+/// CREATE EXTENSION statement
+/// Note: this is a PostgreSQL-specific statement
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateExtension {
+    pub name: Ident,
+    pub if_not_exists: bool,
+    pub cascade: bool,
+    pub schema: Option<Ident>,
+    pub version: Option<Ident>,
+}
+
+impl fmt::Display for CreateExtension {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "CREATE EXTENSION {if_not_exists}{name}",
+            if_not_exists = if self.if_not_exists {
+                "IF NOT EXISTS "
+            } else {
+                ""
+            },
+            name = self.name
+        )?;
+        if self.cascade || self.schema.is_some() || self.version.is_some() {
+            write!(f, " WITH")?;
+
+            if let Some(name) = &self.schema {
+                write!(f, " SCHEMA {name}")?;
+            }
+            if let Some(version) = &self.version {
+                write!(f, " VERSION {version}")?;
+            }
+            if self.cascade {
+                write!(f, " CASCADE")?;
+            }
+        }
+
+        Ok(())
+    }
+}
+
+impl Spanned for CreateExtension {
+    fn span(&self) -> Span {
+        Span::empty()
+    }
+}
+
+/// DROP EXTENSION statement  
+/// Note: this is a PostgreSQL-specific statement
+///
+/// # References
+///
+/// PostgreSQL Documentation:
+/// <https://www.postgresql.org/docs/current/sql-dropextension.html>
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DropExtension {
+    pub names: Vec<Ident>,
+    pub if_exists: bool,
+    /// `CASCADE` or `RESTRICT`
+    pub cascade_or_restrict: Option<ReferentialAction>,
+}
+
+impl fmt::Display for DropExtension {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "DROP EXTENSION")?;
+        if self.if_exists {
+            write!(f, " IF EXISTS")?;
+        }
+        write!(f, " {}", display_comma_separated(&self.names))?;
+        if let Some(cascade_or_restrict) = &self.cascade_or_restrict {
+            write!(f, " {cascade_or_restrict}")?;
+        }
+        Ok(())
+    }
+}
+
+impl Spanned for DropExtension {
+    fn span(&self) -> Span {
+        Span::empty()
+    }
+}
+
+/// ALTER TABLE statement
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct AlterTable {
+    /// Table name
+    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
+    pub name: ObjectName,
+    pub if_exists: bool,
+    pub only: bool,
+    pub operations: Vec<AlterTableOperation>,
+    pub location: Option<HiveSetLocation>,
+    /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE
+    /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
+    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
+    pub on_cluster: Option<Ident>,
+    /// Snowflake "ICEBERG" clause for Iceberg tables
+    /// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
+    pub iceberg: bool,
+    /// Token that represents the end of the statement (semicolon or EOF)
+    pub end_token: AttachedToken,
+}
+
+impl fmt::Display for AlterTable {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        if self.iceberg {
+            write!(f, "ALTER ICEBERG TABLE ")?;
+        } else {
+            write!(f, "ALTER TABLE ")?;
+        }
+
+        if self.if_exists {
+            write!(f, "IF EXISTS ")?;
+        }
+        if self.only {
+            write!(f, "ONLY ")?;
+        }
+        write!(f, "{} ", &self.name)?;
+        if let Some(cluster) = &self.on_cluster {
+            write!(f, "ON CLUSTER {cluster} ")?;
+        }
+        write!(f, "{}", display_comma_separated(&self.operations))?;
+        if let Some(loc) = &self.location {
+            write!(f, " {loc}")?
+        }
+        Ok(())
+    }
+}
+
+/// DROP FUNCTION statement
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DropFunction {
+    pub if_exists: bool,
+    /// One or more functions to drop
+    pub func_desc: Vec<FunctionDesc>,
+    /// `CASCADE` or `RESTRICT`
+    pub drop_behavior: Option<DropBehavior>,
+}
+
+impl fmt::Display for DropFunction {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "DROP FUNCTION{} {}",
+            if self.if_exists { " IF EXISTS" } else { "" },
+            display_comma_separated(&self.func_desc),
+        )?;
+        if let Some(op) = &self.drop_behavior {
+            write!(f, " {op}")?;
+        }
+        Ok(())
+    }
+}
+
+impl Spanned for DropFunction {
+    fn span(&self) -> Span {
+        Span::empty()
+    }
+}
diff --git a/src/ast/dml.rs b/src/ast/dml.rs
index e4d99bcf..c0bfcb19 100644
--- a/src/ast/dml.rs
+++ b/src/ast/dml.rs
@@ -29,7 +29,7 @@ use crate::display_utils::{indented_list, Indent, SpaceOrNewline};
 use super::{
     display_comma_separated, query::InputFormatClause, Assignment, Expr, FromTable, Ident,
     InsertAliases, MysqlInsertPriority, ObjectName, OnInsert, OrderByExpr, Query, SelectItem,
-    Setting, SqliteOnConflict, TableObject, TableWithJoins,
+    Setting, SqliteOnConflict, TableObject, TableWithJoins, UpdateTableFromKind,
 };
 
 /// INSERT statement.
@@ -240,3 +240,66 @@ impl Display for Delete {
         Ok(())
     }
 }
+
+/// UPDATE statement.
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Update {
+    /// TABLE
+    pub table: TableWithJoins,
+    /// Column assignments
+    pub assignments: Vec<Assignment>,
+    /// Table which provide value to be set
+    pub from: Option<UpdateTableFromKind>,
+    /// WHERE
+    pub selection: Option<Expr>,
+    /// RETURNING
+    pub returning: Option<Vec<SelectItem>>,
+    /// SQLite-specific conflict resolution clause
+    pub or: Option<SqliteOnConflict>,
+    /// LIMIT
+    pub limit: Option<Expr>,
+}
+
+impl Display for Update {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str("UPDATE ")?;
+        if let Some(or) = &self.or {
+            or.fmt(f)?;
+            f.write_str(" ")?;
+        }
+        self.table.fmt(f)?;
+        if let Some(UpdateTableFromKind::BeforeSet(from)) = &self.from {
+            SpaceOrNewline.fmt(f)?;
+            f.write_str("FROM")?;
+            indented_list(f, from)?;
+        }
+        if !self.assignments.is_empty() {
+            SpaceOrNewline.fmt(f)?;
+            f.write_str("SET")?;
+            indented_list(f, &self.assignments)?;
+        }
+        if let Some(UpdateTableFromKind::AfterSet(from)) = &self.from {
+            SpaceOrNewline.fmt(f)?;
+            f.write_str("FROM")?;
+            indented_list(f, from)?;
+        }
+        if let Some(selection) = &self.selection {
+            SpaceOrNewline.fmt(f)?;
+            f.write_str("WHERE")?;
+            SpaceOrNewline.fmt(f)?;
+            Indent(selection).fmt(f)?;
+        }
+        if let Some(returning) = &self.returning {
+            SpaceOrNewline.fmt(f)?;
+            f.write_str("RETURNING")?;
+            indented_list(f, returning)?;
+        }
+        if let Some(limit) = &self.limit {
+            SpaceOrNewline.fmt(f)?;
+            write!(f, "LIMIT {limit}")?;
+        }
+        Ok(())
+    }
+}
diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index 52968d7d..0c83b320 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -43,7 +43,7 @@ use serde::{Deserialize, Serialize};
 use sqlparser_derive::{Visit, VisitMut};
 
 use crate::{
-    display_utils::{indented_list, SpaceOrNewline},
+    display_utils::SpaceOrNewline,
     tokenizer::{Span, Token},
 };
 use crate::{
@@ -56,22 +56,24 @@ pub use self::data_type::{
     ExactNumberInfo, IntervalFields, StructBracketKind, TimezoneInfo,
 };
 pub use self::dcl::{
-    AlterRoleOperation, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
+    AlterRoleOperation, CreateRole, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
 };
 pub use self::ddl::{
     AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterPolicyOperation,
-    AlterSchema, AlterSchemaOperation, AlterTableAlgorithm, AlterTableLock, AlterTableOperation,
-    AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename,
-    AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
-    ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain,
-    CreateFunction, CreateIndex, CreateTable, CreateTrigger, Deduplicate, DeferrableInitial,
-    DropBehavior, DropTrigger, GeneratedAs, GeneratedExpressionMode, IdentityParameters,
-    IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
-    IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, NullsDistinctOption, Owner, Partition,
-    ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TagsColumnOption,
-    UserDefinedTypeCompositeAttributeDef, UserDefinedTypeRepresentation, ViewColumnDef,
+    AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm, AlterTableLock,
+    AlterTableOperation, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
+    AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
+    ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty,
+    ConstraintCharacteristics, CreateConnector, CreateDomain, CreateExtension, CreateFunction,
+    CreateIndex, CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial,
+    DropBehavior, DropExtension, DropFunction, DropTrigger, GeneratedAs, GeneratedExpressionMode,
+    IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind,
+    IdentityPropertyOrder, IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, Msck,
+    NullsDistinctOption, Owner, Partition, ProcedureParam, ReferentialAction, RenameTableNameKind,
+    ReplicaIdentity, TagsColumnOption, Truncate, UserDefinedTypeCompositeAttributeDef,
+    UserDefinedTypeRepresentation, ViewColumnDef,
 };
-pub use self::dml::{Delete, Insert};
+pub use self::dml::{Delete, Insert, Update};
 pub use self::operator::{BinaryOperator, UnaryOperator};
 pub use self::query::{
     AfterMatchSkip, ConnectBy, Cte, CteAsMaterialized, Distinct, EmptyMatchesMode,
@@ -3064,6 +3066,59 @@ impl Display for ExceptionWhen {
     }
 }
 
+/// ANALYZE TABLE statement (Hive-specific)
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct Analyze {
+    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
+    pub table_name: ObjectName,
+    pub partitions: Option<Vec<Expr>>,
+    pub for_columns: bool,
+    pub columns: Vec<Ident>,
+    pub cache_metadata: bool,
+    pub noscan: bool,
+    pub compute_statistics: bool,
+    pub has_table_keyword: bool,
+}
+
+impl fmt::Display for Analyze {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(
+            f,
+            "ANALYZE{}{table_name}",
+            if self.has_table_keyword {
+                " TABLE "
+            } else {
+                " "
+            },
+            table_name = self.table_name
+        )?;
+        if let Some(ref parts) = self.partitions {
+            if !parts.is_empty() {
+                write!(f, " PARTITION ({})", display_comma_separated(parts))?;
+            }
+        }
+
+        if self.compute_statistics {
+            write!(f, " COMPUTE STATISTICS")?;
+        }
+        if self.noscan {
+            write!(f, " NOSCAN")?;
+        }
+        if self.cache_metadata {
+            write!(f, " CACHE METADATA")?;
+        }
+        if self.for_columns {
+            write!(f, " FOR COLUMNS")?;
+            if !self.columns.is_empty() {
+                write!(f, " {}", display_comma_separated(&self.columns))?;
+            }
+        }
+        Ok(())
+    }
+}
+
 /// A top-level statement (SELECT, INSERT, CREATE, etc.)
 #[allow(clippy::large_enum_variant)]
 #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
@@ -3078,49 +3133,18 @@ pub enum Statement {
     /// ANALYZE
     /// ```
     /// Analyze (Hive)
-    Analyze {
-        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
-        table_name: ObjectName,
-        partitions: Option<Vec<Expr>>,
-        for_columns: bool,
-        columns: Vec<Ident>,
-        cache_metadata: bool,
-        noscan: bool,
-        compute_statistics: bool,
-        has_table_keyword: bool,
-    },
+    Analyze(Analyze),
     Set(Set),
     /// ```sql
     /// TRUNCATE
     /// ```
     /// Truncate (Hive)
-    Truncate {
-        table_names: Vec<TruncateTableTarget>,
-        partitions: Option<Vec<Expr>>,
-        /// TABLE - optional keyword;
-        table: bool,
-        /// Postgres-specific option
-        /// [ RESTART IDENTITY | CONTINUE IDENTITY ]
-        identity: Option<TruncateIdentityOption>,
-        /// Postgres-specific option
-        /// [ CASCADE | RESTRICT ]
-        cascade: Option<CascadeOption>,
-        /// ClickHouse-specific option
-        /// [ ON CLUSTER cluster_name ]
-        ///
-        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/truncate/)
-        on_cluster: Option<Ident>,
-    },
+    Truncate(Truncate),
     /// ```sql
     /// MSCK
     /// ```
     /// Msck (Hive)
-    Msck {
-        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
-        table_name: ObjectName,
-        repair: bool,
-        partition_action: Option<AddDropSync>,
-    },
+    Msck(Msck),
     /// ```sql
     /// SELECT
     /// ```
@@ -3223,22 +3247,7 @@ pub enum Statement {
     /// ```sql
     /// UPDATE
     /// ```
-    Update {
-        /// TABLE
-        table: TableWithJoins,
-        /// Column assignments
-        assignments: Vec<Assignment>,
-        /// Table which provide value to be set
-        from: Option<UpdateTableFromKind>,
-        /// WHERE
-        selection: Option<Expr>,
-        /// RETURNING
-        returning: Option<Vec<SelectItem>>,
-        /// SQLite-specific conflict resolution clause
-        or: Option<SqliteOnConflict>,
-        /// LIMIT
-        limit: Option<Expr>,
-    },
+    Update(Update),
     /// ```sql
     /// DELETE
     /// ```
@@ -3246,48 +3255,7 @@ pub enum Statement {
     /// ```sql
     /// CREATE VIEW
     /// ```
-    CreateView {
-        /// True if this is a `CREATE OR ALTER VIEW` statement
-        ///
-        /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql)
-        or_alter: bool,
-        or_replace: bool,
-        materialized: bool,
-        /// Snowflake: SECURE view modifier
-        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
-        secure: bool,
-        /// View name
-        name: ObjectName,
-        /// If `if_not_exists` is true, this flag is set to true if the view name comes before the `IF NOT EXISTS` clause.
-        /// Example:
-        /// ```sql
-        /// CREATE VIEW myview IF NOT EXISTS AS SELECT 1`
-        ///  ```
-        /// Otherwise, the flag is set to false if the view name comes after the clause
-        /// Example:
-        /// ```sql
-        /// CREATE VIEW IF NOT EXISTS myview AS SELECT 1`
-        ///  ```
-        name_before_not_exists: bool,
-        columns: Vec<ViewColumnDef>,
-        query: Box<Query>,
-        options: CreateTableOptions,
-        cluster_by: Vec<Ident>,
-        /// Snowflake: Views can have comments in Snowflake.
-        /// <https://docs.snowflake.com/en/sql-reference/sql/create-view#syntax>
-        comment: Option<String>,
-        /// if true, has RedShift [`WITH NO SCHEMA BINDING`] clause <https://docs.aws.amazon.com/redshift/latest/dg/r_CREATE_VIEW.html>
-        with_no_schema_binding: bool,
-        /// if true, has SQLite `IF NOT EXISTS` clause <https://www.sqlite.org/lang_createview.html>
-        if_not_exists: bool,
-        /// if true, has SQLite `TEMP` or `TEMPORARY` clause <https://www.sqlite.org/lang_createview.html>
-        temporary: bool,
-        /// if not None, has Clickhouse `TO` clause, specify the table into which to insert results
-        /// <https://clickhouse.com/docs/en/sql-reference/statements/create/view#materialized-view>
-        to: Option<ObjectName>,
-        /// MySQL: Optional parameters for the view algorithm, definer, and security context
-        params: Option<CreateViewParams>,
-    },
+    CreateView(CreateView),
     /// ```sql
     /// CREATE TABLE
     /// ```
@@ -3311,28 +3279,7 @@ pub enum Statement {
     /// CREATE ROLE
     /// ```
     /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createrole.html)
-    CreateRole {
-        names: Vec<ObjectName>,
-        if_not_exists: bool,
-        // Postgres
-        login: Option<bool>,
-        inherit: Option<bool>,
-        bypassrls: Option<bool>,
-        password: Option<Password>,
-        superuser: Option<bool>,
-        create_db: Option<bool>,
-        create_role: Option<bool>,
-        replication: Option<bool>,
-        connection_limit: Option<Expr>,
-        valid_until: Option<Expr>,
-        in_role: Vec<Ident>,
-        in_group: Vec<Ident>,
-        role: Vec<Ident>,
-        user: Vec<Ident>,
-        admin: Vec<Ident>,
-        // MSSQL
-        authorization_owner: Option<ObjectName>,
-    },
+    CreateRole(CreateRole),
     /// ```sql
     /// CREATE SECRET
     /// ```
@@ -3370,24 +3317,7 @@ pub enum Statement {
     /// ```sql
     /// ALTER TABLE
     /// ```
-    AlterTable {
-        /// Table name
-        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
-        name: ObjectName,
-        if_exists: bool,
-        only: bool,
-        operations: Vec<AlterTableOperation>,
-        location: Option<HiveSetLocation>,
-        /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE
-        /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32`
-        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/update)
-        on_cluster: Option<Ident>,
-        /// Snowflake "ICEBERG" clause for Iceberg tables
-        /// <https://docs.snowflake.com/en/sql-reference/sql/alter-iceberg-table>
-        iceberg: bool,
-        /// Token that represents the end of the statement (semicolon or EOF)
-        end_token: AttachedToken,
-    },
+    AlterTable(AlterTable),
     /// ```sql
     /// ALTER SCHEMA
     /// ```
@@ -3523,13 +3453,7 @@ pub enum Statement {
     /// ```sql
     /// DROP FUNCTION
     /// ```
-    DropFunction {
-        if_exists: bool,
-        /// One or more function to drop
-        func_desc: Vec<FunctionDesc>,
-        /// `CASCADE` or `RESTRICT`
-        drop_behavior: Option<DropBehavior>,
-    },
+    DropFunction(DropFunction),
     /// ```sql
     /// DROP DOMAIN
     /// ```
@@ -3593,25 +3517,13 @@ pub enum Statement {
     /// ```
     ///
     /// Note: this is a PostgreSQL-specific statement,
-    CreateExtension {
-        name: Ident,
-        if_not_exists: bool,
-        cascade: bool,
-        schema: Option<Ident>,
-        version: Option<Ident>,
-    },
+    CreateExtension(CreateExtension),
     /// ```sql
     /// DROP EXTENSION [ IF EXISTS ] name [, ...] [ CASCADE | RESTRICT ]
-    ///
-    /// Note: this is a PostgreSQL-specific statement.
-    /// https://www.postgresql.org/docs/current/sql-dropextension.html
     /// ```
-    DropExtension {
-        names: Vec<Ident>,
-        if_exists: bool,
-        /// `CASCADE` or `RESTRICT`
-        cascade_or_restrict: Option<ReferentialAction>,
-    },
+    /// Note: this is a PostgreSQL-specific statement.
+    /// <https://www.postgresql.org/docs/current/sql-dropextension.html>
+    DropExtension(DropExtension),
     /// ```sql
     /// FETCH
     /// ```
@@ -4328,6 +4240,24 @@ pub enum Statement {
     Vacuum(VacuumStatement),
 }
 
+impl From<Analyze> for Statement {
+    fn from(analyze: Analyze) -> Self {
+        Statement::Analyze(analyze)
+    }
+}
+
+impl From<ddl::Truncate> for Statement {
+    fn from(truncate: ddl::Truncate) -> Self {
+        Statement::Truncate(truncate)
+    }
+}
+
+impl From<ddl::Msck> for Statement {
+    fn from(msck: ddl::Msck) -> Self {
+        Statement::Msck(msck)
+    }
+}
+
 /// ```sql
 /// {COPY | REVOKE} CURRENT GRANTS
 /// ```
@@ -4528,61 +4458,8 @@ impl fmt::Display for Statement {
                 }
                 write!(f, " {source}")
             }
-            Statement::Msck {
-                table_name,
-                repair,
-                partition_action,
-            } => {
-                write!(
-                    f,
-                    "MSCK {repair}TABLE {table}",
-                    repair = if *repair { "REPAIR " } else { "" },
-                    table = table_name
-                )?;
-                if let Some(pa) = partition_action {
-                    write!(f, " {pa}")?;
-                }
-                Ok(())
-            }
-            Statement::Truncate {
-                table_names,
-                partitions,
-                table,
-                identity,
-                cascade,
-                on_cluster,
-            } => {
-                let table = if *table { "TABLE " } else { "" };
-
-                write!(
-                    f,
-                    "TRUNCATE {table}{table_names}",
-                    table_names = display_comma_separated(table_names)
-                )?;
-
-                if let Some(identity) = identity {
-                    match identity {
-                        TruncateIdentityOption::Restart => write!(f, " RESTART IDENTITY")?,
-                        TruncateIdentityOption::Continue => write!(f, " CONTINUE IDENTITY")?,
-                    }
-                }
-                if let Some(cascade) = cascade {
-                    match cascade {
-                        CascadeOption::Cascade => write!(f, " CASCADE")?,
-                        CascadeOption::Restrict => write!(f, " RESTRICT")?,
-                    }
-                }
-
-                if let Some(ref parts) = partitions {
-                    if !parts.is_empty() {
-                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
-                    }
-                }
-                if let Some(on_cluster) = on_cluster {
-                    write!(f, " ON CLUSTER {on_cluster}")?;
-                }
-                Ok(())
-            }
+            Statement::Msck(msck) => msck.fmt(f),
+            Statement::Truncate(truncate) => truncate.fmt(f),
             Statement::Case(stmt) => {
                 write!(f, "{stmt}")
             }
@@ -4637,44 +4514,7 @@ impl fmt::Display for Statement {
                 )?;
                 Ok(())
             }
-            Statement::Analyze {
-                table_name,
-                partitions,
-                for_columns,
-                columns,
-                cache_metadata,
-                noscan,
-                compute_statistics,
-                has_table_keyword,
-            } => {
-                write!(
-                    f,
-                    "ANALYZE{}{table_name}",
-                    if *has_table_keyword { " TABLE " } else { " " }
-                )?;
-                if let Some(ref parts) = partitions {
-                    if !parts.is_empty() {
-                        write!(f, " PARTITION ({})", display_comma_separated(parts))?;
-                    }
-                }
-
-                if *compute_statistics {
-                    write!(f, " COMPUTE STATISTICS")?;
-                }
-                if *noscan {
-                    write!(f, " NOSCAN")?;
-                }
-                if *cache_metadata {
-                    write!(f, " CACHE METADATA")?;
-                }
-                if *for_columns {
-                    write!(f, " FOR COLUMNS")?;
-                    if !columns.is_empty() {
-                        write!(f, " {}", display_comma_separated(columns))?;
-                    }
-                }
-                Ok(())
-            }
+            Statement::Analyze(analyze) => analyze.fmt(f),
             Statement::Insert(insert) => insert.fmt(f),
             Statement::Install {
                 extension_name: name,
@@ -4730,53 +4570,7 @@ impl fmt::Display for Statement {
                 }
                 Ok(())
             }
-            Statement::Update {
-                table,
-                assignments,
-                from,
-                selection,
-                returning,
-                or,
-                limit,
-            } => {
-                f.write_str("UPDATE ")?;
-                if let Some(or) = or {
-                    or.fmt(f)?;
-                    f.write_str(" ")?;
-                }
-                table.fmt(f)?;
-                if let Some(UpdateTableFromKind::BeforeSet(from)) = from {
-                    SpaceOrNewline.fmt(f)?;
-                    f.write_str("FROM")?;
-                    indented_list(f, from)?;
-                }
-                if !assignments.is_empty() {
-                    SpaceOrNewline.fmt(f)?;
-                    f.write_str("SET")?;
-                    indented_list(f, assignments)?;
-                }
-                if let Some(UpdateTableFromKind::AfterSet(from)) = from {
-                    SpaceOrNewline.fmt(f)?;
-                    f.write_str("FROM")?;
-                    indented_list(f, from)?;
-                }
-                if let Some(selection) = selection {
-                    SpaceOrNewline.fmt(f)?;
-                    f.write_str("WHERE")?;
-                    SpaceOrNewline.fmt(f)?;
-                    Indent(selection).fmt(f)?;
-                }
-                if let Some(returning) = returning {
-                    SpaceOrNewline.fmt(f)?;
-                    f.write_str("RETURNING")?;
-                    indented_list(f, returning)?;
-                }
-                if let Some(limit) = limit {
-                    SpaceOrNewline.fmt(f)?;
-                    write!(f, "LIMIT {limit}")?;
-                }
-                Ok(())
-            }
+            Statement::Update(update) => update.fmt(f),
             Statement::Delete(delete) => delete.fmt(f),
             Statement::Open(open) => open.fmt(f),
             Statement::Close { cursor } => {
@@ -4932,80 +4726,7 @@ impl fmt::Display for Statement {
                 }
                 Ok(())
             }
-            Statement::CreateView {
-                or_alter,
-                name,
-                or_replace,
-                columns,
-                query,
-                materialized,
-                secure,
-                options,
-                cluster_by,
-                comment,
-                with_no_schema_binding,
-                if_not_exists,
-                temporary,
-                to,
-                params,
-                name_before_not_exists,
-            } => {
-                write!(
-                    f,
-                    "CREATE {or_alter}{or_replace}",
-                    or_alter = if *or_alter { "OR ALTER " } else { "" },
-                    or_replace = if *or_replace { "OR REPLACE " } else { "" },
-                )?;
-                if let Some(params) = params {
-                    params.fmt(f)?;
-                }
-                write!(
-                    f,
-                    "{secure}{materialized}{temporary}VIEW {if_not_and_name}{to}",
-                    if_not_and_name = if *if_not_exists {
-                        if *name_before_not_exists {
-                            format!("{name} IF NOT EXISTS")
-                        } else {
-                            format!("IF NOT EXISTS {name}")
-                        }
-                    } else {
-                        format!("{name}")
-                    },
-                    secure = if *secure { "SECURE " } else { "" },
-                    materialized = if *materialized { "MATERIALIZED " } else { "" },
-                    temporary = if *temporary { "TEMPORARY " } else { "" },
-                    to = to
-                        .as_ref()
-                        .map(|to| format!(" TO {to}"))
-                        .unwrap_or_default()
-                )?;
-                if !columns.is_empty() {
-                    write!(f, " ({})", display_comma_separated(columns))?;
-                }
-                if matches!(options, CreateTableOptions::With(_)) {
-                    write!(f, " {options}")?;
-                }
-                if let Some(comment) = comment {
-                    write!(
-                        f,
-                        " COMMENT = '{}'",
-                        value::escape_single_quote_string(comment)
-                    )?;
-                }
-                if !cluster_by.is_empty() {
-                    write!(f, " CLUSTER BY ({})", display_comma_separated(cluster_by))?;
-                }
-                if matches!(options, CreateTableOptions::Options(_)) {
-                    write!(f, " {options}")?;
-                }
-                f.write_str(" AS")?;
-                SpaceOrNewline.fmt(f)?;
-                query.fmt(f)?;
-                if *with_no_schema_binding {
-                    write!(f, " WITH NO SCHEMA BINDING")?;
-                }
-                Ok(())
-            }
+            Statement::CreateView(create_view) => create_view.fmt(f),
             Statement::CreateTable(create_table) => create_table.fmt(f),
             Statement::LoadData {
                 local,
@@ -5056,141 +4777,9 @@ impl fmt::Display for Statement {
                 Ok(())
             }
             Statement::CreateIndex(create_index) => create_index.fmt(f),
-            Statement::CreateExtension {
-                name,
-                if_not_exists,
-                cascade,
-                schema,
-                version,
-            } => {
-                write!(
-                    f,
-                    "CREATE EXTENSION {if_not_exists}{name}",
-                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" }
-                )?;
-                if *cascade || schema.is_some() || version.is_some() {
-                    write!(f, " WITH")?;
-
-                    if let Some(name) = schema {
-                        write!(f, " SCHEMA {name}")?;
-                    }
-                    if let Some(version) = version {
-                        write!(f, " VERSION {version}")?;
-                    }
-                    if *cascade {
-                        write!(f, " CASCADE")?;
-                    }
-                }
-
-                Ok(())
-            }
-            Statement::DropExtension {
-                names,
-                if_exists,
-                cascade_or_restrict,
-            } => {
-                write!(f, "DROP EXTENSION")?;
-                if *if_exists {
-                    write!(f, " IF EXISTS")?;
-                }
-                write!(f, " {}", display_comma_separated(names))?;
-                if let Some(cascade_or_restrict) = cascade_or_restrict {
-                    write!(f, " {cascade_or_restrict}")?;
-                }
-                Ok(())
-            }
-            Statement::CreateRole {
-                names,
-                if_not_exists,
-                inherit,
-                login,
-                bypassrls,
-                password,
-                create_db,
-                create_role,
-                superuser,
-                replication,
-                connection_limit,
-                valid_until,
-                in_role,
-                in_group,
-                role,
-                user,
-                admin,
-                authorization_owner,
-            } => {
-                write!(
-                    f,
-                    "CREATE ROLE {if_not_exists}{names}{superuser}{create_db}{create_role}{inherit}{login}{replication}{bypassrls}",
-                    if_not_exists = if *if_not_exists { "IF NOT EXISTS " } else { "" },
-                    names = display_separated(names, ", "),
-                    superuser = match *superuser {
-                        Some(true) => " SUPERUSER",
-                        Some(false) => " NOSUPERUSER",
-                        None => ""
-                    },
-                    create_db = match *create_db {
-                        Some(true) => " CREATEDB",
-                        Some(false) => " NOCREATEDB",
-                        None => ""
-                    },
-                    create_role = match *create_role {
-                        Some(true) => " CREATEROLE",
-                        Some(false) => " NOCREATEROLE",
-                        None => ""
-                    },
-                    inherit = match *inherit {
-                        Some(true) => " INHERIT",
-                        Some(false) => " NOINHERIT",
-                        None => ""
-                    },
-                    login = match *login {
-                        Some(true) => " LOGIN",
-                        Some(false) => " NOLOGIN",
-                        None => ""
-                    },
-                    replication = match *replication {
-                        Some(true) => " REPLICATION",
-                        Some(false) => " NOREPLICATION",
-                        None => ""
-                    },
-                    bypassrls = match *bypassrls {
-                        Some(true) => " BYPASSRLS",
-                        Some(false) => " NOBYPASSRLS",
-                        None => ""
-                    }
-                )?;
-                if let Some(limit) = connection_limit {
-                    write!(f, " CONNECTION LIMIT {limit}")?;
-                }
-                match password {
-                    Some(Password::Password(pass)) => write!(f, " PASSWORD {pass}"),
-                    Some(Password::NullPassword) => write!(f, " PASSWORD NULL"),
-                    None => Ok(()),
-                }?;
-                if let Some(until) = valid_until {
-                    write!(f, " VALID UNTIL {until}")?;
-                }
-                if !in_role.is_empty() {
-                    write!(f, " IN ROLE {}", display_comma_separated(in_role))?;
-                }
-                if !in_group.is_empty() {
-                    write!(f, " IN GROUP {}", display_comma_separated(in_group))?;
-                }
-                if !role.is_empty() {
-                    write!(f, " ROLE {}", display_comma_separated(role))?;
-                }
-                if !user.is_empty() {
-                    write!(f, " USER {}", display_comma_separated(user))?;
-                }
-                if !admin.is_empty() {
-                    write!(f, " ADMIN {}", display_comma_separated(admin))?;
-                }
-                if let Some(owner) = authorization_owner {
-                    write!(f, " AUTHORIZATION {owner}")?;
-                }
-                Ok(())
-            }
+            Statement::CreateExtension(create_extension) => write!(f, "{create_extension}"),
+            Statement::DropExtension(drop_extension) => write!(f, "{drop_extension}"),
+            Statement::CreateRole(create_role) => write!(f, "{create_role}"),
             Statement::CreateSecret {
                 or_replace,
                 temporary,
@@ -5272,42 +4861,7 @@ impl fmt::Display for Statement {
                 Ok(())
             }
             Statement::CreateConnector(create_connector) => create_connector.fmt(f),
-            Statement::AlterTable {
-                name,
-                if_exists,
-                only,
-                operations,
-                location,
-                on_cluster,
-                iceberg,
-                end_token: _,
-            } => {
-                if *iceberg {
-                    write!(f, "ALTER ICEBERG TABLE ")?;
-                } else {
-                    write!(f, "ALTER TABLE ")?;
-                }
-
-                if *if_exists {
-                    write!(f, "IF EXISTS ")?;
-                }
-                if *only {
-                    write!(f, "ONLY ")?;
-                }
-                write!(f, "{name} ")?;
-                if let Some(cluster) = on_cluster {
-                    write!(f, "ON CLUSTER {cluster} ")?;
-                }
-                write!(
-                    f,
-                    "{operations}",
-                    operations = display_comma_separated(operations)
-                )?;
-                if let Some(loc) = location {
-                    write!(f, " {loc}")?
-                }
-                Ok(())
-            }
+            Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
             Statement::AlterIndex { name, operation } => {
                 write!(f, "ALTER INDEX {name} {operation}")
             }
@@ -5410,22 +4964,7 @@ impl fmt::Display for Statement {
                 };
                 Ok(())
             }
-            Statement::DropFunction {
-                if_exists,
-                func_desc,
-                drop_behavior,
-            } => {
-                write!(
-                    f,
-                    "DROP FUNCTION{} {}",
-                    if *if_exists { " IF EXISTS" } else { "" },
-                    display_comma_separated(func_desc),
-                )?;
-                if let Some(op) = drop_behavior {
-                    write!(f, " {op}")?;
-                }
-                Ok(())
-            }
+            Statement::DropFunction(drop_function) => write!(f, "{drop_function}"),
             Statement::DropDomain(DropDomain {
                 if_exists,
                 name,
@@ -10945,6 +10484,48 @@ impl From<Insert> for Statement {
     }
 }
 
+impl From<Update> for Statement {
+    fn from(u: Update) -> Self {
+        Self::Update(u)
+    }
+}
+
+impl From<CreateView> for Statement {
+    fn from(cv: CreateView) -> Self {
+        Self::CreateView(cv)
+    }
+}
+
+impl From<CreateRole> for Statement {
+    fn from(cr: CreateRole) -> Self {
+        Self::CreateRole(cr)
+    }
+}
+
+impl From<AlterTable> for Statement {
+    fn from(at: AlterTable) -> Self {
+        Self::AlterTable(at)
+    }
+}
+
+impl From<DropFunction> for Statement {
+    fn from(df: DropFunction) -> Self {
+        Self::DropFunction(df)
+    }
+}
+
+impl From<CreateExtension> for Statement {
+    fn from(ce: CreateExtension) -> Self {
+        Self::CreateExtension(ce)
+    }
+}
+
+impl From<DropExtension> for Statement {
+    fn from(de: DropExtension) -> Self {
+        Self::DropExtension(de)
+    }
+}
+
 impl From<CaseStatement> for Statement {
     fn from(c: CaseStatement) -> Self {
         Self::Case(c)
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index 0a303fcf..de3439cf 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -16,8 +16,8 @@
 // under the License.
 
 use crate::ast::{
-    ddl::AlterSchema, query::SelectItemQualifiedWildcardKind, AlterSchemaOperation, ColumnOptions,
-    ExportData, Owner, TypedString,
+    ddl::AlterSchema, query::SelectItemQualifiedWildcardKind, AlterSchemaOperation, AlterTable,
+    ColumnOptions, CreateView, ExportData, Owner, TypedString,
 };
 use core::iter;
 
@@ -25,23 +25,23 @@ use crate::tokenizer::Span;
 
 use super::{
     dcl::SecondaryRoles, value::ValueWithSpan, AccessExpr, AlterColumnOperation,
-    AlterIndexOperation, AlterTableOperation, Array, Assignment, AssignmentTarget, AttachedToken,
-    BeginEndStatements, CaseStatement, CloseCursor, ClusteredIndex, ColumnDef, ColumnOption,
-    ColumnOptionDef, ConditionalStatementBlock, ConditionalStatements, ConflictTarget, ConnectBy,
-    ConstraintCharacteristics, CopySource, CreateIndex, CreateTable, CreateTableOptions, Cte,
-    Delete, DoUpdate, ExceptSelectItem, ExcludeSelectItem, Expr, ExprWithAlias, Fetch, FromTable,
-    Function, FunctionArg, FunctionArgExpr, FunctionArgumentClause, FunctionArgumentList,
-    FunctionArguments, GroupByExpr, HavingBound, IfStatement, IlikeSelectItem, IndexColumn, Insert,
-    Interpolate, InterpolateExpr, Join, JoinConstraint, JoinOperator, JsonPath, JsonPathElem,
-    LateralView, LimitClause, MatchRecognizePattern, Measure, NamedParenthesizedList,
-    NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction,
-    OnInsert, OpenStatement, OrderBy, OrderByExpr, OrderByKind, Partition, PivotValueSource,
-    ProjectionSelect, Query, RaiseStatement, RaiseStatementValue, ReferentialAction,
-    RenameSelectItem, ReplaceSelectElement, ReplaceSelectItem, Select, SelectInto, SelectItem,
-    SetExpr, SqlOption, Statement, Subscript, SymbolDefinition, TableAlias, TableAliasColumnDef,
-    TableConstraint, TableFactor, TableObject, TableOptionsClustered, TableWithJoins,
-    UpdateTableFromKind, Use, Value, Values, ViewColumnDef, WhileStatement,
-    WildcardAdditionalOptions, With, WithFill,
+    AlterIndexOperation, AlterTableOperation, Analyze, Array, Assignment, AssignmentTarget,
+    AttachedToken, BeginEndStatements, CaseStatement, CloseCursor, ClusteredIndex, ColumnDef,
+    ColumnOption, ColumnOptionDef, ConditionalStatementBlock, ConditionalStatements,
+    ConflictTarget, ConnectBy, ConstraintCharacteristics, CopySource, CreateIndex, CreateTable,
+    CreateTableOptions, Cte, Delete, DoUpdate, ExceptSelectItem, ExcludeSelectItem, Expr,
+    ExprWithAlias, Fetch, FromTable, Function, FunctionArg, FunctionArgExpr,
+    FunctionArgumentClause, FunctionArgumentList, FunctionArguments, GroupByExpr, HavingBound,
+    IfStatement, IlikeSelectItem, IndexColumn, Insert, Interpolate, InterpolateExpr, Join,
+    JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView, LimitClause,
+    MatchRecognizePattern, Measure, NamedParenthesizedList, NamedWindowDefinition, ObjectName,
+    ObjectNamePart, Offset, OnConflict, OnConflictAction, OnInsert, OpenStatement, OrderBy,
+    OrderByExpr, OrderByKind, Partition, PivotValueSource, ProjectionSelect, Query, RaiseStatement,
+    RaiseStatementValue, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
+    ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption, Statement, Subscript,
+    SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor, TableObject,
+    TableOptionsClustered, TableWithJoins, Update, UpdateTableFromKind, Use, Value, Values,
+    ViewColumnDef, WhileStatement, WildcardAdditionalOptions, With, WithFill,
 };
 
 /// Given an iterator of spans, return the [Span::union] of all spans.
@@ -298,38 +298,9 @@ impl Spanned for Values {
 impl Spanned for Statement {
     fn span(&self) -> Span {
         match self {
-            Statement::Analyze {
-                table_name,
-                partitions,
-                for_columns: _,
-                columns,
-                cache_metadata: _,
-                noscan: _,
-                compute_statistics: _,
-                has_table_keyword: _,
-            } => union_spans(
-                core::iter::once(table_name.span())
-                    .chain(partitions.iter().flat_map(|i| i.iter().map(|k| k.span())))
-                    .chain(columns.iter().map(|i| i.span)),
-            ),
-            Statement::Truncate {
-                table_names,
-                partitions,
-                table: _,
-                identity: _,
-                cascade: _,
-                on_cluster: _,
-            } => union_spans(
-                table_names
-                    .iter()
-                    .map(|i| i.name.span())
-                    .chain(partitions.iter().flat_map(|i| i.iter().map(|k| k.span()))),
-            ),
-            Statement::Msck {
-                table_name,
-                repair: _,
-                partition_action: _,
-            } => table_name.span(),
+            Statement::Analyze(analyze) => analyze.span(),
+            Statement::Truncate(truncate) => truncate.span(),
+            Statement::Msck(msck) => msck.span(),
             Statement::Query(query) => query.span(),
             Statement::Insert(insert) => insert.span(),
             Statement::Install { extension_name } => extension_name.span,
@@ -375,47 +346,9 @@ impl Spanned for Statement {
                 CloseCursor::All => Span::empty(),
                 CloseCursor::Specific { name } => name.span,
             },
-            Statement::Update {
-                table,
-                assignments,
-                from,
-                selection,
-                returning,
-                or: _,
-                limit: _,
-            } => union_spans(
-                core::iter::once(table.span())
-                    .chain(assignments.iter().map(|i| i.span()))
-                    .chain(from.iter().map(|i| i.span()))
-                    .chain(selection.iter().map(|i| i.span()))
-                    .chain(returning.iter().flat_map(|i| i.iter().map(|k| k.span()))),
-            ),
+            Statement::Update(update) => update.span(),
             Statement::Delete(delete) => delete.span(),
-            Statement::CreateView {
-                or_alter: _,
-                or_replace: _,
-                materialized: _,
-                secure: _,
-                name,
-                columns,
-                query,
-                options,
-                cluster_by,
-                comment: _,
-                with_no_schema_binding: _,
-                if_not_exists: _,
-                temporary: _,
-                to,
-                name_before_not_exists: _,
-                params: _,
-            } => union_spans(
-                core::iter::once(name.span())
-                    .chain(columns.iter().map(|i| i.span()))
-                    .chain(core::iter::once(query.span()))
-                    .chain(core::iter::once(options.span()))
-                    .chain(cluster_by.iter().map(|i| i.span))
-                    .chain(to.iter().map(|i| i.span())),
-            ),
+            Statement::CreateView(create_view) => create_view.span(),
             Statement::CreateTable(create_table) => create_table.span(),
             Statement::CreateVirtualTable {
                 name,
@@ -428,25 +361,13 @@ impl Spanned for Statement {
                     .chain(module_args.iter().map(|i| i.span)),
             ),
             Statement::CreateIndex(create_index) => create_index.span(),
-            Statement::CreateRole { .. } => Span::empty(),
+            Statement::CreateRole(create_role) => create_role.span(),
+            Statement::CreateExtension(create_extension) => create_extension.span(),
+            Statement::DropExtension(drop_extension) => drop_extension.span(),
             Statement::CreateSecret { .. } => Span::empty(),
             Statement::CreateServer { .. } => Span::empty(),
             Statement::CreateConnector { .. } => Span::empty(),
-            Statement::AlterTable {
-                name,
-                if_exists: _,
-                only: _,
-                operations,
-                location: _,
-                on_cluster,
-                iceberg: _,
-                end_token,
-            } => union_spans(
-                core::iter::once(name.span())
-                    .chain(operations.iter().map(|i| i.span()))
-                    .chain(on_cluster.iter().map(|i| i.span))
-                    .chain(core::iter::once(end_token.0.span)),
-            ),
+            Statement::AlterTable(alter_table) => alter_table.span(),
             Statement::AlterIndex { name, operation } => name.span().union(&operation.span()),
             Statement::AlterView {
                 name,
@@ -467,13 +388,11 @@ impl Spanned for Statement {
             Statement::AttachDuckDBDatabase { .. } => Span::empty(),
             Statement::DetachDuckDBDatabase { .. } => Span::empty(),
             Statement::Drop { .. } => Span::empty(),
-            Statement::DropFunction { .. } => Span::empty(),
+            Statement::DropFunction(drop_function) => drop_function.span(),
             Statement::DropDomain { .. } => Span::empty(),
             Statement::DropProcedure { .. } => Span::empty(),
             Statement::DropSecret { .. } => Span::empty(),
             Statement::Declare { .. } => Span::empty(),
-            Statement::CreateExtension { .. } => Span::empty(),
-            Statement::DropExtension { .. } => Span::empty(),
             Statement::Fetch { .. } => Span::empty(),
             Statement::Flush { .. } => Span::empty(),
             Statement::Discard { .. } => Span::empty(),
@@ -873,6 +792,20 @@ impl Spanned for ConstraintCharacteristics {
     }
 }
 
+impl Spanned for Analyze {
+    fn span(&self) -> Span {
+        union_spans(
+            core::iter::once(self.table_name.span())
+                .chain(
+                    self.partitions
+                        .iter()
+                        .flat_map(|i| i.iter().map(|k| k.span())),
+                )
+                .chain(self.columns.iter().map(|i| i.span)),
+        )
+    }
+}
+
 /// # partial span
 ///
 /// Missing spans:
@@ -941,6 +874,29 @@ impl Spanned for Delete {
     }
 }
 
+impl Spanned for Update {
+    fn span(&self) -> Span {
+        let Update {
+            table,
+            assignments,
+            from,
+            selection,
+            returning,
+            or: _,
+            limit,
+        } = self;
+
+        union_spans(
+            core::iter::once(table.span())
+                .chain(assignments.iter().map(|i| i.span()))
+                .chain(from.iter().map(|i| i.span()))
+                .chain(selection.iter().map(|i| i.span()))
+                .chain(returning.iter().flat_map(|i| i.iter().map(|k| k.span())))
+                .chain(limit.iter().map(|i| i.span())),
+        )
+    }
+}
+
 impl Spanned for FromTable {
     fn span(&self) -> Span {
         match self {
@@ -2375,6 +2331,30 @@ impl Spanned for AlterSchema {
     }
 }
 
+impl Spanned for CreateView {
+    fn span(&self) -> Span {
+        union_spans(
+            core::iter::once(self.name.span())
+                .chain(self.columns.iter().map(|i| i.span()))
+                .chain(core::iter::once(self.query.span()))
+                .chain(core::iter::once(self.options.span()))
+                .chain(self.cluster_by.iter().map(|i| i.span))
+                .chain(self.to.iter().map(|i| i.span())),
+        )
+    }
+}
+
+impl Spanned for AlterTable {
+    fn span(&self) -> Span {
+        union_spans(
+            core::iter::once(self.name.span())
+                .chain(self.operations.iter().map(|i| i.span()))
+                .chain(self.on_cluster.iter().map(|i| i.span))
+                .chain(core::iter::once(self.end_token.0.span)),
+        )
+    }
+}
+
 #[cfg(test)]
 pub mod tests {
     use crate::dialect::{Dialect, GenericDialect, SnowflakeDialect};
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index d1e9b1e7..2b365e29 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -982,11 +982,12 @@ impl<'a> Parser<'a> {
                 Ok(pa)
             })?
             .unwrap_or_default();
-        Ok(Statement::Msck {
+        Ok(Msck {
             repair,
             table_name,
             partition_action,
-        })
+        }
+        .into())
     }
 
     pub fn parse_truncate(&mut self) -> Result<Statement, ParserError> {
@@ -1024,14 +1025,15 @@ impl<'a> Parser<'a> {
 
         let on_cluster = self.parse_optional_on_cluster()?;
 
-        Ok(Statement::Truncate {
+        Ok(Truncate {
             table_names,
             partitions,
             table,
             identity,
             cascade,
             on_cluster,
-        })
+        }
+        .into())
     }
 
     fn parse_cascade_option(&mut self) -> Option<CascadeOption> {
@@ -1167,7 +1169,7 @@ impl<'a> Parser<'a> {
             }
         }
 
-        Ok(Statement::Analyze {
+        Ok(Analyze {
             has_table_keyword,
             table_name,
             for_columns,
@@ -1176,7 +1178,8 @@ impl<'a> Parser<'a> {
             cache_metadata,
             noscan,
             compute_statistics,
-        })
+        }
+        .into())
     }
 
     /// Parse a new expression including wildcard & qualified wildcard.
@@ -5926,7 +5929,7 @@ impl<'a> Parser<'a> {
                 Keyword::BINDING,
             ]);
 
-        Ok(Statement::CreateView {
+        Ok(CreateView {
             or_alter,
             name,
             columns,
@@ -5943,7 +5946,8 @@ impl<'a> Parser<'a> {
             to,
             params: create_view_params,
             name_before_not_exists,
-        })
+        }
+        .into())
     }
 
     /// Parse optional parameters for the `CREATE VIEW` statement supported by [MySQL].
@@ -6206,7 +6210,7 @@ impl<'a> Parser<'a> {
             }?
         }
 
-        Ok(Statement::CreateRole {
+        Ok(CreateRole {
             names,
             if_not_exists,
             login,
@@ -6225,7 +6229,8 @@ impl<'a> Parser<'a> {
             user,
             admin,
             authorization_owner,
-        })
+        }
+        .into())
     }
 
     pub fn parse_owner(&mut self) -> Result<Owner, ParserError> {
@@ -6503,11 +6508,11 @@ impl<'a> Parser<'a> {
         let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
         let func_desc = self.parse_comma_separated(Parser::parse_function_desc)?;
         let drop_behavior = self.parse_optional_drop_behavior();
-        Ok(Statement::DropFunction {
+        Ok(Statement::DropFunction(DropFunction {
             if_exists,
             func_desc,
             drop_behavior,
-        })
+        }))
     }
 
     /// ```sql
@@ -7175,13 +7180,14 @@ impl<'a> Parser<'a> {
             (None, None, false)
         };
 
-        Ok(Statement::CreateExtension {
+        Ok(CreateExtension {
             name,
             if_not_exists,
             schema,
             version,
             cascade,
-        })
+        }
+        .into())
     }
 
     /// Parse a PostgreSQL-specific [Statement::DropExtension] statement.
@@ -7190,7 +7196,7 @@ impl<'a> Parser<'a> {
         let names = self.parse_comma_separated(|p| p.parse_identifier())?;
         let cascade_or_restrict =
             self.parse_one_of_keywords(&[Keyword::CASCADE, Keyword::RESTRICT]);
-        Ok(Statement::DropExtension {
+        Ok(Statement::DropExtension(DropExtension {
             names,
             if_exists,
             cascade_or_restrict: cascade_or_restrict
@@ -7200,7 +7206,7 @@ impl<'a> Parser<'a> {
                     _ => self.expected("CASCADE or RESTRICT", self.peek_token()),
                 })
                 .transpose()?,
-        })
+        }))
     }
 
     //TODO: Implement parsing for Skewed
@@ -9378,7 +9384,7 @@ impl<'a> Parser<'a> {
             self.get_current_token().clone()
         };
 
-        Ok(Statement::AlterTable {
+        Ok(AlterTable {
             name: table_name,
             if_exists,
             only,
@@ -9387,7 +9393,8 @@ impl<'a> Parser<'a> {
             on_cluster,
             iceberg,
             end_token: AttachedToken(end_token),
-        })
+        }
+        .into())
     }
 
     pub fn parse_alter_view(&mut self) -> Result<Statement, ParserError> {
@@ -15662,7 +15669,7 @@ impl<'a> Parser<'a> {
         } else {
             None
         };
-        Ok(Statement::Update {
+        Ok(Update {
             table,
             assignments,
             from,
@@ -15670,7 +15677,8 @@ impl<'a> Parser<'a> {
             returning,
             or,
             limit,
-        })
+        }
+        .into())
     }
 
     /// Parse a `var = expr` assignment, used in an UPDATE statement
diff --git a/src/test_utils.rs b/src/test_utils.rs
index 03fdee8a..a8c8afd5 100644
--- a/src/test_utils.rs
+++ b/src/test_utils.rs
@@ -343,21 +343,12 @@ pub fn expr_from_projection(item: &SelectItem) -> &Expr {
 
 pub fn alter_table_op_with_name(stmt: Statement, expected_name: &str) -> AlterTableOperation {
     match stmt {
-        Statement::AlterTable {
-            name,
-            if_exists,
-            only: is_only,
-            operations,
-            on_cluster: _,
-            location: _,
-            iceberg,
-            end_token: _,
-        } => {
-            assert_eq!(name.to_string(), expected_name);
-            assert!(!if_exists);
-            assert!(!is_only);
-            assert!(!iceberg);
-            only(operations)
+        Statement::AlterTable(alter_table) => {
+            assert_eq!(alter_table.name.to_string(), expected_name);
+            assert!(!alter_table.if_exists);
+            assert!(!alter_table.only);
+            assert!(!alter_table.iceberg);
+            only(alter_table.operations)
         }
         _ => panic!("Expected ALTER TABLE statement"),
     }
@@ -484,7 +475,7 @@ pub fn index_column(stmt: Statement) -> Expr {
                 _ => panic!("Expected an index, unique, primary, full text, or spatial constraint (foreign key does not support general key part expressions)"),
             }
         }
-        Statement::AlterTable { operations, .. } => match operations.first().unwrap() {
+        Statement::AlterTable(alter_table) => match alter_table.operations.first().unwrap() {
             AlterTableOperation::AddConstraint { constraint, .. } => {
                 match constraint {
                     TableConstraint::Index(constraint) => {
diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs
index 4f0cfa3e..03a0ac81 100644
--- a/tests/sqlparser_bigquery.rs
+++ b/tests/sqlparser_bigquery.rs
@@ -332,13 +332,13 @@ fn parse_create_view_with_options() {
         "AS SELECT column_1, column_2, column_3 FROM myproject.mydataset.mytable",
     );
     match bigquery().verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             name,
             query,
             options,
             columns,
             ..
-        } => {
+        }) => {
             assert_eq!(
                 name,
                 ObjectName::from(vec![
@@ -401,7 +401,7 @@ fn parse_create_view_with_options() {
 fn parse_create_view_if_not_exists() {
     let sql = "CREATE VIEW IF NOT EXISTS mydataset.newview AS SELECT foo FROM bar";
     match bigquery().verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             name,
             columns,
             query,
@@ -414,7 +414,7 @@ fn parse_create_view_if_not_exists() {
             if_not_exists,
             temporary,
             ..
-        } => {
+        }) => {
             assert_eq!("mydataset.newview", name.to_string());
             assert_eq!(Vec::<ViewColumnDef>::new(), columns);
             assert_eq!("SELECT foo FROM bar", query.to_string());
@@ -435,12 +435,12 @@ fn parse_create_view_if_not_exists() {
 fn parse_create_view_with_unquoted_hyphen() {
     let sql = "CREATE VIEW IF NOT EXISTS my-pro-ject.mydataset.myview AS SELECT 1";
     match bigquery().verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             name,
             query,
             if_not_exists,
             ..
-        } => {
+        }) => {
             assert_eq!("my-pro-ject.mydataset.myview", name.to_string());
             assert_eq!("SELECT 1", query.to_string());
             assert!(if_not_exists);
diff --git a/tests/sqlparser_clickhouse.rs b/tests/sqlparser_clickhouse.rs
index bc1431f9..44bfcda4 100644
--- a/tests/sqlparser_clickhouse.rs
+++ b/tests/sqlparser_clickhouse.rs
@@ -243,12 +243,10 @@ fn parse_alter_table_attach_and_detach_partition() {
         match clickhouse_and_generic()
             .verified_stmt(format!("ALTER TABLE t0 {operation} PARTITION part").as_str())
         {
-            Statement::AlterTable {
-                name, operations, ..
-            } => {
-                pretty_assertions::assert_eq!("t0", name.to_string());
+            Statement::AlterTable(alter_table) => {
+                pretty_assertions::assert_eq!("t0", alter_table.name.to_string());
                 pretty_assertions::assert_eq!(
-                    operations[0],
+                    alter_table.operations[0],
                     if operation == &"ATTACH" {
                         AlterTableOperation::AttachPartition {
                             partition: Partition::Expr(Identifier(Ident::new("part"))),
@@ -266,9 +264,9 @@ fn parse_alter_table_attach_and_detach_partition() {
         match clickhouse_and_generic()
             .verified_stmt(format!("ALTER TABLE t1 {operation} PART part").as_str())
         {
-            Statement::AlterTable {
+            Statement::AlterTable(AlterTable {
                 name, operations, ..
-            } => {
+            }) => {
                 pretty_assertions::assert_eq!("t1", name.to_string());
                 pretty_assertions::assert_eq!(
                     operations[0],
@@ -308,9 +306,9 @@ fn parse_alter_table_add_projection() {
         "ALTER TABLE t0 ADD PROJECTION IF NOT EXISTS my_name",
         " (SELECT a, b GROUP BY a ORDER BY b)",
     )) {
-        Statement::AlterTable {
+        Statement::AlterTable(AlterTable {
             name, operations, ..
-        } => {
+        }) => {
             assert_eq!(name, ObjectName::from(vec!["t0".into()]));
             assert_eq!(1, operations.len());
             assert_eq!(
@@ -380,9 +378,9 @@ fn parse_alter_table_add_projection() {
 fn parse_alter_table_drop_projection() {
     match clickhouse_and_generic().verified_stmt("ALTER TABLE t0 DROP PROJECTION IF EXISTS my_name")
     {
-        Statement::AlterTable {
+        Statement::AlterTable(AlterTable {
             name, operations, ..
-        } => {
+        }) => {
             assert_eq!(name, ObjectName::from(vec!["t0".into()]));
             assert_eq!(1, operations.len());
             assert_eq!(
@@ -413,9 +411,9 @@ fn parse_alter_table_clear_and_materialize_projection() {
             format!("ALTER TABLE t0 {keyword} PROJECTION IF EXISTS my_name IN PARTITION p0",)
                 .as_str(),
         ) {
-            Statement::AlterTable {
+            Statement::AlterTable(AlterTable {
                 name, operations, ..
-            } => {
+            }) => {
                 assert_eq!(name, ObjectName::from(vec!["t0".into()]));
                 assert_eq!(1, operations.len());
                 assert_eq!(
@@ -904,7 +902,7 @@ fn parse_create_table_with_variant_default_expressions() {
 #[test]
 fn parse_create_view_with_fields_data_types() {
     match clickhouse().verified_stmt(r#"CREATE VIEW v (i "int", f "String") AS SELECT * FROM t"#) {
-        Statement::CreateView { name, columns, .. } => {
+        Statement::CreateView(CreateView { name, columns, .. }) => {
             assert_eq!(name, ObjectName::from(vec!["v".into()]));
             assert_eq!(
                 columns,
@@ -1518,7 +1516,7 @@ fn parse_freeze_and_unfreeze_partition() {
             Value::SingleQuotedString("2024-08-14".to_string()).with_empty_span(),
         ));
         match clickhouse_and_generic().verified_stmt(&sql) {
-            Statement::AlterTable { operations, .. } => {
+            Statement::AlterTable(AlterTable { operations, .. }) => {
                 assert_eq!(operations.len(), 1);
                 let expected_operation = if operation_name == &"FREEZE" {
                     AlterTableOperation::FreezePartition {
@@ -1542,7 +1540,7 @@ fn parse_freeze_and_unfreeze_partition() {
         let sql =
             format!("ALTER TABLE t {operation_name} PARTITION '2024-08-14' WITH NAME 'hello'");
         match clickhouse_and_generic().verified_stmt(&sql) {
-            Statement::AlterTable { operations, .. } => {
+            Statement::AlterTable(AlterTable { operations, .. }) => {
                 assert_eq!(operations.len(), 1);
                 let expected_partition = Partition::Expr(Expr::Value(
                     Value::SingleQuotedString("2024-08-14".to_string()).with_empty_span(),
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index a1fd48d3..773937c5 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -377,12 +377,12 @@ fn parse_insert_sqlite() {
 fn parse_update() {
     let sql = "UPDATE t SET a = 1, b = 2, c = 3 WHERE d";
     match verified_stmt(sql) {
-        Statement::Update {
+        Statement::Update(Update {
             table,
             assignments,
             selection,
             ..
-        } => {
+        }) => {
             assert_eq!(table.to_string(), "t".to_string());
             assert_eq!(
                 assignments,
@@ -439,7 +439,7 @@ fn parse_update_set_from() {
     let stmt = dialects.verified_stmt(sql);
     assert_eq!(
         stmt,
-        Statement::Update {
+        Statement::Update(Update {
             table: TableWithJoins {
                 relation: table_from_name(ObjectName::from(vec![Ident::new("t1")])),
                 joins: vec![],
@@ -516,7 +516,7 @@ fn parse_update_set_from() {
             returning: None,
             or: None,
             limit: None
-        }
+        })
     );
 
     let sql = "UPDATE T SET a = b FROM U, (SELECT foo FROM V) AS W WHERE 1 = 1";
@@ -527,7 +527,7 @@ fn parse_update_set_from() {
 fn parse_update_with_table_alias() {
     let sql = "UPDATE users AS u SET u.username = 'new_user' WHERE u.username = 'old_user'";
     match verified_stmt(sql) {
-        Statement::Update {
+        Statement::Update(Update {
             table,
             assignments,
             from: _from,
@@ -535,7 +535,7 @@ fn parse_update_with_table_alias() {
             returning,
             or: None,
             limit: None,
-        } => {
+        }) => {
             assert_eq!(
                 TableWithJoins {
                     relation: TableFactor::Table {
@@ -591,7 +591,7 @@ fn parse_update_with_table_alias() {
 #[test]
 fn parse_update_or() {
     let expect_or_clause = |sql: &str, expected_action: SqliteOnConflict| match verified_stmt(sql) {
-        Statement::Update { or, .. } => assert_eq!(or, Some(expected_action)),
+        Statement::Update(Update { or, .. }) => assert_eq!(or, Some(expected_action)),
         other => unreachable!("Expected update with or, got {:?}", other),
     };
     expect_or_clause(
@@ -4846,9 +4846,9 @@ fn test_alter_table_with_on_cluster() {
     match all_dialects()
         .verified_stmt("ALTER TABLE t ON CLUSTER 'cluster' ADD CONSTRAINT bar PRIMARY KEY (baz)")
     {
-        Statement::AlterTable {
+        Statement::AlterTable(AlterTable {
             name, on_cluster, ..
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "t");
             assert_eq!(on_cluster, Some(Ident::with_quote('\'', "cluster")));
         }
@@ -4858,9 +4858,9 @@ fn test_alter_table_with_on_cluster() {
     match all_dialects()
         .verified_stmt("ALTER TABLE t ON CLUSTER cluster_name ADD CONSTRAINT bar PRIMARY KEY (baz)")
     {
-        Statement::AlterTable {
+        Statement::AlterTable(AlterTable {
             name, on_cluster, ..
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "t");
             assert_eq!(on_cluster, Some(Ident::new("cluster_name")));
         }
@@ -7615,7 +7615,7 @@ fn parse_ctes() {
     // CTE in a view
     let sql = &format!("CREATE VIEW v AS {with}");
     match verified_stmt(sql) {
-        Statement::CreateView { query, .. } => assert_ctes_in_select(&cte_sqls, &query),
+        Statement::CreateView(create_view) => assert_ctes_in_select(&cte_sqls, &create_view.query),
         _ => panic!("Expected: CREATE VIEW"),
     }
     // CTE in a CTE...
@@ -8103,7 +8103,7 @@ fn parse_drop_database_if_exists() {
 fn parse_create_view() {
     let sql = "CREATE VIEW myschema.myview AS SELECT foo FROM bar";
     match verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             or_alter,
             name,
             columns,
@@ -8120,7 +8120,7 @@ fn parse_create_view() {
             params,
             name_before_not_exists: _,
             secure: _,
-        } => {
+        }) => {
             assert_eq!(or_alter, false);
             assert_eq!("myschema.myview", name.to_string());
             assert_eq!(Vec::<ViewColumnDef>::new(), columns);
@@ -8146,7 +8146,7 @@ fn parse_create_view() {
 fn parse_create_view_with_options() {
     let sql = "CREATE VIEW v WITH (foo = 'bar', a = 123) AS SELECT 1";
     match verified_stmt(sql) {
-        Statement::CreateView { options, .. } => {
+        Statement::CreateView(create_view) => {
             assert_eq!(
                 CreateTableOptions::With(vec![
                     SqlOption::KeyValue {
@@ -8160,7 +8160,7 @@ fn parse_create_view_with_options() {
                         value: Expr::value(number("123")),
                     },
                 ]),
-                options
+                create_view.options
             );
         }
         _ => unreachable!(),
@@ -8173,24 +8173,21 @@ fn parse_create_view_with_columns() {
     // TODO: why does this fail for ClickHouseDialect? (#1449)
     // match all_dialects().verified_stmt(sql) {
     match all_dialects_except(|d| d.is::<ClickHouseDialect>()).verified_stmt(sql) {
-        Statement::CreateView {
-            or_alter,
-            name,
-            columns,
-            or_replace,
-            options,
-            query,
-            materialized,
-            cluster_by,
-            comment,
-            with_no_schema_binding: late_binding,
-            if_not_exists,
-            temporary,
-            to,
-            params,
-            name_before_not_exists: _,
-            secure: _,
-        } => {
+        Statement::CreateView(create_view) => {
+            let or_alter = create_view.or_alter;
+            let name = create_view.name;
+            let columns = create_view.columns;
+            let or_replace = create_view.or_replace;
+            let options = create_view.options;
+            let query = create_view.query;
+            let materialized = create_view.materialized;
+            let cluster_by = create_view.cluster_by;
+            let comment = create_view.comment;
+            let late_binding = create_view.with_no_schema_binding;
+            let if_not_exists = create_view.if_not_exists;
+            let temporary = create_view.temporary;
+            let to = create_view.to;
+            let params = create_view.params;
             assert_eq!(or_alter, false);
             assert_eq!("v", name.to_string());
             assert_eq!(
@@ -8224,7 +8221,7 @@ fn parse_create_view_with_columns() {
 fn parse_create_view_temporary() {
     let sql = "CREATE TEMPORARY VIEW myschema.myview AS SELECT foo FROM bar";
     match verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             or_alter,
             name,
             columns,
@@ -8241,7 +8238,7 @@ fn parse_create_view_temporary() {
             params,
             name_before_not_exists: _,
             secure: _,
-        } => {
+        }) => {
             assert_eq!(or_alter, false);
             assert_eq!("myschema.myview", name.to_string());
             assert_eq!(Vec::<ViewColumnDef>::new(), columns);
@@ -8265,7 +8262,7 @@ fn parse_create_view_temporary() {
 fn parse_create_or_replace_view() {
     let sql = "CREATE OR REPLACE VIEW v AS SELECT 1";
     match verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             or_alter,
             name,
             columns,
@@ -8282,7 +8279,7 @@ fn parse_create_or_replace_view() {
             params,
             name_before_not_exists: _,
             secure: _,
-        } => {
+        }) => {
             assert_eq!(or_alter, false);
             assert_eq!("v", name.to_string());
             assert_eq!(columns, vec![]);
@@ -8310,7 +8307,7 @@ fn parse_create_or_replace_materialized_view() {
     // https://docs.snowflake.com/en/sql-reference/sql/create-materialized-view.html
     let sql = "CREATE OR REPLACE MATERIALIZED VIEW v AS SELECT 1";
     match verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             or_alter,
             name,
             columns,
@@ -8327,7 +8324,7 @@ fn parse_create_or_replace_materialized_view() {
             params,
             name_before_not_exists: _,
             secure: _,
-        } => {
+        }) => {
             assert_eq!(or_alter, false);
             assert_eq!("v", name.to_string());
             assert_eq!(columns, vec![]);
@@ -8351,7 +8348,7 @@ fn parse_create_or_replace_materialized_view() {
 fn parse_create_materialized_view() {
     let sql = "CREATE MATERIALIZED VIEW myschema.myview AS SELECT foo FROM bar";
     match verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             or_alter,
             name,
             or_replace,
@@ -8368,7 +8365,7 @@ fn parse_create_materialized_view() {
             params,
             name_before_not_exists: _,
             secure: _,
-        } => {
+        }) => {
             assert_eq!(or_alter, false);
             assert_eq!("myschema.myview", name.to_string());
             assert_eq!(Vec::<ViewColumnDef>::new(), columns);
@@ -8392,7 +8389,7 @@ fn parse_create_materialized_view() {
 fn parse_create_materialized_view_with_cluster_by() {
     let sql = "CREATE MATERIALIZED VIEW myschema.myview CLUSTER BY (foo) AS SELECT foo FROM bar";
     match verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             or_alter,
             name,
             or_replace,
@@ -8409,7 +8406,7 @@ fn parse_create_materialized_view_with_cluster_by() {
             params,
             name_before_not_exists: _,
             secure: _,
-        } => {
+        }) => {
             assert_eq!(or_alter, false);
             assert_eq!("myschema.myview", name.to_string());
             assert_eq!(Vec::<ViewColumnDef>::new(), columns);
@@ -9417,21 +9414,17 @@ fn parse_drop_index() {
 fn parse_create_role() {
     let sql = "CREATE ROLE consultant";
     match verified_stmt(sql) {
-        Statement::CreateRole { names, .. } => {
-            assert_eq_vec(&["consultant"], &names);
+        Statement::CreateRole(create_role) => {
+            assert_eq_vec(&["consultant"], &create_role.names);
         }
         _ => unreachable!(),
     }
 
     let sql = "CREATE ROLE IF NOT EXISTS mysql_a, mysql_b";
     match verified_stmt(sql) {
-        Statement::CreateRole {
-            names,
-            if_not_exists,
-            ..
-        } => {
-            assert_eq_vec(&["mysql_a", "mysql_b"], &names);
-            assert!(if_not_exists);
+        Statement::CreateRole(create_role) => {
+            assert_eq_vec(&["mysql_a", "mysql_b"], &create_role.names);
+            assert!(create_role.if_not_exists);
         }
         _ => unreachable!(),
     }
@@ -13351,8 +13344,8 @@ fn test_extract_seconds_single_quote_err() {
 fn test_truncate_table_with_on_cluster() {
     let sql = "TRUNCATE TABLE t ON CLUSTER cluster_name";
     match all_dialects().verified_stmt(sql) {
-        Statement::Truncate { on_cluster, .. } => {
-            assert_eq!(on_cluster, Some(Ident::new("cluster_name")));
+        Statement::Truncate(truncate) => {
+            assert_eq!(truncate.on_cluster, Some(Ident::new("cluster_name")));
         }
         _ => panic!("Expected: TRUNCATE TABLE statement"),
     }
@@ -16407,14 +16400,14 @@ fn parse_truncate_only() {
     ];
 
     assert_eq!(
-        Statement::Truncate {
+        Statement::Truncate(Truncate {
             table_names,
             partitions: None,
             table: true,
             identity: None,
             cascade: None,
             on_cluster: None,
-        },
+        }),
         truncate
     );
 }
@@ -17288,9 +17281,9 @@ fn parse_invisible_column() {
     let sql = r#"ALTER TABLE t ADD COLUMN bar INT INVISIBLE"#;
     let stmt = verified_stmt(sql);
     match stmt {
-        Statement::AlterTable { operations, .. } => {
+        Statement::AlterTable(alter_table) => {
             assert_eq!(
-                operations,
+                alter_table.operations,
                 vec![AlterTableOperation::AddColumn {
                     column_keyword: true,
                     if_not_exists: false,
diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs
index 18189917..9dccce49 100644
--- a/tests/sqlparser_mssql.rs
+++ b/tests/sqlparser_mssql.rs
@@ -778,14 +778,10 @@ fn parse_mssql_bin_literal() {
 fn parse_mssql_create_role() {
     let sql = "CREATE ROLE mssql AUTHORIZATION helena";
     match ms().verified_stmt(sql) {
-        Statement::CreateRole {
-            names,
-            authorization_owner,
-            ..
-        } => {
-            assert_eq_vec(&["mssql"], &names);
+        Statement::CreateRole(create_role) => {
+            assert_eq_vec(&["mssql"], &create_role.names);
             assert_eq!(
-                authorization_owner,
+                create_role.authorization_owner,
                 Some(ObjectName::from(vec![Ident {
                     value: "helena".into(),
                     quote_style: None,
diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs
index 35bac548..9aaa35ba 100644
--- a/tests/sqlparser_mysql.rs
+++ b/tests/sqlparser_mysql.rs
@@ -2603,7 +2603,7 @@ fn parse_insert_with_numeric_prefix_column_name() {
 fn parse_update_with_joins() {
     let sql = "UPDATE orders AS o JOIN customers AS c ON o.customer_id = c.id SET o.completed = true WHERE c.firstname = 'Peter'";
     match mysql().verified_stmt(sql) {
-        Statement::Update {
+        Statement::Update(Update {
             table,
             assignments,
             from: _from,
@@ -2611,7 +2611,7 @@ fn parse_update_with_joins() {
             returning,
             or: None,
             limit: None,
-        } => {
+        }) => {
             assert_eq!(
                 TableWithJoins {
                     relation: TableFactor::Table {
@@ -2729,7 +2729,7 @@ fn parse_delete_with_limit() {
 #[test]
 fn parse_alter_table_add_column() {
     match mysql().verified_stmt("ALTER TABLE tab ADD COLUMN b INT FIRST") {
-        Statement::AlterTable {
+        Statement::AlterTable(AlterTable {
             name,
             if_exists,
             only,
@@ -2738,7 +2738,7 @@ fn parse_alter_table_add_column() {
             location: _,
             on_cluster: _,
             end_token: _,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "tab");
             assert!(!if_exists);
             assert!(!iceberg);
@@ -2761,13 +2761,13 @@ fn parse_alter_table_add_column() {
     }
 
     match mysql().verified_stmt("ALTER TABLE tab ADD COLUMN b INT AFTER foo") {
-        Statement::AlterTable {
+        Statement::AlterTable(AlterTable {
             name,
             if_exists,
             only,
             operations,
             ..
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "tab");
             assert!(!if_exists);
             assert!(!only);
@@ -2798,13 +2798,13 @@ fn parse_alter_table_add_columns() {
     match mysql()
         .verified_stmt("ALTER TABLE tab ADD COLUMN a TEXT FIRST, ADD COLUMN b INT AFTER foo")
     {
-        Statement::AlterTable {
+        Statement::AlterTable(AlterTable {
             name,
             if_exists,
             only,
             operations,
             ..
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "tab");
             assert!(!if_exists);
             assert!(!only);
@@ -3026,7 +3026,7 @@ fn parse_alter_table_with_algorithm() {
         "ALTER TABLE users DROP COLUMN password_digest, ALGORITHM = COPY, RENAME COLUMN name TO username";
     let stmt = mysql_and_generic().verified_stmt(sql);
     match stmt {
-        Statement::AlterTable { operations, .. } => {
+        Statement::AlterTable(AlterTable { operations, .. }) => {
             assert_eq!(
                 operations,
                 vec![
@@ -3074,7 +3074,7 @@ fn parse_alter_table_with_lock() {
         "ALTER TABLE users DROP COLUMN password_digest, LOCK = EXCLUSIVE, RENAME COLUMN name TO username";
     let stmt = mysql_and_generic().verified_stmt(sql);
     match stmt {
-        Statement::AlterTable { operations, .. } => {
+        Statement::AlterTable(AlterTable { operations, .. }) => {
             assert_eq!(
                 operations,
                 vec![
@@ -3857,7 +3857,7 @@ fn parse_revoke() {
 fn parse_create_view_algorithm_param() {
     let sql = "CREATE ALGORITHM = MERGE VIEW foo AS SELECT 1";
     let stmt = mysql().verified_stmt(sql);
-    if let Statement::CreateView {
+    if let Statement::CreateView(CreateView {
         params:
             Some(CreateViewParams {
                 algorithm,
@@ -3865,7 +3865,7 @@ fn parse_create_view_algorithm_param() {
                 security,
             }),
         ..
-    } = stmt
+    }) = stmt
     {
         assert_eq!(algorithm, Some(CreateViewAlgorithm::Merge));
         assert!(definer.is_none());
@@ -3881,7 +3881,7 @@ fn parse_create_view_algorithm_param() {
 fn parse_create_view_definer_param() {
     let sql = "CREATE DEFINER = 'jeffrey'@'localhost' VIEW foo AS SELECT 1";
     let stmt = mysql().verified_stmt(sql);
-    if let Statement::CreateView {
+    if let Statement::CreateView(CreateView {
         params:
             Some(CreateViewParams {
                 algorithm,
@@ -3889,7 +3889,7 @@ fn parse_create_view_definer_param() {
                 security,
             }),
         ..
-    } = stmt
+    }) = stmt
     {
         assert!(algorithm.is_none());
         if let Some(GranteeName::UserHost { user, host }) = definer {
@@ -3910,7 +3910,7 @@ fn parse_create_view_definer_param() {
 fn parse_create_view_security_param() {
     let sql = "CREATE SQL SECURITY DEFINER VIEW foo AS SELECT 1";
     let stmt = mysql().verified_stmt(sql);
-    if let Statement::CreateView {
+    if let Statement::CreateView(CreateView {
         params:
             Some(CreateViewParams {
                 algorithm,
@@ -3918,7 +3918,7 @@ fn parse_create_view_security_param() {
                 security,
             }),
         ..
-    } = stmt
+    }) = stmt
     {
         assert!(algorithm.is_none());
         assert!(definer.is_none());
@@ -3933,7 +3933,7 @@ fn parse_create_view_security_param() {
 fn parse_create_view_multiple_params() {
     let sql = "CREATE ALGORITHM = UNDEFINED DEFINER = `root`@`%` SQL SECURITY INVOKER VIEW foo AS SELECT 1";
     let stmt = mysql().verified_stmt(sql);
-    if let Statement::CreateView {
+    if let Statement::CreateView(CreateView {
         params:
             Some(CreateViewParams {
                 algorithm,
@@ -3941,7 +3941,7 @@ fn parse_create_view_multiple_params() {
                 security,
             }),
         ..
-    } = stmt
+    }) = stmt
     {
         assert_eq!(algorithm, Some(CreateViewAlgorithm::Undefined));
         if let Some(GranteeName::UserHost { user, host }) = definer {
@@ -4179,7 +4179,7 @@ fn test_variable_assignment_using_colon_equal() {
     let stmt = mysql().verified_stmt(sql_update);
 
     match stmt {
-        Statement::Update { assignments, .. } => {
+        Statement::Update(Update { assignments, .. }) => {
             assert_eq!(
                 assignments,
                 vec![Assignment {
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index 45ae32da..3c2a98e1 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -605,7 +605,7 @@ fn parse_alter_table_constraints_unique_nulls_distinct() {
     match pg_and_generic()
         .verified_stmt("ALTER TABLE t ADD CONSTRAINT b UNIQUE NULLS NOT DISTINCT (c)")
     {
-        Statement::AlterTable { operations, .. } => match &operations[0] {
+        Statement::AlterTable(alter_table) => match &alter_table.operations[0] {
             AlterTableOperation::AddConstraint {
                 constraint: TableConstraint::Unique(constraint),
                 ..
@@ -674,93 +674,93 @@ fn parse_create_extension() {
 fn parse_drop_extension() {
     assert_eq!(
         pg_and_generic().verified_stmt("DROP EXTENSION extension_name"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name".into()],
             if_exists: false,
             cascade_or_restrict: None,
-        }
+        })
     );
     assert_eq!(
         pg_and_generic().verified_stmt("DROP EXTENSION extension_name CASCADE"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name".into()],
             if_exists: false,
             cascade_or_restrict: Some(ReferentialAction::Cascade),
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic().verified_stmt("DROP EXTENSION extension_name RESTRICT"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name".into()],
             if_exists: false,
             cascade_or_restrict: Some(ReferentialAction::Restrict),
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic().verified_stmt("DROP EXTENSION extension_name, extension_name2 CASCADE"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name".into(), "extension_name2".into()],
             if_exists: false,
             cascade_or_restrict: Some(ReferentialAction::Cascade),
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic().verified_stmt("DROP EXTENSION extension_name, extension_name2 RESTRICT"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name".into(), "extension_name2".into()],
             if_exists: false,
             cascade_or_restrict: Some(ReferentialAction::Restrict),
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic().verified_stmt("DROP EXTENSION IF EXISTS extension_name"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name".into()],
             if_exists: true,
             cascade_or_restrict: None,
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic().verified_stmt("DROP EXTENSION IF EXISTS extension_name CASCADE"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name".into()],
             if_exists: true,
             cascade_or_restrict: Some(ReferentialAction::Cascade),
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic().verified_stmt("DROP EXTENSION IF EXISTS extension_name RESTRICT"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name".into()],
             if_exists: true,
             cascade_or_restrict: Some(ReferentialAction::Restrict),
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic()
             .verified_stmt("DROP EXTENSION IF EXISTS extension_name1, extension_name2 CASCADE"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name1".into(), "extension_name2".into()],
             if_exists: true,
             cascade_or_restrict: Some(ReferentialAction::Cascade),
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic()
             .verified_stmt("DROP EXTENSION IF EXISTS extension_name1, extension_name2 RESTRICT"),
-        Statement::DropExtension {
+        Statement::DropExtension(DropExtension {
             names: vec!["extension_name1".into(), "extension_name2".into()],
             if_exists: true,
             cascade_or_restrict: Some(ReferentialAction::Restrict),
-        }
+        })
     );
 }
 
@@ -829,13 +829,13 @@ fn parse_alter_table_alter_column_add_generated() {
 #[test]
 fn parse_alter_table_add_columns() {
     match pg().verified_stmt("ALTER TABLE IF EXISTS ONLY tab ADD COLUMN a TEXT, ADD COLUMN b INT") {
-        Statement::AlterTable {
+        Statement::AlterTable(AlterTable {
             name,
             if_exists,
             only,
             operations,
             ..
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "tab");
             assert!(if_exists);
             assert!(only);
@@ -909,13 +909,13 @@ fn parse_alter_table_owner_to() {
 
     for case in test_cases {
         match pg_and_generic().verified_stmt(case.sql) {
-            Statement::AlterTable {
+            Statement::AlterTable(AlterTable {
                 name,
                 if_exists: _,
                 only: _,
                 operations,
                 ..
-            } => {
+            }) => {
                 assert_eq!(name.to_string(), "tab");
                 assert_eq!(
                     operations,
@@ -2009,7 +2009,7 @@ fn parse_pg_returning() {
              RETURNING temp_lo AS lo, temp_hi AS hi, prcp",
     );
     match stmt {
-        Statement::Update { returning, .. } => {
+        Statement::Update(Update { returning, .. }) => {
             assert_eq!(
                 Some(vec![
                     SelectItem::ExprWithAlias {
@@ -3833,47 +3833,29 @@ fn parse_custom_operator() {
 fn parse_create_role() {
     let sql = "CREATE ROLE IF NOT EXISTS mysql_a, mysql_b";
     match pg().verified_stmt(sql) {
-        Statement::CreateRole {
-            names,
-            if_not_exists,
-            ..
-        } => {
-            assert_eq_vec(&["mysql_a", "mysql_b"], &names);
-            assert!(if_not_exists);
+        Statement::CreateRole(create_role) => {
+            assert_eq_vec(&["mysql_a", "mysql_b"], &create_role.names);
+            assert!(create_role.if_not_exists);
         }
         _ => unreachable!(),
     }
 
     let sql = "CREATE ROLE abc LOGIN PASSWORD NULL";
     match pg().parse_sql_statements(sql).as_deref() {
-        Ok(
-            [Statement::CreateRole {
-                names,
-                login,
-                password,
-                ..
-            }],
-        ) => {
-            assert_eq_vec(&["abc"], names);
-            assert_eq!(*login, Some(true));
-            assert_eq!(*password, Some(Password::NullPassword));
+        Ok([Statement::CreateRole(create_role)]) => {
+            assert_eq_vec(&["abc"], &create_role.names);
+            assert_eq!(create_role.login, Some(true));
+            assert_eq!(create_role.password, Some(Password::NullPassword));
         }
         err => panic!("Failed to parse CREATE ROLE test case: {err:?}"),
     }
 
     let sql = "CREATE ROLE abc WITH LOGIN PASSWORD NULL";
     match pg().parse_sql_statements(sql).as_deref() {
-        Ok(
-            [Statement::CreateRole {
-                names,
-                login,
-                password,
-                ..
-            }],
-        ) => {
-            assert_eq_vec(&["abc"], names);
-            assert_eq!(*login, Some(true));
-            assert_eq!(*password, Some(Password::NullPassword));
+        Ok([Statement::CreateRole(create_role)]) => {
+            assert_eq_vec(&["abc"], &create_role.names);
+            assert_eq!(create_role.login, Some(true));
+            assert_eq!(create_role.password, Some(Password::NullPassword));
         }
         err => panic!("Failed to parse CREATE ROLE test case: {err:?}"),
     }
@@ -3881,69 +3863,44 @@ fn parse_create_role() {
     let sql = "CREATE ROLE magician WITH SUPERUSER CREATEROLE NOCREATEDB BYPASSRLS INHERIT PASSWORD 'abcdef' LOGIN VALID UNTIL '2025-01-01' IN ROLE role1, role2 ROLE role3 ADMIN role4, role5 REPLICATION";
     // Roundtrip order of optional parameters is not preserved
     match pg().parse_sql_statements(sql).as_deref() {
-        Ok(
-            [Statement::CreateRole {
-                names,
-                if_not_exists,
-                bypassrls,
-                login,
-                inherit,
-                password,
-                superuser,
-                create_db,
-                create_role,
-                replication,
-                connection_limit,
-                valid_until,
-                in_role,
-                in_group,
-                role,
-                user: _,
-                admin,
-                authorization_owner,
-            }],
-        ) => {
-            assert_eq_vec(&["magician"], names);
-            assert!(!*if_not_exists);
-            assert_eq!(*login, Some(true));
-            assert_eq!(*inherit, Some(true));
-            assert_eq!(*bypassrls, Some(true));
+        Ok([Statement::CreateRole(create_role)]) => {
+            assert_eq_vec(&["magician"], &create_role.names);
+            assert!(!create_role.if_not_exists);
+            assert_eq!(create_role.login, Some(true));
+            assert_eq!(create_role.inherit, Some(true));
+            assert_eq!(create_role.bypassrls, Some(true));
             assert_eq!(
-                *password,
+                create_role.password,
                 Some(Password::Password(Expr::Value(
                     (Value::SingleQuotedString("abcdef".into())).with_empty_span()
                 )))
             );
-            assert_eq!(*superuser, Some(true));
-            assert_eq!(*create_db, Some(false));
-            assert_eq!(*create_role, Some(true));
-            assert_eq!(*replication, Some(true));
-            assert_eq!(*connection_limit, None);
+            assert_eq!(create_role.superuser, Some(true));
+            assert_eq!(create_role.create_db, Some(false));
+            assert_eq!(create_role.create_role, Some(true));
+            assert_eq!(create_role.replication, Some(true));
+            assert_eq!(create_role.connection_limit, None);
             assert_eq!(
-                *valid_until,
+                create_role.valid_until,
                 Some(Expr::Value(
                     (Value::SingleQuotedString("2025-01-01".into())).with_empty_span()
                 ))
             );
-            assert_eq_vec(&["role1", "role2"], in_role);
-            assert!(in_group.is_empty());
-            assert_eq_vec(&["role3"], role);
-            assert_eq_vec(&["role4", "role5"], admin);
-            assert_eq!(*authorization_owner, None);
+            assert_eq_vec(&["role1", "role2"], &create_role.in_role);
+            assert!(create_role.in_group.is_empty());
+            assert_eq_vec(&["role3"], &create_role.role);
+            assert_eq_vec(&["role4", "role5"], &create_role.admin);
+            assert_eq!(create_role.authorization_owner, None);
         }
         err => panic!("Failed to parse CREATE ROLE test case: {err:?}"),
     }
 
     let sql = "CREATE ROLE abc WITH USER foo, bar ROLE baz ";
     match pg().parse_sql_statements(sql).as_deref() {
-        Ok(
-            [Statement::CreateRole {
-                names, user, role, ..
-            }],
-        ) => {
-            assert_eq_vec(&["abc"], names);
-            assert_eq_vec(&["foo", "bar"], user);
-            assert_eq_vec(&["baz"], role);
+        Ok([Statement::CreateRole(create_role)]) => {
+            assert_eq_vec(&["abc"], &create_role.names);
+            assert_eq_vec(&["foo", "bar"], &create_role.user);
+            assert_eq_vec(&["baz"], &create_role.role);
         }
         err => panic!("Failed to parse CREATE ROLE test case: {err:?}"),
     }
@@ -4532,7 +4489,7 @@ fn parse_drop_function() {
     let sql = "DROP FUNCTION IF EXISTS test_func";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::DropFunction {
+        Statement::DropFunction(DropFunction {
             if_exists: true,
             func_desc: vec![FunctionDesc {
                 name: ObjectName::from(vec![Ident {
@@ -4543,13 +4500,13 @@ fn parse_drop_function() {
                 args: None
             }],
             drop_behavior: None
-        }
+        })
     );
 
     let sql = "DROP FUNCTION IF EXISTS test_func(a INTEGER, IN b INTEGER = 1)";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::DropFunction {
+        Statement::DropFunction(DropFunction {
             if_exists: true,
             func_desc: vec![FunctionDesc {
                 name: ObjectName::from(vec![Ident {
@@ -4570,13 +4527,13 @@ fn parse_drop_function() {
                 ]),
             }],
             drop_behavior: None
-        }
+        })
     );
 
     let sql = "DROP FUNCTION IF EXISTS test_func1(a INTEGER, IN b INTEGER = 1), test_func2(a VARCHAR, IN b INTEGER = 1)";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::DropFunction {
+        Statement::DropFunction(DropFunction {
             if_exists: true,
             func_desc: vec![
                 FunctionDesc {
@@ -4617,7 +4574,7 @@ fn parse_drop_function() {
                 }
             ],
             drop_behavior: None
-        }
+        })
     );
 }
 
@@ -4957,14 +4914,14 @@ fn parse_truncate() {
         only: false,
     }];
     assert_eq!(
-        Statement::Truncate {
+        Statement::Truncate(Truncate {
             table_names,
             partitions: None,
             table: false,
             identity: None,
             cascade: None,
             on_cluster: None,
-        },
+        }),
         truncate
     );
 }
@@ -4981,14 +4938,14 @@ fn parse_truncate_with_options() {
     }];
 
     assert_eq!(
-        Statement::Truncate {
+        Statement::Truncate(Truncate {
             table_names,
             partitions: None,
             table: true,
             identity: Some(TruncateIdentityOption::Restart),
             cascade: Some(CascadeOption::Cascade),
             on_cluster: None,
-        },
+        }),
         truncate
     );
 }
@@ -5014,14 +4971,14 @@ fn parse_truncate_with_table_list() {
     ];
 
     assert_eq!(
-        Statement::Truncate {
+        Statement::Truncate(Truncate {
             table_names,
             partitions: None,
             table: true,
             identity: Some(TruncateIdentityOption::Restart),
             cascade: Some(CascadeOption::Cascade),
             on_cluster: None,
-        },
+        }),
         truncate
     );
 }
@@ -6409,7 +6366,7 @@ fn parse_varbit_datatype() {
 #[test]
 fn parse_alter_table_replica_identity() {
     match pg_and_generic().verified_stmt("ALTER TABLE foo REPLICA IDENTITY FULL") {
-        Statement::AlterTable { operations, .. } => {
+        Statement::AlterTable(AlterTable { operations, .. }) => {
             assert_eq!(
                 operations,
                 vec![AlterTableOperation::ReplicaIdentity {
@@ -6421,7 +6378,7 @@ fn parse_alter_table_replica_identity() {
     }
 
     match pg_and_generic().verified_stmt("ALTER TABLE foo REPLICA IDENTITY USING INDEX foo_idx") {
-        Statement::AlterTable { operations, .. } => {
+        Statement::AlterTable(AlterTable { operations, .. }) => {
             assert_eq!(
                 operations,
                 vec![AlterTableOperation::ReplicaIdentity {
@@ -6469,7 +6426,7 @@ fn parse_alter_table_constraint_not_valid() {
     match pg_and_generic().verified_stmt(
         "ALTER TABLE foo ADD CONSTRAINT bar FOREIGN KEY (baz) REFERENCES other(ref) NOT VALID",
     ) {
-        Statement::AlterTable { operations, .. } => {
+        Statement::AlterTable(AlterTable { operations, .. }) => {
             assert_eq!(
                 operations,
                 vec![AlterTableOperation::AddConstraint {
@@ -6495,7 +6452,7 @@ fn parse_alter_table_constraint_not_valid() {
 #[test]
 fn parse_alter_table_validate_constraint() {
     match pg_and_generic().verified_stmt("ALTER TABLE foo VALIDATE CONSTRAINT bar") {
-        Statement::AlterTable { operations, .. } => {
+        Statement::AlterTable(AlterTable { operations, .. }) => {
             assert_eq!(
                 operations,
                 vec![AlterTableOperation::ValidateConstraint { name: "bar".into() }]
diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs
index e04bfaf5..e7a12834 100644
--- a/tests/sqlparser_snowflake.rs
+++ b/tests/sqlparser_snowflake.rs
@@ -53,11 +53,11 @@ fn parse_sf_create_secure_view_and_materialized_view() {
         "CREATE OR REPLACE SECURE MATERIALIZED VIEW v AS SELECT 1",
     ] {
         match snowflake().verified_stmt(sql) {
-            Statement::CreateView {
+            Statement::CreateView(CreateView {
                 secure,
                 materialized,
                 ..
-            } => {
+            }) => {
                 assert!(secure);
                 if sql.contains("MATERIALIZED") {
                     assert!(materialized);
@@ -1047,7 +1047,7 @@ fn parse_sf_create_or_replace_with_comment_for_snowflake() {
         test_utils::TestedDialects::new(vec![Box::new(SnowflakeDialect {}) as Box<dyn Dialect>]);
 
     match dialect.verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             name,
             columns,
             or_replace,
@@ -1060,7 +1060,7 @@ fn parse_sf_create_or_replace_with_comment_for_snowflake() {
             if_not_exists,
             temporary,
             ..
-        } => {
+        }) => {
             assert_eq!("v", name.to_string());
             assert_eq!(columns, vec![]);
             assert_eq!(options, CreateTableOptions::None);
@@ -3281,7 +3281,7 @@ fn parse_view_column_descriptions() {
     let sql = "CREATE OR REPLACE VIEW v (a COMMENT 'Comment', b) AS SELECT a, b FROM table1";
 
     match snowflake().verified_stmt(sql) {
-        Statement::CreateView { name, columns, .. } => {
+        Statement::CreateView(CreateView { name, columns, .. }) => {
             assert_eq!(name.to_string(), "v");
             assert_eq!(
                 columns,
diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs
index 114aca03..5083ecd0 100644
--- a/tests/sqlparser_sqlite.rs
+++ b/tests/sqlparser_sqlite.rs
@@ -166,7 +166,7 @@ fn parse_create_virtual_table() {
 fn parse_create_view_temporary_if_not_exists() {
     let sql = "CREATE TEMPORARY VIEW IF NOT EXISTS myschema.myview AS SELECT foo FROM bar";
     match sqlite_and_generic().verified_stmt(sql) {
-        Statement::CreateView {
+        Statement::CreateView(CreateView {
             name,
             columns,
             query,
@@ -179,7 +179,7 @@ fn parse_create_view_temporary_if_not_exists() {
             if_not_exists,
             temporary,
             ..
-        } => {
+        }) => {
             assert_eq!("myschema.myview", name.to_string());
             assert_eq!(Vec::<ViewColumnDef>::new(), columns);
             assert_eq!("SELECT foo FROM bar", query.to_string());
@@ -467,7 +467,7 @@ fn parse_update_tuple_row_values() {
     // See https://github.com/sqlparser-rs/sqlparser-rs/issues/1311
     assert_eq!(
         sqlite().verified_stmt("UPDATE x SET (a, b) = (1, 2)"),
-        Statement::Update {
+        Statement::Update(Update {
             or: None,
             assignments: vec![Assignment {
                 target: AssignmentTarget::Tuple(vec![
@@ -487,7 +487,7 @@ fn parse_update_tuple_row_values() {
             from: None,
             returning: None,
             limit: None
-        }
+        })
     );
 }
 
@@ -596,7 +596,7 @@ fn test_regexp_operator() {
 #[test]
 fn test_update_delete_limit() {
     match sqlite().verified_stmt("UPDATE foo SET bar = 1 LIMIT 99") {
-        Statement::Update { limit, .. } => {
+        Statement::Update(Update { limit, .. }) => {
             assert_eq!(limit, Some(Expr::value(number("99"))));
         }
         _ => unreachable!(),


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@datafusion.apache.org
For additional commands, e-mail: commits-help@datafusion.apache.org