gu.sql2java.ScriptRunner Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of sql2java-manager Show documentation
Show all versions of sql2java-manager Show documentation
sql2java manager class package for accessing database
/*
* 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-2020 the original author or authors.
*
* 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 gu.sql2java;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Pattern;
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import gu.sql2java.exception.DaoException;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Tool to run database scripts.
*/
public class ScriptRunner {
/** The Constant DEFAULT_DELIMITER. */
private static final String DEFAULT_DELIMITER = ";";
/** The stop on error. */
private boolean stopOnError;
/** The auto commit. */
private boolean autoCommit;
/** The log writer. */
private PrintWriter logWriter = new PrintWriter(System.out);
/** The error log writer. */
private PrintWriter errorLogWriter = new PrintWriter(System.err);
/** The delimiter. */
private String delimiter = DEFAULT_DELIMITER;
/** The full line delimiter. */
private boolean fullLineDelimiter = false;
private boolean clearComment = false;
private String alias = null;
private final List clearnPatterns = Lists.newArrayList();
private final List ignorePatterns = Lists.newArrayList();
private final Map replacePatterns = Maps.newHashMap();
/** all executable SQL statement list */
private final List executableSqls= Lists.newLinkedList();
/**
* Default constructor.
* @param autoCommit
* the auto commit
* @param stopOnError
* stop on error
*/
public ScriptRunner(boolean autoCommit, boolean stopOnError) {
this.autoCommit = autoCommit;
this.stopOnError = stopOnError;
}
/**
* Sets the delimiter.
*
* @param delimiter
* the delimiter
* @param fullLineDelimiter
* the full line delimiter
* @return this instance
*/
public ScriptRunner setDelimiter(String delimiter, boolean fullLineDelimiter) {
this.delimiter = delimiter;
this.fullLineDelimiter = fullLineDelimiter;
return this;
}
/**
* @param clearComment clear all COMMENT statement in SQL script if true
* @return this instance
*/
public ScriptRunner setClearComment(boolean clearComment){
this.clearComment = clearComment;
return this;
}
/**
* set alias name for database connect project
* @param alias
* @return this instance
*/
public ScriptRunner setAlias(String alias) {
this.alias = alias;
return this;
}
public ScriptRunner addClearRegex(String regex){
if(!Strings.isNullOrEmpty(regex)){
this.clearnPatterns.add(Pattern.compile(regex));
}
return this;
}
public ScriptRunner addClearRegex(Pattern pattern){
if(null != pattern){
this.clearnPatterns.add(pattern);
}
return this;
}
public ScriptRunner addIgnoreRegex(Pattern pattern){
if(null != pattern){
this.ignorePatterns.add(pattern);
}
return this;
}
public ScriptRunner addReplaceRegex(Pattern pattern,String replacement){
if(null != pattern && null != replacement){
this.replacePatterns.put(pattern,replacement);
}
return this;
}
/**
* Setter for logWriter property.
*
* @param logWriter
* - the new value of the logWriter property
* @return this instance
*/
public ScriptRunner setLogWriter(PrintWriter logWriter) {
this.logWriter = logWriter;
return this;
}
/**
* Setter for errorLogWriter property.
*
* @param errorLogWriter
* - the new value of the errorLogWriter property
* @return this instance
*/
public ScriptRunner setErrorLogWriter(PrintWriter errorLogWriter) {
this.errorLogWriter = errorLogWriter;
return this;
}
/**
* Runs an SQL script (read in using the Reader parameter).
*
* @param reader
* - the source of the script
* @throws IOException
* Signals that an I/O exception has occurred.
* @throws DaoException
* the wrapped SQL exception
*/
public void runScript(Reader reader) throws IOException, DaoException {
try {
Connection connection = Managers.managerInstanceOfAlias(alias).getConnection();
boolean originalAutoCommit = connection.getAutoCommit();
boolean commit = false;
try {
if (originalAutoCommit != this.autoCommit) {
connection.setAutoCommit(this.autoCommit);
}
runScript(connection, checkNotNull(reader,"reader is null"));
commit = true;
} finally {
if(!autoCommit){
if(commit){
connection.commit();
}else{
connection.rollback();
}
}
connection.setAutoCommit(originalAutoCommit);
Managers.managerInstanceOfAlias(alias).releaseConnection(connection);
}
} catch (SQLException e) {
throw new DaoException(e);
}catch (Exception e) {
Throwables.throwIfInstanceOf(e, IOException.class);
Throwables.throwIfUnchecked(e);
throw new RuntimeException(e);
}
}
/**
* Runs an SQL script (read in using the String parameter).
* @param input
* - the source of the script
* @throws IOException
* @throws DaoException
*/
public void runScript(String input) throws IOException, DaoException {
runScript(new StringReader(checkNotNull(input,"input is null")));
}
/**
* Runs an SQL script (read in using the String parameter).
* @param input
* - the source of the script
* @throws IOException
* @throws DaoException
*/
public void runScript(List input) throws IOException, DaoException {
runScript(new StringReader(checkNotNull(Joiner.on('\n').join(input),"input is null")));
}
/**
* Runs an SQL script (read in using the InputStream parameter).
* @param input
* - the source of the script
* @throws IOException
* @throws DaoException
*/
public void runScript(InputStream input) throws IOException, DaoException {
runScript(new InputStreamReader(checkNotNull(input,"input is null")));
}
/**
* @return all executable SQL statement of last call runScript
*/
public List getExecutableSqls() {
return executableSqls;
}
private boolean isIgnore(String sql){
for(Pattern p : ignorePatterns){
p.matcher(sql);
if(p.matcher(sql).matches()){
println("--" + sql);
return true;
}
}
return false;
}
/**
* 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 IOException
* if there is an error reading from the Reader
* @throws SQLException
* if any SQL errors occur
*/
private void runScript(Connection conn, Reader reader) throws IOException, SQLException {
StringBuilder command = null;
executableSqls.clear();
// auto close the reader
try (LineNumberReader lineReader = new LineNumberReader(reader)){
String line = null;
while ((line = lineReader.readLine()) != null) {
if (command == null) {
command = new StringBuilder();
}
String trimmedLine = line.trim();
if (trimmedLine.startsWith("--")) {
println(trimmedLine);
} else 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 (!fullLineDelimiter && trimmedLine.endsWith(getDelimiter())
|| fullLineDelimiter && trimmedLine.equals(getDelimiter())) {
command.append(line.substring(0, line.lastIndexOf(getDelimiter())));
command.append(" ");
Statement statement = conn.createStatement();
String sql = command.toString();
if(isIgnore(sql)){
command = null;
continue;
}
if(clearComment){
sql = sql.replaceAll("COMMENT +'[^']*'", "");
}
executableSqls.add(sql);
for(Pattern p : clearnPatterns){
sql = p.matcher(sql).replaceAll("");
}
for(Entry p : replacePatterns.entrySet()){
sql = p.getKey().matcher(sql).replaceAll(p.getValue());
}
println(sql);
boolean hasResults = false;
if (stopOnError) {
hasResults = statement.execute(sql);
} else {
try {
statement.execute(sql);
} catch (SQLException e) {
e.fillInStackTrace();
printlnError("Error executing: " + sql);
printlnError(e);
}
}
// if (autoCommit && !conn.getAutoCommit()) {
// conn.commit();
// }
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 + 1);
print(name + "\t");
}
println("");
while (rs.next()) {
for (int i = 0; i < cols; i++) {
String value = rs.getString(i + 1);
print(value + "\t");
}
println("");
}
}
command = null;
try {
statement.close();
} catch (Exception e) {
// Ignore to workaround a bug in Jakarta DBCP
}
Thread.yield();
} 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();
}
}
/**
* Gets the delimiter.
*
* @return the delimiter
*/
private String getDelimiter() {
return delimiter;
}
/**
* Prints the.
*
* @param o
* the o
*/
private void print(Object o) {
if (logWriter != null) {
System.out.print(o);
}
}
/**
* Println.
*
* @param o
* the o
*/
private void println(Object o) {
if (logWriter != null) {
logWriter.println(o);
}
}
/**
* Println error.
*
* @param o
* the o
*/
private void printlnError(Object o) {
if (errorLogWriter != null) {
errorLogWriter.println(o);
}
}
/**
* Flush.
*/
private void flush() {
if (logWriter != null) {
logWriter.flush();
}
if (errorLogWriter != null) {
errorLogWriter.flush();
}
}
}