001: /*
002: * Copyright 2004-2008 H2 Group. Licensed under the H2 License, Version 1.0
003: * (http://h2database.com/html/license.html).
004: * Initial Developer: H2 Group
005: */
006: package org.h2.tools;
007:
008: import java.io.BufferedInputStream;
009: import java.io.BufferedReader;
010: import java.io.File;
011: import java.io.IOException;
012: import java.io.InputStream;
013: import java.io.InputStreamReader;
014: import java.io.Reader;
015: import java.sql.Connection;
016: import java.sql.DriverManager;
017: import java.sql.ResultSet;
018: import java.sql.SQLException;
019: import java.sql.Statement;
020:
021: import org.h2.engine.Constants;
022: import org.h2.message.Message;
023: import org.h2.util.ClassUtils;
024: import org.h2.util.FileUtils;
025: import org.h2.util.IOUtils;
026: import org.h2.util.JdbcUtils;
027: import org.h2.util.ScriptReader;
028: import org.h2.util.StringUtils;
029:
030: /**
031: * Executes the contents of a SQL script file against a database.
032: */
033: public class RunScript {
034:
035: private void showUsage() {
036: System.out
037: .println("java "
038: + getClass().getName()
039: + " -url <url> -user <user> [-password <pwd>] [-script <file>] [-driver <driver] [-options <option> ...]");
040: System.out
041: .println("See also http://h2database.com/javadoc/org/h2/tools/RunScript.html");
042: }
043:
044: /**
045: * The command line interface for this tool. The options must be split into
046: * strings like this: "-user", "sa",... Options are case sensitive. The
047: * following options are supported:
048: * <ul>
049: * <li>-help or -? (print the list of options) </li>
050: * <li>-url jdbc:h2:... (database URL) </li>
051: * <li>-user username </li>
052: * <li>-password password </li>
053: * <li>-script filename (default file name is backup.sql) </li>
054: * <li>-driver driver the JDBC driver class name (not required for H2)
055: * </li>
056: * <li>-options to specify a list of options (only for H2 and only when
057: * using the embedded mode) </li>
058: * </ul>
059: * To include local files when using remote databases, use the special
060: * syntax:
061: *
062: * <pre>
063: * @INCLUDE fileName
064: * </pre>
065: *
066: * This syntax is only supported by this tool. Embedded RUNSCRIPT SQL
067: * statements will be executed by the database.
068: *
069: * @param args the command line arguments
070: * @throws SQLException
071: */
072: public static void main(String[] args) throws SQLException {
073: new RunScript().run(args);
074: }
075:
076: private void run(String[] args) throws SQLException {
077: String url = null;
078: String user = null;
079: String password = "";
080: String script = "backup.sql";
081: String options = null;
082: boolean continueOnError = false;
083: boolean showTime = false;
084: for (int i = 0; args != null && i < args.length; i++) {
085: if (args[i].equals("-url")) {
086: url = args[++i];
087: } else if (args[i].equals("-user")) {
088: user = args[++i];
089: } else if (args[i].equals("-password")) {
090: password = args[++i];
091: } else if (args[i].equals("-continueOnError")) {
092: continueOnError = true;
093: } else if (args[i].equals("-script")) {
094: script = args[++i];
095: } else if (args[i].equals("-time")) {
096: showTime = true;
097: } else if (args[i].equals("-driver")) {
098: String driver = args[++i];
099: try {
100: ClassUtils.loadUserClass(driver);
101: } catch (ClassNotFoundException e) {
102: throw Message.convert(e);
103: }
104: } else if (args[i].equals("-options")) {
105: StringBuffer buff = new StringBuffer();
106: i++;
107: for (; i < args.length; i++) {
108: buff.append(' ');
109: buff.append(args[i]);
110: }
111: options = buff.toString();
112: } else {
113: showUsage();
114: return;
115: }
116: }
117: if (url == null || user == null || password == null
118: || script == null) {
119: showUsage();
120: return;
121: }
122: long time = System.currentTimeMillis();
123: // for(int i=0; i<10; i++) {
124: // int test;
125: if (options != null) {
126: executeRunscript(url, user, password, script, options);
127: } else {
128: execute(url, user, password, script, null, continueOnError);
129: }
130: // }
131: time = System.currentTimeMillis() - time;
132: if (showTime) {
133: System.out.println("Done in " + time + " ms");
134: }
135: }
136:
137: /**
138: * Executes the SQL commands in a script file against a database.
139: *
140: * @param conn the connection to a database
141: * @param reader the reader
142: * @return the last result set
143: */
144: public static ResultSet execute(Connection conn, Reader reader)
145: throws SQLException {
146: reader = new BufferedReader(reader);
147: Statement stat = conn.createStatement();
148: ResultSet rs = null;
149: ScriptReader r = new ScriptReader(reader);
150: while (true) {
151: String sql = r.readStatement();
152: if (sql == null) {
153: break;
154: }
155: boolean resultSet = stat.execute(sql);
156: if (resultSet) {
157: if (rs != null) {
158: rs.close();
159: rs = null;
160: }
161: rs = stat.getResultSet();
162: }
163: }
164: return rs;
165: }
166:
167: private static void execute(Connection conn, String fileName,
168: boolean continueOnError, String charsetName)
169: throws SQLException, IOException {
170: InputStream in = FileUtils.openFileInputStream(fileName);
171: String path = FileUtils.getParent(fileName);
172: try {
173: in = new BufferedInputStream(in, Constants.IO_BUFFER_SIZE);
174: Reader reader = new InputStreamReader(in, charsetName);
175: execute(conn, continueOnError, path, reader, charsetName);
176: } finally {
177: IOUtils.closeSilently(in);
178: }
179: }
180:
181: private static void execute(Connection conn,
182: boolean continueOnError, String path, Reader reader,
183: String charsetName) throws SQLException, IOException {
184: Statement stat = conn.createStatement();
185: ScriptReader r = new ScriptReader(new BufferedReader(reader));
186: while (true) {
187: String sql = r.readStatement();
188: if (sql == null) {
189: break;
190: }
191: sql = sql.trim();
192: if (sql.startsWith("@")
193: && StringUtils.toUpperEnglish(sql).startsWith(
194: "@INCLUDE")) {
195: sql = sql.substring("@INCLUDE".length()).trim();
196: if (!FileUtils.isAbsolute(sql)) {
197: sql = path + File.separator + sql;
198: }
199: execute(conn, sql, continueOnError, charsetName);
200: } else {
201: try {
202: if (sql.trim().length() > 0) {
203: stat.execute(sql);
204: }
205: } catch (SQLException e) {
206: if (continueOnError) {
207: e.printStackTrace();
208: } else {
209: throw e;
210: }
211: }
212: }
213: }
214: }
215:
216: private static void executeRunscript(String url, String user,
217: String password, String fileName, String options)
218: throws SQLException {
219: Connection conn = null;
220: Statement stat = null;
221: try {
222: org.h2.Driver.load();
223: conn = DriverManager.getConnection(url, user, password);
224: stat = conn.createStatement();
225: String sql = "RUNSCRIPT FROM '" + fileName + "' " + options;
226: stat.execute(sql);
227: } finally {
228: JdbcUtils.closeSilently(stat);
229: JdbcUtils.closeSilently(conn);
230: }
231: }
232:
233: /**
234: * Executes the SQL commands in a script file against a database.
235: *
236: * @param url the database URL
237: * @param user the user name
238: * @param password the password
239: * @param fileName the script file
240: * @param charsetName the character set name or null for UTF-8
241: * @param continueOnError if execution should be continued if an error occurs
242: * @throws SQLException
243: */
244: public static void execute(String url, String user,
245: String password, String fileName, String charsetName,
246: boolean continueOnError) throws SQLException {
247: try {
248: org.h2.Driver.load();
249: Connection conn = DriverManager.getConnection(url, user,
250: password);
251: if (charsetName == null) {
252: charsetName = Constants.UTF8;
253: }
254: try {
255: execute(conn, fileName, continueOnError, charsetName);
256: } finally {
257: conn.close();
258: }
259: } catch (IOException e) {
260: throw Message.convertIOException(e, fileName);
261: }
262: }
263:
264: }
|