3个版本
0.1.2 | 2021年4月20日 |
---|---|
0.1.1 | 2019年9月5日 |
0.1.0 | 2019年8月20日 |
#1331 in 解析器实现
19KB
353 行
sql-script-parser遍历SQL脚本中的SQL语句
法律
双许可协议下 MIT
或 UNLICENSE。
功能
- 解析SQL脚本(目前为MySQL)到一系列单独的SQL语句。
- 将SQL语句的部分标记为不同的令牌类型(关键字、字符串、注释等)。
- 不验证输入,只分割SQL语句,不检查它们是否有效。
用法
在Cargo.toml中添加依赖项
[dependencies]
sql-script-parser = "0.1"
解析SQL
use sql_script_parser::sql_script_parser;
let sql = include_bytes!("../tests/demo.sql");
let mut parser = sql_script_parser(sql).map(|x| x.statement);
assert_eq!(parser.next(), Some(&b"select 1;\n"[..]));
assert_eq!(parser.next(), Some(&b"select 2"[..]));
assert_eq!(parser.next(), None);
高级 - 使用自定义令牌化器
use sql_script_parser::*;
struct DmlDdlSqlScriptTokenizer;
struct SqlStatement<'a> {
sql_script: SqlScript<'a>,
kind: SqlStatementKind,
}
#[derive(Debug, PartialEq)]
enum SqlStatementKind {
Ddl,
Dml,
}
impl<'a> SqlScriptTokenizer<'a, SqlStatement<'a>> for DmlDdlSqlScriptTokenizer {
fn apply(&self, sql_script: SqlScript<'a>, tokens: &[SqlToken]) -> SqlStatement<'a> {
let mut tokens_general = tokens.iter().filter(|x| {
[
SqlTokenKind::Word,
SqlTokenKind::Symbol,
SqlTokenKind::String,
]
.contains(&x.kind)
});
let kind = if let Some(first_keyword) = tokens_general.next() {
if first_keyword.kind == SqlTokenKind::Word {
let token = std::str::from_utf8(first_keyword.extract(&sql_script))
.unwrap()
.to_lowercase();
match token.as_str() {
"alter" | "create" | "drop" => SqlStatementKind::Ddl,
_ => SqlStatementKind::Dml,
}
} else {
SqlStatementKind::Dml
}
} else {
SqlStatementKind::Dml
};
SqlStatement { sql_script, kind }
}
}
let sql = include_bytes!("../tests/custom.sql");
let mut parser = SqlScriptParser::new(DmlDdlSqlScriptTokenizer {}, sql).map(|x| x.kind);
assert_eq!(parser.next(), Some(SqlStatementKind::Dml));
assert_eq!(parser.next(), Some(SqlStatementKind::Ddl));
assert_eq!(parser.next(), Some(SqlStatementKind::Dml));
assert_eq!(parser.next(), Some(SqlStatementKind::Ddl));
assert_eq!(parser.next(), None);