Skip to content

Commit 1c766ca

Browse files
authored
Merge pull request #15 from fmguerreiro/feat/catalog-extended
feat: parse CREATE STATISTICS, CREATE ACCESS METHOD, CREATE EVENT TRIGGER, CREATE TRANSFORM
2 parents 2b1ec01 + 40d87f8 commit 1c766ca

6 files changed

Lines changed: 563 additions & 3 deletions

File tree

src/ast/ddl.rs

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6513,6 +6513,28 @@ impl From<CreateSubscription> for crate::ast::Statement {
65136513
}
65146514
}
65156515

6516+
/// A kind of extended statistics collected by `CREATE STATISTICS`.
6517+
///
6518+
/// Note: this is a PostgreSQL-specific concept.
6519+
/// <https://www.postgresql.org/docs/current/sql-createstatistics.html>
6520+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6521+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6522+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6523+
pub enum StatisticsKind {
6524+
/// `ndistinct` — n-distinct statistics
6525+
NDistinct,
6526+
/// `dependencies` — functional dependency statistics
6527+
Dependencies,
6528+
/// `mcv` — most-common-values statistics
6529+
Mcv,
6530+
}
6531+
6532+
impl fmt::Display for StatisticsKind {
6533+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6534+
match self {
6535+
StatisticsKind::NDistinct => write!(f, "ndistinct"),
6536+
StatisticsKind::Dependencies => write!(f, "dependencies"),
6537+
StatisticsKind::Mcv => write!(f, "mcv"),
65166538
/// The object kind targeted by a `SECURITY LABEL` statement.
65176539
///
65186540
/// See <https://www.postgresql.org/docs/current/sql-securitylabel.html>
@@ -6562,6 +6584,38 @@ impl fmt::Display for SecurityLabelObjectKind {
65626584
}
65636585
}
65646586

6587+
/// A `CREATE STATISTICS` statement.
6588+
///
6589+
/// Note: this is a PostgreSQL-specific statement.
6590+
/// <https://www.postgresql.org/docs/current/sql-createstatistics.html>
6591+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6592+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6593+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6594+
pub struct CreateStatistics {
6595+
/// Optional `IF NOT EXISTS` clause.
6596+
pub if_not_exists: bool,
6597+
/// The statistics object name, e.g. `public.s`.
6598+
pub name: ObjectName,
6599+
/// Optional `(ndistinct, dependencies, mcv)` kind list.
6600+
pub kinds: Vec<StatisticsKind>,
6601+
/// The expressions (columns or arbitrary expressions) to collect statistics on.
6602+
pub on: Vec<Expr>,
6603+
/// The table to collect statistics from.
6604+
pub from: ObjectName,
6605+
}
6606+
6607+
impl fmt::Display for CreateStatistics {
6608+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6609+
write!(f, "CREATE STATISTICS")?;
6610+
if self.if_not_exists {
6611+
write!(f, " IF NOT EXISTS")?;
6612+
}
6613+
write!(f, " {}", self.name)?;
6614+
if !self.kinds.is_empty() {
6615+
write!(f, " ({})", display_comma_separated(&self.kinds))?;
6616+
}
6617+
write!(f, " ON {}", display_comma_separated(&self.on))?;
6618+
write!(f, " FROM {}", self.from)?;
65656619
/// A `SECURITY LABEL` statement.
65666620
///
65676621
/// Note: this is a PostgreSQL-specific statement.
@@ -6668,6 +6722,130 @@ impl fmt::Display for CreateUserMapping {
66686722
}
66696723
}
66706724

6725+
impl From<CreateStatistics> for crate::ast::Statement {
6726+
fn from(v: CreateStatistics) -> Self {
6727+
crate::ast::Statement::CreateStatistics(v)
6728+
}
6729+
}
6730+
6731+
/// The type of access method in `CREATE ACCESS METHOD`.
6732+
///
6733+
/// Note: this is a PostgreSQL-specific concept.
6734+
/// <https://www.postgresql.org/docs/current/sql-create-access-method.html>
6735+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6736+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6737+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6738+
pub enum AccessMethodType {
6739+
/// `INDEX` — an index access method
6740+
Index,
6741+
/// `TABLE` — a table access method
6742+
Table,
6743+
}
6744+
6745+
impl fmt::Display for AccessMethodType {
6746+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6747+
match self {
6748+
AccessMethodType::Index => write!(f, "INDEX"),
6749+
AccessMethodType::Table => write!(f, "TABLE"),
6750+
}
6751+
}
6752+
}
6753+
6754+
/// A `CREATE ACCESS METHOD` statement.
6755+
///
6756+
/// Note: this is a PostgreSQL-specific statement.
6757+
/// <https://www.postgresql.org/docs/current/sql-create-access-method.html>
6758+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6759+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6760+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6761+
pub struct CreateAccessMethod {
6762+
/// The access method name.
6763+
pub name: Ident,
6764+
/// `TYPE INDEX | TABLE`
6765+
pub method_type: AccessMethodType,
6766+
/// `HANDLER handler_function`
6767+
pub handler: ObjectName,
6768+
}
6769+
6770+
impl fmt::Display for CreateAccessMethod {
6771+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6772+
write!(
6773+
f,
6774+
"CREATE ACCESS METHOD {name} TYPE {method_type} HANDLER {handler}",
6775+
name = self.name,
6776+
method_type = self.method_type,
6777+
handler = self.handler,
6778+
)
6779+
}
6780+
}
6781+
6782+
impl From<CreateAccessMethod> for crate::ast::Statement {
6783+
fn from(v: CreateAccessMethod) -> Self {
6784+
crate::ast::Statement::CreateAccessMethod(v)
6785+
}
6786+
}
6787+
6788+
/// An event name for `CREATE EVENT TRIGGER`.
6789+
///
6790+
/// Note: this is a PostgreSQL-specific concept.
6791+
/// <https://www.postgresql.org/docs/current/sql-createeventtrigger.html>
6792+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6793+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6794+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6795+
pub enum EventTriggerEvent {
6796+
/// `ddl_command_start`
6797+
DdlCommandStart,
6798+
/// `ddl_command_end`
6799+
DdlCommandEnd,
6800+
/// `table_rewrite`
6801+
TableRewrite,
6802+
/// `sql_drop`
6803+
SqlDrop,
6804+
}
6805+
6806+
impl fmt::Display for EventTriggerEvent {
6807+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6808+
match self {
6809+
EventTriggerEvent::DdlCommandStart => write!(f, "ddl_command_start"),
6810+
EventTriggerEvent::DdlCommandEnd => write!(f, "ddl_command_end"),
6811+
EventTriggerEvent::TableRewrite => write!(f, "table_rewrite"),
6812+
EventTriggerEvent::SqlDrop => write!(f, "sql_drop"),
6813+
}
6814+
}
6815+
}
6816+
6817+
/// A `CREATE EVENT TRIGGER` statement.
6818+
///
6819+
/// Note: this is a PostgreSQL-specific statement.
6820+
/// <https://www.postgresql.org/docs/current/sql-createeventtrigger.html>
6821+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6822+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6823+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6824+
pub struct CreateEventTrigger {
6825+
/// The trigger name.
6826+
pub name: Ident,
6827+
/// The event that fires the trigger.
6828+
pub event: EventTriggerEvent,
6829+
/// Optional `WHEN TAG IN ('tag', ...)` filter.
6830+
pub when_tags: Option<Vec<Value>>,
6831+
/// The handler function name (from `EXECUTE FUNCTION name()`).
6832+
pub execute: ObjectName,
6833+
/// Whether `PROCEDURE` was used instead of `FUNCTION` (older alias).
6834+
pub is_procedure: bool,
6835+
}
6836+
6837+
impl fmt::Display for CreateEventTrigger {
6838+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6839+
write!(f, "CREATE EVENT TRIGGER {} ON {}", self.name, self.event)?;
6840+
if let Some(tags) = &self.when_tags {
6841+
write!(f, " WHEN TAG IN ({})", display_comma_separated(tags))?;
6842+
}
6843+
let func_kw = if self.is_procedure {
6844+
"PROCEDURE"
6845+
} else {
6846+
"FUNCTION"
6847+
};
6848+
write!(f, " EXECUTE {func_kw} {}()", self.execute)?;
66716849
impl From<CreateUserMapping> for crate::ast::Statement {
66726850
fn from(v: CreateUserMapping) -> Self {
66736851
crate::ast::Statement::CreateUserMapping(v)
@@ -6706,6 +6884,79 @@ impl fmt::Display for CreateTablespace {
67066884
}
67076885
}
67086886

6887+
impl From<CreateEventTrigger> for crate::ast::Statement {
6888+
fn from(v: CreateEventTrigger) -> Self {
6889+
crate::ast::Statement::CreateEventTrigger(v)
6890+
}
6891+
}
6892+
6893+
/// A single element in a `CREATE TRANSFORM` transform list.
6894+
///
6895+
/// Either `FROM SQL WITH FUNCTION name(arg_types)` or `TO SQL WITH FUNCTION name(arg_types)`.
6896+
///
6897+
/// Note: this is a PostgreSQL-specific concept.
6898+
/// <https://www.postgresql.org/docs/current/sql-createtransform.html>
6899+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6900+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6901+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6902+
pub struct TransformElement {
6903+
/// `true` = FROM SQL, `false` = TO SQL
6904+
pub is_from: bool,
6905+
/// The function name.
6906+
pub function: ObjectName,
6907+
/// The argument type list (may be empty).
6908+
pub arg_types: Vec<DataType>,
6909+
}
6910+
6911+
impl fmt::Display for TransformElement {
6912+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6913+
let direction = if self.is_from { "FROM" } else { "TO" };
6914+
write!(
6915+
f,
6916+
"{direction} SQL WITH FUNCTION {}({})",
6917+
self.function,
6918+
display_comma_separated(&self.arg_types),
6919+
)
6920+
}
6921+
}
6922+
6923+
/// A `CREATE TRANSFORM` statement.
6924+
///
6925+
/// Note: this is a PostgreSQL-specific statement.
6926+
/// <https://www.postgresql.org/docs/current/sql-createtransform.html>
6927+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6928+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6929+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6930+
pub struct CreateTransform {
6931+
/// Whether `OR REPLACE` was specified.
6932+
pub or_replace: bool,
6933+
/// The data type being transformed.
6934+
pub type_name: DataType,
6935+
/// The procedural language name.
6936+
pub language: Ident,
6937+
/// The list of transform elements (FROM SQL and/or TO SQL).
6938+
pub elements: Vec<TransformElement>,
6939+
}
6940+
6941+
impl fmt::Display for CreateTransform {
6942+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6943+
write!(f, "CREATE")?;
6944+
if self.or_replace {
6945+
write!(f, " OR REPLACE")?;
6946+
}
6947+
write!(
6948+
f,
6949+
" TRANSFORM FOR {} LANGUAGE {} ({})",
6950+
self.type_name,
6951+
self.language,
6952+
display_comma_separated(&self.elements),
6953+
)
6954+
}
6955+
}
6956+
6957+
impl From<CreateTransform> for crate::ast::Statement {
6958+
fn from(v: CreateTransform) -> Self {
6959+
crate::ast::Statement::CreateTransform(v)
67096960
impl From<CreateTablespace> for crate::ast::Statement {
67106961
fn from(v: CreateTablespace) -> Self {
67116962
crate::ast::Statement::CreateTablespace(v)

src/ast/mod.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,11 @@ pub use self::ddl::{
7575
CreateDomain, CreateExtension, CreateForeignDataWrapper, CreateForeignTable, CreateFunction,
7676
CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
7777
CreatePolicyCommand, CreatePolicyType, CreatePublication, CreateSubscription, CreateTable,
78-
CreateTablespace, CreateTextSearchConfiguration, CreateTextSearchDictionary,
79-
CreateTextSearchParser, CreateTextSearchTemplate, CreateTrigger, CreateUserMapping,
80-
PublicationTarget, SecurityLabel, SecurityLabelObjectKind, UserMappingUser,
78+
AccessMethodType, CreateAccessMethod, CreateEventTrigger, CreateStatistics, CreateTablespace,
79+
CreateTextSearchConfiguration, CreateTextSearchDictionary, CreateTextSearchParser,
80+
CreateTextSearchTemplate, CreateTransform, CreateTrigger, CreateUserMapping,
81+
EventTriggerEvent, PublicationTarget, SecurityLabel, SecurityLabelObjectKind, StatisticsKind,
82+
TransformElement, UserMappingUser,
8183
CreateView, Deduplicate, DeferrableInitial, DistStyle, DropBehavior, DropExtension,
8284
DropFunction, DropOperator, DropOperatorClass, DropOperatorFamily, DropOperatorSignature,
8385
DropPolicy, DropTrigger, FdwRoutineClause, ForValues, FunctionReturnType, GeneratedAs,
@@ -4050,6 +4052,30 @@ pub enum Statement {
40504052
/// <https://www.postgresql.org/docs/current/sql-createsubscription.html>
40514053
CreateSubscription(CreateSubscription),
40524054
/// ```sql
4055+
/// CREATE STATISTICS [ IF NOT EXISTS ] name [ ( kind [, ...] ) ] ON expr [, ...] FROM table_name
4056+
/// ```
4057+
/// Note: this is a PostgreSQL-specific statement.
4058+
/// <https://www.postgresql.org/docs/current/sql-createstatistics.html>
4059+
CreateStatistics(CreateStatistics),
4060+
/// ```sql
4061+
/// CREATE ACCESS METHOD name TYPE INDEX | TABLE HANDLER handler_function
4062+
/// ```
4063+
/// Note: this is a PostgreSQL-specific statement.
4064+
/// <https://www.postgresql.org/docs/current/sql-create-access-method.html>
4065+
CreateAccessMethod(CreateAccessMethod),
4066+
/// ```sql
4067+
/// CREATE EVENT TRIGGER name ON event [ WHEN TAG IN ( 'tag' [, ...] ) ] EXECUTE FUNCTION | PROCEDURE function_name()
4068+
/// ```
4069+
/// Note: this is a PostgreSQL-specific statement.
4070+
/// <https://www.postgresql.org/docs/current/sql-createeventtrigger.html>
4071+
CreateEventTrigger(CreateEventTrigger),
4072+
/// ```sql
4073+
/// CREATE [ OR REPLACE ] TRANSFORM FOR type_name LANGUAGE lang_name ( transform_element_list )
4074+
/// ```
4075+
/// Note: this is a PostgreSQL-specific statement.
4076+
/// <https://www.postgresql.org/docs/current/sql-createtransform.html>
4077+
CreateTransform(CreateTransform),
4078+
/// ```sql
40534079
/// SECURITY LABEL [ FOR provider_name ] ON object_type object_name IS { 'label' | NULL }
40544080
/// ```
40554081
/// Note: this is a PostgreSQL-specific statement.
@@ -5556,6 +5582,10 @@ impl fmt::Display for Statement {
55565582
Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
55575583
Statement::CreatePublication(v) => write!(f, "{v}"),
55585584
Statement::CreateSubscription(v) => write!(f, "{v}"),
5585+
Statement::CreateStatistics(v) => write!(f, "{v}"),
5586+
Statement::CreateAccessMethod(v) => write!(f, "{v}"),
5587+
Statement::CreateEventTrigger(v) => write!(f, "{v}"),
5588+
Statement::CreateTransform(v) => write!(f, "{v}"),
55595589
Statement::SecurityLabel(v) => write!(f, "{v}"),
55605590
Statement::CreateUserMapping(v) => write!(f, "{v}"),
55615591
Statement::CreateTablespace(v) => write!(f, "{v}"),

src/ast/spans.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,10 @@ impl Spanned for Statement {
390390
Statement::CreateTextSearchTemplate(_) => Span::empty(),
391391
Statement::CreatePublication(_) => Span::empty(),
392392
Statement::CreateSubscription(_) => Span::empty(),
393+
Statement::CreateStatistics(_) => Span::empty(),
394+
Statement::CreateAccessMethod(_) => Span::empty(),
395+
Statement::CreateEventTrigger(_) => Span::empty(),
396+
Statement::CreateTransform(_) => Span::empty(),
393397
Statement::SecurityLabel(_) => Span::empty(),
394398
Statement::CreateUserMapping(_) => Span::empty(),
395399
Statement::CreateTablespace(_) => Span::empty(),

src/keywords.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,7 @@ define_keywords!(
10761076
TRAN,
10771077
TRANSACTION,
10781078
TRANSIENT,
1079+
TRANSFORM,
10791080
TRANSLATE,
10801081
TRANSLATE_REGEX,
10811082
TRANSLATION,

0 commit comments

Comments
 (0)