surrealdb_core/sql/
array.rs

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