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.regex.Matcher; import java.util.regex.Pattern; 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.SQLSelectQuery; 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.OracleSelect; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.util.JdbcConstants; /** * 由于druid的db2解析部分不够完整,且使用oracle的解析基本能满足需求 * 所以基于oracle的扩展 */ public class DruidSelectDb2Parser extends DruidSelectOracleParser { 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(); 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; //为了继续解出order by 等 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); } } private static final Pattern pattern = Pattern.compile("FETCH(?:\\s)+FIRST(?:\\s)+(\\d+)(?:\\s)+ROWS(?:\\s)+ONLY",Pattern.CASE_INSENSITIVE); protected void parseNativeSql(SQLStatement stmt,RouteResultset rrs, OracleSelectQueryBlock mysqlSelectQuery,SchemaConfig schema) { Matcher matcher = pattern.matcher(getCtx().getSql()); while (matcher.find()) { String row= matcher.group(1); rrs.setLimitStart(0); rrs.setLimitSize(Integer.parseInt(row)); } } protected String getCurentDbType() { return JdbcConstants.DB2; } }