Skip to content

Commit 822c8fc

Browse files
fmguerreiroLucaCappelletti94
authored andcommitted
PostgreSQL: add support for CREATE AGGREGATE
1 parent c23dc05 commit 822c8fc

6 files changed

Lines changed: 772 additions & 42 deletions

File tree

‎src/ast/ddl.rs‎

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6078,3 +6078,165 @@ impl Spanned for CreateForeignTable {
60786078
)
60796079
}
60806080
}
6081+
6082+
/// CREATE AGGREGATE statement.
6083+
/// See <https://www.postgresql.org/docs/current/sql-createaggregate.html>
6084+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6085+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6086+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6087+
pub struct CreateAggregate {
6088+
/// True if `OR REPLACE` was specified.
6089+
pub or_replace: bool,
6090+
/// The aggregate name (can be schema-qualified).
6091+
pub name: ObjectName,
6092+
/// The argument list preceding the options list.
6093+
pub args: CreateAggregateArgs,
6094+
/// The options listed inside the required parentheses after the argument
6095+
/// list (e.g. `SFUNC`, `STYPE`, `FINALFUNC`, `PARALLEL`, …).
6096+
pub options: Vec<CreateAggregateOption>,
6097+
}
6098+
6099+
impl fmt::Display for CreateAggregate {
6100+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6101+
write!(f, "CREATE")?;
6102+
if self.or_replace {
6103+
write!(f, " OR REPLACE")?;
6104+
}
6105+
write!(f, " AGGREGATE {}", self.name)?;
6106+
match &self.args {
6107+
CreateAggregateArgs::Legacy => {}
6108+
CreateAggregateArgs::Star => write!(f, " (*)")?,
6109+
CreateAggregateArgs::List(args) => write!(f, " ({})", display_comma_separated(args))?,
6110+
}
6111+
write!(f, " ({})", display_comma_separated(&self.options))
6112+
}
6113+
}
6114+
6115+
/// The argument list of a [`CreateAggregate`] statement.
6116+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6117+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6118+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6119+
pub enum CreateAggregateArgs {
6120+
/// No argument-list parentheses: the historical form that packs everything,
6121+
/// usually including a `BASETYPE` option, into a single list.
6122+
Legacy,
6123+
/// The wildcard form `(*)`, used by zero-argument aggregates such as
6124+
/// `count(*)`.
6125+
Star,
6126+
/// An explicit argument list, possibly empty: `()`, `(NUMERIC)`,
6127+
/// `(input INT, VARIADIC tail TEXT)`.
6128+
List(Vec<OperateFunctionArg>),
6129+
}
6130+
6131+
impl From<CreateAggregate> for crate::ast::Statement {
6132+
fn from(v: CreateAggregate) -> Self {
6133+
crate::ast::Statement::CreateAggregate(v)
6134+
}
6135+
}
6136+
6137+
/// A single option in a `CREATE AGGREGATE` options list.
6138+
///
6139+
/// See <https://www.postgresql.org/docs/current/sql-createaggregate.html>
6140+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6141+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6142+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6143+
pub enum CreateAggregateOption {
6144+
/// `SFUNC = state_transition_function`
6145+
StateTransitionFunction(ObjectName),
6146+
/// `STYPE = state_data_type`
6147+
StateDataType(DataType),
6148+
/// `SSPACE = state_data_size` (in bytes)
6149+
StateDataSize(u64),
6150+
/// `FINALFUNC = final_function`
6151+
FinalFunction(ObjectName),
6152+
/// `FINALFUNC_EXTRA`. Passes extra dummy arguments to the final function.
6153+
FinalFunctionExtra,
6154+
/// `FINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE }`
6155+
FinalFunctionModify(AggregateModifyKind),
6156+
/// `COMBINEFUNC = combine_function`
6157+
CombineFunction(ObjectName),
6158+
/// `SERIALFUNC = serial_function`
6159+
SerialFunction(ObjectName),
6160+
/// `DESERIALFUNC = deserial_function`
6161+
DeserialFunction(ObjectName),
6162+
/// `INITCOND = initial_condition` (a string literal)
6163+
InitialCondition(ValueWithSpan),
6164+
/// `MSFUNC = moving_state_transition_function`
6165+
MovingStateTransitionFunction(ObjectName),
6166+
/// `MINVFUNC = moving_inverse_transition_function`
6167+
MovingInverseTransitionFunction(ObjectName),
6168+
/// `MSTYPE = moving_state_data_type`
6169+
MovingStateDataType(DataType),
6170+
/// `MSSPACE = moving_state_data_size` (in bytes)
6171+
MovingStateDataSize(u64),
6172+
/// `MFINALFUNC = moving_final_function`
6173+
MovingFinalFunction(ObjectName),
6174+
/// `MFINALFUNC_EXTRA`
6175+
MovingFinalFunctionExtra,
6176+
/// `MFINALFUNC_MODIFY = { READ_ONLY | SHAREABLE | READ_WRITE }`
6177+
MovingFinalFunctionModify(AggregateModifyKind),
6178+
/// `MINITCOND = moving_initial_condition` (a string literal)
6179+
MovingInitialCondition(ValueWithSpan),
6180+
/// `SORTOP = sort_operator`
6181+
SortOperator(ObjectName),
6182+
/// `PARALLEL = { SAFE | RESTRICTED | UNSAFE }`
6183+
Parallel(FunctionParallel),
6184+
/// `HYPOTHETICAL`. Marks the aggregate as hypothetical-set.
6185+
Hypothetical,
6186+
/// `BASETYPE = base_type` (old aggregate syntax).
6187+
BaseType(DataType),
6188+
}
6189+
6190+
impl fmt::Display for CreateAggregateOption {
6191+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6192+
match self {
6193+
Self::StateTransitionFunction(name) => write!(f, "SFUNC = {name}"),
6194+
Self::StateDataType(data_type) => write!(f, "STYPE = {data_type}"),
6195+
Self::StateDataSize(size) => write!(f, "SSPACE = {size}"),
6196+
Self::FinalFunction(name) => write!(f, "FINALFUNC = {name}"),
6197+
Self::FinalFunctionExtra => write!(f, "FINALFUNC_EXTRA"),
6198+
Self::FinalFunctionModify(kind) => write!(f, "FINALFUNC_MODIFY = {kind}"),
6199+
Self::CombineFunction(name) => write!(f, "COMBINEFUNC = {name}"),
6200+
Self::SerialFunction(name) => write!(f, "SERIALFUNC = {name}"),
6201+
Self::DeserialFunction(name) => write!(f, "DESERIALFUNC = {name}"),
6202+
Self::InitialCondition(cond) => write!(f, "INITCOND = {cond}"),
6203+
Self::MovingStateTransitionFunction(name) => write!(f, "MSFUNC = {name}"),
6204+
Self::MovingInverseTransitionFunction(name) => write!(f, "MINVFUNC = {name}"),
6205+
Self::MovingStateDataType(data_type) => write!(f, "MSTYPE = {data_type}"),
6206+
Self::MovingStateDataSize(size) => write!(f, "MSSPACE = {size}"),
6207+
Self::MovingFinalFunction(name) => write!(f, "MFINALFUNC = {name}"),
6208+
Self::MovingFinalFunctionExtra => write!(f, "MFINALFUNC_EXTRA"),
6209+
Self::MovingFinalFunctionModify(kind) => write!(f, "MFINALFUNC_MODIFY = {kind}"),
6210+
Self::MovingInitialCondition(cond) => write!(f, "MINITCOND = {cond}"),
6211+
Self::SortOperator(name) => write!(f, "SORTOP = {name}"),
6212+
Self::Parallel(parallel) => write!(f, "PARALLEL = {}", parallel.as_str()),
6213+
Self::Hypothetical => write!(f, "HYPOTHETICAL"),
6214+
Self::BaseType(data_type) => write!(f, "BASETYPE = {data_type}"),
6215+
}
6216+
}
6217+
}
6218+
6219+
/// Modifier kind for `FINALFUNC_MODIFY` / `MFINALFUNC_MODIFY` in `CREATE AGGREGATE`.
6220+
///
6221+
/// See <https://www.postgresql.org/docs/current/sql-createaggregate.html>
6222+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6223+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6224+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6225+
pub enum AggregateModifyKind {
6226+
/// The final function does not modify the transition state.
6227+
ReadOnly,
6228+
/// The transition state may be shared between aggregate calls.
6229+
Shareable,
6230+
/// The final function may modify the transition state.
6231+
ReadWrite,
6232+
}
6233+
6234+
impl fmt::Display for AggregateModifyKind {
6235+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6236+
match self {
6237+
Self::ReadOnly => write!(f, "READ_ONLY"),
6238+
Self::Shareable => write!(f, "SHAREABLE"),
6239+
Self::ReadWrite => write!(f, "READ_WRITE"),
6240+
}
6241+
}
6242+
}

‎src/ast/mod.rs‎

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -62,16 +62,17 @@ pub use self::dcl::{
6262
SetConfigValue, Use,
6363
};
6464
pub use self::ddl::{
65-
Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation, AlterConnectorOwner,
66-
AlterFunction, AlterFunctionAction, AlterFunctionKind, AlterFunctionOperation,
67-
AlterIndexOperation, AlterOperator, AlterOperatorClass, AlterOperatorClassOperation,
68-
AlterOperatorFamily, AlterOperatorFamilyOperation, AlterOperatorOperation, AlterPolicy,
69-
AlterPolicyOperation, AlterSchema, AlterSchemaOperation, AlterTable, AlterTableAlgorithm,
70-
AlterTableLock, AlterTableOperation, AlterTableType, AlterTextSearch, AlterTextSearchOperation,
71-
AlterTextSearchOption, AlterType, AlterTypeAddValue, AlterTypeAddValuePosition,
72-
AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue, ClusteredBy, ColumnDef,
73-
ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy, ColumnPolicyProperty,
74-
ConstraintCharacteristics, CreateCollation, CreateCollationDefinition, CreateConnector,
65+
AggregateModifyKind, Alignment, AlterCollation, AlterCollationOperation, AlterColumnOperation,
66+
AlterConnectorOwner, AlterFunction, AlterFunctionAction, AlterFunctionKind,
67+
AlterFunctionOperation, AlterIndexOperation, AlterOperator, AlterOperatorClass,
68+
AlterOperatorClassOperation, AlterOperatorFamily, AlterOperatorFamilyOperation,
69+
AlterOperatorOperation, AlterPolicy, AlterPolicyOperation, AlterSchema, AlterSchemaOperation,
70+
AlterTable, AlterTableAlgorithm, AlterTableLock, AlterTableOperation, AlterTableType,
71+
AlterTextSearch, AlterTextSearchOperation, AlterTextSearchOption, AlterType, AlterTypeAddValue,
72+
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
73+
ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions, ColumnPolicy,
74+
ColumnPolicyProperty, ConstraintCharacteristics, CreateAggregate, CreateAggregateArgs,
75+
CreateAggregateOption, CreateCollation, CreateCollationDefinition, CreateConnector,
7576
CreateDomain, CreateExtension, CreateForeignTable, CreateFunction, CreateIndex, CreateOperator,
7677
CreateOperatorClass, CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType,
7778
CreateTable, CreateTextSearch, CreateTrigger, CreateView, Deduplicate, DeferrableInitial,
@@ -3832,6 +3833,11 @@ pub enum Statement {
38323833
/// See [PostgreSQL](https://www.postgresql.org/docs/current/textsearch-intro.html)
38333834
CreateTextSearch(CreateTextSearch),
38343835
/// ```sql
3836+
/// CREATE AGGREGATE
3837+
/// ```
3838+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createaggregate.html)
3839+
CreateAggregate(CreateAggregate),
3840+
/// ```sql
38353841
/// ALTER TABLE
38363842
/// ```
38373843
AlterTable(AlterTable),
@@ -5670,6 +5676,7 @@ impl fmt::Display for Statement {
56705676
create_operator_family.fmt(f)
56715677
}
56725678
Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5679+
Statement::CreateAggregate(create_aggregate) => create_aggregate.fmt(f),
56735680
Statement::CreateTextSearch(create_text_search) => create_text_search.fmt(f),
56745681
Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
56755682
Statement::AlterIndex { name, operation } => {
@@ -10315,16 +10322,23 @@ pub enum FunctionParallel {
1031510322
Safe,
1031610323
}
1031710324

10318-
impl fmt::Display for FunctionParallel {
10319-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10325+
impl FunctionParallel {
10326+
/// Returns the bare keyword for this parallel mode, without the `PARALLEL` prefix.
10327+
pub fn as_str(&self) -> &'static str {
1032010328
match self {
10321-
FunctionParallel::Unsafe => write!(f, "PARALLEL UNSAFE"),
10322-
FunctionParallel::Restricted => write!(f, "PARALLEL RESTRICTED"),
10323-
FunctionParallel::Safe => write!(f, "PARALLEL SAFE"),
10329+
FunctionParallel::Unsafe => "UNSAFE",
10330+
FunctionParallel::Restricted => "RESTRICTED",
10331+
FunctionParallel::Safe => "SAFE",
1032410332
}
1032510333
}
1032610334
}
1032710335

10336+
impl fmt::Display for FunctionParallel {
10337+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
10338+
write!(f, "PARALLEL {}", self.as_str())
10339+
}
10340+
}
10341+
1032810342
/// [BigQuery] Determinism specifier used in a UDF definition.
1032910343
///
1033010344
/// [BigQuery]: https://cloud.google.com/bigquery/docs/reference/standard-sql/data-definition-language#syntax_11

‎src/ast/spans.rs‎

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
use crate::{
1919
ast::{
2020
ddl::AlterSchema, query::SelectItemQualifiedWildcardKind, AlterSchemaOperation, AlterTable,
21-
ColumnOptions, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreateView,
22-
ExportData, Owner, TypedString,
21+
ColumnOptions, CreateAggregate, CreateAggregateArgs, CreateAggregateOption, CreateOperator,
22+
CreateOperatorClass, CreateOperatorFamily, CreateView, ExportData, Owner, TypedString,
2323
},
2424
tokenizer::TokenWithSpan,
2525
};
@@ -41,9 +41,9 @@ use super::{
4141
MatchRecognizePattern, Measure, Merge, MergeAction, MergeClause, MergeInsertExpr,
4242
MergeInsertKind, MergeUpdateExpr, MergeUpdateKind, NamedParenthesizedList,
4343
NamedWindowDefinition, ObjectName, ObjectNamePart, Offset, OnConflict, OnConflictAction,
44-
OnInsert, OpenStatement, OrderBy, OrderByExpr, OrderByKind, OutputClause, Parens, Partition,
45-
PartitionBoundValue, PivotValueSource, ProjectionSelect, Query, RaiseStatement,
46-
RaiseStatementValue, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
44+
OnInsert, OpenStatement, OperateFunctionArg, OrderBy, OrderByExpr, OrderByKind, OutputClause,
45+
Parens, Partition, PartitionBoundValue, PivotValueSource, ProjectionSelect, Query,
46+
RaiseStatement, RaiseStatementValue, ReferentialAction, RenameSelectItem, ReplaceSelectElement,
4747
ReplaceSelectItem, Select, SelectInto, SelectItem, SetExpr, SqlOption, Statement, Subscript,
4848
SymbolDefinition, TableAlias, TableAliasColumnDef, TableConstraint, TableFactor, TableObject,
4949
TableOptionsClustered, TableWithJoins, Update, UpdateTableFromKind, Use, Values, ViewColumnDef,
@@ -524,6 +524,7 @@ impl Spanned for Statement {
524524
Statement::Vacuum(..) => Span::empty(),
525525
Statement::AlterUser(..) => Span::empty(),
526526
Statement::Reset(..) => Span::empty(),
527+
Statement::CreateAggregate(create_aggregate) => create_aggregate.span(),
527528
}
528529
}
529530
}
@@ -2532,6 +2533,65 @@ impl Spanned for AlterTable {
25322533
}
25332534
}
25342535

2536+
impl Spanned for CreateAggregate {
2537+
fn span(&self) -> Span {
2538+
union_spans(
2539+
core::iter::once(self.name.span())
2540+
.chain(core::iter::once(self.args.span()))
2541+
.chain(self.options.iter().map(|option| option.span())),
2542+
)
2543+
}
2544+
}
2545+
2546+
impl Spanned for CreateAggregateArgs {
2547+
fn span(&self) -> Span {
2548+
match self {
2549+
CreateAggregateArgs::Legacy | CreateAggregateArgs::Star => Span::empty(),
2550+
CreateAggregateArgs::List(args) => union_spans(args.iter().map(|arg| arg.span())),
2551+
}
2552+
}
2553+
}
2554+
2555+
impl Spanned for OperateFunctionArg {
2556+
fn span(&self) -> Span {
2557+
union_spans(
2558+
self.name
2559+
.iter()
2560+
.map(|name| name.span)
2561+
.chain(self.default_expr.iter().map(|expr| expr.span())),
2562+
)
2563+
}
2564+
}
2565+
2566+
impl Spanned for CreateAggregateOption {
2567+
fn span(&self) -> Span {
2568+
match self {
2569+
CreateAggregateOption::StateTransitionFunction(name)
2570+
| CreateAggregateOption::FinalFunction(name)
2571+
| CreateAggregateOption::CombineFunction(name)
2572+
| CreateAggregateOption::SerialFunction(name)
2573+
| CreateAggregateOption::DeserialFunction(name)
2574+
| CreateAggregateOption::MovingStateTransitionFunction(name)
2575+
| CreateAggregateOption::MovingInverseTransitionFunction(name)
2576+
| CreateAggregateOption::MovingFinalFunction(name)
2577+
| CreateAggregateOption::SortOperator(name) => name.span(),
2578+
CreateAggregateOption::InitialCondition(value)
2579+
| CreateAggregateOption::MovingInitialCondition(value) => value.span,
2580+
CreateAggregateOption::StateDataType(_)
2581+
| CreateAggregateOption::StateDataSize(_)
2582+
| CreateAggregateOption::FinalFunctionExtra
2583+
| CreateAggregateOption::FinalFunctionModify(_)
2584+
| CreateAggregateOption::MovingStateDataType(_)
2585+
| CreateAggregateOption::MovingStateDataSize(_)
2586+
| CreateAggregateOption::MovingFinalFunctionExtra
2587+
| CreateAggregateOption::MovingFinalFunctionModify(_)
2588+
| CreateAggregateOption::Parallel(_)
2589+
| CreateAggregateOption::Hypothetical
2590+
| CreateAggregateOption::BaseType(_) => Span::empty(),
2591+
}
2592+
}
2593+
}
2594+
25352595
impl Spanned for CreateOperator {
25362596
fn span(&self) -> Span {
25372597
Span::empty()

0 commit comments

Comments
 (0)