Skip to content

Commit a75405d

Browse files
committed
Merge commit 'feea3bab767e946c8d06d8a7d8500c8eb6fbfa78'
2 parents dabfd08 + feea3ba commit a75405d

File tree

6 files changed

+124
-92
lines changed

6 files changed

+124
-92
lines changed

.vscode/launch.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
}
2121
},
2222
"args": [
23-
"--",
2423
"-i",
2524
"-s",
2625
"./test_data",
@@ -45,7 +44,6 @@
4544
}
4645
},
4746
"args": [
48-
"--",
4947
"-m",
5048
"-s",
5149
"./test_data",
@@ -70,7 +68,6 @@
7068
}
7169
},
7270
"args": [
73-
"--",
7471
"-v"
7572
],
7673
"cwd": "${workspaceFolder}"

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "xbatis2sql"
3-
version = "0.1.3"
3+
version = "0.1.4"
44
edition = "2021"
55
authors = ["Helly Guo <[email protected]>"]
66
exclude = ["tests", "examples"]

src/parser/abt_parser.rs

Lines changed: 91 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,67 @@ use xml::reader::*;
1414
/// 回车
1515
const CRLF: [u8; 1] = [0x0a];
1616

17+
pub enum Mode {
18+
Statement,
19+
Select,
20+
Insert,
21+
Update,
22+
Delete,
23+
SqlPart,
24+
}
25+
26+
impl Mode {
27+
pub fn from(name: &str) -> Self {
28+
match name {
29+
"statement" => Mode::Statement,
30+
"select" => Mode::Select,
31+
"insert" => Mode::Insert,
32+
"update" => Mode::Update,
33+
"delete" => Mode::Delete,
34+
"sql" => Mode::SqlPart,
35+
_ => panic!("unkown mode"),
36+
}
37+
}
38+
}
39+
40+
pub struct SqlStatement {
41+
pub mode: Mode,
42+
pub id: String,
43+
pub sql: String,
44+
}
45+
46+
impl SqlStatement {
47+
pub fn new(mode: Mode, id: String, sql: String) -> Self {
48+
return SqlStatement { mode, id, sql };
49+
}
50+
}
51+
1752
/// 解析过程中数据
1853
pub struct XmlParsedState {
54+
/// 过程中变化
1955
/// 是否在语句中
2056
pub in_statement: bool,
21-
/// 是否在 `sql` 块中
22-
pub in_sql: bool,
23-
/// `sql` 索引
24-
pub sql_idx: i32,
25-
/// `sql` 临时存储,以索引为键,`sql` 为值
26-
pub include_temp_sqls: HashMap<i32, String>,
27-
/// `sql` 临时存储,以 `sql` 的 `id` 为键,索引为值
28-
pub include_temp_sqls_ids: HashMap<String, i32>,
57+
/// 当前ID
58+
pub current_id: String,
59+
/// 过程中累计
60+
/// 语句集
61+
pub statements: Vec<SqlStatement>,
62+
/// 语句集
63+
pub sql_part_map: HashMap<String, SqlStatement>,
64+
/// 过程中不再变化
65+
/// 文件名
66+
pub filename: String,
2967
}
3068

3169
impl XmlParsedState {
3270
/// 构建器,构造工厂
3371
pub fn new() -> Self {
3472
return XmlParsedState {
3573
in_statement: false,
36-
in_sql: false,
37-
sql_idx: 0,
38-
include_temp_sqls: HashMap::new(),
39-
include_temp_sqls_ids: HashMap::new(),
74+
current_id: String::from(""),
75+
statements: Vec::new(),
76+
sql_part_map: HashMap::new(),
77+
filename: String::from(""),
4078
};
4179
}
4280
}
@@ -81,23 +119,24 @@ pub trait Parser {
81119
let parser = EventReader::new(buf);
82120
let mut builder = StringBuilder::new();
83121
let mut state = XmlParsedState::new();
122+
state.filename = filename.clone();
84123
for e in parser {
85124
match e {
86125
Ok(XmlEvent::StartElement {
87126
name, attributes, ..
88127
}) => {
89-
self.parse_start_element(name, attributes, &mut builder, &mut state, sql_store);
128+
self.parse_start_element(name, attributes, &mut builder, &mut state);
90129
}
91130
Ok(XmlEvent::EndElement { name }) => {
92-
self.parse_end_element(name, &mut builder, &mut state, sql_store);
131+
self.parse_end_element(name, &mut builder, &mut state);
93132
}
94133
Ok(XmlEvent::CData(s)) => {
95-
if state.in_statement || state.in_sql {
134+
if state.in_statement {
96135
builder.append(s);
97136
}
98137
}
99138
Ok(XmlEvent::Characters(s)) => {
100-
if state.in_statement || state.in_sql {
139+
if state.in_statement {
101140
builder.append(s);
102141
}
103142
}
@@ -108,6 +147,8 @@ pub trait Parser {
108147
_ => {}
109148
}
110149
}
150+
info!("{}", state.filename);
151+
self.replace_and_fill(sql_store, &state.statements, &state.sql_part_map);
111152
}
112153

113154
fn parse_start_element(
@@ -116,34 +157,54 @@ pub trait Parser {
116157
attributes: Vec<OwnedAttribute>,
117158
builder: &mut StringBuilder,
118159
state: &mut XmlParsedState,
119-
sql_store: &mut Vec<String>,
120160
);
121161

122162
fn parse_end_element(
123163
&self,
124164
name: OwnedName,
125165
builder: &mut StringBuilder,
126166
state: &mut XmlParsedState,
127-
sql_store: &mut Vec<String>,
128167
) {
129168
let element_name = name.local_name.as_str().to_ascii_lowercase();
130169
if parse_helper::match_statement(&element_name) {
131-
let sql = parse_helper::replace_included_sql(
132-
builder,
133-
&state.include_temp_sqls,
134-
&state.include_temp_sqls_ids,
135-
);
136-
self.clear_and_push(&sql, sql_store);
170+
let mode = Mode::from(element_name.as_str());
171+
match mode {
172+
Mode::SqlPart => {
173+
let sql_stat =
174+
SqlStatement::new(mode, state.current_id.clone(), builder.to_string());
175+
state
176+
.sql_part_map
177+
.insert(state.current_id.clone(), sql_stat);
178+
}
179+
_ => {
180+
let sql_stat =
181+
SqlStatement::new(mode, state.current_id.clone(), builder.to_string());
182+
state.statements.push(sql_stat);
183+
}
184+
}
137185
state.in_statement = false;
138-
} else if element_name == "sql" {
139-
state
140-
.include_temp_sqls
141-
.insert(state.sql_idx, builder.to_string());
142-
state.sql_idx += 1;
186+
state.current_id = String::from("");
143187
builder.clear();
144-
state.in_sql = false;
145188
}
146189
}
190+
191+
fn replace_and_fill(
192+
&self,
193+
sql_store: &mut Vec<String>,
194+
statements: &Vec<SqlStatement>,
195+
sql_part_map: &HashMap<String, SqlStatement>,
196+
) {
197+
for sql in statements {
198+
sql_store.push("--- ".to_string() + &sql.id);
199+
let mut sql_stat = sql.sql.clone();
200+
for sql_part in sql_part_map {
201+
sql_stat =
202+
parse_helper::replace_included_sql(&sql_stat, &sql_part.0, &sql_part.1.sql);
203+
}
204+
self.clear_and_push(&sql_stat, sql_store);
205+
}
206+
}
207+
147208
fn clear_and_push(&self, origin_sql: &String, sql_store: &mut Vec<String>);
148209

149210
fn save(&self, output_dir: &String, sql_store: Vec<String>) {

src/parser/ibatis_parser.rs

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,11 @@ lazy_static! {
1111
}
1212

1313
lazy_static! {
14-
static ref RE0: Regex = Regex::new("[\r\n\t ]+").unwrap();
15-
static ref RE1: Regex = Regex::new("\\$\\{[^${]+\\}").unwrap();
16-
static ref RE2: Regex = Regex::new("#[^#]+#").unwrap();
17-
static ref RE3: Regex = Regex::new("\\$[^$]+\\$").unwrap();
14+
static ref RE0: Regex = Regex::new("[\t ]?--[^\n]*\n").unwrap();
15+
static ref RE1: Regex = Regex::new("[\r\n\t ]+").unwrap();
16+
static ref RE2: Regex = Regex::new("\\$\\{[^${]+\\}").unwrap();
17+
static ref RE3: Regex = Regex::new("#[^#]+#").unwrap();
18+
static ref RE4: Regex = Regex::new("\\$[^$]+\\$").unwrap();
1819
static ref RE_FIX1: Regex = Regex::new("WHERE[ ]+AND").unwrap();
1920
static ref RE_FIX2: Regex = Regex::new("WHERE[ ]+OR").unwrap();
2021
}
@@ -40,44 +41,37 @@ impl Parser for IBatisParser {
4041
attributes: Vec<OwnedAttribute>,
4142
builder: &mut StringBuilder,
4243
state: &mut XmlParsedState,
43-
sql_store: &mut Vec<String>,
4444
) {
4545
let element_name = name.local_name.as_str().to_ascii_lowercase();
4646
if parse_helper::match_statement(&element_name) {
4747
state.in_statement = true;
4848
parse_helper::search_matched_attr(&attributes, "id", |attr| {
49-
sql_store.push("-- ".to_string() + attr.value.as_str());
49+
state.current_id = attr.value.clone();
5050
});
5151
} else if element_name == "where" {
52-
builder.append("where ");
52+
builder.append(" where ");
5353
} else if element_name == "include" {
5454
parse_helper::search_matched_attr(&attributes, "refid", |attr| {
55-
builder.append("__INCLUDE_ID_");
56-
builder.append(attr.value.as_str());
55+
builder.append(" __INCLUDE_ID_");
56+
builder.append(attr.value.to_ascii_uppercase().as_str());
5757
builder.append("_END__");
5858
});
5959
} else if state.in_statement {
6060
parse_helper::search_matched_attr(&attributes, "prepend", |attr| {
61-
builder.append(attr.value.as_str());
62-
});
63-
} else if element_name == "sql" {
64-
state.in_sql = true;
65-
parse_helper::search_matched_attr(&attributes, "id", |attr| {
66-
state
67-
.include_temp_sqls_ids
68-
.insert(attr.value.as_str().to_string(), state.sql_idx);
61+
builder.append(" ").append(attr.value.as_str()).append(" ");
6962
});
7063
}
7164
}
7265

7366
fn clear_and_push(&self, origin_sql: &String, sql_store: &mut Vec<String>) {
74-
let mut sql = String::from(origin_sql);
67+
let mut sql = String::from(origin_sql.to_ascii_uppercase().trim());
7568
sql = RE0.replace_all(sql.as_str(), " ").to_string();
76-
sql = RE1
69+
sql = RE1.replace_all(sql.as_str(), " ").to_string();
70+
sql = RE2
7771
.replace_all(sql.as_str(), "__REPLACE_SCHEMA__")
7872
.to_string();
79-
sql = RE2.replace_all(sql.as_str(), ":?").to_string();
8073
sql = RE3.replace_all(sql.as_str(), ":?").to_string();
74+
sql = RE4.replace_all(sql.as_str(), ":?").to_string();
8175
sql = RE_FIX1.replace_all(sql.as_str(), "WHERE").to_string();
8276
sql = RE_FIX2.replace_all(sql.as_str(), "WHERE").to_string();
8377
sql_store.push(sql + ";");

src/parser/mybatis_parser.rs

Lines changed: 13 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ lazy_static! {
1111
}
1212

1313
lazy_static! {
14-
static ref RE0: Regex = Regex::new("[\r\n\t ]+").unwrap();
15-
static ref RE1: Regex = Regex::new("#\\{[^#{]+\\}").unwrap();
16-
static ref RE2: Regex = Regex::new("\\$\\{[^${]+\\}").unwrap();
14+
static ref RE0: Regex = Regex::new("[\t ]?--[^\n]*\n").unwrap();
15+
static ref RE1: Regex = Regex::new("[\r\n\t ]+").unwrap();
16+
static ref RE2: Regex = Regex::new("#\\{[^#{]+\\}").unwrap();
17+
static ref RE3: Regex = Regex::new("\\$\\{[^${]+\\}").unwrap();
1718
static ref RE_FIX1: Regex = Regex::new("WHERE[ ]+AND").unwrap();
1819
static ref RE_FIX2: Regex = Regex::new("WHERE[ ]+OR").unwrap();
1920
static ref RE_FIX3: Regex = Regex::new(",[ ]+WHERE").unwrap();
@@ -41,39 +42,32 @@ impl Parser for MyBatisParser {
4142
attributes: Vec<OwnedAttribute>,
4243
builder: &mut StringBuilder,
4344
state: &mut XmlParsedState,
44-
sql_store: &mut Vec<String>,
4545
) {
4646
let element_name = name.local_name.as_str().to_ascii_lowercase();
4747
if parse_helper::match_statement(&element_name) {
4848
state.in_statement = true;
4949
parse_helper::search_matched_attr(&attributes, "id", |attr| {
50-
sql_store.push("-- ".to_string() + attr.value.as_str());
50+
state.current_id = attr.value.clone();
5151
});
5252
} else if element_name == "where" {
53-
builder.append("where ");
53+
builder.append(" where ");
5454
} else if element_name == "set" {
55-
builder.append("set ");
55+
builder.append(" set ");
5656
} else if element_name == "include" {
5757
parse_helper::search_matched_attr(&attributes, "refid", |attr| {
58-
builder.append("__INCLUDE_ID_");
59-
builder.append(attr.value.as_str());
58+
builder.append(" __INCLUDE_ID_");
59+
builder.append(attr.value.to_ascii_uppercase().as_str());
6060
builder.append("_END__");
6161
});
62-
} else if element_name == "sql" {
63-
state.in_sql = true;
64-
parse_helper::search_matched_attr(&attributes, "id", |attr| {
65-
state
66-
.include_temp_sqls_ids
67-
.insert(attr.value.as_str().to_string(), state.sql_idx);
68-
});
6962
}
7063
}
7164

7265
fn clear_and_push(&self, origin_sql: &String, sql_store: &mut Vec<String>) {
73-
let mut sql = String::from(origin_sql);
74-
sql = RE0.replace_all(sql.as_str(), " ").to_string();
75-
sql = RE1.replace_all(sql.as_str(), ":?").to_string();
66+
let mut sql = String::from(origin_sql.to_ascii_uppercase().trim());
67+
sql = RE0.replace_all(sql.as_str(), "").to_string();
68+
sql = RE1.replace_all(sql.as_str(), " ").to_string();
7669
sql = RE2.replace_all(sql.as_str(), ":?").to_string();
70+
sql = RE3.replace_all(sql.as_str(), ":?").to_string();
7771
sql = RE_FIX1.replace_all(sql.as_str(), "WHERE").to_string();
7872
sql = RE_FIX2.replace_all(sql.as_str(), "WHERE").to_string();
7973
sql = RE_FIX3.replace_all(sql.as_str(), " WHERE").to_string();

src/parser/parse_helper.rs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,11 @@
1-
use rstring_builder::StringBuilder;
2-
use std::collections::HashMap;
31
use std::*;
42
use xml::attribute::*;
53

64
/// 替换 `include`,用对应的 `sql` 进行合并
7-
pub fn replace_included_sql(
8-
builder: &mut StringBuilder,
9-
include_temp_sqls: &HashMap<i32, String>,
10-
include_temp_sqls_ids: &HashMap<String, i32>,
11-
) -> String {
12-
let mut sql = builder.to_string().trim().to_ascii_uppercase();
13-
for e in include_temp_sqls_ids {
14-
let replaced = &include_temp_sqls.get(e.1).unwrap().to_ascii_uppercase();
15-
sql = sql.replace(
16-
("__INCLUDE_ID_".to_string() + e.0.as_str() + "_END__")
17-
.to_ascii_uppercase()
18-
.as_str(),
19-
replaced,
20-
);
21-
}
22-
builder.clear();
23-
return sql;
5+
pub fn replace_included_sql(orig_sql: &String, id: &String, sql_part: &String) -> String {
6+
let replace_target = "__INCLUDE_ID_".to_string() + &id.as_str().to_ascii_uppercase() + "_END__";
7+
let replaced = sql_part.as_str();
8+
return orig_sql.replace((replace_target).to_ascii_uppercase().as_str(), replaced);
249
}
2510

2611
/// 检索属性,匹配情况下回调闭包
@@ -44,4 +29,5 @@ pub fn match_statement(element_name: &String) -> bool {
4429
|| *element_name == "update"
4530
|| *element_name == "delete"
4631
|| *element_name == "statement"
32+
|| *element_name == "sql"
4733
}

0 commit comments

Comments
 (0)