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   @safe @nogc const (char) *mg_client_version() pure nothrow;
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   @safe @nogc mg_error mg_init() pure nothrow;
128 
129   /// Finalizes the client (the whole process).
130   /// Should be called at the end of each process using the client.
131   @safe @nogc void mg_finalize() pure nothrow;
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   @safe @nogc mg_value_type mg_value_get_type(const mg_value *val) pure nothrow;
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   @safe @nogc bool mg_value_bool(const mg_value *val) pure nothrow;
556 
557   /// Returns the underlying integer value.
558   ///
559   /// Type check should be made first. Accessing the wrong value results in
560   /// undefined behavior.
561   @safe @nogc long mg_value_integer(const mg_value *val) pure nothrow;
562 
563   /// Returns the underlying float value.
564   ///
565   /// Type check should be made first. Accessing the wrong value results in
566   /// undefined behavior.
567   @safe @nogc double mg_value_float(const mg_value *val) pure nothrow;
568 
569   /// Returns the underlying `mg_string` value.
570   ///
571   /// Type check should be made first. Accessing the wrong value results in
572   /// undefined behavior.
573   @safe @nogc const (mg_string) *mg_value_string(const mg_value *val) pure nothrow;
574 
575   /// Returns the underlying `mg_list` value.
576   ///
577   /// Type check should be made first. Accessing the wrong value results in
578   /// undefined behavior.
579   @safe @nogc const (mg_list) *mg_value_list(const mg_value *val) pure nothrow;
580 
581   /// Returns the underlying `mg_map` value.
582   ///
583   /// Type check should be made first. Accessing the wrong value results in
584   /// undefined behavior.
585   @safe @nogc const (mg_map) *mg_value_map(const mg_value *val) pure nothrow;
586 
587   /// Returns the underlying `mg_node` value.
588   ///
589   /// Type check should be made first. Accessing the wrong value results in
590   /// undefined behavior.
591   @safe @nogc const (mg_node) *mg_value_node(const mg_value *val) pure nothrow;
592 
593   /// Returns the underlying `mg_relationship` value.
594   ///
595   /// Type check should be made first. Accessing the wrong value results in
596   /// undefined behavior.
597   @safe @nogc const (mg_relationship) *mg_value_relationship(const mg_value *val) pure nothrow;
598 
599   /// Returns the underlying `mg_unbound_relationship` value.
600   ///
601   /// Type check should be made first. Accessing the wrong value results in
602   /// undefined behavior.
603   @safe @nogc const (mg_unbound_relationship) *mg_value_unbound_relationship(const mg_value *val) pure nothrow;
604 
605   /// Returns the underlying `mg_path` value.
606   ///
607   /// Type check should be made first. Accessing the wrong value results in
608   /// undefined behavior.
609   @safe @nogc const (mg_path) *mg_value_path(const mg_value *val) pure nothrow;
610 
611   /// Returns the underlying `mg_date` value.
612   ///
613   /// Type check should be made first. Accessing the wrong value results in
614   /// undefined behavior.
615   @safe @nogc const (mg_date) *mg_value_date(const mg_value *val) pure nothrow;
616 
617   /// Returns the underlying `mg_time` value.
618   ///
619   /// Type check should be made first. Accessing the wrong value results in
620   /// undefined behavior.
621   @safe @nogc const (mg_time) *mg_value_time(const mg_value *val) pure nothrow;
622 
623   /// Returns the underlying `mg_local_time` value.
624   ///
625   /// Type check should be made first. Accessing the wrong value results in
626   /// undefined behavior.
627   @safe @nogc const (mg_local_time) *mg_value_local_time(const mg_value *val) pure nothrow;
628 
629   /// Returns the underlying `mg_date_time` value.
630   ///
631   /// Type check should be made first. Accessing the wrong value results in
632   /// undefined behavior.
633   @safe @nogc const (mg_date_time) *mg_value_date_time(const mg_value *val) pure nothrow;
634 
635   /// Returns the underlying `mg_date_time_zone_id` value.
636   ///
637   /// Type check should be made first. Accessing the wrong value results in
638   /// undefined behavior.
639   @safe @nogc const (mg_date_time_zone_id) *mg_value_date_time_zone_id(const mg_value *val) pure nothrow;
640 
641   /// Returns the underlying `mg_local_date_time` value.
642   ///
643   /// Type check should be made first. Accessing the wrong value results in
644   /// undefined behavior.
645   @safe @nogc const (mg_local_date_time) *mg_value_local_date_time(const mg_value *val) pure nothrow;
646 
647   /// Returns the underlying `mg_duration` value.
648   ///
649   /// Type check should be made first. Accessing the wrong value results in
650   /// undefined behavior.
651   @safe @nogc const (mg_duration) *mg_value_duration(const mg_value *val) pure nothrow;
652 
653   /// Returns the underlying `mg_point_2d` value.
654   ///
655   /// Type check should be made first. Accessing the wrong value results in
656   /// undefined behavior.
657   @safe @nogc const (mg_point_2d) *mg_value_point_2d(const mg_value *val) pure nothrow;
658 
659   /// Returns the underlying `mg_point_3d` value.
660   ///
661   /// Type check should be made first. Accessing the wrong value results in
662   /// undefined behavior.
663   @safe @nogc const (mg_point_3d) *mg_value_point_3d(const mg_value *val) pure nothrow;
664 
665   /// Creates a copy of the given value.
666   ///
667   /// Return: Pointer to the copy or NULL if error occurred.
668   @safe @nogc mg_value *mg_value_copy(const mg_value *val) pure nothrow;
669 
670   /// Destroys the given value.
671   @safe @nogc void mg_value_destroy(mg_value *val) pure nothrow;
672 
673   /// Constructs a string given a null-terminated string.
674   ///
675   /// A new buffer of appropriate length will be allocated and the given string
676   /// will be copied there.
677   ///
678   /// Params: str = A null-terminated UTF-8 string.
679   ///
680   /// Return: A pointer to the newly constructed `mg_string` object or NULL
681   ///         if an error occurred.
682   @safe @nogc mg_string *mg_string_make(const char *str) pure nothrow;
683 
684   /// Constructs a string given its length (in bytes) and contents.
685   ///
686   /// A new buffer of will be allocated and the given data will be copied there.
687   ///
688   /// Params: len = Number of bytes in the data buffer.
689   ///        data = The string contents.
690   ///
691   /// Return: A pointer to the newly constructed `mg_string` object or NULL
692   ///         if an error occurred.
693   @safe @nogc mg_string *mg_string_make2(uint len, const char *data) pure nothrow;
694 
695   /// Returns a pointer to the beginning of data buffer of string `str`.
696   @safe @nogc const (char) *mg_string_data(const mg_string *str) pure nothrow;
697 
698   /// Returns the length (in bytes) of string `str`.
699   @safe @nogc uint mg_string_size(const mg_string *str) pure nothrow;
700 
701   /// Creates a copy of the given string.
702   ///
703   /// Return: A pointer to the copy or NULL if an error occurred.
704   @safe @nogc mg_string *mg_string_copy(const mg_string *str) pure nothrow;
705 
706   /// Destroys the given string.
707   @safe @nogc void mg_string_destroy(mg_string *str) pure nothrow;
708 
709   /// Constructs a list that can hold at most `capacity` elements.
710   ///
711   /// Elements should be constructed and then inserted using `mg_list_append`.
712   ///
713   /// Params: capacity = The maximum number of elements that the newly constructed
714   ///                 list can hold.
715   ///
716   /// Return: A pointer to the newly constructed empty list or NULL if an error
717   ///         occurred.
718   @safe @nogc mg_list *mg_list_make_empty(uint capacity) pure nothrow;
719 
720   /// Appends an element at the end of the list `list`.
721   ///
722   /// Insertion will fail if the list capacity is already exhausted. If the
723   /// insertion fails, the map doesn't take ownership of `value`.
724   ///
725   /// Params: list = The list instance to be modified.
726   ///        value = The value to be appended.
727   ///
728   /// Return: The function returns non-zero value if insertion failed, zero
729   ///         otherwise.
730   @safe @nogc mg_error mg_list_append(mg_list *list, mg_value *value) pure nothrow;
731 
732   /// Returns the number of elements in list `list`.
733   @safe @nogc uint mg_list_size(const mg_list *list) pure nothrow;
734 
735   /// Retrieves the element at position `pos` in list `list`.
736   ///
737   /// Return: A pointer to required list element. If `pos` is outside of list
738   ///         bounds, NULL is returned.
739   @safe @nogc const (mg_value) *mg_list_at(const mg_list *list, uint pos) pure nothrow;
740 
741   /// Creates a copy of the given list.
742   ///
743   /// Return: A pointer to the copy or NULL if an error occurred.
744   @safe @nogc mg_list *mg_list_copy(const mg_list *list) pure nothrow;
745 
746   /// Destroys the given list.
747   @safe @nogc void mg_list_destroy(mg_list *list) pure nothrow;
748 
749   /// Constructs an empty map that can hold at most `capacity` key-value pairs.
750   ///
751   /// Key-value pairs should be constructed and then inserted using
752   /// `mg_map_insert`, `mg_map_insert_unsafe` and similar.
753   ///
754   /// Params: capacity = The maximum number of key-value pairs that the newly
755   ///                 constructed list can hold.
756   ///
757   /// Return: A pointer to the newly constructed empty map or NULL if an error
758   ///         occurred.
759   @safe @nogc mg_map *mg_map_make_empty(uint capacity) pure nothrow;
760 
761   /// Inserts the given key-value pair into the map.
762   ///
763   /// A check is performed to see if the given key is unique in the map which
764   /// means that a number of key comparisons equal to the current number of
765   /// elements in the map is made.
766   ///
767   /// If key length is greater that `uint.max`, or the key already exists in
768   /// map, or the map's capacity is exhausted, the insertion will fail. If
769   /// insertion fails, the map doesn't take ownership of `value`.
770   ///
771   /// If the insertion is successful, a new `mg_string` is constructed for
772   /// the storage of the key and the map takes ownership of `value`.
773   ///
774   /// Params: map =   The map instance to be modifed.
775   ///      key_str =  A null-terminated string to be used as key.
776   ///         value = Value to be inserted.
777   ///
778   /// Return: The function returns non-zero value if insertion failed, zero
779   ///         otherwise.
780   @safe @nogc mg_error mg_map_insert(mg_map *map, const char *key_str, mg_value *value) pure nothrow;
781 
782   /// Inserts the given key-value pair into the map.
783   ///
784   /// A check is performed to see if the given key is unique in the map which
785   /// means that a number of key comparisons equal to the current number of
786   /// elements in the map is made.
787   ///
788   /// If the key already exists in map, or the map's capacity is exhausted, the
789   /// insertion will fail. If insertion fails, the map doesn't take ownership of
790   /// `key` and `value`.
791   ///
792   /// If the insertion is successful, map takes ownership of `key` and `value`.
793   ///
794   /// Params: map =   The map instance to be modifed.
795   ///         key =   A `mg_string` to be used as key.
796   ///        value =  Value to be inserted.
797   ///
798   /// Return: The function returns non-zero value if insertion failed, zero
799   ///         otherwise.
800   @safe @nogc int mg_map_insert2(mg_map *map, mg_string *key, mg_value *value) pure nothrow;
801 
802   /// Inserts the given key-value pair into the map.
803   ///
804   /// No check is performed for key uniqueness. Note that map containing duplicate
805   /// keys is considered invalid in Bolt protocol.
806   ///
807   /// If key length is greated than `uint.max` or or the map's capacity is
808   /// exhausted, the insertion will fail. If insertion fails, the map doesn't take
809   /// ownership of `value`.
810   ///
811   /// If the insertion is successful, a new `mg_string` is constructed for the
812   /// storage of the key and the map takes ownership of `value`.
813   ///
814   /// Params: map =  The map instance to be modifed.
815   ///      key_str = A null-terminated string to be used as key.
816   ///        value = Value to be inserted.
817   ///
818   /// Return: The function returns non-zero value if insertion failed, zero
819   ///         otherwise.
820   @safe @nogc int mg_map_insert_unsafe(mg_map *map, const char *key_str, mg_value *value) pure nothrow;
821 
822   /// Inserts the given key-value pair into the map.
823   ///
824   /// No check is performed for key uniqueness. Note that map containing duplicate
825   /// keys is considered invalid in Bolt protocol.
826   ///
827   /// If the map's capacity is exhausted, the insertion will fail. If insertion
828   /// fails, the map doesn't take ownership of `key` and `value`.
829   ///
830   /// If the insertion is successful, map takes ownership of `key` and `value`.
831   ///
832   /// Params:  map = The map instance to be modifed.
833   ///          key = A `mg_string` to be used as key.
834   ///        value = Value to be inserted.
835   ///
836   /// Return: The function returns non-zero value if insertion failed, zero
837   ///         otherwise.
838   @safe @nogc int mg_map_insert_unsafe2(mg_map *map, mg_string *key, mg_value *value) pure nothrow;
839 
840   /// Looks up a map value with the given key.
841   ///
842   /// Params: map =  The map instance to be queried.
843   ///      key_str = A null-terminated string representing the key to be looked-up
844   ///                in the map.
845   ///
846   /// Return: If the key is found in the map, the pointer to the corresponding
847   ///         `mg_value` is returned. Otherwise, NULL is returned.
848   @safe @nogc const (mg_value) *mg_map_at(const mg_map *map, const char *key_str) pure nothrow;
849 
850   /// Looks up a map value with the given key.
851   ///
852   /// Params: map =   The map instance to be queried.
853   ///      key_size = The length of the string representing the key to be
854   ///                 looked-up in the map.
855   ///      key_data = Bytes constituting the key string.
856   ///
857   /// Return: If the key is found in the map, the pointer to the corresponding
858   ///         `mg_value` is returned. Otherwise, NULL is returned.
859   @safe @nogc const (mg_value) *mg_map_at2(const mg_map *map, uint key_size, const char *key_data) pure nothrow;
860 
861   /// Returns the number of key-value pairs in map `map`.
862   @safe @nogc uint mg_map_size(const mg_map *map) pure nothrow;
863 
864   /// Retrieves the key at position `pos` in map `map`.
865   ///
866   /// Return: A pointer to required key. If `pos` is outside of map bounds,
867   ///         NULL is returned.
868   @safe @nogc const (mg_string) *mg_map_key_at(const mg_map *, uint pos) pure nothrow;
869 
870   /// Retrieves the value at position `pos` in map `map`.
871   ///
872   /// Return: A pointer to required value. If `pos` is outside of map bounds,
873   ///         NULL is returned.
874   @safe @nogc const (mg_value) *mg_map_value_at(const mg_map *, uint pos) pure nothrow;
875 
876   /// Creates a copy of the given map.
877   ///
878   /// Return: A pointer to the copy or NULL if an error occurred.
879   @safe @nogc mg_map *mg_map_copy(const mg_map *map) pure nothrow;
880 
881   /// Destroys the given map.
882   @safe @nogc void mg_map_destroy(mg_map *map) pure nothrow;
883 
884   /// Constructs a new mg_node with node id `id`, and `labelCount` labels given in `labels`.
885   /// Note: the new node takes ownership of the `properties` mg_map.
886   /// Return: A pointer to the new node or null if an error occurred.
887   @safe @nogc mg_node *mg_node_make(int id, uint labelCount, mg_string **labels, mg_map *properties) pure nothrow;
888 
889   /// Returns the ID of node `node`.
890   @safe @nogc long mg_node_id(const mg_node *node) pure nothrow;
891 
892   /// Returns the number of labels of node `node`.
893   @safe @nogc uint mg_node_label_count(const mg_node *node) pure nothrow;
894 
895   /// Returns the label at position `pos` in node `node`'s label list.
896   ///
897   /// Return: A pointer to the required label. If `pos` is outside of label list
898   ///         bounds, NULL is returned.
899   @safe @nogc const (mg_string) *mg_node_label_at(const mg_node *node, uint pos) pure nothrow;
900 
901   /// Returns property map of node `node`.
902   @safe @nogc const (mg_map) *mg_node_properties(const mg_node *node) pure nothrow;
903 
904   /// Creates a copy of the given node.
905   ///
906   /// Return: A pointer to the copy or NULL if an error occurred.
907   @safe @nogc mg_node *mg_node_copy(const mg_node *node) pure nothrow;
908 
909   /// Destroys the given node.
910   @safe @nogc void mg_node_destroy(mg_node *node) pure nothrow;
911 
912   /// Creates a new relationship with the given parameters.
913   @safe @nogc mg_relationship *mg_relationship_make(long id, long start_id,
914                                       long end_id, mg_string *type,
915                                       mg_map *properties) pure nothrow;
916 
917   /// Returns the ID of the relationship `rel`.
918   @safe @nogc long mg_relationship_id(const mg_relationship *rel) pure nothrow;
919 
920   /// Returns the ID of the start node of relationship `rel`.
921   @safe @nogc long mg_relationship_start_id(const mg_relationship *rel) pure nothrow;
922 
923   /// Returns the ID of the end node of relationship `rel`.
924   @safe @nogc long mg_relationship_end_id(const mg_relationship *rel) pure nothrow;
925 
926   /// Returns the type of the relationship `rel`.
927   @safe @nogc const (mg_string) *mg_relationship_type(const mg_relationship *rel) pure nothrow;
928 
929   /// Returns the property map of the relationship `rel`.
930   @safe @nogc const (mg_map) *mg_relationship_properties(const mg_relationship *rel) pure nothrow;
931 
932   /// Creates a copy of the given relationship.
933   ///
934   /// Return: A pointer to the copy or NULL if an error occurred.
935   @safe @nogc mg_relationship *mg_relationship_copy(const mg_relationship *rel) pure nothrow;
936 
937   /// Destroys the given relationship.
938   @safe @nogc void mg_relationship_destroy(mg_relationship *rel) pure nothrow;
939 
940   /// Creates a new unbound relationship with the given parameters.
941   @safe @nogc mg_unbound_relationship *mg_unbound_relationship_make(long id,
942                                                       mg_string *type,
943                                                       mg_map *properties) pure nothrow;
944 
945   /// Returns the ID of the unbound relationship `rel`.
946   @safe @nogc long mg_unbound_relationship_id(const mg_unbound_relationship *rel) pure nothrow;
947 
948   /// Returns the type of the unbound relationship `rel`.
949   @safe @nogc const (mg_string) *mg_unbound_relationship_type(const mg_unbound_relationship *rel) pure nothrow;
950 
951   /// Returns the property map of the unbound relationship `rel`.
952   @safe @nogc const (mg_map) *mg_unbound_relationship_properties(const mg_unbound_relationship *rel) pure nothrow;
953 
954   /// Creates a copy of the given unbound relationship.
955   ///
956   /// Return: A pointer to the copy or NULL if an error occurred.
957   @safe @nogc mg_unbound_relationship *mg_unbound_relationship_copy(const mg_unbound_relationship *rel) pure nothrow;
958 
959   /// Destroys the given unbound relationship.
960   @safe @nogc void mg_unbound_relationship_destroy(mg_unbound_relationship *rel) pure nothrow;
961 
962   /// Create a new mg_path from the given parameters.
963   @safe @nogc mg_path *mg_path_make(uint node_count, mg_node **nodes,
964                                     uint relationship_count,
965                                     mg_unbound_relationship **relationships,
966                                     uint sequence_length, const long *sequence) pure nothrow;
967 
968   /// Returns the length (the number of edges) of path `path`.
969   @safe @nogc uint mg_path_length(const mg_path *path) pure nothrow;
970 
971   /// Returns the node at position `pos` in the traversal of path `path`.
972   ///
973   /// Nodes are indexed from 0 to path length.
974   ///
975   /// Return: A pointer to the required node. If `pos` is out of path bounds,
976   ///         NULL is returned.
977   @safe @nogc const (mg_node) *mg_path_node_at(const mg_path *path, uint pos) pure nothrow;
978 
979   /// Returns the relationship at position `pos` in traversal of path `path`.
980   ///
981   /// Relationships are indexed from 0 to path length - 1.
982   ///
983   /// Return: A pointer to the required relationship. If `pos` is outside of
984   ///         path bounds, NULL is returned.
985   @safe @nogc const (mg_unbound_relationship) *mg_path_relationship_at(const mg_path *path, uint pos) pure nothrow;
986 
987   /// Checks if the relationship at position `pos` in traversal of path `path`
988   /// is reversed.
989   ///
990   /// Relationships are indexed from 0 to path length - 1.
991   ///
992   /// Return: Returns 0 if relationships is traversed in the same direction as the
993   ///         underlying relationship in the data graph, and 1 if it is traversed
994   ///         in the opposite direction. If `pos` is outside of path bounds, -1
995   ///         is returned.
996   @safe @nogc int mg_path_relationship_reversed_at(const mg_path *path, uint pos) pure nothrow;
997 
998   /// Creates a copy of the given path.
999   ///
1000   /// Return: A pointer to the copy or NULL if an error occurred.
1001   @safe @nogc mg_path *mg_path_copy(const mg_path *path) pure nothrow;
1002 
1003   /// Destroys the given path.
1004   @safe @nogc void mg_path_destroy(mg_path *path) pure nothrow;
1005 
1006   /// Creates a `mg_date` from the given number of days since the Unix epoch.
1007   /// Return: A pointer to a newly allocated mg_date or `null` if an error occurred.
1008   @safe @nogc mg_date *mg_date_make(long days) pure nothrow;
1009 
1010   /// Returns days since the Unix epoch.
1011   @safe @nogc long mg_date_days(const mg_date *date) pure nothrow;
1012 
1013   /// Creates a copy of the given date.
1014   /// Return: A pointer to the copy or NULL if an error occured.
1015   @safe @nogc mg_date *mg_date_copy(const mg_date *date) pure nothrow;
1016 
1017   /// Destroys the given date.
1018   @safe @nogc void mg_date_destroy(mg_date *date) pure nothrow;
1019 
1020   /// Returns nanoseconds since midnight.
1021   @safe @nogc long mg_time_nanoseconds(const mg_time *time) pure nothrow;
1022 
1023   /// Returns time zone offset in seconds from UTC.
1024   @safe @nogc long mg_time_tz_offset_seconds(const mg_time *time) pure nothrow;
1025 
1026   /// Creates a copy of the given time.
1027   ///
1028   /// Return: A pointer to the copy or NULL if an error occured.
1029   @safe @nogc mg_time *mg_time_copy(const mg_time *time) pure nothrow;
1030 
1031   /// Destroys the given time.
1032   @safe @nogc void mg_time_destroy(mg_time *time) pure nothrow;
1033 
1034   /// Creates a `mg_local_time` from nanoseconds.
1035   /// Return: A pointer to `mg_local_time` or `null` if an error occurred.
1036   @safe @nogc mg_local_time *mg_local_time_make(long nanoseconds) pure nothrow;
1037 
1038   /// Returns nanoseconds since midnight.
1039   @safe @nogc long mg_local_time_nanoseconds(const mg_local_time *local_time) pure nothrow;
1040 
1041   /// Creates a copy of the given local time.
1042   ///
1043   /// Return: A pointer to the copy or NULL if an error occured.
1044   @safe @nogc mg_local_time *mg_local_time_copy(const mg_local_time *local_time) pure nothrow;
1045 
1046   /// Destroys the given local time.
1047   @safe @nogc void mg_local_time_destroy(mg_local_time *local_time) pure nothrow;
1048 
1049   /// Creates a `mg_date_time` from the given `seconds`, `nanoseconds` and `tz_offset_minutes`.
1050   /// Return: A pointer to a mg_date_time or `null` if an error occurred.
1051   @safe @nogc mg_date_time *mg_date_time_make(long seconds, long nanoseconds, long tz_offset_minutes) pure nothrow;
1052 
1053   /// Returns seconds since Unix epoch.
1054   @safe @nogc long mg_date_time_seconds(const mg_date_time *date_time) pure nothrow;
1055 
1056   /// Returns nanoseconds since midnight.
1057   @safe @nogc long mg_date_time_nanoseconds(const mg_date_time *date_time) pure nothrow;
1058 
1059   /// Returns time zone offset in minutes from UTC.
1060   @safe @nogc long mg_date_time_tz_offset_minutes(const mg_date_time *date_time) pure nothrow;
1061 
1062   /// Creates a copy of the given date and time.
1063   ///
1064   /// Return: A pointer to the copy or NULL if an error occured.
1065   @safe @nogc mg_date_time *mg_date_time_copy(const mg_date_time *date_time) pure nothrow;
1066 
1067   /// Destroys the given date and time.
1068   @safe @nogc void mg_date_time_destroy(mg_date_time *date_time) pure nothrow;
1069 
1070   /// Returns seconds since Unix epoch.
1071   @safe @nogc long mg_date_time_zone_id_seconds(const mg_date_time_zone_id *date_time_zone_id) pure nothrow;
1072 
1073   /// Returns nanoseconds since midnight.
1074   @safe @nogc long mg_date_time_zone_id_nanoseconds(const mg_date_time_zone_id *date_time_zone_id) pure nothrow;
1075 
1076   /// Returns time zone represented by the identifier.
1077   @safe @nogc long mg_date_time_zone_id_tz_id(const mg_date_time_zone_id *date_time_zone_id) pure nothrow;
1078 
1079   /// Creates a copy of the given date and time.
1080   ///
1081   /// Return: A pointer to the copy or NULL if an error occured.
1082   @safe @nogc mg_date_time_zone_id *mg_date_time_zone_id_copy(const mg_date_time_zone_id *date_time_zone_id)
1083                           pure nothrow;
1084 
1085   /// Destroys the given date and time.
1086   @safe @nogc void mg_date_time_zone_id_destroy(mg_date_time_zone_id *date_time_zone_id) pure nothrow;
1087 
1088   /// Creates a `mg_local_date_time` from seconds and nanoseconds.
1089   /// Return: A pointer to `mg_local_date_time` or `null` if an error occurred.
1090   @safe @nogc mg_local_date_time *mg_local_date_time_make(long seconds, long nanoseconds) pure nothrow;
1091 
1092   /// Returns seconds since Unix epoch.
1093   @safe @nogc long mg_local_date_time_seconds(const mg_local_date_time *local_date_time) pure nothrow;
1094 
1095   /// Returns nanoseconds since midnight.
1096   @safe @nogc long mg_local_date_time_nanoseconds(const mg_local_date_time *local_date_time) pure nothrow;
1097 
1098   /// Creates a copy of the given local date and time.
1099   ///
1100   /// Return: A pointer to the copy or NULL if an error occured.
1101   @safe @nogc mg_local_date_time *mg_local_date_time_copy(const mg_local_date_time *local_date_time) pure nothrow;
1102 
1103   /// Destroy the given local date and time.
1104   @safe @nogc void mg_local_date_time_destroy(mg_local_date_time *local_date_time) pure nothrow;
1105 
1106   /// Creates a `mg_duration` from the given months, days, seconds and nanoseconds.
1107   /// Return: A pointer to a newly allocated `mg_duration` or `null` if an error occurred.
1108   @safe @nogc mg_duration *mg_duration_make(long months, long days,
1109                                               long seconds,
1110                                               long nanoseconds) pure nothrow;
1111 
1112   /// Returns the months part of the temporal amount.
1113   @safe @nogc long mg_duration_months(const mg_duration *duration) pure nothrow;
1114 
1115   /// Returns the days part of the temporal amount.
1116   @safe @nogc long mg_duration_days(const mg_duration *duration) pure nothrow;
1117 
1118   /// Returns the seconds part of the temporal amount.
1119   @safe @nogc long mg_duration_seconds(const mg_duration *duration) pure nothrow;
1120 
1121   /// Returns the nanoseconds part of the temporal amount.
1122   @safe @nogc long mg_duration_nanoseconds(const mg_duration *duration) pure nothrow;
1123 
1124   /// Creates a copy of the given duration.
1125   ///
1126   /// Return: A pointer to the copy or NULL if an error occured.
1127   @safe @nogc mg_duration *mg_duration_copy(const mg_duration *duration) pure nothrow;
1128 
1129   /// Destroy the given duration.
1130   @safe @nogc void mg_duration_destroy(mg_duration *duration) pure nothrow;
1131 
1132   /// Returns SRID of the 2D point.
1133   @safe @nogc long mg_point_2d_srid(const mg_point_2d *point_2d) pure nothrow;
1134 
1135   /// Returns the x coordinate of the 2D point.
1136   @safe @nogc double mg_point_2d_x(const mg_point_2d *point_2d) pure nothrow;
1137 
1138   /// Returns the y coordinate of the 2D point.
1139   @safe @nogc double mg_point_2d_y(const mg_point_2d *point_2d) pure nothrow;
1140 
1141   /// Creates a copy of the given 2D point.
1142   ///
1143   /// Return: A pointer to the copy or NULL if an error occured.
1144   @safe @nogc mg_point_2d *mg_point_2d_copy(const mg_point_2d *point_2d) pure nothrow;
1145 
1146   /// Destroys the given 2D point.
1147   @safe @nogc void mg_point_2d_destroy(mg_point_2d *point_2d) pure nothrow;
1148 
1149   /// Returns SRID of the 3D point.
1150   @safe @nogc long mg_point_3d_srid(const mg_point_3d *point_3d) pure nothrow;
1151 
1152   /// Returns the x coordinate of the 3D point.
1153   @safe @nogc double mg_point_3d_x(const mg_point_3d *point_3d) pure nothrow;
1154 
1155   /// Returns the y coordinate of the 3D point.
1156   @safe @nogc double mg_point_3d_y(const mg_point_3d *point_3d) pure nothrow;
1157 
1158   /// Returns the z coordinate of the 3D point.
1159   @safe @nogc double mg_point_3d_z(const mg_point_3d *point_3d) pure nothrow;
1160 
1161   /// Creates a copy of the given 3D point.
1162   ///
1163   /// Return: A pointer to the copy or NULL if an error occured.
1164   @safe @nogc mg_point_3d *mg_point_3d_copy(const mg_point_3d *point_3d) pure nothrow;
1165 
1166   /// Destroys the given 3D point.
1167   @safe @nogc void mg_point_3d_destroy(mg_point_3d *point_3d) pure nothrow;
1168 
1169   /// Return codes for `mg_session_status`.
1170   enum mg_session_code {
1171     /// Marks a `mg_session` ready to execute a new query using `mg_session_run`.
1172     MG_SESSION_READY = 0,
1173     /// Marks a `mg_session` which is currently executing a query. Results can be
1174     /// pulled using `mg_session_pull`.
1175     MG_SESSION_EXECUTING = 1,
1176     /// Marks a bad `mg_session` which cannot be used to execute queries and can
1177     /// only be destroyed.
1178     MG_SESSION_BAD = 2,
1179     /// Marks a `mg_session` which is currently fetching result of a query.
1180     /// Results can be fetched using `mg_session_fetch`.
1181     MG_SESSION_FETCHING = 3
1182   }
1183 
1184   /// Return codes used by mgclient functions.
1185   enum mg_error {
1186     /// Success code.
1187     MG_SUCCESS = 0,
1188     /// Failed to send data to server.
1189     MG_ERROR_SEND_FAILED = -1,
1190     /// Failed to receive data from server.
1191     MG_ERROR_RECV_FAILED = -2,
1192     /// Out of memory.
1193     MG_ERROR_OOM = -3,
1194     /// Trying to insert more values in a full container.
1195     MG_ERROR_CONTAINER_FULL = -4,
1196     /// Invalid value type was given as a function argument.
1197     MG_ERROR_INVALID_VALUE = -5,
1198     /// Failed to decode data returned from server.
1199     MG_ERROR_DECODING_FAILED = -6,
1200     /// Trying to insert a duplicate key in map.
1201     MG_ERROR_DUPLICATE_KEY = -7,
1202     /// An error occurred while trying to connect to server.
1203     MG_ERROR_NETWORK_FAILURE = -8,
1204     /// Invalid parameter supplied to `mg_connect`.
1205     MG_ERROR_BAD_PARAMETER = -9,
1206     /// Server violated the Bolt protocol by sending an invalid message type or
1207     /// invalid value.
1208     MG_ERROR_PROTOCOL_VIOLATION = -10,
1209     /// Server sent a FAILURE message containing ClientError code.
1210     MG_ERROR_CLIENT_ERROR = -11,
1211     /// Server sent a FAILURE message containing TransientError code.
1212     MG_ERROR_TRANSIENT_ERROR = -12,
1213     /// Server sent a FAILURE message containing DatabaseError code.
1214     MG_ERROR_DATABASE_ERROR = -13,
1215     /// Got an unknown error message from server.
1216     MG_ERROR_UNKNOWN_ERROR = -14,
1217     /// Invalid usage of the library.
1218     MG_ERROR_BAD_CALL = -15,
1219     /// Maximum container size allowed by Bolt exceeded.
1220     MG_ERROR_SIZE_EXCEEDED = -16,
1221     /// An error occurred during SSL connection negotiation.
1222     MG_ERROR_SSL_ERROR = -17,
1223     /// User provided trust callback returned a non-zeron value after SSL connection
1224     /// negotiation.
1225     MG_ERROR_TRUST_CALLBACK = -18,
1226     /// Unable to initialize the socket (both create and connect).
1227     MG_ERROR_SOCKET = -100,
1228     /// Function unimplemented.
1229     MG_ERROR_UNIMPLEMENTED = -1000
1230   }
1231 
1232   /// Determines whether a secure SSL TCP/IP connection will be negotiated with
1233   /// the server.
1234   enum mg_sslmode {
1235     /// Only try a non-SSL connection.
1236     MG_SSLMODE_DISABLE,
1237     /// Only try a SSL connection.
1238     MG_SSLMODE_REQUIRE,
1239   }
1240 
1241   /// An object encapsulating a Bolt session.
1242   struct mg_session;
1243 
1244   /// An object containing parameters for `mg_connect`.
1245   ///
1246   /// Currently recognized parameters are:
1247   ///  - host
1248   ///
1249   ///      DNS resolvable name of host to connect to. Exactly one of host and
1250   ///      address parameters must be specified.
1251   ///
1252   ///  - address
1253   ///
1254   ///      Numeric IP address of host to connect to. This should be in the
1255   ///      standard IPv4 address format. You can also use IPv6 if your machine
1256   ///      supports it. Exactly one of host and address parameters must be
1257   ///      specified.
1258   ///
1259   ///  - port
1260   ///
1261   ///      Port number to connect to at the server host.
1262   ///
1263   ///  - username
1264   ///
1265   ///      Username to connect as.
1266   ///
1267   ///  - password
1268   ///
1269   ///      Password to be used if the server demands password authentication.
1270   ///
1271   ///  - user_agent
1272   ///
1273   ///      Alternate name and version of the client to send to server. Default is
1274   ///      "MemgraphBolt/0.1".
1275   ///
1276   ///  - sslmode
1277   ///
1278   ///      This option determines whether a secure connection will be negotiated
1279   ///      with the server. There are 2 possible values:
1280   ///
1281   ///      - `MG_SSLMODE_DISABLE`
1282   ///
1283   ///        Only try a non-SSL connection (default).
1284   ///
1285   ///      - `MG_SSLMODE_REQUIRE`
1286   ///
1287   ///        Only try an SSL connection.
1288   ///
1289   ///  - sslcert
1290   ///
1291   ///      This parameter specifies the file name of the client SSL certificate.
1292   ///      It is ignored in case an SSL connection is not made.
1293   ///
1294   ///  - sslkey
1295   ///
1296   ///     This parameter specifies the location of the secret key used for the
1297   ///     client certificate. This parameter is ignored in case an SSL connection
1298   ///     is not made.
1299   ///
1300   ///  - trust_callback
1301   ///
1302   ///     A pointer to a function of prototype:
1303   ///        int trust_callback(const char *hostname, const char *ip_address,
1304   ///                           const char *key_type, const char *fingerprint,
1305   ///                           void *trust_data);
1306   ///
1307   ///     After performing the SSL handshake, `mg_connect` will call this
1308   ///     function providing the hostname, IP address, public key type and
1309   ///     fingerprint and user provided data. If the function returns a non-zero
1310   ///     value, SSL connection will be immediately terminated. This can be used
1311   ///     to implement TOFU (trust on first use) mechanism.
1312   ///     It might happen that hostname can not be determined, in that case the
1313   ///     trust callback will be called with hostname="undefined".
1314   ///
1315   ///  - trust_data
1316   ///
1317   ///    Additional data that will be provided to trust_callback function.
1318   struct mg_session_params;
1319 
1320   /// Prototype of the callback function for verifying an SSL connection by user.
1321   alias mg_trust_callback_type = int function(const char *, const char *, const char *, const char *, void *);
1322 
1323   /// Creates a new `mg_session_params` object.
1324   @safe @nogc mg_session_params *mg_session_params_make() pure nothrow;
1325 
1326   /// Destroys a `mg_session_params` object.
1327   @safe @nogc void mg_session_params_destroy(mg_session_params *) pure nothrow;
1328 
1329   /// Getters and setters for `mg_session_params` values.
1330   @safe @nogc void mg_session_params_set_address(mg_session_params *, const char *address) pure nothrow;
1331   @safe @nogc void mg_session_params_set_host(mg_session_params *, const char *host) pure nothrow;
1332   @safe @nogc void mg_session_params_set_port(mg_session_params *, ushort port) pure nothrow;
1333   @safe @nogc void mg_session_params_set_username(mg_session_params *, const char *username) pure nothrow;
1334   @safe @nogc void mg_session_params_set_password(mg_session_params *, const char *password) pure nothrow;
1335   @safe @nogc void mg_session_params_set_user_agent(mg_session_params *, const char *user_agent) pure nothrow;
1336   @safe @nogc void mg_session_params_set_sslmode(mg_session_params *, mg_sslmode sslmode) pure nothrow;
1337   @safe @nogc void mg_session_params_set_sslcert(mg_session_params *, const char *sslcert) pure nothrow;
1338   @safe @nogc void mg_session_params_set_sslkey(mg_session_params *, const char *sslkey) pure nothrow;
1339   @safe @nogc void mg_session_params_set_trust_callback(mg_session_params *,
1340                                     mg_trust_callback_type trust_callback) pure nothrow;
1341   @safe @nogc void mg_session_params_set_trust_data(mg_session_params *, void *trust_data) pure nothrow;
1342   @safe @nogc const (char) *mg_session_params_get_address(const mg_session_params *) pure nothrow;
1343   @safe @nogc const (char) *mg_session_params_get_host(const mg_session_params *) pure nothrow;
1344   @safe @nogc ushort mg_session_params_get_port(const mg_session_params *) pure nothrow;
1345   @safe @nogc const (char) *mg_session_params_get_username(const mg_session_params *) pure nothrow;
1346   @safe @nogc const (char) *mg_session_params_get_password(const mg_session_params *) pure nothrow;
1347   @safe @nogc const (char) *mg_session_params_get_user_agent(const mg_session_params *) pure nothrow;
1348   @safe @nogc mg_sslmode mg_session_params_get_sslmode(const mg_session_params *) pure nothrow;
1349   @safe @nogc const (char) *mg_session_params_get_sslcert(const mg_session_params *) pure nothrow;
1350   @safe @nogc const (char) *mg_session_params_get_sslkey(const mg_session_params *) pure nothrow;
1351   @safe @nogc mg_trust_callback_type mg_session_params_get_trust_callback(const mg_session_params *params) pure nothrow;
1352   @safe @nogc void *mg_session_params_get_trust_data(const mg_session_params *) pure nothrow;
1353 
1354   /// Makes a new connection to the database server.
1355   ///
1356   /// This function opens a new database connection using the parameters specified
1357   /// in provided `params` argument.
1358   ///
1359   /// Params:  params = New Bolt connection parameters. See documentation for
1360   ///                     `mg_session_params`.
1361   ///         session = A pointer to a newly created `mg_session` is written
1362   ///                     here, unless there wasn't enough memory to allocate a
1363   ///                     `mg_session` object. In that case, it is set to NULL.
1364   ///
1365   /// Return: Returns 0 if connected successfuly, otherwise returns a non-zero
1366   ///         error code. A more detailed error message can be obtained by using
1367   ///         `mg_session_error` on `session`, unless it is set to NULL.
1368   @safe @nogc int mg_connect(const mg_session_params *params, mg_session **session) pure nothrow;
1369 
1370   /// Returns the status of `mg_session`.
1371   ///
1372   /// Return: One of the session codes in `mg_session_code`.
1373   @safe @nogc mg_session_code mg_session_status(const mg_session *session) pure nothrow;
1374 
1375   /// Obtains the error message stored in `mg_session` (if any).
1376   @safe @nogc const (char) *mg_session_error(mg_session *session) pure nothrow;
1377 
1378   /// Destroys a `mg_session` and releases all of its resources.
1379   @safe @nogc void mg_session_destroy(mg_session *session) pure nothrow;
1380 
1381   /// An object encapsulating a single result row or query execution summary. Its
1382   /// lifetime is limited by lifetime of parent `mg_session`. Also, invoking
1383   /// `mg_session_pull` ends the lifetime of previously returned `mg_result`.
1384   struct mg_result;
1385 
1386   /// Submits a query to the server for execution.
1387   ///
1388   /// All records from the previous query must be pulled before executing the
1389   /// next query.
1390   ///
1391   /// Params: session =             A `mg_session` to be used for query execution.
1392   ///         query =               Query string.
1393   ///         params =              A `mg_map` containing query parameters. NULL
1394   ///                              can be supplied instead of an empty parameter
1395   ///                              map.
1396   ///         columns =            Names of the columns output by the query
1397   ///                              execution will be stored in here. This is the
1398   ///                              same as the value
1399   ///                              obtained by `mg_result_columns` on a pulled
1400   ///                              `mg_result`. NULL can be supplied if we're
1401   ///                              not interested in the columns names.
1402   ///      extra_run_information = A `mg_map` containing extra information for
1403   ///                              running the statement.
1404   ///                              It can contain the following information:
1405   ///                               - bookmarks - list of strings containing some
1406   ///                               kind of bookmark identification
1407   ///                               - tx_timeout - integer that specifies a
1408   ///                               transaction timeout in ms.
1409   ///                               - tx_metadata - dictionary taht can contain
1410   ///                               some metadata information, mainly used for
1411   ///                               logging.
1412   ///                               - mode - specifies what kind of server is the
1413   ///                               run targeting. For write access use "w" and
1414   ///                               for read access use "r". Defaults to write
1415   ///                               access.
1416   ///                               - db - specifies the database name for
1417   ///                               multi-database to select where the transaction
1418   ///                               takes place. If no `db` is sent or empty
1419   ///                               string it implies that it is the default
1420   ///                               database.
1421   ///            qid =              QID for the statement will be stored in here
1422   ///                               if an Explicit transaction was started.
1423   /// Return: Returns 0 if query was submitted for execution successfuly.
1424   ///         Otherwise, a non-zero error code is returned.
1425   @safe @nogc mg_error mg_session_run(mg_session *session, const char *query, const mg_map *params,
1426                             const mg_map *extra_run_information, const mg_list **columns, long *qid) pure nothrow;
1427 
1428   /// Starts an Explicit transaction on the server.
1429   ///
1430   /// Every run will be part of that transaction until its explicitly ended.
1431   ///
1432   /// Params: session =              A `mg_session` on which the transaction should be started.
1433   ///       extra_run_information  = A `mg_map` containing extra information that will be used
1434   ///                                 for every statement that is ran as part of the transaction.
1435   ///                              It can contain the following information:
1436   ///                               - bookmarks - list of strings containing some
1437   ///                               kind of bookmark identification
1438   ///                               - tx_timeout - integer that specifies a
1439   ///                               transaction timeout in ms.
1440   ///                               - tx_metadata - dictionary taht can contain
1441   ///                               some metadata information, mainly used for
1442   ///                               logging.
1443   ///                               - mode - specifies what kind of server is the
1444   ///                               run targeting. For write access use "w" and
1445   ///                               for read access use "r". Defaults to write
1446   ///                               access.
1447   ///                               - db - specifies the database name for
1448   ///                               multi-database to select where the transaction
1449   ///                               takes place. If no `db` is sent or empty
1450   ///                               string it implies that it is the default
1451   ///                               database.
1452   /// Return: Returns 0 if the transaction was started successfully.
1453   ///         Otherwise, a non-zero error code is returned.
1454   @safe @nogc mg_error mg_session_begin_transaction(mg_session *session,
1455                                             const mg_map *extra_run_information) pure nothrow;
1456 
1457   /// Commits current Explicit transaction.
1458   ///
1459   /// Params: session = A `mg_session` on which the transaction should be committed.
1460   ///         result =  Contains the information about the committed transaction
1461   ///                   if it was successful.
1462   /// Return: Returns 0 if the transaction was ended successfully.
1463   ///         Otherwise, a non-zero error code is returned.
1464   @safe @nogc mg_error mg_session_commit_transaction(mg_session *session, mg_result **result) pure nothrow;
1465 
1466   /// Rollbacks current Explicit transaction.
1467   ///
1468   /// Params: session = A `mg_session` on which the transaction should be rolled back.
1469   ///         result =  Contains the information about the rolled back transaction
1470   ///                   if it was successful.
1471   /// Return: Returns 0 if the transaction was ended successfully.
1472   ///         Otherwise, a non-zero error code is returned.
1473   @safe @nogc mg_error mg_session_rollback_transaction(mg_session *session, mg_result **result) pure nothrow;
1474 
1475   /// Tries to fetch the next query result from `mg_session`.
1476   ///
1477   /// The owner of the returned result is `mg_session` `session`, and the
1478   /// result is destroyed on next call to `mg_session_fetch`.
1479   ///
1480   /// Return: On success, 0 or 1 is returned. Exit code 1 means that a new result
1481   ///         row was obtained and stored in `result` and its contents may be
1482   ///         accessed using `mg_result_row`. Exit code 0 means that there are
1483   ///         no more result rows and that the query execution summary was stored
1484   ///         in `result`. Its contents may be accessed using `mg_result_summary`.
1485   ///         On failure, a non-zero exit code is returned.
1486   @safe @nogc mg_error mg_session_fetch(mg_session *session, mg_result **result) pure nothrow;
1487 
1488   /// Tries to pull results of a statement.
1489   ///
1490   /// Params: session =       A `mg_session` from which the results should be pulled.
1491   ///      pull_information = A `mg_map` that contains extra information for pulling the results.
1492   ///                         It can contain the following information:
1493   ///                          - n - how many records to fetch. `n=-1` will fetch
1494   ///                          all records.
1495   ///                          - qid - query identification, specifies the result
1496   ///                          from which statement the results should be pulled.
1497   ///                          `qid=-1` denotes the last executed statement. This
1498   ///                          is only for Explicit transactions.
1499   /// Return: Returns 0 if the result was pulled successfuly.
1500   ///         Otherwise, a non-zero error code is returned.
1501   @safe @nogc mg_error mg_session_pull(mg_session *session, const mg_map *pull_information) pure nothrow;
1502 
1503   /// Returns names of columns output by the current query execution.
1504   @safe @nogc const (mg_list) *mg_result_columns(const mg_result *result) pure nothrow;
1505 
1506   /// Returns column values of current result row.
1507   @safe @nogc const (mg_list) *mg_result_row(const mg_result *result) pure nothrow;
1508 
1509   /// Returns query execution summary.
1510   @safe @nogc const (mg_map) *mg_result_summary(const mg_result *result) pure nothrow;
1511 }
1512 
1513 version(unittest) {
1514   // Extern C definitions for allocation of memgraph internal types.
1515   extern (C) {
1516     // Need at least an empty definition for extern struct.
1517     struct mg_allocator {}
1518     extern shared mg_allocator mg_system_allocator;
1519 
1520     @safe @nogc mg_string *mg_string_alloc(uint size, mg_allocator *allocator) pure nothrow;
1521     @safe @nogc mg_list *mg_list_alloc(uint size, mg_allocator *allocator) pure nothrow;
1522     @safe @nogc mg_map *mg_map_alloc(uint size, mg_allocator *allocator) pure nothrow;
1523     @safe @nogc mg_node *mg_node_alloc(uint label_count, mg_allocator *allocator) pure nothrow;
1524     @safe @nogc mg_path *mg_path_alloc(uint node_count, uint relationship_count, uint sequence_length,
1525                                        mg_allocator *allocator) pure nothrow;
1526 
1527     @safe @nogc mg_date *mg_date_alloc(shared mg_allocator *alloc) pure nothrow;
1528     @safe @nogc mg_time *mg_time_alloc(shared mg_allocator *alloc) pure nothrow;
1529     @safe @nogc mg_local_time *mg_local_time_alloc(shared mg_allocator *alloc) pure nothrow;
1530     @safe @nogc mg_date_time *mg_date_time_alloc(shared mg_allocator *alloc) pure nothrow;
1531     @safe @nogc mg_date_time_zone_id *mg_date_time_zone_id_alloc(shared mg_allocator *alloc) pure nothrow;
1532     @safe @nogc mg_local_date_time *mg_local_date_time_alloc(shared mg_allocator *alloc) pure nothrow;
1533     @safe @nogc mg_duration *mg_duration_alloc(shared mg_allocator *alloc) pure nothrow;
1534 
1535     @safe @nogc mg_point_2d *mg_point_2d_alloc(shared mg_allocator *allocator) pure nothrow;
1536     @safe @nogc mg_point_3d *mg_point_3d_alloc(shared mg_allocator *allocator) pure nothrow;
1537   }
1538 }
1539 
1540 unittest {
1541   import testutils : startContainer;
1542   startContainer();
1543 }
1544 
1545 /// Test connection to memgraph on 127.0.0.1, port 7688.
1546 unittest {
1547   import std.string : toStringz, fromStringz;
1548   import std.conv : to;
1549 
1550   assert(mg_init() == 0);
1551 
1552   auto params = mg_session_params_make();
1553   assert(params != null);
1554 
1555   mg_session_params_set_host(params, toStringz("127.0.0.1"));
1556   mg_session_params_set_port(params, to!ushort(7688));
1557   mg_session_params_set_sslmode(params, mg_sslmode.MG_SSLMODE_DISABLE);
1558 
1559   mg_session *session = null;
1560   const int status = mg_connect(params, &session);
1561   mg_session_params_destroy(params);
1562 
1563   assert(status == 0, fromStringz(mg_session_error(session)));
1564 
1565   mg_session_destroy(session);
1566   mg_finalize();
1567 }