Skip to content

Commit

Permalink
fixed a few bugs and added a feature or two w/ sqlscript as a result …
Browse files Browse the repository at this point in the history
…of using it in another project.
  • Loading branch information
chenson42 committed Aug 6, 2008
1 parent c26f66f commit 9b4d357
Showing 1 changed file with 120 additions and 47 deletions.
167 changes: 120 additions & 47 deletions symmetric/src/main/java/org/jumpmind/symmetric/db/SqlScript.java
Expand Up @@ -21,25 +21,29 @@
package org.jumpmind.symmetric.db;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.ConnectionCallback;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.StatementCallback;

/**
* This class is for running sql scripts against a datasource.
* This class is for running SQL scripts against a DataSource.
*/
public class SqlScript {

static final String COMMENT_CHARS_1 = "--";
static final String COMMENT_CHARS_2 = "#";

static final Log logger = LogFactory.getLog(SqlScript.class);

public final static char QUERY_ENDS = ';';
Expand All @@ -50,75 +54,144 @@ public class SqlScript {

private DataSource dataSource;

private int commitRate = 10000;

private boolean failOnError = true;

public SqlScript(URL url, DataSource dataSource) {
this.script = url;
this.dataSource = dataSource;
private Map<String, String> replacementTokens;

public SqlScript(URL url, DataSource ds) {
this(url, ds, true, QUERY_ENDS, null);
}

public SqlScript(URL url, DataSource dataSource, boolean failOnError) {
this(url, dataSource);
this.failOnError = failOnError;
public SqlScript(URL url, DataSource ds, boolean failOnError) {
this(url, ds, failOnError, QUERY_ENDS, null);
}

public SqlScript(URL url, DataSource ds, char delimiter) {
this(url, ds, true, delimiter, null);
}

public SqlScript(URL url, DataSource dataSource, char delimiter) {
this(url, dataSource);
public SqlScript(URL url, DataSource ds, boolean failOnError, char delimiter, Map<String, String> replacementTokens) {
this.script = url;
this.dataSource = ds;
this.failOnError = failOnError;
this.delimiter = delimiter;
this.replacementTokens = replacementTokens;
}

private boolean isComment(String line) {
if ((line != null) && (line.length() > 0))
return (line.charAt(0) == '#' || line.startsWith("--"));
return false;
private void closeQuietly(Statement stmt) {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
logger.error(e, e);
}
}
}

public void execute() {
JdbcTemplate template = new JdbcTemplate(dataSource);
template.execute(new StatementCallback() {
public Object doInStatement(Statement statement) throws SQLException, DataAccessException {
executeScript(statement);
return null;
protected String replaceTokens(String original) {
if (this.replacementTokens != null) {
for (Object key : this.replacementTokens.keySet()) {
original = original.replaceAll("\\%" + key + "\\%", this.replacementTokens.get((String) key));
}
});
}
return original;
}

private void executeScript(Statement st) throws SQLException {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(script.openStream()));
String line;
StringBuilder sql = new StringBuilder();

while ((line = reader.readLine()) != null) {
if (!isComment(line)) {
if (checkStatementEnds(line)) {
sql.append(line.substring(0, line.indexOf(delimiter)));
if (logger.isDebugEnabled()) {
logger.debug("query->" + sql);
}
try {
st.execute(sql.toString());
} catch (SQLException e) {
if (failOnError) {
logger.error(sql.toString() + " failed to execute.", e);
throw e;
public void execute() {
JdbcTemplate template = new JdbcTemplate(this.dataSource);
template.execute(new ConnectionCallback() {
public Object doInConnection(Connection connection) throws SQLException, DataAccessException {
Statement st = null;
String fileName = script.getFile();
fileName = fileName.substring(fileName.lastIndexOf("/") + 1);
logger.info("Running " + fileName);
int lineCount = 0;

try {
connection.setAutoCommit(false);
st = connection.createStatement();
BufferedReader reader = new BufferedReader(new InputStreamReader(script.openStream()));
String line;
StringBuilder sql = new StringBuilder();
int count = 0;
int notFoundCount = 0;
while ((line = reader.readLine()) != null) {
lineCount++;
line = trimComments(line);
if (line.length() > 0) {
if (checkStatementEnds(line)) {
sql.append(" ");
sql.append(line.substring(0, line.lastIndexOf(delimiter)));
if (logger.isDebugEnabled()) {
logger.debug("query->" + sql);
}
try {
st.execute(replaceTokens(sql.toString()));
count++;
if (count % commitRate == 0) {
connection.commit();
}
} catch (SQLException e) {
if (failOnError) {
logger.error(sql.toString() + " failed to execute.", e);
throw e;
} else {
if (e.getErrorCode() != 942 && e.getErrorCode() != 2289) {
logger.warn(e.getMessage() + ": " + sql.toString());
} else if (sql.toString().toLowerCase().startsWith("drop")) {
notFoundCount++;
}
}
}
sql.setLength(0);
} else {
logger.warn(e.getMessage() + ": " + sql.toString());
sql.append(" ");
sql.append(line);
}
}
sql.setLength(0);
} else {
sql.append(line);
}

connection.commit();

logger.info("Ran " + count + " sql statements in " + fileName);
if (notFoundCount > 0) {
logger.info("Could not drop a total of " + notFoundCount
+ " database object because they were not found");
}
} catch (Exception e) {
logger.info("Error on line " + lineCount + " of " + fileName);
throw new RuntimeException(e);
} finally {
closeQuietly(st);
}
return null;
}
} catch (IOException e) {
throw new RuntimeException(e);
});
}

private String trimComments(String line) {
int index = line.indexOf(COMMENT_CHARS_1);
if (index >= 0) {
line = line.substring(0, index);
}
index = line.indexOf(COMMENT_CHARS_2);
if (index >= 0) {
line = line.substring(0, index);
}
return line.trim();
}

private boolean checkStatementEnds(String s) {
return s.trim().endsWith("" + delimiter);
}

public int getCommitRate() {
return commitRate;
}

public void setCommitRate(int commitRate) {
this.commitRate = commitRate;
}
}

0 comments on commit 9b4d357

Please sign in to comment.