surrealdb_sql/statements/
insert.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
use crate::ctx::Context;
use crate::dbs::{Iterable, Iterator, Options, Statement, Transaction};
use crate::doc::CursorDoc;
use crate::err::Error;
use crate::{Data, Output, Timeout, Value};
use derive::Store;
use revision::revisioned;
use serde::{Deserialize, Serialize};
use std::fmt;

#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
#[revisioned(revision = 1)]
pub struct InsertStatement {
	pub into: Value,
	pub data: Data,
	pub ignore: bool,
	pub update: Option<Data>,
	pub output: Option<Output>,
	pub timeout: Option<Timeout>,
	pub parallel: bool,
}

impl InsertStatement {
	/// Check if we require a writeable transaction
	pub(crate) fn writeable(&self) -> bool {
		true
	}
	/// Process this type returning a computed simple Value
	pub(crate) async fn compute(
		&self,
		ctx: &Context<'_>,
		opt: &Options,
		txn: &Transaction,
		doc: Option<&CursorDoc<'_>>,
	) -> Result<Value, Error> {
		// Valid options?
		opt.valid_for_db()?;
		// Create a new iterator
		let mut i = Iterator::new();
		// Ensure futures are stored
		let opt = &opt.new_with_futures(false).with_projections(false);
		// Parse the expression
		match self.into.compute(ctx, opt, txn, doc).await? {
			Value::Table(into) => match &self.data {
				// Check if this is a traditional statement
				Data::ValuesExpression(v) => {
					for v in v {
						// Create a new empty base object
						let mut o = Value::base();
						// Set each field from the expression
						for (k, v) in v.iter() {
							let v = v.compute(ctx, opt, txn, None).await?;
							o.set(ctx, opt, txn, k, v).await?;
						}
						// Specify the new table record id
						let id = o.rid().generate(&into, true)?;
						// Pass the mergeable to the iterator
						i.ingest(Iterable::Mergeable(id, o));
					}
				}
				// Check if this is a modern statement
				Data::SingleExpression(v) => {
					let v = v.compute(ctx, opt, txn, doc).await?;
					match v {
						Value::Array(v) => {
							for v in v {
								// Specify the new table record id
								let id = v.rid().generate(&into, true)?;
								// Pass the mergeable to the iterator
								i.ingest(Iterable::Mergeable(id, v));
							}
						}
						Value::Object(_) => {
							// Specify the new table record id
							let id = v.rid().generate(&into, true)?;
							// Pass the mergeable to the iterator
							i.ingest(Iterable::Mergeable(id, v));
						}
						v => {
							return Err(Error::InsertStatement {
								value: v.to_string(),
							})
						}
					}
				}
				_ => unreachable!(),
			},
			v => {
				return Err(Error::InsertStatement {
					value: v.to_string(),
				})
			}
		}
		// Assign the statement
		let stm = Statement::from(self);
		// Output the results
		i.output(ctx, opt, txn, &stm).await
	}
}

impl fmt::Display for InsertStatement {
	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
		f.write_str("INSERT")?;
		if self.ignore {
			f.write_str(" IGNORE")?
		}
		write!(f, " INTO {} {}", self.into, self.data)?;
		if let Some(ref v) = self.update {
			write!(f, " {v}")?
		}
		if let Some(ref v) = self.output {
			write!(f, " {v}")?
		}
		if let Some(ref v) = self.timeout {
			write!(f, " {v}")?
		}
		if self.parallel {
			f.write_str(" PARALLEL")?
		}
		Ok(())
	}
}