1 /// C API interface to the memgraph mgclient library.
2 ///
3 /// Provides `mg_session`, a data type representing a connection to Bolt
4 /// server, along with functions for connecting to Bolt database and
5 /// executing queries against it, and `mg_value`, a data type representing a
6 /// value in Bolt protocol along with supporting types and manipulation
7 /// functions for them.
8 ///
9 /// `mg_session` is an opaque data type representing a connection to Bolt
10 /// server. Commands can be submitted for execution using `mg_session_run`
11 /// and results can be obtained using `mg_session_pull`. A `mg_session`
12 /// can execute at most one command at a time, and all results should be
13 /// consumed before trying to execute the next query.
14 ///
15 /// The usual flow for execution of a single query would be the following:
16 ///
17 ///  1. Submit the command for execution using `mg_session_run`.
18 ///
19 ///  2. Call `mg_session_pull` until it returns 0 to consume result rows and
20 ///     access result values using `mg_result_row`.
21 ///
22 ///  3. If necessary, access command execution summary using `mg_result_summary`.
23 ///
24 /// If any of the functions returns an error exit code, more detailed error
25 /// message can be obtained by calling `mg_session_error`.
26 ///
27 /// `mg_value` is an opaque data type representing an arbitrary value of any
28 /// of the types specified by the Bolt protocol. It can encapsulate any of its
29 /// supporting types: `mg_string`, `mg_list`, `mg_map`, `mg_node`,
30 /// `mg_relationship`, `mg_unbound_relationship` and `mg_path`.
31 /// Provided along with them are basic manipulation functions for those data
32 /// types. The API for most of data types is quite rudimentary, and as such is
33 /// not usable for complex operations on strings, maps, lists, etc. It is only
34 /// supposed to be used to construct data to be sent to the Bolt server, and
35 /// read data obtained from the Bolt server.
36 ///
37 /// Each object has a corresponding `mg_*_destroy` function that should be
38 /// invoked on the object at the end of its lifetime to free the resources
39 /// allocated for its storage. Each object has an owner, that is responsible for
40 /// its destruction. Object can be owned by the API client or by another
41 /// object. When being destroyed, an object will also destroy all other
42 /// objects it owns. Therefore, API client is only responsible for
43 /// destroying the object it directly owns. For example, if the API client
44 /// constructed a `mg_list` value and inserted some other `mg_value`
45 /// objects into it, they must only invoke `mg_list_destroy` on the list and
46 /// all of its members will be properly destroyed, because the list owns all of
47 /// its elements. Invoking `mg_*_destroy` on objects that are not owned by the
48 /// caller will usually result in memory corruption, double freeing, nuclear
49 /// apocalypse and similar unwanted behaviors. Therefore, object ownership
50 /// should be tracked carefully.
51 ///
52 /// Invoking certain functions on objects might cause ownership changes.
53 /// Obviously, you shouldn't pass objects you don't own to functions that steal
54 /// ownership.
55 ///
56 /// Function signatures are of big help in ownership tracking. Now follow two
57 /// simple rules, all functions that do not conform to those rules (if any) will
58 /// explicitly specify that in their documentation.
59 ///
60 ///  1. Return values
61 ///
62 ///     Functions that return a non-const pointer to an object give
63 ///     ownership of the returned object to the caller. Examples are:
64 ///       - creation functions (e.g. `mg_list_make_empty`).
65 ///       - copy functions (e.g. `mg_value_copy`).
66 ///       - `mg_connect` has a `mg_session **` output parameter because the
67 ///         API client becomes the owner of the `mg_session` object
68 ///
69 ///     Functions that return a const pointer to a object provide
70 ///     read-only access to the returned object that is valid only while the
71 ///     owning object is alive. Examples are:
72 ///       - access functions on `mg_value` (e.g. `mg_value_list`).
73 ///       - member access functions on containers (e.g. `mg_map_key_at`,
74 ///         `mg_list_at`, `mg_map_at`).
75 ///       - field access functions on graph types (e.g. `mg_node_properties`).
76 ///       - `mg_session_pull` has a `const mg_result **` output parameter,
77 ///         because the `mg_session` object keeps ownership of the returned
78 ///         result and destroys it on next pull
79 ///
80 ///  2. Function arguments
81 ///
82 ///     Functions that take a non-const pointer to a object either modify
83 ///     it or change its ownership (it is usually obvious what happens).
84 ///     Examples are:
85 ///       - member insert functions on containers transfer the ownership of
86 ///         inserted values to the container. They also take a non-const pointer
87 ///         to the container because they modify it. Ownership of the container
88 ///         is not changed (e.g. `mg_map_insert` takes ownership of the
89 ///         passed key and value).
90 ///      - `mg_session_run` takes a non-const pointer to the session because
91 ///        it modifies it internal state, but there is no ownership change
92 ///
93 ///     An obvious exception here are `mg_*_destroy` functions which do not
94 ///     change ownership of the object.
95 ///
96 ///     Functions that take a const pointer to a object do not change the
97 ///     owner of the passed object nor they modify it. Examples are:
98 ///       - member access functions on containers take const pointer to the
99 ///         container (e.g. `mg_list_at`, `mg_map_at`, ...).
100 ///       - member access functions on graph types take const pointer to the
101 ///         container (e.g. `mg_path_node_at`, `mg_node_label_count`,
102 ///         ...).
103 ///       - copy functions.
104 module memgraph.mgclient;
105 
106 /// Initializes the client (the whole process).
107 /// Module constructor used to initialise memgraph via a call to mg_init().
108 static this() {
109 	const rc = mg_init();
110 	assert(rc == mg_error.MG_SUCCESS);
111 }
112 
113 /// Finalizes the client (the whole process).
114 /// Module destructor used to finalise memgraph via a call to mg_finalize().
115 static ~this() {
116 	mg_finalize();
117 }
118 
119 extern (C) {
120 	/// Client software version.
121 	/// Return: Client version in the major.minor.patch format.
122 	const (char) *mg_client_version();
123 
124 	/// Initializes the client (the whole process).
125 	/// Should be called at the beginning of each process using the client.
126 	/// Return: Zero if initialization was successful.
127 	mg_error mg_init();
128 
129 	/// Finalizes the client (the whole process).
130 	/// Should be called at the end of each process using the client.
131 	void mg_finalize();
132 
133 	/// An enum listing all the types as specified by Bolt protocol.
134 	enum mg_value_type {
135 		MG_VALUE_TYPE_NULL,
136 		MG_VALUE_TYPE_BOOL,
137 		MG_VALUE_TYPE_INTEGER,
138 		MG_VALUE_TYPE_FLOAT,
139 		MG_VALUE_TYPE_STRING,
140 		MG_VALUE_TYPE_LIST,
141 		MG_VALUE_TYPE_MAP,
142 		MG_VALUE_TYPE_NODE,
143 		MG_VALUE_TYPE_RELATIONSHIP,
144 		MG_VALUE_TYPE_UNBOUND_RELATIONSHIP,
145 		MG_VALUE_TYPE_PATH,
146 		MG_VALUE_TYPE_DATE,
147 		MG_VALUE_TYPE_TIME,
148 		MG_VALUE_TYPE_LOCAL_TIME,
149 		MG_VALUE_TYPE_DATE_TIME,
150 		MG_VALUE_TYPE_DATE_TIME_ZONE_ID,
151 		MG_VALUE_TYPE_LOCAL_DATE_TIME,
152 		MG_VALUE_TYPE_DURATION,
153 		MG_VALUE_TYPE_POINT_2D,
154 		MG_VALUE_TYPE_POINT_3D,
155 		MG_VALUE_TYPE_UNKNOWN
156 	}
157 
158 	/// A Bolt value, encapsulating all other values.
159 	version(unittest) {
160 		struct mg_value {
161 			mg_value_type type;
162 			union {
163 				int bool_v;
164 				long integer_v;
165 				double float_v;
166 				mg_string *string_v;
167 				mg_list *list_v;
168 				mg_map *map_v;
169 				mg_node *node_v;
170 				mg_relationship *relationship_v;
171 				mg_unbound_relationship *unbound_relationship_v;
172 				mg_path *path_v;
173 				mg_date *date_v;
174 				mg_time *time_v;
175 				mg_local_time *local_time_v;
176 				mg_date_time *date_time_v;
177 				mg_date_time_zone_id *date_time_zone_id_v;
178 				mg_local_date_time *local_date_time_v;
179 				mg_duration *duration_v;
180 				mg_point_2d *point_2d_v;
181 				mg_point_3d *point_3d_v;
182 			}
183 		}
184 	} else {
185 		struct mg_value;
186 	}
187 
188 	/// An UTF-8 encoded string.
189 	///
190 	/// Note that the length of the string is the byte count of the UTF-8 encoded
191 	/// data. It is guaranteed that the bytes of the string are stored contiguously,
192 	/// and they can be accessed through a pointer to first element returned by
193 	/// `mg_string_data`.
194 	///
195 	/// Note that the library doesn't perform any checks whatsoever to see if the
196 	/// provided data is a valid UTF-8 encoded string when constructing instances of
197 	/// `mg_string`.
198 	///
199 	/// Maximum possible string length allowed by Bolt protocol is `uint.max`.
200 	version(unittest) {
201 		struct mg_string {
202 			uint size;
203 			char *data;
204 		}
205 	} else {
206 		struct mg_string;
207 	}
208 
209 	/// An ordered sequence of values.
210 	///
211 	/// List may contain a mixture of different types as its elements. A list owns
212 	/// all values stored in it.
213 	///
214 	/// Maximum possible list length allowed by Bolt is `uint.max`.
215 	version(unittest) {
216 		struct mg_list {
217 			uint size;
218 			uint capacity;
219 			mg_value **elements;
220 		}
221 	} else {
222 		struct mg_list;
223 	}
224 
225 	/// Sized sequence of pairs of keys and values.
226 	///
227 	/// Map may contain a mixture of different types as values. A map owns all keys
228 	/// and values stored in it.
229 	///
230 	/// Maximum possible map size allowed by Bolt protocol is `uint.max`.
231 	version(unittest) {
232 		struct mg_map {
233 			uint size;
234 			uint capacity;
235 			mg_string **keys;
236 			mg_value **values;
237 		}
238 	} else {
239 		struct mg_map;
240 	}
241 
242 	/// Represents a node from a labeled property graph.
243 	///
244 	/// Consists of a unique identifier (withing the scope of its origin graph), a
245 	/// list of labels and a map of properties. A node owns its labels and
246 	/// properties.
247 	///
248 	/// Maximum possible number of labels allowed by Bolt protocol is `uint.max`.
249 	version(unittest) {
250 		struct mg_node {
251 			long id;
252 			uint label_count;
253 			mg_string **labels;
254 			mg_map *properties;
255 		}
256 	} else {
257 		struct mg_node;
258 	}
259 
260 	/// Represents a relationship from a labeled property graph.
261 	///
262 	/// Consists of a unique identifier (within the scope of its origin graph),
263 	/// identifiers for the start and end nodes of that relationship, a type and a
264 	/// map of properties. A relationship owns its type string and property map.
265 	version(unittest) {
266 		struct mg_relationship {
267 			long id;
268 			long start_id;
269 			long end_id;
270 			mg_string *type;
271 			mg_map *properties;
272 		}
273 	} else {
274 		struct mg_relationship;
275 	}
276 
277 	/// Represents a relationship from a labeled property graph.
278 	///
279 	/// Like `mg_relationship`, but without identifiers for start and end nodes.
280 	/// Mainly used as a supporting type for `mg_path`. An unbound relationship
281 	/// owns its type string and property map.
282 	version(unittest) {
283 		struct mg_unbound_relationship {
284 			long id;
285 			mg_string *type;
286 			mg_map *properties;
287 		}
288 	} else {
289 		struct mg_unbound_relationship;
290 	}
291 
292 	/// Represents a sequence of alternating nodes and relationships
293 	/// corresponding to a walk in a labeled property graph.
294 	///
295 	/// A path of length L consists of L + 1 nodes indexed from 0 to L, and L
296 	/// unbound relationships, indexed from 0 to L - 1. Each relationship has a
297 	/// direction. A relationship is said to be reversed if it was traversed in the
298 	/// direction opposite of the direction of the underlying relationship in the
299 	/// data graph.
300 	version(unittest) {
301 		struct mg_path {
302 			uint node_count;
303 			uint relationship_count;
304 			uint sequence_length;
305 			mg_node **nodes;
306 			mg_unbound_relationship **relationships;
307 			long *sequence;
308 		}
309 	} else {
310 		struct mg_path;
311 	}
312 
313 	/// Represents a date.
314 	///
315 	/// Date is defined with number of days since the Unix epoch.
316 	version(unittest) {
317 		struct mg_date {
318 			long days;
319 		}
320 	} else {
321 		struct mg_date;
322 	}
323 
324 	/// Represents time with its time zone.
325 	///
326 	/// Time is defined with nanoseconds since midnight.
327 	/// Timezone is defined with seconds from UTC.
328 	version(unittest) {
329 		struct mg_time {
330 			long nanoseconds;
331 			long tz_offset_seconds;
332 		}
333 	} else {
334 		struct mg_time;
335 	}
336 
337 	/// Represents local time.
338 	///
339 	/// Time is defined with nanoseconds since midnight.
340 	version(unittest) {
341 		struct mg_local_time {
342 			long nanoseconds;
343 		}
344 	} else {
345 		struct mg_local_time;
346 	}
347 
348 	/// Represents date and time with its time zone.
349 	///
350 	/// Date is defined with seconds since the adjusted Unix epoch.
351 	/// Time is defined with nanoseconds since midnight.
352 	/// Time zone is defined with minutes from UTC.
353 	version(unittest) {
354 		struct mg_date_time {
355 			long seconds;
356 			long nanoseconds;
357 			long tz_offset_minutes;
358 		}
359 	} else {
360 		struct mg_date_time;
361 	}
362 
363 	/// Represents date and time with its time zone.
364 	///
365 	/// Date is defined with seconds since the adjusted Unix epoch.
366 	/// Time is defined with nanoseconds since midnight.
367 	/// Timezone is defined with an identifier for a specific time zone.
368 	version(unittest) {
369 		struct mg_date_time_zone_id {
370 			long seconds;
371 			long nanoseconds;
372 			long tz_id;
373 		}
374 	} else {
375 		struct mg_date_time_zone_id;
376 	}
377 
378 	/// Represents date and time without its time zone.
379 	///
380 	/// Date is defined with seconds since the Unix epoch.
381 	/// Time is defined with nanoseconds since midnight.
382 	version(unittest) {
383 		struct mg_local_date_time {
384 			long seconds;
385 			long nanoseconds;
386 		}
387 	} else {
388 		struct mg_local_date_time;
389 	}
390 
391 	/// Represents a temporal amount which captures the difference in time
392 	/// between two instants.
393 	///
394 	/// Duration is defined with months, days, seconds, and nanoseconds.
395 	/// Note: Duration can be negative.
396 	version(unittest) {
397 		struct mg_duration {
398 			long months;
399 			long days;
400 			long seconds;
401 			long nanoseconds;
402 		}
403 	} else {
404 		struct mg_duration;
405 	}
406 
407 	/// Represents a single location in 2-dimensional space.
408 	///
409 	/// Contains SRID along with its x and y coordinates.
410 	version(unittest) {
411 		struct mg_point_2d {
412 			long srid;
413 			double x;
414 			double y;
415 		}
416 	} else {
417 		struct mg_point_2d;
418 	}
419 
420 	/// Represents a single location in 3-dimensional space.
421 	///
422 	/// Contains SRID along with its x, y and z coordinates.
423 	version(unittest) {
424 		struct mg_point_3d {
425 			long srid;
426 			double x;
427 			double y;
428 			double z;
429 		}
430 	} else {
431 		struct mg_point_3d;
432 	}
433 
434 	/// Constructs a nil `mg_value`.
435 	///
436 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
437 	@safe @nogc mg_value *mg_value_make_null() pure nothrow;
438 
439 	/// Constructs a boolean `mg_value`.
440 	///
441 	/// Params: val = If the parameter is zero, constructed value will be false.
442 	///               Otherwise, it will be true.
443 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
444 	@safe @nogc mg_value *mg_value_make_bool(int val) pure nothrow;
445 
446 	/// Constructs an integer `mg_value` with the given underlying value.
447 	///
448 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
449 	@safe @nogc mg_value *mg_value_make_integer(long val) pure nothrow;
450 
451 	/// Constructs a float `mg_value` with the given underlying value.
452 	///
453 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
454 	@safe @nogc mg_value *mg_value_make_float(double val) pure nothrow;
455 
456 	/// Constructs a string `mg_value` given a null-terminated string.
457 	///
458 	/// A new `mg_string` instance will be created from the null-terminated
459 	/// string as the underlying value.
460 	///
461 	/// Params: str = A null-terminated UTF-8 string.
462 	///
463 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
464 	@safe @nogc mg_value *mg_value_make_string(const char *str) pure nothrow;
465 
466 	/// Construct a string `mg_value` given the underlying `mg_string`.
467 	///
468 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
469 	@safe @nogc mg_value *mg_value_make_string2(mg_string *str) pure nothrow;
470 
471 	/// Constructs a list `mg_value` given the underlying `mg_list`.
472 	///
473 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
474 	@safe @nogc mg_value *mg_value_make_list(mg_list *list) pure nothrow;
475 
476 	/// Constructs a map `mg_value` given the underlying `mg_map`.
477 	///
478 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
479 	@safe @nogc mg_value *mg_value_make_map(mg_map *map) pure nothrow;
480 
481 	/// Constructs a node `mg_value` given the underlying `mg_node`.
482 	///
483 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
484 	@safe @nogc mg_value *mg_value_make_node(mg_node *node) pure nothrow;
485 
486 	/// Constructs a relationship `mg_value` given the underlying
487 	/// `mg_relationship`.
488 	///
489 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
490 	@safe @nogc mg_value *mg_value_make_relationship(mg_relationship *rel) pure nothrow;
491 
492 	/// Constructs an unbound relationship `mg_value` given the underlying
493 	/// `mg_unbound_relationship`.
494 	///
495 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
496 	@safe @nogc mg_value *mg_value_make_unbound_relationship(mg_unbound_relationship *rel) pure nothrow;
497 
498 	/// Constructs a path `mg_value` given the underlying `mg_path`.
499 	///
500 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
501 	@safe @nogc mg_value *mg_value_make_path(mg_path *path) pure nothrow;
502 
503 	/// Constructs a date `mg_value` given the underlying `mg_date`.
504 	///
505 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
506 	@safe @nogc mg_value *mg_value_make_date(mg_date *date) pure nothrow;
507 
508 	/// Constructs a time `mg_value` given the underlying `mg_time`.
509 	///
510 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
511 	@safe @nogc mg_value *mg_value_make_time(mg_time *time) pure nothrow;
512 
513 	/// Constructs a local time `mg_value` given the underlying `mg_local_time`.
514 	///
515 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
516 	@safe @nogc mg_value *mg_value_make_local_time(mg_local_time *local_time) pure nothrow;
517 
518 	/// Constructs a date and time `mg_value` given the underlying `mg_date_time`.
519 	///
520 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
521 	@safe @nogc mg_value *mg_value_make_date_time(mg_date_time *date_time) pure nothrow;
522 
523 	/// Constructs a date and time `mg_value` given the underlying `mg_date_time_zone_id`.
524 	///
525 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
526 	@safe @nogc mg_value *mg_value_make_date_time_zone_id(mg_date_time_zone_id *date_time_zone_id) pure nothrow;
527 
528 	/// Constructs a local date and time `mg_value` given the underlying `mg_local_date_time`.
529 	///
530 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
531 	@safe @nogc mg_value *mg_value_make_local_date_time(mg_local_date_time *local_date_time) pure nothrow;
532 
533 	/// Constructs a duration `mg_value` given the underlying `mg_duration`.
534 	///
535 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
536 	@safe @nogc mg_value *mg_value_make_duration(mg_duration *duration) pure nothrow;
537 
538 	/// Constructs a 2D point `mg_value` given the underlying `mg_point_2d`.
539 	///
540 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
541 	@safe @nogc mg_value *mg_value_make_point_2d(mg_point_2d *point_2d) pure nothrow;
542 
543 	/// Constructs a 3D point `mg_value` given the underlying `mg_point_3d`.
544 	///
545 	/// Return: Pointer to the newly constructed value or NULL if error occurred.
546 	@safe @nogc mg_value *mg_value_make_point_3d(mg_point_3d *point_3d) pure nothrow;
547 
548 	/// Returns the type of the given `mg_value`.
549 	mg_value_type mg_value_get_type(const mg_value *val);
550 
551 	/// Returns non-zero value if value contains true, zero otherwise.
552 	///
553 	/// Type check should be made first. Accessing the wrong value results in
554 	/// undefined behavior.
555 	/// TODO: check if this is really ok, as the original return type was int !!!
556 	bool mg_value_bool(const mg_value *val);
557 
558 	/// Returns the underlying integer value.
559 	///
560 	/// Type check should be made first. Accessing the wrong value results in
561 	/// undefined behavior.
562 	long mg_value_integer(const mg_value *val);
563 
564 	/// Returns the underlying float value.
565 	///
566 	/// Type check should be made first. Accessing the wrong value results in
567 	/// undefined behavior.
568 	double mg_value_float(const mg_value *val);
569 
570 	/// Returns the underlying `mg_string` value.
571 	///
572 	/// Type check should be made first. Accessing the wrong value results in
573 	/// undefined behavior.
574 	const (mg_string) *mg_value_string(const mg_value *val);
575 
576 	/// Returns the underlying `mg_list` value.
577 	///
578 	/// Type check should be made first. Accessing the wrong value results in
579 	/// undefined behavior.
580 	const (mg_list) *mg_value_list(const mg_value *val);
581 
582 	/// Returns the underlying `mg_map` value.
583 	///
584 	/// Type check should be made first. Accessing the wrong value results in
585 	/// undefined behavior.
586 	const (mg_map) *mg_value_map(const mg_value *val);
587 
588 	/// Returns the underlying `mg_node` value.
589 	///
590 	/// Type check should be made first. Accessing the wrong value results in
591 	/// undefined behavior.
592 	const (mg_node) *mg_value_node(const mg_value *val);
593 
594 	/// Returns the underlying `mg_relationship` value.
595 	///
596 	/// Type check should be made first. Accessing the wrong value results in
597 	/// undefined behavior.
598 	const (mg_relationship) *mg_value_relationship(const mg_value *val);
599 
600 	/// Returns the underlying `mg_unbound_relationship` value.
601 	///
602 	/// Type check should be made first. Accessing the wrong value results in
603 	/// undefined behavior.
604 	const (mg_unbound_relationship) *mg_value_unbound_relationship(const mg_value *val);
605 
606 	/// Returns the underlying `mg_path` value.
607 	///
608 	/// Type check should be made first. Accessing the wrong value results in
609 	/// undefined behavior.
610 	const (mg_path) *mg_value_path(const mg_value *val);
611 
612 	/// Returns the underlying `mg_date` value.
613 	///
614 	/// Type check should be made first. Accessing the wrong value results in
615 	/// undefined behavior.
616 	const (mg_date) *mg_value_date(const mg_value *val);
617 
618 	/// Returns the underlying `mg_time` value.
619 	///
620 	/// Type check should be made first. Accessing the wrong value results in
621 	/// undefined behavior.
622 	const (mg_time) *mg_value_time(const mg_value *val);
623 
624 	/// Returns the underlying `mg_local_time` value.
625 	///
626 	/// Type check should be made first. Accessing the wrong value results in
627 	/// undefined behavior.
628 	const (mg_local_time) *mg_value_local_time(const mg_value *val);
629 
630 	/// Returns the underlying `mg_date_time` value.
631 	///
632 	/// Type check should be made first. Accessing the wrong value results in
633 	/// undefined behavior.
634 	const (mg_date_time) *mg_value_date_time(const mg_value *val);
635 
636 	/// Returns the underlying `mg_date_time_zone_id` value.
637 	///
638 	/// Type check should be made first. Accessing the wrong value results in
639 	/// undefined behavior.
640 	const (mg_date_time_zone_id) *mg_value_date_time_zone_id(const mg_value *val);
641 
642 	/// Returns the underlying `mg_local_date_time` value.
643 	///
644 	/// Type check should be made first. Accessing the wrong value results in
645 	/// undefined behavior.
646 	const (mg_local_date_time) *mg_value_local_date_time(const mg_value *val);
647 
648 	/// Returns the underlying `mg_duration` value.
649 	///
650 	/// Type check should be made first. Accessing the wrong value results in
651 	/// undefined behavior.
652 	const (mg_duration) *mg_value_duration(const mg_value *val);
653 
654 	/// Returns the underlying `mg_point_2d` value.
655 	///
656 	/// Type check should be made first. Accessing the wrong value results in
657 	/// undefined behavior.
658 	const (mg_point_2d) *mg_value_point_2d(const mg_value *val);
659 
660 	/// Returns the underlying `mg_point_3d` value.
661 	///
662 	/// Type check should be made first. Accessing the wrong value results in
663 	/// undefined behavior.
664 	const (mg_point_3d) *mg_value_point_3d(const mg_value *val);
665 
666 	/// Creates a copy of the given value.
667 	///
668 	/// Return: Pointer to the copy or NULL if error occurred.
669 	@safe @nogc mg_value *mg_value_copy(const mg_value *val) pure nothrow;
670 
671 	/// Destroys the given value.
672 	@safe @nogc void mg_value_destroy(mg_value *val) pure nothrow;
673 
674 	/// Constructs a string given a null-terminated string.
675 	///
676 	/// A new buffer of appropriate length will be allocated and the given string
677 	/// will be copied there.
678 	///
679 	/// Params: str = A null-terminated UTF-8 string.
680 	///
681 	/// Return: A pointer to the newly constructed `mg_string` object or NULL
682 	///         if an error occurred.
683 	@safe @nogc mg_string *mg_string_make(const char *str) pure nothrow;
684 
685 	/// Constructs a string given its length (in bytes) and contents.
686 	///
687 	/// A new buffer of will be allocated and the given data will be copied there.
688 	///
689 	/// Params: len = Number of bytes in the data buffer.
690 	///        data = The string contents.
691 	///
692 	/// Return: A pointer to the newly constructed `mg_string` object or NULL
693 	///         if an error occurred.
694 	@safe @nogc mg_string *mg_string_make2(uint len, const char *data) pure nothrow;
695 
696 	/// Returns a pointer to the beginning of data buffer of string `str`.
697 	const (char) *mg_string_data(const mg_string *str);
698 
699 	/// Returns the length (in bytes) of string `str`.
700 	uint mg_string_size(const mg_string *str);
701 
702 	/// Creates a copy of the given string.
703 	///
704 	/// Return: A pointer to the copy or NULL if an error occurred.
705 	@safe @nogc mg_string *mg_string_copy(const mg_string *str) pure nothrow;
706 
707 	/// Destroys the given string.
708 	@safe @nogc void mg_string_destroy(mg_string *str) pure nothrow;
709 
710 	/// Constructs a list that can hold at most `capacity` elements.
711 	///
712 	/// Elements should be constructed and then inserted using `mg_list_append`.
713 	///
714 	/// Params: capacity = The maximum number of elements that the newly constructed
715 	///                 list can hold.
716 	///
717 	/// Return: A pointer to the newly constructed empty list or NULL if an error
718 	///         occurred.
719 	@safe @nogc mg_list *mg_list_make_empty(uint capacity) pure nothrow;
720 
721 	/// Appends an element at the end of the list `list`.
722 	///
723 	/// Insertion will fail if the list capacity is already exhausted. If the
724 	/// insertion fails, the map doesn't take ownership of `value`.
725 	///
726 	/// Params: list = The list instance to be modified.
727 	///        value = The value to be appended.
728 	///
729 	/// Return: The function returns non-zero value if insertion failed, zero
730 	///         otherwise.
731 	mg_error mg_list_append(mg_list *list, mg_value *value);
732 
733 	/// Returns the number of elements in list `list`.
734 	uint mg_list_size(const mg_list *list);
735 
736 	/// Retrieves the element at position `pos` in list `list`.
737 	///
738 	/// Return: A pointer to required list element. If `pos` is outside of list
739 	///         bounds, NULL is returned.
740 	const (mg_value) *mg_list_at(const mg_list *list, uint pos);
741 
742 	/// Creates a copy of the given list.
743 	///
744 	/// Return: A pointer to the copy or NULL if an error occurred.
745 	@safe @nogc mg_list *mg_list_copy(const mg_list *list) pure nothrow;
746 
747 	/// Destroys the given list.
748 	@safe @nogc void mg_list_destroy(mg_list *list) pure nothrow;
749 
750 	/// Constructs an empty map that can hold at most `capacity` key-value pairs.
751 	///
752 	/// Key-value pairs should be constructed and then inserted using
753 	/// `mg_map_insert`, `mg_map_insert_unsafe` and similar.
754 	///
755 	/// Params: capacity = The maximum number of key-value pairs that the newly
756 	///                 constructed list can hold.
757 	///
758 	/// Return: A pointer to the newly constructed empty map or NULL if an error
759 	///         occurred.
760 	@safe @nogc mg_map *mg_map_make_empty(uint capacity) pure nothrow;
761 
762 	/// Inserts the given key-value pair into the map.
763 	///
764 	/// A check is performed to see if the given key is unique in the map which
765 	/// means that a number of key comparisons equal to the current number of
766 	/// elements in the map is made.
767 	///
768 	/// If key length is greater that `uint.max`, or the key already exists in
769 	/// map, or the map's capacity is exhausted, the insertion will fail. If
770 	/// insertion fails, the map doesn't take ownership of `value`.
771 	///
772 	/// If the insertion is successful, a new `mg_string` is constructed for
773 	/// the storage of the key and the map takes ownership of `value`.
774 	///
775 	/// Params: map =   The map instance to be modifed.
776 	///      key_str =  A null-terminated string to be used as key.
777 	///         value = Value to be inserted.
778 	///
779 	/// Return: The function returns non-zero value if insertion failed, zero
780 	///         otherwise.
781 	mg_error mg_map_insert(mg_map *map, const char *key_str, mg_value *value);
782 
783 	/// Inserts the given key-value pair into the map.
784 	///
785 	/// A check is performed to see if the given key is unique in the map which
786 	/// means that a number of key comparisons equal to the current number of
787 	/// elements in the map is made.
788 	///
789 	/// If the key already exists in map, or the map's capacity is exhausted, the
790 	/// insertion will fail. If insertion fails, the map doesn't take ownership of
791 	/// `key` and `value`.
792 	///
793 	/// If the insertion is successful, map takes ownership of `key` and `value`.
794 	///
795 	/// Params: map =   The map instance to be modifed.
796 	///         key =   A `mg_string` to be used as key.
797 	///        value =  Value to be inserted.
798 	///
799 	/// Return: The function returns non-zero value if insertion failed, zero
800 	///         otherwise.
801 	int mg_map_insert2(mg_map *map, mg_string *key, mg_value *value);
802 
803 	/// Inserts the given key-value pair into the map.
804 	///
805 	/// No check is performed for key uniqueness. Note that map containing duplicate
806 	/// keys is considered invalid in Bolt protocol.
807 	///
808 	/// If key length is greated than `uint.max` or or the map's capacity is
809 	/// exhausted, the insertion will fail. If insertion fails, the map doesn't take
810 	/// ownership of `value`.
811 	///
812 	/// If the insertion is successful, a new `mg_string` is constructed for the
813 	/// storage of the key and the map takes ownership of `value`.
814 	///
815 	/// Params: map =  The map instance to be modifed.
816 	///      key_str = A null-terminated string to be used as key.
817 	///        value = Value to be inserted.
818 	///
819 	/// Return: The function returns non-zero value if insertion failed, zero
820 	///         otherwise.
821 	@safe @nogc int mg_map_insert_unsafe(mg_map *map, const char *key_str, mg_value *value);
822 
823 	/// Inserts the given key-value pair into the map.
824 	///
825 	/// No check is performed for key uniqueness. Note that map containing duplicate
826 	/// keys is considered invalid in Bolt protocol.
827 	///
828 	/// If the map's capacity is exhausted, the insertion will fail. If insertion
829 	/// fails, the map doesn't take ownership of `key` and `value`.
830 	///
831 	/// If the insertion is successful, map takes ownership of `key` and `value`.
832 	///
833 	/// Params:  map = The map instance to be modifed.
834 	///          key = A `mg_string` to be used as key.
835 	///        value = Value to be inserted.
836 	///
837 	/// Return: The function returns non-zero value if insertion failed, zero
838 	///         otherwise.
839 	@safe @nogc int mg_map_insert_unsafe2(mg_map *map, mg_string *key, mg_value *value);
840 
841 	/// Looks up a map value with the given key.
842 	///
843 	/// Params: map =  The map instance to be queried.
844 	///      key_str = A null-terminated string representing the key to be looked-up
845 	///                in the map.
846 	///
847 	/// Return: If the key is found in the map, the pointer to the corresponding
848 	///         `mg_value` is returned. Otherwise, NULL is returned.
849 	const (mg_value) *mg_map_at(const mg_map *map, const char *key_str);
850 
851 	/// Looks up a map value with the given key.
852 	///
853 	/// Params: map =   The map instance to be queried.
854 	///      key_size = The length of the string representing the key to be
855 	///                 looked-up in the map.
856 	///      key_data = Bytes constituting the key string.
857 	///
858 	/// Return: If the key is found in the map, the pointer to the corresponding
859 	///         `mg_value` is returned. Otherwise, NULL is returned.
860 	const (mg_value) *mg_map_at2(const mg_map *map, uint key_size, const char *key_data);
861 
862 	/// Returns the number of key-value pairs in map `map`.
863 	uint mg_map_size(const mg_map *map);
864 
865 	/// Retrieves the key at position `pos` in map `map`.
866 	///
867 	/// Return: A pointer to required key. If `pos` is outside of map bounds,
868 	///         NULL is returned.
869 	const (mg_string) *mg_map_key_at(const mg_map *, uint pos);
870 
871 	/// Retrieves the value at position `pos` in map `map`.
872 	///
873 	/// Return: A pointer to required value. If `pos` is outside of map bounds,
874 	///         NULL is returned.
875 	const (mg_value) *mg_map_value_at(const mg_map *, uint pos);
876 
877 	/// Creates a copy of the given map.
878 	///
879 	/// Return: A pointer to the copy or NULL if an error occurred.
880 	@safe @nogc mg_map *mg_map_copy(const mg_map *map) pure nothrow;
881 
882 	/// Destroys the given map.
883 	@safe @nogc void mg_map_destroy(mg_map *map) pure nothrow;
884 
885 	/// Returns the ID of node `node`.
886 	long mg_node_id(const mg_node *node);
887 
888 	/// Returns the number of labels of node `node`.
889 	uint mg_node_label_count(const mg_node *node);
890 
891 	/// Returns the label at position `pos` in node `node`'s label list.
892 	///
893 	/// Return: A pointer to the required label. If `pos` is outside of label list
894 	///         bounds, NULL is returned.
895 	const (mg_string) *mg_node_label_at(const mg_node *node, uint pos);
896 
897 	/// Returns property map of node `node`.
898 	const (mg_map) *mg_node_properties(const mg_node *node);
899 
900 	/// Creates a copy of the given node.
901 	///
902 	/// Return: A pointer to the copy or NULL if an error occurred.
903 	@safe @nogc mg_node *mg_node_copy(const mg_node *node) pure nothrow;
904 
905 	/// Destroys the given node.
906 	@safe @nogc void mg_node_destroy(mg_node *node) pure nothrow;
907 
908 	/// Returns the ID of the relationship `rel`.
909 	long mg_relationship_id(const mg_relationship *rel);
910 
911 	/// Returns the ID of the start node of relationship `rel`.
912 	long mg_relationship_start_id(const mg_relationship *rel);
913 
914 	/// Returns the ID of the end node of relationship `rel`.
915 	long mg_relationship_end_id(const mg_relationship *rel);
916 
917 	/// Returns the type of the relationship `rel`.
918 	const (mg_string) *mg_relationship_type(const mg_relationship *rel);
919 
920 	/// Returns the property map of the relationship `rel`.
921 	const (mg_map) *mg_relationship_properties(const mg_relationship *rel);
922 
923 	/// Creates a copy of the given relationship.
924 	///
925 	/// Return: A pointer to the copy or NULL if an error occurred.
926 	@safe @nogc mg_relationship *mg_relationship_copy(const mg_relationship *rel) pure nothrow;
927 
928 	/// Destroys the given relationship.
929 	@safe @nogc void mg_relationship_destroy(mg_relationship *rel) pure nothrow;
930 
931 	/// Returns the ID of the unbound relationship `rel`.
932 	long mg_unbound_relationship_id(const mg_unbound_relationship *rel);
933 
934 	/// Returns the type of the unbound relationship `rel`.
935 	const (mg_string) *mg_unbound_relationship_type(const mg_unbound_relationship *rel);
936 
937 	/// Returns the property map of the unbound relationship `rel`.
938 	const (mg_map) *mg_unbound_relationship_properties(const mg_unbound_relationship *rel);
939 
940 	/// Creates a copy of the given unbound relationship.
941 	///
942 	/// Return: A pointer to the copy or NULL if an error occurred.
943 	@safe @nogc mg_unbound_relationship *mg_unbound_relationship_copy(const mg_unbound_relationship *rel) pure nothrow;
944 
945 	/// Destroys the given unbound relationship.
946 	@safe @nogc void mg_unbound_relationship_destroy(mg_unbound_relationship *rel) pure nothrow;
947 
948 	/// Returns the length (the number of edges) of path `path`.
949 	uint mg_path_length(const mg_path *path);
950 
951 	/// Returns the node at position `pos` in the traversal of path `path`.
952 	///
953 	/// Nodes are indexed from 0 to path length.
954 	///
955 	/// Return: A pointer to the required node. If `pos` is out of path bounds,
956 	///         NULL is returned.
957 	const (mg_node) *mg_path_node_at(const mg_path *path, uint pos);
958 
959 	/// Returns the relationship at position `pos` in traversal of path `path`.
960 	///
961 	/// Relationships are indexed from 0 to path length - 1.
962 	///
963 	/// Return: A pointer to the required relationship. If `pos` is outside of
964 	///         path bounds, NULL is returned.
965 	const (mg_unbound_relationship) *mg_path_relationship_at(const mg_path *path, uint pos);
966 
967 	/// Checks if the relationship at position `pos` in traversal of path `path`
968 	/// is reversed.
969 	///
970 	/// Relationships are indexed from 0 to path length - 1.
971 	///
972 	/// Return: Returns 0 if relationships is traversed in the same direction as the
973 	///         underlying relationship in the data graph, and 1 if it is traversed
974 	///         in the opposite direction. If `pos` is outside of path bounds, -1
975 	///         is returned.
976 	int mg_path_relationship_reversed_at(const mg_path *path, uint pos);
977 
978 	/// Creates a copy of the given path.
979 	///
980 	/// Return: A pointer to the copy or NULL if an error occurred.
981 	@safe @nogc mg_path *mg_path_copy(const mg_path *path) pure nothrow;
982 
983 	/// Destroys the given path.
984 	@safe @nogc void mg_path_destroy(mg_path *path) pure nothrow;
985 
986 	/// Returns days since the Unix epoch.
987 	long mg_date_days(const mg_date *date);
988 
989 	/// Creates a copy of the given date.
990 	///
991 	/// Return: A pointer to the copy or NULL if an error occured.
992 	@safe @nogc mg_date *mg_date_copy(const mg_date *date) pure nothrow;
993 
994 	/// Destroys the given date.
995 	@safe @nogc void mg_date_destroy(mg_date *date) pure nothrow;
996 
997 	/// Returns nanoseconds since midnight.
998 	long mg_time_nanoseconds(const mg_time *time);
999 
1000 	/// Returns time zone offset in seconds from UTC.
1001 	long mg_time_tz_offset_seconds(const mg_time *time);
1002 
1003 	/// Creates a copy of the given time.
1004 	///
1005 	/// Return: A pointer to the copy or NULL if an error occured.
1006 	@safe @nogc mg_time *mg_time_copy(const mg_time *time) pure nothrow;
1007 
1008 	/// Destroys the given time.
1009 	@safe @nogc void mg_time_destroy(mg_time *time) pure nothrow;
1010 
1011 	/// Returns nanoseconds since midnight.
1012 	long mg_local_time_nanoseconds(const mg_local_time *local_time);
1013 
1014 	/// Creates a copy of the given local time.
1015 	///
1016 	/// Return: A pointer to the copy or NULL if an error occured.
1017 	@safe @nogc mg_local_time *mg_local_time_copy(const mg_local_time *local_time) pure nothrow;
1018 
1019 	/// Destroys the given local time.
1020 	@safe @nogc void mg_local_time_destroy(mg_local_time *local_time) pure nothrow;
1021 
1022 	/// Returns seconds since Unix epoch.
1023 	long mg_date_time_seconds(const mg_date_time *date_time);
1024 
1025 	/// Returns nanoseconds since midnight.
1026 	long mg_date_time_nanoseconds(const mg_date_time *date_time);
1027 
1028 	/// Returns time zone offset in minutes from UTC.
1029 	long mg_date_time_tz_offset_minutes(const mg_date_time *date_time);
1030 
1031 	/// Creates a copy of the given date and time.
1032 	///
1033 	/// Return: A pointer to the copy or NULL if an error occured.
1034 	@safe @nogc mg_date_time *mg_date_time_copy(const mg_date_time *date_time) pure nothrow;
1035 
1036 	/// Destroys the given date and time.
1037 	@safe @nogc void mg_date_time_destroy(mg_date_time *date_time) pure nothrow;
1038 
1039 	/// Returns seconds since Unix epoch.
1040 	long mg_date_time_zone_id_seconds(const mg_date_time_zone_id *date_time_zone_id);
1041 
1042 	/// Returns nanoseconds since midnight.
1043 	long mg_date_time_zone_id_nanoseconds(const mg_date_time_zone_id *date_time_zone_id);
1044 
1045 	/// Returns time zone represented by the identifier.
1046 	long mg_date_time_zone_id_tz_id(const mg_date_time_zone_id *date_time_zone_id);
1047 
1048 	/// Creates a copy of the given date and time.
1049 	///
1050 	/// Return: A pointer to the copy or NULL if an error occured.
1051 	@safe @nogc mg_date_time_zone_id *mg_date_time_zone_id_copy(const mg_date_time_zone_id *date_time_zone_id) pure nothrow;
1052 
1053 	/// Destroys the given date and time.
1054 	@safe @nogc void mg_date_time_zone_id_destroy(mg_date_time_zone_id *date_time_zone_id) pure nothrow;
1055 
1056 	/// Returns seconds since Unix epoch.
1057 	long mg_local_date_time_seconds(const mg_local_date_time *local_date_time);
1058 
1059 	/// Returns nanoseconds since midnight.
1060 	long mg_local_date_time_nanoseconds(const mg_local_date_time *local_date_time);
1061 
1062 	/// Creates a copy of the given local date and time.
1063 	///
1064 	/// Return: A pointer to the copy or NULL if an error occured.
1065 	@safe @nogc mg_local_date_time *mg_local_date_time_copy(const mg_local_date_time *local_date_time) pure nothrow;
1066 
1067 	/// Destroy the given local date and time.
1068 	@safe @nogc void mg_local_date_time_destroy(mg_local_date_time *local_date_time) pure nothrow;
1069 
1070 	/// Returns the months part of the temporal amount.
1071 	long mg_duration_months(const mg_duration *duration);
1072 
1073 	/// Returns the days part of the temporal amount.
1074 	long mg_duration_days(const mg_duration *duration);
1075 
1076 	/// Returns the seconds part of the temporal amount.
1077 	long mg_duration_seconds(const mg_duration *duration);
1078 
1079 	/// Returns the nanoseconds part of the temporal amount.
1080 	long mg_duration_nanoseconds(const mg_duration *duration);
1081 
1082 	/// Creates a copy of the given duration.
1083 	///
1084 	/// Return: A pointer to the copy or NULL if an error occured.
1085 	@safe @nogc mg_duration *mg_duration_copy(const mg_duration *duration) pure nothrow;
1086 
1087 	/// Destroy the given duration.
1088 	@safe @nogc void mg_duration_destroy(mg_duration *duration) pure nothrow;
1089 
1090 	/// Returns SRID of the 2D point.
1091 	long mg_point_2d_srid(const mg_point_2d *point_2d);
1092 
1093 	/// Returns the x coordinate of the 2D point.
1094 	double mg_point_2d_x(const mg_point_2d *point_2d);
1095 
1096 	/// Returns the y coordinate of the 2D point.
1097 	double mg_point_2d_y(const mg_point_2d *point_2d);
1098 
1099 	/// Creates a copy of the given 2D point.
1100 	///
1101 	/// Return: A pointer to the copy or NULL if an error occured.
1102 	@safe @nogc mg_point_2d *mg_point_2d_copy(const mg_point_2d *point_2d) pure nothrow;
1103 
1104 	/// Destroys the given 2D point.
1105 	@safe @nogc void mg_point_2d_destroy(mg_point_2d *point_2d) pure nothrow;
1106 
1107 	/// Returns SRID of the 3D point.
1108 	long mg_point_3d_srid(const mg_point_3d *point_3d);
1109 
1110 	/// Returns the x coordinate of the 3D point.
1111 	double mg_point_3d_x(const mg_point_3d *point_3d);
1112 
1113 	/// Returns the y coordinate of the 3D point.
1114 	double mg_point_3d_y(const mg_point_3d *point_3d);
1115 
1116 	/// Returns the z coordinate of the 3D point.
1117 	double mg_point_3d_z(const mg_point_3d *point_3d);
1118 
1119 	/// Creates a copy of the given 3D point.
1120 	///
1121 	/// Return: A pointer to the copy or NULL if an error occured.
1122 	@safe @nogc mg_point_3d *mg_point_3d_copy(const mg_point_3d *point_3d) pure nothrow;
1123 
1124 	/// Destroys the given 3D point.
1125 	@safe @nogc void mg_point_3d_destroy(mg_point_3d *point_3d) pure nothrow;
1126 
1127 	/// Return codes for `mg_session_status`.
1128 	enum mg_session_code {
1129 		/// Marks a `mg_session` ready to execute a new query using `mg_session_run`.
1130 		MG_SESSION_READY = 0,
1131 		/// Marks a `mg_session` which is currently executing a query. Results can be
1132 		/// pulled using `mg_session_pull`.
1133 		MG_SESSION_EXECUTING = 1,
1134 		/// Marks a bad `mg_session` which cannot be used to execute queries and can
1135 		/// only be destroyed.
1136 		MG_SESSION_BAD = 2,
1137 		/// Marks a `mg_session` which is currently fetching result of a query.
1138 		/// Results can be fetched using `mg_session_fetch`.
1139 		MG_SESSION_FETCHING = 3
1140 	}
1141 
1142 	/// Return codes used by mgclient functions.
1143 	enum mg_error {
1144 		/// Success code.
1145 		MG_SUCCESS = 0,
1146 		/// Failed to send data to server.
1147 		MG_ERROR_SEND_FAILED = -1,
1148 		/// Failed to receive data from server.
1149 		MG_ERROR_RECV_FAILED = -2,
1150 		/// Out of memory.
1151 		MG_ERROR_OOM = -3,
1152 		/// Trying to insert more values in a full container.
1153 		MG_ERROR_CONTAINER_FULL = -4,
1154 		/// Invalid value type was given as a function argument.
1155 		MG_ERROR_INVALID_VALUE = -5,
1156 		/// Failed to decode data returned from server.
1157 		MG_ERROR_DECODING_FAILED = -6,
1158 		/// Trying to insert a duplicate key in map.
1159 		MG_ERROR_DUPLICATE_KEY = -7,
1160 		/// An error occurred while trying to connect to server.
1161 		MG_ERROR_NETWORK_FAILURE = -8,
1162 		/// Invalid parameter supplied to `mg_connect`.
1163 		MG_ERROR_BAD_PARAMETER = -9,
1164 		/// Server violated the Bolt protocol by sending an invalid message type or
1165 		/// invalid value.
1166 		MG_ERROR_PROTOCOL_VIOLATION = -10,
1167 		/// Server sent a FAILURE message containing ClientError code.
1168 		MG_ERROR_CLIENT_ERROR = -11,
1169 		/// Server sent a FAILURE message containing TransientError code.
1170 		MG_ERROR_TRANSIENT_ERROR = -12,
1171 		/// Server sent a FAILURE message containing DatabaseError code.
1172 		MG_ERROR_DATABASE_ERROR = -13,
1173 		/// Got an unknown error message from server.
1174 		MG_ERROR_UNKNOWN_ERROR = -14,
1175 		/// Invalid usage of the library.
1176 		MG_ERROR_BAD_CALL = -15,
1177 		/// Maximum container size allowed by Bolt exceeded.
1178 		MG_ERROR_SIZE_EXCEEDED = -16,
1179 		/// An error occurred during SSL connection negotiation.
1180 		MG_ERROR_SSL_ERROR = -17,
1181 		/// User provided trust callback returned a non-zeron value after SSL connection
1182 		/// negotiation.
1183 		MG_ERROR_TRUST_CALLBACK = -18,
1184 		/// Unable to initialize the socket (both create and connect).
1185 		MG_ERROR_SOCKET = -100,
1186 		/// Function unimplemented.
1187 		MG_ERROR_UNIMPLEMENTED = -1000
1188 	}
1189 
1190 	/// Determines whether a secure SSL TCP/IP connection will be negotiated with
1191 	/// the server.
1192 	enum mg_sslmode {
1193 		/// Only try a non-SSL connection.
1194 		MG_SSLMODE_DISABLE,
1195 		/// Only try a SSL connection.
1196 		MG_SSLMODE_REQUIRE,
1197 	}
1198 
1199 	/// An object encapsulating a Bolt session.
1200 	struct mg_session;
1201 
1202 	/// An object containing parameters for `mg_connect`.
1203 	///
1204 	/// Currently recognized parameters are:
1205 	///  - host
1206 	///
1207 	///      DNS resolvable name of host to connect to. Exactly one of host and
1208 	///      address parameters must be specified.
1209 	///
1210 	///  - address
1211 	///
1212 	///      Numeric IP address of host to connect to. This should be in the
1213 	///      standard IPv4 address format. You can also use IPv6 if your machine
1214 	///      supports it. Exactly one of host and address parameters must be
1215 	///      specified.
1216 	///
1217 	///  - port
1218 	///
1219 	///      Port number to connect to at the server host.
1220 	///
1221 	///  - username
1222 	///
1223 	///      Username to connect as.
1224 	///
1225 	///  - password
1226 	///
1227 	///      Password to be used if the server demands password authentication.
1228 	///
1229 	///  - user_agent
1230 	///
1231 	///      Alternate name and version of the client to send to server. Default is
1232 	///      "MemgraphBolt/0.1".
1233 	///
1234 	///  - sslmode
1235 	///
1236 	///      This option determines whether a secure connection will be negotiated
1237 	///      with the server. There are 2 possible values:
1238 	///
1239 	///      - `MG_SSLMODE_DISABLE`
1240 	///
1241 	///        Only try a non-SSL connection (default).
1242 	///
1243 	///      - `MG_SSLMODE_REQUIRE`
1244 	///
1245 	///        Only try an SSL connection.
1246 	///
1247 	///  - sslcert
1248 	///
1249 	///      This parameter specifies the file name of the client SSL certificate.
1250 	///      It is ignored in case an SSL connection is not made.
1251 	///
1252 	///  - sslkey
1253 	///
1254 	///     This parameter specifies the location of the secret key used for the
1255 	///     client certificate. This parameter is ignored in case an SSL connection
1256 	///     is not made.
1257 	///
1258 	///  - trust_callback
1259 	///
1260 	///     A pointer to a function of prototype:
1261 	///        int trust_callback(const char *hostname, const char *ip_address,
1262 	///                           const char *key_type, const char *fingerprint,
1263 	///                           void *trust_data);
1264 	///
1265 	///     After performing the SSL handshake, `mg_connect` will call this
1266 	///     function providing the hostname, IP address, public key type and
1267 	///     fingerprint and user provided data. If the function returns a non-zero
1268 	///     value, SSL connection will be immediately terminated. This can be used
1269 	///     to implement TOFU (trust on first use) mechanism.
1270 	///     It might happen that hostname can not be determined, in that case the
1271 	///     trust callback will be called with hostname="undefined".
1272 	///
1273 	///  - trust_data
1274 	///
1275 	///    Additional data that will be provided to trust_callback function.
1276 	struct mg_session_params;
1277 
1278 	/// Prototype of the callback function for verifying an SSL connection by user.
1279 	alias mg_trust_callback_type = int function(const char *, const char *, const char *, const char *, void *);
1280 
1281 	/// Creates a new `mg_session_params` object.
1282 	@safe @nogc mg_session_params *mg_session_params_make() pure nothrow;
1283 
1284 	/// Destroys a `mg_session_params` object.
1285 	@safe @nogc void mg_session_params_destroy(mg_session_params *) pure nothrow;
1286 
1287 	/// Getters and setters for `mg_session_params` values.
1288 	void mg_session_params_set_address(mg_session_params *, const char *address);
1289 	void mg_session_params_set_host(mg_session_params *, const char *host);
1290 	void mg_session_params_set_port(mg_session_params *, ushort port);
1291 	void mg_session_params_set_username(mg_session_params *, const char *username);
1292 	void mg_session_params_set_password(mg_session_params *, const char *password);
1293 	void mg_session_params_set_user_agent(mg_session_params *, const char *user_agent);
1294 	void mg_session_params_set_sslmode(mg_session_params *, mg_sslmode sslmode);
1295 	void mg_session_params_set_sslcert(mg_session_params *, const char *sslcert);
1296 	void mg_session_params_set_sslkey(mg_session_params *, const char *sslkey);
1297 	void mg_session_params_set_trust_callback(mg_session_params *, mg_trust_callback_type trust_callback);
1298 	void mg_session_params_set_trust_data(mg_session_params *, void *trust_data);
1299 	const (char) *mg_session_params_get_address(const mg_session_params *);
1300 	const (char) *mg_session_params_get_host(const mg_session_params *);
1301 	ushort mg_session_params_get_port(const mg_session_params *);
1302 	const (char) *mg_session_params_get_username(const mg_session_params *);
1303 	const (char) *mg_session_params_get_password(const mg_session_params *);
1304 	const (char) *mg_session_params_get_user_agent(const mg_session_params *);
1305 	mg_sslmode mg_session_params_get_sslmode(const mg_session_params *);
1306 	const (char) *mg_session_params_get_sslcert(const mg_session_params *);
1307 	const (char) *mg_session_params_get_sslkey(const mg_session_params *);
1308 	mg_trust_callback_type mg_session_params_get_trust_callback(const mg_session_params *params);
1309 	void *mg_session_params_get_trust_data(const mg_session_params *);
1310 
1311 	/// Makes a new connection to the database server.
1312 	///
1313 	/// This function opens a new database connection using the parameters specified
1314 	/// in provided `params` argument.
1315 	///
1316 	/// Params:  params = New Bolt connection parameters. See documentation for
1317 	///                     `mg_session_params`.
1318 	///         session = A pointer to a newly created `mg_session` is written
1319 	///                     here, unless there wasn't enough memory to allocate a
1320 	///                     `mg_session` object. In that case, it is set to NULL.
1321 	///
1322 	/// Return: Returns 0 if connected successfuly, otherwise returns a non-zero
1323 	///         error code. A more detailed error message can be obtained by using
1324 	///         `mg_session_error` on `session`, unless it is set to NULL.
1325 	int mg_connect(const mg_session_params *params, mg_session **session);
1326 
1327 	/// Returns the status of `mg_session`.
1328 	///
1329 	/// Return: One of the session codes in `mg_session_code`.
1330 	mg_session_code mg_session_status(const mg_session *session);
1331 
1332 	/// Obtains the error message stored in `mg_session` (if any).
1333 	const (char) *mg_session_error(mg_session *session);
1334 
1335 	/// Destroys a `mg_session` and releases all of its resources.
1336 	@safe @nogc void mg_session_destroy(mg_session *session) pure nothrow;
1337 
1338 	/// An object encapsulating a single result row or query execution summary. Its
1339 	/// lifetime is limited by lifetime of parent `mg_session`. Also, invoking
1340 	/// `mg_session_pull` ends the lifetime of previously returned `mg_result`.
1341 	struct mg_result;
1342 
1343 	/// Submits a query to the server for execution.
1344 	///
1345 	/// All records from the previous query must be pulled before executing the
1346 	/// next query.
1347 	///
1348 	/// Params: session =             A `mg_session` to be used for query execution.
1349 	///         query =               Query string.
1350 	///         params =              A `mg_map` containing query parameters. NULL
1351 	///                              can be supplied instead of an empty parameter
1352 	///                              map.
1353 	///         columns =            Names of the columns output by the query
1354 	///                              execution will be stored in here. This is the
1355 	///                              same as the value
1356 	///                              obtained by `mg_result_columns` on a pulled
1357 	///                              `mg_result`. NULL can be supplied if we're
1358 	///                              not interested in the columns names.
1359 	///      extra_run_information = A `mg_map` containing extra information for
1360 	///                              running the statement.
1361 	///                              It can contain the following information:
1362 	///                               - bookmarks - list of strings containing some
1363 	///                               kind of bookmark identification
1364 	///                               - tx_timeout - integer that specifies a
1365 	///                               transaction timeout in ms.
1366 	///                               - tx_metadata - dictionary taht can contain
1367 	///                               some metadata information, mainly used for
1368 	///                               logging.
1369 	///                               - mode - specifies what kind of server is the
1370 	///                               run targeting. For write access use "w" and
1371 	///                               for read access use "r". Defaults to write
1372 	///                               access.
1373 	///                               - db - specifies the database name for
1374 	///                               multi-database to select where the transaction
1375 	///                               takes place. If no `db` is sent or empty
1376 	///                               string it implies that it is the default
1377 	///                               database.
1378 	///            qid =              QID for the statement will be stored in here
1379 	///                               if an Explicit transaction was started.
1380 	/// Return: Returns 0 if query was submitted for execution successfuly.
1381 	///         Otherwise, a non-zero error code is returned.
1382 	int mg_session_run(mg_session *session, const char *query, const mg_map *params, const mg_map *extra_run_information, const mg_list **columns, long *qid);
1383 
1384 	/// Starts an Explicit transaction on the server.
1385 	///
1386 	/// Every run will be part of that transaction until its explicitly ended.
1387 	///
1388 	/// Params: session =              A `mg_session` on which the transaction should be started.
1389 	///       extra_run_information  = A `mg_map` containing extra information that will be used
1390 	///                                 for every statement that is ran as part of the transaction.
1391 	///                              It can contain the following information:
1392 	///                               - bookmarks - list of strings containing some
1393 	///                               kind of bookmark identification
1394 	///                               - tx_timeout - integer that specifies a
1395 	///                               transaction timeout in ms.
1396 	///                               - tx_metadata - dictionary taht can contain
1397 	///                               some metadata information, mainly used for
1398 	///                               logging.
1399 	///                               - mode - specifies what kind of server is the
1400 	///                               run targeting. For write access use "w" and
1401 	///                               for read access use "r". Defaults to write
1402 	///                               access.
1403 	///                               - db - specifies the database name for
1404 	///                               multi-database to select where the transaction
1405 	///                               takes place. If no `db` is sent or empty
1406 	///                               string it implies that it is the default
1407 	///                               database.
1408 	/// Return: Returns 0 if the transaction was started successfully.
1409 	///         Otherwise, a non-zero error code is returned.
1410 	int mg_session_begin_transaction(mg_session *session, const mg_map *extra_run_information);
1411 
1412 	/// Commits current Explicit transaction.
1413 	///
1414 	/// Params: session = A `mg_session` on which the transaction should be committed.
1415 	///         result =  Contains the information about the committed transaction
1416 	///                   if it was successful.
1417 	/// Return: Returns 0 if the transaction was ended successfully.
1418 	///         Otherwise, a non-zero error code is returned.
1419 	int mg_session_commit_transaction(mg_session *session, mg_result **result);
1420 
1421 	/// Rollbacks current Explicit transaction.
1422 	///
1423 	/// Params: session = A `mg_session` on which the transaction should be rolled back.
1424 	///         result =  Contains the information about the rolled back transaction
1425 	///                   if it was successful.
1426 	/// Return: Returns 0 if the transaction was ended successfully.
1427 	///         Otherwise, a non-zero error code is returned.
1428 	int mg_session_rollback_transaction(mg_session *session, mg_result **result);
1429 
1430 	/// Tries to fetch the next query result from `mg_session`.
1431 	///
1432 	/// The owner of the returned result is `mg_session` `session`, and the
1433 	/// result is destroyed on next call to `mg_session_fetch`.
1434 	///
1435 	/// Return: On success, 0 or 1 is returned. Exit code 1 means that a new result
1436 	///         row was obtained and stored in `result` and its contents may be
1437 	///         accessed using `mg_result_row`. Exit code 0 means that there are
1438 	///         no more result rows and that the query execution summary was stored
1439 	///         in `result`. Its contents may be accessed using `mg_result_summary`.
1440 	///         On failure, a non-zero exit code is returned.
1441 	int mg_session_fetch(mg_session *session, mg_result **result);
1442 
1443 	/// Tries to pull results of a statement.
1444 	///
1445 	/// Params: session =       A `mg_session` from which the results should be pulled.
1446 	///      pull_information = A `mg_map` that contains extra information for pulling the results.
1447 	///                         It can contain the following information:
1448 	///                          - n - how many records to fetch. `n=-1` will fetch
1449 	///                          all records.
1450 	///                          - qid - query identification, specifies the result
1451 	///                          from which statement the results should be pulled.
1452 	///                          `qid=-1` denotes the last executed statement. This
1453 	///                          is only for Explicit transactions.
1454 	/// Return: Returns 0 if the result was pulled successfuly.
1455 	///         Otherwise, a non-zero error code is returned.
1456 	int mg_session_pull(mg_session *session, const mg_map *pull_information);
1457 
1458 	/// Returns names of columns output by the current query execution.
1459 	const (mg_list) *mg_result_columns(const mg_result *result);
1460 
1461 	/// Returns column values of current result row.
1462 	const (mg_list) *mg_result_row(const mg_result *result);
1463 
1464 	/// Returns query execution summary.
1465 	const (mg_map) *mg_result_summary(const mg_result *result);
1466 }
1467 
1468 version(unittest) {
1469 	// Extern C definitions for allocation of memgraph internal types.
1470 	extern (C) {
1471 		// Need at least an empty definition for extern struct.
1472 		struct mg_allocator {}
1473 		extern shared mg_allocator mg_system_allocator;
1474 
1475 		@safe @nogc mg_string *mg_string_alloc(uint size, mg_allocator *allocator);
1476 		@safe @nogc mg_list *mg_list_alloc(uint size, mg_allocator *allocator);
1477 		@safe @nogc mg_map *mg_map_alloc(uint size, mg_allocator *allocator);
1478 		@safe @nogc mg_node *mg_node_alloc(uint label_count, mg_allocator *allocator);
1479 		@safe @nogc mg_path *mg_path_alloc(uint node_count, uint relationship_count, uint sequence_length, mg_allocator *allocator);
1480 
1481 		@safe @nogc mg_date *mg_date_alloc(shared mg_allocator *alloc) pure nothrow;
1482 		@safe @nogc mg_time *mg_time_alloc(shared mg_allocator *alloc) pure nothrow;
1483 		@safe @nogc mg_local_time *mg_local_time_alloc(shared mg_allocator *alloc) pure nothrow;
1484 		@safe @nogc mg_date_time *mg_date_time_alloc(shared mg_allocator *alloc) pure nothrow;
1485 		@safe @nogc mg_date_time_zone_id *mg_date_time_zone_id_alloc(shared mg_allocator *alloc) pure nothrow;
1486 		@safe @nogc mg_local_date_time *mg_local_date_time_alloc(shared mg_allocator *alloc) pure nothrow;
1487 		@safe @nogc mg_duration *mg_duration_alloc(shared mg_allocator *alloc) pure nothrow;
1488 
1489 		@safe @nogc mg_point_2d *mg_point_2d_alloc(shared mg_allocator *allocator) pure nothrow;
1490 		@safe @nogc mg_point_3d *mg_point_3d_alloc(shared mg_allocator *allocator) pure nothrow;
1491 	}
1492 }
1493 
1494 unittest {
1495 	import testutils : startContainer;
1496 	startContainer();
1497 }
1498 
1499 /// Test connection to memgraph on 127.0.0.1, port 7688.
1500 unittest {
1501 	import std..string : toStringz, fromStringz;
1502 	import std.conv : to;
1503 
1504 	assert(mg_init() == 0);
1505 
1506 	auto params = mg_session_params_make();
1507 	assert(params != null);
1508 
1509 	mg_session_params_set_host(params, toStringz("127.0.0.1"));
1510 	mg_session_params_set_port(params, to!ushort(7688));
1511 	mg_session_params_set_sslmode(params, mg_sslmode.MG_SSLMODE_DISABLE);
1512 
1513 	mg_session *session = null;
1514 	int status = mg_connect(params, &session);
1515 	mg_session_params_destroy(params);
1516 
1517 	assert(status == 0, fromStringz(mg_session_error(session)));
1518 
1519 	mg_session_destroy(session);
1520 	mg_finalize();
1521 }