Coverage Report - org.apache.torque.task.TorqueSQLExec
 
Classes in this File Line Coverage Branch Coverage Complexity
TorqueSQLExec
0%
0/269
0%
0/126
3.97
TorqueSQLExec$DelimiterType
0%
0/2
N/A
3.97
TorqueSQLExec$OnError
0%
0/2
N/A
3.97
TorqueSQLExec$Transaction
0%
0/16
0%
0/6
3.97
 
 1  
 package org.apache.torque.task;
 2  
 
 3  
 /*
 4  
  * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 5  
  * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 6  
  * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 7  
  * 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 distributed under the License is distributed on
 12  
  * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 13  
  * specific language governing permissions and limitations under the License.
 14  
  */
 15  
 
 16  
 import java.io.BufferedOutputStream;
 17  
 import java.io.BufferedReader;
 18  
 import java.io.File;
 19  
 import java.io.FileInputStream;
 20  
 import java.io.FileOutputStream;
 21  
 import java.io.FileReader;
 22  
 import java.io.IOException;
 23  
 import java.io.InputStreamReader;
 24  
 import java.io.PrintStream;
 25  
 import java.io.Reader;
 26  
 import java.io.StringReader;
 27  
 import java.sql.Connection;
 28  
 import java.sql.DatabaseMetaData;
 29  
 import java.sql.Driver;
 30  
 import java.sql.ResultSet;
 31  
 import java.sql.ResultSetMetaData;
 32  
 import java.sql.SQLException;
 33  
 import java.sql.SQLWarning;
 34  
 import java.sql.Statement;
 35  
 import java.util.ArrayList;
 36  
 import java.util.HashMap;
 37  
 import java.util.Iterator;
 38  
 import java.util.List;
 39  
 import java.util.Map;
 40  
 import java.util.Properties;
 41  
 
 42  
 import org.apache.commons.lang.StringUtils;
 43  
 import org.apache.tools.ant.AntClassLoader;
 44  
 import org.apache.tools.ant.BuildException;
 45  
 import org.apache.tools.ant.Project;
 46  
 import org.apache.tools.ant.PropertyHelper;
 47  
 import org.apache.tools.ant.Task;
 48  
 import org.apache.tools.ant.types.EnumeratedAttribute;
 49  
 import org.apache.tools.ant.types.Path;
 50  
 import org.apache.tools.ant.types.Reference;
 51  
 
 52  
 /**
 53  
  * This task uses an SQL -> Database map in the form of a properties file to insert each SQL file listed into its
 54  
  * designated database.
 55  
  * 
 56  
  * @author <a href="mailto:jeff@custommonkey.org">Jeff Martin</a>
 57  
  * @author <a href="mailto:gholam@xtra.co.nz">Michael McCallum</A>
 58  
  * @author <a href="mailto:tim.stephenson@sybase.com">Tim Stephenson</A>
 59  
  * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</A>
 60  
  * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
 61  
  * @version $Id: TorqueSQLExec.java,v 1.1 2007-10-21 07:57:26 abyrne Exp $
 62  
  */
 63  0
 public class TorqueSQLExec extends Task {
 64  0
     private int goodSql = 0;
 65  0
     private int totalSql = 0;
 66  
     private Path classpath;
 67  
     private AntClassLoader loader;
 68  
 
 69  
     /**
 70  
      *
 71  
      */
 72  0
     public static class DelimiterType extends EnumeratedAttribute {
 73  
         public static final String NORMAL = "normal";
 74  
         public static final String ROW = "row";
 75  
 
 76  
         public String[] getValues() {
 77  0
             return new String[] { NORMAL, ROW };
 78  
         }
 79  
     }
 80  
 
 81  
     /** Database connection */
 82  0
     private Connection conn = null;
 83  
 
 84  
     /** Autocommit flag. Default value is false */
 85  0
     private boolean autocommit = false;
 86  
 
 87  
     /** SQL statement */
 88  0
     private Statement statement = null;
 89  
 
 90  
     /** DB driver. */
 91  0
     private String driver = null;
 92  
 
 93  
     /** DB url. */
 94  0
     private String url = null;
 95  
 
 96  
     /** User name. */
 97  0
     private String userId = null;
 98  
 
 99  
     /** Password */
 100  0
     private String password = null;
 101  
 
 102  
     /** SQL Statement delimiter */
 103  0
     private String delimiter = ";";
 104  
 
 105  
     /**
 106  
      * The delimiter type indicating whether the delimiter will only be recognized on a line by itself
 107  
      */
 108  0
     private String delimiterType = DelimiterType.NORMAL;
 109  
 
 110  
     /** Print SQL results. */
 111  0
     private boolean print = false;
 112  
 
 113  
     /** Print header columns. */
 114  0
     private boolean showheaders = true;
 115  
 
 116  
     /** Results Output file. */
 117  0
     private File output = null;
 118  
 
 119  
     /** RDBMS Product needed for this SQL. */
 120  0
     private String rdbms = null;
 121  
 
 122  
     /** RDBMS Version needed for this SQL. */
 123  0
     private String version = null;
 124  
 
 125  
     /** Action to perform if an error is found */
 126  0
     private String onError = "abort";
 127  
 
 128  
     /** Encoding to use when reading SQL statements from a file */
 129  0
     private String encoding = null;
 130  
 
 131  
     /** Src directory for the files listed in the sqldbmap. */
 132  
     private String srcDir;
 133  
 
 134  
     /** Properties file that maps an individual SQL file to a database. */
 135  
     private File sqldbmap;
 136  
 
 137  
     /**
 138  
      * Set the sqldbmap properties file.
 139  
      * 
 140  
      * @param sqldbmap
 141  
      *            filename for the sqldbmap
 142  
      */
 143  
     public void setSqlDbMap(String sqldbmap) {
 144  0
         this.sqldbmap = getProject().resolveFile(sqldbmap);
 145  0
     }
 146  
 
 147  
     /**
 148  
      * Get the sqldbmap properties file.
 149  
      * 
 150  
      * @return filename for the sqldbmap
 151  
      */
 152  
     public File getSqlDbMap() {
 153  0
         return sqldbmap;
 154  
     }
 155  
 
 156  
     /**
 157  
      * Set the src directory for the sql files listed in the sqldbmap file.
 158  
      * 
 159  
      * @param srcDir
 160  
      *            sql source directory
 161  
      */
 162  
     public void setSrcDir(String srcDir) {
 163  0
         this.srcDir = getProject().resolveFile(srcDir).toString();
 164  0
     }
 165  
 
 166  
     /**
 167  
      * Get the src directory for the sql files listed in the sqldbmap file.
 168  
      * 
 169  
      * @return sql source directory
 170  
      */
 171  
     public String getSrcDir() {
 172  0
         return srcDir;
 173  
     }
 174  
 
 175  
     /**
 176  
      * Set the classpath for loading the driver.
 177  
      * 
 178  
      * @param classpath
 179  
      *            the classpath
 180  
      */
 181  
     public void setClasspath(Path classpath) {
 182  0
         if (this.classpath == null) {
 183  0
             this.classpath = classpath;
 184  
         } else {
 185  0
             this.classpath.append(classpath);
 186  
         }
 187  0
     }
 188  
 
 189  
     /**
 190  
      * Create the classpath for loading the driver.
 191  
      * 
 192  
      * @return the classpath
 193  
      */
 194  
     public Path createClasspath() {
 195  0
         if (this.classpath == null) {
 196  0
             this.classpath = new Path(getProject());
 197  
         }
 198  0
         return this.classpath.createPath();
 199  
     }
 200  
 
 201  
     /**
 202  
      * Set the classpath for loading the driver using the classpath reference.
 203  
      * 
 204  
      * @param r
 205  
      *            reference to the classpath
 206  
      */
 207  
     public void setClasspathRef(Reference r) {
 208  0
         createClasspath().setRefid(r);
 209  0
     }
 210  
 
 211  
     /**
 212  
      * Set the sql command to execute
 213  
      * 
 214  
      * @param sql
 215  
      *            sql command to execute
 216  
      * @deprecated This method has no effect and will be removed in a future version.
 217  
      */
 218  
     public void addText(String sql) {
 219  0
     }
 220  
 
 221  
     /**
 222  
      * Set the JDBC driver to be used.
 223  
      * 
 224  
      * @param driver
 225  
      *            driver class name
 226  
      */
 227  
     public void setDriver(String driver) {
 228  0
         this.driver = driver;
 229  0
     }
 230  
 
 231  
     /**
 232  
      * Set the DB connection url.
 233  
      * 
 234  
      * @param url
 235  
      *            connection url
 236  
      */
 237  
     public void setUrl(String url) {
 238  0
         this.url = url;
 239  0
     }
 240  
 
 241  
     /**
 242  
      * Set the user name for the DB connection.
 243  
      * 
 244  
      * @param userId
 245  
      *            database user
 246  
      */
 247  
     public void setUserid(String userId) {
 248  0
         this.userId = userId;
 249  0
     }
 250  
 
 251  
     /**
 252  
      * Set the file encoding to use on the sql files read in
 253  
      * 
 254  
      * @param encoding
 255  
      *            the encoding to use on the files
 256  
      */
 257  
     public void setEncoding(String encoding) {
 258  0
         this.encoding = encoding;
 259  0
     }
 260  
 
 261  
     /**
 262  
      * Set the password for the DB connection.
 263  
      * 
 264  
      * @param password
 265  
      *            database password
 266  
      */
 267  
     public void setPassword(String password) {
 268  0
         this.password = password;
 269  0
     }
 270  
 
 271  
     /**
 272  
      * Set the autocommit flag for the DB connection.
 273  
      * 
 274  
      * @param autocommit
 275  
      *            the autocommit flag
 276  
      */
 277  
     public void setAutocommit(boolean autocommit) {
 278  0
         this.autocommit = autocommit;
 279  0
     }
 280  
 
 281  
     /**
 282  
      * Set the statement delimiter.
 283  
      * 
 284  
      * <p>
 285  
      * For example, set this to "go" and delimitertype to "ROW" for Sybase ASE or MS SQL Server.
 286  
      * </p>
 287  
      * 
 288  
      * @param delimiter
 289  
      */
 290  
     public void setDelimiter(String delimiter) {
 291  0
         this.delimiter = delimiter;
 292  0
     }
 293  
 
 294  
     /**
 295  
      * Set the Delimiter type for this sql task. The delimiter type takes two values - normal and row. Normal means that
 296  
      * any occurence of the delimiter terminate the SQL command whereas with row, only a line containing just the
 297  
      * delimiter is recognized as the end of the command.
 298  
      * 
 299  
      * @param delimiterType
 300  
      */
 301  
     public void setDelimiterType(DelimiterType delimiterType) {
 302  0
         this.delimiterType = delimiterType.getValue();
 303  0
     }
 304  
 
 305  
     /**
 306  
      * Set the print flag.
 307  
      * 
 308  
      * @param print
 309  
      */
 310  
     public void setPrint(boolean print) {
 311  0
         this.print = print;
 312  0
     }
 313  
 
 314  
     /**
 315  
      * Set the showheaders flag.
 316  
      * 
 317  
      * @param showheaders
 318  
      */
 319  
     public void setShowheaders(boolean showheaders) {
 320  0
         this.showheaders = showheaders;
 321  0
     }
 322  
 
 323  
     /**
 324  
      * Set the output file.
 325  
      * 
 326  
      * @param output
 327  
      */
 328  
     public void setOutput(File output) {
 329  0
         this.output = output;
 330  0
     }
 331  
 
 332  
     /**
 333  
      * Set the rdbms required
 334  
      * 
 335  
      * @param vendor
 336  
      */
 337  
     public void setRdbms(String vendor) {
 338  0
         this.rdbms = vendor.toLowerCase();
 339  0
     }
 340  
 
 341  
     /**
 342  
      * Set the version required
 343  
      * 
 344  
      * @param version
 345  
      */
 346  
     public void setVersion(String version) {
 347  0
         this.version = version.toLowerCase();
 348  0
     }
 349  
 
 350  
     /**
 351  
      * Set the action to perform onerror
 352  
      * 
 353  
      * @param action
 354  
      */
 355  
     public void setOnerror(OnError action) {
 356  0
         this.onError = action.getValue();
 357  0
     }
 358  
 
 359  
     /**
 360  
      * Load the sql file and then execute it
 361  
      * 
 362  
      * @throws BuildException
 363  
      */
 364  
     @SuppressWarnings("unchecked")
 365  
     public void execute() throws BuildException {
 366  0
         if (sqldbmap == null || getSqlDbMap().exists() == false) {
 367  0
             throw new BuildException("You haven't provided an sqldbmap, or " + "the one you specified doesn't exist: "
 368  
                     + sqldbmap);
 369  
         }
 370  
 
 371  0
         if (driver == null) {
 372  0
             throw new BuildException("Driver attribute must be set!", getLocation());
 373  
         }
 374  0
         if (userId == null) {
 375  0
             throw new BuildException("User Id attribute must be set!", getLocation());
 376  
         }
 377  0
         if (password == null) {
 378  0
             throw new BuildException("Password attribute must be set!", getLocation());
 379  
         }
 380  0
         if (url == null) {
 381  0
             throw new BuildException("Url attribute must be set!", getLocation());
 382  
         }
 383  
 
 384  0
         Properties map = new Properties();
 385  
 
 386  
         try {
 387  0
             FileInputStream fis = new FileInputStream(getSqlDbMap());
 388  0
             map.load(fis);
 389  0
             fis.close();
 390  0
         } catch (IOException ioe) {
 391  0
             throw new BuildException("Cannot open and process the sqldbmap!");
 392  0
         }
 393  
 
 394  0
         Map<Object, Object> databases = new HashMap<Object, Object>();
 395  
 
 396  0
         Iterator<?> eachFileName = map.keySet().iterator();
 397  0
         while (eachFileName.hasNext()) {
 398  0
             String sqlfile = (String) eachFileName.next();
 399  0
             String database = map.getProperty(sqlfile);
 400  
 
 401  0
             List<Object> files = (List<Object>) databases.get(database);
 402  
 
 403  0
             if (files == null) {
 404  0
                 files = new ArrayList<Object>();
 405  0
                 databases.put(database, files);
 406  
             }
 407  
 
 408  
             // We want to make sure that the base schemas
 409  
             // are inserted first.
 410  0
             if (sqlfile.indexOf("schema.sql") != -1) {
 411  0
                 files.add(0, sqlfile);
 412  
             } else {
 413  0
                 files.add(sqlfile);
 414  
             }
 415  0
         }
 416  
 
 417  0
         Iterator<?> eachDatabase = databases.keySet().iterator();
 418  0
         while (eachDatabase.hasNext()) {
 419  0
             String db = (String) eachDatabase.next();
 420  0
             List<Object> transactions = new ArrayList<Object>();
 421  0
             eachFileName = ((List<?>) databases.get(db)).iterator();
 422  0
             while (eachFileName.hasNext()) {
 423  0
                 String fileName = (String) eachFileName.next();
 424  0
                 File file = new File(srcDir, fileName);
 425  
 
 426  0
                 if (file.exists()) {
 427  0
                     Transaction transaction = new Transaction();
 428  0
                     transaction.setSrc(file);
 429  0
                     transactions.add(transaction);
 430  0
                 } else {
 431  0
                     System.out.println("File '" + file.getAbsolutePath()
 432  
                             + "' in sqldbmap does not exist, so skipping it.");
 433  
                 }
 434  0
             }
 435  
 
 436  0
             insertDatabaseSqlFiles(url, db, transactions);
 437  0
         }
 438  0
     }
 439  
 
 440  
     /**
 441  
      * Take the base url, the target database and insert a set of SQL files into the target database.
 442  
      * 
 443  
      * @param url
 444  
      * @param database
 445  
      * @param transactions
 446  
      */
 447  
     private void insertDatabaseSqlFiles(String url, String database, List<?> transactions) {
 448  0
         url = StringUtils.replace(url, "@DB@", database);
 449  0
         System.out.println("Our new url -> " + url);
 450  
 
 451  0
         Driver driverInstance = null;
 452  
         try {
 453  
             Class<?> dc;
 454  0
             if (classpath != null) {
 455  0
                 log("Loading " + driver + " using AntClassLoader with classpath " + classpath, Project.MSG_VERBOSE);
 456  
 
 457  0
                 loader = new AntClassLoader(getProject(), classpath);
 458  0
                 dc = loader.loadClass(driver);
 459  
             } else {
 460  0
                 log("Loading " + driver + " using system loader.", Project.MSG_VERBOSE);
 461  0
                 dc = Class.forName(driver);
 462  
             }
 463  0
             driverInstance = (Driver) dc.newInstance();
 464  0
         } catch (ClassNotFoundException e) {
 465  0
             throw new BuildException("Class Not Found: JDBC driver " + driver + " could not be loaded", getLocation());
 466  0
         } catch (IllegalAccessException e) {
 467  0
             throw new BuildException("Illegal Access: JDBC driver " + driver + " could not be loaded", getLocation());
 468  0
         } catch (InstantiationException e) {
 469  0
             throw new BuildException("Instantiation Exception: JDBC driver " + driver + " could not be loaded",
 470  
                     getLocation());
 471  0
         }
 472  
 
 473  
         try {
 474  0
             log("connecting to " + url, Project.MSG_VERBOSE);
 475  0
             Properties info = new Properties();
 476  0
             info.put("user", userId);
 477  0
             info.put("password", password);
 478  0
             conn = driverInstance.connect(url, info);
 479  
 
 480  0
             if (conn == null) {
 481  
                 // Driver doesn't understand the URL
 482  0
                 throw new SQLException("No suitable Driver for " + url);
 483  
             }
 484  
 
 485  0
             if (!isValidRdbms(conn)) {
 486  
                 return;
 487  
             }
 488  
 
 489  0
             conn.setAutoCommit(autocommit);
 490  0
             statement = conn.createStatement();
 491  0
             PrintStream out = System.out;
 492  
             try {
 493  0
                 if (output != null) {
 494  0
                     log("Opening PrintStream to output file " + output, Project.MSG_VERBOSE);
 495  0
                     out = new PrintStream(new BufferedOutputStream(new FileOutputStream(output)));
 496  
                 }
 497  
 
 498  
                 // Process all transactions
 499  0
                 for (Iterator<?> it = transactions.iterator(); it.hasNext();) {
 500  0
                     Transaction transaction = (Transaction) it.next();
 501  0
                     transaction.runTransaction(out);
 502  0
                     if (!autocommit) {
 503  0
                         log("Commiting transaction", Project.MSG_VERBOSE);
 504  0
                         conn.commit();
 505  
                     }
 506  0
                 }
 507  
             } finally {
 508  0
                 if (out != null && out != System.out) {
 509  0
                     out.close();
 510  
                 }
 511  
             }
 512  0
         } catch (IOException e) {
 513  0
             if (!autocommit && conn != null && onError.equals("abort")) {
 514  
                 try {
 515  0
                     conn.rollback();
 516  0
                 } catch (SQLException ex) {
 517  
                     // do nothing.
 518  0
                 }
 519  
             }
 520  0
             throw new BuildException(e, getLocation());
 521  0
         } catch (SQLException e) {
 522  0
             if (!autocommit && conn != null && onError.equals("abort")) {
 523  
                 try {
 524  0
                     conn.rollback();
 525  0
                 } catch (SQLException ex) {
 526  
                     // do nothing.
 527  0
                 }
 528  
             }
 529  0
             throw new BuildException(e, getLocation());
 530  
         } finally {
 531  0
             try {
 532  0
                 if (statement != null) {
 533  0
                     statement.close();
 534  
                 }
 535  0
                 if (conn != null) {
 536  0
                     conn.close();
 537  
                 }
 538  0
             } catch (SQLException e) {
 539  0
             }
 540  0
         }
 541  
 
 542  0
         System.out.println(goodSql + " of " + totalSql + " SQL statements executed successfully");
 543  0
     }
 544  
 
 545  
     /**
 546  
      * Read the statements from the .sql file and execute them. Lines starting with '//', '--' or 'REM ' are ignored.
 547  
      * 
 548  
      * @param reader
 549  
      * @param out
 550  
      * @throws SQLException
 551  
      * @throws IOException
 552  
      */
 553  
     protected void runStatements(Reader reader, PrintStream out) throws SQLException, IOException {
 554  0
         String sql = "";
 555  0
         String line = "";
 556  
 
 557  0
         BufferedReader in = new BufferedReader(reader);
 558  0
         PropertyHelper ph = PropertyHelper.getPropertyHelper(getProject());
 559  
 
 560  
         try {
 561  0
             while ((line = in.readLine()) != null) {
 562  0
                 line = line.trim();
 563  0
                 line = ph.replaceProperties("", line, getProject().getProperties());
 564  0
                 if (line.startsWith("//") || line.startsWith("--")) {
 565  0
                     continue;
 566  
                 }
 567  0
                 if (line.length() > 4 && line.substring(0, 4).equalsIgnoreCase("REM ")) {
 568  0
                     continue;
 569  
                 }
 570  
 
 571  0
                 sql += " " + line;
 572  0
                 sql = sql.trim();
 573  
 
 574  
                 // SQL defines "--" as a comment to EOL
 575  
                 // and in Oracle it may contain a hint
 576  
                 // so we cannot just remove it, instead we must end it
 577  0
                 if (line.indexOf("--") >= 0) {
 578  0
                     sql += "\n";
 579  
                 }
 580  
 
 581  0
                 if (delimiterType.equals(DelimiterType.NORMAL) && sql.endsWith(delimiter)
 582  
                         || delimiterType.equals(DelimiterType.ROW) && line.equals(delimiter)) {
 583  0
                     log("SQL: " + sql, Project.MSG_VERBOSE);
 584  0
                     execSQL(sql.substring(0, sql.length() - delimiter.length()), out);
 585  0
                     sql = "";
 586  
                 }
 587  
             }
 588  
 
 589  
             // Catch any statements not followed by ;
 590  0
             if (!sql.equals("")) {
 591  0
                 execSQL(sql, out);
 592  
             }
 593  0
         } catch (SQLException e) {
 594  0
             throw e;
 595  0
         }
 596  0
     }
 597  
 
 598  
     /**
 599  
      * Verify if connected to the correct RDBMS
 600  
      * 
 601  
      * @param conn
 602  
      */
 603  
     protected boolean isValidRdbms(Connection conn) {
 604  0
         if (rdbms == null && version == null) {
 605  0
             return true;
 606  
         }
 607  
 
 608  
         try {
 609  0
             DatabaseMetaData dmd = conn.getMetaData();
 610  
 
 611  0
             if (rdbms != null) {
 612  0
                 String theVendor = dmd.getDatabaseProductName().toLowerCase();
 613  
 
 614  0
                 log("RDBMS = " + theVendor, Project.MSG_VERBOSE);
 615  0
                 if (theVendor == null || theVendor.indexOf(rdbms) < 0) {
 616  0
                     log("Not the required RDBMS: " + rdbms, Project.MSG_VERBOSE);
 617  0
                     return false;
 618  
                 }
 619  
             }
 620  
 
 621  0
             if (version != null) {
 622  0
                 String theVersion = dmd.getDatabaseProductVersion().toLowerCase();
 623  
 
 624  0
                 log("Version = " + theVersion, Project.MSG_VERBOSE);
 625  0
                 if (theVersion == null || !(theVersion.startsWith(version) || theVersion.indexOf(" " + version) >= 0)) {
 626  0
                     log("Not the required version: \"" + version + "\"", Project.MSG_VERBOSE);
 627  0
                     return false;
 628  
                 }
 629  
             }
 630  0
         } catch (SQLException e) {
 631  
             // Could not get the required information
 632  0
             log("Failed to obtain required RDBMS information", Project.MSG_ERR);
 633  0
             return false;
 634  0
         }
 635  
 
 636  0
         return true;
 637  
     }
 638  
 
 639  
     /**
 640  
      * Exec the sql statement.
 641  
      * 
 642  
      * @param sql
 643  
      * @param out
 644  
      * @throws SQLException
 645  
      */
 646  
     protected void execSQL(String sql, PrintStream out) throws SQLException {
 647  
         // Check and ignore empty statements
 648  0
         if ("".equals(sql.trim())) {
 649  0
             return;
 650  
         }
 651  
 
 652  
         try {
 653  0
             totalSql++;
 654  0
             if (!statement.execute(sql)) {
 655  0
                 log(statement.getUpdateCount() + " rows affected", Project.MSG_VERBOSE);
 656  
             } else {
 657  0
                 if (print) {
 658  0
                     printResults(out);
 659  
                 }
 660  
             }
 661  
 
 662  0
             SQLWarning warning = conn.getWarnings();
 663  0
             while (warning != null) {
 664  0
                 log(warning + " sql warning", Project.MSG_VERBOSE);
 665  0
                 warning = warning.getNextWarning();
 666  
             }
 667  0
             conn.clearWarnings();
 668  0
             goodSql++;
 669  0
         } catch (SQLException e) {
 670  0
             System.out.println("Failed to execute: " + sql);
 671  0
             if (!onError.equals("continue")) {
 672  0
                 throw e;
 673  
             }
 674  0
             log(e.toString(), Project.MSG_ERR);
 675  0
         }
 676  0
     }
 677  
 
 678  
     /**
 679  
      * print any results in the statement.
 680  
      * 
 681  
      * @param out
 682  
      * @throws SQLException
 683  
      */
 684  
     protected void printResults(PrintStream out) throws java.sql.SQLException {
 685  0
         ResultSet rs = null;
 686  
         do {
 687  0
             rs = statement.getResultSet();
 688  0
             if (rs != null) {
 689  0
                 log("Processing new result set.", Project.MSG_VERBOSE);
 690  0
                 ResultSetMetaData md = rs.getMetaData();
 691  0
                 int columnCount = md.getColumnCount();
 692  0
                 StringBuffer line = new StringBuffer();
 693  0
                 if (showheaders) {
 694  0
                     for (int col = 1; col < columnCount; col++) {
 695  0
                         line.append(md.getColumnName(col));
 696  0
                         line.append(",");
 697  
                     }
 698  0
                     line.append(md.getColumnName(columnCount));
 699  0
                     out.println(line);
 700  0
                     line.setLength(0);
 701  
                 }
 702  0
                 while (rs.next()) {
 703  0
                     boolean first = true;
 704  0
                     for (int col = 1; col <= columnCount; col++) {
 705  0
                         String columnValue = rs.getString(col);
 706  0
                         if (columnValue != null) {
 707  0
                             columnValue = columnValue.trim();
 708  
                         }
 709  
 
 710  0
                         if (first) {
 711  0
                             first = false;
 712  
                         } else {
 713  0
                             line.append(",");
 714  
                         }
 715  0
                         line.append(columnValue);
 716  
                     }
 717  0
                     out.println(line);
 718  0
                     line.setLength(0);
 719  0
                 }
 720  
             }
 721  0
         } while (statement.getMoreResults());
 722  0
         out.println();
 723  0
     }
 724  
 
 725  
     /**
 726  
      * Enumerated attribute with the values "continue", "stop" and "abort" for the onerror attribute.
 727  
      */
 728  0
     public static class OnError extends EnumeratedAttribute {
 729  
         public static final String CONTINUE = "continue";
 730  
 
 731  
         public static final String STOP = "stop";
 732  
 
 733  
         public static final String ABORT = "abort";
 734  
 
 735  
         public String[] getValues() {
 736  0
             return new String[] { CONTINUE, STOP, ABORT };
 737  
         }
 738  
     }
 739  
 
 740  
     /**
 741  
      * Contains the definition of a new transaction element. Transactions allow several files or blocks of statements to
 742  
      * be executed using the same JDBC connection and commit operation in between.
 743  
      */
 744  0
     public class Transaction {
 745  0
         private File tSrcFile = null;
 746  0
         private String tSqlCommand = "";
 747  
 
 748  
         public void setSrc(File src) {
 749  0
             this.tSrcFile = src;
 750  0
         }
 751  
 
 752  
         public void addText(String sql) {
 753  0
             this.tSqlCommand += sql;
 754  0
         }
 755  
 
 756  
         private void runTransaction(PrintStream out) throws IOException, SQLException {
 757  0
             if (tSqlCommand.length() != 0) {
 758  0
                 log("Executing commands", Project.MSG_INFO);
 759  0
                 runStatements(new StringReader(tSqlCommand), out);
 760  
             }
 761  
 
 762  0
             if (tSrcFile != null) {
 763  0
                 System.out.println("Executing file: " + tSrcFile.getAbsolutePath());
 764  0
                 Reader reader = (encoding == null) ? new FileReader(tSrcFile) : new InputStreamReader(
 765  
                         new FileInputStream(tSrcFile), encoding);
 766  0
                 runStatements(reader, out);
 767  0
                 reader.close();
 768  
             }
 769  0
         }
 770  
     }
 771  
 }