surrealdb_sql/statements/
insert.rs

1use crate::ctx::Context;
2use crate::dbs::{Iterable, Iterator, Options, Statement, Transaction};
3use crate::doc::CursorDoc;
4use crate::err::Error;
5use crate::{Data, Output, Timeout, Value};
6use derive::Store;
7use revision::revisioned;
8use serde::{Deserialize, Serialize};
9use std::fmt;
10
11#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Serialize, Deserialize, Store, Hash)]
12#[revisioned(revision = 1)]
13pub struct InsertStatement {
14	pub into: Value,
15	pub data: Data,
16	pub ignore: bool,
17	pub update: Option<Data>,
18	pub output: Option<Output>,
19	pub timeout: Option<Timeout>,
20	pub parallel: bool,
21}
22
23impl InsertStatement {
24	/// Check if we require a writeable transaction
25	pub(crate) fn writeable(&self) -> bool {
26		true
27	}
28	/// Process this type returning a computed simple Value
29	pub(crate) async fn compute(
30		&self,
31		ctx: &Context<'_>,
32		opt: &Options,
33		txn: &Transaction,
34		doc: Option<&CursorDoc<'_>>,
35	) -> Result<Value, Error> {
36		// Valid options?
37		opt.valid_for_db()?;
38		// Create a new iterator
39		let mut i = Iterator::new();
40		// Ensure futures are stored
41		let opt = &opt.new_with_futures(false).with_projections(false);
42		// Parse the expression
43		match self.into.compute(ctx, opt, txn, doc).await? {
44			Value::Table(into) => match &self.data {
45				// Check if this is a traditional statement
46				Data::ValuesExpression(v) => {
47					for v in v {
48						// Create a new empty base object
49						let mut o = Value::base();
50						// Set each field from the expression
51						for (k, v) in v.iter() {
52							let v = v.compute(ctx, opt, txn, None).await?;
53							o.set(ctx, opt, txn, k, v).await?;
54						}
55						// Specify the new table record id
56						let id = o.rid().generate(&into, true)?;
57						// Pass the mergeable to the iterator
58						i.ingest(Iterable::Mergeable(id, o));
59					}
60				}
61				// Check if this is a modern statement
62				Data::SingleExpression(v) => {
63					let v = v.compute(ctx, opt, txn, doc).await?;
64					match v {
65						Value::Array(v) => {
66							for v in v {
67								// Specify the new table record id
68								let id = v.rid().generate(&into, true)?;
69								// Pass the mergeable to the iterator
70								i.ingest(Iterable::Mergeable(id, v));
71							}
72						}
73						Value::Object(_) => {
74							// Specify the new table record id
75							let id = v.rid().generate(&into, true)?;
76							// Pass the mergeable to the iterator
77							i.ingest(Iterable::Mergeable(id, v));
78						}
79						v => {
80							return Err(Error::InsertStatement {
81								value: v.to_string(),
82							})
83						}
84					}
85				}
86				_ => unreachable!(),
87			},
88			v => {
89				return Err(Error::InsertStatement {
90					value: v.to_string(),
91				})
92			}
93		}
94		// Assign the statement
95		let stm = Statement::from(self);
96		// Output the results
97		i.output(ctx, opt, txn, &stm).await
98	}
99}
100
101impl fmt::Display for InsertStatement {
102	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
103		f.write_str("INSERT")?;
104		if self.ignore {
105			f.write_str(" IGNORE")?
106		}
107		write!(f, " INTO {} {}", self.into, self.data)?;
108		if let Some(ref v) = self.update {
109			write!(f, " {v}")?
110		}
111		if let Some(ref v) = self.output {
112			write!(f, " {v}")?
113		}
114		if let Some(ref v) = self.timeout {
115			write!(f, " {v}")?
116		}
117		if self.parallel {
118			f.write_str(" PARALLEL")?
119		}
120		Ok(())
121	}
122}