「Rust 重写 sqlite」错误处理

「这是我参与11月更文挑战的第 15 天,活动详情查看:2021最后一次更文挑战


错误处理

你可能已经注意到,在整个代码中,一直都在引用一个 SQLRiteError 类型。这是我使用 thiserror crate 定义的错误类型,它很容易使用的库,为标准库的 std::error::Error 特质提供了一个方便的衍生宏。不过提到我遇到了这个trait,它基本上解决了很多问题,代码看起来超级干净!目前的错误模块,位于 src/error.rs 中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
rust复制代码use thiserror::Error;

use sqlparser::parser::ParserError;

// 别名,便于书写,偷个懒~~~
pub type Result<T> = result::Result<T, SQLRiteError>;

#[derive(Error, Debug, PartialEq)]
pub enum SQLRiteError {
#[error("Not Implemented error: {0}")]
NotImplemented(String),
#[error("General error: {0}")]
General(String),
#[error("Internal error: {0}")]
Internal(String),
#[error("Unknown command error: {0}")]
UnknownCommand(String),
#[error("SQL error: {0:?}")]
SqlError(#[from] ParserError),
}

/// Return SQLRite errors from String
pub fn sqlrite_error(message: &str) -> SQLRiteError {
SQLRiteError::General(message.to_owned())
}

简单介绍一下

Rust界的大佬 dtolnay 设计了两个crate:thiserroranyhow。在这之前已经有很多提升错误处理的库了,但最后最终还是解决 thiserror + anyhow 是最易用和实用的。

注意事项:thiserror 是给lib使用的,而 anyhow 是给bin程序使用,当然bin程序可以使用thiser+anyhow但是切记 anyhow 不要在lib里面使用

而我们在上面的 SQLRiteError 定义中,使用的就是 thiserror 的包装,其实就是使用 enum 封装的思路。

1
2
3
4
5
6
rust复制代码use anyhow::Result; 
fn get_cluster_info() -> Result<ClusterMap> {
let config = std::fs::read_to_string("cluster.json")?;
let map: ClusterMap = serde_json::from_str(&config)?;
Ok(map)
}

anyhow 使用上,直接返回 anyhow::Result,因为它实现了 From<E> where E: Error,所以就不用再维护一个 enum 类型。

暂时总结

目前我们成功地解析了用户的命令,区分了 MetaCommandSQLCommand。以及实现了一个可扩展的MetaCommand 模块,使得将来增加更多的命令变得容易。

然后添加了sql模块,通过使用 sqlparser-rs crate,我们成功地解析了SQL语句,并能够从每个SQL语句中生成一个 ast。我们已经从 CREATE TABLE SQL 语句中解析并生成了至少一个简化版的字节码,可以进入数据库(将在后面进行)。最后,我们还创建了一个错误模块,所以我们有一个标准化的方法来处理整个应用程序的错误。

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%