Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions src/ast/ddl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,43 @@ impl fmt::Display for AlterPolicyOperation {
}
}

/// An `ALTER TRIGGER` (`Statement::AlterTrigger`) operation
///
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-altertrigger.html)
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub enum AlterTriggerOperation {
/// `RENAME TO new_name`
Rename {
/// The new identifier for the trigger.
new_name: Ident,
},
/// `[ NO ] DEPENDS ON EXTENSION extension_name`
DependsOnExtension {
/// `true` when `NO DEPENDS ON EXTENSION`.
no: bool,
/// Extension name.
extension_name: ObjectName,
},
}

impl fmt::Display for AlterTriggerOperation {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AlterTriggerOperation::Rename { new_name } => {
write!(f, "RENAME TO {new_name}")
}
AlterTriggerOperation::DependsOnExtension { no, extension_name } => {
if *no {
write!(f, "NO ")?;
}
write!(f, "DEPENDS ON EXTENSION {extension_name}")
}
}
}
}

/// [MySQL] `ALTER TABLE` algorithm.
///
/// [MySQL]: https://dev.mysql.com/doc/refman/8.4/en/alter-table.html
Expand Down Expand Up @@ -6041,6 +6078,45 @@ impl From<AlterPolicy> for crate::ast::Statement {
}
}

/// ALTER TRIGGER statement.
///
/// Its source span covers `name`, `table_name` and `operation`.
///
/// ```sql
/// ALTER TRIGGER <NAME> ON <TABLE NAME> <OPERATION>
/// ```
/// (Postgresql-specific)
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
pub struct AlterTrigger {
/// Trigger name to alter.
pub name: Ident,
/// Target table name the trigger is defined on.
#[cfg_attr(feature = "visitor", visit(with = "visit_relation"))]
pub table_name: ObjectName,
/// Operation specific to the trigger alteration.
pub operation: AlterTriggerOperation,
}

impl fmt::Display for AlterTrigger {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"ALTER TRIGGER {name} ON {table_name} {operation}",
name = self.name,
table_name = self.table_name,
operation = self.operation
)
}
}

impl From<AlterTrigger> for crate::ast::Statement {
fn from(v: AlterTrigger) -> Self {
crate::ast::Statement::AlterTrigger(v)
}
}

/// A `CREATE FOREIGN TABLE` statement.
///
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createforeigntable.html)
Expand Down
43 changes: 25 additions & 18 deletions src/ast/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,24 +68,25 @@ pub use self::ddl::{
AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
AlterTableLock, AlterTableOperation, AlterTableType, AlterTextSearch, AlterTextSearchOperation,
AlterTextSearchOption, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty,
ConstraintCharacteristics, CreateCollation, CreateCollationDefinition, CreateConnector,
CreateDomain, CreateExtension, CreateForeignTable, CreateFunction, CreateIndex, CreateOperator,
CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
CreateTable, CreateTextSearch, CreateTrigger, CreateView, Deduplicate, DeferrableInitial,
DistStyle, DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass,
DropOperatorFamily, DropOperatorSignature, DropPolicy, DropTrigger, ForValues,
FunctionReturnType, GeneratedAs, GeneratedExpressionMode, IdentityParameters, IdentityProperty,
IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder, IndexColumn,
IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption, OperatorArgTypes,
OperatorClassItem, OperatorFamilyDropItem, OperatorFamilyItem, OperatorOption, OperatorPurpose,
Owner, Partition, PartitionBoundValue, ProcedureParam, ReferentialAction, RenameTableNameKind,
ReplicaIdentity, SqliteTableOption, SqliteTableOptions, TagsColumnOption, TextSearchObjectType,
TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef, WithData,
AlterTextSearchOption, AlterTrigger, AlterTriggerOperation, AlterType, AlterTypeAddValue,
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
ColumnPolicyProperty, ConstraintCharacteristics, CreateCollation, CreateCollationDefinition,
CreateConnector, CreateDomain, CreateExtension, CreateForeignTable, CreateFunction,
CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
CreatePolicyCommand, CreatePolicyType, CreateTable, CreateTextSearch, CreateTrigger,
CreateView, Deduplicate, DeferrableInitial, DistStyle, DropBehavior, DropExtension,
DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily, DropOperatorSignature,
DropPolicy, DropTrigger, ForValues, FunctionReturnType, GeneratedAs, GeneratedExpressionMode,
IdentityParameters, IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind,
IdentityPropertyOrder, IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, Msck,
NullsDistinctOption, OperatorArgTypes, OperatorClassItem, OperatorFamilyDropItem,
OperatorFamilyItem, OperatorOption, OperatorPurpose, Owner, Partition, PartitionBoundValue,
ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, SqliteTableOption,
SqliteTableOptions, TagsColumnOption, TextSearchObjectType, TriggerObjectKind, Truncate,
UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
UserDefinedTypeStorage, ViewColumnDef, WithData,
};
pub use self::dml::{
Delete, Insert, InsertOverriding, Merge, MergeAction, MergeClause, MergeClauseKind,
Expand Down Expand Up @@ -3928,6 +3929,11 @@ pub enum Statement {
/// (Postgresql-specific)
AlterPolicy(AlterPolicy),
/// ```sql
/// ALTER TRIGGER <NAME> ON <TABLE NAME> <OPERATION>
/// ```
/// (Postgresql-specific)
AlterTrigger(AlterTrigger),
/// ```sql
/// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
/// or
/// ALTER CONNECTOR connector_name SET URL new_url;
Expand Down Expand Up @@ -5729,6 +5735,7 @@ impl fmt::Display for Statement {
write!(f, "ALTER ROLE {name} {operation}")
}
Statement::AlterPolicy(alter_policy) => write!(f, "{alter_policy}"),
Statement::AlterTrigger(alter_trigger) => write!(f, "{alter_trigger}"),
Statement::AlterConnector {
name,
properties,
Expand Down
49 changes: 34 additions & 15 deletions src/ast/spans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,21 @@ use crate::tokenizer::Span;

use super::{
comments, dcl::SecondaryRoles, value::ValueWithSpan, AccessExpr, AlterColumnOperation,
AlterIndexOperation, AlterTableOperation, Analyze, Array, Assignment, AssignmentTarget,
AttachedToken, BeginEndStatements, CaseStatement, CloseCursor, ClusteredIndex, ColumnDef,
ColumnOption, ColumnOptionDef, ConditionalStatementBlock, ConditionalStatements,
ConflictTarget, ConnectByKind, ConstraintCharacteristics, CopySource, CreateIndex, CreateTable,
CreateTableOptions, Cte, Delete, DoUpdate, ExceptSelectItem, ExcludeConstraintElement,
ExcludeSelectItem, Expr, ExprWithAlias, Fetch, ForValues, FromTable, Function, FunctionArg,
FunctionArgExpr, FunctionArgumentClause, FunctionArgumentList, FunctionArguments, GroupByExpr,
HavingBound, IfStatement, IlikeSelectItem, InTarget, IndexColumn, Insert, Interpolate,
InterpolateExpr, Join, JoinConstraint, JoinOperator, JsonPath, JsonPathElem, LateralView,
LimitClause, MatchRecognizePattern, Measure, Merge, MergeAction, MergeClause, MergeInsertExpr,
MergeInsertKind, MergeUpdateExpr, MergeUpdateKind, NamedParenthesizedList,
NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction,
OnInsert, OpenStatement, OrderBy, OrderByExpr, OrderByKind, OutputClause, Parens, Partition,
PartitionBoundValue, PivotValueSource, ProjectionSelect, Query, RaiseStatement,
RaiseStatementValue, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
AlterIndexOperation, AlterTableOperation, AlterTrigger, AlterTriggerOperation, Analyze, Array,
Assignment, AssignmentTarget, AttachedToken, BeginEndStatements, CaseStatement, CloseCursor,
ClusteredIndex, ColumnDef, ColumnOption, ColumnOptionDef, ConditionalStatementBlock,
ConditionalStatements, ConflictTarget, ConnectByKind, ConstraintCharacteristics, CopySource,
CreateIndex, CreateTable, CreateTableOptions, Cte, Delete, DoUpdate, ExceptSelectItem,
ExcludeConstraintElement, ExcludeSelectItem, Expr, ExprWithAlias, Fetch, ForValues, FromTable,
Function, FunctionArg, FunctionArgExpr, FunctionArgumentClause, FunctionArgumentList,
FunctionArguments, GroupByExpr, HavingBound, IfStatement, IlikeSelectItem, InTarget,
IndexColumn, Insert, Interpolate, InterpolateExpr, Join, JoinConstraint, JoinOperator,
JsonPath, JsonPathElem, LateralView, LimitClause, MatchRecognizePattern, Measure, Merge,
MergeAction, MergeClause, MergeInsertExpr, MergeInsertKind, MergeUpdateExpr, MergeUpdateKind,
NamedParenthesizedList, NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict,
OnConflictAction, OnInsert, OpenStatement, OrderBy, OrderByExpr, OrderByKind, OutputClause,
Parens, Partition, PartitionBoundValue, PivotValueSource, ProjectionSelect, Query,
RaiseStatement, RaiseStatementValue, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, Setting, SqlOption, Statement,
Subscript, SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor,
TableObject, TableOptionsClustered, TableWithJoins, Update, UpdateTableFromKind, Use, Values,
Expand Down Expand Up @@ -488,6 +488,7 @@ impl Spanned for Statement {
Statement::OptimizeTable { .. } => Span::empty(),
Statement::CreatePolicy { .. } => Span::empty(),
Statement::AlterPolicy { .. } => Span::empty(),
Statement::AlterTrigger(trigger) => trigger.span(),
Statement::AlterConnector { .. } => Span::empty(),
Statement::DropPolicy { .. } => Span::empty(),
Statement::DropConnector { .. } => Span::empty(),
Expand Down Expand Up @@ -528,6 +529,24 @@ impl Spanned for Statement {
}
}

impl Spanned for AlterTrigger {
fn span(&self) -> Span {
self.name
.span
.union(&self.table_name.span())
.union(&self.operation.span())
}
}

impl Spanned for AlterTriggerOperation {
fn span(&self) -> Span {
match self {
Self::Rename { new_name } => new_name.span,
Self::DependsOnExtension { extension_name, .. } => extension_name.span(),
}
}
}

impl Spanned for Use {
fn span(&self) -> Span {
match self {
Expand Down
53 changes: 49 additions & 4 deletions src/parser/alter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@ use super::{Parser, ParserError};
use crate::{
ast::{
helpers::key_value_options::{KeyValueOptions, KeyValueOptionsDelimiter},
AlterConnectorOwner, AlterPolicy, AlterPolicyOperation, AlterRoleOperation, AlterUser,
AlterUserAddMfaMethodOtp, AlterUserAddRoleDelegation, AlterUserModifyMfaMethod,
AlterUserPassword, AlterUserRemoveRoleDelegation, AlterUserSetPolicy, Expr, MfaMethodKind,
Password, ResetConfig, RoleOption, SetConfigValue, Statement, UserPolicyKind,
AlterConnectorOwner, AlterPolicy, AlterPolicyOperation, AlterRoleOperation, AlterTrigger,
AlterTriggerOperation, AlterUser, AlterUserAddMfaMethodOtp, AlterUserAddRoleDelegation,
AlterUserModifyMfaMethod, AlterUserPassword, AlterUserRemoveRoleDelegation,
AlterUserSetPolicy, Expr, MfaMethodKind, Password, ResetConfig, RoleOption, SetConfigValue,
Statement, UserPolicyKind,
},
dialect::{MsSqlDialect, PostgreSqlDialect},
keywords::Keyword,
Expand Down Expand Up @@ -103,6 +104,50 @@ impl Parser<'_> {
}
}

/// Parse ALTER TRIGGER statement
/// ```sql
/// ALTER TRIGGER trigger_name ON table_name RENAME TO new_name
/// or
/// ALTER TRIGGER trigger_name ON table_name [ NO ] DEPENDS ON EXTENSION extension_name
/// ```
///
/// [PostgreSQL](https://www.postgresql.org/docs/current/sql-altertrigger.html)
pub fn parse_alter_trigger(&mut self) -> Result<AlterTrigger, ParserError> {
let name = self.parse_identifier()?;
self.expect_keyword_is(Keyword::ON)?;
let table_name = self.parse_object_name(false)?;

let operation = if self.parse_keyword(Keyword::RENAME) {
self.expect_keyword_is(Keyword::TO)?;
AlterTriggerOperation::Rename {
new_name: self.parse_identifier()?,
}
} else {
let no = self.parse_keyword(Keyword::NO);
if !self.parse_keyword(Keyword::DEPENDS) {
return self.expected_ref(
if no {
"DEPENDS after NO"
} else {
"RENAME, DEPENDS or NO DEPENDS after ALTER TRIGGER"
},
self.peek_token_ref(),
);
}
self.expect_keywords(&[Keyword::ON, Keyword::EXTENSION])?;
AlterTriggerOperation::DependsOnExtension {
no,
extension_name: self.parse_object_name(false)?,
}
};

Ok(AlterTrigger {
name,
table_name,
operation,
})
}

/// Parse an `ALTER CONNECTOR` statement
/// ```sql
/// ALTER CONNECTOR connector_name SET DCPROPERTIES(property_name=property_value, ...);
Expand Down
34 changes: 14 additions & 20 deletions src/parser/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11376,22 +11376,12 @@ impl<'a> Parser<'a> {
return self.parse_alter_text_search().map(Into::into);
}

let object_type = self.expect_one_of_keywords(&[
Keyword::VIEW,
Keyword::TYPE,
Keyword::COLLATION,
Keyword::TABLE,
Keyword::INDEX,
Keyword::FUNCTION,
Keyword::AGGREGATE,
Keyword::ROLE,
Keyword::POLICY,
Keyword::CONNECTOR,
Keyword::ICEBERG,
Keyword::SCHEMA,
Keyword::USER,
Keyword::OPERATOR,
])?;
let index = self.index;
self.advance_token();
let object_type = match &self.get_current_token().token {
Token::Word(word) => word.keyword,
_ => Keyword::NoKeyword,
};
match object_type {
Keyword::SCHEMA => {
self.prev_token();
Expand Down Expand Up @@ -11437,15 +11427,19 @@ impl<'a> Parser<'a> {
}
Keyword::ROLE => self.parse_alter_role(),
Keyword::POLICY => self.parse_alter_policy().map(Into::into),
Keyword::TRIGGER => self.parse_alter_trigger().map(Into::into),
Keyword::CONNECTOR => self.parse_alter_connector(),
Keyword::USER if self.dialect.supports_alter_user_as_alter_role() => {
self.parse_alter_role()
}
Keyword::USER => self.parse_alter_user().map(Into::into),
// unreachable because expect_one_of_keywords used above
unexpected_keyword => Err(ParserError::ParserError(
format!("Internal parser error: expected any of {{TEXT SEARCH, VIEW, TYPE, COLLATION, TABLE, INDEX, FUNCTION, AGGREGATE, ROLE, POLICY, CONNECTOR, ICEBERG, SCHEMA, USER, OPERATOR}}, got {unexpected_keyword:?}"),
)),
_ => {
self.index = index;
self.expected_ref(
"one of VIEW or TYPE or COLLATION or TABLE or INDEX or FUNCTION or AGGREGATE or ROLE or POLICY or TRIGGER or CONNECTOR or ICEBERG or SCHEMA or USER or OPERATOR",
self.peek_token_ref(),
)
}
}
}

Expand Down
Loading
Loading