增强Parser

git-svn-id: http://code.alibabatech.com/svn/druid/trunk@132 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
wenshao
2011-05-19 06:52:32 +00:00
parent 6311c67f54
commit d9776a1530
13 changed files with 215 additions and 41 deletions
@@ -560,6 +560,10 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
}
public boolean visit(OracleSelectHierachicalQueryClause x) {
print("START WITH ");
x.getStartWith().accept(this);
println();
print("CONNECT BY ");
if (x.isPrior()) {
@@ -571,8 +575,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
}
x.getConnectBy().accept(this);
print(" START WITH ");
x.getStartWith().accept(this);
return false;
}
@@ -15,8 +15,10 @@
*/
package com.alibaba.druid.sql.dialect.oracle.parser;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleOrderBy;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalytic;
@@ -55,6 +57,24 @@ public class OracleExprParser extends SQLExprParser {
return false;
}
public SQLExpr primary() throws ParserException {
final Token tok = lexer.token();
switch (tok) {
case COLON:
lexer.nextToken();
if (lexer.token() == Token.LITERAL_INT) {
String name = ":" + lexer.numberString();
lexer.nextToken();
return new SQLVariantRefExpr(name);
} else{
throw new ParserException("syntax error : " + lexer.token());
}
default:
return super.primary();
}
}
@Override
public OracleOrderBy parseOrderBy() {
if (lexer.token() == (Token.ORDER)) {
@@ -15,7 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.oracle.parser;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
@@ -32,7 +32,7 @@ public class OracleInsertParser extends SQLStatementParser {
super(lexer);
}
public SQLInsertStatement parseInsert() throws ParserException {
public SQLStatement parseInsert() throws ParserException {
throw new ParserException("TODO");
}
@@ -36,6 +36,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
@@ -48,6 +49,10 @@ public class OracleSelectParser extends SQLSelectParser {
public OracleSelectParser(Lexer lexer){
super(lexer);
}
protected SQLExprParser createExprParser() {
return new OracleExprParser(lexer);
}
public OracleSelect select() {
OracleSelect select = new OracleSelect();
@@ -24,6 +24,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateViewStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.ParserException;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLStatementParser;
import com.alibaba.druid.sql.parser.Token;
@@ -37,6 +38,10 @@ public class OracleStatementParser extends SQLStatementParser {
public OracleStatementParser(Lexer lexer){
super(lexer);
}
protected SQLExprParser createExprParser() {
return new OracleExprParser(lexer);
}
@Override
public void parseStatementList(List<SQLStatement> statementList) throws ParserException {
@@ -84,6 +84,7 @@ public class CharTypes {
whitespaceFlags['\t'] = true;
whitespaceFlags['\f'] = true;
whitespaceFlags['\b'] = true;
whitespaceFlags[160] = true; // 特别处理
}
/**
@@ -85,7 +85,7 @@ public class SQLStatementParser extends SQLParser {
}
if (lexer.token() == (Token.INSERT)) {
SQLInsertStatement insertStatement = parseInsert();
SQLStatement insertStatement = parseInsert();
statementList.add(insertStatement);
continue;
@@ -130,7 +130,7 @@ public class SQLStatementParser extends SQLParser {
}
}
public SQLInsertStatement parseInsert() {
public SQLStatement parseInsert() {
accept(Token.INSERT);
accept(Token.INTO);
@@ -102,7 +102,8 @@ public enum Token {
PRIOR("PRIOR"),
CONNECT("CONNECT"),
EOF, ERROR,
EOF,
ERROR,
IDENTIFIER,
HINT,
VARIANT,
@@ -0,0 +1,76 @@
package com.alibaba.druid.sql.oracle.bvt;
import java.util.List;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateSetListClause;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateSetListSingleColumnItem;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleOutputVisitor;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
public class OracleSQLParserResourceTest extends TestCase {
public void test_0() throws Exception {
String sql = "UPDATE employees SET salary = salary * 1.1 WHERE employee_id IN (SELECT employee_id FROM job_history);";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
Assert.assertEquals(1, statementList.size());
OracleUpdateStatement statement = (OracleUpdateStatement) statementList.get(0);
Assert.assertEquals(0, statement.getHints().size());
OracleUpdateSetListClause setList = (OracleUpdateSetListClause) statement.getSetClause();
Assert.assertEquals(1, setList.getItems().size());
OracleUpdateSetListSingleColumnItem item = (OracleUpdateSetListSingleColumnItem) setList.getItems().get(0);
SQLIdentifierExpr column = (SQLIdentifierExpr) item.getColumn();
Assert.assertEquals("salary", column.getName());
SQLBinaryOpExpr value = (SQLBinaryOpExpr) item.getValue();
Assert.assertEquals(SQLBinaryOperator.Multiply, value.getOperator());
String text = output(statementList);
System.out.println(text);
}
public void test_1() throws Exception {
String sql = "SELECT employees_seq.nextval FROM DUAL;";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
Assert.assertEquals(1, statementList.size());
String text = output(statementList);
System.out.println(text);
}
public void test_2() throws Exception {
String sql = "SELECT LPAD(' ',2*(LEVEL-1)) || last_name org_chart, employee_id, manager_id, job_id FROM employees WHERE job_id != 'FI_MGR' START WITH job_id = 'AD_VP' CONNECT BY PRIOR employee_id = manager_id; ";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
Assert.assertEquals(1, statementList.size());
String text = output(statementList);
System.out.println(text);
}
private String output(List<SQLStatement> stmtList) {
StringBuilder out = new StringBuilder();
OracleOutputVisitor visitor = new OracleOutputVisitor(out);
for (SQLStatement stmt : stmtList) {
stmt.accept(visitor);
}
return out.toString();
}
}
@@ -1,64 +1,52 @@
package com.alibaba.druid.sql.oracle.bvt;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import junit.framework.Assert;
import junit.framework.TestCase;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateSetListClause;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateSetListSingleColumnItem;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleOutputVisitor;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.Token;
import com.alibaba.druid.util.JdbcUtils;
public class OracleSQLParserTest extends TestCase {
public void test_0() throws Exception {
String sql = "UPDATE employees SET salary = salary * 1.1 WHERE employee_id IN (SELECT employee_id FROM job_history);";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
Assert.assertEquals(1, statementList.size());
OracleUpdateStatement statement = (OracleUpdateStatement) statementList.get(0);
Assert.assertEquals(0, statement.getHints().size());
OracleUpdateSetListClause setList = (OracleUpdateSetListClause) statement.getSetClause();
Assert.assertEquals(1, setList.getItems().size());
OracleUpdateSetListSingleColumnItem item = (OracleUpdateSetListSingleColumnItem) setList.getItems().get(0);
SQLIdentifierExpr column = (SQLIdentifierExpr) item.getColumn();
Assert.assertEquals("salary", column.getName());
SQLBinaryOpExpr value = (SQLBinaryOpExpr) item.getValue();
Assert.assertEquals(SQLBinaryOperator.Multiply, value.getOperator());
String text = output(statementList);
System.out.println(text);
}
public void test_1() throws Exception {
String sql = "SELECT employees_seq.nextval FROM DUAL;";
InputStream is = null;
is = Thread.currentThread().getContextClassLoader().getResourceAsStream("bvt/parser/oracle-0.txt");
Reader reader = new InputStreamReader(is);
String sql = JdbcUtils.read(reader);
JdbcUtils.close(reader);
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
Assert.assertEquals(1, statementList.size());
String text = output(statementList);
System.out.println(text);
}
public void test_2() throws Exception {
String sql = "SELECT LPAD(' ',2*(LEVEL-1)) || last_name org_chart, employee_id, manager_id, job_id FROM employees WHERE job_id != 'FI_MGR' START WITH job_id = 'AD_VP' CONNECT BY PRIOR employee_id = manager_id; ";
InputStream is = null;
is = Thread.currentThread().getContextClassLoader().getResourceAsStream("bvt/parser/oracle-1.txt");
Reader reader = new InputStreamReader(is);
String sql = JdbcUtils.read(reader);
JdbcUtils.close(reader);
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
Assert.assertEquals(1, statementList.size());
String text = output(statementList);
System.out.println(text);
}
@@ -13,6 +13,8 @@ public class SQLLexerTest2 extends TestCase {
if (tok == Token.IDENTIFIER) {
System.out.println(tok.name() + "\t\t" + lexer.stringVal());
} else if (tok == Token.LITERAL_INT) {
System.out.println(tok.name() + "\t\t" + lexer.numberString());
} else {
System.out.println(tok.name() + "\t\t\t" + tok.name);
}
@@ -0,0 +1,14 @@
SELECT                
ID as id,                
to_char(GMT_MODIFIED,'yyyymmdd hh24:mi:ss') as gmtModified,                               
COL5 as col5            
FROM BPM_ACTINST            
WHERE IS_DELETED='n'                  
AND end_time is null  
AND deadline_time < sysdate  
AND approval_time is null
AND             id > :1        
AND col2 in    
(:2,:3,:4,:5,:6,:7,:8,:9,:10,:11,:12,:13,:14,:15,:16,:17,:18,:19,:20,:21,:22,:23,:24,:25,:26,:27,:28,:29,:30,:31,:32,:33)      
AND rownum<:34  
ORDER BY id   ;
@@ -0,0 +1,59 @@
INSERT INTO GLOBAL_ACCOUNT_SMD
(ID,
GMT_MODIFIED,
MODIFIER,
GMT_CREATE,
CREATOR,
DOMAIN,
EMPLOYEE_NUMBER,
COMPANY_NAME,
HOMEPAGE_URL,
BACKGROUND,
CATEGORY_ID,
REMARK,
MEMBER_ID,
SALES_OWNER_ID,
ACCOUNT_ID,
IS_DELETED,
CUST_GRADE)
SELECT ID,
GMT_MODIFIED,
MODIFIER,
GMT_CREATE,
CREATOR,
DOMAIN,
EMPLOYEE_NUMBER,
COMPANY_NAME,
HOMEPAGE_URL,
BACKGROUND,
CATEGORY_ID,
REMARK,
MEMBER_ID,
SALES_OWNER_ID,
ACCOUNT_ID,
IS_DELETED,
CUST_GRADE
FROM APOLLO_ZEUS.GLOBAL_ACCOUNT
WHERE ACCOUNT_ID = :B2
AND DOMAIN = :B1
UNION ALL
SELECT ID,
GMT_MODIFIED,
MODIFIER,
GMT_CREATE,
CREATOR,
DOMAIN,
EMPLOYEE_NUMBER,
COMPANY_NAME,
HOMEPAGE_URL,
BACKGROUND,
CATEGORY_ID,
REMARK,
MEMBER_ID,
SALES_OWNER_ID,
ACCOUNT_ID,
IS_DELETED,
CUST_GRADE
FROM APOLLO_NIR.GLOBAL_ACCOUNT
WHERE ACCOUNT_ID = :B2
AND DOMAIN = :B1