stevel 2003/03/13 13:41:11
Modified: src/main/org/apache/tools/ant/taskdefs SQLExec.java Log: option to preserve formatting in inline SQL, bug ID http://nagoya.apache.org/bugzilla/show_bug.cgi?id=10719 The diff is bigger than it need be; someone's editor must have stripped extroneous whitespace, or tab to spaced it. There are no tabs or trailing spaces in the commit, I believe. Revision Changes Path 1.50 +137 -116 ant/src/main/org/apache/tools/ant/taskdefs/SQLExec.java Index: SQLExec.java =================================================================== RCS file: /home/cvs/ant/src/main/org/apache/tools/ant/taskdefs/SQLExec.java,v retrieving revision 1.49 retrieving revision 1.50 diff -u -r1.49 -r1.50 --- SQLExec.java 10 Feb 2003 14:13:36 -0000 1.49 +++ SQLExec.java 13 Mar 2003 21:41:11 -0000 1.50 @@ -1,7 +1,7 @@ /* * The Apache Software License, Version 1.1 * - * Copyright (c) 2000-2002 The Apache Software Foundation. All rights + * Copyright (c) 2000-2003 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without @@ -23,7 +23,7 @@ * Alternately, this acknowlegement may appear in the software itself, * if and wherever such third-party acknowlegements normally appear. * - * 4. The names "Ant" and "Apache Software + * 4. The names "The Jakarta Project", "Ant", and "Apache Software * Foundation" must not be used to endorse or promote products derived * from this software without prior written permission. For written * permission, please contact [EMAIL PROTECTED] @@ -54,54 +54,57 @@ package org.apache.tools.ant.taskdefs; -import java.io.BufferedOutputStream; -import java.io.BufferedReader; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.types.EnumeratedAttribute; +import org.apache.tools.ant.types.FileSet; + import java.io.File; -import java.io.FileInputStream; +import java.io.PrintStream; +import java.io.BufferedOutputStream; import java.io.FileOutputStream; -import java.io.FileReader; import java.io.IOException; -import java.io.InputStreamReader; -import java.io.PrintStream; import java.io.Reader; +import java.io.BufferedReader; import java.io.StringReader; -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.io.FileReader; +import java.io.InputStreamReader; +import java.io.FileInputStream; import java.util.Enumeration; import java.util.StringTokenizer; import java.util.Vector; -import org.apache.tools.ant.BuildException; -import org.apache.tools.ant.DirectoryScanner; -import org.apache.tools.ant.Project; -import org.apache.tools.ant.types.EnumeratedAttribute; -import org.apache.tools.ant.types.FileSet; + +import java.sql.Connection; +import java.sql.Statement; +import java.sql.SQLException; +import java.sql.SQLWarning; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; /** * 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 + * 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 + * + * <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 + * + * <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. + * + * <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> - * + + * * @author <a href="mailto:[EMAIL PROTECTED]">Jeff Martin</a> * @author <A href="mailto:[EMAIL PROTECTED]">Michael McCallum</A> * @author <A href="mailto:[EMAIL PROTECTED]">Tim Stephenson</A> @@ -123,8 +126,8 @@ } } - - + + private int goodSql = 0; private int totalSql = 0; @@ -163,13 +166,13 @@ * SQL Statement delimiter */ private String delimiter = ";"; - + /** * The delimiter type indicating whether the delimiter will * only be recognized on a line by itself */ private String delimiterType = DelimiterType.NORMAL; - + /** * Print SQL results. */ @@ -185,12 +188,12 @@ */ private File output = null; - + /** * Action to perform if an error is found **/ private String onError = "abort"; - + /** * Encoding to use when reading SQL statements from a file */ @@ -200,7 +203,11 @@ * Append to an existing file or overwrite it? */ private boolean append = false; - + + /** + * Keep the format of a sql block? + */ + private boolean keepformat = false; /** * Set the name of the SQL file to be run. @@ -209,15 +216,15 @@ public void setSrc(File srcFile) { this.srcFile = srcFile; } - + /** - * Set an inline SQL command to execute. + * Set an inline SQL command to execute. * NB: Properties are not expanded in this text. */ public void addText(String sql) { this.sqlCommand += sql; } - + /** * Adds a set of files (nested fileset attribute). */ @@ -234,7 +241,7 @@ transactions.addElement(t); return t; } - + /** * Set the file encoding to use on the SQL files read in * @@ -243,10 +250,10 @@ public void setEncoding(String encoding) { this.encoding = encoding; } - + /** - * Sets the delimiter that separates SQL statements. - * Optional, defaults to ";". + * Set the delimiter that separates SQL statements; + * optional, default ";" * * <p>For example, set this to "go" and delimitertype to "ROW" for * Sybase ASE or MS SQL Server.</p> @@ -266,7 +273,7 @@ public void setDelimiterType(DelimiterType delimiterType) { this.delimiterType = delimiterType.getValue(); } - + /** * Print result sets from the statements; * optional, default false @@ -274,9 +281,9 @@ public void setPrint(boolean print) { this.print = print; } - + /** - * Print headers for result sets from the + * Print headers for result sets from the * statements; optional, default true. */ public void setShowheaders(boolean showheaders) { @@ -284,7 +291,7 @@ } /** - * Set the output file; + * Set the output file; * optional, defaults to the Ant log. */ public void setOutput(File output) { @@ -301,7 +308,7 @@ this.append = append; } - + /** * Action to perform when statement fails: continue, stop, or abort * optional; default "abort" @@ -311,6 +318,16 @@ } /** + * whether or not format should be preserved. + * Defaults to false. + * + * @param keepformat The keepformat to set + */ + public void setKeepformat(boolean keepformat) { + this.keepformat = keepformat; + } + + /** * Load the sql file and then execute it */ public void execute() throws BuildException { @@ -320,34 +337,34 @@ sqlCommand = sqlCommand.trim(); try { - if (srcFile == null && sqlCommand.length() == 0 - && filesets.isEmpty()) { + if (srcFile == null && sqlCommand.length() == 0 + && filesets.isEmpty()) { if (transactions.size() == 0) { throw new BuildException("Source file or fileset, " + "transactions or sql statement " - + "must be set!", getLocation()); + + "must be set!", location); } } - + if (srcFile != null && !srcFile.exists()) { - throw new BuildException("Source file does not exist!", getLocation()); + throw new BuildException("Source file does not exist!", location); } // deal with the filesets for (int i = 0; i < filesets.size(); i++) { FileSet fs = (FileSet) filesets.elementAt(i); - DirectoryScanner ds = fs.getDirectoryScanner(getProject()); - File srcDir = fs.getDir(getProject()); - + DirectoryScanner ds = fs.getDirectoryScanner(project); + File srcDir = fs.getDir(project); + String[] srcFiles = ds.getIncludedFiles(); - + // Make a transaction for each file for (int j = 0 ; j < srcFiles.length ; j++) { Transaction t = createTransaction(); t.setSrc(new File(srcDir, srcFiles[j])); } } - + // Make a transaction group for the outer command Transaction t = createTransaction(); t.setSrc(srcFile); @@ -359,11 +376,11 @@ try { statement = conn.createStatement(); - + PrintStream out = System.out; try { if (output != null) { - log("Opening PrintStream to output file " + output, + log("Opening PrintStream to output file " + output, Project.MSG_VERBOSE); out = new PrintStream( new BufferedOutputStream( @@ -371,11 +388,11 @@ .getAbsolutePath(), append))); } - + // Process all transactions - for (Enumeration e = transactions.elements(); + for (Enumeration e = transactions.elements(); e.hasMoreElements();) { - + ((Transaction) e.nextElement()).runTransaction(out); if (!isAutocommit()) { log("Commiting transaction", Project.MSG_VERBOSE); @@ -386,21 +403,21 @@ if (out != null && out != System.out) { out.close(); } - } + } } catch (IOException e){ if (!isAutocommit() && conn != null && onError.equals("abort")) { try { conn.rollback(); } catch (SQLException ex) {} } - throw new BuildException(e, getLocation()); + throw new BuildException(e, location); } catch (SQLException e){ if (!isAutocommit() && conn != null && onError.equals("abort")) { try { conn.rollback(); } catch (SQLException ex) {} } - throw new BuildException(e, getLocation()); + throw new BuildException(e, location); } finally { try { if (statement != null) { @@ -411,8 +428,8 @@ } } catch (SQLException e) {} } - - log(goodSql + " of " + totalSql + + + log(goodSql + " of " + totalSql + " SQL statements executed successfully"); } finally { transactions = savedTransaction; @@ -420,63 +437,69 @@ } } - /** * read in lines and execute them */ - protected void runStatements(Reader reader, PrintStream out) + protected void runStatements(Reader reader, PrintStream out) throws SQLException, IOException { - String sql = ""; + StringBuffer sql = new StringBuffer(); String line = ""; - + BufferedReader in = new BufferedReader(reader); - + while ((line = in.readLine()) != null){ - line = line.trim(); - line = getProject().replaceProperties(line); - if (line.startsWith("//")) { - continue; - } - if (line.startsWith("--")) { - continue; - } - StringTokenizer st = new StringTokenizer(line); - if (st.hasMoreTokens()) { - String token = st.nextToken(); - if ("REM".equalsIgnoreCase(token)) { + if (!keepformat) { + line = line.trim(); + } + line = project.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 += " " + line; - sql = sql.trim(); - + + if (!keepformat) { + sql.append(" " + line); + } else { + sql.append("\n" + 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 (line.indexOf("--") >= 0) { - sql += "\n"; + if (!keepformat) { + if (line.indexOf("--") >= 0) { + sql.append("\n"); + } } - - if ((delimiterType.equals(DelimiterType.NORMAL) - && sql.endsWith(delimiter)) + if ((delimiterType.equals(DelimiterType.NORMAL) + && sql.toString().endsWith(delimiter)) || - (delimiterType.equals(DelimiterType.ROW) + (delimiterType.equals(DelimiterType.ROW) && line.equals(delimiter))) { log("SQL: " + sql, Project.MSG_VERBOSE); - execSQL(sql.substring(0, sql.length() - delimiter.length()), + execSQL(sql.substring(0, sql.length() - delimiter.length()), out); - sql = ""; + sql.replace(0, sql.length(), ""); } } - // Catch any statements not followed by ; if (!sql.equals("")){ - execSQL(sql, out); + execSQL(sql.toString(), out); } } - - + + /** * Exec the sql statement. */ @@ -485,18 +508,18 @@ if ("".equals(sql.trim())) { return; } - - try { + + try { totalSql++; if (!statement.execute(sql)) { - log(statement.getUpdateCount() + " rows affected", + log(statement.getUpdateCount() + " rows affected", Project.MSG_VERBOSE); } else { if (print) { printResults(out); } } - + SQLWarning warning = conn.getWarnings(); while (warning != null){ log(warning + " sql warning", Project.MSG_VERBOSE); @@ -512,7 +535,7 @@ log(e.toString(), Project.MSG_ERR); } } - + /** * print any results in the statement. */ @@ -541,7 +564,7 @@ if (columnValue != null) { columnValue = columnValue.trim(); } - + if (first) { first = false; } else { @@ -595,20 +618,20 @@ /** * */ - private void runTransaction(PrintStream out) + private void runTransaction(PrintStream out) throws IOException, SQLException { if (tSqlCommand.length() != 0) { log("Executing commands", Project.MSG_INFO); runStatements(new StringReader(tSqlCommand), out); } - + if (tSrcFile != null) { - log("Executing file: " + tSrcFile.getAbsolutePath(), + log("Executing file: " + tSrcFile.getAbsolutePath(), Project.MSG_INFO); - Reader reader = + Reader reader = (encoding == null) ? new FileReader(tSrcFile) : new InputStreamReader( - new FileInputStream(tSrcFile), + new FileInputStream(tSrcFile), encoding); try { runStatements(reader, out); @@ -618,7 +641,5 @@ } } } - - }