Turso简介
SQLite的下一步发展:一款专为Rust语言设计的、具有高性能且与SQLite兼容的数据库。
一、Turso特点
- 兼容SQLite:其接口与rusqlite类似,拥有熟悉的API;不同之处在于它使用的是异步Rust语言。
- Sqlite同时只能一个写操作,Turso可以并发写操作。
- 高性能:采用Rust语言开发,以实现极致的速度与效率
- 支持异步/等待机制:具备tokio支持的原生异步操作功能
- 处理中:无需网络开销,可直接在应用程序中运行。
- 跨平台:支持Linux、macOS和Windows系统
- 事务支持:具备回滚功能的全ACID事务支持
- 预处理语句:通过参数绑定实现高效的查询执行
- 云同步:通过
Builder::new_remote()与Turso Cloud实现同步(可选的sync功能)
二、安装
将其添加到你的Cargo.toml中:
toml
[dependencies]
turso = "0.6.1"
tokio = { version = "1.52", features = ["full"] }
三、内存数据库案例
rust
use turso::Builder;
#[tokio::main]
async fn main() -> turso::Result<()> {
// 创建一个内存数据库数据库连接
let db = Builder::new_local(":memory:").build().await?;
let conn = db.connect()?; // 连接数据库
// 创建一个表
conn.execute(
"CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT)",
(),
)
.await?;
// 插入数据到表
conn.execute(
"INSERT INTO users (name, email) VALUES (?1, ?2)",
["Alice", "alice@example.com"],
)
.await?;
conn.execute(
"INSERT INTO users (name, email) VALUES (?1, ?2)",
["Bob", "bob@example.com"],
)
.await?;
// 查询表中的数据
let mut rows = conn.query("SELECT * FROM users", ()).await?;
while let Some(row) = rows.next().await? {
let id = row.get_value(0)?;
let name = row.get_value(1)?;
let email = row.get_value(2)?;
println!(
"用户id: {},用户名:{},邮箱:{}",
id.as_integer().unwrap_or(&0),
name.as_text().unwrap_or(&"".to_string()),
email.as_text().unwrap_or(&"".to_string())
);
}
Ok(())
}
四、文件的数据库案例
rust
use turso::{Builder, params};
#[tokio::main]
async fn main() -> turso::Result<()> {
// new_local 按照路径构建一个基本的数据库参数对象;build 根据数据库参数对象创建数据库并打开,connect 连接数据库
let db = Builder::new_local("my-database.db").build().await?;
let conn = db.connect()?;
// 创建一个表
conn.execute(
r#"CREATE TABLE IF NOT EXISTS posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
content TEXT,
f_test REAL, --浮点数据
b_test BLOB, --二进制数据
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
)"#,
(),
)
.await?;
let f_test = 16.55555555225;
let b_test = "hello world".as_bytes().to_vec();
// 插入一条数据, 并返回影响的行数
let rows_affected = conn
.execute(
"INSERT INTO posts (title, content, f_test, b_test) VALUES (?1, ?2, ?3, ?4)",
params!["我的第一个帖子", "这是我的第一个帖子", f_test, b_test],
)
.await?;
println!("插入 {} 行数据", rows_affected);
println!("-----------------");
// 查询所有数据, 并返回查询结果
let mut rows = conn.query("SELECT * FROM posts", ()).await?;
// 遍历查询结果, 并打印每个字段的值
while let Some(row) = rows.next().await? {
println!("帖子id: {}", row.get_value(0)?.as_integer().unwrap_or(&0));
println!(
"标题: {}",
row.get_value(1)?.as_text().unwrap_or(&"".to_string())
);
println!(
"内容: {}",
row.get_value(2)?.as_text().unwrap_or(&"".to_string())
);
println!("浮点数据: {}", row.get_value(3)?.as_real().unwrap_or(&0.0));
println!(
"二进制数据: {:?}",
row.get_value(4)?.as_blob().unwrap_or(&Vec::new())
);
println!(
"发帖时间: {:?}",
row.get_value(5)?.as_text().unwrap_or(&"".to_string())
);
println!("-----------------");
}
Ok(())
}
五、创建新数据库
rust
let db = Builder::new_local(":memory:").build().await?; // 内存数据库
let db = Builder::new_local("data.db").build().await?; // 本地数据库
六、执行SQL语句
rust
// 直接执行SQL
let rows_affected = conn.execute("INSERT INTO users (name) VALUES (?1)", ["Alice"]).await?;
// 多行查询
let mut rows = conn.query("SELECT * FROM users WHERE age > ?1", [18]).await?;
// sql预编译,然后执行预编译查询
let mut stmt = conn.prepare("SELECT * FROM users WHERE id = ?1").await?;
// 执行预编译查询
let mut rows = stmt.query([42]).await?;
// 执行预编译语句
let rows_affected = stmt.execute(["Alice"]).await?;
七、插入的数据
["aaa","bbb"],只能是同一种数据类型params!["aaa", 22, 2.2],可以不同的数据类型
八、数据集相关操作rows
rows.next() -> Result<Option<Row>>:获取下一行数据rows.column_count() -> usize:获取字段数量rows.column_name(idx: usize) -> Result<String>:根据索引获取字段名rows.column_names() -> Vec<String>:获取所有字段名rows.column_index(name: &str) -> Result<usize>:根据字段名获取结果的索引rows.columns() -> Vec<Column>:获取查询结果的:字段名+类型,Column{name: String, decl_type: Option<String>}
九、数据行相关操作row
row.get_value(index: usize) -> Result<Value>:根据索引获取值let title = row.get_value(1)?.as_text().unwrap_or(&"".to_string()):获取字段值转换为相应类型,空值设置为空字符串
row.get<T>(idx: usize) -> Result<T>:根据索引获取查询结果的字段值let title = row.get::<String>(1)?:根据类型获取字段值
row.column_count() -> usize:获取字段数量
十、值相关操作Value
1、Value的定义
rust
pub enum Value {
Null, // 空值
Integer(i64), // 整型
Real(f64), // 浮点型
Text(String), // 字符串
Blob(Vec<u8>), // 二进制
}
2、Value值的判断
Value.is_null() -> bool,值是否为空Value.is_integer(&self) -> bool,值是否为i64Value.is_real(&self) -> bool,值是否为f64Value.is_text(&self) -> bool,值是否为StringValue.is_blob(&self) -> bool,值是否为Vec<u8>
3、Value值的转换
Value.as_integer() -> Option<&i64>Value.as_real() -> Option<&f64>Value.as_text() -> Option<&String>Value.as_blob() -> Option<&Vec<u8>>
4、空值处理
-
.unwrap_or(&0),整型 -
.unwrap_or(&0.0),浮点型 -
.unwrap_or(&"".to_string()),字符串 -
.unwrap_or(&Vec::new()),二进制