| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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 org.apache.empire.db; |
| |
| import java.sql.SQLException; |
| import java.util.ArrayList; |
| import java.util.Iterator; |
| |
| import org.apache.empire.db.context.DBContextAware; |
| import org.apache.empire.db.exceptions.EmpireSQLException; |
| import org.apache.empire.dbms.DBMSHandler; |
| import org.apache.empire.exceptions.InvalidArgumentException; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * DBSQLScript<br> |
| * This class is a collection of sql command strings.<br> |
| * The class is used for obtaining and executing DDL commands supplied by the |
| * database dbms (@see {@link DBMSHandler#getDDLScript(DBCmdType, DBObject, DBSQLScript)}) |
| */ |
| public class DBSQLScript implements DBContextAware, Iterable<String> |
| { |
| // Logger |
| private static final Logger log = LoggerFactory.getLogger(DBSQLScript.class); |
| private static final String DEFAULT_COMMAND_SEPARATOR = ";\r\n\r\n"; |
| |
| /** |
| * SQLCmd |
| * @author doebele |
| */ |
| protected static class SQLStmt |
| { |
| private String cmd; |
| private Object[] params; |
| |
| public SQLStmt(String cmd, Object[] params) |
| { |
| this.cmd = cmd; |
| this.params = params; |
| } |
| |
| public String getCmd() |
| { |
| return cmd; |
| } |
| |
| public void setCmd(String cmd) |
| { |
| this.cmd = cmd; |
| } |
| |
| public Object[] getParams() |
| { |
| return params; |
| } |
| |
| public void setParams(Object[] params) |
| { |
| this.params = params; |
| } |
| } |
| |
| /** |
| * SQLCmdIterator |
| * @author doebele |
| */ |
| private static class SQLStmtIterator implements Iterator<String> |
| { |
| private final Iterator<SQLStmt> iterator; |
| |
| private SQLStmtIterator(Iterator<SQLStmt> iterator) |
| { |
| this.iterator = iterator; |
| } |
| |
| @Override |
| public boolean hasNext() |
| { |
| return iterator.hasNext(); |
| } |
| |
| @Override |
| public String next() |
| { |
| return iterator.next().getCmd(); |
| } |
| |
| @Override |
| public void remove() |
| { |
| iterator.remove(); |
| } |
| } |
| |
| // Properties |
| protected String commandSeparator = DEFAULT_COMMAND_SEPARATOR; |
| |
| protected ArrayList<SQLStmt> sqlStmtList = new ArrayList<SQLStmt>(); |
| |
| // the context |
| protected final DBContext context; |
| |
| public DBSQLScript(DBContext context) |
| { |
| // nothing |
| this.context = context; |
| } |
| |
| public DBSQLScript(DBContext context, String commandSeparator) |
| { |
| this(context); |
| this.commandSeparator = commandSeparator; |
| } |
| |
| /** |
| * Returns the current Context |
| * @return |
| */ |
| @Override |
| public DBContext getContext() |
| { |
| return context; |
| } |
| |
| /** |
| * Adds a statement to the script. |
| * |
| * @param sql the statement |
| */ |
| public void addStmt(String sql) |
| { |
| sqlStmtList.add(new SQLStmt(sql, null)); |
| } |
| |
| /** |
| * Adds a statement to the script. |
| * |
| * @param sql the statement |
| * @param params the statement parameters |
| */ |
| public void addStmt(String sql, Object[] params) |
| { |
| sqlStmtList.add(new SQLStmt(sql, params)); |
| } |
| |
| /** |
| * Adds a statement to the script.<br> |
| * The supplied StringBuilder will be reset to a length of 0 |
| * |
| * @param sql the statement |
| */ |
| public final void addStmt(StringBuilder sql) |
| { |
| addStmt(sql.toString()); |
| // Clear Builder |
| sql.setLength(0); |
| } |
| |
| /** |
| * Adds an insert statement |
| * @param cmd the insert command |
| */ |
| public void addInsert(DBCommand cmd) |
| { |
| if (cmd == null) |
| throw new InvalidArgumentException("cmd", cmd); |
| addStmt(cmd.getInsert(), cmd.getParamValues()); |
| } |
| |
| /** |
| * Adds an update statement |
| * @param cmd the insert command |
| */ |
| public void addUpdate(DBCommand cmd) |
| { |
| if (cmd == null) |
| throw new InvalidArgumentException("cmd", cmd); |
| addStmt(cmd.getUpdate(), cmd.getParamValues()); |
| } |
| |
| /** |
| * Adds an delete statement |
| * @param cmd the insert command |
| */ |
| public void addDelete(DBCommand cmd, DBTable table) |
| { |
| if (cmd == null) |
| throw new InvalidArgumentException("cmd", cmd); |
| addStmt(cmd.getDelete(table), cmd.getParamValues()); |
| } |
| |
| /** |
| * Returns the number of statements in this script |
| * |
| * @return number of statements in this script |
| */ |
| public int getCount() |
| { |
| return sqlStmtList.size(); |
| } |
| |
| /** |
| * Returns the statement command at the given index |
| * @param i index of the statement to retrieve |
| * @return the sql statement command |
| */ |
| public String getStmt(int i) |
| { |
| if (i < 0 || i >= sqlStmtList.size()) |
| throw new InvalidArgumentException("index", i); |
| // return statement command |
| return sqlStmtList.get(i).getCmd(); |
| } |
| |
| /** |
| * Returns the statement command at the given index |
| * @param i index of the statement to retrieve |
| * @return the sql statement params |
| */ |
| public Object[] getStmtParams(int i) |
| { |
| if (i < 0 || i >= sqlStmtList.size()) |
| throw new InvalidArgumentException("index", i); |
| // return statement params |
| return sqlStmtList.get(i).getParams(); |
| } |
| |
| /** |
| * Inserts an entry in the list |
| * |
| * @param i index of the statement to replace |
| * @param stmt the new statement for this index, or NULL to remove the statement |
| */ |
| public void insertStmt(int i, String stmt, Object[] params) |
| { |
| if (stmt == null) |
| throw new InvalidArgumentException("stmt", stmt); |
| if (i < 0 || i > sqlStmtList.size()) |
| throw new InvalidArgumentException("index", i); |
| // insert statement |
| sqlStmtList.add(i, new SQLStmt(stmt, params)); |
| } |
| |
| /** |
| * Inserts an entry in the list |
| * |
| * @param i index of the statement to replace |
| * @param stmt the new statement for this index, or NULL to remove the statement |
| */ |
| public final void insertStmt(int i, String stmt) |
| { |
| // replace or remove statement |
| insertStmt(i, stmt, null); |
| } |
| |
| /** |
| * Replaces an entry in the list |
| * |
| * @param i index of the statement to replace |
| * @param cmd the new statement for this index, or NULL to remove the statement |
| * @param params the command params (optional) |
| */ |
| public void replaceStmt(int i, String cmd, Object[] params) |
| { |
| if (cmd == null) |
| throw new InvalidArgumentException("cmd", cmd); |
| if (i < 0 || i >= sqlStmtList.size()) |
| throw new InvalidArgumentException("index", i); |
| // replace statement |
| SQLStmt stmt = sqlStmtList.get(i); |
| stmt.setCmd(cmd); |
| stmt.setParams(params); |
| } |
| |
| /** |
| * Replaces an entry in the list |
| * |
| * @param i index of the statement to replace |
| * @param cmd the new statement for this index, or NULL to remove the statement |
| */ |
| public final void replaceStmt(int i, String cmd) |
| { |
| // replace |
| replaceStmt(i, cmd, null); |
| } |
| |
| /** |
| * Removes a statement from the list |
| * @param i index of the statement to replace |
| */ |
| public void removeStmt(int i) |
| { |
| // check index |
| if (i < 0 || i >= sqlStmtList.size()) |
| throw new InvalidArgumentException("index", i); |
| // remove statement |
| sqlStmtList.remove(i); |
| } |
| |
| /** |
| * Clears the script by removing all statements |
| */ |
| public void clear() |
| { |
| sqlStmtList.clear(); |
| } |
| |
| /** |
| * Executes all SQL Statements one by one using the supplied dbms and connection. |
| * |
| * @param ignoreErrors true if errors should be ignored |
| * |
| * @return number of records affected |
| */ |
| public int executeAll(boolean ignoreErrors) |
| { |
| log.debug("Running script containing " + String.valueOf(getCount()) + " statements."); |
| int result = 0; |
| DBMSHandler dbms = context.getDbms(); |
| for (SQLStmt stmt : sqlStmtList) |
| { |
| try |
| { |
| // Execute Statement |
| log.debug("Executing: {}", stmt.getCmd()); |
| int count = dbms.executeSQL(stmt.getCmd(), stmt.getParams(), context.getConnection(), null); |
| result += (count >= 0 ? count : 0); |
| } |
| catch (SQLException e) |
| { |
| // SQLException |
| log.error(e.toString(), e); |
| if (ignoreErrors == false) |
| { // forward exception |
| throw new EmpireSQLException(dbms, e); |
| } |
| // continue |
| log.debug("Ignoring error. Continuing with script..."); |
| } |
| } |
| log.debug("Script completed. {} records affected.", result); |
| return result; |
| } |
| |
| /** |
| * Executes all SQL Statements one by one using the supplied dbms and connection. |
| |
| * @return number of records affected |
| */ |
| public final int executeAll() |
| { |
| return executeAll(false); |
| } |
| |
| /** |
| * Executes all SQL Statements as a JDBC Batch Job. |
| */ |
| public int executeBatch() |
| { |
| log.debug("Running batch containing " + String.valueOf(getCount()) + " statements."); |
| DBMSHandler dbms = context.getDbms(); |
| try |
| { |
| // Execute Statement |
| int count = sqlStmtList.size(); |
| String[] cmdList = new String[count]; |
| Object[][] paramList = null; |
| int i = 0; |
| for (SQLStmt stmt : sqlStmtList) |
| { |
| cmdList[i] = stmt.getCmd(); |
| // set params |
| if (stmt.getParams() != null) |
| { |
| if (paramList == null) |
| paramList = new Object[count][]; |
| paramList[i] = stmt.getParams(); |
| } |
| i++; |
| } |
| // Execute batch |
| int[] res = dbms.executeBatch(cmdList, paramList, context.getConnection()); |
| for (count = 0, i = 0; i < (res != null ? res.length : 0); i++) |
| count += (res[i] >= 0 ? res[i] : 0); |
| log.debug("Script completed. {} records affected.", count); |
| return count; |
| } |
| catch (SQLException e) |
| { |
| // SQLException |
| log.error(e.toString(), e); |
| throw new EmpireSQLException(dbms, e); |
| } |
| } |
| |
| /** |
| * Returns an iterator |
| */ |
| @Override |
| public Iterator<String> iterator() |
| { |
| return new SQLStmtIterator(sqlStmtList.iterator()); |
| } |
| |
| /** |
| * Returns the sql script as a string |
| */ |
| @Override |
| public String toString() |
| { |
| StringBuilder script = new StringBuilder(); |
| for (SQLStmt stmt : sqlStmtList) |
| { |
| script.append(stmt.getCmd()); |
| script.append(commandSeparator); |
| } |
| return script.toString(); |
| } |
| } |