SQLServer2005Dialect.java 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. /**
  2. * Copyright &copy; 2015-2020 <a href="http://www.jeeplus.org/">JeePlus</a> All rights reserved.
  3. */
  4. package com.jeeplus.common.persistence.dialect.db;
  5. import org.apache.commons.lang3.StringUtils;
  6. import com.jeeplus.common.persistence.dialect.Dialect;
  7. /**
  8. * Sql 2005的方言实现
  9. * @author poplar.yfyang
  10. * @version 1.0 2010-10-10 下午12:31
  11. * @since JDK 1.5
  12. */
  13. public class SQLServer2005Dialect implements Dialect {
  14. @Override
  15. public boolean supportsLimit() {
  16. return true;
  17. }
  18. @Override
  19. public String getLimitString(String sql, int offset, int limit) {
  20. return getLimitString(sql, offset,
  21. limit, Integer.toString(limit));
  22. }
  23. /**
  24. * Add a LIMIT clause to the given SQL SELECT
  25. * <p/>
  26. * The LIMIT SQL will look like:
  27. * <p/>
  28. * WITH query AS
  29. * (SELECT TOP 100 percent ROW_NUMBER() OVER (ORDER BY CURRENT_TIMESTAMP) as __row_number__, * from table_name)
  30. * SELECT *
  31. * FROM query
  32. * WHERE __row_number__ BETWEEN :offset and :lastRows
  33. * ORDER BY __row_number__
  34. *
  35. * @param querySqlString The SQL statement to base the limit query off of.
  36. * @param offset Offset of the first row to be returned by the query (zero-based)
  37. * @param limit Maximum number of rows to be returned by the query
  38. * @param limitPlaceholder limitPlaceholder
  39. * @return A new SQL statement with the LIMIT clause applied.
  40. */
  41. private String getLimitString(String querySqlString, int offset, int limit, String limitPlaceholder) {
  42. StringBuilder pagingBuilder = new StringBuilder();
  43. String orderby = getOrderByPart(querySqlString);
  44. String distinctStr = "";
  45. String loweredString = querySqlString.toLowerCase();
  46. String sqlPartString = querySqlString;
  47. if (loweredString.trim().startsWith("select")) {
  48. int index = 6;
  49. if (loweredString.startsWith("select distinct")) {
  50. distinctStr = "DISTINCT ";
  51. index = 15;
  52. }
  53. sqlPartString = sqlPartString.substring(index);
  54. }
  55. pagingBuilder.append(sqlPartString);
  56. // if no ORDER BY is specified use fake ORDER BY field to avoid errors
  57. if (StringUtils.isEmpty(orderby)) {
  58. orderby = "ORDER BY CURRENT_TIMESTAMP";
  59. }
  60. StringBuilder result = new StringBuilder();
  61. result.append("WITH query AS (SELECT ")
  62. .append(distinctStr)
  63. .append("TOP 100 PERCENT ")
  64. .append(" ROW_NUMBER() OVER (")
  65. .append(orderby)
  66. .append(") as __row_number__, ")
  67. .append(pagingBuilder)
  68. .append(") SELECT * FROM query WHERE __row_number__ BETWEEN ")
  69. .append(offset).append(" AND ").append(offset + limit)
  70. .append(" ORDER BY __row_number__");
  71. return result.toString();
  72. }
  73. static String getOrderByPart(String sql) {
  74. String loweredString = sql.toLowerCase();
  75. int orderByIndex = loweredString.indexOf("order by");
  76. if (orderByIndex != -1) {
  77. // if we find a new "order by" then we need to ignore
  78. // the previous one since it was probably used for a subquery
  79. return sql.substring(orderByIndex);
  80. } else {
  81. return "";
  82. }
  83. }
  84. }