Skip to main content

surrealdb_expr/expr/
order.rs

1use std::cmp;
2use std::ops::Deref;
3
4use surrealdb_types::{SqlFormat, ToSql};
5
6use crate::expr::Value;
7use crate::expr::idiom::Idiom;
8
9#[derive(Clone, Debug, Eq, PartialEq, Hash)]
10pub enum Ordering {
11	Random,
12	Order(OrderList),
13}
14
15impl Ordering {
16	/// Whether evaluating the ordering can be done on a read-only transaction.
17	pub fn read_only(&self) -> bool {
18		match self {
19			Ordering::Random => true,
20			Ordering::Order(list) => list.read_only(),
21		}
22	}
23}
24
25impl ToSql for Ordering {
26	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
27		let sql_ordering: crate::sql::order::Ordering = self.clone().into();
28		sql_ordering.fmt_sql(f, sql_fmt);
29	}
30}
31
32#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
33pub struct OrderList(pub Vec<Order>);
34
35impl OrderList {
36	/// Whether evaluating every ordering key can be done on a read-only
37	/// transaction.
38	pub fn read_only(&self) -> bool {
39		self.0.iter().all(|x| x.value.read_only())
40	}
41}
42
43impl Deref for OrderList {
44	type Target = Vec<Order>;
45	fn deref(&self) -> &Self::Target {
46		&self.0
47	}
48}
49
50impl ToSql for OrderList {
51	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
52		let sql_order_list: crate::sql::order::OrderList = self.clone().into();
53		sql_order_list.fmt_sql(f, sql_fmt);
54	}
55}
56
57impl OrderList {
58	pub fn compare(&self, a: &Value, b: &Value) -> cmp::Ordering {
59		for order in &self.0 {
60			// Reverse the ordering if DESC
61			let o = if order.direction {
62				a.compare(b, &order.value.0, order.collate, order.numeric)
63			} else {
64				b.compare(a, &order.value.0, order.collate, order.numeric)
65			};
66			//
67			match o {
68				None | Some(cmp::Ordering::Equal) => continue,
69				Some(cmp::Ordering::Greater) => return cmp::Ordering::Greater,
70				Some(cmp::Ordering::Less) => return cmp::Ordering::Less,
71			}
72		}
73		cmp::Ordering::Equal
74	}
75}
76
77impl IntoIterator for OrderList {
78	type Item = Order;
79	type IntoIter = std::vec::IntoIter<Self::Item>;
80	fn into_iter(self) -> Self::IntoIter {
81		self.0.into_iter()
82	}
83}
84
85#[derive(Clone, Debug, Default, Eq, PartialEq, Hash)]
86pub struct Order {
87	/// The value to order by
88	pub value: Idiom,
89	pub collate: bool,
90	pub numeric: bool,
91	/// true if the direction is ascending
92	pub direction: bool,
93}
94
95impl ToSql for Order {
96	fn fmt_sql(&self, f: &mut String, sql_fmt: SqlFormat) {
97		let sql_order: crate::sql::Order = self.clone().into();
98		sql_order.fmt_sql(f, sql_fmt);
99	}
100}