rsmgp_sys/memgraph/
mod.rs1use std::ffi::CStr;
17
18use crate::list::*;
19use crate::mgp::*;
20use crate::result::*;
21use crate::rsmgp::*;
22use crate::vertex::*;
23#[double]
25use crate::mgp::ffi;
26use mockall_double::double;
27
28fn resolve_mgp_type(types: &[Type]) -> *const mgp_type {
31 unsafe {
32 let mut mgp_type: *const mgp_type = std::ptr::null_mut();
33 for field_type in types.iter().rev() {
34 mgp_type = match field_type {
35 Type::Any => ffi::mgp_type_any(),
36 Type::Bool => ffi::mgp_type_bool(),
37 Type::Number => ffi::mgp_type_number(),
38 Type::Int => ffi::mgp_type_int(),
39 Type::Double => ffi::mgp_type_float(),
40 Type::String => ffi::mgp_type_string(),
41 Type::Map => ffi::mgp_type_map(),
42 Type::Vertex => ffi::mgp_type_node(),
43 Type::Edge => ffi::mgp_type_relationship(),
44 Type::Path => ffi::mgp_type_path(),
45 Type::Nullable => ffi::mgp_type_nullable(mgp_type),
46 Type::List => ffi::mgp_type_list(mgp_type),
47 };
48 }
49 mgp_type
50 }
51}
52
53#[derive(Clone)]
55pub struct Memgraph {
56 args: *const mgp_list,
57 graph: *const mgp_graph,
58 result: *mut mgp_result,
59 memory: *mut mgp_memory,
60 module: *mut mgp_module,
61}
62
63impl Memgraph {
64 pub fn new(
69 args: *const mgp_list,
70 graph: *const mgp_graph,
71 result: *mut mgp_result,
72 memory: *mut mgp_memory,
73 module: *mut mgp_module,
74 ) -> Memgraph {
75 Memgraph {
76 args,
77 graph,
78 result,
79 memory,
80 module,
81 }
82 }
83
84 #[cfg(test)]
86 pub(crate) fn new_default() -> Memgraph {
87 Memgraph {
88 args: std::ptr::null(),
89 graph: std::ptr::null(),
90 result: std::ptr::null_mut(),
91 memory: std::ptr::null_mut(),
92 module: std::ptr::null_mut(),
93 }
94 }
95
96 pub fn args(&self) -> MgpResult<List> {
98 unsafe { List::mgp_copy(self.args_ptr(), &self) }
100 }
101
102 pub(crate) fn args_ptr(&self) -> *const mgp_list {
104 self.args
105 }
106
107 pub(crate) fn graph_ptr(&self) -> *const mgp_graph {
109 self.graph
110 }
111
112 pub(crate) fn result_ptr(&self) -> *mut mgp_result {
114 self.result
115 }
116
117 pub(crate) fn memory_ptr(&self) -> *mut mgp_memory {
119 self.memory
120 }
121
122 pub fn module_ptr(&self) -> *mut mgp_module {
124 self.module
125 }
126
127 pub fn vertices_iter(&self) -> MgpResult<VerticesIterator> {
128 unsafe {
129 let mgp_iterator = ffi::mgp_graph_iter_vertices(self.graph_ptr(), self.memory_ptr());
130 if mgp_iterator.is_null() {
131 return Err(MgpError::UnableToCreateGraphVerticesIterator);
132 }
133 Ok(VerticesIterator::new(mgp_iterator, &self))
134 }
135 }
136
137 pub fn vertex_by_id(&self, id: i64) -> MgpResult<Vertex> {
138 unsafe {
139 let mgp_vertex = ffi::mgp_graph_get_vertex_by_id(
140 self.graph_ptr(),
141 mgp_vertex_id { as_int: id },
142 self.memory_ptr(),
143 );
144 if mgp_vertex.is_null() {
145 return Err(MgpError::UnableToFindVertexById);
146 }
147 Ok(Vertex::new(mgp_vertex, &self))
148 }
149 }
150
151 pub fn result_record(&self) -> MgpResult<ResultRecord> {
156 ResultRecord::create(self)
157 }
158
159 pub fn add_read_procedure(
170 &self,
171 proc_ptr: extern "C" fn(
172 *const mgp_list,
173 *const mgp_graph,
174 *mut mgp_result,
175 *mut mgp_memory,
176 ),
177 name: &CStr,
178 required_arg_types: &[NamedType],
179 optional_arg_types: &[OptionalNamedType],
180 result_field_types: &[NamedType],
181 ) -> MgpResult<()> {
182 unsafe {
183 let procedure = ffi::mgp_module_add_read_procedure(
184 self.module_ptr(),
185 name.as_ptr(),
186 Some(proc_ptr),
187 );
188 if procedure.is_null() {
189 return Err(MgpError::UnableToRegisterReadProcedure);
190 }
191
192 for required_type in required_arg_types {
193 let mgp_type = resolve_mgp_type(&required_type.types);
194 if ffi::mgp_proc_add_arg(procedure, required_type.name.as_ptr(), mgp_type) == 0 {
195 return Err(MgpError::UnableToAddRequiredArguments);
196 }
197 }
198
199 for optional_input in optional_arg_types {
200 let mgp_type = resolve_mgp_type(&optional_input.types);
201 if ffi::mgp_proc_add_opt_arg(
202 procedure,
203 optional_input.name.as_ptr(),
204 mgp_type,
205 optional_input.default.mgp_ptr(),
206 ) == 0
207 {
208 return Err(MgpError::UnableToAddOptionalArguments);
209 }
210 }
211
212 for result_field in result_field_types {
213 let mgp_type = resolve_mgp_type(&result_field.types);
214 if result_field.deprecated {
215 if ffi::mgp_proc_add_deprecated_result(
216 procedure,
217 result_field.name.as_ptr(),
218 mgp_type,
219 ) == 0
220 {
221 return Err(MgpError::UnableToAddDeprecatedReturnType);
222 }
223 } else if ffi::mgp_proc_add_result(procedure, result_field.name.as_ptr(), mgp_type)
224 == 0
225 {
226 return Err(MgpError::UnableToAddReturnType);
227 }
228 }
229
230 Ok(())
231 }
232 }
233
234 pub fn must_abort(&self) -> bool {
242 unsafe { ffi::mgp_must_abort(self.graph_ptr()) != 0 }
243 }
244}
245
246#[cfg(test)]
247mod tests;