1use core::fmt::{self, Display};
19
20#[cfg(not(feature = "std"))]
21use alloc::{boxed::Box, vec::Vec};
22#[cfg(feature = "std")]
23use std::boxed::Box;
24
25#[cfg(feature = "serde")]
26use serde::{Deserialize, Serialize};
27
28#[cfg(feature = "visitor")]
29use sqlparser_derive::{Visit, VisitMut};
30
31use super::{DataType, Expr, Ident, ObjectName, Statement, ValueWithSpan};
32
33#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
34#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
35#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
36pub struct PlPgSqlBlock {
38 pub declarations: Vec<PlPgSqlDeclaration>,
40 pub statements: Vec<PlPgSqlStatement>,
42}
43
44impl Display for PlPgSqlBlock {
45 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46 if !self.declarations.is_empty() {
47 write!(f, "DECLARE ")?;
48 for declaration in &self.declarations {
49 write!(f, "{declaration}; ")?;
50 }
51 }
52 write!(f, "BEGIN")?;
53 for statement in &self.statements {
54 write!(f, " {statement};")?;
55 }
56 write!(f, " END")
57 }
58}
59
60#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
63pub struct PlPgSqlDeclaration {
65 pub name: Ident,
67 pub data_type: DataType,
69 pub initializer: Option<Expr>,
71}
72
73impl Display for PlPgSqlDeclaration {
74 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75 write!(f, "{} {}", self.name, self.data_type)?;
76 if let Some(initializer) = &self.initializer {
77 write!(f, " := {initializer}")?;
78 }
79 Ok(())
80 }
81}
82
83#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
84#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
85#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
86pub enum PlPgSqlStatement {
88 Assignment {
90 target: ObjectName,
92 value: Expr,
94 },
95 If {
97 branches: Vec<PlPgSqlIfBranch>,
99 else_statements: Option<Vec<PlPgSqlStatement>>,
101 },
102 Return(Expr),
104 Sql(Box<Statement>),
106 GetRowCount {
108 target: Ident,
110 },
111 RaiseException {
113 format: ValueWithSpan,
115 arguments: Vec<Expr>,
117 hint: Option<Expr>,
119 },
120}
121
122impl Display for PlPgSqlStatement {
123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124 match self {
125 Self::Assignment { target, value } => write!(f, "{target} := {value}"),
126 Self::If {
127 branches,
128 else_statements,
129 } => {
130 for (index, branch) in branches.iter().enumerate() {
131 if index == 0 {
132 write!(f, "IF {} THEN", branch.condition)?;
133 } else {
134 write!(f, " ELSIF {} THEN", branch.condition)?;
135 }
136 for statement in &branch.statements {
137 write!(f, " {statement};")?;
138 }
139 }
140 if let Some(statements) = else_statements {
141 write!(f, " ELSE")?;
142 for statement in statements {
143 write!(f, " {statement};")?;
144 }
145 }
146 write!(f, " END IF")
147 }
148 Self::Return(expression) => write!(f, "RETURN {expression}"),
149 Self::Sql(statement) => statement.fmt(f),
150 Self::GetRowCount { target } => {
151 write!(f, "GET DIAGNOSTICS {target} = ROW_COUNT")
152 }
153 Self::RaiseException {
154 format,
155 arguments,
156 hint,
157 } => {
158 write!(f, "RAISE EXCEPTION {format}")?;
159 for argument in arguments {
160 write!(f, ", {argument}")?;
161 }
162 if let Some(hint) = hint {
163 write!(f, " USING HINT = {hint}")?;
164 }
165 Ok(())
166 }
167 }
168 }
169}
170
171#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
172#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
173#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
174pub struct PlPgSqlIfBranch {
176 pub condition: Expr,
178 pub statements: Vec<PlPgSqlStatement>,
180}
181
182#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
183#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
184#[cfg_attr(feature = "visitor", derive(Visit, VisitMut))]
185pub struct DoStatement {
187 pub body: ValueWithSpan,
189 pub language: Option<Ident>,
191 pub language_before_body: bool,
193}
194
195impl Display for DoStatement {
196 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197 write!(f, "DO")?;
198 if self.language_before_body {
199 if let Some(language) = &self.language {
200 write!(f, " LANGUAGE {language}")?;
201 }
202 }
203 write!(f, " {}", self.body)?;
204 if !self.language_before_body {
205 if let Some(language) = &self.language {
206 write!(f, " LANGUAGE {language}")?;
207 }
208 }
209 Ok(())
210 }
211}