Skip to content

Commit 5fd2807

Browse files
feat(postgres): add statistics DDL AST and parser support
1 parent bd7f70e commit 5fd2807

File tree

3 files changed

+470
-5
lines changed

3 files changed

+470
-5
lines changed

src/ast/mod.rs

Lines changed: 182 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2459,6 +2459,8 @@ pub enum CommentObject {
24592459
Schema,
24602460
/// A sequence.
24612461
Sequence,
2462+
/// Statistics object.
2463+
Statistics,
24622464
/// A table.
24632465
Table,
24642466
/// A type.
@@ -2483,6 +2485,7 @@ impl fmt::Display for CommentObject {
24832485
CommentObject::Role => f.write_str("ROLE"),
24842486
CommentObject::Schema => f.write_str("SCHEMA"),
24852487
CommentObject::Sequence => f.write_str("SEQUENCE"),
2488+
CommentObject::Statistics => f.write_str("STATISTICS"),
24862489
CommentObject::Table => f.write_str("TABLE"),
24872490
CommentObject::Type => f.write_str("TYPE"),
24882491
CommentObject::User => f.write_str("USER"),
@@ -3707,6 +3710,11 @@ pub enum Statement {
37073710
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createopclass.html)
37083711
CreateOperatorClass(CreateOperatorClass),
37093712
/// ```sql
3713+
/// CREATE STATISTICS
3714+
/// ```
3715+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-createstatistics.html)
3716+
CreateStatistics(CreateStatistics),
3717+
/// ```sql
37103718
/// ALTER TABLE
37113719
/// ```
37123720
AlterTable(AlterTable),
@@ -3759,6 +3767,11 @@ pub enum Statement {
37593767
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alteropclass.html)
37603768
AlterOperatorClass(AlterOperatorClass),
37613769
/// ```sql
3770+
/// ALTER STATISTICS
3771+
/// ```
3772+
/// See [PostgreSQL](https://www.postgresql.org/docs/current/sql-alterstatistics.html)
3773+
AlterStatistics(AlterStatistics),
3774+
/// ```sql
37623775
/// ALTER ROLE
37633776
/// ```
37643777
AlterRole {
@@ -5443,6 +5456,7 @@ impl fmt::Display for Statement {
54435456
create_operator_family.fmt(f)
54445457
}
54455458
Statement::CreateOperatorClass(create_operator_class) => create_operator_class.fmt(f),
5459+
Statement::CreateStatistics(create_statistics) => create_statistics.fmt(f),
54465460
Statement::AlterTable(alter_table) => write!(f, "{alter_table}"),
54475461
Statement::AlterIndex { name, operation } => {
54485462
write!(f, "ALTER INDEX {name} {operation}")
@@ -5472,6 +5486,7 @@ impl fmt::Display for Statement {
54725486
Statement::AlterOperatorClass(alter_operator_class) => {
54735487
write!(f, "{alter_operator_class}")
54745488
}
5489+
Statement::AlterStatistics(alter_statistics) => write!(f, "{alter_statistics}"),
54755490
Statement::AlterRole { name, operation } => {
54765491
write!(f, "ALTER ROLE {name} {operation}")
54775492
}
@@ -8246,6 +8261,8 @@ pub enum ObjectType {
82468261
Role,
82478262
/// A sequence.
82488263
Sequence,
8264+
/// Statistics object.
8265+
Statistics,
82498266
/// A stage.
82508267
Stage,
82518268
/// A type definition.
@@ -8267,6 +8284,7 @@ impl fmt::Display for ObjectType {
82678284
ObjectType::Database => "DATABASE",
82688285
ObjectType::Role => "ROLE",
82698286
ObjectType::Sequence => "SEQUENCE",
8287+
ObjectType::Statistics => "STATISTICS",
82708288
ObjectType::Stage => "STAGE",
82718289
ObjectType::Type => "TYPE",
82728290
ObjectType::User => "USER",
@@ -8697,6 +8715,158 @@ impl fmt::Display for SecretOption {
86978715
}
86988716
}
86998717

8718+
/// Statistics kinds supported by PostgreSQL `CREATE STATISTICS`.
8719+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8720+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8721+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8722+
pub enum StatisticsType {
8723+
/// `ndistinct` kind.
8724+
Ndistinct,
8725+
/// `dependencies` kind.
8726+
Dependencies,
8727+
/// `mcv` kind.
8728+
Mcv,
8729+
/// Any other statistics kind identifier accepted by PostgreSQL grammar.
8730+
Other(Ident),
8731+
}
8732+
8733+
impl fmt::Display for StatisticsType {
8734+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8735+
match self {
8736+
StatisticsType::Ndistinct => write!(f, "NDISTINCT"),
8737+
StatisticsType::Dependencies => write!(f, "DEPENDENCIES"),
8738+
StatisticsType::Mcv => write!(f, "MCV"),
8739+
StatisticsType::Other(ident) => write!(f, "{ident}"),
8740+
}
8741+
}
8742+
}
8743+
8744+
/// A `CREATE STATISTICS` statement.
8745+
///
8746+
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createstatistics.html)
8747+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8748+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8749+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8750+
pub struct CreateStatistics {
8751+
/// Whether `IF NOT EXISTS` was specified.
8752+
pub if_not_exists: bool,
8753+
/// Optional name of the statistics object.
8754+
pub name: Option<ObjectName>,
8755+
/// Optional list of statistics kinds.
8756+
pub statistics_types: Vec<StatisticsType>,
8757+
/// Target expressions listed after `ON`.
8758+
pub columns: Vec<Expr>,
8759+
/// Source relation list after `FROM`.
8760+
pub from: Vec<TableWithJoins>,
8761+
}
8762+
8763+
impl fmt::Display for CreateStatistics {
8764+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8765+
write!(f, "CREATE STATISTICS")?;
8766+
if self.if_not_exists {
8767+
write!(f, " IF NOT EXISTS")?;
8768+
}
8769+
if let Some(name) = &self.name {
8770+
write!(f, " {name}")?;
8771+
}
8772+
if !self.statistics_types.is_empty() {
8773+
write!(f, " ({})", display_comma_separated(&self.statistics_types))?;
8774+
}
8775+
write!(
8776+
f,
8777+
" ON {} FROM {}",
8778+
display_comma_separated(&self.columns),
8779+
display_comma_separated(&self.from)
8780+
)
8781+
}
8782+
}
8783+
8784+
/// Target value for `ALTER STATISTICS ... SET STATISTICS`.
8785+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8786+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8787+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8788+
pub enum AlterStatisticsTarget {
8789+
/// Numeric target value.
8790+
Value(i64),
8791+
/// `DEFAULT` target.
8792+
Default,
8793+
}
8794+
8795+
impl fmt::Display for AlterStatisticsTarget {
8796+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8797+
match self {
8798+
AlterStatisticsTarget::Value(value) => write!(f, "{value}"),
8799+
AlterStatisticsTarget::Default => write!(f, "DEFAULT"),
8800+
}
8801+
}
8802+
}
8803+
8804+
/// Operation variants for `ALTER STATISTICS`.
8805+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8806+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8807+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8808+
pub enum AlterStatisticsOperation {
8809+
/// `RENAME TO new_name`.
8810+
RenameTo {
8811+
/// New name of the statistics object.
8812+
new_name: ObjectName,
8813+
},
8814+
/// `OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }`.
8815+
OwnerTo(Owner),
8816+
/// `SET SCHEMA new_schema`.
8817+
SetSchema {
8818+
/// New schema for the statistics object.
8819+
schema_name: ObjectName,
8820+
},
8821+
/// `SET STATISTICS { integer | DEFAULT }`.
8822+
SetStatistics {
8823+
/// New statistics target value.
8824+
target: AlterStatisticsTarget,
8825+
},
8826+
}
8827+
8828+
impl fmt::Display for AlterStatisticsOperation {
8829+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8830+
match self {
8831+
AlterStatisticsOperation::RenameTo { new_name } => write!(f, "RENAME TO {new_name}"),
8832+
AlterStatisticsOperation::OwnerTo(owner) => write!(f, "OWNER TO {owner}"),
8833+
AlterStatisticsOperation::SetSchema { schema_name } => {
8834+
write!(f, "SET SCHEMA {schema_name}")
8835+
}
8836+
AlterStatisticsOperation::SetStatistics { target } => {
8837+
write!(f, "SET STATISTICS {target}")
8838+
}
8839+
}
8840+
}
8841+
}
8842+
8843+
/// An `ALTER STATISTICS` statement.
8844+
///
8845+
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-alterstatistics.html)
8846+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
8847+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
8848+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
8849+
pub struct AlterStatistics {
8850+
/// Whether `IF EXISTS` was specified.
8851+
pub if_exists: bool,
8852+
/// Name of the statistics object.
8853+
pub name: ObjectName,
8854+
/// Operation to apply.
8855+
pub operation: AlterStatisticsOperation,
8856+
}
8857+
8858+
impl fmt::Display for AlterStatistics {
8859+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
8860+
write!(
8861+
f,
8862+
"ALTER STATISTICS {if_exists}{name} {operation}",
8863+
if_exists = if self.if_exists { "IF EXISTS " } else { "" },
8864+
name = self.name,
8865+
operation = self.operation
8866+
)
8867+
}
8868+
}
8869+
87008870
/// A `CREATE SERVER` statement.
87018871
///
87028872
/// [PostgreSQL Documentation](https://www.postgresql.org/docs/current/sql-createserver.html)
@@ -11912,6 +12082,12 @@ impl From<CreateOperatorClass> for Statement {
1191212082
}
1191312083
}
1191412084

12085+
impl From<CreateStatistics> for Statement {
12086+
fn from(c: CreateStatistics) -> Self {
12087+
Self::CreateStatistics(c)
12088+
}
12089+
}
12090+
1191512091
impl From<AlterSchema> for Statement {
1191612092
fn from(a: AlterSchema) -> Self {
1191712093
Self::AlterSchema(a)
@@ -11942,6 +12118,12 @@ impl From<AlterOperatorClass> for Statement {
1194212118
}
1194312119
}
1194412120

12121+
impl From<AlterStatistics> for Statement {
12122+
fn from(a: AlterStatistics) -> Self {
12123+
Self::AlterStatistics(a)
12124+
}
12125+
}
12126+
1194512127
impl From<Merge> for Statement {
1194612128
fn from(m: Merge) -> Self {
1194712129
Self::Merge(m)

src/ast/spans.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ impl Spanned for Statement {
388388
create_operator_family.span()
389389
}
390390
Statement::CreateOperatorClass(create_operator_class) => create_operator_class.span(),
391+
Statement::CreateStatistics(..) => Span::empty(),
391392
Statement::AlterTable(alter_table) => alter_table.span(),
392393
Statement::AlterIndex { name, operation } => name.span().union(&operation.span()),
393394
Statement::AlterView {
@@ -406,6 +407,7 @@ impl Spanned for Statement {
406407
Statement::AlterOperator { .. } => Span::empty(),
407408
Statement::AlterOperatorFamily { .. } => Span::empty(),
408409
Statement::AlterOperatorClass { .. } => Span::empty(),
410+
Statement::AlterStatistics(..) => Span::empty(),
409411
Statement::AlterRole { .. } => Span::empty(),
410412
Statement::AlterSession { .. } => Span::empty(),
411413
Statement::AttachDatabase { .. } => Span::empty(),

0 commit comments

Comments
 (0)