1use serde::{Deserialize, Serialize};
13
14mod constraints;
15mod cte;
16mod events;
17mod expressions;
18mod from;
19mod function_binding;
20mod locking;
21mod ranges;
22mod relation_hierarchy;
23mod relation_lifecycle;
24mod routine_security;
25mod sequence;
26
27pub use constraints::*;
28pub use cte::*;
29pub use events::*;
30pub use expressions::*;
31pub use from::*;
32pub use function_binding::*;
33pub use locking::*;
34pub use ranges::*;
35pub use relation_hierarchy::*;
36pub use relation_lifecycle::*;
37pub use routine_security::*;
38pub use sequence::*;
39
40const fn default_include_descendants() -> bool {
41 true
42}
43
44const fn default_true() -> bool {
45 true
46}
47
48#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
49pub enum ColumnType {
50 SmallInteger,
51 Integer,
52 BigInteger,
53 Oid,
55 Xid,
57 Boolean,
58 Text,
59 RefCursor,
61 Name,
62 Uuid,
63 Varchar(Option<u32>),
64 Bpchar,
66 Character(u32),
70 Real,
71 DoublePrecision,
72 Numeric {
77 precision: Option<u32>,
78 scale: Option<i32>,
79 },
80 Json,
82 JsonB,
84 Bytea,
86 InternalChar,
88 Regproc,
89 Regclass,
91 Regnamespace,
93 Regtype,
94 PgNodeTree,
95 AclItem,
96 Int2Vector,
97 OidVector,
98 AnyArray,
99 Record,
101 Array(Box<ColumnType>),
104 Date,
106 Time,
108 TimeTz,
110 Timestamp,
113 TimestampTz,
116 Interval,
117 Range(RangeSubtype),
121 Multirange(RangeSubtype),
123 Vector(u32),
125 Tensor(u32),
129 Domain {
132 schema: String,
133 name: String,
134 oid: u32,
135 base: Box<ColumnType>,
136 },
137}
138
139pub(crate) fn builtin_array_element_name(type_name: &str) -> Option<&'static str> {
140 Some(match type_name {
141 "_bool" => "bool",
142 "_bytea" => "bytea",
143 "_char" => "\"char\"",
144 "_name" => "name",
145 "_int8" => "int8",
146 "_int2" => "int2",
147 "_int2vector" => "int2vector",
148 "_int4" => "int4",
149 "_regproc" => "regproc",
150 "_regclass" => "regclass",
151 "_text" => "text",
152 "_refcursor" => "refcursor",
153 "_oid" => "oid",
154 "_oidvector" => "oidvector",
155 "_bpchar" => "bpchar",
156 "_varchar" => "varchar",
157 "_float4" => "float4",
158 "_float8" => "float8",
159 "_aclitem" => "aclitem",
160 "_date" => "date",
161 "_time" => "time",
162 "_timestamp" => "timestamp",
163 "_timestamptz" => "timestamptz",
164 "_interval" => "interval",
165 "_numeric" => "numeric",
166 "_timetz" => "timetz",
167 "_record" => "record",
168 "_uuid" => "uuid",
169 "_json" => "json",
170 "_jsonb" => "jsonb",
171 "_regtype" => "regtype",
172 "_xid" => "xid",
173 "_pg_node_tree" => "pg_node_tree",
174 "_int4range" => "int4range",
175 "_int8range" => "int8range",
176 "_numrange" => "numrange",
177 "_daterange" => "daterange",
178 "_tsrange" => "tsrange",
179 "_tstzrange" => "tstzrange",
180 "_int4multirange" => "int4multirange",
181 "_int8multirange" => "int8multirange",
182 "_nummultirange" => "nummultirange",
183 "_datemultirange" => "datemultirange",
184 "_tsmultirange" => "tsmultirange",
185 "_tstzmultirange" => "tstzmultirange",
186 _ => return None,
187 })
188}
189
190impl ColumnType {
191 #[must_use]
192 pub fn is_integer(&self) -> bool {
193 match self {
194 Self::SmallInteger | Self::Integer | Self::BigInteger | Self::Oid | Self::Xid => true,
195 Self::Domain { base, .. } => base.is_integer(),
196 _ => false,
197 }
198 }
199
200 #[must_use]
201 pub fn is_character_string(&self) -> bool {
202 match self {
203 Self::Text
204 | Self::Name
205 | Self::Varchar(_)
206 | Self::Bpchar
207 | Self::Character(_)
208 | Self::InternalChar
209 | Self::PgNodeTree
210 | Self::AclItem => true,
211 Self::Domain { base, .. } => base.is_character_string(),
212 _ => false,
213 }
214 }
215
216 pub fn from_sql_name(name: &str) -> Result<Self, crate::SQLError> {
220 let normalized = name.trim().to_ascii_lowercase();
221 if let Some(element) = builtin_array_element_name(&normalized) {
222 return Self::from_sql_name(element).map(|ty| Self::Array(Box::new(ty)));
223 }
224 if let Some(element) = normalized.strip_suffix("[]") {
225 return Self::from_sql_name(element).map(|ty| Self::Array(Box::new(ty)));
226 }
227 let (base, modifier) = normalized
228 .strip_suffix(')')
229 .and_then(|prefix| prefix.rsplit_once('('))
230 .map_or((normalized.as_str(), None), |(base, modifier)| {
231 (base.trim(), Some(modifier.trim()))
232 });
233 let base = base.strip_prefix("pg_catalog.").unwrap_or(base);
234 let character_length = || -> Result<Option<u32>, crate::SQLError> {
235 modifier
236 .map(|value| {
237 value
238 .parse::<u32>()
239 .ok()
240 .filter(|length| *length > 0)
241 .ok_or_else(|| {
242 crate::SQLError::TypeMismatch(format!(
243 "character length must be greater than zero, got {value}"
244 ))
245 })
246 })
247 .transpose()
248 };
249 match base {
250 "smallint" | "int2" | "smallserial" | "serial2" => Ok(Self::SmallInteger),
251 "integer" | "int" | "int4" | "serial" | "serial4" => Ok(Self::Integer),
252 "bigint" | "int8" | "bigserial" | "serial8" => Ok(Self::BigInteger),
253 "oid" => Ok(Self::Oid),
254 "xid" => Ok(Self::Xid),
255 "boolean" | "bool" => Ok(Self::Boolean),
256 "text" => Ok(Self::Text),
257 "refcursor" => Ok(Self::RefCursor),
258 "name" => Ok(Self::Name),
259 "uuid" => Ok(Self::Uuid),
260 "varchar" | "character varying" => Ok(Self::Varchar(character_length()?)),
261 "character" | "char" => Ok(Self::Character(character_length()?.unwrap_or(1))),
262 "bpchar" => Ok(character_length()?.map_or(Self::Bpchar, Self::Character)),
263 "real" | "float4" => Ok(Self::Real),
264 "double" | "double precision" | "float8" => Ok(Self::DoublePrecision),
265 "numeric" | "decimal" => {
266 let (precision, scale) = match modifier {
267 None => (None, None),
268 Some(modifier) => {
269 let mut parts = modifier.split(',').map(str::trim);
270 let precision = parts
271 .next()
272 .and_then(|value| value.parse::<u32>().ok())
273 .ok_or_else(|| {
274 crate::SQLError::TypeMismatch(format!(
275 "invalid numeric modifier `{modifier}`"
276 ))
277 })?;
278 let scale = parts
279 .next()
280 .map(|value| value.parse::<i32>())
281 .transpose()
282 .map_err(|_| {
283 crate::SQLError::TypeMismatch(format!(
284 "invalid numeric modifier `{modifier}`"
285 ))
286 })?
287 .unwrap_or(0);
288 if parts.next().is_some() {
289 return Err(crate::SQLError::TypeMismatch(format!(
290 "invalid numeric modifier `{modifier}`"
291 )));
292 }
293 (Some(precision), Some(scale))
294 }
295 };
296 Ok(Self::Numeric { precision, scale })
297 }
298 "json" => Ok(Self::Json),
299 "jsonb" => Ok(Self::JsonB),
300 "bytea" => Ok(Self::Bytea),
301 "\"char\"" => Ok(Self::InternalChar),
302 "regproc" => Ok(Self::Regproc),
303 "regclass" => Ok(Self::Regclass),
304 "regnamespace" => Ok(Self::Regnamespace),
305 "regtype" => Ok(Self::Regtype),
306 "pg_node_tree" => Ok(Self::PgNodeTree),
307 "aclitem" => Ok(Self::AclItem),
308 "int2vector" => Ok(Self::Int2Vector),
309 "oidvector" => Ok(Self::OidVector),
310 "anyarray" => Ok(Self::AnyArray),
311 "record" => Ok(Self::Record),
312 "date" => Ok(Self::Date),
313 "time" | "time without time zone" => Ok(Self::Time),
314 "timetz" | "time with time zone" => Ok(Self::TimeTz),
315 "timestamp" | "datetime" | "timestamp without time zone" => Ok(Self::Timestamp),
316 "timestamptz" | "timestamp with time zone" => Ok(Self::TimestampTz),
317 "interval" => Ok(Self::Interval),
318 "int4range" => Ok(Self::Range(RangeSubtype::Integer)),
319 "int8range" => Ok(Self::Range(RangeSubtype::BigInteger)),
320 "numrange" => Ok(Self::Range(RangeSubtype::Numeric)),
321 "daterange" => Ok(Self::Range(RangeSubtype::Date)),
322 "tsrange" => Ok(Self::Range(RangeSubtype::Timestamp)),
323 "tstzrange" => Ok(Self::Range(RangeSubtype::TimestampTz)),
324 "int4multirange" => Ok(Self::Multirange(RangeSubtype::Integer)),
325 "int8multirange" => Ok(Self::Multirange(RangeSubtype::BigInteger)),
326 "nummultirange" => Ok(Self::Multirange(RangeSubtype::Numeric)),
327 "datemultirange" => Ok(Self::Multirange(RangeSubtype::Date)),
328 "tsmultirange" => Ok(Self::Multirange(RangeSubtype::Timestamp)),
329 "tstzmultirange" => Ok(Self::Multirange(RangeSubtype::TimestampTz)),
330 "vector" => modifier
331 .and_then(|value| value.parse::<u32>().ok())
332 .filter(|dimension| *dimension > 0)
333 .map(Self::Vector)
334 .ok_or_else(|| crate::SQLError::TypeMismatch("VECTOR requires a dimension".into())),
335 "tensor" => modifier
336 .and_then(|value| value.parse::<u32>().ok())
337 .filter(|dimension| *dimension > 0)
338 .map(Self::Tensor)
339 .ok_or_else(|| crate::SQLError::TypeMismatch("TENSOR requires a dimension".into())),
340 other => Err(crate::SQLError::Unsupported(format!(
341 "SQL type `{other}` is not supported"
342 ))),
343 }
344 }
345
346 #[must_use]
347 pub fn sql_name(&self) -> String {
348 match self {
349 Self::SmallInteger => "smallint".into(),
350 Self::Integer => "integer".into(),
351 Self::BigInteger => "bigint".into(),
352 Self::Oid => "oid".into(),
353 Self::Xid => "xid".into(),
354 Self::Boolean => "boolean".into(),
355 Self::Text => "text".into(),
356 Self::RefCursor => "refcursor".into(),
357 Self::Name => "name".into(),
358 Self::Uuid => "uuid".into(),
359 Self::Varchar(Some(length)) => format!("character varying({length})"),
360 Self::Varchar(None) => "character varying".into(),
361 Self::Bpchar => "bpchar".into(),
362 Self::Character(length) => format!("character({length})"),
363 Self::Real => "real".into(),
364 Self::DoublePrecision => "double precision".into(),
365 Self::Numeric {
366 precision: Some(precision),
367 scale: Some(scale),
368 } => format!("numeric({precision},{scale})"),
369 Self::Numeric { .. } => "numeric".into(),
370 Self::Json => "json".into(),
371 Self::JsonB => "jsonb".into(),
372 Self::Bytea => "bytea".into(),
373 Self::InternalChar => "\"char\"".into(),
374 Self::Regproc => "regproc".into(),
375 Self::Regclass => "regclass".into(),
376 Self::Regnamespace => "regnamespace".into(),
377 Self::Regtype => "regtype".into(),
378 Self::PgNodeTree => "pg_node_tree".into(),
379 Self::AclItem => "aclitem".into(),
380 Self::Int2Vector => "int2vector".into(),
381 Self::OidVector => "oidvector".into(),
382 Self::AnyArray => "anyarray".into(),
383 Self::Record => "record".into(),
384 Self::Array(element) => format!("{}[]", element.sql_name()),
385 Self::Date => "date".into(),
386 Self::Time => "time without time zone".into(),
387 Self::TimeTz => "time with time zone".into(),
388 Self::Timestamp => "timestamp without time zone".into(),
389 Self::TimestampTz => "timestamp with time zone".into(),
390 Self::Interval => "interval".into(),
391 Self::Range(subtype) => subtype.range_name().into(),
392 Self::Multirange(subtype) => subtype.multirange_name().into(),
393 Self::Vector(dimension) => format!("vector({dimension})"),
394 Self::Tensor(dimension) => format!("tensor({dimension})"),
395 Self::Domain { schema, name, .. } => format!("{schema}.{name}"),
396 }
397 }
398
399 #[must_use]
402 pub fn regtype_name(&self) -> String {
403 match self {
404 Self::Varchar(_) => "character varying".into(),
405 Self::Bpchar | Self::Character(_) => "character".into(),
406 Self::Numeric { .. } => "numeric".into(),
407 Self::Vector(_) => "vector".into(),
408 Self::Tensor(_) => "tensor".into(),
409 Self::Domain { schema, name, .. } => format!("{schema}.{name}"),
410 Self::Array(element) => format!("{}[]", element.regtype_name()),
411 other => other.sql_name(),
412 }
413 }
414}
415
416#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
417pub enum GeneratedColumnKind {
418 Virtual,
419 Stored,
420}
421
422#[derive(Debug, Clone, Serialize, Deserialize)]
423pub struct GeneratedColumn {
424 pub kind: GeneratedColumnKind,
425 pub expression: Box<Expr>,
426 #[serde(default, skip_serializing_if = "Vec::is_empty")]
427 pub function_dependencies: Vec<GeneratedFunctionDependency>,
428}
429
430#[derive(Debug, Clone, Serialize, Deserialize)]
431pub struct CreateIndex {
432 pub name: Option<String>,
433 pub table: String,
434 pub access_method: String,
436 pub columns: Vec<String>,
437 pub if_not_exists: bool,
439 pub options: Vec<(String, String)>,
443}
444
445#[derive(Debug, Clone, Serialize, Deserialize)]
446pub struct DropStmt {
447 pub kind: DropKind,
448 pub names: Vec<String>,
449 pub if_exists: bool,
450 pub cascade: bool,
451}
452
453#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
454pub enum DropKind {
455 Table,
456 Index,
457 View,
458 MaterializedView,
459 Schema,
460}
461
462#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
465pub enum FunctionParamMode {
466 In,
468 Out,
471 InOut,
473 Variadic,
475 Table,
478}
479
480#[derive(Debug, Clone, Serialize, Deserialize)]
482pub struct FunctionParam {
483 pub name: String,
486 pub type_name: String,
489 #[serde(default, skip_serializing_if = "Option::is_none")]
491 pub type_reference: Option<RoutineColumnTypeReference>,
492 pub mode: FunctionParamMode,
493 #[serde(default, skip_serializing_if = "Option::is_none")]
495 pub default: Option<Expr>,
496}
497
498#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
500pub struct RoutineColumnTypeReference {
501 pub schema: Option<String>,
502 pub relation: String,
503 pub column: String,
504}
505
506impl RoutineColumnTypeReference {
507 pub fn new(schema: Option<String>, relation: String, column: String) -> Self {
508 Self {
509 schema,
510 relation,
511 column,
512 }
513 }
514
515 pub fn relation_reference(&self) -> String {
516 match self.schema.as_deref() {
517 Some(schema) => format!(
518 "{}.{}",
519 render_identifier_component(schema),
520 render_identifier_component(&self.relation)
521 ),
522 None => render_identifier_component(&self.relation),
523 }
524 }
525
526 pub fn type_reference(&self) -> String {
527 format!(
528 "{}.{}%type",
529 self.relation_reference(),
530 render_identifier_component(&self.column)
531 )
532 }
533}
534
535fn render_identifier_component(component: &str) -> String {
536 let can_render_bare = component
537 .bytes()
538 .enumerate()
539 .all(|(index, byte)| match byte {
540 b'a'..=b'z' | b'_' => true,
541 b'0'..=b'9' | b'$' => index != 0,
542 _ => false,
543 });
544 if can_render_bare && !component.is_empty() {
545 component.to_string()
546 } else {
547 format!("\"{}\"", component.replace('"', "\"\""))
548 }
549}
550
551#[derive(Debug, Clone, Serialize, Deserialize)]
553pub enum FunctionReturns {
554 None,
557 Scalar { type_name: String },
559 SetOf { type_name: String },
561 Table,
565}
566
567#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
569pub enum FunctionVolatility {
570 Immutable,
571 Stable,
572 #[default]
573 Volatile,
574}
575
576#[derive(Debug, Clone, Serialize, Deserialize)]
578pub enum FunctionBody {
579 Source(String),
582 Statements(Vec<Statement>),
585}
586
587#[derive(Debug, Clone, Serialize, Deserialize)]
589pub struct CreateFunction {
590 pub name: String,
591 pub or_replace: bool,
592 pub is_procedure: bool,
593 pub params: Vec<FunctionParam>,
594 pub returns: FunctionReturns,
595 #[serde(default, skip_serializing_if = "Option::is_none")]
597 pub return_type_reference: Option<RoutineColumnTypeReference>,
598 pub language: String,
600 pub body: FunctionBody,
601 #[serde(default, skip_serializing_if = "Vec::is_empty")]
603 pub creation_search_path: Vec<String>,
604 pub volatility: FunctionVolatility,
605 pub strict: bool,
608 #[serde(default)]
610 pub owner: String,
611 #[serde(default, flatten)]
613 pub security: RoutineSecurityAttributes,
614 #[serde(default)]
616 pub parallel: FunctionParallel,
617 #[serde(default, skip_serializing_if = "Option::is_none")]
619 pub support: Option<String>,
620 #[serde(default, skip_serializing_if = "Vec::is_empty")]
622 pub config: Vec<(String, String)>,
623 #[serde(default, skip_serializing_if = "Vec::is_empty")]
625 pub config_actions: Vec<RoutineConfigAction>,
626 #[serde(default, skip_serializing_if = "Option::is_none")]
628 pub execute_acl: Option<Vec<RoutineAclEntry>>,
629}
630
631impl CreateFunction {
632 pub fn identity_params(&self) -> Vec<&FunctionParam> {
634 self.params
635 .iter()
636 .filter(|param| Self::is_identity_param(param))
637 .collect()
638 }
639
640 pub fn identity_arity(&self) -> usize {
642 self.params
643 .iter()
644 .filter(|param| Self::is_identity_param(param))
645 .count()
646 }
647
648 fn is_identity_param(param: &FunctionParam) -> bool {
649 matches!(
650 param.mode,
651 FunctionParamMode::In | FunctionParamMode::InOut | FunctionParamMode::Variadic
652 )
653 }
654
655 pub fn call_params(&self) -> Vec<&FunctionParam> {
657 self.params
658 .iter()
659 .filter(|param| self.is_call_param(param))
660 .collect()
661 }
662
663 pub fn call_arity(&self) -> usize {
665 self.params
666 .iter()
667 .filter(|param| self.is_call_param(param))
668 .count()
669 }
670
671 pub fn required_call_arity(&self) -> usize {
673 self.params
674 .iter()
675 .filter(|param| {
676 self.is_call_param(param)
677 && param.default.is_none()
678 && param.mode != FunctionParamMode::Variadic
679 })
680 .count()
681 }
682
683 fn is_call_param(&self, param: &FunctionParam) -> bool {
684 match param.mode {
685 FunctionParamMode::In | FunctionParamMode::InOut | FunctionParamMode::Variadic => true,
686 FunctionParamMode::Out => self.is_procedure,
687 FunctionParamMode::Table => false,
688 }
689 }
690
691 pub fn signature_arity(&self) -> usize {
693 self.call_arity()
694 }
695
696 pub fn required_arity(&self) -> usize {
698 self.required_call_arity()
699 }
700
701 pub fn signature_params(&self) -> Vec<&FunctionParam> {
703 self.call_params()
704 }
705
706 pub fn output_params(&self) -> Vec<&FunctionParam> {
709 self.params
710 .iter()
711 .filter(|p| {
712 matches!(
713 p.mode,
714 FunctionParamMode::Out | FunctionParamMode::InOut | FunctionParamMode::Table
715 )
716 })
717 .collect()
718 }
719
720 pub fn returns_set(&self) -> bool {
723 matches!(
724 self.returns,
725 FunctionReturns::SetOf { .. } | FunctionReturns::Table
726 )
727 }
728}
729
730#[derive(Debug, Clone, Serialize, Deserialize)]
732pub struct DropFunctionItem {
733 pub name: String,
734 pub arg_types: Option<Vec<String>>,
739}
740
741#[derive(Debug, Clone, Serialize, Deserialize)]
744pub struct DropFunctionStmt {
745 pub is_procedure: bool,
746 pub if_exists: bool,
747 #[serde(default)]
748 pub cascade: bool,
749 pub items: Vec<DropFunctionItem>,
750}
751
752#[derive(Debug, Clone, Serialize, Deserialize)]
753pub struct AlterTableStmt {
754 pub table: String,
755 pub qualifier: String,
757 pub if_exists: bool,
758 #[serde(default = "default_true")]
760 pub recurse: bool,
761 pub actions: Vec<AlterTableAction>,
762}
763
764#[derive(Debug, Clone, Serialize, Deserialize)]
765#[allow(clippy::large_enum_variant)]
766pub enum AlterTableAction {
767 AddInheritance {
768 parent: String,
769 },
770 DropInheritance {
771 parent: String,
772 },
773 AttachPartition {
774 partition: String,
775 bound: PartitionBound,
776 },
777 DetachPartition {
778 partition: String,
779 concurrently: bool,
780 finalize: bool,
781 },
782 AddColumn {
783 column: ColumnDef,
784 if_not_exists: bool,
785 },
786 AddKeyConstraint {
787 constraint: TableKeyConstraint,
788 },
789 AddCheckConstraint {
790 constraint: TableCheck,
791 },
792 AddForeignKeyConstraint {
793 constraint: ForeignKey,
794 },
795 AddNotNullConstraint {
796 name: Option<String>,
797 column: String,
798 validated: bool,
799 no_inherit: bool,
800 },
801 ValidateConstraint {
802 name: String,
803 },
804 AlterConstraint {
805 name: String,
806 enforceability: Option<bool>,
807 deferrability: Option<(bool, bool)>,
808 no_inherit: Option<bool>,
809 },
810 DropConstraint {
811 name: String,
812 if_exists: bool,
813 cascade: bool,
814 },
815 DropColumn {
816 name: String,
817 if_exists: bool,
818 cascade: bool,
819 },
820 RenameColumn {
821 from: String,
822 to: String,
823 },
824 RenameTable {
825 to: String,
826 },
827 RenameTrigger {
828 from: String,
829 to: String,
830 },
831 RenameConstraint {
832 from: String,
833 to: String,
834 },
835 RenameRule {
836 from: String,
837 to: String,
838 },
839 SetTriggerEnableMode {
840 name: Option<String>,
841 user_only: bool,
842 mode: EventEnableMode,
843 },
844 SetRuleEnableMode {
845 name: String,
846 mode: EventEnableMode,
847 },
848 SetDefault {
849 name: String,
850 default: Expr,
851 },
852 DropDefault {
853 name: String,
854 },
855 SetExpression {
856 name: String,
857 expression: Expr,
858 },
859 DropExpression {
860 name: String,
861 },
862 SetNotNull {
863 name: String,
864 },
865 DropNotNull {
866 name: String,
867 },
868 AlterColumnType {
869 name: String,
870 ty: ColumnType,
871 #[serde(default, skip_serializing_if = "Option::is_none")]
872 using: Option<Expr>,
873 },
874}
875
876#[derive(Debug, Clone, Serialize, Deserialize)]
877pub struct InsertStmt {
878 pub table: String,
879 pub target_qualifier: String,
881 #[serde(default = "default_include_descendants")]
882 pub include_descendants: bool,
883 pub columns: Vec<String>,
884 pub with: Vec<CTE>,
886 pub rows: Vec<Vec<ValueExpr>>,
890 pub select_source: Option<Box<SelectStmt>>,
894 pub on_conflict: Option<OnConflict>,
897 pub returning: Vec<Projection>,
899 pub returning_aliases: ReturningAliases,
902}
903
904#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
905pub struct ReturningAliases {
906 pub old: String,
907 pub new: String,
908 #[serde(default)]
909 pub old_explicit: bool,
910 #[serde(default)]
911 pub new_explicit: bool,
912}
913
914impl Default for ReturningAliases {
915 fn default() -> Self {
916 Self {
917 old: "old".into(),
918 new: "new".into(),
919 old_explicit: false,
920 new_explicit: false,
921 }
922 }
923}
924
925#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
926pub struct OnConflict {
927 pub conflict_columns: Vec<String>,
931 pub action: OnConflictAction,
932}
933
934#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
935pub enum OnConflictAction {
936 Nothing,
938 Update {
942 assignments: Vec<(String, Expr)>,
943 r#where: Option<Expr>,
944 },
945}
946
947#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
948pub struct SelectStmt {
949 pub projections: Vec<Projection>,
950 #[serde(default, skip_serializing_if = "Vec::is_empty")]
954 pub values: Vec<Vec<Expr>>,
955 pub from: Option<FromClause>,
956 pub r#where: Option<Expr>,
957 pub group_by: Vec<Expr>,
958 pub grouping_sets: Vec<Vec<Expr>>,
964 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
966 pub group_distinct: bool,
967 pub having: Option<Expr>,
971 pub order_by: Vec<OrderBy>,
972 pub limit: Option<Expr>,
976 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
978 pub with_ties: bool,
979 pub offset: Option<Expr>,
981 pub with: Vec<CTE>,
983 pub set_op: Option<Box<SetOp>>,
987 pub distinct: bool,
990 pub distinct_on: Vec<Expr>,
993 #[serde(default, skip_serializing_if = "Vec::is_empty")]
995 pub locking: Vec<LockingClause>,
996}
997
998#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
999pub struct SetOp {
1000 pub kind: SetOpKind,
1001 pub all: bool,
1002 #[serde(default, skip_serializing_if = "Option::is_none")]
1006 pub left: Option<Box<SelectStmt>>,
1007 pub right: SelectStmt,
1008 pub combined_order_by: Vec<OrderBy>,
1011 pub combined_limit: Option<Expr>,
1014 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1016 pub combined_with_ties: bool,
1017 pub combined_offset: Option<Expr>,
1019}
1020
1021#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1022pub enum SetOpKind {
1023 Union,
1024 Intersect,
1025 Except,
1026}
1027
1028#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1030pub enum DiscardTarget {
1031 All,
1032 Plans,
1033 Sequences,
1034 Temp,
1035}
1036
1037#[derive(Debug, Clone, Serialize, Deserialize)]
1038pub struct UpdateStmt {
1039 pub table: String,
1040 pub target_qualifier: String,
1041 #[serde(default = "default_include_descendants")]
1042 pub include_descendants: bool,
1043 pub assignments: Vec<(String, Expr)>,
1044 pub r#where: Option<Expr>,
1045 pub with: Vec<CTE>,
1047 pub from: Option<FromClause>,
1050 pub returning: Vec<Projection>,
1052 pub returning_aliases: ReturningAliases,
1053}
1054
1055#[derive(Debug, Clone, Serialize, Deserialize)]
1056pub struct DeleteStmt {
1057 pub table: String,
1058 pub target_qualifier: String,
1059 #[serde(default = "default_include_descendants")]
1060 pub include_descendants: bool,
1061 pub r#where: Option<Expr>,
1062 pub with: Vec<CTE>,
1064 pub using: Option<FromClause>,
1068 pub returning: Vec<Projection>,
1070 pub returning_aliases: ReturningAliases,
1071}
1072
1073#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1074pub struct SetConstraintName {
1075 pub catalog: Option<String>,
1076 pub schema: Option<String>,
1077 pub name: String,
1078}
1079
1080#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1082pub struct VacuumOption {
1083 pub name: String,
1084 pub value: Option<VacuumOptionValue>,
1085}
1086
1087#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1088pub enum VacuumOptionValue {
1089 Boolean(bool),
1090 Integer(i32),
1091 String(String),
1092}
1093
1094#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1096pub struct VacuumTarget {
1097 pub catalog: Option<String>,
1098 pub table: String,
1099 #[serde(default = "default_include_descendants")]
1100 pub include_descendants: bool,
1101 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1102 pub columns: Vec<String>,
1103}
1104
1105#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1106pub struct VacuumStmt {
1107 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1108 pub options: Vec<VacuumOption>,
1109 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1110 pub targets: Vec<VacuumTarget>,
1111}
1112
1113#[derive(Debug, Clone, Serialize, Deserialize)]
1114pub enum Statement {
1115 CreateTable(CreateTable),
1116 CreateIndex(CreateIndex),
1117 Insert(InsertStmt),
1118 Select(Box<SelectStmt>),
1122 Update(UpdateStmt),
1123 Delete(DeleteStmt),
1124 Drop(DropStmt),
1125 AlterTable(AlterTableStmt),
1126 AlterViewOptions(AlterViewOptionsStmt),
1127 CreateView {
1129 name: String,
1130 #[serde(default)]
1131 column_names: Vec<String>,
1132 body: Box<SelectStmt>,
1133 or_replace: bool,
1134 #[serde(default)]
1135 persistence: RelationPersistence,
1136 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1138 options: Vec<(String, String)>,
1139 },
1140 CreateMaterializedView {
1142 name: String,
1143 #[serde(default)]
1144 column_names: Vec<String>,
1145 #[serde(default)]
1146 if_not_exists: bool,
1147 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1148 with_no_data: bool,
1149 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1150 options: Vec<(String, String)>,
1151 body: Box<SelectStmt>,
1152 },
1153 RefreshMaterializedView {
1155 name: String,
1156 concurrently: bool,
1157 with_no_data: bool,
1158 },
1159 CreateSchema {
1163 name: String,
1164 if_not_exists: bool,
1165 },
1166 SetVariable {
1170 name: String,
1171 value: String,
1172 },
1173 ResetVariable {
1175 name: String,
1176 },
1177 ResetAllVariables,
1179 SetConstraints {
1181 constraints: Vec<SetConstraintName>,
1182 deferred: bool,
1183 },
1184 ShowVariable {
1187 name: String,
1188 },
1189 Discard {
1192 target: DiscardTarget,
1193 },
1194 Load {
1199 library: String,
1200 },
1201 Explain {
1204 analyze: bool,
1205 verbose: bool,
1206 format: Option<String>,
1207 body: Box<Statement>,
1208 },
1209 Analyze {
1212 table: Option<String>,
1213 },
1214 Vacuum(VacuumStmt),
1216 Truncate {
1219 tables: Vec<TruncateTarget>,
1220 cascade: bool,
1221 #[serde(default)]
1222 restart_identity: bool,
1223 },
1224 Transaction(TransactionStmt),
1226 DeclareCursor(DeclareCursorStmt),
1228 FetchCursor(FetchCursorStmt),
1230 CloseCursor {
1232 name: Option<String>,
1233 },
1234 CreateSequence(CreateSequence),
1236 AlterSequence(AlterSequence),
1239 CreateTableAs {
1241 name: String,
1242 if_not_exists: bool,
1243 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1244 column_names: Vec<String>,
1245 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1246 with_no_data: bool,
1247 #[serde(default)]
1248 persistence: RelationPersistence,
1249 #[serde(default)]
1250 on_commit: OnCommitAction,
1251 body: Box<SelectStmt>,
1252 },
1253 Prepare {
1255 name: String,
1256 body: Box<Statement>,
1257 },
1258 Execute {
1260 name: String,
1261 params: Vec<Expr>,
1262 },
1263 Deallocate {
1265 name: Option<String>,
1266 },
1267 Values {
1270 rows: Vec<Vec<Expr>>,
1271 },
1272 CreateForeignServer(CreateForeignServer),
1274 CreateForeignTable(CreateForeignTable),
1276 Merge(MergeStmt),
1279 CreateFunction(Box<CreateFunction>),
1282 DropFunction(DropFunctionStmt),
1284 AlterRoutine(AlterRoutineStmt),
1286 AlterRoutineOwner(AlterRoutineOwnerStmt),
1287 GrantRoutine(GrantRoutineStmt),
1288 CreateRole(CreateRoleStmt),
1289 AlterRole(AlterRoleStmt),
1290 DropRole(DropRoleStmt),
1291 CreateTrigger(CreateTrigger),
1293 DropTrigger(DropTrigger),
1295 CreateRule(CreateRule),
1297 DropRule(DropRule),
1299 DoBlock {
1301 language: String,
1302 body: String,
1303 },
1304 Call {
1307 name: String,
1308 args: Vec<Expr>,
1309 },
1310}
1311
1312#[derive(Debug, Clone, Serialize, Deserialize)]
1313pub struct TruncateTarget {
1314 pub table: String,
1315 #[serde(default = "default_include_descendants")]
1316 pub include_descendants: bool,
1317}
1318
1319#[derive(Debug, Clone, Serialize, Deserialize)]
1320pub struct MergeStmt {
1321 pub target: String,
1322 pub target_qualifier: String,
1323 pub target_alias: Option<String>,
1324 #[serde(default = "default_include_descendants")]
1325 pub include_descendants: bool,
1326 pub source: FromClause,
1327 pub join_condition: Expr,
1328 pub when_clauses: Vec<MergeWhen>,
1329 pub returning: Vec<Projection>,
1331 pub returning_aliases: ReturningAliases,
1332}
1333
1334#[derive(Debug, Clone, Serialize, Deserialize)]
1335pub enum MergeWhen {
1336 UpdateMatched {
1338 condition: Option<Expr>,
1339 assignments: Vec<(String, Expr)>,
1340 },
1341 DeleteMatched { condition: Option<Expr> },
1343 UpdateNotMatchedBySource {
1345 condition: Option<Expr>,
1346 assignments: Vec<(String, Expr)>,
1347 },
1348 DeleteNotMatchedBySource { condition: Option<Expr> },
1350 InsertNotMatched {
1352 condition: Option<Expr>,
1353 columns: Vec<String>,
1354 values: Vec<Expr>,
1355 },
1356 NothingMatched { condition: Option<Expr> },
1358 NothingNotMatched { condition: Option<Expr> },
1360 NothingNotMatchedBySource { condition: Option<Expr> },
1362}
1363
1364#[derive(Debug, Clone, Serialize, Deserialize)]
1365pub struct CreateForeignServer {
1366 pub name: String,
1367 pub fdw_type: String,
1368 pub options: Vec<(String, String)>,
1369 pub if_not_exists: bool,
1370}
1371
1372#[derive(Debug, Clone, Serialize, Deserialize)]
1373pub struct CreateForeignTable {
1374 pub name: String,
1375 pub server_name: String,
1376 pub columns: Vec<ColumnDef>,
1377 pub options: Vec<(String, String)>,
1378 pub if_not_exists: bool,
1379}
1380
1381#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1382pub enum TransactionIsolationLevel {
1383 ReadUncommitted,
1384 ReadCommitted,
1385 RepeatableRead,
1386 Serializable,
1387}
1388
1389impl TransactionIsolationLevel {
1390 #[must_use]
1391 pub const fn as_str(self) -> &'static str {
1392 match self {
1393 Self::ReadUncommitted => "read uncommitted",
1394 Self::ReadCommitted => "read committed",
1395 Self::RepeatableRead => "repeatable read",
1396 Self::Serializable => "serializable",
1397 }
1398 }
1399}
1400
1401#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1402pub struct TransactionCharacteristics {
1403 pub isolation: Option<TransactionIsolationLevel>,
1404 pub read_only: Option<bool>,
1405 pub deferrable: Option<bool>,
1406}
1407
1408#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1409pub enum TransactionStmt {
1410 Begin,
1411 BeginWithCharacteristics(TransactionCharacteristics),
1412 Commit,
1413 CommitAndChain,
1414 Rollback,
1415 RollbackAndChain,
1416 SetCharacteristics(TransactionCharacteristics),
1417 SetSessionCharacteristics(TransactionCharacteristics),
1418 SetSnapshot(String),
1419 Savepoint(String),
1420 ReleaseSavepoint(String),
1421 RollbackToSavepoint(String),
1422}
1423
1424#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1425pub enum CursorDirection {
1426 Forward,
1427 Backward,
1428 Absolute,
1429 Relative,
1430}
1431
1432#[derive(Debug, Clone, Serialize, Deserialize)]
1433pub struct DeclareCursorStmt {
1434 pub name: String,
1435 pub binary: bool,
1436 pub scroll: Option<bool>,
1438 pub hold: bool,
1439 pub query: Box<SelectStmt>,
1440}
1441
1442#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1443pub struct FetchCursorStmt {
1444 pub name: String,
1445 pub direction: CursorDirection,
1446 pub count: i64,
1448 pub move_only: bool,
1449}
1450
1451#[cfg(test)]
1452mod tests;