surrealdb_expr/expr/record_id/
key.rs1use std::ops::Bound;
2
3use surrealdb_strand::Strand;
4use surrealdb_types::{SqlFormat, ToSql};
5
6use crate::expr::literal::ObjectEntry;
7use crate::expr::{Expr, Kind, KindLiteral, RecordIdKeyRangeLit};
8use crate::val::{RecordIdKey, Uuid};
9
10#[derive(Clone, Debug, Eq, PartialEq, Hash)]
11pub enum RecordIdKeyGen {
12 Rand,
13 Ulid,
14 Uuid,
15}
16
17impl RecordIdKeyGen {
18 pub fn compute(&self) -> RecordIdKey {
19 match self {
20 RecordIdKeyGen::Rand => RecordIdKey::rand(),
21 RecordIdKeyGen::Ulid => RecordIdKey::ulid(),
22 RecordIdKeyGen::Uuid => RecordIdKey::uuid(),
23 }
24 }
25}
26
27#[derive(Clone, Debug, Eq, PartialEq, Hash)]
28pub enum RecordIdKeyLit {
29 Number(i64),
30 String(Strand),
31 Uuid(Uuid),
32 Array(Vec<Expr>),
33 Object(Vec<ObjectEntry>),
34 Generate(RecordIdKeyGen),
35 Range(Box<RecordIdKeyRangeLit>),
36}
37
38impl RecordIdKeyLit {
39 pub fn kind_supported(kind: &Kind) -> bool {
40 match kind {
41 Kind::Any => true,
42 Kind::Number => true,
43 Kind::Int => true,
44 Kind::String => true,
45 Kind::Uuid => true,
46 Kind::Array(_, _) => true,
47 Kind::Object => true,
48 Kind::Literal(l) => matches!(
49 l,
50 KindLiteral::Integer(_)
51 | KindLiteral::String(_)
52 | KindLiteral::Array(_)
53 | KindLiteral::Object(_)
54 ),
55 Kind::Either(x) => x.iter().all(RecordIdKeyLit::kind_supported),
56 _ => false,
57 }
58 }
59}
60
61impl From<RecordIdKeyRangeLit> for RecordIdKeyLit {
62 fn from(v: RecordIdKeyRangeLit) -> Self {
63 Self::Range(Box::new(v))
64 }
65}
66
67impl ToSql for RecordIdKeyLit {
68 fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
69 let sql_record_id_key_lit: crate::sql::RecordIdKeyLit = self.clone().into();
70 sql_record_id_key_lit.fmt_sql(f, fmt);
71 }
72}
73
74impl RecordIdKeyLit {
75 pub fn is_static(&self) -> bool {
76 match self {
77 RecordIdKeyLit::Number(_)
78 | RecordIdKeyLit::String(_)
79 | RecordIdKeyLit::Uuid(_)
80 | RecordIdKeyLit::Generate(_) => true,
81 RecordIdKeyLit::Range(record_id_key_range_lit) => record_id_key_range_lit.is_static(),
82 RecordIdKeyLit::Array(exprs) => exprs.iter().all(|x| x.is_static()),
83 RecordIdKeyLit::Object(items) => items.iter().all(|x| x.value.is_static()),
84 }
85 }
86
87 pub fn read_only(&self) -> bool {
89 match self {
90 RecordIdKeyLit::Number(_)
91 | RecordIdKeyLit::String(_)
92 | RecordIdKeyLit::Uuid(_)
93 | RecordIdKeyLit::Generate(_) => true,
94 RecordIdKeyLit::Range(record_id_key_range_lit) => record_id_key_range_lit.read_only(),
95 RecordIdKeyLit::Array(exprs) => exprs.iter().all(|x| x.read_only()),
96 RecordIdKeyLit::Object(items) => items.iter().all(|x| x.value.read_only()),
97 }
98 }
99}
100
101impl From<crate::types::PublicRecordIdKey> for RecordIdKeyLit {
102 fn from(value: crate::types::PublicRecordIdKey) -> Self {
103 match value {
104 crate::types::PublicRecordIdKey::Number(x) => Self::Number(x),
105 crate::types::PublicRecordIdKey::String(x) => Self::String(x.into()),
106 crate::types::PublicRecordIdKey::Uuid(x) => Self::Uuid(x.into()),
107 crate::types::PublicRecordIdKey::Array(x) => {
108 Self::Array(x.into_iter().map(Expr::from_public_value).collect())
109 }
110 crate::types::PublicRecordIdKey::Object(x) => Self::Object(
111 x.into_iter()
112 .map(|(k, v)| ObjectEntry {
113 key: k.into(),
114 value: Expr::from_public_value(v),
115 })
116 .collect(),
117 ),
118 crate::types::PublicRecordIdKey::Range(x) => {
119 Self::Range(Box::new(RecordIdKeyRangeLit {
120 start: match x.start {
121 Bound::Included(x) => Bound::Included(Self::from(x)),
122 Bound::Excluded(x) => Bound::Excluded(Self::from(x)),
123 Bound::Unbounded => Bound::Unbounded,
124 },
125 end: match x.end {
126 Bound::Included(x) => Bound::Included(Self::from(x)),
127 Bound::Excluded(x) => Bound::Excluded(Self::from(x)),
128 Bound::Unbounded => Bound::Unbounded,
129 },
130 }))
131 }
132 }
133 }
134}