mirror of
https://github.com/wahyd4/pinpoint.git
synced 2026-08-13 23:06:54 +10:00
[강운덕] [LUCYSUS-1744] sql parser 보완.
git-svn-id: http://svn.bds.nhncorp.com/pe/hippo-commons/trunk@1062 84d0f5b1-2673-498c-a247-62c4ff18d310
This commit is contained in:
+28
-19
@@ -3,10 +3,12 @@ package com.profiler.common.util;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SqlUtils {
|
||||
public class SqlParser {
|
||||
public static final char SYMBOL_REPLACE = '$';
|
||||
public static final char NUMBER_REPLACE = '#';
|
||||
public static final char SEPARATOR = ',';
|
||||
|
||||
public static final String normalizedSql(String sql, StringBuilder outputParam) {
|
||||
public String normalizedSql(String sql, StringBuilder outputParam) {
|
||||
if (sql == null) {
|
||||
return "";
|
||||
}
|
||||
@@ -42,14 +44,7 @@ public class SqlUtils {
|
||||
} else if (lookAhead1Char == '/') {
|
||||
normalized.append("//");
|
||||
i += 2;
|
||||
for (; i < length; i++) {
|
||||
char stateCh = sql.charAt(i);
|
||||
if (stateCh == '\n') {
|
||||
normalized.append(stateCh);
|
||||
break;
|
||||
}
|
||||
normalized.append(stateCh);
|
||||
}
|
||||
i = readLine(sql, normalized, i);
|
||||
break;
|
||||
|
||||
} else {
|
||||
@@ -65,14 +60,7 @@ public class SqlUtils {
|
||||
if (lookAhead1(sql, i) == '-') {
|
||||
normalized.append("--");
|
||||
i += 2;
|
||||
for (; i < length; i++) {
|
||||
char stateCh = sql.charAt(i);
|
||||
if (stateCh == '\n') {
|
||||
normalized.append(stateCh);
|
||||
break;
|
||||
}
|
||||
normalized.append(stateCh);
|
||||
}
|
||||
i = readLine(sql, normalized, i);
|
||||
break;
|
||||
} else {
|
||||
// unary operator
|
||||
@@ -125,6 +113,8 @@ public class SqlUtils {
|
||||
// http://www.h2database.com/html/grammar.html 추가로 state machine을 더볼것.
|
||||
if (numberTokenStartEnable) {
|
||||
normalized.append('#');
|
||||
// number token start
|
||||
appendSeparator(outputParam);
|
||||
outputParam.append(ch);
|
||||
i++;
|
||||
tokenEnd:
|
||||
@@ -147,6 +137,7 @@ public class SqlUtils {
|
||||
break;
|
||||
default:
|
||||
// 여기서 처리하지 말고 루프 바깥으로 나가서 다시 token을 봐야 된다.
|
||||
// outputParam.append(SEPARATOR);
|
||||
i--;
|
||||
break tokenEnd;
|
||||
}
|
||||
@@ -192,6 +183,7 @@ public class SqlUtils {
|
||||
case '.':
|
||||
case '_':
|
||||
case '@': // Assignment Operator
|
||||
case ':': // 오라클쪽의 bind 변수는 :bindvalue로도 가능.
|
||||
numberTokenStartEnable = false;
|
||||
normalized.append(ch);
|
||||
break;
|
||||
@@ -210,6 +202,17 @@ public class SqlUtils {
|
||||
return normalized.toString();
|
||||
}
|
||||
|
||||
private int readLine(String sql, StringBuilder normalized, int index) {
|
||||
for (; index < sql.length(); index++) {
|
||||
char ch = sql.charAt(index);
|
||||
normalized.append(ch);
|
||||
if (ch == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* 미리 다음 문자열 하나를 까본다.
|
||||
*
|
||||
@@ -217,7 +220,7 @@ public class SqlUtils {
|
||||
* @param index
|
||||
* @return
|
||||
*/
|
||||
private static int lookAhead1(String sql, int index) {
|
||||
private int lookAhead1(String sql, int index) {
|
||||
index++;
|
||||
if (index < sql.length()) {
|
||||
return sql.charAt(index);
|
||||
@@ -226,4 +229,10 @@ public class SqlUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private void appendSeparator(StringBuilder outputParam) {
|
||||
if (outputParam.length() != 0) {
|
||||
outputParam.append(SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+46
-31
@@ -7,18 +7,20 @@ import org.junit.Test;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class SqlUtilsTest {
|
||||
public class SqlParserTest {
|
||||
private SqlParser sqlParser = new SqlParser();
|
||||
|
||||
@Test
|
||||
public void normalizedSql() {
|
||||
StringBuilder sb = new StringBuilder(10);
|
||||
|
||||
String s = SqlUtils.normalizedSql("select * from table a = 1 and b=50 and c=? and d='11'", sb);
|
||||
String s = sqlParser.normalizedSql("select * from table a = 1 and b=50 and c=? and d='11'", sb);
|
||||
|
||||
System.out.println(s);
|
||||
System.out.println(sb.toString());
|
||||
|
||||
StringBuilder sb2 = new StringBuilder(10);
|
||||
String s2 = SqlUtils.normalizedSql(" ", sb2);
|
||||
String s2 = sqlParser.normalizedSql(" ", sb2);
|
||||
System.out.println(s2);
|
||||
|
||||
System.out.println((char) -1);
|
||||
@@ -32,11 +34,16 @@ public class SqlUtilsTest {
|
||||
System.out.println((int) Character.MAX_HIGH_SURROGATE);
|
||||
|
||||
StringBuilder sb3 = new StringBuilder();
|
||||
String s3 = SqlUtils.normalizedSql("''", sb3);
|
||||
String s3 = sqlParser.normalizedSql("''", sb3);
|
||||
System.out.println("s3:" + s3);
|
||||
System.out.println("sb3:" + sb3.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nullCheck() {
|
||||
sqlParser.normalizedSql(null, new StringBuilder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void complex() {
|
||||
|
||||
@@ -69,39 +76,39 @@ public class SqlUtilsTest {
|
||||
|
||||
@Test
|
||||
public void numberState() {
|
||||
assertEqual("123", "#");
|
||||
assertEqual("123", "#", "123");
|
||||
// -가 진짜 숫자의 -인지 알려면 구문분석이 필요하므로 그냥 숫자만 치환한다.
|
||||
assertEqual("-123", "-#");
|
||||
assertEqual("+123", "+#");
|
||||
assertEqual("1.23", "#");
|
||||
assertEqual("1.23.34", "#");
|
||||
assertEqual("123 456", "# #");
|
||||
assertEqual("1.23 4.56", "# #");
|
||||
assertEqual("1.23-4.56", "#-#");
|
||||
assertEqual("-123", "-#", "123");
|
||||
assertEqual("+123", "+#", "123");
|
||||
assertEqual("1.23", "#", "1.23");
|
||||
assertEqual("1.23.34", "#", "1.23.34");
|
||||
assertEqual("123 456", "# #", "123,456");
|
||||
assertEqual("1.23 4.56", "# #", "1.23,4.56");
|
||||
assertEqual("1.23-4.56", "#-#", "1.23,4.56");
|
||||
|
||||
assertEqual("1<2", "#<#");
|
||||
assertEqual("1< 2", "#< #");
|
||||
assertEqual("(1< 2)", "(#< #)");
|
||||
assertEqual("1<2", "#<#", "1,2");
|
||||
assertEqual("1< 2", "#< #", "1,2");
|
||||
assertEqual("(1< 2)", "(#< #)", "1,2");
|
||||
|
||||
assertEqual("-- 1.23", "-- 1.23");
|
||||
assertEqual("- -1.23", "- -#");
|
||||
assertEqual("--1.23", "--1.23");
|
||||
assertEqual("/* 1.23 */", "/* 1.23 */");
|
||||
assertEqual("/*1.23*/", "/*1.23*/");
|
||||
assertEqual("/* 1.23 \n*/", "/* 1.23 \n*/");
|
||||
assertEqual("-- 1.23", "-- 1.23", "");
|
||||
assertEqual("- -1.23", "- -#", "1.23");
|
||||
assertEqual("--1.23", "--1.23", "");
|
||||
assertEqual("/* 1.23 */", "/* 1.23 */", "");
|
||||
assertEqual("/*1.23*/", "/*1.23*/", "");
|
||||
assertEqual("/* 1.23 \n*/", "/* 1.23 \n*/", "");
|
||||
|
||||
assertEqual("test123", "test123");
|
||||
assertEqual("test_123", "test_123");
|
||||
assertEqual("test_ 123", "test_ #");
|
||||
assertEqual("test123", "test123", "");
|
||||
assertEqual("test_123", "test_123", "");
|
||||
assertEqual("test_ 123", "test_ #", "123");
|
||||
|
||||
// 사실 이건 불가능한 토큰임.
|
||||
assertEqual("123tst", "#tst");
|
||||
assertEqual("123tst", "#tst", "123");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void singleLineCommentState() {
|
||||
assertEqual("--", "--");
|
||||
assertEqual("--", "--", "");
|
||||
assertEqual("//", "//");
|
||||
assertEqual("--123", "--123");
|
||||
assertEqual("//123", "//123");
|
||||
@@ -109,6 +116,7 @@ public class SqlUtilsTest {
|
||||
assertEqual("//test", "//test");
|
||||
assertEqual("--test\ntest", "--test\ntest");
|
||||
assertEqual("--test\t\n", "--test\t\n");
|
||||
assertEqual("--test\n123 test", "--test\n# test");
|
||||
}
|
||||
|
||||
|
||||
@@ -161,7 +169,7 @@ public class SqlUtilsTest {
|
||||
|
||||
private void assertEqual(String expected, String actual) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String normalizedSql = SqlUtils.normalizedSql(expected, sb);
|
||||
String normalizedSql = sqlParser.normalizedSql(expected, sb);
|
||||
try {
|
||||
Assert.assertEquals(actual, normalizedSql);
|
||||
} catch (AssertionFailedError e) {
|
||||
@@ -170,9 +178,16 @@ public class SqlUtilsTest {
|
||||
}
|
||||
}
|
||||
|
||||
private void assertEqual(String expected, String actual, String expectedSb) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
String normalizedSql = SqlUtils.normalizedSql(expected, sb);
|
||||
Assert.assertEquals(actual, normalizedSql);
|
||||
private void assertEqual(String expected, String actual, String ouputExpected) {
|
||||
StringBuilder output = new StringBuilder();
|
||||
String normalizedSql = sqlParser.normalizedSql(expected, output);
|
||||
try {
|
||||
Assert.assertEquals("normalizedSql check", actual, normalizedSql);
|
||||
} catch (AssertionFailedError e) {
|
||||
System.err.println("Original :" + expected);
|
||||
throw e;
|
||||
}
|
||||
|
||||
Assert.assertEquals("outputParam check", ouputExpected, output.toString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user