sqlite_bindings_lunatic/
lib.rs

1//! Interface to [SQLite][1].
2//!
3//! ## Example
4//!
5//! Open a connection, create a table, and insert a few rows:
6//!
7//! ```
8//! let connection = sqlite_bindings_lunatic::open(":memory:").unwrap();
9//!
10//! let query = "
11//!     CREATE TABLE users (name TEXT, age INTEGER);
12//!     INSERT INTO users VALUES ('Alice', 42);
13//!     INSERT INTO users VALUES ('Bob', 69);
14//! ";
15//! connection.execute(query).unwrap();
16//! ```
17//!
18//! Select some rows and process them one by one as plain text, which is generally
19//! not efficient:
20//!
21//! ```
22//! # let connection = sqlite_bindings_lunatic::open(":memory:").unwrap();
23//! # let query = "
24//! #     CREATE TABLE users (name TEXT, age INTEGER);
25//! #     INSERT INTO users VALUES ('Alice', 42);
26//! #     INSERT INTO users VALUES ('Bob', 69);
27//! # ";
28//! # connection.execute(query).unwrap();
29//! let query = "SELECT * FROM users WHERE age > 50";
30//!
31//! connection
32//!     .iterate(query, |pairs| {
33//!         for &(name, value) in pairs.iter() {
34//!             println!("{} = {}", name, value.unwrap());
35//!         }
36//!         true
37//!     })
38//!     .unwrap();
39//! ```
40//!
41//! Run the same query but using a prepared statement, which is much more efficient
42//! than the previous technique:
43//!
44//! ```
45//! use sqlite_bindings_lunatic::State;
46//! # let connection = sqlite_bindings_lunatic::open(":memory:").unwrap();
47//! # let query = "
48//! #     CREATE TABLE users (name TEXT, age INTEGER);
49//! #     INSERT INTO users VALUES ('Alice', 42);
50//! #     INSERT INTO users VALUES ('Bob', 69);
51//! # ";
52//! # connection.execute(query).unwrap();
53//!
54//! let query = "SELECT * FROM users WHERE age > ?";
55//! let mut statement = connection.prepare(query).unwrap();
56//! statement.bind((1, 50)).unwrap();
57//!
58//! while let Ok(State::Row) = statement.next() {
59//!     println!("name = {}", statement.read::<String, _>("name").unwrap());
60//!     println!("age = {}", statement.read::<i64, _>("age").unwrap());
61//! }
62//! ```
63//!
64//! Run the same query but using a cursor, which is iterable:
65//!
66//! ```
67//! # let connection = sqlite_bindings_lunatic::open(":memory:").unwrap();
68//! # let query = "
69//! #     CREATE TABLE users (name TEXT, age INTEGER);
70//! #     INSERT INTO users VALUES ('Alice', 42);
71//! #     INSERT INTO users VALUES ('Bob', 69);
72//! # ";
73//! # connection.execute(query).unwrap();
74//!
75//! let query = "SELECT * FROM users WHERE age > ?";
76//!
77//! for row in connection
78//!     .prepare(query)
79//!     .unwrap()
80//!     .into_iter()
81//!     .bind((1, 50))
82//!     .unwrap()
83//!     .map(|row| row.unwrap())
84//! {
85//!     println!("name = {}", row.read::<&str, _>("name"));
86//!     println!("age = {}", row.read::<i64, _>("age"));
87//! }
88//! ```
89//!
90//! [1]: https://www.sqlite.org
91
92extern crate libc;
93extern crate sqlite3_sys as ffi;
94
95macro_rules! c_str_to_str(
96    ($string:expr) => (::std::str::from_utf8(::std::ffi::CStr::from_ptr($string).to_bytes()));
97);
98
99macro_rules! c_str_to_string(
100    ($string:expr) => (
101        String::from_utf8_lossy(::std::ffi::CStr::from_ptr($string as *const _).to_bytes())
102               .into_owned()
103    );
104);
105
106macro_rules! path_to_cstr(
107    ($path:expr) => (
108        match $path.to_str() {
109            Some(path) => {
110                match ::std::ffi::CString::new(path) {
111                    Ok(string) => string,
112                    _ => raise!("failed to process a path"),
113                }
114            }
115            _ => raise!("failed to process a path"),
116        }
117    );
118);
119
120macro_rules! str_to_cstr(
121    ($string:expr) => (
122        match ::std::ffi::CString::new($string) {
123            Ok(string) => string,
124            _ => raise!("failed to process a string"),
125        }
126    );
127);
128
129#[macro_use]
130mod error;
131mod value;
132
133mod connection;
134mod cursor;
135mod statement;
136
137pub use error::{Error, Result};
138pub use value::{Type, Value};
139
140pub use connection::{Connection, ConnectionWithFullMutex, OpenFlags};
141pub use cursor::{Cursor, CursorWithOwnership, Row, RowIndex};
142pub use statement::{
143    Bindable, BindableWithIndex, ColumnIndex, ParameterIndex, ReadableWithIndex, State, Statement,
144};
145
146/// Open a read-write connection to a new or existing database.
147#[inline]
148pub fn open<T: AsRef<std::path::Path>>(path: T) -> Result<Connection> {
149    Connection::open(path)
150}
151
152/// Return the version number of SQLite.
153///
154/// For instance, the version `3.8.11.1` corresponds to the integer `3008011`.
155#[inline]
156pub fn version() -> usize {
157    unsafe { ffi::sqlite3_libversion_number() as usize }
158}