1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package com.ibatis.common.jdbc;
17
18 import com.ibatis.common.resources.Resources;
19
20 import java.io.IOException;
21 import java.io.LineNumberReader;
22 import java.io.PrintWriter;
23 import java.io.Reader;
24 import java.sql.Connection;
25 import java.sql.Driver;
26 import java.sql.DriverManager;
27 import java.sql.ResultSet;
28 import java.sql.ResultSetMetaData;
29 import java.sql.SQLException;
30 import java.sql.Statement;
31
32
33
34
35 public class ScriptRunner {
36
37
38 private static final String DEFAULT_DELIMITER = ";";
39
40
41 private Connection connection;
42
43
44 private String driver;
45
46
47 private String url;
48
49
50 private String username;
51
52
53 private String password;
54
55
56 private boolean stopOnError;
57
58
59 private boolean autoCommit;
60
61
62 private PrintWriter logWriter = new PrintWriter(System.out);
63
64
65 private PrintWriter errorLogWriter = new PrintWriter(System.err);
66
67
68 private String delimiter = DEFAULT_DELIMITER;
69
70
71 private boolean fullLineDelimiter;
72
73
74
75
76
77
78
79
80
81
82
83 public ScriptRunner(Connection connection, boolean autoCommit, boolean stopOnError) {
84 this.connection = connection;
85 this.autoCommit = autoCommit;
86 this.stopOnError = stopOnError;
87 }
88
89
90
91
92
93
94
95
96
97 public void setDelimiter(String delimiter, boolean fullLineDelimiter) {
98 this.delimiter = delimiter;
99 this.fullLineDelimiter = fullLineDelimiter;
100 }
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118 public ScriptRunner(String driver, String url, String username, String password, boolean autoCommit,
119 boolean stopOnError) {
120 this.driver = driver;
121 this.url = url;
122 this.username = username;
123 this.password = password;
124 this.autoCommit = autoCommit;
125 this.stopOnError = stopOnError;
126 }
127
128
129
130
131
132
133
134 public void setLogWriter(PrintWriter logWriter) {
135 this.logWriter = logWriter;
136 }
137
138
139
140
141
142
143
144 public void setErrorLogWriter(PrintWriter errorLogWriter) {
145 this.errorLogWriter = errorLogWriter;
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159 public void runScript(Reader reader) throws IOException, SQLException {
160 try {
161 if (connection == null) {
162 DriverManager.registerDriver((Driver) Resources.instantiate(driver));
163 Connection conn = DriverManager.getConnection(url, username, password);
164 try {
165 if (conn.getAutoCommit() != autoCommit) {
166 conn.setAutoCommit(autoCommit);
167 }
168 runScript(conn, reader);
169 } finally {
170 conn.close();
171 }
172 } else {
173 boolean originalAutoCommit = connection.getAutoCommit();
174 try {
175 if (originalAutoCommit != this.autoCommit) {
176 connection.setAutoCommit(this.autoCommit);
177 }
178 runScript(connection, reader);
179 } finally {
180 connection.setAutoCommit(originalAutoCommit);
181 }
182 }
183 } catch (IOException | SQLException e) {
184 throw e;
185 } catch (Exception e) {
186 throw new RuntimeException("Error running script. Cause: " + e, e);
187 }
188 }
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203 private void runScript(Connection conn, Reader reader) throws IOException, SQLException {
204 StringBuilder command = null;
205 try {
206 LineNumberReader lineReader = new LineNumberReader(reader);
207 String line = null;
208 while ((line = lineReader.readLine()) != null) {
209 if (command == null) {
210 command = new StringBuilder();
211 }
212 String trimmedLine = line.trim();
213 if (trimmedLine.startsWith("--")) {
214 println(trimmedLine);
215 } else if (trimmedLine.isEmpty() || trimmedLine.startsWith("//") || trimmedLine.startsWith("--")) {
216
217 } else if (!fullLineDelimiter && trimmedLine.endsWith(getDelimiter())
218 || fullLineDelimiter && trimmedLine.equals(getDelimiter())) {
219 command.append(line.substring(0, line.lastIndexOf(getDelimiter())));
220 command.append(" ");
221 Statement statement = conn.createStatement();
222
223 println(command);
224
225 boolean hasResults = false;
226 if (stopOnError) {
227 hasResults = statement.execute(command.toString());
228 } else {
229 try {
230 statement.execute(command.toString());
231 } catch (SQLException e) {
232 e.fillInStackTrace();
233 printlnError("Error executing: " + command);
234 printlnError(e);
235 }
236 }
237
238 if (autoCommit && !conn.getAutoCommit()) {
239 conn.commit();
240 }
241
242 ResultSet rs = statement.getResultSet();
243 if (hasResults && rs != null) {
244 ResultSetMetaData md = rs.getMetaData();
245 int cols = md.getColumnCount();
246 for (int i = 0; i < cols; i++) {
247 String name = md.getColumnLabel(i + 1);
248 print(name + "\t");
249 }
250 println("");
251 while (rs.next()) {
252 for (int i = 0; i < cols; i++) {
253 String value = rs.getString(i + 1);
254 print(value + "\t");
255 }
256 println("");
257 }
258 }
259
260 command = null;
261 try {
262 statement.close();
263 } catch (Exception e) {
264
265 }
266 Thread.yield();
267 } else {
268 command.append(line);
269 command.append(" ");
270 }
271 }
272 if (!autoCommit) {
273 conn.commit();
274 }
275 } catch (IOException | SQLException e) {
276 e.fillInStackTrace();
277 printlnError("Error executing: " + command);
278 printlnError(e);
279 throw e;
280 } finally {
281 conn.rollback();
282 flush();
283 }
284 }
285
286
287
288
289
290
291 private String getDelimiter() {
292 return delimiter;
293 }
294
295
296
297
298
299
300
301 private void print(Object o) {
302 if (logWriter != null) {
303 System.out.print(o);
304 }
305 }
306
307
308
309
310
311
312
313 private void println(Object o) {
314 if (logWriter != null) {
315 logWriter.println(o);
316 }
317 }
318
319
320
321
322
323
324
325 private void printlnError(Object o) {
326 if (errorLogWriter != null) {
327 errorLogWriter.println(o);
328 }
329 }
330
331
332
333
334 private void flush() {
335 if (logWriter != null) {
336 logWriter.flush();
337 }
338 if (errorLogWriter != null) {
339 errorLogWriter.flush();
340 }
341 }
342
343 }