edgedb_query/queries/
conflict.rs1use edgedb_protocol::value::Value;
2use crate::{EdgeQl, ToEdgeQl, ToEdgeQuery, ToEdgeValue};
3
4
5const UNLESS_CONFLICT: &str = " unless conflict ";
6const ON: &str = "on ";
7const OPEN_PARENTHESIS: &str = "( ";
8const CLOSE_PARENTHESIS: &str = " ) ";
9const COMMA: &str = ", ";
10const ELSE: &str = "else ( ";
11
12pub trait Conflict<T: ToEdgeQuery + Clone> {
14 fn else_query(&self) -> Option<T>;
15}
16
17#[derive(Debug, Clone)]
19pub struct UnlessConflictElse<T: ToEdgeQuery> {
20 pub else_query: T
21}
22
23impl<T: ToEdgeQuery + Clone> Conflict<T> for UnlessConflictElse<T> {
24 fn else_query(&self) -> Option<T> {
25 Some(self.else_query.clone())
26 }
27}
28
29
30#[derive(Debug, Clone)]
32pub struct UnlessConflict;
33
34#[derive(Clone)]
35pub struct EmptyQuery;
36
37impl ToEdgeQl for EmptyQuery {
38 fn to_edgeql(&self) -> EdgeQl {
39 EdgeQl::default()
40 }
41}
42
43impl ToEdgeValue for EmptyQuery {
44 fn to_edge_value(&self) -> Value {
45 Value::Nothing
46 }
47}
48
49impl ToEdgeQuery for EmptyQuery{}
50
51impl Conflict<EmptyQuery> for UnlessConflict {
52 fn else_query(&self) -> Option<EmptyQuery> {
53 None
54 }
55}
56
57
58pub fn parse_conflict<T: ToEdgeQuery + Clone, R: Conflict<T>>(conflict: &R, on_fields: Vec<&str>) -> String {
95 let mut stmt = UNLESS_CONFLICT.to_owned();
96
97 if !on_fields.is_empty() {
98
99 stmt.push_str(ON);
100
101 if on_fields.len() > 1 {
102 stmt.push_str(OPEN_PARENTHESIS);
103 }
104
105 stmt.push_str(on_fields
106 .iter()
107 .map(|s| format!(".{s}"))
108 .collect::<Vec<String>>()
109 .join(COMMA).as_str()
110 );
111
112 if on_fields.len() > 1 {
113 stmt.push_str(CLOSE_PARENTHESIS);
114 } else {
115 stmt.push(' ');
116 }
117 }
118
119 if let Some(else_query)= conflict.else_query() {
120 stmt.push_str(ELSE);
121 stmt.push_str(else_query.to_edgeql().to_string().as_str());
122 stmt.push_str(CLOSE_PARENTHESIS);
123 }
124
125 stmt
126}
127