Skip to content

Commit fe63df5

Browse files
authored
Merge pull request #16 from fmguerreiro/feat/catalog-small
feat: parse CREATE CAST, CREATE CONVERSION, CREATE LANGUAGE, CREATE RULE
2 parents 1c766ca + 69d9f70 commit fe63df5

6 files changed

Lines changed: 687 additions & 1 deletion

File tree

src/ast/ddl.rs

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

6516+
/// The function binding kind for a `CREATE CAST` statement.
6517+
///
6518+
/// Note: this is a PostgreSQL-specific construct.
6519+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6520+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6521+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6522+
pub enum CastFunctionKind {
6523+
/// `WITH FUNCTION function_name(arg_types)`
6524+
WithFunction {
6525+
function_name: ObjectName,
6526+
argument_types: Vec<DataType>,
6527+
},
6528+
/// `WITHOUT FUNCTION`
6529+
WithoutFunction,
6530+
/// `WITH INOUT`
6531+
WithInout,
6532+
}
6533+
6534+
impl fmt::Display for CastFunctionKind {
6535+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6536+
match self {
6537+
CastFunctionKind::WithFunction {
6538+
function_name,
6539+
argument_types,
6540+
} => {
6541+
write!(f, "WITH FUNCTION {function_name}")?;
6542+
if !argument_types.is_empty() {
6543+
write!(f, "({})", display_comma_separated(argument_types))?;
6544+
}
6545+
Ok(())
6546+
}
6547+
CastFunctionKind::WithoutFunction => write!(f, "WITHOUT FUNCTION"),
6548+
CastFunctionKind::WithInout => write!(f, "WITH INOUT"),
65166549
/// A kind of extended statistics collected by `CREATE STATISTICS`.
65176550
///
65186551
/// Note: this is a PostgreSQL-specific concept.
@@ -6584,6 +6617,156 @@ impl fmt::Display for SecurityLabelObjectKind {
65846617
}
65856618
}
65866619

6620+
/// The context in which a cast may be invoked automatically.
6621+
///
6622+
/// Note: this is a PostgreSQL-specific construct.
6623+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6624+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6625+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6626+
pub enum CastContext {
6627+
/// No `AS` clause — explicit cast only (default).
6628+
Explicit,
6629+
/// `AS ASSIGNMENT`
6630+
Assignment,
6631+
/// `AS IMPLICIT`
6632+
Implicit,
6633+
}
6634+
6635+
impl fmt::Display for CastContext {
6636+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6637+
match self {
6638+
CastContext::Explicit => Ok(()),
6639+
CastContext::Assignment => write!(f, " AS ASSIGNMENT"),
6640+
CastContext::Implicit => write!(f, " AS IMPLICIT"),
6641+
}
6642+
}
6643+
}
6644+
6645+
/// A `CREATE CAST` statement.
6646+
///
6647+
/// Note: this is a PostgreSQL-specific statement.
6648+
/// <https://www.postgresql.org/docs/current/sql-createcast.html>
6649+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6650+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6651+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6652+
pub struct CreateCast {
6653+
/// The source type.
6654+
pub source_type: DataType,
6655+
/// The target type.
6656+
pub target_type: DataType,
6657+
/// How the cast is implemented.
6658+
pub function_kind: CastFunctionKind,
6659+
/// The cast context (explicit, assignment, or implicit).
6660+
pub cast_context: CastContext,
6661+
}
6662+
6663+
impl fmt::Display for CreateCast {
6664+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6665+
write!(
6666+
f,
6667+
"CREATE CAST ({source} AS {target}) {function_kind}{context}",
6668+
source = self.source_type,
6669+
target = self.target_type,
6670+
function_kind = self.function_kind,
6671+
context = self.cast_context,
6672+
)
6673+
}
6674+
}
6675+
6676+
impl From<CreateCast> for crate::ast::Statement {
6677+
fn from(v: CreateCast) -> Self {
6678+
crate::ast::Statement::CreateCast(v)
6679+
}
6680+
}
6681+
6682+
/// A `CREATE CONVERSION` statement.
6683+
///
6684+
/// Note: this is a PostgreSQL-specific statement.
6685+
/// <https://www.postgresql.org/docs/current/sql-createconversion.html>
6686+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6687+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6688+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6689+
pub struct CreateConversion {
6690+
/// The conversion name.
6691+
pub name: ObjectName,
6692+
/// Whether this is a `DEFAULT` conversion.
6693+
pub is_default: bool,
6694+
/// The source encoding name (a string literal like `'LATIN1'`).
6695+
pub source_encoding: String,
6696+
/// The destination encoding name (a string literal like `'UTF8'`).
6697+
pub destination_encoding: String,
6698+
/// The conversion function name.
6699+
pub function_name: ObjectName,
6700+
}
6701+
6702+
impl fmt::Display for CreateConversion {
6703+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6704+
write!(f, "CREATE")?;
6705+
if self.is_default {
6706+
write!(f, " DEFAULT")?;
6707+
}
6708+
write!(
6709+
f,
6710+
" CONVERSION {name} FOR '{source}' TO '{destination}' FROM {function}",
6711+
name = self.name,
6712+
source = self.source_encoding,
6713+
destination = self.destination_encoding,
6714+
function = self.function_name,
6715+
)
6716+
}
6717+
}
6718+
6719+
impl From<CreateConversion> for crate::ast::Statement {
6720+
fn from(v: CreateConversion) -> Self {
6721+
crate::ast::Statement::CreateConversion(v)
6722+
}
6723+
}
6724+
6725+
/// A `CREATE LANGUAGE` statement.
6726+
///
6727+
/// Note: this is a PostgreSQL-specific statement.
6728+
/// <https://www.postgresql.org/docs/current/sql-createlanguage.html>
6729+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6730+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6731+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6732+
pub struct CreateLanguage {
6733+
/// The language name.
6734+
pub name: Ident,
6735+
/// Whether `OR REPLACE` was specified.
6736+
pub or_replace: bool,
6737+
/// Whether `TRUSTED` was specified.
6738+
pub trusted: bool,
6739+
/// Whether `PROCEDURAL` was specified.
6740+
pub procedural: bool,
6741+
/// Optional `HANDLER handler_function` clause.
6742+
pub handler: Option<ObjectName>,
6743+
/// Optional `INLINE inline_function` clause.
6744+
pub inline_handler: Option<ObjectName>,
6745+
/// Optional `VALIDATOR validator_function` clause.
6746+
pub validator: Option<ObjectName>,
6747+
}
6748+
6749+
impl fmt::Display for CreateLanguage {
6750+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6751+
write!(f, "CREATE")?;
6752+
if self.or_replace {
6753+
write!(f, " OR REPLACE")?;
6754+
}
6755+
if self.trusted {
6756+
write!(f, " TRUSTED")?;
6757+
}
6758+
if self.procedural {
6759+
write!(f, " PROCEDURAL")?;
6760+
}
6761+
write!(f, " LANGUAGE {}", self.name)?;
6762+
if let Some(handler) = &self.handler {
6763+
write!(f, " HANDLER {handler}")?;
6764+
}
6765+
if let Some(inline) = &self.inline_handler {
6766+
write!(f, " INLINE {inline}")?;
6767+
}
6768+
if let Some(validator) = &self.validator {
6769+
write!(f, " VALIDATOR {validator}")?;
65876770
/// A `CREATE STATISTICS` statement.
65886771
///
65896772
/// Note: this is a PostgreSQL-specific statement.
@@ -6722,6 +6905,32 @@ impl fmt::Display for CreateUserMapping {
67226905
}
67236906
}
67246907

6908+
impl From<CreateLanguage> for crate::ast::Statement {
6909+
fn from(v: CreateLanguage) -> Self {
6910+
crate::ast::Statement::CreateLanguage(v)
6911+
}
6912+
}
6913+
6914+
/// The event that triggers a rule.
6915+
///
6916+
/// Note: this is a PostgreSQL-specific construct.
6917+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6918+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6919+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6920+
pub enum RuleEvent {
6921+
Select,
6922+
Insert,
6923+
Update,
6924+
Delete,
6925+
}
6926+
6927+
impl fmt::Display for RuleEvent {
6928+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6929+
match self {
6930+
RuleEvent::Select => write!(f, "SELECT"),
6931+
RuleEvent::Insert => write!(f, "INSERT"),
6932+
RuleEvent::Update => write!(f, "UPDATE"),
6933+
RuleEvent::Delete => write!(f, "DELETE"),
67256934
impl From<CreateStatistics> for crate::ast::Statement {
67266935
fn from(v: CreateStatistics) -> Self {
67276936
crate::ast::Statement::CreateStatistics(v)
@@ -6751,6 +6960,88 @@ impl fmt::Display for AccessMethodType {
67516960
}
67526961
}
67536962

6963+
/// The action performed by a rule.
6964+
///
6965+
/// Note: this is a PostgreSQL-specific construct.
6966+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
6967+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
6968+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
6969+
pub enum RuleAction {
6970+
/// `NOTHING`
6971+
Nothing,
6972+
/// One or more statements (parenthesized when more than one).
6973+
Statements(Vec<crate::ast::Statement>),
6974+
}
6975+
6976+
impl fmt::Display for RuleAction {
6977+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
6978+
match self {
6979+
RuleAction::Nothing => write!(f, "NOTHING"),
6980+
RuleAction::Statements(stmts) => {
6981+
if stmts.len() == 1 {
6982+
write!(f, "{}", stmts[0])
6983+
} else {
6984+
write!(f, "(")?;
6985+
for (i, stmt) in stmts.iter().enumerate() {
6986+
if i > 0 {
6987+
write!(f, "; ")?;
6988+
}
6989+
write!(f, "{stmt}")?;
6990+
}
6991+
write!(f, ")")
6992+
}
6993+
}
6994+
}
6995+
}
6996+
}
6997+
6998+
/// A `CREATE RULE` statement.
6999+
///
7000+
/// Note: this is a PostgreSQL-specific statement.
7001+
/// <https://www.postgresql.org/docs/current/sql-createrule.html>
7002+
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
7003+
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
7004+
#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
7005+
pub struct CreateRule {
7006+
/// The rule name.
7007+
pub name: Ident,
7008+
/// The event that triggers the rule.
7009+
pub event: RuleEvent,
7010+
/// The table the rule applies to.
7011+
pub table: ObjectName,
7012+
/// Optional `WHERE condition` clause.
7013+
pub condition: Option<Expr>,
7014+
/// Whether the rule is `INSTEAD` (true) or `ALSO` (false).
7015+
pub instead: bool,
7016+
/// The action(s) taken by the rule.
7017+
pub action: RuleAction,
7018+
}
7019+
7020+
impl fmt::Display for CreateRule {
7021+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
7022+
write!(
7023+
f,
7024+
"CREATE RULE {name} AS ON {event} TO {table}",
7025+
name = self.name,
7026+
event = self.event,
7027+
table = self.table,
7028+
)?;
7029+
if let Some(condition) = &self.condition {
7030+
write!(f, " WHERE {condition}")?;
7031+
}
7032+
write!(f, " DO")?;
7033+
if self.instead {
7034+
write!(f, " INSTEAD")?;
7035+
} else {
7036+
write!(f, " ALSO")?;
7037+
}
7038+
write!(f, " {}", self.action)
7039+
}
7040+
}
7041+
7042+
impl From<CreateRule> for crate::ast::Statement {
7043+
fn from(v: CreateRule) -> Self {
7044+
crate::ast::Statement::CreateRule(v)
67547045
/// A `CREATE ACCESS METHOD` statement.
67557046
///
67567047
/// Note: this is a PostgreSQL-specific statement.

src/ast/mod.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,16 @@ pub use self::ddl::{
6969
AlterTableLock, AlterTableOperation, AlterTableType, AlterTrigger, AlterTriggerOperation,
7070
AlterType, AlterTypeAddValue,
7171
AlterTypeAddValuePosition, AlterTypeOperation, AlterTypeRename, AlterTypeRenameValue,
72-
AggregateModifyKind, ClusteredBy, ColumnDef, ColumnOption, ColumnOptionDef, ColumnOptions,
72+
AggregateModifyKind, CastContext, CastFunctionKind, ClusteredBy, ColumnDef, ColumnOption,
73+
ColumnOptionDef, ColumnOptions,
7374
ColumnPolicy, ColumnPolicyProperty, ConstraintCharacteristics, CreateAggregate,
75+
CreateAggregateOption, CreateCast, CreateCollation, CreateCollationDefinition, CreateConnector,
76+
CreateConversion, CreateDomain, CreateExtension, CreateForeignDataWrapper, CreateForeignTable,
77+
CreateFunction, CreateIndex, CreateLanguage, CreateOperator, CreateOperatorClass,
78+
CreateOperatorFamily, CreatePolicy, CreatePolicyCommand, CreatePolicyType, CreatePublication,
79+
CreateRule, CreateSubscription, CreateTable,
80+
CreateTextSearchConfiguration, CreateTextSearchDictionary, CreateTextSearchParser,
81+
CreateTextSearchTemplate, CreateTrigger, PublicationTarget, RuleAction, RuleEvent,
7482
CreateAggregateOption, CreateCollation, CreateCollationDefinition, CreateConnector,
7583
CreateDomain, CreateExtension, CreateForeignDataWrapper, CreateForeignTable, CreateFunction,
7684
CreateIndex, CreateOperator, CreateOperatorClass, CreateOperatorFamily, CreatePolicy,
@@ -4052,6 +4060,31 @@ pub enum Statement {
40524060
/// <https://www.postgresql.org/docs/current/sql-createsubscription.html>
40534061
CreateSubscription(CreateSubscription),
40544062
/// ```sql
4063+
/// CREATE CAST (source_type AS target_type) WITH FUNCTION func_name [(arg_types)] [AS ASSIGNMENT | AS IMPLICIT]
4064+
/// CREATE CAST (source_type AS target_type) WITHOUT FUNCTION [AS ASSIGNMENT | AS IMPLICIT]
4065+
/// CREATE CAST (source_type AS target_type) WITH INOUT [AS ASSIGNMENT | AS IMPLICIT]
4066+
/// ```
4067+
/// Note: this is a PostgreSQL-specific statement.
4068+
/// <https://www.postgresql.org/docs/current/sql-createcast.html>
4069+
CreateCast(CreateCast),
4070+
/// ```sql
4071+
/// CREATE [DEFAULT] CONVERSION name FOR 'source_encoding' TO 'dest_encoding' FROM function_name
4072+
/// ```
4073+
/// Note: this is a PostgreSQL-specific statement.
4074+
/// <https://www.postgresql.org/docs/current/sql-createconversion.html>
4075+
CreateConversion(CreateConversion),
4076+
/// ```sql
4077+
/// CREATE [OR REPLACE] [TRUSTED] [PROCEDURAL] LANGUAGE name [HANDLER handler_func] [INLINE inline_func] [VALIDATOR validator_func | NO VALIDATOR]
4078+
/// ```
4079+
/// Note: this is a PostgreSQL-specific statement.
4080+
/// <https://www.postgresql.org/docs/current/sql-createlanguage.html>
4081+
CreateLanguage(CreateLanguage),
4082+
/// ```sql
4083+
/// CREATE RULE name AS ON event TO table [WHERE condition] DO [ALSO | INSTEAD] { NOTHING | command | (command ; ...) }
4084+
/// ```
4085+
/// Note: this is a PostgreSQL-specific statement.
4086+
/// <https://www.postgresql.org/docs/current/sql-createrule.html>
4087+
CreateRule(CreateRule),
40554088
/// CREATE STATISTICS [ IF NOT EXISTS ] name [ ( kind [, ...] ) ] ON expr [, ...] FROM table_name
40564089
/// ```
40574090
/// Note: this is a PostgreSQL-specific statement.
@@ -5582,6 +5615,10 @@ impl fmt::Display for Statement {
55825615
Statement::CreateTextSearchTemplate(v) => write!(f, "{v}"),
55835616
Statement::CreatePublication(v) => write!(f, "{v}"),
55845617
Statement::CreateSubscription(v) => write!(f, "{v}"),
5618+
Statement::CreateCast(v) => write!(f, "{v}"),
5619+
Statement::CreateConversion(v) => write!(f, "{v}"),
5620+
Statement::CreateLanguage(v) => write!(f, "{v}"),
5621+
Statement::CreateRule(v) => write!(f, "{v}"),
55855622
Statement::CreateStatistics(v) => write!(f, "{v}"),
55865623
Statement::CreateAccessMethod(v) => write!(f, "{v}"),
55875624
Statement::CreateEventTrigger(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::CreateCast(_) => Span::empty(),
394+
Statement::CreateConversion(_) => Span::empty(),
395+
Statement::CreateLanguage(_) => Span::empty(),
396+
Statement::CreateRule(_) => Span::empty(),
393397
Statement::CreateStatistics(_) => Span::empty(),
394398
Statement::CreateAccessMethod(_) => Span::empty(),
395399
Statement::CreateEventTrigger(_) => Span::empty(),

0 commit comments

Comments
 (0)