improved sql parser, support translate oracle to mysql

This commit is contained in:
wenshao
2014-11-19 10:23:43 +08:00
parent 0aa403bb4e
commit baad7dc724
10 changed files with 272 additions and 8 deletions
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -67,4 +68,8 @@ public class OracleSelect extends SQLSelect {
}
visitor.endVisit(this);
}
public String toString() {
return SQLUtils.toOracleString(this);
}
}
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause;
@@ -90,4 +91,7 @@ public class OracleSelectJoin extends SQLJoinTableSource implements OracleSelect
}
}
public String toString () {
return SQLUtils.toOracleString(this);
}
}
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLCommentHint;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause;
@@ -78,4 +79,8 @@ public class OracleSelectQueryBlock extends SQLSelectQueryBlock {
}
visitor.endVisit(this);
}
public String toString() {
return SQLUtils.toOracleString(this);
}
}
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause;
@@ -73,4 +74,7 @@ public class OracleSelectSubqueryTableSource extends SQLSubqueryTableSource impl
visitor.endVisit(this);
}
public String toString () {
return SQLUtils.toOracleString(this);
}
}
@@ -15,6 +15,7 @@
*/
package com.alibaba.druid.sql.dialect.oracle.ast.stmt;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.FlashbackQueryClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause;
@@ -109,4 +110,8 @@ public class OracleSelectTableReference extends SQLExprTableSource implements Or
buf.append(this.alias);
}
}
public String toString () {
return SQLUtils.toOracleString(this);
}
}
@@ -0,0 +1,145 @@
package com.alibaba.druid.sql.dialect.oracle.visitor;
import com.alibaba.druid.sql.ast.SQLExpr;
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.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
public class OracleToMySqlOutputVisitor extends OracleOutputVisitor {
public OracleToMySqlOutputVisitor(Appendable appender, boolean printPostSemi){
super(appender, printPostSemi);
}
public OracleToMySqlOutputVisitor(Appendable appender){
super(appender);
}
public boolean visit(OracleSelectQueryBlock x) {
boolean parentIsSelectStatment = false;
{
if (x.getParent() instanceof SQLSelect) {
SQLSelect select = (SQLSelect) x.getParent();
if (select.getParent() instanceof SQLSelectStatement) {
parentIsSelectStatment = true;
}
}
}
if (!parentIsSelectStatment) {
return super.visit(x);
}
if (x.getWhere() instanceof SQLBinaryOpExpr //
&& x.getFrom() instanceof SQLSubqueryTableSource //
) {
int rownum;
String ident;
SQLBinaryOpExpr where = (SQLBinaryOpExpr) x.getWhere();
if (where.getRight() instanceof SQLIntegerExpr && where.getLeft() instanceof SQLIdentifierExpr) {
rownum = ((SQLIntegerExpr) where.getRight()).getNumber().intValue();
ident = ((SQLIdentifierExpr) where.getLeft()).getName();
} else {
return super.visit(x);
}
SQLSelect select = ((SQLSubqueryTableSource) x.getFrom()).getSelect();
SQLSelectQueryBlock queryBlock = null;
SQLSelect subSelect = null;
SQLBinaryOpExpr subWhere = null;
boolean isSubQueryRowNumMapping = false;
if (select.getQuery() instanceof SQLSelectQueryBlock) {
queryBlock = (SQLSelectQueryBlock) select.getQuery();
if (queryBlock.getWhere() instanceof SQLBinaryOpExpr) {
subWhere = (SQLBinaryOpExpr) queryBlock.getWhere();
}
for (SQLSelectItem selectItem : queryBlock.getSelectList()) {
if (isRowNumber(selectItem.getExpr())) {
if (where.getLeft() instanceof SQLIdentifierExpr
&& ((SQLIdentifierExpr) where.getLeft()).getName().equals(selectItem.getAlias())) {
isSubQueryRowNumMapping = true;
}
}
}
SQLTableSource subTableSource = queryBlock.getFrom();
if (subTableSource instanceof SQLSubqueryTableSource) {
subSelect = ((SQLSubqueryTableSource) subTableSource).getSelect();
}
}
if ("ROWNUM".equalsIgnoreCase(ident)) {
SQLBinaryOperator op = where.getOperator();
Integer limit = null;
if (op == SQLBinaryOperator.LessThanOrEqual) {
limit = rownum;
} else if (op == SQLBinaryOperator.LessThan) {
limit = rownum - 1;
}
if (limit != null) {
select.accept(this);
println();
print("LIMIT ");
print(limit);
return false;
}
} else if (isSubQueryRowNumMapping) {
SQLBinaryOperator op = where.getOperator();
SQLBinaryOperator subOp = subWhere.getOperator();
if (isRowNumber(subWhere.getLeft()) //
&& subWhere.getRight() instanceof SQLIntegerExpr) {
int subRownum = ((SQLIntegerExpr) subWhere.getRight()).getNumber().intValue();
Integer offset = null;
if (op == SQLBinaryOperator.GreaterThanOrEqual) {
offset = rownum + 1;
} else if (op == SQLBinaryOperator.GreaterThan) {
offset = rownum;
}
if (offset != null) {
Integer limit = null;
if (subOp == SQLBinaryOperator.LessThanOrEqual) {
limit = subRownum - offset;
} else if (subOp == SQLBinaryOperator.LessThan) {
limit = subRownum - 1 - offset;
}
if (limit != null) {
subSelect.accept(this);
println();
print("LIMIT ");
print(offset);
print(", ");
print(limit);
return false;
}
}
}
}
}
return super.visit(x);
}
static boolean isRowNumber(SQLExpr expr) {
if (expr instanceof SQLIdentifierExpr) {
String lownerName = ((SQLIdentifierExpr) expr).getLowerName();
return "rownum".equals(lownerName);
}
return false;
}
}