mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
增强Parser
git-svn-id: http://code.alibabatech.com/svn/druid/trunk@132 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
+5
-2
@@ -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
|
||||
Reference in New Issue
Block a user