surrealdb_core/sql/
graph.rs1use crate::sql::cond::Cond;
2use crate::sql::dir::Dir;
3use crate::sql::field::Fields;
4use crate::sql::group::Groups;
5use crate::sql::idiom::Idiom;
6use crate::sql::limit::Limit;
7use crate::sql::order::{OldOrders, Order, OrderList, Ordering};
8use crate::sql::split::Splits;
9use crate::sql::start::Start;
10use crate::sql::table::Tables;
11use revision::revisioned;
12use serde::{Deserialize, Serialize};
13use std::fmt::{self, Display, Formatter, Write};
14
15#[revisioned(revision = 3)]
16#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
17#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
18#[non_exhaustive]
19pub struct Graph {
20 pub dir: Dir,
21 #[revision(end = 3, convert_fn = "convert_old_expr")]
22 pub old_expr: Fields,
23 #[revision(start = 3)]
24 pub expr: Option<Fields>,
25 pub what: Tables,
26 pub cond: Option<Cond>,
27 pub split: Option<Splits>,
28 pub group: Option<Groups>,
29 #[revision(end = 2, convert_fn = "convert_old_orders")]
30 pub old_order: Option<OldOrders>,
31 #[revision(start = 2)]
32 pub order: Option<Ordering>,
33 pub limit: Option<Limit>,
34 pub start: Option<Start>,
35 pub alias: Option<Idiom>,
36}
37
38impl Graph {
39 fn convert_old_orders(
40 &mut self,
41 _rev: u16,
42 old_value: Option<OldOrders>,
43 ) -> Result<(), revision::Error> {
44 let Some(x) = old_value else {
45 return Ok(());
47 };
48
49 if x.0.iter().any(|x| x.random) {
50 self.order = Some(Ordering::Random);
51 return Ok(());
52 }
53
54 let new_ord =
55 x.0.into_iter()
56 .map(|x| Order {
57 value: x.order,
58 collate: x.collate,
59 numeric: x.numeric,
60 direction: x.direction,
61 })
62 .collect();
63
64 self.order = Some(Ordering::Order(OrderList(new_ord)));
65
66 Ok(())
67 }
68
69 fn convert_old_expr(&mut self, _rev: u16, _old_value: Fields) -> Result<(), revision::Error> {
70 self.expr = None;
73 Ok(())
74 }
75
76 pub fn to_raw(&self) -> String {
78 self.to_string()
79 }
80}
81
82impl Display for Graph {
83 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
84 if self.what.0.len() <= 1 && self.cond.is_none() && self.alias.is_none() {
85 Display::fmt(&self.dir, f)?;
86 match self.what.len() {
87 0 => f.write_char('?'),
88 _ => Display::fmt(&self.what, f),
89 }
90 } else {
91 write!(f, "{}(", self.dir)?;
92 match self.what.len() {
93 0 => f.write_char('?'),
94 _ => Display::fmt(&self.what, f),
95 }?;
96 if let Some(ref v) = self.cond {
97 write!(f, " {v}")?
98 }
99 if let Some(ref v) = self.split {
100 write!(f, " {v}")?
101 }
102 if let Some(ref v) = self.group {
103 write!(f, " {v}")?
104 }
105 if let Some(ref v) = self.order {
106 write!(f, " {v}")?
107 }
108 if let Some(ref v) = self.limit {
109 write!(f, " {v}")?
110 }
111 if let Some(ref v) = self.start {
112 write!(f, " {v}")?
113 }
114 if let Some(ref v) = self.alias {
115 write!(f, " AS {v}")?
116 }
117 f.write_char(')')
118 }
119 }
120}