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 RenameRule {
832 from: String,
833 to: String,
834 },
835 SetTriggerEnableMode {
836 name: Option<String>,
837 user_only: bool,
838 mode: EventEnableMode,
839 },
840 SetRuleEnableMode {
841 name: String,
842 mode: EventEnableMode,
843 },
844 SetDefault {
845 name: String,
846 default: Expr,
847 },
848 DropDefault {
849 name: String,
850 },
851 SetExpression {
852 name: String,
853 expression: Expr,
854 },
855 DropExpression {
856 name: String,
857 },
858 SetNotNull {
859 name: String,
860 },
861 DropNotNull {
862 name: String,
863 },
864 AlterColumnType {
865 name: String,
866 ty: ColumnType,
867 #[serde(default, skip_serializing_if = "Option::is_none")]
868 using: Option<Expr>,
869 },
870}
871
872#[derive(Debug, Clone, Serialize, Deserialize)]
873pub struct InsertStmt {
874 pub table: String,
875 pub target_qualifier: String,
877 #[serde(default = "default_include_descendants")]
878 pub include_descendants: bool,
879 pub columns: Vec<String>,
880 pub with: Vec<CTE>,
882 pub rows: Vec<Vec<ValueExpr>>,
886 pub select_source: Option<Box<SelectStmt>>,
890 pub on_conflict: Option<OnConflict>,
893 pub returning: Vec<Projection>,
895 pub returning_aliases: ReturningAliases,
898}
899
900#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
901pub struct ReturningAliases {
902 pub old: String,
903 pub new: String,
904 #[serde(default)]
905 pub old_explicit: bool,
906 #[serde(default)]
907 pub new_explicit: bool,
908}
909
910impl Default for ReturningAliases {
911 fn default() -> Self {
912 Self {
913 old: "old".into(),
914 new: "new".into(),
915 old_explicit: false,
916 new_explicit: false,
917 }
918 }
919}
920
921#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
922pub struct OnConflict {
923 pub conflict_columns: Vec<String>,
927 pub action: OnConflictAction,
928}
929
930#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
931pub enum OnConflictAction {
932 Nothing,
934 Update {
938 assignments: Vec<(String, Expr)>,
939 r#where: Option<Expr>,
940 },
941}
942
943#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
944pub struct SelectStmt {
945 pub projections: Vec<Projection>,
946 #[serde(default, skip_serializing_if = "Vec::is_empty")]
950 pub values: Vec<Vec<Expr>>,
951 pub from: Option<FromClause>,
952 pub r#where: Option<Expr>,
953 pub group_by: Vec<Expr>,
954 pub grouping_sets: Vec<Vec<Expr>>,
960 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
962 pub group_distinct: bool,
963 pub having: Option<Expr>,
967 pub order_by: Vec<OrderBy>,
968 pub limit: Option<Expr>,
972 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
974 pub with_ties: bool,
975 pub offset: Option<Expr>,
977 pub with: Vec<CTE>,
979 pub set_op: Option<Box<SetOp>>,
983 pub distinct: bool,
986 pub distinct_on: Vec<Expr>,
989 #[serde(default, skip_serializing_if = "Vec::is_empty")]
991 pub locking: Vec<LockingClause>,
992}
993
994#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
995pub struct SetOp {
996 pub kind: SetOpKind,
997 pub all: bool,
998 #[serde(default, skip_serializing_if = "Option::is_none")]
1002 pub left: Option<Box<SelectStmt>>,
1003 pub right: SelectStmt,
1004 pub combined_order_by: Vec<OrderBy>,
1007 pub combined_limit: Option<Expr>,
1010 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1012 pub combined_with_ties: bool,
1013 pub combined_offset: Option<Expr>,
1015}
1016
1017#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1018pub enum SetOpKind {
1019 Union,
1020 Intersect,
1021 Except,
1022}
1023
1024#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1026pub enum DiscardTarget {
1027 All,
1028 Plans,
1029 Sequences,
1030 Temp,
1031}
1032
1033#[derive(Debug, Clone, Serialize, Deserialize)]
1034pub struct UpdateStmt {
1035 pub table: String,
1036 pub target_qualifier: String,
1037 #[serde(default = "default_include_descendants")]
1038 pub include_descendants: bool,
1039 pub assignments: Vec<(String, Expr)>,
1040 pub r#where: Option<Expr>,
1041 pub with: Vec<CTE>,
1043 pub from: Option<FromClause>,
1046 pub returning: Vec<Projection>,
1048 pub returning_aliases: ReturningAliases,
1049}
1050
1051#[derive(Debug, Clone, Serialize, Deserialize)]
1052pub struct DeleteStmt {
1053 pub table: String,
1054 pub target_qualifier: String,
1055 #[serde(default = "default_include_descendants")]
1056 pub include_descendants: bool,
1057 pub r#where: Option<Expr>,
1058 pub with: Vec<CTE>,
1060 pub using: Option<FromClause>,
1064 pub returning: Vec<Projection>,
1066 pub returning_aliases: ReturningAliases,
1067}
1068
1069#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1070pub struct SetConstraintName {
1071 pub catalog: Option<String>,
1072 pub schema: Option<String>,
1073 pub name: String,
1074}
1075
1076#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1078pub struct VacuumOption {
1079 pub name: String,
1080 pub value: Option<VacuumOptionValue>,
1081}
1082
1083#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1084pub enum VacuumOptionValue {
1085 Boolean(bool),
1086 Integer(i32),
1087 String(String),
1088}
1089
1090#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1092pub struct VacuumTarget {
1093 pub catalog: Option<String>,
1094 pub table: String,
1095 #[serde(default = "default_include_descendants")]
1096 pub include_descendants: bool,
1097 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1098 pub columns: Vec<String>,
1099}
1100
1101#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1102pub struct VacuumStmt {
1103 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1104 pub options: Vec<VacuumOption>,
1105 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1106 pub targets: Vec<VacuumTarget>,
1107}
1108
1109#[derive(Debug, Clone, Serialize, Deserialize)]
1110pub enum Statement {
1111 CreateTable(CreateTable),
1112 CreateIndex(CreateIndex),
1113 Insert(InsertStmt),
1114 Select(Box<SelectStmt>),
1118 Update(UpdateStmt),
1119 Delete(DeleteStmt),
1120 Drop(DropStmt),
1121 AlterTable(AlterTableStmt),
1122 AlterViewOptions(AlterViewOptionsStmt),
1123 CreateView {
1125 name: String,
1126 #[serde(default)]
1127 column_names: Vec<String>,
1128 body: Box<SelectStmt>,
1129 or_replace: bool,
1130 #[serde(default)]
1131 persistence: RelationPersistence,
1132 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1134 options: Vec<(String, String)>,
1135 },
1136 CreateMaterializedView {
1138 name: String,
1139 #[serde(default)]
1140 column_names: Vec<String>,
1141 #[serde(default)]
1142 if_not_exists: bool,
1143 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1144 with_no_data: bool,
1145 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1146 options: Vec<(String, String)>,
1147 body: Box<SelectStmt>,
1148 },
1149 RefreshMaterializedView {
1151 name: String,
1152 concurrently: bool,
1153 with_no_data: bool,
1154 },
1155 CreateSchema {
1159 name: String,
1160 if_not_exists: bool,
1161 },
1162 SetVariable {
1166 name: String,
1167 value: String,
1168 },
1169 ResetVariable {
1171 name: String,
1172 },
1173 ResetAllVariables,
1175 SetConstraints {
1177 constraints: Vec<SetConstraintName>,
1178 deferred: bool,
1179 },
1180 ShowVariable {
1183 name: String,
1184 },
1185 Discard {
1188 target: DiscardTarget,
1189 },
1190 Load {
1195 library: String,
1196 },
1197 Explain {
1200 analyze: bool,
1201 verbose: bool,
1202 format: Option<String>,
1203 body: Box<Statement>,
1204 },
1205 Analyze {
1208 table: Option<String>,
1209 },
1210 Vacuum(VacuumStmt),
1212 Truncate {
1215 tables: Vec<TruncateTarget>,
1216 cascade: bool,
1217 #[serde(default)]
1218 restart_identity: bool,
1219 },
1220 Transaction(TransactionStmt),
1222 DeclareCursor(DeclareCursorStmt),
1224 FetchCursor(FetchCursorStmt),
1226 CloseCursor {
1228 name: Option<String>,
1229 },
1230 CreateSequence(CreateSequence),
1232 AlterSequence(AlterSequence),
1235 CreateTableAs {
1237 name: String,
1238 if_not_exists: bool,
1239 #[serde(default, skip_serializing_if = "Vec::is_empty")]
1240 column_names: Vec<String>,
1241 #[serde(default, skip_serializing_if = "std::ops::Not::not")]
1242 with_no_data: bool,
1243 #[serde(default)]
1244 persistence: RelationPersistence,
1245 #[serde(default)]
1246 on_commit: OnCommitAction,
1247 body: Box<SelectStmt>,
1248 },
1249 Prepare {
1251 name: String,
1252 body: Box<Statement>,
1253 },
1254 Execute {
1256 name: String,
1257 params: Vec<Expr>,
1258 },
1259 Deallocate {
1261 name: Option<String>,
1262 },
1263 Values {
1266 rows: Vec<Vec<Expr>>,
1267 },
1268 CreateForeignServer(CreateForeignServer),
1270 CreateForeignTable(CreateForeignTable),
1272 Merge(MergeStmt),
1275 CreateFunction(Box<CreateFunction>),
1278 DropFunction(DropFunctionStmt),
1280 AlterRoutine(AlterRoutineStmt),
1282 AlterRoutineOwner(AlterRoutineOwnerStmt),
1283 GrantRoutine(GrantRoutineStmt),
1284 CreateRole(CreateRoleStmt),
1285 AlterRole(AlterRoleStmt),
1286 DropRole(DropRoleStmt),
1287 CreateTrigger(CreateTrigger),
1289 DropTrigger(DropTrigger),
1291 CreateRule(CreateRule),
1293 DropRule(DropRule),
1295 DoBlock {
1297 language: String,
1298 body: String,
1299 },
1300 Call {
1303 name: String,
1304 args: Vec<Expr>,
1305 },
1306}
1307
1308#[derive(Debug, Clone, Serialize, Deserialize)]
1309pub struct TruncateTarget {
1310 pub table: String,
1311 #[serde(default = "default_include_descendants")]
1312 pub include_descendants: bool,
1313}
1314
1315#[derive(Debug, Clone, Serialize, Deserialize)]
1316pub struct MergeStmt {
1317 pub target: String,
1318 pub target_qualifier: String,
1319 pub target_alias: Option<String>,
1320 #[serde(default = "default_include_descendants")]
1321 pub include_descendants: bool,
1322 pub source: FromClause,
1323 pub join_condition: Expr,
1324 pub when_clauses: Vec<MergeWhen>,
1325 pub returning: Vec<Projection>,
1327 pub returning_aliases: ReturningAliases,
1328}
1329
1330#[derive(Debug, Clone, Serialize, Deserialize)]
1331pub enum MergeWhen {
1332 UpdateMatched {
1334 condition: Option<Expr>,
1335 assignments: Vec<(String, Expr)>,
1336 },
1337 DeleteMatched { condition: Option<Expr> },
1339 UpdateNotMatchedBySource {
1341 condition: Option<Expr>,
1342 assignments: Vec<(String, Expr)>,
1343 },
1344 DeleteNotMatchedBySource { condition: Option<Expr> },
1346 InsertNotMatched {
1348 condition: Option<Expr>,
1349 columns: Vec<String>,
1350 values: Vec<Expr>,
1351 },
1352 NothingMatched { condition: Option<Expr> },
1354 NothingNotMatched { condition: Option<Expr> },
1356 NothingNotMatchedBySource { condition: Option<Expr> },
1358}
1359
1360#[derive(Debug, Clone, Serialize, Deserialize)]
1361pub struct CreateForeignServer {
1362 pub name: String,
1363 pub fdw_type: String,
1364 pub options: Vec<(String, String)>,
1365 pub if_not_exists: bool,
1366}
1367
1368#[derive(Debug, Clone, Serialize, Deserialize)]
1369pub struct CreateForeignTable {
1370 pub name: String,
1371 pub server_name: String,
1372 pub columns: Vec<ColumnDef>,
1373 pub options: Vec<(String, String)>,
1374 pub if_not_exists: bool,
1375}
1376
1377#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1378pub enum TransactionIsolationLevel {
1379 ReadUncommitted,
1380 ReadCommitted,
1381 RepeatableRead,
1382 Serializable,
1383}
1384
1385impl TransactionIsolationLevel {
1386 #[must_use]
1387 pub const fn as_str(self) -> &'static str {
1388 match self {
1389 Self::ReadUncommitted => "read uncommitted",
1390 Self::ReadCommitted => "read committed",
1391 Self::RepeatableRead => "repeatable read",
1392 Self::Serializable => "serializable",
1393 }
1394 }
1395}
1396
1397#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
1398pub struct TransactionCharacteristics {
1399 pub isolation: Option<TransactionIsolationLevel>,
1400 pub read_only: Option<bool>,
1401 pub deferrable: Option<bool>,
1402}
1403
1404#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1405pub enum TransactionStmt {
1406 Begin,
1407 BeginWithCharacteristics(TransactionCharacteristics),
1408 Commit,
1409 CommitAndChain,
1410 Rollback,
1411 RollbackAndChain,
1412 SetCharacteristics(TransactionCharacteristics),
1413 SetSessionCharacteristics(TransactionCharacteristics),
1414 SetSnapshot(String),
1415 Savepoint(String),
1416 ReleaseSavepoint(String),
1417 RollbackToSavepoint(String),
1418}
1419
1420#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
1421pub enum CursorDirection {
1422 Forward,
1423 Backward,
1424 Absolute,
1425 Relative,
1426}
1427
1428#[derive(Debug, Clone, Serialize, Deserialize)]
1429pub struct DeclareCursorStmt {
1430 pub name: String,
1431 pub binary: bool,
1432 pub scroll: Option<bool>,
1434 pub hold: bool,
1435 pub query: Box<SelectStmt>,
1436}
1437
1438#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
1439pub struct FetchCursorStmt {
1440 pub name: String,
1441 pub direction: CursorDirection,
1442 pub count: i64,
1444 pub move_only: bool,
1445}
1446
1447#[cfg(test)]
1448mod tests;