1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.apache.ibatis.jdbc;
17
18 import java.io.IOException;
19 import java.util.ArrayList;
20 import java.util.List;
21
22
23
24
25
26
27 public abstract class AbstractSQL<T> {
28
29 private static final String AND = ") \nAND (";
30 private static final String OR = ") \nOR (";
31
32 private SQLStatement sql = new SQLStatement();
33
34 public abstract T getSelf();
35
36 public T UPDATE(String table) {
37 sql().statementType = SQLStatement.StatementType.UPDATE;
38 sql().tables.add(table);
39 return getSelf();
40 }
41
42 public T SET(String sets) {
43 sql().sets.add(sets);
44 return getSelf();
45 }
46
47 public T INSERT_INTO(String tableName) {
48 sql().statementType = SQLStatement.StatementType.INSERT;
49 sql().tables.add(tableName);
50 return getSelf();
51 }
52
53 public T VALUES(String columns, String values) {
54 sql().columns.add(columns);
55 sql().values.add(values);
56 return getSelf();
57 }
58
59 public T SELECT(String columns) {
60 sql().statementType = SQLStatement.StatementType.SELECT;
61 sql().select.add(columns);
62 return getSelf();
63 }
64
65 public T SELECT_DISTINCT(String columns) {
66 sql().distinct = true;
67 SELECT(columns);
68 return getSelf();
69 }
70
71 public T DELETE_FROM(String table) {
72 sql().statementType = SQLStatement.StatementType.DELETE;
73 sql().tables.add(table);
74 return getSelf();
75 }
76
77 public T FROM(String table) {
78 sql().tables.add(table);
79 return getSelf();
80 }
81
82 public T JOIN(String join) {
83 sql().join.add(join);
84 return getSelf();
85 }
86
87 public T INNER_JOIN(String join) {
88 sql().innerJoin.add(join);
89 return getSelf();
90 }
91
92 public T LEFT_OUTER_JOIN(String join) {
93 sql().leftOuterJoin.add(join);
94 return getSelf();
95 }
96
97 public T RIGHT_OUTER_JOIN(String join) {
98 sql().rightOuterJoin.add(join);
99 return getSelf();
100 }
101
102 public T OUTER_JOIN(String join) {
103 sql().outerJoin.add(join);
104 return getSelf();
105 }
106
107 public T WHERE(String conditions) {
108 sql().where.add(conditions);
109 sql().lastList = sql().where;
110 return getSelf();
111 }
112
113 public T OR() {
114 sql().lastList.add(OR);
115 return getSelf();
116 }
117
118 public T AND() {
119 sql().lastList.add(AND);
120 return getSelf();
121 }
122
123 public T GROUP_BY(String columns) {
124 sql().groupBy.add(columns);
125 return getSelf();
126 }
127
128 public T HAVING(String conditions) {
129 sql().having.add(conditions);
130 sql().lastList = sql().having;
131 return getSelf();
132 }
133
134 public T ORDER_BY(String columns) {
135 sql().orderBy.add(columns);
136 return getSelf();
137 }
138
139 private SQLStatement sql() {
140 return sql;
141 }
142
143 public <A extends Appendable> A usingAppender(A a) {
144 sql().sql(a);
145 return a;
146 }
147
148 @Override
149 public String toString() {
150 StringBuilder sb = new StringBuilder();
151 sql().sql(sb);
152 return sb.toString();
153 }
154
155 private static class SafeAppendable {
156 private final Appendable a;
157 private boolean empty = true;
158
159 public SafeAppendable(Appendable a) {
160 super();
161 this.a = a;
162 }
163
164 public SafeAppendable append(CharSequence s) {
165 try {
166 if (empty && s.length() > 0) {
167 empty = false;
168 }
169 a.append(s);
170 } catch (IOException e) {
171 throw new RuntimeException(e);
172 }
173 return this;
174 }
175
176 public boolean isEmpty() {
177 return empty;
178 }
179
180 }
181
182 private static class SQLStatement {
183
184 public enum StatementType {
185 DELETE, INSERT, SELECT, UPDATE
186 }
187
188 StatementType statementType;
189 List<String> sets = new ArrayList<String>();
190 List<String> select = new ArrayList<String>();
191 List<String> tables = new ArrayList<String>();
192 List<String> join = new ArrayList<String>();
193 List<String> innerJoin = new ArrayList<String>();
194 List<String> outerJoin = new ArrayList<String>();
195 List<String> leftOuterJoin = new ArrayList<String>();
196 List<String> rightOuterJoin = new ArrayList<String>();
197 List<String> where = new ArrayList<String>();
198 List<String> having = new ArrayList<String>();
199 List<String> groupBy = new ArrayList<String>();
200 List<String> orderBy = new ArrayList<String>();
201 List<String> lastList = new ArrayList<String>();
202 List<String> columns = new ArrayList<String>();
203 List<String> values = new ArrayList<String>();
204 boolean distinct;
205
206 public SQLStatement() {
207
208 }
209
210 private void sqlClause(SafeAppendable builder, String keyword, List<String> parts, String open, String close,
211 String conjunction) {
212 if (!parts.isEmpty()) {
213 if (!builder.isEmpty()) {
214 builder.append("\n");
215 }
216 builder.append(keyword);
217 builder.append(" ");
218 builder.append(open);
219 String last = "________";
220 for (int i = 0, n = parts.size(); i < n; i++) {
221 String part = parts.get(i);
222 if (i > 0 && !part.equals(AND) && !part.equals(OR) && !last.equals(AND) && !last.equals(OR)) {
223 builder.append(conjunction);
224 }
225 builder.append(part);
226 last = part;
227 }
228 builder.append(close);
229 }
230 }
231
232 private String selectSQL(SafeAppendable builder) {
233 if (distinct) {
234 sqlClause(builder, "SELECT DISTINCT", select, "", "", ", ");
235 } else {
236 sqlClause(builder, "SELECT", select, "", "", ", ");
237 }
238
239 sqlClause(builder, "FROM", tables, "", "", ", ");
240 sqlClause(builder, "JOIN", join, "", "", "\nJOIN ");
241 sqlClause(builder, "INNER JOIN", innerJoin, "", "", "\nINNER JOIN ");
242 sqlClause(builder, "OUTER JOIN", outerJoin, "", "", "\nOUTER JOIN ");
243 sqlClause(builder, "LEFT OUTER JOIN", leftOuterJoin, "", "", "\nLEFT OUTER JOIN ");
244 sqlClause(builder, "RIGHT OUTER JOIN", rightOuterJoin, "", "", "\nRIGHT OUTER JOIN ");
245 sqlClause(builder, "WHERE", where, "(", ")", " AND ");
246 sqlClause(builder, "GROUP BY", groupBy, "", "", ", ");
247 sqlClause(builder, "HAVING", having, "(", ")", " AND ");
248 sqlClause(builder, "ORDER BY", orderBy, "", "", ", ");
249 return builder.toString();
250 }
251
252 private String insertSQL(SafeAppendable builder) {
253 sqlClause(builder, "INSERT INTO", tables, "", "", "");
254 sqlClause(builder, "", columns, "(", ")", ", ");
255 sqlClause(builder, "VALUES", values, "(", ")", ", ");
256 return builder.toString();
257 }
258
259 private String deleteSQL(SafeAppendable builder) {
260 sqlClause(builder, "DELETE FROM", tables, "", "", "");
261 sqlClause(builder, "WHERE", where, "(", ")", " AND ");
262 return builder.toString();
263 }
264
265 private String updateSQL(SafeAppendable builder) {
266
267 sqlClause(builder, "UPDATE", tables, "", "", "");
268 sqlClause(builder, "SET", sets, "", "", ", ");
269 sqlClause(builder, "WHERE", where, "(", ")", " AND ");
270 return builder.toString();
271 }
272
273 public String sql(Appendable a) {
274 SafeAppendable builder = new SafeAppendable(a);
275 if (statementType == null) {
276 return null;
277 }
278
279 String answer;
280
281 switch (statementType) {
282 case DELETE:
283 answer = deleteSQL(builder);
284 break;
285
286 case INSERT:
287 answer = insertSQL(builder);
288 break;
289
290 case SELECT:
291 answer = selectSQL(builder);
292 break;
293
294 case UPDATE:
295 answer = updateSQL(builder);
296 break;
297
298 default:
299 answer = null;
300 }
301
302 return answer;
303 }
304 }
305 }