surrealdb_sql/
array.rs

1use crate::ctx::Context;
2use crate::dbs::{Options, Transaction};
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::{
6	fmt::{pretty_indent, Fmt, Pretty},
7	Number, Operation, Value,
8};
9use revision::revisioned;
10use serde::{Deserialize, Serialize};
11use std::collections::HashSet;
12use std::fmt::{self, Display, Formatter, Write};
13use std::ops;
14use std::ops::Deref;
15use std::ops::DerefMut;
16
17pub(crate) const TOKEN: &str = "$surrealdb::private::crate::Array";
18
19#[derive(Clone, Debug, Default, Eq, Ord, PartialEq, PartialOrd, Serialize, Deserialize, Hash)]
20#[serde(rename = "$surrealdb::private::crate::Array")]
21#[revisioned(revision = 1)]
22pub struct Array(pub Vec<Value>);
23
24impl From<Value> for Array {
25	fn from(v: Value) -> Self {
26		vec![v].into()
27	}
28}
29
30impl From<Vec<Value>> for Array {
31	fn from(v: Vec<Value>) -> Self {
32		Self(v)
33	}
34}
35
36impl From<Vec<i32>> for Array {
37	fn from(v: Vec<i32>) -> Self {
38		Self(v.into_iter().map(Value::from).collect())
39	}
40}
41
42impl From<Vec<f64>> for Array {
43	fn from(v: Vec<f64>) -> Self {
44		Self(v.into_iter().map(Value::from).collect())
45	}
46}
47
48impl From<Vec<&str>> for Array {
49	fn from(v: Vec<&str>) -> Self {
50		Self(v.into_iter().map(Value::from).collect())
51	}
52}
53
54impl From<Vec<String>> for Array {
55	fn from(v: Vec<String>) -> Self {
56		Self(v.into_iter().map(Value::from).collect())
57	}
58}
59
60impl From<Vec<Number>> for Array {
61	fn from(v: Vec<Number>) -> Self {
62		Self(v.into_iter().map(Value::from).collect())
63	}
64}
65
66impl From<Vec<Operation>> for Array {
67	fn from(v: Vec<Operation>) -> Self {
68		Self(v.into_iter().map(Value::from).collect())
69	}
70}
71
72impl From<Vec<bool>> for Array {
73	fn from(v: Vec<bool>) -> Self {
74		Self(v.into_iter().map(Value::from).collect())
75	}
76}
77
78impl From<Array> for Vec<Value> {
79	fn from(s: Array) -> Self {
80		s.0
81	}
82}
83
84impl FromIterator<Value> for Array {
85	fn from_iter<I: IntoIterator<Item = Value>>(iter: I) -> Self {
86		Array(iter.into_iter().collect())
87	}
88}
89
90impl Deref for Array {
91	type Target = Vec<Value>;
92	fn deref(&self) -> &Self::Target {
93		&self.0
94	}
95}
96
97impl DerefMut for Array {
98	fn deref_mut(&mut self) -> &mut Self::Target {
99		&mut self.0
100	}
101}
102
103impl IntoIterator for Array {
104	type Item = Value;
105	type IntoIter = std::vec::IntoIter<Self::Item>;
106	fn into_iter(self) -> Self::IntoIter {
107		self.0.into_iter()
108	}
109}
110
111impl Array {
112	// Create a new empty array
113	pub fn new() -> Self {
114		Self::default()
115	}
116	// Create a new array with capacity
117	pub fn with_capacity(len: usize) -> Self {
118		Self(Vec::with_capacity(len))
119	}
120	// Get the length of the array
121	pub fn len(&self) -> usize {
122		self.0.len()
123	}
124	// Check if there array is empty
125	pub fn is_empty(&self) -> bool {
126		self.0.is_empty()
127	}
128}
129
130impl Array {
131	/// Process this type returning a computed simple Value
132	pub(crate) async fn compute(
133		&self,
134		ctx: &Context<'_>,
135		opt: &Options,
136		txn: &Transaction,
137		doc: Option<&CursorDoc<'_>>,
138	) -> Result<Value, Error> {
139		let mut x = Self::with_capacity(self.len());
140		for v in self.iter() {
141			match v.compute(ctx, opt, txn, doc).await {
142				Ok(v) => x.push(v),
143				Err(e) => return Err(e),
144			};
145		}
146		Ok(Value::Array(x))
147	}
148
149	pub(crate) fn is_all_none_or_null(&self) -> bool {
150		self.0.iter().all(|v| v.is_none_or_null())
151	}
152
153	pub(crate) fn is_static(&self) -> bool {
154		self.iter().all(Value::is_static)
155	}
156}
157
158impl Display for Array {
159	fn fmt(&self, f: &mut Formatter) -> fmt::Result {
160		let mut f = Pretty::from(f);
161		f.write_char('[')?;
162		if !self.is_empty() {
163			let indent = pretty_indent();
164			write!(f, "{}", Fmt::pretty_comma_separated(self.as_slice()))?;
165			drop(indent);
166		}
167		f.write_char(']')
168	}
169}
170
171// ------------------------------
172
173impl ops::Add<Value> for Array {
174	type Output = Self;
175	fn add(mut self, other: Value) -> Self {
176		self.0.push(other);
177		self
178	}
179}
180
181impl ops::Add for Array {
182	type Output = Self;
183	fn add(mut self, mut other: Self) -> Self {
184		self.0.append(&mut other.0);
185		self
186	}
187}
188
189// ------------------------------
190
191impl ops::Sub<Value> for Array {
192	type Output = Self;
193	fn sub(mut self, other: Value) -> Self {
194		if let Some(p) = self.0.iter().position(|x| *x == other) {
195			self.0.remove(p);
196		}
197		self
198	}
199}
200
201impl ops::Sub for Array {
202	type Output = Self;
203	fn sub(mut self, other: Self) -> Self {
204		for v in other.0 {
205			if let Some(p) = self.0.iter().position(|x| *x == v) {
206				self.0.remove(p);
207			}
208		}
209		self
210	}
211}
212
213// ------------------------------
214
215pub trait Abolish<T> {
216	fn abolish<F>(&mut self, f: F)
217	where
218		F: FnMut(usize) -> bool;
219}
220
221impl<T> Abolish<T> for Vec<T> {
222	fn abolish<F>(&mut self, mut f: F)
223	where
224		F: FnMut(usize) -> bool,
225	{
226		let mut i = 0;
227		// FIXME: use drain_filter once stabilized (https://github.com/rust-lang/rust/issues/43244)
228		// to avoid negation of the predicate return value.
229		self.retain(|_| {
230			let retain = !f(i);
231			i += 1;
232			retain
233		});
234	}
235}
236
237// ------------------------------
238
239pub(crate) trait Clump<T> {
240	fn clump(self, clump_size: usize) -> T;
241}
242
243impl Clump<Array> for Array {
244	fn clump(self, clump_size: usize) -> Array {
245		self.0
246			.chunks(clump_size)
247			.map::<Value, _>(|chunk| chunk.to_vec().into())
248			.collect::<Vec<_>>()
249			.into()
250	}
251}
252
253// ------------------------------
254
255pub(crate) trait Combine<T> {
256	fn combine(self, other: T) -> T;
257}
258
259impl Combine<Array> for Array {
260	fn combine(self, other: Self) -> Array {
261		let mut out = Self::with_capacity(self.len().saturating_mul(other.len()));
262		for a in self.iter() {
263			for b in other.iter() {
264				out.push(vec![a.clone(), b.clone()].into());
265			}
266		}
267		out
268	}
269}
270
271// ------------------------------
272
273pub(crate) trait Complement<T> {
274	fn complement(self, other: T) -> T;
275}
276
277impl Complement<Array> for Array {
278	fn complement(self, other: Self) -> Array {
279		let mut out = Array::new();
280		for v in self.into_iter() {
281			if !other.contains(&v) {
282				out.push(v)
283			}
284		}
285		out
286	}
287}
288
289// ------------------------------
290
291pub(crate) trait Concat<T> {
292	fn concat(self, other: T) -> T;
293}
294
295impl Concat<Array> for Array {
296	fn concat(mut self, mut other: Array) -> Array {
297		self.append(&mut other);
298		self
299	}
300}
301
302// ------------------------------
303
304pub(crate) trait Difference<T> {
305	fn difference(self, other: T) -> T;
306}
307
308impl Difference<Array> for Array {
309	fn difference(self, mut other: Array) -> Array {
310		let mut out = Array::new();
311		for v in self.into_iter() {
312			if let Some(pos) = other.iter().position(|w| v == *w) {
313				other.remove(pos);
314			} else {
315				out.push(v);
316			}
317		}
318		out.append(&mut other);
319		out
320	}
321}
322
323// ------------------------------
324
325pub(crate) trait Flatten<T> {
326	fn flatten(self) -> T;
327}
328
329impl Flatten<Array> for Array {
330	fn flatten(self) -> Array {
331		let mut out = Array::new();
332		for v in self.into_iter() {
333			match v {
334				Value::Array(mut a) => out.append(&mut a),
335				_ => out.push(v),
336			}
337		}
338		out
339	}
340}
341
342// ------------------------------
343
344pub(crate) trait Intersect<T> {
345	fn intersect(self, other: T) -> T;
346}
347
348impl Intersect<Self> for Array {
349	fn intersect(self, mut other: Self) -> Self {
350		let mut out = Self::new();
351		for v in self.0.into_iter() {
352			if let Some(pos) = other.iter().position(|w| v == *w) {
353				other.remove(pos);
354				out.push(v);
355			}
356		}
357		out
358	}
359}
360
361// ------------------------------
362
363// Documented with the assumption that it is just for arrays.
364pub(crate) trait Matches<T> {
365	/// Returns an array complimenting the original where each value is true or false
366	/// depending on whether it is == to the compared value.
367	///
368	/// Admittedly, this is most often going to be used in `count(array::matches($arr, $val))`
369	/// to count the number of times an element appears in an array but it's nice to have
370	/// this in addition.
371	fn matches(self, compare_val: Value) -> T;
372}
373
374impl Matches<Array> for Array {
375	fn matches(self, compare_val: Value) -> Array {
376		self.iter().map(|arr_val| (arr_val == &compare_val).into()).collect::<Vec<Value>>().into()
377	}
378}
379
380// ------------------------------
381
382// Documented with the assumption that it is just for arrays.
383pub(crate) trait Transpose<T> {
384	/// Stacks arrays on top of each other. This can serve as 2d array transposition.
385	///
386	/// The input array can contain regular values which are treated as arrays with
387	/// a single element.
388	///
389	/// It's best to think of the function as creating a layered structure of the arrays
390	/// rather than transposing them when the input is not a 2d array. See the examples
391	/// for what happense when the input arrays are not all the same size.
392	///
393	/// Here's a diagram:
394	/// [0, 1, 2, 3], [4, 5, 6]
395	/// ->
396	/// [0    | 1    | 2   |  3]
397	/// [4    | 5    | 6   ]
398	///  ^      ^      ^      ^
399	/// [0, 4] [1, 5] [2, 6] [3]
400	///
401	/// # Examples
402	///
403	/// ```ignore
404	/// fn array(sql: &str) -> Array {
405	///     unimplemented!();
406	/// }
407	///
408	/// // Example of `transpose` doing what it says on the tin.
409	/// assert_eq!(array("[[0, 1], [2, 3]]").transpose(), array("[[0, 2], [1, 3]]"));
410	/// // `transpose` can be thought of layering arrays on top of each other so when
411	/// // one array runs out, it stops appearing in the output.
412	/// assert_eq!(array("[[0, 1], [2]]").transpose(), array("[[0, 2], [1]]"));
413	/// assert_eq!(array("[0, 1, 2]").transpose(), array("[[0, 1, 2]]"));
414	/// ```
415	fn transpose(self) -> T;
416}
417
418impl Transpose<Array> for Array {
419	fn transpose(self) -> Array {
420		if self.is_empty() {
421			return self;
422		}
423		// I'm sure there's a way more efficient way to do this that I don't know about.
424		// The new array will be at *least* this large so we can start there;
425		let mut transposed_vec = Vec::<Value>::with_capacity(self.len());
426		let mut iters = self
427			.iter()
428			.map(|v| {
429				if let Value::Array(arr) = v {
430					Box::new(arr.iter().cloned()) as Box<dyn ExactSizeIterator<Item = Value>>
431				} else {
432					Box::new(std::iter::once(v).cloned())
433						as Box<dyn ExactSizeIterator<Item = Value>>
434				}
435			})
436			.collect::<Vec<_>>();
437		// We know there is at least one element in the array therefore iters is not empty.
438		// This is safe.
439		let longest_length = iters.iter().map(|i| i.len()).max().unwrap();
440		for _ in 0..longest_length {
441			transposed_vec
442				.push(iters.iter_mut().filter_map(|i| i.next()).collect::<Vec<_>>().into());
443		}
444		transposed_vec.into()
445	}
446}
447
448// ------------------------------
449
450pub(crate) trait Union<T> {
451	fn union(self, other: T) -> T;
452}
453
454impl Union<Self> for Array {
455	fn union(mut self, mut other: Self) -> Array {
456		self.append(&mut other);
457		self.uniq()
458	}
459}
460
461// ------------------------------
462
463pub(crate) trait Uniq<T> {
464	fn uniq(self) -> T;
465}
466
467impl Uniq<Array> for Array {
468	fn uniq(mut self) -> Array {
469		let mut set: HashSet<&Value> = HashSet::new();
470		let mut to_remove: Vec<usize> = Vec::new();
471		for (i, item) in self.iter().enumerate() {
472			if !set.insert(item) {
473				to_remove.push(i);
474			}
475		}
476		for i in to_remove.iter().rev() {
477			self.remove(*i);
478		}
479		self
480	}
481}