1use serde::{Deserialize, Serialize};
10
11use super::{DeleteStmt, Expr, InsertStmt, MergeStmt, SelectStmt, Statement, UpdateStmt};
12
13#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
14pub struct CTE {
15 pub name: String,
16 pub columns: Vec<String>,
17 pub recursive: bool,
18 #[serde(default)]
19 pub materialization: CteMaterialization,
20 #[serde(default, skip_serializing_if = "Option::is_none")]
21 pub search: Option<CteSearchClause>,
22 #[serde(default, skip_serializing_if = "Option::is_none")]
23 pub cycle: Option<CteCycleClause>,
24 #[serde(flatten)]
25 pub body: CteBody,
26}
27
28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
30pub enum CteBody {
31 #[serde(rename = "query")]
32 Query(Box<SelectStmt>),
33 #[serde(rename = "insert")]
34 Insert(Box<InsertStmt>),
35 #[serde(rename = "update")]
36 Update(Box<UpdateStmt>),
37 #[serde(rename = "delete")]
38 Delete(Box<DeleteStmt>),
39 #[serde(rename = "merge")]
40 Merge(Box<MergeStmt>),
41}
42
43impl CteBody {
44 pub fn query(&self) -> Option<&SelectStmt> {
45 match self {
46 Self::Query(query) => Some(query),
47 _ => None,
48 }
49 }
50
51 pub fn query_mut(&mut self) -> Option<&mut SelectStmt> {
52 match self {
53 Self::Query(query) => Some(query),
54 _ => None,
55 }
56 }
57
58 pub const fn modifies_data(&self) -> bool {
59 !matches!(self, Self::Query(_))
60 }
61
62 pub fn returning(&self) -> Option<&[super::Projection]> {
63 match self {
64 Self::Query(_) => None,
65 Self::Insert(command) => Some(&command.returning),
66 Self::Update(command) => Some(&command.returning),
67 Self::Delete(command) => Some(&command.returning),
68 Self::Merge(command) => Some(&command.returning),
69 }
70 }
71
72 pub fn into_statement(self) -> Statement {
73 match self {
74 Self::Query(query) => Statement::Select(query),
75 Self::Insert(command) => Statement::Insert(*command),
76 Self::Update(command) => Statement::Update(*command),
77 Self::Delete(command) => Statement::Delete(*command),
78 Self::Merge(command) => Statement::Merge(*command),
79 }
80 }
81}
82
83impl TryFrom<Statement> for CteBody {
84 type Error = crate::SQLError;
85
86 fn try_from(statement: Statement) -> Result<Self, Self::Error> {
87 match statement {
88 Statement::Select(query) => Ok(Self::Query(query)),
89 Statement::Insert(command) => Ok(Self::Insert(Box::new(command))),
90 Statement::Update(command) => Ok(Self::Update(Box::new(command))),
91 Statement::Delete(command) => Ok(Self::Delete(Box::new(command))),
92 Statement::Merge(command) => Ok(Self::Merge(Box::new(command))),
93 _ => Err(crate::SQLError::Unsupported(
94 "WITH body must be a SELECT, INSERT, UPDATE, DELETE, or MERGE statement".into(),
95 )),
96 }
97 }
98}
99
100#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
102pub enum CteMaterialization {
103 #[default]
104 Default,
105 Materialized,
106 NotMaterialized,
107}
108
109#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
111pub struct CteSearchClause {
112 pub columns: Vec<String>,
113 pub breadth_first: bool,
114 pub sequence_column: String,
115}
116
117#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
119pub struct CteCycleClause {
120 pub columns: Vec<String>,
121 pub mark_column: String,
122 pub mark_value: Expr,
123 pub mark_default: Expr,
124 pub path_column: String,
125}