Skip to main content

surql_parser/upstream/sql/record_id/
key.rs

1use crate::compat::types::{PublicRecordIdKey, PublicUuid};
2use crate::upstream::fmt::{CoverStmts, EscapeObjectKey, EscapeRidKey, Fmt};
3use crate::upstream::sql::literal::ObjectEntry;
4use crate::upstream::sql::{Expr, RecordIdKeyRangeLit};
5use std::ops::Bound;
6use surrealdb_types::{SqlFormat, ToSql, write_sql};
7#[derive(Clone, Debug, Eq, PartialEq, Hash)]
8#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
9pub enum RecordIdKeyGen {
10	Rand,
11	Ulid,
12	Uuid,
13}
14#[derive(Clone, Debug, PartialEq, Eq)]
15#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
16pub enum RecordIdKeyLit {
17	Number(i64),
18	String(String),
19	Uuid(PublicUuid),
20	Array(Vec<Expr>),
21	Object(Vec<ObjectEntry>),
22	Generate(RecordIdKeyGen),
23	Range(Box<RecordIdKeyRangeLit>),
24}
25impl RecordIdKeyLit {
26	pub fn from_record_id_key(key: PublicRecordIdKey) -> Self {
27		match key {
28			PublicRecordIdKey::Number(x) => RecordIdKeyLit::Number(x),
29			PublicRecordIdKey::String(x) => RecordIdKeyLit::String(x),
30			PublicRecordIdKey::Uuid(x) => RecordIdKeyLit::Uuid(x),
31			PublicRecordIdKey::Array(x) => {
32				RecordIdKeyLit::Array(x.into_iter().map(Expr::from_public_value).collect())
33			}
34			PublicRecordIdKey::Object(x) => RecordIdKeyLit::Object(
35				x.into_iter()
36					.map(|(k, v)| ObjectEntry {
37						key: k,
38						value: Expr::from_public_value(v),
39					})
40					.collect(),
41			),
42			PublicRecordIdKey::Range(x) => {
43				let range = x.into_inner();
44				RecordIdKeyLit::Range(Box::new(RecordIdKeyRangeLit {
45					start: match range.0 {
46						Bound::Included(x) => Bound::Included(Self::from_record_id_key(x)),
47						Bound::Excluded(x) => Bound::Excluded(Self::from_record_id_key(x)),
48						Bound::Unbounded => Bound::Unbounded,
49					},
50					end: match range.1 {
51						Bound::Included(x) => Bound::Included(Self::from_record_id_key(x)),
52						Bound::Excluded(x) => Bound::Excluded(Self::from_record_id_key(x)),
53						Bound::Unbounded => Bound::Unbounded,
54					},
55				}))
56			}
57		}
58	}
59}
60impl ToSql for RecordIdKeyLit {
61	fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
62		match self {
63			Self::Number(v) => write_sql!(f, fmt, "{v}"),
64			Self::String(v) => EscapeRidKey(v).fmt_sql(f, fmt),
65			Self::Uuid(v) => v.fmt_sql(f, fmt),
66			Self::Array(v) => {
67				f.push('[');
68				if !v.is_empty() {
69					let fmt = fmt.increment();
70					write_sql!(
71						f,
72						fmt,
73						"{}",
74						Fmt::pretty_comma_separated(v.iter().map(CoverStmts))
75					);
76				}
77				f.push(']');
78			}
79			Self::Object(v) => {
80				if fmt.is_pretty() {
81					f.push('{');
82				} else {
83					f.push_str("{ ");
84				}
85				if !v.is_empty() {
86					let fmt = fmt.increment();
87					write_sql!(
88						f,
89						fmt,
90						"{}",
91						Fmt::pretty_comma_separated(v.iter().map(|args| Fmt::new(
92							args,
93							|entry, f, fmt| write_sql!(
94								f,
95								fmt,
96								"{}: {}",
97								EscapeObjectKey(&entry.key),
98								CoverStmts(&entry.value)
99							)
100						)),)
101					);
102				}
103				if fmt.is_pretty() {
104					f.push('}');
105				} else {
106					f.push_str(" }");
107				}
108			}
109			Self::Generate(v) => match v {
110				RecordIdKeyGen::Rand => f.push_str("rand()"),
111				RecordIdKeyGen::Ulid => f.push_str("ulid()"),
112				RecordIdKeyGen::Uuid => f.push_str("uuid()"),
113			},
114			Self::Range(v) => v.fmt_sql(f, fmt),
115		}
116	}
117}