mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
Oracle Parser支持Hint
git-svn-id: http://code.alibabatech.com/svn/druid/trunk@122 b9813039-fb51-4c41-a8b9-e21c2acb5095
This commit is contained in:
@@ -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)) {
|
||||
|
||||
+12
-1
@@ -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) {
|
||||
|
||||
+14
-5
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user