Move inline Statement variants into named structs
diff --git a/src/ast/helpers/stmt_create_database.rs b/src/ast/helpers/stmt_create_database.rs
index e524228..866c418 100644
--- a/src/ast/helpers/stmt_create_database.rs
+++ b/src/ast/helpers/stmt_create_database.rs
@@ -24,6 +24,7 @@
 #[cfg(feature = "visitor")]
 use sqlparser_derive::{Visit, VisitMut};
 
+use crate::ast::CreateDatabaseStatement;
 use crate::ast::{
     CatalogSyncNamespaceMode, ContactEntry, ObjectName, Statement, StorageSerializationPolicy, Tag,
 };
@@ -278,7 +279,7 @@
 
     /// Build the `CREATE DATABASE` statement.
     pub fn build(self) -> Statement {
-        Statement::CreateDatabase {
+        Statement::CreateDatabase(CreateDatabaseStatement {
             db_name: self.db_name,
             if_not_exists: self.if_not_exists,
             managed_location: self.managed_location,
@@ -301,7 +302,7 @@
             catalog_sync_namespace_flatten_delimiter: self.catalog_sync_namespace_flatten_delimiter,
             with_tags: self.with_tags,
             with_contacts: self.with_contacts,
-        }
+        })
     }
 }
 
@@ -310,7 +311,7 @@
 
     fn try_from(stmt: Statement) -> Result<Self, Self::Error> {
         match stmt {
-            Statement::CreateDatabase {
+            Statement::CreateDatabase(CreateDatabaseStatement {
                 db_name,
                 if_not_exists,
                 location,
@@ -333,7 +334,7 @@
                 catalog_sync_namespace_flatten_delimiter,
                 with_tags,
                 with_contacts,
-            } => Ok(Self {
+            }) => Ok(Self {
                 db_name,
                 if_not_exists,
                 location,
@@ -367,7 +368,7 @@
 #[cfg(test)]
 mod tests {
     use crate::ast::helpers::stmt_create_database::CreateDatabaseBuilder;
-    use crate::ast::{Ident, ObjectName, Statement};
+    use crate::ast::{CommitStatement, Ident, ObjectName, Statement};
     use crate::parser::ParserError;
 
     #[test]
@@ -381,11 +382,11 @@
 
     #[test]
     pub fn test_from_invalid_statement() {
-        let stmt = Statement::Commit {
+        let stmt = Statement::Commit(CommitStatement {
             chain: false,
             end: false,
             modifier: None,
-        };
+        });
 
         assert_eq!(
             CreateDatabaseBuilder::try_from(stmt).unwrap_err(),
diff --git a/src/ast/helpers/stmt_create_table.rs b/src/ast/helpers/stmt_create_table.rs
index 84a93dd..dc61330 100644
--- a/src/ast/helpers/stmt_create_table.rs
+++ b/src/ast/helpers/stmt_create_table.rs
@@ -767,7 +767,7 @@
 #[cfg(test)]
 mod tests {
     use crate::ast::helpers::stmt_create_table::CreateTableBuilder;
-    use crate::ast::{Ident, ObjectName, Statement};
+    use crate::ast::{CommitStatement, Ident, ObjectName, Statement};
     use crate::parser::ParserError;
 
     #[test]
@@ -782,11 +782,11 @@
 
     #[test]
     pub fn test_from_invalid_statement() {
-        let stmt = Statement::Commit {
+        let stmt = Statement::Commit(CommitStatement {
             chain: false,
             end: false,
             modifier: None,
-        };
+        });
 
         assert_eq!(
             CreateTableBuilder::try_from(stmt).unwrap_err(),
diff --git a/src/ast/mod.rs b/src/ast/mod.rs
index 509478b..197e0bd 100644
--- a/src/ast/mod.rs
+++ b/src/ast/mod.rs
@@ -149,7 +149,9 @@
 mod operator;
 mod query;
 mod spans;
+mod statements;
 pub use spans::Spanned;
+pub use statements::*;
 
 pub mod comments;
 mod trigger;
@@ -3630,31 +3632,14 @@
     /// ```sql
     /// INSTALL
     /// ```
-    Install {
-        /// Only for DuckDB
-        extension_name: Ident,
-    },
+    Install(InstallStatement),
     /// ```sql
     /// LOAD
     /// ```
-    Load {
-        /// Only for DuckDB
-        extension_name: Ident,
-    },
+    Load(LoadStatement),
     // TODO: Support ROW FORMAT
     /// LOAD DATA from a directory or query source.
-    Directory {
-        /// Whether to overwrite existing files.
-        overwrite: bool,
-        /// Whether the directory is local to the server.
-        local: bool,
-        /// Path to the directory or files.
-        path: String,
-        /// Optional file format for the data.
-        file_format: Option<FileFormat>,
-        /// Source query providing data to load.
-        source: Box<Query>,
-    },
+    Directory(DirectoryStatement),
     /// A `CASE` statement.
     Case(CaseStatement),
     /// An `IF` statement.
@@ -3670,20 +3655,7 @@
     /// ```sql
     /// COPY [TO | FROM] ...
     /// ```
-    Copy {
-        /// The source of 'COPY TO', or the target of 'COPY FROM'
-        source: CopySource,
-        /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
-        to: bool,
-        /// The target of 'COPY TO', or the source of 'COPY FROM'
-        target: CopyTarget,
-        /// WITH options (from PostgreSQL version 9.0)
-        options: Vec<CopyOption>,
-        /// WITH options (before PostgreSQL version 9.0)
-        legacy_options: Vec<CopyLegacyOption>,
-        /// VALUES a vector of values to be copied
-        values: Vec<Option<String>>,
-    },
+    Copy(CopyStatement),
     /// ```sql
     /// COPY INTO <table> | <location>
     /// ```
@@ -3695,36 +3667,7 @@
     /// Postgres. Although they share common prefix, it is reasonable to implement them
     /// in different enums. This can be refactored later once custom dialects
     /// are allowed to have custom Statements.
-    CopyIntoSnowflake {
-        /// Kind of COPY INTO operation (table or location).
-        kind: CopyIntoSnowflakeKind,
-        /// Target object for the COPY INTO operation.
-        into: ObjectName,
-        /// Optional list of target columns.
-        into_columns: Option<Vec<Ident>>,
-        /// Optional source object name (staged data).
-        from_obj: Option<ObjectName>,
-        /// Optional alias for the source object.
-        from_obj_alias: Option<Ident>,
-        /// Stage-specific parameters (e.g., credentials, path).
-        stage_params: StageParamsObject,
-        /// Optional list of transformations applied when loading.
-        from_transformations: Option<Vec<StageLoadSelectItemKind>>,
-        /// Optional source query instead of a staged object.
-        from_query: Option<Box<Query>>,
-        /// Optional list of specific file names to load.
-        files: Option<Vec<String>>,
-        /// Optional filename matching pattern.
-        pattern: Option<String>,
-        /// File format options.
-        file_format: KeyValueOptions,
-        /// Additional copy options.
-        copy_options: KeyValueOptions,
-        /// Optional validation mode string.
-        validation_mode: Option<String>,
-        /// Optional partition expression for loading.
-        partition: Option<Box<Expr>>,
-    },
+    CopyIntoSnowflake(CopyIntoSnowflakeStatement),
     /// ```sql
     /// OPEN cursor_name
     /// ```
@@ -3734,10 +3677,7 @@
     /// CLOSE
     /// ```
     /// Closes the portal underlying an open cursor.
-    Close {
-        /// Cursor name
-        cursor: CloseCursor,
-    },
+    Close(CloseStatement),
     /// ```sql
     /// UPDATE
     /// ```
@@ -3758,17 +3698,7 @@
     /// CREATE VIRTUAL TABLE .. USING <module_name> (<module_args>)`
     /// ```
     /// Sqlite specific statement
-    CreateVirtualTable {
-        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
-        /// Name of the virtual table module instance.
-        name: ObjectName,
-        /// `true` when `IF NOT EXISTS` was specified.
-        if_not_exists: bool,
-        /// Module name used by the virtual table.
-        module_name: Ident,
-        /// Arguments passed to the module.
-        module_args: Vec<Ident>,
-    },
+    CreateVirtualTable(CreateVirtualTableStatement),
     /// ```sql
     /// `CREATE INDEX`
     /// ```
@@ -3782,22 +3712,7 @@
     /// CREATE SECRET
     /// ```
     /// See [DuckDB](https://duckdb.org/docs/sql/statements/create_secret.html)
-    CreateSecret {
-        /// `true` when `OR REPLACE` was specified.
-        or_replace: bool,
-        /// Optional `TEMPORARY` flag.
-        temporary: Option<bool>,
-        /// `true` when `IF NOT EXISTS` was present.
-        if_not_exists: bool,
-        /// Optional secret name.
-        name: Option<Ident>,
-        /// Optional storage specifier identifier.
-        storage_specifier: Option<Ident>,
-        /// The secret type identifier.
-        secret_type: Ident,
-        /// Additional secret options.
-        options: Vec<SecretOption>,
-    },
+    CreateSecret(CreateSecretStatement),
     /// A `CREATE SERVER` statement.
     CreateServer(CreateServerStatement),
     /// ```sql
@@ -3841,26 +3756,11 @@
     /// ```sql
     /// ALTER INDEX
     /// ```
-    AlterIndex {
-        /// Name of the index to alter.
-        name: ObjectName,
-        /// The operation to perform on the index.
-        operation: AlterIndexOperation,
-    },
+    AlterIndex(AlterIndexStatement),
     /// ```sql
     /// ALTER VIEW
     /// ```
-    AlterView {
-        /// View name being altered.
-        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
-        name: ObjectName,
-        /// Optional new column list for the view.
-        columns: Vec<Ident>,
-        /// Replacement query for the view definition.
-        query: Box<Query>,
-        /// Additional WITH options for the view.
-        with_options: Vec<SqlOption>,
-    },
+    AlterView(AlterViewStatement),
     /// ```sql
     /// ALTER FUNCTION
     /// ALTER AGGREGATE
@@ -3900,12 +3800,7 @@
     /// ```sql
     /// ALTER ROLE
     /// ```
-    AlterRole {
-        /// Role name being altered.
-        name: Ident,
-        /// Operation to perform on the role.
-        operation: AlterRoleOperation,
-    },
+    AlterRole(AlterRoleStatement),
     /// ```sql
     /// ALTER POLICY <NAME> ON <TABLE NAME> [<OPERATION>]
     /// ```
@@ -3919,94 +3814,34 @@
     /// ALTER CONNECTOR connector_name SET OWNER [USER|ROLE] user_or_role;
     /// ```
     /// (Hive-specific)
-    AlterConnector {
-        /// Name of the connector to alter.
-        name: Ident,
-        /// Optional connector properties to set.
-        properties: Option<Vec<SqlOption>>,
-        /// Optional new URL for the connector.
-        url: Option<String>,
-        /// Optional new owner specification.
-        owner: Option<ddl::AlterConnectorOwner>,
-    },
+    AlterConnector(AlterConnectorStatement),
     /// ```sql
     /// ALTER SESSION SET sessionParam
     /// ALTER SESSION UNSET <param_name> [ , <param_name> , ... ]
     /// ```
     /// See <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
-    AlterSession {
-        /// true is to set for the session parameters, false is to unset
-        set: bool,
-        /// The session parameters to set or unset
-        session_params: KeyValueOptions,
-    },
+    AlterSession(AlterSessionStatement),
     /// ```sql
     /// ATTACH DATABASE 'path/to/file' AS alias
     /// ```
     /// (SQLite-specific)
-    AttachDatabase {
-        /// The name to bind to the newly attached database
-        schema_name: Ident,
-        /// An expression that indicates the path to the database file
-        database_file_name: Expr,
-        /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
-        database: bool,
-    },
+    AttachDatabase(AttachDatabaseStatement),
     /// (DuckDB-specific)
     /// ```sql
     /// ATTACH 'sqlite_file.db' AS sqlite_db (READ_ONLY, TYPE SQLITE);
     /// ```
     /// See <https://duckdb.org/docs/sql/statements/attach.html>
-    AttachDuckDBDatabase {
-        /// `true` when `IF NOT EXISTS` was present.
-        if_not_exists: bool,
-        /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
-        database: bool,
-        /// The path identifier to the database file being attached.
-        database_path: Ident,
-        /// Optional alias assigned to the attached database.
-        database_alias: Option<Ident>,
-        /// Dialect-specific attach options (e.g., `READ_ONLY`).
-        attach_options: Vec<AttachDuckDBDatabaseOption>,
-    },
+    AttachDuckDBDatabase(AttachDuckDBDatabaseStatement),
     /// (DuckDB-specific)
     /// ```sql
     /// DETACH db_alias;
     /// ```
     /// See <https://duckdb.org/docs/sql/statements/attach.html>
-    DetachDuckDBDatabase {
-        /// `true` when `IF EXISTS` was present.
-        if_exists: bool,
-        /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
-        database: bool,
-        /// Alias of the database to detach.
-        database_alias: Ident,
-    },
+    DetachDuckDBDatabase(DetachDuckDBDatabaseStatement),
     /// ```sql
     /// DROP [TABLE, VIEW, ...]
     /// ```
-    Drop {
-        /// The type of the object to drop: TABLE, VIEW, etc.
-        object_type: ObjectType,
-        /// An optional `IF EXISTS` clause. (Non-standard.)
-        if_exists: bool,
-        /// One or more objects to drop. (ANSI SQL requires exactly one.)
-        names: Vec<ObjectName>,
-        /// Whether `CASCADE` was specified. This will be `false` when
-        /// `RESTRICT` or no drop behavior at all was specified.
-        cascade: bool,
-        /// Whether `RESTRICT` was specified. This will be `false` when
-        /// `CASCADE` or no drop behavior at all was specified.
-        restrict: bool,
-        /// Hive allows you specify whether the table's stored data will be
-        /// deleted along with the dropped table
-        purge: bool,
-        /// MySQL-specific "TEMPORARY" keyword
-        temporary: bool,
-        /// MySQL-specific drop index syntax, which requires table specification
-        /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
-        table: Option<ObjectName>,
-    },
+    Drop(DropStatement),
     /// ```sql
     /// DROP FUNCTION
     /// ```
@@ -4022,27 +3857,11 @@
     /// ```sql
     /// DROP PROCEDURE
     /// ```
-    DropProcedure {
-        /// `true` when `IF EXISTS` was present.
-        if_exists: bool,
-        /// One or more functions/procedures to drop.
-        proc_desc: Vec<FunctionDesc>,
-        /// Optional drop behavior (`CASCADE` or `RESTRICT`).
-        drop_behavior: Option<DropBehavior>,
-    },
+    DropProcedure(DropProcedureStatement),
     /// ```sql
     /// DROP SECRET
     /// ```
-    DropSecret {
-        /// `true` when `IF EXISTS` was present.
-        if_exists: bool,
-        /// Optional `TEMPORARY` marker.
-        temporary: Option<bool>,
-        /// Name of the secret to drop.
-        name: Ident,
-        /// Optional storage specifier identifier.
-        storage_specifier: Option<Ident>,
-    },
+    DropSecret(DropSecretStatement),
     ///```sql
     /// DROP POLICY
     /// ```
@@ -4052,12 +3871,7 @@
     /// DROP CONNECTOR
     /// ```
     /// See [Hive](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362034#LanguageManualDDL-DropConnector)
-    DropConnector {
-        /// `true` when `IF EXISTS` was present.
-        if_exists: bool,
-        /// Name of the connector to drop.
-        name: Ident,
-    },
+    DropConnector(DropConnectorStatement),
     /// ```sql
     /// DECLARE
     /// ```
@@ -4065,10 +3879,7 @@
     ///
     /// Note: this is a PostgreSQL-specific statement,
     /// but may also compatible with other SQL.
-    Declare {
-        /// Cursor declaration statements collected by `DECLARE`.
-        stmts: Vec<Declare>,
-    },
+    Declare(DeclareStatement),
     /// ```sql
     /// CREATE EXTENSION [ IF NOT EXISTS ] extension_name
     ///     [ WITH ] [ SCHEMA schema_name ]
@@ -4115,152 +3926,71 @@
     ///
     /// Note: this is a PostgreSQL-specific statement,
     /// but may also compatible with other SQL.
-    Fetch {
-        /// Cursor name
-        name: Ident,
-        /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
-        direction: FetchDirection,
-        /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
-        position: FetchPosition,
-        /// Optional target table to fetch rows into.
-        into: Option<ObjectName>,
-    },
+    Fetch(FetchStatement),
     /// ```sql
     /// FLUSH [NO_WRITE_TO_BINLOG | LOCAL] flush_option [, flush_option] ... | tables_option
     /// ```
     ///
     /// Note: this is a Mysql-specific statement,
     /// but may also compatible with other SQL.
-    Flush {
-        /// The specific flush option or object to flush.
-        object_type: FlushType,
-        /// Optional flush location (dialect-specific).
-        location: Option<FlushLocation>,
-        /// Optional channel name used for flush operations.
-        channel: Option<String>,
-        /// Whether a read lock was requested.
-        read_lock: bool,
-        /// Whether this is an export flush operation.
-        export: bool,
-        /// Optional list of tables involved in the flush.
-        tables: Vec<ObjectName>,
-    },
+    Flush(FlushStatement),
     /// ```sql
     /// DISCARD [ ALL | PLANS | SEQUENCES | TEMPORARY | TEMP ]
     /// ```
     ///
     /// Note: this is a PostgreSQL-specific statement,
     /// but may also compatible with other SQL.
-    Discard {
-        /// The kind of object(s) to discard (ALL, PLANS, etc.).
-        object_type: DiscardObject,
-    },
+    Discard(DiscardStatement),
     /// `SHOW FUNCTIONS`
     ///
     /// Note: this is a Presto-specific statement.
-    ShowFunctions {
-        /// Optional filter for which functions to display.
-        filter: Option<ShowStatementFilter>,
-    },
+    ShowFunctions(ShowFunctionsStatement),
     /// ```sql
     /// SHOW <variable>
     /// ```
     ///
     /// Note: this is a PostgreSQL-specific statement.
-    ShowVariable {
-        /// Variable name as one or more identifiers.
-        variable: Vec<Ident>,
-    },
+    ShowVariable(ShowVariableStatement),
     /// ```sql
     /// SHOW [GLOBAL | SESSION] STATUS [LIKE 'pattern' | WHERE expr]
     /// ```
     ///
     /// Note: this is a MySQL-specific statement.
-    ShowStatus {
-        /// Optional filter for which status entries to display.
-        filter: Option<ShowStatementFilter>,
-        /// `true` when `GLOBAL` scope was requested.
-        global: bool,
-        /// `true` when `SESSION` scope was requested.
-        session: bool,
-    },
+    ShowStatus(ShowStatusStatement),
     /// ```sql
     /// SHOW VARIABLES
     /// ```
     ///
     /// Note: this is a MySQL-specific statement.
-    ShowVariables {
-        /// Optional filter for which variables to display.
-        filter: Option<ShowStatementFilter>,
-        /// `true` when `GLOBAL` scope was requested.
-        global: bool,
-        /// `true` when `SESSION` scope was requested.
-        session: bool,
-    },
+    ShowVariables(ShowVariablesStatement),
     /// ```sql
     /// SHOW CREATE TABLE
     /// ```
     ///
     /// Note: this is a MySQL-specific statement.
-    ShowCreate {
-        /// The kind of object being shown (TABLE, VIEW, etc.).
-        obj_type: ShowCreateObject,
-        /// The name of the object to show create statement for.
-        obj_name: ObjectName,
-    },
+    ShowCreate(ShowCreateStatement),
     /// ```sql
     /// SHOW COLUMNS
     /// ```
-    ShowColumns {
-        /// `true` when extended column information was requested.
-        extended: bool,
-        /// `true` when full column details were requested.
-        full: bool,
-        /// Additional options for `SHOW COLUMNS`.
-        show_options: ShowStatementOptions,
-    },
+    ShowColumns(ShowColumnsStatement),
     /// ```sql
     /// SHOW CATALOGS
     /// ```
-    ShowCatalogs {
-        /// `true` when terse output format was requested.
-        terse: bool,
-        /// `true` when history information was requested.
-        history: bool,
-        /// Additional options for `SHOW CATALOGS`.
-        show_options: ShowStatementOptions,
-    },
+    ShowCatalogs(ShowCatalogsStatement),
     /// ```sql
     /// SHOW DATABASES
     /// ```
-    ShowDatabases {
-        /// `true` when terse output format was requested.
-        terse: bool,
-        /// `true` when history information was requested.
-        history: bool,
-        /// Additional options for `SHOW DATABASES`.
-        show_options: ShowStatementOptions,
-    },
+    ShowDatabases(ShowDatabasesStatement),
     /// ```sql
     /// SHOW [FULL] PROCESSLIST
     /// ```
     ///
     /// Note: this is a MySQL-specific statement.
-    ShowProcessList {
-        /// `true` when full process information was requested.
-        full: bool,
-    },
+    ShowProcessList(ShowProcessListStatement),
     /// ```sql
     /// SHOW SCHEMAS
     /// ```
-    ShowSchemas {
-        /// `true` when terse (compact) output was requested.
-        terse: bool,
-        /// `true` when history information was requested.
-        history: bool,
-        /// Additional options for `SHOW SCHEMAS`.
-        show_options: ShowStatementOptions,
-    },
+    ShowSchemas(ShowSchemasStatement),
     // ```sql
     // SHOW {CHARACTER SET | CHARSET}
     // ```
@@ -4277,40 +4007,17 @@
     /// ```sql
     /// SHOW TABLES
     /// ```
-    ShowTables {
-        /// `true` when terse output format was requested (compact listing).
-        terse: bool,
-        /// `true` when history rows are requested.
-        history: bool,
-        /// `true` when extended information should be shown.
-        extended: bool,
-        /// `true` when a full listing was requested.
-        full: bool,
-        /// `true` when external tables should be included.
-        external: bool,
-        /// Additional options for `SHOW` statements.
-        show_options: ShowStatementOptions,
-    },
+    ShowTables(ShowTablesStatement),
     /// ```sql
     /// SHOW VIEWS
     /// ```
-    ShowViews {
-        /// `true` when terse output format was requested.
-        terse: bool,
-        /// `true` when materialized views should be included.
-        materialized: bool,
-        /// Additional options for `SHOW` statements.
-        show_options: ShowStatementOptions,
-    },
+    ShowViews(ShowViewsStatement),
     /// ```sql
     /// SHOW COLLATION
     /// ```
     ///
     /// Note: this is a MySQL-specific statement.
-    ShowCollation {
-        /// Optional filter for which collations to display.
-        filter: Option<ShowStatementFilter>,
-    },
+    ShowCollation(ShowCollationStatement),
     /// ```sql
     /// `USE ...`
     /// ```
@@ -4324,57 +4031,13 @@
     /// `BEGIN  [ TRANSACTION | WORK ] | START TRANSACTION } ...`
     /// ```
     /// If `begin` is true
-    StartTransaction {
-        /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
-        modes: Vec<TransactionMode>,
-        /// `true` when this was parsed as `BEGIN` instead of `START`.
-        begin: bool,
-        /// Optional specific keyword used: `TRANSACTION` or `WORK`.
-        transaction: Option<BeginTransactionKind>,
-        /// Optional transaction modifier (e.g., `AND NO CHAIN`).
-        modifier: Option<TransactionModifier>,
-        /// List of statements belonging to the `BEGIN` block.
-        /// Example:
-        /// ```sql
-        /// BEGIN
-        ///     SELECT 1;
-        ///     SELECT 2;
-        /// END;
-        /// ```
-        statements: Vec<Statement>,
-        /// Exception handling with exception clauses.
-        /// Example:
-        /// ```sql
-        /// EXCEPTION
-        ///     WHEN EXCEPTION_1 THEN
-        ///         SELECT 2;
-        ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
-        ///         SELECT 3;
-        ///     WHEN OTHER THEN
-        ///         SELECT 4;
-        /// ```
-        /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
-        /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
-        exception: Option<Vec<ExceptionWhen>>,
-        /// TRUE if the statement has an `END` keyword.
-        has_end_keyword: bool,
-    },
+    StartTransaction(StartTransactionStatement),
     /// ```sql
     /// COMMENT ON ...
     /// ```
     ///
     /// Note: this is a PostgreSQL-specific statement.
-    Comment {
-        /// Type of object being commented (table, column, etc.).
-        object_type: CommentObject,
-        /// Name of the object the comment applies to.
-        object_name: ObjectName,
-        /// Optional comment text (None to remove comment).
-        comment: Option<String>,
-        /// An optional `IF EXISTS` clause. (Non-standard.)
-        /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
-        if_exists: bool,
-    },
+    Comment(CommentStatement),
     /// ```sql
     /// COMMIT [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ]
     /// ```
@@ -4384,117 +4047,21 @@
     /// END [ TRY | CATCH ]
     /// ```
     /// If `end` is true
-    Commit {
-        /// `true` when `AND [ NO ] CHAIN` was present.
-        chain: bool,
-        /// `true` when this `COMMIT` was parsed as an `END` block terminator.
-        end: bool,
-        /// Optional transaction modifier for commit semantics.
-        modifier: Option<TransactionModifier>,
-    },
+    Commit(CommitStatement),
     /// ```sql
     /// ROLLBACK [ TRANSACTION | WORK ] [ AND [ NO ] CHAIN ] [ TO [ SAVEPOINT ] savepoint_name ]
     /// ```
-    Rollback {
-        /// `true` when `AND [ NO ] CHAIN` was present.
-        chain: bool,
-        /// Optional savepoint name to roll back to.
-        savepoint: Option<Ident>,
-    },
+    Rollback(RollbackStatement),
     /// ```sql
     /// CREATE SCHEMA
     /// ```
-    CreateSchema {
-        /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
-        schema_name: SchemaName,
-        /// `true` when `OR REPLACE` was present.
-        or_replace: bool,
-        /// `true` when `IF NOT EXISTS` was present.
-        if_not_exists: bool,
-        /// Schema properties.
-        ///
-        /// ```sql
-        /// CREATE SCHEMA myschema WITH (key1='value1');
-        /// ```
-        ///
-        /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
-        with: Option<Vec<SqlOption>>,
-        /// Schema options.
-        ///
-        /// ```sql
-        /// CREATE SCHEMA myschema OPTIONS(key1='value1');
-        /// ```
-        ///
-        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
-        options: Option<Vec<SqlOption>>,
-        /// Default collation specification for the schema.
-        ///
-        /// ```sql
-        /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
-        /// ```
-        ///
-        /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
-        default_collate_spec: Option<Expr>,
-        /// Clones a schema
-        ///
-        /// ```sql
-        /// CREATE SCHEMA myschema CLONE otherschema
-        /// ```
-        ///
-        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
-        clone: Option<ObjectName>,
-    },
+    CreateSchema(CreateSchemaStatement),
     /// ```sql
     /// CREATE DATABASE
     /// ```
     /// See:
     /// <https://docs.snowflake.com/en/sql-reference/sql/create-database>
-    CreateDatabase {
-        /// Database name.
-        db_name: ObjectName,
-        /// `IF NOT EXISTS` flag.
-        if_not_exists: bool,
-        /// Optional location URI.
-        location: Option<String>,
-        /// Optional managed location.
-        managed_location: Option<String>,
-        /// `OR REPLACE` flag.
-        or_replace: bool,
-        /// `TRANSIENT` flag.
-        transient: bool,
-        /// Optional clone source.
-        clone: Option<ObjectName>,
-        /// Optional data retention time in days.
-        data_retention_time_in_days: Option<u64>,
-        /// Optional maximum data extension time in days.
-        max_data_extension_time_in_days: Option<u64>,
-        /// Optional external volume identifier.
-        external_volume: Option<String>,
-        /// Optional catalog name.
-        catalog: Option<String>,
-        /// Whether to replace invalid characters.
-        replace_invalid_characters: Option<bool>,
-        /// Default DDL collation string.
-        default_ddl_collation: Option<String>,
-        /// Storage serialization policy.
-        storage_serialization_policy: Option<StorageSerializationPolicy>,
-        /// Optional comment.
-        comment: Option<String>,
-        /// Optional default character set (MySQL).
-        default_charset: Option<String>,
-        /// Optional default collation (MySQL).
-        default_collation: Option<String>,
-        /// Optional catalog sync identifier.
-        catalog_sync: Option<String>,
-        /// Catalog sync namespace mode.
-        catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
-        /// Optional flatten delimiter for namespace sync.
-        catalog_sync_namespace_flatten_delimiter: Option<String>,
-        /// Optional tags for the database.
-        with_tags: Option<Vec<Tag>>,
-        /// Optional contact entries for the database.
-        with_contacts: Option<Vec<ContactEntry>>,
-    },
+    CreateDatabase(CreateDatabaseStatement),
     /// ```sql
     /// CREATE FUNCTION
     /// ```
@@ -4512,82 +4079,26 @@
     /// ```sql
     /// CREATE PROCEDURE
     /// ```
-    CreateProcedure {
-        /// `OR ALTER` flag.
-        or_alter: bool,
-        /// Procedure name.
-        name: ObjectName,
-        /// Optional procedure parameters.
-        params: Option<Vec<ProcedureParam>>,
-        /// Optional language identifier.
-        language: Option<Ident>,
-        /// Procedure body statements.
-        body: ConditionalStatements,
-    },
+    CreateProcedure(CreateProcedureStatement),
     /// ```sql
     /// CREATE MACRO
     /// ```
     ///
     /// Supported variants:
     /// 1. [DuckDB](https://duckdb.org/docs/sql/statements/create_macro)
-    CreateMacro {
-        /// `OR REPLACE` flag.
-        or_replace: bool,
-        /// Whether macro is temporary.
-        temporary: bool,
-        /// Macro name.
-        name: ObjectName,
-        /// Optional macro arguments.
-        args: Option<Vec<MacroArg>>,
-        /// Macro definition body.
-        definition: MacroDefinition,
-    },
+    CreateMacro(CreateMacroStatement),
     /// ```sql
     /// CREATE STAGE
     /// ```
     /// See <https://docs.snowflake.com/en/sql-reference/sql/create-stage>
-    CreateStage {
-        /// `OR REPLACE` flag for stage.
-        or_replace: bool,
-        /// Whether stage is temporary.
-        temporary: bool,
-        /// `IF NOT EXISTS` flag.
-        if_not_exists: bool,
-        /// Stage name.
-        name: ObjectName,
-        /// Stage parameters.
-        stage_params: StageParamsObject,
-        /// Directory table parameters.
-        directory_table_params: KeyValueOptions,
-        /// File format options.
-        file_format: KeyValueOptions,
-        /// Copy options for stage.
-        copy_options: KeyValueOptions,
-        /// Optional comment.
-        comment: Option<String>,
-    },
+    CreateStage(CreateStageStatement),
     /// ```sql
     /// CREATE [ OR REPLACE ] [ { TEMP | TEMPORARY | VOLATILE } ] FILE FORMAT [ IF NOT EXISTS ] <name>
     ///   [ TYPE = { CSV | JSON | AVRO | ORC | PARQUET | XML } [ formatTypeOptions ] ]
     ///   [ COMMENT = '<string_literal>' ]
     /// ```
     /// See <https://docs.snowflake.com/en/sql-reference/sql/create-file-format>
-    CreateFileFormat {
-        /// `OR REPLACE` flag.
-        or_replace: bool,
-        /// Whether file format is temporary.
-        temporary: bool,
-        /// Whether file format is volatile.
-        volatile: bool,
-        /// `IF NOT EXISTS` flag.
-        if_not_exists: bool,
-        /// File format name.
-        name: ObjectName,
-        /// Format type options (e.g. `TYPE`, `FIELD_DELIMITER`, `COMPRESSION`, ...).
-        options: KeyValueOptions,
-        /// Optional comment.
-        comment: Option<String>,
-    },
+    CreateFileFormat(CreateFileFormatStatement),
     /// ```sql
     /// CREATE [ OR REPLACE ] WAREHOUSE [ IF NOT EXISTS ] <name>
     ///   [ [ WITH ] <property> = <value> [ ... ] ]
@@ -4599,12 +4110,7 @@
     /// ```sql
     /// ASSERT <condition> [AS <message>]
     /// ```
-    Assert {
-        /// Assertion condition expression.
-        condition: Expr,
-        /// Optional message expression.
-        message: Option<Expr>,
-    },
+    Assert(AssertStatement),
     /// ```sql
     /// GRANT privileges ON objects TO grantees
     /// ```
@@ -4622,12 +4128,7 @@
     /// ```
     ///
     /// Note: this is a PostgreSQL-specific statement.
-    Deallocate {
-        /// Name to deallocate (or `ALL`).
-        name: Ident,
-        /// Whether `PREPARE` keyword was present.
-        prepare: bool,
-    },
+    Deallocate(DeallocateStatement),
     /// ```sql
     /// An `EXECUTE` statement
     /// ```
@@ -4636,110 +4137,38 @@
     /// MSSQL: <https://learn.microsoft.com/en-us/sql/relational-databases/stored-procedures/execute-a-stored-procedure>
     /// BigQuery: <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#execute_immediate>
     /// Snowflake: <https://docs.snowflake.com/en/sql-reference/sql/execute-immediate>
-    Execute {
-        /// Optional function/procedure name.
-        name: Option<ObjectName>,
-        /// Parameter expressions passed to execute.
-        parameters: Vec<Expr>,
-        /// Whether parentheses were present around `parameters`.
-        has_parentheses: bool,
-        /// Is this an `EXECUTE IMMEDIATE`.
-        immediate: bool,
-        /// Identifiers to capture results into.
-        into: Vec<Ident>,
-        /// `USING` expressions with optional aliases.
-        using: Vec<ExprWithAlias>,
-        /// Whether the last parameter is the return value of the procedure
-        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
-        output: bool,
-        /// Whether to invoke the procedure with the default parameter values
-        /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
-        default: bool,
-    },
+    Execute(ExecuteStatement),
     /// ```sql
     /// PREPARE name [ ( data_type [, ...] ) ] AS statement
     /// ```
     ///
     /// Note: this is a PostgreSQL-specific statement.
-    Prepare {
-        /// Name of the prepared statement.
-        name: Ident,
-        /// Optional data types for parameters.
-        data_types: Vec<DataType>,
-        /// Statement being prepared.
-        statement: Box<Statement>,
-    },
+    Prepare(PrepareStatement),
     /// ```sql
     /// KILL [CONNECTION | QUERY | MUTATION]
     /// ```
     ///
     /// See <https://clickhouse.com/docs/en/sql-reference/statements/kill/>
     /// See <https://dev.mysql.com/doc/refman/8.0/en/kill.html>
-    Kill {
-        /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
-        modifier: Option<KillType>,
-        // processlist_id
-        /// The id of the process to kill.
-        id: u64,
-    },
+    Kill(KillStatement),
     /// ```sql
     /// [EXPLAIN | DESC | DESCRIBE] TABLE
     /// ```
     /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/explain.html>
-    ExplainTable {
-        /// `EXPLAIN | DESC | DESCRIBE`
-        describe_alias: DescribeAlias,
-        /// Hive style `FORMATTED | EXTENDED`
-        hive_format: Option<HiveDescribeFormat>,
-        /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
-        ///
-        /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
-        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
-        has_table_keyword: bool,
-        /// Table name
-        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
-        table_name: ObjectName,
-    },
+    ExplainTable(ExplainTableStatement),
     /// ```sql
     /// [EXPLAIN | DESC | DESCRIBE]  <statement>
     /// ```
-    Explain {
-        /// `EXPLAIN | DESC | DESCRIBE`
-        describe_alias: DescribeAlias,
-        /// Carry out the command and show actual run times and other statistics.
-        analyze: bool,
-        /// Display additional information regarding the plan.
-        verbose: bool,
-        /// `EXPLAIN QUERY PLAN`
-        /// Display the query plan without running the query.
-        ///
-        /// [SQLite](https://sqlite.org/lang_explain.html)
-        query_plan: bool,
-        /// `EXPLAIN ESTIMATE`
-        /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
-        estimate: bool,
-        /// A SQL query that specifies what to explain
-        statement: Box<Statement>,
-        /// Optional output format of explain
-        format: Option<AnalyzeFormatKind>,
-        /// Postgres style utility options, `(analyze, verbose true)`
-        options: Option<Vec<UtilityOption>>,
-    },
+    Explain(ExplainStatement),
     /// ```sql
     /// SAVEPOINT
     /// ```
     /// Define a new savepoint within the current transaction
-    Savepoint {
-        /// Name of the savepoint being defined.
-        name: Ident,
-    },
+    Savepoint(SavepointStatement),
     /// ```sql
     /// RELEASE [ SAVEPOINT ] savepoint_name
     /// ```
-    ReleaseSavepoint {
-        /// Name of the savepoint to release.
-        name: Ident,
-    },
+    ReleaseSavepoint(ReleaseSavepointStatement),
     /// A `MERGE` statement.
     ///
     /// ```sql
@@ -4756,69 +4185,26 @@
     /// See [Spark SQL docs] for more details.
     ///
     /// [Spark SQL docs]: https://docs.databricks.com/spark/latest/spark-sql/language-manual/sql-ref-syntax-aux-cache-cache-table.html
-    Cache {
-        /// Table flag
-        table_flag: Option<ObjectName>,
-        /// Table name
-        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
-        table_name: ObjectName,
-        /// `true` if `AS` keyword was present before the query.
-        has_as: bool,
-        /// Table confs
-        options: Vec<SqlOption>,
-        /// Cache table as a Query
-        query: Option<Box<Query>>,
-    },
+    Cache(CacheStatement),
     /// ```sql
     /// UNCACHE TABLE [ IF EXISTS ]  <table_name>
     /// ```
-    UNCache {
-        /// Table name
-        #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
-        table_name: ObjectName,
-        /// `true` when `IF EXISTS` was present.
-        if_exists: bool,
-    },
+    UNCache(UNCacheStatement),
     /// ```sql
     /// CREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name>
     /// ```
     /// Define a new sequence:
-    CreateSequence {
-        /// Whether the sequence is temporary.
-        temporary: bool,
-        /// `IF NOT EXISTS` flag.
-        if_not_exists: bool,
-        /// Sequence name.
-        name: ObjectName,
-        /// Optional data type for the sequence.
-        data_type: Option<DataType>,
-        /// Sequence options (INCREMENT, MINVALUE, etc.).
-        sequence_options: Vec<SequenceOptions>,
-        /// Optional `OWNED BY` target.
-        owned_by: Option<ObjectName>,
-    },
+    CreateSequence(CreateSequenceStatement),
     /// A `CREATE DOMAIN` statement.
     CreateDomain(CreateDomain),
     /// ```sql
     /// CREATE TYPE <name>
     /// ```
-    CreateType {
-        /// Type name to create.
-        name: ObjectName,
-        /// Optional type representation details.
-        representation: Option<UserDefinedTypeRepresentation>,
-    },
+    CreateType(CreateTypeStatement),
     /// ```sql
     /// PRAGMA <schema-name>.<pragma-name> = <pragma-value>
     /// ```
-    Pragma {
-        /// Pragma name (possibly qualified).
-        name: ObjectName,
-        /// Optional pragma value.
-        value: Option<ValueWithSpan>,
-        /// Whether the pragma used `=`.
-        is_eq: bool,
-    },
+    Pragma(PragmaStatement),
     /// ```sql
     /// LOCK [ TABLE ] [ ONLY ] name [ * ] [, ...] [ IN lockmode MODE ] [ NOWAIT ]
     /// ```
@@ -4829,15 +4215,12 @@
     /// LOCK TABLES <table_name> [READ [LOCAL] | [LOW_PRIORITY] WRITE]
     /// ```
     /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
-    LockTables {
-        /// List of tables to lock with modes.
-        tables: Vec<LockTable>,
-    },
+    LockTables(LockTablesStatement),
     /// ```sql
     /// UNLOCK TABLES
     /// ```
     /// Note: this is a MySQL-specific statement. See <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
-    UnlockTables,
+    UnlockTables(UnlockTablesStatement),
     /// Unloads the result of a query to file
     ///
     /// [Athena](https://docs.aws.amazon.com/athena/latest/ug/unload.html):
@@ -4849,20 +4232,7 @@
     /// ```sql
     /// UNLOAD('statement') TO <destination> [ OPTIONS ]
     /// ```
-    Unload {
-        /// Optional query AST to unload.
-        query: Option<Box<Query>>,
-        /// Optional original query text.
-        query_text: Option<String>,
-        /// Destination identifier.
-        to: Ident,
-        /// Optional IAM role/auth information.
-        auth: Option<IamRoleKind>,
-        /// Additional `WITH` options.
-        with: Vec<SqlOption>,
-        /// Legacy copy-style options.
-        options: Vec<CopyLegacyOption>,
-    },
+    Unload(UnloadStatement),
     /// ClickHouse:
     /// ```sql
     /// OPTIMIZE TABLE [db.]name [ON CLUSTER cluster] [PARTITION partition | PARTITION ID 'partition_id'] [FINAL] [DEDUPLICATE [BY expression]]
@@ -4874,62 +4244,28 @@
     /// OPTIMIZE table_name [WHERE predicate] [ZORDER BY (col_name1 [, ...])]
     /// ```
     /// See Databricks <https://docs.databricks.com/en/sql/language-manual/delta-optimize.html>
-    OptimizeTable {
-        /// Table name to optimize.
-        name: ObjectName,
-        /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
-        has_table_keyword: bool,
-        /// Optional cluster identifier.
-        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
-        on_cluster: Option<Ident>,
-        /// Optional partition spec.
-        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
-        partition: Option<Partition>,
-        /// Whether `FINAL` was specified.
-        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
-        include_final: bool,
-        /// Optional deduplication settings.
-        /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
-        deduplicate: Option<Deduplicate>,
-        /// Optional WHERE predicate.
-        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
-        predicate: Option<Expr>,
-        /// Optional ZORDER BY columns.
-        /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
-        zorder: Option<Vec<Expr>>,
-    },
+    OptimizeTable(OptimizeTableStatement),
     /// ```sql
     /// LISTEN
     /// ```
     /// listen for a notification channel
     ///
     /// See Postgres <https://www.postgresql.org/docs/current/sql-listen.html>
-    LISTEN {
-        /// Notification channel identifier.
-        channel: Ident,
-    },
+    LISTEN(LISTENStatement),
     /// ```sql
     /// UNLISTEN
     /// ```
     /// stop listening for a notification
     ///
     /// See Postgres <https://www.postgresql.org/docs/current/sql-unlisten.html>
-    UNLISTEN {
-        /// Notification channel identifier.
-        channel: Ident,
-    },
+    UNLISTEN(UNLISTENStatement),
     /// ```sql
     /// NOTIFY channel [ , payload ]
     /// ```
     /// send a notification event together with an optional "payload" string to channel
     ///
     /// See Postgres <https://www.postgresql.org/docs/current/sql-notify.html>
-    NOTIFY {
-        /// Notification channel identifier.
-        channel: Ident,
-        /// Optional payload string.
-        payload: Option<String>,
-    },
+    NOTIFY(NOTIFYStatement),
     /// ```sql
     /// LOAD DATA [LOCAL] INPATH 'filepath' [OVERWRITE] INTO TABLE tablename
     /// [PARTITION (partcol1=val1, partcol2=val2 ...)]
@@ -4938,20 +4274,7 @@
     /// Loading files into tables
     ///
     /// See Hive <https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=27362036#LanguageManualDML-Loadingfilesintotables>
-    LoadData {
-        /// Whether `LOCAL` is present.
-        local: bool,
-        /// Input path for files to load.
-        inpath: String,
-        /// Whether `OVERWRITE` was specified.
-        overwrite: bool,
-        /// Target table name to load into.
-        table_name: ObjectName,
-        /// Optional partition specification.
-        partitioned: Option<Vec<Expr>>,
-        /// Optional table format information.
-        table_format: Option<HiveLoadDataFormat>,
-    },
+    LoadData(LoadDataStatement),
     /// ```sql
     /// Rename TABLE tbl_name TO new_tbl_name[, tbl_name2 TO new_tbl_name2] ...
     /// ```
@@ -4968,14 +4291,7 @@
     /// ```
     /// Options include `PARALLEL`, `AUTO_COMPRESS`, `SOURCE_COMPRESSION`, `OVERWRITE`.
     /// See: <https://docs.snowflake.com/en/sql-reference/sql/put>
-    Put {
-        /// Local source URI as written in the statement, e.g. `file:///tmp/data.csv`.
-        source: String,
-        /// Target internal stage (e.g. `@mystage`, `@~`, `@%table`).
-        stage: ObjectName,
-        /// Trailing options (`PARALLEL=4`, `AUTO_COMPRESS=TRUE`, ...).
-        options: KeyValueOptions,
-    },
+    Put(PutStatement),
     /// Snowflake `REMOVE`
     /// See: <https://docs.snowflake.com/en/sql-reference/sql/remove>
     Remove(FileStagingCommand),
@@ -4985,18 +4301,7 @@
     /// [ , argument [ , ...n ] ] )
     /// [ WITH option [ , ...n ] ]
     /// See <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/raiserror-transact-sql?view=sql-server-ver16>
-    RaisError {
-        /// Error message expression or identifier.
-        message: Box<Expr>,
-        /// Severity expression.
-        severity: Box<Expr>,
-        /// State expression.
-        state: Box<Expr>,
-        /// Substitution arguments for the message.
-        arguments: Vec<Expr>,
-        /// Additional `WITH` options for RAISERROR.
-        options: Vec<RaisErrorOption>,
-    },
+    RaisError(RaisErrorStatement),
     /// A MSSQL `THROW` statement.
     Throw(ThrowStatement),
     /// ```sql
@@ -5151,14 +4456,14 @@
     #[allow(clippy::cognitive_complexity)]
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match self {
-            Statement::Flush {
+            Statement::Flush(FlushStatement {
                 object_type,
                 location,
                 channel,
                 read_lock,
                 export,
                 tables,
-            } => {
+            }) => {
                 write!(f, "FLUSH")?;
                 if let Some(location) = location {
                     f.write_str(" ")?;
@@ -5182,7 +4487,7 @@
                     read = if *read_lock { " WITH READ LOCK" } else { "" }
                 )
             }
-            Statement::Kill { modifier, id } => {
+            Statement::Kill(KillStatement { modifier, id }) => {
                 write!(f, "KILL ")?;
 
                 if let Some(m) = modifier {
@@ -5191,12 +4496,12 @@
 
                 write!(f, "{id}")
             }
-            Statement::ExplainTable {
+            Statement::ExplainTable(ExplainTableStatement {
                 describe_alias,
                 hive_format,
                 has_table_keyword,
                 table_name,
-            } => {
+            }) => {
                 write!(f, "{describe_alias} ")?;
 
                 if let Some(format) = hive_format {
@@ -5208,7 +4513,7 @@
 
                 write!(f, "{table_name}")
             }
-            Statement::Explain {
+            Statement::Explain(ExplainStatement {
                 describe_alias,
                 verbose,
                 analyze,
@@ -5217,7 +4522,7 @@
                 statement,
                 format,
                 options,
-            } => {
+            }) => {
                 write!(f, "{describe_alias} ")?;
 
                 if *query_plan {
@@ -5245,16 +4550,16 @@
                 write!(f, "{statement}")
             }
             Statement::Query(s) => s.fmt(f),
-            Statement::Declare { stmts } => {
+            Statement::Declare(DeclareStatement { stmts }) => {
                 write!(f, "DECLARE ")?;
                 write!(f, "{}", display_separated(stmts, "; "))
             }
-            Statement::Fetch {
+            Statement::Fetch(FetchStatement {
                 name,
                 direction,
                 position,
                 into,
-            } => {
+            }) => {
                 write!(f, "FETCH {direction} {position} {name}")?;
 
                 if let Some(into) = into {
@@ -5263,13 +4568,13 @@
 
                 Ok(())
             }
-            Statement::Directory {
+            Statement::Directory(DirectoryStatement {
                 overwrite,
                 local,
                 path,
                 file_format,
                 source,
-            } => {
+            }) => {
                 write!(
                     f,
                     "INSERT{overwrite}{local} DIRECTORY '{path}'",
@@ -5296,21 +4601,21 @@
             Statement::Raise(stmt) => {
                 write!(f, "{stmt}")
             }
-            Statement::AttachDatabase {
+            Statement::AttachDatabase(AttachDatabaseStatement {
                 schema_name,
                 database_file_name,
                 database,
-            } => {
+            }) => {
                 let keyword = if *database { "DATABASE " } else { "" };
                 write!(f, "ATTACH {keyword}{database_file_name} AS {schema_name}")
             }
-            Statement::AttachDuckDBDatabase {
+            Statement::AttachDuckDBDatabase(AttachDuckDBDatabaseStatement {
                 if_not_exists,
                 database,
                 database_path,
                 database_alias,
                 attach_options,
-            } => {
+            }) => {
                 write!(
                     f,
                     "ATTACH{database}{if_not_exists} {database_path}",
@@ -5325,11 +4630,11 @@
                 }
                 Ok(())
             }
-            Statement::DetachDuckDBDatabase {
+            Statement::DetachDuckDBDatabase(DetachDuckDBDatabaseStatement {
                 if_exists,
                 database,
                 database_alias,
-            } => {
+            }) => {
                 write!(
                     f,
                     "DETACH{database}{if_exists} {database_alias}",
@@ -5340,24 +4645,24 @@
             }
             Statement::Analyze(analyze) => analyze.fmt(f),
             Statement::Insert(insert) => insert.fmt(f),
-            Statement::Install {
+            Statement::Install(InstallStatement {
                 extension_name: name,
-            } => write!(f, "INSTALL {name}"),
+            }) => write!(f, "INSTALL {name}"),
 
-            Statement::Load {
+            Statement::Load(LoadStatement {
                 extension_name: name,
-            } => write!(f, "LOAD {name}"),
+            }) => write!(f, "LOAD {name}"),
 
             Statement::Call(function) => write!(f, "CALL {function}"),
 
-            Statement::Copy {
+            Statement::Copy(CopyStatement {
                 source,
                 to,
                 target,
                 options,
                 legacy_options,
                 values,
-            } => {
+            }) => {
                 write!(f, "COPY")?;
                 match source {
                     CopySource::Query(query) => write!(f, " ({query})")?,
@@ -5397,12 +4702,12 @@
             Statement::Update(update) => update.fmt(f),
             Statement::Delete(delete) => delete.fmt(f),
             Statement::Open(open) => open.fmt(f),
-            Statement::Close { cursor } => {
+            Statement::Close(CloseStatement { cursor }) => {
                 write!(f, "CLOSE {cursor}")?;
 
                 Ok(())
             }
-            Statement::CreateDatabase {
+            Statement::CreateDatabase(CreateDatabaseStatement {
                 db_name,
                 if_not_exists,
                 location,
@@ -5425,7 +4730,7 @@
                 catalog_sync_namespace_flatten_delimiter,
                 with_tags,
                 with_contacts,
-            } => {
+            }) => {
                 write!(
                     f,
                     "CREATE {or_replace}{transient}DATABASE {if_not_exists}{name}",
@@ -5512,13 +4817,13 @@
             Statement::CreateDomain(create_domain) => create_domain.fmt(f),
             Statement::CreateTrigger(create_trigger) => create_trigger.fmt(f),
             Statement::DropTrigger(drop_trigger) => drop_trigger.fmt(f),
-            Statement::CreateProcedure {
+            Statement::CreateProcedure(CreateProcedureStatement {
                 name,
                 or_alter,
                 params,
                 language,
                 body,
-            } => {
+            }) => {
                 write!(
                     f,
                     "CREATE {or_alter}PROCEDURE {name}",
@@ -5538,13 +4843,13 @@
 
                 write!(f, " AS {body}")
             }
-            Statement::CreateMacro {
+            Statement::CreateMacro(CreateMacroStatement {
                 or_replace,
                 temporary,
                 name,
                 args,
                 definition,
-            } => {
+            }) => {
                 write!(
                     f,
                     "CREATE {or_replace}{temp}MACRO {name}",
@@ -5562,14 +4867,14 @@
             }
             Statement::CreateView(create_view) => create_view.fmt(f),
             Statement::CreateTable(create_table) => create_table.fmt(f),
-            Statement::LoadData {
+            Statement::LoadData(LoadDataStatement {
                 local,
                 inpath,
                 overwrite,
                 table_name,
                 partitioned,
                 table_format,
-            } => {
+            }) => {
                 write!(
                     f,
                     "LOAD DATA {local}INPATH '{inpath}' {overwrite}INTO TABLE {table_name}",
@@ -5592,12 +4897,12 @@
                 }
                 Ok(())
             }
-            Statement::CreateVirtualTable {
+            Statement::CreateVirtualTable(CreateVirtualTableStatement {
                 name,
                 if_not_exists,
                 module_name,
                 module_args,
-            } => {
+            }) => {
                 write!(
                     f,
                     "CREATE VIRTUAL TABLE {if_not_exists}{name} USING {module_name}",
@@ -5622,7 +4927,7 @@
                 write!(f, "{drop_operator_class}")
             }
             Statement::CreateRole(create_role) => write!(f, "{create_role}"),
-            Statement::CreateSecret {
+            Statement::CreateSecret(CreateSecretStatement {
                 or_replace,
                 temporary,
                 if_not_exists,
@@ -5630,7 +4935,7 @@
                 storage_specifier,
                 secret_type,
                 options,
-            } => {
+            }) => {
                 write!(
                     f,
                     "CREATE {or_replace}",
@@ -5669,15 +4974,15 @@
             Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
             Statement::CreateTextSearch(create_text_search) => create_text_search.fmt(f),
             Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
-            Statement::AlterIndex { name, operation } => {
+            Statement::AlterIndex(AlterIndexStatement { name, operation }) => {
                 write!(f, "ALTER INDEX {name} {operation}")
             }
-            Statement::AlterView {
+            Statement::AlterView(AlterViewStatement {
                 name,
                 columns,
                 query,
                 with_options,
-            } => {
+            }) => {
                 write!(f, "ALTER VIEW {name}")?;
                 if !with_options.is_empty() {
                     write!(f, " WITH ({})", display_comma_separated(with_options))?;
@@ -5700,16 +5005,16 @@
                 write!(f, "{alter_operator_class}")
             }
             Statement::AlterTextSearch(alter_text_search) => write!(f, "{alter_text_search}"),
-            Statement::AlterRole { name, operation } => {
+            Statement::AlterRole(AlterRoleStatement { name, operation }) => {
                 write!(f, "ALTER ROLE {name} {operation}")
             }
             Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
-            Statement::AlterConnector {
+            Statement::AlterConnector(AlterConnectorStatement {
                 name,
                 properties,
                 url,
                 owner,
-            } => {
+            }) => {
                 write!(f, "ALTER CONNECTOR {name}")?;
                 if let Some(properties) = properties {
                     write!(
@@ -5726,10 +5031,10 @@
                 }
                 Ok(())
             }
-            Statement::AlterSession {
+            Statement::AlterSession(AlterSessionStatement {
                 set,
                 session_params,
-            } => {
+            }) => {
                 write!(
                     f,
                     "ALTER SESSION {set}",
@@ -5749,7 +5054,7 @@
                 }
                 Ok(())
             }
-            Statement::Drop {
+            Statement::Drop(DropStatement {
                 object_type,
                 if_exists,
                 names,
@@ -5758,7 +5063,7 @@
                 purge,
                 temporary,
                 table,
-            } => {
+            }) => {
                 write!(
                     f,
                     "DROP {}{}{} {}{}{}{}",
@@ -5791,11 +5096,11 @@
                 }
                 Ok(())
             }
-            Statement::DropProcedure {
+            Statement::DropProcedure(DropProcedureStatement {
                 if_exists,
                 proc_desc,
                 drop_behavior,
-            } => {
+            }) => {
                 write!(
                     f,
                     "DROP PROCEDURE{} {}",
@@ -5807,12 +5112,12 @@
                 }
                 Ok(())
             }
-            Statement::DropSecret {
+            Statement::DropSecret(DropSecretStatement {
                 if_exists,
                 temporary,
                 name,
                 storage_specifier,
-            } => {
+            }) => {
                 write!(f, "DROP ")?;
                 if let Some(t) = temporary {
                     write!(f, "{}", if *t { "TEMPORARY " } else { "PERSISTENT " })?;
@@ -5828,7 +5133,7 @@
                 Ok(())
             }
             Statement::DropPolicy(policy) => write!(f, "{policy}"),
-            Statement::DropConnector { if_exists, name } => {
+            Statement::DropConnector(DropConnectorStatement { if_exists, name }) => {
                 write!(
                     f,
                     "DROP CONNECTOR {if_exists}{name}",
@@ -5836,23 +5141,23 @@
                 )?;
                 Ok(())
             }
-            Statement::Discard { object_type } => {
+            Statement::Discard(DiscardStatement { object_type }) => {
                 write!(f, "DISCARD {object_type}")?;
                 Ok(())
             }
             Self::Set(set) => write!(f, "{set}"),
-            Statement::ShowVariable { variable } => {
+            Statement::ShowVariable(ShowVariableStatement { variable }) => {
                 write!(f, "SHOW")?;
                 if !variable.is_empty() {
                     write!(f, " {}", display_separated(variable, " "))?;
                 }
                 Ok(())
             }
-            Statement::ShowStatus {
+            Statement::ShowStatus(ShowStatusStatement {
                 filter,
                 global,
                 session,
-            } => {
+            }) => {
                 write!(f, "SHOW")?;
                 if *global {
                     write!(f, " GLOBAL")?;
@@ -5866,11 +5171,11 @@
                 }
                 Ok(())
             }
-            Statement::ShowVariables {
+            Statement::ShowVariables(ShowVariablesStatement {
                 filter,
                 global,
                 session,
-            } => {
+            }) => {
                 write!(f, "SHOW")?;
                 if *global {
                     write!(f, " GLOBAL")?;
@@ -5884,15 +5189,15 @@
                 }
                 Ok(())
             }
-            Statement::ShowCreate { obj_type, obj_name } => {
+            Statement::ShowCreate(ShowCreateStatement { obj_type, obj_name }) => {
                 write!(f, "SHOW CREATE {obj_type} {obj_name}",)?;
                 Ok(())
             }
-            Statement::ShowColumns {
+            Statement::ShowColumns(ShowColumnsStatement {
                 extended,
                 full,
                 show_options,
-            } => {
+            }) => {
                 write!(
                     f,
                     "SHOW {extended}{full}COLUMNS{show_options}",
@@ -5901,11 +5206,11 @@
                 )?;
                 Ok(())
             }
-            Statement::ShowDatabases {
+            Statement::ShowDatabases(ShowDatabasesStatement {
                 terse,
                 history,
                 show_options,
-            } => {
+            }) => {
                 write!(
                     f,
                     "SHOW {terse}DATABASES{history}{show_options}",
@@ -5914,11 +5219,11 @@
                 )?;
                 Ok(())
             }
-            Statement::ShowCatalogs {
+            Statement::ShowCatalogs(ShowCatalogsStatement {
                 terse,
                 history,
                 show_options,
-            } => {
+            }) => {
                 write!(
                     f,
                     "SHOW {terse}CATALOGS{history}{show_options}",
@@ -5927,7 +5232,7 @@
                 )?;
                 Ok(())
             }
-            Statement::ShowProcessList { full } => {
+            Statement::ShowProcessList(ShowProcessListStatement { full }) => {
                 write!(
                     f,
                     "SHOW {full}PROCESSLIST",
@@ -5935,11 +5240,11 @@
                 )?;
                 Ok(())
             }
-            Statement::ShowSchemas {
+            Statement::ShowSchemas(ShowSchemasStatement {
                 terse,
                 history,
                 show_options,
-            } => {
+            }) => {
                 write!(
                     f,
                     "SHOW {terse}SCHEMAS{history}{show_options}",
@@ -5959,14 +5264,14 @@
                 )?;
                 Ok(())
             }
-            Statement::ShowTables {
+            Statement::ShowTables(ShowTablesStatement {
                 terse,
                 history,
                 extended,
                 full,
                 external,
                 show_options,
-            } => {
+            }) => {
                 write!(
                     f,
                     "SHOW {terse}{extended}{full}{external}TABLES{history}{show_options}",
@@ -5978,11 +5283,11 @@
                 )?;
                 Ok(())
             }
-            Statement::ShowViews {
+            Statement::ShowViews(ShowViewsStatement {
                 terse,
                 materialized,
                 show_options,
-            } => {
+            }) => {
                 write!(
                     f,
                     "SHOW {terse}{materialized}VIEWS{show_options}",
@@ -5991,7 +5296,7 @@
                 )?;
                 Ok(())
             }
-            Statement::ShowFunctions { filter } => {
+            Statement::ShowFunctions(ShowFunctionsStatement { filter }) => {
                 write!(f, "SHOW FUNCTIONS")?;
                 if let Some(filter) = filter {
                     write!(f, " {filter}")?;
@@ -5999,7 +5304,7 @@
                 Ok(())
             }
             Statement::Use(use_expr) => use_expr.fmt(f),
-            Statement::ShowCollation { filter } => {
+            Statement::ShowCollation(ShowCollationStatement { filter }) => {
                 write!(f, "SHOW COLLATION")?;
                 if let Some(filter) = filter {
                     write!(f, " {filter}")?;
@@ -6007,7 +5312,7 @@
                 Ok(())
             }
             Statement::ShowCharset(show_stm) => show_stm.fmt(f),
-            Statement::StartTransaction {
+            Statement::StartTransaction(StartTransactionStatement {
                 modes,
                 begin: syntax_begin,
                 transaction,
@@ -6015,7 +5320,7 @@
                 statements,
                 exception,
                 has_end_keyword,
-            } => {
+            }) => {
                 if *syntax_begin {
                     if let Some(modifier) = *modifier {
                         write!(f, "BEGIN {modifier}")?;
@@ -6046,11 +5351,11 @@
                 }
                 Ok(())
             }
-            Statement::Commit {
+            Statement::Commit(CommitStatement {
                 chain,
                 end: end_syntax,
                 modifier,
-            } => {
+            }) => {
                 if *end_syntax {
                     write!(f, "END")?;
                     if let Some(modifier) = *modifier {
@@ -6064,7 +5369,7 @@
                 }
                 Ok(())
             }
-            Statement::Rollback { chain, savepoint } => {
+            Statement::Rollback(RollbackStatement { chain, savepoint }) => {
                 write!(f, "ROLLBACK")?;
 
                 if *chain {
@@ -6077,7 +5382,7 @@
 
                 Ok(())
             }
-            Statement::CreateSchema {
+            Statement::CreateSchema(CreateSchemaStatement {
                 schema_name,
                 or_replace,
                 if_not_exists,
@@ -6085,7 +5390,7 @@
                 options,
                 default_collate_spec,
                 clone,
-            } => {
+            }) => {
                 write!(
                     f,
                     "CREATE {or_replace}SCHEMA {if_not_exists}{name}",
@@ -6111,7 +5416,7 @@
                 }
                 Ok(())
             }
-            Statement::Assert { condition, message } => {
+            Statement::Assert(AssertStatement { condition, message }) => {
                 write!(f, "ASSERT {condition}")?;
                 if let Some(m) = message {
                     write!(f, " AS {m}")?;
@@ -6121,13 +5426,13 @@
             Statement::Grant(grant) => write!(f, "{grant}"),
             Statement::Deny(s) => write!(f, "{s}"),
             Statement::Revoke(revoke) => write!(f, "{revoke}"),
-            Statement::Deallocate { name, prepare } => write!(
+            Statement::Deallocate(DeallocateStatement { name, prepare }) => write!(
                 f,
                 "DEALLOCATE {prepare}{name}",
                 prepare = if *prepare { "PREPARE " } else { "" },
                 name = name,
             ),
-            Statement::Execute {
+            Statement::Execute(ExecuteStatement {
                 name,
                 parameters,
                 has_parentheses,
@@ -6136,7 +5441,7 @@
                 using,
                 output,
                 default,
-            } => {
+            }) => {
                 let (open, close) = if *has_parentheses {
                     // Space before `(` only when there is no name directly preceding it.
                     (if name.is_some() { "(" } else { " (" }, ")")
@@ -6165,23 +5470,23 @@
                 }
                 Ok(())
             }
-            Statement::Prepare {
+            Statement::Prepare(PrepareStatement {
                 name,
                 data_types,
                 statement,
-            } => {
+            }) => {
                 write!(f, "PREPARE {name} ")?;
                 if !data_types.is_empty() {
                     write!(f, "({}) ", display_comma_separated(data_types))?;
                 }
                 write!(f, "AS {statement}")
             }
-            Statement::Comment {
+            Statement::Comment(CommentStatement {
                 object_type,
                 object_name,
                 comment,
                 if_exists,
-            } => {
+            }) => {
                 write!(f, "COMMENT ")?;
                 if *if_exists {
                     write!(f, "IF EXISTS ")?
@@ -6193,21 +5498,21 @@
                     write!(f, "NULL")
                 }
             }
-            Statement::Savepoint { name } => {
+            Statement::Savepoint(SavepointStatement { name }) => {
                 write!(f, "SAVEPOINT ")?;
                 write!(f, "{name}")
             }
-            Statement::ReleaseSavepoint { name } => {
+            Statement::ReleaseSavepoint(ReleaseSavepointStatement { name }) => {
                 write!(f, "RELEASE SAVEPOINT {name}")
             }
             Statement::Merge(merge) => merge.fmt(f),
-            Statement::Cache {
+            Statement::Cache(CacheStatement {
                 table_name,
                 table_flag,
                 has_as,
                 options,
                 query,
-            } => {
+            }) => {
                 if let Some(table_flag) = table_flag {
                     write!(f, "CACHE {table_flag} TABLE {table_name}")?;
                 } else {
@@ -6225,24 +5530,24 @@
                     (false, None) => Ok(()),
                 }
             }
-            Statement::UNCache {
+            Statement::UNCache(UNCacheStatement {
                 table_name,
                 if_exists,
-            } => {
+            }) => {
                 if *if_exists {
                     write!(f, "UNCACHE TABLE IF EXISTS {table_name}")
                 } else {
                     write!(f, "UNCACHE TABLE {table_name}")
                 }
             }
-            Statement::CreateSequence {
+            Statement::CreateSequence(CreateSequenceStatement {
                 temporary,
                 if_not_exists,
                 name,
                 data_type,
                 sequence_options,
                 owned_by,
-            } => {
+            }) => {
                 let as_type: String = if let Some(dt) = data_type.as_ref() {
                     //Cannot use format!(" AS {}", dt), due to format! is not available in --target thumbv6m-none-eabi
                     // " AS ".to_owned() + &dt.to_string()
@@ -6266,7 +5571,7 @@
                 }
                 write!(f, "")
             }
-            Statement::CreateStage {
+            Statement::CreateStage(CreateStageStatement {
                 or_replace,
                 temporary,
                 if_not_exists,
@@ -6277,7 +5582,7 @@
                 copy_options,
                 comment,
                 ..
-            } => {
+            }) => {
                 write!(
                     f,
                     "CREATE {or_replace}{temp}STAGE {if_not_exists}{name}{stage_params}",
@@ -6299,7 +5604,7 @@
                 }
                 Ok(())
             }
-            Statement::CreateFileFormat {
+            Statement::CreateFileFormat(CreateFileFormatStatement {
                 or_replace,
                 temporary,
                 volatile,
@@ -6307,7 +5612,7 @@
                 name,
                 options,
                 comment,
-            } => {
+            }) => {
                 write!(
                     f,
                     "CREATE {or_replace}{temp}{volatile}FILE FORMAT {if_not_exists}{name}",
@@ -6325,7 +5630,7 @@
                 Ok(())
             }
             Statement::CreateWarehouse(s) => write!(f, "{s}"),
-            Statement::CopyIntoSnowflake {
+            Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
                 kind,
                 into,
                 into_columns,
@@ -6340,7 +5645,7 @@
                 copy_options,
                 validation_mode,
                 partition,
-            } => {
+            }) => {
                 write!(f, "COPY INTO {into}")?;
                 if let Some(into_columns) = into_columns {
                     write!(f, " ({})", display_comma_separated(into_columns))?;
@@ -6396,17 +5701,17 @@
                 }
                 Ok(())
             }
-            Statement::CreateType {
+            Statement::CreateType(CreateTypeStatement {
                 name,
                 representation,
-            } => {
+            }) => {
                 write!(f, "CREATE TYPE {name}")?;
                 if let Some(repr) = representation {
                     write!(f, " {repr}")?;
                 }
                 Ok(())
             }
-            Statement::Pragma { name, value, is_eq } => {
+            Statement::Pragma(PragmaStatement { name, value, is_eq }) => {
                 write!(f, "PRAGMA {name}")?;
                 if let Some(value) = value {
                     if *is_eq {
@@ -6418,20 +5723,20 @@
                 Ok(())
             }
             Statement::Lock(lock) => lock.fmt(f),
-            Statement::LockTables { tables } => {
+            Statement::LockTables(LockTablesStatement { tables }) => {
                 write!(f, "LOCK TABLES {}", display_comma_separated(tables))
             }
-            Statement::UnlockTables => {
+            Statement::UnlockTables(UnlockTablesStatement) => {
                 write!(f, "UNLOCK TABLES")
             }
-            Statement::Unload {
+            Statement::Unload(UnloadStatement {
                 query,
                 query_text,
                 to,
                 auth,
                 with,
                 options,
-            } => {
+            }) => {
                 write!(f, "UNLOAD(")?;
                 if let Some(query) = query {
                     write!(f, "{query}")?;
@@ -6451,7 +5756,7 @@
                 }
                 Ok(())
             }
-            Statement::OptimizeTable {
+            Statement::OptimizeTable(OptimizeTableStatement {
                 name,
                 has_table_keyword,
                 on_cluster,
@@ -6460,7 +5765,7 @@
                 deduplicate,
                 predicate,
                 zorder,
-            } => {
+            }) => {
                 write!(f, "OPTIMIZE")?;
                 if *has_table_keyword {
                     write!(f, " TABLE")?;
@@ -6486,15 +5791,15 @@
                 }
                 Ok(())
             }
-            Statement::LISTEN { channel } => {
+            Statement::LISTEN(LISTENStatement { channel }) => {
                 write!(f, "LISTEN {channel}")?;
                 Ok(())
             }
-            Statement::UNLISTEN { channel } => {
+            Statement::UNLISTEN(UNLISTENStatement { channel }) => {
                 write!(f, "UNLISTEN {channel}")?;
                 Ok(())
             }
-            Statement::NOTIFY { channel, payload } => {
+            Statement::NOTIFY(NOTIFYStatement { channel, payload }) => {
                 write!(f, "NOTIFY {channel}")?;
                 if let Some(payload) = payload {
                     write!(f, ", '{payload}'")?;
@@ -6504,13 +5809,13 @@
             Statement::RenameTable(rename_tables) => {
                 write!(f, "RENAME TABLE {}", display_comma_separated(rename_tables))
             }
-            Statement::RaisError {
+            Statement::RaisError(RaisErrorStatement {
                 message,
                 severity,
                 state,
                 arguments,
                 options,
-            } => {
+            }) => {
                 write!(f, "RAISERROR({message}, {severity}, {state}")?;
                 if !arguments.is_empty() {
                     write!(f, ", {}", display_comma_separated(arguments))?;
@@ -6526,11 +5831,11 @@
             Statement::WaitFor(s) => write!(f, "{s}"),
             Statement::Return(r) => write!(f, "{r}"),
             Statement::List(command) => write!(f, "LIST {command}"),
-            Statement::Put {
+            Statement::Put(PutStatement {
                 source,
                 stage,
                 options,
-            } => {
+            }) => {
                 write!(f, "PUT '{source}' {stage}")?;
                 if !options.options.is_empty() {
                     write!(f, " {options}")?;
diff --git a/src/ast/spans.rs b/src/ast/spans.rs
index 65190cd..79e6121 100644
--- a/src/ast/spans.rs
+++ b/src/ast/spans.rs
@@ -15,6 +15,26 @@
 // specific language governing permissions and limitations
 // under the License.
 
+use crate::ast::{
+    AlterConnectorStatement, AlterIndexStatement, AlterRoleStatement, AlterSessionStatement,
+    AlterViewStatement, AssertStatement, AttachDatabaseStatement, AttachDuckDBDatabaseStatement,
+    CacheStatement, CloseStatement, CommentStatement, CommitStatement, CopyIntoSnowflakeStatement,
+    CopyStatement, CreateDatabaseStatement, CreateFileFormatStatement, CreateMacroStatement,
+    CreateProcedureStatement, CreateSchemaStatement, CreateSecretStatement,
+    CreateSequenceStatement, CreateStageStatement, CreateTypeStatement,
+    CreateVirtualTableStatement, DeallocateStatement, DeclareStatement,
+    DetachDuckDBDatabaseStatement, DirectoryStatement, DiscardStatement, DropConnectorStatement,
+    DropProcedureStatement, DropSecretStatement, DropStatement, ExecuteStatement, ExplainStatement,
+    ExplainTableStatement, FetchStatement, FlushStatement, InstallStatement, KillStatement,
+    LISTENStatement, LoadDataStatement, LoadStatement, LockTablesStatement, NOTIFYStatement,
+    OptimizeTableStatement, PragmaStatement, PrepareStatement, PutStatement, RaisErrorStatement,
+    ReleaseSavepointStatement, RollbackStatement, SavepointStatement, ShowCatalogsStatement,
+    ShowCollationStatement, ShowColumnsStatement, ShowCreateStatement, ShowDatabasesStatement,
+    ShowFunctionsStatement, ShowProcessListStatement, ShowSchemasStatement, ShowStatusStatement,
+    ShowTablesStatement, ShowVariableStatement, ShowVariablesStatement, ShowViewsStatement,
+    StartTransactionStatement, UNCacheStatement, UNLISTENStatement, UnloadStatement,
+    UnlockTablesStatement,
+};
 use crate::{
     ast::{
         ddl::AlterSchema, query::SelectItemQualifiedWildcardKind, AlterSchemaOperation, AlterTable,
@@ -336,7 +356,7 @@
 /// - [Statement::Pragma]
 /// - [Statement::Lock]
 /// - [Statement::LockTables]
-/// - [Statement::UnlockTables]
+/// - [Statement::UnlockTables(UnlockTablesStatement)]
 /// - [Statement::Unload]
 /// - [Statement::OptimizeTable]
 /// - [Statement::CreatePolicy]
@@ -375,29 +395,29 @@
             Statement::Msck(msck) => msck.span(),
             Statement::Query(query) => query.span(),
             Statement::Insert(insert) => insert.span(),
-            Statement::Install { extension_name } => extension_name.span,
-            Statement::Load { extension_name } => extension_name.span,
-            Statement::Directory {
+            Statement::Install(InstallStatement { extension_name }) => extension_name.span,
+            Statement::Load(LoadStatement { extension_name }) => extension_name.span,
+            Statement::Directory(DirectoryStatement {
                 overwrite: _,
                 local: _,
                 path: _,
                 file_format: _,
                 source,
-            } => source.span(),
+            }) => source.span(),
             Statement::Case(stmt) => stmt.span(),
             Statement::If(stmt) => stmt.span(),
             Statement::While(stmt) => stmt.span(),
             Statement::Raise(stmt) => stmt.span(),
             Statement::Call(function) => function.span(),
-            Statement::Copy {
+            Statement::Copy(CopyStatement {
                 source,
                 to: _,
                 target: _,
                 options: _,
                 legacy_options: _,
                 values: _,
-            } => source.span(),
-            Statement::CopyIntoSnowflake {
+            }) => source.span(),
+            Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
                 into: _,
                 into_columns: _,
                 from_obj: _,
@@ -412,9 +432,9 @@
                 kind: _,
                 from_query: _,
                 partition: _,
-            } => Span::empty(),
+            }) => Span::empty(),
             Statement::Open(open) => open.span(),
-            Statement::Close { cursor } => match cursor {
+            Statement::Close(CloseStatement { cursor }) => match cursor {
                 CloseCursor::All => Span::empty(),
                 CloseCursor::Specific { name } => name.span,
             },
@@ -422,12 +442,12 @@
             Statement::Delete(delete) => delete.span(),
             Statement::CreateView(create_view) => create_view.span(),
             Statement::CreateTable(create_table) => create_table.span(),
-            Statement::CreateVirtualTable {
+            Statement::CreateVirtualTable(CreateVirtualTableStatement {
                 name,
                 if_not_exists: _,
                 module_name,
                 module_args,
-            } => union_spans(
+            }) => union_spans(
                 core::iter::once(name.span())
                     .chain(core::iter::once(module_name.span))
                     .chain(module_args.iter().map(|i| i.span)),
@@ -440,7 +460,7 @@
             Statement::DropOperator(drop_operator) => drop_operator.span(),
             Statement::DropOperatorFamily(drop_operator_family) => drop_operator_family.span(),
             Statement::DropOperatorClass(drop_operator_class) => drop_operator_class.span(),
-            Statement::CreateSecret { .. } => Span::empty(),
+            Statement::CreateSecret(CreateSecretStatement { .. }) => Span::empty(),
             Statement::CreateServer { .. } => Span::empty(),
             Statement::CreateConnector { .. } => Span::empty(),
             Statement::CreateOperator(create_operator) => create_operator.span(),
@@ -450,13 +470,15 @@
             Statement::CreateOperatorClass(create_operator_class) => create_operator_class.span(),
             Statement::CreateTextSearch(create_text_search) => create_text_search.span(),
             Statement::AlterTable(alter_table) => alter_table.span(),
-            Statement::AlterIndex { name, operation } => name.span().union(&operation.span()),
-            Statement::AlterView {
+            Statement::AlterIndex(AlterIndexStatement { name, operation }) => {
+                name.span().union(&operation.span())
+            }
+            Statement::AlterView(AlterViewStatement {
                 name,
                 columns,
                 query,
                 with_options,
-            } => union_spans(
+            }) => union_spans(
                 core::iter::once(name.span())
                     .chain(columns.iter().map(|i| i.span))
                     .chain(core::iter::once(query.span()))
@@ -470,91 +492,93 @@
             Statement::AlterOperatorFamily { .. } => Span::empty(),
             Statement::AlterOperatorClass { .. } => Span::empty(),
             Statement::AlterTextSearch { .. } => Span::empty(),
-            Statement::AlterRole { .. } => Span::empty(),
-            Statement::AlterSession { .. } => Span::empty(),
-            Statement::AttachDatabase { .. } => Span::empty(),
-            Statement::AttachDuckDBDatabase { .. } => Span::empty(),
-            Statement::DetachDuckDBDatabase { .. } => Span::empty(),
-            Statement::Drop { .. } => Span::empty(),
+            Statement::AlterRole(AlterRoleStatement { .. }) => Span::empty(),
+            Statement::AlterSession(AlterSessionStatement { .. }) => Span::empty(),
+            Statement::AttachDatabase(AttachDatabaseStatement { .. }) => Span::empty(),
+            Statement::AttachDuckDBDatabase(AttachDuckDBDatabaseStatement { .. }) => Span::empty(),
+            Statement::DetachDuckDBDatabase(DetachDuckDBDatabaseStatement { .. }) => Span::empty(),
+            Statement::Drop(DropStatement { .. }) => 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::Fetch { .. } => Span::empty(),
-            Statement::Flush { .. } => Span::empty(),
-            Statement::Discard { .. } => Span::empty(),
+            Statement::DropProcedure(DropProcedureStatement { .. }) => Span::empty(),
+            Statement::DropSecret(DropSecretStatement { .. }) => Span::empty(),
+            Statement::Declare(DeclareStatement { .. }) => Span::empty(),
+            Statement::Fetch(FetchStatement { .. }) => Span::empty(),
+            Statement::Flush(FlushStatement { .. }) => Span::empty(),
+            Statement::Discard(DiscardStatement { .. }) => Span::empty(),
             Statement::Set(_) => Span::empty(),
-            Statement::ShowFunctions { .. } => Span::empty(),
-            Statement::ShowVariable { .. } => Span::empty(),
-            Statement::ShowStatus { .. } => Span::empty(),
-            Statement::ShowVariables { .. } => Span::empty(),
-            Statement::ShowCreate { .. } => Span::empty(),
-            Statement::ShowColumns { .. } => Span::empty(),
-            Statement::ShowTables { .. } => Span::empty(),
-            Statement::ShowCollation { .. } => Span::empty(),
+            Statement::ShowFunctions(ShowFunctionsStatement { .. }) => Span::empty(),
+            Statement::ShowVariable(ShowVariableStatement { .. }) => Span::empty(),
+            Statement::ShowStatus(ShowStatusStatement { .. }) => Span::empty(),
+            Statement::ShowVariables(ShowVariablesStatement { .. }) => Span::empty(),
+            Statement::ShowCreate(ShowCreateStatement { .. }) => Span::empty(),
+            Statement::ShowColumns(ShowColumnsStatement { .. }) => Span::empty(),
+            Statement::ShowTables(ShowTablesStatement { .. }) => Span::empty(),
+            Statement::ShowCollation(ShowCollationStatement { .. }) => Span::empty(),
             Statement::ShowCharset { .. } => Span::empty(),
             Statement::Use(u) => u.span(),
-            Statement::StartTransaction { .. } => Span::empty(),
-            Statement::Comment { .. } => Span::empty(),
-            Statement::Commit { .. } => Span::empty(),
-            Statement::Rollback { .. } => Span::empty(),
-            Statement::CreateSchema { .. } => Span::empty(),
-            Statement::CreateDatabase { .. } => Span::empty(),
+            Statement::StartTransaction(StartTransactionStatement { .. }) => Span::empty(),
+            Statement::Comment(CommentStatement { .. }) => Span::empty(),
+            Statement::Commit(CommitStatement { .. }) => Span::empty(),
+            Statement::Rollback(RollbackStatement { .. }) => Span::empty(),
+            Statement::CreateSchema(CreateSchemaStatement { .. }) => Span::empty(),
+            Statement::CreateDatabase(CreateDatabaseStatement { .. }) => Span::empty(),
             Statement::CreateFunction { .. } => Span::empty(),
             Statement::CreateDomain { .. } => Span::empty(),
             Statement::CreateTrigger { .. } => Span::empty(),
             Statement::DropTrigger { .. } => Span::empty(),
-            Statement::CreateProcedure { .. } => Span::empty(),
-            Statement::CreateMacro { .. } => Span::empty(),
-            Statement::CreateStage { .. } => Span::empty(),
-            Statement::CreateFileFormat { .. } => Span::empty(),
+            Statement::CreateProcedure(CreateProcedureStatement { .. }) => Span::empty(),
+            Statement::CreateMacro(CreateMacroStatement { .. }) => Span::empty(),
+            Statement::CreateStage(CreateStageStatement { .. }) => Span::empty(),
+            Statement::CreateFileFormat(CreateFileFormatStatement { .. }) => Span::empty(),
             Statement::CreateWarehouse(..) => Span::empty(),
-            Statement::Assert { .. } => Span::empty(),
+            Statement::Assert(AssertStatement { .. }) => Span::empty(),
             Statement::Grant { .. } => Span::empty(),
             Statement::Deny { .. } => Span::empty(),
             Statement::Revoke { .. } => Span::empty(),
-            Statement::Deallocate { .. } => Span::empty(),
-            Statement::Execute { .. } => Span::empty(),
-            Statement::Prepare { .. } => Span::empty(),
-            Statement::Kill { .. } => Span::empty(),
-            Statement::ExplainTable { .. } => Span::empty(),
-            Statement::Explain { .. } => Span::empty(),
-            Statement::Savepoint { .. } => Span::empty(),
-            Statement::ReleaseSavepoint { .. } => Span::empty(),
+            Statement::Deallocate(DeallocateStatement { .. }) => Span::empty(),
+            Statement::Execute(ExecuteStatement { .. }) => Span::empty(),
+            Statement::Prepare(PrepareStatement { .. }) => Span::empty(),
+            Statement::Kill(KillStatement { .. }) => Span::empty(),
+            Statement::ExplainTable(ExplainTableStatement { .. }) => Span::empty(),
+            Statement::Explain(ExplainStatement { .. }) => Span::empty(),
+            Statement::Savepoint(SavepointStatement { .. }) => Span::empty(),
+            Statement::ReleaseSavepoint(ReleaseSavepointStatement { .. }) => Span::empty(),
             Statement::Merge(merge) => merge.span(),
-            Statement::Cache { .. } => Span::empty(),
-            Statement::UNCache { .. } => Span::empty(),
-            Statement::CreateSequence { .. } => Span::empty(),
-            Statement::CreateType { .. } => Span::empty(),
-            Statement::Pragma { .. } => Span::empty(),
+            Statement::Cache(CacheStatement { .. }) => Span::empty(),
+            Statement::UNCache(UNCacheStatement { .. }) => Span::empty(),
+            Statement::CreateSequence(CreateSequenceStatement { .. }) => Span::empty(),
+            Statement::CreateType(CreateTypeStatement { .. }) => Span::empty(),
+            Statement::Pragma(PragmaStatement { .. }) => Span::empty(),
             Statement::Lock(_) => Span::empty(),
-            Statement::LockTables { .. } => Span::empty(),
-            Statement::UnlockTables => Span::empty(),
-            Statement::Unload { .. } => Span::empty(),
-            Statement::OptimizeTable { .. } => Span::empty(),
+            Statement::LockTables(LockTablesStatement { .. }) => Span::empty(),
+            Statement::UnlockTables(UnlockTablesStatement) => Span::empty(),
+            Statement::Unload(UnloadStatement { .. }) => Span::empty(),
+            Statement::OptimizeTable(OptimizeTableStatement { .. }) => Span::empty(),
             Statement::CreatePolicy { .. } => Span::empty(),
             Statement::AlterPolicy { .. } => Span::empty(),
-            Statement::AlterConnector { .. } => Span::empty(),
+            Statement::AlterConnector(AlterConnectorStatement { .. }) => Span::empty(),
             Statement::DropPolicy { .. } => Span::empty(),
-            Statement::DropConnector { .. } => Span::empty(),
-            Statement::ShowCatalogs { .. } => Span::empty(),
-            Statement::ShowDatabases { .. } => Span::empty(),
-            Statement::ShowProcessList { .. } => Span::empty(),
-            Statement::ShowSchemas { .. } => Span::empty(),
+            Statement::DropConnector(DropConnectorStatement { .. }) => Span::empty(),
+            Statement::ShowCatalogs(ShowCatalogsStatement { .. }) => Span::empty(),
+            Statement::ShowDatabases(ShowDatabasesStatement { .. }) => Span::empty(),
+            Statement::ShowProcessList(ShowProcessListStatement { .. }) => Span::empty(),
+            Statement::ShowSchemas(ShowSchemasStatement { .. }) => Span::empty(),
             Statement::ShowObjects { .. } => Span::empty(),
-            Statement::ShowViews { .. } => Span::empty(),
-            Statement::LISTEN { .. } => Span::empty(),
-            Statement::NOTIFY { .. } => Span::empty(),
-            Statement::LoadData { .. } => Span::empty(),
-            Statement::UNLISTEN { .. } => Span::empty(),
+            Statement::ShowViews(ShowViewsStatement { .. }) => Span::empty(),
+            Statement::LISTEN(LISTENStatement { .. }) => Span::empty(),
+            Statement::NOTIFY(NOTIFYStatement { .. }) => Span::empty(),
+            Statement::LoadData(LoadDataStatement { .. }) => Span::empty(),
+            Statement::UNLISTEN(UNLISTENStatement { .. }) => Span::empty(),
             Statement::RenameTable { .. } => Span::empty(),
-            Statement::RaisError { .. } => Span::empty(),
+            Statement::RaisError(RaisErrorStatement { .. }) => Span::empty(),
             Statement::Throw(_) => Span::empty(),
             Statement::Print { .. } => Span::empty(),
             Statement::WaitFor(_) => Span::empty(),
             Statement::Return { .. } => Span::empty(),
-            Statement::List(..) | Statement::Put { .. } | Statement::Remove(..) => Span::empty(),
+            Statement::List(..) | Statement::Put(PutStatement { .. }) | Statement::Remove(..) => {
+                Span::empty()
+            }
             Statement::ExportData(ExportData {
                 options,
                 query,
diff --git a/src/ast/statements.rs b/src/ast/statements.rs
new file mode 100644
index 0000000..7d49c2b
--- /dev/null
+++ b/src/ast/statements.rs
@@ -0,0 +1,1152 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+//! Named structs for the fields of [`Statement`] variants.
+
+#[cfg(not(feature = "std"))]
+use alloc::{boxed::Box, string::String, vec::Vec};
+
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Serialize};
+
+#[cfg(feature = "visitor")]
+use sqlparser_derive::{Visit, VisitMut};
+
+use super::*;
+
+/// The fields of [`Statement::Install`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct InstallStatement {
+    /// Only for DuckDB
+    pub extension_name: Ident,
+}
+
+/// The fields of [`Statement::Load`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct LoadStatement {
+    /// Only for DuckDB
+    pub extension_name: Ident,
+}
+
+/// The fields of [`Statement::Directory`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DirectoryStatement {
+    /// Whether to overwrite existing files.
+    pub overwrite: bool,
+    /// Whether the directory is local to the server.
+    pub local: bool,
+    /// Path to the directory or files.
+    pub path: String,
+    /// Optional file format for the data.
+    pub file_format: Option<FileFormat>,
+    /// Source query providing data to load.
+    pub source: Box<Query>,
+}
+
+/// The fields of [`Statement::Copy`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CopyStatement {
+    /// The source of 'COPY TO', or the target of 'COPY FROM'
+    pub source: CopySource,
+    /// If true, is a 'COPY TO' statement. If false is a 'COPY FROM'
+    pub to: bool,
+    /// The target of 'COPY TO', or the source of 'COPY FROM'
+    pub target: CopyTarget,
+    /// WITH options (from PostgreSQL version 9.0)
+    pub options: Vec<CopyOption>,
+    /// WITH options (before PostgreSQL version 9.0)
+    pub legacy_options: Vec<CopyLegacyOption>,
+    /// VALUES a vector of values to be copied
+    pub values: Vec<Option<String>>,
+}
+
+/// The fields of [`Statement::CopyIntoSnowflake`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CopyIntoSnowflakeStatement {
+    /// Kind of COPY INTO operation (table or location).
+    pub kind: CopyIntoSnowflakeKind,
+    /// Target object for the COPY INTO operation.
+    pub into: ObjectName,
+    /// Optional list of target columns.
+    pub into_columns: Option<Vec<Ident>>,
+    /// Optional source object name (staged data).
+    pub from_obj: Option<ObjectName>,
+    /// Optional alias for the source object.
+    pub from_obj_alias: Option<Ident>,
+    /// Stage-specific parameters (e.g., credentials, path).
+    pub stage_params: StageParamsObject,
+    /// Optional list of transformations applied when loading.
+    pub from_transformations: Option<Vec<StageLoadSelectItemKind>>,
+    /// Optional source query instead of a staged object.
+    pub from_query: Option<Box<Query>>,
+    /// Optional list of specific file names to load.
+    pub files: Option<Vec<String>>,
+    /// Optional filename matching pattern.
+    pub pattern: Option<String>,
+    /// File format options.
+    pub file_format: KeyValueOptions,
+    /// Additional copy options.
+    pub copy_options: KeyValueOptions,
+    /// Optional validation mode string.
+    pub validation_mode: Option<String>,
+    /// Optional partition expression for loading.
+    pub partition: Option<Box<Expr>>,
+}
+
+/// The fields of [`Statement::Close`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CloseStatement {
+    /// Cursor name
+    pub cursor: CloseCursor,
+}
+
+/// The fields of [`Statement::CreateVirtualTable`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateVirtualTableStatement {
+    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
+    /// Name of the virtual table module instance.
+    pub name: ObjectName,
+    /// `true` when `IF NOT EXISTS` was specified.
+    pub if_not_exists: bool,
+    /// Module name used by the virtual table.
+    pub module_name: Ident,
+    /// Arguments passed to the module.
+    pub module_args: Vec<Ident>,
+}
+
+/// The fields of [`Statement::CreateSecret`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateSecretStatement {
+    /// `true` when `OR REPLACE` was specified.
+    pub or_replace: bool,
+    /// Optional `TEMPORARY` flag.
+    pub temporary: Option<bool>,
+    /// `true` when `IF NOT EXISTS` was present.
+    pub if_not_exists: bool,
+    /// Optional secret name.
+    pub name: Option<Ident>,
+    /// Optional storage specifier identifier.
+    pub storage_specifier: Option<Ident>,
+    /// The secret type identifier.
+    pub secret_type: Ident,
+    /// Additional secret options.
+    pub options: Vec<SecretOption>,
+}
+
+/// The fields of [`Statement::AlterIndex`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct AlterIndexStatement {
+    /// Name of the index to alter.
+    pub name: ObjectName,
+    /// The operation to perform on the index.
+    pub operation: AlterIndexOperation,
+}
+
+/// The fields of [`Statement::AlterView`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct AlterViewStatement {
+    /// View name being altered.
+    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
+    pub name: ObjectName,
+    /// Optional new column list for the view.
+    pub columns: Vec<Ident>,
+    /// Replacement query for the view definition.
+    pub query: Box<Query>,
+    /// Additional WITH options for the view.
+    pub with_options: Vec<SqlOption>,
+}
+
+/// The fields of [`Statement::AlterRole`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct AlterRoleStatement {
+    /// Role name being altered.
+    pub name: Ident,
+    /// Operation to perform on the role.
+    pub operation: AlterRoleOperation,
+}
+
+/// The fields of [`Statement::AlterConnector`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct AlterConnectorStatement {
+    /// Name of the connector to alter.
+    pub name: Ident,
+    /// Optional connector properties to set.
+    pub properties: Option<Vec<SqlOption>>,
+    /// Optional new URL for the connector.
+    pub url: Option<String>,
+    /// Optional new owner specification.
+    pub owner: Option<ddl::AlterConnectorOwner>,
+}
+
+/// The fields of [`Statement::AlterSession`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct AlterSessionStatement {
+    /// true is to set for the session parameters, false is to unset
+    pub set: bool,
+    /// The session parameters to set or unset
+    pub session_params: KeyValueOptions,
+}
+
+/// The fields of [`Statement::AttachDatabase`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct AttachDatabaseStatement {
+    /// The name to bind to the newly attached database
+    pub schema_name: Ident,
+    /// An expression that indicates the path to the database file
+    pub database_file_name: Expr,
+    /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH'
+    pub database: bool,
+}
+
+/// The fields of [`Statement::AttachDuckDBDatabase`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct AttachDuckDBDatabaseStatement {
+    /// `true` when `IF NOT EXISTS` was present.
+    pub if_not_exists: bool,
+    /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`.
+    pub database: bool,
+    /// The path identifier to the database file being attached.
+    pub database_path: Ident,
+    /// Optional alias assigned to the attached database.
+    pub database_alias: Option<Ident>,
+    /// Dialect-specific attach options (e.g., `READ_ONLY`).
+    pub attach_options: Vec<AttachDuckDBDatabaseOption>,
+}
+
+/// The fields of [`Statement::DetachDuckDBDatabase`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DetachDuckDBDatabaseStatement {
+    /// `true` when `IF EXISTS` was present.
+    pub if_exists: bool,
+    /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`.
+    pub database: bool,
+    /// Alias of the database to detach.
+    pub database_alias: Ident,
+}
+
+/// The fields of [`Statement::Drop`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DropStatement {
+    /// The type of the object to drop: TABLE, VIEW, etc.
+    pub object_type: ObjectType,
+    /// An optional `IF EXISTS` clause. (Non-standard.)
+    pub if_exists: bool,
+    /// One or more objects to drop. (ANSI SQL requires exactly one.)
+    pub names: Vec<ObjectName>,
+    /// Whether `CASCADE` was specified. This will be `false` when
+    /// `RESTRICT` or no drop behavior at all was specified.
+    pub cascade: bool,
+    /// Whether `RESTRICT` was specified. This will be `false` when
+    /// `CASCADE` or no drop behavior at all was specified.
+    pub restrict: bool,
+    /// Hive allows you specify whether the table's stored data will be
+    /// deleted along with the dropped table
+    pub purge: bool,
+    /// MySQL-specific "TEMPORARY" keyword
+    pub temporary: bool,
+    /// MySQL-specific drop index syntax, which requires table specification
+    /// See <https://dev.mysql.com/doc/refman/8.4/en/drop-index.html>
+    pub table: Option<ObjectName>,
+}
+
+/// The fields of [`Statement::DropProcedure`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DropProcedureStatement {
+    /// `true` when `IF EXISTS` was present.
+    pub if_exists: bool,
+    /// One or more functions/procedures to drop.
+    pub proc_desc: Vec<FunctionDesc>,
+    /// Optional drop behavior (`CASCADE` or `RESTRICT`).
+    pub drop_behavior: Option<DropBehavior>,
+}
+
+/// The fields of [`Statement::DropSecret`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DropSecretStatement {
+    /// `true` when `IF EXISTS` was present.
+    pub if_exists: bool,
+    /// Optional `TEMPORARY` marker.
+    pub temporary: Option<bool>,
+    /// Name of the secret to drop.
+    pub name: Ident,
+    /// Optional storage specifier identifier.
+    pub storage_specifier: Option<Ident>,
+}
+
+/// The fields of [`Statement::DropConnector`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DropConnectorStatement {
+    /// `true` when `IF EXISTS` was present.
+    pub if_exists: bool,
+    /// Name of the connector to drop.
+    pub name: Ident,
+}
+
+/// The fields of [`Statement::Declare`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DeclareStatement {
+    /// Cursor declaration statements collected by `DECLARE`.
+    pub stmts: Vec<Declare>,
+}
+
+/// The fields of [`Statement::Fetch`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct FetchStatement {
+    /// Cursor name
+    pub name: Ident,
+    /// The fetch direction (e.g., `FORWARD`, `BACKWARD`).
+    pub direction: FetchDirection,
+    /// The fetch position (e.g., `ALL`, `NEXT`, `ABSOLUTE`).
+    pub position: FetchPosition,
+    /// Optional target table to fetch rows into.
+    pub into: Option<ObjectName>,
+}
+
+/// The fields of [`Statement::Flush`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct FlushStatement {
+    /// The specific flush option or object to flush.
+    pub object_type: FlushType,
+    /// Optional flush location (dialect-specific).
+    pub location: Option<FlushLocation>,
+    /// Optional channel name used for flush operations.
+    pub channel: Option<String>,
+    /// Whether a read lock was requested.
+    pub read_lock: bool,
+    /// Whether this is an export flush operation.
+    pub export: bool,
+    /// Optional list of tables involved in the flush.
+    pub tables: Vec<ObjectName>,
+}
+
+/// The fields of [`Statement::Discard`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DiscardStatement {
+    /// The kind of object(s) to discard (ALL, PLANS, etc.).
+    pub object_type: DiscardObject,
+}
+
+/// The fields of [`Statement::ShowFunctions`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowFunctionsStatement {
+    /// Optional filter for which functions to display.
+    pub filter: Option<ShowStatementFilter>,
+}
+
+/// The fields of [`Statement::ShowVariable`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowVariableStatement {
+    /// Variable name as one or more identifiers.
+    pub variable: Vec<Ident>,
+}
+
+/// The fields of [`Statement::ShowStatus`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowStatusStatement {
+    /// Optional filter for which status entries to display.
+    pub filter: Option<ShowStatementFilter>,
+    /// `true` when `GLOBAL` scope was requested.
+    pub global: bool,
+    /// `true` when `SESSION` scope was requested.
+    pub session: bool,
+}
+
+/// The fields of [`Statement::ShowVariables`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowVariablesStatement {
+    /// Optional filter for which variables to display.
+    pub filter: Option<ShowStatementFilter>,
+    /// `true` when `GLOBAL` scope was requested.
+    pub global: bool,
+    /// `true` when `SESSION` scope was requested.
+    pub session: bool,
+}
+
+/// The fields of [`Statement::ShowCreate`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowCreateStatement {
+    /// The kind of object being shown (TABLE, VIEW, etc.).
+    pub obj_type: ShowCreateObject,
+    /// The name of the object to show create statement for.
+    pub obj_name: ObjectName,
+}
+
+/// The fields of [`Statement::ShowColumns`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowColumnsStatement {
+    /// `true` when extended column information was requested.
+    pub extended: bool,
+    /// `true` when full column details were requested.
+    pub full: bool,
+    /// Additional options for `SHOW COLUMNS`.
+    pub show_options: ShowStatementOptions,
+}
+
+/// The fields of [`Statement::ShowCatalogs`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowCatalogsStatement {
+    /// `true` when terse output format was requested.
+    pub terse: bool,
+    /// `true` when history information was requested.
+    pub history: bool,
+    /// Additional options for `SHOW CATALOGS`.
+    pub show_options: ShowStatementOptions,
+}
+
+/// The fields of [`Statement::ShowDatabases`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowDatabasesStatement {
+    /// `true` when terse output format was requested.
+    pub terse: bool,
+    /// `true` when history information was requested.
+    pub history: bool,
+    /// Additional options for `SHOW DATABASES`.
+    pub show_options: ShowStatementOptions,
+}
+
+/// The fields of [`Statement::ShowProcessList`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowProcessListStatement {
+    /// `true` when full process information was requested.
+    pub full: bool,
+}
+
+/// The fields of [`Statement::ShowSchemas`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowSchemasStatement {
+    /// `true` when terse (compact) output was requested.
+    pub terse: bool,
+    /// `true` when history information was requested.
+    pub history: bool,
+    /// Additional options for `SHOW SCHEMAS`.
+    pub show_options: ShowStatementOptions,
+}
+
+/// The fields of [`Statement::ShowTables`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowTablesStatement {
+    /// `true` when terse output format was requested (compact listing).
+    pub terse: bool,
+    /// `true` when history rows are requested.
+    pub history: bool,
+    /// `true` when extended information should be shown.
+    pub extended: bool,
+    /// `true` when a full listing was requested.
+    pub full: bool,
+    /// `true` when external tables should be included.
+    pub external: bool,
+    /// Additional options for `SHOW` statements.
+    pub show_options: ShowStatementOptions,
+}
+
+/// The fields of [`Statement::ShowViews`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowViewsStatement {
+    /// `true` when terse output format was requested.
+    pub terse: bool,
+    /// `true` when materialized views should be included.
+    pub materialized: bool,
+    /// Additional options for `SHOW` statements.
+    pub show_options: ShowStatementOptions,
+}
+
+/// The fields of [`Statement::ShowCollation`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ShowCollationStatement {
+    /// Optional filter for which collations to display.
+    pub filter: Option<ShowStatementFilter>,
+}
+
+/// The fields of [`Statement::StartTransaction`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct StartTransactionStatement {
+    /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`.
+    pub modes: Vec<TransactionMode>,
+    /// `true` when this was parsed as `BEGIN` instead of `START`.
+    pub begin: bool,
+    /// Optional specific keyword used: `TRANSACTION` or `WORK`.
+    pub transaction: Option<BeginTransactionKind>,
+    /// Optional transaction modifier (e.g., `AND NO CHAIN`).
+    pub modifier: Option<TransactionModifier>,
+    /// List of statements belonging to the `BEGIN` block.
+    /// Example:
+    /// ```sql
+    /// BEGIN
+    ///     SELECT 1;
+    ///     SELECT 2;
+    /// END;
+    /// ```
+    pub statements: Vec<Statement>,
+    /// Exception handling with exception clauses.
+    /// Example:
+    /// ```sql
+    /// EXCEPTION
+    ///     WHEN EXCEPTION_1 THEN
+    ///         SELECT 2;
+    ///     WHEN EXCEPTION_2 OR EXCEPTION_3 THEN
+    ///         SELECT 3;
+    ///     WHEN OTHER THEN
+    ///         SELECT 4;
+    /// ```
+    /// <https://cloud.google.com/bigquery/docs/reference/standard-sql/procedural-language#beginexceptionend>
+    /// <https://docs.snowflake.com/en/sql-reference/snowflake-scripting/exception>
+    pub exception: Option<Vec<ExceptionWhen>>,
+    /// TRUE if the statement has an `END` keyword.
+    pub has_end_keyword: bool,
+}
+
+/// The fields of [`Statement::Comment`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CommentStatement {
+    /// Type of object being commented (table, column, etc.).
+    pub object_type: CommentObject,
+    /// Name of the object the comment applies to.
+    pub object_name: ObjectName,
+    /// Optional comment text (None to remove comment).
+    pub comment: Option<String>,
+    /// An optional `IF EXISTS` clause. (Non-standard.)
+    /// See <https://docs.snowflake.com/en/sql-reference/sql/comment>
+    pub if_exists: bool,
+}
+
+/// The fields of [`Statement::Commit`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CommitStatement {
+    /// `true` when `AND [ NO ] CHAIN` was present.
+    pub chain: bool,
+    /// `true` when this `COMMIT` was parsed as an `END` block terminator.
+    pub end: bool,
+    /// Optional transaction modifier for commit semantics.
+    pub modifier: Option<TransactionModifier>,
+}
+
+/// The fields of [`Statement::Rollback`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct RollbackStatement {
+    /// `true` when `AND [ NO ] CHAIN` was present.
+    pub chain: bool,
+    /// Optional savepoint name to roll back to.
+    pub savepoint: Option<Ident>,
+}
+
+/// The fields of [`Statement::CreateSchema`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateSchemaStatement {
+    /// `<schema name> | AUTHORIZATION <schema authorization identifier>  | <schema name>  AUTHORIZATION <schema authorization identifier>`
+    pub schema_name: SchemaName,
+    /// `true` when `OR REPLACE` was present.
+    pub or_replace: bool,
+    /// `true` when `IF NOT EXISTS` was present.
+    pub if_not_exists: bool,
+    /// Schema properties.
+    ///
+    /// ```sql
+    /// CREATE SCHEMA myschema WITH (key1='value1');
+    /// ```
+    ///
+    /// [Trino](https://trino.io/docs/current/sql/create-schema.html)
+    pub with: Option<Vec<SqlOption>>,
+    /// Schema options.
+    ///
+    /// ```sql
+    /// CREATE SCHEMA myschema OPTIONS(key1='value1');
+    /// ```
+    ///
+    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
+    pub options: Option<Vec<SqlOption>>,
+    /// Default collation specification for the schema.
+    ///
+    /// ```sql
+    /// CREATE SCHEMA myschema DEFAULT COLLATE 'und:ci';
+    /// ```
+    ///
+    /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#create_schema_statement)
+    pub default_collate_spec: Option<Expr>,
+    /// Clones a schema
+    ///
+    /// ```sql
+    /// CREATE SCHEMA myschema CLONE otherschema
+    /// ```
+    ///
+    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/create-clone#databases-schemas)
+    pub clone: Option<ObjectName>,
+}
+
+/// The fields of [`Statement::CreateDatabase`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateDatabaseStatement {
+    /// Database name.
+    pub db_name: ObjectName,
+    /// `IF NOT EXISTS` flag.
+    pub if_not_exists: bool,
+    /// Optional location URI.
+    pub location: Option<String>,
+    /// Optional managed location.
+    pub managed_location: Option<String>,
+    /// `OR REPLACE` flag.
+    pub or_replace: bool,
+    /// `TRANSIENT` flag.
+    pub transient: bool,
+    /// Optional clone source.
+    pub clone: Option<ObjectName>,
+    /// Optional data retention time in days.
+    pub data_retention_time_in_days: Option<u64>,
+    /// Optional maximum data extension time in days.
+    pub max_data_extension_time_in_days: Option<u64>,
+    /// Optional external volume identifier.
+    pub external_volume: Option<String>,
+    /// Optional catalog name.
+    pub catalog: Option<String>,
+    /// Whether to replace invalid characters.
+    pub replace_invalid_characters: Option<bool>,
+    /// Default DDL collation string.
+    pub default_ddl_collation: Option<String>,
+    /// Storage serialization policy.
+    pub storage_serialization_policy: Option<StorageSerializationPolicy>,
+    /// Optional comment.
+    pub comment: Option<String>,
+    /// Optional default character set (MySQL).
+    pub default_charset: Option<String>,
+    /// Optional default collation (MySQL).
+    pub default_collation: Option<String>,
+    /// Optional catalog sync identifier.
+    pub catalog_sync: Option<String>,
+    /// Catalog sync namespace mode.
+    pub catalog_sync_namespace_mode: Option<CatalogSyncNamespaceMode>,
+    /// Optional flatten delimiter for namespace sync.
+    pub catalog_sync_namespace_flatten_delimiter: Option<String>,
+    /// Optional tags for the database.
+    pub with_tags: Option<Vec<Tag>>,
+    /// Optional contact entries for the database.
+    pub with_contacts: Option<Vec<ContactEntry>>,
+}
+
+/// The fields of [`Statement::CreateProcedure`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateProcedureStatement {
+    /// `OR ALTER` flag.
+    pub or_alter: bool,
+    /// Procedure name.
+    pub name: ObjectName,
+    /// Optional procedure parameters.
+    pub params: Option<Vec<ProcedureParam>>,
+    /// Optional language identifier.
+    pub language: Option<Ident>,
+    /// Procedure body statements.
+    pub body: ConditionalStatements,
+}
+
+/// The fields of [`Statement::CreateMacro`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateMacroStatement {
+    /// `OR REPLACE` flag.
+    pub or_replace: bool,
+    /// Whether macro is temporary.
+    pub temporary: bool,
+    /// Macro name.
+    pub name: ObjectName,
+    /// Optional macro arguments.
+    pub args: Option<Vec<MacroArg>>,
+    /// Macro definition body.
+    pub definition: MacroDefinition,
+}
+
+/// The fields of [`Statement::CreateStage`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateStageStatement {
+    /// `OR REPLACE` flag for stage.
+    pub or_replace: bool,
+    /// Whether stage is temporary.
+    pub temporary: bool,
+    /// `IF NOT EXISTS` flag.
+    pub if_not_exists: bool,
+    /// Stage name.
+    pub name: ObjectName,
+    /// Stage parameters.
+    pub stage_params: StageParamsObject,
+    /// Directory table parameters.
+    pub directory_table_params: KeyValueOptions,
+    /// File format options.
+    pub file_format: KeyValueOptions,
+    /// Copy options for stage.
+    pub copy_options: KeyValueOptions,
+    /// Optional comment.
+    pub comment: Option<String>,
+}
+
+/// The fields of [`Statement::CreateFileFormat`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateFileFormatStatement {
+    /// `OR REPLACE` flag.
+    pub or_replace: bool,
+    /// Whether file format is temporary.
+    pub temporary: bool,
+    /// Whether file format is volatile.
+    pub volatile: bool,
+    /// `IF NOT EXISTS` flag.
+    pub if_not_exists: bool,
+    /// File format name.
+    pub name: ObjectName,
+    /// Format type options (e.g. `TYPE`, `FIELD_DELIMITER`, `COMPRESSION`, ...).
+    pub options: KeyValueOptions,
+    /// Optional comment.
+    pub comment: Option<String>,
+}
+
+/// The fields of [`Statement::Assert`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct AssertStatement {
+    /// Assertion condition expression.
+    pub condition: Expr,
+    /// Optional message expression.
+    pub message: Option<Expr>,
+}
+
+/// The fields of [`Statement::Deallocate`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct DeallocateStatement {
+    /// Name to deallocate (or `ALL`).
+    pub name: Ident,
+    /// Whether `PREPARE` keyword was present.
+    pub prepare: bool,
+}
+
+/// The fields of [`Statement::Execute`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ExecuteStatement {
+    /// Optional function/procedure name.
+    pub name: Option<ObjectName>,
+    /// Parameter expressions passed to execute.
+    pub parameters: Vec<Expr>,
+    /// Whether parentheses were present around `parameters`.
+    pub has_parentheses: bool,
+    /// Is this an `EXECUTE IMMEDIATE`.
+    pub immediate: bool,
+    /// Identifiers to capture results into.
+    pub into: Vec<Ident>,
+    /// `USING` expressions with optional aliases.
+    pub using: Vec<ExprWithAlias>,
+    /// Whether the last parameter is the return value of the procedure
+    /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#output>
+    pub output: bool,
+    /// Whether to invoke the procedure with the default parameter values
+    /// MSSQL: <https://learn.microsoft.com/en-us/sql/t-sql/language-elements/execute-transact-sql?view=sql-server-ver17#default>
+    pub default: bool,
+}
+
+/// The fields of [`Statement::Prepare`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct PrepareStatement {
+    /// Name of the prepared statement.
+    pub name: Ident,
+    /// Optional data types for parameters.
+    pub data_types: Vec<DataType>,
+    /// Statement being prepared.
+    pub statement: Box<Statement>,
+}
+
+/// The fields of [`Statement::Kill`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct KillStatement {
+    /// Optional kill modifier (CONNECTION, QUERY, MUTATION).
+    pub modifier: Option<KillType>,
+    // processlist_id
+    /// The id of the process to kill.
+    pub id: u64,
+}
+
+/// The fields of [`Statement::ExplainTable`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ExplainTableStatement {
+    /// `EXPLAIN | DESC | DESCRIBE`
+    pub describe_alias: DescribeAlias,
+    /// Hive style `FORMATTED | EXTENDED`
+    pub hive_format: Option<HiveDescribeFormat>,
+    /// Snowflake and ClickHouse support `DESC|DESCRIBE TABLE <table_name>` syntax
+    ///
+    /// [Snowflake](https://docs.snowflake.com/en/sql-reference/sql/desc-table.html)
+    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/describe-table)
+    pub has_table_keyword: bool,
+    /// Table name
+    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
+    pub table_name: ObjectName,
+}
+
+/// The fields of [`Statement::Explain`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ExplainStatement {
+    /// `EXPLAIN | DESC | DESCRIBE`
+    pub describe_alias: DescribeAlias,
+    /// Carry out the command and show actual run times and other statistics.
+    pub analyze: bool,
+    /// Display additional information regarding the plan.
+    pub verbose: bool,
+    /// `EXPLAIN QUERY PLAN`
+    /// Display the query plan without running the query.
+    ///
+    /// [SQLite](https://sqlite.org/lang_explain.html)
+    pub query_plan: bool,
+    /// `EXPLAIN ESTIMATE`
+    /// [Clickhouse](https://clickhouse.com/docs/en/sql-reference/statements/explain#explain-estimate)
+    pub estimate: bool,
+    /// A SQL query that specifies what to explain
+    pub statement: Box<Statement>,
+    /// Optional output format of explain
+    pub format: Option<AnalyzeFormatKind>,
+    /// Postgres style utility options, `(analyze, verbose true)`
+    pub options: Option<Vec<UtilityOption>>,
+}
+
+/// The fields of [`Statement::Savepoint`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct SavepointStatement {
+    /// Name of the savepoint being defined.
+    pub name: Ident,
+}
+
+/// The fields of [`Statement::ReleaseSavepoint`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct ReleaseSavepointStatement {
+    /// Name of the savepoint to release.
+    pub name: Ident,
+}
+
+/// The fields of [`Statement::Cache`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CacheStatement {
+    /// Table flag
+    pub table_flag: Option<ObjectName>,
+    /// Table name
+    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
+    pub table_name: ObjectName,
+    /// `true` if `AS` keyword was present before the query.
+    pub has_as: bool,
+    /// Table confs
+    pub options: Vec<SqlOption>,
+    /// Cache table as a Query
+    pub query: Option<Box<Query>>,
+}
+
+/// The fields of [`Statement::UNCache`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct UNCacheStatement {
+    /// Table name
+    #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
+    pub table_name: ObjectName,
+    /// `true` when `IF EXISTS` was present.
+    pub if_exists: bool,
+}
+
+/// The fields of [`Statement::CreateSequence`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateSequenceStatement {
+    /// Whether the sequence is temporary.
+    pub temporary: bool,
+    /// `IF NOT EXISTS` flag.
+    pub if_not_exists: bool,
+    /// Sequence name.
+    pub name: ObjectName,
+    /// Optional data type for the sequence.
+    pub data_type: Option<DataType>,
+    /// Sequence options (INCREMENT, MINVALUE, etc.).
+    pub sequence_options: Vec<SequenceOptions>,
+    /// Optional `OWNED BY` target.
+    pub owned_by: Option<ObjectName>,
+}
+
+/// The fields of [`Statement::CreateType`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct CreateTypeStatement {
+    /// Type name to create.
+    pub name: ObjectName,
+    /// Optional type representation details.
+    pub representation: Option<UserDefinedTypeRepresentation>,
+}
+
+/// The fields of [`Statement::Pragma`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct PragmaStatement {
+    /// Pragma name (possibly qualified).
+    pub name: ObjectName,
+    /// Optional pragma value.
+    pub value: Option<ValueWithSpan>,
+    /// Whether the pragma used `=`.
+    pub is_eq: bool,
+}
+
+/// The fields of [`Statement::LockTables`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct LockTablesStatement {
+    /// List of tables to lock with modes.
+    pub tables: Vec<LockTable>,
+}
+
+/// The fields of [`Statement::UnlockTables`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct UnlockTablesStatement;
+
+/// The fields of [`Statement::Unload`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct UnloadStatement {
+    /// Optional query AST to unload.
+    pub query: Option<Box<Query>>,
+    /// Optional original query text.
+    pub query_text: Option<String>,
+    /// Destination identifier.
+    pub to: Ident,
+    /// Optional IAM role/auth information.
+    pub auth: Option<IamRoleKind>,
+    /// Additional `WITH` options.
+    pub with: Vec<SqlOption>,
+    /// Legacy copy-style options.
+    pub options: Vec<CopyLegacyOption>,
+}
+
+/// The fields of [`Statement::OptimizeTable`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct OptimizeTableStatement {
+    /// Table name to optimize.
+    pub name: ObjectName,
+    /// Whether the `TABLE` keyword was present (ClickHouse uses `OPTIMIZE TABLE`, Databricks uses `OPTIMIZE`).
+    pub has_table_keyword: bool,
+    /// Optional cluster identifier.
+    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
+    pub on_cluster: Option<Ident>,
+    /// Optional partition spec.
+    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
+    pub partition: Option<Partition>,
+    /// Whether `FINAL` was specified.
+    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
+    pub include_final: bool,
+    /// Optional deduplication settings.
+    /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/optimize)
+    pub deduplicate: Option<Deduplicate>,
+    /// Optional WHERE predicate.
+    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
+    pub predicate: Option<Expr>,
+    /// Optional ZORDER BY columns.
+    /// [Databricks](https://docs.databricks.com/en/sql/language-manual/delta-optimize.html)
+    pub zorder: Option<Vec<Expr>>,
+}
+
+/// The fields of [`Statement::LISTEN`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct LISTENStatement {
+    /// Notification channel identifier.
+    pub channel: Ident,
+}
+
+/// The fields of [`Statement::UNLISTEN`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct UNLISTENStatement {
+    /// Notification channel identifier.
+    pub channel: Ident,
+}
+
+/// The fields of [`Statement::NOTIFY`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct NOTIFYStatement {
+    /// Notification channel identifier.
+    pub channel: Ident,
+    /// Optional payload string.
+    pub payload: Option<String>,
+}
+
+/// The fields of [`Statement::LoadData`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct LoadDataStatement {
+    /// Whether `LOCAL` is present.
+    pub local: bool,
+    /// Input path for files to load.
+    pub inpath: String,
+    /// Whether `OVERWRITE` was specified.
+    pub overwrite: bool,
+    /// Target table name to load into.
+    pub table_name: ObjectName,
+    /// Optional partition specification.
+    pub partitioned: Option<Vec<Expr>>,
+    /// Optional table format information.
+    pub table_format: Option<HiveLoadDataFormat>,
+}
+
+/// The fields of [`Statement::Put`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct PutStatement {
+    /// Local source URI as written in the statement, e.g. `file:///tmp/data.csv`.
+    pub source: String,
+    /// Target internal stage (e.g. `@mystage`, `@~`, `@%table`).
+    pub stage: ObjectName,
+    /// Trailing options (`PARALLEL=4`, `AUTO_COMPRESS=TRUE`, ...).
+    pub options: KeyValueOptions,
+}
+
+/// The fields of [`Statement::RaisError`].
+#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
+pub struct RaisErrorStatement {
+    /// Error message expression or identifier.
+    pub message: Box<Expr>,
+    /// Severity expression.
+    pub severity: Box<Expr>,
+    /// State expression.
+    pub state: Box<Expr>,
+    /// Substitution arguments for the message.
+    pub arguments: Vec<Expr>,
+    /// Additional `WITH` options for RAISERROR.
+    pub options: Vec<RaisErrorOption>,
+}
diff --git a/src/dialect/mysql.rs b/src/dialect/mysql.rs
index 2be39f5..b9627d1 100644
--- a/src/dialect/mysql.rs
+++ b/src/dialect/mysql.rs
@@ -18,6 +18,7 @@
 #[cfg(not(feature = "std"))]
 use alloc::boxed::Box;
 
+use crate::ast::{LockTablesStatement, UnlockTablesStatement};
 use crate::{
     ast::{BinaryOperator, Expr, LockTable, LockTableType, Statement},
     dialect::Dialect,
@@ -236,7 +237,7 @@
 /// <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
 fn parse_lock_tables(parser: &mut Parser) -> Result<Statement, ParserError> {
     let tables = parser.parse_comma_separated(parse_lock_table)?;
-    Ok(Statement::LockTables { tables })
+    Ok(Statement::LockTables(LockTablesStatement { tables }))
 }
 
 // tbl_name [[AS] alias] lock_type
@@ -275,5 +276,5 @@
 /// UNLOCK TABLES
 /// <https://dev.mysql.com/doc/refman/8.0/en/lock-tables.html>
 fn parse_unlock_tables(_parser: &mut Parser) -> Result<Statement, ParserError> {
-    Ok(Statement::UnlockTables)
+    Ok(Statement::UnlockTables(UnlockTablesStatement))
 }
diff --git a/src/dialect/snowflake.rs b/src/dialect/snowflake.rs
index ce9ccfb..b002db0 100644
--- a/src/dialect/snowflake.rs
+++ b/src/dialect/snowflake.rs
@@ -27,6 +27,10 @@
     FileStagingCommand, StageLoadSelectItem, StageLoadSelectItemKind, StageParamsObject,
 };
 use crate::ast::{
+    AlterSessionStatement, CopyIntoSnowflakeStatement, CreateFileFormatStatement,
+    CreateStageStatement, PutStatement,
+};
+use crate::ast::{
     AlterTable, AlterTableOperation, AlterTableType, CatalogSyncNamespaceMode, ColumnOption,
     ColumnPolicy, ColumnPolicyProperty, ContactEntry, CopyIntoSnowflakeKind, CreateTable,
     CreateTableLikeKind, DollarQuotedString, Ident, IdentityParameters, IdentityProperty,
@@ -730,11 +734,11 @@
     let source = parser.parse_literal_string()?;
     let stage = parse_snowflake_stage_name(parser)?;
     let options = parser.parse_key_value_options(false, &[])?;
-    Ok(Statement::Put {
+    Ok(Statement::Put(PutStatement {
         source,
         stage,
         options,
-    })
+    }))
 }
 
 fn parse_file_staging_command(kw: Keyword, parser: &mut Parser) -> Result<Statement, ParserError> {
@@ -841,13 +845,13 @@
 /// <https://docs.snowflake.com/en/sql-reference/sql/alter-session>
 fn parse_alter_session(parser: &mut Parser, set: bool) -> Result<Statement, ParserError> {
     let session_options = parse_session_options(parser, set)?;
-    Ok(Statement::AlterSession {
+    Ok(Statement::AlterSession(AlterSessionStatement {
         set,
         session_params: KeyValueOptions {
             options: session_options,
             delimiter: KeyValueOptionsDelimiter::Space,
         },
-    })
+    }))
 }
 
 /// Parse snowflake create table statement.
@@ -1272,7 +1276,7 @@
         comment = Some(parser.parse_comment_value()?);
     }
 
-    Ok(Statement::CreateStage {
+    Ok(Statement::CreateStage(CreateStageStatement {
         or_replace,
         temporary,
         if_not_exists,
@@ -1291,7 +1295,7 @@
             delimiter: KeyValueOptionsDelimiter::Space,
         },
         comment,
-    })
+    }))
 }
 
 /// Parse a Snowflake `CREATE FILE FORMAT` statement.
@@ -1312,7 +1316,7 @@
         None
     };
 
-    Ok(Statement::CreateFileFormat {
+    Ok(Statement::CreateFileFormat(CreateFileFormatStatement {
         or_replace,
         temporary,
         volatile,
@@ -1320,7 +1324,7 @@
         name,
         options,
         comment,
-    })
+    }))
 }
 
 pub fn parse_stage_name_identifier(parser: &mut Parser) -> Result<Ident, ParserError> {
@@ -1515,7 +1519,7 @@
         }
     }
 
-    Ok(Statement::CopyIntoSnowflake {
+    Ok(Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
         kind,
         into,
         into_columns,
@@ -1536,7 +1540,7 @@
         },
         validation_mode,
         partition,
-    })
+    }))
 }
 
 fn parse_select_items_for_data_load(
diff --git a/src/parser/alter.rs b/src/parser/alter.rs
index 4000eb2..2858146 100644
--- a/src/parser/alter.rs
+++ b/src/parser/alter.rs
@@ -16,6 +16,7 @@
 use alloc::{string::ToString, vec};
 
 use super::{Parser, ParserError};
+use crate::ast::{AlterConnectorStatement, AlterRoleStatement};
 use crate::{
     ast::{
         helpers::key_value_options::{KeyValueOptions, KeyValueOptionsDelimiter},
@@ -136,12 +137,12 @@
             None
         };
 
-        Ok(Statement::AlterConnector {
+        Ok(Statement::AlterConnector(AlterConnectorStatement {
             name,
             properties,
             url,
             owner,
-        })
+        }))
     }
 
     /// Parse an `ALTER USER` statement
@@ -364,10 +365,10 @@
             return self.expected_ref("'ADD' or 'DROP' or 'WITH NAME'", self.peek_token_ref());
         };
 
-        Ok(Statement::AlterRole {
+        Ok(Statement::AlterRole(AlterRoleStatement {
             name: role_name,
             operation,
-        })
+        }))
     }
 
     fn parse_pg_alter_role(&mut self) -> Result<Statement, ParserError> {
@@ -448,10 +449,10 @@
             AlterRoleOperation::WithOptions { options }
         };
 
-        Ok(Statement::AlterRole {
+        Ok(Statement::AlterRole(AlterRoleStatement {
             name: role_name,
             operation,
-        })
+        }))
     }
 
     fn parse_pg_role_option(&mut self) -> Result<RoleOption, ParserError> {
diff --git a/src/parser/mod.rs b/src/parser/mod.rs
index d48f00e..076f568 100644
--- a/src/parser/mod.rs
+++ b/src/parser/mod.rs
@@ -986,12 +986,12 @@
         } else {
             Some(self.parse_literal_string()?)
         };
-        Ok(Statement::Comment {
+        Ok(Statement::Comment(CommentStatement {
             object_type,
             object_name,
             comment,
             if_exists,
-        })
+        }))
     }
 
     /// Parse `FLUSH` statement.
@@ -1075,14 +1075,14 @@
             );
         };
 
-        Ok(Statement::Flush {
+        Ok(Statement::Flush(FlushStatement {
             object_type,
             location,
             channel,
             read_lock,
             export,
             tables,
-        })
+        }))
     }
 
     /// Parse `MSCK` statement.
@@ -1223,13 +1223,15 @@
         };
 
         let attach_options = self.parse_attach_duckdb_database_options()?;
-        Ok(Statement::AttachDuckDBDatabase {
-            if_not_exists,
-            database,
-            database_path,
-            database_alias,
-            attach_options,
-        })
+        Ok(Statement::AttachDuckDBDatabase(
+            AttachDuckDBDatabaseStatement {
+                if_not_exists,
+                database,
+                database_path,
+                database_alias,
+                attach_options,
+            },
+        ))
     }
 
     /// Parse `DETACH DUCKDB DATABASE` statement.
@@ -1237,11 +1239,13 @@
         let database = self.parse_keyword(Keyword::DATABASE);
         let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
         let database_alias = self.parse_identifier()?;
-        Ok(Statement::DetachDuckDBDatabase {
-            if_exists,
-            database,
-            database_alias,
-        })
+        Ok(Statement::DetachDuckDBDatabase(
+            DetachDuckDBDatabaseStatement {
+                if_exists,
+                database,
+                database_alias,
+            },
+        ))
     }
 
     /// Parse `ATTACH DATABASE` statement.
@@ -1250,11 +1254,11 @@
         let database_file_name = self.parse_expr()?;
         self.expect_keyword_is(Keyword::AS)?;
         let schema_name = self.parse_identifier()?;
-        Ok(Statement::AttachDatabase {
+        Ok(Statement::AttachDatabase(AttachDatabaseStatement {
             database,
             schema_name,
             database_file_name,
-        })
+        }))
     }
 
     /// Parse `ANALYZE` statement.
@@ -1458,13 +1462,13 @@
             None
         };
 
-        Ok(Statement::Assert { condition, message })
+        Ok(Statement::Assert(AssertStatement { condition, message }))
     }
 
     /// Parse `SAVEPOINT` statement.
     pub fn parse_savepoint(&mut self) -> Result<Statement, ParserError> {
         let name = self.parse_identifier()?;
-        Ok(Statement::Savepoint { name })
+        Ok(Statement::Savepoint(SavepointStatement { name }))
     }
 
     /// Parse `RELEASE` statement.
@@ -1472,13 +1476,15 @@
         let _ = self.parse_keyword(Keyword::SAVEPOINT);
         let name = self.parse_identifier()?;
 
-        Ok(Statement::ReleaseSavepoint { name })
+        Ok(Statement::ReleaseSavepoint(ReleaseSavepointStatement {
+            name,
+        }))
     }
 
     /// Parse `LISTEN` statement.
     pub fn parse_listen(&mut self) -> Result<Statement, ParserError> {
         let channel = self.parse_identifier()?;
-        Ok(Statement::LISTEN { channel })
+        Ok(Statement::LISTEN(LISTENStatement { channel }))
     }
 
     /// Parse `UNLISTEN` statement.
@@ -1494,7 +1500,7 @@
                 }
             }
         };
-        Ok(Statement::UNLISTEN { channel })
+        Ok(Statement::UNLISTEN(UNLISTENStatement { channel }))
     }
 
     /// Parse `NOTIFY` statement.
@@ -1505,7 +1511,7 @@
         } else {
             None
         };
-        Ok(Statement::NOTIFY { channel, payload })
+        Ok(Statement::NOTIFY(NOTIFYStatement { channel, payload }))
     }
 
     /// Parses a `RENAME TABLE` statement. See [Statement::RenameTable]
@@ -5530,7 +5536,7 @@
             _ => self.expected_ref("TEMPORARY or PERSISTENT", self.peek_token_ref())?,
         };
 
-        Ok(Statement::CreateSecret {
+        Ok(Statement::CreateSecret(CreateSecretStatement {
             or_replace,
             temporary: temp,
             if_not_exists,
@@ -5538,7 +5544,7 @@
             storage_specifier,
             secret_type,
             options,
-        })
+        }))
     }
 
     /// Parse a CACHE TABLE statement
@@ -5559,21 +5565,21 @@
                     query = Some(q);
                 }
 
-                Ok(Statement::Cache {
+                Ok(Statement::Cache(CacheStatement {
                     table_flag,
                     table_name,
                     has_as,
                     options,
                     query,
-                })
+                }))
             } else {
-                Ok(Statement::Cache {
+                Ok(Statement::Cache(CacheStatement {
                     table_flag,
                     table_name,
                     has_as,
                     options,
                     query,
-                })
+                }))
             }
         } else {
             table_flag = Some(self.parse_object_name(false)?);
@@ -5592,21 +5598,21 @@
                         query = Some(q);
                     }
 
-                    Ok(Statement::Cache {
+                    Ok(Statement::Cache(CacheStatement {
                         table_flag,
                         table_name,
                         has_as,
                         options,
                         query,
-                    })
+                    }))
                 } else {
-                    Ok(Statement::Cache {
+                    Ok(Statement::Cache(CacheStatement {
                         table_flag,
                         table_name,
                         has_as,
                         options,
                         query,
-                    })
+                    }))
                 }
             } else {
                 if self.peek_token_ref().token == Token::EOF {
@@ -5636,10 +5642,10 @@
         self.expect_keyword_is(Keyword::TABLE)?;
         let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
         let table_name = self.parse_object_name(false)?;
-        Ok(Statement::UNCache {
+        Ok(Statement::UNCache(UNCacheStatement {
             table_name,
             if_exists,
-        })
+        }))
     }
 
     /// SQLite-specific `CREATE VIRTUAL TABLE`
@@ -5654,12 +5660,12 @@
         // definitions in a traditional CREATE TABLE statement", but
         // we don't implement that.
         let module_args = self.parse_parenthesized_column_list(Optional, false)?;
-        Ok(Statement::CreateVirtualTable {
+        Ok(Statement::CreateVirtualTable(CreateVirtualTableStatement {
             name: table_name,
             if_not_exists,
             module_name,
             module_args,
-        })
+        }))
     }
 
     /// Parse a `CREATE SCHEMA` statement.
@@ -5692,7 +5698,7 @@
             None
         };
 
-        Ok(Statement::CreateSchema {
+        Ok(Statement::CreateSchema(CreateSchemaStatement {
             schema_name,
             or_replace,
             if_not_exists,
@@ -5700,7 +5706,7 @@
             options,
             default_collate_spec,
             clone,
-        })
+        }))
     }
 
     fn parse_schema_name(&mut self) -> Result<SchemaName, ParserError> {
@@ -5769,7 +5775,7 @@
             }
         }
 
-        Ok(Statement::CreateDatabase {
+        Ok(Statement::CreateDatabase(CreateDatabaseStatement {
             db_name,
             if_not_exists: ine,
             location,
@@ -5792,7 +5798,7 @@
             catalog_sync_namespace_flatten_delimiter: None,
             with_tags: None,
             with_contacts: None,
-        })
+        }))
     }
 
     /// Parse an optional `USING` clause for `CREATE FUNCTION`.
@@ -6599,7 +6605,7 @@
             self.expect_token(&Token::RParen)?;
             self.expect_keyword_is(Keyword::AS)?;
 
-            Ok(Statement::CreateMacro {
+            Ok(Statement::CreateMacro(CreateMacroStatement {
                 or_replace,
                 temporary,
                 name,
@@ -6609,7 +6615,7 @@
                 } else {
                     MacroDefinition::Expr(self.parse_expr()?)
                 },
-            })
+            }))
         } else {
             self.prev_token();
             self.expected_ref("an object type after CREATE", self.peek_token_ref())
@@ -7690,7 +7696,7 @@
         } else {
             None
         };
-        Ok(Statement::Drop {
+        Ok(Statement::Drop(DropStatement {
             object_type,
             if_exists,
             names,
@@ -7699,7 +7705,7 @@
             purge,
             temporary,
             table,
-        })
+        }))
     }
 
     fn parse_optional_drop_behavior(&mut self) -> Option<DropBehavior> {
@@ -7751,7 +7757,10 @@
     fn parse_drop_connector(&mut self) -> Result<Statement, ParserError> {
         let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
         let name = self.parse_identifier()?;
-        Ok(Statement::DropConnector { if_exists, name })
+        Ok(Statement::DropConnector(DropConnectorStatement {
+            if_exists,
+            name,
+        }))
     }
 
     /// ```sql
@@ -7776,11 +7785,11 @@
         let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]);
         let proc_desc = self.parse_comma_separated(Parser::parse_function_desc)?;
         let drop_behavior = self.parse_optional_drop_behavior();
-        Ok(Statement::DropProcedure {
+        Ok(Statement::DropProcedure(DropProcedureStatement {
             if_exists,
             proc_desc,
             drop_behavior,
-        })
+        }))
     }
 
     fn parse_function_desc(&mut self) -> Result<FunctionDesc, ParserError> {
@@ -7821,12 +7830,12 @@
             _ => self.expected_ref("TEMPORARY or PERSISTENT", self.peek_token_ref())?,
         };
 
-        Ok(Statement::DropSecret {
+        Ok(Statement::DropSecret(DropSecretStatement {
             if_exists,
             temporary: temp,
             name,
             storage_specifier,
-        })
+        }))
     }
 
     /// Parse a `DECLARE` statement.
@@ -7889,7 +7898,7 @@
 
         let query = Some(self.parse_query()?);
 
-        Ok(Statement::Declare {
+        Ok(Statement::Declare(DeclareStatement {
             stmts: vec![Declare {
                 names: vec![name],
                 data_type: None,
@@ -7901,7 +7910,7 @@
                 hold,
                 for_query: query,
             }],
-        })
+        }))
     }
 
     /// Parse a [BigQuery] `DECLARE` statement.
@@ -7932,7 +7941,7 @@
             Some(self.parse_expr()?)
         };
 
-        Ok(Statement::Declare {
+        Ok(Statement::Declare(DeclareStatement {
             stmts: vec![Declare {
                 names,
                 data_type,
@@ -7944,7 +7953,7 @@
                 hold: None,
                 for_query: None,
             }],
-        })
+        }))
     }
 
     /// Parse a [Snowflake] `DECLARE` statement.
@@ -8060,7 +8069,7 @@
             break;
         }
 
-        Ok(Statement::Declare { stmts })
+        Ok(Statement::Declare(DeclareStatement { stmts }))
     }
 
     /// Parse a [MsSql] `DECLARE` statement.
@@ -8077,7 +8086,7 @@
     pub fn parse_mssql_declare(&mut self) -> Result<Statement, ParserError> {
         let stmts = self.parse_comma_separated(Parser::parse_mssql_declare_stmt)?;
 
-        Ok(Statement::Declare { stmts })
+        Ok(Statement::Declare(DeclareStatement { stmts }))
     }
 
     /// Parse the body of a [MsSql] `DECLARE`statement.
@@ -8251,12 +8260,12 @@
             None
         };
 
-        Ok(Statement::Fetch {
+        Ok(Statement::Fetch(FetchStatement {
             name,
             direction,
             position,
             into,
-        })
+        }))
     }
 
     /// Parse a `DISCARD` statement.
@@ -8275,7 +8284,7 @@
                 self.peek_token_ref(),
             );
         };
-        Ok(Statement::Discard { object_type })
+        Ok(Statement::Discard(DiscardStatement { object_type }))
     }
 
     /// Parse a `CREATE INDEX` statement.
@@ -11224,10 +11233,10 @@
                     return self.expected_ref("RENAME after ALTER INDEX", self.peek_token_ref());
                 };
 
-                Ok(Statement::AlterIndex {
+                Ok(Statement::AlterIndex(AlterIndexStatement {
                     name: index_name,
                     operation,
-                })
+                }))
             }
             Keyword::FUNCTION => self.parse_alter_function(AlterFunctionKind::Function),
             Keyword::AGGREGATE => self.parse_alter_function(AlterFunctionKind::Aggregate),
@@ -11529,12 +11538,12 @@
         self.expect_keyword_is(Keyword::AS)?;
         let query = self.parse_query()?;
 
-        Ok(Statement::AlterView {
+        Ok(Statement::AlterView(AlterViewStatement {
             name,
             columns,
             query,
             with_options,
-        })
+        }))
     }
 
     /// Parse a [Statement::AlterType]
@@ -12044,14 +12053,14 @@
             } else {
                 vec![]
             };
-        Ok(Statement::Copy {
+        Ok(Statement::Copy(CopyStatement {
             source,
             to,
             target,
             options,
             legacy_options,
             values,
-        })
+        }))
     }
 
     /// Parse [Statement::Open]
@@ -12072,7 +12081,7 @@
             CloseCursor::Specific { name }
         };
 
-        Ok(Statement::Close { cursor })
+        Ok(Statement::Close(CloseStatement { cursor }))
     }
 
     fn parse_copy_option(&mut self) -> Result<CopyOption, ParserError> {
@@ -14480,7 +14489,7 @@
             _ => None,
         };
 
-        Ok(Statement::Kill { modifier, id })
+        Ok(Statement::Kill(KillStatement { modifier, id }))
     }
 
     /// Parse an `EXPLAIN` statement, handling dialect-specific options and modifiers.
@@ -14515,10 +14524,11 @@
         }
 
         match self.maybe_parse(|parser| parser.parse_statement())? {
-            Some(Statement::Explain { .. }) | Some(Statement::ExplainTable { .. }) => Err(
+            Some(Statement::Explain(ExplainStatement { .. }))
+            | Some(Statement::ExplainTable(ExplainTableStatement { .. })) => Err(
                 ParserError::ParserError("Explain must be root of the plan".to_string()),
             ),
-            Some(statement) => Ok(Statement::Explain {
+            Some(statement) => Ok(Statement::Explain(ExplainStatement {
                 describe_alias,
                 analyze,
                 verbose,
@@ -14527,7 +14537,7 @@
                 statement: Box::new(statement),
                 format,
                 options,
-            }),
+            })),
             _ => {
                 let hive_format =
                     match self.parse_one_of_keywords(&[Keyword::EXTENDED, Keyword::FORMATTED]) {
@@ -14544,12 +14554,12 @@
                 };
 
                 let table_name = self.parse_object_name(false)?;
-                Ok(Statement::ExplainTable {
+                Ok(Statement::ExplainTable(ExplainTableStatement {
                     describe_alias,
                     hive_format,
                     has_table_keyword,
                     table_name,
-                })
+                }))
             }
         }
     }
@@ -16005,7 +16015,9 @@
         } else if self.parse_keyword(Keyword::FUNCTIONS) {
             Ok(self.parse_show_functions()?)
         } else if self.parse_keyword(Keyword::PROCESSLIST) {
-            Ok(Statement::ShowProcessList { full })
+            Ok(Statement::ShowProcessList(ShowProcessListStatement {
+                full,
+            }))
         } else if extended || full {
             Err(ParserError::ParserError(
                 "EXTENDED/FULL are not supported with this type of SHOW query".to_string(),
@@ -16017,19 +16029,19 @@
         } else if self.parse_keyword(Keyword::VARIABLES)
             && dialect_of!(self is MySqlDialect | GenericDialect)
         {
-            Ok(Statement::ShowVariables {
+            Ok(Statement::ShowVariables(ShowVariablesStatement {
                 filter: self.parse_show_statement_filter()?,
                 session,
                 global,
-            })
+            }))
         } else if self.parse_keyword(Keyword::STATUS)
             && dialect_of!(self is MySqlDialect | GenericDialect)
         {
-            Ok(Statement::ShowStatus {
+            Ok(Statement::ShowStatus(ShowStatusStatement {
                 filter: self.parse_show_statement_filter()?,
                 session,
                 global,
-            })
+            }))
         } else if self.parse_keyword(Keyword::CATALOGS) {
             self.parse_show_catalogs(terse)
         } else if self.parse_keyword(Keyword::DATABASES) {
@@ -16041,9 +16053,9 @@
         } else if self.parse_keyword(Keyword::CHARSET) {
             self.parse_show_charset(true)
         } else {
-            Ok(Statement::ShowVariable {
+            Ok(Statement::ShowVariable(ShowVariableStatement {
                 variable: self.parse_identifiers()?,
-            })
+            }))
         }
     }
 
@@ -16058,31 +16070,31 @@
     fn parse_show_catalogs(&mut self, terse: bool) -> Result<Statement, ParserError> {
         let history = self.parse_keyword(Keyword::HISTORY);
         let show_options = self.parse_show_stmt_options()?;
-        Ok(Statement::ShowCatalogs {
+        Ok(Statement::ShowCatalogs(ShowCatalogsStatement {
             terse,
             history,
             show_options,
-        })
+        }))
     }
 
     fn parse_show_databases(&mut self, terse: bool) -> Result<Statement, ParserError> {
         let history = self.parse_keyword(Keyword::HISTORY);
         let show_options = self.parse_show_stmt_options()?;
-        Ok(Statement::ShowDatabases {
+        Ok(Statement::ShowDatabases(ShowDatabasesStatement {
             terse,
             history,
             show_options,
-        })
+        }))
     }
 
     fn parse_show_schemas(&mut self, terse: bool) -> Result<Statement, ParserError> {
         let history = self.parse_keyword(Keyword::HISTORY);
         let show_options = self.parse_show_stmt_options()?;
-        Ok(Statement::ShowSchemas {
+        Ok(Statement::ShowSchemas(ShowSchemasStatement {
             terse,
             history,
             show_options,
-        })
+        }))
     }
 
     /// Parse `SHOW CREATE <object>` returning the corresponding `ShowCreate` statement.
@@ -16108,7 +16120,10 @@
 
         let obj_name = self.parse_object_name(false)?;
 
-        Ok(Statement::ShowCreate { obj_type, obj_name })
+        Ok(Statement::ShowCreate(ShowCreateStatement {
+            obj_type,
+            obj_name,
+        }))
     }
 
     /// Parse `SHOW COLUMNS`/`SHOW FIELDS` and return a `ShowColumns` statement.
@@ -16118,11 +16133,11 @@
         full: bool,
     ) -> Result<Statement, ParserError> {
         let show_options = self.parse_show_stmt_options()?;
-        Ok(Statement::ShowColumns {
+        Ok(Statement::ShowColumns(ShowColumnsStatement {
             extended,
             full,
             show_options,
-        })
+        }))
     }
 
     fn parse_show_tables(
@@ -16134,14 +16149,14 @@
     ) -> Result<Statement, ParserError> {
         let history = !external && self.parse_keyword(Keyword::HISTORY);
         let show_options = self.parse_show_stmt_options()?;
-        Ok(Statement::ShowTables {
+        Ok(Statement::ShowTables(ShowTablesStatement {
             terse,
             history,
             extended,
             full,
             external,
             show_options,
-        })
+        }))
     }
 
     fn parse_show_views(
@@ -16150,23 +16165,23 @@
         materialized: bool,
     ) -> Result<Statement, ParserError> {
         let show_options = self.parse_show_stmt_options()?;
-        Ok(Statement::ShowViews {
+        Ok(Statement::ShowViews(ShowViewsStatement {
             materialized,
             terse,
             show_options,
-        })
+        }))
     }
 
     /// Parse `SHOW FUNCTIONS` and optional filter.
     pub fn parse_show_functions(&mut self) -> Result<Statement, ParserError> {
         let filter = self.parse_show_statement_filter()?;
-        Ok(Statement::ShowFunctions { filter })
+        Ok(Statement::ShowFunctions(ShowFunctionsStatement { filter }))
     }
 
     /// Parse `SHOW COLLATION` and optional filter.
     pub fn parse_show_collation(&mut self) -> Result<Statement, ParserError> {
         let filter = self.parse_show_statement_filter()?;
-        Ok(Statement::ShowCollation { filter })
+        Ok(Statement::ShowCollation(ShowCollationStatement { filter }))
     }
 
     /// Parse an optional filter used by `SHOW` statements (LIKE, ILIKE, WHERE, or literal).
@@ -18459,13 +18474,13 @@
                 None
             };
             let source = self.parse_query()?;
-            Ok(Statement::Directory {
+            Ok(Statement::Directory(DirectoryStatement {
                 local,
                 path,
                 overwrite,
                 file_format,
                 source,
-            })
+            }))
         } else {
             // Hive lets you put table here regardless
             let table = self.parse_keyword(Keyword::TABLE);
@@ -19760,7 +19775,7 @@
     /// Parse a 'START TRANSACTION' statement
     pub fn parse_start_transaction(&mut self) -> Result<Statement, ParserError> {
         self.expect_keyword_is(Keyword::TRANSACTION)?;
-        Ok(Statement::StartTransaction {
+        Ok(Statement::StartTransaction(StartTransactionStatement {
             modes: self.parse_transaction_modes()?,
             begin: false,
             transaction: Some(BeginTransactionKind::Transaction),
@@ -19768,7 +19783,7 @@
             statements: vec![],
             exception: None,
             has_end_keyword: false,
-        })
+        }))
     }
 
     /// Parse a transaction modifier keyword that can follow a `BEGIN` statement.
@@ -19801,7 +19816,7 @@
                 Some(Keyword::TRAN) => Some(BeginTransactionKind::Tran),
                 _ => None,
             };
-        Ok(Statement::StartTransaction {
+        Ok(Statement::StartTransaction(StartTransactionStatement {
             modes: self.parse_transaction_modes()?,
             begin: true,
             transaction,
@@ -19809,7 +19824,7 @@
             statements: vec![],
             exception: None,
             has_end_keyword: false,
-        })
+        }))
     }
 
     /// Parse a 'BEGIN ... EXCEPTION ... END' block
@@ -19847,7 +19862,7 @@
 
         self.expect_keyword(Keyword::END)?;
 
-        Ok(Statement::StartTransaction {
+        Ok(Statement::StartTransaction(StartTransactionStatement {
             begin: true,
             statements,
             exception,
@@ -19855,7 +19870,7 @@
             transaction: None,
             modifier: None,
             modes: Default::default(),
-        })
+        }))
     }
 
     /// Parse an 'END' statement
@@ -19869,11 +19884,11 @@
         } else {
             None
         };
-        Ok(Statement::Commit {
+        Ok(Statement::Commit(CommitStatement {
             chain: self.parse_commit_rollback_chain()?,
             end: true,
             modifier,
-        })
+        }))
     }
 
     /// Parse a list of transaction modes
@@ -19917,11 +19932,11 @@
 
     /// Parse a 'COMMIT' statement
     pub fn parse_commit(&mut self) -> Result<Statement, ParserError> {
-        Ok(Statement::Commit {
+        Ok(Statement::Commit(CommitStatement {
             chain: self.parse_commit_rollback_chain()?,
             end: false,
             modifier: None,
-        })
+        }))
     }
 
     /// Parse a 'ROLLBACK' statement
@@ -19929,7 +19944,7 @@
         let chain = self.parse_commit_rollback_chain()?;
         let savepoint = self.parse_rollback_savepoint()?;
 
-        Ok(Statement::Rollback { chain, savepoint })
+        Ok(Statement::Rollback(RollbackStatement { chain, savepoint }))
     }
 
     /// Parse an 'ABORT' statement
@@ -19940,10 +19955,10 @@
     pub fn parse_abort(&mut self) -> Result<Statement, ParserError> {
         let chain = self.parse_commit_rollback_chain()?;
 
-        Ok(Statement::Rollback {
+        Ok(Statement::Rollback(RollbackStatement {
             chain,
             savepoint: None,
-        })
+        }))
     }
 
     /// Parse an optional `AND [NO] CHAIN` clause for `COMMIT` and `ROLLBACK` statements
@@ -19989,13 +20004,13 @@
         } else {
             vec![]
         };
-        Ok(Statement::RaisError {
+        Ok(Statement::RaisError(RaisErrorStatement {
             message,
             severity,
             state,
             arguments,
             options,
-        })
+        }))
     }
 
     /// Parse a single `RAISERROR` option
@@ -20039,7 +20054,7 @@
     pub fn parse_deallocate(&mut self) -> Result<Statement, ParserError> {
         let prepare = self.parse_keyword(Keyword::PREPARE);
         let name = self.parse_identifier()?;
-        Ok(Statement::Deallocate { name, prepare })
+        Ok(Statement::Deallocate(DeallocateStatement { name, prepare }))
     }
 
     /// Parse a SQL `EXECUTE` statement
@@ -20090,7 +20105,7 @@
 
         let default = self.parse_keyword(Keyword::DEFAULT);
 
-        Ok(Statement::Execute {
+        Ok(Statement::Execute(ExecuteStatement {
             immediate,
             name,
             parameters,
@@ -20099,7 +20114,7 @@
             using,
             output,
             default,
-        })
+        }))
     }
 
     /// Parse a SQL `PREPARE` statement
@@ -20114,11 +20129,11 @@
 
         self.expect_keyword_is(Keyword::AS)?;
         let statement = Box::new(self.parse_statement()?);
-        Ok(Statement::Prepare {
+        Ok(Statement::Prepare(PrepareStatement {
             name,
             data_types,
             statement,
-        })
+        }))
     }
 
     /// Parse a SQL `UNLOAD` statement
@@ -20145,14 +20160,14 @@
         while let Some(opt) = self.maybe_parse(|parser| parser.parse_copy_legacy_option())? {
             options.push(opt);
         }
-        Ok(Statement::Unload {
+        Ok(Statement::Unload(UnloadStatement {
             query,
             query_text,
             to,
             auth,
             with,
             options,
-        })
+        }))
     }
 
     fn parse_select_into(&mut self) -> Result<SelectInto, ParserError> {
@@ -20191,23 +20206,23 @@
         if self.consume_token(&Token::LParen) {
             let value = self.parse_pragma_value()?;
             self.expect_token(&Token::RParen)?;
-            Ok(Statement::Pragma {
+            Ok(Statement::Pragma(PragmaStatement {
                 name,
                 value: Some(value),
                 is_eq: false,
-            })
+            }))
         } else if self.consume_token(&Token::Eq) {
-            Ok(Statement::Pragma {
+            Ok(Statement::Pragma(PragmaStatement {
                 name,
                 value: Some(self.parse_pragma_value()?),
                 is_eq: true,
-            })
+            }))
         } else {
-            Ok(Statement::Pragma {
+            Ok(Statement::Pragma(PragmaStatement {
                 name,
                 value: None,
                 is_eq: false,
-            })
+            }))
         }
     }
 
@@ -20215,14 +20230,14 @@
     pub fn parse_install(&mut self) -> Result<Statement, ParserError> {
         let extension_name = self.parse_identifier()?;
 
-        Ok(Statement::Install { extension_name })
+        Ok(Statement::Install(InstallStatement { extension_name }))
     }
 
     /// Parse a SQL LOAD statement
     pub fn parse_load(&mut self) -> Result<Statement, ParserError> {
         if self.dialect.supports_load_extension() {
             let extension_name = self.parse_identifier()?;
-            Ok(Statement::Load { extension_name })
+            Ok(Statement::Load(LoadStatement { extension_name }))
         } else if self.parse_keyword(Keyword::DATA) && self.dialect.supports_load_data() {
             let local = self.parse_one_of_keywords(&[Keyword::LOCAL]).is_some();
             self.expect_keyword_is(Keyword::INPATH)?;
@@ -20233,14 +20248,14 @@
             let table_name = self.parse_object_name(false)?;
             let partitioned = self.parse_insert_partition()?;
             let table_format = self.parse_load_data_table_format()?;
-            Ok(Statement::LoadData {
+            Ok(Statement::LoadData(LoadDataStatement {
                 local,
                 inpath,
                 overwrite,
                 table_name,
                 partitioned,
                 table_format,
-            })
+            }))
         } else {
             self.expected_ref(
                 "`DATA` or an extension name after `LOAD`",
@@ -20306,7 +20321,7 @@
             None
         };
 
-        Ok(Statement::OptimizeTable {
+        Ok(Statement::OptimizeTable(OptimizeTableStatement {
             name,
             has_table_keyword,
             on_cluster,
@@ -20315,7 +20330,7 @@
             deduplicate,
             predicate,
             zorder,
-        })
+        }))
     }
 
     /// ```sql
@@ -20344,14 +20359,14 @@
         } else {
             None
         };
-        Ok(Statement::CreateSequence {
+        Ok(Statement::CreateSequence(CreateSequenceStatement {
             temporary,
             if_not_exists,
             name,
             data_type,
             sequence_options,
             owned_by,
-        })
+        }))
     }
 
     fn parse_create_sequence_options(&mut self) -> Result<Vec<SequenceOptions>, ParserError> {
@@ -20478,13 +20493,13 @@
 
         let body = self.parse_conditional_statements(&[Keyword::END])?;
 
-        Ok(Statement::CreateProcedure {
+        Ok(Statement::CreateProcedure(CreateProcedureStatement {
             name,
             or_alter,
             params,
             language,
             body,
-        })
+        }))
     }
 
     /// Parse a window specification.
@@ -20535,17 +20550,17 @@
                 // CREATE TYPE name (options) - SQL definition without AS
                 let options = self.parse_create_type_sql_definition_options()?;
                 self.expect_token(&Token::RParen)?;
-                return Ok(Statement::CreateType {
+                return Ok(Statement::CreateType(CreateTypeStatement {
                     name,
                     representation: Some(UserDefinedTypeRepresentation::SqlDefinition { options }),
-                });
+                }));
             }
 
             // CREATE TYPE name; - no representation
-            return Ok(Statement::CreateType {
+            return Ok(Statement::CreateType(CreateTypeStatement {
                 name,
                 representation: None,
-            });
+            }));
         }
 
         // We have AS keyword
@@ -20569,12 +20584,12 @@
     fn parse_create_type_composite(&mut self, name: ObjectName) -> Result<Statement, ParserError> {
         if self.consume_token(&Token::RParen) {
             // Empty composite type
-            return Ok(Statement::CreateType {
+            return Ok(Statement::CreateType(CreateTypeStatement {
                 name,
                 representation: Some(UserDefinedTypeRepresentation::Composite {
                     attributes: vec![],
                 }),
-            });
+            }));
         }
 
         let mut attributes = vec![];
@@ -20598,10 +20613,10 @@
         }
         self.expect_token(&Token::RParen)?;
 
-        Ok(Statement::CreateType {
+        Ok(Statement::CreateType(CreateTypeStatement {
             name,
             representation: Some(UserDefinedTypeRepresentation::Composite { attributes }),
-        })
+        }))
     }
 
     /// Parse remainder of `CREATE TYPE AS ENUM` statement (see [Statement::CreateType] and [Self::parse_create_type])
@@ -20612,10 +20627,10 @@
         let labels = self.parse_comma_separated0(|p| p.parse_identifier(), Token::RParen)?;
         self.expect_token(&Token::RParen)?;
 
-        Ok(Statement::CreateType {
+        Ok(Statement::CreateType(CreateTypeStatement {
             name,
             representation: Some(UserDefinedTypeRepresentation::Enum { labels }),
-        })
+        }))
     }
 
     /// Parse remainder of `CREATE TYPE AS RANGE` statement
@@ -20626,10 +20641,10 @@
         let options = self.parse_comma_separated0(|p| p.parse_range_option(), Token::RParen)?;
         self.expect_token(&Token::RParen)?;
 
-        Ok(Statement::CreateType {
+        Ok(Statement::CreateType(CreateTypeStatement {
             name,
             representation: Some(UserDefinedTypeRepresentation::Range { options }),
-        })
+        }))
     }
 
     /// Parse a single range option for a `CREATE TYPE AS RANGE` statement
diff --git a/tests/sqlparser_bigquery.rs b/tests/sqlparser_bigquery.rs
index d6ae192..4d9b02b 100644
--- a/tests/sqlparser_bigquery.rs
+++ b/tests/sqlparser_bigquery.rs
@@ -264,12 +264,12 @@
 #[test]
 fn parse_begin() {
     let sql = r#"BEGIN SELECT 1; EXCEPTION WHEN ERROR THEN SELECT 2; RAISE USING MESSAGE = FORMAT('ERR: %s', 'Bad'); END"#;
-    let Statement::StartTransaction {
+    let Statement::StartTransaction(StartTransactionStatement {
         statements,
         exception,
         has_end_keyword,
         ..
-    } = bigquery().verified_stmt(sql)
+    }) = bigquery().verified_stmt(sql)
     else {
         unreachable!();
     };
@@ -2174,7 +2174,7 @@
         ),
     ] {
         match bigquery().verified_stmt(sql) {
-            Statement::Declare { mut stmts } => {
+            Statement::Declare(DeclareStatement { mut stmts }) => {
                 assert_eq!(1, stmts.len());
                 let Declare {
                     names,
diff --git a/tests/sqlparser_clickhouse.rs b/tests/sqlparser_clickhouse.rs
index 2d55ae0..f646dad 100644
--- a/tests/sqlparser_clickhouse.rs
+++ b/tests/sqlparser_clickhouse.rs
@@ -147,10 +147,10 @@
     let stmt = clickhouse().verified_stmt("KILL MUTATION 5");
     assert_eq!(
         stmt,
-        Statement::Kill {
+        Statement::Kill(KillStatement {
             modifier: Some(KillType::Mutation),
             id: 5,
-        }
+        })
     );
 }
 
@@ -546,14 +546,14 @@
     match clickhouse_and_generic().verified_stmt(
         "OPTIMIZE TABLE t0 ON CLUSTER cluster PARTITION ID '2024-07' FINAL DEDUPLICATE BY id",
     ) {
-        Statement::OptimizeTable {
+        Statement::OptimizeTable(OptimizeTableStatement {
             name,
             on_cluster,
             partition,
             include_final,
             deduplicate,
             ..
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "t0");
             assert_eq!(on_cluster, Some(Ident::new("cluster")));
             assert_eq!(
@@ -1752,12 +1752,12 @@
 #[test]
 fn parse_explain_table() {
     match clickhouse().verified_stmt("EXPLAIN TABLE test_identifier") {
-        Statement::ExplainTable {
+        Statement::ExplainTable(ExplainTableStatement {
             describe_alias,
             hive_format,
             has_table_keyword,
             table_name,
-        } => {
+        }) => {
             pretty_assertions::assert_eq!(describe_alias, DescribeAlias::Explain);
             pretty_assertions::assert_eq!(hive_format, None);
             pretty_assertions::assert_eq!(has_table_keyword, true);
diff --git a/tests/sqlparser_common.rs b/tests/sqlparser_common.rs
index 7dbcc91..d119e2d 100644
--- a/tests/sqlparser_common.rs
+++ b/tests/sqlparser_common.rs
@@ -4701,10 +4701,10 @@
     let sql = "ASSERT (SELECT COUNT(*) FROM my_table) > 0";
     let ast = one_statement_parses_to(sql, "ASSERT (SELECT COUNT(*) FROM my_table) > 0");
     match ast {
-        Statement::Assert {
+        Statement::Assert(AssertStatement {
             condition: _condition,
             message,
-        } => {
+        }) => {
             assert_eq!(message, None);
         }
         _ => unreachable!(),
@@ -4720,10 +4720,10 @@
         "ASSERT (SELECT COUNT(*) FROM my_table) > 0 AS 'No rows in my_table'",
     );
     match ast {
-        Statement::Assert {
+        Statement::Assert(AssertStatement {
             condition: _condition,
             message: Some(message),
-        } => {
+        }) => {
             match message {
                 Expr::Value(ValueWithSpan {
                     value: Value::SingleQuotedString(s),
@@ -4741,7 +4741,7 @@
     let sql = "CREATE SCHEMA X";
 
     match verified_stmt(sql) {
-        Statement::CreateSchema { schema_name, .. } => {
+        Statement::CreateSchema(CreateSchemaStatement { schema_name, .. }) => {
             assert_eq!(schema_name.to_string(), "X".to_owned())
         }
         _ => unreachable!(),
@@ -4760,12 +4760,12 @@
 #[test]
 fn parse_create_or_replace_schema() {
     match verified_stmt("CREATE OR REPLACE SCHEMA X") {
-        Statement::CreateSchema {
+        Statement::CreateSchema(CreateSchemaStatement {
             schema_name,
             or_replace,
             if_not_exists,
             ..
-        } => {
+        }) => {
             assert_eq!(schema_name.to_string(), "X".to_owned());
             assert!(or_replace);
             assert!(!if_not_exists);
@@ -4781,7 +4781,7 @@
     let sql = "CREATE SCHEMA AUTHORIZATION Y";
 
     match verified_stmt(sql) {
-        Statement::CreateSchema { schema_name, .. } => {
+        Statement::CreateSchema(CreateSchemaStatement { schema_name, .. }) => {
             assert_eq!(schema_name.to_string(), "AUTHORIZATION Y".to_owned())
         }
         _ => unreachable!(),
@@ -4793,7 +4793,7 @@
     let sql = "CREATE SCHEMA X AUTHORIZATION Y";
 
     match verified_stmt(sql) {
-        Statement::CreateSchema { schema_name, .. } => {
+        Statement::CreateSchema(CreateSchemaStatement { schema_name, .. }) => {
             assert_eq!(schema_name.to_string(), "X AUTHORIZATION Y".to_owned())
         }
         _ => unreachable!(),
@@ -4805,7 +4805,9 @@
     let sql = "DROP SCHEMA X";
 
     match verified_stmt(sql) {
-        Statement::Drop { object_type, .. } => assert_eq!(object_type, ObjectType::Schema),
+        Statement::Drop(DropStatement { object_type, .. }) => {
+            assert_eq!(object_type, ObjectType::Schema)
+        }
         _ => unreachable!(),
     }
 }
@@ -5355,10 +5357,10 @@
 fn parse_alter_index() {
     let rename_index = "ALTER INDEX idx RENAME TO new_idx";
     match verified_stmt(rename_index) {
-        Statement::AlterIndex {
+        Statement::AlterIndex(AlterIndexStatement {
             name,
             operation: AlterIndexOperation::RenameIndex { index_name },
-        } => {
+        }) => {
             assert_eq!("idx", name.to_string());
             assert_eq!("new_idx", index_name.to_string())
         }
@@ -5370,12 +5372,12 @@
 fn parse_alter_view() {
     let sql = "ALTER VIEW myschema.myview AS SELECT foo FROM bar";
     match verified_stmt(sql) {
-        Statement::AlterView {
+        Statement::AlterView(AlterViewStatement {
             name,
             columns,
             query,
             with_options,
-        } => {
+        }) => {
             assert_eq!("myschema.myview", name.to_string());
             assert_eq!(Vec::<Ident>::new(), columns);
             assert_eq!("SELECT foo FROM bar", query.to_string());
@@ -5389,7 +5391,7 @@
 fn parse_alter_view_with_options() {
     let sql = "ALTER VIEW v WITH (foo = 'bar', a = 123) AS SELECT 1";
     match verified_stmt(sql) {
-        Statement::AlterView { with_options, .. } => {
+        Statement::AlterView(AlterViewStatement { with_options, .. }) => {
             assert_eq!(
                 vec![
                     SqlOption::KeyValue {
@@ -5414,12 +5416,12 @@
 fn parse_alter_view_with_columns() {
     let sql = "ALTER VIEW v (has, cols) AS SELECT 1, 2";
     match verified_stmt(sql) {
-        Statement::AlterView {
+        Statement::AlterView(AlterViewStatement {
             name,
             columns,
             query,
             with_options,
-        } => {
+        }) => {
             assert_eq!("v", name.to_string());
             assert_eq!(columns, vec![Ident::new("has"), Ident::new("cols")]);
             assert_eq!("SELECT 1, 2", query.to_string());
@@ -5696,7 +5698,7 @@
     expected_options: Option<Vec<UtilityOption>>,
 ) {
     match dialect.verified_stmt(query) {
-        Statement::Explain {
+        Statement::Explain(ExplainStatement {
             describe_alias: _,
             analyze,
             verbose,
@@ -5705,7 +5707,7 @@
             statement,
             format,
             options,
-        } => {
+        }) => {
             assert_eq!(verbose, expected_verbose);
             assert_eq!(analyze, expected_analyze);
             assert_eq!(format, expected_format);
@@ -5723,12 +5725,12 @@
     let validate_explain =
         |query: &str, expected_describe_alias: DescribeAlias, expected_table_keyword| {
             match verified_stmt(query) {
-                Statement::ExplainTable {
+                Statement::ExplainTable(ExplainTableStatement {
                     describe_alias,
                     hive_format,
                     has_table_keyword,
                     table_name,
-                } => {
+                }) => {
                     assert_eq!(describe_alias, expected_describe_alias);
                     assert_eq!(hive_format, None);
                     assert_eq!(has_table_keyword, expected_table_keyword);
@@ -5874,13 +5876,13 @@
 #[test]
 fn parse_explain_query_plan() {
     match all_dialects().verified_stmt("EXPLAIN QUERY PLAN SELECT sqrt(id) FROM foo") {
-        Statement::Explain {
+        Statement::Explain(ExplainStatement {
             query_plan,
             analyze,
             verbose,
             statement,
             ..
-        } => {
+        }) => {
             assert!(query_plan);
             assert!(!analyze);
             assert!(!verbose);
@@ -5906,14 +5908,14 @@
     let statement = all_dialects().verified_stmt("EXPLAIN ESTIMATE SELECT sqrt(id) FROM foo");
 
     match &statement {
-        Statement::Explain {
+        Statement::Explain(ExplainStatement {
             query_plan,
             estimate,
             analyze,
             verbose,
             statement,
             ..
-        } => {
+        }) => {
             assert!(estimate);
             assert!(!query_plan);
             assert!(!analyze);
@@ -8587,14 +8589,14 @@
 fn parse_create_database() {
     let sql = "CREATE DATABASE mydb";
     match verified_stmt(sql) {
-        Statement::CreateDatabase {
+        Statement::CreateDatabase(CreateDatabaseStatement {
             db_name,
             if_not_exists,
             location,
             managed_location,
             clone,
             ..
-        } => {
+        }) => {
             assert_eq!("mydb", db_name.to_string());
             assert!(!if_not_exists);
             assert_eq!(None, location);
@@ -8605,14 +8607,14 @@
     }
     let sql = "CREATE DATABASE mydb CLONE otherdb";
     match verified_stmt(sql) {
-        Statement::CreateDatabase {
+        Statement::CreateDatabase(CreateDatabaseStatement {
             db_name,
             if_not_exists,
             location,
             managed_location,
             clone,
             ..
-        } => {
+        }) => {
             assert_eq!("mydb", db_name.to_string());
             assert!(!if_not_exists);
             assert_eq!(None, location);
@@ -8630,14 +8632,14 @@
 fn parse_create_database_ine() {
     let sql = "CREATE DATABASE IF NOT EXISTS mydb";
     match verified_stmt(sql) {
-        Statement::CreateDatabase {
+        Statement::CreateDatabase(CreateDatabaseStatement {
             db_name,
             if_not_exists,
             location,
             managed_location,
             clone,
             ..
-        } => {
+        }) => {
             assert_eq!("mydb", db_name.to_string());
             assert!(if_not_exists);
             assert_eq!(None, location);
@@ -8652,12 +8654,12 @@
 fn parse_drop_database() {
     let sql = "DROP DATABASE mycatalog.mydb";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names,
             object_type,
             if_exists,
             ..
-        } => {
+        }) => {
             assert_eq!(
                 vec!["mycatalog.mydb"],
                 names.iter().map(ToString::to_string).collect::<Vec<_>>()
@@ -8673,11 +8675,11 @@
 fn parse_drop_database_if_exists() {
     let sql = "DROP DATABASE IF EXISTS mydb";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             object_type,
             if_exists,
             ..
-        } => {
+        }) => {
             assert_eq!(ObjectType::Database, object_type);
             assert!(if_exists);
         }
@@ -9022,7 +9024,7 @@
 fn parse_drop_table() {
     let sql = "DROP TABLE foo";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             object_type,
             if_exists,
             names,
@@ -9030,7 +9032,7 @@
             purge: _,
             temporary,
             ..
-        } => {
+        }) => {
             assert!(!if_exists);
             assert_eq!(ObjectType::Table, object_type);
             assert_eq!(
@@ -9045,7 +9047,7 @@
 
     let sql = "DROP TABLE IF EXISTS foo, bar CASCADE";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             object_type,
             if_exists,
             names,
@@ -9053,7 +9055,7 @@
             purge: _,
             temporary,
             ..
-        } => {
+        }) => {
             assert!(if_exists);
             assert_eq!(ObjectType::Table, object_type);
             assert_eq!(
@@ -9083,9 +9085,9 @@
 fn parse_drop_view() {
     let sql = "DROP VIEW myschema.myview";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names, object_type, ..
-        } => {
+        }) => {
             assert_eq!(
                 vec!["myschema.myview"],
                 names.iter().map(ToString::to_string).collect::<Vec<_>>()
@@ -9103,9 +9105,9 @@
 fn parse_drop_user() {
     let sql = "DROP USER u1";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names, object_type, ..
-        } => {
+        }) => {
             assert_eq!(
                 vec!["u1"],
                 names.iter().map(ToString::to_string).collect::<Vec<_>>()
@@ -9447,7 +9449,7 @@
     match dialects
         .verified_stmt("START TRANSACTION READ ONLY, READ WRITE, ISOLATION LEVEL SERIALIZABLE")
     {
-        Statement::StartTransaction { modes, .. } => assert_eq!(
+        Statement::StartTransaction(StartTransactionStatement { modes, .. }) => assert_eq!(
             modes,
             vec![
                 TransactionMode::AccessMode(TransactionAccessMode::ReadOnly),
@@ -9464,7 +9466,7 @@
         "START TRANSACTION READ ONLY READ WRITE ISOLATION LEVEL SERIALIZABLE",
         "START TRANSACTION READ ONLY, READ WRITE, ISOLATION LEVEL SERIALIZABLE",
     ) {
-        Statement::StartTransaction { modes, .. } => assert_eq!(
+        Statement::StartTransaction(StartTransactionStatement { modes, .. }) => assert_eq!(
             modes,
             vec![
                 TransactionMode::AccessMode(TransactionAccessMode::ReadOnly),
@@ -9749,12 +9751,12 @@
 #[test]
 fn parse_commit() {
     match verified_stmt("COMMIT") {
-        Statement::Commit { chain: false, .. } => (),
+        Statement::Commit(CommitStatement { chain: false, .. }) => (),
         _ => unreachable!(),
     }
 
     match verified_stmt("COMMIT AND CHAIN") {
-        Statement::Commit { chain: true, .. } => (),
+        Statement::Commit(CommitStatement { chain: true, .. }) => (),
         _ => unreachable!(),
     }
 
@@ -9785,36 +9787,36 @@
 #[test]
 fn parse_rollback() {
     match verified_stmt("ROLLBACK") {
-        Statement::Rollback {
+        Statement::Rollback(RollbackStatement {
             chain: false,
             savepoint: None,
-        } => (),
+        }) => (),
         _ => unreachable!(),
     }
 
     match verified_stmt("ROLLBACK AND CHAIN") {
-        Statement::Rollback {
+        Statement::Rollback(RollbackStatement {
             chain: true,
             savepoint: None,
-        } => (),
+        }) => (),
         _ => unreachable!(),
     }
 
     match verified_stmt("ROLLBACK TO SAVEPOINT test1") {
-        Statement::Rollback {
+        Statement::Rollback(RollbackStatement {
             chain: false,
             savepoint,
-        } => {
+        }) => {
             assert_eq!(savepoint, Some(Ident::new("test1")));
         }
         _ => unreachable!(),
     }
 
     match verified_stmt("ROLLBACK AND CHAIN TO SAVEPOINT test1") {
-        Statement::Rollback {
+        Statement::Rollback(RollbackStatement {
             chain: true,
             savepoint,
-        } => {
+        }) => {
             assert_eq!(savepoint, Some(Ident::new("test1")));
         }
         _ => unreachable!(),
@@ -10032,9 +10034,9 @@
 fn parse_drop_index() {
     let sql = "DROP INDEX idx_a";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names, object_type, ..
-        } => {
+        }) => {
             assert_eq!(
                 vec!["idx_a"],
                 names.iter().map(ToString::to_string).collect::<Vec<_>>()
@@ -10069,12 +10071,12 @@
 fn parse_drop_role() {
     let sql = "DROP ROLE abc";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names,
             object_type,
             if_exists,
             ..
-        } => {
+        }) => {
             assert_eq_vec(&["abc"], &names);
             assert_eq!(ObjectType::Role, object_type);
             assert!(!if_exists);
@@ -10084,12 +10086,12 @@
 
     let sql = "DROP ROLE IF EXISTS def, magician, quaternion";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names,
             object_type,
             if_exists,
             ..
-        } => {
+        }) => {
             assert_eq_vec(&["def", "magician", "quaternion"], &names);
             assert_eq!(ObjectType::Role, object_type);
             assert!(if_exists);
@@ -11350,25 +11352,33 @@
 fn parse_discard() {
     let sql = "DISCARD ALL";
     match verified_stmt(sql) {
-        Statement::Discard { object_type, .. } => assert_eq!(object_type, DiscardObject::ALL),
+        Statement::Discard(DiscardStatement { object_type, .. }) => {
+            assert_eq!(object_type, DiscardObject::ALL)
+        }
         _ => unreachable!(),
     }
 
     let sql = "DISCARD PLANS";
     match verified_stmt(sql) {
-        Statement::Discard { object_type, .. } => assert_eq!(object_type, DiscardObject::PLANS),
+        Statement::Discard(DiscardStatement { object_type, .. }) => {
+            assert_eq!(object_type, DiscardObject::PLANS)
+        }
         _ => unreachable!(),
     }
 
     let sql = "DISCARD SEQUENCES";
     match verified_stmt(sql) {
-        Statement::Discard { object_type, .. } => assert_eq!(object_type, DiscardObject::SEQUENCES),
+        Statement::Discard(DiscardStatement { object_type, .. }) => {
+            assert_eq!(object_type, DiscardObject::SEQUENCES)
+        }
         _ => unreachable!(),
     }
 
     let sql = "DISCARD TEMP";
     match verified_stmt(sql) {
-        Statement::Discard { object_type, .. } => assert_eq!(object_type, DiscardObject::TEMP),
+        Statement::Discard(DiscardStatement { object_type, .. }) => {
+            assert_eq!(object_type, DiscardObject::TEMP)
+        }
         _ => unreachable!(),
     }
 }
@@ -11377,7 +11387,7 @@
 fn parse_cursor() {
     let sql = r#"CLOSE my_cursor"#;
     match verified_stmt(sql) {
-        Statement::Close { cursor } => assert_eq!(
+        Statement::Close(CloseStatement { cursor }) => assert_eq!(
             cursor,
             CloseCursor::Specific {
                 name: Ident::new("my_cursor"),
@@ -11388,7 +11398,7 @@
 
     let sql = r#"CLOSE ALL"#;
     match verified_stmt(sql) {
-        Statement::Close { cursor } => assert_eq!(cursor, CloseCursor::All),
+        Statement::Close(CloseStatement { cursor }) => assert_eq!(cursor, CloseCursor::All),
         _ => unreachable!(),
     }
 }
@@ -11397,9 +11407,9 @@
 fn parse_show_functions() {
     assert_eq!(
         verified_stmt("SHOW FUNCTIONS LIKE 'pattern'"),
-        Statement::ShowFunctions {
+        Statement::ShowFunctions(ShowFunctionsStatement {
             filter: Some(ShowStatementFilter::Like("pattern".into())),
-        }
+        })
     );
 }
 
@@ -11412,24 +11422,24 @@
 
     assert_eq!(
         verified_stmt(format!("CACHE TABLE '{cache_table_name}'").as_str()),
-        Statement::Cache {
+        Statement::Cache(CacheStatement {
             table_flag: None,
             table_name: ObjectName::from(vec![Ident::with_quote('\'', cache_table_name)]),
             has_as: false,
             options: vec![],
             query: None,
-        }
+        })
     );
 
     assert_eq!(
         verified_stmt(format!("CACHE {table_flag} TABLE '{cache_table_name}'").as_str()),
-        Statement::Cache {
+        Statement::Cache(CacheStatement {
             table_flag: Some(ObjectName::from(vec![Ident::new(table_flag)])),
             table_name: ObjectName::from(vec![Ident::with_quote('\'', cache_table_name)]),
             has_as: false,
             options: vec![],
             query: None,
-        }
+        })
     );
 
     assert_eq!(
@@ -11439,7 +11449,7 @@
             )
             .as_str()
         ),
-        Statement::Cache {
+        Statement::Cache(CacheStatement {
             table_flag: Some(ObjectName::from(vec![Ident::new(table_flag)])),
             table_name: ObjectName::from(vec![Ident::with_quote('\'', cache_table_name)]),
             has_as: false,
@@ -11454,7 +11464,7 @@
                 },
             ],
             query: None,
-        }
+        })
     );
 
     assert_eq!(
@@ -11464,7 +11474,7 @@
             )
                 .as_str()
         ),
-        Statement::Cache {
+        Statement::Cache(CacheStatement {
             table_flag: Some(ObjectName::from(vec![Ident::new(table_flag)])),
             table_name: ObjectName::from(vec![Ident::with_quote('\'', cache_table_name)]),
             has_as: false,
@@ -11479,7 +11489,7 @@
                 },
             ],
             query: Some(query.clone().into()),
-        }
+        })
     );
 
     assert_eq!(
@@ -11489,7 +11499,7 @@
             )
                 .as_str()
         ),
-        Statement::Cache {
+        Statement::Cache(CacheStatement {
             table_flag: Some(ObjectName::from(vec![Ident::new(table_flag)])),
             table_name: ObjectName::from(vec![Ident::with_quote('\'', cache_table_name)]),
             has_as: true,
@@ -11504,29 +11514,29 @@
                 },
             ],
             query: Some(query.clone().into()),
-        }
+        })
     );
 
     assert_eq!(
         verified_stmt(format!("CACHE {table_flag} TABLE '{cache_table_name}' {sql}").as_str()),
-        Statement::Cache {
+        Statement::Cache(CacheStatement {
             table_flag: Some(ObjectName::from(vec![Ident::new(table_flag)])),
             table_name: ObjectName::from(vec![Ident::with_quote('\'', cache_table_name)]),
             has_as: false,
             options: vec![],
             query: Some(query.clone().into()),
-        }
+        })
     );
 
     assert_eq!(
         verified_stmt(format!("CACHE {table_flag} TABLE '{cache_table_name}' AS {sql}").as_str()),
-        Statement::Cache {
+        Statement::Cache(CacheStatement {
             table_flag: Some(ObjectName::from(vec![Ident::new(table_flag)])),
             table_name: ObjectName::from(vec![Ident::with_quote('\'', cache_table_name)]),
             has_as: true,
             options: vec![],
             query: Some(query.into()),
-        }
+        })
     );
 
     let res = parse_sql_statements("CACHE TABLE 'table_name' foo");
@@ -11584,18 +11594,18 @@
 fn parse_uncache_table() {
     assert_eq!(
         verified_stmt("UNCACHE TABLE 'table_name'"),
-        Statement::UNCache {
+        Statement::UNCache(UNCacheStatement {
             table_name: ObjectName::from(vec![Ident::with_quote('\'', "table_name")]),
             if_exists: false,
-        }
+        })
     );
 
     assert_eq!(
         verified_stmt("UNCACHE TABLE IF EXISTS 'table_name'"),
-        Statement::UNCache {
+        Statement::UNCache(UNCacheStatement {
             table_name: ObjectName::from(vec![Ident::with_quote('\'', "table_name")]),
             if_exists: true,
-        }
+        })
     );
 
     let res = parse_sql_statements("UNCACHE TABLE 'table_name' foo");
@@ -12499,10 +12509,10 @@
 #[test]
 fn parse_create_type() {
     match verified_stmt("CREATE TYPE mytype") {
-        Statement::CreateType {
+        Statement::CreateType(CreateTypeStatement {
             name,
             representation,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "mytype");
             assert!(representation.is_none());
         }
@@ -12511,10 +12521,10 @@
 
     match verified_stmt("CREATE TYPE address AS (street VARCHAR(100), city TEXT COLLATE \"en_US\")")
     {
-        Statement::CreateType {
+        Statement::CreateType(CreateTypeStatement {
             name,
             representation,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "address");
             match representation {
                 Some(UserDefinedTypeRepresentation::Composite { attributes }) => {
@@ -12545,10 +12555,10 @@
     verified_stmt("CREATE TYPE empty AS ()");
 
     match verified_stmt("CREATE TYPE mood AS ENUM ('happy', 'sad')") {
-        Statement::CreateType {
+        Statement::CreateType(CreateTypeStatement {
             name,
             representation,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "mood");
             match representation {
                 Some(UserDefinedTypeRepresentation::Enum { labels }) => {
@@ -12563,10 +12573,10 @@
     }
 
     match verified_stmt("CREATE TYPE int4range AS RANGE (SUBTYPE = INTEGER, CANONICAL = fn1)") {
-        Statement::CreateType {
+        Statement::CreateType(CreateTypeStatement {
             name,
             representation,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "int4range");
             match representation {
                 Some(UserDefinedTypeRepresentation::Range { options }) => {
@@ -12591,10 +12601,10 @@
     match verified_stmt(
         "CREATE TYPE int4range AS RANGE (SUBTYPE = INTEGER, SUBTYPE_OPCLASS = int4_ops)",
     ) {
-        Statement::CreateType {
+        Statement::CreateType(CreateTypeStatement {
             name,
             representation,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "int4range");
             match representation {
                 Some(UserDefinedTypeRepresentation::Range { options }) => {
@@ -12619,10 +12629,10 @@
     match verified_stmt(
         "CREATE TYPE int4range AS RANGE (SUBTYPE = INTEGER, SUBTYPE_DIFF = int4range_subdiff)",
     ) {
-        Statement::CreateType {
+        Statement::CreateType(CreateTypeStatement {
             name,
             representation,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "int4range");
             match representation {
                 Some(UserDefinedTypeRepresentation::Range { options }) => {
@@ -12647,10 +12657,10 @@
     match verified_stmt(
         "CREATE TYPE int4range AS RANGE (SUBTYPE = INTEGER, SUBTYPE_OPCLASS = int4_ops, CANONICAL = int4range_canonical, SUBTYPE_DIFF = int4range_subdiff, MULTIRANGE_TYPE_NAME = int4multirange)",
     ) {
-        Statement::CreateType {
+        Statement::CreateType(CreateTypeStatement {
             name,
             representation,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "int4range");
             match representation {
                 Some(UserDefinedTypeRepresentation::Range { options }) => {
@@ -12685,10 +12695,10 @@
     match verified_stmt(
         "CREATE TYPE mytype (INPUT = in_fn, OUTPUT = out_fn, INTERNALLENGTH = 16, PASSEDBYVALUE)",
     ) {
-        Statement::CreateType {
+        Statement::CreateType(CreateTypeStatement {
             name,
             representation,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "mytype");
             match representation {
                 Some(UserDefinedTypeRepresentation::SqlDefinition { options }) => {
@@ -12745,13 +12755,13 @@
 fn parse_drop_type() {
     let sql = "DROP TYPE abc";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names,
             object_type,
             if_exists,
             cascade,
             ..
-        } => {
+        }) => {
             assert_eq_vec(&["abc"], &names);
             assert_eq!(ObjectType::Type, object_type);
             assert!(!if_exists);
@@ -12762,13 +12772,13 @@
 
     let sql = "DROP TYPE IF EXISTS def, magician, quaternion";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names,
             object_type,
             if_exists,
             cascade,
             ..
-        } => {
+        }) => {
             assert_eq_vec(&["def", "magician", "quaternion"], &names);
             assert_eq!(ObjectType::Type, object_type);
             assert!(if_exists);
@@ -12779,13 +12789,13 @@
 
     let sql = "DROP TYPE IF EXISTS my_type CASCADE";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names,
             object_type,
             if_exists,
             cascade,
             ..
-        } => {
+        }) => {
             assert_eq_vec(&["my_type"], &names);
             assert_eq!(ObjectType::Type, object_type);
             assert!(if_exists);
@@ -12824,7 +12834,7 @@
 
 #[test]
 fn parse_execute_stored_procedure() {
-    let expected = Statement::Execute {
+    let expected = Statement::Execute(ExecuteStatement {
         name: Some(ObjectName::from(vec![
             Ident {
                 value: "my_schema".to_string(),
@@ -12847,7 +12857,7 @@
         into: vec![],
         output: false,
         default: false,
-    };
+    });
     assert_eq!(
         // Microsoft SQL Server does not use parentheses around arguments for EXECUTE
         ms_and_generic()
@@ -12862,13 +12872,13 @@
         expected
     );
     match ms_and_generic().verified_stmt("EXECUTE dbo.proc1 @ReturnVal = @X OUTPUT") {
-        Statement::Execute { output, .. } => {
+        Statement::Execute(ExecuteStatement { output, .. }) => {
             assert!(output);
         }
         _ => unreachable!(),
     }
     match ms_and_generic().verified_stmt("EXECUTE dbo.proc1 DEFAULT") {
-        Statement::Execute { default, .. } => {
+        Statement::Execute(ExecuteStatement { default, .. }) => {
             assert!(default);
         }
         _ => unreachable!(),
@@ -12881,7 +12891,7 @@
 fn parse_execute_immediate() {
     let dialects = all_dialects_where(|d| d.supports_execute_immediate());
 
-    let expected = Statement::Execute {
+    let expected = Statement::Execute(ExecuteStatement {
         parameters: vec![Expr::Value(
             (Value::SingleQuotedString("SELECT 1".to_string())).with_empty_span(),
         )],
@@ -12895,7 +12905,7 @@
         has_parentheses: false,
         output: false,
         default: false,
-    };
+    });
 
     let stmt = dialects.verified_stmt("EXECUTE IMMEDIATE 'SELECT 1' INTO a USING 1 AS b");
     assert_eq!(expected, stmt);
@@ -12989,7 +12999,7 @@
     let unload = verified_stmt("UNLOAD(SELECT cola FROM tab) TO 's3://...' WITH (format = 'AVRO')");
     assert_eq!(
         unload,
-        Statement::Unload {
+        Statement::Unload(UnloadStatement {
             query: Some(Box::new(Query {
                 body: Box::new(SetExpr::Select(Box::new(Select {
                     select_token: AttachedToken::empty(),
@@ -13048,7 +13058,7 @@
             query_text: None,
             auth: None,
             options: vec![],
-        }
+        })
     );
 
     one_statement_parses_to(
@@ -13163,7 +13173,7 @@
 #[test]
 fn test_savepoint() {
     match verified_stmt("SAVEPOINT test1") {
-        Statement::Savepoint { name } => {
+        Statement::Savepoint(SavepointStatement { name }) => {
             assert_eq!(Ident::new("test1"), name);
         }
         _ => unreachable!(),
@@ -13173,7 +13183,7 @@
 #[test]
 fn test_release_savepoint() {
     match verified_stmt("RELEASE SAVEPOINT test1") {
-        Statement::ReleaseSavepoint { name } => {
+        Statement::ReleaseSavepoint(ReleaseSavepointStatement { name }) => {
             assert_eq!(Ident::new("test1"), name);
         }
         _ => unreachable!(),
@@ -15084,7 +15094,7 @@
 fn test_drop_connector() {
     let dialects = all_dialects();
     match dialects.verified_stmt("DROP CONNECTOR IF EXISTS my_connector") {
-        Statement::DropConnector { if_exists, name } => {
+        Statement::DropConnector(DropConnectorStatement { if_exists, name }) => {
             assert_eq!(if_exists, true);
             assert_eq!(name.to_string(), "my_connector");
         }
@@ -15110,12 +15120,12 @@
     match dialects.verified_stmt(
         "ALTER CONNECTOR my_connector SET DCPROPERTIES('user' = 'root', 'password' = 'password')",
     ) {
-        Statement::AlterConnector {
+        Statement::AlterConnector(AlterConnectorStatement {
             name,
             properties,
             url,
             owner,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "my_connector");
             assert_eq!(
                 properties,
@@ -15143,12 +15153,12 @@
     match dialects
         .verified_stmt("ALTER CONNECTOR my_connector SET URL 'jdbc:mysql://localhost:3306/mydb'")
     {
-        Statement::AlterConnector {
+        Statement::AlterConnector(AlterConnectorStatement {
             name,
             properties,
             url,
             owner,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "my_connector");
             assert_eq!(properties, None);
             assert_eq!(url, Some("jdbc:mysql://localhost:3306/mydb".to_string()));
@@ -15158,12 +15168,12 @@
     }
 
     match dialects.verified_stmt("ALTER CONNECTOR my_connector SET OWNER USER 'root'") {
-        Statement::AlterConnector {
+        Statement::AlterConnector(AlterConnectorStatement {
             name,
             properties,
             url,
             owner,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "my_connector");
             assert_eq!(properties, None);
             assert_eq!(url, None);
@@ -15176,12 +15186,12 @@
     }
 
     match dialects.verified_stmt("ALTER CONNECTOR my_connector SET OWNER ROLE 'admin'") {
-        Statement::AlterConnector {
+        Statement::AlterConnector(AlterConnectorStatement {
             name,
             properties,
             url,
             owner,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "my_connector");
             assert_eq!(properties, None);
             assert_eq!(url, None);
@@ -15378,7 +15388,7 @@
     let dialects = all_dialects_where(|d| d.supports_listen_notify());
 
     match dialects.verified_stmt("LISTEN test1") {
-        Statement::LISTEN { channel } => {
+        Statement::LISTEN(LISTENStatement { channel }) => {
             assert_eq!(Ident::new("test1"), channel);
         }
         _ => unreachable!(),
@@ -15402,14 +15412,14 @@
     let dialects = all_dialects_where(|d| d.supports_listen_notify());
 
     match dialects.verified_stmt("UNLISTEN test1") {
-        Statement::UNLISTEN { channel } => {
+        Statement::UNLISTEN(UNLISTENStatement { channel }) => {
             assert_eq!(Ident::new("test1"), channel);
         }
         _ => unreachable!(),
     };
 
     match dialects.verified_stmt("UNLISTEN *") {
-        Statement::UNLISTEN { channel } => {
+        Statement::UNLISTEN(UNLISTENStatement { channel }) => {
             assert_eq!(Ident::new("*"), channel);
         }
         _ => unreachable!(),
@@ -15433,7 +15443,7 @@
     let dialects = all_dialects_where(|d| d.supports_listen_notify());
 
     match dialects.verified_stmt("NOTIFY test1") {
-        Statement::NOTIFY { channel, payload } => {
+        Statement::NOTIFY(NOTIFYStatement { channel, payload }) => {
             assert_eq!(Ident::new("test1"), channel);
             assert_eq!(payload, None);
         }
@@ -15441,10 +15451,10 @@
     };
 
     match dialects.verified_stmt("NOTIFY test1, 'this is a test notification'") {
-        Statement::NOTIFY {
+        Statement::NOTIFY(NOTIFYStatement {
             channel,
             payload: Some(payload),
-        } => {
+        }) => {
             assert_eq!(Ident::new("test1"), channel);
             assert_eq!("this is a test notification", payload);
         }
@@ -15486,14 +15496,14 @@
 
     let sql = "LOAD DATA INPATH '/local/path/to/data.txt' INTO TABLE test.my_table";
     match dialects.verified_stmt(sql) {
-        Statement::LoadData {
+        Statement::LoadData(LoadDataStatement {
             local,
             inpath,
             overwrite,
             table_name,
             partitioned,
             table_format,
-        } => {
+        }) => {
             assert_eq!(false, local);
             assert_eq!("/local/path/to/data.txt", inpath);
             assert_eq!(false, overwrite);
@@ -15510,14 +15520,14 @@
     // with OVERWRITE keyword
     let sql = "LOAD DATA INPATH '/local/path/to/data.txt' OVERWRITE INTO TABLE my_table";
     match dialects.verified_stmt(sql) {
-        Statement::LoadData {
+        Statement::LoadData(LoadDataStatement {
             local,
             inpath,
             overwrite,
             table_name,
             partitioned,
             table_format,
-        } => {
+        }) => {
             assert_eq!(false, local);
             assert_eq!("/local/path/to/data.txt", inpath);
             assert_eq!(true, overwrite);
@@ -15546,14 +15556,14 @@
     // with LOCAL keyword
     let sql = "LOAD DATA LOCAL INPATH '/local/path/to/data.txt' INTO TABLE test.my_table";
     match dialects.verified_stmt(sql) {
-        Statement::LoadData {
+        Statement::LoadData(LoadDataStatement {
             local,
             inpath,
             overwrite,
             table_name,
             partitioned,
             table_format,
-        } => {
+        }) => {
             assert_eq!(true, local);
             assert_eq!("/local/path/to/data.txt", inpath);
             assert_eq!(false, overwrite);
@@ -15585,14 +15595,14 @@
     // with PARTITION  clause
     let sql = "LOAD DATA LOCAL INPATH '/local/path/to/data.txt' INTO TABLE my_table PARTITION (year = 2024, month = 11)";
     match dialects.verified_stmt(sql) {
-        Statement::LoadData {
+        Statement::LoadData(LoadDataStatement {
             local,
             inpath,
             overwrite,
             table_name,
             partitioned,
             table_format,
-        } => {
+        }) => {
             assert_eq!(true, local);
             assert_eq!("/local/path/to/data.txt", inpath);
             assert_eq!(false, overwrite);
@@ -15624,14 +15634,14 @@
     // with PARTITION  clause
     let sql = "LOAD DATA LOCAL INPATH '/local/path/to/data.txt' OVERWRITE INTO TABLE good.my_table PARTITION (year = 2024, month = 11) INPUTFORMAT 'org.apache.hadoop.mapred.TextInputFormat' SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'";
     match dialects.verified_stmt(sql) {
-        Statement::LoadData {
+        Statement::LoadData(LoadDataStatement {
             local,
             inpath,
             overwrite,
             table_name,
             partitioned,
             table_format,
-        } => {
+        }) => {
             assert_eq!(true, local);
             assert_eq!("/local/path/to/data.txt", inpath);
             assert_eq!(true, overwrite);
@@ -15696,7 +15706,7 @@
     let sql = "LOAD my_extension";
 
     match dialects.verified_stmt(sql) {
-        Statement::Load { extension_name } => {
+        Statement::Load(LoadStatement { extension_name }) => {
             assert_eq!(Ident::new("my_extension"), extension_name);
         }
         _ => unreachable!(),
@@ -15714,7 +15724,7 @@
     let sql = "LOAD 'filename'";
 
     match dialects.verified_stmt(sql) {
-        Statement::Load { extension_name } => {
+        Statement::Load(LoadStatement { extension_name }) => {
             assert_eq!(
                 Ident {
                     value: "filename".to_string(),
@@ -15855,12 +15865,12 @@
     match all_dialects_where(|d| d.supports_comment_on())
         .verified_stmt("COMMENT ON COLUMN tab.name IS 'comment'")
     {
-        Statement::Comment {
+        Statement::Comment(CommentStatement {
             object_type,
             object_name,
             comment: Some(comment),
             if_exists,
-        } => {
+        }) => {
             assert_eq!("comment", comment);
             assert_eq!("tab.name", object_name.to_string());
             assert_eq!(CommentObject::Column, object_type);
@@ -15892,12 +15902,12 @@
         match all_dialects_where(|d| d.supports_comment_on())
             .verified_stmt(format!("COMMENT IF EXISTS ON {keyword} db.t0 IS 'comment'").as_str())
         {
-            Statement::Comment {
+            Statement::Comment(CommentStatement {
                 object_type,
                 object_name,
                 comment: Some(comment),
                 if_exists,
-            } => {
+            }) => {
                 assert_eq!("comment", comment);
                 assert_eq!("db.t0", object_name.to_string());
                 assert_eq!(*expected_object_type, object_type);
@@ -15910,12 +15920,12 @@
     match all_dialects_where(|d| d.supports_comment_on())
         .verified_stmt("COMMENT IF EXISTS ON TABLE public.tab IS NULL")
     {
-        Statement::Comment {
+        Statement::Comment(CommentStatement {
             object_type,
             object_name,
             comment: None,
             if_exists,
-        } => {
+        }) => {
             assert_eq!("public.tab", object_name.to_string());
             assert_eq!(CommentObject::Table, object_type);
             assert!(if_exists);
@@ -18216,13 +18226,13 @@
 fn parse_create_procedure_with_language() {
     let sql = r#"CREATE PROCEDURE test_proc LANGUAGE sql AS BEGIN SELECT 1; END"#;
     match verified_stmt(sql) {
-        Statement::CreateProcedure {
+        Statement::CreateProcedure(CreateProcedureStatement {
             or_alter,
             name,
             params,
             language,
             ..
-        } => {
+        }) => {
             assert_eq!(or_alter, false);
             assert_eq!(name.to_string(), "test_proc");
             assert_eq!(params, Some(vec![]));
@@ -18246,12 +18256,12 @@
 fn parse_create_procedure_with_parameter_modes() {
     let sql = r#"CREATE PROCEDURE test_proc (IN a INTEGER, OUT b TEXT, INOUT c TIMESTAMP, d BOOL) AS BEGIN SELECT 1; END"#;
     match verified_stmt(sql) {
-        Statement::CreateProcedure {
+        Statement::CreateProcedure(CreateProcedureStatement {
             or_alter,
             name,
             params,
             ..
-        } => {
+        }) => {
             assert_eq!(or_alter, false);
             assert_eq!(name.to_string(), "test_proc");
             let fake_span = Span {
@@ -18310,12 +18320,12 @@
     // parameters with default values
     let sql = r#"CREATE PROCEDURE test_proc (IN a INTEGER = 1, OUT b TEXT = '2', INOUT c TIMESTAMP = NULL, d BOOL = 0) AS BEGIN SELECT 1; END"#;
     match verified_stmt(sql) {
-        Statement::CreateProcedure {
+        Statement::CreateProcedure(CreateProcedureStatement {
             or_alter,
             name,
             params,
             ..
-        } => {
+        }) => {
             assert_eq!(or_alter, false);
             assert_eq!(name.to_string(), "test_proc");
             assert_eq!(
@@ -18710,9 +18720,9 @@
 fn parse_drop_stream() {
     let sql = "DROP STREAM s1";
     match verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names, object_type, ..
-        } => {
+        }) => {
             assert_eq!(
                 vec!["s1"],
                 names.iter().map(ToString::to_string).collect::<Vec<_>>()
@@ -18884,7 +18894,7 @@
         r#"COPY dst (c1, c2, c3) FROM 's3://redshift-downloads/tickit/category_pipe.txt' IAM_ROLE 'arn:aws:iam::123456789:role/role1' CSV IGNOREHEADER 1"#,
     );
     match copy {
-        Statement::Copy { legacy_options, .. } => {
+        Statement::Copy(CopyStatement { legacy_options, .. }) => {
             assert_eq!(
                 legacy_options,
                 vec![
@@ -18904,7 +18914,7 @@
         r#"COPY dst (c1, c2, c3) FROM 's3://redshift-downloads/tickit/category_pipe.txt' IAM_ROLE DEFAULT CSV IGNOREHEADER 1"#,
     );
     match copy {
-        Statement::Copy { legacy_options, .. } => {
+        Statement::Copy(CopyStatement { legacy_options, .. }) => {
             assert_eq!(
                 legacy_options,
                 vec![
diff --git a/tests/sqlparser_custom_dialect.rs b/tests/sqlparser_custom_dialect.rs
index 5bf38dd..fc6b51e 100644
--- a/tests/sqlparser_custom_dialect.rs
+++ b/tests/sqlparser_custom_dialect.rs
@@ -18,7 +18,7 @@
 //! Test the ability for dialects to override parsing
 
 use sqlparser::{
-    ast::{BinaryOperator, Expr, Statement, Value},
+    ast::{BinaryOperator, CommitStatement, Expr, Statement, Value},
     dialect::Dialect,
     keywords::Keyword,
     parser::{Parser, ParserError},
@@ -116,11 +116,11 @@
                 for _ in 0..3 {
                     let _ = parser.next_token();
                 }
-                Some(Ok(Statement::Commit {
+                Some(Ok(Statement::Commit(CommitStatement {
                     chain: false,
                     end: false,
                     modifier: None,
-                }))
+                })))
             } else {
                 None
             }
diff --git a/tests/sqlparser_databricks.rs b/tests/sqlparser_databricks.rs
index dd51bd1..8cbebfa 100644
--- a/tests/sqlparser_databricks.rs
+++ b/tests/sqlparser_databricks.rs
@@ -311,11 +311,11 @@
     databricks().verified_stmt("SHOW CATALOGS HISTORY STARTS WITH 'pay'");
 
     match databricks().verified_stmt("SHOW CATALOGS LIKE 'pay*'") {
-        Statement::ShowCatalogs {
+        Statement::ShowCatalogs(ShowCatalogsStatement {
             terse,
             history,
             show_options,
-        } => {
+        }) => {
             assert!(!terse);
             assert!(!history);
             assert_eq!(show_options.show_in, None);
@@ -338,11 +338,11 @@
     databricks().verified_stmt("SHOW TERSE CATALOGS HISTORY IN ACCOUNT");
 
     match databricks().verified_stmt("SHOW TERSE CATALOGS HISTORY IN ACCOUNT") {
-        Statement::ShowCatalogs {
+        Statement::ShowCatalogs(ShowCatalogsStatement {
             terse,
             history,
             show_options,
-        } => {
+        }) => {
             assert!(terse);
             assert!(history);
             assert_eq!(show_options.filter_position, None);
@@ -488,7 +488,7 @@
     match databricks()
         .verified_stmt("OPTIMIZE my_table WHERE date = '2023-01-01' ZORDER BY (col1, col2)")
     {
-        Statement::OptimizeTable {
+        Statement::OptimizeTable(OptimizeTableStatement {
             name,
             has_table_keyword,
             on_cluster,
@@ -497,7 +497,7 @@
             deduplicate,
             predicate,
             zorder,
-        } => {
+        }) => {
             assert_eq!(name.to_string(), "my_table");
             assert!(!has_table_keyword);
             assert!(on_cluster.is_none());
diff --git a/tests/sqlparser_duckdb.rs b/tests/sqlparser_duckdb.rs
index 51bc77f..b2865c0 100644
--- a/tests/sqlparser_duckdb.rs
+++ b/tests/sqlparser_duckdb.rs
@@ -196,7 +196,7 @@
 #[test]
 fn test_create_macro() {
     let macro_ = duckdb().verified_stmt("CREATE MACRO schema.add(a, b) AS a + b");
-    let expected = Statement::CreateMacro {
+    let expected = Statement::CreateMacro(CreateMacroStatement {
         or_replace: false,
         temporary: false,
         name: ObjectName::from(vec![Ident::new("schema"), Ident::new("add")]),
@@ -206,14 +206,14 @@
             op: BinaryOperator::Plus,
             right: Box::new(Expr::Identifier(Ident::new("b"))),
         }),
-    };
+    });
     assert_eq!(expected, macro_);
 }
 
 #[test]
 fn test_create_macro_default_args() {
     let macro_ = duckdb().verified_stmt("CREATE MACRO add_default(a, b := 5) AS a + b");
-    let expected = Statement::CreateMacro {
+    let expected = Statement::CreateMacro(CreateMacroStatement {
         or_replace: false,
         temporary: false,
         name: ObjectName::from(vec![Ident::new("add_default")]),
@@ -229,7 +229,7 @@
             op: BinaryOperator::Plus,
             right: Box::new(Expr::Identifier(Ident::new("b"))),
         }),
-    };
+    });
     assert_eq!(expected, macro_);
 }
 
@@ -241,7 +241,7 @@
             .to_string()
             + query),
     );
-    let expected = Statement::CreateMacro {
+    let expected = Statement::CreateMacro(CreateMacroStatement {
         or_replace: true,
         temporary: true,
         name: ObjectName::from(vec![Ident::new("dynamic_table")]),
@@ -250,7 +250,7 @@
             MacroArg::new("col2_value"),
         ]),
         definition: MacroDefinition::Table(duckdb().verified_query(query).into()),
-    };
+    });
     assert_eq!(expected, macro_);
 }
 
@@ -344,13 +344,13 @@
     let stmt = duckdb().verified_stmt("INSTALL tpch");
     assert_eq!(
         stmt,
-        Statement::Install {
+        Statement::Install(InstallStatement {
             extension_name: Ident {
                 value: "tpch".to_string(),
                 quote_style: None,
                 span: Span::empty()
             }
-        }
+        })
     );
 }
 
@@ -358,13 +358,13 @@
 fn test_duckdb_load_extension() {
     let stmt = duckdb().verified_stmt("LOAD my_extension");
     assert_eq!(
-        Statement::Load {
+        Statement::Load(LoadStatement {
             extension_name: Ident {
                 value: "my_extension".to_string(),
                 quote_style: None,
                 span: Span::empty()
             }
-        },
+        }),
         stmt
     );
 }
@@ -492,7 +492,7 @@
     let sql = r#"CREATE OR REPLACE PERSISTENT SECRET IF NOT EXISTS name IN storage ( TYPE type, key1 value1, key2 value2 )"#;
     let stmt = duckdb().verified_stmt(sql);
     assert_eq!(
-        Statement::CreateSecret {
+        Statement::CreateSecret(CreateSecretStatement {
             or_replace: true,
             temporary: Some(false),
             if_not_exists: true,
@@ -509,7 +509,7 @@
                     value: Ident::new("value2"),
                 }
             ]
-        },
+        }),
         stmt
     );
 }
@@ -519,7 +519,7 @@
     let sql = r#"CREATE SECRET ( TYPE type )"#;
     let stmt = duckdb().verified_stmt(sql);
     assert_eq!(
-        Statement::CreateSecret {
+        Statement::CreateSecret(CreateSecretStatement {
             or_replace: false,
             temporary: None,
             if_not_exists: false,
@@ -527,7 +527,7 @@
             storage_specifier: None,
             secret_type: Ident::new("type"),
             options: vec![]
-        },
+        }),
         stmt
     );
 }
@@ -537,12 +537,12 @@
     let sql = r#"DROP PERSISTENT SECRET IF EXISTS secret FROM storage"#;
     let stmt = duckdb().verified_stmt(sql);
     assert_eq!(
-        Statement::DropSecret {
+        Statement::DropSecret(DropSecretStatement {
             if_exists: true,
             temporary: Some(false),
             name: Ident::new("secret"),
             storage_specifier: Some(Ident::new("storage"))
-        },
+        }),
         stmt
     );
 }
@@ -552,12 +552,12 @@
     let sql = r#"DROP SECRET secret"#;
     let stmt = duckdb().verified_stmt(sql);
     assert_eq!(
-        Statement::DropSecret {
+        Statement::DropSecret(DropSecretStatement {
             if_exists: false,
             temporary: None,
             name: Ident::new("secret"),
             storage_specifier: None
-        },
+        }),
         stmt
     );
 }
@@ -567,7 +567,7 @@
     let sql = r#"ATTACH DATABASE IF NOT EXISTS 'sqlite_file.db' AS sqlite_db (READ_ONLY false, TYPE SQLITE)"#;
     let stmt = duckdb().verified_stmt(sql);
     assert_eq!(
-        Statement::AttachDuckDBDatabase {
+        Statement::AttachDuckDBDatabase(AttachDuckDBDatabaseStatement {
             if_not_exists: true,
             database: true,
             database_path: Ident::with_quote('\'', "sqlite_file.db"),
@@ -576,7 +576,7 @@
                 AttachDuckDBDatabaseOption::ReadOnly(Some(false)),
                 AttachDuckDBDatabaseOption::Type(Ident::new("SQLITE")),
             ]
-        },
+        }),
         stmt
     );
 }
@@ -586,7 +586,7 @@
     let sql = r#"ATTACH 'postgres://user.name:pass-word@some.url.com:5432/postgres'"#;
     let stmt = duckdb().verified_stmt(sql);
     assert_eq!(
-        Statement::AttachDuckDBDatabase {
+        Statement::AttachDuckDBDatabase(AttachDuckDBDatabaseStatement {
             if_not_exists: false,
             database: false,
             database_path: Ident::with_quote(
@@ -595,7 +595,7 @@
             ),
             database_alias: None,
             attach_options: vec![]
-        },
+        }),
         stmt
     );
 }
@@ -605,11 +605,11 @@
     let sql = r#"DETACH DATABASE IF EXISTS db_name"#;
     let stmt = duckdb().verified_stmt(sql);
     assert_eq!(
-        Statement::DetachDuckDBDatabase {
+        Statement::DetachDuckDBDatabase(DetachDuckDBDatabaseStatement {
             if_exists: true,
             database: true,
             database_alias: Ident::new("db_name"),
-        },
+        }),
         stmt
     );
 }
@@ -619,11 +619,11 @@
     let sql = r#"DETACH db_name"#;
     let stmt = duckdb().verified_stmt(sql);
     assert_eq!(
-        Statement::DetachDuckDBDatabase {
+        Statement::DetachDuckDBDatabase(DetachDuckDBDatabaseStatement {
             if_exists: false,
             database: false,
             database_alias: Ident::new("db_name"),
-        },
+        }),
         stmt
     );
 }
diff --git a/tests/sqlparser_mssql.rs b/tests/sqlparser_mssql.rs
index 4510f95..a3ba74c 100644
--- a/tests/sqlparser_mssql.rs
+++ b/tests/sqlparser_mssql.rs
@@ -126,7 +126,7 @@
 
     assert_eq!(
         ms().verified_stmt(sql),
-        Statement::CreateProcedure {
+        Statement::CreateProcedure(CreateProcedureStatement {
             or_alter: true,
             body: ConditionalStatements::BeginEnd(BeginEndStatements {
                 begin_token: AttachedToken::empty(),
@@ -202,7 +202,7 @@
                 span: Span::empty(),
             }]),
             language: None,
-        }
+        })
     )
 }
 
@@ -796,7 +796,7 @@
     let sql = "ALTER ROLE old_name WITH NAME = new_name";
     assert_eq!(
         ms().parse_sql_statements(sql).unwrap(),
-        [Statement::AlterRole {
+        [Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "old_name".into(),
                 quote_style: None,
@@ -809,13 +809,13 @@
                     span: Span::empty(),
                 }
             },
-        }]
+        })]
     );
 
     let sql = "ALTER ROLE role_name ADD MEMBER new_member";
     assert_eq!(
         ms().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -828,13 +828,13 @@
                     span: Span::empty(),
                 }
             },
-        }
+        })
     );
 
     let sql = "ALTER ROLE role_name DROP MEMBER old_member";
     assert_eq!(
         ms().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -847,7 +847,7 @@
                     span: Span::empty(),
                 }
             },
-        }
+        })
     );
 }
 
@@ -1418,7 +1418,7 @@
     let ast = ms().parse_sql_statements(sql).unwrap();
 
     assert_eq!(
-        vec![Statement::Declare {
+        vec![Statement::Declare(DeclareStatement {
             stmts: vec![
                 Declare {
                     names: vec![Ident {
@@ -1468,7 +1468,7 @@
                     for_query: None
                 }
             ]
-        }],
+        })],
         ast
     );
 
@@ -1476,7 +1476,7 @@
     let ast = ms().parse_sql_statements(sql).unwrap();
     assert_eq!(
         vec![
-            Statement::Declare {
+            Statement::Declare(DeclareStatement {
                 stmts: vec![Declare {
                     names: vec![Ident::new("@bar"),],
                     data_type: Some(Int(None)),
@@ -1488,7 +1488,7 @@
                     hold: None,
                     for_query: None
                 }]
-            },
+            }),
             Statement::Set(Set::SingleAssignment {
                 scope: None,
                 hivevar: false,
@@ -1635,7 +1635,7 @@
     let s = ms().verified_stmt(sql);
     assert_eq!(
         s,
-        Statement::RaisError {
+        Statement::RaisError(RaisErrorStatement {
             message: Box::new(Expr::Value(
                 (Value::SingleQuotedString("This is a test".to_string())).with_empty_span()
             )),
@@ -1647,7 +1647,7 @@
             )),
             arguments: vec![],
             options: vec![],
-        }
+        })
     );
 
     let sql = r#"RAISERROR('This is a test', 16, 1) WITH NOWAIT"#;
@@ -2292,7 +2292,7 @@
         .parse_sql_statements("DECLARE @A INT; IF 1=1 BEGIN SET @A = 1 END ELSE SET @A = 2")
         .unwrap();
     match &stmts[..] {
-        [Statement::Declare { .. }, Statement::If(stmt)] => {
+        [Statement::Declare(DeclareStatement { .. }), Statement::If(stmt)] => {
             assert_eq!(
                 stmt.to_string(),
                 "IF 1 = 1 BEGIN SET @A = 1; END ELSE SET @A = 2;"
@@ -2495,7 +2495,7 @@
             exec_body: None,
             statements_as: true,
             statements: Some(ConditionalStatements::Sequence {
-                statements: vec![Statement::RaisError {
+                statements: vec![Statement::RaisError(RaisErrorStatement {
                     message: Box::new(Expr::Value(
                         (Value::SingleQuotedString("Notify Customer Relations".to_string()))
                             .with_empty_span()
@@ -2508,7 +2508,7 @@
                     )),
                     arguments: vec![],
                     options: vec![],
-                }],
+                })],
             }),
             characteristics: None,
         })
@@ -2614,7 +2614,9 @@
     "#;
     let stmts = tsql().parse_sql_statements(sql).unwrap();
     assert_eq!(stmts.len(), 2);
-    assert!(stmts.iter().all(|s| matches!(s, Statement::Declare { .. })));
+    assert!(stmts
+        .iter()
+        .all(|s| matches!(s, Statement::Declare(DeclareStatement { .. }))));
 
     let sql = r#"
 SELECT col FROM tbl
@@ -2661,14 +2663,14 @@
     let sql = "BEGIN SELECT 1; END";
     let stmt = ms().verified_stmt(sql);
     match &stmt {
-        Statement::StartTransaction {
+        Statement::StartTransaction(StartTransactionStatement {
             begin,
             has_end_keyword,
             statements,
             transaction,
             modifier,
             ..
-        } => {
+        }) => {
             assert!(begin);
             assert!(has_end_keyword);
             assert!(transaction.is_none());
@@ -2682,11 +2684,11 @@
     let sql = "BEGIN SELECT 1; SELECT 2; END";
     let stmt = ms().verified_stmt(sql);
     match &stmt {
-        Statement::StartTransaction {
+        Statement::StartTransaction(StartTransactionStatement {
             statements,
             has_end_keyword,
             ..
-        } => {
+        }) => {
             assert!(has_end_keyword);
             assert_eq!(statements.len(), 2);
         }
@@ -2697,11 +2699,11 @@
     let sql = "BEGIN INSERT INTO t VALUES (1); UPDATE t SET x = 2; END";
     let stmt = ms().verified_stmt(sql);
     match &stmt {
-        Statement::StartTransaction {
+        Statement::StartTransaction(StartTransactionStatement {
             statements,
             has_end_keyword,
             ..
-        } => {
+        }) => {
             assert!(has_end_keyword);
             assert_eq!(statements.len(), 2);
         }
@@ -2712,12 +2714,12 @@
     let sql = "BEGIN TRANSACTION";
     let stmt = ms().verified_stmt(sql);
     match &stmt {
-        Statement::StartTransaction {
+        Statement::StartTransaction(StartTransactionStatement {
             begin,
             has_end_keyword,
             transaction,
             ..
-        } => {
+        }) => {
             assert!(begin);
             assert!(!has_end_keyword);
             assert!(transaction.is_some());
@@ -2734,12 +2736,12 @@
     let sql = "BEGIN TRAN";
     let stmt = ms().verified_stmt(sql);
     match &stmt {
-        Statement::StartTransaction {
+        Statement::StartTransaction(StartTransactionStatement {
             begin,
             transaction,
             has_end_keyword,
             ..
-        } => {
+        }) => {
             assert!(begin);
             assert_eq!(*transaction, Some(BeginTransactionKind::Tran));
             assert!(!has_end_keyword);
@@ -2817,7 +2819,7 @@
         .expect("EXEC (@sql) should parse");
     assert_eq!(stmts.len(), 1);
     assert!(
-        matches!(&stmts[0], Statement::Execute { .. }),
+        matches!(&stmts[0], Statement::Execute(ExecuteStatement { .. })),
         "expected Execute, got: {:?}",
         stmts[0]
     );
@@ -2838,7 +2840,7 @@
         .expect("EXEC with string concatenation should parse");
     assert_eq!(stmts.len(), 1);
     assert!(
-        matches!(&stmts[0], Statement::Execute { .. }),
+        matches!(&stmts[0], Statement::Execute(ExecuteStatement { .. })),
         "expected Execute, got: {:?}",
         stmts[0]
     );
diff --git a/tests/sqlparser_mysql.rs b/tests/sqlparser_mysql.rs
index e3fa77f..dbb6690 100644
--- a/tests/sqlparser_mysql.rs
+++ b/tests/sqlparser_mysql.rs
@@ -65,84 +65,84 @@
 fn parse_flush() {
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH OPTIMIZER_COSTS"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: None,
             object_type: FlushType::OptimizerCosts,
             channel: None,
             read_lock: false,
             export: false,
             tables: vec![]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH BINARY LOGS"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: None,
             object_type: FlushType::BinaryLogs,
             channel: None,
             read_lock: false,
             export: false,
             tables: vec![]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH ENGINE LOGS"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: None,
             object_type: FlushType::EngineLogs,
             channel: None,
             read_lock: false,
             export: false,
             tables: vec![]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH ERROR LOGS"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: None,
             object_type: FlushType::ErrorLogs,
             channel: None,
             read_lock: false,
             export: false,
             tables: vec![]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH NO_WRITE_TO_BINLOG GENERAL LOGS"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: Some(FlushLocation::NoWriteToBinlog),
             object_type: FlushType::GeneralLogs,
             channel: None,
             read_lock: false,
             export: false,
             tables: vec![]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH RELAY LOGS FOR CHANNEL test"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: None,
             object_type: FlushType::RelayLogs,
             channel: Some("test".to_string()),
             read_lock: false,
             export: false,
             tables: vec![]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH LOCAL SLOW LOGS"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: Some(FlushLocation::Local),
             object_type: FlushType::SlowLogs,
             channel: None,
             read_lock: false,
             export: false,
             tables: vec![]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH TABLES `mek`.`table1`, table2"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: None,
             object_type: FlushType::Tables,
             channel: None,
@@ -167,22 +167,22 @@
                     span: Span::empty(),
                 }])
             ]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH TABLES WITH READ LOCK"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: None,
             object_type: FlushType::Tables,
             channel: None,
             read_lock: true,
             export: false,
             tables: vec![]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH TABLES `mek`.`table1`, table2 WITH READ LOCK"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: None,
             object_type: FlushType::Tables,
             channel: None,
@@ -207,11 +207,11 @@
                     span: Span::empty(),
                 }])
             ]
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("FLUSH TABLES `mek`.`table1`, table2 FOR EXPORT"),
-        Statement::Flush {
+        Statement::Flush(FlushStatement {
             location: None,
             object_type: FlushType::Tables,
             channel: None,
@@ -236,7 +236,7 @@
                     span: Span::empty(),
                 }])
             ]
-        }
+        })
     );
 }
 
@@ -244,7 +244,7 @@
 fn parse_show_columns() {
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW COLUMNS FROM mytable"),
-        Statement::ShowColumns {
+        Statement::ShowColumns(ShowColumnsStatement {
             extended: false,
             full: false,
             show_options: ShowStatementOptions {
@@ -258,11 +258,11 @@
                 limit: None,
                 starts_with: None,
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW COLUMNS FROM mydb.mytable"),
-        Statement::ShowColumns {
+        Statement::ShowColumns(ShowColumnsStatement {
             extended: false,
             full: false,
             show_options: ShowStatementOptions {
@@ -279,11 +279,11 @@
                 limit: None,
                 starts_with: None,
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW EXTENDED COLUMNS FROM mytable"),
-        Statement::ShowColumns {
+        Statement::ShowColumns(ShowColumnsStatement {
             extended: true,
             full: false,
             show_options: ShowStatementOptions {
@@ -297,11 +297,11 @@
                 limit: None,
                 starts_with: None,
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW FULL COLUMNS FROM mytable"),
-        Statement::ShowColumns {
+        Statement::ShowColumns(ShowColumnsStatement {
             extended: false,
             full: true,
             show_options: ShowStatementOptions {
@@ -315,11 +315,11 @@
                 limit: None,
                 starts_with: None,
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW COLUMNS FROM mytable LIKE 'pattern'"),
-        Statement::ShowColumns {
+        Statement::ShowColumns(ShowColumnsStatement {
             extended: false,
             full: false,
             show_options: ShowStatementOptions {
@@ -335,11 +335,11 @@
                 limit: None,
                 starts_with: None,
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW COLUMNS FROM mytable WHERE 1 = 2"),
-        Statement::ShowColumns {
+        Statement::ShowColumns(ShowColumnsStatement {
             extended: false,
             full: false,
             show_options: ShowStatementOptions {
@@ -355,7 +355,7 @@
                 limit: None,
                 starts_with: None,
             }
-        }
+        })
     );
     mysql_and_generic()
         .one_statement_parses_to("SHOW FIELDS FROM mytable", "SHOW COLUMNS FROM mytable");
@@ -373,11 +373,11 @@
 fn parse_show_process_list() {
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW PROCESSLIST"),
-        Statement::ShowProcessList { full: false }
+        Statement::ShowProcessList(ShowProcessListStatement { full: false })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW FULL PROCESSLIST"),
-        Statement::ShowProcessList { full: true }
+        Statement::ShowProcessList(ShowProcessListStatement { full: true })
     );
 }
 
@@ -385,29 +385,29 @@
 fn parse_show_status() {
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW SESSION STATUS LIKE 'ssl_cipher'"),
-        Statement::ShowStatus {
+        Statement::ShowStatus(ShowStatusStatement {
             filter: Some(ShowStatementFilter::Like("ssl_cipher".into())),
             session: true,
             global: false
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW GLOBAL STATUS LIKE 'ssl_cipher'"),
-        Statement::ShowStatus {
+        Statement::ShowStatus(ShowStatusStatement {
             filter: Some(ShowStatementFilter::Like("ssl_cipher".into())),
             session: false,
             global: true
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW STATUS WHERE value = 2"),
-        Statement::ShowStatus {
+        Statement::ShowStatus(ShowStatusStatement {
             filter: Some(ShowStatementFilter::Where(
                 mysql_and_generic().verified_expr("value = 2")
             )),
             session: false,
             global: false
-        }
+        })
     );
 }
 
@@ -415,7 +415,7 @@
 fn parse_show_tables() {
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW TABLES"),
-        Statement::ShowTables {
+        Statement::ShowTables(ShowTablesStatement {
             terse: false,
             history: false,
             extended: false,
@@ -428,11 +428,11 @@
                 show_in: None,
                 filter_position: None
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW TABLES FROM mydb"),
-        Statement::ShowTables {
+        Statement::ShowTables(ShowTablesStatement {
             terse: false,
             history: false,
             extended: false,
@@ -449,11 +449,11 @@
                 }),
                 filter_position: None
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW EXTENDED TABLES"),
-        Statement::ShowTables {
+        Statement::ShowTables(ShowTablesStatement {
             terse: false,
             history: false,
             extended: true,
@@ -466,11 +466,11 @@
                 show_in: None,
                 filter_position: None
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW FULL TABLES"),
-        Statement::ShowTables {
+        Statement::ShowTables(ShowTablesStatement {
             terse: false,
             history: false,
             extended: false,
@@ -483,11 +483,11 @@
                 show_in: None,
                 filter_position: None
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW TABLES LIKE 'pattern'"),
-        Statement::ShowTables {
+        Statement::ShowTables(ShowTablesStatement {
             terse: false,
             history: false,
             extended: false,
@@ -502,11 +502,11 @@
                     ShowStatementFilter::Like("pattern".into())
                 ))
             }
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW TABLES WHERE 1 = 2"),
-        Statement::ShowTables {
+        Statement::ShowTables(ShowTablesStatement {
             terse: false,
             history: false,
             extended: false,
@@ -521,7 +521,7 @@
                     ShowStatementFilter::Where(mysql_and_generic().verified_expr("1 = 2"))
                 ))
             }
-        }
+        })
     );
     mysql_and_generic().verified_stmt("SHOW TABLES IN mydb");
     mysql_and_generic().verified_stmt("SHOW TABLES FROM mydb");
@@ -561,10 +561,10 @@
     ] {
         assert_eq!(
             mysql_and_generic().verified_stmt(format!("SHOW CREATE {obj_type} myident").as_str()),
-            Statement::ShowCreate {
+            Statement::ShowCreate(ShowCreateStatement {
                 obj_type: *obj_type,
                 obj_name: obj_name.clone(),
-            }
+            })
         );
     }
 }
@@ -573,21 +573,21 @@
 fn parse_show_collation() {
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW COLLATION"),
-        Statement::ShowCollation { filter: None }
+        Statement::ShowCollation(ShowCollationStatement { filter: None })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW COLLATION LIKE 'pattern'"),
-        Statement::ShowCollation {
+        Statement::ShowCollation(ShowCollationStatement {
             filter: Some(ShowStatementFilter::Like("pattern".into())),
-        }
+        })
     );
     assert_eq!(
         mysql_and_generic().verified_stmt("SHOW COLLATION WHERE 1 = 2"),
-        Statement::ShowCollation {
+        Statement::ShowCollation(ShowCollationStatement {
             filter: Some(ShowStatementFilter::Where(
                 mysql_and_generic().verified_expr("1 = 2")
             )),
-        }
+        })
     );
 }
 
@@ -3452,28 +3452,28 @@
     let stmt = mysql_and_generic().verified_stmt("KILL CONNECTION 5");
     assert_eq!(
         stmt,
-        Statement::Kill {
+        Statement::Kill(KillStatement {
             modifier: Some(KillType::Connection),
             id: 5,
-        }
+        })
     );
 
     let stmt = mysql_and_generic().verified_stmt("KILL QUERY 5");
     assert_eq!(
         stmt,
-        Statement::Kill {
+        Statement::Kill(KillStatement {
             modifier: Some(KillType::Query),
             id: 5,
-        }
+        })
     );
 
     let stmt = mysql_and_generic().verified_stmt("KILL 5");
     assert_eq!(
         stmt,
-        Statement::Kill {
+        Statement::Kill(KillStatement {
             modifier: None,
             id: 5,
-        }
+        })
     );
 }
 
@@ -3819,7 +3819,7 @@
 fn parse_drop_temporary_table() {
     let sql = "DROP TEMPORARY TABLE foo";
     match mysql().verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             object_type,
             if_exists,
             names,
@@ -3827,7 +3827,7 @@
             purge: _,
             temporary,
             ..
-        } => {
+        }) => {
             assert!(!if_exists);
             assert_eq!(ObjectType::Table, object_type);
             assert_eq!(
@@ -4720,7 +4720,7 @@
 fn parse_drop_index() {
     let sql = "DROP INDEX idx_name ON table_name";
     match mysql().verified_stmt(sql) {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             object_type,
             if_exists,
             names,
@@ -4729,7 +4729,7 @@
             purge,
             temporary,
             table,
-        } => {
+        }) => {
             assert!(!if_exists);
             assert_eq!(ObjectType::Index, object_type);
             assert_eq!(
diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs
index ae30950..84c5ad5 100644
--- a/tests/sqlparser_postgres.rs
+++ b/tests/sqlparser_postgres.rs
@@ -1094,7 +1094,7 @@
 fn parse_drop_and_comment_collation_ast() {
     assert_eq!(
         pg_and_generic().verified_stmt("DROP COLLATION test0"),
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             object_type: ObjectType::Collation,
             if_exists: false,
             names: vec![ObjectName::from(vec![Ident::new("test0")])],
@@ -1103,12 +1103,12 @@
             purge: false,
             temporary: false,
             table: None,
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic().verified_stmt("DROP COLLATION IF EXISTS test0"),
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             object_type: ObjectType::Collation,
             if_exists: true,
             names: vec![ObjectName::from(vec![Ident::new("test0")])],
@@ -1117,17 +1117,17 @@
             purge: false,
             temporary: false,
             table: None,
-        }
+        })
     );
 
     assert_eq!(
         pg_and_generic().verified_stmt("COMMENT ON COLLATION test0 IS 'US English'"),
-        Statement::Comment {
+        Statement::Comment(CommentStatement {
             object_type: CommentObject::Collation,
             object_name: ObjectName::from(vec![Ident::new("test0")]),
             comment: Some("US English".to_string()),
             if_exists: false,
-        }
+        })
     );
 }
 
@@ -1410,11 +1410,11 @@
     let sql = "CREATE SCHEMA IF NOT EXISTS schema_name";
     let ast = pg_and_generic().verified_stmt(sql);
     match ast {
-        Statement::CreateSchema {
+        Statement::CreateSchema(CreateSchemaStatement {
             if_not_exists: true,
             schema_name,
             ..
-        } => assert_eq!("schema_name", schema_name.to_string()),
+        }) => assert_eq!("schema_name", schema_name.to_string()),
         _ => unreachable!(),
     }
 }
@@ -1424,11 +1424,11 @@
     let sql = "DROP SCHEMA IF EXISTS schema_name";
     let ast = pg().verified_stmt(sql);
     match ast {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             object_type,
             if_exists: true,
             ..
-        } => assert_eq!(object_type, ObjectType::Schema),
+        }) => assert_eq!(object_type, ObjectType::Schema),
         _ => unreachable!(),
     }
 }
@@ -1463,7 +1463,7 @@
     let stmt = pg().verified_stmt("COPY bitwise_test FROM STDIN NULL 'null'");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["bitwise_test".into()]),
                 columns: vec![],
@@ -1473,7 +1473,7 @@
             options: vec![],
             legacy_options: vec![CopyLegacyOption::Null("null".into())],
             values: vec![],
-        }
+        })
     );
 }
 
@@ -1498,12 +1498,12 @@
 
     for sql in cases {
         match pg().verified_stmt(sql) {
-            Statement::Copy {
+            Statement::Copy(CopyStatement {
                 to: false,
                 target: CopyTarget::Stdin,
                 values,
                 ..
-            } => {
+            }) => {
                 assert!(
                     values.is_empty(),
                     "expected no inline COPY payload for `{sql}`"
@@ -1519,7 +1519,7 @@
     let stmt = pg().verified_stmt("COPY users FROM 'data.csv'");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1531,13 +1531,13 @@
             options: vec![],
             legacy_options: vec![],
             values: vec![],
-        }
+        })
     );
 
     let stmt = pg().verified_stmt("COPY users FROM 'data.csv' DELIMITER ','");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1549,13 +1549,13 @@
             options: vec![],
             legacy_options: vec![CopyLegacyOption::Delimiter(',')],
             values: vec![],
-        }
+        })
     );
 
     let stmt = pg().verified_stmt("COPY users FROM 'data.csv' DELIMITER ',' CSV HEADER");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1570,7 +1570,7 @@
                 CopyLegacyOption::Csv(vec![CopyLegacyCsvOption::Header,])
             ],
             values: vec![],
-        }
+        })
     );
 }
 
@@ -1579,7 +1579,7 @@
     let stmt = pg().verified_stmt("COPY users TO 'data.csv'");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1591,13 +1591,13 @@
             options: vec![],
             legacy_options: vec![],
             values: vec![],
-        }
+        })
     );
 
     let stmt = pg().verified_stmt("COPY users TO 'data.csv' DELIMITER ','");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1609,13 +1609,13 @@
             options: vec![],
             legacy_options: vec![CopyLegacyOption::Delimiter(',')],
             values: vec![],
-        }
+        })
     );
 
     let stmt = pg().verified_stmt("COPY users TO 'data.csv' DELIMITER ',' CSV HEADER");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1630,7 +1630,7 @@
                 CopyLegacyOption::Csv(vec![CopyLegacyCsvOption::Header,])
             ],
             values: vec![],
-        }
+        })
     )
 }
 
@@ -1656,7 +1656,7 @@
     )";
     assert_eq!(
         pg_and_generic().one_statement_parses_to(sql, ""),
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["table".into()]),
                 columns: vec!["a".into(), "b".into()],
@@ -1684,7 +1684,7 @@
             ],
             legacy_options: vec![],
             values: vec![],
-        }
+        })
     );
 }
 
@@ -1702,7 +1702,7 @@
     let stmt = pg().verified_stmt("COPY users TO 'data.csv'");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1714,13 +1714,13 @@
             options: vec![],
             legacy_options: vec![],
             values: vec![],
-        }
+        })
     );
 
     let stmt = pg().verified_stmt("COPY country TO STDOUT (DELIMITER '|')");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["country".into()]),
                 columns: vec![],
@@ -1730,14 +1730,14 @@
             options: vec![CopyOption::Delimiter('|')],
             legacy_options: vec![],
             values: vec![],
-        }
+        })
     );
 
     let stmt =
         pg().verified_stmt("COPY country TO PROGRAM 'gzip > /usr1/proj/bray/sql/country_data.gz'");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["country".into()]),
                 columns: vec![],
@@ -1749,13 +1749,13 @@
             options: vec![],
             legacy_options: vec![],
             values: vec![],
-        }
+        })
     );
 
     let stmt = pg().verified_stmt("COPY (SELECT 42 AS a, 'hello' AS b) TO 'query.csv'");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Query(Box::new(Query {
                 with: None,
                 body: Box::new(SetExpr::Select(Box::new(Select {
@@ -1819,7 +1819,7 @@
             options: vec![],
             legacy_options: vec![],
             values: vec![],
-        }
+        })
     )
 }
 
@@ -1828,7 +1828,7 @@
     let stmt = pg().verified_stmt("COPY users FROM 'data.csv' BINARY DELIMITER ',' NULL 'null' CSV HEADER QUOTE '\"' ESCAPE '\\' FORCE NOT NULL column");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1850,14 +1850,14 @@
                 ]),
             ],
             values: vec![],
-        }
+        })
     );
 
     // test 'AS' keyword
     let sql = "COPY users FROM 'data.csv' DELIMITER AS ',' NULL AS 'null' CSV QUOTE AS '\"' ESCAPE AS '\\'";
     assert_eq!(
         pg_and_generic().one_statement_parses_to(sql, ""),
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1876,7 +1876,7 @@
                 ]),
             ],
             values: vec![],
-        }
+        })
     );
 }
 
@@ -1885,7 +1885,7 @@
     let stmt = pg().verified_stmt("COPY users TO 'data.csv' BINARY DELIMITER ',' NULL 'null' CSV HEADER QUOTE '\"' ESCAPE '\\' FORCE QUOTE column");
     assert_eq!(
         stmt,
-        Statement::Copy {
+        Statement::Copy(CopyStatement {
             source: CopySource::Table {
                 table_name: ObjectName::from(vec!["users".into()]),
                 columns: vec![],
@@ -1907,7 +1907,7 @@
                 ]),
             ],
             values: vec![],
-        }
+        })
     )
 }
 
@@ -2082,17 +2082,17 @@
     let stmt = pg_and_generic().verified_stmt("SHOW a a");
     assert_eq!(
         stmt,
-        Statement::ShowVariable {
+        Statement::ShowVariable(ShowVariableStatement {
             variable: vec!["a".into(), "a".into()]
-        }
+        })
     );
 
     let stmt = pg_and_generic().verified_stmt("SHOW ALL ALL");
     assert_eq!(
         stmt,
-        Statement::ShowVariable {
+        Statement::ShowVariable(ShowVariableStatement {
             variable: vec!["ALL".into(), "ALL".into()]
-        }
+        })
     )
 }
 
@@ -2101,37 +2101,37 @@
     let stmt = pg_and_generic().verified_stmt("DEALLOCATE a");
     assert_eq!(
         stmt,
-        Statement::Deallocate {
+        Statement::Deallocate(DeallocateStatement {
             name: "a".into(),
             prepare: false,
-        }
+        })
     );
 
     let stmt = pg_and_generic().verified_stmt("DEALLOCATE ALL");
     assert_eq!(
         stmt,
-        Statement::Deallocate {
+        Statement::Deallocate(DeallocateStatement {
             name: "ALL".into(),
             prepare: false,
-        }
+        })
     );
 
     let stmt = pg_and_generic().verified_stmt("DEALLOCATE PREPARE a");
     assert_eq!(
         stmt,
-        Statement::Deallocate {
+        Statement::Deallocate(DeallocateStatement {
             name: "a".into(),
             prepare: true,
-        }
+        })
     );
 
     let stmt = pg_and_generic().verified_stmt("DEALLOCATE PREPARE ALL");
     assert_eq!(
         stmt,
-        Statement::Deallocate {
+        Statement::Deallocate(DeallocateStatement {
             name: "ALL".into(),
             prepare: true,
-        }
+        })
     );
 }
 
@@ -2140,7 +2140,7 @@
     let stmt = pg_and_generic().verified_stmt("EXECUTE a");
     assert_eq!(
         stmt,
-        Statement::Execute {
+        Statement::Execute(ExecuteStatement {
             name: Some(ObjectName::from(vec!["a".into()])),
             parameters: vec![],
             has_parentheses: false,
@@ -2149,13 +2149,13 @@
             into: vec![],
             output: false,
             default: false,
-        }
+        })
     );
 
     let stmt = pg_and_generic().verified_stmt("EXECUTE a(1, 't')");
     assert_eq!(
         stmt,
-        Statement::Execute {
+        Statement::Execute(ExecuteStatement {
             name: Some(ObjectName::from(vec!["a".into()])),
             parameters: vec![
                 Expr::value(number("1")),
@@ -2167,14 +2167,14 @@
             into: vec![],
             output: false,
             default: false,
-        }
+        })
     );
 
     let stmt = pg_and_generic()
         .verified_stmt("EXECUTE a USING CAST(1337 AS SMALLINT), CAST(7331 AS SMALLINT)");
     assert_eq!(
         stmt,
-        Statement::Execute {
+        Statement::Execute(ExecuteStatement {
             name: Some(ObjectName::from(vec!["a".into()])),
             parameters: vec![],
             has_parentheses: false,
@@ -2206,7 +2206,7 @@
             into: vec![],
             output: false,
             default: false,
-        }
+        })
     );
 }
 
@@ -2215,12 +2215,12 @@
     let stmt =
         pg_and_generic().verified_stmt("PREPARE a AS INSERT INTO customers VALUES (a1, a2, a3)");
     let sub_stmt = match stmt {
-        Statement::Prepare {
+        Statement::Prepare(PrepareStatement {
             name,
             data_types,
             statement,
             ..
-        } => {
+        }) => {
             assert_eq!(name, "a".into());
             assert!(data_types.is_empty());
 
@@ -2256,12 +2256,12 @@
     let stmt = pg_and_generic()
         .verified_stmt("PREPARE a (INT, TEXT) AS SELECT * FROM customers WHERE customers.id = a1");
     let sub_stmt = match stmt {
-        Statement::Prepare {
+        Statement::Prepare(PrepareStatement {
             name,
             data_types,
             statement,
             ..
-        } => {
+        }) => {
             assert_eq!(name, "a".into());
             assert_eq!(data_types, vec![DataType::Int(None), DataType::Text]);
 
@@ -4562,7 +4562,7 @@
     let sql = "ALTER ROLE old_name RENAME TO new_name";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "old_name".into(),
                 quote_style: None,
@@ -4575,13 +4575,13 @@
                     span: Span::empty(),
                 }
             },
-        }
+        })
     );
 
     let sql = "ALTER ROLE role_name WITH SUPERUSER CREATEDB CREATEROLE INHERIT LOGIN REPLICATION BYPASSRLS CONNECTION LIMIT 100 PASSWORD 'abcdef' VALID UNTIL '2025-01-01'";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -4607,13 +4607,13 @@
                     ))
                 ]
             },
-        }
+        })
     );
 
     let sql = "ALTER ROLE role_name WITH NOSUPERUSER NOCREATEDB NOCREATEROLE NOINHERIT NOLOGIN NOREPLICATION NOBYPASSRLS PASSWORD NULL";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -4631,13 +4631,13 @@
                     RoleOption::Password(Password::NullPassword),
                 ]
             },
-        }
+        })
     );
 
     let sql = "ALTER ROLE role_name SET maintenance_work_mem FROM CURRENT";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -4652,13 +4652,13 @@
                 config_value: SetConfigValue::FromCurrent,
                 in_database: None
             },
-        }
+        })
     );
 
     let sql = "ALTER ROLE role_name IN DATABASE database_name SET maintenance_work_mem = 100000";
     assert_eq!(
         pg().parse_sql_statements(sql).unwrap(),
-        [Statement::AlterRole {
+        [Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -4679,13 +4679,13 @@
                     span: Span::empty(),
                 }]))
             },
-        }]
+        })]
     );
 
     let sql = "ALTER ROLE role_name IN DATABASE database_name SET maintenance_work_mem TO 100000";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -4706,13 +4706,13 @@
                     span: Span::empty(),
                 }]))
             },
-        }
+        })
     );
 
     let sql = "ALTER ROLE role_name IN DATABASE database_name SET maintenance_work_mem TO DEFAULT";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -4731,13 +4731,13 @@
                     span: Span::empty(),
                 }]))
             },
-        }
+        })
     );
 
     let sql = "ALTER ROLE role_name RESET ALL";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -4747,13 +4747,13 @@
                 config_name: ResetConfig::ALL,
                 in_database: None
             },
-        }
+        })
     );
 
     let sql = "ALTER ROLE role_name IN DATABASE database_name RESET maintenance_work_mem";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident {
                 value: "role_name".into(),
                 quote_style: None,
@@ -4771,7 +4771,7 @@
                     span: Span::empty(),
                 }]))
             },
-        }
+        })
     );
 }
 
@@ -4781,12 +4781,12 @@
     let canonical = "ALTER ROLE old_name RENAME TO new_name";
     assert_eq!(
         pg().one_statement_parses_to("ALTER USER old_name RENAME TO new_name", canonical),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident::new("old_name"),
             operation: AlterRoleOperation::RenameRole {
                 role_name: Ident::new("new_name"),
             },
-        }
+        })
     );
 
     let canonical = "ALTER ROLE bob WITH SUPERUSER PASSWORD 'x' CONNECTION LIMIT 5";
@@ -4795,7 +4795,7 @@
             "ALTER USER bob WITH SUPERUSER PASSWORD 'x' CONNECTION LIMIT 5",
             canonical
         ),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident::new("bob"),
             operation: AlterRoleOperation::WithOptions {
                 options: vec![
@@ -4806,7 +4806,7 @@
                     RoleOption::ConnectionLimit(Expr::value(number("5"))),
                 ]
             },
-        }
+        })
     );
 
     assert_eq!(
@@ -4814,14 +4814,14 @@
             "ALTER USER bob SET search_path TO public",
             "ALTER ROLE bob SET search_path TO public"
         ),
-        Statement::AlterRole {
+        Statement::AlterRole(AlterRoleStatement {
             name: Ident::new("bob"),
             operation: AlterRoleOperation::Set {
                 config_name: ObjectName::from(vec![Ident::new("search_path")]),
                 config_value: SetConfigValue::Value(Expr::Identifier(Ident::new("public"))),
                 in_database: None,
             },
-        }
+        })
     );
 }
 
@@ -5489,7 +5489,7 @@
     let sql = "DROP PROCEDURE IF EXISTS test_proc";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::DropProcedure {
+        Statement::DropProcedure(DropProcedureStatement {
             if_exists: true,
             proc_desc: vec![FunctionDesc {
                 name: ObjectName::from(vec![Ident {
@@ -5500,13 +5500,13 @@
                 args: None
             }],
             drop_behavior: None
-        }
+        })
     );
 
     let sql = "DROP PROCEDURE IF EXISTS test_proc(a INTEGER, IN b INTEGER = 1)";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::DropProcedure {
+        Statement::DropProcedure(DropProcedureStatement {
             if_exists: true,
             proc_desc: vec![FunctionDesc {
                 name: ObjectName::from(vec![Ident {
@@ -5527,13 +5527,13 @@
                 ]),
             }],
             drop_behavior: None
-        }
+        })
     );
 
     let sql = "DROP PROCEDURE IF EXISTS test_proc1(a INTEGER, IN b INTEGER = 1), test_proc2(a VARCHAR, IN b INTEGER = 1)";
     assert_eq!(
         pg().verified_stmt(sql),
-        Statement::DropProcedure {
+        Statement::DropProcedure(DropProcedureStatement {
             if_exists: true,
             proc_desc: vec![
                 FunctionDesc {
@@ -5574,7 +5574,7 @@
                 }
             ],
             drop_behavior: None
-        }
+        })
     );
 
     let res = pg().parse_sql_statements("DROP PROCEDURE testproc DROP");
@@ -7268,10 +7268,10 @@
     let sql = "CREATE TYPE public.my_type AS ENUM ('label1', 'label2', 'label3', 'label4')";
     let statement = pg_and_generic().verified_stmt(sql);
     match statement {
-        Statement::CreateType {
+        Statement::CreateType(CreateTypeStatement {
             name,
             representation: Some(UserDefinedTypeRepresentation::Enum { labels }),
-        } => {
+        }) => {
             assert_eq!("public.my_type", name.to_string());
             assert_eq!(
                 vec!["label1", "label2", "label3", "label4"]
diff --git a/tests/sqlparser_snowflake.rs b/tests/sqlparser_snowflake.rs
index ab6e242..dabc9b1 100644
--- a/tests/sqlparser_snowflake.rs
+++ b/tests/sqlparser_snowflake.rs
@@ -1693,18 +1693,18 @@
 #[test]
 fn test_drop_stage() {
     match snowflake_and_generic().verified_stmt("DROP STAGE s1") {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names, if_exists, ..
-        } => {
+        }) => {
             assert!(!if_exists);
             assert_eq!("s1", names[0].to_string());
         }
         _ => unreachable!(),
     };
     match snowflake_and_generic().verified_stmt("DROP STAGE IF EXISTS s1") {
-        Statement::Drop {
+        Statement::Drop(DropStatement {
             names, if_exists, ..
-        } => {
+        }) => {
             assert!(if_exists);
             assert_eq!("s1", names[0].to_string());
         }
@@ -1736,7 +1736,7 @@
         ),
     ] {
         match snowflake().verified_stmt(sql) {
-            Statement::Declare { mut stmts } => {
+            Statement::Declare(DeclareStatement { mut stmts }) => {
                 assert_eq!(1, stmts.len());
                 let Declare {
                     names,
@@ -1804,7 +1804,7 @@
         ("DECLARE res RESULTSET", "res", None),
     ] {
         match snowflake().verified_stmt(sql) {
-            Statement::Declare { mut stmts } => {
+            Statement::Declare(DeclareStatement { mut stmts }) => {
                 assert_eq!(1, stmts.len());
                 let Declare {
                     names,
@@ -1857,7 +1857,7 @@
         ("DECLARE ex EXCEPTION", "ex", None),
     ] {
         match snowflake().verified_stmt(sql) {
-            Statement::Declare { mut stmts } => {
+            Statement::Declare(DeclareStatement { mut stmts }) => {
                 assert_eq!(1, stmts.len());
                 let Declare {
                     names,
@@ -1897,7 +1897,7 @@
         ("DECLARE profit", "profit", None, None),
     ] {
         match snowflake().verified_stmt(sql) {
-            Statement::Declare { mut stmts } => {
+            Statement::Declare(DeclareStatement { mut stmts }) => {
                 assert_eq!(1, stmts.len());
                 let Declare {
                     names,
@@ -1947,7 +1947,7 @@
         "ex EXCEPTION (-20003, 'ERROR: Could not create table.')"
     );
     match snowflake().verified_stmt(sql) {
-        Statement::Declare { stmts } => {
+        Statement::Declare(DeclareStatement { stmts }) => {
             let actual = stmts
                 .iter()
                 .map(|stmt| (stmt.names[0].value.as_str(), stmt.declare_type.clone()))
@@ -1977,14 +1977,14 @@
 fn test_create_stage() {
     let sql = "CREATE STAGE s1.s2";
     match snowflake().verified_stmt(sql) {
-        Statement::CreateStage {
+        Statement::CreateStage(CreateStageStatement {
             or_replace,
             temporary,
             if_not_exists,
             name,
             comment,
             ..
-        } => {
+        }) => {
             assert!(!or_replace);
             assert!(!temporary);
             assert!(!if_not_exists);
@@ -2000,7 +2000,7 @@
         "COMMENT='some-comment'"
     );
     match snowflake().verified_stmt(extended_sql) {
-        Statement::CreateStage {
+        Statement::CreateStage(CreateStageStatement {
             or_replace,
             temporary,
             if_not_exists,
@@ -2008,7 +2008,7 @@
             stage_params,
             comment,
             ..
-        } => {
+        }) => {
             assert!(or_replace);
             assert!(temporary);
             assert!(if_not_exists);
@@ -2037,7 +2037,7 @@
     );
 
     match snowflake().verified_stmt(sql) {
-        Statement::CreateStage { stage_params, .. } => {
+        Statement::CreateStage(CreateStageStatement { stage_params, .. }) => {
             assert_eq!("s3://load/files/", stage_params.url.unwrap());
             assert_eq!("myint", stage_params.storage_integration.unwrap());
             assert_eq!(
@@ -2084,10 +2084,10 @@
     );
 
     match snowflake().verified_stmt(sql) {
-        Statement::CreateStage {
+        Statement::CreateStage(CreateStageStatement {
             directory_table_params,
             ..
-        } => {
+        }) => {
             assert!(directory_table_params.options.contains(&KeyValueOption {
                 option_name: "ENABLE".to_string(),
                 option_value: KeyValueOptionKind::Single(Value::Boolean(true).with_empty_span()),
@@ -2117,7 +2117,7 @@
     );
 
     match snowflake_without_unescape().verified_stmt(sql) {
-        Statement::CreateStage { file_format, .. } => {
+        Statement::CreateStage(CreateStageStatement { file_format, .. }) => {
             assert!(file_format.options.contains(&KeyValueOption {
                 option_name: "COMPRESSION".to_string(),
                 option_value: KeyValueOptionKind::Single(
@@ -2153,7 +2153,7 @@
         "COPY_OPTIONS=(ON_ERROR=CONTINUE FORCE=true)"
     );
     match snowflake().verified_stmt(sql) {
-        Statement::CreateStage { copy_options, .. } => {
+        Statement::CreateStage(CreateStageStatement { copy_options, .. }) => {
             assert!(copy_options.options.contains(&KeyValueOption {
                 option_name: "ON_ERROR".to_string(),
                 option_value: KeyValueOptionKind::Single(
@@ -2174,7 +2174,7 @@
 fn test_create_file_format() {
     let sql = "CREATE FILE FORMAT my_fmt";
     match snowflake().verified_stmt(sql) {
-        Statement::CreateFileFormat {
+        Statement::CreateFileFormat(CreateFileFormatStatement {
             or_replace,
             temporary,
             volatile,
@@ -2182,7 +2182,7 @@
             name,
             options,
             comment,
-        } => {
+        }) => {
             assert!(!or_replace);
             assert!(!temporary);
             assert!(!volatile);
@@ -2200,14 +2200,14 @@
         "COMMENT='some-comment'"
     );
     match snowflake().verified_stmt(extended_sql) {
-        Statement::CreateFileFormat {
+        Statement::CreateFileFormat(CreateFileFormatStatement {
             or_replace,
             temporary,
             if_not_exists,
             name,
             comment,
             ..
-        } => {
+        }) => {
             assert!(or_replace);
             assert!(temporary);
             assert!(if_not_exists);
@@ -2229,7 +2229,7 @@
         "TYPE=CSV FIELD_DELIMITER='|' SKIP_HEADER=1 COMPRESSION=GZIP"
     );
     match snowflake().verified_stmt(sql) {
-        Statement::CreateFileFormat { options, .. } => {
+        Statement::CreateFileFormat(CreateFileFormatStatement { options, .. }) => {
             assert!(options.options.contains(&KeyValueOption {
                 option_name: "TYPE".to_string(),
                 option_value: KeyValueOptionKind::Single(
@@ -2264,12 +2264,12 @@
 fn test_create_file_format_volatile() {
     let sql = "CREATE VOLATILE FILE FORMAT my_fmt TYPE=JSON STRIP_OUTER_ARRAY=true";
     match snowflake().verified_stmt(sql) {
-        Statement::CreateFileFormat {
+        Statement::CreateFileFormat(CreateFileFormatStatement {
             temporary,
             volatile,
             options,
             ..
-        } => {
+        }) => {
             assert!(!temporary);
             assert!(volatile);
             assert!(options.options.contains(&KeyValueOption {
@@ -2300,7 +2300,7 @@
         "FROM 'gcs://mybucket/./../a.csv'"
     );
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
             kind,
             into,
             from_obj,
@@ -2308,7 +2308,7 @@
             pattern,
             validation_mode,
             ..
-        } => {
+        }) => {
             assert_eq!(kind, CopyIntoSnowflakeKind::Table);
             assert_eq!(
                 into,
@@ -2331,14 +2331,14 @@
 
     let sql = concat!("COPY INTO 's3://a/b/c/data.parquet' ", "FROM db.sc.tbl ", "PARTITION BY ('date=' || to_varchar(dt, 'YYYY-MM-DD') || '/hour=' || to_varchar(date_part(hour, ts)))");
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
             kind,
             into,
             from_obj,
             from_query,
             partition,
             ..
-        } => {
+        }) => {
             assert_eq!(kind, CopyIntoSnowflakeKind::Location);
             assert_eq!(
                 into,
@@ -2364,13 +2364,13 @@
         "FROM (SELECT * FROM tbl)"
     );
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
             kind,
             into,
             from_obj,
             from_query,
             ..
-        } => {
+        }) => {
             assert_eq!(kind, CopyIntoSnowflakeKind::Location);
             assert_eq!(
                 into,
@@ -2396,11 +2396,11 @@
     );
 
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
             from_obj,
             stage_params,
             ..
-        } => {
+        }) => {
             //assert_eq!("s3://load/files/", stage_params.url.unwrap());
             assert_eq!(
                 from_obj,
@@ -2451,11 +2451,11 @@
     );
 
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
             from_obj,
             stage_params,
             ..
-        } => {
+        }) => {
             assert_eq!(
                 from_obj,
                 Some(ObjectName::from(vec![Ident::with_quote(
@@ -2480,13 +2480,13 @@
     );
 
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
             files,
             pattern,
             validation_mode,
             from_obj_alias,
             ..
-        } => {
+        }) => {
             assert_eq!(files.unwrap(), vec!["file1.json", "file2.json"]);
             assert_eq!(pattern.unwrap(), ".*employees0[1-5].csv.gz");
             assert_eq!(validation_mode.unwrap(), "RETURN_7_ROWS");
@@ -2508,11 +2508,11 @@
     );
 
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement {
             from_obj,
             from_transformations,
             ..
-        } => {
+        }) => {
             assert_eq!(
                 from_obj,
                 Some(ObjectName::from(vec![
@@ -2613,7 +2613,7 @@
     );
 
     match snowflake_without_unescape().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake { file_format, .. } => {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement { file_format, .. }) => {
             assert!(file_format.options.contains(&KeyValueOption {
                 option_name: "COMPRESSION".to_string(),
                 option_value: KeyValueOptionKind::Single(
@@ -2655,7 +2655,7 @@
         .first()
         .unwrap()
     {
-        Statement::CopyIntoSnowflake { file_format, .. } => {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement { file_format, .. }) => {
             assert!(file_format.options.contains(&KeyValueOption {
                 option_name: "COMPRESSION".to_string(),
                 option_value: KeyValueOptionKind::Single(
@@ -2690,7 +2690,7 @@
     );
 
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake { copy_options, .. } => {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement { copy_options, .. }) => {
             assert!(copy_options.options.contains(&KeyValueOption {
                 option_name: "ON_ERROR".to_string(),
                 option_value: KeyValueOptionKind::Single(
@@ -2735,7 +2735,7 @@
         let (formatted_name, object_name) = it;
         let sql = format!("COPY INTO {formatted_name} FROM 'gcs://mybucket/./../a.csv'");
         match snowflake().verified_stmt(&sql) {
-            Statement::CopyIntoSnowflake { into, .. } => {
+            Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement { into, .. }) => {
                 assert_eq!(into.0, object_name.0)
             }
             _ => unreachable!(),
@@ -2758,7 +2758,7 @@
         let (formatted_name, object_name) = it;
         let sql = format!("COPY INTO {formatted_name} FROM 'gcs://mybucket/./../a.csv'");
         match snowflake().verified_stmt(&sql) {
-            Statement::CopyIntoSnowflake { into, .. } => {
+            Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement { into, .. }) => {
                 assert_eq!(into.0, object_name.0)
             }
             _ => unreachable!(),
@@ -2771,7 +2771,7 @@
     let sql = "COPY INTO a.b FROM @namespace.stage_name";
     assert_eq!(snowflake().verified_stmt(sql).to_string(), sql);
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake { into, from_obj, .. } => {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement { into, from_obj, .. }) => {
             assert_eq!(
                 into,
                 ObjectName::from(vec![Ident::new("a"), Ident::new("b")])
@@ -2791,7 +2791,7 @@
     let sql = "COPY INTO a.b FROM @namespace.stage_name/x@x~x%x+/20250723_data-x";
     assert_eq!(snowflake().verified_stmt(sql).to_string(), sql);
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake { into, from_obj, .. } => {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement { into, from_obj, .. }) => {
             assert_eq!(
                 into,
                 ObjectName::from(vec![Ident::new("a"), Ident::new("b")])
@@ -2813,7 +2813,7 @@
     let sql = "COPY INTO SCHEMA.SOME_MONITORING_SYSTEM FROM (SELECT t.$1:st AS st FROM @schema.general_finished)";
     assert_eq!(snowflake().verified_stmt(sql).to_string(), sql);
     match snowflake().verified_stmt(sql) {
-        Statement::CopyIntoSnowflake { into, from_obj, .. } => {
+        Statement::CopyIntoSnowflake(CopyIntoSnowflakeStatement { into, from_obj, .. }) => {
             assert_eq!(
                 into,
                 ObjectName::from(vec![
@@ -3250,12 +3250,12 @@
 #[test]
 fn parse_explain_table() {
     match snowflake().verified_stmt("EXPLAIN TABLE test_identifier") {
-        Statement::ExplainTable {
+        Statement::ExplainTable(ExplainTableStatement {
             describe_alias,
             hive_format,
             has_table_keyword,
             table_name,
-        } => {
+        }) => {
             assert_eq!(describe_alias, DescribeAlias::Explain);
             assert_eq!(hive_format, None);
             assert_eq!(has_table_keyword, true);
@@ -3998,11 +3998,11 @@
 fn test_put() {
     let sql = "PUT 'file:///tmp/data.csv' @my_stage";
     match snowflake().verified_stmt(sql) {
-        Statement::Put {
+        Statement::Put(PutStatement {
             source,
             stage,
             options,
-        } => {
+        }) => {
             assert_eq!("file:///tmp/data.csv", source);
             assert_eq!(ObjectName::from(vec!["@my_stage".into()]), stage);
             assert!(options.options.is_empty());
@@ -4017,7 +4017,7 @@
     // Stage names can be quoted (e.g. Snowflake driver `write_pandas`)
     let sql = r#"PUT 'file:///tmp/data.csv' @"my stage" PARALLEL=4"#;
     match snowflake().verified_stmt(sql) {
-        Statement::Put { stage, .. } => {
+        Statement::Put(PutStatement { stage, .. }) => {
             assert_eq!(ObjectName::from(vec![r#"@"my stage""#.into()]), stage);
         }
         _ => unreachable!(),
@@ -4032,7 +4032,7 @@
         "PARALLEL=8 AUTO_COMPRESS=true SOURCE_COMPRESSION=GZIP OVERWRITE=false"
     );
     match snowflake().verified_stmt(sql) {
-        Statement::Put { options, .. } => {
+        Statement::Put(PutStatement { options, .. }) => {
             assert!(options.options.contains(&KeyValueOption {
                 option_name: "PARALLEL".to_string(),
                 option_value: KeyValueOptionKind::Single(
@@ -4461,7 +4461,7 @@
         .parse_sql_statements("ALTER SESSION SET QUERY_TAG='hello'; SELECT 42")
         .unwrap();
     match stmts[..] {
-        [Statement::AlterSession { .. }, Statement::Query { .. }] => {}
+        [Statement::AlterSession(AlterSessionStatement { .. }), Statement::Query { .. }] => {}
         _ => panic!("Unexpected statements: {stmts:?}"),
     }
 }
@@ -4541,7 +4541,7 @@
 "#;
 
     // Outer `BEGIN` of the two nested `BEGIN` statements.
-    let Statement::StartTransaction { mut statements, .. } = snowflake()
+    let Statement::StartTransaction(StartTransactionStatement { mut statements, .. }) = snowflake()
         .parse_sql_statements(sql)
         .unwrap()
         .pop()
@@ -4551,12 +4551,12 @@
     };
 
     // Inner `BEGIN` of the two nested `BEGIN` statements.
-    let Statement::StartTransaction {
+    let Statement::StartTransaction(StartTransactionStatement {
         statements,
         exception,
         has_end_keyword,
         ..
-    } = statements.pop().unwrap()
+    }) = statements.pop().unwrap()
     else {
         unreachable!();
     };
@@ -4736,7 +4736,7 @@
 
     // Using IDENTIFIER to reference a database
     match snowflake().verified_stmt("CREATE DATABASE IDENTIFIER('tbl')") {
-        Statement::CreateDatabase { db_name, .. } => {
+        Statement::CreateDatabase(CreateDatabaseStatement { db_name, .. }) => {
             assert_eq!(
                 db_name,
                 ObjectName(vec![ObjectNamePart::Function(ObjectNamePartFunction {
@@ -4752,7 +4752,7 @@
 
     // Using IDENTIFIER to reference a schema
     match snowflake().verified_stmt("CREATE SCHEMA IDENTIFIER('db1.sc1')") {
-        Statement::CreateSchema { schema_name, .. } => {
+        Statement::CreateSchema(CreateSchemaStatement { schema_name, .. }) => {
             assert_eq!(
                 schema_name,
                 SchemaName::Simple(ObjectName(vec![ObjectNamePart::Function(
diff --git a/tests/sqlparser_sqlite.rs b/tests/sqlparser_sqlite.rs
index a017562..000fb93 100644
--- a/tests/sqlparser_sqlite.rs
+++ b/tests/sqlparser_sqlite.rs
@@ -37,11 +37,11 @@
 fn pragma_no_value() {
     let sql = "PRAGMA cache_size";
     match sqlite_and_generic().verified_stmt(sql) {
-        Statement::Pragma {
+        Statement::Pragma(PragmaStatement {
             name,
             value: None,
             is_eq: false,
-        } => {
+        }) => {
             assert_eq!("cache_size", name.to_string());
         }
         _ => unreachable!(),
@@ -51,11 +51,11 @@
 fn pragma_eq_style() {
     let sql = "PRAGMA cache_size = 10";
     match sqlite_and_generic().verified_stmt(sql) {
-        Statement::Pragma {
+        Statement::Pragma(PragmaStatement {
             name,
             value: Some(val),
             is_eq: true,
-        } => {
+        }) => {
             assert_eq!("cache_size", name.to_string());
             assert_eq!("10", val.to_string());
         }
@@ -66,11 +66,11 @@
 fn pragma_function_style() {
     let sql = "PRAGMA cache_size(10)";
     match sqlite_and_generic().verified_stmt(sql) {
-        Statement::Pragma {
+        Statement::Pragma(PragmaStatement {
             name,
             value: Some(val),
             is_eq: false,
-        } => {
+        }) => {
             assert_eq!("cache_size", name.to_string());
             assert_eq!("10", val.to_string());
         }
@@ -82,11 +82,11 @@
 fn pragma_eq_string_style() {
     let sql = "PRAGMA table_info = 'sqlite_master'";
     match sqlite_and_generic().verified_stmt(sql) {
-        Statement::Pragma {
+        Statement::Pragma(PragmaStatement {
             name,
             value: Some(val),
             is_eq: true,
-        } => {
+        }) => {
             assert_eq!("table_info", name.to_string());
             assert_eq!("'sqlite_master'", val.to_string());
         }
@@ -98,11 +98,11 @@
 fn pragma_function_string_style() {
     let sql = "PRAGMA table_info(\"sqlite_master\")";
     match sqlite_and_generic().verified_stmt(sql) {
-        Statement::Pragma {
+        Statement::Pragma(PragmaStatement {
             name,
             value: Some(val),
             is_eq: false,
-        } => {
+        }) => {
             assert_eq!("table_info", name.to_string());
             assert_eq!("\"sqlite_master\"", val.to_string());
         }
@@ -114,11 +114,11 @@
 fn pragma_eq_placeholder_style() {
     let sql = "PRAGMA table_info = ?";
     match sqlite_and_generic().verified_stmt(sql) {
-        Statement::Pragma {
+        Statement::Pragma(PragmaStatement {
             name,
             value: Some(val),
             is_eq: true,
-        } => {
+        }) => {
             assert_eq!("table_info", name.to_string());
             assert_eq!("?", val.to_string());
         }
@@ -145,12 +145,12 @@
 fn parse_create_virtual_table() {
     let sql = "CREATE VIRTUAL TABLE IF NOT EXISTS t USING module_name (arg1, arg2)";
     match sqlite_and_generic().verified_stmt(sql) {
-        Statement::CreateVirtualTable {
+        Statement::CreateVirtualTable(CreateVirtualTableStatement {
             name,
             if_not_exists: true,
             module_name,
             module_args,
-        } => {
+        }) => {
             let args = vec![Ident::new("arg1"), Ident::new("arg2")];
             assert_eq!("t", name.to_string());
             assert_eq!("module_name", module_name.to_string());
@@ -457,7 +457,7 @@
     let verified_stmt = sqlite().verified_stmt(sql);
     assert_eq!(sql, format!("{verified_stmt}"));
     match verified_stmt {
-        Statement::AttachDatabase {
+        Statement::AttachDatabase(AttachDatabaseStatement {
             schema_name,
             database_file_name:
                 Expr::Value(ValueWithSpan {
@@ -465,7 +465,7 @@
                     span: _,
                 }),
             database: true,
-        } => {
+        }) => {
             assert_eq!(schema_name.value, "test");
             assert_eq!(literal_name, "test.db");
         }