| /* |
| * Slightly modified version of the com.ibatis.common.jdbc.ScriptRunner class |
| * from the iBATIS Apache project. Only removed dependency on Resource class |
| * and a constructor |
| */ |
| /* |
| * Copyright 2004 Clinton Begin |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package com.cloud.utils.db; |
| |
| import java.io.IOException; |
| import java.io.LineNumberReader; |
| import java.io.Reader; |
| import java.sql.Connection; |
| import java.sql.ResultSet; |
| import java.sql.ResultSetMetaData; |
| import java.sql.SQLException; |
| import java.sql.Statement; |
| |
| import org.apache.log4j.Logger; |
| |
| /** |
| * Tool to run database scripts |
| */ |
| public class ScriptRunner { |
| private static Logger s_logger = Logger.getLogger(ScriptRunner.class); |
| |
| private static final String DEFAULT_DELIMITER = ";"; |
| |
| private Connection connection; |
| |
| private boolean stopOnError; |
| private boolean autoCommit; |
| private boolean verbosity = true; |
| |
| private String delimiter = DEFAULT_DELIMITER; |
| private boolean fullLineDelimiter = false; |
| |
| private StringBuffer _logBuffer = new StringBuffer(); |
| |
| /** |
| * Default constructor |
| */ |
| public ScriptRunner(Connection connection, boolean autoCommit, boolean stopOnError) { |
| this.connection = connection; |
| this.autoCommit = autoCommit; |
| this.stopOnError = stopOnError; |
| } |
| |
| public ScriptRunner(Connection connection, boolean autoCommit, boolean stopOnError, boolean verbosity) { |
| this.connection = connection; |
| this.autoCommit = autoCommit; |
| this.stopOnError = stopOnError; |
| this.verbosity = verbosity; |
| } |
| |
| public void setDelimiter(String delimiter, boolean fullLineDelimiter) { |
| this.delimiter = delimiter; |
| this.fullLineDelimiter = fullLineDelimiter; |
| } |
| |
| /** |
| * Runs an SQL script (read in using the Reader parameter) |
| * |
| * @param reader |
| * - the source of the script |
| */ |
| public void runScript(Reader reader) throws IOException, SQLException { |
| try { |
| boolean originalAutoCommit = connection.getAutoCommit(); |
| try { |
| if (originalAutoCommit != this.autoCommit) { |
| connection.setAutoCommit(this.autoCommit); |
| } |
| runScript(connection, reader); |
| } finally { |
| connection.setAutoCommit(originalAutoCommit); |
| } |
| } catch (IOException e) { |
| throw e; |
| } catch (SQLException e) { |
| throw e; |
| } catch (Exception e) { |
| throw new RuntimeException("Error running script. Cause: " + e, e); |
| } |
| } |
| |
| /** |
| * Runs an SQL script (read in using the Reader parameter) using the |
| * connection passed in |
| * |
| * @param conn |
| * - the connection to use for the script |
| * @param reader |
| * - the source of the script |
| * @throws SQLException |
| * if any SQL errors occur |
| * @throws IOException |
| * if there is an error reading from the Reader |
| */ |
| private void runScript(Connection conn, Reader reader) throws IOException, SQLException { |
| StringBuffer command = null; |
| try { |
| LineNumberReader lineReader = new LineNumberReader(reader); |
| String line = null; |
| while ((line = lineReader.readLine()) != null) { |
| if (command == null) { |
| command = new StringBuffer(); |
| } |
| String trimmedLine = line.trim(); |
| if (trimmedLine.startsWith("--")) { |
| println(trimmedLine); |
| } else if (trimmedLine.length() < 1 || trimmedLine.startsWith("//")) { |
| // Do nothing |
| } else if (trimmedLine.length() < 1 || trimmedLine.startsWith("--")) { |
| // Do nothing |
| } else if (trimmedLine.length() < 1 || trimmedLine.startsWith("#")) { |
| // Do nothing |
| } else if (!fullLineDelimiter && trimmedLine.endsWith(getDelimiter()) || fullLineDelimiter && trimmedLine.equals(getDelimiter())) { |
| command.append(line.substring(0, line.lastIndexOf(getDelimiter()))); |
| command.append(" "); |
| try (Statement statement = conn.createStatement();) { |
| println(command); |
| boolean hasResults = false; |
| if (stopOnError) { |
| hasResults = statement.execute(command.toString()); |
| } else { |
| try { |
| statement.execute(command.toString()); |
| } catch (SQLException e) { |
| e.fillInStackTrace(); |
| printlnError("Error executing: " + command); |
| printlnError(e); |
| } |
| } |
| if (autoCommit && !conn.getAutoCommit()) { |
| conn.commit(); |
| } |
| try(ResultSet rs = statement.getResultSet();) { |
| if (hasResults && rs != null) { |
| ResultSetMetaData md = rs.getMetaData(); |
| int cols = md.getColumnCount(); |
| for (int i = 0; i < cols; i++) { |
| String name = md.getColumnLabel(i); |
| print(name + "\t"); |
| } |
| println(""); |
| while (rs.next()) { |
| for (int i = 1; i <= cols; i++) { |
| String value = rs.getString(i); |
| print(value + "\t"); |
| } |
| println(""); |
| } |
| } |
| command = null; |
| Thread.yield(); |
| } |
| } |
| } else { |
| int idx = line.indexOf("--"); |
| if (idx != -1) |
| command.append(line.substring(0, idx)); |
| else |
| command.append(line); |
| command.append(" "); |
| } |
| } |
| if (!autoCommit) { |
| conn.commit(); |
| } |
| } catch (SQLException e) { |
| e.fillInStackTrace(); |
| printlnError("Error executing: " + command); |
| printlnError(e); |
| throw e; |
| } catch (IOException e) { |
| e.fillInStackTrace(); |
| printlnError("Error executing: " + command); |
| printlnError(e); |
| throw e; |
| } finally { |
| conn.rollback(); |
| flush(); |
| } |
| } |
| |
| private String getDelimiter() { |
| return delimiter; |
| } |
| |
| private void print(Object o) { |
| _logBuffer.append(o); |
| } |
| |
| private void println(Object o) { |
| _logBuffer.append(o); |
| if (verbosity) |
| s_logger.debug(_logBuffer.toString()); |
| _logBuffer = new StringBuffer(); |
| } |
| |
| private void printlnError(Object o) { |
| s_logger.error("" + o); |
| } |
| |
| private void flush() { |
| if (_logBuffer.length() > 0) { |
| s_logger.debug(_logBuffer.toString()); |
| _logBuffer = new StringBuffer(); |
| } |
| } |
| } |