tarantool_module/
lib.rs

1//! Tarantool C API bindings for Rust.
2//! This library contains the following Tarantool API's:
3//!
4//! - Box: spaces, indexes, sequences
5//! - Fibers: fiber attributes, conditional variables
6//! - CoIO
7//! - Transactions
8//! - Latches
9//! - Tuple utils
10//! - Logging (see https://!docs.rs/log/0.4.11/log/)
11//! - Error handling
12//!
13//! > **Caution!** The library is currently under development.
14//! > API may be unstable until version 1.0 will be released.
15//!
16//! ### Prerequisites
17//!
18//! - rustc 1.45.0 or newer (other versions were not tested)
19//! - tarantool 2.2
20//!
21//! ### Stored procedures
22//!
23//! Tarantool can call Rust code via a plugin, from Lua using FFI, or as a stored procedure.
24//! This tutorial only is about the third
25//! option, Rust stored procedures. In fact Rust routines are always "C
26//! functions" to Tarantool but the phrase "stored procedure" is commonly used
27//! for historical reasons.
28//!
29//! This tutorial contains the following simple steps:
30//! 1. `examples/easy` - prints "hello world";
31//! 1. `examples/harder` - decodes a passed parameter value;
32//! 1. `examples/hardest` - uses this library to do a DBMS insert;
33//! 1. `examples/read` - uses this library to do a DBMS select;
34//! 1. `examples/write` - uses this library to do a DBMS replace.
35//!
36//! By following the instructions and seeing that the results users should
37//! become confident in writing their own stored procedures.
38//!
39//! #### Example
40//!
41//! Check that these items exist on the computer:
42//! - Tarantool 2.2
43//! - A rustc compiler + cargo builder. Any modern version should work
44//!
45//! Create cargo project:
46//! ```shell script
47//! $ cargo init --lib
48//! ```
49//!
50//! Add the following lines to `Cargo.toml`:
51//! ```toml
52//! [package]
53//! name = "easy"
54//! version = "0.1.0"
55//! edition = "2018"
56//! # author, license, etc
57//!
58//! [dependencies]
59//! tarantool-module = "0.2.0" # (1)
60//! serde = "1.0" # (2)
61//!
62//! [lib]
63//! crate-type = ["cdylib"] # (3)
64//! ```
65//!
66//! 1. add to dependencies `tarantool-module` library;
67//! 1. add to dependencies [Serde](https://!github.com/serde-rs/serde), this is optional and required if you want to use rust
68//! structures as a tuple values (see [this example](#harder));
69//! 1. you need to compile dynamic library.
70//!
71//! Requests will be done using Tarantool as a client. Start Tarantool, and enter these requests:
72//! ```lua
73//! box.cfg{listen=3306}
74//! box.schema.space.create('capi_test')
75//! box.space.capi_test:create_index('primary')
76//! net_box = require('net.box')
77//! capi_connection = net_box:new(3306)
78//! ```
79//!
80//! In plain language: create a space named `capi_test`, and make a connection to self named `capi_connection`.
81//!
82//! Leave the client running. It will be used to enter more requests later.
83//!
84//! Edit `lib.rs` file and add the following lines:
85//! ```rust
86//! use std::os::raw::c_int;
87//! use tarantool_module::tuple::{FunctionArgs, FunctionCtx};
88//!
89//! #[no_mangle]
90//! pub extern "C" fn easy(_: FunctionCtx, _: FunctionArgs) -> c_int {
91//!     println!("hello world");
92//!     0
93//! }
94//!
95//! #[no_mangle]
96//! pub extern "C" fn easy2(_: FunctionCtx, _: FunctionArgs) -> c_int {
97//!     println!("hello world -- easy2");
98//!     0
99//! }
100//! ```
101//!
102//! Compile the program:
103//! ```shell script
104//! $ cargo build
105//! ```
106//!
107//! Start another shell. Change directory (`cd`) so that it is the same as the directory that the client is running in.
108//! Copy the compiled library (it is located in subfolder `target/debug` at you
109//! project sources folder) to the current folder and rename it to `easy.so`
110//!
111//! Now go back to the client and execute these requests:
112//! ```lua
113//! box.schema.func.create('easy', {language = 'C'})
114//! box.schema.user.grant('guest', 'execute', 'function', 'easy')
115//! capi_connection:call('easy')
116//! ```
117//!
118//! If these requests appear unfamiliar, read the descriptions of
119//! [box.schema.func.create()](https://!www.tarantool.io/en/doc/2.2/reference/reference_lua/box_schema/#box-schema-func-create),
120//! [box.schema.user.grant()](https://!www.tarantool.io/en/doc/2.2/reference/reference_lua/box_schema/#box-schema-user-grant)
121//! and [conn:call()](https://!www.tarantool.io/en/doc/2.2/reference/reference_lua/net_box/#net-box-call).
122//!
123//! The function that matters is `capi_connection:call('easy')`.
124//!
125//! Its first job is to find the 'easy' function, which should be easy because by default Tarantool looks on the current directory
126//! for a file named `easy.so`.
127//!
128//! Its second job is to call the 'easy' function. Since the `easy()` function in `lib.rs` begins with `println!("hello world")`,
129//! the words "hello world" will appear on the screen.
130//!
131//! Its third job is to check that the call was successful. Since the `easy()` function in `lib.rs` ends with return 0, there
132//! is no error message to display and the request is over.
133//!
134//! The result should look like this:
135//! ```text
136//! tarantool> capi_connection:call('easy')
137//! hello world
138//! ---
139//! - []
140//! ...
141//! ```
142//!
143//! Now let's call the other function in lib.rs - `easy2()`. This is almost the same as the `easy()` function, but there's a
144//! detail: when the file name is not the same as the function name, then we have to specify _{file-name}_._{function-name}_
145//! ```lua
146//! box.schema.func.create('easy.easy2', {language = 'C'})
147//! box.schema.user.grant('guest', 'execute', 'function', 'easy.easy2')
148//! capi_connection:call('easy.easy2')
149//! ```
150//!
151//! ... and this time the result will be `hello world -- easy2`.
152//!
153//! Conclusion: calling a Rust function is easy.
154#[macro_use]
155extern crate bitflags;
156#[macro_use]
157extern crate derivative;
158#[macro_use]
159extern crate failure;
160#[macro_use]
161extern crate num_derive;
162#[macro_use]
163extern crate serde;
164
165pub mod clock;
166pub mod coio;
167pub mod error;
168pub mod fiber;
169pub mod index;
170pub mod log;
171pub mod sequence;
172pub mod space;
173pub mod transaction;
174pub mod tuple;