You can not select more than 25 topics Topics must start with a chinese character,a letter or number, can include dashes ('-') and can be up to 35 characters long.

SQLExec.java 25 kB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  1. /*
  2. * Licensed to the Apache Software Foundation (ASF) under one or more
  3. * contributor license agreements. See the NOTICE file distributed with
  4. * this work for additional information regarding copyright ownership.
  5. * The ASF licenses this file to You under the Apache License, Version 2.0
  6. * (the "License"); you may not use this file except in compliance with
  7. * the License. You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. *
  17. */
  18. package org.apache.tools.ant.taskdefs;
  19. import org.apache.tools.ant.BuildException;
  20. import org.apache.tools.ant.Project;
  21. import org.apache.tools.ant.util.FileUtils;
  22. import org.apache.tools.ant.util.StringUtils;
  23. import org.apache.tools.ant.types.EnumeratedAttribute;
  24. import org.apache.tools.ant.types.FileSet;
  25. import org.apache.tools.ant.types.Resource;
  26. import org.apache.tools.ant.types.ResourceCollection;
  27. import org.apache.tools.ant.types.resources.FileResource;
  28. import org.apache.tools.ant.types.resources.Union;
  29. import java.io.File;
  30. import java.io.PrintStream;
  31. import java.io.BufferedOutputStream;
  32. import java.io.FileOutputStream;
  33. import java.io.IOException;
  34. import java.io.Reader;
  35. import java.io.BufferedReader;
  36. import java.io.StringReader;
  37. import java.io.InputStream;
  38. import java.io.InputStreamReader;
  39. import java.util.Enumeration;
  40. import java.util.Iterator;
  41. import java.util.StringTokenizer;
  42. import java.util.Vector;
  43. import java.sql.Connection;
  44. import java.sql.Statement;
  45. import java.sql.SQLException;
  46. import java.sql.SQLWarning;
  47. import java.sql.ResultSet;
  48. import java.sql.ResultSetMetaData;
  49. import java.sql.Types;
  50. /**
  51. * Executes a series of SQL statements on a database using JDBC.
  52. *
  53. * <p>Statements can
  54. * either be read in from a text file using the <i>src</i> attribute or from
  55. * between the enclosing SQL tags.</p>
  56. *
  57. * <p>Multiple statements can be provided, separated by semicolons (or the
  58. * defined <i>delimiter</i>). Individual lines within the statements can be
  59. * commented using either --, // or REM at the start of the line.</p>
  60. *
  61. * <p>The <i>autocommit</i> attribute specifies whether auto-commit should be
  62. * turned on or off whilst executing the statements. If auto-commit is turned
  63. * on each statement will be executed and committed. If it is turned off the
  64. * statements will all be executed as one transaction.</p>
  65. *
  66. * <p>The <i>onerror</i> attribute specifies how to proceed when an error occurs
  67. * during the execution of one of the statements.
  68. * The possible values are: <b>continue</b> execution, only show the error;
  69. * <b>stop</b> execution and commit transaction;
  70. * and <b>abort</b> execution and transaction and fail task.</p>
  71. *
  72. * @since Ant 1.2
  73. *
  74. * @ant.task name="sql" category="database"
  75. */
  76. public class SQLExec extends JDBCTask {
  77. /**
  78. * delimiters we support, "normal" and "row"
  79. */
  80. public static class DelimiterType extends EnumeratedAttribute {
  81. /** The enumerated strings */
  82. public static final String NORMAL = "normal", ROW = "row";
  83. /** @return the enumerated strings */
  84. public String[] getValues() {
  85. return new String[] {NORMAL, ROW};
  86. }
  87. }
  88. private int goodSql = 0;
  89. private int totalSql = 0;
  90. /**
  91. * Database connection
  92. */
  93. private Connection conn = null;
  94. /**
  95. * files to load
  96. */
  97. private Union resources;
  98. /**
  99. * SQL statement
  100. */
  101. private Statement statement = null;
  102. /**
  103. * SQL input file
  104. */
  105. private File srcFile = null;
  106. /**
  107. * SQL input command
  108. */
  109. private String sqlCommand = "";
  110. /**
  111. * SQL transactions to perform
  112. */
  113. private Vector transactions = new Vector();
  114. /**
  115. * SQL Statement delimiter
  116. */
  117. private String delimiter = ";";
  118. /**
  119. * The delimiter type indicating whether the delimiter will
  120. * only be recognized on a line by itself
  121. */
  122. private String delimiterType = DelimiterType.NORMAL;
  123. /**
  124. * Print SQL results.
  125. */
  126. private boolean print = false;
  127. /**
  128. * Print header columns.
  129. */
  130. private boolean showheaders = true;
  131. /**
  132. * Print SQL stats (rows affected)
  133. */
  134. private boolean showtrailers = true;
  135. /**
  136. * Results Output file.
  137. */
  138. private File output = null;
  139. /**
  140. * Action to perform if an error is found
  141. **/
  142. private String onError = "abort";
  143. /**
  144. * Encoding to use when reading SQL statements from a file
  145. */
  146. private String encoding = null;
  147. /**
  148. * Append to an existing file or overwrite it?
  149. */
  150. private boolean append = false;
  151. /**
  152. * Keep the format of a sql block?
  153. */
  154. private boolean keepformat = false;
  155. /**
  156. * Argument to Statement.setEscapeProcessing
  157. *
  158. * @since Ant 1.6
  159. */
  160. private boolean escapeProcessing = true;
  161. /**
  162. * should properties be expanded in text?
  163. * false for backwards compatibility
  164. *
  165. * @since Ant 1.7
  166. */
  167. private boolean expandProperties = true;
  168. /**
  169. * should we print raw BLOB data?
  170. * @since Ant 1.7.1
  171. */
  172. private boolean rawBlobs;
  173. /**
  174. * Set the name of the SQL file to be run.
  175. * Required unless statements are enclosed in the build file
  176. * @param srcFile the file containing the SQL command.
  177. */
  178. public void setSrc(File srcFile) {
  179. this.srcFile = srcFile;
  180. }
  181. /**
  182. * Enable property expansion inside nested text
  183. *
  184. * @param expandProperties if true expand properties.
  185. * @since Ant 1.7
  186. */
  187. public void setExpandProperties(boolean expandProperties) {
  188. this.expandProperties = expandProperties;
  189. }
  190. /**
  191. * is property expansion inside inline text enabled?
  192. *
  193. * @return true if properties are to be expanded.
  194. * @since Ant 1.7
  195. */
  196. public boolean getExpandProperties() {
  197. return expandProperties;
  198. }
  199. /**
  200. * Set an inline SQL command to execute.
  201. * NB: Properties are not expanded in this text unless {@link #expandProperties}
  202. * is set.
  203. * @param sql an inline string containing the SQL command.
  204. */
  205. public void addText(String sql) {
  206. //there is no need to expand properties here as that happens when Transaction.addText is
  207. //called; to do so here would be an error.
  208. this.sqlCommand += sql;
  209. }
  210. /**
  211. * Adds a set of files (nested fileset attribute).
  212. * @param set a set of files contains SQL commands, each File is run in
  213. * a separate transaction.
  214. */
  215. public void addFileset(FileSet set) {
  216. add(set);
  217. }
  218. /**
  219. * Adds a collection of resources (nested element).
  220. * @param rc a collection of resources containing SQL commands,
  221. * each resource is run in a separate transaction.
  222. * @since Ant 1.7
  223. */
  224. public void add(ResourceCollection rc) {
  225. if (rc == null) {
  226. throw new BuildException("Cannot add null ResourceCollection");
  227. }
  228. synchronized (this) {
  229. if (resources == null) {
  230. resources = new Union();
  231. }
  232. }
  233. resources.add(rc);
  234. }
  235. /**
  236. * Add a SQL transaction to execute
  237. * @return a Transaction to be configured.
  238. */
  239. public Transaction createTransaction() {
  240. Transaction t = new Transaction();
  241. transactions.addElement(t);
  242. return t;
  243. }
  244. /**
  245. * Set the file encoding to use on the SQL files read in
  246. *
  247. * @param encoding the encoding to use on the files
  248. */
  249. public void setEncoding(String encoding) {
  250. this.encoding = encoding;
  251. }
  252. /**
  253. * Set the delimiter that separates SQL statements. Defaults to &quot;;&quot;;
  254. * optional
  255. *
  256. * <p>For example, set this to "go" and delimitertype to "ROW" for
  257. * Sybase ASE or MS SQL Server.</p>
  258. * @param delimiter the separator.
  259. */
  260. public void setDelimiter(String delimiter) {
  261. this.delimiter = delimiter;
  262. }
  263. /**
  264. * Set the delimiter type: "normal" or "row" (default "normal").
  265. *
  266. * <p>The delimiter type takes two values - normal and row. Normal
  267. * means that any occurrence of the delimiter terminate the SQL
  268. * command whereas with row, only a line containing just the
  269. * delimiter is recognized as the end of the command.</p>
  270. * @param delimiterType the type of delimiter - "normal" or "row".
  271. */
  272. public void setDelimiterType(DelimiterType delimiterType) {
  273. this.delimiterType = delimiterType.getValue();
  274. }
  275. /**
  276. * Print result sets from the statements;
  277. * optional, default false
  278. * @param print if true print result sets.
  279. */
  280. public void setPrint(boolean print) {
  281. this.print = print;
  282. }
  283. /**
  284. * Print headers for result sets from the
  285. * statements; optional, default true.
  286. * @param showheaders if true print headers of result sets.
  287. */
  288. public void setShowheaders(boolean showheaders) {
  289. this.showheaders = showheaders;
  290. }
  291. /**
  292. * Print trailing info (rows affected) for the SQL
  293. * Addresses Bug/Request #27446
  294. * @param showtrailers if true prints the SQL rows affected
  295. * @since Ant 1.7
  296. */
  297. public void setShowtrailers(boolean showtrailers) {
  298. this.showtrailers = showtrailers;
  299. }
  300. /**
  301. * Set the output file;
  302. * optional, defaults to the Ant log.
  303. * @param output the output file to use for logging messages.
  304. */
  305. public void setOutput(File output) {
  306. this.output = output;
  307. }
  308. /**
  309. * whether output should be appended to or overwrite
  310. * an existing file. Defaults to false.
  311. *
  312. * @since Ant 1.5
  313. * @param append if true append to an existing file.
  314. */
  315. public void setAppend(boolean append) {
  316. this.append = append;
  317. }
  318. /**
  319. * Action to perform when statement fails: continue, stop, or abort
  320. * optional; default &quot;abort&quot;
  321. * @param action the action to perform on statement failure.
  322. */
  323. public void setOnerror(OnError action) {
  324. this.onError = action.getValue();
  325. }
  326. /**
  327. * whether or not format should be preserved.
  328. * Defaults to false.
  329. *
  330. * @param keepformat The keepformat to set
  331. */
  332. public void setKeepformat(boolean keepformat) {
  333. this.keepformat = keepformat;
  334. }
  335. /**
  336. * Set escape processing for statements.
  337. * @param enable if true enable escape processing, default is true.
  338. * @since Ant 1.6
  339. */
  340. public void setEscapeProcessing(boolean enable) {
  341. escapeProcessing = enable;
  342. }
  343. /**
  344. * Set whether to print raw BLOBs rather than their string (hex) representations.
  345. * @param rawBlobs whether to print raw BLOBs.
  346. * @since Ant 1.7.1
  347. */
  348. public void setRawBlobs(boolean rawBlobs) {
  349. this.rawBlobs = rawBlobs;
  350. }
  351. /**
  352. * Load the sql file and then execute it
  353. * @throws BuildException on error.
  354. */
  355. public void execute() throws BuildException {
  356. Vector savedTransaction = (Vector) transactions.clone();
  357. String savedSqlCommand = sqlCommand;
  358. sqlCommand = sqlCommand.trim();
  359. try {
  360. if (srcFile == null && sqlCommand.length() == 0 && resources == null) {
  361. if (transactions.size() == 0) {
  362. throw new BuildException("Source file or resource collection, "
  363. + "transactions or sql statement "
  364. + "must be set!", getLocation());
  365. }
  366. }
  367. if (srcFile != null && !srcFile.isFile()) {
  368. throw new BuildException("Source file " + srcFile
  369. + " is not a file!", getLocation());
  370. }
  371. if (resources != null) {
  372. // deal with the resources
  373. Iterator iter = resources.iterator();
  374. while (iter.hasNext()) {
  375. Resource r = (Resource) iter.next();
  376. // Make a transaction for each resource
  377. Transaction t = createTransaction();
  378. t.setSrcResource(r);
  379. }
  380. }
  381. // Make a transaction group for the outer command
  382. Transaction t = createTransaction();
  383. t.setSrc(srcFile);
  384. t.addText(sqlCommand);
  385. conn = getConnection();
  386. if (!isValidRdbms(conn)) {
  387. return;
  388. }
  389. try {
  390. statement = conn.createStatement();
  391. statement.setEscapeProcessing(escapeProcessing);
  392. PrintStream out = System.out;
  393. try {
  394. if (output != null) {
  395. log("Opening PrintStream to output file " + output, Project.MSG_VERBOSE);
  396. out = new PrintStream(new BufferedOutputStream(
  397. new FileOutputStream(output.getAbsolutePath(), append)));
  398. }
  399. // Process all transactions
  400. for (Enumeration e = transactions.elements();
  401. e.hasMoreElements();) {
  402. ((Transaction) e.nextElement()).runTransaction(out);
  403. if (!isAutocommit()) {
  404. log("Committing transaction", Project.MSG_VERBOSE);
  405. conn.commit();
  406. }
  407. }
  408. } finally {
  409. FileUtils.close(out);
  410. }
  411. } catch (IOException e) {
  412. closeQuietly();
  413. if (onError.equals("abort")) {
  414. throw new BuildException(e, getLocation());
  415. }
  416. } catch (SQLException e) {
  417. closeQuietly();
  418. if (onError.equals("abort")) {
  419. throw new BuildException(e, getLocation());
  420. }
  421. } finally {
  422. try {
  423. if (statement != null) {
  424. statement.close();
  425. }
  426. } catch (SQLException ex) {
  427. // ignore
  428. }
  429. try {
  430. if (conn != null) {
  431. conn.close();
  432. }
  433. } catch (SQLException ex) {
  434. // ignore
  435. }
  436. }
  437. log(goodSql + " of " + totalSql + " SQL statements executed successfully");
  438. } finally {
  439. transactions = savedTransaction;
  440. sqlCommand = savedSqlCommand;
  441. }
  442. }
  443. /**
  444. * read in lines and execute them
  445. * @param reader the reader contains sql lines.
  446. * @param out the place to output results.
  447. * @throws SQLException on sql problems
  448. * @throws IOException on io problems
  449. */
  450. protected void runStatements(Reader reader, PrintStream out)
  451. throws SQLException, IOException {
  452. StringBuffer sql = new StringBuffer();
  453. String line;
  454. BufferedReader in = new BufferedReader(reader);
  455. while ((line = in.readLine()) != null) {
  456. if (!keepformat) {
  457. line = line.trim();
  458. }
  459. if (expandProperties) {
  460. line = getProject().replaceProperties(line);
  461. }
  462. if (!keepformat) {
  463. if (line.startsWith("//")) {
  464. continue;
  465. }
  466. if (line.startsWith("--")) {
  467. continue;
  468. }
  469. StringTokenizer st = new StringTokenizer(line);
  470. if (st.hasMoreTokens()) {
  471. String token = st.nextToken();
  472. if ("REM".equalsIgnoreCase(token)) {
  473. continue;
  474. }
  475. }
  476. }
  477. sql.append(keepformat ? "\n" : " ").append(line);
  478. // SQL defines "--" as a comment to EOL
  479. // and in Oracle it may contain a hint
  480. // so we cannot just remove it, instead we must end it
  481. if (!keepformat && line.indexOf("--") >= 0) {
  482. sql.append("\n");
  483. }
  484. if ((delimiterType.equals(DelimiterType.NORMAL) && StringUtils.endsWith(sql, delimiter))
  485. || (delimiterType.equals(DelimiterType.ROW) && line.equals(delimiter))) {
  486. execSQL(sql.substring(0, sql.length() - delimiter.length()), out);
  487. sql.replace(0, sql.length(), "");
  488. }
  489. }
  490. // Catch any statements not followed by ;
  491. if (sql.length() > 0) {
  492. execSQL(sql.toString(), out);
  493. }
  494. }
  495. /**
  496. * Exec the sql statement.
  497. * @param sql the SQL statement to execute
  498. * @param out the place to put output
  499. * @throws SQLException on SQL problems
  500. */
  501. protected void execSQL(String sql, PrintStream out) throws SQLException {
  502. // Check and ignore empty statements
  503. if ("".equals(sql.trim())) {
  504. return;
  505. }
  506. ResultSet resultSet = null;
  507. try {
  508. totalSql++;
  509. log("SQL: " + sql, Project.MSG_VERBOSE);
  510. boolean ret;
  511. int updateCount = 0, updateCountTotal = 0;
  512. ret = statement.execute(sql);
  513. updateCount = statement.getUpdateCount();
  514. resultSet = statement.getResultSet();
  515. do {
  516. if (!ret) {
  517. if (updateCount != -1) {
  518. updateCountTotal += updateCount;
  519. }
  520. } else if (print) {
  521. printResults(resultSet, out);
  522. }
  523. ret = statement.getMoreResults();
  524. if (ret) {
  525. updateCount = statement.getUpdateCount();
  526. resultSet = statement.getResultSet();
  527. }
  528. } while (ret);
  529. log(updateCountTotal + " rows affected", Project.MSG_VERBOSE);
  530. if (print && showtrailers) {
  531. out.println(updateCountTotal + " rows affected");
  532. }
  533. SQLWarning warning = conn.getWarnings();
  534. while (warning != null) {
  535. log(warning + " sql warning", Project.MSG_VERBOSE);
  536. warning = warning.getNextWarning();
  537. }
  538. conn.clearWarnings();
  539. goodSql++;
  540. } catch (SQLException e) {
  541. log("Failed to execute: " + sql, Project.MSG_ERR);
  542. if (!onError.equals("abort")) {
  543. log(e.toString(), Project.MSG_ERR);
  544. }
  545. if (!onError.equals("continue")) {
  546. throw e;
  547. }
  548. } finally {
  549. if (resultSet != null) {
  550. try {
  551. resultSet.close();
  552. } catch (SQLException e) {
  553. //ignore
  554. }
  555. }
  556. }
  557. }
  558. /**
  559. * print any results in the statement
  560. * @deprecated since 1.6.x.
  561. * Use {@link #printResults(java.sql.ResultSet, java.io.PrintStream)
  562. * the two arg version} instead.
  563. * @param out the place to print results
  564. * @throws SQLException on SQL problems.
  565. */
  566. protected void printResults(PrintStream out) throws SQLException {
  567. ResultSet rs = statement.getResultSet();
  568. try {
  569. printResults(rs, out);
  570. } finally {
  571. if (rs != null) {
  572. rs.close();
  573. }
  574. }
  575. }
  576. /**
  577. * print any results in the result set.
  578. * @param rs the resultset to print information about
  579. * @param out the place to print results
  580. * @throws SQLException on SQL problems.
  581. * @since Ant 1.6.3
  582. */
  583. protected void printResults(ResultSet rs, PrintStream out) throws SQLException {
  584. if (rs != null) {
  585. log("Processing new result set.", Project.MSG_VERBOSE);
  586. ResultSetMetaData md = rs.getMetaData();
  587. int columnCount = md.getColumnCount();
  588. if (columnCount > 0) {
  589. if (showheaders) {
  590. out.print(md.getColumnName(1));
  591. for (int col = 2; col <= columnCount; col++) {
  592. out.write(',');
  593. out.print(md.getColumnName(col));
  594. }
  595. out.println();
  596. }
  597. while (rs.next()) {
  598. printValue(rs, 1, out);
  599. for (int col = 2; col <= columnCount; col++) {
  600. out.write(',');
  601. printValue(rs, col, out);
  602. }
  603. out.println();
  604. }
  605. }
  606. }
  607. out.println();
  608. }
  609. private void printValue(ResultSet rs, int col, PrintStream out)
  610. throws SQLException {
  611. if (rawBlobs && rs.getMetaData().getColumnType(col) == Types.BLOB) {
  612. new StreamPumper(rs.getBlob(col).getBinaryStream(), out).run();
  613. } else {
  614. out.print(rs.getString(col));
  615. }
  616. }
  617. /*
  618. * Closes an unused connection after an error and doesn't rethrow
  619. * a possible SQLException
  620. * @since Ant 1.7
  621. */
  622. private void closeQuietly() {
  623. if (!isAutocommit() && conn != null && onError.equals("abort")) {
  624. try {
  625. conn.rollback();
  626. } catch (SQLException ex) {
  627. // ignore
  628. }
  629. }
  630. }
  631. /**
  632. * The action a task should perform on an error,
  633. * one of "continue", "stop" and "abort"
  634. */
  635. public static class OnError extends EnumeratedAttribute {
  636. /** @return the enumerated values */
  637. public String[] getValues() {
  638. return new String[] {"continue", "stop", "abort"};
  639. }
  640. }
  641. /**
  642. * Contains the definition of a new transaction element.
  643. * Transactions allow several files or blocks of statements
  644. * to be executed using the same JDBC connection and commit
  645. * operation in between.
  646. */
  647. public class Transaction {
  648. private Resource tSrcResource = null;
  649. private String tSqlCommand = "";
  650. /**
  651. * Set the source file attribute.
  652. * @param src the source file
  653. */
  654. public void setSrc(File src) {
  655. //there are places (in this file, and perhaps elsewhere, where it is assumed
  656. //that null is an acceptable parameter.
  657. if (src != null) {
  658. setSrcResource(new FileResource(src));
  659. }
  660. }
  661. /**
  662. * Set the source resource attribute.
  663. * @param src the source file
  664. * @since Ant 1.7
  665. */
  666. public void setSrcResource(Resource src) {
  667. if (tSrcResource != null) {
  668. throw new BuildException("only one resource per transaction");
  669. }
  670. tSrcResource = src;
  671. }
  672. /**
  673. * Set inline text
  674. * @param sql the inline text
  675. */
  676. public void addText(String sql) {
  677. if (sql != null) {
  678. this.tSqlCommand += sql;
  679. }
  680. }
  681. /**
  682. * Set the source resource.
  683. * @param a the source resource collection.
  684. * @since Ant 1.7
  685. */
  686. public void addConfigured(ResourceCollection a) {
  687. if (a.size() != 1) {
  688. throw new BuildException("only single argument resource "
  689. + "collections are supported.");
  690. }
  691. setSrcResource((Resource) a.iterator().next());
  692. }
  693. /**
  694. *
  695. */
  696. private void runTransaction(PrintStream out)
  697. throws IOException, SQLException {
  698. if (tSqlCommand.length() != 0) {
  699. log("Executing commands", Project.MSG_INFO);
  700. runStatements(new StringReader(tSqlCommand), out);
  701. }
  702. if (tSrcResource != null) {
  703. log("Executing resource: " + tSrcResource.toString(),
  704. Project.MSG_INFO);
  705. InputStream is = null;
  706. Reader reader = null;
  707. try {
  708. is = tSrcResource.getInputStream();
  709. reader = (encoding == null) ? new InputStreamReader(is)
  710. : new InputStreamReader(is, encoding);
  711. runStatements(reader, out);
  712. } finally {
  713. FileUtils.close(is);
  714. FileUtils.close(reader);
  715. }
  716. }
  717. }
  718. }
  719. }