diff --git a/src/ast/comments.rs b/src/ast/comments.rs index 1f5b3102d..b398474b3 100644 --- a/src/ast/comments.rs +++ b/src/ast/comments.rs @@ -174,7 +174,16 @@ pub enum Comment { /// until end-of-line or end-of-file in the source code. /// /// Note: `content` will include the terminating new-line character, if any. - SingleLine { content: String, prefix: String }, + /// A single-line comment, typically introduced with a prefix and spanning + /// until end-of-line or end-of-file in the source code. + /// + /// Note: `content` will include the terminating new-line character, if any. + SingleLine { + /// The content of the comment (including trailing newline, if any). + content: String, + /// The prefix introducing the comment (e.g. `--`, `#`). + prefix: String, + }, /// A multi-line comment, typically enclosed in `/* .. */` markers. The /// string represents the content excluding the markers. diff --git a/src/ast/data_type.rs b/src/ast/data_type.rs index 6da6a90d0..535a52323 100644 --- a/src/ast/data_type.rs +++ b/src/ast/data_type.rs @@ -32,7 +32,9 @@ use super::{value::escape_single_quote_string, ColumnDef}; #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A member of an ENUM type. pub enum EnumMember { + /// Just a name. Name(String), /// ClickHouse allows to specify an integer value for each enum value. /// @@ -957,18 +959,31 @@ impl fmt::Display for TimezoneInfo { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum IntervalFields { + /// `YEAR` field Year, + /// `MONTH` field Month, + /// `DAY` field Day, + /// `HOUR` field Hour, + /// `MINUTE` field Minute, + /// `SECOND` field Second, + /// `YEAR TO MONTH` field YearToMonth, + /// `DAY TO HOUR` field DayToHour, + /// `DAY TO MINUTE` field DayToMinute, + /// `DAY TO SECOND` field DayToSecond, + /// `HOUR TO MINUTE` field HourToMinute, + /// `HOUR TO SECOND` field HourToSecond, + /// `MINUTE TO SECOND` field MinuteToSecond, } @@ -1000,11 +1015,11 @@ impl fmt::Display for IntervalFields { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ExactNumberInfo { - /// No additional information, e.g. `DECIMAL` + /// No additional information, e.g. `DECIMAL`. None, - /// Only precision information, e.g. `DECIMAL(10)` + /// Only precision information, e.g. `DECIMAL(10)`. Precision(u64), - /// Precision and scale information, e.g. `DECIMAL(10,2)` + /// Precision and scale information, e.g. `DECIMAL(10,2)`. PrecisionAndScale(u64, i64), } @@ -1031,13 +1046,14 @@ impl fmt::Display for ExactNumberInfo { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum CharacterLength { + /// Integer length with optional unit (e.g. `CHAR(10)` or `VARCHAR(10 CHARACTERS)`). IntegerLength { /// Default (if VARYING) or maximum (if not VARYING) length length: u64, /// Optional unit. If not informed, the ANSI handles it as CHARACTERS implicitly unit: Option, }, - /// VARCHAR(MAX) or NVARCHAR(MAX), used in T-SQL (Microsoft SQL Server) + /// VARCHAR(MAX) or NVARCHAR(MAX), used in T-SQL (Microsoft SQL Server). Max, } @@ -1087,12 +1103,16 @@ impl fmt::Display for CharLengthUnits { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Information about [binary length][1], including length and possibly unit. +/// +/// [1]: https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#binary-length pub enum BinaryLength { + /// Integer length for binary types (e.g. `VARBINARY(100)`). IntegerLength { /// Default (if VARYING) length: u64, }, - /// VARBINARY(MAX) used in T-SQL (Microsoft SQL Server) + /// VARBINARY(MAX) used in T-SQL (Microsoft SQL Server). Max, } @@ -1118,13 +1138,13 @@ impl fmt::Display for BinaryLength { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ArrayElemTypeDef { - /// `ARRAY` + /// Use `ARRAY` style without an explicit element type. None, - /// `ARRAY` + /// Angle-bracket style, e.g. `ARRAY`. AngleBracket(Box), - /// `INT[]` or `INT[2]` + /// Square-bracket style, e.g. `INT[]` or `INT[2]`. SquareBracket(Box, Option), - /// `Array(Int64)` + /// Parenthesis style, e.g. `Array(Int64)`. Parenthesis(Box), } @@ -1136,12 +1156,19 @@ pub enum ArrayElemTypeDef { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum GeometricTypeKind { + /// Point geometry Point, + /// Line geometry Line, + /// Line segment geometry LineSegment, + /// Box geometry GeometricBox, + /// Path geometry GeometricPath, + /// Polygon geometry Polygon, + /// Circle geometry Circle, } diff --git a/src/ast/dcl.rs b/src/ast/dcl.rs index d04875a73..7183bc3fb 100644 --- a/src/ast/dcl.rs +++ b/src/ast/dcl.rs @@ -39,15 +39,25 @@ use crate::tokenizer::Span; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum RoleOption { + /// Enable or disable BYPASSRLS. BypassRLS(bool), + /// Connection limit expression. ConnectionLimit(Expr), + /// CREATEDB flag. CreateDB(bool), + /// CREATEROLE flag. CreateRole(bool), + /// INHERIT flag. Inherit(bool), + /// LOGIN flag. Login(bool), + /// Password value or NULL password. Password(Password), + /// Replication privilege flag. Replication(bool), + /// SUPERUSER flag. SuperUser(bool), + /// `VALID UNTIL` expression. ValidUntil(Expr), } @@ -104,8 +114,11 @@ impl fmt::Display for RoleOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum SetConfigValue { + /// Use the default value. Default, + /// Use the current value (`FROM CURRENT`). FromCurrent, + /// Set to the provided expression value. Value(Expr), } @@ -116,7 +129,9 @@ pub enum SetConfigValue { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ResetConfig { + /// Reset all configuration parameters. ALL, + /// Reset the named configuration parameter. ConfigName(ObjectName), } @@ -127,28 +142,48 @@ pub enum ResetConfig { pub enum AlterRoleOperation { /// Generic RenameRole { + /// Role name to rename. role_name: Ident, }, /// MS SQL Server /// AddMember { + /// Member name to add to the role. member_name: Ident, }, + /// MS SQL Server + /// + /// DropMember { + /// Member name to remove from the role. member_name: Ident, }, /// PostgreSQL /// WithOptions { + /// Role options to apply. options: Vec, }, + /// PostgreSQL + /// + /// + /// `SET configuration_parameter { TO | = } { value | DEFAULT }` Set { + /// Configuration name to set. config_name: ObjectName, + /// Value to assign to the configuration. config_value: SetConfigValue, + /// Optional database scope for the setting. in_database: Option, }, + /// PostgreSQL + /// + /// + /// `RESET configuration_parameter` | `RESET ALL` Reset { + /// Configuration to reset. config_name: ResetConfig, + /// Optional database scope for the reset. in_database: Option, }, } @@ -205,14 +240,22 @@ impl fmt::Display for AlterRoleOperation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum Use { - Catalog(ObjectName), // e.g. `USE CATALOG foo.bar` - Schema(ObjectName), // e.g. `USE SCHEMA foo.bar` - Database(ObjectName), // e.g. `USE DATABASE foo.bar` - Warehouse(ObjectName), // e.g. `USE WAREHOUSE foo.bar` - Role(ObjectName), // e.g. `USE ROLE PUBLIC` - SecondaryRoles(SecondaryRoles), // e.g. `USE SECONDARY ROLES ALL` - Object(ObjectName), // e.g. `USE foo.bar` - Default, // e.g. `USE DEFAULT` + /// Switch to the given catalog (e.g. `USE CATALOG ...`). + Catalog(ObjectName), + /// Switch to the given schema (e.g. `USE SCHEMA ...`). + Schema(ObjectName), + /// Switch to the given database (e.g. `USE DATABASE ...`). + Database(ObjectName), + /// Switch to the given warehouse (e.g. `USE WAREHOUSE ...`). + Warehouse(ObjectName), + /// Switch to the given role (e.g. `USE ROLE ...`). + Role(ObjectName), + /// Use secondary roles specification (e.g. `USE SECONDARY ROLES ...`). + SecondaryRoles(SecondaryRoles), + /// Use the specified object (e.g. `USE foo.bar`). + Object(ObjectName), + /// Reset to default (e.g. `USE DEFAULT`). + Default, } impl fmt::Display for Use { @@ -239,8 +282,11 @@ impl fmt::Display for Use { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum SecondaryRoles { + /// Use all secondary roles. All, + /// Use no secondary roles. None, + /// Explicit list of secondary roles. List(Vec), } @@ -260,25 +306,43 @@ impl fmt::Display for SecondaryRoles { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateRole { + /// Role names to create. pub names: Vec, + /// Whether `IF NOT EXISTS` was specified. pub if_not_exists: bool, // Postgres + /// Whether `LOGIN` was specified. pub login: Option, + /// Whether `INHERIT` was specified. pub inherit: Option, + /// Whether `BYPASSRLS` was specified. pub bypassrls: Option, + /// Optional password for the role. pub password: Option, + /// Whether `SUPERUSER` was specified. pub superuser: Option, + /// Whether `CREATEDB` was specified. pub create_db: Option, + /// Whether `CREATEROLE` was specified. pub create_role: Option, + /// Whether `REPLICATION` privilege was specified. pub replication: Option, + /// Optional connection limit expression. pub connection_limit: Option, + /// Optional account validity expression. pub valid_until: Option, + /// Members of `IN ROLE` clause. pub in_role: Vec, + /// Members of `IN GROUP` clause. pub in_group: Vec, + /// Roles listed in `ROLE` clause. pub role: Vec, + /// Users listed in `USER` clause. pub user: Vec, + /// Admin users listed in `ADMIN` clause. pub admin: Vec, // MSSQL + /// Optional authorization owner. pub authorization_owner: Option, } diff --git a/src/ast/ddl.rs b/src/ast/ddl.rs index 4e042a365..be2b38710 100644 --- a/src/ast/ddl.rs +++ b/src/ast/ddl.rs @@ -60,7 +60,9 @@ use crate::tokenizer::{Span, Token}; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct IndexColumn { + /// The indexed column expression. pub column: OrderByExpr, + /// Optional operator class (index operator name). pub operator_class: Option, } @@ -96,9 +98,13 @@ impl fmt::Display for IndexColumn { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ReplicaIdentity { + /// No replica identity (`REPLICA IDENTITY NONE`). None, + /// Full replica identity (`REPLICA IDENTITY FULL`). Full, + /// Default replica identity (`REPLICA IDENTITY DEFAULT`). Default, + /// Use the given index as replica identity (`REPLICA IDENTITY USING INDEX`). Index(Ident), } @@ -120,7 +126,9 @@ impl fmt::Display for ReplicaIdentity { pub enum AlterTableOperation { /// `ADD [NOT VALID]` AddConstraint { + /// The table constraint to add. constraint: TableConstraint, + /// Whether the constraint should be marked `NOT VALID`. not_valid: bool, }, /// `ADD [COLUMN] [IF NOT EXISTS] ` @@ -139,8 +147,11 @@ pub enum AlterTableOperation { /// Note: this is a ClickHouse-specific operation. /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#add-projection) AddProjection { + /// Whether `IF NOT EXISTS` was specified. if_not_exists: bool, + /// Name of the projection to add. name: Ident, + /// The projection's select clause. select: ProjectionSelect, }, /// `DROP PROJECTION [IF EXISTS] name` @@ -148,7 +159,9 @@ pub enum AlterTableOperation { /// Note: this is a ClickHouse-specific operation. /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#drop-projection) DropProjection { + /// Whether `IF EXISTS` was specified. if_exists: bool, + /// Name of the projection to drop. name: Ident, }, /// `MATERIALIZE PROJECTION [IF EXISTS] name [IN PARTITION partition_name]` @@ -156,8 +169,11 @@ pub enum AlterTableOperation { /// Note: this is a ClickHouse-specific operation. /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#materialize-projection) MaterializeProjection { + /// Whether `IF EXISTS` was specified. if_exists: bool, + /// Name of the projection to materialize. name: Ident, + /// Optional partition name to operate on. partition: Option, }, /// `CLEAR PROJECTION [IF EXISTS] name [IN PARTITION partition_name]` @@ -165,8 +181,11 @@ pub enum AlterTableOperation { /// Note: this is a ClickHouse-specific operation. /// Please refer to [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/projection#clear-projection) ClearProjection { + /// Whether `IF EXISTS` was specified. if_exists: bool, + /// Name of the projection to clear. name: Ident, + /// Optional partition name to operate on. partition: Option, }, /// `DISABLE ROW LEVEL SECURITY` @@ -177,25 +196,34 @@ pub enum AlterTableOperation { /// /// Note: this is a PostgreSQL-specific operation. DisableRule { + /// Name of the rule to disable. name: Ident, }, /// `DISABLE TRIGGER [ trigger_name | ALL | USER ]` /// /// Note: this is a PostgreSQL-specific operation. DisableTrigger { + /// Name of the trigger to disable (or ALL/USER). name: Ident, }, /// `DROP CONSTRAINT [ IF EXISTS ] ` DropConstraint { + /// `IF EXISTS` flag for dropping the constraint. if_exists: bool, + /// Name of the constraint to drop. name: Ident, + /// Optional drop behavior (`CASCADE`/`RESTRICT`). drop_behavior: Option, }, /// `DROP [ COLUMN ] [ IF EXISTS ] [ , , ... ] [ CASCADE ]` DropColumn { + /// Whether the `COLUMN` keyword was present. has_column_keyword: bool, + /// Names of columns to drop. column_names: Vec, + /// Whether `IF EXISTS` was specified for the columns. if_exists: bool, + /// Optional drop behavior for the column removal. drop_behavior: Option, }, /// `ATTACH PART|PARTITION ` @@ -204,6 +232,7 @@ pub enum AlterTableOperation { AttachPartition { // PART is not a short form of PARTITION, it's a separate keyword // which represents a physical file on disk and partition is a logical entity. + /// Partition expression to attach. partition: Partition, }, /// `DETACH PART|PARTITION ` @@ -211,20 +240,25 @@ pub enum AlterTableOperation { /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#detach-partitionpart) DetachPartition { // See `AttachPartition` for more details + /// Partition expression to detach. partition: Partition, }, /// `FREEZE PARTITION ` /// Note: this is a ClickHouse-specific operation, please refer to /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#freeze-partition) FreezePartition { + /// Partition to freeze. partition: Partition, + /// Optional name for the freeze operation. with_name: Option, }, /// `UNFREEZE PARTITION ` /// Note: this is a ClickHouse-specific operation, please refer to /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#unfreeze-partition) UnfreezePartition { + /// Partition to unfreeze. partition: Partition, + /// Optional name associated with the unfreeze operation. with_name: Option, }, /// `DROP PRIMARY KEY` @@ -232,6 +266,7 @@ pub enum AlterTableOperation { /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/alter-table.html) /// [Snowflake](https://docs.snowflake.com/en/sql-reference/constraints-drop) DropPrimaryKey { + /// Optional drop behavior for the primary key (`CASCADE`/`RESTRICT`). drop_behavior: Option, }, /// `DROP FOREIGN KEY ` @@ -239,37 +274,44 @@ pub enum AlterTableOperation { /// [MySQL](https://dev.mysql.com/doc/refman/8.4/en/alter-table.html) /// [Snowflake](https://docs.snowflake.com/en/sql-reference/constraints-drop) DropForeignKey { + /// Foreign key symbol/name to drop. name: Ident, + /// Optional drop behavior for the foreign key. drop_behavior: Option, }, /// `DROP INDEX ` /// /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html DropIndex { + /// Name of the index to drop. name: Ident, }, /// `ENABLE ALWAYS RULE rewrite_rule_name` /// /// Note: this is a PostgreSQL-specific operation. EnableAlwaysRule { + /// Name of the rule to enable. name: Ident, }, /// `ENABLE ALWAYS TRIGGER trigger_name` /// /// Note: this is a PostgreSQL-specific operation. EnableAlwaysTrigger { + /// Name of the trigger to enable. name: Ident, }, /// `ENABLE REPLICA RULE rewrite_rule_name` /// /// Note: this is a PostgreSQL-specific operation. EnableReplicaRule { + /// Name of the replica rule to enable. name: Ident, }, /// `ENABLE REPLICA TRIGGER trigger_name` /// /// Note: this is a PostgreSQL-specific operation. EnableReplicaTrigger { + /// Name of the replica trigger to enable. name: Ident, }, /// `ENABLE ROW LEVEL SECURITY` @@ -280,17 +322,21 @@ pub enum AlterTableOperation { /// /// Note: this is a PostgreSQL-specific operation. EnableRule { + /// Name of the rule to enable. name: Ident, }, /// `ENABLE TRIGGER [ trigger_name | ALL | USER ]` /// /// Note: this is a PostgreSQL-specific operation. EnableTrigger { + /// Name of the trigger to enable (or ALL/USER). name: Ident, }, /// `RENAME TO PARTITION (partition=val)` RenamePartitions { + /// Old partition expressions to be renamed. old_partitions: Vec, + /// New partition expressions corresponding to the old ones. new_partitions: Vec, }, /// REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING } @@ -298,78 +344,109 @@ pub enum AlterTableOperation { /// Note: this is a PostgreSQL-specific operation. /// Please refer to [PostgreSQL documentation](https://www.postgresql.org/docs/current/sql-altertable.html) ReplicaIdentity { + /// Replica identity setting to apply. identity: ReplicaIdentity, }, /// Add Partitions AddPartitions { + /// Whether `IF NOT EXISTS` was present when adding partitions. if_not_exists: bool, + /// New partitions to add. new_partitions: Vec, }, + /// `DROP PARTITIONS ...` / drop partitions from the table. DropPartitions { + /// Partitions to drop (expressions). partitions: Vec, + /// Whether `IF EXISTS` was specified for dropping partitions. if_exists: bool, }, /// `RENAME [ COLUMN ] TO ` RenameColumn { + /// Existing column name to rename. old_column_name: Ident, + /// New column name. new_column_name: Ident, }, /// `RENAME TO ` RenameTable { + /// The new table name or renaming kind. table_name: RenameTableNameKind, }, // CHANGE [ COLUMN ] [ ] + /// Change an existing column's name, type, and options. ChangeColumn { + /// Old column name. old_name: Ident, + /// New column name. new_name: Ident, + /// New data type for the column. data_type: DataType, + /// Column options to apply after the change. options: Vec, - /// MySQL `ALTER TABLE` only [FIRST | AFTER column_name] + /// MySQL-specific column position (`FIRST`/`AFTER`). column_position: Option, }, // CHANGE [ COLUMN ] [ ] + /// Modify an existing column's type and options. ModifyColumn { + /// Column name to modify. col_name: Ident, + /// New data type for the column. data_type: DataType, + /// Column options to set. options: Vec, - /// MySQL `ALTER TABLE` only [FIRST | AFTER column_name] + /// MySQL-specific column position (`FIRST`/`AFTER`). column_position: Option, }, /// `RENAME CONSTRAINT TO ` /// /// Note: this is a PostgreSQL-specific operation. + /// Rename a constraint on the table. RenameConstraint { + /// Existing constraint name. old_name: Ident, + /// New constraint name. new_name: Ident, }, /// `ALTER [ COLUMN ]` + /// Alter a specific column with the provided operation. AlterColumn { + /// The column to alter. column_name: Ident, + /// Operation to apply to the column. op: AlterColumnOperation, }, /// 'SWAP WITH ' /// /// Note: this is Snowflake specific SwapWith { + /// Table name to swap with. table_name: ObjectName, }, /// 'SET TBLPROPERTIES ( { property_key [ = ] property_val } [, ...] )' SetTblProperties { + /// Table properties specified as SQL options. table_properties: Vec, }, /// `OWNER TO { | CURRENT_ROLE | CURRENT_USER | SESSION_USER }` /// /// Note: this is PostgreSQL-specific OwnerTo { + /// The new owner to assign to the table. new_owner: Owner, }, /// Snowflake table clustering options /// ClusterBy { + /// Expressions used for clustering the table. exprs: Vec, }, + /// Remove the clustering key from the table. DropClusteringKey, + /// Suspend background reclustering operations. SuspendRecluster, + /// Resume background reclustering operations. ResumeRecluster, /// `REFRESH [ '' ]` /// @@ -394,7 +471,9 @@ pub enum AlterTableOperation { /// /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html Algorithm { + /// Whether the `=` sign was used (`ALGORITHM = ...`). equals: bool, + /// The algorithm to use for the alter operation (MySQL-specific). algorithm: AlterTableAlgorithm, }, @@ -404,7 +483,9 @@ pub enum AlterTableOperation { /// /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html Lock { + /// Whether the `=` sign was used (`LOCK = ...`). equals: bool, + /// The locking behavior to apply (MySQL-specific). lock: AlterTableLock, }, /// `AUTO_INCREMENT [=] ` @@ -413,11 +494,14 @@ pub enum AlterTableOperation { /// /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html AutoIncrement { + /// Whether the `=` sign was used (`AUTO_INCREMENT = ...`). equals: bool, + /// Value to set for the auto-increment counter. value: ValueWithSpan, }, /// `VALIDATE CONSTRAINT ` ValidateConstraint { + /// Name of the constraint to validate. name: Ident, }, /// Arbitrary parenthesized `SET` options. @@ -428,6 +512,7 @@ pub enum AlterTableOperation { /// ``` /// [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertable.html) SetOptionsParens { + /// Parenthesized options supplied to `SET (...)`. options: Vec, }, } @@ -439,12 +524,18 @@ pub enum AlterTableOperation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum AlterPolicyOperation { + /// Rename the policy to `new_name`. Rename { + /// The new identifier for the policy. new_name: Ident, }, + /// Apply/modify policy properties. Apply { + /// Optional list of owners the policy applies to. to: Option>, + /// Optional `USING` expression for the policy. using: Option, + /// Optional `WITH CHECK` expression for the policy. with_check: Option, }, } @@ -481,10 +572,15 @@ impl fmt::Display for AlterPolicyOperation { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Algorithm option for `ALTER TABLE` operations (MySQL-specific). pub enum AlterTableAlgorithm { + /// Default algorithm selection. Default, + /// `INSTANT` algorithm. Instant, + /// `INPLACE` algorithm. Inplace, + /// `COPY` algorithm. Copy, } @@ -505,10 +601,15 @@ impl fmt::Display for AlterTableAlgorithm { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Locking behavior for `ALTER TABLE` (MySQL-specific). pub enum AlterTableLock { + /// `DEFAULT` lock behavior. Default, + /// `NONE` lock. None, + /// `SHARED` lock. Shared, + /// `EXCLUSIVE` lock. Exclusive, } @@ -526,10 +627,15 @@ impl fmt::Display for AlterTableLock { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// New owner specification for `ALTER TABLE ... OWNER TO ...` pub enum Owner { + /// A specific user/role identifier. Ident(Ident), + /// `CURRENT_ROLE` keyword. CurrentRole, + /// `CURRENT_USER` keyword. CurrentUser, + /// `SESSION_USER` keyword. SessionUser, } @@ -547,8 +653,11 @@ impl fmt::Display for Owner { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// New connector owner specification for `ALTER CONNECTOR ... OWNER TO ...` pub enum AlterConnectorOwner { + /// `USER ` connector owner. User(Ident), + /// `ROLE ` connector owner. Role(Ident), } @@ -564,8 +673,13 @@ impl fmt::Display for AlterConnectorOwner { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Alterations that can be applied to an index. pub enum AlterIndexOperation { - RenameIndex { index_name: ObjectName }, + /// Rename the index to `index_name`. + RenameIndex { + /// The new name for the index. + index_name: ObjectName, + }, } impl fmt::Display for AlterTableOperation { @@ -920,7 +1034,9 @@ impl fmt::Display for AlterIndexOperation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterType { + /// Name of the type being altered (may be schema-qualified). pub name: ObjectName, + /// The specific alteration operation to perform. pub operation: AlterTypeOperation, } @@ -929,8 +1045,11 @@ pub struct AlterType { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum AlterTypeOperation { + /// Rename the type. Rename(AlterTypeRename), + /// Add a new value to the type (for enum-like types). AddValue(AlterTypeAddValue), + /// Rename an existing value of the type. RenameValue(AlterTypeRenameValue), } @@ -939,6 +1058,7 @@ pub enum AlterTypeOperation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterTypeRename { + /// The new name for the type. pub new_name: Ident, } @@ -947,8 +1067,11 @@ pub struct AlterTypeRename { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterTypeAddValue { + /// If true, do not error when the value already exists (`IF NOT EXISTS`). pub if_not_exists: bool, + /// The identifier for the new value to add. pub value: Ident, + /// Optional relative position for the new value (`BEFORE` / `AFTER`). pub position: Option, } @@ -957,7 +1080,9 @@ pub struct AlterTypeAddValue { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum AlterTypeAddValuePosition { + /// Place the new value before the given neighbor value. Before(Ident), + /// Place the new value after the given neighbor value. After(Ident), } @@ -966,7 +1091,9 @@ pub enum AlterTypeAddValuePosition { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterTypeRenameValue { + /// Existing value identifier to rename. pub from: Ident, + /// New identifier for the value. pub to: Ident, } @@ -1028,7 +1155,11 @@ pub enum AlterOperatorOperation { /// `OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }` OwnerTo(Owner), /// `SET SCHEMA new_schema` - SetSchema { schema_name: ObjectName }, + /// Set the operator's schema name. + SetSchema { + /// New schema name for the operator + schema_name: ObjectName, + }, /// `SET ( options )` Set { /// List of operator options to set @@ -1111,15 +1242,20 @@ pub enum AlterColumnOperation { /// `DROP NOT NULL` DropNotNull, /// `SET DEFAULT ` - SetDefault { value: Expr }, + /// Set the column default value. + SetDefault { + /// Expression representing the new default value. + value: Expr, + }, /// `DROP DEFAULT` DropDefault, /// `[SET DATA] TYPE [USING ]` SetDataType { + /// Target data type for the column. data_type: DataType, - /// PostgreSQL specific + /// PostgreSQL-specific `USING ` expression for conversion. using: Option, - /// Set to true if the statement includes the `SET DATA TYPE` keywords + /// Set to true if the statement includes the `SET DATA TYPE` keywords. had_set: bool, }, @@ -1127,7 +1263,9 @@ pub enum AlterColumnOperation { /// /// Note: this is a PostgreSQL-specific operation. AddGenerated { + /// Optional `GENERATED AS` specifier (e.g. `ALWAYS` or `BY DEFAULT`). generated_as: Option, + /// Optional sequence options for identity generation. sequence_options: Option>, }, } @@ -1203,6 +1341,7 @@ pub enum KeyOrIndexDisplay { } impl KeyOrIndexDisplay { + /// Check if this is the `None` variant. pub fn is_none(self) -> bool { matches!(self, Self::None) } @@ -1242,12 +1381,19 @@ impl fmt::Display for KeyOrIndexDisplay { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum IndexType { + /// B-Tree index (commonly default for many databases). BTree, + /// Hash index. Hash, + /// Generalized Inverted Index (GIN). GIN, + /// Generalized Search Tree (GiST) index. GiST, + /// Space-partitioned GiST (SPGiST) index. SPGiST, + /// Block Range Index (BRIN). BRIN, + /// Bloom filter based index. Bloom, /// Users may define their own index types, which would /// not be covered by the above variants. @@ -1323,10 +1469,15 @@ impl fmt::Display for NullsDistinctOption { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A parameter of a stored procedure or function declaration. pub struct ProcedureParam { + /// Parameter name. pub name: Ident, + /// Parameter data type. pub data_type: DataType, + /// Optional mode (`IN`, `OUT`, `INOUT`, etc.). pub mode: Option, + /// Optional default expression for the parameter. pub default: Option, } @@ -1351,8 +1502,11 @@ impl fmt::Display for ProcedureParam { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ColumnDef { + /// Column name. pub name: Ident, + /// Column data type. pub data_type: DataType, + /// Column options (defaults, constraints, generated, etc.). pub options: Vec, } @@ -1390,20 +1544,27 @@ impl fmt::Display for ColumnDef { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ViewColumnDef { + /// Column identifier. pub name: Ident, + /// Optional data type for the column. pub data_type: Option, + /// Optional column options (defaults, comments, etc.). pub options: Option, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Representation of how multiple `ColumnOption`s are grouped for a column. pub enum ColumnOptions { + /// Options separated by comma: `OPTIONS(a, b, c)`. CommaSeparated(Vec), + /// Options separated by spaces: `OPTION_A OPTION_B`. SpaceSeparated(Vec), } impl ColumnOptions { + /// Get the column options as a slice. pub fn as_slice(&self) -> &[ColumnOption] { match self { ColumnOptions::CommaSeparated(options) => options.as_slice(), @@ -1452,7 +1613,9 @@ impl fmt::Display for ViewColumnDef { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ColumnOptionDef { + /// Optional name of the constraint. pub name: Option, + /// The actual column option (e.g. `NOT NULL`, `DEFAULT`, `GENERATED`, ...). pub option: ColumnOption, } @@ -1513,11 +1676,14 @@ impl fmt::Display for IdentityPropertyKind { } } +/// Properties for the `IDENTITY` / `AUTOINCREMENT` column option. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct IdentityProperty { + /// Optional parameters specifying seed/increment for the identity column. pub parameters: Option, + /// Optional ordering specifier (`ORDER` / `NOORDER`). pub order: Option, } @@ -1572,11 +1738,14 @@ impl fmt::Display for IdentityPropertyFormatKind { } } } +/// Parameters specifying seed and increment for identity columns. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct IdentityParameters { + /// The initial seed expression for the identity column. pub seed: Expr, + /// The increment expression for the identity column. pub increment: Expr, } @@ -1590,7 +1759,9 @@ pub struct IdentityParameters { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum IdentityPropertyOrder { + /// `ORDER` - preserve ordering for generated values (where supported). Order, + /// `NOORDER` - do not enforce ordering for generated values. NoOrder, } @@ -1614,7 +1785,9 @@ impl fmt::Display for IdentityPropertyOrder { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ColumnPolicy { + /// `MASKING POLICY ()` MaskingPolicy(ColumnPolicyProperty), + /// `PROJECTION POLICY ()` ProjectionPolicy(ColumnPolicyProperty), } @@ -1638,6 +1811,7 @@ impl fmt::Display for ColumnPolicy { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Properties describing a column policy (masking or projection). pub struct ColumnPolicyProperty { /// This flag indicates that the column policy option is declared using the `WITH` prefix. /// Example @@ -1646,7 +1820,9 @@ pub struct ColumnPolicyProperty { /// ``` /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table pub with: bool, + /// The name of the policy to apply to the column. pub policy_name: ObjectName, + /// Optional list of column identifiers referenced by the policy. pub using_columns: Option>, } @@ -1667,6 +1843,7 @@ pub struct TagsColumnOption { /// ``` /// [Snowflake]: https://docs.snowflake.com/en/sql-reference/sql/create-table pub with: bool, + /// List of tags to attach to the column. pub tags: Vec, } @@ -1725,16 +1902,24 @@ pub enum ColumnOption { /// - MySQL's `AUTO_INCREMENT` or SQLite's `AUTOINCREMENT` /// - ... DialectSpecific(Vec), + /// `CHARACTER SET ` column option CharacterSet(ObjectName), + /// `COLLATE ` column option Collation(ObjectName), + /// `COMMENT ''` column option Comment(String), + /// `ON UPDATE ` column option OnUpdate(Expr), /// `Generated`s are modifiers that follow a column definition in a `CREATE /// TABLE` statement. Generated { + /// How the column is generated (e.g. `GENERATED ALWAYS`, `BY DEFAULT`, or expression-stored). generated_as: GeneratedAs, + /// Sequence/identity options when generation is backed by a sequence. sequence_options: Option>, + /// Optional expression used to generate the column value. generation_expr: Option, + /// Mode of the generated expression (`VIRTUAL` or `STORED`) when `generation_expr` is present. generation_expr_mode: Option, /// false if 'GENERATED ALWAYS' is skipped (option starts with AS) generated_keyword: bool, @@ -1946,8 +2131,11 @@ impl fmt::Display for ColumnOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum GeneratedAs { + /// `GENERATED ALWAYS` Always, + /// `GENERATED BY DEFAULT` ByDefault, + /// Expression-based generated column that is stored (used internally for expression-stored columns) ExpStored, } @@ -1957,7 +2145,9 @@ pub enum GeneratedAs { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum GeneratedExpressionMode { + /// `VIRTUAL` generated expression Virtual, + /// `STORED` generated expression Stored, } @@ -2020,6 +2210,7 @@ pub struct ConstraintCharacteristics { pub enforced: Option, } +/// Initial setting for deferrable constraints (`INITIALLY IMMEDIATE` or `INITIALLY DEFERRED`). #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] @@ -2091,10 +2282,15 @@ impl fmt::Display for ConstraintCharacteristics { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ReferentialAction { + /// `RESTRICT` - disallow action if it would break referential integrity. Restrict, + /// `CASCADE` - propagate the action to referencing rows. Cascade, + /// `SET NULL` - set referencing columns to NULL. SetNull, + /// `NO ACTION` - no action at the time; may be deferred. NoAction, + /// `SET DEFAULT` - set referencing columns to their default values. SetDefault, } @@ -2117,7 +2313,9 @@ impl fmt::Display for ReferentialAction { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum DropBehavior { + /// `RESTRICT` - refuse to drop if there are any dependent objects. Restrict, + /// `CASCADE` - automatically drop objects that depend on the object being dropped. Cascade, } @@ -2137,16 +2335,22 @@ impl fmt::Display for DropBehavior { pub enum UserDefinedTypeRepresentation { /// Composite type: `CREATE TYPE name AS (attributes)` Composite { + /// List of attributes for the composite type. attributes: Vec, }, /// Enum type: `CREATE TYPE name AS ENUM (labels)` /// /// Note: this is PostgreSQL-specific. See - Enum { labels: Vec }, + /// Enum type: `CREATE TYPE name AS ENUM (labels)` + Enum { + /// Labels that make up the enum type. + labels: Vec, + }, /// Range type: `CREATE TYPE name AS RANGE (options)` /// /// Note: this is PostgreSQL-specific. See Range { + /// Options for the range type definition. options: Vec, }, /// Base type (SQL definition): `CREATE TYPE name (options)` @@ -2155,6 +2359,7 @@ pub enum UserDefinedTypeRepresentation { /// /// Note: this is PostgreSQL-specific. See SqlDefinition { + /// Options for SQL definition of the user-defined type. options: Vec, }, } @@ -2183,8 +2388,11 @@ impl fmt::Display for UserDefinedTypeRepresentation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct UserDefinedTypeCompositeAttributeDef { + /// Attribute name. pub name: Ident, + /// Attribute data type. pub data_type: DataType, + /// Optional collation for the attribute. pub collation: Option, } @@ -2487,11 +2695,14 @@ impl fmt::Display for UserDefinedTypeSqlDefinitionOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum Partition { + /// ClickHouse supports PARTITION ID 'partition_id' syntax. Identifier(Ident), + /// ClickHouse supports PARTITION expr syntax. Expr(Expr), /// ClickHouse supports PART expr which represents physical partition in disk. /// [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/alter/partition#attach-partitionpart) Part(Expr), + /// Hive supports multiple partitions in PARTITION (part1, part2, ...) syntax. Partitions(Vec), } @@ -2514,7 +2725,9 @@ impl fmt::Display for Partition { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum Deduplicate { + /// DEDUPLICATE ALL All, + /// DEDUPLICATE BY expr ByExpression(Expr), } @@ -2535,8 +2748,11 @@ impl fmt::Display for Deduplicate { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ClusteredBy { + /// columns used for clustering pub columns: Vec, + /// optional sorted by expressions pub sorted_by: Option>, + /// number of buckets pub num_buckets: Value, } @@ -2562,19 +2778,28 @@ pub struct CreateIndex { /// index name pub name: Option, #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] + /// table name pub table_name: ObjectName, /// Index type used in the statement. Can also be found inside [`CreateIndex::index_options`] /// depending on the position of the option within the statement. pub using: Option, + /// columns included in the index pub columns: Vec, + /// whether the index is unique pub unique: bool, + /// whether the index is created concurrently pub concurrently: bool, + /// IF NOT EXISTS clause pub if_not_exists: bool, + /// INCLUDE clause: pub include: Vec, + /// NULLS DISTINCT / NOT DISTINCT clause: pub nulls_distinct: Option, /// WITH clause: pub with: Vec, + /// WHERE clause: pub predicate: Option, + /// Index options: pub index_options: Vec, /// [MySQL] allows a subset of options normally used for `ALTER TABLE`: /// @@ -2641,35 +2866,57 @@ impl fmt::Display for CreateIndex { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateTable { + /// `OR REPLACE` clause pub or_replace: bool, + /// `TEMP` or `TEMPORARY` clause pub temporary: bool, + /// `EXTERNAL` clause pub external: bool, + /// `DYNAMIC` clause pub dynamic: bool, + /// `GLOBAL` clause pub global: Option, + /// `IF NOT EXISTS` clause pub if_not_exists: bool, + /// `TRANSIENT` clause pub transient: bool, + /// `VOLATILE` clause pub volatile: bool, + /// `ICEBERG` clause pub iceberg: bool, /// Table name #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] pub name: ObjectName, - /// Optional schema + /// Column definitions pub columns: Vec, + /// Table constraints pub constraints: Vec, + /// Hive-specific distribution style pub hive_distribution: HiveDistributionStyle, + /// Hive-specific formats like `ROW FORMAT DELIMITED` or `ROW FORMAT SERDE 'serde_class' WITH SERDEPROPERTIES (...)` pub hive_formats: Option, + /// Table options pub table_options: CreateTableOptions, + /// General comment for the table pub file_format: Option, + /// Location of the table data pub location: Option, + /// Query used to populate the table pub query: Option>, + /// If the table should be created without a rowid (SQLite) pub without_rowid: bool, + /// `LIKE` clause pub like: Option, + /// `CLONE` clause pub clone: Option, + /// Table version (for systems that support versioned tables) pub version: Option, - // For Hive dialect, the table comment is after the column definitions without `=`, - // so the `comment` field is optional and different than the comment field in the general options list. - // [Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable) + /// For Hive dialect, the table comment is after the column definitions without `=`, + /// so the `comment` field is optional and different than the comment field in the general options list. + /// [Hive](https://cwiki.apache.org/confluence/display/Hive/LanguageManual+DDL#LanguageManualDDL-CreateTable) pub comment: Option, + /// ClickHouse "ON COMMIT" clause: + /// pub on_commit: Option, /// ClickHouse "ON CLUSTER" clause: /// @@ -3105,16 +3352,23 @@ impl fmt::Display for CreateDomain { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// CREATE FUNCTION statement pub struct CreateFunction { /// True if this is a `CREATE OR ALTER FUNCTION` statement /// /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-function-transact-sql?view=sql-server-ver16#or-alter) pub or_alter: bool, + /// True if this is a `CREATE OR REPLACE FUNCTION` statement pub or_replace: bool, + /// True if this is a `CREATE TEMPORARY FUNCTION` statement pub temporary: bool, + /// True if this is a `CREATE IF NOT EXISTS FUNCTION` statement pub if_not_exists: bool, + /// Name of the function to be created. pub name: ObjectName, + /// List of arguments for the function. pub args: Option>, + /// The return type of the function. pub return_type: Option, /// The expression that defines the function. /// @@ -3256,11 +3510,17 @@ impl fmt::Display for CreateFunction { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateConnector { + /// The name of the connector to be created. pub name: Ident, + /// Whether `IF NOT EXISTS` was specified. pub if_not_exists: bool, + /// The type of the connector. pub connector_type: Option, + /// The URL of the connector. pub url: Option, + /// The comment for the connector. pub comment: Option, + /// The DC properties for the connector. pub with_dcproperties: Option>, } @@ -3309,23 +3569,36 @@ impl fmt::Display for CreateConnector { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum AlterSchemaOperation { + /// Set the default collation for the schema. SetDefaultCollate { + /// The collation to set as default. collate: Expr, }, + /// Add a replica to the schema. AddReplica { + /// The replica to add. replica: Ident, + /// Optional options for the replica. options: Option>, }, + /// Drop a replica from the schema. DropReplica { + /// The replica to drop. replica: Ident, }, + /// Set options for the schema. SetOptionsParens { + /// The options to set. options: Vec, }, + /// Rename the schema. Rename { + /// The new name for the schema. name: ObjectName, }, + /// Change the owner of the schema. OwnerTo { + /// The new owner of the schema. owner: Owner, }, } @@ -3361,7 +3634,9 @@ impl fmt::Display for AlterSchemaOperation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum RenameTableNameKind { + /// `AS new_table_name` As(ObjectName), + /// `TO new_table_name` To(ObjectName), } @@ -3377,9 +3652,13 @@ impl fmt::Display for RenameTableNameKind { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// An `ALTER SCHEMA` (`Statement::AlterSchema`) statement. pub struct AlterSchema { + /// The schema name to alter. pub name: ObjectName, + /// Whether `IF EXISTS` was specified. pub if_exists: bool, + /// The list of operations to perform on the schema. pub operations: Vec, } @@ -3787,7 +4066,9 @@ pub struct CreateView { /// /// [MsSql](https://learn.microsoft.com/en-us/sql/t-sql/statements/create-view-transact-sql) pub or_alter: bool, + /// The `OR REPLACE` clause is used to re-create the view if it already exists. pub or_replace: bool, + /// if true, has MATERIALIZED view modifier pub materialized: bool, /// Snowflake: SECURE view modifier /// @@ -3805,9 +4086,13 @@ pub struct CreateView { /// CREATE VIEW IF NOT EXISTS myview AS SELECT 1` /// ``` pub name_before_not_exists: bool, + /// Optional column definitions pub columns: Vec, + /// The query that defines the view. pub query: Box, + /// Table options (e.g., WITH (..), OPTIONS (...)) pub options: CreateTableOptions, + /// BigQuery: CLUSTER BY columns pub cluster_by: Vec, /// Snowflake: Views can have comments in Snowflake. /// @@ -3896,10 +4181,15 @@ impl fmt::Display for CreateView { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateExtension { + /// Extension name pub name: Ident, + /// Whether `IF NOT EXISTS` was specified for the CREATE EXTENSION. pub if_not_exists: bool, + /// Whether `CASCADE` was specified for the CREATE EXTENSION. pub cascade: bool, + /// Optional schema name for the extension. pub schema: Option, + /// Optional version for the extension. pub version: Option, } @@ -3950,9 +4240,11 @@ impl Spanned for CreateExtension { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct DropExtension { + /// One or more extension names to drop pub names: Vec, + /// Whether `IF EXISTS` was specified for the DROP EXTENSION. pub if_exists: bool, - /// `CASCADE` or `RESTRICT` + /// `CASCADE` or `RESTRICT` behaviour for the drop. pub cascade_or_restrict: Option, } @@ -4001,9 +4293,13 @@ pub struct AlterTable { /// Table name #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] pub name: ObjectName, + /// Whether `IF EXISTS` was specified for the `ALTER TABLE`. pub if_exists: bool, + /// Whether the `ONLY` keyword was used (restrict scope to the named table). pub only: bool, + /// List of `ALTER TABLE` operations to apply. pub operations: Vec, + /// Optional Hive `SET LOCATION` clause for the alter operation. pub location: Option, /// ClickHouse dialect supports `ON CLUSTER` clause for ALTER TABLE /// For example: `ALTER TABLE table_name ON CLUSTER cluster_name ADD COLUMN c UInt32` @@ -4047,6 +4343,7 @@ impl fmt::Display for AlterTable { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct DropFunction { + /// Whether to include the `IF EXISTS` clause. pub if_exists: bool, /// One or more functions to drop pub func_desc: Vec, @@ -4183,7 +4480,9 @@ impl fmt::Display for CreateOperatorClass { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct OperatorArgTypes { + /// Left-hand operand data type for the operator. pub left: DataType, + /// Right-hand operand data type for the operator. pub right: DataType, } @@ -4198,26 +4497,33 @@ impl fmt::Display for OperatorArgTypes { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum OperatorClassItem { - /// `OPERATOR` clause + /// `OPERATOR` clause describing a specific operator implementation. Operator { + /// Strategy number identifying the operator position in the opclass. strategy_number: u64, + /// The operator name referenced by this clause. operator_name: ObjectName, - /// Optional operator argument types + /// Optional operator argument types. op_types: Option, - /// `FOR SEARCH` or `FOR ORDER BY` + /// Optional purpose such as `FOR SEARCH` or `FOR ORDER BY`. purpose: Option, }, - /// `FUNCTION` clause + /// `FUNCTION` clause describing a support function for the operator class. Function { + /// Support function number for this entry. support_number: u64, - /// Optional function argument types for the operator class + /// Optional function argument types for the operator class. op_types: Option>, + /// The function name implementing the support function. function_name: ObjectName, - /// Function argument types + /// Function argument types for the support function. argument_types: Vec, }, - /// `STORAGE` clause - Storage { storage_type: DataType }, + /// `STORAGE` clause specifying the storage type. + Storage { + /// The storage data type. + storage_type: DataType, + }, } /// Purpose of an operator in an operator class @@ -4225,8 +4531,13 @@ pub enum OperatorClassItem { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum OperatorPurpose { + /// Purpose: used for index/search operations. ForSearch, - ForOrderBy { sort_family: ObjectName }, + /// Purpose: used for ORDER BY; optionally includes a sort family name. + ForOrderBy { + /// Optional sort family object name. + sort_family: ObjectName, + }, } impl fmt::Display for OperatorClassItem { @@ -4419,22 +4730,26 @@ impl Spanned for DropOperatorClass { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum OperatorFamilyItem { - /// `OPERATOR` clause + /// `OPERATOR` clause in an operator family modification. Operator { + /// Strategy number for the operator. strategy_number: u64, + /// Operator name referenced by this entry. operator_name: ObjectName, - /// Operator argument types + /// Operator argument types. op_types: Vec, - /// `FOR SEARCH` or `FOR ORDER BY` + /// Optional purpose such as `FOR SEARCH` or `FOR ORDER BY`. purpose: Option, }, - /// `FUNCTION` clause + /// `FUNCTION` clause in an operator family modification. Function { + /// Support function number. support_number: u64, - /// Optional operator argument types for the function + /// Optional operator argument types for the function. op_types: Option>, + /// Function name for the support function. function_name: ObjectName, - /// Function argument types + /// Function argument types. argument_types: Vec, }, } @@ -4444,16 +4759,18 @@ pub enum OperatorFamilyItem { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum OperatorFamilyDropItem { - /// `OPERATOR` clause + /// `OPERATOR` clause for DROP within an operator family. Operator { + /// Strategy number for the operator. strategy_number: u64, - /// Operator argument types + /// Operator argument types. op_types: Vec, }, - /// `FUNCTION` clause + /// `FUNCTION` clause for DROP within an operator family. Function { + /// Support function number. support_number: u64, - /// Operator argument types for the function + /// Operator argument types for the function. op_types: Vec, }, } @@ -4554,11 +4871,17 @@ pub enum AlterOperatorFamilyOperation { items: Vec, }, /// `RENAME TO new_name` - RenameTo { new_name: ObjectName }, + RenameTo { + /// The new name for the operator family. + new_name: ObjectName, + }, /// `OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }` OwnerTo(Owner), /// `SET SCHEMA new_schema` - SetSchema { schema_name: ObjectName }, + SetSchema { + /// The target schema name. + schema_name: ObjectName, + }, } impl fmt::Display for AlterOperatorFamily { @@ -4599,3 +4922,67 @@ impl Spanned for AlterOperatorFamily { Span::empty() } } + +/// `ALTER OPERATOR CLASS` statement +/// See +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub struct AlterOperatorClass { + /// Operator class name (can be schema-qualified) + pub name: ObjectName, + /// Index method (btree, hash, gist, gin, etc.) + pub using: Ident, + /// The operation to perform + pub operation: AlterOperatorClassOperation, +} + +/// An [AlterOperatorClass] operation +#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +pub enum AlterOperatorClassOperation { + /// `RENAME TO new_name` + /// Rename the operator class to a new name. + RenameTo { + /// The new name for the operator class. + new_name: ObjectName, + }, + /// `OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }` + OwnerTo(Owner), + /// `SET SCHEMA new_schema` + /// Set the schema for the operator class. + SetSchema { + /// The target schema name. + schema_name: ObjectName, + }, +} + +impl fmt::Display for AlterOperatorClass { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "ALTER OPERATOR CLASS {} USING {}", self.name, self.using)?; + write!(f, " {}", self.operation) + } +} + +impl fmt::Display for AlterOperatorClassOperation { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + AlterOperatorClassOperation::RenameTo { new_name } => { + write!(f, "RENAME TO {new_name}") + } + AlterOperatorClassOperation::OwnerTo(owner) => { + write!(f, "OWNER TO {owner}") + } + AlterOperatorClassOperation::SetSchema { schema_name } => { + write!(f, "SET SCHEMA {schema_name}") + } + } + } +} + +impl Spanned for AlterOperatorClass { + fn span(&self) -> Span { + Span::empty() + } +} diff --git a/src/ast/dml.rs b/src/ast/dml.rs index d740b140e..150a54892 100644 --- a/src/ast/dml.rs +++ b/src/ast/dml.rs @@ -68,6 +68,7 @@ pub struct Insert { pub after_columns: Vec, /// whether the insert has the table keyword (Hive) pub has_table_keyword: bool, + /// ON INSERT pub on: Option, /// RETURNING pub returning: Option>, @@ -331,7 +332,7 @@ pub struct Merge { pub on: Box, /// Specifies the actions to perform when values match or do not match. pub clauses: Vec, - // Specifies the output to save changes in MSSQL + /// Specifies the output to save changes in MSSQL pub output: Option, } @@ -367,8 +368,11 @@ impl Display for Merge { pub struct MergeClause { /// The `WHEN` token that starts the sub-expression. pub when_token: AttachedToken, + /// The type of `WHEN` clause. pub clause_kind: MergeClauseKind, + /// An optional predicate to further restrict the clause. pub predicate: Option, + /// The action to perform when the clause is matched. pub action: MergeAction, } @@ -607,13 +611,20 @@ impl Display for MergeUpdateExpr { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum OutputClause { + /// `OUTPUT` clause Output { + /// The `OUTPUT` token that starts the sub-expression. output_token: AttachedToken, + /// The select items to output select_items: Vec, + /// Optional `INTO` table to direct the output into_table: Option, }, + /// `RETURNING` clause Returning { + /// The `RETURNING` token that starts the sub-expression. returning_token: AttachedToken, + /// The select items to return select_items: Vec, }, } diff --git a/src/ast/helpers/key_value_options.rs b/src/ast/helpers/key_value_options.rs index 745c3a65a..e8e543b01 100644 --- a/src/ast/helpers/key_value_options.rs +++ b/src/ast/helpers/key_value_options.rs @@ -34,24 +34,33 @@ use crate::ast::{display_comma_separated, display_separated, Value}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A collection of key-value options. pub struct KeyValueOptions { + /// The list of key-value options. pub options: Vec, + /// The delimiter used between options. pub delimiter: KeyValueOptionsDelimiter, } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// The delimiter used between key-value options. pub enum KeyValueOptionsDelimiter { + /// Options are separated by spaces. Space, + /// Options are separated by commas. Comma, } #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A single key-value option. pub struct KeyValueOption { + /// The name of the option. pub option_name: String, + /// The value of the option. pub option_value: KeyValueOptionKind, } @@ -63,9 +72,13 @@ pub struct KeyValueOption { #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// The kind of value for a key-value option. pub enum KeyValueOptionKind { + /// A single value. Single(Value), + /// Multiple values. Multi(Vec), + /// A nested list of key-value options. KeyValueOptions(Box), } diff --git a/src/ast/helpers/mod.rs b/src/ast/helpers/mod.rs index 3efbcf7b0..344895dc1 100644 --- a/src/ast/helpers/mod.rs +++ b/src/ast/helpers/mod.rs @@ -14,8 +14,14 @@ // KIND, either express or implied. See the License for the // specific language governing permissions and limitations // under the License. + +/// Helper utilities for attached tokens used by AST helpers. pub mod attached_token; +/// Utilities for parsing key/value style options in helper statements. pub mod key_value_options; +/// Helpers for `CREATE DATABASE` statement construction/parsing. pub mod stmt_create_database; +/// Helpers for `CREATE TABLE` statement construction/parsing. pub mod stmt_create_table; +/// Helpers for data loading/unloading related statements (stages, PUT, COPY INTO). pub mod stmt_data_loading; diff --git a/src/ast/helpers/stmt_create_database.rs b/src/ast/helpers/stmt_create_database.rs index 58a7b0906..c718dbce1 100644 --- a/src/ast/helpers/stmt_create_database.rs +++ b/src/ast/helpers/stmt_create_database.rs @@ -55,29 +55,54 @@ use crate::parser::ParserError; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateDatabaseBuilder { + /// The database name to create. pub db_name: ObjectName, + /// Whether `IF NOT EXISTS` was specified. pub if_not_exists: bool, + /// Optional storage location for the database. pub location: Option, + /// Optional managed storage location. pub managed_location: Option, + /// Whether `OR REPLACE` was specified. pub or_replace: bool, + /// Whether the database is `TRANSIENT`. pub transient: bool, + /// Optional `CLONE` source object name. pub clone: Option, + /// Optional data retention time in days. pub data_retention_time_in_days: Option, + /// Optional max data extension time in days. pub max_data_extension_time_in_days: Option, + /// Optional external volume identifier. pub external_volume: Option, + /// Optional catalog name. pub catalog: Option, + /// Whether to replace invalid characters. pub replace_invalid_characters: Option, + /// Optional default DDL collation. pub default_ddl_collation: Option, + /// Optional storage serialization policy. pub storage_serialization_policy: Option, + /// Optional comment attached to the database. pub comment: Option, + /// Optional catalog sync configuration. pub catalog_sync: Option, + /// Optional catalog sync namespace mode. pub catalog_sync_namespace_mode: Option, + /// Optional namespace flatten delimiter for catalog sync. pub catalog_sync_namespace_flatten_delimiter: Option, + /// Optional tags attached to the database. pub with_tags: Option>, + /// Optional contact entries associated with the database. pub with_contacts: Option>, } impl CreateDatabaseBuilder { + /// Create a new `CreateDatabaseBuilder` with the given database name. + /// + /// # Arguments + /// + /// * `name` - The name of the database to be created. pub fn new(name: ObjectName) -> Self { Self { db_name: name, @@ -103,41 +128,49 @@ impl CreateDatabaseBuilder { } } + /// Set the location for the database. pub fn location(mut self, location: Option) -> Self { self.location = location; self } + /// Set the managed location for the database. pub fn managed_location(mut self, managed_location: Option) -> Self { self.managed_location = managed_location; self } + /// Set whether this is an `OR REPLACE` operation. pub fn or_replace(mut self, or_replace: bool) -> Self { self.or_replace = or_replace; self } + /// Set whether this is a transient database. pub fn transient(mut self, transient: bool) -> Self { self.transient = transient; self } + /// Set whether to use `IF NOT EXISTS`. pub fn if_not_exists(mut self, if_not_exists: bool) -> Self { self.if_not_exists = if_not_exists; self } + /// Set the clone clause for the database. pub fn clone_clause(mut self, clone: Option) -> Self { self.clone = clone; self } + /// Set the data retention time in days. pub fn data_retention_time_in_days(mut self, data_retention_time_in_days: Option) -> Self { self.data_retention_time_in_days = data_retention_time_in_days; self } + /// Set the maximum data extension time in days. pub fn max_data_extension_time_in_days( mut self, max_data_extension_time_in_days: Option, @@ -146,26 +179,31 @@ impl CreateDatabaseBuilder { self } + /// Set the external volume for the database. pub fn external_volume(mut self, external_volume: Option) -> Self { self.external_volume = external_volume; self } + /// Set the catalog for the database. pub fn catalog(mut self, catalog: Option) -> Self { self.catalog = catalog; self } + /// Set whether to replace invalid characters. pub fn replace_invalid_characters(mut self, replace_invalid_characters: Option) -> Self { self.replace_invalid_characters = replace_invalid_characters; self } + /// Set the default DDL collation. pub fn default_ddl_collation(mut self, default_ddl_collation: Option) -> Self { self.default_ddl_collation = default_ddl_collation; self } + /// Set the storage serialization policy. pub fn storage_serialization_policy( mut self, storage_serialization_policy: Option, @@ -174,16 +212,19 @@ impl CreateDatabaseBuilder { self } + /// Set the comment for the database. pub fn comment(mut self, comment: Option) -> Self { self.comment = comment; self } + /// Set the catalog sync for the database. pub fn catalog_sync(mut self, catalog_sync: Option) -> Self { self.catalog_sync = catalog_sync; self } + /// Set the catalog sync namespace mode for the database. pub fn catalog_sync_namespace_mode( mut self, catalog_sync_namespace_mode: Option, @@ -192,6 +233,7 @@ impl CreateDatabaseBuilder { self } + /// Set the catalog sync namespace flatten delimiter for the database. pub fn catalog_sync_namespace_flatten_delimiter( mut self, catalog_sync_namespace_flatten_delimiter: Option, @@ -200,16 +242,19 @@ impl CreateDatabaseBuilder { self } + /// Set the tags for the database. pub fn with_tags(mut self, with_tags: Option>) -> Self { self.with_tags = with_tags; self } + /// Set the contacts for the database. pub fn with_contacts(mut self, with_contacts: Option>) -> Self { self.with_contacts = with_contacts; self } + /// Build the `CREATE DATABASE` statement. pub fn build(self) -> Statement { Statement::CreateDatabase { db_name: self.db_name, diff --git a/src/ast/helpers/stmt_create_table.rs b/src/ast/helpers/stmt_create_table.rs index fe950c909..b6e486675 100644 --- a/src/ast/helpers/stmt_create_table.rs +++ b/src/ast/helpers/stmt_create_table.rs @@ -64,60 +64,112 @@ use crate::parser::ParserError; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateTableBuilder { + /// Whether the statement uses `OR REPLACE`. pub or_replace: bool, + /// Whether the table is `TEMPORARY`. pub temporary: bool, + /// Whether the table is `EXTERNAL`. pub external: bool, + /// Optional `GLOBAL` flag for dialects that support it. pub global: Option, + /// Whether `IF NOT EXISTS` was specified. pub if_not_exists: bool, + /// Whether `TRANSIENT` was specified. pub transient: bool, + /// Whether `VOLATILE` was specified. pub volatile: bool, + /// Iceberg-specific table flag. pub iceberg: bool, + /// Whether `DYNAMIC` table option is set. pub dynamic: bool, + /// The table name. pub name: ObjectName, + /// Column definitions for the table. pub columns: Vec, + /// Table-level constraints. pub constraints: Vec, + /// Hive distribution style. pub hive_distribution: HiveDistributionStyle, + /// Optional Hive format settings. pub hive_formats: Option, + /// Optional file format for storage. pub file_format: Option, + /// Optional storage location. pub location: Option, + /// Optional `AS SELECT` query for the table. pub query: Option>, + /// Whether `WITHOUT ROWID` is set. pub without_rowid: bool, + /// Optional `LIKE` clause kind. pub like: Option, + /// Optional `CLONE` source object name. pub clone: Option, + /// Optional table version. pub version: Option, + /// Optional table comment. pub comment: Option, + /// Optional `ON COMMIT` behavior. pub on_commit: Option, + /// Optional cluster identifier. pub on_cluster: Option, + /// Optional primary key expression. pub primary_key: Option>, + /// Optional `ORDER BY` for clustering/sorting. pub order_by: Option>, + /// Optional `PARTITION BY` expression. pub partition_by: Option>, + /// Optional `CLUSTER BY` expressions. pub cluster_by: Option>>, + /// Optional `CLUSTERED BY` clause. pub clustered_by: Option, + /// Optional parent tables (`INHERITS`). pub inherits: Option>, + /// `STRICT` table flag. pub strict: bool, + /// Whether to copy grants from the source. pub copy_grants: bool, + /// Optional flag for schema evolution support. pub enable_schema_evolution: Option, + /// Optional change tracking flag. pub change_tracking: Option, + /// Optional data retention time in days. pub data_retention_time_in_days: Option, + /// Optional max data extension time in days. pub max_data_extension_time_in_days: Option, + /// Optional default DDL collation. pub default_ddl_collation: Option, + /// Optional aggregation policy object name. pub with_aggregation_policy: Option, + /// Optional row access policy applied to the table. pub with_row_access_policy: Option, + /// Optional tags/labels attached to the table metadata. pub with_tags: Option>, + /// Optional base location for staged data. pub base_location: Option, + /// Optional external volume identifier. pub external_volume: Option, + /// Optional catalog name. pub catalog: Option, + /// Optional catalog synchronization option. pub catalog_sync: Option, + /// Optional storage serialization policy. pub storage_serialization_policy: Option, + /// Parsed table options from the statement. pub table_options: CreateTableOptions, + /// Optional target lag configuration. pub target_lag: Option, + /// Optional warehouse identifier. pub warehouse: Option, + /// Optional refresh mode for materialized tables. pub refresh_mode: Option, + /// Optional initialization kind for the table. pub initialize: Option, + /// Whether operations require a user identity. pub require_user: bool, } impl CreateTableBuilder { + /// Create a new `CreateTableBuilder` for the given table name. pub fn new(name: ObjectName) -> Self { Self { or_replace: false, @@ -173,175 +225,178 @@ impl CreateTableBuilder { require_user: false, } } + /// Set `OR REPLACE` for the CREATE TABLE statement. pub fn or_replace(mut self, or_replace: bool) -> Self { self.or_replace = or_replace; self } - + /// Mark the table as `TEMPORARY`. pub fn temporary(mut self, temporary: bool) -> Self { self.temporary = temporary; self } - + /// Mark the table as `EXTERNAL`. pub fn external(mut self, external: bool) -> Self { self.external = external; self } - + /// Set optional `GLOBAL` flag (dialect-specific). pub fn global(mut self, global: Option) -> Self { self.global = global; self } - + /// Set `IF NOT EXISTS`. pub fn if_not_exists(mut self, if_not_exists: bool) -> Self { self.if_not_exists = if_not_exists; self } - + /// Set `TRANSIENT` flag. pub fn transient(mut self, transient: bool) -> Self { self.transient = transient; self } - + /// Set `VOLATILE` flag. pub fn volatile(mut self, volatile: bool) -> Self { self.volatile = volatile; self } - + /// Enable Iceberg table semantics. pub fn iceberg(mut self, iceberg: bool) -> Self { self.iceberg = iceberg; self } - + /// Set `DYNAMIC` table option. pub fn dynamic(mut self, dynamic: bool) -> Self { self.dynamic = dynamic; self } - + /// Set the table column definitions. pub fn columns(mut self, columns: Vec) -> Self { self.columns = columns; self } - + /// Set table-level constraints. pub fn constraints(mut self, constraints: Vec) -> Self { self.constraints = constraints; self } - + /// Set Hive distribution style. pub fn hive_distribution(mut self, hive_distribution: HiveDistributionStyle) -> Self { self.hive_distribution = hive_distribution; self } - + /// Set Hive-specific formats. pub fn hive_formats(mut self, hive_formats: Option) -> Self { self.hive_formats = hive_formats; self } - + /// Set file format for the table (e.g., PARQUET). pub fn file_format(mut self, file_format: Option) -> Self { self.file_format = file_format; self } + /// Set storage `location` for the table. pub fn location(mut self, location: Option) -> Self { self.location = location; self } - + /// Set an underlying `AS SELECT` query for the table. pub fn query(mut self, query: Option>) -> Self { self.query = query; self } + /// Set `WITHOUT ROWID` option. pub fn without_rowid(mut self, without_rowid: bool) -> Self { self.without_rowid = without_rowid; self } - + /// Set `LIKE` clause for the table. pub fn like(mut self, like: Option) -> Self { self.like = like; self } - // Different name to allow the object to be cloned + /// Set `CLONE` source object name. pub fn clone_clause(mut self, clone: Option) -> Self { self.clone = clone; self } - + /// Set table `VERSION`. pub fn version(mut self, version: Option) -> Self { self.version = version; self } - + /// Set a comment for the table or following column definitions. pub fn comment_after_column_def(mut self, comment: Option) -> Self { self.comment = comment; self } - + /// Set `ON COMMIT` behavior for temporary tables. pub fn on_commit(mut self, on_commit: Option) -> Self { self.on_commit = on_commit; self } - + /// Set cluster identifier for the table. pub fn on_cluster(mut self, on_cluster: Option) -> Self { self.on_cluster = on_cluster; self } - + /// Set a primary key expression for the table. pub fn primary_key(mut self, primary_key: Option>) -> Self { self.primary_key = primary_key; self } - + /// Set `ORDER BY` clause for clustered/sorted tables. pub fn order_by(mut self, order_by: Option>) -> Self { self.order_by = order_by; self } - + /// Set `PARTITION BY` expression. pub fn partition_by(mut self, partition_by: Option>) -> Self { self.partition_by = partition_by; self } - + /// Set `CLUSTER BY` expression(s). pub fn cluster_by(mut self, cluster_by: Option>>) -> Self { self.cluster_by = cluster_by; self } - + /// Set `CLUSTERED BY` clause. pub fn clustered_by(mut self, clustered_by: Option) -> Self { self.clustered_by = clustered_by; self } - + /// Set parent tables via `INHERITS`. pub fn inherits(mut self, inherits: Option>) -> Self { self.inherits = inherits; self } - + /// Set `STRICT` option. pub fn strict(mut self, strict: bool) -> Self { self.strict = strict; self } - + /// Enable copying grants from source object. pub fn copy_grants(mut self, copy_grants: bool) -> Self { self.copy_grants = copy_grants; self } - + /// Enable or disable schema evolution features. pub fn enable_schema_evolution(mut self, enable_schema_evolution: Option) -> Self { self.enable_schema_evolution = enable_schema_evolution; self } - + /// Enable or disable change tracking. pub fn change_tracking(mut self, change_tracking: Option) -> Self { self.change_tracking = change_tracking; self } - + /// Set data retention time (in days). pub fn data_retention_time_in_days(mut self, data_retention_time_in_days: Option) -> Self { self.data_retention_time_in_days = data_retention_time_in_days; self } - + /// Set maximum data extension time (in days). pub fn max_data_extension_time_in_days( mut self, max_data_extension_time_in_days: Option, @@ -349,17 +404,17 @@ impl CreateTableBuilder { self.max_data_extension_time_in_days = max_data_extension_time_in_days; self } - + /// Set default DDL collation. pub fn default_ddl_collation(mut self, default_ddl_collation: Option) -> Self { self.default_ddl_collation = default_ddl_collation; self } - + /// Set aggregation policy object. pub fn with_aggregation_policy(mut self, with_aggregation_policy: Option) -> Self { self.with_aggregation_policy = with_aggregation_policy; self } - + /// Attach a row access policy to the table. pub fn with_row_access_policy( mut self, with_row_access_policy: Option, @@ -367,32 +422,32 @@ impl CreateTableBuilder { self.with_row_access_policy = with_row_access_policy; self } - + /// Attach tags/labels to the table metadata. pub fn with_tags(mut self, with_tags: Option>) -> Self { self.with_tags = with_tags; self } - + /// Set a base storage location for staged data. pub fn base_location(mut self, base_location: Option) -> Self { self.base_location = base_location; self } - + /// Set an external volume identifier. pub fn external_volume(mut self, external_volume: Option) -> Self { self.external_volume = external_volume; self } - + /// Set the catalog name for the table. pub fn catalog(mut self, catalog: Option) -> Self { self.catalog = catalog; self } - + /// Set catalog synchronization option. pub fn catalog_sync(mut self, catalog_sync: Option) -> Self { self.catalog_sync = catalog_sync; self } - + /// Set a storage serialization policy. pub fn storage_serialization_policy( mut self, storage_serialization_policy: Option, @@ -400,37 +455,37 @@ impl CreateTableBuilder { self.storage_serialization_policy = storage_serialization_policy; self } - + /// Set arbitrary table options parsed from the statement. pub fn table_options(mut self, table_options: CreateTableOptions) -> Self { self.table_options = table_options; self } - + /// Set a target lag configuration (dialect-specific). pub fn target_lag(mut self, target_lag: Option) -> Self { self.target_lag = target_lag; self } - + /// Associate the table with a warehouse identifier. pub fn warehouse(mut self, warehouse: Option) -> Self { self.warehouse = warehouse; self } - + /// Set refresh mode for materialized/managed tables. pub fn refresh_mode(mut self, refresh_mode: Option) -> Self { self.refresh_mode = refresh_mode; self } - + /// Set initialization mode for the table. pub fn initialize(mut self, initialize: Option) -> Self { self.initialize = initialize; self } - + /// Require a user identity for table operations. pub fn require_user(mut self, require_user: bool) -> Self { self.require_user = require_user; self } - + /// Consume the builder and produce a `Statement::CreateTable`. pub fn build(self) -> Statement { CreateTable { or_replace: self.or_replace, diff --git a/src/ast/helpers/stmt_data_loading.rs b/src/ast/helpers/stmt_data_loading.rs index 62ee77ce3..dfc1f4b0b 100644 --- a/src/ast/helpers/stmt_data_loading.rs +++ b/src/ast/helpers/stmt_data_loading.rs @@ -34,11 +34,17 @@ use sqlparser_derive::{Visit, VisitMut}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Parameters for a named stage object used in data loading/unloading. pub struct StageParamsObject { + /// Optional URL for the stage. pub url: Option, + /// Encryption-related key/value options. pub encryption: KeyValueOptions, + /// Optional endpoint string. pub endpoint: Option, + /// Optional storage integration identifier. pub storage_integration: Option, + /// Credentials for accessing the stage. pub credentials: KeyValueOptions, } @@ -48,7 +54,9 @@ pub struct StageParamsObject { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum StageLoadSelectItemKind { + /// A standard SQL select item expression. SelectItem(SelectItem), + /// A Snowflake-specific select item used for stage loading. StageLoadSelectItem(StageLoadSelectItem), } @@ -64,10 +72,15 @@ impl fmt::Display for StageLoadSelectItemKind { #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A single item in the `SELECT` list for data loading from staged files. pub struct StageLoadSelectItem { + /// Optional alias for the input source. pub alias: Option, + /// Column number within the staged file (1-based). pub file_col_num: i32, + /// Optional element identifier following the column reference. pub element: Option, + /// Optional alias for the item (AS clause). pub item_as: Option, } @@ -116,9 +129,12 @@ impl fmt::Display for StageLoadSelectItem { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A command to stage files to a named stage. pub struct FileStagingCommand { + /// The stage to which files are being staged. #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] pub stage: ObjectName, + /// Optional file matching `PATTERN` expression. pub pattern: Option, } diff --git a/src/ast/mod.rs b/src/ast/mod.rs index 467678602..943e4c1b8 100644 --- a/src/ast/mod.rs +++ b/src/ast/mod.rs @@ -60,22 +60,22 @@ pub use self::dcl::{ }; pub use self::ddl::{ Alignment, AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterOperator, - AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, - AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm, - AlterTableLock, AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue, - AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, - ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, - ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain, - CreateExtension, CreateFunction, CreateIndex, CreateOperator, CreateOperatorClass, - CreateOperatorFamily, CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial, - DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily, - DropOperatorSignature, DropTrigger, GeneratedAs, GeneratedExpressionMode, IdentityParameters, - IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, - IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, - OperatorArgTypes, OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem, - OperatorOption, OperatorPurpose, Owner, Partition, ProcedureParam, ReferentialAction, - RenameTableNameKind, ReplicaIdentity, TagsColumnOption, TriggerObjectKind, Truncate, - UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength, + AlterOperatorClass, AlterOperatorClassOperation, AlterOperatorFamily, + AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicyOperation, AlterSchema, + AlterSchemaOperation, AlterTable, AlterTableAlgorithm, AlterTableLock, AlterTableOperation, + AlterTableType, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, + AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, + ColumnOptions, ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, + CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator, + CreateOperatorClass, CreateOperatorFamily, CreateTable, CreateTrigger, CreateView, Deduplicate, + DeferrableInitial, DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass, + DropOperatorFamily, DropOperatorSignature, DropTrigger, GeneratedAs, GeneratedExpressionMode, + IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, + IdentityPropertyOrder, IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, Msck, + NullsDistinctOption, OperatorArgTypes, OperatorClassItem, OperatorFamilyDropItem, + OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition, ProcedureParam, + ReferentialAction, RenameTableNameKind, ReplicaIdentity, TagsColumnOption, TriggerObjectKind, + Truncate, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef, }; @@ -127,6 +127,7 @@ mod data_type; mod dcl; mod ddl; mod dml; +/// Helper modules for building and manipulating AST nodes. pub mod helpers; pub mod table_constraints; pub use table_constraints::{ @@ -145,6 +146,7 @@ mod value; #[cfg(feature = "visitor")] mod visitor; +/// Helper used to format a slice using a separator string (e.g., `", "`). pub struct DisplaySeparated<'a, T> where T: fmt::Display, @@ -290,6 +292,7 @@ impl Ident { } } + /// Create an `Ident` with the given `span` and `value` (unquoted). pub fn with_span(span: Span, value: S) -> Self where S: Into, @@ -301,6 +304,7 @@ impl Ident { } } + /// Create a quoted `Ident` with the given `quote` and `span`. pub fn with_quote_and_span(quote: char, span: Span, value: S) -> Self where S: Into, @@ -367,11 +371,14 @@ impl fmt::Display for ObjectName { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ObjectNamePart { + /// A single identifier part, e.g. `schema` or `table`. Identifier(Ident), + /// A function that returns an identifier (dialect-specific). Function(ObjectNamePartFunction), } impl ObjectNamePart { + /// Return the identifier if this is an `Identifier` variant. pub fn as_ident(&self) -> Option<&Ident> { match self { ObjectNamePart::Identifier(ident) => Some(ident), @@ -397,7 +404,9 @@ impl fmt::Display for ObjectNamePart { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ObjectNamePartFunction { + /// The function name that produces the object name part. pub name: Ident, + /// Function arguments used to compute the identifier. pub args: Vec, } @@ -444,14 +453,17 @@ impl fmt::Display for Array { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Interval { + /// The interval value expression (commonly a string literal). pub value: Box, + /// Optional leading time unit (e.g., `HOUR`, `MINUTE`). pub leading_field: Option, + /// Optional leading precision for the leading field. pub leading_precision: Option, + /// Optional trailing time unit for a range (e.g., `SECOND`). pub last_field: Option, - /// The seconds precision can be specified in SQL source as - /// `INTERVAL '__' SECOND(_, x)` (in which case the `leading_field` - /// will be `Second` and the `last_field` will be `None`), - /// or as `__ TO SECOND(x)`. + /// The fractional seconds precision, when specified. + /// + /// See SQL `SECOND(n)` or `SECOND(m, n)` forms. pub fractional_seconds_precision: Option, } @@ -503,9 +515,11 @@ impl fmt::Display for Interval { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct StructField { + /// Optional name of the struct field. pub field_name: Option, + /// The field data type. pub field_type: DataType, - /// Struct field options. + /// Struct field options (e.g., `OPTIONS(...)` on BigQuery). /// See [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#column_name_and_column_schema) pub options: Option>, } @@ -532,7 +546,9 @@ impl fmt::Display for StructField { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct UnionField { + /// Name of the union field. pub field_name: Ident, + /// Type of the union field. pub field_type: DataType, } @@ -549,7 +565,9 @@ impl fmt::Display for UnionField { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct DictionaryField { + /// Dictionary key identifier. pub key: Ident, + /// Value expression for the dictionary entry. pub value: Box, } @@ -564,6 +582,7 @@ impl fmt::Display for DictionaryField { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Map { + /// Entries of the map as key/value pairs. pub entries: Vec, } @@ -580,7 +599,9 @@ impl Display for Map { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct MapEntry { + /// Key expression of the map entry. pub key: Box, + /// Value expression of the map entry. pub value: Box, } @@ -596,7 +617,9 @@ impl fmt::Display for MapEntry { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum CastFormat { + /// A simple cast format specified by a `Value`. Value(Value), + /// A cast format with an explicit time zone: `(format, timezone)`. ValueAtTimeZone(Value, Value), } @@ -608,12 +631,20 @@ pub enum JsonPathElem { /// Accesses an object field using dot notation, e.g. `obj:foo.bar.baz`. /// /// See . - Dot { key: String, quoted: bool }, + Dot { + /// The object key text (without quotes). + key: String, + /// `true` when the key was quoted in the source. + quoted: bool, + }, /// Accesses an object field or array element using bracket notation, /// e.g. `obj['foo']`. /// /// See . - Bracket { key: Expr }, + Bracket { + /// The expression used as the bracket key (string or numeric expression). + key: Expr, + }, } /// A JSON path. @@ -624,6 +655,7 @@ pub enum JsonPathElem { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct JsonPath { + /// Sequence of path elements that form the JSON path. pub path: Vec, } @@ -738,7 +770,9 @@ pub enum CeilFloorKind { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CaseWhen { + /// The `WHEN` condition expression. pub condition: Expr, + /// The expression returned when `condition` matches. pub result: Expr, } @@ -801,7 +835,9 @@ pub enum Expr { /// `CompoundFieldAccess(Ident('a'), vec![Subscript('field1'), Ident('field2')]` /// - If a struct access likes `a.field1.field2`, it will be represented by CompoundIdentifier([a, field1, field2]) CompoundFieldAccess { + /// The base expression being accessed. root: Box, + /// Sequence of access operations (subscript or identifier accesses). access_chain: Vec, }, /// Access data nested in a value containing semi-structured data, such as @@ -837,95 +873,138 @@ pub enum Expr { IsNotDistinctFrom(Box, Box), /// ` IS [ NOT ] [ form ] NORMALIZED` IsNormalized { + /// Expression being tested. expr: Box, + /// Optional normalization `form` (e.g., NFC, NFD). form: Option, + /// `true` when `NOT` is present. negated: bool, }, /// `[ NOT ] IN (val1, val2, ...)` InList { + /// Left-hand expression to test for membership. expr: Box, + /// Literal list of expressions to check against. list: Vec, + /// `true` when the `NOT` modifier is present. negated: bool, }, /// `[ NOT ] IN (SELECT ...)` InSubquery { + /// Left-hand expression to test for membership. expr: Box, + /// The subquery providing the candidate values. subquery: Box, + /// `true` when the `NOT` modifier is present. negated: bool, }, /// `[ NOT ] IN UNNEST(array_expression)` InUnnest { + /// Left-hand expression to test for membership. expr: Box, + /// Array expression being unnested. array_expr: Box, + /// `true` when the `NOT` modifier is present. negated: bool, }, /// ` [ NOT ] BETWEEN AND ` Between { + /// Expression being compared. expr: Box, + /// `true` when the `NOT` modifier is present. negated: bool, + /// Lower bound. low: Box, + /// Upper bound. high: Box, }, /// Binary operation e.g. `1 + 1` or `foo > bar` BinaryOp { + /// Left operand. left: Box, + /// Operator between operands. op: BinaryOperator, + /// Right operand. right: Box, }, /// `[NOT] LIKE [ESCAPE ]` Like { + /// `true` when `NOT` is present. negated: bool, - // Snowflake supports the ANY keyword to match against a list of patterns - // https://docs.snowflake.com/en/sql-reference/functions/like_any + /// Snowflake supports the ANY keyword to match against a list of patterns + /// any: bool, + /// Expression to match. expr: Box, + /// Pattern expression. pattern: Box, + /// Optional escape character. escape_char: Option, }, /// `ILIKE` (case-insensitive `LIKE`) ILike { + /// `true` when `NOT` is present. negated: bool, - // Snowflake supports the ANY keyword to match against a list of patterns - // https://docs.snowflake.com/en/sql-reference/functions/like_any + /// Snowflake supports the ANY keyword to match against a list of patterns + /// any: bool, + /// Expression to match. expr: Box, + /// Pattern expression. pattern: Box, + /// Optional escape character. escape_char: Option, }, - /// SIMILAR TO regex + /// `SIMILAR TO` regex SimilarTo { + /// `true` when `NOT` is present. negated: bool, + /// Expression to test. expr: Box, + /// Pattern expression. pattern: Box, + /// Optional escape character. escape_char: Option, }, - /// MySQL: RLIKE regex or REGEXP regex + /// MySQL: `RLIKE` regex or `REGEXP` regex RLike { + /// `true` when `NOT` is present. negated: bool, + /// Expression to test. expr: Box, + /// Pattern expression. pattern: Box, - // true for REGEXP, false for RLIKE (no difference in semantics) + /// true for REGEXP, false for RLIKE (no difference in semantics) regexp: bool, }, /// `ANY` operation e.g. `foo > ANY(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]` /// AnyOp { + /// Left operand. left: Box, + /// Comparison operator. compare_op: BinaryOperator, + /// Right-hand subquery expression. right: Box, - // ANY and SOME are synonymous: https://docs.cloudera.com/cdw-runtime/cloud/using-hiveql/topics/hive_comparison_predicates.html + /// ANY and SOME are synonymous: is_some: bool, }, /// `ALL` operation e.g. `foo > ALL(bar)`, comparison operator is one of `[=, >, <, =>, =<, !=]` /// AllOp { + /// Left operand. left: Box, + /// Comparison operator. compare_op: BinaryOperator, + /// Right-hand subquery expression. right: Box, }, + /// Unary operation e.g. `NOT foo` UnaryOp { + /// The unary operator (e.g., `NOT`, `-`). op: UnaryOperator, + /// Operand expression. expr: Box, }, /// CONVERT a value to a different data type or character encoding. e.g. `CONVERT(foo USING utf8mb4)` @@ -933,13 +1012,13 @@ pub enum Expr { /// CONVERT (false) or TRY_CONVERT (true) /// is_try: bool, - /// The expression to convert + /// The expression to convert. expr: Box, - /// The target data type + /// The target data type, if provided. data_type: Option, - /// The target character encoding + /// Optional target character encoding (e.g., `utf8mb4`). charset: Option, - /// whether the target comes before the expr (MSSQL syntax) + /// `true` when target precedes the value (MSSQL syntax). target_before_value: bool, /// How to translate the expression. /// @@ -948,8 +1027,11 @@ pub enum Expr { }, /// `CAST` an expression to a different data type e.g. `CAST(foo AS VARCHAR(123))` Cast { + /// The cast kind (e.g., `CAST`, `TRY_CAST`). kind: CastKind, + /// Expression being cast. expr: Box, + /// Target data type. data_type: DataType, /// Optional CAST(string_expression AS type FORMAT format_string_expression) as used by [BigQuery] /// @@ -958,7 +1040,9 @@ pub enum Expr { }, /// AT a timestamp to a different timezone e.g. `FROM_UNIXTIME(0) AT TIME ZONE 'UTC-06:00'` AtTimeZone { + /// Timestamp expression to shift. timestamp: Box, + /// Time zone expression to apply. time_zone: Box, }, /// Extract a field from a timestamp e.g. `EXTRACT(MONTH FROM foo)` @@ -969,8 +1053,11 @@ pub enum Expr { /// EXTRACT(DateTimeField FROM ) | EXTRACT(DateTimeField, ) /// ``` Extract { + /// Which datetime field is being extracted. field: DateTimeField, + /// Syntax variant used (`From` or `Comma`). syntax: ExtractSyntax, + /// Expression to extract from. expr: Box, }, /// ```sql @@ -980,7 +1067,9 @@ pub enum Expr { /// CEIL( [, ] ) /// ``` Ceil { + /// Expression to ceil. expr: Box, + /// The CEIL/FLOOR kind (datetime field or scale). field: CeilFloorKind, }, /// ```sql @@ -990,14 +1079,18 @@ pub enum Expr { /// FLOOR( [, ] ) /// Floor { + /// Expression to floor. expr: Box, + /// The CEIL/FLOOR kind (datetime field or scale). field: CeilFloorKind, }, /// ```sql /// POSITION( in ) /// ``` Position { + /// Expression to search for. expr: Box, + /// Expression to search in. r#in: Box, }, /// ```sql @@ -1008,8 +1101,11 @@ pub enum Expr { /// SUBSTRING(, , ) /// ``` Substring { + /// Source expression. expr: Box, + /// Optional `FROM` expression. substring_from: Option>, + /// Optional `FOR` expression. substring_for: Option>, /// false if the expression is represented using the `SUBSTRING(expr [FROM start] [FOR len])` syntax @@ -1027,24 +1123,33 @@ pub enum Expr { /// TRIM(, [, characters]) -- only Snowflake or Bigquery /// ``` Trim { + /// The expression to trim from. expr: Box, - // ([BOTH | LEADING | TRAILING] + /// Which side to trim: `BOTH`, `LEADING`, or `TRAILING`. trim_where: Option, + /// Optional expression specifying what to trim from the value. trim_what: Option>, + /// Optional list of characters to trim (dialect-specific). trim_characters: Option>, }, /// ```sql /// OVERLAY( PLACING FROM [ FOR ] /// ``` Overlay { + /// The target expression being overlayed. expr: Box, + /// The expression to place into the target. overlay_what: Box, + /// The `FROM` position expression indicating where to start overlay. overlay_from: Box, + /// Optional `FOR` length expression limiting the overlay span. overlay_for: Option>, }, /// `expr COLLATE collation` Collate { + /// The expression being collated. expr: Box, + /// The collation name to apply to the expression. collation: ObjectName, }, /// Nested expression e.g. `(foo > bar)` or `(1)` @@ -1055,8 +1160,9 @@ pub enum Expr { /// /// Prefixed { + /// The prefix identifier (introducer or projection prefix). prefix: Ident, - /// The value of the constant. + /// The value expression being prefixed. /// Hint: you can unwrap the string value using `value.into_string()`. value: Box, }, @@ -1072,16 +1178,23 @@ pub enum Expr { /// not `< 0` nor `1, 2, 3` as allowed in a `` per /// Case { + /// The attached `CASE` token (keeps original spacing/comments). case_token: AttachedToken, + /// The attached `END` token (keeps original spacing/comments). end_token: AttachedToken, + /// Optional operand expression after `CASE` (for simple CASE). operand: Option>, + /// The `WHEN ... THEN` conditions and results. conditions: Vec, + /// Optional `ELSE` result expression. else_result: Option>, }, /// An exists expression `[ NOT ] EXISTS(SELECT ...)`, used in expressions like /// `WHERE [ NOT ] EXISTS (SELECT ...)`. Exists { + /// The subquery checked by `EXISTS`. subquery: Box, + /// Whether the `EXISTS` is negated (`NOT EXISTS`). negated: bool, }, /// A parenthesized subquery `(SELECT ...)`, used in expression like @@ -1117,7 +1230,9 @@ pub enum Expr { /// ``` /// [1]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-types#struct_type Named { + /// The expression being named. expr: Box, + /// The assigned identifier name for the expression. name: Ident, }, /// `DuckDB` specific `Struct` literal expression [1] @@ -1158,6 +1273,7 @@ pub enum Expr { /// `` opt_search_modifier: Option, }, + /// An unqualified `*` wildcard token (e.g. `*`). Wildcard(AttachedToken), /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`. /// (Same caveats apply to `QualifiedWildcard` as to `Wildcard`.) @@ -1207,7 +1323,10 @@ impl Expr { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum Subscript { /// Accesses the element of the array at the given index. - Index { index: Expr }, + Index { + /// The index expression used to access the array element. + index: Expr, + }, /// Accesses a slice of an array on PostgreSQL, e.g. /// @@ -1231,8 +1350,11 @@ pub enum Subscript { /// {1,3,5} /// ``` Slice { + /// Optional lower bound for the slice (inclusive). lower_bound: Option, + /// Optional upper bound for the slice (inclusive). upper_bound: Option, + /// Optional stride for the slice (step size). stride: Option, }, } @@ -1982,11 +2104,21 @@ impl fmt::Display for Expr { } } +/// The type of a window used in `OVER` clauses. +/// +/// A window can be either an inline specification (`WindowSpec`) or a +/// reference to a previously defined named window. +/// +/// - `WindowSpec(WindowSpec)`: An inline window specification, e.g. +/// `OVER (PARTITION BY ... ORDER BY ...)`. +/// - `NamedWindow(Ident)`: A reference to a named window declared elsewhere. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum WindowType { + /// An inline window specification. WindowSpec(WindowSpec), + /// A reference to a previously defined named window. NamedWindow(Ident), } @@ -2081,7 +2213,9 @@ impl fmt::Display for WindowSpec { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct WindowFrame { + /// Units for the frame (e.g. `ROWS`, `RANGE`, `GROUPS`). pub units: WindowFrameUnits, + /// The start bound of the window frame. pub start_bound: WindowFrameBound, /// The right bound of the `BETWEEN .. AND` clause. The end bound of `None` /// indicates the shorthand form (e.g. `ROWS 1 PRECEDING`), which must @@ -2106,9 +2240,13 @@ impl Default for WindowFrame { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Units used to describe the window frame scope. pub enum WindowFrameUnits { + /// `ROWS` unit. Rows, + /// `RANGE` unit. Range, + /// `GROUPS` unit. Groups, } @@ -2128,8 +2266,11 @@ impl fmt::Display for WindowFrameUnits { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// How NULL values are treated in certain window functions. pub enum NullTreatment { + /// Ignore NULL values (e.g. `IGNORE NULLS`). IgnoreNulls, + /// Respect NULL values (e.g. `RESPECT NULLS`). RespectNulls, } @@ -2170,9 +2311,13 @@ impl fmt::Display for WindowFrameBound { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Indicates partition operation type for partition management statements. pub enum AddDropSync { + /// Add partitions. ADD, + /// Drop partitions. DROP, + /// Sync partitions. SYNC, } @@ -2189,12 +2334,19 @@ impl fmt::Display for AddDropSync { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Object kinds supported by `SHOW CREATE` statements. pub enum ShowCreateObject { + /// An event object for `SHOW CREATE EVENT`. Event, + /// A function object for `SHOW CREATE FUNCTION`. Function, + /// A procedure object for `SHOW CREATE PROCEDURE`. Procedure, + /// A table object for `SHOW CREATE TABLE`. Table, + /// A trigger object for `SHOW CREATE TRIGGER`. Trigger, + /// A view object for `SHOW CREATE VIEW`. View, } @@ -2214,13 +2366,21 @@ impl fmt::Display for ShowCreateObject { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Objects that can be targeted by a `COMMENT` statement. pub enum CommentObject { + /// A table column. Column, + /// A table. Table, + /// An extension. Extension, + /// A schema. Schema, + /// A database. Database, + /// A user. User, + /// A role. Role, } @@ -2241,8 +2401,11 @@ impl fmt::Display for CommentObject { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Password specification variants used in user-related statements. pub enum Password { + /// A concrete password expression. Password(Expr), + /// Represents a `NULL` password. NullPassword, } @@ -2268,8 +2431,11 @@ pub enum Password { pub struct CaseStatement { /// The `CASE` token that starts the statement. pub case_token: AttachedToken, + /// Optional expression to match against in `CASE ... WHEN`. pub match_expr: Option, + /// The `WHEN ... THEN` blocks of the `CASE` statement. pub when_blocks: Vec, + /// Optional `ELSE` block for the `CASE` statement. pub else_block: Option, /// The last token of the statement (`END` or `CASE`). pub end_case_token: AttachedToken, @@ -2336,9 +2502,13 @@ impl fmt::Display for CaseStatement { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct IfStatement { + /// The initial `IF` block containing the condition and statements. pub if_block: ConditionalStatementBlock, + /// Additional `ELSEIF` blocks. pub elseif_blocks: Vec, + /// Optional `ELSE` block. pub else_block: Option, + /// Optional trailing `END` token for the `IF` statement. pub end_token: Option, } @@ -2384,6 +2554,7 @@ impl fmt::Display for IfStatement { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct WhileStatement { + /// Block executed while the condition holds. pub while_block: ConditionalStatementBlock, } @@ -2423,13 +2594,18 @@ impl fmt::Display for WhileStatement { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ConditionalStatementBlock { + /// Token representing the start of the block (e.g., WHEN/IF/WHILE). pub start_token: AttachedToken, + /// Optional condition expression for the block. pub condition: Option, + /// Optional token for the `THEN` keyword. pub then_token: Option, + /// The statements contained in this conditional block. pub conditional_statements: ConditionalStatements, } impl ConditionalStatementBlock { + /// Get the statements in this conditional block. pub fn statements(&self) -> &Vec { self.conditional_statements.statements() } @@ -2466,14 +2642,19 @@ impl fmt::Display for ConditionalStatementBlock { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Statements used inside conditional blocks (`IF`, `WHEN`, `WHILE`). pub enum ConditionalStatements { - /// SELECT 1; SELECT 2; SELECT 3; ... - Sequence { statements: Vec }, - /// BEGIN SELECT 1; SELECT 2; SELECT 3; ... END + /// Simple sequence of statements (no `BEGIN`/`END`). + Sequence { + /// The statements in the sequence. + statements: Vec, + }, + /// Block enclosed by `BEGIN` and `END`. BeginEnd(BeginEndStatements), } impl ConditionalStatements { + /// Get the statements in this conditional statements block. pub fn statements(&self) -> &Vec { match self { ConditionalStatements::Sequence { statements } => statements, @@ -2508,8 +2689,11 @@ impl fmt::Display for ConditionalStatements { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct BeginEndStatements { + /// Token representing the `BEGIN` keyword (may include span info). pub begin_token: AttachedToken, + /// Statements contained within the block. pub statements: Vec, + /// Token representing the `END` keyword (may include span info). pub end_token: AttachedToken, } @@ -2549,6 +2733,7 @@ impl fmt::Display for BeginEndStatements { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct RaiseStatement { + /// Optional value provided to the RAISE statement. pub value: Option, } @@ -2806,33 +2991,18 @@ impl fmt::Display for Declare { #[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Options allowed within a `CREATE TABLE` statement. pub enum CreateTableOptions { + /// No options specified. #[default] None, - /// Options specified using the `WITH` keyword. - /// e.g. `WITH (description = "123")` - /// - /// - /// - /// MSSQL supports more specific options that's not only key-value pairs. - /// - /// WITH ( - /// DISTRIBUTION = ROUND_ROBIN, - /// CLUSTERED INDEX (column_a DESC, column_b) - /// ) - /// - /// + /// Options specified using the `WITH` keyword, e.g. `WITH (k = v)`. With(Vec), - /// Options specified using the `OPTIONS` keyword. - /// e.g. `OPTIONS(description = "123")` - /// - /// + /// Options specified using the `OPTIONS(...)` clause. Options(Vec), - - /// Plain options, options which are not part on any declerative statement e.g. WITH/OPTIONS/... - /// + /// Plain space-separated options. Plain(Vec), - + /// Table properties (e.g., TBLPROPERTIES / storage properties). TableProperties(Vec), } @@ -2893,8 +3063,11 @@ impl Display for FromTable { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Type of `CREATE POLICY` (permissive or restrictive). pub enum CreatePolicyType { + /// Policy allows operations unless explicitly denied. Permissive, + /// Policy denies operations unless explicitly allowed. Restrictive, } @@ -2906,35 +3079,54 @@ pub enum CreatePolicyType { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Commands that a policy can apply to (FOR clause). pub enum CreatePolicyCommand { + /// Applies to all commands. All, + /// Applies to SELECT. Select, + /// Applies to INSERT. Insert, + /// Applies to UPDATE. Update, + /// Applies to DELETE. Delete, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Variants for the `SET` family of statements. pub enum Set { /// SQL Standard-style /// SET a = 1; + /// `SET var = value` (standard SQL-style assignment). SingleAssignment { + /// Optional scope modifier (`SESSION` / `LOCAL`). scope: Option, + /// Whether this is a Hive-style `HIVEVAR:` assignment. hivevar: bool, + /// Variable name to assign. variable: ObjectName, + /// Values assigned to the variable. values: Vec, }, /// Snowflake-style /// SET (a, b, ..) = (1, 2, ..); + /// `SET (a, b) = (1, 2)` (tuple assignment syntax). ParenthesizedAssignments { + /// Variables being assigned in tuple form. variables: Vec, + /// Corresponding values for the variables. values: Vec, }, /// MySQL-style /// SET a = 1, b = 2, ..; - MultipleAssignments { assignments: Vec }, + /// `SET a = 1, b = 2` (MySQL-style comma-separated assignments). + MultipleAssignments { + /// List of `SET` assignments (MySQL-style comma-separated). + assignments: Vec, + }, /// Session authorization for Postgres/Redshift /// /// ```sql @@ -2971,12 +3163,21 @@ pub enum Set { /// Note: this is a PostgreSQL-specific statements /// `SET TIME ZONE ` is an alias for `SET timezone TO ` in PostgreSQL /// However, we allow it for all dialects. - SetTimeZone { local: bool, value: Expr }, + /// `SET TIME ZONE` statement. `local` indicates the `LOCAL` keyword. + /// `SET TIME ZONE ` statement. + SetTimeZone { + /// Whether the `LOCAL` keyword was specified. + local: bool, + /// Time zone expression value. + value: Expr, + }, /// ```sql /// SET NAMES 'charset_name' [COLLATE 'collation_name'] /// ``` SetNames { + /// Character set name to set. charset_name: Ident, + /// Optional collation name. collation_name: Option, }, /// ```sql @@ -2989,8 +3190,11 @@ pub enum Set { /// SET TRANSACTION ... /// ``` SetTransaction { + /// Transaction modes (e.g., ISOLATION LEVEL, READ ONLY). modes: Vec, + /// Optional snapshot value for transaction snapshot control. snapshot: Option, + /// `true` when the `SESSION` keyword was used. session: bool, }, } @@ -3091,7 +3295,9 @@ impl Display for Set { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ExceptionWhen { + /// Identifiers that trigger this branch (error conditions). pub idents: Vec, + /// Statements to execute when the condition matches. pub statements: Vec, } @@ -3118,13 +3324,21 @@ impl Display for ExceptionWhen { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Analyze { #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] + /// Name of the table to analyze. pub table_name: ObjectName, + /// Optional partition expressions to restrict the analysis. pub partitions: Option>, + /// `true` when analyzing specific columns. pub for_columns: bool, + /// Columns to analyze when `for_columns` is `true`. pub columns: Vec, + /// Whether to cache metadata before analyzing. pub cache_metadata: bool, + /// Whether to skip scanning the table. pub noscan: bool, + /// Whether to compute statistics during analysis. pub compute_statistics: bool, + /// Whether the `TABLE` keyword was present. pub has_table_keyword: bool, } @@ -3180,6 +3394,7 @@ pub enum Statement { /// ``` /// Analyze (Hive) Analyze(Analyze), + /// `SET` statements (session, transaction, timezone, etc.). Set(Set), /// ```sql /// TRUNCATE @@ -3214,11 +3429,17 @@ pub enum Statement { extension_name: Ident, }, // 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, + /// Source query providing data to load. source: Box, }, /// A `CASE` statement. @@ -3262,19 +3483,33 @@ pub enum Statement { /// 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>, + /// Optional source object name (staged data). from_obj: Option, + /// Optional alias for the source object. from_obj_alias: Option, + /// Stage-specific parameters (e.g., credentials, path). stage_params: StageParamsObject, + /// Optional list of transformations applied when loading. from_transformations: Option>, + /// Optional source query instead of a staged object. from_query: Option>, + /// Optional list of specific file names to load. files: Option>, + /// Optional filename matching pattern. pattern: Option, + /// File format options. file_format: KeyValueOptions, + /// Additional copy options. copy_options: KeyValueOptions, + /// Optional validation mode string. validation_mode: Option, + /// Optional partition expression for loading. partition: Option>, }, /// ```sql @@ -3312,9 +3547,13 @@ pub enum Statement { /// 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, }, /// ```sql @@ -3331,12 +3570,19 @@ pub enum Statement { /// ``` /// 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, + /// `true` when `IF NOT EXISTS` was present. if_not_exists: bool, + /// Optional secret name. name: Option, + /// Optional storage specifier identifier. storage_specifier: Option, + /// The secret type identifier. secret_type: Ident, + /// Additional secret options. options: Vec, }, /// A `CREATE SERVER` statement. @@ -3346,13 +3592,20 @@ pub enum Statement { /// ``` /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createpolicy.html) CreatePolicy { + /// Name of the policy. name: Ident, + /// Table the policy is defined on. #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, + /// Optional policy type (e.g., `PERMISSIVE` / `RESTRICTIVE`). policy_type: Option, + /// Optional command the policy applies to (e.g., `SELECT`). command: Option, + /// Optional list of grantee owners. to: Option>, + /// Optional expression for the `USING` clause. using: Option, + /// Optional expression for the `WITH CHECK` clause. with_check: Option, }, /// ```sql @@ -3388,18 +3641,23 @@ pub enum Statement { /// ALTER INDEX /// ``` AlterIndex { + /// Name of the index to alter. name: ObjectName, + /// The operation to perform on the index. operation: AlterIndexOperation, }, /// ```sql /// ALTER VIEW /// ``` AlterView { - /// View name + /// View name being altered. #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] name: ObjectName, + /// Optional new column list for the view. columns: Vec, + /// Replacement query for the view definition. query: Box, + /// Additional WITH options for the view. with_options: Vec, }, /// ```sql @@ -3418,10 +3676,17 @@ pub enum Statement { /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropfamily.html) AlterOperatorFamily(AlterOperatorFamily), /// ```sql + /// ALTER OPERATOR CLASS + /// ``` + /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html) + AlterOperatorClass(AlterOperatorClass), + /// ```sql /// ALTER ROLE /// ``` AlterRole { + /// Role name being altered. name: Ident, + /// Operation to perform on the role. operation: AlterRoleOperation, }, /// ```sql @@ -3429,9 +3694,12 @@ pub enum Statement { /// ``` /// (Postgresql-specific) AlterPolicy { + /// Policy name to alter. name: Ident, + /// Target table name the policy is defined on. #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, + /// Optional operation specific to the policy alteration. operation: AlterPolicyOperation, }, /// ```sql @@ -3443,9 +3711,13 @@ pub enum Statement { /// ``` /// (Hive-specific) AlterConnector { + /// Name of the connector to alter. name: Ident, + /// Optional connector properties to set. properties: Option>, + /// Optional new URL for the connector. url: Option, + /// Optional new owner specification. owner: Option, }, /// ```sql @@ -3477,12 +3749,15 @@ pub enum Statement { /// ``` /// See AttachDuckDBDatabase { + /// `true` when `IF NOT EXISTS` was present. if_not_exists: bool, - /// true if the syntax is 'ATTACH DATABASE', false if it's just 'ATTACH' + /// `true` if the syntax used `ATTACH DATABASE` rather than `ATTACH`. database: bool, - /// An expression that indicates the path to the database file + /// The path identifier to the database file being attached. database_path: Ident, + /// Optional alias assigned to the attached database. database_alias: Option, + /// Dialect-specific attach options (e.g., `READ_ONLY`). attach_options: Vec, }, /// (DuckDB-specific) @@ -3491,9 +3766,11 @@ pub enum Statement { /// ``` /// See DetachDuckDBDatabase { + /// `true` when `IF EXISTS` was present. if_exists: bool, - /// true if the syntax is 'DETACH DATABASE', false if it's just 'DETACH' + /// `true` if the syntax used `DETACH DATABASE` rather than `DETACH`. database: bool, + /// Alias of the database to detach. database_alias: Ident, }, /// ```sql @@ -3537,19 +3814,24 @@ pub enum Statement { /// DROP PROCEDURE /// ``` DropProcedure { + /// `true` when `IF EXISTS` was present. if_exists: bool, - /// One or more function to drop + /// One or more functions/procedures to drop. proc_desc: Vec, - /// `CASCADE` or `RESTRICT` + /// Optional drop behavior (`CASCADE` or `RESTRICT`). drop_behavior: Option, }, /// ```sql /// DROP SECRET /// ``` DropSecret { + /// `true` when `IF EXISTS` was present. if_exists: bool, + /// Optional `TEMPORARY` marker. temporary: Option, + /// Name of the secret to drop. name: Ident, + /// Optional storage specifier identifier. storage_specifier: Option, }, ///```sql @@ -3557,9 +3839,13 @@ pub enum Statement { /// ``` /// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-droppolicy.html) DropPolicy { + /// `true` when `IF EXISTS` was present. if_exists: bool, + /// Name of the policy to drop. name: Ident, + /// Name of the table the policy applies to. table_name: ObjectName, + /// Optional drop behavior (`CASCADE` or `RESTRICT`). drop_behavior: Option, }, /// ```sql @@ -3567,7 +3853,9 @@ pub enum Statement { /// ``` /// 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, }, /// ```sql @@ -3578,6 +3866,7 @@ pub enum Statement { /// Note: this is a PostgreSQL-specific statement, /// but may also compatible with other SQL. Declare { + /// Cursor declaration statements collected by `DECLARE`. stmts: Vec, }, /// ```sql @@ -3623,9 +3912,11 @@ pub enum Statement { 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, It's possible to fetch rows form cursor to the table + /// Optional target table to fetch rows into. into: Option, }, /// ```sql @@ -3635,11 +3926,17 @@ pub enum Statement { /// 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, + /// Optional channel name used for flush operations. channel: Option, + /// 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, }, /// ```sql @@ -3649,12 +3946,14 @@ pub enum Statement { /// 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, }, /// `SHOW FUNCTIONS` /// /// Note: this is a Presto-specific statement. ShowFunctions { + /// Optional filter for which functions to display. filter: Option, }, /// ```sql @@ -3663,6 +3962,7 @@ pub enum Statement { /// /// Note: this is a PostgreSQL-specific statement. ShowVariable { + /// Variable name as one or more identifiers. variable: Vec, }, /// ```sql @@ -3671,8 +3971,11 @@ pub enum Statement { /// /// Note: this is a MySQL-specific statement. ShowStatus { + /// Optional filter for which status entries to display. filter: Option, + /// `true` when `GLOBAL` scope was requested. global: bool, + /// `true` when `SESSION` scope was requested. session: bool, }, /// ```sql @@ -3681,8 +3984,11 @@ pub enum Statement { /// /// Note: this is a MySQL-specific statement. ShowVariables { + /// Optional filter for which variables to display. filter: Option, + /// `true` when `GLOBAL` scope was requested. global: bool, + /// `true` when `SESSION` scope was requested. session: bool, }, /// ```sql @@ -3691,31 +3997,42 @@ pub enum Statement { /// /// 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, }, /// ```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, }, /// ```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, }, /// ```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, }, // ```sql @@ -3723,6 +4040,7 @@ pub enum Statement { // ``` // [MySQL]: // + /// Show the available character sets (alias `CHARSET`). ShowCharset(ShowCharset), /// ```sql /// SHOW OBJECTS LIKE 'line%' IN mydb.public @@ -3734,19 +4052,28 @@ pub enum Statement { /// 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, }, /// ```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, }, /// ```sql @@ -3755,6 +4082,7 @@ pub enum Statement { /// /// Note: this is a MySQL-specific statement. ShowCollation { + /// Optional filter for which collations to display. filter: Option, }, /// ```sql @@ -3771,9 +4099,13 @@ pub enum Statement { /// ``` /// If `begin` is true StartTransaction { + /// Transaction modes such as `ISOLATION LEVEL` or `READ WRITE`. modes: Vec, + /// `true` when this was parsed as `BEGIN` instead of `START`. begin: bool, + /// Optional specific keyword used: `TRANSACTION` or `WORK`. transaction: Option, + /// Optional transaction modifier (e.g., `AND NO CHAIN`). modifier: Option, /// List of statements belonging to the `BEGIN` block. /// Example: @@ -3807,8 +4139,11 @@ pub enum Statement { /// /// 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, /// An optional `IF EXISTS` clause. (Non-standard.) /// See @@ -3824,15 +4159,20 @@ pub enum Statement { /// ``` /// 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, }, /// ```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, }, /// ```sql @@ -3841,6 +4181,7 @@ pub enum Statement { CreateSchema { /// ` | AUTHORIZATION | AUTHORIZATION ` schema_name: SchemaName, + /// `true` when `IF NOT EXISTS` was present. if_not_exists: bool, /// Schema properties. /// @@ -3881,25 +4222,45 @@ pub enum Statement { /// See: /// CreateDatabase { + /// Database name. db_name: ObjectName, + /// `IF NOT EXISTS` flag. if_not_exists: bool, + /// Optional location URI. location: Option, + /// Optional managed location. managed_location: Option, + /// `OR REPLACE` flag. or_replace: bool, + /// `TRANSIENT` flag. transient: bool, + /// Optional clone source. clone: Option, + /// Optional data retention time in days. data_retention_time_in_days: Option, + /// Optional maximum data extension time in days. max_data_extension_time_in_days: Option, + /// Optional external volume identifier. external_volume: Option, + /// Optional catalog name. catalog: Option, + /// Whether to replace invalid characters. replace_invalid_characters: Option, + /// Default DDL collation string. default_ddl_collation: Option, + /// Storage serialization policy. storage_serialization_policy: Option, + /// Optional comment. comment: Option, + /// Optional catalog sync identifier. catalog_sync: Option, + /// Catalog sync namespace mode. catalog_sync_namespace_mode: Option, + /// Optional flatten delimiter for namespace sync. catalog_sync_namespace_flatten_delimiter: Option, + /// Optional tags for the database. with_tags: Option>, + /// Optional contact entries for the database. with_contacts: Option>, }, /// ```sql @@ -3920,10 +4281,15 @@ pub enum Statement { /// CREATE PROCEDURE /// ``` CreateProcedure { + /// `OR ALTER` flag. or_alter: bool, + /// Procedure name. name: ObjectName, + /// Optional procedure parameters. params: Option>, + /// Optional language identifier. language: Option, + /// Procedure body statements. body: ConditionalStatements, }, /// ```sql @@ -3933,10 +4299,15 @@ pub enum Statement { /// 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>, + /// Macro definition body. definition: MacroDefinition, }, /// ```sql @@ -3944,33 +4315,51 @@ pub enum Statement { /// ``` /// See 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, }, /// ```sql /// ASSERT [AS ] /// ``` Assert { + /// Assertion condition expression. condition: Expr, + /// Optional message expression. message: Option, }, /// ```sql /// GRANT privileges ON objects TO grantees /// ``` Grant { + /// Privileges being granted. privileges: Privileges, + /// Optional objects the privileges apply to. objects: Option, + /// List of grantees receiving the privileges. grantees: Vec, + /// Whether `WITH GRANT OPTION` is present. with_grant_option: bool, + /// Optional `AS GRANTOR` identifier. as_grantor: Option, + /// Optional `GRANTED BY` identifier. granted_by: Option, + /// Optional `CURRENT GRANTS` modifier. current_grants: Option, }, /// ```sql @@ -3981,10 +4370,15 @@ pub enum Statement { /// REVOKE privileges ON objects FROM grantees /// ``` Revoke { + /// Privileges to revoke. privileges: Privileges, + /// Optional objects from which to revoke. objects: Option, + /// Grantees affected by the revoke. grantees: Vec, + /// Optional `GRANTED BY` identifier. granted_by: Option, + /// Optional `CASCADE`/`RESTRICT` behavior. cascade: Option, }, /// ```sql @@ -3993,7 +4387,9 @@ pub enum Statement { /// /// Note: this is a PostgreSQL-specific statement. Deallocate { + /// Name to deallocate (or `ALL`). name: Ident, + /// Whether `PREPARE` keyword was present. prepare: bool, }, /// ```sql @@ -4005,12 +4401,17 @@ pub enum Statement { /// BigQuery: /// Snowflake: Execute { + /// Optional function/procedure name. name: Option, + /// Parameter expressions passed to execute. parameters: Vec, + /// Whether parentheses were present. has_parentheses: bool, - /// Is this an `EXECUTE IMMEDIATE` + /// Is this an `EXECUTE IMMEDIATE`. immediate: bool, + /// Identifiers to capture results into. into: Vec, + /// `USING` expressions with optional aliases. using: Vec, /// Whether the last parameter is the return value of the procedure /// MSSQL: @@ -4025,8 +4426,11 @@ pub enum Statement { /// /// Note: this is a PostgreSQL-specific statement. Prepare { + /// Name of the prepared statement. name: Ident, + /// Optional data types for parameters. data_types: Vec, + /// Statement being prepared. statement: Box, }, /// ```sql @@ -4036,8 +4440,10 @@ pub enum Statement { /// See /// See Kill { + /// Optional kill modifier (CONNECTION, QUERY, MUTATION). modifier: Option, // processlist_id + /// The id of the process to kill. id: u64, }, /// ```sql @@ -4066,7 +4472,7 @@ pub enum Statement { describe_alias: DescribeAlias, /// Carry out the command and show actual run times and other statistics. analyze: bool, - // Display additional information regarding the plan. + /// Display additional information regarding the plan. verbose: bool, /// `EXPLAIN QUERY PLAN` /// Display the query plan without running the query. @@ -4088,12 +4494,14 @@ pub enum Statement { /// ``` /// Define a new savepoint within the current transaction Savepoint { + /// Name of the savepoint being defined. name: Ident, }, /// ```sql /// RELEASE [ SAVEPOINT ] savepoint_name /// ``` ReleaseSavepoint { + /// Name of the savepoint to release. name: Ident, }, /// A `MERGE` statement. @@ -4118,6 +4526,7 @@ pub enum Statement { /// 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, @@ -4131,6 +4540,7 @@ pub enum Statement { /// Table name #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] table_name: ObjectName, + /// `true` when `IF EXISTS` was present. if_exists: bool, }, /// ```sql @@ -4138,11 +4548,17 @@ pub enum Statement { /// ``` /// 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, + /// Sequence options (INCREMENT, MINVALUE, etc.). sequence_options: Vec, + /// Optional `OWNED BY` target. owned_by: Option, }, /// A `CREATE DOMAIN` statement. @@ -4151,15 +4567,20 @@ pub enum Statement { /// CREATE TYPE /// ``` CreateType { + /// Type name to create. name: ObjectName, + /// Optional type representation details. representation: Option, }, /// ```sql /// PRAGMA . = /// ``` Pragma { + /// Pragma name (possibly qualified). name: ObjectName, + /// Optional pragma value. value: Option, + /// Whether the pragma used `=`. is_eq: bool, }, /// ```sql @@ -4167,6 +4588,7 @@ pub enum Statement { /// ``` /// Note: this is a MySQL-specific statement. See LockTables { + /// List of tables to lock with modes. tables: Vec, }, /// ```sql @@ -4186,11 +4608,17 @@ pub enum Statement { /// UNLOAD('statement') TO [ OPTIONS ] /// ``` Unload { + /// Optional query AST to unload. query: Option>, + /// Optional original query text. query_text: Option, + /// Destination identifier. to: Ident, + /// Optional IAM role/auth information. auth: Option, + /// Additional `WITH` options. with: Vec, + /// Legacy copy-style options. options: Vec, }, /// ```sql @@ -4199,10 +4627,15 @@ pub enum Statement { /// /// See ClickHouse OptimizeTable { + /// Table name to optimize. name: ObjectName, + /// Optional cluster identifier. on_cluster: Option, + /// Optional partition spec. partition: Option, + /// Whether `FINAL` was specified. include_final: bool, + /// Optional deduplication settings. deduplicate: Option, }, /// ```sql @@ -4212,6 +4645,7 @@ pub enum Statement { /// /// See Postgres LISTEN { + /// Notification channel identifier. channel: Ident, }, /// ```sql @@ -4221,6 +4655,7 @@ pub enum Statement { /// /// See Postgres UNLISTEN { + /// Notification channel identifier. channel: Ident, }, /// ```sql @@ -4230,7 +4665,9 @@ pub enum Statement { /// /// See Postgres NOTIFY { + /// Notification channel identifier. channel: Ident, + /// Optional payload string. payload: Option, }, /// ```sql @@ -4242,11 +4679,17 @@ pub enum Statement { /// /// See Hive 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>, + /// Optional table format information. table_format: Option, }, /// ```sql @@ -4269,10 +4712,15 @@ pub enum Statement { /// [ WITH option [ , ...n ] ] /// See RaisError { + /// Error message expression or identifier. message: Box, + /// Severity expression. severity: Box, + /// State expression. state: Box, + /// Substitution arguments for the message. arguments: Vec, + /// Additional `WITH` options for RAISERROR. options: Vec, }, /// ```sql @@ -4350,7 +4798,9 @@ impl From for Statement { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum CurrentGrantsKind { + /// `COPY CURRENT GRANTS` (copy current grants to target). CopyCurrentGrants, + /// `REVOKE CURRENT GRANTS` (revoke current grants from target). RevokeCurrentGrants, } @@ -4366,9 +4816,14 @@ impl fmt::Display for CurrentGrantsKind { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `RAISERROR` options +/// See pub enum RaisErrorOption { + /// Log the error. Log, + /// Do not wait for completion. NoWait, + /// Set the error state. SetError, } @@ -4982,6 +5437,9 @@ impl fmt::Display for Statement { Statement::AlterOperatorFamily(alter_operator_family) => { write!(f, "{alter_operator_family}") } + Statement::AlterOperatorClass(alter_operator_class) => { + write!(f, "{alter_operator_class}") + } Statement::AlterRole { name, operation } => { write!(f, "ALTER ROLE {name} {operation}") } @@ -5831,11 +6289,17 @@ impl fmt::Display for Statement { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum SequenceOptions { + /// `INCREMENT [BY] ` option; second value indicates presence of `BY` keyword. IncrementBy(Expr, bool), + /// `MINVALUE ` or `NO MINVALUE`. MinValue(Option), + /// `MAXVALUE ` or `NO MAXVALUE`. MaxValue(Option), + /// `START [WITH] `; second value indicates presence of `WITH`. StartWith(Expr, bool), + /// `CACHE ` option. Cache(Expr), + /// `CYCLE` or `NO CYCLE` option. Cycle(bool), } @@ -5885,8 +6349,11 @@ impl fmt::Display for SequenceOptions { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct SetAssignment { + /// Optional context scope (e.g., SESSION or LOCAL). pub scope: Option, + /// Assignment target name. pub name: ObjectName, + /// Assigned expression value. pub value: Expr, } @@ -5933,7 +6400,9 @@ impl fmt::Display for TruncateTableTarget { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum TruncateIdentityOption { + /// Restart identity values (RESTART IDENTITY). Restart, + /// Continue identity values (CONTINUE IDENTITY). Continue, } @@ -5943,7 +6412,9 @@ pub enum TruncateIdentityOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum CascadeOption { + /// Apply cascading action (e.g., CASCADE). Cascade, + /// Restrict the action (e.g., RESTRICT). Restrict, } @@ -5961,7 +6432,9 @@ impl Display for CascadeOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum BeginTransactionKind { + /// Standard `TRANSACTION` keyword. Transaction, + /// Alternate `WORK` keyword. Work, } @@ -5980,11 +6453,11 @@ impl Display for BeginTransactionKind { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum MinMaxValue { - // clause is not specified + /// Clause is not specified. Empty, - // NO MINVALUE/NO MAXVALUE + /// NO MINVALUE / NO MAXVALUE. None, - // MINVALUE / MAXVALUE + /// `MINVALUE ` / `MAXVALUE `. Some(Expr), } @@ -5992,6 +6465,7 @@ pub enum MinMaxValue { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[non_exhaustive] +/// Behavior to apply for `INSERT` when a conflict occurs. pub enum OnInsert { /// ON DUPLICATE KEY UPDATE (MySQL when the key already exists, then execute an update instead) DuplicateKeyUpdate(Vec), @@ -6002,40 +6476,53 @@ pub enum OnInsert { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Optional aliases for `INSERT` targets: row alias and optional column aliases. pub struct InsertAliases { + /// Row alias (table-style alias) for the inserted values. pub row_alias: ObjectName, + /// Optional list of column aliases for the inserted values. pub col_aliases: Option>, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `ON CONFLICT` clause representation. pub struct OnConflict { + /// Optional conflict target specifying columns or constraint. pub conflict_target: Option, + /// Action to take when a conflict occurs. pub action: OnConflictAction, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Target specification for an `ON CONFLICT` clause. pub enum ConflictTarget { + /// Target specified as a list of columns. Columns(Vec), + /// Target specified as a named constraint. OnConstraint(ObjectName), } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Action to perform when an `ON CONFLICT` target is matched. pub enum OnConflictAction { + /// Do nothing on conflict. DoNothing, + /// Perform an update on conflict. DoUpdate(DoUpdate), } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Details for `DO UPDATE` action of an `ON CONFLICT` clause. pub struct DoUpdate { - /// Column assignments + /// Column assignments to perform on update. pub assignments: Vec, - /// WHERE + /// Optional WHERE clause limiting the update. pub selection: Option, } @@ -6132,21 +6619,48 @@ impl fmt::Display for Privileges { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FetchDirection { - Count { limit: Value }, + /// Fetch a specific count of rows. + Count { + /// The limit value for the count. + limit: Value, + }, + /// Fetch the next row. Next, + /// Fetch the prior row. Prior, + /// Fetch the first row. First, + /// Fetch the last row. Last, - Absolute { limit: Value }, - Relative { limit: Value }, + /// Fetch an absolute row by index. + Absolute { + /// The absolute index value. + limit: Value, + }, + /// Fetch a row relative to the current position. + Relative { + /// The relative offset value. + limit: Value, + }, + /// Fetch all rows. All, // FORWARD // FORWARD count - Forward { limit: Option }, + /// Fetch forward by an optional limit. + Forward { + /// Optional forward limit. + limit: Option, + }, + /// Fetch all forward rows. ForwardAll, // BACKWARD // BACKWARD count - Backward { limit: Option }, + /// Fetch backward by an optional limit. + Backward { + /// Optional backward limit. + limit: Option, + }, + /// Fetch all backward rows. BackwardAll, } @@ -6198,7 +6712,9 @@ impl fmt::Display for FetchDirection { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FetchPosition { + /// Use `FROM ` position specifier. From, + /// Use `IN ` position specifier. In, } @@ -6218,71 +6734,125 @@ impl fmt::Display for FetchPosition { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum Action { + /// Add a search optimization. AddSearchOptimization, + /// Apply an `APPLY` operation with a specific type. Apply { + /// The type of apply operation. apply_type: ActionApplyType, }, + /// Apply a budget operation. ApplyBudget, + /// Attach a listing. AttachListing, + /// Attach a policy. AttachPolicy, + /// Audit operation. Audit, + /// Bind a service endpoint. BindServiceEndpoint, + /// Connect permission. Connect, + /// Create action, optionally specifying an object type. Create { + /// Optional object type to create. obj_type: Option, }, + /// Actions related to database roles. DatabaseRole { + /// The role name. role: ObjectName, }, + /// Delete permission. Delete, + /// Drop permission. Drop, + /// Evolve schema permission. EvolveSchema, + /// Exec action (execute) with optional object type. Exec { + /// Optional execute object type. obj_type: Option, }, + /// Execute action with optional object type. Execute { + /// Optional execute object type. obj_type: Option, }, + /// Failover operation. Failover, + /// Use imported privileges. ImportedPrivileges, + /// Import a share. ImportShare, + /// Insert rows with optional column list. Insert { + /// Optional list of target columns for insert. columns: Option>, }, + /// Manage operation with a specific manage type. Manage { + /// The specific manage sub-type. manage_type: ActionManageType, }, + /// Manage releases. ManageReleases, + /// Manage versions. ManageVersions, + /// Modify operation with an optional modify type. Modify { + /// The optional modify sub-type. modify_type: Option, }, + /// Monitor operation with an optional monitor type. Monitor { + /// The optional monitor sub-type. monitor_type: Option, }, + /// Operate permission. Operate, + /// Override share restrictions. OverrideShareRestrictions, + /// Ownership permission. Ownership, + /// Purchase a data exchange listing. PurchaseDataExchangeListing, + + /// Read access. Read, + /// Read session-level access. ReadSession, + /// References with optional column list. References { + /// Optional list of referenced column identifiers. columns: Option>, }, + /// Replication permission. Replicate, + /// Resolve all references. ResolveAll, + /// Role-related permission with target role name. Role { + /// The target role name. role: ObjectName, }, + /// Select permission with optional column list. Select { + /// Optional list of selected columns. columns: Option>, }, + /// Temporary object permission. Temporary, + /// Trigger-related permission. Trigger, + /// Truncate permission. Truncate, + /// Update permission with optional affected columns. Update { + /// Optional list of columns affected by update. columns: Option>, }, + /// Usage permission. Usage, } @@ -6376,22 +6946,39 @@ impl fmt::Display for Action { /// See /// under `globalPrivileges` in the `CREATE` privilege. pub enum ActionCreateObjectType { + /// An account-level object. Account, + /// An application object. Application, + /// An application package object. ApplicationPackage, + /// A compute pool object. ComputePool, + /// A data exchange listing. DataExchangeListing, + /// A database object. Database, + /// An external volume object. ExternalVolume, + /// A failover group object. FailoverGroup, + /// An integration object. Integration, + /// A network policy object. NetworkPolicy, + /// An organization listing. OrganiationListing, + /// A replication group object. ReplicationGroup, + /// A role object. Role, + /// A schema object. Schema, + /// A share object. Share, + /// A user object. User, + /// A warehouse object. Warehouse, } @@ -6425,15 +7012,25 @@ impl fmt::Display for ActionCreateObjectType { /// See /// under `globalPrivileges` in the `APPLY` privilege. pub enum ActionApplyType { + /// Apply an aggregation policy. AggregationPolicy, + /// Apply an authentication policy. AuthenticationPolicy, + /// Apply a join policy. JoinPolicy, + /// Apply a masking policy. MaskingPolicy, + /// Apply a packages policy. PackagesPolicy, + /// Apply a password policy. PasswordPolicy, + /// Apply a projection policy. ProjectionPolicy, + /// Apply a row access policy. RowAccessPolicy, + /// Apply a session policy. SessionPolicy, + /// Apply a tag. Tag, } @@ -6460,10 +7057,15 @@ impl fmt::Display for ActionApplyType { /// See /// under `globalPrivileges` in the `EXECUTE` privilege. pub enum ActionExecuteObjectType { + /// Alert object. Alert, + /// Data metric function object. DataMetricFunction, + /// Managed alert object. ManagedAlert, + /// Managed task object. ManagedTask, + /// Task object. Task, } @@ -6485,12 +7087,19 @@ impl fmt::Display for ActionExecuteObjectType { /// See /// under `globalPrivileges` in the `MANAGE` privilege. pub enum ActionManageType { + /// Account support cases management. AccountSupportCases, + /// Event sharing management. EventSharing, + /// Grants management. Grants, + /// Listing auto-fulfillment management. ListingAutoFulfillment, + /// Organization support cases management. OrganizationSupportCases, + /// User support cases management. UserSupportCases, + /// Warehouses management. Warehouses, } @@ -6514,9 +7123,13 @@ impl fmt::Display for ActionManageType { /// See /// under `globalPrivileges` in the `MODIFY` privilege. pub enum ActionModifyType { + /// Modify log level. LogLevel, + /// Modify trace level. TraceLevel, + /// Modify session log level. SessionLogLevel, + /// Modify session trace level. SessionTraceLevel, } @@ -6537,8 +7150,11 @@ impl fmt::Display for ActionModifyType { /// See /// under `globalPrivileges` in the `MONITOR` privilege. pub enum ActionMonitorType { + /// Monitor execution. Execution, + /// Monitor security. Security, + /// Monitor usage. Usage, } @@ -6557,7 +7173,9 @@ impl fmt::Display for ActionMonitorType { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Grantee { + /// The category/type of grantee (role, user, share, etc.). pub grantee_type: GranteesType, + /// Optional name of the grantee (identifier or user@host). pub name: Option, } @@ -6600,15 +7218,25 @@ impl fmt::Display for Grantee { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// The kind of principal receiving privileges. pub enum GranteesType { + /// A role principal. Role, + /// A share principal. Share, + /// A user principal. User, + /// A group principal. Group, + /// The public principal. Public, + /// A database role principal. DatabaseRole, + /// An application principal. Application, + /// An application role principal. ApplicationRole, + /// No specific principal (e.g. `NONE`). None, } @@ -6620,7 +7248,12 @@ pub enum GranteeName { /// A bare identifier ObjectName(ObjectName), /// A MySQL user/host pair such as 'root'@'%' - UserHost { user: Ident, host: Ident }, + UserHost { + /// The user identifier portion. + user: Ident, + /// The host identifier portion. + host: Ident, + }, } impl fmt::Display for GranteeName { @@ -6640,29 +7273,65 @@ impl fmt::Display for GranteeName { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum GrantObjects { /// Grant privileges on `ALL SEQUENCES IN SCHEMA [, ...]` - AllSequencesInSchema { schemas: Vec }, + AllSequencesInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `ALL TABLES IN SCHEMA [, ...]` - AllTablesInSchema { schemas: Vec }, + AllTablesInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `ALL VIEWS IN SCHEMA [, ...]` - AllViewsInSchema { schemas: Vec }, + AllViewsInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `ALL MATERIALIZED VIEWS IN SCHEMA [, ...]` - AllMaterializedViewsInSchema { schemas: Vec }, + AllMaterializedViewsInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `ALL EXTERNAL TABLES IN SCHEMA [, ...]` - AllExternalTablesInSchema { schemas: Vec }, + AllExternalTablesInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `ALL FUNCTIONS IN SCHEMA [, ...]` - AllFunctionsInSchema { schemas: Vec }, + AllFunctionsInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `FUTURE SCHEMAS IN DATABASE [, ...]` - FutureSchemasInDatabase { databases: Vec }, + FutureSchemasInDatabase { + /// The target database names. + databases: Vec, + }, /// Grant privileges on `FUTURE TABLES IN SCHEMA [, ...]` - FutureTablesInSchema { schemas: Vec }, + FutureTablesInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `FUTURE VIEWS IN SCHEMA [, ...]` - FutureViewsInSchema { schemas: Vec }, + FutureViewsInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `FUTURE EXTERNAL TABLES IN SCHEMA [, ...]` - FutureExternalTablesInSchema { schemas: Vec }, + FutureExternalTablesInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `FUTURE MATERIALIZED VIEWS IN SCHEMA [, ...]` - FutureMaterializedViewsInSchema { schemas: Vec }, + FutureMaterializedViewsInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on `FUTURE SEQUENCES IN SCHEMA [, ...]` - FutureSequencesInSchema { schemas: Vec }, + FutureSequencesInSchema { + /// The target schema names. + schemas: Vec, + }, /// Grant privileges on specific databases Databases(Vec), /// Grant privileges on specific schemas @@ -6697,7 +7366,9 @@ pub enum GrantObjects { /// For example: /// `GRANT USAGE ON PROCEDURE foo(varchar) TO ROLE role1` Procedure { + /// The procedure name. name: ObjectName, + /// Optional argument types for overloaded procedures. arg_types: Vec, }, @@ -6707,7 +7378,9 @@ pub enum GrantObjects { /// For example: /// `GRANT USAGE ON FUNCTION foo(varchar) TO ROLE role1` Function { + /// The function name. name: ObjectName, + /// Optional argument types for overloaded functions. arg_types: Vec, }, } @@ -6866,10 +7539,15 @@ impl fmt::Display for GrantObjects { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct DenyStatement { + /// The privileges to deny. pub privileges: Privileges, + /// The objects the privileges apply to. pub objects: GrantObjects, + /// The grantees (users/roles) to whom the denial applies. pub grantees: Vec, + /// Optional identifier of the principal that performed the grant. pub granted_by: Option, + /// Optional cascade option controlling dependent objects. pub cascade: Option, } @@ -6895,7 +7573,9 @@ impl fmt::Display for DenyStatement { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Assignment { + /// The left-hand side of the assignment. pub target: AssignmentTarget, + /// The expression assigned to the target. pub value: Expr, } @@ -6930,11 +7610,13 @@ impl fmt::Display for AssignmentTarget { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Expression forms allowed as a function argument. pub enum FunctionArgExpr { + /// A normal expression argument. Expr(Expr), /// Qualified wildcard, e.g. `alias.*` or `schema.table.*`. QualifiedWildcard(ObjectName), - /// An unqualified `*` + /// An unqualified `*` wildcard. Wildcard, } @@ -6990,23 +7672,31 @@ impl fmt::Display for FunctionArgOperator { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Forms of function arguments (named, expression-named, or positional). pub enum FunctionArg { /// `name` is identifier /// /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'false' Named { + /// The identifier name of the argument. name: Ident, + /// The argument expression or wildcard form. arg: FunctionArgExpr, + /// The operator separating name and value. operator: FunctionArgOperator, }, /// `name` is arbitrary expression /// /// Enabled when `Dialect::supports_named_fn_args_with_expr_name` returns 'true' ExprNamed { + /// The expression used as the argument name. name: Expr, + /// The argument expression or wildcard form. arg: FunctionArgExpr, + /// The operator separating name and value. operator: FunctionArgOperator, }, + /// An unnamed argument (positional), given by expression or wildcard. Unnamed(FunctionArgExpr), } @@ -7031,9 +7721,15 @@ impl fmt::Display for FunctionArg { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Which cursor(s) to close. pub enum CloseCursor { + /// Close all cursors. All, - Specific { name: Ident }, + /// Close a specific cursor by name. + Specific { + /// The name of the cursor to close. + name: Ident, + }, } impl fmt::Display for CloseCursor { @@ -7065,6 +7761,7 @@ pub struct DropDomain { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct TypedString { + /// The data type of the typed string (e.g. DATE, TIME, TIMESTAMP). pub data_type: DataType, /// The value of the constant. /// Hint: you can unwrap the string value using `value.into_string()`. @@ -7109,6 +7806,7 @@ impl fmt::Display for TypedString { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Function { + /// The function name (may be qualified). pub name: ObjectName, /// Flags whether this function call uses the [ODBC syntax]. /// @@ -7250,6 +7948,7 @@ impl fmt::Display for FunctionArgumentList { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Clauses that can appear inside a function argument list. pub enum FunctionArgumentClause { /// Indicates how `NULL`s should be handled in the calculation, e.g. in `FIRST_VALUE` on [BigQuery]. /// @@ -7321,8 +8020,10 @@ impl fmt::Display for FunctionArgumentClause { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Method { + /// The expression on which the method is invoked. pub expr: Box, // always non-empty + /// The sequence of chained method calls. pub method_chain: Vec, } @@ -7340,8 +8041,9 @@ impl fmt::Display for Method { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// How duplicate values are treated inside function argument lists. pub enum DuplicateTreatment { - /// Perform the calculation only unique values. + /// Consider only unique values. Distinct, /// Retain all duplicate values (the default). All, @@ -7359,10 +8061,11 @@ impl fmt::Display for DuplicateTreatment { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// How the `ANALYZE`/`EXPLAIN ANALYZE` format is specified. pub enum AnalyzeFormatKind { - /// e.g. `EXPLAIN ANALYZE FORMAT JSON SELECT * FROM tbl` + /// Format provided as a keyword, e.g. `FORMAT JSON`. Keyword(AnalyzeFormat), - /// e.g. `EXPLAIN ANALYZE FORMAT=JSON SELECT * FROM tbl` + /// Format provided as an assignment, e.g. `FORMAT=JSON`. Assignment(AnalyzeFormat), } @@ -7378,11 +8081,17 @@ impl fmt::Display for AnalyzeFormatKind { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Output formats supported for `ANALYZE`/`EXPLAIN ANALYZE`. pub enum AnalyzeFormat { + /// Plain text format. TEXT, + /// Graphviz DOT format. GRAPHVIZ, + /// JSON format. JSON, + /// Traditional explain output. TRADITIONAL, + /// Tree-style explain output. TREE, } @@ -7403,12 +8112,19 @@ impl fmt::Display for AnalyzeFormat { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FileFormat { + /// Text file format. TEXTFILE, + /// Sequence file format. SEQUENCEFILE, + /// ORC file format. ORC, + /// Parquet file format. PARQUET, + /// Avro file format. AVRO, + /// RCFile format. RCFILE, + /// JSON file format. JSONFILE, } @@ -7437,7 +8153,9 @@ pub enum ListAggOnOverflow { /// `ON OVERFLOW TRUNCATE [ ] WITH[OUT] COUNT` Truncate { + /// Optional filler expression used when truncating. filler: Option>, + /// Whether to include a count when truncating. with_count: bool, }, } @@ -7478,8 +8196,11 @@ impl fmt::Display for HavingBound { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Which bound is used in a HAVING clause for ANY_VALUE on BigQuery. pub enum HavingBoundKind { + /// The minimum bound. Min, + /// The maximum bound. Max, } @@ -7495,18 +8216,31 @@ impl fmt::Display for HavingBoundKind { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Types of database objects referenced by DDL statements. pub enum ObjectType { + /// A table. Table, + /// A view. View, + /// A materialized view. MaterializedView, + /// An index. Index, + /// A schema. Schema, + /// A database. Database, + /// A role. Role, + /// A sequence. Sequence, + /// A stage. Stage, + /// A type definition. Type, + /// A user. User, + /// A stream. Stream, } @@ -7532,9 +8266,13 @@ impl fmt::Display for ObjectType { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Types supported by `KILL` statements. pub enum KillType { + /// Kill a connection. Connection, + /// Kill a running query. Query, + /// Kill a mutation (ClickHouse). Mutation, } @@ -7553,39 +8291,62 @@ impl fmt::Display for KillType { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Distribution style options for Hive tables. pub enum HiveDistributionStyle { + /// Partitioned distribution with the given columns. PARTITIONED { + /// Columns used for partitioning. columns: Vec, }, + /// Skewed distribution definition. SKEWED { + /// Columns participating in the skew definition. columns: Vec, + /// Columns listed in the `ON` clause for skewing. on: Vec, + /// Whether skewed data is stored as directories. stored_as_directories: bool, }, + /// No distribution style specified. NONE, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Row format specification for Hive tables (SERDE or DELIMITED). pub enum HiveRowFormat { - SERDE { class: String }, - DELIMITED { delimiters: Vec }, + /// SerDe class specification with the implementing class name. + SERDE { + /// The SerDe implementation class name. + class: String, + }, + /// Delimited row format with one or more delimiter specifications. + DELIMITED { + /// The list of delimiters used for delimiting fields/lines. + delimiters: Vec, + }, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Format specification for `LOAD DATA` Hive operations. pub struct HiveLoadDataFormat { + /// SerDe expression used for the table. pub serde: Expr, + /// Input format expression. pub input_format: Expr, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A single row delimiter specification for Hive `ROW FORMAT`. pub struct HiveRowDelimiter { + /// The delimiter kind (fields/lines/etc.). pub delimiter: HiveDelimiter, + /// The delimiter character identifier. pub char: Ident, } @@ -7599,12 +8360,19 @@ impl fmt::Display for HiveRowDelimiter { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Kind of delimiter used in Hive `ROW FORMAT` definitions. pub enum HiveDelimiter { + /// Fields terminated by a delimiter. FieldsTerminatedBy, + /// Fields escaped by a character. FieldsEscapedBy, + /// Collection items terminated by a delimiter. CollectionItemsTerminatedBy, + /// Map keys terminated by a delimiter. MapKeysTerminatedBy, + /// Lines terminated by a delimiter. LinesTerminatedBy, + /// Null represented by a specific token. NullDefinedAs, } @@ -7625,8 +8393,11 @@ impl fmt::Display for HiveDelimiter { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Describe output format options for Hive `DESCRIBE`/`EXPLAIN`. pub enum HiveDescribeFormat { + /// Extended describe output. Extended, + /// Formatted describe output. Formatted, } @@ -7643,9 +8414,13 @@ impl fmt::Display for HiveDescribeFormat { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Aliases accepted for describe-style commands. pub enum DescribeAlias { + /// `DESCRIBE` alias. Describe, + /// `EXPLAIN` alias. Explain, + /// `DESC` alias. Desc, } @@ -7664,12 +8439,18 @@ impl fmt::Display for DescribeAlias { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[allow(clippy::large_enum_variant)] +/// Hive input/output format specification used in `CREATE TABLE`. pub enum HiveIOFormat { + /// Generic IO format with separate input and output expressions. IOF { + /// Expression for the input format. input_format: Expr, + /// Expression for the output format. output_format: Expr, }, + /// File format wrapper referencing a `FileFormat` variant. FileFormat { + /// The file format used for storage. format: FileFormat, }, } @@ -7677,18 +8458,26 @@ pub enum HiveIOFormat { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Hive table format and storage-related options. pub struct HiveFormat { + /// Optional row format specification. pub row_format: Option, + /// Optional SerDe properties expressed as SQL options. pub serde_properties: Option>, + /// Optional input/output storage format details. pub storage: Option, + /// Optional location (URI or path) for table data. pub location: Option, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A clustered index column specification. pub struct ClusteredIndex { + /// Column identifier for the clustered index entry. pub name: Ident, + /// Optional sort direction: `Some(true)` for ASC, `Some(false)` for DESC, `None` for unspecified. pub asc: Option, } @@ -7706,9 +8495,13 @@ impl fmt::Display for ClusteredIndex { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Clustered options used for `CREATE TABLE` clustered/indexed storage. pub enum TableOptionsClustered { + /// Use a columnstore index. ColumnstoreIndex, + /// Columnstore index with an explicit ordering of columns. ColumnstoreIndexOrder(Vec), + /// A named clustered index with one or more columns. Index(Vec), } @@ -7737,13 +8530,16 @@ impl fmt::Display for TableOptionsClustered { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum PartitionRangeDirection { + /// LEFT range direction. Left, + /// RIGHT range direction. Right, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// SQL option syntax used in table and server definitions. pub enum SqlOption { /// Clustered represents the clustered version of table storage for MSSQL. /// @@ -7756,7 +8552,12 @@ pub enum SqlOption { /// Any option that consists of a key value pair where the value is an expression. e.g. /// /// WITH(DISTRIBUTION = ROUND_ROBIN) - KeyValue { key: Ident, value: Expr }, + KeyValue { + /// The option key identifier. + key: Ident, + /// The expression value for the option. + value: Expr, + }, /// One or more table partitions and represents which partition the boundary values belong to, /// e.g. /// @@ -7764,8 +8565,11 @@ pub enum SqlOption { /// /// Partition { + /// The partition column name. column_name: Ident, + /// Optional direction for the partition range (LEFT/RIGHT). range_direction: Option, + /// Values that define the partition boundaries. for_values: Vec, }, /// Comment parameter (supports `=` and no `=` syntax) @@ -7844,8 +8648,11 @@ impl fmt::Display for SqlOption { #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Storage type options for a tablespace. pub enum StorageType { + /// Store on disk. Disk, + /// Store in memory. Memory, } @@ -7855,15 +8662,20 @@ pub enum StorageType { /// MySql TableSpace option /// pub struct TablespaceOption { + /// Name of the tablespace. pub name: String, + /// Optional storage type for the tablespace. pub storage: Option, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A key/value identifier pair used for secret or key-based options. pub struct SecretOption { + /// The option key identifier. pub key: Ident, + /// The option value identifier. pub value: Ident, } @@ -7880,11 +8692,17 @@ impl fmt::Display for SecretOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateServerStatement { + /// The server name. pub name: ObjectName, + /// Whether `IF NOT EXISTS` was specified. pub if_not_exists: bool, + /// Optional server type identifier. pub server_type: Option, + /// Optional server version identifier. pub version: Option, + /// Foreign-data wrapper object name. pub foreign_data_wrapper: ObjectName, + /// Optional list of server options. pub options: Option>, } @@ -7923,11 +8741,14 @@ impl fmt::Display for CreateServerStatement { } } +/// A key/value option for `CREATE SERVER`. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateServerOption { + /// Option key identifier. pub key: Ident, + /// Option value identifier. pub value: Ident, } @@ -7940,8 +8761,11 @@ impl fmt::Display for CreateServerOption { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Options supported by DuckDB for `ATTACH DATABASE`. pub enum AttachDuckDBDatabaseOption { + /// READ_ONLY option, optional boolean value. ReadOnly(Option), + /// TYPE option specifying a database type identifier. Type(Ident), } @@ -7959,8 +8783,11 @@ impl fmt::Display for AttachDuckDBDatabaseOption { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Mode for transactions: access mode or isolation level. pub enum TransactionMode { + /// Access mode for a transaction (e.g. `READ ONLY` / `READ WRITE`). AccessMode(TransactionAccessMode), + /// Isolation level for a transaction (e.g. `SERIALIZABLE`). IsolationLevel(TransactionIsolationLevel), } @@ -7977,8 +8804,11 @@ impl fmt::Display for TransactionMode { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Transaction access mode (READ ONLY / READ WRITE). pub enum TransactionAccessMode { + /// READ ONLY access mode. ReadOnly, + /// READ WRITE access mode. ReadWrite, } @@ -7995,11 +8825,17 @@ impl fmt::Display for TransactionAccessMode { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Transaction isolation levels. pub enum TransactionIsolationLevel { + /// READ UNCOMMITTED isolation level. ReadUncommitted, + /// READ COMMITTED isolation level. ReadCommitted, + /// REPEATABLE READ isolation level. RepeatableRead, + /// SERIALIZABLE isolation level. Serializable, + /// SNAPSHOT isolation level. Snapshot, } @@ -8024,10 +8860,15 @@ impl fmt::Display for TransactionIsolationLevel { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum TransactionModifier { + /// DEFERRED transaction modifier. Deferred, + /// IMMEDIATE transaction modifier. Immediate, + /// EXCLUSIVE transaction modifier. Exclusive, + /// TRY block modifier (MS-SQL style TRY/CATCH). Try, + /// CATCH block modifier (MS-SQL style TRY/CATCH). Catch, } @@ -8047,10 +8888,15 @@ impl fmt::Display for TransactionModifier { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Filter forms usable in SHOW statements. pub enum ShowStatementFilter { + /// Filter using LIKE pattern. Like(String), + /// Filter using ILIKE pattern. ILike(String), + /// Filter using a WHERE expression. Where(Expr), + /// Filter provided without a keyword (raw string). NoKeyword(String), } @@ -8069,8 +8915,11 @@ impl fmt::Display for ShowStatementFilter { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Clause types used with SHOW ... IN/FROM. pub enum ShowStatementInClause { + /// Use the `IN` clause. IN, + /// Use the `FROM` clause. FROM, } @@ -8092,10 +8941,15 @@ impl fmt::Display for ShowStatementInClause { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum SqliteOnConflict { + /// Use ROLLBACK on conflict. Rollback, + /// Use ABORT on conflict. Abort, + /// Use FAIL on conflict. Fail, + /// Use IGNORE on conflict. Ignore, + /// Use REPLACE on conflict. Replace, } @@ -8121,8 +8975,11 @@ impl fmt::Display for SqliteOnConflict { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum MysqlInsertPriority { + /// LOW_PRIORITY modifier for INSERT/REPLACE. LowPriority, + /// DELAYED modifier for INSERT/REPLACE. Delayed, + /// HIGH_PRIORITY modifier for INSERT/REPLACE. HighPriority, } @@ -8140,7 +8997,9 @@ impl fmt::Display for crate::ast::MysqlInsertPriority { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Source for the `COPY` command: a table or a query. pub enum CopySource { + /// Copy from a table with optional column list. Table { /// The name of the table to copy from. table_name: ObjectName, @@ -8148,19 +9007,25 @@ pub enum CopySource { /// are copied. columns: Vec, }, + /// Copy from the results of a query. Query(Box), } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Target for the `COPY` command: STDIN, STDOUT, a file, or a program. pub enum CopyTarget { + /// Use standard input as the source. Stdin, + /// Use standard output as the target. Stdout, + /// Read from or write to a file. File { /// The path name of the input or output file. filename: String, }, + /// Use a program as the source or target (shell command). Program { /// A command to execute command: String, @@ -8186,9 +9051,13 @@ impl fmt::Display for CopyTarget { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Action to take `ON COMMIT` for temporary tables. pub enum OnCommit { + /// Delete rows on commit. DeleteRows, + /// Preserve rows on commit. PreserveRows, + /// Drop the table on commit. Drop, } @@ -8271,7 +9140,12 @@ pub enum CopyLegacyOption { /// CLEANPATH CleanPath, /// COMPUPDATE [ PRESET | { ON | TRUE } | { OFF | FALSE } ] - CompUpdate { preset: bool, enabled: Option }, + CompUpdate { + /// Whether the COMPUPDATE PRESET option was used. + preset: bool, + /// Optional enabled flag for COMPUPDATE. + enabled: Option, + }, /// CSV ... Csv(Vec), /// DATEFORMAT \[ AS \] {'dateformat_string' | 'auto' } @@ -8280,8 +9154,11 @@ pub enum CopyLegacyOption { Delimiter(char), /// EMPTYASNULL EmptyAsNull, - /// ENCRYPTED \[ AUTO \] - Encrypted { auto: bool }, + /// `ENCRYPTED \[ AUTO \]` + Encrypted { + /// Whether `AUTO` was specified for encryption. + auto: bool, + }, /// ESCAPE Escape, /// EXTENSION 'extension-name' @@ -8298,13 +9175,16 @@ pub enum CopyLegacyOption { IgnoreHeader(u64), /// JSON Json, - /// MANIFEST \[ VERBOSE \] - Manifest { verbose: bool }, - /// MAXFILESIZE \[ AS \] max-size \[ MB | GB \] + /// `MANIFEST \[ VERBOSE \]` + Manifest { + /// Whether the MANIFEST is verbose. + verbose: bool, + }, + /// `MAXFILESIZE \[ AS \] max-size \[ MB | GB \]` MaxFileSize(FileSize), - /// NULL \[ AS \] 'null_string' + /// `NULL \[ AS \] 'null_string'` Null(String), - /// PARALLEL [ { ON | TRUE } | { OFF | FALSE } ] + /// `PARALLEL [ { ON | TRUE } | { OFF | FALSE } ]` Parallel(Option), /// PARQUET Parquet, @@ -8439,7 +9319,9 @@ impl fmt::Display for CopyLegacyOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct FileSize { + /// Numeric size value. pub size: Value, + /// Optional unit for the size (MB or GB). pub unit: Option, } @@ -8453,11 +9335,14 @@ impl fmt::Display for FileSize { } } +/// Units for `FileSize` (MB or GB). #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FileSizeUnit { + /// Megabytes. MB, + /// Gigabytes. GB, } @@ -8479,7 +9364,9 @@ impl fmt::Display for FileSizeUnit { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct UnloadPartitionBy { + /// Columns used to partition the unload output. pub columns: Vec, + /// Whether to include the partition in the output. pub include: bool, } @@ -8550,13 +9437,18 @@ impl fmt::Display for CopyLegacyCsvOption { } } +/// Objects that can be discarded with `DISCARD`. #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum DiscardObject { + /// Discard all session state. ALL, + /// Discard cached plans. PLANS, + /// Discard sequence values. SEQUENCES, + /// Discard temporary objects. TEMP, } @@ -8571,22 +9463,36 @@ impl fmt::Display for DiscardObject { } } +/// Types of flush operations supported by `FLUSH`. #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FlushType { + /// Flush binary logs. BinaryLogs, + /// Flush engine logs. EngineLogs, + /// Flush error logs. ErrorLogs, + /// Flush general logs. GeneralLogs, + /// Flush hosts information. Hosts, + /// Flush logs. Logs, + /// Flush privileges. Privileges, + /// Flush optimizer costs. OptimizerCosts, + /// Flush relay logs. RelayLogs, + /// Flush slow logs. SlowLogs, + /// Flush status. Status, + /// Flush user resources. UserResources, + /// Flush table data. Tables, } @@ -8610,11 +9516,14 @@ impl fmt::Display for FlushType { } } +/// Location modifier for flush commands. #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FlushLocation { + /// Do not write changes to the binary log. NoWriteToBinlog, + /// Apply flush locally. Local, } @@ -8660,7 +9569,9 @@ impl fmt::Display for ContextModifier { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum DropFunctionOption { + /// `RESTRICT` option for DROP FUNCTION. Restrict, + /// `CASCADE` option for DROP FUNCTION. Cascade, } @@ -8678,7 +9589,9 @@ impl fmt::Display for DropFunctionOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct FunctionDesc { + /// The function name. pub name: ObjectName, + /// Optional list of function arguments. pub args: Option>, } @@ -8697,9 +9610,13 @@ impl fmt::Display for FunctionDesc { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct OperateFunctionArg { + /// Optional argument mode (`IN`, `OUT`, `INOUT`). pub mode: Option, + /// Optional argument identifier/name. pub name: Option, + /// The data type of the argument. pub data_type: DataType, + /// Optional default expression for the argument. pub default_expr: Option, } @@ -8746,8 +9663,11 @@ impl fmt::Display for OperateFunctionArg { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ArgMode { + /// `IN` mode. In, + /// `OUT` mode. Out, + /// `INOUT` mode. InOut, } @@ -8766,8 +9686,11 @@ impl fmt::Display for ArgMode { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FunctionBehavior { + /// Function is immutable. Immutable, + /// Function is stable. Stable, + /// Function is volatile. Volatile, } @@ -8786,8 +9709,11 @@ impl fmt::Display for FunctionBehavior { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FunctionCalledOnNull { + /// Function is called even when inputs are null. CalledOnNullInput, + /// Function returns null when any input is null. ReturnsNullOnNullInput, + /// Function is strict about null inputs. Strict, } @@ -8806,8 +9732,11 @@ impl fmt::Display for FunctionCalledOnNull { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FunctionParallel { + /// The function is not safe to run in parallel. Unsafe, + /// The function is restricted for parallel execution. Restricted, + /// The function is safe to run in parallel. Safe, } @@ -8828,7 +9757,9 @@ impl fmt::Display for FunctionParallel { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FunctionDeterminismSpecifier { + /// Function is deterministic. Deterministic, + /// Function is not deterministic. NotDeterministic, } @@ -8948,9 +9879,13 @@ pub enum CreateFunctionBody { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `USING` clause options for `CREATE FUNCTION` (e.g., JAR, FILE, ARCHIVE). pub enum CreateFunctionUsing { + /// Use a JAR file located at the given URI. Jar(String), + /// Use a file located at the given URI. File(String), + /// Use an archive located at the given URI. Archive(String), } @@ -8973,7 +9908,9 @@ impl fmt::Display for CreateFunctionUsing { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct MacroArg { + /// The argument name. pub name: Ident, + /// Optional default expression for the argument. pub default_expr: Option, } @@ -9000,8 +9937,11 @@ impl fmt::Display for MacroArg { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Definition for a DuckDB macro: either an expression or a table-producing query. pub enum MacroDefinition { + /// The macro is defined as an expression. Expr(Expr), + /// The macro is defined as a table (query). Table(Box), } @@ -9084,12 +10024,16 @@ impl fmt::Display for SearchModifier { } } +/// Represents a `LOCK TABLE` clause with optional alias and lock type. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct LockTable { + /// The table identifier to lock. pub table: Ident, + /// Optional alias for the table. pub alias: Option, + /// The type of lock to apply to the table. pub lock_type: LockTableType, } @@ -9113,9 +10057,18 @@ impl fmt::Display for LockTable { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// The type of lock used in `LOCK TABLE` statements. pub enum LockTableType { - Read { local: bool }, - Write { low_priority: bool }, + /// Shared/read lock. If `local` is true, it's a local read lock. + Read { + /// Whether the read lock is local. + local: bool, + }, + /// Exclusive/write lock. If `low_priority` is true, the write is low priority. + Write { + /// Whether the write lock is low priority. + low_priority: bool, + }, } impl fmt::Display for LockTableType { @@ -9142,8 +10095,11 @@ impl fmt::Display for LockTableType { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Hive-specific `SET LOCATION` helper used in some `LOAD DATA` statements. pub struct HiveSetLocation { + /// Whether the `SET` keyword was present. pub has_set: bool, + /// The location identifier. pub location: Ident, } @@ -9161,8 +10117,11 @@ impl fmt::Display for HiveSetLocation { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// MySQL `ALTER TABLE` column position specifier: `FIRST` or `AFTER `. pub enum MySQLColumnPosition { + /// Place the column first in the table. First, + /// Place the column after the specified identifier. After(Ident), } @@ -9182,9 +10141,13 @@ impl Display for MySQLColumnPosition { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// MySQL `CREATE VIEW` algorithm options. pub enum CreateViewAlgorithm { + /// `UNDEFINED` algorithm. Undefined, + /// `MERGE` algorithm. Merge, + /// `TEMPTABLE` algorithm. TempTable, } @@ -9201,8 +10164,11 @@ impl Display for CreateViewAlgorithm { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// MySQL `CREATE VIEW` SQL SECURITY options. pub enum CreateViewSecurity { + /// The view runs with the privileges of the definer. Definer, + /// The view runs with the privileges of the invoker. Invoker, } @@ -9222,8 +10188,11 @@ impl Display for CreateViewSecurity { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateViewParams { + /// Optional view algorithm (e.g., MERGE, TEMPTABLE). pub algorithm: Option, + /// Optional definer (the security principal that will own the view). pub definer: Option, + /// Optional SQL SECURITY setting for the view. pub security: Option, } @@ -9258,8 +10227,11 @@ impl Display for CreateViewParams { /// ENGINE = SummingMergeTree([columns]) /// ``` pub struct NamedParenthesizedList { + /// The option key (identifier) for this named list. pub key: Ident, + /// Optional secondary name associated with the key. pub name: Option, + /// The list of identifier values for the key. pub values: Vec, } @@ -9271,11 +10243,14 @@ pub struct NamedParenthesizedList { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct RowAccessPolicy { + /// The fully-qualified policy object name. pub policy: ObjectName, + /// Identifiers for the columns or objects the policy applies to. pub on: Vec, } impl RowAccessPolicy { + /// Create a new `RowAccessPolicy` for the given `policy` and `on` identifiers. pub fn new(policy: ObjectName, on: Vec) -> Self { Self { policy, on } } @@ -9299,11 +10274,14 @@ impl Display for RowAccessPolicy { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Tag { + /// The tag key (can be qualified). pub key: ObjectName, + /// The tag value as a string. pub value: String, } impl Tag { + /// Create a new `Tag` with the given key and value. pub fn new(key: ObjectName, value: String) -> Self { Self { key, value } } @@ -9322,7 +10300,9 @@ impl Display for Tag { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ContactEntry { + /// The purpose label for the contact entry. pub purpose: String, + /// The contact information associated with the purpose. pub contact: String, } @@ -9340,6 +10320,7 @@ pub enum CommentDef { /// Includes `=` when printing the comment, as `COMMENT = 'comment'` /// Does not include `=` when printing the comment, as `COMMENT 'comment'` WithEq(String), + /// Comment variant that omits the `=` when displayed. WithoutEq(String), } @@ -9418,7 +10399,9 @@ where #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct UtilityOption { + /// The option name (identifier). pub name: Ident, + /// Optional argument for the option (number, string, keyword, etc.). pub arg: Option, } @@ -9439,10 +10422,15 @@ impl Display for UtilityOption { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ShowStatementOptions { + /// Optional scope to show in (for example: TABLE, SCHEMA). pub show_in: Option, + /// Optional `STARTS WITH` filter value. pub starts_with: Option, + /// Optional `LIMIT` expression. pub limit: Option, + /// Optional `FROM` value used with `LIMIT`. pub limit_from: Option, + /// Optional filter position (infix or suffix) for `LIKE`/`FILTER`. pub filter_position: Option, } @@ -9484,19 +10472,28 @@ impl Display for ShowStatementOptions { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Where a `SHOW` filter appears relative to the main clause. pub enum ShowStatementFilterPosition { + /// Put the filter in an infix position (e.g. `SHOW COLUMNS LIKE '%name%' IN TABLE tbl`). Infix(ShowStatementFilter), // For example: SHOW COLUMNS LIKE '%name%' IN TABLE tbl + /// Put the filter in a suffix position (e.g. `SHOW COLUMNS IN tbl LIKE '%name%'`). Suffix(ShowStatementFilter), // For example: SHOW COLUMNS IN tbl LIKE '%name%' } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Parent object types usable with `SHOW ... IN ` clauses. pub enum ShowStatementInParentType { + /// ACCOUNT parent type for SHOW statements. Account, + /// DATABASE parent type for SHOW statements. Database, + /// SCHEMA parent type for SHOW statements. Schema, + /// TABLE parent type for SHOW statements. Table, + /// VIEW parent type for SHOW statements. View, } @@ -9515,9 +10512,13 @@ impl fmt::Display for ShowStatementInParentType { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Represents a `SHOW ... IN` clause with optional parent qualifier and name. pub struct ShowStatementIn { + /// The clause that specifies what to show (e.g. COLUMNS, TABLES). pub clause: ShowStatementInClause, + /// Optional parent type qualifier (ACCOUNT/DATABASE/...). pub parent_type: Option, + /// Optional parent object name for the SHOW clause. #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] pub parent_name: Option, } @@ -9543,6 +10544,7 @@ pub struct ShowCharset { /// The statement can be written as `SHOW CHARSET` or `SHOW CHARACTER SET` /// true means CHARSET was used and false means CHARACTER SET was used pub is_shorthand: bool, + /// Optional `LIKE`/`WHERE`-style filter for the statement. pub filter: Option, } @@ -9564,8 +10566,11 @@ impl fmt::Display for ShowCharset { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Options for a `SHOW OBJECTS` statement. pub struct ShowObjects { + /// Whether to show terse output. pub terse: bool, + /// Additional options controlling the SHOW output. pub show_options: ShowStatementOptions, } @@ -9582,7 +10587,9 @@ pub struct ShowObjects { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum JsonNullClause { + /// `NULL ON NULL` behavior for JSON functions. NullOnNull, + /// `ABSENT ON NULL` behavior for JSON functions. AbsentOnNull, } @@ -9605,6 +10612,7 @@ impl Display for JsonNullClause { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct JsonReturningClause { + /// The data type to return from the JSON function (e.g. JSON/JSONB). pub data_type: DataType, } @@ -9619,7 +10627,9 @@ impl Display for JsonReturningClause { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct RenameTable { + /// The current name of the object to rename. pub old_name: ObjectName, + /// The new name for the object. pub new_name: ObjectName, } @@ -9665,7 +10675,9 @@ impl fmt::Display for TableObject { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct SetSessionAuthorizationParam { + /// The scope for the `SET SESSION AUTHORIZATION` (e.g., GLOBAL/SESSION). pub scope: ContextModifier, + /// The specific authorization parameter kind. pub kind: SetSessionAuthorizationParamKind, } @@ -9699,10 +10711,15 @@ impl fmt::Display for SetSessionAuthorizationParamKind { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Kind of session parameter being set by `SET SESSION`. pub enum SetSessionParamKind { + /// Generic session parameter (name/value pair). Generic(SetSessionParamGeneric), + /// Identity insert related parameter. IdentityInsert(SetSessionParamIdentityInsert), + /// Offsets-related parameter. Offsets(SetSessionParamOffsets), + /// Statistics-related parameter. Statistics(SetSessionParamStatistics), } @@ -9720,8 +10737,11 @@ impl fmt::Display for SetSessionParamKind { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Generic `SET SESSION` parameter represented as name(s) and value. pub struct SetSessionParamGeneric { + /// Names of the session parameters being set. pub names: Vec, + /// The value to assign to the parameter(s). pub value: String, } @@ -9734,8 +10754,11 @@ impl fmt::Display for SetSessionParamGeneric { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `IDENTITY_INSERT` session parameter for a specific object. pub struct SetSessionParamIdentityInsert { + /// Object name targeted by `IDENTITY_INSERT`. pub obj: ObjectName, + /// Value (ON/OFF) for the identity insert setting. pub value: SessionParamValue, } @@ -9748,8 +10771,11 @@ impl fmt::Display for SetSessionParamIdentityInsert { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Offsets-related session parameter with keywords and a value. pub struct SetSessionParamOffsets { + /// Keywords specifying which offsets to modify. pub keywords: Vec, + /// Value (ON/OFF) for the offsets setting. pub value: SessionParamValue, } @@ -9767,8 +10793,11 @@ impl fmt::Display for SetSessionParamOffsets { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Statistics-related session parameter specifying topic and value. pub struct SetSessionParamStatistics { + /// Statistics topic to set (IO/PROFILE/TIME/XML). pub topic: SessionParamStatsTopic, + /// Value (ON/OFF) for the statistics topic. pub value: SessionParamValue, } @@ -9781,10 +10810,15 @@ impl fmt::Display for SetSessionParamStatistics { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Topics available for session statistics configuration. pub enum SessionParamStatsTopic { + /// Input/output statistics. IO, + /// Profile statistics. Profile, + /// Time statistics. Time, + /// XML-related statistics. Xml, } @@ -9802,8 +10836,11 @@ impl fmt::Display for SessionParamStatsTopic { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Value for a session boolean-like parameter (ON/OFF). pub enum SessionParamValue { + /// Session parameter enabled. On, + /// Session parameter disabled. Off, } @@ -9826,7 +10863,9 @@ impl fmt::Display for SessionParamValue { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum StorageSerializationPolicy { + /// Use compatible serialization mode. Compatible, + /// Use optimized serialization mode. Optimized, } @@ -9849,7 +10888,9 @@ impl Display for StorageSerializationPolicy { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum CatalogSyncNamespaceMode { + /// Nest namespaces when syncing catalog. Nest, + /// Flatten namespaces when syncing catalog. Flatten, } @@ -9878,7 +10919,9 @@ pub enum CopyIntoSnowflakeKind { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `PRINT` statement for producing debug/output messages. pub struct PrintStatement { + /// The expression producing the message to print. pub message: Box, } @@ -9896,6 +10939,7 @@ impl fmt::Display for PrintStatement { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ReturnStatement { + /// Optional return value expression. pub value: Option, } @@ -9913,6 +10957,7 @@ impl fmt::Display for ReturnStatement { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ReturnStatementValue { + /// Return an expression from a function or trigger. Expr(Expr), } @@ -9938,7 +10983,9 @@ impl fmt::Display for OpenStatement { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum NullInclusion { + /// Include NULL values in the UNPIVOT output. IncludeNulls, + /// Exclude NULL values from the UNPIVOT output. ExcludeNulls, } @@ -9962,7 +11009,9 @@ impl fmt::Display for NullInclusion { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct MemberOf { + /// The value to check for membership. pub value: Box, + /// The JSON array expression to check against. pub array: Box, } @@ -9975,9 +11024,13 @@ impl fmt::Display for MemberOf { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Represents an `EXPORT DATA` statement. pub struct ExportData { + /// Options for the export operation. pub options: Vec, + /// The query producing the data to export. pub query: Box, + /// Optional named connection to use for export. pub connection: Option, } @@ -10012,11 +11065,17 @@ impl fmt::Display for ExportData { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct CreateUser { + /// Replace existing user if present. pub or_replace: bool, + /// Only create the user if it does not already exist. pub if_not_exists: bool, + /// The name of the user to create. pub name: Ident, + /// Key/value options for user creation. pub options: KeyValueOptions, + /// Whether tags are specified using `WITH TAG`. pub with_tags: bool, + /// Tags for the user. pub tags: KeyValueOptions, } @@ -10056,24 +11115,42 @@ impl fmt::Display for CreateUser { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterUser { + /// Whether to only alter the user if it exists. pub if_exists: bool, + /// The name of the user to alter. pub name: Ident, - /// The following fields are Snowflake-specific: + /// Optional new name for the user (Snowflake-specific). + /// See: pub rename_to: Option, + /// Reset the user's password. pub reset_password: bool, + /// Abort all running queries for the user. pub abort_all_queries: bool, + /// Optionally add a delegated role authorization. pub add_role_delegation: Option, + /// Optionally remove a delegated role authorization. pub remove_role_delegation: Option, + /// Enroll the user in MFA. pub enroll_mfa: bool, + /// Set the default MFA method for the user. pub set_default_mfa_method: Option, + /// Remove the user's default MFA method. pub remove_mfa_method: Option, + /// Modify an MFA method for the user. pub modify_mfa_method: Option, + /// Add an MFA OTP method with optional count. pub add_mfa_method_otp: Option, + /// Set a user policy. pub set_policy: Option, + /// Unset a user policy. pub unset_policy: Option, + /// Key/value tag options to set on the user. pub set_tag: KeyValueOptions, + /// Tags to unset on the user. pub unset_tag: Vec, + /// Key/value properties to set on the user. pub set_props: KeyValueOptions, + /// Properties to unset on the user. pub unset_props: Vec, } @@ -10084,7 +11161,9 @@ pub struct AlterUser { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterUserAddRoleDelegation { + /// Role name to delegate. pub role: Ident, + /// Security integration receiving the delegation. pub integration: Ident, } @@ -10095,7 +11174,9 @@ pub struct AlterUserAddRoleDelegation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterUserRemoveRoleDelegation { + /// Optional role name to remove delegation for. pub role: Option, + /// Security integration from which to remove delegation. pub integration: Ident, } @@ -10106,6 +11187,7 @@ pub struct AlterUserRemoveRoleDelegation { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterUserAddMfaMethodOtp { + /// Optional OTP count parameter. pub count: Option, } @@ -10116,7 +11198,9 @@ pub struct AlterUserAddMfaMethodOtp { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterUserModifyMfaMethod { + /// The MFA method being modified. pub method: MfaMethodKind, + /// The new comment for the MFA method. pub comment: String, } @@ -10125,8 +11209,11 @@ pub struct AlterUserModifyMfaMethod { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum MfaMethodKind { + /// PassKey (hardware or platform passkey) MFA method. PassKey, + /// Time-based One-Time Password (TOTP) MFA method. Totp, + /// Duo Security MFA method. Duo, } @@ -10147,7 +11234,9 @@ impl fmt::Display for MfaMethodKind { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct AlterUserSetPolicy { + /// The kind of user policy being set (authentication/password/session). pub policy_kind: UserPolicyKind, + /// The identifier of the policy to apply. pub policy: Ident, } @@ -10156,8 +11245,11 @@ pub struct AlterUserSetPolicy { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum UserPolicyKind { + /// Authentication policy. Authentication, + /// Password policy. Password, + /// Session policy. Session, } @@ -10279,8 +11371,11 @@ pub enum CreateTableLikeKind { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Controls whether defaults are included when creating a table FROM/LILE another. pub enum CreateTableLikeDefaults { + /// Include default values from the source table. Including, + /// Exclude default values from the source table. Excluding, } @@ -10296,8 +11391,11 @@ impl fmt::Display for CreateTableLikeDefaults { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Represents the `LIKE` clause of a `CREATE TABLE` statement. pub struct CreateTableLike { + /// The source table name to copy the schema from. pub name: ObjectName, + /// Optional behavior controlling whether defaults are copied. pub defaults: Option, } @@ -10318,8 +11416,11 @@ impl fmt::Display for CreateTableLike { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum RefreshModeKind { + /// Automatic refresh mode (`AUTO`). Auto, + /// Full refresh mode (`FULL`). Full, + /// Incremental refresh mode (`INCREMENTAL`). Incremental, } @@ -10340,7 +11441,9 @@ impl fmt::Display for RefreshModeKind { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum InitializeKind { + /// Initialize on creation (`ON CREATE`). OnCreate, + /// Initialize on schedule (`ON SCHEDULE`). OnSchedule, } @@ -10363,13 +11466,21 @@ impl fmt::Display for InitializeKind { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct VacuumStatement { + /// Whether `FULL` was specified. pub full: bool, + /// Whether `SORT ONLY` was specified. pub sort_only: bool, + /// Whether `DELETE ONLY` was specified. pub delete_only: bool, + /// Whether `REINDEX` was specified. pub reindex: bool, + /// Whether `RECLUSTER` was specified. pub recluster: bool, + /// Optional table to run `VACUUM` on. pub table_name: Option, + /// Optional threshold value (percent) for `TO threshold PERCENT`. pub threshold: Option, + /// Whether `BOOST` was specified. pub boost: bool, } @@ -10417,6 +11528,7 @@ pub enum Reset { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ResetStatement { + /// The reset action to perform (either `ALL` or a specific configuration parameter). pub reset: Reset, } diff --git a/src/ast/query.rs b/src/ast/query.rs index 16fc9ec0e..ab8779f57 100644 --- a/src/ast/query.rs +++ b/src/ast/query.rs @@ -120,8 +120,11 @@ impl fmt::Display for Query { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ProjectionSelect { + /// The list of projected select items. pub projection: Vec, + /// Optional `ORDER BY` clause for the projection-select. pub order_by: Option, + /// Optional `GROUP BY` clause for the projection-select. pub group_by: Option, } @@ -151,17 +154,28 @@ pub enum SetExpr { /// in its body and an optional ORDER BY / LIMIT. Query(Box), /// UNION/EXCEPT/INTERSECT of two queries + /// A set operation combining two query expressions. SetOperation { + /// The set operator used (e.g. `UNION`, `EXCEPT`). op: SetOperator, + /// Optional quantifier (`ALL`, `DISTINCT`, etc.). set_quantifier: SetQuantifier, + /// Left operand of the set operation. left: Box, + /// Right operand of the set operation. right: Box, }, + /// `VALUES (...)` Values(Values), + /// `INSERT` statement Insert(Statement), + /// `UPDATE` statement Update(Statement), + /// `DELETE` statement Delete(Statement), + /// `MERGE` statement Merge(Statement), + /// `TABLE` command Table(Box), } @@ -222,10 +236,15 @@ impl fmt::Display for SetExpr { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A set operator for combining two `SetExpr`s. pub enum SetOperator { + /// `UNION` set operator Union, + /// `EXCEPT` set operator Except, + /// `INTERSECT` set operator Intersect, + /// `MINUS` set operator (non-standard) Minus, } @@ -247,11 +266,17 @@ impl fmt::Display for SetOperator { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum SetQuantifier { + /// `ALL` quantifier All, + /// `DISTINCT` quantifier Distinct, + /// `BY NAME` quantifier ByName, + /// `ALL BY NAME` quantifier AllByName, + /// `DISTINCT BY NAME` quantifier DistinctByName, + /// No quantifier specified None, } @@ -272,8 +297,11 @@ impl fmt::Display for SetQuantifier { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] /// A [`TABLE` command]( https://www.postgresql.org/docs/current/sql-select.html#SQL-TABLE) #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A (possibly schema-qualified) table reference used in `FROM` clauses. pub struct Table { + /// Optional table name (absent for e.g. `TABLE` command without argument). pub table_name: Option, + /// Optional schema/catalog name qualifying the table. pub schema_name: Option, } @@ -588,6 +616,7 @@ impl fmt::Display for NamedWindowExpr { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A named window definition: ` AS ` pub struct NamedWindowDefinition(pub Ident, pub NamedWindowExpr); impl fmt::Display for NamedWindowDefinition { @@ -599,10 +628,13 @@ impl fmt::Display for NamedWindowDefinition { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A `WITH` clause, introducing common table expressions (CTEs). pub struct With { - /// Token for the "WITH" keyword + /// Token for the `WITH` keyword pub with_token: AttachedToken, + /// Whether the `WITH` is recursive (`WITH RECURSIVE`). pub recursive: bool, + /// The list of CTEs declared by this `WITH` clause. pub cte_tables: Vec, } @@ -620,6 +652,7 @@ impl fmt::Display for With { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Indicates whether a CTE is materialized or not. pub enum CteAsMaterialized { /// The `WITH` statement specifies `AS MATERIALIZED` behavior Materialized, @@ -649,11 +682,15 @@ impl fmt::Display for CteAsMaterialized { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Cte { + /// The CTE alias (name introduced before the `AS` keyword). pub alias: TableAlias, + /// The query that defines the CTE body. pub query: Box, + /// Optional `FROM` identifier for materialized CTEs. pub from: Option, + /// Optional `AS MATERIALIZED` / `AS NOT MATERIALIZED` hint. pub materialized: Option, - /// Token for the closing parenthesis + /// Token for the closing parenthesis of the CTE definition. pub closing_paren_token: AttachedToken, } @@ -708,7 +745,12 @@ pub enum SelectItem { /// Any expression, not followed by `[ AS ] alias` UnnamedExpr(Expr), /// An expression, followed by `[ AS ] alias` - ExprWithAlias { expr: Expr, alias: Ident }, + ExprWithAlias { + /// The expression being projected. + expr: Expr, + /// The alias for the expression. + alias: Ident, + }, /// An expression, followed by a wildcard expansion. /// e.g. `alias.*`, `STRUCT('foo').*` QualifiedWildcard(SelectItemQualifiedWildcardKind, WildcardAdditionalOptions), @@ -737,7 +779,9 @@ impl fmt::Display for SelectItemQualifiedWildcardKind { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct IdentWithAlias { + /// The identifier being aliased. pub ident: Ident, + /// The alias to apply to `ident`. pub alias: Ident, } @@ -815,6 +859,7 @@ impl fmt::Display for WildcardAdditionalOptions { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct IlikeSelectItem { + /// The pattern expression used with `ILIKE`. pub pattern: String, } @@ -954,6 +999,7 @@ impl fmt::Display for ExceptSelectItem { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ReplaceSelectItem { + /// List of replacement elements contained in the `REPLACE(...)` clause. pub items: Vec>, } @@ -973,8 +1019,11 @@ impl fmt::Display for ReplaceSelectItem { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ReplaceSelectElement { + /// Expression producing the replacement value. pub expr: Expr, + /// The target column name for the replacement. pub column_name: Ident, + /// Whether the `AS` keyword was present in the original syntax. pub as_keyword: bool, } @@ -1013,8 +1062,11 @@ impl fmt::Display for SelectItem { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A left table followed by zero or more joins. pub struct TableWithJoins { + /// The starting table factor (left side) of the join chain. pub relation: TableFactor, + /// The sequence of joins applied to the relation. pub joins: Vec, } @@ -1056,8 +1108,11 @@ impl fmt::Display for ConnectBy { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A single setting key-value pair. pub struct Setting { + /// Setting name/key. pub key: Ident, + /// The value expression assigned to the setting. pub value: Expr, } @@ -1077,7 +1132,9 @@ impl fmt::Display for Setting { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ExprWithAlias { + /// The expression. pub expr: Expr, + /// Optional alias for the expression. pub alias: Option, } @@ -1102,7 +1159,9 @@ impl fmt::Display for ExprWithAlias { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ExprWithAliasAndOrderBy { + /// Expression with optional alias. pub expr: ExprWithAlias, + /// Ordering options applied to the expression. pub order_by: OrderByOptions, } @@ -1117,8 +1176,9 @@ impl fmt::Display for ExprWithAliasAndOrderBy { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct TableFunctionArgs { + /// The list of arguments passed to the table-valued function. pub args: Vec, - /// ClickHouse-specific SETTINGS clause. + /// ClickHouse-specific `SETTINGS` clause. /// For example, /// `SELECT * FROM executable('generate_random.py', TabSeparated, 'id UInt32, random String', SETTINGS send_chunk_header = false, pool_size = 16)` /// [`executable` table function](https://clickhouse.com/docs/en/engines/table-functions/executable) @@ -1128,9 +1188,13 @@ pub struct TableFunctionArgs { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Type of index hint (e.g., `USE`, `IGNORE`, `FORCE`). pub enum TableIndexHintType { + /// `USE` hint. Use, + /// `IGNORE` hint. Ignore, + /// `FORCE` hint. Force, } @@ -1147,8 +1211,11 @@ impl fmt::Display for TableIndexHintType { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// The kind of index referenced by an index hint (e.g. `USE INDEX`). pub enum TableIndexType { + /// The `INDEX` kind. Index, + /// The `KEY` kind. Key, } @@ -1164,9 +1231,13 @@ impl fmt::Display for TableIndexType { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Which clause the table index hint applies to. pub enum TableIndexHintForClause { + /// Apply the hint to JOIN clauses. Join, + /// Apply the hint to `ORDER BY` clauses. OrderBy, + /// Apply the hint to `GROUP BY` clauses. GroupBy, } @@ -1183,10 +1254,15 @@ impl fmt::Display for TableIndexHintForClause { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// MySQL-style index hints attached to a table (e.g., `USE INDEX(...)`). pub struct TableIndexHints { + /// Type of hint (e.g., `USE`, `FORCE`, or `IGNORE`). pub hint_type: TableIndexHintType, + /// The index type (e.g., `INDEX`). pub index_type: TableIndexType, + /// Optional `FOR` clause specifying the scope (JOIN / ORDER BY / GROUP BY). pub for_clause: Option, + /// List of index names referred to by the hint. pub index_names: Vec, } @@ -1206,9 +1282,12 @@ impl fmt::Display for TableIndexHints { #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[cfg_attr(feature = "visitor", visit(with = "visit_table_factor"))] pub enum TableFactor { + /// A named table or relation, possibly with arguments, hints, or sampling. Table { #[cfg_attr(feature = "visitor", visit(with = "visit_relation"))] + /// Table or relation name. name: ObjectName, + /// Optional alias for the table (e.g. `table AS t`). alias: Option, /// Arguments of a table-valued function, as supported by Postgres /// and MSSQL. Note that deprecated MSSQL `FROM foo (NOLOCK)` syntax @@ -1238,21 +1317,31 @@ pub enum TableFactor { /// See: index_hints: Vec, }, + /// A derived table (a parenthesized subquery), optionally `LATERAL`. Derived { + /// Whether the derived table is LATERAL. lateral: bool, + /// The subquery producing the derived table. subquery: Box, + /// Optional alias for the derived table. alias: Option, }, /// `TABLE()[ AS ]` TableFunction { + /// Expression representing the table function call. expr: Expr, + /// Optional alias for the table function result. alias: Option, }, /// `e.g. LATERAL FLATTEN()[ AS ]` Function { + /// Whether the function is LATERAL. lateral: bool, + /// Name of the table function. name: ObjectName, + /// Arguments passed to the function. args: Vec, + /// Optional alias for the result of the function. alias: Option, }, /// ```sql @@ -1266,10 +1355,15 @@ pub enum TableFactor { /// +---------+--------+ /// ``` UNNEST { + /// Optional alias for the UNNEST table (e.g. `UNNEST(...) AS t`). alias: Option, + /// Expressions producing the arrays to be unnested. array_exprs: Vec, + /// Whether `WITH OFFSET` was specified to include element offsets. with_offset: bool, + /// Optional alias for the offset column when `WITH OFFSET` is used. with_offset_alias: Option, + /// Whether `WITH ORDINALITY` was specified to include ordinality. with_ordinality: bool, }, /// The `JSON_TABLE` table-valued function. @@ -1327,7 +1421,9 @@ pub enum TableFactor { /// The parser may also accept non-standard nesting of bare tables for some /// dialects, but the information about such nesting is stripped from AST. NestedJoin { + /// The nested join expression contained in parentheses. table_with_joins: Box, + /// Optional alias for the nested join. alias: Option, }, /// Represents PIVOT operation on a table. @@ -1336,11 +1432,17 @@ pub enum TableFactor { /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/query-syntax#pivot_operator) /// [Snowflake](https://docs.snowflake.com/en/sql-reference/constructs/pivot) Pivot { + /// The input table to pivot. table: Box, + /// Aggregate expressions used as pivot values (optionally aliased). aggregate_functions: Vec, // Function expression + /// Columns producing the values to be pivoted. value_column: Vec, + /// Source of pivot values (e.g. list of literals or columns). value_source: PivotValueSource, + /// Optional expression providing a default when a pivot produces NULL. default_on_null: Option, + /// Optional alias for the pivoted table. alias: Option, }, /// An UNPIVOT operation on a table. @@ -1353,17 +1455,24 @@ pub enum TableFactor { /// See . /// See . Unpivot { + /// The input table to unpivot. table: Box, + /// Expression producing the unpivoted value. value: Expr, + /// Identifier used for the generated column name. name: Ident, + /// Columns or expressions to unpivot, optionally aliased. columns: Vec, + /// Whether to include or exclude NULLs during unpivot. null_inclusion: Option, + /// Optional alias for the resulting table. alias: Option, }, /// A `MATCH_RECOGNIZE` operation on a table. /// /// See . MatchRecognize { + /// The input table to apply `MATCH_RECOGNIZE` on. table: Box, /// `PARTITION BY [, ... ]` partition_by: Vec, @@ -1379,6 +1488,7 @@ pub enum TableFactor { pattern: MatchRecognizePattern, /// `DEFINE AS [, ... ]` symbols: Vec, + /// The alias for the table. alias: Option, }, /// The `XMLTABLE` table-valued function. @@ -1453,20 +1563,30 @@ pub enum TableSampleKind { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Represents a `TABLESAMPLE` clause and its options. pub struct TableSample { + /// Modifier (e.g. `SAMPLE` or `TABLESAMPLE`). pub modifier: TableSampleModifier, + /// Optional sampling method name (e.g. `BERNOULLI`, `SYSTEM`). pub name: Option, + /// Optional sampling quantity (value and optional unit). pub quantity: Option, + /// Optional seed clause. pub seed: Option, + /// Optional bucket specification for `BUCKET ... OUT OF ...`-style sampling. pub bucket: Option, + /// Optional offset expression for sampling. pub offset: Option, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Modifier specifying whether `SAMPLE` or `TABLESAMPLE` keyword was used. pub enum TableSampleModifier { + /// `SAMPLE` modifier. Sample, + /// `TABLESAMPLE` modifier. TableSample, } @@ -1483,9 +1603,13 @@ impl fmt::Display for TableSampleModifier { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Quantity for a `TABLESAMPLE` clause (e.g. `10 PERCENT` or `(10)`). pub struct TableSampleQuantity { + /// Whether the quantity was wrapped in parentheses. pub parenthesized: bool, + /// The numeric expression specifying the quantity. pub value: Expr, + /// Optional unit (e.g. `PERCENT`, `ROWS`). pub unit: Option, } @@ -1509,10 +1633,15 @@ impl fmt::Display for TableSampleQuantity { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Sampling method used by `TABLESAMPLE`. pub enum TableSampleMethod { + /// `ROW` sampling method. Row, + /// `BERNOULLI` sampling method. Bernoulli, + /// `SYSTEM` sampling method. System, + /// `BLOCK` sampling method. Block, } @@ -1530,8 +1659,11 @@ impl fmt::Display for TableSampleMethod { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `SEED` or `REPEATABLE` clause used with sampling. pub struct TableSampleSeed { + /// Seed modifier (e.g. `REPEATABLE` or `SEED`). pub modifier: TableSampleSeedModifier, + /// The seed value expression. pub value: Value, } @@ -1545,8 +1677,11 @@ impl fmt::Display for TableSampleSeed { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Modifier specifying how the sample seed is applied. pub enum TableSampleSeedModifier { + /// `REPEATABLE` modifier. Repeatable, + /// `SEED` modifier. Seed, } @@ -1562,8 +1697,11 @@ impl fmt::Display for TableSampleSeedModifier { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Unit used with a `TABLESAMPLE` quantity (rows or percent). pub enum TableSampleUnit { + /// `ROWS` unit. Rows, + /// `PERCENT` unit. Percent, } @@ -1579,9 +1717,13 @@ impl fmt::Display for TableSampleUnit { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Bucket-based sampling clause: `BUCKET OUT OF [ON ]`. pub struct TableSampleBucket { + /// The bucket index expression. pub bucket: Value, + /// The total number of buckets expression. pub total: Value, + /// Optional `ON ` specification. pub on: Option, } @@ -1657,8 +1799,11 @@ impl fmt::Display for PivotValueSource { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// An item in the `MEASURES` clause of `MATCH_RECOGNIZE`. pub struct Measure { + /// Expression producing the measure value. pub expr: Expr, + /// Alias for the measure column. pub alias: Ident, } @@ -1728,6 +1873,7 @@ impl fmt::Display for AfterMatchSkip { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// The mode for handling empty matches in a `MATCH_RECOGNIZE` operation. pub enum EmptyMatchesMode { /// `SHOW EMPTY MATCHES` Show, @@ -1753,8 +1899,11 @@ impl fmt::Display for EmptyMatchesMode { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A symbol defined in a `MATCH_RECOGNIZE` operation. pub struct SymbolDefinition { + /// The symbol identifier. pub symbol: Ident, + /// The expression defining the symbol. pub definition: Expr, } @@ -2180,12 +2329,15 @@ impl fmt::Display for TableFactor { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// An alias for a table reference, optionally including an explicit `AS` and column names. pub struct TableAlias { /// Tells whether the alias was introduced with an explicit, preceding "AS" /// keyword, e.g. `AS name`. Typically, the keyword is preceding the name /// (e.g. `.. FROM table AS t ..`). pub explicit: bool, + /// Alias identifier for the table. pub name: Ident, + /// Optional column aliases declared in parentheses after the table alias. pub columns: Vec, } @@ -2237,6 +2389,7 @@ impl fmt::Display for TableAliasColumnDef { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Specifies a table version selection, e.g. `FOR SYSTEM_TIME AS OF` or `AT(...)`. pub enum TableVersion { /// When the table version is defined using `FOR SYSTEM_TIME AS OF`. /// For example: `SELECT * FROM tbl FOR SYSTEM_TIME AS OF TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)` @@ -2259,11 +2412,14 @@ impl Display for TableVersion { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A single `JOIN` clause including relation and join operator/options. pub struct Join { + /// The joined table factor (table reference or derived table). pub relation: TableFactor, /// ClickHouse supports the optional `GLOBAL` keyword before the join operator. /// See [ClickHouse](https://clickhouse.com/docs/en/sql-reference/statements/select/join) pub global: bool, + /// The join operator and its constraint (INNER/LEFT/RIGHT/CROSS/ASOF/etc.). pub join_operator: JoinOperator, } @@ -2400,41 +2556,50 @@ impl fmt::Display for Join { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// The operator used for joining two tables, e.g. `INNER`, `LEFT`, `CROSS`, `ASOF`, etc. pub enum JoinOperator { + /// Generic `JOIN` with an optional constraint. Join(JoinConstraint), + /// `INNER JOIN` with an optional constraint. Inner(JoinConstraint), + /// `LEFT JOIN` with an optional constraint. Left(JoinConstraint), + /// `LEFT OUTER JOIN` with an optional constraint. LeftOuter(JoinConstraint), + /// `RIGHT JOIN` with an optional constraint. Right(JoinConstraint), + /// `RIGHT OUTER JOIN` with an optional constraint. RightOuter(JoinConstraint), + /// `FULL OUTER JOIN` with an optional constraint. FullOuter(JoinConstraint), - /// CROSS (constraint is non-standard) + /// `CROSS JOIN` (constraint usage is non-standard). CrossJoin(JoinConstraint), - /// SEMI (non-standard) + /// `SEMI JOIN` (non-standard) Semi(JoinConstraint), - /// LEFT SEMI (non-standard) + /// `LEFT SEMI JOIN` (non-standard) LeftSemi(JoinConstraint), - /// RIGHT SEMI (non-standard) + /// `RIGHT SEMI JOIN` (non-standard) RightSemi(JoinConstraint), - /// ANTI (non-standard) + /// `ANTI JOIN` (non-standard) Anti(JoinConstraint), - /// LEFT ANTI (non-standard) + /// `LEFT ANTI JOIN` (non-standard) LeftAnti(JoinConstraint), - /// RIGHT ANTI (non-standard) + /// `RIGHT ANTI JOIN` (non-standard) RightAnti(JoinConstraint), - /// CROSS APPLY (non-standard) + /// `CROSS APPLY` (non-standard) CrossApply, - /// OUTER APPLY (non-standard) + /// `OUTER APPLY` (non-standard) OuterApply, - /// `ASOF` joins are used for joining tables containing time-series data - /// whose timestamp columns do not match exactly. + /// `ASOF` joins are used for joining time-series tables whose timestamp columns do not match exactly. /// /// See . AsOf { + /// Condition used to match records in the `ASOF` join. match_condition: Expr, + /// Additional constraint applied to the `ASOF` join. constraint: JoinConstraint, }, - /// STRAIGHT_JOIN (non-standard) + /// `STRAIGHT_JOIN` (MySQL non-standard behavior) /// /// See . StraightJoin(JoinConstraint), @@ -2443,35 +2608,42 @@ pub enum JoinOperator { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Represents how two tables are constrained in a join: `ON`, `USING`, `NATURAL`, or none. pub enum JoinConstraint { + /// `ON ` join condition. On(Expr), + /// `USING(...)` list of column names. Using(Vec), + /// `NATURAL` join (columns matched automatically). Natural, + /// No constraint specified (e.g. `CROSS JOIN`). None, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// The kind of `ORDER BY` clause: either `ALL` with modifiers or a list of expressions. pub enum OrderByKind { - /// ALL syntax of [DuckDB] and [ClickHouse]. + /// `GROUP BY ALL`/`ORDER BY ALL` syntax with optional modifiers. /// /// [DuckDB]: /// [ClickHouse]: All(OrderByOptions), - /// Expressions + /// A standard list of ordering expressions. Expressions(Vec), } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Represents an `ORDER BY` clause with its kind and optional `INTERPOLATE`. pub struct OrderBy { + /// The kind of ordering (expressions or `ALL`). pub kind: OrderByKind, - /// Optional: `INTERPOLATE` - /// Supported by [ClickHouse syntax] + /// Optional `INTERPOLATE` clause (ClickHouse extension). pub interpolate: Option, } @@ -2503,10 +2675,11 @@ impl fmt::Display for OrderBy { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct OrderByExpr { + /// The expression to order by. pub expr: Expr, + /// Ordering options such as `ASC`/`DESC` and `NULLS` behavior. pub options: OrderByOptions, - /// Optional: `WITH FILL` - /// Supported by [ClickHouse syntax]: + /// Optional `WITH FILL` clause (ClickHouse extension) which specifies how to fill gaps. pub with_fill: Option, } @@ -2537,9 +2710,13 @@ impl fmt::Display for OrderByExpr { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `WITH FILL` options for ClickHouse `ORDER BY` expressions. pub struct WithFill { + /// Optional lower bound expression for the fill range (`FROM `). pub from: Option, + /// Optional upper bound expression for the fill range (`TO `). pub to: Option, + /// Optional step expression specifying interpolation step (`STEP `). pub step: Option, } @@ -2566,15 +2743,20 @@ impl fmt::Display for WithFill { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// An expression used by `WITH FILL`/`INTERPOLATE` to specify interpolation for a column. pub struct InterpolateExpr { + /// The column to interpolate. pub column: Ident, + /// Optional `AS ` expression specifying how to compute interpolated values. pub expr: Option, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `INTERPOLATE` clause used with ClickHouse `WITH FILL` to compute missing values. pub struct Interpolate { + /// Optional list of interpolation expressions. pub exprs: Option>, } @@ -2591,10 +2773,11 @@ impl fmt::Display for InterpolateExpr { #[derive(Default, Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Options for an `ORDER BY` expression (ASC/DESC and NULLS FIRST/LAST). pub struct OrderByOptions { - /// Optional `ASC` or `DESC` + /// Optional `ASC` (`Some(true)`) or `DESC` (`Some(false)`). pub asc: Option, - /// Optional `NULLS FIRST` or `NULLS LAST` + /// Optional `NULLS FIRST` (`Some(true)`) or `NULLS LAST` (`Some(false)`). pub nulls_first: Option, } @@ -2617,26 +2800,26 @@ impl fmt::Display for OrderByOptions { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Represents the different syntactic forms of `LIMIT` clauses. pub enum LimitClause { - /// Standard SQL syntax + /// Standard SQL `LIMIT` syntax (optionally `BY` and `OFFSET`). /// /// `LIMIT [BY ,,...] [OFFSET ]` LimitOffset { - /// `LIMIT { | ALL }` + /// `LIMIT { | ALL }` expression. limit: Option, - /// `OFFSET [ { ROW | ROWS } ]` + /// Optional `OFFSET` expression with optional `ROW(S)` keyword. offset: Option, - /// `BY { ,,... } }` - /// - /// [ClickHouse](https://clickhouse.com/docs/sql-reference/statements/select/limit-by) + /// Optional `BY { ,... }` list used by some dialects (ClickHouse). limit_by: Vec, }, - /// [MySQL]-specific syntax; the order of expressions is reversed. - /// - /// `LIMIT , ` - /// - /// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/select.html - OffsetCommaLimit { offset: Expr, limit: Expr }, + /// MySQL-specific syntax: `LIMIT , ` (order reversed). + OffsetCommaLimit { + /// The offset expression. + offset: Expr, + /// The limit expression. + limit: Expr, + }, } impl fmt::Display for LimitClause { @@ -2669,8 +2852,11 @@ impl fmt::Display for LimitClause { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `OFFSET` clause consisting of a value and a rows specifier. pub struct Offset { + /// The numeric expression following `OFFSET`. pub value: Expr, + /// Whether the offset uses `ROW`/`ROWS` or omits it. pub rows: OffsetRows, } @@ -2685,9 +2871,11 @@ impl fmt::Display for Offset { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum OffsetRows { - /// Omitting ROW/ROWS is non-standard MySQL quirk. + /// Omitting `ROW`/`ROWS` entirely (non-standard MySQL quirk). None, + /// `ROW` keyword present. Row, + /// `ROWS` keyword present. Rows, } @@ -2721,45 +2909,71 @@ pub enum PipeOperator { /// Syntax: `|> LIMIT [OFFSET ]` /// /// See more at - Limit { expr: Expr, offset: Option }, + Limit { + /// The expression specifying the number of rows to return. + expr: Expr, + /// Optional offset expression provided inline with `LIMIT`. + offset: Option, + }, /// Filters the results of the input table. /// /// Syntax: `|> WHERE ` /// /// See more at - Where { expr: Expr }, + Where { + /// The filter expression. + expr: Expr, + }, /// `ORDER BY [ASC|DESC], ...` - OrderBy { exprs: Vec }, + OrderBy { + /// The ordering expressions. + exprs: Vec, + }, /// Produces a new table with the listed columns, similar to the outermost SELECT clause in a table subquery in standard syntax. /// /// Syntax `|> SELECT [[AS] alias], ...` /// /// See more at - Select { exprs: Vec }, + Select { + /// The select items to produce. + exprs: Vec, + }, /// Propagates the existing table and adds computed columns, similar to SELECT *, new_column in standard syntax. /// /// Syntax: `|> EXTEND [[AS] alias], ...` /// /// See more at - Extend { exprs: Vec }, + Extend { + /// Expressions defining added columns. + exprs: Vec, + }, /// Replaces the value of a column in the current table, similar to SELECT * REPLACE (expression AS column) in standard syntax. /// /// Syntax: `|> SET = , ...` /// /// See more at - Set { assignments: Vec }, + Set { + /// Assignments to apply (`column = expr`). + assignments: Vec, + }, /// Removes listed columns from the current table, similar to SELECT * EXCEPT (column) in standard syntax. /// /// Syntax: `|> DROP , ...` /// /// See more at - Drop { columns: Vec }, + Drop { + /// Columns to drop. + columns: Vec, + }, /// Introduces a table alias for the input table, similar to applying the AS alias clause on a table subquery in standard syntax. /// /// Syntax: `|> AS ` /// /// See more at - As { alias: Ident }, + As { + /// Alias to assign to the input table. + alias: Ident, + }, /// Performs aggregation on data across grouped rows or an entire table. /// /// Syntax: `|> AGGREGATE [[AS] alias], ...` @@ -2772,26 +2986,36 @@ pub enum PipeOperator { /// /// See more at Aggregate { + /// Expressions computed for each row prior to grouping. full_table_exprs: Vec, + /// Grouping expressions for aggregation. group_by_expr: Vec, }, /// Selects a random sample of rows from the input table. /// Syntax: `|> TABLESAMPLE SYSTEM (10 PERCENT) /// See more at - TableSample { sample: Box }, + TableSample { + /// Sampling clause describing the sample. + sample: Box, + }, /// Renames columns in the input table. /// /// Syntax: `|> RENAME old_name AS new_name, ...` /// /// See more at - Rename { mappings: Vec }, + Rename { + /// Mappings of old to new identifiers. + mappings: Vec, + }, /// Combines the input table with one or more tables using UNION. /// /// Syntax: `|> UNION [ALL|DISTINCT] (), (), ...` /// /// See more at Union { + /// Set quantifier (`ALL` or `DISTINCT`). set_quantifier: SetQuantifier, + /// The queries to combine with `UNION`. queries: Vec, }, /// Returns only the rows that are present in both the input table and the specified tables. @@ -2800,7 +3024,9 @@ pub enum PipeOperator { /// /// See more at Intersect { + /// Set quantifier for the `INTERSECT` operator. set_quantifier: SetQuantifier, + /// The queries to intersect. queries: Vec, }, /// Returns only the rows that are present in the input table but not in the specified tables. @@ -2809,7 +3035,9 @@ pub enum PipeOperator { /// /// See more at Except { + /// Set quantifier for the `EXCEPT` operator. set_quantifier: SetQuantifier, + /// The queries to exclude from the input set. queries: Vec, }, /// Calls a table function or procedure that returns a table. @@ -2818,7 +3046,9 @@ pub enum PipeOperator { /// /// See more at Call { + /// The function or procedure to call which returns a table. function: Function, + /// Optional alias for the result table. alias: Option, }, /// Pivots data from rows to columns. @@ -2827,9 +3057,13 @@ pub enum PipeOperator { /// /// See more at Pivot { + /// Aggregate functions to compute during pivot. aggregate_functions: Vec, + /// Column(s) that provide the pivot values. value_column: Vec, + /// The source of pivot values (literal list or subquery). value_source: PivotValueSource, + /// Optional alias for the output. alias: Option, }, /// The `UNPIVOT` pipe operator transforms columns into rows. @@ -2841,9 +3075,13 @@ pub enum PipeOperator { /// /// See more at Unpivot { + /// Output column that will receive the unpivoted value. value_column: Ident, + /// Column name holding the unpivoted column name. name_column: Ident, + /// Columns to unpivot. unpivot_columns: Vec, + /// Optional alias for the unpivot result. alias: Option, }, /// Joins the input table with another table. @@ -2994,9 +3232,13 @@ impl PipeOperator { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `FETCH` clause options. pub struct Fetch { + /// `WITH TIES` option is present. pub with_ties: bool, + /// `PERCENT` modifier is present. pub percent: bool, + /// Optional quantity expression (e.g. `FETCH FIRST 10 ROWS`). pub quantity: Option, } @@ -3015,9 +3257,13 @@ impl fmt::Display for Fetch { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `FOR ...` locking clause. pub struct LockClause { + /// The kind of lock requested (e.g. `SHARE`, `UPDATE`). pub lock_type: LockType, + /// Optional object name after `OF` (e.g. `FOR UPDATE OF t1`). pub of: Option, + /// Optional non-blocking behavior (`NOWAIT` / `SKIP LOCKED`). pub nonblock: Option, } @@ -3037,8 +3283,11 @@ impl fmt::Display for LockClause { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// The lock type used in `FOR ` clauses (e.g. `FOR SHARE`, `FOR UPDATE`). pub enum LockType { + /// `SHARE` lock (shared lock). Share, + /// `UPDATE` lock (exclusive/update lock). Update, } @@ -3055,8 +3304,11 @@ impl fmt::Display for LockType { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Non-blocking lock options for `FOR ...` clauses. pub enum NonBlock { + /// `NOWAIT` — do not wait for the lock. Nowait, + /// `SKIP LOCKED` — skip rows that are locked. SkipLocked, } @@ -3073,11 +3325,12 @@ impl fmt::Display for NonBlock { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `DISTINCT` or `DISTINCT ON (...)` modifiers for `SELECT` lists. pub enum Distinct { - /// DISTINCT + /// `DISTINCT` (remove duplicate rows) Distinct, - /// DISTINCT ON({column names}) + /// `DISTINCT ON (...)` (Postgres extension) On(Vec), } @@ -3096,22 +3349,25 @@ impl fmt::Display for Distinct { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// MSSQL `TOP` clause options. pub struct Top { /// SQL semantic equivalent of LIMIT but with same structure as FETCH. /// MSSQL only. pub with_ties: bool, - /// MSSQL only. + /// Apply `PERCENT` extension. pub percent: bool, + /// The optional quantity (expression or constant) following `TOP`. pub quantity: Option, } #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Quantity used in a `TOP` clause: either an expression or a constant. pub enum TopQuantity { - // A parenthesized expression. MSSQL only. + /// A parenthesized expression (MSSQL syntax: `TOP (expr)`). Expr(Expr), - // An unparenthesized integer constant. + /// An unparenthesized integer constant: `TOP 10`. Constant(u64), } @@ -3135,13 +3391,15 @@ impl fmt::Display for Top { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// An explicit `VALUES` clause and its rows. pub struct Values { - /// Was there an explicit ROWs keyword (MySQL)? + /// Was there an explicit `ROW` keyword (MySQL)? /// pub explicit_row: bool, - // MySql supports both VALUES and VALUE keywords. - // + /// `true` if `VALUE` (singular) keyword was used instead of `VALUES`. + /// pub value_keyword: bool, + /// The list of rows, each row is a list of expressions. pub rows: Vec>, } @@ -3166,10 +3424,15 @@ impl fmt::Display for Values { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// `SELECT INTO` clause options. pub struct SelectInto { + /// `TEMPORARY` modifier. pub temporary: bool, + /// `UNLOGGED` modifier. pub unlogged: bool, + /// `TABLE` keyword present. pub table: bool, + /// Name of the target table. pub name: ObjectName, } @@ -3190,12 +3453,15 @@ impl fmt::Display for SelectInto { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Modifiers used with `GROUP BY` such as `WITH ROLLUP` or `WITH CUBE`. pub enum GroupByWithModifier { + /// `WITH ROLLUP` modifier. Rollup, + /// `WITH CUBE` modifier. Cube, + /// `WITH TOTALS` modifier (ClickHouse). Totals, - /// Hive supports GROUP BY GROUPING SETS syntax. - /// e.g. GROUP BY year , month GROUPING SETS((year,month),(year),(month)) + /// Hive supports GROUPING SETS syntax, e.g. `GROUP BY GROUPING SETS(...)`. /// /// [Hive]: GroupingSets(Expr), @@ -3217,6 +3483,8 @@ impl fmt::Display for GroupByWithModifier { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Represents the two syntactic forms that `GROUP BY` can take, including +/// `GROUP BY ALL` with optional modifiers and ordinary `GROUP BY `. pub enum GroupByExpr { /// ALL syntax of [Snowflake], [DuckDB] and [ClickHouse]. /// @@ -3228,8 +3496,7 @@ pub enum GroupByExpr { /// /// [ClickHouse]: All(Vec), - - /// Expressions + /// `GROUP BY ` with optional modifiers. Expressions(Vec, Vec), } @@ -3256,14 +3523,16 @@ impl fmt::Display for GroupByExpr { } } -/// FORMAT identifier or FORMAT NULL clause, specific to ClickHouse. +/// `FORMAT` identifier or `FORMAT NULL` clause, specific to ClickHouse. /// /// [ClickHouse]: #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum FormatClause { + /// The format identifier. Identifier(Ident), + /// `FORMAT NULL` clause. Null, } @@ -3283,7 +3552,9 @@ impl fmt::Display for FormatClause { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct InputFormatClause { + /// The format identifier. pub ident: Ident, + /// Optional format parameters. pub values: Vec, } @@ -3299,24 +3570,35 @@ impl fmt::Display for InputFormatClause { } } -/// FOR XML or FOR JSON clause, specific to MSSQL -/// (formats the output of a query as XML or JSON) +/// `FOR XML` or `FOR JSON` clause (MSSQL): formats the output of a query as XML or JSON. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum ForClause { + /// `FOR BROWSE` clause. Browse, + /// `FOR JSON ...` clause and its options. Json { + /// JSON mode (`AUTO` or `PATH`). for_json: ForJson, + /// Optional `ROOT('...')` parameter. root: Option, + /// `INCLUDE_NULL_VALUES` flag. include_null_values: bool, + /// `WITHOUT_ARRAY_WRAPPER` flag. without_array_wrapper: bool, }, + /// `FOR XML ...` clause and its options. Xml { + /// XML mode (`RAW`, `AUTO`, `EXPLICIT`, `PATH`). for_xml: ForXml, + /// `ELEMENTS` flag. elements: bool, + /// `BINARY BASE64` flag. binary_base64: bool, + /// Optional `ROOT('...')` parameter. root: Option, + /// `TYPE` flag. r#type: bool, }, } @@ -3374,10 +3656,15 @@ impl fmt::Display for ForClause { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Modes for `FOR XML` clause. pub enum ForXml { + /// `RAW` mode with optional root name: `RAW('root')`. Raw(Option), + /// `AUTO` mode. Auto, + /// `EXPLICIT` mode. Explicit, + /// `PATH` mode with optional root: `PATH('root')`. Path(Option), } @@ -3407,8 +3694,11 @@ impl fmt::Display for ForXml { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +/// Modes for `FOR JSON` clause. pub enum ForJson { + /// `AUTO` mode. Auto, + /// `PATH` mode. Path, } @@ -3473,8 +3763,11 @@ impl fmt::Display for JsonTableColumn { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +/// A nested column in a `JSON_TABLE` column list. pub struct JsonTableNestedColumn { + /// JSON path expression (must be a literal `Value`). pub path: Value, + /// Columns extracted from the matched nested array. pub columns: Vec, } @@ -3539,9 +3832,13 @@ impl fmt::Display for JsonTableNamedColumn { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +/// Error/empty-value handling for `JSON_TABLE` columns. pub enum JsonTableColumnErrorHandling { + /// `NULL` — return NULL when the path does not match. Null, + /// `DEFAULT ` — use the provided `Value` as a default. Default(Value), + /// `ERROR` — raise an error. Error, } @@ -3600,10 +3897,15 @@ impl fmt::Display for OpenJsonTableColumn { #[derive(Debug, Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Mode of BigQuery value tables, e.g. `AS STRUCT` or `AS VALUE`. pub enum ValueTableMode { + /// `AS STRUCT` AsStruct, + /// `AS VALUE` AsValue, + /// `DISTINCT AS STRUCT` DistinctAsStruct, + /// `DISTINCT AS VALUE` DistinctAsValue, } @@ -3706,10 +4008,14 @@ impl fmt::Display for XmlTableColumn { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +/// Argument passed in the `XMLTABLE PASSING` clause. pub struct XmlPassingArgument { + /// Expression to pass to the XML table. pub expr: Expr, + /// Optional alias for the argument. pub alias: Option, - pub by_value: bool, // True if BY VALUE is specified + /// `true` if `BY VALUE` is specified for the argument. + pub by_value: bool, } impl fmt::Display for XmlPassingArgument { @@ -3729,7 +4035,9 @@ impl fmt::Display for XmlPassingArgument { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +/// The PASSING clause for `XMLTABLE`. pub struct XmlPassingClause { + /// The list of passed arguments. pub arguments: Vec, } diff --git a/src/ast/spans.rs b/src/ast/spans.rs index d4e843157..34abcb695 100644 --- a/src/ast/spans.rs +++ b/src/ast/spans.rs @@ -404,6 +404,7 @@ impl Spanned for Statement { Statement::AlterType { .. } => Span::empty(), Statement::AlterOperator { .. } => Span::empty(), Statement::AlterOperatorFamily { .. } => Span::empty(), + Statement::AlterOperatorClass { .. } => Span::empty(), Statement::AlterRole { .. } => Span::empty(), Statement::AlterSession { .. } => Span::empty(), Statement::AttachDatabase { .. } => Span::empty(), diff --git a/src/ast/table_constraints.rs b/src/ast/table_constraints.rs index ddf0c1253..cb3c2376d 100644 --- a/src/ast/table_constraints.rs +++ b/src/ast/table_constraints.rs @@ -155,10 +155,13 @@ impl fmt::Display for TableConstraint { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A `CHECK` constraint (`[ CONSTRAINT ] CHECK () [[NOT] ENFORCED]`). pub struct CheckConstraint { + /// Optional constraint name. pub name: Option, + /// The boolean expression the CHECK constraint enforces. pub expr: Box, - /// MySQL-specific syntax + /// MySQL-specific `ENFORCED` / `NOT ENFORCED` flag. /// pub enforced: Option, } @@ -197,16 +200,24 @@ impl crate::ast::Spanned for CheckConstraint { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ForeignKeyConstraint { + /// Optional constraint name. pub name: Option, - /// MySQL-specific field + /// MySQL-specific index name associated with the foreign key. /// pub index_name: Option, + /// Columns in the local table that participate in the foreign key. pub columns: Vec, + /// Referenced foreign table name. pub foreign_table: ObjectName, + /// Columns in the referenced table. pub referred_columns: Vec, + /// Action to perform `ON DELETE`. pub on_delete: Option, + /// Action to perform `ON UPDATE`. pub on_update: Option, + /// Optional `MATCH` kind (FULL | PARTIAL | SIMPLE). pub match_kind: Option, + /// Optional characteristics (e.g., `DEFERRABLE`). pub characteristics: Option, } @@ -344,6 +355,7 @@ pub struct IndexConstraint { /// Referred column identifier list. pub columns: Vec, /// Optional index options such as `USING`; see [`IndexOption`]. + /// Options applied to the index (e.g., `COMMENT`, `WITH` options). pub index_options: Vec, } @@ -413,7 +425,9 @@ pub struct PrimaryKeyConstraint { pub index_type: Option, /// Identifiers of the columns that form the primary key. pub columns: Vec, + /// Optional index options such as `USING`. pub index_options: Vec, + /// Optional characteristics like `DEFERRABLE`. pub characteristics: Option, } @@ -458,6 +472,7 @@ impl crate::ast::Spanned for PrimaryKeyConstraint { #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// Unique constraint definition. pub struct UniqueConstraint { /// Constraint name. /// @@ -473,7 +488,9 @@ pub struct UniqueConstraint { pub index_type: Option, /// Identifiers of the columns that are unique. pub columns: Vec, + /// Optional index options such as `USING`. pub index_options: Vec, + /// Optional characteristics like `DEFERRABLE`. pub characteristics: Option, /// Optional Postgres nulls handling: `[ NULLS [ NOT ] DISTINCT ]` pub nulls_distinct: NullsDistinctOption, diff --git a/src/ast/trigger.rs b/src/ast/trigger.rs index 2c64e4239..8c189a337 100644 --- a/src/ast/trigger.rs +++ b/src/ast/trigger.rs @@ -23,7 +23,9 @@ use super::*; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum TriggerObject { + /// The trigger fires once for each row affected by the triggering event Row, + /// The trigger fires once for the triggering SQL statement Statement, } @@ -36,12 +38,14 @@ impl fmt::Display for TriggerObject { } } -/// This clause indicates whether the following relation name is for the before-image transition relation or the after-image transition relation #[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// This clause indicates whether the following relation name is for the before-image transition relation or the after-image transition relation pub enum TriggerReferencingType { + /// The transition relation containing the old rows affected by the triggering statement OldTable, + /// The transition relation containing the new rows affected by the triggering statement NewTable, } @@ -59,8 +63,11 @@ impl fmt::Display for TriggerReferencingType { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct TriggerReferencing { + /// The referencing type (`OLD TABLE` or `NEW TABLE`). pub refer_type: TriggerReferencingType, + /// True if the `AS` keyword is present in the referencing clause. pub is_as: bool, + /// The transition relation name provided by the referencing clause. pub transition_relation_name: ObjectName, } @@ -81,9 +88,13 @@ impl fmt::Display for TriggerReferencing { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum TriggerEvent { + /// Trigger on INSERT event Insert, + /// Trigger on UPDATE event, with optional list of columns Update(Vec), + /// Trigger on DELETE event Delete, + /// Trigger on TRUNCATE event Truncate, } @@ -110,9 +121,13 @@ impl fmt::Display for TriggerEvent { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum TriggerPeriod { + /// The trigger fires once for each row affected by the triggering event For, + /// The trigger fires once for the triggering SQL statement After, + /// The trigger fires before the triggering event Before, + /// The trigger fires instead of the triggering event InsteadOf, } @@ -132,7 +147,9 @@ impl fmt::Display for TriggerPeriod { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum TriggerExecBodyType { + /// Execute a function Function, + /// Execute a procedure Procedure, } @@ -149,7 +166,9 @@ impl fmt::Display for TriggerExecBodyType { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct TriggerExecBody { + /// Whether the body is a `FUNCTION` or `PROCEDURE` invocation. pub exec_type: TriggerExecBodyType, + /// Description of the function/procedure to execute. pub func_desc: FunctionDesc, } diff --git a/src/ast/value.rs b/src/ast/value.rs index ccbb12a33..dc46a5bbb 100644 --- a/src/ast/value.rs +++ b/src/ast/value.rs @@ -64,11 +64,14 @@ use sqlparser_derive::{Visit, VisitMut}; /// // convert back to `Value` /// let value: Value = value_with_span.into(); /// ``` +/// A `Value` paired with its source `Span` location. #[derive(Debug, Clone, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct ValueWithSpan { + /// The wrapped `Value`. pub value: Value, + /// The source `Span` covering the token(s) that produced the value. pub span: Span, } @@ -121,13 +124,14 @@ pub enum Value { #[cfg(not(feature = "bigdecimal"))] Number(String, bool), #[cfg(feature = "bigdecimal")] - // HINT: use `test_utils::number` to make an instance of - // Value::Number This might help if you your tests pass locally - // but fail on CI with the `--all-features` flag enabled + /// HINT: use `test_utils::number` to make an instance of + /// Value::Number This might help if you your tests pass locally + /// but fail on CI with the `--all-features` flag enabled + /// Numeric literal (uses `BigDecimal` when the `bigdecimal` feature is enabled). Number(BigDecimal, bool), /// 'string value' SingleQuotedString(String), - // $$string value$$ (postgres syntax) + /// Dollar-quoted string literal, e.g. `$$...$$` or `$tag$...$tag$` (Postgres syntax). DollarQuotedString(DollarQuotedString), /// Triple single quoted strings: Example '''abc''' /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/lexical#quoted_literals) @@ -176,6 +180,7 @@ pub enum Value { /// X'hex value' HexStringLiteral(String), + /// Double quoted string literal, e.g. `"abc"`. DoubleQuotedString(String), /// Boolean value true or false Boolean(bool), @@ -219,10 +224,12 @@ impl Value { } } + /// Attach the provided `span` to this `Value` and return `ValueWithSpan`. pub fn with_span(self, span: Span) -> ValueWithSpan { ValueWithSpan { value: self, span } } + /// Convenience for attaching an empty span to this `Value`. pub fn with_empty_span(self) -> ValueWithSpan { self.with_span(Span::empty()) } @@ -268,11 +275,14 @@ impl fmt::Display for Value { } } +/// A dollar-quoted string literal, e.g. `$$...$$` or `$tag$...$tag$`. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct DollarQuotedString { + /// Inner string contents. pub value: String, + /// Optional tag used in the opening/closing delimiter. pub tag: Option, } @@ -311,59 +321,102 @@ impl fmt::Display for QuoteDelimitedString { } } +/// Represents the date/time fields used by functions like `EXTRACT`. +/// +/// Each variant corresponds to a supported date/time part (for example +/// `YEAR`, `MONTH`, `DAY`, etc.). The `Custom` variant allows arbitrary +/// identifiers (e.g. dialect-specific abbreviations). #[derive(Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum DateTimeField { + /// `YEAR` Year, + /// `YEARS` (plural form) Years, + /// `MONTH` Month, + /// `MONTHS` (plural form) Months, - /// Week optionally followed by a WEEKDAY. - /// - /// ```sql - /// WEEK(MONDAY) - /// ``` + /// `WEEK`, optionally followed by a weekday, e.g. `WEEK(MONDAY)`. /// /// [BigQuery](https://cloud.google.com/bigquery/docs/reference/standard-sql/date_functions#extract) Week(Option), + /// `WEEKS` (plural form) Weeks, + /// `DAY` Day, + /// `DAYOFWEEK` DayOfWeek, + /// `DAYOFYEAR` DayOfYear, + /// `DAYS` (plural form) Days, + /// `DATE` Date, + /// `DATETIME` Datetime, + /// `HOUR` Hour, + /// `HOURS` (plural form) Hours, + /// `MINUTE` Minute, + /// `MINUTES` (plural form) Minutes, + /// `SECOND` Second, + /// `SECONDS` (plural form) Seconds, + /// `CENTURY` Century, + /// `DECADE` Decade, + /// `DOW` (day of week short form) Dow, + /// `DOY` (day of year short form) Doy, + /// `EPOCH` Epoch, + /// `ISODOW` Isodow, - IsoWeek, + /// `ISOYEAR` Isoyear, + /// `ISOWEEK` + IsoWeek, + /// `JULIAN` Julian, + /// `MICROSECOND` Microsecond, + /// `MICROSECONDS` (plural form) Microseconds, + /// `MILLENIUM` (alternate spelling) Millenium, + /// `MILLENNIUM` (alternate spelling) Millennium, + /// `MILLISECOND` Millisecond, + /// `MILLISECONDS` (plural form) Milliseconds, + /// `NANOSECOND` Nanosecond, + /// `NANOSECONDS` (plural form) Nanoseconds, + /// `QUARTER` Quarter, + /// `TIME` Time, + /// `TIMEZONE` Timezone, + /// `TIMEZONE_ABBR` TimezoneAbbr, + /// `TIMEZONE_HOUR` TimezoneHour, + /// `TIMEZONE_MINUTE` TimezoneMinute, + /// `TIMEZONE_REGION` TimezoneRegion, + /// `NODATETIME` indicates no date/time part NoDateTime, /// Arbitrary abbreviation or custom date-time part. /// @@ -523,14 +576,18 @@ impl fmt::Display for EscapeQuotedString<'_> { } } +/// Return a helper which formats `string` for inclusion inside a quoted +/// literal that uses `quote` as the delimiter. pub fn escape_quoted_string(string: &str, quote: char) -> EscapeQuotedString<'_> { EscapeQuotedString { string, quote } } +/// Convenience wrapper for escaping strings for single-quoted literals (`'`). pub fn escape_single_quote_string(s: &str) -> EscapeQuotedString<'_> { escape_quoted_string(s, '\'') } +/// Convenience wrapper for escaping strings for double-quoted literals (`").` pub fn escape_double_quote_string(s: &str) -> EscapeQuotedString<'_> { escape_quoted_string(s, '\"') } @@ -565,6 +622,8 @@ impl fmt::Display for EscapeEscapedStringLiteral<'_> { } } +/// Return a helper which escapes characters for string literals that use +/// PostgreSQL-style escaped string literals (e.g. `E'...')`. pub fn escape_escaped_string(s: &str) -> EscapeEscapedStringLiteral<'_> { EscapeEscapedStringLiteral(s) } @@ -600,16 +659,24 @@ impl fmt::Display for EscapeUnicodeStringLiteral<'_> { } } +/// Return a helper which escapes non-ASCII characters using `\XXXX` or +/// `\+XXXXXX` Unicode escape formats (used for `U&'...'` style literals). pub fn escape_unicode_string(s: &str) -> EscapeUnicodeStringLiteral<'_> { EscapeUnicodeStringLiteral(s) } +/// The side on which `TRIM` should be applied. +/// +/// Corresponds to `TRIM(BOTH|LEADING|TRAILING)` SQL syntax. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum TrimWhereField { + /// `BOTH` (trim from both ends) Both, + /// `LEADING` (trim from start) Leading, + /// `TRAILING` (trim from end) Trailing, } diff --git a/src/ast/visitor.rs b/src/ast/visitor.rs index 328f925f7..5d841655b 100644 --- a/src/ast/visitor.rs +++ b/src/ast/visitor.rs @@ -32,6 +32,10 @@ use core::ops::ControlFlow; /// #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] /// ``` pub trait Visit { + /// Visit this node with the provided [`Visitor`]. + /// + /// Implementations should call the appropriate visitor hooks to traverse + /// child nodes and return a `ControlFlow` value to allow early exit. fn visit(&self, visitor: &mut V) -> ControlFlow; } @@ -47,6 +51,11 @@ pub trait Visit { /// #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] /// ``` pub trait VisitMut { + /// Mutably visit this node with the provided [`VisitorMut`]. + /// + /// Implementations should call the appropriate mutable visitor hooks to + /// traverse and allow in-place mutation of child nodes. Returning a + /// `ControlFlow` value permits early termination of the traversal. fn visit(&mut self, visitor: &mut V) -> ControlFlow; } diff --git a/src/dialect/clickhouse.rs b/src/dialect/clickhouse.rs index bdac1f57b..39e8a0b30 100644 --- a/src/dialect/clickhouse.rs +++ b/src/dialect/clickhouse.rs @@ -17,7 +17,7 @@ use crate::dialect::Dialect; -// A [`Dialect`] for [ClickHouse](https://clickhouse.com/). +/// A [`Dialect`] for [ClickHouse](https://clickhouse.com/). #[derive(Debug)] pub struct ClickHouseDialect {} diff --git a/src/dialect/mod.rs b/src/dialect/mod.rs index 1a416e4df..97882acca 100644 --- a/src/dialect/mod.rs +++ b/src/dialect/mod.rs @@ -881,10 +881,14 @@ pub trait Dialect: Debug + Any { false } + /// Returns true if the dialect supports `EXPLAIN` statements with utility options + /// e.g. `EXPLAIN (ANALYZE TRUE, BUFFERS TRUE) SELECT * FROM tbl;` fn supports_explain_with_utility_options(&self) -> bool { false } + /// Returns true if the dialect supports `ASC` and `DESC` in column definitions + /// e.g. `CREATE TABLE t (a INT ASC, b INT DESC);` fn supports_asc_desc_in_column_definition(&self) -> bool { false } @@ -1113,6 +1117,13 @@ pub trait Dialect: Debug + Any { false } + /// Returns true if the dialect supports space-separated column options + /// in a `CREATE TABLE` statement. For example: + /// ```sql + /// CREATE TABLE tbl ( + /// col INT NOT NULL DEFAULT 0 + /// ); + /// ``` fn supports_space_separated_column_options(&self) -> bool { false } @@ -1218,31 +1229,50 @@ pub trait Dialect: Debug + Any { } } -/// This represents the operators for which precedence must be defined +/// Operators for which precedence must be defined. /// -/// higher number -> higher precedence +/// Higher number -> higher precedence. +/// See expression parsing for how these values are used. #[derive(Debug, Clone, Copy)] pub enum Precedence { + /// Member access operator `.` (highest precedence). Period, + /// Postgres style type cast `::`. DoubleColon, + /// Timezone operator (e.g. `AT TIME ZONE`). AtTz, + /// Multiplication / Division / Modulo operators (`*`, `/`, `%`). MulDivModOp, + /// Addition / Subtraction (`+`, `-`). PlusMinus, + /// Bitwise `XOR` operator (`^`). Xor, + /// Bitwise `AND` operator (`&`). Ampersand, + /// Bitwise `CARET` (^) for some dialects. Caret, + /// Bitwise `OR` / pipe operator (`|`). Pipe, + /// `BETWEEN` operator. Between, + /// Equality operator (`=`). Eq, + /// Pattern matching (`LIKE`). Like, + /// `IS` operator (e.g. `IS NULL`). Is, + /// Other Postgres-specific operators. PgOther, + /// Unary `NOT`. UnaryNot, + /// Logical `AND`. And, + /// Logical `OR` (lowest precedence). Or, } impl dyn Dialect { + /// Returns true if `self` is the concrete dialect `T`. #[inline] pub fn is(&self) -> bool { // borrowed from `Any` implementation diff --git a/src/keywords.rs b/src/keywords.rs index f06842ec6..0aec6facf 100644 --- a/src/keywords.rs +++ b/src/keywords.rs @@ -37,6 +37,7 @@ use sqlparser_derive::{Visit, VisitMut}; /// expands to `pub const SELECT = "SELECT";` macro_rules! kw_def { ($ident:ident = $string_keyword:expr) => { + #[doc = concat!("The `", $string_keyword, "` SQL keyword.")] pub const $ident: &'static str = $string_keyword; }; ($ident:ident) => { @@ -54,16 +55,23 @@ macro_rules! define_keywords { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] #[allow(non_camel_case_types)] + /// An enumeration of SQL keywords recognized by the parser. pub enum Keyword { + /// Represents no keyword. NoKeyword, - $($ident),* + $( + #[doc = concat!("The `", stringify!($ident), "` SQL keyword.")] + $ident + ),* } + /// Array of all `Keyword` enum values in declaration order. pub const ALL_KEYWORDS_INDEX: &[Keyword] = &[ $(Keyword::$ident),* ]; $(kw_def!($ident $(= $string_keyword)?);)* + /// Array of all SQL keywords as string constants. pub const ALL_KEYWORDS: &[&str] = &[ $($ident),* ]; @@ -1247,9 +1255,9 @@ pub const RESERVED_FOR_COLUMN_ALIAS: &[Keyword] = &[ Keyword::END, ]; -// Global list of reserved keywords allowed after FROM. -// Parser should call Dialect::get_reserved_keyword_after_from -// to allow for each dialect to customize the list. +/// Global list of reserved keywords allowed after FROM. +/// Parser should call Dialect::get_reserved_keyword_after_from +/// to allow for each dialect to customize the list. pub const RESERVED_FOR_TABLE_FACTOR: &[Keyword] = &[ Keyword::INTO, Keyword::LIMIT, diff --git a/src/lib.rs b/src/lib.rs index 4050173ca..f5d23a21f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -154,6 +154,7 @@ // would bloat the API and hide intent. Extra memory is a worthwhile tradeoff. #![allow(clippy::large_enum_variant)] #![forbid(clippy::unreachable)] +#![forbid(missing_docs)] // Allow proc-macros to find this crate extern crate self as sqlparser; @@ -167,6 +168,7 @@ extern crate pretty_assertions; pub mod ast; #[macro_use] +/// Submodules for SQL dialects. pub mod dialect; mod display_utils; pub mod keywords; diff --git a/src/parser/alter.rs b/src/parser/alter.rs index b3e3c99e6..cc708d597 100644 --- a/src/parser/alter.rs +++ b/src/parser/alter.rs @@ -30,6 +30,7 @@ use crate::{ }; impl Parser<'_> { + /// Parse `ALTER ROLE` statement pub fn parse_alter_role(&mut self) -> Result { if dialect_of!(self is PostgreSqlDialect) { return self.parse_pg_alter_role(); diff --git a/src/parser/merge.rs b/src/parser/merge.rs index 2bc1544f0..81798c456 100644 --- a/src/parser/merge.rs +++ b/src/parser/merge.rs @@ -39,6 +39,7 @@ impl Parser<'_> { Ok(Box::new(SetExpr::Merge(self.parse_merge(merge_token)?))) } + /// Parse a `MERGE` statement pub fn parse_merge(&mut self, merge_token: TokenWithSpan) -> Result { let into = self.parse_keyword(Keyword::INTO); diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 74b06ec8d..2e8538e5c 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -48,10 +48,14 @@ use crate::keywords::{Keyword, ALL_KEYWORDS}; use crate::tokenizer::*; use sqlparser::parser::ParserState::ColumnDefinition; +/// Errors produced by the SQL parser. #[derive(Debug, Clone, PartialEq, Eq)] pub enum ParserError { + /// Error originating from the tokenizer with a message. TokenizerError(String), + /// Generic parser error with a message. ParserError(String), + /// Raised when a recursion depth limit is exceeded. RecursionLimitExceeded, } @@ -154,19 +158,29 @@ mod recursion { } #[derive(PartialEq, Eq)] +/// Indicates whether a parser element is optional or mandatory. pub enum IsOptional { + /// The element is optional. Optional, + /// The element is mandatory. Mandatory, } +/// Indicates if a table expression is lateral. pub enum IsLateral { + /// The expression is lateral. Lateral, + /// The expression is not lateral. NotLateral, } +/// Represents a wildcard expression used in SELECT lists. pub enum WildcardExpr { + /// A specific expression used instead of a wildcard. Expr(Expr), + /// A qualified wildcard like `table.*`. QualifiedWildcard(ObjectName), + /// An unqualified `*` wildcard. Wildcard, } @@ -228,6 +242,7 @@ impl From for MatchedTrailingBracket { /// Options that control how the [`Parser`] parses SQL text #[derive(Debug, Clone, PartialEq, Eq)] pub struct ParserOptions { + /// Allow trailing commas in lists (e.g. `a, b,`). pub trailing_commas: bool, /// Controls how literal values are unescaped. See /// [`Tokenizer::with_unescape`] for more details. @@ -872,7 +887,9 @@ impl<'a> Parser<'a> { Ok(Statement::Raise(RaiseStatement { value })) } - + /// Parse a COMMENT statement. + /// + /// See [Statement::Comment] pub fn parse_comment(&mut self) -> Result { let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); @@ -918,6 +935,7 @@ impl<'a> Parser<'a> { }) } + /// Parse `FLUSH` statement. pub fn parse_flush(&mut self) -> Result { let mut channel = None; let mut tables: Vec = vec![]; @@ -1005,6 +1023,7 @@ impl<'a> Parser<'a> { }) } + /// Parse `MSCK` statement. pub fn parse_msck(&mut self) -> Result { let repair = self.parse_keyword(Keyword::REPAIR); self.expect_keyword_is(Keyword::TABLE)?; @@ -1033,6 +1052,7 @@ impl<'a> Parser<'a> { .into()) } + /// Parse `TRUNCATE` statement. pub fn parse_truncate(&mut self) -> Result { let table = self.parse_keyword(Keyword::TABLE); @@ -1089,6 +1109,7 @@ impl<'a> Parser<'a> { } } + /// Parse options for `ATTACH DUCKDB DATABASE` statement. pub fn parse_attach_duckdb_database_options( &mut self, ) -> Result, ParserError> { @@ -1124,6 +1145,7 @@ impl<'a> Parser<'a> { } } + /// Parse `ATTACH DUCKDB DATABASE` statement. pub fn parse_attach_duckdb_database(&mut self) -> Result { let database = self.parse_keyword(Keyword::DATABASE); let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); @@ -1144,6 +1166,7 @@ impl<'a> Parser<'a> { }) } + /// Parse `DETACH DUCKDB DATABASE` statement. pub fn parse_detach_duckdb_database(&mut self) -> Result { let database = self.parse_keyword(Keyword::DATABASE); let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); @@ -1155,6 +1178,7 @@ impl<'a> Parser<'a> { }) } + /// Parse `ATTACH DATABASE` statement. pub fn parse_attach_database(&mut self) -> Result { let database = self.parse_keyword(Keyword::DATABASE); let database_file_name = self.parse_expr()?; @@ -1167,6 +1191,7 @@ impl<'a> Parser<'a> { }) } + /// Parse `ANALYZE` statement. pub fn parse_analyze(&mut self) -> Result { let has_table_keyword = self.parse_keyword(Keyword::TABLE); let table_name = self.parse_object_name(false)?; @@ -1280,6 +1305,7 @@ impl<'a> Parser<'a> { self.parse_subexpr(self.dialect.prec_unknown()) } + /// Parse expression with optional alias and order by. pub fn parse_expr_with_alias_and_order_by( &mut self, ) -> Result { @@ -1327,6 +1353,7 @@ impl<'a> Parser<'a> { Ok(expr) } + /// Parse `ASSERT` statement. pub fn parse_assert(&mut self) -> Result { let condition = self.parse_expr()?; let message = if self.parse_keyword(Keyword::AS) { @@ -1338,11 +1365,13 @@ impl<'a> Parser<'a> { Ok(Statement::Assert { condition, message }) } + /// Parse `SAVEPOINT` statement. pub fn parse_savepoint(&mut self) -> Result { let name = self.parse_identifier()?; Ok(Statement::Savepoint { name }) } + /// Parse `RELEASE` statement. pub fn parse_release(&mut self) -> Result { let _ = self.parse_keyword(Keyword::SAVEPOINT); let name = self.parse_identifier()?; @@ -1350,11 +1379,13 @@ impl<'a> Parser<'a> { Ok(Statement::ReleaseSavepoint { name }) } + /// Parse `LISTEN` statement. pub fn parse_listen(&mut self) -> Result { let channel = self.parse_identifier()?; Ok(Statement::LISTEN { channel }) } + /// Parse `UNLISTEN` statement. pub fn parse_unlisten(&mut self) -> Result { let channel = if self.consume_token(&Token::Mul) { Ident::new(Expr::Wildcard(AttachedToken::empty()).to_string()) @@ -1370,6 +1401,7 @@ impl<'a> Parser<'a> { Ok(Statement::UNLISTEN { channel }) } + /// Parse `NOTIFY` statement. pub fn parse_notify(&mut self) -> Result { let channel = self.parse_identifier()?; let payload = if self.consume_token(&Token::Comma) { @@ -2056,6 +2088,7 @@ impl<'a> Parser<'a> { && self.consume_tokens(&[Token::LParen, Token::Plus, Token::RParen]) } + /// Parse utility options in the form of `(option1, option2 arg2, option3 arg3, ...)` pub fn parse_utility_options(&mut self) -> Result, ParserError> { self.expect_token(&Token::LParen)?; let options = self.parse_comma_separated(Self::parse_utility_option)?; @@ -2165,6 +2198,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a function call expression named by `name` and return it as an `Expr`. pub fn parse_function(&mut self, name: ObjectName) -> Result { self.parse_function_call(name).map(Expr::Function) } @@ -2273,6 +2307,7 @@ impl<'a> Parser<'a> { } } + /// Parse time-related function `name` possibly followed by `(...)` arguments. pub fn parse_time_functions(&mut self, name: ObjectName) -> Result { let args = if self.consume_token(&Token::LParen) { FunctionArguments::List(self.parse_function_argument_list()?) @@ -2291,6 +2326,7 @@ impl<'a> Parser<'a> { })) } + /// Parse window frame `UNITS` clause: `ROWS`, `RANGE`, or `GROUPS`. pub fn parse_window_frame_units(&mut self) -> Result { let next_token = self.next_token(); match &next_token.token { @@ -2304,6 +2340,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `WINDOW` frame definition (units and bounds). pub fn parse_window_frame(&mut self) -> Result { let units = self.parse_window_frame_units()?; let (start_bound, end_bound) = if self.parse_keyword(Keyword::BETWEEN) { @@ -2321,7 +2358,7 @@ impl<'a> Parser<'a> { }) } - /// Parse `CURRENT ROW` or `{ | UNBOUNDED } { PRECEDING | FOLLOWING }` + /// Parse a window frame bound: `CURRENT ROW` or ` PRECEDING|FOLLOWING`. pub fn parse_window_frame_bound(&mut self) -> Result { if self.parse_keywords(&[Keyword::CURRENT, Keyword::ROW]) { Ok(WindowFrameBound::CurrentRow) @@ -2410,6 +2447,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `CASE` expression and return an [`Expr::Case`]. pub fn parse_case_expr(&mut self) -> Result { let case_token = AttachedToken(self.get_current_token().clone()); let mut operand = None; @@ -2442,6 +2480,7 @@ impl<'a> Parser<'a> { }) } + /// Parse an optional `FORMAT` clause for `CAST` expressions. pub fn parse_optional_cast_format(&mut self) -> Result, ParserError> { if self.parse_keyword(Keyword::FORMAT) { let value = self.parse_value()?.value; @@ -2454,6 +2493,7 @@ impl<'a> Parser<'a> { } } + /// Parse an optional `AT TIME ZONE` clause. pub fn parse_optional_time_zone(&mut self) -> Result, ParserError> { if self.parse_keywords(&[Keyword::AT, Keyword::TIME, Keyword::ZONE]) { self.parse_value().map(|v| Some(v.value)) @@ -2551,6 +2591,7 @@ impl<'a> Parser<'a> { Ok(exists_node) } + /// Parse a SQL `EXTRACT` expression e.g. `EXTRACT(YEAR FROM date)`. pub fn parse_extract_expr(&mut self) -> Result { self.expect_token(&Token::LParen)?; let field = self.parse_date_time_field()?; @@ -2576,6 +2617,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a `CEIL` or `FLOOR` expression. pub fn parse_ceil_floor_expr(&mut self, is_ceil: bool) -> Result { self.expect_token(&Token::LParen)?; let expr = self.parse_expr()?; @@ -2610,6 +2652,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `POSITION` expression. pub fn parse_position_expr(&mut self, ident: Ident) -> Result { let between_prec = self.dialect.prec_value(Precedence::Between); let position_expr = self.maybe_parse(|p| { @@ -2634,7 +2677,7 @@ impl<'a> Parser<'a> { } } - // { SUBSTRING | SUBSTR } ( [FROM 1] [FOR 3]) + /// Parse `SUBSTRING`/`SUBSTR` expressions: `SUBSTRING(expr FROM start FOR length)` or `SUBSTR(expr, start, length)`. pub fn parse_substring(&mut self) -> Result { let shorthand = match self.expect_one_of_keywords(&[Keyword::SUBSTR, Keyword::SUBSTRING])? { Keyword::SUBSTR => true, @@ -2667,6 +2710,9 @@ impl<'a> Parser<'a> { }) } + /// Parse an OVERLAY expression. + /// + /// See [Expr::Overlay] pub fn parse_overlay_expr(&mut self) -> Result { // PARSE OVERLAY (EXPR PLACING EXPR FROM 1 [FOR 3]) self.expect_token(&Token::LParen)?; @@ -2735,6 +2781,9 @@ impl<'a> Parser<'a> { } } + /// Parse the `WHERE` field for a `TRIM` expression. + /// + /// See [TrimWhereField] pub fn parse_trim_where(&mut self) -> Result { let next_token = self.next_token(); match &next_token.token { @@ -2756,6 +2805,9 @@ impl<'a> Parser<'a> { Ok(Expr::Array(Array { elem: exprs, named })) } + /// Parse the `ON OVERFLOW` clause for `LISTAGG`. + /// + /// See [`ListAggOnOverflow`] pub fn parse_listagg_on_overflow(&mut self) -> Result, ParserError> { if self.parse_keywords(&[Keyword::ON, Keyword::OVERFLOW]) { if self.parse_keyword(Keyword::ERROR) { @@ -2792,10 +2844,12 @@ impl<'a> Parser<'a> { } } - // This function parses date/time fields for the EXTRACT function-like - // operator, interval qualifiers, and the ceil/floor operations. - // EXTRACT supports a wider set of date/time fields than interval qualifiers, - // so this function may need to be split in two. + /// Parse a date/time field for `EXTRACT`, interval qualifiers, and ceil/floor operations. + /// + /// `EXTRACT` supports a wider set of date/time fields than interval qualifiers, + /// so this function may need to be split in two. + /// + /// See [`DateTimeField`] pub fn parse_date_time_field(&mut self) -> Result { let next_token = self.next_token(); match &next_token.token { @@ -2869,6 +2923,9 @@ impl<'a> Parser<'a> { } } + /// Parse a `NOT` expression. + /// + /// Represented in the AST as `Expr::UnaryOp` with `UnaryOperator::Not`. pub fn parse_not(&mut self) -> Result { match self.peek_token().token { Token::Word(w) => match w.keyword { @@ -4302,6 +4359,9 @@ impl<'a> Parser<'a> { } #[must_use] + /// Check if the current token is the expected keyword without consuming it. + /// + /// Returns true if the current token matches the expected keyword. pub fn peek_keyword(&self, expected: Keyword) -> bool { matches!(&self.peek_token_ref().token, Token::Word(w) if expected == w.keyword) } @@ -4508,6 +4568,7 @@ impl<'a> Parser<'a> { ) } + /// Parse a list of actions for `GRANT` statements. pub fn parse_actions_list(&mut self) -> Result, ParserError> { let mut values = vec![]; loop { @@ -4657,6 +4718,7 @@ impl<'a> Parser<'a> { Ok(values) } + /// Parse an expression enclosed in parentheses. pub fn parse_parenthesized(&mut self, mut f: F) -> Result where F: FnMut(&mut Parser<'a>) -> Result, @@ -5076,6 +5138,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a `CREATE SCHEMA` statement. pub fn parse_create_schema(&mut self) -> Result { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); @@ -5132,6 +5195,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `CREATE DATABASE` statement. pub fn parse_create_database(&mut self) -> Result { let ine = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); let db_name = self.parse_object_name(false)?; @@ -5176,6 +5240,7 @@ impl<'a> Parser<'a> { }) } + /// Parse an optional `USING` clause for `CREATE FUNCTION`. pub fn parse_optional_create_function_using( &mut self, ) -> Result, ParserError> { @@ -5198,6 +5263,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `CREATE FUNCTION` statement. pub fn parse_create_function( &mut self, or_alter: bool, @@ -5666,6 +5732,7 @@ impl<'a> Parser<'a> { })) } + /// Parse a `CREATE TRIGGER` statement. pub fn parse_create_trigger( &mut self, temporary: bool, @@ -5758,6 +5825,7 @@ impl<'a> Parser<'a> { .into()) } + /// Parse the period part of a trigger (`BEFORE`, `AFTER`, etc.). pub fn parse_trigger_period(&mut self) -> Result { Ok( match self.expect_one_of_keywords(&[ @@ -5779,6 +5847,7 @@ impl<'a> Parser<'a> { ) } + /// Parse the event part of a trigger (`INSERT`, `UPDATE`, etc.). pub fn parse_trigger_event(&mut self) -> Result { Ok( match self.expect_one_of_keywords(&[ @@ -5805,6 +5874,7 @@ impl<'a> Parser<'a> { ) } + /// Parse the `REFERENCING` clause of a trigger. pub fn parse_trigger_referencing(&mut self) -> Result, ParserError> { let refer_type = match self.parse_one_of_keywords(&[Keyword::OLD, Keyword::NEW]) { Some(Keyword::OLD) if self.parse_keyword(Keyword::TABLE) => { @@ -5827,6 +5897,7 @@ impl<'a> Parser<'a> { })) } + /// Parse the execution body of a trigger (`FUNCTION` or `PROCEDURE`). pub fn parse_trigger_exec_body(&mut self) -> Result { Ok(TriggerExecBody { exec_type: match self @@ -5842,6 +5913,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a `CREATE MACRO` statement. pub fn parse_create_macro( &mut self, or_replace: bool, @@ -5889,6 +5961,7 @@ impl<'a> Parser<'a> { Ok(MacroArg { name, default_expr }) } + /// Parse a `CREATE EXTERNAL TABLE` statement. pub fn parse_create_external_table( &mut self, or_replace: bool, @@ -5934,6 +6007,7 @@ impl<'a> Parser<'a> { .build()) } + /// Parse a file format for external tables. pub fn parse_file_format(&mut self) -> Result { let next_token = self.next_token(); match &next_token.token { @@ -5959,6 +6033,7 @@ impl<'a> Parser<'a> { } } + /// Parse an `ANALYZE FORMAT`. pub fn parse_analyze_format(&mut self) -> Result { let next_token = self.next_token(); match &next_token.token { @@ -5972,6 +6047,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `CREATE VIEW` statement. pub fn parse_create_view( &mut self, or_alter: bool, @@ -6123,6 +6199,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `CREATE ROLE` statement. pub fn parse_create_role(&mut self) -> Result { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); let names = self.parse_comma_separated(|p| p.parse_object_name(false))?; @@ -6348,6 +6425,7 @@ impl<'a> Parser<'a> { .into()) } + /// Parse an `OWNER` clause. pub fn parse_owner(&mut self) -> Result { let owner = match self.parse_one_of_keywords(&[Keyword::CURRENT_USER, Keyword::CURRENT_ROLE, Keyword::SESSION_USER]) { Some(Keyword::CURRENT_USER) => Owner::CurrentUser, @@ -6806,6 +6884,7 @@ impl<'a> Parser<'a> { })) } + /// Parse a `DROP` statement. pub fn parse_drop(&mut self) -> Result { // MySQL dialect supports `TEMPORARY` let temporary = dialect_of!(self is MySqlDialect | GenericDialect | DuckDbDialect) @@ -7390,7 +7469,7 @@ impl<'a> Parser<'a> { }) } - // FETCH [ direction { FROM | IN } ] cursor INTO target; + /// Parse `FETCH [direction] { FROM | IN } cursor INTO target;` statement. pub fn parse_fetch_statement(&mut self) -> Result { let direction = if self.parse_keyword(Keyword::NEXT) { FetchDirection::Next @@ -7460,6 +7539,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a `DISCARD` statement. pub fn parse_discard(&mut self) -> Result { let object_type = if self.parse_keyword(Keyword::ALL) { DiscardObject::ALL @@ -7478,6 +7558,7 @@ impl<'a> Parser<'a> { Ok(Statement::Discard { object_type }) } + /// Parse a `CREATE INDEX` statement. pub fn parse_create_index(&mut self, unique: bool) -> Result { let concurrently = self.parse_keyword(Keyword::CONCURRENTLY); let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); @@ -7569,6 +7650,7 @@ impl<'a> Parser<'a> { })) } + /// Parse a `CREATE EXTENSION` statement. pub fn parse_create_extension(&mut self) -> Result { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); let name = self.parse_identifier()?; @@ -7696,7 +7778,9 @@ impl<'a> Parser<'a> { })) } - //TODO: Implement parsing for Skewed + /// Parse Hive distribution style. + /// + /// TODO: Support parsing for `SKEWED` distribution style. pub fn parse_hive_distribution(&mut self) -> Result { if self.parse_keywords(&[Keyword::PARTITIONED, Keyword::BY]) { self.expect_token(&Token::LParen)?; @@ -7708,6 +7792,7 @@ impl<'a> Parser<'a> { } } + /// Parse Hive formats. pub fn parse_hive_formats(&mut self) -> Result, ParserError> { let mut hive_format: Option = None; loop { @@ -7763,6 +7848,7 @@ impl<'a> Parser<'a> { Ok(hive_format) } + /// Parse Hive row format. pub fn parse_row_format(&mut self) -> Result { self.expect_keyword_is(Keyword::FORMAT)?; match self.parse_one_of_keywords(&[Keyword::SERDE, Keyword::DELIMITED]) { @@ -7867,6 +7953,7 @@ impl<'a> Parser<'a> { } } + /// Parse `CREATE TABLE` statement. pub fn parse_create_table( &mut self, or_replace: bool, @@ -8296,6 +8383,7 @@ impl<'a> Parser<'a> { Ok(Some(SqlOption::KeyValue { key, value })) } + /// Parse plain options. pub fn parse_plain_options(&mut self) -> Result, ParserError> { let mut options = Vec::new(); @@ -8309,6 +8397,7 @@ impl<'a> Parser<'a> { Ok(options) } + /// Parse optional inline comment. pub fn parse_optional_inline_comment(&mut self) -> Result, ParserError> { let comment = if self.parse_keyword(Keyword::COMMENT) { let has_eq = self.consume_token(&Token::Eq); @@ -8324,6 +8413,7 @@ impl<'a> Parser<'a> { Ok(comment) } + /// Parse comment value. pub fn parse_comment_value(&mut self) -> Result { let next_token = self.next_token(); let value = match next_token.token { @@ -8334,6 +8424,7 @@ impl<'a> Parser<'a> { Ok(value) } + /// Parse optional procedure parameters. pub fn parse_optional_procedure_parameters( &mut self, ) -> Result>, ParserError> { @@ -8356,6 +8447,7 @@ impl<'a> Parser<'a> { Ok(Some(params)) } + /// Parse columns and constraints. pub fn parse_columns(&mut self) -> Result<(Vec, Vec), ParserError> { let mut columns = vec![]; let mut constraints = vec![]; @@ -8392,6 +8484,7 @@ impl<'a> Parser<'a> { Ok((columns, constraints)) } + /// Parse procedure parameter. pub fn parse_procedure_param(&mut self) -> Result { let mode = if self.parse_keyword(Keyword::IN) { Some(ArgMode::In) @@ -8418,6 +8511,7 @@ impl<'a> Parser<'a> { }) } + /// Parse column definition. pub fn parse_column_def(&mut self) -> Result { let col_name = self.parse_identifier()?; let data_type = if self.is_column_type_sqlite_unspecified() { @@ -8473,6 +8567,7 @@ impl<'a> Parser<'a> { } } + /// Parse optional column option. pub fn parse_optional_column_option(&mut self) -> Result, ParserError> { if let Some(option) = self.dialect.parse_column_option(self)? { return option; @@ -8826,6 +8921,7 @@ impl<'a> Parser<'a> { })) } + /// Parse optional `CLUSTERED BY` clause for Hive/Generic dialects. pub fn parse_optional_clustered_by(&mut self) -> Result, ParserError> { let clustered_by = if dialect_of!(self is HiveDialect|GenericDialect) && self.parse_keywords(&[Keyword::CLUSTERED, Keyword::BY]) @@ -8855,6 +8951,9 @@ impl<'a> Parser<'a> { Ok(clustered_by) } + /// Parse a referential action used in foreign key clauses. + /// + /// Recognized forms: `RESTRICT`, `CASCADE`, `SET NULL`, `NO ACTION`, `SET DEFAULT`. pub fn parse_referential_action(&mut self) -> Result { if self.parse_keyword(Keyword::RESTRICT) { Ok(ReferentialAction::Restrict) @@ -8874,6 +8973,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `MATCH` kind for constraint references: `FULL`, `PARTIAL`, or `SIMPLE`. pub fn parse_match_kind(&mut self) -> Result { if self.parse_keyword(Keyword::FULL) { Ok(ConstraintReferenceMatchKind::Full) @@ -8886,6 +8986,7 @@ impl<'a> Parser<'a> { } } + /// Parse optional constraint characteristics such as `DEFERRABLE`, `INITIALLY` and `ENFORCED`. pub fn parse_constraint_characteristics( &mut self, ) -> Result, ParserError> { @@ -8923,6 +9024,7 @@ impl<'a> Parser<'a> { } } + /// Parse an optional table constraint (e.g. `PRIMARY KEY`, `UNIQUE`, `FOREIGN KEY`, `CHECK`). pub fn parse_optional_table_constraint( &mut self, ) -> Result, ParserError> { @@ -9138,6 +9240,7 @@ impl<'a> Parser<'a> { }) } + /// Optionally parse a parenthesized list of `SqlOption`s introduced by `keyword`. pub fn maybe_parse_options( &mut self, keyword: Keyword, @@ -9150,6 +9253,7 @@ impl<'a> Parser<'a> { Ok(None) } + /// Parse a parenthesized list of `SqlOption`s following `keyword`, or return an empty vec. pub fn parse_options(&mut self, keyword: Keyword) -> Result, ParserError> { if self.parse_keyword(keyword) { self.expect_token(&Token::LParen)?; @@ -9161,6 +9265,7 @@ impl<'a> Parser<'a> { } } + /// Parse options introduced by one of `keywords` followed by a parenthesized list. pub fn parse_options_with_keywords( &mut self, keywords: &[Keyword], @@ -9175,6 +9280,7 @@ impl<'a> Parser<'a> { } } + /// Parse an index type token (e.g. `BTREE`, `HASH`, or a custom identifier). pub fn parse_index_type(&mut self) -> Result { Ok(if self.parse_keyword(Keyword::BTREE) { IndexType::BTree @@ -9200,6 +9306,7 @@ impl<'a> Parser<'a> { /// ```sql //// USING BTREE (name, age DESC) /// ``` + /// Optionally parse `USING ` and return the parsed `IndexType` if present. pub fn parse_optional_using_then_index_type( &mut self, ) -> Result, ParserError> { @@ -9212,11 +9319,13 @@ impl<'a> Parser<'a> { /// Parse `[ident]`, mostly `ident` is name, like: /// `window_name`, `index_name`, ... + /// Parse an optional identifier, returning `Some(Ident)` if present. pub fn parse_optional_ident(&mut self) -> Result, ParserError> { self.maybe_parse(|parser| parser.parse_identifier()) } #[must_use] + /// Parse optional `KEY` or `INDEX` display tokens used in index/constraint declarations. pub fn parse_index_type_display(&mut self) -> KeyOrIndexDisplay { if self.parse_keyword(Keyword::KEY) { KeyOrIndexDisplay::Key @@ -9227,6 +9336,7 @@ impl<'a> Parser<'a> { } } + /// Parse an optional index option such as `USING ` or `COMMENT `. pub fn parse_optional_index_option(&mut self) -> Result, ParserError> { if let Some(index_type) = self.parse_optional_using_then_index_type()? { Ok(Some(IndexOption::Using(index_type))) @@ -9238,6 +9348,7 @@ impl<'a> Parser<'a> { } } + /// Parse zero or more index options and return them as a vector. pub fn parse_index_options(&mut self) -> Result, ParserError> { let mut options = Vec::new(); @@ -9249,6 +9360,7 @@ impl<'a> Parser<'a> { } } + /// Parse a single `SqlOption` used by various dialect-specific DDL statements. pub fn parse_sql_option(&mut self) -> Result { let is_mssql = dialect_of!(self is MsSqlDialect|GenericDialect); @@ -9272,6 +9384,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `CLUSTERED` table option (MSSQL-specific syntaxes supported). pub fn parse_option_clustered(&mut self) -> Result { if self.parse_keywords(&[ Keyword::CLUSTERED, @@ -9308,6 +9421,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `PARTITION(...) FOR VALUES(...)` table option. pub fn parse_option_partition(&mut self) -> Result { self.expect_keyword_is(Keyword::PARTITION)?; self.expect_token(&Token::LParen)?; @@ -9337,6 +9451,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a parenthesized list of partition expressions and return a `Partition` value. pub fn parse_partition(&mut self) -> Result { self.expect_token(&Token::LParen)?; let partitions = self.parse_comma_separated(Parser::parse_expr)?; @@ -9344,6 +9459,7 @@ impl<'a> Parser<'a> { Ok(Partition::Partitions(partitions)) } + /// Parse a parenthesized `SELECT` projection used for projection-based operations. pub fn parse_projection_select(&mut self) -> Result { self.expect_token(&Token::LParen)?; self.expect_keyword_is(Keyword::SELECT)?; @@ -9357,6 +9473,7 @@ impl<'a> Parser<'a> { order_by, }) } + /// Parse `ALTER TABLE ... ADD PROJECTION ...` operation. pub fn parse_alter_table_add_projection(&mut self) -> Result { let if_not_exists = self.parse_keywords(&[Keyword::IF, Keyword::NOT, Keyword::EXISTS]); let name = self.parse_identifier()?; @@ -9368,6 +9485,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a single `ALTER TABLE` operation and return an `AlterTableOperation`. pub fn parse_alter_table_operation(&mut self) -> Result { let operation = if self.parse_keyword(Keyword::ADD) { if let Some(constraint) = self.parse_optional_table_constraint()? { @@ -9853,6 +9971,7 @@ impl<'a> Parser<'a> { } } + /// Parse an `ALTER ` statement and dispatch to the appropriate alter handler. pub fn parse_alter(&mut self) -> Result { let object_type = self.expect_one_of_keywords(&[ Keyword::VIEW, @@ -9901,6 +10020,8 @@ impl<'a> Parser<'a> { Keyword::OPERATOR => { if self.parse_keyword(Keyword::FAMILY) { self.parse_alter_operator_family() + } else if self.parse_keyword(Keyword::CLASS) { + self.parse_alter_operator_class() } else { self.parse_alter_operator() } @@ -9960,6 +10081,7 @@ impl<'a> Parser<'a> { .into()) } + /// Parse an `ALTER VIEW` statement. pub fn parse_alter_view(&mut self) -> Result { let name = self.parse_object_name(false)?; let columns = self.parse_parenthesized_column_list(Optional, false)?; @@ -10300,8 +10422,40 @@ impl<'a> Parser<'a> { })) } - // Parse a [Statement::AlterSchema] - // ALTER SCHEMA [ IF EXISTS ] schema_name + /// Parse an `ALTER OPERATOR CLASS` statement. + /// + /// Handles operations like `RENAME TO`, `OWNER TO`, and `SET SCHEMA`. + pub fn parse_alter_operator_class(&mut self) -> Result { + let name = self.parse_object_name(false)?; + self.expect_keyword(Keyword::USING)?; + let using = self.parse_identifier()?; + + let operation = if self.parse_keywords(&[Keyword::RENAME, Keyword::TO]) { + let new_name = self.parse_object_name(false)?; + AlterOperatorClassOperation::RenameTo { new_name } + } else if self.parse_keywords(&[Keyword::OWNER, Keyword::TO]) { + let owner = self.parse_owner()?; + AlterOperatorClassOperation::OwnerTo(owner) + } else if self.parse_keywords(&[Keyword::SET, Keyword::SCHEMA]) { + let schema_name = self.parse_object_name(false)?; + AlterOperatorClassOperation::SetSchema { schema_name } + } else { + return self.expected_ref( + "RENAME TO, OWNER TO, or SET SCHEMA after ALTER OPERATOR CLASS", + self.peek_token_ref(), + ); + }; + + Ok(Statement::AlterOperatorClass(AlterOperatorClass { + name, + using, + operation, + })) + } + + /// Parse an `ALTER SCHEMA` statement. + /// + /// Supports operations such as setting options, renaming, adding/dropping replicas, and changing owner. pub fn parse_alter_schema(&mut self) -> Result { self.expect_keywords(&[Keyword::ALTER, Keyword::SCHEMA])?; let if_exists = self.parse_keywords(&[Keyword::IF, Keyword::EXISTS]); @@ -10441,6 +10595,7 @@ impl<'a> Parser<'a> { })) } + /// Parse a `CLOSE` cursor statement. pub fn parse_close(&mut self) -> Result { let cursor = if self.parse_keyword(Keyword::ALL) { CloseCursor::All @@ -10763,6 +10918,7 @@ impl<'a> Parser<'a> { self.parse_tab_value() } + /// Parse a single tab-separated value row used by `COPY` payload parsing. pub fn parse_tab_value(&mut self) -> Vec> { let mut values = vec![]; let mut content = String::from(""); @@ -11072,6 +11228,7 @@ impl<'a> Parser<'a> { self.expected("unicode normalization form", self.peek_token()) } + /// Parse parenthesized enum members, used with `ENUM(...)` type definitions. pub fn parse_enum_values(&mut self) -> Result, ParserError> { self.expect_token(&Token::LParen)?; let values = self.parse_comma_separated(|parser| { @@ -11537,6 +11694,7 @@ impl<'a> Parser<'a> { Ok(columns) } + /// Parse a parenthesized, comma-separated list of single-quoted strings. pub fn parse_string_values(&mut self) -> Result, ParserError> { self.expect_token(&Token::LParen)?; let mut values = Vec::new(); @@ -11751,6 +11909,7 @@ impl<'a> Parser<'a> { } } + /// Parse an optional `GROUP BY` clause, returning `Some(GroupByExpr)` when present. pub fn parse_optional_group_by(&mut self) -> Result, ParserError> { if self.parse_keywords(&[Keyword::GROUP, Keyword::BY]) { let expressions = if self.parse_keyword(Keyword::ALL) { @@ -11807,6 +11966,7 @@ impl<'a> Parser<'a> { } } + /// Parse an optional `ORDER BY` clause, returning `Some(OrderBy)` when present. pub fn parse_optional_order_by(&mut self) -> Result, ParserError> { if self.parse_keywords(&[Keyword::ORDER, Keyword::BY]) { let order_by = @@ -12267,6 +12427,7 @@ impl<'a> Parser<'a> { self.parse_parenthesized_column_list_inner(optional, allow_empty, |p| p.parse_identifier()) } + /// Parse a parenthesized list of compound identifiers as expressions. pub fn parse_parenthesized_compound_identifier_list( &mut self, optional: IsOptional, @@ -12341,6 +12502,7 @@ impl<'a> Parser<'a> { } } + /// Parse an unsigned precision value enclosed in parentheses, e.g. `(10)`. pub fn parse_precision(&mut self) -> Result { self.expect_token(&Token::LParen)?; let n = self.parse_literal_uint()?; @@ -12348,6 +12510,7 @@ impl<'a> Parser<'a> { Ok(n) } + /// Parse an optional precision `(n)` and return it as `Some(n)` when present. pub fn parse_optional_precision(&mut self) -> Result, ParserError> { if self.consume_token(&Token::LParen) { let n = self.parse_literal_uint()?; @@ -12457,6 +12620,7 @@ impl<'a> Parser<'a> { Ok((precision, time_zone)) } + /// Parse an optional character length specification `(n | MAX [CHARACTERS|OCTETS])`. pub fn parse_optional_character_length( &mut self, ) -> Result, ParserError> { @@ -12469,6 +12633,7 @@ impl<'a> Parser<'a> { } } + /// Parse an optional binary length specification like `(n)`. pub fn parse_optional_binary_length(&mut self) -> Result, ParserError> { if self.consume_token(&Token::LParen) { let binary_length = self.parse_binary_length()?; @@ -12479,6 +12644,7 @@ impl<'a> Parser<'a> { } } + /// Parse a character length, handling `MAX` or integer lengths with optional units. pub fn parse_character_length(&mut self) -> Result { if self.parse_keyword(Keyword::MAX) { return Ok(CharacterLength::Max); @@ -12494,6 +12660,7 @@ impl<'a> Parser<'a> { Ok(CharacterLength::IntegerLength { length, unit }) } + /// Parse a binary length specification, returning `BinaryLength`. pub fn parse_binary_length(&mut self) -> Result { if self.parse_keyword(Keyword::MAX) { return Ok(BinaryLength::Max); @@ -12502,6 +12669,7 @@ impl<'a> Parser<'a> { Ok(BinaryLength::IntegerLength { length }) } + /// Parse an optional `(precision[, scale])` and return `(Option, Option)`. pub fn parse_optional_precision_scale( &mut self, ) -> Result<(Option, Option), ParserError> { @@ -12519,6 +12687,7 @@ impl<'a> Parser<'a> { } } + /// Parse exact-number precision/scale info like `(precision[, scale])` for decimal types. pub fn parse_exact_number_optional_precision_scale( &mut self, ) -> Result { @@ -12562,6 +12731,7 @@ impl<'a> Parser<'a> { } } + /// Parse optional type modifiers appearing in parentheses e.g. `(UNSIGNED, ZEROFILL)`. pub fn parse_optional_type_modifiers(&mut self) -> Result>, ParserError> { if self.consume_token(&Token::LParen) { let mut modifiers = Vec::new(); @@ -12609,6 +12779,7 @@ impl<'a> Parser<'a> { Ok(Box::new(SetExpr::Delete(self.parse_delete(delete_token)?))) } + /// Parse a `DELETE` statement and return `Statement::Delete`. pub fn parse_delete(&mut self, delete_token: TokenWithSpan) -> Result { let (tables, with_from_keyword) = if !self.parse_keyword(Keyword::FROM) { // `FROM` keyword is optional in BigQuery SQL. @@ -12667,7 +12838,8 @@ impl<'a> Parser<'a> { })) } - // KILL [CONNECTION | QUERY | MUTATION] processlist_id + /// Parse a `KILL` statement, optionally specifying `CONNECTION`, `QUERY`, or `MUTATION`. + /// KILL [CONNECTION | QUERY | MUTATION] processlist_id pub fn parse_kill(&mut self) -> Result { let modifier_keyword = self.parse_one_of_keywords(&[Keyword::CONNECTION, Keyword::QUERY, Keyword::MUTATION]); @@ -12693,6 +12865,7 @@ impl<'a> Parser<'a> { Ok(Statement::Kill { modifier, id }) } + /// Parse an `EXPLAIN` statement, handling dialect-specific options and modifiers. pub fn parse_explain( &mut self, describe_alias: DescribeAlias, @@ -13373,6 +13546,7 @@ impl<'a> Parser<'a> { Ok(expr.into()) } + /// Parse a set operator token into its `SetOperator` variant. pub fn parse_set_operator(&mut self, token: &Token) -> Option { match token { Token::Word(w) if w.keyword == Keyword::UNION => Some(SetOperator::Union), @@ -13383,6 +13557,7 @@ impl<'a> Parser<'a> { } } + /// Parse a set quantifier (e.g., `ALL`, `DISTINCT BY NAME`) for the given set operator. pub fn parse_set_quantifier(&mut self, op: &Option) -> SetQuantifier { match op { Some( @@ -13671,6 +13846,7 @@ impl<'a> Parser<'a> { res } + /// Parse a `CONNECT BY` clause (Oracle-style hierarchical query support). pub fn parse_connect_by(&mut self) -> Result { let (condition, relationships) = if self.parse_keywords(&[Keyword::CONNECT, Keyword::BY]) { let relationships = self.with_state(ParserState::ConnectBy, |parser| { @@ -13980,6 +14156,7 @@ impl<'a> Parser<'a> { self.expected("equals sign or TO", self.peek_token()) } + /// Parse session parameter assignments after `SET` when no `=` or `TO` is present. pub fn parse_set_session_params(&mut self) -> Result { if self.parse_keyword(Keyword::STATISTICS) { let topic = match self.parse_one_of_keywords(&[ @@ -14054,6 +14231,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `SHOW` statement and dispatch to specific SHOW handlers. pub fn parse_show(&mut self) -> Result { let terse = self.parse_keyword(Keyword::TERSE); let extended = self.parse_keyword(Keyword::EXTENDED); @@ -14141,6 +14319,7 @@ impl<'a> Parser<'a> { }) } + /// Parse `SHOW CREATE ` returning the corresponding `ShowCreate` statement. pub fn parse_show_create(&mut self) -> Result { let obj_type = match self.expect_one_of_keywords(&[ Keyword::TABLE, @@ -14166,6 +14345,7 @@ impl<'a> Parser<'a> { Ok(Statement::ShowCreate { obj_type, obj_name }) } + /// Parse `SHOW COLUMNS`/`SHOW FIELDS` and return a `ShowColumns` statement. pub fn parse_show_columns( &mut self, extended: bool, @@ -14211,16 +14391,19 @@ impl<'a> Parser<'a> { }) } + /// Parse `SHOW FUNCTIONS` and optional filter. pub fn parse_show_functions(&mut self) -> Result { let filter = self.parse_show_statement_filter()?; Ok(Statement::ShowFunctions { filter }) } + /// Parse `SHOW COLLATION` and optional filter. pub fn parse_show_collation(&mut self) -> Result { let filter = self.parse_show_statement_filter()?; Ok(Statement::ShowCollation { filter }) } + /// Parse an optional filter used by `SHOW` statements (LIKE, ILIKE, WHERE, or literal). pub fn parse_show_statement_filter( &mut self, ) -> Result, ParserError> { @@ -14244,6 +14427,7 @@ impl<'a> Parser<'a> { } } + /// Parse a `USE` statement (database/catalog/schema/warehouse/role selection). pub fn parse_use(&mut self) -> Result { // Determine which keywords are recognized by the current dialect let parsed_keyword = if dialect_of!(self is HiveDialect) { @@ -14295,6 +14479,7 @@ impl<'a> Parser<'a> { } } + /// Parse a table factor followed by any join clauses, returning `TableWithJoins`. pub fn parse_table_and_joins(&mut self) -> Result { let relation = self.parse_table_factor()?; // Note that for keywords to be properly handled here, they need to be @@ -15451,6 +15636,7 @@ impl<'a> Parser<'a> { Ok(Some(res)) } + /// Parse a derived table factor (a parenthesized subquery), handling optional LATERAL. pub fn parse_derived_table_factor( &mut self, lateral: IsLateral, @@ -15515,6 +15701,7 @@ impl<'a> Parser<'a> { Ok(ExprWithAlias { expr, alias }) } + /// Parse a PIVOT table factor (ClickHouse/Oracle style pivot), returning a TableFactor. pub fn parse_pivot_table_factor( &mut self, table: TableFactor, @@ -15568,6 +15755,7 @@ impl<'a> Parser<'a> { }) } + /// Parse an UNPIVOT table factor, returning a TableFactor. pub fn parse_unpivot_table_factor( &mut self, table: TableFactor, @@ -15601,6 +15789,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a JOIN constraint (`NATURAL`, `ON `, `USING (...)`, or no constraint). pub fn parse_join_constraint(&mut self, natural: bool) -> Result { if natural { Ok(JoinConstraint::Natural) @@ -15726,6 +15915,7 @@ impl<'a> Parser<'a> { Ok(values) } + /// Parse privileges and optional target objects for GRANT/DENY/REVOKE statements. pub fn parse_grant_deny_revoke_privileges_objects( &mut self, ) -> Result<(Privileges, Option), ParserError> { @@ -15939,6 +16129,7 @@ impl<'a> Parser<'a> { } } + /// Parse a single grantable permission/action (used within GRANT statements). pub fn parse_grant_permission(&mut self) -> Result { fn parse_columns(parser: &mut Parser) -> Result>, ParserError> { let columns = parser.parse_parenthesized_column_list(Optional, false)?; @@ -16190,6 +16381,7 @@ impl<'a> Parser<'a> { } } + /// Parse a grantee name, possibly with a host qualifier (user@host). pub fn parse_grantee_name(&mut self) -> Result { let mut name = self.parse_object_name(false)?; if self.dialect.supports_user_host_grantee() @@ -16486,9 +16678,9 @@ impl<'a> Parser<'a> { } } - // Parses input format clause used for [ClickHouse]. - // - // + /// Parses input format clause used for ClickHouse. + /// + /// pub fn parse_input_format_clause(&mut self) -> Result { let ident = self.parse_identifier()?; let values = self @@ -16524,6 +16716,7 @@ impl<'a> Parser<'a> { } } + /// Parse an optional `PARTITION (...)` clause for INSERT statements. pub fn parse_insert_partition(&mut self) -> Result>, ParserError> { if self.parse_keyword(Keyword::PARTITION) { self.expect_token(&Token::LParen)?; @@ -16535,6 +16728,7 @@ impl<'a> Parser<'a> { } } + /// Parse optional Hive `INPUTFORMAT ... SERDE ...` clause used by LOAD DATA. pub fn parse_load_data_table_format( &mut self, ) -> Result, ParserError> { @@ -16561,6 +16755,7 @@ impl<'a> Parser<'a> { Ok(Box::new(SetExpr::Update(self.parse_update(update_token)?))) } + /// Parse an `UPDATE` statement and return `Statement::Update`. pub fn parse_update(&mut self, update_token: TokenWithSpan) -> Result { let or = self.parse_conflict_clause(); let table = self.parse_table_and_joins()?; @@ -16628,6 +16823,7 @@ impl<'a> Parser<'a> { } } + /// Parse a single function argument, handling named and unnamed variants. pub fn parse_function_args(&mut self) -> Result { let arg = if self.dialect.supports_named_fn_args_with_expr_name() { self.maybe_parse(|p| { @@ -16687,6 +16883,7 @@ impl<'a> Parser<'a> { } } + /// Parse an optional, comma-separated list of function arguments (consumes closing paren). pub fn parse_optional_args(&mut self) -> Result, ParserError> { if self.consume_token(&Token::RParen) { Ok(vec![]) @@ -17072,6 +17269,7 @@ impl<'a> Parser<'a> { Ok(opt_replace) } + /// Parse a single element of a `REPLACE (...)` select-item clause. pub fn parse_replace_elements(&mut self) -> Result { let expr = self.parse_expr()?; let as_keyword = self.parse_keyword(Keyword::AS); @@ -17167,6 +17365,7 @@ impl<'a> Parser<'a> { // Parse a WITH FILL clause (ClickHouse dialect) // that follow the WITH FILL keywords in a ORDER BY clause + /// Parse a `WITH FILL` clause used in ORDER BY (ClickHouse dialect). pub fn parse_with_fill(&mut self) -> Result { let from = if self.parse_keyword(Keyword::FROM) { Some(self.parse_expr()?) @@ -17189,8 +17388,8 @@ impl<'a> Parser<'a> { Ok(WithFill { from, to, step }) } - // Parse a set of comma separated INTERPOLATE expressions (ClickHouse dialect) - // that follow the INTERPOLATE keyword in an ORDER BY clause with the WITH FILL modifier + /// Parse a set of comma separated INTERPOLATE expressions (ClickHouse dialect) + /// that follow the INTERPOLATE keyword in an ORDER BY clause with the WITH FILL modifier pub fn parse_interpolations(&mut self) -> Result, ParserError> { if !self.parse_keyword(Keyword::INTERPOLATE) { return Ok(None); @@ -17210,7 +17409,7 @@ impl<'a> Parser<'a> { Ok(Some(Interpolate { exprs: None })) } - // Parse a INTERPOLATE expression (ClickHouse dialect) + /// Parse a INTERPOLATE expression (ClickHouse dialect) pub fn parse_interpolation(&mut self) -> Result { let column = self.parse_identifier()?; let expr = if self.parse_keyword(Keyword::AS) { @@ -17327,6 +17526,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a VALUES clause pub fn parse_values( &mut self, allow_empty: bool, @@ -17356,6 +17556,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a 'START TRANSACTION' statement pub fn parse_start_transaction(&mut self) -> Result { self.expect_keyword_is(Keyword::TRANSACTION)?; Ok(Statement::StartTransaction { @@ -17369,6 +17570,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a 'BEGIN' statement pub fn parse_begin(&mut self) -> Result { let modifier = if !self.dialect.supports_start_transaction_modifier() { None @@ -17401,6 +17603,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a 'BEGIN ... EXCEPTION ... END' block pub fn parse_begin_exception_end(&mut self) -> Result { let statements = self.parse_statement_list(&[Keyword::EXCEPTION, Keyword::END])?; @@ -17446,6 +17649,7 @@ impl<'a> Parser<'a> { }) } + /// Parse an 'END' statement pub fn parse_end(&mut self) -> Result { let modifier = if !self.dialect.supports_end_transaction_modifier() { None @@ -17463,6 +17667,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a list of transaction modes pub fn parse_transaction_modes(&mut self) -> Result, ParserError> { let mut modes = vec![]; let mut required = false; @@ -17501,6 +17706,7 @@ impl<'a> Parser<'a> { Ok(modes) } + /// Parse a 'COMMIT' statement pub fn parse_commit(&mut self) -> Result { Ok(Statement::Commit { chain: self.parse_commit_rollback_chain()?, @@ -17509,6 +17715,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a 'ROLLBACK' statement pub fn parse_rollback(&mut self) -> Result { let chain = self.parse_commit_rollback_chain()?; let savepoint = self.parse_rollback_savepoint()?; @@ -17516,6 +17723,7 @@ impl<'a> Parser<'a> { Ok(Statement::Rollback { chain, savepoint }) } + /// Parse an optional `AND [NO] CHAIN` clause for `COMMIT` and `ROLLBACK` statements pub fn parse_commit_rollback_chain(&mut self) -> Result { let _ = self.parse_one_of_keywords(&[Keyword::TRANSACTION, Keyword::WORK]); if self.parse_keyword(Keyword::AND) { @@ -17527,6 +17735,7 @@ impl<'a> Parser<'a> { } } + /// Parse an optional 'TO SAVEPOINT savepoint_name' clause for ROLLBACK statements pub fn parse_rollback_savepoint(&mut self) -> Result, ParserError> { if self.parse_keyword(Keyword::TO) { let _ = self.parse_keyword(Keyword::SAVEPOINT); @@ -17566,6 +17775,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a single `RAISERROR` option pub fn parse_raiserror_option(&mut self) -> Result { match self.expect_one_of_keywords(&[Keyword::LOG, Keyword::NOWAIT, Keyword::SETERROR])? { Keyword::LOG => Ok(RaisErrorOption::Log), @@ -17578,12 +17788,14 @@ impl<'a> Parser<'a> { } } + /// Parse a SQL `DEALLOCATE` statement pub fn parse_deallocate(&mut self) -> Result { let prepare = self.parse_keyword(Keyword::PREPARE); let name = self.parse_identifier()?; Ok(Statement::Deallocate { name, prepare }) } + /// Parse a SQL `EXECUTE` statement pub fn parse_execute(&mut self) -> Result { let name = if self.dialect.supports_execute_immediate() && self.parse_keyword(Keyword::IMMEDIATE) @@ -17642,6 +17854,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a SQL `PREPARE` statement pub fn parse_prepare(&mut self) -> Result { let name = self.parse_identifier()?; @@ -17660,6 +17873,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a SQL `UNLOAD` statement pub fn parse_unload(&mut self) -> Result { self.expect_keyword(Keyword::UNLOAD)?; self.expect_token(&Token::LParen)?; @@ -17722,7 +17936,7 @@ impl<'a> Parser<'a> { } } - // PRAGMA [schema-name '.'] pragma-name [('=' pragma-value) | '(' pragma-value ')'] + /// PRAGMA [schema-name '.'] pragma-name [('=' pragma-value) | '(' pragma-value ')'] pub fn parse_pragma(&mut self) -> Result { let name = self.parse_object_name(false)?; if self.consume_token(&Token::LParen) { @@ -17954,6 +18168,7 @@ impl<'a> Parser<'a> { self.index } + /// Parse a named window definition. pub fn parse_named_window(&mut self) -> Result { let ident = self.parse_identifier()?; self.expect_keyword_is(Keyword::AS)?; @@ -17969,6 +18184,7 @@ impl<'a> Parser<'a> { Ok(NamedWindowDefinition(ident, window_expr)) } + /// Parse `CREATE PROCEDURE` statement. pub fn parse_create_procedure(&mut self, or_alter: bool) -> Result { let name = self.parse_object_name(false)?; let params = self.parse_optional_procedure_parameters()?; @@ -17992,6 +18208,7 @@ impl<'a> Parser<'a> { }) } + /// Parse a window specification. pub fn parse_window_spec(&mut self) -> Result { let window_name = match self.peek_token().token { Token::Word(word) if word.keyword == Keyword::NoKeyword => { @@ -18026,6 +18243,7 @@ impl<'a> Parser<'a> { }) } + /// Parse `CREATE TYPE` statement. pub fn parse_create_type(&mut self) -> Result { let name = self.parse_object_name(false)?; @@ -18736,6 +18954,7 @@ fn maybe_prefixed_expr(expr: Expr, prefix: Option) -> Expr { impl Word { #[deprecated(since = "0.54.0", note = "please use `into_ident` instead")] + /// Convert this word into an [`Ident`] identifier pub fn to_ident(&self, span: Span) -> Ident { Ident { value: self.value.clone(), diff --git a/src/tokenizer.rs b/src/tokenizer.rs index 8666563ac..eb935a4f2 100644 --- a/src/tokenizer.rs +++ b/src/tokenizer.rs @@ -401,10 +401,17 @@ impl fmt::Display for Token { } impl Token { + /// Create a `Token::Word` from an unquoted `keyword`. + /// + /// The lookup is case-insensitive; unknown values become `Keyword::NoKeyword`. pub fn make_keyword(keyword: &str) -> Self { Token::make_word(keyword, None) } + /// Create a `Token::Word` from `word` with an optional `quote_style`. + /// + /// When `quote_style` is `None`, the parser attempts a case-insensitive keyword + /// lookup and sets the `Word::keyword` accordingly. pub fn make_word(word: &str, quote_style: Option) -> Self { let word_uppercase = word.to_uppercase(); Token::Word(Word { @@ -460,14 +467,27 @@ impl Word { } } +/// Represents whitespace in the input: spaces, newlines, tabs and comments. #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub enum Whitespace { + /// A single space character. Space, + /// A newline character. Newline, + /// A tab character. Tab, - SingleLineComment { comment: String, prefix: String }, + /// A single-line comment (e.g. `-- comment` or `# comment`). + /// The `comment` field contains the text, and `prefix` contains the comment prefix. + SingleLineComment { + /// The content of the comment (without the prefix). + comment: String, + /// The prefix used for the comment (for example `--` or `#`). + prefix: String, + }, + + /// A multi-line comment (without the `/* ... */` delimiters). MultiLineComment(String), } @@ -569,7 +589,9 @@ impl From<(u64, u64)> for Location { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] pub struct Span { + /// Start `Location` (inclusive). pub start: Location, + /// End `Location` (inclusive). pub end: Location, } @@ -691,8 +713,11 @@ pub type TokenWithLocation = TokenWithSpan; #[derive(Debug, Clone, Hash, Ord, PartialOrd, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "visitor", derive(Visit, VisitMut))] +/// A `Token` together with its `Span` (location in the source). pub struct TokenWithSpan { + /// The token value. pub token: Token, + /// The span covering the token in the input. pub span: Span, } @@ -736,10 +761,12 @@ impl fmt::Display for TokenWithSpan { } } -/// Tokenizer error +/// An error reported by the tokenizer, with a human-readable `message` and a `location`. #[derive(Debug, PartialEq, Eq)] pub struct TokenizerError { + /// A descriptive error message. pub message: String, + /// The `Location` where the error was detected. pub location: Location, } @@ -754,8 +781,8 @@ impl std::error::Error for TokenizerError {} struct State<'a> { peekable: Peekable>, - pub line: u64, - pub col: u64, + line: u64, + col: u64, } impl State<'_> { @@ -780,6 +807,7 @@ impl State<'_> { self.peekable.peek() } + /// Return the current `Location` (line and column) pub fn location(&self) -> Location { Location { line: self.line, diff --git a/tests/sqlparser_postgres.rs b/tests/sqlparser_postgres.rs index 9f4564ef2..ab1a52f48 100644 --- a/tests/sqlparser_postgres.rs +++ b/tests/sqlparser_postgres.rs @@ -7531,6 +7531,156 @@ fn parse_alter_operator_family() { .is_err()); } +#[test] +fn parse_alter_operator_class() { + // Test ALTER OPERATOR CLASS ... RENAME TO + let sql = "ALTER OPERATOR CLASS int_ops USING btree RENAME TO integer_ops"; + assert_eq!( + pg_and_generic().verified_stmt(sql), + Statement::AlterOperatorClass(AlterOperatorClass { + name: ObjectName::from(vec![Ident::new("int_ops")]), + using: Ident::new("btree"), + operation: AlterOperatorClassOperation::RenameTo { + new_name: ObjectName::from(vec![Ident::new("integer_ops")]), + }, + }) + ); + + // Test ALTER OPERATOR CLASS ... OWNER TO + let sql = "ALTER OPERATOR CLASS int_ops USING btree OWNER TO joe"; + assert_eq!( + pg_and_generic().verified_stmt(sql), + Statement::AlterOperatorClass(AlterOperatorClass { + name: ObjectName::from(vec![Ident::new("int_ops")]), + using: Ident::new("btree"), + operation: AlterOperatorClassOperation::OwnerTo(Owner::Ident(Ident::new("joe"))), + }) + ); + + // Test ALTER OPERATOR CLASS ... OWNER TO CURRENT_USER + let sql = "ALTER OPERATOR CLASS int_ops USING btree OWNER TO CURRENT_USER"; + assert_eq!( + pg_and_generic().verified_stmt(sql), + Statement::AlterOperatorClass(AlterOperatorClass { + name: ObjectName::from(vec![Ident::new("int_ops")]), + using: Ident::new("btree"), + operation: AlterOperatorClassOperation::OwnerTo(Owner::CurrentUser), + }) + ); + + // Test ALTER OPERATOR CLASS ... SET SCHEMA + let sql = "ALTER OPERATOR CLASS int_ops USING btree SET SCHEMA new_schema"; + assert_eq!( + pg_and_generic().verified_stmt(sql), + Statement::AlterOperatorClass(AlterOperatorClass { + name: ObjectName::from(vec![Ident::new("int_ops")]), + using: Ident::new("btree"), + operation: AlterOperatorClassOperation::SetSchema { + schema_name: ObjectName::from(vec![Ident::new("new_schema")]), + }, + }) + ); + + // Test with schema-qualified operator class name + let sql = "ALTER OPERATOR CLASS myschema.int_ops USING btree RENAME TO integer_ops"; + assert_eq!( + pg_and_generic().verified_stmt(sql), + Statement::AlterOperatorClass(AlterOperatorClass { + name: ObjectName::from(vec![Ident::new("myschema"), Ident::new("int_ops")]), + using: Ident::new("btree"), + operation: AlterOperatorClassOperation::RenameTo { + new_name: ObjectName::from(vec![Ident::new("integer_ops")]), + }, + }) + ); + + // Test with different index methods + for index_method in &["hash", "gist", "gin", "spgist", "brin"] { + let sql = format!( + "ALTER OPERATOR CLASS int_ops USING {} RENAME TO integer_ops", + index_method + ); + pg_and_generic().verified_stmt(&sql); + } + + // Test error cases + // Missing USING clause + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops RENAME TO integer_ops") + .is_err()); + + // Invalid operation + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops USING btree INVALID_OPERATION") + .is_err()); + + // Missing new name for RENAME TO + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops USING btree RENAME TO") + .is_err()); + + // Missing owner for OWNER TO + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops USING btree OWNER TO") + .is_err()); + + // Missing schema for SET SCHEMA + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops USING btree SET SCHEMA") + .is_err()); + + // Invalid new name + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops USING btree RENAME TO 123invalid") + .is_err()); + + // Invalid owner + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops USING btree OWNER TO 123invalid") + .is_err()); + + // Invalid schema name + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops USING btree SET SCHEMA 123invalid") + .is_err()); + + // Missing operator class name + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS USING btree RENAME TO integer_ops") + .is_err()); + + // Extra tokens at end + assert!(pg() + .parse_sql_statements( + "ALTER OPERATOR CLASS int_ops USING btree RENAME TO integer_ops EXTRA" + ) + .is_err()); + + // Missing index method + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops RENAME TO integer_ops") + .is_err()); + + // Invalid index method + assert!(pg() + .parse_sql_statements("ALTER OPERATOR CLASS int_ops USING 123invalid RENAME TO integer_ops") + .is_err()); + + // Trying to use ADD operation (only valid for OPERATOR FAMILY) + assert!(pg() + .parse_sql_statements( + "ALTER OPERATOR CLASS int_ops USING btree ADD OPERATOR 1 < (INT4, INT2)" + ) + .is_err()); + + // Trying to use DROP operation (only valid for OPERATOR FAMILY) + assert!(pg() + .parse_sql_statements( + "ALTER OPERATOR CLASS int_ops USING btree DROP OPERATOR 1 (INT4, INT2)" + ) + .is_err()); +} + #[test] fn parse_drop_operator_family() { for if_exists in [true, false] {