Oracle Parser支持Hint

git-svn-id: http://code.alibabatech.com/svn/druid/trunk@122 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
wenshao
2011-05-18 14:46:41 +00:00
parent 7ff33b50ae
commit a67cb09f38
8 changed files with 203 additions and 29 deletions
@@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OracleSelect extends SQLSelect {
@@ -51,6 +52,22 @@ public class OracleSelect extends SQLSelect {
if (this.orderBy != null) this.orderBy.output(buf);
}
protected void accept0(SQLASTVisitor visitor) {
if (visitor instanceof OracleASTVisitor) {
accept0((OracleASTVisitor) visitor);
return;
}
if (visitor.visit(this)) {
acceptChild(visitor, this.query);
acceptChild(visitor, this.restriction);
acceptChild(visitor, this.orderBy);
acceptChild(visitor, this.forUpdate);
}
visitor.endVisit(this);
}
protected void accept0(OracleASTVisitor visitor) {
if (visitor.visit(this)) {
@@ -51,7 +51,18 @@ public class OracleSelectQueryBlock extends SQLSelectQueryBlock {
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((OracleASTVisitor) visitor);
if (visitor instanceof OracleASTVisitor) {
accept0((OracleASTVisitor) visitor);
return;
}
if (visitor.visit(this)) {
acceptChild(visitor, this.selectList);
acceptChild(visitor, this.from);
acceptChild(visitor, this.where);
acceptChild(visitor, this.groupBy);
}
visitor.endVisit(this);
}
protected void accept0(OracleASTVisitor visitor) {
@@ -378,7 +378,8 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
}
public boolean visit(OracleHint x) {
throw new UnsupportedOperationException();
print(x.getName());
return false;
}
public boolean visit(OracleInsertStatement x) {
@@ -655,12 +656,20 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS
public boolean visit(OracleSelectQueryBlock select) {
print("SELECT ");
if (SQLSetQuantifier.ALL == select.getDistionOption()) print("ALL ");
else if (SQLSetQuantifier.DISTINCT == select.getDistionOption()) print("DISTINCT ");
else if (SQLSetQuantifier.UNIQUE == select.getDistionOption()) {
if (SQLSetQuantifier.ALL == select.getDistionOption()) {
print("ALL ");
} else if (SQLSetQuantifier.DISTINCT == select.getDistionOption()) {
print("DISTINCT ");
} else if (SQLSetQuantifier.UNIQUE == select.getDistionOption()) {
print("UNIQUE ");
}
if (select.getHints().size() > 0) {
print("/*+");
printAndAccept(select.getHints(), ", ");
print("*/ ");
}
printAndAccept(select.getSelectList(), ", ");
println();
@@ -0,0 +1,99 @@
package com.alibaba.druid.sql.dialect.oracle.parser;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.Token;
public class OracleLexer extends Lexer {
public OracleLexer(char[] input, int inputLength, boolean skipComment){
super(input, inputLength, skipComment);
}
public OracleLexer(String input){
super(input);
}
public void scanComment() {
if (ch != '/') {
throw new IllegalStateException();
}
np = bp;
sp = 0;
scanChar();
sp++;
// /*+ */
if (ch == '*') {
scanChar();
sp++;
while (ch == ' ') {
scanChar();
sp++;
}
boolean isHint = false;
int startHintSp = sp + 1;
if (ch == '+') {
isHint = true;
scanChar();
sp++;
}
for (;;) {
if (ch == '*' && buf[bp + 1] == '/') {
sp += 2;
scanChar();
scanChar();
break;
}
scanChar();
sp++;
}
if (isHint) {
stringVal = new String(buf, np + startHintSp, (sp - startHintSp) - 2).trim();
token = Token.HINT;
} else {
stringVal = new String(buf, np, sp);
token = Token.MULTI_LINE_COMMENT;
}
return;
}
if (ch == '/') {
scanChar();
sp++;
for (;;) {
if (ch == '\r') {
if (buf[bp + 1] == '\n') {
sp += 2;
scanChar();
break;
}
sp++;
break;
}
if (ch == '\r') {
scanChar();
sp++;
break;
}
scanChar();
sp++;
}
stringVal = new String(buf, np + 1, sp);
token = Token.LINE_COMMENT;
return;
}
}
}
@@ -21,6 +21,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleHint;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectForUpdate;
@@ -129,9 +130,11 @@ public class OracleSelectParser extends SQLSelectParser {
OracleSelectQueryBlock queryBlock = new OracleSelectQueryBlock();
parseHints(queryBlock);
if (lexer.token() == (Token.DISTINCT)) queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
else if (lexer.token() == (Token.UNIQUE)) queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);
else if (lexer.token() == (Token.ALL)) {
if (lexer.token() == (Token.DISTINCT)) {
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
} else if (lexer.token() == (Token.UNIQUE)) {
queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);
} else if (lexer.token() == (Token.ALL)) {
queryBlock.setDistionOption(SQLSetQuantifier.ALL);
}
@@ -484,6 +487,9 @@ public class OracleSelectParser extends SQLSelectParser {
}
private void parseHints(OracleSelectQueryBlock queryBlock) {
if (lexer.token() == Token.HINT) throw new ParserException("TODO");
if (lexer.token() == Token.HINT) {
queryBlock.getHints().add(new OracleHint(lexer.stringVal()));
lexer.nextToken();
}
}
}
@@ -30,7 +30,8 @@ import com.alibaba.druid.sql.parser.Token;
public class OracleStatementParser extends SQLStatementParser {
public OracleStatementParser(String sql){
super(sql);
super(new OracleLexer(sql));
this.lexer.nextToken();
}
public OracleStatementParser(Lexer lexer){
@@ -97,7 +98,7 @@ public class OracleStatementParser extends SQLStatementParser {
throw new ParserException("TODO");
}
throw new ParserException("TODO");
throw new ParserException("TODO : " + lexer.token() + " " + lexer.stringVal());
}
}
@@ -0,0 +1,23 @@
package com.alibaba.druid.sql.oracle.bvt;
import java.util.List;
import junit.framework.TestCase;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
public class OracleSampleTest1 extends TestCase {
public void test_0 () throws Exception {
}
private void output(List<SQLStatement> stmtList) {
for (SQLStatement stmt : stmtList) {
stmt.accept(new MySqlOutputVisitor(System.out));
System.out.println(";");
System.out.println();
}
}
}
@@ -20,30 +20,38 @@ import java.util.List;
import junit.framework.TestCase;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
import com.alibaba.druid.sql.dialect.oracle.ast.visitor.OracleOutputVisitor;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleSelectParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
public class OracleSelectParserTest extends TestCase {
public void test_select() throws Exception {
String sql = "SELECT TRIM('xxxxxxx') FROM `T_USER` WHERE FID >= 100 AND ROWNUM < 10";
SQLSelectParser parser = new OracleSelectParser(sql);
SQLSelect select = parser.select();
public void f_test_select() throws Exception {
String sql = "SELECT last_name, department_id FROM employees WHERE department_id = (SELECT department_id FROM employees WHERE last_name = 'Lorentz') ORDER BY last_name, department_id;";
select.accept(new OracleOutputVisitor(System.out));
System.out.println();
System.out.println(select);
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
output(statementList);
}
public void test_hinits() throws Exception {
String sql = "SELECT /*+FIRST_ROWS*/ * FROM T";
OracleStatementParser parser = new OracleStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
output(statementList);
}
private void output(List<SQLStatement> stmtList) {
for (SQLStatement stmt : stmtList) {
stmt.accept(new MySqlOutputVisitor(System.out));
System.out.println(";");
System.out.println();
}
}
StringBuilder out = new StringBuilder();
OracleOutputVisitor visitor = new OracleOutputVisitor(out);
for (SQLStatement stmt : stmtList) {
stmt.accept(visitor);
visitor.println();
}
System.out.println(out.toString());
}
}