Skip to content

Commit 326f111

Browse files
Added support for ALTER OPERATOR syntax (#2114)
1 parent effaac5 commit 326f111

File tree

8 files changed

+585
-142
lines changed

8 files changed

+585
-142
lines changed

src/ast/ddl.rs

Lines changed: 103 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -995,6 +995,103 @@ impl fmt::Display for AlterTypeOperation {
995995
}
996996
}
997997

998+
/// `ALTER OPERATOR` statement
999+
/// See <https://www.postgresql.org/docs/current/sql-alteroperator.html>
1000+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1001+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1002+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1003+
pub struct AlterOperator {
1004+
/// Operator name (can be schema-qualified)
1005+
pub name: ObjectName,
1006+
/// Left operand type (`None` if no left operand)
1007+
pub left_type: Option<DataType>,
1008+
/// Right operand type
1009+
pub right_type: DataType,
1010+
/// The operation to perform
1011+
pub operation: AlterOperatorOperation,
1012+
}
1013+
1014+
/// An [AlterOperator] operation
1015+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1016+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1017+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1018+
pub enum AlterOperatorOperation {
1019+
/// `OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }`
1020+
OwnerTo(Owner),
1021+
/// `SET SCHEMA new_schema`
1022+
SetSchema { schema_name: ObjectName },
1023+
/// `SET ( options )`
1024+
Set {
1025+
/// List of operator options to set
1026+
options: Vec<OperatorOption>,
1027+
},
1028+
}
1029+
1030+
/// Option for `ALTER OPERATOR SET` operation
1031+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
1032+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
1033+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
1034+
pub enum OperatorOption {
1035+
/// `RESTRICT = { res_proc | NONE }`
1036+
Restrict(Option<ObjectName>),
1037+
/// `JOIN = { join_proc | NONE }`
1038+
Join(Option<ObjectName>),
1039+
/// `COMMUTATOR = com_op`
1040+
Commutator(ObjectName),
1041+
/// `NEGATOR = neg_op`
1042+
Negator(ObjectName),
1043+
/// `HASHES`
1044+
Hashes,
1045+
/// `MERGES`
1046+
Merges,
1047+
}
1048+
1049+
impl fmt::Display for AlterOperator {
1050+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1051+
write!(f, "ALTER OPERATOR {} (", self.name)?;
1052+
if let Some(left_type) = &self.left_type {
1053+
write!(f, "{}", left_type)?;
1054+
} else {
1055+
write!(f, "NONE")?;
1056+
}
1057+
write!(f, ", {}) {}", self.right_type, self.operation)
1058+
}
1059+
}
1060+
1061+
impl fmt::Display for AlterOperatorOperation {
1062+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1063+
match self {
1064+
Self::OwnerTo(owner) => write!(f, "OWNER TO {}", owner),
1065+
Self::SetSchema { schema_name } => write!(f, "SET SCHEMA {}", schema_name),
1066+
Self::Set { options } => {
1067+
write!(f, "SET (")?;
1068+
for (i, option) in options.iter().enumerate() {
1069+
if i > 0 {
1070+
write!(f, ", ")?;
1071+
}
1072+
write!(f, "{}", option)?;
1073+
}
1074+
write!(f, ")")
1075+
}
1076+
}
1077+
}
1078+
}
1079+
1080+
impl fmt::Display for OperatorOption {
1081+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1082+
match self {
1083+
Self::Restrict(Some(proc_name)) => write!(f, "RESTRICT = {}", proc_name),
1084+
Self::Restrict(None) => write!(f, "RESTRICT = NONE"),
1085+
Self::Join(Some(proc_name)) => write!(f, "JOIN = {}", proc_name),
1086+
Self::Join(None) => write!(f, "JOIN = NONE"),
1087+
Self::Commutator(op_name) => write!(f, "COMMUTATOR = {}", op_name),
1088+
Self::Negator(op_name) => write!(f, "NEGATOR = {}", op_name),
1089+
Self::Hashes => write!(f, "HASHES"),
1090+
Self::Merges => write!(f, "MERGES"),
1091+
}
1092+
}
1093+
}
1094+
9981095
/// An `ALTER COLUMN` (`Statement::AlterTable`) operation
9991096
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
10001097
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@@ -1790,7 +1887,7 @@ impl fmt::Display for ColumnOption {
17901887
GeneratedAs::Always => "ALWAYS",
17911888
GeneratedAs::ByDefault => "BY DEFAULT",
17921889
// ExpStored goes with an expression, handled above
1793-
GeneratedAs::ExpStored => unreachable!(),
1890+
GeneratedAs::ExpStored => "",
17941891
};
17951892
write!(f, "GENERATED {when} AS IDENTITY")?;
17961893
if sequence_options.is_some() {
@@ -3981,18 +4078,8 @@ pub struct CreateOperator {
39814078
pub left_arg: Option<DataType>,
39824079
/// RIGHTARG parameter (right operand type)
39834080
pub right_arg: Option<DataType>,
3984-
/// COMMUTATOR parameter (commutator operator)
3985-
pub commutator: Option<ObjectName>,
3986-
/// NEGATOR parameter (negator operator)
3987-
pub negator: Option<ObjectName>,
3988-
/// RESTRICT parameter (restriction selectivity function)
3989-
pub restrict: Option<ObjectName>,
3990-
/// JOIN parameter (join selectivity function)
3991-
pub join: Option<ObjectName>,
3992-
/// HASHES flag
3993-
pub hashes: bool,
3994-
/// MERGES flag
3995-
pub merges: bool,
4081+
/// Operator options (COMMUTATOR, NEGATOR, RESTRICT, JOIN, HASHES, MERGES)
4082+
pub options: Vec<OperatorOption>,
39964083
}
39974084

39984085
/// CREATE OPERATOR FAMILY statement
@@ -4044,23 +4131,9 @@ impl fmt::Display for CreateOperator {
40444131
if let Some(right_arg) = &self.right_arg {
40454132
params.push(format!("RIGHTARG = {}", right_arg));
40464133
}
4047-
if let Some(commutator) = &self.commutator {
4048-
params.push(format!("COMMUTATOR = {}", commutator));
4049-
}
4050-
if let Some(negator) = &self.negator {
4051-
params.push(format!("NEGATOR = {}", negator));
4052-
}
4053-
if let Some(restrict) = &self.restrict {
4054-
params.push(format!("RESTRICT = {}", restrict));
4055-
}
4056-
if let Some(join) = &self.join {
4057-
params.push(format!("JOIN = {}", join));
4058-
}
4059-
if self.hashes {
4060-
params.push("HASHES".to_string());
4061-
}
4062-
if self.merges {
4063-
params.push("MERGES".to_string());
4134+
4135+
for option in &self.options {
4136+
params.push(option.to_string());
40644137
}
40654138

40664139
write!(f, "{}", params.join(", "))?;

src/ast/helpers/stmt_data_loading.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -99,15 +99,15 @@ impl fmt::Display for StageParamsObject {
9999

100100
impl fmt::Display for StageLoadSelectItem {
101101
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102-
if self.alias.is_some() {
103-
write!(f, "{}.", self.alias.as_ref().unwrap())?;
102+
if let Some(alias) = &self.alias {
103+
write!(f, "{alias}.")?;
104104
}
105105
write!(f, "${}", self.file_col_num)?;
106-
if self.element.is_some() {
107-
write!(f, ":{}", self.element.as_ref().unwrap())?;
106+
if let Some(element) = &self.element {
107+
write!(f, ":{element}")?;
108108
}
109-
if self.item_as.is_some() {
110-
write!(f, " AS {}", self.item_as.as_ref().unwrap())?;
109+
if let Some(item_as) = &self.item_as {
110+
write!(f, " AS {item_as}")?;
111111
}
112112
Ok(())
113113
}

src/ast/mod.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -59,23 +59,23 @@ pub use self::dcl::{
5959
AlterRoleOperation, CreateRole, ResetConfig, RoleOption, SecondaryRoles, SetConfigValue, Use,
6060
};
6161
pub use self::ddl::{
62-
Alignment, AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation,
63-
AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
64-
AlterTableLock, AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue,
65-
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
66-
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
67-
ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain,
62+
Alignment, AlterColumnOperation, AlterConnectorOwner, AlterIndexOperation, AlterOperator,
63+
AlterOperatorOperation, AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable,
64+
AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterTableType, AlterType,
65+
AlterTypeAddValue, AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename,
66+
AlterTypeRenameValue, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
67+
ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateConnector, CreateDomain,
6868
CreateExtension, CreateFunction, CreateIndex, CreateOperator, CreateOperatorClass,
6969
CreateOperatorFamily, CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial,
7070
DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
7171
DropOperatorSignature, DropTrigger, GeneratedAs, GeneratedExpressionMode, IdentityParameters,
7272
IdentityProperty, IdentityPropertyFormatKind, IdentityPropertyKind, IdentityPropertyOrder,
7373
IndexColumn, IndexOption, IndexType, KeyOrIndexDisplay, Msck, NullsDistinctOption,
74-
OperatorArgTypes, OperatorClassItem, OperatorPurpose, Owner, Partition, ProcedureParam,
75-
ReferentialAction, RenameTableNameKind, ReplicaIdentity, TagsColumnOption, TriggerObjectKind,
76-
Truncate, UserDefinedTypeCompositeAttributeDef, UserDefinedTypeInternalLength,
77-
UserDefinedTypeRangeOption, UserDefinedTypeRepresentation, UserDefinedTypeSqlDefinitionOption,
78-
UserDefinedTypeStorage, ViewColumnDef,
74+
OperatorArgTypes, OperatorClassItem, OperatorOption, OperatorPurpose, Owner, Partition,
75+
ProcedureParam, ReferentialAction, RenameTableNameKind, ReplicaIdentity, TagsColumnOption,
76+
TriggerObjectKind, Truncate, UserDefinedTypeCompositeAttributeDef,
77+
UserDefinedTypeInternalLength, UserDefinedTypeRangeOption, UserDefinedTypeRepresentation,
78+
UserDefinedTypeSqlDefinitionOption, UserDefinedTypeStorage, ViewColumnDef,
7979
};
8080
pub use self::dml::{Delete, Insert, Update};
8181
pub use self::operator::{BinaryOperator, UnaryOperator};
@@ -3396,6 +3396,11 @@ pub enum Statement {
33963396
/// ```
33973397
AlterType(AlterType),
33983398
/// ```sql
3399+
/// ALTER OPERATOR
3400+
/// ```
3401+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteroperator.html)
3402+
AlterOperator(AlterOperator),
3403+
/// ```sql
33993404
/// ALTER ROLE
34003405
/// ```
34013406
AlterRole {
@@ -4971,6 +4976,7 @@ impl fmt::Display for Statement {
49714976
Statement::AlterType(AlterType { name, operation }) => {
49724977
write!(f, "ALTER TYPE {name} {operation}")
49734978
}
4979+
Statement::AlterOperator(alter_operator) => write!(f, "{alter_operator}"),
49744980
Statement::AlterRole { name, operation } => {
49754981
write!(f, "ALTER ROLE {name} {operation}")
49764982
}
@@ -9814,8 +9820,8 @@ impl fmt::Display for ShowCharset {
98149820
} else {
98159821
write!(f, " CHARACTER SET")?;
98169822
}
9817-
if self.filter.is_some() {
9818-
write!(f, " {}", self.filter.as_ref().unwrap())?;
9823+
if let Some(filter) = &self.filter {
9824+
write!(f, " {filter}")?;
98199825
}
98209826
Ok(())
98219827
}

src/ast/spans.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,7 @@ impl Spanned for Values {
252252
/// - [Statement::CreateSecret]
253253
/// - [Statement::CreateRole]
254254
/// - [Statement::AlterType]
255+
/// - [Statement::AlterOperator]
255256
/// - [Statement::AlterRole]
256257
/// - [Statement::AttachDatabase]
257258
/// - [Statement::AttachDuckDBDatabase]
@@ -401,6 +402,7 @@ impl Spanned for Statement {
401402
),
402403
// These statements need to be implemented
403404
Statement::AlterType { .. } => Span::empty(),
405+
Statement::AlterOperator { .. } => Span::empty(),
404406
Statement::AlterRole { .. } => Span::empty(),
405407
Statement::AlterSession { .. } => Span::empty(),
406408
Statement::AttachDatabase { .. } => Span::empty(),

src/keywords.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,15 @@ macro_rules! define_keywords {
6767
pub const ALL_KEYWORDS: &[&str] = &[
6868
$($ident),*
6969
];
70+
71+
impl core::fmt::Display for Keyword {
72+
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
73+
match self {
74+
Keyword::NoKeyword => write!(f, "NoKeyword"),
75+
$(Keyword::$ident => write!(f, "{}", $ident),)*
76+
}
77+
}
78+
}
7079
};
7180
}
7281

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
// Splitting complex nodes (expressions, statements, types) into separate types
154154
// would bloat the API and hide intent. Extra memory is a worthwhile tradeoff.
155155
#![allow(clippy::large_enum_variant)]
156+
#![forbid(clippy::unreachable)]
156157

157158
// Allow proc-macros to find this crate
158159
extern crate self as sqlparser;

0 commit comments

Comments
 (0)