sql_peas/lib.rs
1//! sql-peas is yet another [sqlite3](https://www.sqlite.org) synchronous Rust crate.
2//!
3//! ## Example
4//!
5//! Open a connection, create a table, and insert a few rows:
6//!
7//! ```
8//! let connection = sql_peas::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 not efficient:
19//!
20//! ```
21//! # let connection = sql_peas::open(":memory:").unwrap();
22//! # let query = "
23//! # CREATE TABLE users (name TEXT, age INTEGER);
24//! # INSERT INTO users VALUES ('Alice', 42);
25//! # INSERT INTO users VALUES ('Bob', 69);
26//! # ";
27//! # connection.execute(query).unwrap();
28//! let query = "SELECT * FROM users WHERE age > 50";
29//!
30//! connection
31//! .iterate(query, |pairs| {
32//! for &(name, value) in pairs.iter() {
33//! println!("{} = {}", name, value.unwrap());
34//! }
35//! true
36//! })
37//! .unwrap();
38//! ```
39//!
40//! Run the same query but using a prepared statement, which is much more efficient than the
41//! previous technique:
42//!
43//! ```
44//! use sql_peas::State;
45//! # let mut connection = sql_peas::open(":memory:").unwrap();
46//! # let query = "
47//! # CREATE TABLE users (name TEXT, age INTEGER);
48//! # INSERT INTO users VALUES ('Alice', 42);
49//! # INSERT INTO users VALUES ('Bob', 69);
50//! # ";
51//! # connection.execute(query).unwrap();
52//!
53//! let query = "SELECT * FROM users WHERE age > ?";
54//! let handle = connection.prepare(query).unwrap();
55//! let statement = connection.borrow_statement(handle).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 mut connection = sql_peas::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//! let handle = connection.prepare(query).unwrap();
77//!
78//! for row in connection
79//! .borrow_statement(handle)
80//! .unwrap()
81//! .iter()
82//! .bind((1, 50))
83//! .unwrap()
84//! .map(|row| row.unwrap())
85//! {
86//! println!("name = {}", row.read::<&str, _>("name"));
87//! println!("age = {}", row.read::<i64, _>("age"));
88//! }
89//! ```
90//!
91//! [1]: https://www.sqlite.org
92
93pub extern 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 columns;
134mod connection;
135mod cursor;
136mod statement;
137
138pub use error::{Error, Result};
139pub use value::{Type, Value};
140
141pub use columns::{Bindable, BindableWithIndex, ReadableWithIndex};
142pub use connection::{Connection, ConnectionThreadSafe, OpenFlags};
143pub use cursor::{Cursor, /* FIXME CursorWithOwnership, */ Row, RowIndex};
144pub use statement::{ColumnIndex, Handle as StatementHandle, ParameterIndex, State, Statement};
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}