package com.qmth.qrzk.repository.common.base;

public class Dialect {
	private static final String SQL_END_DELIMITER = ";";

	public static String getLimitString(String dbName, String sql, int offset,int limit) {
		dbName = dbName.toLowerCase();
		String limitString = sql;
		if (dbName.contains("mysql")) {
			limitString = getMysqlLimitString(sql, offset, limit);
		} else if (dbName.contains("microsoft sql server")) {
			limitString = getMssqlLimitString(sql, offset, limit);
		} else if (dbName.contains("oracle")) {
			limitString = getOracleLimitString(sql, offset, limit);
		} else {
			throw new RuntimeException("当前分页查询功能不支持此数据库：" + dbName);
		}
		return limitString;
	}

	private static String getMysqlLimitString(String sql, int offset, int limit) {
		sql = trim(sql);
		StringBuffer sb = new StringBuffer(sql.length() + 20);
		sb.append(sql);
		if (offset > 0) {
			sb.append(" limit ").append(offset).append(',').append(limit);
		} else {
			sb.append(" limit ").append(limit);
		}
		return sb.toString();
	}

	private static String getOracleLimitString(String sql, int offset, int limit) {
		sql = trim(sql);
		StringBuffer sb = new StringBuffer(sql.length() + 100);
		if (offset > 0) {
			sb.append("select * from ( select row_.*, rownum rownum_ from ( ")
					.append(sql).append(" ) row_ where rownum <= ")
					.append(offset + limit).append(") where rownum_ > ")
					.append(offset);
		} else {
			sb.append("select * from ( ").append(sql)
					.append(" ) where rownum <= ").append(limit);
		}
		return sb.toString();
	}

	private static String getMssqlLimitString(String sql, int offset, int limit) {
		int orderByIndex = sql.toLowerCase().lastIndexOf("order by");
		if (orderByIndex <= 0) {
	    	throw new UnsupportedOperationException("must specify 'order by' statement to support limit operation with offset in sql server 2005");  
	    }
		String sqlOrderBy = sql.substring(orderByIndex + 8);
		String sqlRemoveOrderBy = sql.substring(0, orderByIndex);
		int insertPoint = getSqlAfterSelectInsertPoint(sql);
		
		return new StringBuffer(sql.length() + 100).append("with tempPagination as(").append(sqlRemoveOrderBy).insert(
	    		insertPoint + 23, " ROW_NUMBER() OVER(ORDER BY " + sqlOrderBy + ") as RowNumber,").append(
	    				") select * from tempPagination where RowNumber between " + (offset + 1) + " and " + (offset + limit)).toString();
	}
	
	private static int getSqlAfterSelectInsertPoint(String sql) {
		int selectIndex = sql.toLowerCase().indexOf("select");
		int selectDistinctIndex = sql.toLowerCase().indexOf("select distinct");
		return selectIndex + (selectDistinctIndex == selectIndex ? 15 : 6);
	} 

	private static String trim(String sql) {
		sql = sql.trim();
		if (sql.endsWith(SQL_END_DELIMITER)) {
			sql = sql.substring(0,sql.length() - 1 - SQL_END_DELIMITER.length());
		}
		return sql;
	}
	
	public static void main(String[] args) {
		String sql = "select id,course_id from zk_question where 1=1 order by id";
		String newSql = getMssqlLimitString(sql,0,3);
		System.out.println(newSql);
	}
}
