1 | /* |
2 | * Copyright 2006-2008 the original author or authors. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | package org.springframework.batch.item.database.support; |
18 | |
19 | import org.springframework.util.StringUtils; |
20 | |
21 | /** |
22 | * Generic Paging Query Provider using standard SQL:2003 windowing functions. |
23 | * These features are supported by DB2, Oracle, SQL Server 2005, Sybase and |
24 | * Apache Derby version 10.4.1.3 |
25 | * |
26 | * @author Thomas Risberg |
27 | * @since 2.0 |
28 | */ |
29 | public class SqlWindowingPagingQueryProvider extends AbstractSqlPagingQueryProvider { |
30 | |
31 | @Override |
32 | public String generateFirstPageQuery(int pageSize) { |
33 | StringBuilder sql = new StringBuilder(); |
34 | sql.append("SELECT * FROM ( "); |
35 | sql.append("SELECT ").append(getSelectClause()).append(", "); |
36 | sql.append("ROW_NUMBER() OVER (").append(getOverClause()); |
37 | sql.append(") AS ROW_NUMBER"); |
38 | sql.append(getOverSubstituteClauseStart()); |
39 | sql.append(" FROM ").append(getFromClause()).append( |
40 | getWhereClause() == null ? "" : " WHERE " + getWhereClause()); |
41 | sql.append(getOverSubstituteClauseEnd()); |
42 | sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append( |
43 | "ROW_NUMBER <= ").append(pageSize); |
44 | |
45 | return sql.toString(); |
46 | } |
47 | |
48 | protected Object getSubQueryAlias() { |
49 | return "AS TMP_SUB "; |
50 | } |
51 | |
52 | protected Object extractTableAlias() { |
53 | String alias = "" + getSubQueryAlias(); |
54 | if (StringUtils.hasText(alias) && alias.toUpperCase().startsWith("AS")) { |
55 | alias = alias.substring(3).trim() + "."; |
56 | } |
57 | return alias; |
58 | } |
59 | |
60 | @Override |
61 | public String generateRemainingPagesQuery(int pageSize) { |
62 | StringBuilder sql = new StringBuilder(); |
63 | sql.append("SELECT * FROM ( "); |
64 | sql.append("SELECT ").append(getSelectClause()).append(", "); |
65 | sql.append("ROW_NUMBER() OVER (").append(getOverClause()); |
66 | sql.append(") AS ROW_NUMBER"); |
67 | sql.append(getOverSubstituteClauseStart()); |
68 | sql.append(" FROM ").append(getFromClause()); |
69 | sql.append(" WHERE "); |
70 | if (getWhereClause() != null) { |
71 | sql.append(getWhereClause()); |
72 | sql.append(" AND "); |
73 | } |
74 | sql.append(getSortKey()); |
75 | if (isAscending()) { |
76 | sql.append(" > "); |
77 | } |
78 | else { |
79 | sql.append(" < "); |
80 | } |
81 | sql.append(getSortKeyPlaceHolder()); |
82 | sql.append(getOverSubstituteClauseEnd()); |
83 | sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append( |
84 | "ROW_NUMBER <= ").append(pageSize); |
85 | |
86 | return sql.toString(); |
87 | } |
88 | |
89 | @Override |
90 | public String generateJumpToItemQuery(int itemIndex, int pageSize) { |
91 | int page = itemIndex / pageSize; |
92 | int lastRowNum = (page * pageSize); |
93 | if (lastRowNum <= 0) { |
94 | lastRowNum = 1; |
95 | } |
96 | |
97 | StringBuilder sql = new StringBuilder(); |
98 | sql.append("SELECT SORT_KEY FROM ( "); |
99 | sql.append("SELECT ").append(getSortKey()).append(" AS SORT_KEY, "); |
100 | sql.append("ROW_NUMBER() OVER (").append(getOverClause()); |
101 | sql.append(") AS ROW_NUMBER"); |
102 | sql.append(getOverSubstituteClauseStart()); |
103 | sql.append(" FROM ").append(getFromClause()); |
104 | sql.append(getWhereClause() == null ? "" : " WHERE " + getWhereClause()); |
105 | sql.append(getOverSubstituteClauseEnd()); |
106 | sql.append(") ").append(getSubQueryAlias()).append("WHERE ").append(extractTableAlias()).append( |
107 | "ROW_NUMBER = ").append(lastRowNum); |
108 | |
109 | return sql.toString(); |
110 | } |
111 | |
112 | protected String getOverClause() { |
113 | return "ORDER BY " + getSortKeyWithoutAlias() + " " + getAscendingClause(); |
114 | } |
115 | |
116 | protected String getOverSubstituteClauseStart() { |
117 | return ""; |
118 | } |
119 | |
120 | protected String getOverSubstituteClauseEnd() { |
121 | return ""; |
122 | } |
123 | |
124 | private String getAscendingClause() { |
125 | if (isAscending()) { |
126 | return "ASC"; |
127 | } |
128 | else { |
129 | return "DESC"; |
130 | } |
131 | } |
132 | |
133 | } |