Skip to main content

surrealdb_sql/
method.rs

1//! The static mirror of the builtin method dispatch tables.
2//!
3//! Method-call syntax (`value.name(args)`) dispatches to a builtin function
4//! when `name` is a registered method, and otherwise falls through to a
5//! closure stored under that name on the receiver. Read-only classification
6//! has to make that distinction before any engine resolves the call: a
7//! builtin method writes nothing the classifier cannot already see in its
8//! arguments, while an unregistered name invokes a runtime value whose body
9//! is invisible, so it must be over-approximated as writable.
10//!
11//! [`BUILTIN_METHOD_NAMES`] mirrors the names registered by the executor's
12//! method registry (`build_method_registry` in the core crate), which cannot
13//! be consulted from here without inverting the crate dependency. A test in
14//! that module asserts the two stay identical.
15//!
16//! It lives in this layer rather than the expression layer because both the
17//! surface AST and the expression tree classify a method call the same way.
18
19/// Every method name that dispatches to a builtin function, sorted so
20/// membership is a binary search.
21pub const BUILTIN_METHOD_NAMES: &[&str] = &[
22	"abs",
23	"acos",
24	"acot",
25	"add",
26	"all",
27	"any",
28	"append",
29	"area",
30	"asin",
31	"at",
32	"atan",
33	"bearing",
34	"boolean_and",
35	"boolean_not",
36	"boolean_or",
37	"boolean_xor",
38	"bucket",
39	"capitalize",
40	"ceil",
41	"centroid",
42	"chain",
43	"clump",
44	"combine",
45	"complement",
46	"concat",
47	"contains",
48	"copy",
49	"copy_if_not_exists",
50	"cos",
51	"cot",
52	"day",
53	"days",
54	"deg2rad",
55	"delete",
56	"diff",
57	"difference",
58	"distance",
59	"distance_damerau_levenshtein",
60	"distance_hamming",
61	"distance_levenshtein",
62	"distance_normalized_damerau_levenshtein",
63	"distance_normalized_levenshtein",
64	"distinct",
65	"ends_with",
66	"entries",
67	"every",
68	"exists",
69	"expect",
70	"extend",
71	"fill",
72	"filter",
73	"filter_index",
74	"find",
75	"find_index",
76	"first",
77	"flatten",
78	"floor",
79	"fold",
80	"format",
81	"get",
82	"group",
83	"hash_decode",
84	"hash_encode",
85	"head",
86	"hour",
87	"hours",
88	"html_encode",
89	"html_sanitize",
90	"id",
91	"includes",
92	"index_of",
93	"insert",
94	"intersect",
95	"is_alpha",
96	"is_alphanum",
97	"is_array",
98	"is_ascii",
99	"is_bool",
100	"is_bytes",
101	"is_collection",
102	"is_datetime",
103	"is_decimal",
104	"is_domain",
105	"is_duration",
106	"is_edge",
107	"is_email",
108	"is_empty",
109	"is_float",
110	"is_geometry",
111	"is_hexadecimal",
112	"is_int",
113	"is_ip",
114	"is_ipv4",
115	"is_ipv6",
116	"is_latitude",
117	"is_leap_year",
118	"is_line",
119	"is_longitude",
120	"is_multiline",
121	"is_multipoint",
122	"is_multipolygon",
123	"is_none",
124	"is_null",
125	"is_number",
126	"is_numeric",
127	"is_object",
128	"is_point",
129	"is_polygon",
130	"is_range",
131	"is_record",
132	"is_semver",
133	"is_set",
134	"is_string",
135	"is_ulid",
136	"is_url",
137	"is_uuid",
138	"is_valid",
139	"join",
140	"key",
141	"keys",
142	"last",
143	"len",
144	"list",
145	"ln",
146	"log",
147	"log10",
148	"log2",
149	"logical_and",
150	"logical_or",
151	"logical_xor",
152	"lowercase",
153	"map",
154	"matches",
155	"max",
156	"micros",
157	"millis",
158	"min",
159	"mins",
160	"minute",
161	"month",
162	"nano",
163	"nanos",
164	"patch",
165	"pop",
166	"prepend",
167	"push",
168	"put",
169	"put_if_not_exists",
170	"rad2deg",
171	"reduce",
172	"remove",
173	"rename",
174	"rename_if_not_exists",
175	"repeat",
176	"replace",
177	"reverse",
178	"round",
179	"second",
180	"secs",
181	"semver_compare",
182	"semver_inc_major",
183	"semver_inc_minor",
184	"semver_inc_patch",
185	"semver_major",
186	"semver_minor",
187	"semver_patch",
188	"semver_set_major",
189	"semver_set_minor",
190	"semver_set_patch",
191	"set_day",
192	"set_hour",
193	"set_minute",
194	"set_month",
195	"set_nanosecond",
196	"set_second",
197	"set_year",
198	"shuffle",
199	"sign",
200	"similarity_fuzzy",
201	"similarity_jaro",
202	"similarity_jaro_winkler",
203	"similarity_smithwaterman",
204	"similarity_sorensen_dice",
205	"sin",
206	"slice",
207	"slug",
208	"some",
209	"sort",
210	"sort_asc",
211	"sort_desc",
212	"sort_lexical",
213	"sort_natural",
214	"sort_natural_lexical",
215	"split",
216	"starts_with",
217	"swap",
218	"table",
219	"tan",
220	"tb",
221	"to_array",
222	"to_bool",
223	"to_bytes",
224	"to_datetime",
225	"to_decimal",
226	"to_duration",
227	"to_float",
228	"to_geometry",
229	"to_int",
230	"to_number",
231	"to_point",
232	"to_range",
233	"to_record",
234	"to_set",
235	"to_string",
236	"to_string_lossy",
237	"to_uuid",
238	"transpose",
239	"trim",
240	"type_of",
241	"union",
242	"unix",
243	"uppercase",
244	"values",
245	"vector_add",
246	"vector_angle",
247	"vector_cross",
248	"vector_distance_chebyshev",
249	"vector_distance_euclidean",
250	"vector_distance_hamming",
251	"vector_distance_mahalanobis",
252	"vector_distance_manhattan",
253	"vector_distance_minkowski",
254	"vector_divide",
255	"vector_dot",
256	"vector_magnitude",
257	"vector_multiply",
258	"vector_normalize",
259	"vector_project",
260	"vector_scale",
261	"vector_similarity_cosine",
262	"vector_similarity_jaccard",
263	"vector_similarity_pearson",
264	"vector_similarity_spearman",
265	"vector_subtract",
266	"vector_sum",
267	"wday",
268	"week",
269	"weeks",
270	"windows",
271	"words",
272	"yday",
273	"year",
274	"years",
275];
276
277/// Whether `name` in `value.name(args)` dispatches to a builtin function
278/// rather than a closure stored on the receiver.
279pub fn is_builtin_method(name: &str) -> bool {
280	BUILTIN_METHOD_NAMES.binary_search(&name).is_ok()
281}
282
283/// Whether the named builtin can evaluate arbitrary nested statements, and so
284/// needs a write transaction whatever its arguments look like.
285///
286/// Every other builtin writes nothing of its own; only its arguments carry
287/// user expressions. Both `read_only` predicates and the planner's access-mode
288/// choice ask this, so a builtin added to one is added to all three.
289pub fn is_writer_builtin(name: &str) -> bool {
290	matches!(name, "api::invoke" | "eval::gql" | "eval::surql")
291}
292
293#[cfg(test)]
294mod tests {
295	use super::BUILTIN_METHOD_NAMES;
296
297	/// Membership is a binary search, which is only correct on a sorted,
298	/// duplicate-free table.
299	#[test]
300	fn the_name_table_is_sorted_and_unique() {
301		for pair in BUILTIN_METHOD_NAMES.windows(2) {
302			assert!(pair[0] < pair[1], "{:?} must sort strictly before {:?}", pair[0], pair[1]);
303		}
304	}
305}