package io.mycat.route.util; import java.util.List; import com.alibaba.druid.sql.PagerUtils; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExpr; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.ast.SQLOver; import com.alibaba.druid.sql.ast.expr.SQLAggregateExpr; import com.alibaba.druid.sql.ast.expr.SQLAllColumnExpr; 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.SQLNumberExpr; import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectQuery; 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.db2.ast.stmt.DB2SelectQueryBlock; import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.parser.PGSQLStatementParser; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; import com.alibaba.druid.util.JdbcConstants; /** * Created by magicdoom on 2015/3/15. */ public class PageSQLUtil { public static String convertLimitToNativePageSql(String dbType, String sql, int offset, int count) { if (JdbcConstants.ORACLE.equalsIgnoreCase(dbType)) { OracleStatementParser oracleParser = new OracleStatementParser(sql); SQLSelectStatement oracleStmt = (SQLSelectStatement) oracleParser.parseStatement(); return PagerUtils.limit(oracleStmt.getSelect(), JdbcConstants.ORACLE, offset, count); } else if (JdbcConstants.SQL_SERVER.equalsIgnoreCase(dbType)) { SQLServerStatementParser oracleParser = new SQLServerStatementParser(sql); SQLSelectStatement sqlserverStmt = (SQLSelectStatement) oracleParser.parseStatement(); SQLSelect select = sqlserverStmt.getSelect(); SQLOrderBy orderBy= select.getOrderBy() ; if(orderBy==null) { SQLSelectQuery sqlSelectQuery= select.getQuery(); if(sqlSelectQuery instanceof SQLServerSelectQueryBlock) { SQLServerSelectQueryBlock sqlServerSelectQueryBlock= (SQLServerSelectQueryBlock) sqlSelectQuery; SQLTableSource from= sqlServerSelectQueryBlock.getFrom(); if("limit".equalsIgnoreCase(from.getAlias())) { from.setAlias(null); } } SQLOrderBy newOrderBy=new SQLOrderBy(new SQLIdentifierExpr("(select 0)")); select.setOrderBy(newOrderBy); } return PagerUtils.limit(select, JdbcConstants.SQL_SERVER, offset, count) ; } else if (JdbcConstants.DB2.equalsIgnoreCase(dbType)) { DB2StatementParser db2Parser = new DB2StatementParser(sql); SQLSelectStatement db2Stmt = (SQLSelectStatement) db2Parser.parseStatement(); return limitDB2(db2Stmt.getSelect(), JdbcConstants.DB2, offset, count); } else if (JdbcConstants.POSTGRESQL.equalsIgnoreCase(dbType)) { PGSQLStatementParser pgParser = new PGSQLStatementParser(sql); SQLSelectStatement pgStmt = (SQLSelectStatement) pgParser.parseStatement(); SQLSelect select = pgStmt.getSelect(); SQLSelectQuery query= select.getQuery(); if(query instanceof PGSelectQueryBlock) { PGSelectQueryBlock pgSelectQueryBlock= (PGSelectQueryBlock) query; pgSelectQueryBlock.setLimit(null); pgSelectQueryBlock.setOffset(null); } return PagerUtils.limit(select, JdbcConstants.POSTGRESQL, offset, count); } else if (JdbcConstants.MYSQL.equalsIgnoreCase(dbType)) { MySqlStatementParser pgParser = new MySqlStatementParser(sql); SQLSelectStatement pgStmt = (SQLSelectStatement) pgParser.parseStatement(); SQLSelect select = pgStmt.getSelect(); SQLSelectQuery query= select.getQuery(); if(query instanceof MySqlSelectQueryBlock) { MySqlSelectQueryBlock pgSelectQueryBlock= (MySqlSelectQueryBlock) query; pgSelectQueryBlock.setLimit(null); } return PagerUtils.limit(select, JdbcConstants.MYSQL, offset, count); } return sql; } private static String limitDB2(SQLSelect select, String dbType, int offset, int count) { SQLSelectQuery query = select.getQuery(); SQLBinaryOpExpr gt = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // SQLBinaryOperator.GreaterThan, // new SQLNumberExpr(offset), // JdbcConstants.DB2); SQLBinaryOpExpr lteq = new SQLBinaryOpExpr(new SQLIdentifierExpr("ROWNUM"), // SQLBinaryOperator.LessThanOrEqual, // new SQLNumberExpr(count + offset), // JdbcConstants.DB2); SQLBinaryOpExpr pageCondition = new SQLBinaryOpExpr(gt, SQLBinaryOperator.BooleanAnd, lteq, JdbcConstants.DB2); if (query instanceof SQLSelectQueryBlock) { DB2SelectQueryBlock queryBlock = (DB2SelectQueryBlock) query; List<SQLSelectItem> selectItemList = queryBlock.getSelectList(); for (int i = 0; i < selectItemList.size(); i++) { SQLSelectItem sqlSelectItem = selectItemList.get(i); SQLExpr expr = sqlSelectItem.getExpr(); String alias = sqlSelectItem.getAlias(); if (expr instanceof SQLAllColumnExpr && alias == null) { //未加别名会报语法错误 sqlSelectItem.setExpr(new SQLPropertyExpr(new SQLIdentifierExpr("XXYY"), "*")); queryBlock.getFrom().setAlias("XXYY"); } } // 此处生成order by的顺序不对 // if (offset <= 0) { // queryBlock.setFirst(new SQLNumberExpr(count)); // return SQLUtils.toSQLString(select, dbType); // } SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER"); SQLOrderBy orderBy = select.getOrderBy(); aggregateExpr.setOver(new SQLOver(orderBy)); select.setOrderBy(null); queryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock(); countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); countQueryBlock.setWhere(pageCondition); return SQLUtils.toSQLString(countQueryBlock, dbType); } DB2SelectQueryBlock countQueryBlock = new DB2SelectQueryBlock(); countQueryBlock.getSelectList().add(new SQLSelectItem(new SQLPropertyExpr(new SQLIdentifierExpr("XX"), "*"))); SQLAggregateExpr aggregateExpr = new SQLAggregateExpr("ROW_NUMBER"); SQLOrderBy orderBy = select.getOrderBy(); aggregateExpr.setOver(new SQLOver(orderBy)); select.setOrderBy(null); countQueryBlock.getSelectList().add(new SQLSelectItem(aggregateExpr, "ROWNUM")); countQueryBlock.setFrom(new SQLSubqueryTableSource(select, "XX")); if (offset <= 0) { return SQLUtils.toSQLString(countQueryBlock, dbType); } DB2SelectQueryBlock offsetQueryBlock = new DB2SelectQueryBlock(); offsetQueryBlock.getSelectList().add(new SQLSelectItem(new SQLAllColumnExpr())); offsetQueryBlock.setFrom(new SQLSubqueryTableSource(new SQLSelect(countQueryBlock), "XXX")); offsetQueryBlock.setWhere(pageCondition); return SQLUtils.toSQLString(offsetQueryBlock, dbType); } }