Skip to main content

surrealdb_expr/expr/
function.rs

1use surrealdb_types::{SqlFormat, ToSql};
2
3use crate::expr::{Expr, Idiom, Model, Script};
4
5#[derive(Clone, Debug, Eq, PartialEq, Hash)]
6pub enum Function {
7	Normal(String),
8	Custom(String),
9	Script(Script),
10	Model(Model),
11	Module(String, Option<String>),
12	Silo {
13		org: String,
14		pkg: String,
15		major: u32,
16		minor: u32,
17		patch: u32,
18		sub: Option<String>,
19	},
20}
21
22impl Function {
23	/// Convert function call to a field name
24	pub fn to_idiom(&self) -> Idiom {
25		match self {
26			// Safety: "function" does not contain null bytes"
27			Self::Script(_) => Idiom::field("function".to_owned()),
28			Self::Normal(f) => Idiom::field(f.to_owned()),
29			Self::Custom(f) => Idiom::field(format!("fn::{f}")),
30			Self::Model(m) => Idiom::field(m.to_sql()),
31			Self::Module(m, s) => match s {
32				Some(s) => Idiom::field(format!("mod::{m}::{s}")),
33				None => Idiom::field(format!("mod::{m}")),
34			},
35			Self::Silo {
36				org,
37				pkg,
38				major,
39				minor,
40				patch,
41				sub,
42			} => match sub {
43				Some(s) => {
44					Idiom::field(format!("silo::{org}::{pkg}::<{major}.{minor}.{patch}>::{s}"))
45				}
46				None => Idiom::field(format!("silo::{org}::{pkg}::<{major}.{minor}.{patch}>")),
47			},
48		}
49	}
50
51	/// Checks if this function invocation is writable
52	pub fn read_only(&self) -> bool {
53		match self {
54			Self::Custom(_)
55			| Self::Script(_)
56			| Self::Module(_, _)
57			| Self::Silo {
58				..
59			} => false,
60			Self::Normal(f) => !crate::sql::method::is_writer_builtin(f),
61			Self::Model(_) => true,
62		}
63	}
64}
65
66#[derive(Clone, Debug, Eq, PartialEq, Hash)]
67pub struct FunctionCall {
68	pub receiver: Function,
69	pub arguments: Vec<Expr>,
70}
71
72impl FunctionCall {
73	/// Returns if this expression type object can do any writes.
74	pub fn read_only(&self) -> bool {
75		self.receiver.read_only() && self.arguments.iter().all(|x| x.read_only())
76	}
77}
78
79impl ToSql for FunctionCall {
80	fn fmt_sql(&self, f: &mut String, fmt: SqlFormat) {
81		let fnc: crate::sql::FunctionCall = self.clone().into();
82		fnc.fmt_sql(f, fmt);
83	}
84}