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"); }