[강운덕] [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:
Woonduk Kang
2012-12-26 10:59:41 +00:00
parent b91e5ade7f
commit 596ad27919
2 changed files with 74 additions and 50 deletions
@@ -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);
}
}
}
@@ -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());
}
}