diff --git a/crates/squawk_ide/src/inlay_hints.rs b/crates/squawk_ide/src/inlay_hints.rs index 4081c08f..90b4e98c 100644 --- a/crates/squawk_ide/src/inlay_hints.rs +++ b/crates/squawk_ide/src/inlay_hints.rs @@ -142,39 +142,33 @@ fn inlay_hint_insert( .collect() }; - let Some(values) = insert.values() else { - // `insert into t select 1, 2;` - return inlay_hint_insert_select(hints, columns, insert.stmt()?); - }; - // `insert into t values (1, 2);` - for row in values.row_list()?.rows() { - for ((column_name, target, file_id), expr) in columns.iter().zip(row.exprs()) { - let expr_start = expr.syntax().text_range().start(); - hints.push(InlayHint { - position: expr_start, - label: format!("{}: ", column_name), - kind: InlayHintKind::Parameter, - target: *target, - file: *file_id, - }); - } - } - - Some(()) + inlay_hint_insert_select(hints, columns, insert.select_variant()?) } fn inlay_hint_insert_select( hints: &mut Vec, columns: Vec<(Name, Option, Option)>, - stmt: ast::Stmt, + select_variant: ast::SelectVariant, ) -> Option<()> { - let target_list = match stmt { - ast::Stmt::Select(select) => select.select_clause()?.target_list(), - ast::Stmt::SelectInto(select_into) => select_into.select_clause()?.target_list(), - ast::Stmt::ParenSelect(paren_select) => paren_select.select()?.target_list(), - _ => None, - }?; + if let ast::SelectVariant::Values(values) = &select_variant { + // `insert into t values (1, 2);` + for row in values.row_list()?.rows() { + for ((column_name, target, file_id), expr) in columns.iter().zip(row.exprs()) { + let expr_start = expr.syntax().text_range().start(); + hints.push(InlayHint { + position: expr_start, + label: format!("{}: ", column_name), + kind: InlayHintKind::Parameter, + target: *target, + file: *file_id, + }); + } + } + return Some(()); + } + // `insert into t select 1, 2;` + let target_list = select_variant.target_list()?; for ((column_name, target, file_id), target_expr) in columns.iter().zip(target_list.targets()) { let expr = target_expr.expr()?; let expr_start = expr.syntax().text_range().start(); diff --git a/crates/squawk_syntax/src/ast/generated/nodes.rs b/crates/squawk_syntax/src/ast/generated/nodes.rs index e18539f3..ed35eabf 100644 --- a/crates/squawk_syntax/src/ast/generated/nodes.rs +++ b/crates/squawk_syntax/src/ast/generated/nodes.rs @@ -4782,11 +4782,11 @@ impl CreateRule { support::child(&self.syntax) } #[inline] - pub fn stmt(&self) -> Option { + pub fn rule_stmt(&self) -> Option { support::child(&self.syntax) } #[inline] - pub fn stmts(&self) -> AstChildren { + pub fn rule_stmts(&self) -> AstChildren { support::children(&self.syntax) } #[inline] @@ -9734,11 +9734,7 @@ impl Insert { support::child(&self.syntax) } #[inline] - pub fn stmt(&self) -> Option { - support::child(&self.syntax) - } - #[inline] - pub fn values(&self) -> Option { + pub fn select_variant(&self) -> Option { support::child(&self.syntax) } #[inline] @@ -18802,6 +18798,15 @@ pub enum RefAction { SetNullColumns(SetNullColumns), } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub enum RuleStmt { + Delete(Delete), + Insert(Insert), + Notify(Notify), + Update(Update), + SelectVariant(SelectVariant), +} + #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub enum SchemaElement { CreateIndex(CreateIndex), @@ -34424,6 +34429,65 @@ impl From for RefAction { RefAction::SetNullColumns(node) } } +impl AstNode for RuleStmt { + #[inline] + fn can_cast(kind: SyntaxKind) -> bool { + matches!( + kind, + SyntaxKind::DELETE | SyntaxKind::INSERT | SyntaxKind::NOTIFY | SyntaxKind::UPDATE + ) + } + #[inline] + fn cast(syntax: SyntaxNode) -> Option { + let res = match syntax.kind() { + SyntaxKind::DELETE => RuleStmt::Delete(Delete { syntax }), + SyntaxKind::INSERT => RuleStmt::Insert(Insert { syntax }), + SyntaxKind::NOTIFY => RuleStmt::Notify(Notify { syntax }), + SyntaxKind::UPDATE => RuleStmt::Update(Update { syntax }), + _ => { + if let Some(result) = SelectVariant::cast(syntax) { + return Some(RuleStmt::SelectVariant(result)); + } + return None; + } + }; + Some(res) + } + #[inline] + fn syntax(&self) -> &SyntaxNode { + match self { + RuleStmt::Delete(it) => &it.syntax, + RuleStmt::Insert(it) => &it.syntax, + RuleStmt::Notify(it) => &it.syntax, + RuleStmt::Update(it) => &it.syntax, + RuleStmt::SelectVariant(it) => it.syntax(), + } + } +} +impl From for RuleStmt { + #[inline] + fn from(node: Delete) -> RuleStmt { + RuleStmt::Delete(node) + } +} +impl From for RuleStmt { + #[inline] + fn from(node: Insert) -> RuleStmt { + RuleStmt::Insert(node) + } +} +impl From for RuleStmt { + #[inline] + fn from(node: Notify) -> RuleStmt { + RuleStmt::Notify(node) + } +} +impl From for RuleStmt { + #[inline] + fn from(node: Update) -> RuleStmt { + RuleStmt::Update(node) + } +} impl AstNode for SchemaElement { #[inline] fn can_cast(kind: SyntaxKind) -> bool { diff --git a/crates/squawk_syntax/src/postgresql.ungram b/crates/squawk_syntax/src/postgresql.ungram index 46e5ec6c..80cf345b 100644 --- a/crates/squawk_syntax/src/postgresql.ungram +++ b/crates/squawk_syntax/src/postgresql.ungram @@ -1343,7 +1343,7 @@ Insert = WithClause? 'insert' 'into' Path Alias? ColumnList? ('overriding' ('system' | 'user') 'value')? - ('default' 'values' | Values | Stmt) + ('default' 'values' | SelectVariant) OnConflictClause? ReturningClause? @@ -2618,7 +2618,17 @@ CreateRole = CreateRule = 'create' OrReplace? 'rule' Name 'as' 'on' ('#ident' | 'select' | 'insert' | 'update' | 'delete') 'to' Path WhereClause? - 'do' ('also' | 'instead')? ('nothing' | '(' (Stmt (',' Stmt)*) ')' | Stmt) + 'do' ('also' | 'instead')? + ('nothing' + | '(' (RuleStmt (',' RuleStmt)*) ')' + | RuleStmt) + +RuleStmt = + SelectVariant +| Insert +| Update +| Delete +| Notify CreateSequence = 'create' Persistence? 'sequence' IfNotExists? Path