org.test4j.module.tracer.jdbc.TracerSQLUtility Maven / Gradle / Ivy
package org.test4j.module.tracer.jdbc;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.test4j.tools.commons.StringHelper;
/**
* SQL语法高亮显示器
*/
public class TracerSQLUtility {
// 关键字
public static final String[] SQL_KEY_WORDS = { "select", "from", "update", "delete", "insert", "into", "where",
"group", "by", "having", "values", "and", "or", "(", ")", "as", "like", "not", "in", "exists", "order",
"asc", "desc", "on", "join", "outer", "set", "create", "table", "alter", "drop", "index" };
// 关键字替换前缀
private static String keywordLightPrefix = "";
// 关键字替换后缀
private static String keywordLightSuffix = "";
// 表名替换前缀
private static String tablesLightPrefix = "";
// 表名替换后缀
private static String tablesLightSuffix = "";
/**
* 分析出表名列表
*
* @param sql
* @return
*/
public static Collection analyseSqlTables(String sql) {
// 词法分析
String[] words = splitWord(sql, null);
Collection tables = new ArrayList();
// 语法分析
tableAnalyse(new Counter(), words, tables);
return tables;
}
/**
* 高亮关键字
*
* @param sql
* @return
*/
public static String highlightKeywords(String sql) {
String lightSql = replaceSql(sql, null, true);
return lightSql;
}
/**
* 高亮sql,包括关键字和表名
*
* @param sql
* @return
*/
public static String highlightSql(String sql) {
Collection tables = analyseSqlTables(sql);
String lightSql = replaceSql(sql, tables, true);
return lightSql;
}
/**
* 完成sql替换,包括
*
* @return
*/
private static String replaceSql(String sql, final Collection tables, final boolean replaceKeyword) {
// 替换必须保证在一次词法扫描完成,否则,替换的内容会互相影响
// @ TODO 这里splitWord还不能做到真正的一次扫描,只是模拟一次词法分析
final StringBuffer replacement = new StringBuffer(" ");
// 词法分析处理
LexicalAnalysisProcessor processor = new LexicalAnalysisProcessor() {
public void process(String word) {
int placeType = 0;
if (replaceKeyword) {
for (int i = 0; i < SQL_KEY_WORDS.length; i++) {
if (SQL_KEY_WORDS[i].equals(word.toLowerCase())) {
placeType = 1;
break;// 表名的优先级大于关键字,所以这里不return
}
}
}
if (tables != null && tables.contains(word)) {
placeType = 2;
}
switch (placeType) {
case 0:// 普通词汇
replacement.append(word + " ");
break;
case 1:// 关键字
replacement.append(keywordLightPrefix + word + keywordLightSuffix + " ");
break;
case 2:// 表名
replacement.append(tablesLightPrefix + word + tablesLightSuffix + " ");
break;
default:
}
}
};
splitWord(sql, processor);
return replacement.toString();
}
private static class Counter {
int num = 0;
}
/**
* 对表名的语法分析
*
* @param words
* @return
*/
private static void tableAnalyse(Counter i, String[] words, Collection tables) {
for (; i.num < words.length; i.num++) {
// 如果遇到'('跳入下一个子句语法分析
if ("(".equals(words[i.num].trim().toLowerCase())) {
i.num++;
tableAnalyse(i, words, tables);
continue;
}
// 如果遇到')'退出当前子句语法分析
if (")".equals(words[i.num].trim().toLowerCase())) {
return;
}
// 如果遇到from
if ("from".equals(words[i.num].trim().toLowerCase())) {
for (i.num++; i.num < words.length; i.num++) {
String fromNext = words[i.num];
// 如果遇到'('跳入下一个子句语法分析
if ("(".equals(fromNext.trim().toLowerCase())) {
i.num++;
tableAnalyse(i, words, tables);
continue;
}
// 如果遇到')'退出当前子句语法分析
if (")".equals(fromNext.trim().toLowerCase())) {
return;
}
// 如果遇到'where,into'from表达式结束
if ("where".equals(fromNext.trim().toLowerCase()) || "into".equals(fromNext.trim().toLowerCase())) {
break;
}
// 如果是,则前面的就是表名
if (",".equals(fromNext.trim()) == false
&& ("from".equals(words[i.num - 1]) || ",".equals(words[i.num - 1]))
|| "join".equals(words[i.num - 1])) {
tables.add(words[i.num]);
} // else // 什么也不做
}
}
if (i.num >= words.length)
break;
// 如果遇到update
if ("update".equals(words[i.num].trim().toLowerCase())) {
i.num++;
if (i.num >= words.length)
break;
tables.add(words[i.num]);
}
if (i.num >= words.length)
break;
// 如果遇到into
if ("into".equals(words[i.num].trim().toLowerCase())) {
i.num++;
if (i.num >= words.length)
break;
tables.add(words[i.num]);
}
}
}
/**
* 分词,在做SQL分析之前,先进行词法分析,找出SQL里面有意义的词汇
*
* @param sql
* @return
*/
public static String[] splitWord(String sql, LexicalAnalysisProcessor processor) {
List words = new ArrayList();
String[] spaceSplit = sql.split(" ");
for (String word : spaceSplit) {
word = word.replaceAll(",", "#,#");
word = word.replaceAll("\\(", "#(#");
word = word.replaceAll("\\)", "#)#");
String[] wordSplits = word.split("#");
for (String wordSplit : wordSplits) {
if (StringHelper.isBlankOrNull(wordSplit)) {
continue;
}
words.add(wordSplit);
if (processor != null) {
processor.process(wordSplit);
}
}
}
String[] result = new String[words.size()];
words.toArray(result);
return result;
}
}
/**
* sql词法分析处理器,以便在一次词法扫描过程,嵌入额外的动作
*/
abstract class LexicalAnalysisProcessor {
/**
*
* @param word
* 词汇
*/
public abstract void process(String word);
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy