Rust 语言 编写 SQL 脚本格式化工具 缩进调整 + 关键字高亮

Rust阿木 发布于 4 天前 4 次阅读


Rust 语言下的 SQL 脚本格式化工具:缩进调整与关键字高亮

SQL(Structured Query Language)是数据库管理系统中使用的一种标准语言,用于执行各种数据库操作,如查询、更新、插入和删除数据。随着数据库应用的日益普及,SQL 脚本的数量也在不断增加。编写和阅读大量的 SQL 脚本可能会变得非常困难,尤其是在缩进和关键字高亮方面。为了提高开发效率和代码可读性,本文将介绍如何使用 Rust 语言开发一个 SQL 脚本格式化工具,该工具能够实现缩进调整和关键字高亮功能。

Rust 语言简介

Rust 是一种系统编程语言,由 Mozilla Research 开发。它旨在提供高性能、内存安全、并发和跨平台的编程环境。Rust 的语法简洁,同时提供了丰富的标准库和第三方库,使得开发各种应用程序变得容易。

SQL 脚本格式化工具的设计目标

我们的 SQL 脚本格式化工具需要实现以下功能:

1. 缩进调整:自动调整 SQL 脚本的缩进,使得代码结构更加清晰。
2. 关键字高亮:高亮显示 SQL 语句中的关键字,如 SELECT、FROM、WHERE 等,以提高代码的可读性。

工具实现

1. 项目结构

我们需要创建一个 Rust 项目。以下是项目的基本结构:


sql_formatter/
├── src/
│ ├── main.rs
│ ├── formatter.rs
│ └── highlighter.rs
└── Cargo.toml

2. 依赖管理

在 `Cargo.toml` 文件中,我们需要添加必要的依赖项:

toml
[dependencies]
regex = "1"
clap = "3"

3. 缩进调整

在 `formatter.rs` 文件中,我们将实现缩进调整功能。以下是核心代码:

rust
use std::io::{self, BufRead, BufReader, Write};
use std::fs::File;

pub fn format_sql(input: &str) -> String {
let mut lines = input.lines();
let mut formatted_lines = Vec::new();
let mut indent_level = 0;

for line in lines {
let stripped_line = line.trim();
if stripped_line.starts_with("SELECT") || stripped_line.starts_with("FROM") {
indent_level += 1;
} else if stripped_line.starts_with("WHERE") || stripped_line.starts_with("ORDER BY") {
indent_level -= 1;
}

let mut formatted_line = String::new();
for _ in 0..indent_level {
formatted_line.push_str(" ");
}
formatted_line.push_str(stripped_line);
formatted_lines.push(formatted_line);
}

formatted_lines.join("")
}

pub fn format_file(input_path: &str, output_path: &str) -> io::Result {
let input = File::open(input_path)?;
let mut output = File::create(output_path)?;

let mut buffer = BufReader::new(input);
let mut formatted_sql = String::new();

loop {
let line = buffer.read_line()?;
if line.is_empty() {
break;
}
formatted_sql.push_str(&format_sql(&line)?);
formatted_sql.push('');
}

output.write_all(formatted_sql.as_bytes())?;
Ok(())
}

4. 关键字高亮

在 `highlighter.rs` 文件中,我们将实现关键字高亮功能。以下是核心代码:

rust
use std::io::{self, BufRead, BufReader, Write};
use std::fs::File;

pub fn highlight_sql(input: &str) -> String {
let mut highlighted_sql = String::new();
let keywords = vec![
"SELECT", "FROM", "WHERE", "ORDER BY", "INSERT", "UPDATE", "DELETE", "CREATE", "DROP",
// ... 添加更多关键字
];

for line in input.lines() {
let mut highlighted_line = String::new();
let mut in_keyword = false;

for word in line.split_whitespace() {
if keywords.contains(&word) {
if !in_keyword {
highlighted_line.push_str(&format!("33[1;31m{}33[0m ", word));
in_keyword = true;
} else {
highlighted_line.push_str(word);
}
} else {
highlighted_line.push_str(word);
in_keyword = false;
}
highlighted_line.push(' ');
}
highlighted_sql.push_str(&highlighted_line);
highlighted_sql.push('');
}

highlighted_sql
}

pub fn highlight_file(input_path: &str, output_path: &str) -> io::Result {
let input = File::open(input_path)?;
let mut output = File::create(output_path)?;

let mut buffer = BufReader::new(input);
let mut highlighted_sql = String::new();

loop {
let line = buffer.read_line()?;
if line.is_empty() {
break;
}
highlighted_sql.push_str(&highlight_sql(&line)?);
highlighted_sql.push('');
}

output.write_all(highlighted_sql.as_bytes())?;
Ok(())
}

5. 主程序

在 `main.rs` 文件中,我们将实现主程序逻辑:

rust
use std::env;

fn main() {
let args: Vec = env::args().collect();
if args.len() < 3 {
eprintln!("Usage: {} ", args[0]);
return;
}

let input_path = &args[1];
let output_path = &args[2];

match (input_path, output_path) {
("-", "-") => {
let stdin = io::stdin();
let mut buffer = BufReader::new(stdin.lock());
let mut sql = String::new();

loop {
let line = buffer.read_line()?;
if line.is_empty() {
break;
}
sql.push_str(&line?);
sql.push('');
}

let formatted_sql = format_sql(&sql);
let highlighted_sql = highlight_sql(&formatted_sql);

println!("{}", highlighted_sql);
},
("-", _) => {
let stdin = io::stdin();
let mut buffer = BufReader::new(stdin.lock());
let mut sql = String::new();

loop {
let line = buffer.read_line()?;
if line.is_empty() {
break;
}
sql.push_str(&line?);
sql.push('');
}

let formatted_sql = format_sql(&sql);
let highlighted_sql = highlight_sql(&formatted_sql);

let mut output = File::create(output_path).unwrap();
output.write_all(highlighted_sql.as_bytes()).unwrap();
},
(_, _) => {
format_file(input_path, output_path).unwrap();
highlight_file(input_path, output_path).unwrap();
},
}
}

总结

本文介绍了如何使用 Rust 语言开发一个 SQL 脚本格式化工具,该工具能够实现缩进调整和关键字高亮功能。通过以上代码,我们可以轻松地对 SQL 脚本进行格式化,提高代码的可读性和开发效率。这个工具还可以进一步完善,例如支持更多的 SQL 关键字、语法错误检查等。