Rust数据库连接库libsql-hrana的使用:支持高性能SQLite操作与异步查询的Hrana协议实现
Rust数据库连接库libsql-hrana的使用:支持高性能SQLite操作与异步查询的Hrana协议实现
安装
在项目目录中运行以下Cargo命令:
cargo add libsql-hrana
或者在Cargo.toml中添加以下行:
libsql-hrana = "0.9.19"
示例代码
以下是使用libsql-hrana进行SQLite操作的完整示例:
use libsql_hrana::client::{Client, Config};
use tokio::runtime::Runtime;
async fn async_query() -> Result<(), Box<dyn std::error::Error>> {
// 创建客户端配置
let config = Config::new("http://localhost:8080") // 替换为你的Hrana服务器地址
.auth_token("your-auth-token"); // 如果需要认证
// 创建客户端
let client = Client::new(config).await?;
// 创建连接
let conn = client.open().await?;
// 执行查询
let stmt = conn.prepare("SELECT * FROM users WHERE id = ?").await?;
let rows = stmt.query([1]).await?;
// 处理结果
while let Some(row) = rows.next().await? {
let id: i64 = row.get(0)?;
let name: String = row.get(1)?;
println!("User: id={}, name={}", id, name);
}
Ok(())
}
fn main() {
// 创建Tokio运行时
let rt = Runtime::new().unwrap();
// 运行异步查询
rt.block_on(async_query()).unwrap();
}
特性说明
- 高性能SQLite操作:通过Hrana协议实现高效的SQLite数据库访问
- 异步支持:完全基于异步I/O设计,适合高并发场景
- 预编译语句:支持参数化查询和预编译语句
- 连接池:内置连接池管理,提高连接复用率
完整示例demo
use libsql_hrana::client::{Client, Config};
use tokio::runtime::Runtime;
async fn demo() -> Result<(), Box<dyn std::error::Error>> {
// 1. 配置客户端
let config = Config::new("http://localhost:8080")
.auth_token("your-secret-token");
// 2. 创建客户端
let client = Client::new(config).await?;
// 3. 获取数据库连接
let conn = client.open().await?;
// 4. 创建表
conn.execute(
"CREATE TABLE IF NOT EXISTS products (
id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
price REAL
)"
).await?;
// 5. 插入数据
let insert_stmt = conn.prepare(
"INSERT INTO products (name, price) VALUES (?, ?)"
).await?;
insert_stmt.execute(["Rust Book", 39.99]).await?;
insert_stmt.execute(["TypeScript Guide", 29.99]).await?;
// 6. 查询数据
let query_stmt = conn.prepare(
"SELECT id, name, price FROM products WHERE price > ?"
).await?;
let rows = query_stmt.query([30.0]).await?;
// 7. 处理结果
while let Some(row) = rows.next().await? {
let id: i64 = row.get(0)?;
let name: String = row.get(1)?;
let price: f64 = row.get(2)?;
println!("Product: id={}, name={}, price={:.2}", id, name, price);
}
Ok(())
}
fn main() {
let rt = Runtime::new().unwrap();
rt.block_on(demo()).unwrap();
}
所有者
- tursodatabase/publish团队
- Pekka Enberg (@penberg)
许可证
MIT License
1 回复
Rust数据库连接库libsql-hrana的使用:支持高性能SQLite操作与异步查询的Hrana协议实现
介绍
libsql-hrana是一个Rust实现的Hrana协议客户端库,用于与SQLite数据库进行高性能交互。Hrana协议是由Turso(原libSQL)团队开发的专有协议,提供了比传统SQLite接口更好的性能和异步支持。
主要特点:
- 支持异步/await语法
- 高性能的SQLite操作
- 兼容标准SQLite语法
- 支持批量操作
- 提供连接池管理
安装方法
在Cargo.toml中添加依赖:
[dependencies]
libsql-hrana = "0.1"
tokio = { version = "1.0", features = ["full"] }
基本使用方法
1. 建立连接
use libsql_hrana::client::{Client, Config};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = Config {
url: "libsql://your-database.turso.io".to_string(),
auth_token: Some("your-auth-token".to_string()),
};
let client = Client::connect(config).await?;
Ok(())
}
2. 执行查询
// 同步查询
let rows = client.execute("SELECT * FROM users WHERE age > ?", [18]).await?;
for row in rows {
let id: i64 = row.get(0)?;
let name: String = row.get(1)?;
println!("id: {}, name: {}", id, name);
}
// 异步流式查询
let mut stmt = client.prepare("SELECT * FROM posts ORDER BY created_at DESC").await?;
let mut rows = stmt.query([]).await?;
while let Some(row) = rows.next().await? {
let title: String = row.get("title")?;
println!("Post title: {}", title);
}
3. 事务处理
let tx = client.transaction().await?;
tx.execute("INSERT INTO logs (message) VALUES (?)", ["Transaction started"]).await?;
tx.execute("UPDATE accounts SET balance = balance - 100 WHERE id = 1", []).await?;
tx.execute("UPDATE accounts SET balance = balance + 100 WHERE id = 2", []).await?;
tx.commit().await?;
高级用法
批量操作
let batch = client.batch();
batch.execute("INSERT INTO users (name, email) VALUES (?, ?)", ["Alice", "alice@example.com"]);
batch.execute("INSERT INTO users (name, email) VALUES (?, ?)", ["Bob", "bob@example.com"]);
let results = batch.commit().await?;
println!("Inserted {} rows", results.len());
连接池
use libsql_hrana::pool::Pool;
let pool = Pool::new(Config {
url: "libsql://your-database.turso.io".to_string(),
auth_token: Some("your-auth-token".to_string()),
}, 5); // 最大5个连接
let conn = pool.get().await?;
let rows = conn.execute("SELECT COUNT(*) FROM users", []).await?;
性能优化技巧
- 使用预编译语句重复查询:
let stmt = client.prepare("SELECT * FROM products WHERE category = ?").await?;
// 多次使用同一个预编译语句
let tech_products = stmt.query(["technology"]).await?;
let food_products = stmt.query(["food"]).await?;
- 批量插入数据时使用事务:
let tx = client.transaction().await?;
for i in 0..1000 {
tx.execute("INSERT INTO metrics (value) VALUES (?)", [i]).await?;
}
tx.commit().await?;
错误处理
match client.execute("SELECT * FROM non_existent_table", []).await {
Ok(rows) => {
// 处理结果
},
Err(libsql_hrana::Error::ApiError(e)) => {
eprintln!("API error: {}", e.message);
},
Err(e) => {
eprintln!("Other error: {}", e);
}
}
注意事项
- Hrana协议需要服务端支持,不能直接连接本地SQLite文件
- 生产环境建议使用连接池管理连接
- 敏感操作务必使用事务保证数据一致性
- 注意处理网络错误和重连逻辑
libsql-hrana为Rust开发者提供了现代化的SQLite操作方式,特别适合云原生环境下的数据库操作需求。
完整示例代码
use libsql_hrana::{
client::{Client, Config},
pool::Pool,
};
use tokio;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
// 1. 创建连接配置
let config = Config {
url: "libsql://your-database.turso.io".to_string(),
auth_token: Some("your-auth-token".to_string()),
};
// 2. 创建连接池
let pool = Pool::new(config, 5); // 最大5个连接
// 3. 从连接池获取连接
let conn = pool.get().await?;
// 4. 创建表
conn.execute(
"CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, name TEXT, age INTEGER)",
[],
)
.await?;
// 5. 插入数据
let tx = conn.transaction().await?;
tx.execute("INSERT INTO users (name, age) VALUES (?, ?)", ["Alice", 25])
.await?;
tx.execute("INSERT INTO users (name, age) VALUES (?, ?)", ["Bob", 30])
.await?;
tx.commit().await?;
// 6. 预编译查询语句
let stmt = conn
.prepare("SELECT id, name, age FROM users WHERE age > ?")
.await?;
// 7. 执行查询
let mut rows = stmt.query([18]).await?;
while let Some(row) = rows.next().await? {
let id: i64 = row.get(0)?;
let name: String = row.get(1)?;
let age: i64 = row.get(2)?;
println!("User - id: {}, name: {}, age: {}", id, name, age);
}
// 8. 批量操作
let batch = conn.batch();
batch.execute("UPDATE users SET age = age + 1 WHERE name = ?", ["Alice"]);
batch.execute("UPDATE users SET age = age + 1 WHERE name = ?", ["Bob"]);
let _ = batch.commit().await?;
// 9. 错误处理示例
match conn.execute("SELECT * FROM non_existent_table", []).await {
Ok(rows) => {
println!("Query successful, got {} rows", rows.len());
}
Err(libsql_hrana::Error::ApiError(e)) => {
eprintln!("API error occurred: {}", e.message);
}
Err(e) => {
eprintln!("Other error occurred: {}", e);
}
}
Ok(())
}
这个完整示例演示了:
- 创建连接池
- 执行DDL语句创建表
- 使用事务插入数据
- 预编译SQL语句并执行查询
- 批量更新操作
- 错误处理机制
要运行这个示例,需要确保:
- 已配置正确的数据库URL和认证令牌
- 项目中已添加libsql-hrana和tokio依赖
- 运行在支持async/await的Rust环境(1.45+)