surrealdb_core/sql/
order.rs

1use crate::sql::fmt::Fmt;
2use crate::sql::idiom::Idiom;
3use crate::sql::Value;
4use revision::revisioned;
5use serde::{Deserialize, Serialize};
6use std::ops::Deref;
7use std::{cmp, fmt};
8
9#[revisioned(revision = 1)]
10#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
11#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
12#[non_exhaustive]
13pub enum Ordering {
14	Random,
15	Order(OrderList),
16}
17
18impl fmt::Display for Ordering {
19	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
20		match self {
21			Ordering::Random => write!(f, "ORDER BY RAND()"),
22			Ordering::Order(list) => writeln!(f, "ORDER BY {list}"),
23		}
24	}
25}
26
27#[revisioned(revision = 1)]
28#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
29#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
30#[non_exhaustive]
31pub struct OrderList(pub Vec<Order>);
32
33impl Deref for OrderList {
34	type Target = Vec<Order>;
35	fn deref(&self) -> &Self::Target {
36		&self.0
37	}
38}
39
40impl fmt::Display for OrderList {
41	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42		write!(f, "{}", Fmt::comma_separated(&self.0))
43	}
44}
45
46impl OrderList {
47	pub(crate) fn compare(&self, a: &Value, b: &Value) -> cmp::Ordering {
48		for order in &self.0 {
49			// Reverse the ordering if DESC
50			let o = match order.direction {
51				true => a.compare(b, &order.value.0, order.collate, order.numeric),
52				false => b.compare(a, &order.value.0, order.collate, order.numeric),
53			};
54			//
55			match o {
56				Some(cmp::Ordering::Greater) => return cmp::Ordering::Greater,
57				Some(cmp::Ordering::Equal) => continue,
58				Some(cmp::Ordering::Less) => return cmp::Ordering::Less,
59				None => continue,
60			}
61		}
62		cmp::Ordering::Equal
63	}
64}
65
66#[revisioned(revision = 1)]
67#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
68#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
69#[non_exhaustive]
70pub struct Order {
71	/// The value to order by
72	pub value: Idiom,
73	pub collate: bool,
74	pub numeric: bool,
75	/// true if the direction is ascending
76	pub direction: bool,
77}
78
79impl fmt::Display for Order {
80	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81		write!(f, "{}", self.value)?;
82		if self.collate {
83			write!(f, " COLLATE")?;
84		}
85		if self.numeric {
86			write!(f, " NUMERIC")?;
87		}
88		if !self.direction {
89			write!(f, " DESC")?;
90		}
91		Ok(())
92	}
93}
94
95#[revisioned(revision = 1)]
96#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
97#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
98#[non_exhaustive]
99pub struct OldOrders(pub Vec<OldOrder>);
100
101#[revisioned(revision = 1)]
102#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
103#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
104#[non_exhaustive]
105pub struct OldOrder {
106	pub order: Idiom,
107	pub random: bool,
108	pub collate: bool,
109	pub numeric: bool,
110	/// true if the direction is ascending
111	pub direction: bool,
112}