/*
 *  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
 *
 *      https://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.tools.ant.taskdefs;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.Reader;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.sql.Blob;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.sql.Types;
import java.util.List;
import java.util.Locale;
import java.util.StringTokenizer;
import java.util.Vector;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.Appendable;
import org.apache.tools.ant.types.resources.FileProvider;
import org.apache.tools.ant.types.resources.FileResource;
import org.apache.tools.ant.types.resources.Union;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.KeepAliveOutputStream;
import org.apache.tools.ant.util.StringUtils;

Executes a series of SQL statements on a database using JDBC.

Statements can either be read in from a text file using the src attribute or from between the enclosing SQL tags.

Multiple statements can be provided, separated by semicolons (or the defined delimiter). Individual lines within the statements can be commented using either --, // or REM at the start of the line.

The autocommit attribute specifies whether auto-commit should be turned on or off whilst executing the statements. If auto-commit is turned on each statement will be executed and committed. If it is turned off the statements will all be executed as one transaction.

The onerror attribute specifies how to proceed when an error occurs during the execution of one of the statements. The possible values are: continue execution, only show the error; stop execution and commit transaction; and abort execution and transaction and fail task.

Since:Ant 1.2
@ant.taskname="sql" category="database"
/** * Executes a series of SQL statements on a database using JDBC. * * <p>Statements can * either be read in from a text file using the <i>src</i> attribute or from * between the enclosing SQL tags.</p> * * <p>Multiple statements can be provided, separated by semicolons (or the * defined <i>delimiter</i>). Individual lines within the statements can be * commented using either --, // or REM at the start of the line.</p> * * <p>The <i>autocommit</i> attribute specifies whether auto-commit should be * turned on or off whilst executing the statements. If auto-commit is turned * on each statement will be executed and committed. If it is turned off the * statements will all be executed as one transaction.</p> * * <p>The <i>onerror</i> attribute specifies how to proceed when an error occurs * during the execution of one of the statements. * The possible values are: <b>continue</b> execution, only show the error; * <b>stop</b> execution and commit transaction; * and <b>abort</b> execution and transaction and fail task.</p> * * @since Ant 1.2 * * @ant.task name="sql" category="database" */
public class SQLExec extends JDBCTask {
delimiters we support, "normal" and "row"
/** * delimiters we support, "normal" and "row" */
public static class DelimiterType extends EnumeratedAttribute {
The enumerated strings
/** The enumerated strings */
public static final String NORMAL = "normal", ROW = "row";
Returns:the enumerated strings
/** @return the enumerated strings */
@Override public String[] getValues() { return new String[] {NORMAL, ROW}; } } private int goodSql = 0; private int totalSql = 0;
Database connection
/** * Database connection */
private Connection conn = null;
files to load
/** * files to load */
private Union resources;
SQL statement
/** * SQL statement */
private Statement statement = null;
SQL input file
/** * SQL input file */
private File srcFile = null;
SQL input command
/** * SQL input command */
private String sqlCommand = "";
SQL transactions to perform
/** * SQL transactions to perform */
private List<Transaction> transactions = new Vector<>();
SQL Statement delimiter
/** * SQL Statement delimiter */
private String delimiter = ";";
The delimiter type indicating whether the delimiter will only be recognized on a line by itself
/** * The delimiter type indicating whether the delimiter will * only be recognized on a line by itself */
private String delimiterType = DelimiterType.NORMAL;
Print SQL results.
/** * Print SQL results. */
private boolean print = false;
Print header columns.
/** * Print header columns. */
private boolean showheaders = true;
Print SQL stats (rows affected)
/** * Print SQL stats (rows affected) */
private boolean showtrailers = true;
Results Output Resource.
/** * Results Output Resource. */
private Resource output = null;
Output encoding.
/** * Output encoding. */
private String outputEncoding = null;
Action to perform if an error is found
/** * Action to perform if an error is found */
private String onError = "abort";
Encoding to use when reading SQL statements from a file
/** * Encoding to use when reading SQL statements from a file */
private String encoding = null;
Append to an existing file or overwrite it?
/** * Append to an existing file or overwrite it? */
private boolean append = false;
Keep the format of a sql block?
/** * Keep the format of a sql block? */
private boolean keepformat = false;
Argument to Statement.setEscapeProcessing
Since:Ant 1.6
/** * Argument to Statement.setEscapeProcessing * * @since Ant 1.6 */
private boolean escapeProcessing = true;
should properties be expanded in text? false for backwards compatibility
Since:Ant 1.7
/** * should properties be expanded in text? * false for backwards compatibility * * @since Ant 1.7 */
private boolean expandProperties = true;
should we print raw BLOB data?
Since:Ant 1.7.1
/** * should we print raw BLOB data? * @since Ant 1.7.1 */
private boolean rawBlobs;
delimiters must match in case and whitespace is significant.
Since:Ant 1.8.0
/** * delimiters must match in case and whitespace is significant. * @since Ant 1.8.0 */
private boolean strictDelimiterMatching = true;
whether to show SQLWarnings as WARN messages.
Since:Ant 1.8.0
/** * whether to show SQLWarnings as WARN messages. * @since Ant 1.8.0 */
private boolean showWarnings = false;
The column separator used when printing the results.

Defaults to ","

Since:Ant 1.8.0
/** * The column separator used when printing the results. * * <p>Defaults to ","</p> * * @since Ant 1.8.0 */
private String csvColumnSep = ",";
The character used to quote column values.

If set, columns that contain either the column separator or the quote character itself will be surrounded by the quote character. The quote character itself will be doubled if it appears inside of the column's value.

If this value is not set (the default), no column values will be quoted, not even if they contain the column separator.

Note: BLOB values will never be quoted.

Defaults to "not set"

Since:Ant 1.8.0
/** * The character used to quote column values. * * <p>If set, columns that contain either the column separator or * the quote character itself will be surrounded by the quote * character. The quote character itself will be doubled if it * appears inside of the column's value.</p> * * <p>If this value is not set (the default), no column values * will be quoted, not even if they contain the column * separator.</p> * * <p><b>Note:<b> BLOB values will never be quoted.</p> * * <p>Defaults to "not set"</p> * * @since Ant 1.8.0 */
private String csvQuoteChar = null;
Whether a warning is an error - in which case onError applies.
Since:Ant 1.8.0
/** * Whether a warning is an error - in which case onError applies. * @since Ant 1.8.0 */
private boolean treatWarningsAsErrors = false;
The name of the property to set in the event of an error
Since:Ant 1.8.0
/** * The name of the property to set in the event of an error * @since Ant 1.8.0 */
private String errorProperty = null;
The name of the property to set in the event of a warning
Since:Ant 1.8.0
/** * The name of the property to set in the event of a warning * @since Ant 1.8.0 */
private String warningProperty = null;
The name of the property that receives the number of rows returned
Since:Ant 1.8.0
/** * The name of the property that receives the number of rows * returned * @since Ant 1.8.0 */
private String rowCountProperty = null;
The name of the property to force the csv quote character
/** * The name of the property to force the csv quote character */
private boolean forceCsvQuoteChar = false;
Set the name of the SQL file to be run. Required unless statements are enclosed in the build file
Params:
  • srcFile – the file containing the SQL command.
/** * Set the name of the SQL file to be run. * Required unless statements are enclosed in the build file * @param srcFile the file containing the SQL command. */
public void setSrc(File srcFile) { this.srcFile = srcFile; }
Enable property expansion inside nested text
Params:
  • expandProperties – if true expand properties.
Since:Ant 1.7
/** * Enable property expansion inside nested text * * @param expandProperties if true expand properties. * @since Ant 1.7 */
public void setExpandProperties(boolean expandProperties) { this.expandProperties = expandProperties; }
is property expansion inside inline text enabled?
Returns:true if properties are to be expanded.
Since:Ant 1.7
/** * is property expansion inside inline text enabled? * * @return true if properties are to be expanded. * @since Ant 1.7 */
public boolean getExpandProperties() { return expandProperties; }
Set an inline SQL command to execute. NB: Properties are not expanded in this text unless expandProperties is set.
Params:
  • sql – an inline string containing the SQL command.
/** * Set an inline SQL command to execute. * NB: Properties are not expanded in this text unless {@link #expandProperties} * is set. * @param sql an inline string containing the SQL command. */
public void addText(String sql) { //there is no need to expand properties here as that happens when Transaction.addText is //called; to do so here would be an error. this.sqlCommand += sql; }
Adds a set of files (nested fileset attribute).
Params:
  • set – a set of files contains SQL commands, each File is run in a separate transaction.
/** * Adds a set of files (nested fileset attribute). * @param set a set of files contains SQL commands, each File is run in * a separate transaction. */
public void addFileset(FileSet set) { add(set); }
Adds a collection of resources (nested element).
Params:
  • rc – a collection of resources containing SQL commands, each resource is run in a separate transaction.
Since:Ant 1.7
/** * Adds a collection of resources (nested element). * @param rc a collection of resources containing SQL commands, * each resource is run in a separate transaction. * @since Ant 1.7 */
public void add(ResourceCollection rc) { if (rc == null) { throw new BuildException("Cannot add null ResourceCollection"); } synchronized (this) { if (resources == null) { resources = new Union(); } } resources.add(rc); }
Add a SQL transaction to execute
Returns:a Transaction to be configured.
/** * Add a SQL transaction to execute * @return a Transaction to be configured. */
public Transaction createTransaction() { Transaction t = new Transaction(); transactions.add(t); return t; }
Set the file encoding to use on the SQL files read in
Params:
  • encoding – the encoding to use on the files
/** * Set the file encoding to use on the SQL files read in * * @param encoding the encoding to use on the files */
public void setEncoding(String encoding) { this.encoding = encoding; }
Set the delimiter that separates SQL statements. Defaults to ";"; optional

For example, set this to "go" and delimitertype to "ROW" for Sybase ASE or MS SQL Server.

Params:
  • delimiter – the separator.
/** * Set the delimiter that separates SQL statements. Defaults to &quot;;&quot;; * optional * * <p>For example, set this to "go" and delimitertype to "ROW" for * Sybase ASE or MS SQL Server.</p> * @param delimiter the separator. */
public void setDelimiter(String delimiter) { this.delimiter = delimiter; }
Set the delimiter type: "normal" or "row" (default "normal").

The delimiter type takes two values - normal and row. Normal means that any occurrence of the delimiter terminate the SQL command whereas with row, only a line containing just the delimiter is recognized as the end of the command.

Params:
  • delimiterType – the type of delimiter - "normal" or "row".
/** * Set the delimiter type: "normal" or "row" (default "normal"). * * <p>The delimiter type takes two values - normal and row. Normal * means that any occurrence of the delimiter terminate the SQL * command whereas with row, only a line containing just the * delimiter is recognized as the end of the command.</p> * @param delimiterType the type of delimiter - "normal" or "row". */
public void setDelimiterType(DelimiterType delimiterType) { this.delimiterType = delimiterType.getValue(); }
Print result sets from the statements; optional, default false
Params:
  • print – if true print result sets.
/** * Print result sets from the statements; * optional, default false * @param print if true print result sets. */
public void setPrint(boolean print) { this.print = print; }
Print headers for result sets from the statements; optional, default true.
Params:
  • showheaders – if true print headers of result sets.
/** * Print headers for result sets from the * statements; optional, default true. * @param showheaders if true print headers of result sets. */
public void setShowheaders(boolean showheaders) { this.showheaders = showheaders; }
Print trailing info (rows affected) for the SQL Addresses Bug/Request #27446
Params:
  • showtrailers – if true prints the SQL rows affected
Since:Ant 1.7
/** * Print trailing info (rows affected) for the SQL * Addresses Bug/Request #27446 * @param showtrailers if true prints the SQL rows affected * @since Ant 1.7 */
public void setShowtrailers(boolean showtrailers) { this.showtrailers = showtrailers; }
Set the output file; optional, defaults to the Ant log.
Params:
  • output – the output file to use for logging messages.
/** * Set the output file; * optional, defaults to the Ant log. * @param output the output file to use for logging messages. */
public void setOutput(File output) { setOutput(new FileResource(getProject(), output)); }
Set the output Resource; optional, defaults to the Ant log.
Params:
  • output – the output Resource to store results.
Since:Ant 1.8
/** * Set the output Resource; * optional, defaults to the Ant log. * @param output the output Resource to store results. * @since Ant 1.8 */
public void setOutput(Resource output) { this.output = output; }
The encoding to use when writing the result to a resource.

Default's to the platform's default encoding

Params:
  • outputEncoding – the name of the encoding or null for the platform's default encoding
Since:Ant 1.9.4
/** * The encoding to use when writing the result to a resource. * <p>Default's to the platform's default encoding</p> * @param outputEncoding the name of the encoding or null for the * platform's default encoding * @since Ant 1.9.4 */
public void setOutputEncoding(String outputEncoding) { this.outputEncoding = outputEncoding; }
whether output should be appended to or overwrite an existing file. Defaults to false.
Params:
  • append – if true append to an existing file.
Since:Ant 1.5
/** * whether output should be appended to or overwrite * an existing file. Defaults to false. * * @since Ant 1.5 * @param append if true append to an existing file. */
public void setAppend(boolean append) { this.append = append; }
Action to perform when statement fails: continue, stop, or abort optional; default "abort"
Params:
  • action – the action to perform on statement failure.
/** * Action to perform when statement fails: continue, stop, or abort * optional; default &quot;abort&quot; * @param action the action to perform on statement failure. */
public void setOnerror(OnError action) { this.onError = action.getValue(); }
whether or not format should be preserved. Defaults to false.
Params:
  • keepformat – The keepformat to set
/** * whether or not format should be preserved. * Defaults to false. * * @param keepformat The keepformat to set */
public void setKeepformat(boolean keepformat) { this.keepformat = keepformat; }
Set escape processing for statements.
Params:
  • enable – if true enable escape processing, default is true.
Since:Ant 1.6
/** * Set escape processing for statements. * @param enable if true enable escape processing, default is true. * @since Ant 1.6 */
public void setEscapeProcessing(boolean enable) { escapeProcessing = enable; }
Set whether to print raw BLOBs rather than their string (hex) representations.
Params:
  • rawBlobs – whether to print raw BLOBs.
Since:Ant 1.7.1
/** * Set whether to print raw BLOBs rather than their string (hex) representations. * @param rawBlobs whether to print raw BLOBs. * @since Ant 1.7.1 */
public void setRawBlobs(boolean rawBlobs) { this.rawBlobs = rawBlobs; }
If false, delimiters will be searched for in a case-insensitive manner (i.e. delimiter="go" matches "GO") and surrounding whitespace will be ignored (delimiter="go" matches "GO ").
Params:
  • b – boolean
Since:Ant 1.8.0
/** * If false, delimiters will be searched for in a case-insensitive * manner (i.e. delimiter="go" matches "GO") and surrounding * whitespace will be ignored (delimiter="go" matches "GO "). * * @param b boolean * @since Ant 1.8.0 */
public void setStrictDelimiterMatching(boolean b) { strictDelimiterMatching = b; }
whether to show SQLWarnings as WARN messages.
Params:
  • b – boolean
Since:Ant 1.8.0
/** * whether to show SQLWarnings as WARN messages. * * @param b boolean * @since Ant 1.8.0 */
public void setShowWarnings(boolean b) { showWarnings = b; }
Whether a warning is an error - in which case onError applies.
Params:
  • b – boolean
Since:Ant 1.8.0
/** * Whether a warning is an error - in which case onError applies. * * @param b boolean * @since Ant 1.8.0 */
public void setTreatWarningsAsErrors(boolean b) { treatWarningsAsErrors = b; }
The column separator used when printing the results.

Defaults to ","

Params:
  • s – String
Since:Ant 1.8.0
/** * The column separator used when printing the results. * * <p>Defaults to ","</p> * * @param s String * @since Ant 1.8.0 */
public void setCsvColumnSeparator(String s) { csvColumnSep = s; }
The character used to quote column values.

If set, columns that contain either the column separator or the quote character itself will be surrounded by the quote character. The quote character itself will be doubled if it appears inside of the column's value.

If this value is not set (the default), no column values will be quoted, not even if they contain the column separator.

Note: BLOB values will never be quoted.

Defaults to "not set"

Params:
  • s – String
Since:Ant 1.8.0
/** * The character used to quote column values. * * <p>If set, columns that contain either the column separator or * the quote character itself will be surrounded by the quote * character. The quote character itself will be doubled if it * appears inside of the column's value.</p> * * <p>If this value is not set (the default), no column values * will be quoted, not even if they contain the column * separator.</p> * * <p><b>Note:</b> BLOB values will never be quoted.</p> * * <p>Defaults to "not set"</p> * * @param s String * @since Ant 1.8.0 */
public void setCsvQuoteCharacter(String s) { if (s != null && s.length() > 1) { throw new BuildException( "The quote character must be a single character."); } csvQuoteChar = s; }
Property to set to "true" if a statement throws an error.
Params:
  • errorProperty – the name of the property to set in the event of an error.
Since:Ant 1.8.0
/** * Property to set to "true" if a statement throws an error. * * @param errorProperty the name of the property to set in the * event of an error. * @since Ant 1.8.0 */
public void setErrorProperty(String errorProperty) { this.errorProperty = errorProperty; }
Property to set to "true" if a statement produces a warning.
Params:
  • warningProperty – the name of the property to set in the event of a warning.
Since:Ant 1.8.0
/** * Property to set to "true" if a statement produces a warning. * * @param warningProperty the name of the property to set in the * event of a warning. * @since Ant 1.8.0 */
public void setWarningProperty(String warningProperty) { this.warningProperty = warningProperty; }
Sets a given property to the number of rows in the first statement that returned a row count.
Params:
  • rowCountProperty – String
Since:Ant 1.8.0
/** * Sets a given property to the number of rows in the first * statement that returned a row count. * @param rowCountProperty String * @since Ant 1.8.0 */
public void setRowCountProperty(String rowCountProperty) { this.rowCountProperty = rowCountProperty; }
Force the csv quote character
Params:
  • forceCsvQuoteChar – boolean
/** * Force the csv quote character * @param forceCsvQuoteChar boolean */
public void setForceCsvQuoteChar(boolean forceCsvQuoteChar) { this.forceCsvQuoteChar = forceCsvQuoteChar; }
Load the sql file and then execute it
Throws:
  • BuildException – on error.
/** * Load the sql file and then execute it * @throws BuildException on error. */
@Override public void execute() throws BuildException { List<Transaction> savedTransaction = new Vector<>(transactions); String savedSqlCommand = sqlCommand; sqlCommand = sqlCommand.trim(); try { if (srcFile == null && sqlCommand.isEmpty() && resources == null) { if (transactions.isEmpty()) { throw new BuildException( "Source file or resource collection, transactions or sql statement must be set!", getLocation()); } } if (srcFile != null && !srcFile.isFile()) { throw new BuildException("Source file " + srcFile + " is not a file!", getLocation()); } if (resources != null) { // deal with the resources for (Resource r : resources) { // Make a transaction for each resource Transaction t = createTransaction(); t.setSrcResource(r); } } // Make a transaction group for the outer command Transaction t = createTransaction(); t.setSrc(srcFile); t.addText(sqlCommand); if (getConnection() == null) { // not a valid rdbms return; } try { PrintStream out = KeepAliveOutputStream.wrapSystemOut(); try { if (output != null) { log("Opening PrintStream to output Resource " + output, Project.MSG_VERBOSE); OutputStream os = null; FileProvider fp = output.as(FileProvider.class); if (fp != null) { os = FileUtils.newOutputStream(fp.getFile().toPath(), append); } else { if (append) { Appendable a = output.as(Appendable.class); if (a != null) { os = a.getAppendOutputStream(); } } if (os == null) { os = output.getOutputStream(); if (append) { log("Ignoring append=true for non-appendable" + " resource " + output, Project.MSG_WARN); } } } if (outputEncoding != null) { out = new PrintStream(new BufferedOutputStream(os), false, outputEncoding); } else { out = new PrintStream(new BufferedOutputStream(os)); } } // Process all transactions for (Transaction txn : transactions) { txn.runTransaction(out); if (!isAutocommit()) { log("Committing transaction", Project.MSG_VERBOSE); getConnection().commit(); } } } finally { FileUtils.close(out); } } catch (IOException | SQLException e) { closeQuietly(); setErrorProperty(); if ("abort".equals(onError)) { throw new BuildException(e, getLocation()); } } finally { try { FileUtils.close(getStatement()); } catch (SQLException ex) { // ignore } FileUtils.close(getConnection()); } log(goodSql + " of " + totalSql + " SQL statements executed successfully"); } finally { transactions = savedTransaction; sqlCommand = savedSqlCommand; } }
read in lines and execute them
Params:
  • reader – the reader contains sql lines.
  • out – the place to output results.
Throws:
/** * read in lines and execute them * @param reader the reader contains sql lines. * @param out the place to output results. * @throws SQLException on sql problems * @throws IOException on io problems */
protected void runStatements(Reader reader, PrintStream out) throws SQLException, IOException { StringBuffer sql = new StringBuffer(); BufferedReader in = new BufferedReader(reader); String line; while ((line = in.readLine()) != null) { if (!keepformat) { line = line.trim(); } if (expandProperties) { line = getProject().replaceProperties(line); } if (!keepformat) { if (line.startsWith("//")) { continue; } if (line.startsWith("--")) { continue; } StringTokenizer st = new StringTokenizer(line); if (st.hasMoreTokens()) { String token = st.nextToken(); if ("REM".equalsIgnoreCase(token)) { continue; } } } sql.append(keepformat ? "\n" : " ").append(line); // SQL defines "--" as a comment to EOL // and in Oracle it may contain a hint // so we cannot just remove it, instead we must end it if (!keepformat && line.contains("--")) { sql.append("\n"); } int lastDelimPos = lastDelimiterPosition(sql, line); if (lastDelimPos > -1) { execSQL(sql.substring(0, lastDelimPos), out); sql.replace(0, sql.length(), ""); } } // Catch any statements not followed by ; if (sql.length() > 0) { execSQL(sql.toString(), out); } }
Exec the sql statement.
Params:
  • sql – the SQL statement to execute
  • out – the place to put output
Throws:
/** * Exec the sql statement. * @param sql the SQL statement to execute * @param out the place to put output * @throws SQLException on SQL problems */
protected void execSQL(String sql, PrintStream out) throws SQLException { // Check and ignore empty statements if (sql.trim().isEmpty()) { return; } ResultSet resultSet = null; try { totalSql++; log("SQL: " + sql, Project.MSG_VERBOSE); boolean ret; int updateCount = 0, updateCountTotal = 0; ret = getStatement().execute(sql); updateCount = getStatement().getUpdateCount(); do { if (updateCount != -1) { updateCountTotal += updateCount; } if (ret) { resultSet = getStatement().getResultSet(); printWarnings(resultSet.getWarnings(), false); resultSet.clearWarnings(); if (print) { printResults(resultSet, out); } } ret = getStatement().getMoreResults(); updateCount = getStatement().getUpdateCount(); } while (ret || updateCount != -1); printWarnings(getStatement().getWarnings(), false); getStatement().clearWarnings(); log(updateCountTotal + " rows affected", Project.MSG_VERBOSE); if (updateCountTotal != -1) { setRowCountProperty(updateCountTotal); } if (print && showtrailers) { out.println(updateCountTotal + " rows affected"); } SQLWarning warning = getConnection().getWarnings(); printWarnings(warning, true); getConnection().clearWarnings(); goodSql++; } catch (SQLException e) { log("Failed to execute: " + sql, Project.MSG_ERR); setErrorProperty(); if (!"abort".equals(onError)) { log(e.toString(), Project.MSG_ERR); } if (!"continue".equals(onError)) { throw e; } } finally { FileUtils.close(resultSet); } }
print any results in the statement
Params:
  • out – the place to print results
Throws:
Deprecated:since 1.6.x. Use the two arg version instead.
/** * print any results in the statement * @deprecated since 1.6.x. * Use {@link #printResults(java.sql.ResultSet, java.io.PrintStream) * the two arg version} instead. * @param out the place to print results * @throws SQLException on SQL problems. */
@Deprecated protected void printResults(PrintStream out) throws SQLException { try (ResultSet rs = getStatement().getResultSet()) { printResults(rs, out); } }
print any results in the result set.
Params:
  • rs – the resultset to print information about
  • out – the place to print results
Throws:
Since:Ant 1.6.3
/** * print any results in the result set. * @param rs the resultset to print information about * @param out the place to print results * @throws SQLException on SQL problems. * @since Ant 1.6.3 */
protected void printResults(ResultSet rs, PrintStream out) throws SQLException { if (rs != null) { log("Processing new result set.", Project.MSG_VERBOSE); ResultSetMetaData md = rs.getMetaData(); int columnCount = md.getColumnCount(); if (columnCount > 0) { if (showheaders) { out.print(maybeQuote(md.getColumnName(1))); for (int col = 2; col <= columnCount; col++) { out.print(csvColumnSep); out.print(maybeQuote(md.getColumnName(col))); } out.println(); } while (rs.next()) { printValue(rs, 1, out); for (int col = 2; col <= columnCount; col++) { out.print(csvColumnSep); printValue(rs, col, out); } out.println(); printWarnings(rs.getWarnings(), false); } } } out.println(); } private void printValue(ResultSet rs, int col, PrintStream out) throws SQLException { if (rawBlobs && rs.getMetaData().getColumnType(col) == Types.BLOB) { Blob blob = rs.getBlob(col); if (blob != null) { new StreamPumper(rs.getBlob(col).getBinaryStream(), out).run(); } } else { out.print(maybeQuote(rs.getString(col))); } } private String maybeQuote(String s) { if (csvQuoteChar == null || s == null || (!forceCsvQuoteChar && !s.contains(csvColumnSep) && !s.contains(csvQuoteChar))) { return s; } StringBuilder sb = new StringBuilder(csvQuoteChar); char q = csvQuoteChar.charAt(0); for (final char c : s.toCharArray()) { if (c == q) { sb.append(q); } sb.append(c); } return sb.append(csvQuoteChar).toString(); } /* * Closes an unused connection after an error and doesn't rethrow * a possible SQLException * @since Ant 1.7 */ private void closeQuietly() { if (!isAutocommit() && getConnection() != null && "abort".equals(onError)) { try { getConnection().rollback(); } catch (SQLException ex) { // ignore } } }
Caches the connection returned by the base class's getConnection method.

Subclasses that need to provide a different connection than the base class would, should override this method but keep in mind that this class expects to get the same connection instance on consecutive calls.

returns null if the connection does not connect to the expected RDBMS.

/** * Caches the connection returned by the base class's getConnection method. * * <p>Subclasses that need to provide a different connection than * the base class would, should override this method but keep in * mind that this class expects to get the same connection * instance on consecutive calls.</p> * * <p>returns null if the connection does not connect to the * expected RDBMS.</p> */
@Override protected Connection getConnection() { if (conn == null) { conn = super.getConnection(); if (!isValidRdbms(conn)) { conn = null; } } return conn; }
Creates and configures a Statement instance which is then cached for subsequent calls.

Subclasses that want to provide different Statement instances, should override this method but keep in mind that this class expects to get the same connection instance on consecutive calls.

Throws:
Returns:Statement
/** * Creates and configures a Statement instance which is then * cached for subsequent calls. * * <p>Subclasses that want to provide different Statement * instances, should override this method but keep in mind that * this class expects to get the same connection instance on * consecutive calls.</p> * * @return Statement * @throws SQLException if statement creation or processing fails */
protected Statement getStatement() throws SQLException { if (statement == null) { statement = getConnection().createStatement(); statement.setEscapeProcessing(escapeProcessing); } return statement; }
The action a task should perform on an error, one of "continue", "stop" and "abort"
/** * The action a task should perform on an error, * one of "continue", "stop" and "abort" */
public static class OnError extends EnumeratedAttribute {
Returns:the enumerated values
/** @return the enumerated values */
@Override public String[] getValues() { return new String[] {"continue", "stop", "abort"}; } }
Contains the definition of a new transaction element. Transactions allow several files or blocks of statements to be executed using the same JDBC connection and commit operation in between.
/** * Contains the definition of a new transaction element. * Transactions allow several files or blocks of statements * to be executed using the same JDBC connection and commit * operation in between. */
public class Transaction { private Resource tSrcResource = null; private String tSqlCommand = "";
Set the source file attribute.
Params:
  • src – the source file
/** * Set the source file attribute. * @param src the source file */
public void setSrc(File src) { //there are places (in this file, and perhaps elsewhere, where it is assumed //that null is an acceptable parameter. if (src != null) { setSrcResource(new FileResource(src)); } }
Set the source resource attribute.
Params:
  • src – the source file
Since:Ant 1.7
/** * Set the source resource attribute. * @param src the source file * @since Ant 1.7 */
public void setSrcResource(Resource src) { if (tSrcResource != null) { throw new BuildException("only one resource per transaction"); } tSrcResource = src; }
Set inline text
Params:
  • sql – the inline text
/** * Set inline text * @param sql the inline text */
public void addText(String sql) { if (sql != null) { this.tSqlCommand += sql; } }
Set the source resource.
Params:
  • a – the source resource collection.
Since:Ant 1.7
/** * Set the source resource. * @param a the source resource collection. * @since Ant 1.7 */
public void addConfigured(ResourceCollection a) { if (a.size() != 1) { throw new BuildException( "only single argument resource collections are supported."); } setSrcResource(a.iterator().next()); } private void runTransaction(PrintStream out) throws IOException, SQLException { if (!tSqlCommand.isEmpty()) { log("Executing commands", Project.MSG_INFO); runStatements(new StringReader(tSqlCommand), out); } if (tSrcResource != null) { log("Executing resource: " + tSrcResource.toString(), Project.MSG_INFO); Charset charset = encoding == null ? Charset.defaultCharset() : Charset.forName(encoding); try (Reader reader = new InputStreamReader( tSrcResource.getInputStream(), charset)) { runStatements(reader, out); } } } } public int lastDelimiterPosition(StringBuffer buf, String currentLine) { if (strictDelimiterMatching) { if ((delimiterType.equals(DelimiterType.NORMAL) && StringUtils.endsWith(buf, delimiter)) || (delimiterType.equals(DelimiterType.ROW) && currentLine.equals(delimiter))) { return buf.length() - delimiter.length(); } // no match return -1; } String d = delimiter.trim().toLowerCase(Locale.ENGLISH); if (DelimiterType.NORMAL.equals(delimiterType)) { // still trying to avoid wasteful copying, see // StringUtils.endsWith int endIndex = delimiter.length() - 1; int bufferIndex = buf.length() - 1; while (bufferIndex >= 0 && Character.isWhitespace(buf.charAt(bufferIndex))) { --bufferIndex; } if (bufferIndex < endIndex) { return -1; } while (endIndex >= 0) { if (buf.substring(bufferIndex, bufferIndex + 1).toLowerCase(Locale.ENGLISH) .charAt(0) != d.charAt(endIndex)) { return -1; } bufferIndex--; endIndex--; } return bufferIndex + 1; } return currentLine.trim().toLowerCase(Locale.ENGLISH).equals(d) ? buf.length() - currentLine.length() : -1; } private void printWarnings(SQLWarning warning, boolean force) throws SQLException { SQLWarning initialWarning = warning; if (showWarnings || force) { while (warning != null) { log(warning + " sql warning", showWarnings ? Project.MSG_WARN : Project.MSG_VERBOSE); warning = warning.getNextWarning(); } } if (initialWarning != null) { setWarningProperty(); } if (treatWarningsAsErrors && initialWarning != null) { throw initialWarning; } } protected final void setErrorProperty() { setProperty(errorProperty, "true"); } protected final void setWarningProperty() { setProperty(warningProperty, "true"); } protected final void setRowCountProperty(int rowCount) { setProperty(rowCountProperty, Integer.toString(rowCount)); } private void setProperty(String name, String value) { if (name != null) { getProject().setNewProperty(name, value); } } }