Skip to content

Commit 6774b8a

Browse files
committed
feat(ast): add CreateAggregate type
Add Statement::CreateAggregate, CreateAggregate struct, CreateAggregateOption enum, and AggregateModifyKind enum to represent PostgreSQL CREATE AGGREGATE DDL. Options are stored as a typed enum covering all documented parameters (SFUNC, STYPE, FINALFUNC, PARALLEL, moving-aggregate variants, etc.).
1 parent a736c67 commit 6774b8a

2 files changed

Lines changed: 164 additions & 4 deletions

File tree

src/ast/ddl.rs

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5757,3 +5757,156 @@ impl From<AlterPolicy> for crate::ast::Statement {
57575757
crate::ast::Statement::AlterPolicy(v)
57585758
}
57595759
}
5760+
5761+
/// CREATE AGGREGATE statement.
5762+
/// See <https://www.postgresql.org/docs/current/sql-createaggregate.html>
5763+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5764+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5765+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5766+
pub struct CreateAggregate {
5767+
/// True if `OR REPLACE` was specified.
5768+
pub or_replace: bool,
5769+
/// The aggregate name (can be schema-qualified).
5770+
pub name: ObjectName,
5771+
/// Input argument types. Empty for zero-argument aggregates.
5772+
pub args: Vec<DataType>,
5773+
/// The options listed inside the required parentheses after the argument
5774+
/// list (e.g. `SFUNC`, `STYPE`, `FINALFUNC`, `PARALLEL`, …).
5775+
pub options: Vec<CreateAggregateOption>,
5776+
}
5777+
5778+
impl fmt::Display for CreateAggregate {
5779+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5780+
write!(f, "CREATE")?;
5781+
if self.or_replace {
5782+
write!(f, " OR REPLACE")?;
5783+
}
5784+
write!(f, " AGGREGATE {}", self.name)?;
5785+
write!(f, " ({})", display_comma_separated(&self.args))?;
5786+
write!(f, " (")?;
5787+
for (i, option) in self.options.iter().enumerate() {
5788+
if i > 0 {
5789+
write!(f, ", ")?;
5790+
}
5791+
write!(f, "{option}")?;
5792+
}
5793+
write!(f, ")")
5794+
}
5795+
}
5796+
5797+
impl From<CreateAggregate> for crate::ast::Statement {
5798+
fn from(v: CreateAggregate) -> Self {
5799+
crate::ast::Statement::CreateAggregate(v)
5800+
}
5801+
}
5802+
5803+
/// A single option in a `CREATE AGGREGATE` options list.
5804+
///
5805+
/// See <https://www.postgresql.org/docs/current/sql-createaggregate.html>
5806+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5807+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5808+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5809+
pub enum CreateAggregateOption {
5810+
/// `SFUNC = state_transition_function`
5811+
Sfunc(ObjectName),
5812+
/// `STYPE = state_data_type`
5813+
Stype(DataType),
5814+
/// `SSPACE = state_data_size` (in bytes)
5815+
Sspace(u64),
5816+
/// `FINALFUNC = final_function`
5817+
Finalfunc(ObjectName),
5818+
/// `FINALFUNC_EXTRA` — pass extra dummy arguments to the final function.
5819+
FinalfuncExtra,
5820+
/// `FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE }`
5821+
FinalfuncModify(AggregateModifyKind),
5822+
/// `COMBINEFUNC = combine_function`
5823+
Combinefunc(ObjectName),
5824+
/// `SERIALFUNC = serial_function`
5825+
Serialfunc(ObjectName),
5826+
/// `DESERIALFUNC = deserial_function`
5827+
Deserialfunc(ObjectName),
5828+
/// `INITCOND = initial_condition` (a string literal)
5829+
Initcond(Value),
5830+
/// `MSFUNC = moving_state_transition_function`
5831+
Msfunc(ObjectName),
5832+
/// `MINVFUNC = moving_inverse_transition_function`
5833+
Minvfunc(ObjectName),
5834+
/// `MSTYPE = moving_state_data_type`
5835+
Mstype(DataType),
5836+
/// `MSSPACE = moving_state_data_size` (in bytes)
5837+
Msspace(u64),
5838+
/// `MFINALFUNC = moving_final_function`
5839+
Mfinalfunc(ObjectName),
5840+
/// `MFINALFUNC_EXTRA`
5841+
MfinalfuncExtra,
5842+
/// `MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE }`
5843+
MfinalfuncModify(AggregateModifyKind),
5844+
/// `MINITCOND = moving_initial_condition` (a string literal)
5845+
Minitcond(Value),
5846+
/// `SORTOP = sort_operator`
5847+
Sortop(ObjectName),
5848+
/// `PARALLEL = { SAFE | RESTRICTED | UNSAFE }`
5849+
Parallel(FunctionParallel),
5850+
/// `HYPOTHETICAL` — marks the aggregate as hypothetical-set.
5851+
Hypothetical,
5852+
}
5853+
5854+
impl fmt::Display for CreateAggregateOption {
5855+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5856+
match self {
5857+
Self::Sfunc(name) => write!(f, "SFUNC = {name}"),
5858+
Self::Stype(data_type) => write!(f, "STYPE = {data_type}"),
5859+
Self::Sspace(size) => write!(f, "SSPACE = {size}"),
5860+
Self::Finalfunc(name) => write!(f, "FINALFUNC = {name}"),
5861+
Self::FinalfuncExtra => write!(f, "FINALFUNC_EXTRA"),
5862+
Self::FinalfuncModify(kind) => write!(f, "FINALFUNC_MODIFY = {kind}"),
5863+
Self::Combinefunc(name) => write!(f, "COMBINEFUNC = {name}"),
5864+
Self::Serialfunc(name) => write!(f, "SERIALFUNC = {name}"),
5865+
Self::Deserialfunc(name) => write!(f, "DESERIALFUNC = {name}"),
5866+
Self::Initcond(cond) => write!(f, "INITCOND = {cond}"),
5867+
Self::Msfunc(name) => write!(f, "MSFUNC = {name}"),
5868+
Self::Minvfunc(name) => write!(f, "MINVFUNC = {name}"),
5869+
Self::Mstype(data_type) => write!(f, "MSTYPE = {data_type}"),
5870+
Self::Msspace(size) => write!(f, "MSSPACE = {size}"),
5871+
Self::Mfinalfunc(name) => write!(f, "MFINALFUNC = {name}"),
5872+
Self::MfinalfuncExtra => write!(f, "MFINALFUNC_EXTRA"),
5873+
Self::MfinalfuncModify(kind) => write!(f, "MFINALFUNC_MODIFY = {kind}"),
5874+
Self::Minitcond(cond) => write!(f, "MINITCOND = {cond}"),
5875+
Self::Sortop(name) => write!(f, "SORTOP = {name}"),
5876+
Self::Parallel(parallel) => {
5877+
let kind = match parallel {
5878+
FunctionParallel::Safe => "SAFE",
5879+
FunctionParallel::Restricted => "RESTRICTED",
5880+
FunctionParallel::Unsafe => "UNSAFE",
5881+
};
5882+
write!(f, "PARALLEL = {kind}")
5883+
}
5884+
Self::Hypothetical => write!(f, "HYPOTHETICAL"),
5885+
}
5886+
}
5887+
}
5888+
5889+
/// Modifier kind for `FINALFUNC_MODIFY` / `MFINALFUNC_MODIFY` in `CREATE AGGREGATE`.
5890+
///
5891+
/// See <https://www.postgresql.org/docs/current/sql-createaggregate.html>
5892+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5893+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
5894+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
5895+
pub enum AggregateModifyKind {
5896+
/// The final function does not modify the transition state.
5897+
ReadOnly,
5898+
/// The transition state may be shared between aggregate calls.
5899+
Shareable,
5900+
/// The final function may modify the transition state.
5901+
ReadWrite,
5902+
}
5903+
5904+
impl fmt::Display for AggregateModifyKind {
5905+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5906+
match self {
5907+
Self::ReadOnly => write!(f, "READ_ONLY"),
5908+
Self::Shareable => write!(f, "SHAREABLE"),
5909+
Self::ReadWrite => write!(f, "READ_WRITE"),
5910+
}
5911+
}
5912+
}

src/ast/mod.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,11 @@ pub use self::ddl::{
6767
AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
6868
AlterTableLock, AlterTableOperation, AlterTableType, AlterType, AlterTypeAddValue,
6969
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
70-
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
71-
ColumnPolicyProperty, ConstraintCharacteristics, CreateCollation, CreateCollationDefinition,
72-
CreateConnector, CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator,
73-
CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
70+
AggregateModifyKind, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
71+
ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateAggregate,
72+
CreateAggregateOption, CreateCollation, CreateCollationDefinition, CreateConnector,
73+
CreateDomain, CreateExtension, CreateFunction, CreateIndex, CreateOperator, CreateOperatorClass,
74+
CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
7475
CreateTable, CreateTrigger, CreateView, Deduplicate, DeferrableInitial, DistStyle,
7576
DropBehavior, DropExtension, DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily,
7677
DropOperatorSignature, DropPolicy, DropTrigger, ForValues, FunctionReturnType, GeneratedAs,
@@ -3724,6 +3725,11 @@ pub enum Statement {
37243725
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
37253726
CreateOperatorClass(CreateOperatorClass),
37263727
/// ```sql
3728+
/// CREATE AGGREGATE
3729+
/// ```
3730+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createaggregate.html)
3731+
CreateAggregate(CreateAggregate),
3732+
/// ```sql
37273733
/// ALTER TABLE
37283734
/// ```
37293735
AlterTable(AlterTable),
@@ -5511,6 +5517,7 @@ impl fmt::Display for Statement {
55115517
create_operator_family.fmt(f)
55125518
}
55135519
Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5520+
Statement::CreateAggregate(create_aggregate) => create_aggregate.fmt(f),
55145521
Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
55155522
Statement::AlterIndex { name, operation } => {
55165523
write!(f, "ALTER INDEX {name} {operation}")

0 commit comments

Comments
 (0)