Skip to content

Commit

Permalink
添加oracle和sql server的分页语句
Browse files Browse the repository at this point in the history
  • Loading branch information
tian-junwei committed Aug 18, 2016
1 parent e742378 commit fe46bcb
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 12 deletions.
45 changes: 42 additions & 3 deletions src/main/java/com/tianjunwei/page/dialect/OracleDialect.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.tianjunwei.page.dialect;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.RowBounds;

Expand All @@ -11,7 +14,13 @@ public OracleDialect(MappedStatement mappedStatement,
}

/**
*
* <blockquote><pre>
* 参数:sql = " select * from table order by i_id asc"; limit=10; offset =1;
* 结果:return "select * from ( select row_.*, rownum rownum_ from ( select * from table order by i_id asc ) row_ ) where rownum_ <=11 and rownum_ > 1";
* 或者
* 参数:sql = " select * from table order by i_id asc"; limit=10; offset =0;
* 结果:return "select * from ( select * from table order by i_id asc ) where rownum <= 10";
* </blockquote></pre>
* @param sql
* @param offsetName
* @param offset
Expand All @@ -22,8 +31,38 @@ public OracleDialect(MappedStatement mappedStatement,
*/
@Override
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
// TODO Auto-generated method stub
return null;

sql = sql.trim();
boolean isForUpdate = false;
Pattern p = Pattern.compile("\t|\r|\n");
Matcher m = p.matcher(sql);
sql = m.replaceAll(" ");
sql = sql.replaceAll(" +", " ");

if ( sql.toLowerCase().endsWith(" for update") ) {
sql = sql.substring( 0, sql.length()-11 );
isForUpdate = true;
}
StringBuffer pagingSelect = new StringBuffer( sql.length()+100 );
if (offset > 0) {
pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
}else {
pagingSelect.append("select * from ( ");
}
pagingSelect.append(sql);
if (offset > 0) {
pagingSelect.append(" ) row_ ) where rownum_ <= ? and rownum_ > ?");
setPageParameter("__offsetEnd",offset+limit,Integer.class);
setPageParameter(offsetName,offset,Integer.class);
}else {
pagingSelect.append(" ) where rownum <= ?");
setPageParameter(limitName,limit,Integer.class);
}
if ( isForUpdate ) {
pagingSelect.append( " for update" );
}

return pagingSelect.toString();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ public Sqlserver2005Dialect(MappedStatement mappedStatement,
}

/**
*
* <blockquote><pre>
* 参数:sql = " select * from table order by i_id asc"; limit=10; offset =1;
* 结果:return "WITH query AS (SELECT TOP 100 PERCENT ROW_NUMBER() OVER (order by i_id asc) as __row_number__, * from table order by i_id asc) SELECT * FROM query WHERE __row_number__ > 1 AND __row_number__ <= 11 ORDER BY __row_number__";
* 或者
* 参数:sql = " select * from table order by i_id asc"; limit=10; offset =0;
* 结果:return "WITH query AS (SELECT TOP 100 PERCENT ROW_NUMBER() OVER (order by i_id asc) as __row_number__, * from table order by i_id asc) SELECT * FROM query WHERE __row_number__ > 0 AND __row_number__ <= 10 ORDER BY __row_number__";
* </blockquote></pre>
* @param sql
* @param offsetName
* @param offset
Expand All @@ -22,8 +28,48 @@ public Sqlserver2005Dialect(MappedStatement mappedStatement,
*/
@Override
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
// TODO Auto-generated method stub
return null;
StringBuffer pagingBuilder = new StringBuffer();
String orderby = getOrderByPart(sql);
String distinctStr = "";
String loweredString = sql.toLowerCase();
String sqlPartString = sql;
if (loweredString.trim().startsWith("select")) {
int index = 6;
if (loweredString.startsWith("select distinct")) {
distinctStr = "DISTINCT ";
index = 15;
}
sqlPartString = sqlPartString.substring(index);
}
pagingBuilder.append(sqlPartString);
// if no ORDER BY is specified use fake ORDER BY field to avoid errors
if (orderby == null || orderby.length() == 0) {
orderby = "ORDER BY CURRENT_TIMESTAMP";
}
StringBuffer result = new StringBuffer();
result.append("WITH query AS (SELECT ")
.append(distinctStr)
.append("TOP 100 PERCENT ")
.append(" ROW_NUMBER() OVER (")
.append(orderby)
.append(") as __row_number__, ")
.append(pagingBuilder)
.append(") SELECT * FROM query WHERE __row_number__ > ? AND __row_number__ <= ?")
.append(" ORDER BY __row_number__");
setPageParameter(offsetName,offset,Integer.class);
setPageParameter("__offsetEnd",offset+limit,Integer.class);
return result.toString();
}
static String getOrderByPart(String sql) {
String loweredString = sql.toLowerCase();
int orderByIndex = loweredString.indexOf("order by");
if (orderByIndex != -1) {
// if we find a new "order by" then we need to ignore
// the previous one since it was probably used for a subquery
return sql.substring(orderByIndex);
} else {
return "";
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,24 @@
import org.apache.ibatis.session.RowBounds;

public class Sqlserver2008Dialect extends Dialect{

private static final String ORDERBY = "order by";
private static final String SELECT = "select";
private static final String SELECT_DISTINCT = "select distinct";

public Sqlserver2008Dialect(MappedStatement mappedStatement,
Object parameterObject, RowBounds pageBounds) {
super(mappedStatement, parameterObject, pageBounds);
}

/**
*
* <blockquote><pre>
* 参数:sql = " select * from table order by i_id asc"; limit=10; offset =1;
* 结果:return "WITH page_query AS (select ROW_NUMBER() OVER (order by i_id asc) as row_nr__, * from table ) SELECT * FROM page_query WHERE row_nr__ between 2 and 11";
* 或者
* 参数:sql = " select * from table order by i_id asc"; limit=10; offset =0;
* 结果:return "select top 10 * from table order by i_id asc ";
* </blockquote></pre>
* @param sql
* @param offsetName
* @param offset
Expand All @@ -22,8 +32,38 @@ public Sqlserver2008Dialect(MappedStatement mappedStatement,
*/
@Override
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
// TODO Auto-generated method stub
return null;
String newsql="";
if(offset == 0){
newsql= new StringBuffer( sql.length() + 8 )
.append( sql )
.insert( getAfterSelectInsertPoint( sql ), " top " + limit )
.toString();
return newsql;
}else{
int endIndex = offset + limit;
StringBuilder sb = new StringBuilder(sql.replaceAll("\\s{2,}", " ").toLowerCase().trim());
if(sb.indexOf(SELECT_DISTINCT)==sb.indexOf(SELECT)){
throw new UnsupportedOperationException(getClass().getName()+".getLimitString(String queryString, int limit, int offset) unsupport key DISTINCT in query");
}
int orderByIndex = sb.indexOf(ORDERBY);
//判断queryString中是否有order by 若没有则创建。
CharSequence orderby = orderByIndex > 0 ? sb.subSequence(orderByIndex, sb.length()) : " order by CURRENT_TIMESTAMP";
if(orderByIndex > 0){
//原句中有orderby时将其提取至Over()内
sb.delete(orderByIndex, orderByIndex + orderby.length());
}
int selectEndIndex = sb.indexOf(SELECT) + SELECT.length();
//构建分页sql
sb.insert(selectEndIndex, " ROW_NUMBER() OVER (" + orderby + ") as row_nr__,");
sb.insert(0, "WITH page_query AS (").append(") SELECT * FROM page_query ");
sb.append("WHERE row_nr__ between ").append(offset+1).append(" and ").append(endIndex);
return sb.toString();
}
}
static int getAfterSelectInsertPoint(String sql) {
int selectIndex = sql.toLowerCase().indexOf( "select" );
final int selectDistinctIndex = sql.toLowerCase().indexOf( "select distinct" );
return selectIndex + ( selectDistinctIndex == selectIndex ? 15 : 6 );
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,13 @@ public Sqlserver2012Dialect(MappedStatement mappedStatement,
}

/**
*
* <blockquote><pre>
* 参数:sql = " select * from table order by i_id asc"; limit=10; offset =1;
* 结果:return "select * from table order by i_id asc offset 1 row fetch next 10 rows only";
* 或者
* 参数:sql = " select * from table order by i_id asc"; limit=10; offset =0;
* 结果:return "select * from table order by i_id asc offset 0 row fetch next 10 rows only";
* </blockquote></pre>
* @param sql
* @param offsetName
* @param offset
Expand All @@ -22,8 +28,13 @@ public Sqlserver2012Dialect(MappedStatement mappedStatement,
*/
@Override
protected String getLimitString(String sql, String offsetName, int offset, String limitName, int limit) {
// TODO Auto-generated method stub
return null;
sql = new StringBuilder(sql)
.append(" offset ")
.append(offset)
.append(" row fetch next ")
.append(limit)
.append(" rows only").toString();
return sql;
}

}

0 comments on commit fe46bcb

Please sign in to comment.