Skip to content

Commit ad286ef

Browse files
committed
Ensure that all results are processed when executing multiple statements (i.e. sendFullScript=true).
Otherwise, an error in the second and subsequent statement might be ignored according to the JDBC spec (in practice, though, most RDBMSs throw an exception with the old code). See mybatis/migrations#118
1 parent e155f8e commit ad286ef

File tree

2 files changed

+56
-43
lines changed

2 files changed

+56
-43
lines changed

src/main/java/org/apache/ibatis/jdbc/ScriptRunner.java

Lines changed: 54 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* Copyright 2009-2017 the original author or authors.
2+
* Copyright 2009-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -225,59 +225,70 @@ private boolean commandReadyToExecute(String trimmedLine) {
225225
}
226226

227227
private void executeStatement(String command) throws SQLException {
228-
boolean hasResults = false;
229228
Statement statement = connection.createStatement();
230-
statement.setEscapeProcessing(escapeProcessing);
231-
String sql = command;
232-
if (removeCRs) {
233-
sql = sql.replaceAll("\r\n", "\n");
234-
}
235-
if (stopOnError) {
236-
hasResults = statement.execute(sql);
237-
if (throwWarning) {
238-
// In Oracle, CRATE PROCEDURE, FUNCTION, etc. returns warning
239-
// instead of throwing exception if there is compilation error.
240-
SQLWarning warning = statement.getWarnings();
241-
if (warning != null) {
242-
throw warning;
243-
}
229+
try {
230+
statement.setEscapeProcessing(escapeProcessing);
231+
String sql = command;
232+
if (removeCRs) {
233+
sql = sql.replaceAll("\r\n", "\n");
244234
}
245-
} else {
246235
try {
247-
hasResults = statement.execute(sql);
236+
boolean hasResults = statement.execute(sql);
237+
while (!(!hasResults && statement.getUpdateCount() == -1)) {
238+
checkWarnings(statement);
239+
printResults(statement, hasResults);
240+
hasResults = statement.getMoreResults();
241+
}
242+
} catch (SQLWarning e) {
243+
throw e;
248244
} catch (SQLException e) {
249-
String message = "Error executing: " + command + ". Cause: " + e;
250-
printlnError(message);
245+
if (stopOnError) {
246+
throw e;
247+
} else {
248+
String message = "Error executing: " + command + ". Cause: " + e;
249+
printlnError(message);
250+
}
251+
}
252+
} finally {
253+
try {
254+
statement.close();
255+
} catch (Exception e) {
256+
// Ignore to workaround a bug in some connection pools
257+
// (Does anyone know the details of the bug?)
251258
}
252259
}
253-
printResults(statement, hasResults);
254-
try {
255-
statement.close();
256-
} catch (Exception e) {
257-
// Ignore to workaround a bug in some connection pools
260+
}
261+
262+
private void checkWarnings(Statement statement) throws SQLException {
263+
if (!throwWarning) {
264+
return;
265+
}
266+
// In Oracle, CREATE PROCEDURE, FUNCTION, etc. returns warning
267+
// instead of throwing exception if there is compilation error.
268+
SQLWarning warning = statement.getWarnings();
269+
if (warning != null) {
270+
throw warning;
258271
}
259272
}
260273

261274
private void printResults(Statement statement, boolean hasResults) {
262-
try {
263-
if (hasResults) {
264-
ResultSet rs = statement.getResultSet();
265-
if (rs != null) {
266-
ResultSetMetaData md = rs.getMetaData();
267-
int cols = md.getColumnCount();
268-
for (int i = 0; i < cols; i++) {
269-
String name = md.getColumnLabel(i + 1);
270-
print(name + "\t");
271-
}
272-
println("");
273-
while (rs.next()) {
274-
for (int i = 0; i < cols; i++) {
275-
String value = rs.getString(i + 1);
276-
print(value + "\t");
277-
}
278-
println("");
279-
}
275+
if (!hasResults) {
276+
return;
277+
}
278+
try (ResultSet rs = statement.getResultSet()) {
279+
ResultSetMetaData md = rs.getMetaData();
280+
int cols = md.getColumnCount();
281+
for (int i = 0; i < cols; i++) {
282+
String name = md.getColumnLabel(i + 1);
283+
print(name + "\t");
284+
}
285+
println("");
286+
while (rs.next()) {
287+
for (int i = 0; i < cols; i++) {
288+
String value = rs.getString(i + 1);
289+
print(value + "\t");
280290
}
291+
println("");
281292
}
282293
} catch (SQLException e) {
283294
printlnError("Error printing results: " + e.getMessage());

src/test/java/org/apache/ibatis/jdbc/ScriptRunnerTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ public void shouldAcceptDelimiterVariations() throws Exception {
251251
Connection conn = mock(Connection.class);
252252
Statement stmt = mock(Statement.class);
253253
when(conn.createStatement()).thenReturn(stmt);
254+
when(stmt.getUpdateCount()).thenReturn(-1);
254255
ScriptRunner runner = new ScriptRunner(conn);
255256

256257
String sql = "-- @DELIMITER | \n"
@@ -289,6 +290,7 @@ public void shouldAcceptMultiCharDelimiter() throws Exception {
289290
Connection conn = mock(Connection.class);
290291
Statement stmt = mock(Statement.class);
291292
when(conn.createStatement()).thenReturn(stmt);
293+
when(stmt.getUpdateCount()).thenReturn(-1);
292294
ScriptRunner runner = new ScriptRunner(conn);
293295

294296
String sql = "-- @DELIMITER || \n"

0 commit comments

Comments
 (0)