package io.mycat.route.parser.druid.impl; import io.mycat.route.RouteResultset; import io.mycat.server.config.node.SchemaConfig; import java.util.List; import java.util.Map; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.SQLStatement; import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; 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.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; import com.alibaba.druid.util.JdbcConstants; public class DruidSelectOracleParser extends DruidSelectParser { @Override public void statementParse(SchemaConfig schema, RouteResultset rrs, SQLStatement stmt) { SQLSelectStatement selectStmt = (SQLSelectStatement)stmt; SQLSelectQuery sqlSelectQuery = selectStmt.getSelect().getQuery(); //从mysql解析过来 if(sqlSelectQuery instanceof MySqlSelectQueryBlock) { MySqlSelectQueryBlock mysqlSelectQuery = (MySqlSelectQueryBlock)selectStmt.getSelect().getQuery(); Limit limit=mysqlSelectQuery.getLimit(); if(limit==null) { //使用oracle的解析,否则会有部分oracle语法识别错误 OracleStatementParser oracleParser = new OracleStatementParser(getCtx().getSql()); SQLSelectStatement oracleStmt = (SQLSelectStatement) oracleParser.parseStatement(); selectStmt= oracleStmt; SQLSelectQuery oracleSqlSelectQuery = oracleStmt.getSelect().getQuery(); if(oracleSqlSelectQuery instanceof OracleSelectQueryBlock) { parseNativePageSql(oracleStmt, rrs, (OracleSelectQueryBlock) oracleSqlSelectQuery, schema); } } if(isNeedParseOrderAgg) { parseOrderAggGroupMysql(schema, selectStmt,rrs, mysqlSelectQuery); //更改canRunInReadDB属性 if ((mysqlSelectQuery.isForUpdate() || mysqlSelectQuery.isLockInShareMode()) && !rrs.isAutocommit()) { rrs.setCanRunInReadDB(false); } } } } protected void parseOrderAggGroupOracle(SQLStatement stmt, RouteResultset rrs, OracleSelectQueryBlock mysqlSelectQuery, SchemaConfig schema) { Map<String, String> aliaColumns = parseAggGroupCommon(schema, stmt,rrs, mysqlSelectQuery); OracleSelect oracleSelect= (OracleSelect) mysqlSelectQuery.getParent(); if(oracleSelect.getOrderBy() != null) { List<SQLSelectOrderByItem> orderByItems = oracleSelect.getOrderBy().getItems(); rrs.setOrderByCols(buildOrderByCols(orderByItems,aliaColumns)); } isNeedParseOrderAgg=false; } protected void parseNativePageSql(SQLStatement stmt, RouteResultset rrs, OracleSelectQueryBlock mysqlSelectQuery, SchemaConfig schema) { //第一层子查询 SQLExpr where= mysqlSelectQuery.getWhere(); SQLTableSource from= mysqlSelectQuery.getFrom(); if(where instanceof SQLBinaryOpExpr &&from instanceof SQLSubqueryTableSource) { SQLBinaryOpExpr one= (SQLBinaryOpExpr) where; SQLExpr left=one.getLeft(); SQLBinaryOperator operator =one.getOperator(); //解析只有一层rownum限制大小 if(one.getRight() instanceof SQLIntegerExpr &&"rownum".equalsIgnoreCase(left.toString()) &&(operator==SQLBinaryOperator.LessThanOrEqual||operator==SQLBinaryOperator.LessThan)) { SQLIntegerExpr right = (SQLIntegerExpr) one.getRight(); int firstrownum = right.getNumber().intValue(); if (operator == SQLBinaryOperator.LessThan&&firstrownum!=0) firstrownum = firstrownum - 1; SQLSelectQuery subSelect = ((SQLSubqueryTableSource) from).getSelect().getQuery(); if (subSelect instanceof OracleSelectQueryBlock) { rrs.setLimitStart(0); rrs.setLimitSize(firstrownum); mysqlSelectQuery = (OracleSelectQueryBlock) subSelect; //为了继续解出order by 等 parseOrderAggGroupOracle(stmt,rrs, mysqlSelectQuery, schema); isNeedParseOrderAgg=false; } } else //解析oracle三层嵌套分页 if(one.getRight() instanceof SQLIntegerExpr &&!"rownum".equalsIgnoreCase(left.toString()) &&(operator==SQLBinaryOperator.GreaterThan||operator==SQLBinaryOperator.GreaterThanOrEqual)) { parseThreeLevelPageSql(stmt, rrs, schema, (SQLSubqueryTableSource) from, one, operator); } else //解析oracle rownumber over分页 { SQLSelectQuery subSelect = ((SQLSubqueryTableSource) from).getSelect().getQuery(); SQLOrderBy orderBy=null; if (subSelect instanceof OracleSelectQueryBlock) { boolean hasRowNumber=false; OracleSelectQueryBlock subSelectOracle = (OracleSelectQueryBlock) subSelect; List<SQLSelectItem> sqlSelectItems= subSelectOracle.getSelectList(); for (SQLSelectItem sqlSelectItem : sqlSelectItems) { SQLExpr sqlExpr= sqlSelectItem.getExpr() ; if(sqlExpr instanceof SQLAggregateExpr ) { SQLAggregateExpr agg= (SQLAggregateExpr) sqlExpr; if("row_number".equalsIgnoreCase(agg.getMethodName())&&agg.getOver()!=null) { hasRowNumber=true; orderBy= agg.getOver().getOrderBy(); } } } if(hasRowNumber) { if((operator==SQLBinaryOperator.LessThan||operator==SQLBinaryOperator.LessThanOrEqual) && one.getRight() instanceof SQLIntegerExpr ) { SQLIntegerExpr right = (SQLIntegerExpr) one.getRight(); int firstrownum = right.getNumber().intValue(); if (operator == SQLBinaryOperator.LessThan&&firstrownum!=0) firstrownum = firstrownum - 1; if (subSelect instanceof OracleSelectQueryBlock) { rrs.setLimitStart(0); rrs.setLimitSize(firstrownum); mysqlSelectQuery = (OracleSelectQueryBlock) subSelect; if(orderBy!=null) { OracleSelect oracleSelect= (OracleSelect) subSelect.getParent(); oracleSelect.setOrderBy(orderBy); } parseOrderAggGroupOracle(stmt,rrs, mysqlSelectQuery, schema); isNeedParseOrderAgg=false; } } else if(operator==SQLBinaryOperator.BooleanAnd && left instanceof SQLBinaryOpExpr&&one.getRight() instanceof SQLBinaryOpExpr ) { SQLBinaryOpExpr leftE= (SQLBinaryOpExpr) left; SQLBinaryOpExpr rightE= (SQLBinaryOpExpr) one.getRight(); SQLBinaryOpExpr small=null ; SQLBinaryOpExpr larger=null ; int firstrownum =0; int lastrownum =0; if(leftE.getRight() instanceof SQLIntegerExpr&&(leftE.getOperator()==SQLBinaryOperator.GreaterThan||leftE.getOperator()==SQLBinaryOperator.GreaterThanOrEqual)) { small=leftE; firstrownum=((SQLIntegerExpr) leftE.getRight()).getNumber().intValue(); if(leftE.getOperator()==SQLBinaryOperator.GreaterThanOrEqual &&firstrownum!=0) firstrownum = firstrownum - 1; } else if(leftE.getRight() instanceof SQLIntegerExpr&&(leftE.getOperator()==SQLBinaryOperator.LessThan||leftE.getOperator()==SQLBinaryOperator.LessThanOrEqual)) { larger=leftE; lastrownum=((SQLIntegerExpr) leftE.getRight()).getNumber().intValue(); if(leftE.getOperator()==SQLBinaryOperator.LessThan&&lastrownum!=0) lastrownum = lastrownum - 1; } if(rightE.getRight() instanceof SQLIntegerExpr&&(rightE.getOperator()==SQLBinaryOperator.GreaterThan||rightE.getOperator()==SQLBinaryOperator.GreaterThanOrEqual)) { small=rightE; firstrownum=((SQLIntegerExpr) rightE.getRight()).getNumber().intValue(); if(rightE.getOperator()==SQLBinaryOperator.GreaterThanOrEqual&&firstrownum!=0) firstrownum = firstrownum - 1; } else if(rightE.getRight() instanceof SQLIntegerExpr&&(rightE.getOperator()==SQLBinaryOperator.LessThan||rightE.getOperator()==SQLBinaryOperator.LessThanOrEqual)) { larger=rightE; lastrownum=((SQLIntegerExpr) rightE.getRight()).getNumber().intValue(); if(rightE.getOperator()==SQLBinaryOperator.LessThan&&lastrownum!=0) lastrownum = lastrownum - 1; } if(small!=null&&larger!=null) { setLimitIFChange(stmt, rrs, schema, small, firstrownum, lastrownum); if(orderBy!=null) { OracleSelect oracleSelect= (OracleSelect) subSelect.getParent(); oracleSelect.setOrderBy(orderBy); } parseOrderAggGroupOracle(stmt,rrs, (OracleSelectQueryBlock) subSelect, schema); isNeedParseOrderAgg=false; } } } else { parseNativeSql(stmt,rrs,mysqlSelectQuery,schema); } } } } else { parseNativeSql(stmt,rrs,mysqlSelectQuery,schema); } if(isNeedParseOrderAgg) { parseOrderAggGroupOracle(stmt,rrs, mysqlSelectQuery, schema); } } protected String getCurentDbType() { return JdbcConstants.ORACLE; } protected void parseNativeSql(SQLStatement stmt,RouteResultset rrs, OracleSelectQueryBlock mysqlSelectQuery,SchemaConfig schema) { //解析分页以外的语法 } private void parseThreeLevelPageSql(SQLStatement stmt, RouteResultset rrs, SchemaConfig schema, SQLSubqueryTableSource from, SQLBinaryOpExpr one, SQLBinaryOperator operator) { SQLIntegerExpr right = (SQLIntegerExpr) one.getRight(); int firstrownum = right.getNumber().intValue(); if (operator == SQLBinaryOperator.GreaterThanOrEqual&&firstrownum!=0) firstrownum = firstrownum - 1; SQLSelectQuery subSelect = from.getSelect().getQuery(); if (subSelect instanceof OracleSelectQueryBlock) { //第二层子查询 OracleSelectQueryBlock twoSubSelect = (OracleSelectQueryBlock) subSelect; if (twoSubSelect.getWhere() instanceof SQLBinaryOpExpr && twoSubSelect.getFrom() instanceof SQLSubqueryTableSource) { SQLBinaryOpExpr twoWhere = (SQLBinaryOpExpr) twoSubSelect.getWhere(); boolean isRowNum = "rownum".equalsIgnoreCase(twoWhere.getLeft().toString()); boolean isLess = twoWhere.getOperator() == SQLBinaryOperator.LessThanOrEqual || twoWhere.getOperator() == SQLBinaryOperator.LessThan; if (isRowNum && twoWhere.getRight() instanceof SQLIntegerExpr && isLess) { int lastrownum = ((SQLIntegerExpr) twoWhere.getRight()).getNumber().intValue(); if (operator == SQLBinaryOperator.LessThan&&lastrownum!=0) lastrownum = lastrownum - 1; SQLSelectQuery finalQuery = ((SQLSubqueryTableSource) twoSubSelect.getFrom()).getSelect().getQuery(); if (finalQuery instanceof OracleSelectQueryBlock) { setLimitIFChange(stmt, rrs, schema, one, firstrownum, lastrownum); parseOrderAggGroupOracle(stmt,rrs, (OracleSelectQueryBlock) finalQuery, schema); isNeedParseOrderAgg=false; } } } } } }